From 008471b09f36b796f845549da4fb87586fb0294c Mon Sep 17 00:00:00 2001 From: Nazar Kornienko Date: Tue, 21 Jan 2025 22:24:53 +0100 Subject: [PATCH] migrate: picocolors to @reliverse/relico --- build.optim.ts | 133 ++++++++++------- build.publish.ts | 211 ++++++++++++++++++++------- bun.lockb | Bin 321658 -> 324047 bytes cspell.json | 4 +- examples/launcher.ts | 22 +-- examples/other/simple.ts | 4 +- examples/src/prompts.ts | 6 +- examples/src/simple/input.ts | 4 +- jsr.jsonc | 2 +- package.json | 43 +++--- publish.ts | 25 ++-- src/checkbox/index.ts | 8 +- src/confirm/confirm-main.ts | 10 +- src/core/Separator.ts | 4 +- src/core/theme.ts | 38 ++--- src/date/date.ts | 4 +- src/expand/index.ts | 6 +- src/flags/usage.ts | 12 +- src/input/input-main.ts | 4 +- src/input/input.ts | 6 +- src/multiselect/multiselect-main.ts | 28 ++-- src/multiselect/num-multi-select.ts | 6 +- src/range/range.ts | 10 +- src/rawlist/index.ts | 4 +- src/search/index.ts | 8 +- src/select/index.ts | 6 +- src/select/select-main.ts | 26 ++-- src/select/select-two.ts | 8 +- src/task/progress.ts | 6 +- src/task/spinner.ts | 12 +- src/task/task.ts | 57 +++++--- src/toggle/index.ts | 10 +- src/utils/color.ts | 4 +- src/utils/colorize.ts | 52 +++---- src/utils/component.ts | 218 ++++++++++++++-------------- src/utils/prevent.ts | 4 +- src/utils/prompt-end.ts | 8 +- src/utils/system.ts | 2 +- 38 files changed, 582 insertions(+), 433 deletions(-) diff --git a/build.optim.ts b/build.optim.ts index e827fd9..fec9926 100644 --- a/build.optim.ts +++ b/build.optim.ts @@ -1,11 +1,10 @@ import fs from "fs-extra"; import { globby } from "globby"; import path from "pathe"; -import strip from "strip-comments"; import { fileURLToPath } from "url"; // Verbose logging -const debug = false; +export const verbose = false; // Parse command-line arguments to check for '--jsr' flag const args: string[] = process.argv.slice(2); @@ -14,7 +13,7 @@ const isJSR: boolean = args.includes("--jsr"); // Get current directory using import.meta.url const currentDir = path.dirname(fileURLToPath(import.meta.url)); -// Define directories based on the presence of '--jsr' flag +// Directories based on the presence of '--jsr' flag const sourceDir: string = path.resolve(currentDir, "src"); const outputDir: string = path.resolve( currentDir, @@ -22,30 +21,18 @@ const outputDir: string = path.resolve( ); // Separate patterns for files to delete in different modes -const npmFilesToDelete: string[] = [ +const arrayFilesToDelete: string[] = [ "**/*.test.js", + "**/*.test.ts", "**/*.test.d.ts", - "**/*.spec.js", - "**/*.spec.d.ts", "types/internal.js", "types/internal.d.ts", "**/*.temp.js", "**/*.temp.d.ts", - "__snapshots__", - "testing", -]; - -const jsrFilesToDelete: string[] = [ - "**/*.test.ts", - "**/*.spec.ts", - "**/*.temp.ts", - "__snapshots__", ]; /** * Deletes files matching the provided patterns within the base directory. - * @param patterns - Array of glob patterns to match files for deletion. - * @param baseDir - The base directory to search for files. */ async function deleteFiles(patterns: string[], baseDir: string): Promise { try { @@ -62,25 +49,27 @@ async function deleteFiles(patterns: string[], baseDir: string): Promise { for (const filePath of files) { try { await fs.remove(filePath); - if (debug) { + if (verbose) { console.log(`Deleted: ${filePath}`); } } catch (error) { - console.error(`Error deleting file ${filePath}:`, error); + console.error( + `Error deleting file ${filePath}:`, + error instanceof Error ? error.message : JSON.stringify(error), + ); } } } catch (error) { - console.error("Error processing deletion patterns:", error); + console.error( + "Error processing deletion patterns:", + error instanceof Error ? error.message : JSON.stringify(error), + ); } } /** * Replaces import paths that use '~/' with relative paths. * If `isJSR` is true, also replaces '.js' extensions with '.ts'. - * @param content - The file content. - * @param fileDir - The directory of the current file. - * @param rootDir - The root directory to resolve relative paths. - * @param isJSR - Flag indicating whether to apply JSR-specific transformations. * @returns The updated file content with modified import paths. */ function replaceImportPaths( @@ -98,7 +87,7 @@ function replaceImportPaths( importPath: string, suffix: string, ): string => { - const relativePathToRoot: string = path.relative(fileDir, rootDir) || "."; + const relativePathToRoot: string = path.relative(fileDir, rootDir); // Remove leading '~/' or '~' from importPath importPath = importPath.replace(/^~\/?/, ""); let newPath: string = path.join(relativePathToRoot, importPath); @@ -117,7 +106,7 @@ function replaceImportPaths( // @see https://jsr.io/docs/publishing-packages#relative-imports updatedContent = updatedContent.replace(/(\.js)(?=['";])/g, ".ts"); - if (debug) { + if (verbose) { console.log("Replaced '.js' with '.ts' in import paths."); } } @@ -128,31 +117,29 @@ function replaceImportPaths( /** * Removes comments from the given content string. * - Strips block comments using `strip-comments`. - * @param content - The file content. - * @param filePath - The path of the file being processed. * @returns The content without unwanted comments. */ -function removeComments(content: string, filePath: string): string { +// function removeComments(content: string, filePath: string): string { +function removeComments(content: string): string { // When not in JSR mode, strip all comments using strip-comments - const stripped = strip(content, { - line: true, - block: true, - keepProtected: true, - preserveNewlines: false, - }); + // const stripped = strip(content, { + // line: true, + // block: true, + // keepProtected: true, + // preserveNewlines: false, + // }); - if (debug) { - console.log(`\nProcessing file: ${filePath}`); - console.log("Stripped all comments."); - } + // if (debug) { + // console.log(`\nProcessing file: ${filePath}`); + // console.log("Stripped all comments."); + // } - return stripped; + return content; // return stripped; } /** * Processes all relevant files in the given directory * by replacing import paths and removing comments. - * @param dir - The directory to process. */ async function processFiles(dir: string): Promise { const files: string[] = await fs.readdir(dir); @@ -174,9 +161,10 @@ async function processFiles(dir: string): Promise { filePath.endsWith(".mts") || filePath.endsWith(".cts") ) { - if (debug) { + if (verbose) { console.log(`\nProcessing file: ${filePath}`); } + try { const content: string = await fs.readFile(filePath, "utf8"); @@ -188,17 +176,21 @@ async function processFiles(dir: string): Promise { ); if (!isJSR) { - updatedContent = removeComments(updatedContent, filePath); + // updatedContent = removeComments(updatedContent, filePath); + updatedContent = removeComments(updatedContent); } if (content !== updatedContent) { await fs.writeFile(filePath, updatedContent, "utf8"); - if (debug) { + if (verbose) { console.log(`Updated file: ${filePath}`); } } } catch (error) { - console.error(`Error processing file ${filePath}:`, error); + console.error( + `Error processing file ${filePath}:`, + error instanceof Error ? error.message : JSON.stringify(error), + ); } } } @@ -212,12 +204,15 @@ async function removeOutputDirectory(): Promise { const exists: boolean = await fs.pathExists(outputDir); if (exists) { await fs.remove(outputDir); - if (debug) { + if (verbose) { console.log(`Removed existing '${outputDir}' directory.`); } } } catch (error) { - console.error(`Error removing '${outputDir}' directory:`, error); + console.error( + `Error removing '${outputDir}' directory:`, + error instanceof Error ? error.message : JSON.stringify(error), + ); throw error; } } @@ -231,18 +226,44 @@ async function copySrcToOutput(): Promise { overwrite: true, errorOnExist: false, }); - if (debug) { + if (verbose) { console.log(`Copied 'src' to '${outputDir}'`); } } catch (error) { - console.error(`Error copying 'src' to '${outputDir}':`, error); + console.error( + `Error copying 'src' to '${outputDir}':`, + error instanceof Error ? error.message : JSON.stringify(error), + ); throw error; } } +/** + * Renames all .tsx files to -tsx.txt in the specified directory and its subdirectories. + */ +async function renameTsxFiles(dir: string): Promise { + try { + const files = await globby("**/*.tsx", { + cwd: dir, + absolute: true, + }); + + for (const filePath of files) { + const newPath = filePath.replace(/\.tsx$/, "-tsx.txt"); + await fs.rename(filePath, newPath); + if (verbose) { + console.log(`Renamed: ${filePath} -> ${newPath}`); + } + } + } catch (error) { + console.error( + `Error renaming .tsx files: ${error instanceof Error ? error.message : JSON.stringify(error)}`, + ); + } +} + /** * Optimizes the build for production by processing files and deleting unnecessary ones. - * @param dir - The directory to optimize. */ async function optimizeBuildForProduction(dir: string): Promise { if (isJSR) { @@ -252,11 +273,13 @@ async function optimizeBuildForProduction(dir: string): Promise { await copySrcToOutput(); console.log("Processing copied files to replace import paths..."); await processFiles(outputDir); // Process files after copying + console.log("Renaming .tsx files to -tsx.txt for JSR compatibility..."); + await renameTsxFiles(outputDir); } else { console.log("Creating an optimized production build..."); await processFiles(dir); console.log("Cleaning up unnecessary files..."); - const filesToDelete: string[] = isJSR ? jsrFilesToDelete : npmFilesToDelete; + const filesToDelete: string[] = arrayFilesToDelete; await deleteFiles(filesToDelete, dir); } } @@ -283,14 +306,14 @@ await optimizeBuildForProduction(outputDir) .then(() => { getDirectorySize(outputDir) .then((size) => { - console.log(`Total size of ${outputDir}: ${size} bytes`); + console.log(`Total size of ${outputDir}: ${String(size)} bytes`); }) - .catch((error) => { + .catch((error: unknown) => { console.error( `Error calculating directory size for ${outputDir}: ${error instanceof Error ? error.message : "Unknown error"}`, ); }); }) - .catch((error: Error) => { - console.error(error.message); + .catch((error: unknown) => { + console.log(error instanceof Error ? error.message : JSON.stringify(error)); }); diff --git a/build.publish.ts b/build.publish.ts index 5f24bfa..8583ba3 100644 --- a/build.publish.ts +++ b/build.publish.ts @@ -1,13 +1,18 @@ // 👉 usage example: `bun pub --bump=1.2.3` +import { parseJSONC, parseJSON5 } from "confbox"; +import { destr } from "destr"; import { execaCommand } from "execa"; import fs from "fs-extra"; import { globby } from "globby"; import mri from "mri"; -import path from "path"; +import path from "pathe"; + +// TODO: implement @reliverse/bump npm library function showHelp() { - console.log(`Usage: bun tsx build.publish.ts [newVersion] [options] + console.log( + `Usage: bun tsx build.publish.ts [newVersion] [options] Arguments: newVersion The new version to set (e.g. 1.2.3) @@ -16,7 +21,8 @@ Options: --jsr Publish to JSR registry --dry-run Perform a dry run of the publish process -h, --help Show help -`); +`, + ); } const argv = mri(process.argv.slice(2), { @@ -57,9 +63,12 @@ async function publishNpm(dryRun: boolean) { await execaCommand("bun build:npm", { stdio: "inherit" }); await execaCommand("npm publish", { stdio: "inherit" }); } - console.log("Published to npm successfully."); + console.log("success", "Published to npm successfully."); } catch (error) { - console.error("❌ Failed to publish to npm:", error); + console.error( + "❌ Failed to publish to npm:", + error instanceof Error ? error.message : String(error), + ); process.exit(1); } } @@ -67,81 +76,171 @@ async function publishNpm(dryRun: boolean) { async function publishJsr(dryRun: boolean) { try { if (dryRun) { - await execaCommand( - "bunx jsr publish --allow-slow-types --allow-dirty --dry-run", - { stdio: "inherit" }, - ); + await execaCommand("bunx jsr publish --dry-run", { + stdio: "inherit", + }); } else { await execaCommand("bun build:jsr", { stdio: "inherit" }); await execaCommand("bunx jsr publish --allow-slow-types --allow-dirty", { stdio: "inherit", }); } - console.log("Published to JSR successfully."); + console.log("success", "Published to JSR successfully."); } catch (error) { - console.error("❌ Failed to publish to JSR:", error); + console.error( + "❌ Failed to publish to JSR:", + error instanceof Error ? error.message : String(error), + ); process.exit(1); } } async function bumpVersions(oldVersion: string, newVersion: string) { - // Update package.json - const pkgPath = path.resolve("package.json"); - const pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8")) as { - version: string; - }; - pkg.version = newVersion; - await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2)); - - // Update jsr.jsonc - const jsrPath = path.resolve("jsr.jsonc"); - if (await fs.pathExists(jsrPath)) { - const jsrConfig = JSON.parse(await fs.readFile(jsrPath, "utf-8")) as { - version: string; - }; - jsrConfig.version = newVersion; - await fs.writeFile(jsrPath, JSON.stringify(jsrConfig, null, 2)); - } + try { + // Find all relevant files + const codebase = await globby("**/*.{reliverse,json,jsonc,json5,ts}", { + ignore: [ + "**/node_modules/**", + "**/.git/**", + "**/dist/**", + "**/build/**", + "**/.next/**", + "**/coverage/**", + "**/.cache/**", + "**/tmp/**", + "**/.temp/**", + "**/package-lock.json", + "**/pnpm-lock.yaml", + "**/yarn.lock", + "**/bun.lockb", + ], + }); + + // Track which files were updated + const updatedFiles: string[] = []; + + // Process each file + for (const file of codebase) { + try { + const content = await fs.readFile(file, "utf-8"); + + // Handle different file types + if (file.endsWith(".json") || file.endsWith(".reliverse")) { + const parsed = destr(content); + if (parsed && typeof parsed === "object" && "version" in parsed) { + parsed.version = newVersion; + await fs.writeFile(file, `${JSON.stringify(parsed, null, 2)}\n`); + updatedFiles.push(file); + continue; + } + } else if (file.endsWith(".jsonc")) { + const parsed = parseJSONC(content); + if (parsed && typeof parsed === "object" && "version" in parsed) { + parsed.version = newVersion; + await fs.writeFile(file, `${JSON.stringify(parsed, null, 2)}\n`); + updatedFiles.push(file); + continue; + } + } else if (file.endsWith(".json5")) { + const parsed = parseJSON5(content); + if (parsed && typeof parsed === "object" && "version" in parsed) { + parsed.version = newVersion; + await fs.writeFile(file, `${JSON.stringify(parsed, null, 2)}\n`); + updatedFiles.push(file); + continue; + } + } + + // For other files (including .ts), do string replacement if version is found + if (content.includes(oldVersion)) { + const updated = content.replaceAll(oldVersion, newVersion); + await fs.writeFile(file, updated); + updatedFiles.push(file); + } + } catch (error) { + console.warn( + `Failed to process ${file}:`, + error instanceof Error ? error.message : String(error), + ); + } + } - // Replace version in src/**/*.ts and examples/**/*.ts - const tsFiles = await globby(["src/**/*.ts", "examples/**/*.ts"]); - for (const file of tsFiles) { - const content = await fs.readFile(file, "utf-8"); - if (content.includes(oldVersion)) { - const updated = content.replaceAll(oldVersion, newVersion); - await fs.writeFile(file, updated); + if (updatedFiles.length > 0) { + console.log( + `Version updated from ${oldVersion} to ${newVersion}`, + `Updated ${String(updatedFiles.length)} files:`, + updatedFiles.join("\n"), + ); + } else { + console.warn("No files were updated with the new version"); } + } catch (error) { + console.error( + "Failed to bump versions:", + error instanceof Error ? error.message : String(error), + ); + throw error; } - - console.log(`Version updated from ${oldVersion} to ${newVersion}`); } async function main() { - const { jsr, "dry-run": dryRun } = argv; - const newVersion = argv._[0]; // The new version provided by the user (if any) - - if (newVersion) { - // Perform version bump - const pkg = JSON.parse(await fs.readFile("package.json", "utf-8")) as { - version: string; + try { + const { jsr, "dry-run": dryRun } = argv as unknown as { + jsr: boolean; + "dry-run": boolean; }; - const oldVersion = pkg.version; - if (oldVersion !== newVersion) { - await bumpVersions(oldVersion, newVersion); + const newVersion = argv._[0]; + + if (!newVersion) { + console.log("No version specified, skipping version bump"); } else { - console.log(`No version change required: already at ${oldVersion}`); + // Validate version format + if (!/^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(newVersion)) { + throw new Error( + "Invalid version format. Must be a valid semver (e.g., 1.2.3, 1.2.3-beta.1)", + ); + } + + // Read current version + const pkgPath = path.resolve("package.json"); + if (!(await fs.pathExists(pkgPath))) { + throw new Error("package.json not found"); + } + + const pkg = destr<{ version: string }>( + await fs.readFile(pkgPath, "utf-8"), + ); + if (!pkg.version) { + throw new Error("No version field found in package.json"); + } + + const oldVersion = pkg.version; + if (oldVersion === newVersion) { + console.log(`No version change required: already at ${oldVersion}`); + } else { + await bumpVersions(oldVersion, newVersion); + } } - } - // After potential bump, proceed with publishing - if (jsr) { - await publishJsr(dryRun); - } else { - await publishNpm(dryRun); + // Proceed with publishing + if (jsr) { + await publishJsr(dryRun); + } else { + await publishNpm(dryRun); + } + } catch (error) { + console.error( + "❌ An unexpected error occurred:", + error instanceof Error ? error.message : String(error), + ); + process.exit(1); } } -main().catch((error) => { - console.error("❌ An unexpected error occurred:", error); +main().catch((error: unknown) => { + console.error( + "❌ An unexpected error occurred:", + error instanceof Error ? error.message : String(error), + ); process.exit(1); }); diff --git a/bun.lockb b/bun.lockb index c98e7f73f7be6688905ba118827388512ff96082..a6fb7f1f31236d1c2c78dbfc26c1dd34fa6a07d5 100644 GIT binary patch delta 68165 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 BziR*h diff --git a/cspell.json b/cspell.json index 70b316e..56ba033 100644 --- a/cspell.json +++ b/cspell.json @@ -1,5 +1,5 @@ { - "version": "0.2", + "version": "1.4.9", "language": "en", "import": ["@cspell/dict-npm/cspell-ext.json"], "ignorePaths": ["examples/deprecated", "dist-jsr", "dist-npm"], @@ -100,7 +100,6 @@ "outro", "pagedown", "pageup", - "picocolors", "polski", "printj", "rawlist", @@ -140,7 +139,6 @@ "unpub", "unstub", "valign", - "valtio", "venv", "Vous", "vsprintf", diff --git a/examples/launcher.ts b/examples/launcher.ts index 2659ed1..bcb72ed 100644 --- a/examples/launcher.ts +++ b/examples/launcher.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { errorHandler, selectPrompt } from "~/main.js"; @@ -22,29 +22,29 @@ async function examplesRunner() { hint: "experimental", }, { - label: pc.dim("Task Example"), + label: re.dim("Task Example"), value: "task", - hint: pc.dim("not finished"), + hint: re.dim("not finished"), }, { - label: pc.dim("Progressbar Example"), + label: re.dim("Progressbar Example"), value: "progressbar", - hint: pc.dim("not finished"), + hint: re.dim("not finished"), }, { - label: pc.dim("Simple Example"), + label: re.dim("Simple Example"), value: "simple", - hint: pc.dim("not finished"), + hint: re.dim("not finished"), }, { - label: pc.dim("with flags 1 Example"), + label: re.dim("with flags 1 Example"), value: "cmd-a", - hint: pc.dim("not finished"), + hint: re.dim("not finished"), }, { - label: pc.dim("with flags 2 Example"), + label: re.dim("with flags 2 Example"), value: "cmd-b", - hint: pc.dim("not finished"), + hint: re.dim("not finished"), }, { label: "🗝️ Exit", value: "exit" }, ] as const, diff --git a/examples/other/simple.ts b/examples/other/simple.ts index 2b334bc..b192104 100644 --- a/examples/other/simple.ts +++ b/examples/other/simple.ts @@ -1,6 +1,6 @@ #!/usr/bin/env node -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import figures from "~/figures/index.js"; import { select } from "~/prompts/index.js"; @@ -66,7 +66,7 @@ async function askNextDemo() { ], theme: { prefix: { - done: pc.magenta(figures.play), + done: re.magenta(figures.play), }, }, }); diff --git a/examples/src/prompts.ts b/examples/src/prompts.ts index b3165ea..366fcda 100644 --- a/examples/src/prompts.ts +++ b/examples/src/prompts.ts @@ -1,7 +1,7 @@ import { msg } from "@reliverse/relinka"; import { detect } from "detect-package-manager"; import { emojify } from "node-emoji"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { anykeyPrompt, spinnerTaskPrompt } from "~/main.js"; import { multiselectPrompt } from "~/main.js"; @@ -36,7 +36,7 @@ const pkg = packageJson; // const pkg = { // name: "@reliverse/prompts", -// version: "1.4.7", +// version: "1.4.9", // description: // "@reliverse/prompts is a powerful library that enables seamless, typesafe, and resilient prompts for command-line applications. Crafted with simplicity and elegance, it provides developers with an intuitive and robust way to build interactive CLIs.", // }; @@ -76,7 +76,7 @@ export async function showAnykeyPrompt( username?: string, ) { const pm = await detect(); - let notification = pc.bold("[anykeyPrompt] Press any key to continue..."); + let notification = re.bold("[anykeyPrompt] Press any key to continue..."); if (kind === "privacy") { notification = `Before you continue, please note that you are only testing an example CLI app. None of your responses will be sent anywhere. No actions, such as installing dependencies, will actually take place; this is simply a simulation with a sleep timer and spinner. You can always review the source code to learn more.\n============================\n${notification}`; } diff --git a/examples/src/simple/input.ts b/examples/src/simple/input.ts index 5dcba4f..a5aa35b 100644 --- a/examples/src/simple/input.ts +++ b/examples/src/simple/input.ts @@ -1,5 +1,5 @@ import * as url from "node:url"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { input } from "~/prompts/index.js"; @@ -21,7 +21,7 @@ const demo = async () => { message: "Enter an hex color?", // biome-ignore lint/style/useDefaultParameterLast: transformer(value = "", { isFinal }) { - return isFinal ? pc.underline(value) : value; + return isFinal ? re.underline(value) : value; }, validate: (value = "") => isHex(value) || "Pass a valid hex value", }); diff --git a/jsr.jsonc b/jsr.jsonc index 9bd30e2..61aa9ec 100644 --- a/jsr.jsonc +++ b/jsr.jsonc @@ -1,6 +1,6 @@ { "name": "@reliverse/prompts", - "version": "1.4.7", + "version": "1.4.9", "author": "blefnk", "license": "MIT", "exports": "./dist-jsr/main.ts", diff --git a/package.json b/package.json index 0826dde..561b039 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@reliverse/prompts", - "version": "1.4.7", + "version": "1.4.9", "author": "blefnk", "type": "module", "description": "@reliverse/prompts is a powerful library that enables seamless, typesafe, and resilient prompts for command-line applications. Crafted with simplicity and elegance, it provides developers with an intuitive and robust way to build interactive CLIs.", @@ -42,15 +42,24 @@ "url": "https://github.com/reliverse/prompts/issues", "email": "blefnk@gmail.com" }, - "files": ["package.json", "README.md", "LICENSE.md", "dist-npm"], + "files": [ + "package.json", + "README.md", + "LICENSE.md", + "dist-npm" + ], "homepage": "https://github.com/reliverse/prompts", - "keywords": ["cli", "reliverse"], + "keywords": [ + "cli", + "reliverse" + ], "license": "MIT", "dependencies": { "@alcalzone/ansi-tokenize": "^0.1.3", "@figliolia/chalk-animation": "^1.0.4", + "@reliverse/relico": "^1.0.0", "@reliverse/relinka": "^1.2.8", - "@sinclair/typebox": "^0.34.13", + "@sinclair/typebox": "^0.34.14", "ansi-diff-stream": "^1.2.1", "ansi-escapes": "^7.0.0", "auto-bind": "^5.0.1", @@ -69,7 +78,7 @@ "es-toolkit": "^1.31.0", "external-editor": "^3.1.0", "figlet": "^1.8.0", - "fs-extra": "^11.2.0", + "fs-extra": "^11.3.0", "get-pixels": "^3.3.3", "globby": "^14.0.2", "gradient-string": "^3.0.0", @@ -80,12 +89,11 @@ "mri": "^1.2.0", "mute-stream": "^2.0.0", "node-emoji": "^2.2.0", - "nypm": "^0.4.1", + "nypm": "^0.5.0", "ora": "^8.1.1", "p-map": "^7.0.3", "patch-console": "^2.0.0", - "pathe": "^2.0.1", - "picocolors": "^1.1.1", + "pathe": "^2.0.2", "plur": "^5.1.0", "precision": "^1.0.1", "read-package-up": "^11.0.0", @@ -99,7 +107,6 @@ "strip-ansi": "^7.1.0", "terminal-size": "^4.0.0", "ts-regex-builder": "^1.8.2", - "valtio": "^2.1.2", "widest-line": "^5.0.0", "window-size": "^1.1.1", "wrap-ansi": "^9.0.0", @@ -109,20 +116,20 @@ "devDependencies": { "@arethetypeswrong/cli": "^0.17.3", "@biomejs/biome": "1.9.4", - "@cspell/dict-npm": "^5.1.22", + "@cspell/dict-npm": "^5.1.23", "@eslint/js": "^9.18.0", - "@eslint/json": "^0.9.0", + "@eslint/json": "^0.9.1", "@eslint/markdown": "^6.2.1", - "@faker-js/faker": "^9.3.0", + "@faker-js/faker": "^9.4.0", "@stylistic/eslint-plugin": "^2.13.0", "@types/ansi-diff-stream": "^1.2.3", - "@types/bun": "^1.1.16", + "@types/bun": "^1.1.18", "@types/chalk-animation": "^1.6.3", "@types/eslint__js": "^8.42.3", "@types/figlet": "^1.7.0", "@types/fs-extra": "^11.0.4", "@types/mute-stream": "^0.0.4", - "@types/node": "^22.10.6", + "@types/node": "^22.10.7", "@types/sentencer": "^0.2.3", "@types/signal-exit": "^3.0.4", "@types/strip-comments": "^2.0.4", @@ -130,10 +137,10 @@ "@types/wrap-ansi": "^8.1.0", "delay": "^6.0.0", "eslint": "^9.18.0", - "eslint-plugin-perfectionist": "^4.6.0", + "eslint-plugin-perfectionist": "^4.7.0", "execa": "^9.5.2", "jiti": "^2.4.2", - "knip": "^5.42.0", + "knip": "^5.42.3", "mock-stdin": "^1.0.0", "p-queue": "^8.0.1", "printj": "^1.3.1", @@ -141,8 +148,8 @@ "strip-comments": "^2.0.1", "tsx": "^4.19.2", "typescript": "^5.7.3", - "typescript-eslint": "^8.20.0", + "typescript-eslint": "^8.21.0", "unbuild": "^3.3.1", - "vitest": "^2.1.8" + "vitest": "^3.0.3" } } diff --git a/publish.ts b/publish.ts index a94b0a6..35ee885 100644 --- a/publish.ts +++ b/publish.ts @@ -1,10 +1,8 @@ // 👉 usage example: `bun pub --bump=1.2.3` -import { relinka } from "@reliverse/relinka"; +import { defineCommand, runMain } from "citty"; import { execa } from "execa"; -import { defineCommand, errorHandler, runMain } from "~/main.js"; - const main = defineCommand({ meta: { name: "pub", @@ -30,31 +28,36 @@ const main = defineCommand({ }, run: async ({ args }) => { if (args.jsr) { - relinka("info", "Publishing the JSR version"); + console.log("Publishing the JSR version"); await execa("bun", ["build.publish.ts", args.bump, "--jsr"], { stdio: "inherit", }); } else if (args.npm) { - relinka("info", "Publishing the NPM version"); + console.log("Publishing the NPM version"); await execa("bun", ["build.publish.ts", args.bump], { stdio: "inherit" }); } else if (args.dryRun) { - relinka("info", "Dry run the publish process"); + console.log("Dry run the publish process"); await execa("bun", ["pub:jsr", "--dry-run"], { stdio: "inherit" }); await execa("bun", ["pub:npm", "--dry-run"], { stdio: "inherit" }); } else { - relinka("info", "Publishing the JSR version"); + console.log("Publishing the JSR version"); await execa("bun", ["build.publish.ts", args.bump, "--jsr"], { stdio: "inherit", }); - relinka("info", "Publishing the NPM version"); + console.log("Publishing the NPM version"); await execa("bun", ["pub:npm", args.bump], { stdio: "inherit" }); } }, }); -await runMain(main).catch((error: unknown) => +function errorHandler(error: unknown, message: string) { + console.error(message); + console.error(error instanceof Error ? error.message : String(error)); +} + +await runMain(main).catch((error: unknown) => { errorHandler( error instanceof Error ? error : new Error(String(error)), "If this issue is related to @reliverse/cli itself, please\n│ report the details at https://github.com/reliverse/cli", - ), -); + ); +}); diff --git a/src/checkbox/index.ts b/src/checkbox/index.ts index f027066..51b91bb 100644 --- a/src/checkbox/index.ts +++ b/src/checkbox/index.ts @@ -1,5 +1,5 @@ import ansiEscapes from "ansi-escapes"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PartialDeep } from "~/types/utils.js"; @@ -43,15 +43,15 @@ type CheckboxTheme = { const checkboxTheme: CheckboxTheme = { icon: { - checked: pc.green(figures.circleFilled), + checked: re.green(figures.circleFilled), unchecked: figures.circle, cursor: figures.pointer, }, style: { - disabledChoice: (text: string) => pc.dim(`- ${text}`), + disabledChoice: (text: string) => re.dim(`- ${text}`), renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "), - description: (text: string) => pc.cyan(text), + description: (text: string) => re.cyan(text), }, helpMode: "auto", }; diff --git a/src/confirm/confirm-main.ts b/src/confirm/confirm-main.ts index 4f5c7d5..b8ed39f 100644 --- a/src/confirm/confirm-main.ts +++ b/src/confirm/confirm-main.ts @@ -9,7 +9,7 @@ import { bar, msg } from "@reliverse/relinka"; import { deleteLastLine } from "@reliverse/relinka"; import { stdin as input, stdout as output } from "node:process"; import readline from "node:readline/promises"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { colorize } from "~/main.js"; import { completePrompt } from "~/utils/prompt-end.js"; @@ -112,7 +112,7 @@ function renderPrompt(params: { if (displayInstructions && !isRerender) { msg({ type: "M_NULL", - title: pc.blue(instructions), + title: re.blue(instructions), }); uiLineCount++; } @@ -121,7 +121,7 @@ function renderPrompt(params: { if (errorMessage) { msg({ type: "M_NULL", - title: pc.redBright(errorMessage), + title: re.redBright(errorMessage), }); uiLineCount++; } @@ -164,7 +164,7 @@ export async function confirmPrompt( // Only prepend the default hint to the title if instructions are not displayed const adjustedTitle = displayInstructions ? title - : `${pc.blue(defaultHint)} ${title}`; + : `${re.blue(defaultHint)} ${title}`; const instructions = `Use to confirm or deny, for default (${effectiveDefault ? "Y" : "N"}), to exit`; @@ -236,7 +236,7 @@ export async function confirmPrompt( deleteLastLine(); msg({ type: "M_NULL", - title: `${colorize(pc.reset(formattedBar), borderColor)} ${pc.reset(effectiveDefault ? "y" : "n")}`, + title: `${colorize(re.reset(formattedBar), borderColor)} ${re.reset(effectiveDefault ? "y" : "n")}`, }); result = effectiveDefault; } else if (answer === "y" || answer === "yes") { diff --git a/src/core/Separator.ts b/src/core/Separator.ts index 60fd016..2d507f0 100644 --- a/src/core/Separator.ts +++ b/src/core/Separator.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import figures from "~/figures/index.js"; @@ -8,7 +8,7 @@ import figures from "~/figures/index.js"; */ export class Separator { - readonly separator = pc.dim(Array.from({ length: 15 }).join(figures.line)); + readonly separator = re.dim(Array.from({ length: 15 }).join(figures.line)); readonly type = "separator"; constructor(separator?: string) { diff --git a/src/core/theme.ts b/src/core/theme.ts index 9f91378..1db1143 100644 --- a/src/core/theme.ts +++ b/src/core/theme.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { Prettify } from "~/types/index.js"; @@ -28,7 +28,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (status) => status === 'done' ? pc.green('✔') : pc.blue('?') + * (status) => status === 'done' ? re.green('✔') : re.blue('?') * ``` */ prefix: string | Prettify, "loading">>; @@ -73,7 +73,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text) => pc.cyan(text) + * (text) => re.cyan(text) * ``` */ answer: (text: string) => string; @@ -88,7 +88,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text, status) => pc.bold(text) + * (text, status) => re.bold(text) * ``` */ message: (text: string, status: Status) => string; @@ -102,7 +102,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text) => pc.red(`> ${text}`) + * (text) => re.red(`> ${text}`) * ``` */ error: (text: string) => string; @@ -116,7 +116,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text) => pc.dim(`(${text})`) + * (text) => re.dim(`(${text})`) * ``` */ defaultAnswer: (text: string) => string; @@ -130,7 +130,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text) => pc.dim(text) + * (text) => re.dim(text) * ``` */ help: (text: string) => string; @@ -144,7 +144,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text) => pc.cyan(text) + * (text) => re.cyan(text) * ``` */ highlight: (text: string) => string; @@ -158,7 +158,7 @@ type DefaultTheme = { * @defaultValue * ```ts * // import colors from 'yoctocolors-cjs'; - * (text) => pc.cyan(pc.bold(`<${text}>`)) + * (text) => re.cyan(re.bold(`<${text}>`)) * ``` */ key: (text: string) => string; @@ -171,23 +171,23 @@ export type Theme = Prettify< export const defaultTheme: DefaultTheme = { prefix: { - idle: pc.blue("?"), + idle: re.blue("?"), // TODO: use figure - done: pc.green(figures.tick), + done: re.green(figures.tick), }, spinner: { interval: 80, frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"].map((frame) => - pc.yellow(frame), + re.yellow(frame), ), }, style: { - answer: pc.cyan, - message: pc.bold, - error: (text) => pc.red(`> ${text}`), - defaultAnswer: (text) => pc.dim(`(${text})`), - help: pc.dim, - highlight: pc.cyan, - key: (text: string) => pc.cyan(pc.bold(`<${text}>`)), + answer: re.cyan, + message: re.bold, + error: (text) => re.red(`> ${text}`), + defaultAnswer: (text) => re.dim(`(${text})`), + help: re.dim, + highlight: re.cyan, + key: (text: string) => re.cyan(re.bold(`<${text}>`)), }, }; diff --git a/src/date/date.ts b/src/date/date.ts index b4a4be6..2b92773 100644 --- a/src/date/date.ts +++ b/src/date/date.ts @@ -12,7 +12,7 @@ import { Type, type TSchema } from "@sinclair/typebox"; import { Value } from "@sinclair/typebox/value"; import { stdin as input, stdout as output } from "node:process"; import readline from "node:readline/promises"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { buildRegExp, digit, @@ -170,7 +170,7 @@ export async function datePrompt( } // Prompt the user for input - const answerInput = await rl.question(`${pc.dim(symbols.middle)} `); + const answerInput = await rl.question(`${re.dim(symbols.middle)} `); // Check if user pressed Ctrl+C or input stream closed: if (answerInput === null) { diff --git a/src/expand/index.ts b/src/expand/index.ts index 36e7f21..22ace8d 100644 --- a/src/expand/index.ts +++ b/src/expand/index.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PartialDeep } from "~/types/utils.js"; @@ -139,7 +139,7 @@ const expand = createPrompt( } else if (value === "") { setError("Please input a value"); } else { - setError(`"${pc.red(value)}" isn't an available option`); + setError(`"${re.red(value)}" isn't an available option`); } } } else { @@ -203,7 +203,7 @@ const expand = createPrompt( !Separator.isSeparator(choice) && choice.key === value.toLowerCase(), ); if (currentOption) { - helpTip = `${pc.cyan(">>")} ${currentOption.name}`; + helpTip = `${re.cyan(">>")} ${currentOption.name}`; } let error = ""; diff --git a/src/flags/usage.ts b/src/flags/usage.ts index 3431ed3..600da32 100644 --- a/src/flags/usage.ts +++ b/src/flags/usage.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { ArgsDef, CommandDef } from "./types.js"; @@ -98,7 +98,7 @@ export async function renderUsage( const version = cmdMeta.version || parentMeta.version; usageLines.push( - pc.gray( + re.gray( `${cmdMeta.description} (${ commandName + (version ? ` v${version}` : "") })`, @@ -108,26 +108,26 @@ export async function renderUsage( const hasOptions = argLines.length > 0 || posLines.length > 0; usageLines.push( - `${pc.underline(pc.bold("USAGE"))} \`${commandName}${ + `${re.underline(re.bold("USAGE"))} \`${commandName}${ hasOptions ? " [OPTIONS]" : "" } ${usageLine.join(" ")}\``, "", ); if (posLines.length > 0) { - usageLines.push(pc.underline(pc.bold("ARGUMENTS")), ""); + usageLines.push(re.underline(re.bold("ARGUMENTS")), ""); usageLines.push(formatLineColumns(posLines, " ")); usageLines.push(""); } if (argLines.length > 0) { - usageLines.push(pc.underline(pc.bold("OPTIONS")), ""); + usageLines.push(re.underline(re.bold("OPTIONS")), ""); usageLines.push(formatLineColumns(argLines, " ")); usageLines.push(""); } if (commandsLines.length > 0) { - usageLines.push(pc.underline(pc.bold("COMMANDS")), ""); + usageLines.push(re.underline(re.bold("COMMANDS")), ""); usageLines.push(formatLineColumns(commandsLines, " ")); usageLines.push( "", diff --git a/src/input/input-main.ts b/src/input/input-main.ts index 35870ab..081fa86 100644 --- a/src/input/input-main.ts +++ b/src/input/input-main.ts @@ -18,7 +18,7 @@ import { } from "@reliverse/relinka"; import { Value } from "@sinclair/typebox/value"; import readline from "node:readline/promises"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PromptOptions } from "~/main.js"; @@ -512,7 +512,7 @@ export async function inputPrompt( }); } else { deleteLastLine(); - msg({ type: "M_MIDDLE", title: ` ${pc.reset(defaultValue)}` }); + msg({ type: "M_MIDDLE", title: ` ${re.reset(defaultValue)}` }); } } if (errorMessage) { diff --git a/src/input/input.ts b/src/input/input.ts index a623606..e8ca898 100644 --- a/src/input/input.ts +++ b/src/input/input.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PromptOptions } from "../prompts/prompt.js"; @@ -25,11 +25,11 @@ export default class InputPrompt extends Prompt { }); this.on("value", () => { if (this.cursor >= this.value.length) { - this.valueWithCursor = `${this.value}${pc.inverse(pc.hidden("_"))}`; + this.valueWithCursor = `${this.value}${re.inverse(re.hidden("_"))}`; } else { const s1 = this.value.slice(0, this.cursor); const s2 = this.value.slice(this.cursor); - this.valueWithCursor = `${s1}${pc.inverse(s2[0])}${s2.slice(1)}`; + this.valueWithCursor = `${s1}${re.inverse(s2[0])}${s2.slice(1)}`; } }); } diff --git a/src/multiselect/multiselect-main.ts b/src/multiselect/multiselect-main.ts index 058ac4c..26bd43c 100644 --- a/src/multiselect/multiselect-main.ts +++ b/src/multiselect/multiselect-main.ts @@ -9,7 +9,7 @@ import { } from "@reliverse/relinka"; import { stdin as input, stdout as output } from "node:process"; import readline from "node:readline"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import terminalSize from "terminal-size"; import { completePrompt } from "~/utils/prompt-end.js"; @@ -130,19 +130,19 @@ function renderPromptUI(params: { if (errorMessage) { msg({ type: "M_NULL", - title: `${pc.redBright(symbols.step_error)} ${pc.redBright(errorMessage)}`, + title: `${re.redBright(symbols.step_error)} ${re.redBright(errorMessage)}`, }); uiLineCount++; } else if (allDisabled) { msg({ type: "M_NULL", - title: pc.redBright("All options are disabled."), + title: re.redBright("All options are disabled."), }); uiLineCount++; } else if (displayInstructions && !isRerender) { msg({ type: "M_NULL", - title: pc.blue(instructions), + title: re.blue(instructions), }); uiLineCount++; } @@ -177,7 +177,7 @@ function renderPromptUI(params: { ); if (shouldRenderTopEllipsis) { - msg({ type: "M_NULL", title: pc.dim("...") }); + msg({ type: "M_NULL", title: re.dim("...") }); uiLineCount++; } @@ -196,7 +196,7 @@ function renderPromptUI(params: { const lineSymbol = symbolKey in symbols ? symbols[symbolKey] : "─"; msg({ type: "M_NULL", - title: pc.dim(lineSymbol.repeat(width)), + title: re.dim(lineSymbol.repeat(width)), }); uiLineCount++; continue; @@ -206,20 +206,20 @@ function renderPromptUI(params: { const isHighlighted = index === pointer; const isDisabled = option.disabled; const checkbox = isSelected ? "[x]" : "[ ]"; - const prefix = isHighlighted ? pc.yellow(pc.reset("> ")) : " "; + const prefix = isHighlighted ? re.yellow(re.reset("> ")) : " "; const labelColor = isDisabled - ? pc.dim(pc.reset(option.label)) + ? re.dim(re.reset(option.label)) : isHighlighted - ? pc.reset(pc.yellow(option.label)) - : pc.reset(option.label); + ? re.reset(re.yellow(option.label)) + : re.reset(option.label); const hint = option.hint - ? pc.reset( - ` (${isDisabled ? pc.dim(option.hint) : pc.gray(option.hint)})`, + ? re.reset( + ` (${isDisabled ? re.dim(option.hint) : re.gray(option.hint)})`, ) : ""; - const formattedCheckbox = isHighlighted ? pc.yellow(checkbox) : checkbox; + const formattedCheckbox = isHighlighted ? re.yellow(checkbox) : checkbox; msg({ type: "M_NULL", @@ -229,7 +229,7 @@ function renderPromptUI(params: { } if (shouldRenderBottomEllipsis) { - msg({ type: "M_NULL", title: pc.dim("...") }); + msg({ type: "M_NULL", title: re.dim("...") }); uiLineCount++; } diff --git a/src/multiselect/num-multi-select.ts b/src/multiselect/num-multi-select.ts index e0bf8db..e176c65 100644 --- a/src/multiselect/num-multi-select.ts +++ b/src/multiselect/num-multi-select.ts @@ -9,7 +9,7 @@ import { import { Value } from "@sinclair/typebox/value"; import { stdin as input, stdout as output } from "node:process"; import readline from "node:readline/promises"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PromptOptions } from "~/types/general.js"; @@ -73,7 +73,7 @@ export async function numMultiSelectPrompt(opts: NumMultiSelectPromptOptions) { // Generate choices text with formatted bar const choicesText = choices .map((choice, index) => - pc.dim( + re.dim( `${formattedBar} ${index + 1}) ${choice.title}${ choice.description ? ` - ${choice.description}` : "" }`, @@ -81,7 +81,7 @@ export async function numMultiSelectPrompt(opts: NumMultiSelectPromptOptions) { ) .join("\n"); - const fullPrompt = `${question}\n${choicesText}\n${formattedBar} ${pc.bold(pc.blue(`Enter your choices (comma-separated numbers between 1-${choices.length})`))}:\n${formattedBar} `; + const fullPrompt = `${question}\n${choicesText}\n${formattedBar} ${re.bold(re.blue(`Enter your choices (comma-separated numbers between 1-${choices.length})`))}:\n${formattedBar} `; const { text: formattedPrompt } = fmt({ hintPlaceholderColor, diff --git a/src/range/range.ts b/src/range/range.ts index d5e5b96..cc048af 100644 --- a/src/range/range.ts +++ b/src/range/range.ts @@ -4,7 +4,7 @@ import Differ from "ansi-diff-stream"; import esc from "ansi-escapes"; import ui from "cli-styles"; import { EventEmitter } from "events"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import precision from "precision"; import stringWidth from "string-width"; import windowSize from "window-size"; @@ -67,7 +67,7 @@ export class RangePrompt extends EventEmitter { // Default options const defaults: Required = { hint: "– Use arrow keys or type a value.", - marker: pc.cyan("●"), + marker: re.cyan("●"), bar: "–", values: [], value: null, @@ -346,10 +346,10 @@ export class RangePrompt extends EventEmitter { out += [ ui.symbol(this.done, this.aborted), - pc.bold(this.msg), + re.bold(this.msg), ui.delimiter(this.done), this.value !== null ? this.value : "", - pc.gray(this.unit), + re.gray(this.unit), ].join(" ") + "\n"; const size = @@ -372,7 +372,7 @@ export class RangePrompt extends EventEmitter { [ "", this.min, - pc.gray(leftBar) + this.marker + pc.gray(rightBar), + re.gray(leftBar) + this.marker + re.gray(rightBar), this.max, "", ].join(" ") + "\n"; diff --git a/src/rawlist/index.ts b/src/rawlist/index.ts index a65bb9e..5141508 100644 --- a/src/rawlist/index.ts +++ b/src/rawlist/index.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PartialDeep } from "~/types/utils.js"; @@ -110,7 +110,7 @@ const rawlist = createPrompt( } else if (value === "") { setError("Please input a value"); } else { - setError(`"${pc.red(value)}" isn't an available option`); + setError(`"${re.red(value)}" isn't an available option`); } } else { setValue(rl.line); diff --git a/src/search/index.ts b/src/search/index.ts index 3447dfa..061cbbe 100644 --- a/src/search/index.ts +++ b/src/search/index.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PartialDeep } from "~/types/utils.js"; @@ -32,9 +32,9 @@ type SearchTheme = { const searchTheme: SearchTheme = { icon: { cursor: figures.pointer }, style: { - disabled: (text: string) => pc.dim(`- ${text}`), - searchTerm: (text: string) => pc.cyan(text), - description: (text: string) => pc.cyan(text), + disabled: (text: string) => re.dim(`- ${text}`), + searchTerm: (text: string) => re.cyan(text), + description: (text: string) => re.cyan(text), }, helpMode: "auto", }; diff --git a/src/select/index.ts b/src/select/index.ts index f46f651..8181bb7 100644 --- a/src/select/index.ts +++ b/src/select/index.ts @@ -1,5 +1,5 @@ import ansiEscapes from "ansi-escapes"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PartialDeep } from "~/types/utils.js"; @@ -37,8 +37,8 @@ type SelectTheme = { const selectTheme: SelectTheme = { icon: { cursor: figures.pointer }, style: { - disabled: (text: string) => pc.dim(`- ${text}`), - description: (text: string) => pc.cyan(text), + disabled: (text: string) => re.dim(`- ${text}`), + description: (text: string) => re.cyan(text), }, helpMode: "auto", }; diff --git a/src/select/select-main.ts b/src/select/select-main.ts index 2f08355..f7fc938 100644 --- a/src/select/select-main.ts +++ b/src/select/select-main.ts @@ -4,7 +4,7 @@ import { deleteLastLine, symbols } from "@reliverse/relinka"; import { msg, type ColorName, type TypographyName } from "@reliverse/relinka"; import { stdin as input, stdout as output } from "node:process"; import readline from "node:readline"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import terminalSize from "terminal-size"; import { completePrompt } from "~/utils/prompt-end.js"; @@ -119,19 +119,19 @@ function renderPromptUI(params: { if (errorMessage) { msg({ type: "M_ERROR", - title: `${pc.redBright(symbols.step_error)} ${pc.redBright(errorMessage)}`, + title: `${re.redBright(symbols.step_error)} ${re.redBright(errorMessage)}`, }); uiLineCount++; } else if (allDisabled) { msg({ type: "M_ERROR", - title: pc.redBright("All options are disabled."), + title: re.redBright("All options are disabled."), }); uiLineCount++; } else if (displayInstructions && !isRerender) { msg({ type: "M_NULL", - title: pc.blue(instructions), + title: re.blue(instructions), }); uiLineCount++; } @@ -169,7 +169,7 @@ function renderPromptUI(params: { ); if (shouldRenderTopEllipsis) { - msg({ type: "M_NULL", title: pc.dim("...") }); + msg({ type: "M_NULL", title: re.dim("...") }); uiLineCount++; } @@ -189,7 +189,7 @@ function renderPromptUI(params: { const lineSymbol = symbolKey in symbols ? symbols[symbolKey] : "─"; msg({ type: "M_NULL", - title: pc.dim(lineSymbol.repeat(width)), + title: re.dim(lineSymbol.repeat(width)), }); uiLineCount++; continue; @@ -197,16 +197,16 @@ function renderPromptUI(params: { const isSelected = index === selectedIndex; const isDisabled = option.disabled; - const prefix = isSelected ? pc.dim(pc.reset("> ")) : " "; + const prefix = isSelected ? re.dim(re.reset("> ")) : " "; const labelColor = isDisabled - ? pc.dim(pc.reset(option.label)) + ? re.dim(re.reset(option.label)) : isSelected - ? pc.reset(pc.yellow(option.label)) - : pc.reset(option.label); + ? re.reset(re.yellow(option.label)) + : re.reset(option.label); const hint = option.hint - ? pc.reset( - ` (${isDisabled ? pc.dim(option.hint) : pc.italic(pc.dim(option.hint))})`, + ? re.reset( + ` (${isDisabled ? re.dim(option.hint) : re.italic(re.dim(option.hint))})`, ) : ""; @@ -218,7 +218,7 @@ function renderPromptUI(params: { } if (shouldRenderBottomEllipsis) { - msg({ type: "M_NULL", title: pc.dim("...") }); + msg({ type: "M_NULL", title: re.dim("...") }); uiLineCount++; } diff --git a/src/select/select-two.ts b/src/select/select-two.ts index f890ce3..154ae13 100644 --- a/src/select/select-two.ts +++ b/src/select/select-two.ts @@ -2,7 +2,7 @@ import type { Key } from "node:readline"; import { Value } from "@sinclair/typebox/value"; import { stdout } from "node:process"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import type { PromptOptions } from "~/types/general.js"; @@ -54,12 +54,12 @@ export async function selectPrompt( throw new Error("Choices are required for select prompt."); } resetCursorAndClear(stdout, 0, 0); - console.log(pc.cyanBright(pc.bold(coloredTitle))); + console.log(re.cyanBright(re.bold(coloredTitle))); choices.forEach((choice, index) => { const isSelected = index === selectedIndex; - const prefix = isSelected ? pc.green(">") : " "; + const prefix = isSelected ? re.green(">") : " "; const choiceText = isSelected - ? pc.bgGreen(pc.black(choice.title)) + ? re.bgGreen(re.black(choice.title)) : choice.title; console.log(`${prefix} ${choiceText}`); }); diff --git a/src/task/progress.ts b/src/task/progress.ts index 422dac9..2ecd333 100644 --- a/src/task/progress.ts +++ b/src/task/progress.ts @@ -1,4 +1,4 @@ -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { cursor, erase } from "sisteransi"; import type { ProgressBar, ProgressBarOptions } from "./types.js"; @@ -38,7 +38,7 @@ export async function progressTaskPrompt( const filled = state.completeChar.repeat(filledLength); const empty = state.incompleteChar.repeat(emptyLength); - return state.colorize ? pc.green(filled) + pc.red(empty) : filled + empty; + return state.colorize ? re.green(filled) + re.red(empty) : filled + empty; }; const render = async () => { @@ -52,7 +52,7 @@ export async function progressTaskPrompt( .replace(":elapsed", elapsed); process.stdout.write(cursor.move(-999, 0) + erase.line); - process.stdout.write(pc.green("◆") + " " + output); + process.stdout.write(re.green("◆") + " " + output); if (state.current >= state.total) { process.stdout.write("\n"); diff --git a/src/task/spinner.ts b/src/task/spinner.ts index 79a9b71..42f1d4b 100644 --- a/src/task/spinner.ts +++ b/src/task/spinner.ts @@ -2,7 +2,7 @@ import { msg } from "@reliverse/relinka"; import { type SpinnerName } from "cli-spinners"; import process from "node:process"; import ora from "ora"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { cursor, erase } from "sisteransi"; type SimpleSpinnerType = "default" | "dottedCircle" | "boxSpinner"; @@ -59,7 +59,7 @@ export async function spinnerTaskPrompt( }); } catch (error) { oraSpinner.stopAndPersist({ - symbol: pc.red("✖"), + symbol: re.red("✖"), text: errorMessage, }); @@ -102,9 +102,9 @@ export async function spinnerTaskPrompt( } interval = setInterval(() => { - const frame = pc.magenta(frames[frameIndex]); + const frame = re.magenta(frames[frameIndex]); process.stdout.write( - `${cursor.move(-999, 0)}${erase.line}${frame} ${pc.cyan(message)}`, + `${cursor.move(-999, 0)}${erase.line}${frame} ${re.cyan(message)}`, ); frameIndex = (frameIndex + 1) % frames.length; }, delay); @@ -117,7 +117,7 @@ export async function spinnerTaskPrompt( interval = null; process.stdout.write( - `\r${erase.line}${pc.green("✔")} ${successMessage}\n`, + `\r${erase.line}${re.green("✔")} ${successMessage}\n`, ); msg({ @@ -131,7 +131,7 @@ export async function spinnerTaskPrompt( } process.stdout.write( - `\r${erase.line}${pc.red("✖")} ${ + `\r${erase.line}${re.red("✖")} ${ error instanceof Error ? errorMessage : "An unknown error occurred." }\n`, ); diff --git a/src/task/task.ts b/src/task/task.ts index 24f29b4..41dcec7 100644 --- a/src/task/task.ts +++ b/src/task/task.ts @@ -1,12 +1,12 @@ import type { Options } from "p-map"; import { msg } from "@reliverse/relinka"; +import { EventEmitter } from "node:events"; import process from "node:process"; import ora from "ora"; import pMap from "p-map"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { cursor, erase } from "sisteransi"; -import { proxy, subscribe } from "valtio"; import type { ProgressBar } from "~/task/types.js"; @@ -157,6 +157,9 @@ function arrayRemove(array: T[], element: T) { } } +// Create a simple event emitter for state changes +const stateEmitter = new EventEmitter(); + function registerTask( taskList: TaskList, taskTitle: string, @@ -185,8 +188,8 @@ function registerTask( task.cancelToken = cancelToken; - // Subscribe to state changes for timing information - subscribe(task, () => { + // Replace valtio subscribe with event emitter + const handleStateChange = () => { if (task.state === "loading" && !task.startTime) { task.startTime = Date.now(); } else if ( @@ -197,7 +200,9 @@ function registerTask( task.endTime = Date.now(); task.duration = task.endTime - task.startTime; } - }); + }; + + stateEmitter.on(`stateChange:${task.id}`, handleStateChange); // Set up spinner const frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"]; @@ -230,8 +235,8 @@ function registerTask( const frames = spinnerType ? simpleSpinners[spinnerType] : simpleSpinners.default; - const currentFrame = pc.magenta(frames[frameIndex]); - process.stdout.write(`${currentFrame} ${pc.cyan(task.title)}`); + const currentFrame = re.magenta(frames[frameIndex]); + process.stdout.write(`${currentFrame} ${re.cyan(task.title)}`); if (task.status) { process.stdout.write(` - ${task.status}`); } @@ -275,25 +280,25 @@ function registerTask( // Write status with proper styling if (task.state === "success") { process.stdout.write( - `${statusIcon} ${pc.cyan(task.title)}${task.status ? ` - ${pc.greenBright(task.status)}` : ""}\n`, + `${statusIcon} ${re.cyan(task.title)}${task.status ? ` - ${re.greenBright(task.status)}` : ""}\n`, ); } else if (task.state === "error" || task.state === "cancelled") { process.stdout.write( - `${statusIcon} ${pc.cyan(task.title)}${task.status ? ` - ${pc.red(task.status)}` : ""}\n`, + `${statusIcon} ${re.cyan(task.title)}${task.status ? ` - ${re.red(task.status)}` : ""}\n`, ); if (task.error?.message) { - process.stdout.write(` ${pc.red(task.error.message)}\n`); + process.stdout.write(` ${re.red(task.error.message)}\n`); } } else { process.stdout.write( - `${statusIcon} ${pc.cyan(task.title)}${task.status ? ` - ${task.status}` : ""}\n`, + `${statusIcon} ${re.cyan(task.title)}${task.status ? ` - ${task.status}` : ""}\n`, ); } } }; - // Start spinner when task starts - subscribe(task, () => { + // Start spinner when task state changes + stateEmitter.on(`stateChange:${task.id}`, () => { if (task.state === "loading" && !interval) { interval = setInterval(() => { frameIndex = (frameIndex + 1) % frames.length; @@ -309,6 +314,7 @@ function registerTask( async [runSymbol]() { const api = createTaskInnerApi(task); task.state = "loading"; + stateEmitter.emit(`stateChange:${task.id}`); try { if (cancelToken.signal.aborted) { @@ -342,6 +348,7 @@ function registerTask( } catch (error) { if (cancelToken.signal.aborted) { task.state = "cancelled"; + stateEmitter.emit(`stateChange:${task.id}`); } else if (error instanceof Error) { api.setError(error); } else { @@ -351,22 +358,26 @@ function registerTask( process.exit(1); } throw error; + } finally { + stateEmitter.removeAllListeners(`stateChange:${task.id}`); } }, clear() { clearLine(); arrayRemove(taskList, task); + stateEmitter.removeAllListeners(`stateChange:${task.id}`); }, cancel() { clearLine(); cancelToken.abort(); task.state = "cancelled"; + stateEmitter.emit(`stateChange:${task.id}`); }, }; } -// Create and export the root task list and default task function -const rootTaskList = proxy([]); +// Create and export the root task list without valtio proxy +const rootTaskList: TaskList = []; // Add a task state manager const taskStateManager = new Map(); @@ -522,9 +533,11 @@ const createTaskInnerApi = (taskState: TaskObject): TaskInnerAPI => { task: advancedTaskPrompt(taskState.children), setTitle(title) { taskState.title = title; + stateEmitter.emit(`stateChange:${taskState.id}`); }, setStatus(status) { taskState.status = status; + stateEmitter.emit(`stateChange:${taskState.id}`); }, setOutput(output) { taskState.output = @@ -533,6 +546,7 @@ const createTaskInnerApi = (taskState: TaskObject): TaskInnerAPI => { : "message" in output ? output.message : ""; + stateEmitter.emit(`stateChange:${taskState.id}`); }, setWarning(warning) { taskState.state = "warning"; @@ -542,6 +556,7 @@ const createTaskInnerApi = (taskState: TaskObject): TaskInnerAPI => { taskState.error = warning; } } + stateEmitter.emit(`stateChange:${taskState.id}`); }, setError(error) { taskState.state = "error"; @@ -551,9 +566,11 @@ const createTaskInnerApi = (taskState: TaskObject): TaskInnerAPI => { taskState.error = error; } } + stateEmitter.emit(`stateChange:${taskState.id}`); }, setProgress(progress) { taskState.progress = progress; + stateEmitter.emit(`stateChange:${taskState.id}`); }, updateProgress(current: number, total?: number, message?: string) { const currentProgress = taskState.progress || { current: 0, total: 100 }; @@ -562,11 +579,13 @@ const createTaskInnerApi = (taskState: TaskObject): TaskInnerAPI => { total: total ?? currentProgress.total, message: message ?? currentProgress.message, }; + stateEmitter.emit(`stateChange:${taskState.id}`); }, cancel() { if (taskState.cancelToken) { taskState.cancelToken.abort(); taskState.state = "cancelled"; + stateEmitter.emit(`stateChange:${taskState.id}`); } }, isCancelled() { @@ -612,7 +631,7 @@ export async function spinnerTask(options: SpinnerTaskOptions): Promise { oraSpinner.stop(); } catch (error) { oraSpinner.stopAndPersist({ - symbol: pc.red("✖"), + symbol: re.red("✖"), text: errorMessage, }); @@ -656,9 +675,9 @@ export async function spinnerTask(options: SpinnerTaskOptions): Promise { } interval = setInterval(() => { - const frame = pc.magenta(frames[frameIndex]); + const frame = re.magenta(frames[frameIndex]); process.stdout.write( - `${cursor.move(-999, 0)}${erase.line}${frame} ${pc.cyan(message)}`, + `${cursor.move(-999, 0)}${erase.line}${frame} ${re.cyan(message)}`, ); frameIndex = (frameIndex + 1) % frames.length; }, delay); @@ -675,7 +694,7 @@ export async function spinnerTask(options: SpinnerTaskOptions): Promise { } process.stdout.write( - `\r${erase.line}${pc.red("✖")} ${ + `\r${erase.line}${re.red("✖")} ${ error instanceof Error ? errorMessage : "An unknown error occurred." }\n`, ); diff --git a/src/toggle/index.ts b/src/toggle/index.ts index cb1a503..51ca037 100644 --- a/src/toggle/index.ts +++ b/src/toggle/index.ts @@ -8,7 +8,7 @@ import type { VariantName } from "@reliverse/relinka"; import { deleteLastLine, msg } from "@reliverse/relinka"; import { stdin as input, stdout as output } from "node:process"; import readline from "node:readline"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import { completePrompt } from "~/utils/prompt-end.js"; @@ -99,22 +99,22 @@ function renderTogglePrompt(params: { if (errorMessage) { msg({ type: "M_NULL", - title: pc.redBright(errorMessage), + title: re.redBright(errorMessage), }); uiLineCount++; } else if (displayInstructions && !isRerender) { msg({ type: "M_NULL", - title: pc.yellow(instructions), + title: re.yellow(instructions), }); uiLineCount++; } const displayString = options .map((option, index) => - index === selectedIndex ? pc.yellow(option) : pc.reset(option), + index === selectedIndex ? re.yellow(option) : re.reset(option), ) - .join(pc.dim(pc.reset(" / "))); + .join(re.dim(re.reset(" / "))); msg({ type: "M_NULL", title: displayString }); uiLineCount++; diff --git a/src/utils/color.ts b/src/utils/color.ts index 3b97a52..e2d5bf3 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -127,7 +127,7 @@ export type ColorFunction = (text: string | number) => string; * Creates an object that maps color names to their respective color functions, * based on whether or not color support is enabled. * @param {boolean} [useColor=isColorSupported] - Specifies whether to use color functions or fallback to plain strings. - * @returns {Record} An object where keys are color names and values are functions to apply those pc. See {@link ColorFunction}. + * @returns {Record} An object where keys are color names and values are functions to apply those re. See {@link ColorFunction}. */ function createColors(useColor = isColorSupported) { return useColor @@ -136,7 +136,7 @@ function createColors(useColor = isColorSupported) { } /** - * An object containing functions for coloring text. Each function corresponds to a terminal color. See {@link ColorName} for available pc. + * An object containing functions for coloring text. Each function corresponds to a terminal color. See {@link ColorName} for available re. */ export const colors = createColors() as Record< DeprecatedColorName, diff --git a/src/utils/colorize.ts b/src/utils/colorize.ts index 98a0be1..a4266e7 100644 --- a/src/utils/colorize.ts +++ b/src/utils/colorize.ts @@ -1,5 +1,6 @@ import type { ColorName, TypographyName } from "@reliverse/relinka"; +import { re } from "@reliverse/relico"; import gradient, { cristal, mind, @@ -7,11 +8,10 @@ import gradient, { rainbow, vice, } from "gradient-string"; -import pc from "picocolors"; -// Strip ANSI color codes using picocolors +// Strip ANSI color codes using @reliverse/relico function stripAnsi(text: string): string { - return pc.reset(text); + return re.reset(text); } export function colorize( @@ -65,61 +65,61 @@ export function colorize( // Handle regular colors switch (colorName) { case "inverse": - result = pc.inverse(` ${result} `); + result = re.inverse(` ${result} `); break; case "dim": - result = pc.dim(result); + result = re.dim(result); break; case "black": - result = pc.black(result); + result = re.black(result); break; case "red": - result = pc.red(result); + result = re.red(result); break; case "redBright": - result = pc.redBright(result); + result = re.redBright(result); break; case "green": - result = pc.green(result); + result = re.green(result); break; case "greenBright": - result = pc.greenBright(result); + result = re.greenBright(result); break; case "yellow": - result = pc.yellow(result); + result = re.yellow(result); break; case "yellowBright": - result = pc.yellowBright(result); + result = re.yellowBright(result); break; case "blue": - result = pc.blue(result); + result = re.blue(result); break; case "blueBright": - result = pc.blueBright(result); + result = re.blueBright(result); break; case "magenta": - result = pc.magenta(result); + result = re.magenta(result); break; case "magentaBright": - result = pc.magentaBright(result); + result = re.magentaBright(result); break; case "cyan": - result = pc.cyan(result); + result = re.cyan(result); break; case "cyanBright": - result = pc.cyanBright(result); + result = re.cyanBright(result); break; case "bgCyan": - result = pc.bgCyan(` ${result} `); + result = re.bgCyan(` ${result} `); break; case "bgCyanBright": - result = pc.bgCyanBright(` ${result} `); + result = re.bgCyanBright(` ${result} `); break; case "white": - result = pc.white(result); + result = re.white(result); break; case "gray": - result = pc.gray(result); + result = re.gray(result); break; case "none": break; @@ -132,16 +132,16 @@ export function colorize( if (typography) { switch (typography) { case "bold": - result = pc.bold(result); + result = re.bold(result); break; case "strikethrough": - result = pc.strikethrough(result); + result = re.strikethrough(result); break; case "underline": - result = pc.underline(result); + result = re.underline(result); break; case "italic": - result = pc.italic(result); + result = re.italic(result); break; default: break; diff --git a/src/utils/component.ts b/src/utils/component.ts index 7ccee18..1d8b9a3 100644 --- a/src/utils/component.ts +++ b/src/utils/component.ts @@ -1,5 +1,5 @@ +import { re } from "@reliverse/relico"; import { isUnicodeSupported } from "@reliverse/relinka"; -import pc from "picocolors"; import { cursor, erase } from "sisteransi"; import type { State } from "~/types/general.js"; @@ -48,13 +48,13 @@ const symbol = (state: State) => { switch (state) { case "initial": case "active": - return pc.cyan(S_STEP_ACTIVE); + return re.cyan(S_STEP_ACTIVE); case "cancel": - return pc.red(S_STEP_CANCEL); + return re.red(S_STEP_CANCEL); case "error": - return pc.yellow(S_STEP_ERROR); + return re.yellow(S_STEP_ERROR); case "submit": - return pc.green(S_STEP_SUBMIT); + return re.green(S_STEP_SUBMIT); } }; @@ -97,7 +97,7 @@ const limitOptions = ( const isTopLimit = i === 0 && shouldRenderTopEllipsis; const isBottomLimit = i === arr.length - 1 && shouldRenderBottomEllipsis; return isTopLimit || isBottomLimit - ? pc.dim("...") + ? re.dim("...") : style(option, i + slidingWindowLocation === cursor); }); }; @@ -116,25 +116,25 @@ export const text = (opts: TextOptions) => { defaultValue: opts.defaultValue, initialValue: opts.initialValue, render() { - const title = `${pc.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const title = `${re.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; const placeholder = opts.placeholder - ? pc.inverse(opts.placeholder[0]) + pc.dim(opts.placeholder.slice(1)) - : pc.inverse(pc.hidden("_")); + ? re.inverse(opts.placeholder[0]) + re.dim(opts.placeholder.slice(1)) + : re.inverse(re.hidden("_")); const value = !this.value ? placeholder : this.valueWithCursor; switch (this.state) { case "error": - return `${title.trim()}\n${pc.yellow(S_BAR)} ${value}\n${pc.yellow( + return `${title.trim()}\n${re.yellow(S_BAR)} ${value}\n${re.yellow( S_BAR_END, - )} ${pc.yellow(this.error)}\n`; + )} ${re.yellow(this.error)}\n`; case "submit": - return `${title}${pc.gray(S_BAR)} ${pc.dim(this.value || opts.placeholder)}`; + return `${title}${re.gray(S_BAR)} ${re.dim(this.value || opts.placeholder)}`; case "cancel": - return `${title}${pc.gray(S_BAR)} ${pc.strikethrough( - pc.dim(this.value ?? ""), - )}${this.value?.trim() ? `\n${pc.gray(S_BAR)}` : ""}`; + return `${title}${re.gray(S_BAR)} ${re.strikethrough( + re.dim(this.value ?? ""), + )}${this.value?.trim() ? `\n${re.gray(S_BAR)}` : ""}`; default: - return `${title}${pc.cyan(S_BAR)} ${value}\n${pc.cyan(S_BAR_END)}\n`; + return `${title}${re.cyan(S_BAR)} ${value}\n${re.cyan(S_BAR_END)}\n`; } }, }).prompt(); @@ -154,26 +154,26 @@ export const confirm = (opts: ConfirmOptions) => { inactive, initialValue: opts.initialValue ?? true, render() { - const title = `${pc.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const title = `${re.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; const value = this.value ? active : inactive; switch (this.state) { case "submit": - return `${title}${pc.gray(S_BAR)} ${pc.dim(value)}`; + return `${title}${re.gray(S_BAR)} ${re.dim(value)}`; case "cancel": - return `${title}${pc.gray(S_BAR)} ${pc.strikethrough( - pc.dim(value), - )}\n${pc.gray(S_BAR)}`; + return `${title}${re.gray(S_BAR)} ${re.strikethrough( + re.dim(value), + )}\n${re.gray(S_BAR)}`; default: { - return `${title}${pc.cyan(S_BAR)} ${ + return `${title}${re.cyan(S_BAR)} ${ this.value - ? `${pc.green(S_RADIO_ACTIVE)} ${active}` - : `${pc.dim(S_RADIO_INACTIVE)} ${pc.dim(active)}` - } ${pc.dim("/")} ${ + ? `${re.green(S_RADIO_ACTIVE)} ${active}` + : `${re.dim(S_RADIO_INACTIVE)} ${re.dim(active)}` + } ${re.dim("/")} ${ !this.value - ? `${pc.green(S_RADIO_ACTIVE)} ${inactive}` - : `${pc.dim(S_RADIO_INACTIVE)} ${pc.dim(inactive)}` - }\n${pc.cyan(S_BAR_END)}\n`; + ? `${re.green(S_RADIO_ACTIVE)} ${inactive}` + : `${re.dim(S_RADIO_INACTIVE)} ${re.dim(inactive)}` + }\n${re.cyan(S_BAR_END)}\n`; } } }, @@ -201,15 +201,15 @@ export const select = (opts: SelectOptions) => { const label = option.label ?? String(option.value); switch (state) { case "selected": - return pc.dim(label); + return re.dim(label); case "active": - return `${pc.green(S_RADIO_ACTIVE)} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.green(S_RADIO_ACTIVE)} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; case "cancelled": - return pc.strikethrough(pc.dim(label)); + return re.strikethrough(re.dim(label)); default: - return `${pc.dim(S_RADIO_INACTIVE)} ${pc.dim(label)}`; + return `${re.dim(S_RADIO_INACTIVE)} ${re.dim(label)}`; } }; @@ -217,23 +217,23 @@ export const select = (opts: SelectOptions) => { options: opts.options, initialValue: opts.initialValue, render() { - const title = `${pc.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const title = `${re.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; switch (this.state) { case "submit": - return `${title}${pc.gray(S_BAR)} ${opt(this.options[this.cursor], "selected")}`; + return `${title}${re.gray(S_BAR)} ${opt(this.options[this.cursor], "selected")}`; case "cancel": - return `${title}${pc.gray(S_BAR)} ${opt( + return `${title}${re.gray(S_BAR)} ${opt( this.options[this.cursor], "cancelled", - )}\n${pc.gray(S_BAR)}`; + )}\n${re.gray(S_BAR)}`; default: { - return `${title}${pc.cyan(S_BAR)} ${limitOptions({ + return `${title}${re.cyan(S_BAR)} ${limitOptions({ cursor: this.cursor, options: this.options, maxItems: opts.maxItems, style: (item, active) => opt(item, active ? "active" : "inactive"), - }).join(`\n${pc.cyan(S_BAR)} `)}\n${pc.cyan(S_BAR_END)}\n`; + }).join(`\n${re.cyan(S_BAR)} `)}\n${re.cyan(S_BAR_END)}\n`; } } }, @@ -247,16 +247,16 @@ export const selectKey = (opts: SelectOptions) => { ) => { const label = option.label ?? String(option.value); if (state === "selected") { - return pc.dim(label); + return re.dim(label); } else if (state === "cancelled") { - return pc.strikethrough(pc.dim(label)); + return re.strikethrough(re.dim(label)); } else if (state === "active") { - return `${pc.bgCyan(pc.gray(` ${option.value} `))} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.bgCyan(re.gray(` ${option.value} `))} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; } - return `${pc.gray(pc.bgWhite(pc.inverse(` ${option.value} `)))} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.gray(re.bgWhite(re.inverse(` ${option.value} `)))} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; }; @@ -264,24 +264,24 @@ export const selectKey = (opts: SelectOptions) => { options: opts.options, initialValue: opts.initialValue, render() { - const title = `${pc.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const title = `${re.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; switch (this.state) { case "submit": - return `${title}${pc.gray(S_BAR)} ${opt( + return `${title}${re.gray(S_BAR)} ${opt( this.options.find((opt) => opt.value === this.value), "selected", )}`; case "cancel": - return `${title}${pc.gray(S_BAR)} ${opt(this.options[0], "cancelled")}\n${pc.gray( + return `${title}${re.gray(S_BAR)} ${opt(this.options[0], "cancelled")}\n${re.gray( S_BAR, )}`; default: { - return `${title}${pc.cyan(S_BAR)} ${this.options + return `${title}${re.cyan(S_BAR)} ${this.options .map((option, i) => opt(option, i === this.cursor ? "active" : "inactive"), ) - .join(`\n${pc.cyan(S_BAR)} `)}\n${pc.cyan(S_BAR_END)}\n`; + .join(`\n${re.cyan(S_BAR)} `)}\n${re.cyan(S_BAR_END)}\n`; } } }, @@ -309,21 +309,21 @@ export const multiselect = (opts: MultiSelectOptions) => { ) => { const label = option.label ?? String(option.value); if (state === "active") { - return `${pc.cyan(S_CHECKBOX_ACTIVE)} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.cyan(S_CHECKBOX_ACTIVE)} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; } else if (state === "selected") { - return `${pc.green(S_CHECKBOX_SELECTED)} ${pc.dim(label)}`; + return `${re.green(S_CHECKBOX_SELECTED)} ${re.dim(label)}`; } else if (state === "cancelled") { - return pc.strikethrough(pc.dim(label)); + return re.strikethrough(re.dim(label)); } else if (state === "active-selected") { - return `${pc.green(S_CHECKBOX_SELECTED)} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.green(S_CHECKBOX_SELECTED)} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; } else if (state === "submitted") { - return pc.dim(label); + return re.dim(label); } - return `${pc.dim(S_CHECKBOX_INACTIVE)} ${pc.dim(label)}`; + return `${re.dim(S_CHECKBOX_INACTIVE)} ${re.dim(label)}`; }; return new MultiSelectPrompt({ @@ -332,7 +332,7 @@ export const multiselect = (opts: MultiSelectOptions) => { required: opts.required ?? true, cursorAt: opts.cursorAt, render() { - const title = `${pc.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const title = `${re.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; const styleOption = (option: Option, active: boolean) => { const selected = this.value.includes(option.value); @@ -347,20 +347,20 @@ export const multiselect = (opts: MultiSelectOptions) => { switch (this.state) { case "submit": { - return `${title}${pc.gray(S_BAR)} ${ + return `${title}${re.gray(S_BAR)} ${ this.options .filter(({ value }) => this.value.includes(value)) .map((option) => opt(option, "submitted")) - .join(pc.dim(", ")) || pc.dim("none") + .join(re.dim(", ")) || re.dim("none") }`; } case "cancel": { const label = this.options .filter(({ value }) => this.value.includes(value)) .map((option) => opt(option, "cancelled")) - .join(pc.dim(", ")); - return `${title}${pc.gray(S_BAR)} ${ - label.trim() ? `${label}\n${pc.gray(S_BAR)}` : "" + .join(re.dim(", ")); + return `${title}${re.gray(S_BAR)} ${ + label.trim() ? `${label}\n${re.gray(S_BAR)}` : "" }`; } case "error": { @@ -368,24 +368,24 @@ export const multiselect = (opts: MultiSelectOptions) => { .split("\n") .map((ln, i) => i === 0 - ? `${pc.yellow(S_BAR_END)} ${pc.yellow(ln)}` + ? `${re.yellow(S_BAR_END)} ${re.yellow(ln)}` : ` ${ln}`, ) .join("\n"); - return `${title + pc.yellow(S_BAR)} ${limitOptions({ + return `${title + re.yellow(S_BAR)} ${limitOptions({ options: this.options, cursor: this.cursor, maxItems: opts.maxItems, style: styleOption, - }).join(`\n${pc.yellow(S_BAR)} `)}\n${footer}\n`; + }).join(`\n${re.yellow(S_BAR)} `)}\n${footer}\n`; } default: { - return `${title}${pc.cyan(S_BAR)} ${limitOptions({ + return `${title}${re.cyan(S_BAR)} ${limitOptions({ options: this.options, cursor: this.cursor, maxItems: opts.maxItems, style: styleOption, - }).join(`\n${pc.cyan(S_BAR)} `)}\n${pc.cyan(S_BAR_END)}\n`; + }).join(`\n${re.cyan(S_BAR)} `)}\n${re.cyan(S_BAR_END)}\n`; } } }, @@ -423,25 +423,25 @@ export const groupMultiselect = ( const prefix = isItem ? `${isLast ? S_BAR_END : S_BAR} ` : ""; if (state === "active") { - return `${pc.dim(prefix)}${pc.cyan(S_CHECKBOX_ACTIVE)} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.dim(prefix)}${re.cyan(S_CHECKBOX_ACTIVE)} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; } else if (state === "group-active") { - return `${prefix}${pc.cyan(S_CHECKBOX_ACTIVE)} ${pc.dim(label)}`; + return `${prefix}${re.cyan(S_CHECKBOX_ACTIVE)} ${re.dim(label)}`; } else if (state === "group-active-selected") { - return `${prefix}${pc.green(S_CHECKBOX_SELECTED)} ${pc.dim(label)}`; + return `${prefix}${re.green(S_CHECKBOX_SELECTED)} ${re.dim(label)}`; } else if (state === "selected") { - return `${pc.dim(prefix)}${pc.green(S_CHECKBOX_SELECTED)} ${pc.dim(label)}`; + return `${re.dim(prefix)}${re.green(S_CHECKBOX_SELECTED)} ${re.dim(label)}`; } else if (state === "cancelled") { - return pc.strikethrough(pc.dim(label)); + return re.strikethrough(re.dim(label)); } else if (state === "active-selected") { - return `${pc.dim(prefix)}${pc.green(S_CHECKBOX_SELECTED)} ${label} ${ - option.hint ? pc.dim(`(${option.hint})`) : "" + return `${re.dim(prefix)}${re.green(S_CHECKBOX_SELECTED)} ${label} ${ + option.hint ? re.dim(`(${option.hint})`) : "" }`; } else if (state === "submitted") { - return pc.dim(label); + return re.dim(label); } - return `${pc.dim(prefix)}${pc.dim(S_CHECKBOX_INACTIVE)} ${pc.dim(label)}`; + return `${re.dim(prefix)}${re.dim(S_CHECKBOX_INACTIVE)} ${re.dim(label)}`; }; return new GroupMultiSelectPrompt({ @@ -450,22 +450,22 @@ export const groupMultiselect = ( required: opts.required ?? true, cursorAt: opts.cursorAt, render() { - const title = `${pc.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; + const title = `${re.gray(S_BAR)}\n${symbol(this.state)} ${opts.message}\n`; switch (this.state) { case "submit": { - return `${title}${pc.gray(S_BAR)} ${this.options + return `${title}${re.gray(S_BAR)} ${this.options .filter(({ value }) => this.value.includes(value)) .map((option) => opt(option, "submitted")) - .join(pc.dim(", "))}`; + .join(re.dim(", "))}`; } case "cancel": { const label = this.options .filter(({ value }) => this.value.includes(value)) .map((option) => opt(option, "cancelled")) - .join(pc.dim(", ")); - return `${title}${pc.gray(S_BAR)} ${ - label.trim() ? `${label}\n${pc.gray(S_BAR)}` : "" + .join(re.dim(", ")); + return `${title}${re.gray(S_BAR)} ${ + label.trim() ? `${label}\n${re.gray(S_BAR)}` : "" }`; } case "error": { @@ -473,11 +473,11 @@ export const groupMultiselect = ( .split("\n") .map((ln, i) => i === 0 - ? `${pc.yellow(S_BAR_END)} ${pc.yellow(ln)}` + ? `${re.yellow(S_BAR_END)} ${re.yellow(ln)}` : ` ${ln}`, ) .join("\n"); - return `${title}${pc.yellow(S_BAR)} ${this.options + return `${title}${re.yellow(S_BAR)} ${this.options .map((option, i, options) => { const selected = this.value.includes(option.value) || @@ -503,10 +503,10 @@ export const groupMultiselect = ( } return opt(option, active ? "active" : "inactive", options); }) - .join(`\n${pc.yellow(S_BAR)} `)}\n${footer}\n`; + .join(`\n${re.yellow(S_BAR)} `)}\n${footer}\n`; } default: { - return `${title}${pc.cyan(S_BAR)} ${this.options + return `${title}${re.cyan(S_BAR)} ${this.options .map((option, i, options) => { const selected = this.value.includes(option.value) || @@ -532,7 +532,7 @@ export const groupMultiselect = ( } return opt(option, active ? "active" : "inactive", options); }) - .join(`\n${pc.cyan(S_BAR)} `)}\n${pc.cyan(S_BAR_END)}\n`; + .join(`\n${re.cyan(S_BAR)} `)}\n${re.cyan(S_BAR_END)}\n`; } } }, @@ -554,29 +554,29 @@ export const note = (message = "", title = "") => { const msg = lines .map( (ln) => - `${pc.gray(S_BAR)} ${pc.dim(ln)}${" ".repeat(len - strip(ln).length)}${pc.gray( + `${re.gray(S_BAR)} ${re.dim(ln)}${" ".repeat(len - strip(ln).length)}${re.gray( S_BAR, )}`, ) .join("\n"); process.stdout.write( - `${pc.gray(S_BAR)}\n${pc.green(S_STEP_SUBMIT)} ${pc.reset(title)} ${pc.gray( + `${re.gray(S_BAR)}\n${re.green(S_STEP_SUBMIT)} ${re.reset(title)} ${re.gray( S_BAR_H.repeat(Math.max(len - titleLen - 1, 1)) + S_CORNER_TOP_RIGHT, - )}\n${msg}\n${pc.gray(S_CONNECT_LEFT + S_BAR_H.repeat(len + 2) + S_CORNER_BOTTOM_RIGHT)}\n`, + )}\n${msg}\n${re.gray(S_CONNECT_LEFT + S_BAR_H.repeat(len + 2) + S_CORNER_BOTTOM_RIGHT)}\n`, ); }; export const cancel = (message = "") => { - process.stdout.write(`${pc.gray(S_BAR_END)} ${pc.red(message)}\n\n`); + process.stdout.write(`${re.gray(S_BAR_END)} ${re.red(message)}\n\n`); }; export const intro = (title = "") => { - process.stdout.write(`${pc.gray(S_BAR_START)} ${title}\n`); + process.stdout.write(`${re.gray(S_BAR_START)} ${title}\n`); }; export const outro = (message = "") => { process.stdout.write( - `${pc.gray(S_BAR)}\n${pc.gray(S_BAR_END)} ${message}\n\n`, + `${re.gray(S_BAR)}\n${re.gray(S_BAR_END)} ${message}\n\n`, ); }; @@ -586,36 +586,36 @@ export type LogMessageOptions = { export const log = { message: ( message = "", - { symbol = pc.gray(S_BAR) }: LogMessageOptions = {}, + { symbol = re.gray(S_BAR) }: LogMessageOptions = {}, ) => { - const parts = [pc.gray(S_BAR)]; + const parts = [re.gray(S_BAR)]; if (message) { const [firstLine, ...lines] = message.split("\n"); parts.push( `${symbol} ${firstLine}`, - ...lines.map((ln) => `${pc.gray(S_BAR)} ${ln}`), + ...lines.map((ln) => `${re.gray(S_BAR)} ${ln}`), ); } process.stdout.write(`${parts.join("\n")}\n`); }, info: (message: string) => { - log.message(message, { symbol: pc.blue(S_INFO) }); + log.message(message, { symbol: re.blue(S_INFO) }); }, success: (message: string) => { - log.message(message, { symbol: pc.green(S_SUCCESS) }); + log.message(message, { symbol: re.green(S_SUCCESS) }); }, step: (message: string) => { - log.message(message, { symbol: pc.green(S_STEP_SUBMIT) }); + log.message(message, { symbol: re.green(S_STEP_SUBMIT) }); }, warn: (message: string) => { - log.message(message, { symbol: pc.yellow(S_WARN) }); + log.message(message, { symbol: re.yellow(S_WARN) }); }, /** alias for `log.warn()`. */ warning: (message: string) => { log.warn(message); }, error: (message: string) => { - log.message(message, { symbol: pc.red(S_ERROR) }); + log.message(message, { symbol: re.red(S_ERROR) }); }, }; @@ -665,14 +665,14 @@ export const spinner = () => { isSpinnerActive = true; unblock = block(); _message = msg.replace(/\.+$/, ""); - process.stdout.write(`${pc.gray(S_BAR)}\n`); + process.stdout.write(`${re.gray(S_BAR)}\n`); let frameIndex = 0; let dotsTimer = 0; registerHooks(); // @ts-expect-error TODO: fix ts loop = setInterval(() => { - const frame = pc.magenta(frames[frameIndex]); + const frame = re.magenta(frames[frameIndex]); const loadingDots = ".".repeat(Math.floor(dotsTimer)).slice(0, 3); process.stdout.write(cursor.move(-999, 0)); process.stdout.write(erase.down(1)); @@ -688,10 +688,10 @@ export const spinner = () => { clearInterval(loop); const step = code === 0 - ? pc.green(S_STEP_SUBMIT) + ? re.green(S_STEP_SUBMIT) : code === 1 - ? pc.red(S_STEP_CANCEL) - : pc.red(S_STEP_ERROR); + ? re.red(S_STEP_CANCEL) + : re.red(S_STEP_ERROR); process.stdout.write(cursor.move(-999, 0)); process.stdout.write(erase.down(1)); process.stdout.write(`${step} ${_message}\n`); diff --git a/src/utils/prevent.ts b/src/utils/prevent.ts index bf44dcd..7fc10c3 100644 --- a/src/utils/prevent.ts +++ b/src/utils/prevent.ts @@ -3,7 +3,7 @@ import { getTerminalWidth, msg, } from "@reliverse/relinka"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; import terminalSize from "terminal-size"; export type PreventWrongTerminalSizeOptions = { @@ -43,7 +43,7 @@ export async function preventWrongTerminalSize({ if (errors.length > 0) { msg({ type: "M_ERROR", - title: pc.redBright(errors.join("\n││ ")), + title: re.redBright(errors.join("\n││ ")), content: size.rows >= 7 && terminalWidth >= 70 ? sizeErrorDescription : "", contentColor: "redBright", diff --git a/src/utils/prompt-end.ts b/src/utils/prompt-end.ts index 83c897a..e84b266 100644 --- a/src/utils/prompt-end.ts +++ b/src/utils/prompt-end.ts @@ -7,7 +7,7 @@ import { type ColorName, type TypographyName, } from "@reliverse/relinka"; -import pc from "picocolors"; +import { re } from "@reliverse/relico"; /** * Ends the prompt by optionally displaying an end message and running the action if confirmed. @@ -66,14 +66,14 @@ export async function completePrompt( export function renderEndLine() { const lineLength = getExactTerminalWidth() - 2; - console.log(pc.dim(symbols.middle)); - console.log(pc.dim(`${symbols.end}${symbols.line.repeat(lineLength)}⊱`)); + console.log(re.dim(symbols.middle)); + console.log(re.dim(`${symbols.end}${symbols.line.repeat(lineLength)}⊱`)); console.log(); } export function renderEndLineInput() { const lineLength = getExactTerminalWidth() - 2; console.log(); - console.log(pc.dim(`${symbols.end}${symbols.line.repeat(lineLength)}⊱`)); + console.log(re.dim(`${symbols.end}${symbols.line.repeat(lineLength)}⊱`)); console.log(); } diff --git a/src/utils/system.ts b/src/utils/system.ts index b833a00..78ed749 100644 --- a/src/utils/system.ts +++ b/src/utils/system.ts @@ -4,7 +4,7 @@ export const pm = await detect(); export const pmv = await getNpmVersion(pm); export const pkg = { name: "@reliverse/prompts", - version: "1.4.7", + version: "1.4.9", description: "@reliverse/prompts is a powerful library that enables seamless, typesafe, and resilient prompts for command-line applications. Crafted with simplicity and elegance, it provides developers with an intuitive and robust way to build interactive CLIs.", };