@ls-stack/cli 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.mjs","names":[],"sources":["../src/cliInput.ts","../node_modules/.pnpm/@ls-stack+utils@3.68.0/node_modules/@ls-stack/utils/dist/assertions-CsE3pD8P.mjs","../node_modules/.pnpm/@ls-stack+utils@3.68.0/node_modules/@ls-stack/utils/dist/arrayUtils.mjs","../node_modules/.pnpm/@ls-stack+utils@3.68.0/node_modules/@ls-stack/utils/dist/dedent.mjs","../node_modules/.pnpm/@ls-stack+utils@3.68.0/node_modules/@ls-stack/utils/dist/stringUtils-DEEj_Z1p.mjs","../node_modules/.pnpm/@ls-stack+utils@3.68.0/node_modules/@ls-stack/utils/dist/typingFnUtils-BLxmDUp5.mjs","../src/createCli.ts"],"sourcesContent":["import {\n checkbox,\n confirm,\n input,\n number,\n search,\n select,\n} from '@inquirer/prompts';\nimport * as readline from 'readline';\n\nfunction isUserCancellation(e: unknown): boolean {\n return (\n e instanceof Error &&\n (e.name === 'ExitPromptError' ||\n e.name === 'AbortError' ||\n e.name === 'AbortPromptError')\n );\n}\n\nfunction handlePromptError(e: unknown): never {\n if (isUserCancellation(e)) {\n process.exit(0);\n }\n\n console.error(e);\n process.exit(1);\n}\n\nfunction createEscapeAbortController(): {\n signal: AbortSignal;\n cleanup: () => void;\n} {\n const controller = new AbortController();\n\n readline.emitKeypressEvents(process.stdin);\n\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n }\n\n function onKeypress(_: string, key: readline.Key) {\n if (key.name === 'escape') {\n controller.abort();\n }\n }\n\n process.stdin.on('keypress', onKeypress);\n\n function cleanup() {\n process.stdin.removeListener('keypress', onKeypress);\n }\n\n return { signal: controller.signal, cleanup };\n}\n\nasync function withEscapeSupport<T>(\n promptFn: (signal: AbortSignal) => Promise<T>,\n): Promise<T> {\n const { signal, cleanup } = createEscapeAbortController();\n\n try {\n return await promptFn(signal);\n } finally {\n cleanup();\n }\n}\n\n/**\n * Validation function for text inputs.\n *\n * @param value - The current input value to validate\n * @returns `true` if valid, `false` if invalid, or a string error message\n *\n * @example\n * ```ts\n * const validate: ValidateFn = (value) => {\n * if (value.length < 3) return 'Must be at least 3 characters';\n * return true;\n * };\n * ```\n */\nexport type ValidateFn = (\n value: string,\n) => boolean | string | Promise<boolean | string>;\n\n/**\n * Option configuration for select and autocomplete prompts.\n *\n * @template T - The string literal type for the option value\n *\n * @example\n * ```ts\n * const options: SelectOption<'dev' | 'prod'>[] = [\n * { value: 'dev', label: 'Development', hint: 'Local environment' },\n * { value: 'prod', label: 'Production' },\n * ];\n * ```\n */\nexport type SelectOption<T extends string> = {\n /** The value returned when this option is selected */\n value: T;\n /** Display text shown to the user (defaults to value if not provided) */\n label?: string;\n /** Additional description or help text for the option */\n hint?: string;\n};\n\n/**\n * Interactive CLI input utilities with ESC-to-cancel support.\n *\n * All prompts exit the process with code 0 when the user presses ESC or Ctrl+C.\n *\n * @example\n * ```ts\n * import { cliInput } from '@ls-stack/cli';\n *\n * const name = await cliInput.text('Enter your name');\n * const confirm = await cliInput.confirm('Proceed?', { initial: true });\n * ```\n */\nexport const cliInput = {\n /**\n * Single selection prompt from a list of options.\n *\n * @template T - String literal union type of option values\n * @param title - The prompt message displayed to the user\n * @param options - Configuration object containing the selectable options\n * @returns The value of the selected option\n *\n * @example\n * ```ts\n * const env = await cliInput.select('Select environment', {\n * options: [\n * { value: 'dev', label: 'Development', hint: 'Local server' },\n * { value: 'prod', label: 'Production' },\n * ],\n * });\n * // env: 'dev' | 'prod'\n * ```\n */\n select: async <T extends string>(\n title: string,\n { options }: { options: SelectOption<T>[] },\n ): Promise<T> => {\n try {\n return await withEscapeSupport((signal) =>\n select(\n {\n message: title,\n choices: options.map((option) => ({\n value: option.value,\n name: option.label ?? option.value,\n description: option.hint,\n })),\n },\n { signal },\n ),\n );\n } catch (e) {\n handlePromptError(e);\n }\n },\n\n /**\n * Text input with autocomplete suggestions.\n *\n * Searches across option values, labels, and hints (case-insensitive).\n * Allows free-form text input with optional validation.\n *\n * @template T - String literal union type of option values\n * @param title - The prompt message displayed to the user\n * @param options - Configuration with autocomplete options and optional validation\n * @returns The selected or entered value\n *\n * @example\n * ```ts\n * const framework = await cliInput.textWithAutocomplete('Select framework', {\n * options: [\n * { value: 'react', label: 'React', hint: 'UI library' },\n * { value: 'vue', label: 'Vue', hint: 'Progressive framework' },\n * ],\n * validate: (v) => v.length > 0 || 'Required',\n * });\n * ```\n */\n textWithAutocomplete: async <T extends string>(\n title: string,\n {\n options,\n validate,\n }: { options: SelectOption<T>[]; validate?: ValidateFn },\n ): Promise<T> => {\n try {\n const choices = options.map((option) => ({\n value: option.value,\n name: option.label ?? option.value,\n description: option.hint,\n }));\n\n return await withEscapeSupport((signal) =>\n search(\n {\n message: title,\n source: (term: string | undefined) => {\n if (!term) return choices;\n\n const lowerTerm = term.toLowerCase();\n\n return choices.filter(\n (c) =>\n c.name.toLowerCase().includes(lowerTerm) ||\n c.value.toLowerCase().includes(lowerTerm) ||\n c.description?.toLowerCase().includes(lowerTerm),\n );\n },\n validate,\n },\n { signal },\n ),\n );\n } catch (e) {\n handlePromptError(e);\n }\n },\n\n /**\n * Text input prompt with optional default value and validation.\n *\n * @param title - The prompt message displayed to the user\n * @param options - Configuration with optional initial value and validation\n * @returns The entered text\n *\n * @example\n * ```ts\n * const name = await cliInput.text('Project name', {\n * initial: 'my-project',\n * validate: (v) => /^[a-z0-9-]+$/.test(v) || 'Invalid name',\n * });\n * ```\n */\n text: async (\n title: string,\n {\n initial,\n validate,\n }: {\n initial?: string;\n validate?: ValidateFn;\n } = {},\n ): Promise<string> => {\n try {\n return await withEscapeSupport((signal) =>\n input(\n { message: title, default: initial, required: true, validate },\n { signal },\n ),\n );\n } catch (e) {\n handlePromptError(e);\n }\n },\n\n /**\n * Yes/No confirmation prompt.\n *\n * @param title - The prompt message displayed to the user\n * @param options - Configuration with optional default value\n * @returns `true` for yes, `false` for no\n *\n * @example\n * ```ts\n * const proceed = await cliInput.confirm('Deploy to production?', {\n * initial: false,\n * });\n * ```\n */\n confirm: async (\n title: string,\n { initial }: { initial?: boolean } = {},\n ): Promise<boolean> => {\n try {\n return await withEscapeSupport((signal) =>\n confirm({ message: title, default: initial }, { signal }),\n );\n } catch (e) {\n handlePromptError(e);\n }\n },\n\n /**\n * Multi-select prompt with checkboxes.\n *\n * Requires at least one option to be selected.\n *\n * @template T - String literal union type of option values\n * @param title - The prompt message displayed to the user\n * @param options - Configuration object containing the selectable options\n * @returns Array of selected option values\n *\n * @example\n * ```ts\n * const features = await cliInput.multipleSelect('Enable features', {\n * options: [\n * { value: 'typescript', label: 'TypeScript' },\n * { value: 'eslint', label: 'ESLint' },\n * { value: 'prettier', label: 'Prettier' },\n * ],\n * });\n * // features: ('typescript' | 'eslint' | 'prettier')[]\n * ```\n */\n multipleSelect: async <T extends string>(\n title: string,\n { options }: { options: SelectOption<T>[] },\n ): Promise<T[]> => {\n try {\n return await withEscapeSupport((signal) =>\n checkbox(\n {\n message: title,\n required: true,\n choices: options.map((option) => ({\n value: option.value,\n name: option.label ?? option.value,\n description: option.hint,\n })),\n },\n { signal },\n ),\n );\n } catch (e) {\n handlePromptError(e);\n }\n },\n\n /**\n * Numeric input prompt.\n *\n * Returns `null` on non-cancellation errors (cancellation exits the process).\n *\n * @param title - The prompt message displayed to the user\n * @param options - Configuration with optional default value\n * @returns The entered number, or `null` on error\n *\n * @example\n * ```ts\n * const port = await cliInput.number('Enter port', { initial: 3000 });\n * if (port !== null) {\n * console.log(`Using port ${port}`);\n * }\n * ```\n */\n number: async (\n title: string,\n { initial }: { initial?: number } = {},\n ): Promise<number | null> => {\n try {\n return await withEscapeSupport((signal) =>\n number(\n { message: title, default: initial, required: true },\n { signal },\n ),\n );\n } catch (e) {\n if (isUserCancellation(e)) {\n process.exit(0);\n }\n\n console.error(e);\n return null;\n }\n },\n};\n","import { a as isPlainObject$1, i as isObject$1, n as isFunction$1, o as isPromise$1 } from \"./typeGuards-CMQqixVr.mjs\";\n\n//#region src/assertions.ts\nconst undefErrMsg = \"not undefined assertion failed\";\nconst nullishErrMsg = \"not nullish assertion failed\";\n/**\n* Ensures a value is not undefined and returns it with the correct type.\n*\n* Throws an error if the value is undefined. Use it instead of `!` operator for\n* better type safety.\n*\n* @example\n* ```typescript\n* const maybeString: string | undefined = getValue();\n* const definiteString = notUndefined(maybeString); // Type: string\n*\n* // With custom error message\n* const value = notUndefined(maybeValue, 'Value must be defined');\n*\n* // With custom error function\n* const value = notUndefined(maybeValue, () => new ValidationError('Required field'));\n* ```;\n*\n* @template T - The type of the input value\n* @param value - The value to check for undefined\n* @param error - Error message string or function that returns an Error to\n* throw if value is undefined\n* @returns The input value with undefined excluded from its type\n* @throws {Error} When the value is undefined\n*/\nfunction notUndefined(value, error = undefErrMsg) {\n\tif (value === void 0) throw typeof error === \"function\" ? error() : new Error(error);\n\treturn value;\n}\n/**\n* Ensures a value is not null or undefined and returns it with the correct\n* type.\n*\n* Throws an error if the value is null or undefined. Use it instead of `!`\n* operator for better type safety.\n*\n* @example\n* ```typescript\n* const maybeString: string | null | undefined = getValue();\n* const definiteString = notNullish(maybeString); // Type: string\n*\n* // With custom error message\n* const value = notNullish(maybeValue, 'Value cannot be null or undefined');\n*\n* // With custom error function\n* const value = notNullish(maybeValue, () => new ValidationError('Required field'));\n* ```;\n*\n* @template T - The type of the input value\n* @param value - The value to check for null or undefined\n* @param error - Error message string or function that returns an Error to\n* throw if value is nullish\n* @returns The input value with null and undefined excluded from its type\n* @throws {Error} When the value is null or undefined\n*/\nfunction notNullish(value, error = nullishErrMsg) {\n\tif (value === void 0 || value === null) throw typeof error === \"function\" ? error() : new Error(error);\n\treturn value;\n}\n/**\n* Asserts that a value is not null or undefined using TypeScript's assertion\n* signature.\n*\n* Throws an error if the value is null or undefined. Use it instead of `!`\n* operator for better type safety.\n*\n* @example\n* ```typescript\n* function processValue(input: string | null | undefined) {\n* assertIsNotNullish(input);\n* // TypeScript now knows input is string\n* console.log(input.toUpperCase());\n* }\n*\n* // With custom error\n* assertIsNotNullish(value, 'Value is required for processing');\n* ```;\n*\n* @template T - The type of the input value\n* @param value - The value to assert is not null or undefined\n* @param error - Error message string or function that returns an Error to\n* throw if value is nullish\n* @throws {Error} When the value is null or undefined\n*/\nfunction assertIsNotNullish(value, error = nullishErrMsg) {\n\tif (value === void 0 || value === null) throw typeof error === \"function\" ? error() : new Error(error);\n}\n/**\n* Asserts that a value is not undefined using TypeScript's assertion signature.\n*\n* Throws an error if the value is undefined. Use it instead of `!` operator for\n* better type safety.\n*\n* @example\n* ```typescript\n* function processValue(input: string | undefined) {\n* assertIsNotUndefined(input);\n* // TypeScript now knows input is string\n* console.log(input.toUpperCase());\n* }\n*\n* // With custom error\n* assertIsNotUndefined(value, 'Value must be defined');\n* ```;\n*\n* @template T - The type of the input value\n* @param value - The value to assert is not undefined\n* @param error - Error message string or function that returns an Error to\n* throw if value is undefined\n* @throws {Error} When the value is undefined\n*/\nfunction assertIsNotUndefined(value, error = undefErrMsg) {\n\tif (value === void 0) throw typeof error === \"function\" ? error() : new Error(error);\n}\n/**\n* Asserts that a condition is always true, throwing an error if it's falsy.\n*\n* This function is useful for enforcing invariants in your code - conditions\n* that should always be true. It uses TypeScript's assertion signature to\n* narrow types based on the condition.\n*\n* @example\n* ```typescript\n* function divide(a: number, b: number) {\n* invariant(b !== 0, 'Division by zero is not allowed');\n* return a / b;\n* }\n*\n* // Type narrowing example\n* function processUser(user: User | null) {\n* invariant(user, 'User must be logged in');\n* // TypeScript now knows user is User, not null\n* console.log(user.name);\n* }\n*\n* // With custom error function\n* invariant(isValid, () => new ValidationError('Invalid state detected'));\n* ```;\n*\n* @param condition - The condition to check (any truthy/falsy value)\n* @param error - Error message string or function that returns an Error to\n* throw if condition is falsy\n* @throws {Error} When the condition is falsy\n*/\nfunction invariant(condition, error = \"Invariant violation\") {\n\tif (!condition) throw typeof error === \"function\" ? error() : /* @__PURE__ */ new Error(`Invariant violation: ${error}`);\n}\n/**\n* Ensures exhaustive type checking in switch statements or conditional logic.\n*\n* This function should be used in the default case of switch statements or the\n* final else branch of conditional logic to ensure all possible cases are\n* handled. It helps catch missing cases at compile time when new union members\n* are added.\n*\n* @example\n* ```typescript\n* type Status = 'pending' | 'success' | 'error';\n*\n* function handleStatus(status: Status) {\n* switch (status) {\n* case 'pending':\n* return 'Loading...';\n* case 'success':\n* return 'Done!';\n* case 'error':\n* return 'Failed!';\n* default:\n* throw exhaustiveCheck(status); // TypeScript error if Status gains new members\n* }\n* }\n*\n* // In conditional logic\n* function processValue(value: string | number) {\n* if (typeof value === 'string') {\n* return value.toUpperCase();\n* } else if (typeof value === 'number') {\n* return value.toString();\n* } else {\n* throw exhaustiveCheck(value); // Ensures all cases are covered\n* }\n* }\n* ```;\n*\n* @template Except - The type that should never be reached\n* @param narrowedType - The value that should never exist at runtime\n* @returns An Error object (this function should never actually execute)\n*/\nfunction exhaustiveCheck(narrowedType) {\n\treturn /* @__PURE__ */ new Error(\"This should never happen\");\n}\n/** @deprecated Use import from `@ls-stack/typeGuards` instead */\nconst isFunction = isFunction$1;\n/** @deprecated Use import from `@ls-stack/typeGuards` instead */\nconst isObject = isObject$1;\n/** @deprecated Use import from `@ls-stack/typeGuards` instead */\nconst isPlainObject = isPlainObject$1;\n/** @deprecated Use import from `@ls-stack/typeGuards` instead */\nconst isPromise = isPromise$1;\n\n//#endregion\nexport { isFunction as a, isPromise as c, invariant as i, notNullish as l, assertIsNotUndefined as n, isObject as o, exhaustiveCheck as r, isPlainObject as s, assertIsNotNullish as t, notUndefined as u };","import { a as isFunction } from \"./assertions-CsE3pD8P.mjs\";\n\n//#region src/arrayUtils.ts\n/**\n* Allow to filter and map with better typing ergonomics\n*\n* In the `mapFilter` function return `false` to reject the item, or any other\n* value to map it.\n*\n* @example\n* // Filter reject and turn value into `value mapped`\n* const items = ['value', 'value', 'reject', 'reject'];\n*\n* const mappedItems = filterAndMap(items, (item) =>\n* item === 'reject' ? false : `${item} mapped`,\n* );\n*\n* mappedItems; // ['value mapped', 'value mapped']\n*\n* @param array\n* @param mapFilter\n*/\nfunction filterAndMap(array, mapFilter) {\n\tconst result = [];\n\tlet i = -1;\n\tfor (const item of array) {\n\t\ti += 1;\n\t\tconst filterResult = mapFilter(item, i);\n\t\tif (filterResult !== false) result.push(filterResult);\n\t}\n\treturn result;\n}\n/**\n* Sort an array based on a value\n*\n* Sort by `ascending` order by default\n*\n* Use `Infinity` as as wildcard to absolute max and min values\n*\n* @example\n* const items = [1, 3, 2, 4];\n*\n* const sortedItems = sortBy(items, (item) => item);\n* // [1, 2, 3, 4]\n*\n* const items2 = [\n* { a: 1, b: 2 },\n* { a: 2, b: 1 },\n* { a: 1, b: 1 },\n* ];\n*\n* // return a array to sort by multiple values\n* const sortedItems = sortBy(items, (item) => [item.a, item.b]);\n*\n* @param arr\n* @param sortByValue\n* @param props\n*/\nfunction sortBy(arr, sortByValue, props = \"asc\") {\n\tconst order = Array.isArray(props) || typeof props === \"string\" ? props : props.order ?? \"asc\";\n\treturn [...arr].sort((a, b) => {\n\t\tconst _aPriority = sortByValue(a);\n\t\tconst _bPriority = sortByValue(b);\n\t\tconst aPriority = Array.isArray(_aPriority) ? _aPriority : [_aPriority];\n\t\tconst bPriority = Array.isArray(_bPriority) ? _bPriority : [_bPriority];\n\t\tfor (let i = 0; i < aPriority.length; i++) {\n\t\t\tconst levelOrder = typeof order === \"string\" ? order : order[i] ?? \"asc\";\n\t\t\tconst aP = aPriority[i] ?? 0;\n\t\t\tconst bP = bPriority[i] ?? 0;\n\t\t\tif (aP === bP) continue;\n\t\t\tif (bP === Infinity || aP === -Infinity || aP < bP) return levelOrder === \"asc\" ? -1 : 1;\n\t\t\tif (aP === Infinity || bP === -Infinity || aP > bP) return levelOrder === \"asc\" ? 1 : -1;\n\t\t}\n\t\treturn 0;\n\t});\n}\n/**\n* Get the correct 0 based value for sync with other array in ascending order\n*\n* @example\n* ```ts\n* const items = [1, 2, 3];\n*\n* const index = sortBy(\n* items,\n* (item) => getAscIndexOrder(\n* followOrder.findIndex((order) => order === item)\n* )\n* );\n* ```;\n*\n* @param index\n*/\nfunction getAscIndexOrder(index) {\n\treturn index === -1 ? Infinity : index ?? Infinity;\n}\nfunction arrayWithPrev(array) {\n\treturn array.map((item, i) => [item, array[i - 1] ?? null]);\n}\nfunction arrayWithPrevAndIndex(array) {\n\treturn array.map((item, i) => ({\n\t\titem,\n\t\tprev: array[i - 1] ?? null,\n\t\tindex: i\n\t}));\n}\nfunction isInArray(value, oneOf) {\n\tfor (let i = 0; i < oneOf.length; i++) if (oneOf[i] === value) return true;\n\treturn false;\n}\nfunction isInArrayWithoutNarrowing(value, oneOf) {\n\treturn oneOf.includes(value);\n}\nfunction looseIsInArray(value, array) {\n\treturn array.includes(value);\n}\nfunction findAfterIndex(array, index, predicate) {\n\tfor (let i = index + 1; i < array.length; i++) if (predicate(array[i])) return array[i];\n}\nfunction findBeforeIndex(array, index, predicate) {\n\tlet indexToUse = index;\n\tif (indexToUse >= array.length) indexToUse = array.length;\n\tfor (let i = indexToUse - 1; i >= 0; i--) if (predicate(array[i])) return array[i];\n}\nfunction rejectArrayUndefinedValues(array) {\n\treturn array.filter((item) => item !== void 0);\n}\nfunction hasDuplicates(array, getKey = (item) => item) {\n\tconst seen = /* @__PURE__ */ new Set();\n\tfor (const item of array) {\n\t\tconst key = getKey(item);\n\t\tif (seen.has(key)) return true;\n\t\tseen.add(key);\n\t}\n\treturn false;\n}\nfunction rejectDuplicates(array, getKey = (item) => item) {\n\tconst seen = /* @__PURE__ */ new Set();\n\tconst result = [];\n\tfor (const item of array) {\n\t\tconst key = getKey(item);\n\t\tif (seen.has(key)) continue;\n\t\tseen.add(key);\n\t\tresult.push(item);\n\t}\n\treturn result;\n}\nfunction truncateArray(array, maxLength, appendIfTruncated) {\n\tconst truncate = array.length > maxLength;\n\tconst result = truncate ? [...array.slice(0, maxLength)] : array;\n\tif (truncate && appendIfTruncated) {\n\t\tif (isFunction(appendIfTruncated)) return [...result, appendIfTruncated(array.length - maxLength)];\n\t\treturn [...result, appendIfTruncated];\n\t}\n\treturn result;\n}\n/**\n* Finds the first item in an array where the predicate returns a non-false\n* value and returns that mapped value.\n*\n* Combines find and map operations - applies the predicate to each item until\n* one returns a value that is not `false`, then returns that mapped value. If\n* no item matches, returns `undefined`.\n*\n* @example\n* const users = [\n* { id: 1, name: 'Alice' },\n* { id: 2, name: 'Bob' },\n* ];\n*\n* const foundName = findAndMap(users, (user) =>\n* user.id === 2 ? user.name.toUpperCase() : false,\n* );\n* // foundName is 'BOB'\n*\n* @param array - The array to search through\n* @param predicate - Function that returns a mapped value or `false` to skip\n* the item\n* @returns The first mapped value that is not `false`, or `undefined` if no\n* item matches\n*/\nfunction findAndMap(array, predicate) {\n\tfor (const item of array) {\n\t\tconst value = predicate(item);\n\t\tif (value !== false) return value;\n\t}\n}\n/**\n* Enhance an array with extra methods\n*\n* @example\n* const enhancedItems = arrayOps(array);\n*\n* enhancedItems.filterAndMap((item) => (item === 2 ? false : item));\n* enhancedItems.sortBy((item) => item);\n* enhancedItems.rejectDuplicates((item) => item);\n*\n* @param array\n*/\nfunction arrayOps(array) {\n\treturn {\n\t\tfilterAndMap: (mapFilter) => filterAndMap(array, mapFilter),\n\t\tsortBy: (sortByValue, props) => sortBy(array, sortByValue, props),\n\t\trejectDuplicates: (getKey) => rejectDuplicates(array, getKey),\n\t\tfindAndMap: (predicate) => findAndMap(array, predicate)\n\t};\n}\n/**\n* Inserts a separator value between each element in an array.\n*\n* @example\n* intersperse([1, 2, 3], 0); // [1, 0, 2, 0, 3]\n*\n* @param array - The array to intersperse\n* @param separator - The value to insert between elements\n* @returns A new array with separator values inserted between elements\n*/\nfunction intersperse(array, separator) {\n\tconst result = [];\n\tfor (let i = 0; i < array.length; i++) {\n\t\tresult.push(array[i]);\n\t\tif (i < array.length - 1) result.push(separator);\n\t}\n\treturn result;\n}\n/**\n* Creates an array by repeating a value a specified number of times, optionally\n* with a separator between each repetition.\n*\n* @example\n* repeat('x', 3); // ['x', 'x', 'x']\n* repeat('x', 3, '-'); // ['x', '-', 'x', '-', 'x']\n*\n* @param value - The value to repeat\n* @param count - Number of times to repeat the value\n* @param separator - Optional separator to insert between repetitions\n* @returns A new array with the repeated values\n*/\nfunction repeat(value, count, separator) {\n\tconst result = [];\n\tfor (let i = 0; i < count; i++) {\n\t\tresult.push(value);\n\t\tif (separator !== void 0 && i < count - 1) result.push(separator);\n\t}\n\treturn result;\n}\n\n//#endregion\nexport { arrayOps, arrayWithPrev, arrayWithPrevAndIndex, filterAndMap, findAfterIndex, findAndMap, findBeforeIndex, getAscIndexOrder, hasDuplicates, intersperse, isInArray, isInArrayWithoutNarrowing, looseIsInArray, rejectArrayUndefinedValues, rejectDuplicates, repeat, sortBy, truncateArray };","//#region src/dedent.ts\n/**\n* Remove common leading indentation from multi-line strings while preserving\n* relative indentation. Can be used as a tagged template literal or called with\n* a plain string.\n*\n* By default, it will dedent interpolated multi-line strings to match the\n* surrounding context. And it will not show falsy values.\n*\n* @example\n* ```typescript\n* const text = dedent`;\n* function hello() {\n* console.log('world');\n* }\n* `;\n* // Result:\n* \"function hello() {\n* console.log('world');\n* }\"\n* ```;\n*/\nconst dedent = createDedent({ identInterpolations: true });\nfunction createDedent(options) {\n\td.withOptions = (newOptions) => createDedent({\n\t\t...options,\n\t\t...newOptions\n\t});\n\treturn d;\n\tfunction d(strings, ...values) {\n\t\tconst raw = typeof strings === \"string\" ? [strings] : strings.raw;\n\t\tconst { escapeSpecialCharacters = Array.isArray(strings), trimWhitespace = true, identInterpolations = true, showNullishOrFalseValues = false } = options;\n\t\tlet result = \"\";\n\t\tfor (let i = 0; i < raw.length; i++) {\n\t\t\tlet next = raw[i];\n\t\t\tif (escapeSpecialCharacters) next = next.replace(/\\\\\\n[ \\t]*/g, \"\").replace(/\\\\`/g, \"`\").replace(/\\\\\\$/g, \"$\").replace(/\\\\\\{/g, \"{\");\n\t\t\tresult += next;\n\t\t\tif (i < values.length) {\n\t\t\t\tlet val = values[i];\n\t\t\t\tif (!showNullishOrFalseValues && (val === false || val === null || val === void 0)) continue;\n\t\t\t\tval = String(val);\n\t\t\t\tif (identInterpolations && val.includes(\"\\n\")) {\n\t\t\t\t\tlet withIdent = val;\n\t\t\t\t\tconst currentIndent = getCurrentIndent(result);\n\t\t\t\t\tif (currentIndent && withIdent) withIdent = withIdent.split(\"\\n\").map((line, index) => {\n\t\t\t\t\t\treturn index === 0 || line === \"\" ? line : currentIndent + line;\n\t\t\t\t\t}).join(\"\\n\");\n\t\t\t\t\tresult += withIdent;\n\t\t\t\t} else result += val;\n\t\t\t}\n\t\t}\n\t\tconst lines = result.split(\"\\n\");\n\t\tlet mindent = null;\n\t\tfor (const l of lines) {\n\t\t\tconst m = l.match(/^(\\s+)\\S+/);\n\t\t\tif (m) {\n\t\t\t\tconst indent = m[1].length;\n\t\t\t\tif (!mindent) mindent = indent;\n\t\t\t\telse mindent = Math.min(mindent, indent);\n\t\t\t}\n\t\t}\n\t\tif (mindent !== null) {\n\t\t\tconst m = mindent;\n\t\t\tresult = lines.map((l) => l[0] === \" \" || l[0] === \"\t\" ? l.slice(m) : l).join(\"\\n\");\n\t\t}\n\t\tif (trimWhitespace) result = result.trim();\n\t\tif (escapeSpecialCharacters) result = result.replace(/\\\\n/g, \"\\n\");\n\t\treturn result;\n\t}\n}\nfunction getCurrentIndent(str) {\n\tconst lines = str.split(\"\\n\");\n\tconst lastLine = lines[lines.length - 1];\n\tif (!lastLine) return \"\";\n\tconst match = lastLine.match(/^(\\s*)/);\n\treturn match ? match[1] : \"\";\n}\n\n//#endregion\nexport { dedent };","//#region src/stringUtils.ts\n/**\n* A util to create more legible conditional concatenated strings\n*\n* @example\n* joinStrings('a', 'b', 'c'); // 'abc'\n* joinStrings('a', false, 'c'); // 'ac'\n* joinStrings('a', addBString ? 'b' : null, 'c'); // 'ac' if addBString is false, 'abc' if addBString is true\n*\n* @param args\n*/\nfunction concatStrings(...args) {\n\tconst strings = [];\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tif (!arg) continue;\n\t\tif (Array.isArray(arg)) {\n\t\t\tstrings.push(concatStrings(...arg));\n\t\t\tcontinue;\n\t\t}\n\t\tstrings.push(arg);\n\t}\n\treturn strings.join(\"\");\n}\n/** @deprecated Use {@link concatStrings} instead */\nconst joinStrings = concatStrings;\nfunction formatNum(num, maxDecimalsOrOptions = 2) {\n\tconst options = typeof maxDecimalsOrOptions === \"number\" ? { maximumFractionDigits: maxDecimalsOrOptions } : maxDecimalsOrOptions;\n\treturn num.toLocaleString(\"en-US\", options);\n}\n/** Check if a string is `snake_case` */\nfunction isSnakeCase(str) {\n\treturn /^[a-z0-9_]+$/.test(str);\n}\n/** Check if a string is `kebab-case` */\nfunction isKebabCase(str) {\n\treturn /^[a-z0-9]+(-[a-z0-9]+)*$/.test(str);\n}\n/** Check if a string is `PascalCase` */\nfunction isPascalCase(str) {\n\treturn /^[A-Z][a-zA-Z0-9]*$/.test(str);\n}\n/** Check if a string is `camelCase` */\nfunction isCamelCase(str) {\n\treturn /^[a-z][a-zA-Z0-9]*$/.test(str);\n}\n/** Check if a string is `Title Case` */\nfunction isTitleCase(str) {\n\treturn /^[A-Z][a-z0-9]*( ([A-Z][a-z0-9]*|[0-9]+))*$/.test(str);\n}\n/** Check if a string is `Sentence Case` */\nfunction isSentenceCase(str) {\n\treturn /^[A-Z][a-z0-9]*( [a-z0-9]+)*$/.test(str);\n}\n/** Check if a string is `CONSTANT_CASE` */\nfunction isConstantCase(str) {\n\treturn /^[A-Z_][A-Z0-9_]*$/.test(str);\n}\n/** Check if a string is `dot.case` */\nfunction isDotCase(str) {\n\treturn /^[a-z0-9]+(\\.[a-z0-9]+)*$/.test(str);\n}\n/** Check if a string is `path/case` */\nfunction isPathCase(str) {\n\treturn /^[a-z0-9]+(\\/[a-z0-9]+)*$/.test(str);\n}\n/** Convert a string to `kebab-case` */\nfunction convertToKebabCase(str) {\n\treturn convertToSnakeCase(str).replace(/_/g, \"-\");\n}\n/** Convert a string to `snake_case` */\nfunction convertToSnakeCase(str) {\n\treturn str.replace(/[\\s\\-.]+/g, \"_\").replace(/([a-z0-9])([A-Z])/g, \"$1_$2\").replace(/([A-Z])([A-Z][a-z])/g, \"$1_$2\").toLowerCase().replace(/[^a-z0-9_]/g, \"\").replace(/^_+|_+$/g, \"\").replace(/_+/g, \"_\");\n}\n/** Convert a string to `PascalCase` */\nfunction convertToPascalCase(str) {\n\treturn str.split(/[\\s_-]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(\"\");\n}\n/** Convert a string to `camelCase` */\nfunction convertToCamelCase(str) {\n\tconst pascalCase = convertToPascalCase(str);\n\treturn pascalCase.charAt(0).toLowerCase() + pascalCase.slice(1);\n}\n/** Convert a string to `Sentence Case` */\nfunction convertToSentenceCase(str) {\n\treturn str.replace(/[\\s\\-.]+/g, \" \").replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").replace(/([A-Z])([A-Z][a-z])/g, \"$1 $2\").split(/[\\s_-]+/).map((word) => word.toLowerCase()).join(\" \").replace(/^\\w/, (char) => char.toUpperCase());\n}\n/** Convert a string to `Title Case` */\nfunction convertToTitleCase(str) {\n\treturn str.replace(/[\\s\\-.]+/g, \" \").replace(/([a-z0-9])([A-Z])/g, \"$1 $2\").replace(/([A-Z])([A-Z][a-z])/g, \"$1 $2\").split(/[\\s_-]+/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(\" \");\n}\n/** Convert a string to `CONSTANT_CASE` */\nfunction convertToConstantCase(str) {\n\treturn convertToSnakeCase(str).toUpperCase();\n}\n/** Convert a string to `dot.case` */\nfunction convertToDotCase(str) {\n\treturn convertToSnakeCase(str).replace(/_/g, \".\");\n}\n/** Convert a string to `path/case` */\nfunction convertToPathCase(str) {\n\treturn convertToSnakeCase(str).replace(/_/g, \"/\");\n}\nfunction truncateString(str, length, ellipsis = \"…\") {\n\tif (str.length <= length) return str;\n\treturn str.slice(0, length - 1) + ellipsis;\n}\nfunction removeANSIColors(str) {\n\treturn str.replace(/\\u001b\\[\\d+m/g, \"\");\n}\n\n//#endregion\nexport { truncateString as C, removeANSIColors as S, isPathCase as _, convertToKebabCase as a, isTitleCase as b, convertToSentenceCase as c, formatNum as d, isCamelCase as f, isPascalCase as g, isKebabCase as h, convertToDotCase as i, convertToSnakeCase as l, isDotCase as m, convertToCamelCase as n, convertToPascalCase as o, isConstantCase as p, convertToConstantCase as r, convertToPathCase as s, concatStrings as t, convertToTitleCase as u, isSentenceCase as v, joinStrings as x, isSnakeCase as y };","//#region src/typingFnUtils.ts\nfunction asNonPartial(obj) {\n\treturn obj;\n}\n/**\n* A wrapper to Object.entries with a better typing inference\n*\n* @param obj\n*/\nfunction typedObjectEntries(obj) {\n\treturn Object.entries(obj);\n}\n/**\n* A wrapper to Object.entries with a better typing inference, but with strict\n* typing narrowing keys to strings.\n*\n* @param obj\n*/\nfunction strictTypedObjectEntries(obj) {\n\treturn Object.entries(obj);\n}\n/**\n* A wrapper to Object.keys with a better typing inference\n*\n* @param obj\n*/\nfunction typedObjectKeys(obj) {\n\treturn Object.keys(obj);\n}\n/**\n* A safe way to cast types, use to substitute the `as Type`\n*\n* @param value\n*/\nfunction asType(value) {\n\treturn value;\n}\n/**\n* Narrow a string to a union of strings\n*\n* @param key\n* @param union\n*/\nfunction narrowStringToUnion(key, union) {\n\tif (!key) return void 0;\n\tif (union instanceof Set) return union.has(key) ? key : void 0;\n\tif (union.includes(key)) return key;\n}\n/**\n* Type helper to check if a type is a subtype of another type.\n*\n* @template BaseType - The base type to check against\n* @template SubType - The type that should extend BaseType\n* @returns Returns undefined, only used for type checking\n*/\nfunction typeOnRightExtendsLeftType() {}\n/** @deprecated Use typeOnRightExtendsLeftType instead */\nconst isSubTypeOf = typeOnRightExtendsLeftType;\n/**\n* Type helper to narrow a string to a key of an object.\n*\n* @param key\n* @param obj\n*/\nfunction isObjKey(key, obj) {\n\treturn typeof key === \"string\" && key in obj;\n}\n/**\n* Type helper to compare two union types and determine their relationship.\n*\n* @template T - The first union type (left side)\n* @template U - The second union type (right side)\n* @param _diff - Null if unions are identical, or an object describing the\n* errors\n*/\nfunction unionsAreTheSame(_diff) {}\nfunction asPartialUndefinedValues(value) {\n\treturn value;\n}\n/**\n* Type guard to check if an array has at least one element.\n*\n* @param array - The array to check\n* @returns True if the array is non-empty, false otherwise\n*/\nfunction isNonEmptyArray(array) {\n\treturn array.length > 0;\n}\n/**\n* Type guard to check if an object has a specific key and narrow its type.\n*\n* @param obj - The object to check\n* @param key - The key to check for\n* @returns True if the object has the key, false otherwise\n*/\nfunction objectHasKey(obj, key) {\n\treturn key in obj;\n}\n\n//#endregion\nexport { isObjKey as a, objectHasKey as c, typedObjectEntries as d, typedObjectKeys as f, isNonEmptyArray as i, strictTypedObjectEntries as l, asPartialUndefinedValues as n, isSubTypeOf as o, unionsAreTheSame as p, asType as r, narrowStringToUnion as s, asNonPartial as t, typeOnRightExtendsLeftType as u };","import { cliInput } from './cliInput';\nimport { getAscIndexOrder, sortBy } from '@ls-stack/utils/arrayUtils';\nimport { exhaustiveCheck } from '@ls-stack/utils/assertions';\nimport { dedent } from '@ls-stack/utils/dedent';\nimport { removeANSIColors } from '@ls-stack/utils/stringUtils';\nimport { isObjKey, typedObjectEntries } from '@ls-stack/utils/typingFnUtils';\nimport { styleText } from 'node:util';\n\nconst [, , cmdFromTerminal, ...cmdArgs] = process.argv;\n\n/**\n * Positional argument definition for CLI commands.\n *\n * Positional arguments are parsed in the order they are defined in the `args` object.\n *\n * @example\n * ```ts\n * // String positional arg (required)\n * { type: 'positional-string', name: 'filename', description: 'File to process' }\n *\n * // Number positional arg with default (optional)\n * { type: 'positional-number', name: 'port', description: 'Port number', default: 3000 }\n * ```\n */\nexport type PositionalArg =\n | {\n type: 'positional-string';\n name: string;\n default?: string;\n description: string;\n }\n | {\n type: 'positional-number';\n name: string;\n default?: number;\n description: string;\n };\n\n/**\n * Argument definition for CLI commands.\n *\n * Supports positional arguments, boolean flags, and value flags.\n *\n * **Argument Types:**\n * - `positional-string` - Required string argument (optional if `default` is provided)\n * - `positional-number` - Required number argument (optional if `default` is provided)\n * - `flag` - Boolean flag (`--verbose`), defaults to `false`\n * - `value-string-flag` - Flag with string value (`--config file.json`)\n * - `value-number-flag` - Flag with number value (`--port 8080`)\n *\n * @example\n * ```ts\n * const args = {\n * name: { type: 'positional-string', name: 'name', description: 'Project name' },\n * port: { type: 'value-number-flag', name: 'port', description: 'Port', default: 3000 },\n * verbose: { type: 'flag', name: 'verbose', description: 'Verbose output' },\n * };\n * ```\n */\nexport type Arg =\n | PositionalArg\n | {\n type: 'flag';\n name: string;\n description: string;\n }\n | {\n type: 'value-string-flag';\n default?: string;\n name: string;\n description: string;\n }\n | {\n type: 'value-number-flag';\n default?: number;\n name: string;\n description: string;\n };\n\ntype Cmd = {\n short?: string;\n description: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- internal type\n run: (...args: any[]) => Promise<void> | void;\n args?: Record<string, Arg>;\n examples?: {\n args: string[];\n description: string;\n }[];\n};\n\ntype GetArgType<T extends Arg> =\n T extends PositionalArg ?\n T['type'] extends 'positional-string' ?\n T['default'] extends string ?\n string\n : string | undefined\n : T['type'] extends 'positional-number' ?\n T['default'] extends number ?\n number\n : number | undefined\n : never\n : T extends { type: 'flag' } ? boolean\n : T extends { type: 'value-string-flag' } ?\n T['default'] extends string ?\n string\n : string | undefined\n : T extends { type: 'value-number-flag' } ?\n T['default'] extends number ?\n number\n : number | undefined\n : never;\n\n/**\n * Creates a type-safe command definition for use with `createCLI`.\n *\n * The `run` function receives fully typed arguments based on the `args` definition.\n * Positional arguments are parsed in declaration order.\n *\n * @template Args - Record of argument definitions\n * @param options - Command configuration\n * @param options.description - Command description shown in help\n * @param options.short - Optional single-character alias (cannot be 'i' or 'h')\n * @param options.args - Typed argument definitions\n * @param options.run - Handler function receiving parsed arguments\n * @param options.examples - Optional usage examples for help text\n * @returns Command definition object\n *\n * @example\n * ```ts\n * const deploy = createCmd({\n * short: 'd',\n * description: 'Deploy the application',\n * args: {\n * env: {\n * type: 'positional-string',\n * name: 'env',\n * description: 'Target environment',\n * },\n * port: {\n * type: 'value-number-flag',\n * name: 'port',\n * description: 'Port number',\n * default: 3000,\n * },\n * verbose: {\n * type: 'flag',\n * name: 'verbose',\n * description: 'Enable verbose logging',\n * },\n * },\n * examples: [\n * { args: ['production'], description: 'Deploy to production' },\n * { args: ['staging', '--port', '8080'], description: 'Deploy to staging on port 8080' },\n * ],\n * run: async ({ env, port, verbose }) => {\n * // env: string, port: number, verbose: boolean\n * console.log(`Deploying to ${env} on port ${port}`);\n * },\n * });\n * ```\n */\nexport function createCmd<Args extends undefined | Record<string, Arg>>({\n short,\n description,\n run,\n args,\n examples,\n}: {\n short?: string;\n description: string;\n args?: Args;\n run: (cmdArgs: {\n [K in keyof Args]: Args[K] extends Arg ? GetArgType<Args[K]> : never;\n }) => Promise<void> | void;\n examples?: {\n args: string[];\n description: string;\n }[];\n}) {\n return {\n short,\n description,\n run,\n args,\n examples,\n };\n}\n\n/**\n * Creates and runs a CLI application with the given commands.\n *\n * Automatically handles argument parsing, help generation, and interactive mode.\n *\n * **Built-in commands:**\n * - `h` or `--help` - Shows help with all commands\n * - `i` - Interactive mode (select command from list)\n * - `<command> -h` - Shows help for a specific command\n *\n * @template C - String literal union of command names\n * @param options - CLI configuration\n * @param options.name - CLI display name shown in header\n * @param options.baseCmd - Command prefix for help text (e.g., 'my-cli')\n * @param options.sort - Optional array to customize command display order\n * @param cmds - Record of command definitions created with `createCmd`\n *\n * @example\n * ```ts\n * await createCLI(\n * { name: 'My CLI', baseCmd: 'my-cli' },\n * {\n * hello: createCmd({\n * short: 'hi',\n * description: 'Say hello',\n * run: async () => console.log('Hello!'),\n * }),\n * deploy: createCmd({\n * short: 'd',\n * description: 'Deploy the app',\n * args: {\n * env: { type: 'positional-string', name: 'env', description: 'Environment' },\n * },\n * run: async ({ env }) => console.log(`Deploying to ${env}`),\n * }),\n * },\n * );\n * ```\n *\n * @example\n * ```bash\n * # Usage examples:\n * my-cli # Show interactive menu\n * my-cli h # Show help\n * my-cli i # Interactive mode\n * my-cli hello # Run hello command\n * my-cli hi # Run hello via short alias\n * my-cli deploy prod # Run deploy with argument\n * my-cli deploy -h # Show deploy command help\n * ```\n */\nexport async function createCLI<C extends string>(\n {\n name,\n sort,\n baseCmd,\n }: { name: string; sort?: NoInfer<C>[]; baseCmd: string },\n cmds: Record<C, Cmd>,\n) {\n function getCmdId(cmd: string): C {\n if (isObjKey(cmd, cmds)) return cmd;\n\n console.error(styleText(['red', 'bold'], `Command '${cmd}' not found`));\n process.exit(1);\n }\n\n process.stdout.write('\\x1Bc'); // Clear console\n\n console.info(styleText(['blue', 'bold'], name));\n\n const addedShortCmds = new Set<string>();\n const reservedShortCmds = ['i', 'h'];\n\n let runCmdId: string | undefined = cmdFromTerminal;\n\n for (const [, cmd] of typedObjectEntries(cmds)) {\n if (cmd.short) {\n if (reservedShortCmds.includes(cmd.short)) {\n console.error(\n styleText(['red', 'bold'], `Short cmd \"${cmd.short}\" is reserved for built-in commands`),\n );\n process.exit(1);\n }\n\n if (addedShortCmds.has(cmd.short)) {\n console.error(\n styleText(['red', 'bold'], `Short cmd \"${cmd.short}\" is duplicated`),\n );\n process.exit(1);\n }\n\n addedShortCmds.add(cmd.short);\n }\n }\n\n function printHelp() {\n const pipeChar = styleText(['dim'], ' or ');\n const fmtCmd = (c: string) => styleText(['blue', 'bold'], c);\n const beforeDescription = styleText(['dim'], '->');\n\n const largestCmdTextLength = Math.max(\n ...typedObjectEntries(cmds).map(\n ([cmd, { short }]) => `${cmd}${short ? ` or ${short}` : ''}`.length,\n ),\n );\n\n console.info(dedent`\n ${styleText(['blue', 'bold'], 'Docs:')}\n\n ${styleText(['bold', 'underline'], 'Usage:')} ${baseCmd} <command> [command-args...]\n\n ${styleText(['bold', 'underline'], 'Commands:')}\n\n ${typedObjectEntries(cmds)\n .map(([cmd, { description, short, args }]) => {\n const cmdText = `${fmtCmd(cmd)}${short ? `${pipeChar}${fmtCmd(short)}` : ''}`;\n const unformattedCmdText = removeANSIColors(cmdText);\n\n let result = `${cmdText}${' '.repeat(\n largestCmdTextLength - unformattedCmdText.length + 1,\n )}${beforeDescription} ${description}`;\n\n if (args && Object.keys(args).length > 0) {\n const briefArgs = typedObjectEntries(args)\n .sort(([, a], [, b]) => {\n // Positional args first (in declaration order), then flags\n if (a.type.startsWith('positional') && !b.type.startsWith('positional')) return -1;\n if (!a.type.startsWith('positional') && b.type.startsWith('positional')) return 1;\n return 0; // Keep original order within each group\n })\n .map(([, arg]) => {\n switch (arg.type) {\n case 'positional-string':\n case 'positional-number':\n return `[${arg.name}]`;\n case 'flag':\n return `[--${arg.name}]`;\n case 'value-string-flag':\n case 'value-number-flag':\n return `[--${arg.name}]`;\n default:\n throw exhaustiveCheck(arg);\n }\n })\n .join(' ');\n result += `\\n${styleText(['dim'], ` └─ args: ${briefArgs}`)}`;\n }\n\n return result;\n })\n .join('\\n')}\n\n ${styleText(['dim'], `Use ${baseCmd} <cmd> -h for more details about a command`)}\n\n ${fmtCmd('i')} ${beforeDescription} Starts in interactive mode\n ${fmtCmd('h')} ${beforeDescription} Prints this help message\n `);\n\n console.info(styleText(['dim'], 'Use a command to get started!'));\n }\n\n function printCmdHelp(cmdId: string) {\n const cmd = cmds[getCmdId(cmdId)];\n\n function formatArg(arg: Arg): string {\n switch (arg.type) {\n case 'positional-string':\n case 'positional-number':\n return `[${arg.name}]`;\n case 'flag':\n return `[--${arg.name}]`;\n case 'value-string-flag':\n return `[--${arg.name} <value>]`;\n case 'value-number-flag':\n return `[--${arg.name} <number>]`;\n default:\n throw exhaustiveCheck(arg);\n }\n }\n\n function getArgsUsage(args?: Record<string, Arg>): string {\n if (!args) return '';\n\n const sortedArgs = typedObjectEntries(args).sort(([, a], [, b]) => {\n // Positional args first (in declaration order), then flags\n if (a.type.startsWith('positional') && !b.type.startsWith('positional')) return -1;\n if (!a.type.startsWith('positional') && b.type.startsWith('positional')) return 1;\n return 0; // Keep original order within each group\n });\n\n const colors = [\n 'cyan',\n 'yellow',\n 'magenta',\n 'blue',\n 'green',\n 'red',\n ] as const;\n return sortedArgs\n .map(([, arg], index) => {\n const color = colors[index % colors.length];\n\n if (!color) return formatArg(arg);\n\n return styleText([color], formatArg(arg)) || formatArg(arg);\n })\n .join(' ');\n }\n\n const cmdTitle = cmd.short ? `${cmdId} (${cmd.short})` : cmdId;\n let helpText = `${styleText(['blue', 'bold'], `${cmdTitle}:`) || `${cmdTitle}:`} ${cmd.description}\\n\\n${styleText(['bold', 'underline'], 'Usage:') || 'Usage:'} ${styleText(['dim'], baseCmd) || baseCmd} ${styleText(['bold'], cmdId) || cmdId}`;\n\n if (cmd.args) {\n const argsUsage = getArgsUsage(cmd.args);\n if (argsUsage) {\n helpText += ` ${argsUsage}`;\n }\n }\n \n if (cmd.short) {\n helpText += `\\n ${styleText(['dim'], baseCmd) || baseCmd} ${styleText(['bold'], cmd.short) || cmd.short} ...`;\n }\n\n if (cmd.args) {\n const argEntries = typedObjectEntries(cmd.args);\n if (argEntries.length > 0) {\n helpText += `\\n\\n${styleText(['bold', 'underline'], 'Arguments:') || 'Arguments:'}`;\n const colors = [\n 'cyan',\n 'yellow',\n 'magenta',\n 'blue',\n 'green',\n 'red',\n ] as const;\n for (const [index, [, arg]] of argEntries.entries()) {\n const color = colors[index % colors.length];\n\n if (!color) continue;\n\n const argDisplayName =\n arg.type === 'flag' ? `--${arg.name}`\n : arg.type === 'value-string-flag' ? `--${arg.name}`\n : arg.type === 'value-number-flag' ? `--${arg.name}`\n : arg.name;\n const argName = styleText([color], argDisplayName) || argDisplayName;\n const required = '';\n helpText += `\\n ${argName}${required} - ${arg.description}`;\n }\n }\n }\n\n if (cmd.examples) {\n helpText += `\\n\\n${styleText(['bold', 'underline'], 'Examples:') || 'Examples:'}`;\n for (const { args: exampleArgs, description: exampleDesc } of cmd.examples) {\n helpText += `\\n ${baseCmd} ${cmdId} ${exampleArgs.join(' ')} ${styleText(['dim'], `# ${exampleDesc}`) || `# ${exampleDesc}`}`;\n }\n }\n\n console.info(helpText);\n console.info(styleText(['dim'], 'Use a command to get started!'));\n }\n\n if (!cmdFromTerminal) {\n const response = await cliInput.select('Choose an action', {\n options: [\n {\n value: 'run-cmd',\n label: 'Start interactive mode',\n hint: `Select a command to run from a list | ${baseCmd} i`,\n },\n {\n value: 'print-help',\n label: 'Print help',\n hint: `${baseCmd} h`,\n },\n ],\n });\n\n if (response === 'print-help') {\n printHelp();\n process.exit(0);\n } else {\n runCmdId = 'i';\n }\n }\n\n if (\n runCmdId === '-h' ||\n runCmdId === '--help' ||\n runCmdId === 'help' ||\n runCmdId === 'h'\n ) {\n printHelp();\n process.exit(0);\n }\n\n type ParsedArgs = Record<string, string | number | boolean | undefined>;\n\n function parseArgs(rawArgs: string[], commandArgs?: Record<string, Arg>): ParsedArgs {\n if (!commandArgs) return {};\n\n const parsed: ParsedArgs = {};\n const argEntries = typedObjectEntries(commandArgs);\n\n // Initialize with defaults\n for (const [key, argDef] of argEntries) {\n if (argDef.type === 'flag') {\n parsed[key] = false;\n } else if ('default' in argDef && argDef.default !== undefined) {\n parsed[key] = argDef.default;\n }\n }\n\n // Parse positional arguments (use object declaration order)\n const positionalArgs = argEntries\n .filter(([, argDef]) => argDef.type.startsWith('positional'));\n\n let positionalIndex = 0;\n let i = 0;\n \n while (i < rawArgs.length) {\n const currentArg = rawArgs[i];\n \n if (currentArg?.startsWith('--')) {\n // Handle flags\n const flagName = currentArg.slice(2);\n const flagEntry = argEntries.find(([, argDef]) => argDef.name === flagName);\n \n if (flagEntry) {\n const [key, argDef] = flagEntry;\n \n if (argDef.type === 'flag') {\n parsed[key] = true;\n i++;\n } else if (argDef.type === 'value-string-flag' || argDef.type === 'value-number-flag') {\n const value = rawArgs[i + 1];\n if (value && !value.startsWith('--')) {\n if (argDef.type === 'value-number-flag') {\n const numValue = Number(value);\n if (isNaN(numValue)) {\n console.error(styleText(['red', 'bold'], `Error: Invalid number \"${value}\" for --${argDef.name}`));\n process.exit(1);\n }\n parsed[key] = numValue;\n } else {\n parsed[key] = value;\n }\n i += 2;\n } else {\n console.error(styleText(['red', 'bold'], `Error: Missing value for --${argDef.name}`));\n process.exit(1);\n }\n } else {\n i++;\n }\n } else {\n console.error(styleText(['red', 'bold'], `Error: Unknown flag --${flagName}`));\n process.exit(1);\n }\n } else {\n // Handle positional arguments\n if (positionalIndex < positionalArgs.length) {\n const positionalEntry = positionalArgs[positionalIndex];\n if (positionalEntry) {\n const [key, argDef] = positionalEntry;\n if (argDef.type === 'positional-number') {\n const numValue = Number(currentArg);\n if (isNaN(numValue)) {\n console.error(styleText(['red', 'bold'], `Error: Invalid number \"${currentArg}\" for ${argDef.name}`));\n process.exit(1);\n }\n parsed[key] = numValue;\n } else {\n parsed[key] = currentArg;\n }\n positionalIndex++;\n }\n }\n i++;\n }\n }\n\n // Validate required positional arguments\n for (const [key, argDef] of positionalArgs) {\n if (!('default' in argDef) && parsed[key] === undefined) {\n console.error(styleText(['red', 'bold'], `Error: Missing required argument <${argDef.name}>`));\n process.exit(1);\n }\n }\n\n return parsed;\n }\n\n async function runCmd(cmd: string, args: string[]) {\n process.stdout.write('\\x1Bc'); // Clear console\n\n for (const [cmdId, { short, run: fn, args: commandArgs }] of typedObjectEntries(cmds)) {\n if (cmd === short || cmd === cmdId) {\n // Check if help is requested for this specific command\n if (args.includes('-h') || args.includes('--help')) {\n printCmdHelp(cmdId);\n process.exit(0);\n }\n\n console.info(\n `Running ${styleText(['blue', 'bold'], cmdId)}${short ? styleText(['dim'], `|${short}`) : ''}:\\n`,\n );\n\n const parsedArgs = parseArgs(args, commandArgs);\n await fn(parsedArgs);\n process.exit(0);\n }\n }\n\n console.error(styleText(['red', 'bold'], `Command '${cmd}' not found`));\n printHelp();\n process.exit(1);\n }\n\n if (runCmdId === 'i') {\n function hasRequiredArgs(args?: Record<string, Arg>): boolean {\n if (!args) return false;\n return typedObjectEntries(args).some(\n ([, arg]) =>\n (arg.type === 'positional-string' || arg.type === 'positional-number') &&\n !('default' in arg),\n );\n }\n\n let cmdEntries = typedObjectEntries(cmds);\n\n if (sort) {\n cmdEntries = sortBy(cmdEntries, ([cmd]) =>\n getAscIndexOrder(sort.indexOf(cmd)),\n );\n }\n\n const availableCmds = cmdEntries.filter(([, cmd]) => !hasRequiredArgs(cmd.args));\n\n const response = await cliInput.select('Select a command', {\n options: availableCmds.map(([cmd, { short, description }]) => ({\n value: cmd,\n label: short ? `${cmd} ${styleText(['dim'], '|')} ${short}` : cmd,\n hint: description,\n })),\n });\n\n await runCmd(response, []);\n } else {\n if (!runCmdId) {\n console.error(\n styleText(\n ['red', 'bold'],\n `Command not found, use \\`${baseCmd} h\\` to list all supported commands`,\n ),\n );\n console.info(styleText(['dim'], 'Use a command to get started!'));\n process.exit(1);\n }\n\n await runCmd(runCmdId, cmdArgs);\n }\n}\n"],"x_google_ignoreList":[1,2,3,4,5],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@ls-stack/cli",
3
+ "description": "CLI input utilities for interactive prompts",
4
+ "version": "0.1.0",
5
+ "license": "MIT",
6
+ "files": [
7
+ "dist"
8
+ ],
9
+ "repository": "github:lucasols/cli",
10
+ "author": "Lucas Santos",
11
+ "type": "module",
12
+ "module": "./dist/main.mjs",
13
+ "types": "./dist/main.d.mts",
14
+ "exports": {
15
+ ".": {
16
+ "import": {
17
+ "types": "./dist/main.d.mts",
18
+ "default": "./dist/main.mjs"
19
+ }
20
+ }
21
+ },
22
+ "sideEffects": false,
23
+ "engines": {
24
+ "node": ">=21.5.0"
25
+ },
26
+ "devDependencies": {
27
+ "@ls-stack/eslint-cfg": "^0.5.1",
28
+ "@ls-stack/utils": "^3.68.0",
29
+ "@types/node": "^24.7.1",
30
+ "prettier": "3.6.2",
31
+ "tsdown": "^0.20.2",
32
+ "tsx": "^4.19.4",
33
+ "typescript": "5.9.3",
34
+ "vitest": "^4.0.18"
35
+ },
36
+ "dependencies": {
37
+ "@inquirer/prompts": "^7.5.1"
38
+ },
39
+ "scripts": {
40
+ "test": "tsx scripts/test-cli.ts",
41
+ "lint": "pnpm tsc && pnpm eslint",
42
+ "tsc": "tsc -p tsconfig.prod.json",
43
+ "eslint": "CI=true eslint src/ scripts/ --color --max-warnings=0",
44
+ "build": "pnpm lint && tsdown",
45
+ "build:no-test": "tsdown"
46
+ }
47
+ }