@wise/wds-codemods 1.2.0 → 1.2.1-experimental-1f1926f

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.
@@ -1,18 +1,13 @@
1
- const require_common = require('./common-DdEQmI2h.js');
2
- let node_child_process = require("node:child_process");
3
- let node_path = require("node:path");
4
- let node_fs = require("node:fs");
5
- let _anthropic_ai_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
6
- let node_https = require("node:https");
7
- node_https = require_common.__toESM(node_https);
8
- let _listr2_manager = require("@listr2/manager");
9
- let listr2 = require("listr2");
10
-
1
+ import { t as CONSOLE_ICONS } from "./common-nTdKnfMB.js";
2
+ import { execSync } from "node:child_process";
3
+ import { resolve } from "node:path";
4
+ import { readFileSync } from "node:fs";
5
+ import { query } from "@anthropic-ai/claude-agent-sdk";
6
+ import https from "node:https";
7
+ import { Manager } from "@listr2/manager";
8
+ import { Listr } from "listr2";
11
9
  //#region src/constants/claude.ts
12
10
  const CLAUDE_SETTINGS_FILE = ".claude/settings.json";
13
- const VPN_COUNTDOWN_TIMEOUT = 5;
14
- const DIRECTORY_CONCURRENCY_LIMIT = 3;
15
- const FILE_CONCURRENCY_LIMIT = 10;
16
11
  const INITIAL_CLAUDE_PROMPT = `You are a code migration assistant that helps migrate TypeScript/JSX code of deprecated Wise Design System (WDS) components from '@transferwise/components', to their new replacement components as detailed in the relevant migration guide. The following is a list of rules that must always be followed throughout the migration process.
17
12
 
18
13
  Rules:
@@ -37,7 +32,6 @@ Additionally you'll receive:
37
32
  - File paths to migrate in individual queries
38
33
  - Deprecated component names at the end of this prompt
39
34
  - Migration context and guide for each deprecated component`;
40
-
41
35
  //#endregion
42
36
  //#region src/helpers/common/pathUtils.ts
43
37
  /** Split the path string to get the relative path after the directory, and wrap with ANSI color codes */
@@ -45,19 +39,16 @@ function formatPathOutput(directory, path, asDim) {
45
39
  const relativePath = path ? path.split(directory.replace(".", ""))[1] ?? path : directory;
46
40
  return asDim ? `\x1b[2m${relativePath}\x1b[0m` : `\x1b[32m${relativePath}\x1b[0m`;
47
41
  }
48
-
49
42
  //#endregion
50
43
  //#region src/helpers/common/timerUtils.ts
51
44
  /** Generates a formatted string representing the total elapsed time since the given start time */
52
45
  function generateElapsedTime(startTime) {
53
- const endTime = Date.now();
54
- const elapsedTime = Math.floor((endTime - startTime) / 1e3);
46
+ const elapsedTime = Math.floor((Date.now() - startTime) / 1e3);
55
47
  const hours = Math.floor(elapsedTime / 3600);
56
48
  const minutes = Math.floor(elapsedTime % 3600 / 60);
57
49
  const seconds = elapsedTime % 60;
58
50
  return `${hours ? `${hours}h ` : ""}${minutes ? `${minutes}m ` : ""}${seconds ? `${seconds}s` : ""}`;
59
51
  }
60
-
61
52
  //#endregion
62
53
  //#region src/helpers/common/vpnUtils.ts
63
54
  /** Checks VPN connectivity by pinging the provided base URL's /health endpoint, with countdown retries */
