From f206e162aa9f51f8e133d925aa32d62adc6fff6b Mon Sep 17 00:00:00 2001 From: Zeno Jiricek Date: Sat, 23 Aug 2025 16:45:00 +0930 Subject: [PATCH 1/3] 1228: Process commands with context that might be strings or array of strings --- packages/knip/src/plugins/moonrepo/index.ts | 9 +++-- packages/knip/src/plugins/moonrepo/types.ts | 2 +- packages/knip/src/util/string.ts | 38 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/packages/knip/src/plugins/moonrepo/index.ts b/packages/knip/src/plugins/moonrepo/index.ts index cdfaf1b34..6d2ae3987 100644 --- a/packages/knip/src/plugins/moonrepo/index.ts +++ b/packages/knip/src/plugins/moonrepo/index.ts @@ -1,5 +1,6 @@ import type { IsPluginEnabled, Plugin, ResolveConfig } from '../../types/config.js'; import { hasDependency } from '../../util/plugin.js'; +import { createCommandProcessor } from '../../util/string.js'; import type { MoonConfiguration } from './types.js'; // https://moonrepo.dev/docs @@ -15,16 +16,20 @@ const isRootOnly = true; const config = ['moon.yml', '.moon/tasks.yml', '.moon/tasks/*.yml']; const resolveConfig: ResolveConfig = async (config, options) => { + const commandProcessor = createCommandProcessor({ + '$projectRoot': options.cwd, + '$workspaceRoot': options.rootCwd, + }) const tasks = config.tasks ? Object.values(config.tasks) : []; const inputs = tasks .map(task => task.command) .filter(command => command) - .map(command => command.replace('$workspaceRoot', options.rootCwd)) - .map(command => command.replace('$projectRoot', options.cwd)) + .map(commandProcessor) .flatMap(command => options.getInputsFromScripts(command)); return [...inputs]; }; + export default { title, enablers, diff --git a/packages/knip/src/plugins/moonrepo/types.ts b/packages/knip/src/plugins/moonrepo/types.ts index b94f4f425..ef2b529fc 100644 --- a/packages/knip/src/plugins/moonrepo/types.ts +++ b/packages/knip/src/plugins/moonrepo/types.ts @@ -1,7 +1,7 @@ export interface MoonConfiguration { tasks?: { [taskName: string]: { - command: string; + command: string | string[]; }; }; } diff --git a/packages/knip/src/util/string.ts b/packages/knip/src/util/string.ts index df3886ef5..19dffad20 100644 --- a/packages/knip/src/util/string.ts +++ b/packages/knip/src/util/string.ts @@ -68,3 +68,41 @@ export const prettyMilliseconds = (ms: number): string => { if (minutes > 0) return `${minutes}m ${Math.floor(seconds % 60)}s`; return seconds % 1 ? `${seconds.toFixed(1)}s` : `${Math.floor(seconds)}s`; }; + +/** + * Template literal processor for commands that might be + * strings or arrays of strings. + * + * @example + * ```ts + * const processor = createCommandProcessor({ '$projectRoot': '/path/to/project' }); + * const command = processor('echo $projectRoot'); + * console.log(command); // 'echo /path/to/project' + * ``` + */ +export const createCommandProcessor = (context: T) => { + + const templater = (template: string):string => { + return template.replace(/\$(\w+)/g, (_, key) => { + const value = context[key as keyof T]; + if (!value) { + return key; + } + return String(value); + }); + } + + const processor = (command: C): C => { + if (typeof command === 'string') { + return templater(command) as C; + } + + if (Array.isArray(command)) { + return command.map(cmd => processor(cmd)) as C; + } + + throw new TypeError('Command must be a string or an array of strings'); + } + + return processor +} \ No newline at end of file From 40d0140c1a52e901b75560698d0c704dcd268983 Mon Sep 17 00:00:00 2001 From: Zeno Jiricek Date: Sat, 23 Aug 2025 16:51:45 +0930 Subject: [PATCH 2/3] update comment --- packages/knip/src/util/string.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/knip/src/util/string.ts b/packages/knip/src/util/string.ts index 19dffad20..b7bbbda94 100644 --- a/packages/knip/src/util/string.ts +++ b/packages/knip/src/util/string.ts @@ -77,7 +77,12 @@ export const prettyMilliseconds = (ms: number): string => { * ```ts * const processor = createCommandProcessor({ '$projectRoot': '/path/to/project' }); * const command = processor('echo $projectRoot'); - * console.log(command); // 'echo /path/to/project' + * + * console.log(command); + * // 'echo /path/to/project' + * + * processor(['npx', 'tsx', '$projectRoot/server/worker.js', '--', '--force']); + * // ['npx', 'tsx', '/path/to/project/server/worker.js', '--', '--force'] * ``` */ export const createCommandProcessor = (context: T) => { From 0e6c724a6148d2c799e7faf37c6a7a5390b9c3d4 Mon Sep 17 00:00:00 2001 From: Zeno Jiricek Date: Sat, 23 Aug 2025 16:52:57 +0930 Subject: [PATCH 3/3] more update --- packages/knip/src/util/string.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/knip/src/util/string.ts b/packages/knip/src/util/string.ts index b7bbbda94..338d1515a 100644 --- a/packages/knip/src/util/string.ts +++ b/packages/knip/src/util/string.ts @@ -76,12 +76,11 @@ export const prettyMilliseconds = (ms: number): string => { * @example * ```ts * const processor = createCommandProcessor({ '$projectRoot': '/path/to/project' }); - * const command = processor('echo $projectRoot'); * - * console.log(command); + * console.log(processor('echo $projectRoot')); * // 'echo /path/to/project' * - * processor(['npx', 'tsx', '$projectRoot/server/worker.js', '--', '--force']); + * console.log(processor(['npx', 'tsx', '$projectRoot/server/worker.js', '--', '--force'])); * // ['npx', 'tsx', '/path/to/project/server/worker.js', '--', '--force'] * ``` */