@@ -65,7 +56,7 @@ async function checkVPN(baseUrl, task) {
65
56
  if (!baseUrl) return;
66
57
  const checkOnce = async () => new Promise((resolveCheck) => {
67
58
  const url = new URL("/health", baseUrl);
68
- const req = node_https.default.get(url, {
59
+ const req = https.get(url, {
69
60
  timeout: 2e3,
70
61
  rejectUnauthorized: false
71
62
  }, (res) => {
@@ -83,7 +74,7 @@ async function checkVPN(baseUrl, task) {
83
74
  task.title = "Connected to VPN";
84
75
  break;
85
76
  }
86
- for (let countdown = VPN_COUNTDOWN_TIMEOUT; countdown > 0; countdown -= 1) {
77
+ for (let countdown = 5; countdown > 0; countdown -= 1) {
87
78
  task.output = `Please connect to VPN... retrying in ${countdown}s`;
88
79
  await new Promise((response) => {
89
80
  setTimeout(response, 1e3);
@@ -91,18 +82,17 @@ async function checkVPN(baseUrl, task) {
91
82
  }
92
83
  }
93
84
  }
94
-
95
85
  //#endregion
96
86
  //#region src/helpers/claude/query.ts
97
87
  /**
98
88
  * Creates reusable query options for Claude session, including authentication and system prompt
99
89
  */
100
90
  function getQueryOptions({ additionalPromptContext }) {
101
- const claudeSettingsPath = (0, node_path.resolve)(process.env.HOME || "", CLAUDE_SETTINGS_FILE);
102
- const settings = JSON.parse((0, node_fs.readFileSync)(claudeSettingsPath, "utf-8"));
91
+ const claudeSettingsPath = resolve(process.env.HOME || "", CLAUDE_SETTINGS_FILE);
92
+ const settings = JSON.parse(readFileSync(claudeSettingsPath, "utf-8"));
103
93
  let apiKey;
104
94
  try {
105
- apiKey = (0, node_child_process.execSync)(`bash ${settings.apiKeyHelper}`, { encoding: "utf-8" }).trim();
95
+ apiKey = execSync(`bash ${settings.apiKeyHelper}`, { encoding: "utf-8" }).trim();
106
96
  } catch {}
107
97
  if (!apiKey || !settings.env?.ANTHROPIC_BASE_URL) throw new Error("Failed to retrieve Anthropic API key or Base URL. Please check your Claude Code x LLM Gateway configuration - https://transferwise.atlassian.net/wiki/x/_YUe3Q");
108
98
  const { ANTHROPIC_CUSTOM_HEADERS, ...restEnvVars } = settings?.env ?? {};
@@ -143,7 +133,7 @@ async function initiateClaudeSessionOptions(manager, additionalPromptContext) {
143
133
  title: "Initialising Claude session",
144
134
  task: async (subCtx, subtask) => {
145
135
  subtask.output = "Your browser may open for Okta authentication if required";
146
- const result = (0, _anthropic_ai_claude_agent_sdk.query)({
136
+ const result = query({
147
137
  options,
148
138
  prompt: `This is an initialisation query to start a new Claude code migration session. No text response is needed.`
149
139
  });
@@ -159,7 +149,7 @@ async function initiateClaudeSessionOptions(manager, additionalPromptContext) {
159
149
  }
160
150
  }]);
161
151
  await manager.runAll().finally(() => {
162
- manager.options = { concurrent: DIRECTORY_CONCURRENCY_LIMIT };
152
+ manager.options = { concurrent: 3 };
163
153
  });
164
154
  return options;
165
155
  }
@@ -168,7 +158,7 @@ async function initiateClaudeSessionOptions(manager, additionalPromptContext) {
168
158
  */
169
159
  async function queryClaude(directory, filePath, options, task, isDebug = false) {
170
160
  const startTime = Date.now();
171
- const result = (0, _anthropic_ai_claude_agent_sdk.query)({
161
+ const result = query({
172
162
  options,
173
163
  prompt: filePath
174
164
  });
@@ -179,13 +169,12 @@ async function queryClaude(directory, filePath, options, task, isDebug = false)
179
169
  task.output = `\x1b[2mMigrated in ${generateElapsedTime(startTime)}\x1b[0m`;
180
170
  } else if (message.is_error) {
181
171
  task.title = `\x1b[2m${formatPathOutput(directory, filePath)}\x1b[0m]`;
182
- task.output = `${require_common.CONSOLE_ICONS.error} Claude encountered an error: ${JSON.stringify(message)}`;
172
+ task.output = `${CONSOLE_ICONS.error} Claude encountered an error: ${JSON.stringify(message)}`;
183
173
  }
184
174
  break;
185
175
  default:
186
176
  }
187
177
  }
188
-
189
178
  //#endregion
190
179
  //#region src/helpers/claude/transformer.ts
191
180
  /**
@@ -198,14 +187,14 @@ async function queryClaude(directory, filePath, options, task, isDebug = false)
198
187
  const claudeTransformer = async ({ targetDirectories, componentGrepPattern, additionalPromptContext, isDebug = false }) => {
199
188
  process.setMaxListeners(20);
200
189
  const startTime = Date.now();
201
- const manager = new _listr2_manager.Manager({ concurrent: true });
190
+ const manager = new Manager({ concurrent: true });
202
191
  const queryOptions = await initiateClaudeSessionOptions(manager, additionalPromptContext);
203
192
  manager.add([{
204
193
  title: "Processing target directories for migration...",
205
194
  task: async (ctx, task) => {
206
195
  return task.newListr(targetDirectories.map((directory) => {
207
- const matchingFilePaths = (0, node_child_process.execSync)(`find "${directory}" -name "*.tsx" -type f`, { encoding: "utf-8" }).trim().split("\n").filter(Boolean).filter((filePath) => {
208
- const content = (0, node_fs.readFileSync)(filePath, "utf-8");
196
+ const matchingFilePaths = execSync(`find "${directory}" -name "*.tsx" -type f`, { encoding: "utf-8" }).trim().split("\n").filter(Boolean).filter((filePath) => {
197
+ const content = readFileSync(filePath, "utf-8");
209
198
  return componentGrepPattern.test(content);
210
199
  });
211
200
  if (matchingFilePaths.length === 0) return {
@@ -228,7 +217,7 @@ const claudeTransformer = async ({ targetDirectories, componentGrepPattern, addi
228
217
  parentTask.title = `${isDim ? "\x1B[2m" : ""}${formatPathOutput(directory)} - Migrated \x1b[32m${completedFilesInDirectory.count}\x1b[0m/\x1b[32m${matchingFilePaths.length}\x1b[0m files${isDim ? "\x1B[0m" : ""}`;
229
218
  });
230
219
  }
231
- })), { concurrent: FILE_CONCURRENCY_LIMIT }).run();
220
+ })), { concurrent: 10 }).run();
232
221
  }
233
222
  };
234
223
  }), { rendererOptions: {
@@ -238,18 +227,13 @@ const claudeTransformer = async ({ targetDirectories, componentGrepPattern, addi
238
227
  }
239
228
  }]);
240
229
  await manager.runAll().finally(async () => {
241
- await new listr2.Listr([{
230
+ await new Listr([{
242
231
  title: `Finished migrating - elapsed time: \x1b[32m${generateElapsedTime(startTime)}\x1b[0m `,
243
232
  task: async () => {}
244
233
  }]).run();
245
234
  });
246
235
  };
247
-
248
236
  //#endregion
249
- Object.defineProperty(exports, 'claudeTransformer', {
250
- enumerable: true,
251
- get: function () {
252
- return claudeTransformer;
253
- }
254
- });
255
- //# sourceMappingURL=claude-BHYfEMfb.js.map
237
+ export { claudeTransformer as t };
238
+
239
+ //# sourceMappingURL=claude-cHSlHbX1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-cHSlHbX1.js","names":[],"sources":["../src/constants/claude.ts","../src/helpers/common/pathUtils.ts","../src/helpers/common/timerUtils.ts","../src/helpers/common/vpnUtils.ts","../src/helpers/claude/query.ts","../src/helpers/claude/transformer.ts"],"sourcesContent":["export const CLAUDE_SETTINGS_FILE = '.claude/settings.json';\nexport const VPN_COUNTDOWN_TIMEOUT = 5;\nexport const DIRECTORY_CONCURRENCY_LIMIT = 3;\nexport const FILE_CONCURRENCY_LIMIT = 10;\n\nexport const INITIAL_CLAUDE_PROMPT = `You are a code migration assistant that helps migrate TypeScript/JSX code of deprecated Wise Design System (WDS) components from '@transferwise/components', to their new replacement components as detailed in the relevant migration guide. The following is a list of rules that must always be followed throughout the migration process.\n\nRules:\n1. Only ever modify files via the Edit tool - do not use the Write tool\n2. When identifying what code to migrate within a file, explain how you identified it first.\n3. Migrate components per provided migration rules\n4. Maintain TypeScript type safety and update types to match new API\n5. Map props: handle renamed, deprecated, new required, and changed types\n6. Update imports to new WDS components and types\n7. Preserve code style, formatting, and calculated logic\n8. Handle conditional rendering, spread props, and complex expressions\n9. Note: New components may lack feature parity with legacy versions\n10. Only modify code requiring changes per migration rules, and any impacted surrounding code for context.\n11. Final result response should just be whether the migration was successful overall, or if any errors were encountered\n - Do not summarise or explain the changes made\n12. Explain your reasoning and justification before making changes, as you edit each file.\n - Keep it concise and succinct, as only bullet points\n13. After modifying the file, do not summarise the changes made.\n14. If you do not have permission to edit a file, still attempt to edit it and then move onto the next file.\n\nAdditionally you'll receive:\n- File paths to migrate in individual queries\n- Deprecated component names at the end of this prompt\n- Migration context and guide for each deprecated component`;\n","/** Split the path string to get the relative path after the directory, and wrap with ANSI color codes */\nexport function formatPathOutput(directory: string, path?: string, asDim?: boolean): string {\n const relativePath = path ? (path.split(directory.replace('.', ''))[1] ?? path) : directory;\n return asDim ? `\\x1b[2m${relativePath}\\x1b[0m` : `\\x1b[32m${relativePath}\\x1b[0m`;\n}\n","/** Generates a formatted string representing the total elapsed time since the given start time */\nexport function generateElapsedTime(startTime: number): string {\n const endTime = Date.now();\n const elapsedTime = Math.floor((endTime - startTime) / 1000);\n const hours = Math.floor(elapsedTime / 3600);\n const minutes = Math.floor((elapsedTime % 3600) / 60);\n const seconds = elapsedTime % 60;\n\n return `${hours ? `${hours}h ` : ''}${minutes ? `${minutes}m ` : ''}${seconds ? `${seconds}s` : ''}`;\n}\n","import https from 'node:https';\n\nimport type { DefaultRenderer, ListrTaskWrapper, SimpleRenderer } from 'listr2';\n\nimport { VPN_COUNTDOWN_TIMEOUT } from '../../constants/claude';\n\n/** Checks VPN connectivity by pinging the provided base URL's /health endpoint, with countdown retries */\nexport async function checkVPN(\n baseUrl: string | undefined,\n task: ListrTaskWrapper<never, typeof DefaultRenderer, typeof SimpleRenderer>,\n): Promise<void> {\n if (!baseUrl) return;\n\n const checkOnce = async (): Promise<boolean> =>\n new Promise<boolean>((resolveCheck) => {\n const url = new URL('/health', baseUrl);\n const req = https.get(url, { timeout: 2000, rejectUnauthorized: false }, (res) => {\n const ok = !!(res.statusCode && res.statusCode >= 200 && res.statusCode < 400);\n res.resume();\n resolveCheck(ok);\n });\n req.on('timeout', () => {\n req.destroy(new Error('timeout'));\n });\n req.on('error', () => resolveCheck(false));\n });\n\n while (true) {\n const ok = await checkOnce();\n if (ok) {\n // eslint-disable-next-line no-param-reassign\n task.title = 'Connected to VPN';\n break;\n }\n\n // Countdown from 5s\n for (let countdown = VPN_COUNTDOWN_TIMEOUT; countdown > 0; countdown -= 1) {\n // eslint-disable-next-line no-param-reassign\n task.output = `Please connect to VPN... retrying in ${countdown}s`;\n await new Promise<void>((response) => {\n setTimeout(response, 1000);\n });\n }\n }\n}\n","import { execSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\n\nimport { type Options, query } from '@anthropic-ai/claude-agent-sdk';\nimport type { Manager } from '@listr2/manager';\nimport type { DefaultRenderer, ListrTaskWrapper, SimpleRenderer } from 'listr2';\n\nimport {\n CLAUDE_SETTINGS_FILE,\n DIRECTORY_CONCURRENCY_LIMIT,\n INITIAL_CLAUDE_PROMPT,\n} from '../../constants/claude';\nimport { CONSOLE_ICONS } from '../../constants/common';\nimport { checkVPN, formatPathOutput, generateElapsedTime } from '../common';\n\ninterface ClaudeSettings {\n apiKeyHelper?: string;\n env?: {\n ANTHROPIC_BASE_URL?: string;\n ANTHROPIC_CUSTOM_HEADERS?: string;\n ANTHROPIC_DEFAULT_SONNET_MODEL?: string;\n ANTHROPIC_DEFAULT_HAIKU_MODEL?: string;\n ANTHROPIC_DEFAULT_OPUS_MODEL?: string;\n API_TIMEOUT_MS?: string;\n [key: string]: unknown;\n };\n [key: string]: unknown;\n}\n\ninterface QueryOptionProps {\n additionalPromptContext?: string;\n}\n\n/**\n * Creates reusable query options for Claude session, including authentication and system prompt\n */\nfunction getQueryOptions({ additionalPromptContext }: QueryOptionProps): Options {\n // Read settings from ~/.claude/settings.json to get headers and apiKeyHelper\n const claudeSettingsPath = resolve(process.env.HOME || '', CLAUDE_SETTINGS_FILE);\n const settings = JSON.parse(readFileSync(claudeSettingsPath, 'utf-8')) as ClaudeSettings;\n\n // Get API key by executing the apiKeyHelper script, for authenticating with Okta via LLM Gateway\n let apiKey;\n try {\n apiKey = execSync(`bash ${settings.apiKeyHelper}`, {\n encoding: 'utf-8',\n }).trim();\n } catch {}\n\n if (!apiKey || !settings.env?.ANTHROPIC_BASE_URL) {\n throw new Error(\n 'Failed to retrieve Anthropic API key or Base URL. Please check your Claude Code x LLM Gateway configuration - https://transferwise.atlassian.net/wiki/x/_YUe3Q',\n );\n }\n\n const { ANTHROPIC_CUSTOM_HEADERS, ...restEnvVars } = settings?.env ?? {};\n\n const envVars = {\n ANTHROPIC_AUTH_TOKEN: apiKey,\n ANTHROPIC_CUSTOM_HEADERS,\n ...restEnvVars,\n PATH: process.env.PATH, // Specifying PATH, as Claude Agent SDK seems to struggle consuming the actual environment PATH\n };\n\n return {\n env: envVars,\n permissionMode: 'acceptEdits',\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: `${INITIAL_CLAUDE_PROMPT}\\n${additionalPromptContext}`,\n },\n allowedTools: ['Grep', 'Read'],\n settingSources: ['local', 'project', 'user'],\n };\n}\n\n/**\n * Initiate a new Claude session/conversation and return reusable options\n */\nexport async function initiateClaudeSessionOptions(\n manager: Manager,\n additionalPromptContext: string,\n): Promise<Options> {\n let options: Options = {};\n\n manager.add([\n {\n title: 'Configuring Claude connection and instance...',\n task: async (ctx, task) => {\n options = getQueryOptions({ additionalPromptContext });\n\n return task.newListr([\n {\n title: 'Checking VPN connection...',\n task: async (\n subCtx,\n subtask: ListrTaskWrapper<never, typeof DefaultRenderer, typeof SimpleRenderer>,\n ) => checkVPN(options.env?.ANTHROPIC_BASE_URL, subtask),\n },\n {\n title: 'Initialising Claude session',\n task: async (\n subCtx,\n subtask: ListrTaskWrapper<never, typeof DefaultRenderer, typeof SimpleRenderer>,\n ) => {\n // eslint-disable-next-line no-param-reassign\n subtask.output = 'Your browser may open for Okta authentication if required';\n\n const result = query({\n options,\n prompt: `This is an initialisation query to start a new Claude code migration session. No text response is needed.`,\n });\n\n for await (const message of result) {\n switch (message.type) {\n case 'system':\n if (message.subtype === 'init' && !options.resume) {\n // Set the session ID to resume the conversation in future queries\n options.resume = message.session_id;\n }\n break;\n default:\n if (message.type === 'result' && message.subtype !== 'success') {\n throw new Error(\n `Claude encountered an error when initialising: ${message.errors.join('\\n')}`,\n );\n }\n }\n }\n\n // eslint-disable-next-line no-param-reassign\n task.title = 'Successfully configured and initialised Claude\\n';\n },\n },\n ]);\n },\n },\n ]);\n\n // Set manager to run tasks concurrently, once initialisation steps are done\n await manager.runAll().finally(() => {\n // eslint-disable-next-line no-param-reassign\n manager.options = {\n concurrent: DIRECTORY_CONCURRENCY_LIMIT,\n };\n });\n\n return options;\n}\n\n/**\n * Queries Claude with the given path and handles logging of success/error messages\n */\nexport async function queryClaude(\n directory: string,\n filePath: string,\n options: Options,\n task: ListrTaskWrapper<never, typeof DefaultRenderer, typeof SimpleRenderer>,\n isDebug = false,\n) {\n const startTime = Date.now();\n const result = query({\n options,\n prompt: filePath,\n });\n\n for await (const message of result) {\n switch (message.type) {\n case 'result':\n if (message.subtype === 'success' && isDebug) {\n // eslint-disable-next-line no-param-reassign\n task.title = `\\x1b[2m${formatPathOutput(directory, filePath)}\\x1b[0m]`;\n // eslint-disable-next-line no-param-reassign\n task.output = `\\x1b[2mMigrated in ${generateElapsedTime(startTime)}\\x1b[0m`;\n } else if (message.is_error) {\n // eslint-disable-next-line no-param-reassign\n task.title = `\\x1b[2m${formatPathOutput(directory, filePath)}\\x1b[0m]`;\n // eslint-disable-next-line no-param-reassign\n task.output = `${CONSOLE_ICONS.error} Claude encountered an error: ${JSON.stringify(message)}`;\n }\n break;\n default:\n }\n }\n}\n","import { execSync } from 'node:child_process';\nimport { readFileSync } from 'node:fs';\n\nimport { Manager } from '@listr2/manager';\nimport {\n type DefaultRenderer,\n Listr,\n type ListrTask,\n type ListrTaskWrapper,\n type SimpleRenderer,\n} from 'listr2';\n\nimport { FILE_CONCURRENCY_LIMIT } from '../../constants/claude';\nimport { formatPathOutput, generateElapsedTime } from '../common';\nimport { initiateClaudeSessionOptions, queryClaude } from './query';\n\ninterface ClaudeTransformerOptions {\n targetDirectories: string[];\n componentGrepPattern: RegExp;\n additionalPromptContext: string;\n isDebug?: boolean;\n}\n\n/**\n * Performs code migration using Claude for the specified target directories, for the provided deprecated components and migration guides.\n * @param targetDirectories - Array of directory paths to process\n * @param componentGrepPattern - RegExp pattern to identify files needing migration (e.g. via deprecated component imports)\n * @param isDebug - Whether to enable debug logging\n * @param additionalPromptContext - Additional context to include in the initial Claude prompt before processing files\n */\nexport const claudeTransformer = async ({\n targetDirectories,\n componentGrepPattern,\n additionalPromptContext,\n isDebug = false,\n}: ClaudeTransformerOptions) => {\n process.setMaxListeners(20); // Resolves potential memory issues with how Claude handles its own event listeners\n const startTime = Date.now();\n // Create manager for handling multiple listr instances\n const manager = new Manager({\n concurrent: true,\n });\n const queryOptions = await initiateClaudeSessionOptions(manager, additionalPromptContext);\n\n manager.add([\n {\n title: 'Processing target directories for migration...',\n task: async (ctx, task) => {\n return task.newListr(\n targetDirectories.map((directory) => {\n // Find all .tsx files in the directory\n const allTsxFiles = execSync(`find \"${directory}\" -name \"*.tsx\" -type f`, {\n encoding: 'utf-8',\n })\n .trim()\n .split('\\n')\n .filter(Boolean);\n\n // Filter files that match the pattern by reading and testing each file\n const matchingFilePaths = allTsxFiles.filter((filePath) => {\n const content = readFileSync(filePath, 'utf-8');\n return componentGrepPattern.test(content);\n });\n\n // No files to process in this directory, so we add a task that's immediately skipped\n if (matchingFilePaths.length === 0) {\n return {\n title: `\\x1b[2m${formatPathOutput(directory)} - No files need migration\\x1b[0m`,\n task: (subCtx: ListrTask): void => {\n // eslint-disable-next-line no-param-reassign\n subCtx.skip = true;\n },\n };\n }\n\n return {\n title: `${formatPathOutput(directory)} - Found \\x1b[32m${matchingFilePaths.length}\\x1b[0m file(s) needing migration`,\n task: async (subCtx, parentTask) => {\n // eslint-disable-next-line no-param-reassign\n parentTask.title = `${formatPathOutput(directory)} - Migrating \\x1b[32m${matchingFilePaths.length}\\x1b[0m file(s)...`;\n const completedFilesInDirectory = { count: 0 };\n return parentTask\n .newListr(\n matchingFilePaths.map((filePath) => ({\n title: '', // No title so it runs in the background without any console output\n task: async (\n fileCtx,\n fileTask: ListrTaskWrapper<\n never,\n typeof DefaultRenderer,\n typeof SimpleRenderer\n >,\n ) => {\n await queryClaude(\n directory,\n filePath,\n queryOptions,\n fileTask,\n isDebug,\n ).finally(() => {\n // Update parent task title with progress for each completed file migration\n completedFilesInDirectory.count += 1;\n const isDim =\n completedFilesInDirectory.count === matchingFilePaths.length;\n // eslint-disable-next-line no-param-reassign\n parentTask.title = `${isDim ? '\\x1b[2m' : ''}${formatPathOutput(directory)} - Migrated \\x1b[32m${completedFilesInDirectory.count}\\x1b[0m/\\x1b[32m${matchingFilePaths.length}\\x1b[0m files${isDim ? '\\x1b[0m' : ''}`;\n });\n },\n })),\n { concurrent: FILE_CONCURRENCY_LIMIT },\n )\n .run();\n },\n };\n }),\n { rendererOptions: { suffixSkips: false, collapseSubtasks: false } },\n );\n },\n },\n ]);\n\n // Run all directory tasks concurrently, with final follow up/summary task\n await manager.runAll().finally(async () => {\n await new Listr([\n {\n title: `Finished migrating - elapsed time: \\x1b[32m${generateElapsedTime(startTime)}\\x1b[0m `,\n task: async () => {\n // Task completes immediately\n },\n },\n ]).run();\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ //#region src/constants/common.ts
2
+ const CONSOLE_ICONS = {
3
+ info: "\x1B[34mℹ\x1B[0m",
4
+ focus: "\x1B[34m➙\x1B[0m",
5
+ success: "\x1B[32m✔\x1B[0m",
6
+ warning: "\x1B[33m⚠\x1B[0m",
7
+ error: "\x1B[31m✖\x1B[0m",
8
+ claude: "\x1B[35m💬\x1B[0m"
9
+ };
10
+ //#endregion
11
+ export { CONSOLE_ICONS as t };
12
+
13
+ //# sourceMappingURL=common-nTdKnfMB.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"common-DdEQmI2h.js","names":[],"sources":["../src/constants/common.ts"],"sourcesContent":["export const CONSOLE_ICONS = {\n info: '\\x1b[34mℹ\\x1b[0m', // Blue info icon\n focus: '\\x1b[34m➙\\x1b[0m', // Blue arrow icon\n success: '\\x1b[32m✔\\x1b[0m', // Green checkmark\n warning: '\\x1b[33m⚠\\x1b[0m', // Yellow warning icon\n error: '\\x1b[31m✖\\x1b[0m', // Red cross icon\n claude: '\\x1b[35m💬\\x1b[0m', // Speech bubble\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,MAAa,gBAAgB;CAC3B,MAAM;CACN,OAAO;CACP,SAAS;CACT,SAAS;CACT,OAAO;CACP,QAAQ;CACT"}
1
+ {"version":3,"file":"common-nTdKnfMB.js","names":[],"sources":["../src/constants/common.ts"],"sourcesContent":["export const CONSOLE_ICONS = {\n info: '\\x1b[34mℹ\\x1b[0m', // Blue info icon\n focus: '\\x1b[34m➙\\x1b[0m', // Blue arrow icon\n success: '\\x1b[32m✔\\x1b[0m', // Green checkmark\n warning: '\\x1b[33m⚠\\x1b[0m', // Yellow warning icon\n error: '\\x1b[31m✖\\x1b[0m', // Red cross icon\n claude: '\\x1b[35m💬\\x1b[0m', // Speech bubble\n};\n"],"mappings":";AAAA,MAAa,gBAAgB;CAC3B,MAAM;CACN,OAAO;CACP,SAAS;CACT,SAAS;CACT,OAAO;CACP,QAAQ;CACT"}