@wise/wds-codemods 1.0.0-experimental-7b44bcb → 1.0.0-experimental-0f5c549
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.
- package/dist/{helpers-DK6VpT4p.js → helpers-Cca1yIbM.js} +4 -59
- package/dist/helpers-Cca1yIbM.js.map +1 -0
- package/dist/index.js +24 -36
- package/dist/index.js.map +1 -1
- package/dist/{transformer-CzbLs8NN.js → transformer-BqBEjGcV.js} +78 -28
- package/dist/transformer-BqBEjGcV.js.map +1 -0
- package/dist/transforms/button/transformer.js +1 -1
- package/dist/transforms/list-item/transformer.js +1 -1
- package/package.json +3 -3
- package/dist/helpers-DK6VpT4p.js.map +0 -1
- package/dist/transformer-CzbLs8NN.js.map +0 -1
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
const require_helpers = require('./helpers-
|
|
1
|
+
const require_helpers = require('./helpers-Cca1yIbM.js');
|
|
2
2
|
let node_child_process = require("node:child_process");
|
|
3
3
|
let node_path = require("node:path");
|
|
4
|
-
let node_fs = require("node:fs");
|
|
5
4
|
let __anthropic_ai_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
5
|
+
let node_fs = require("node:fs");
|
|
6
|
+
let diff = require("diff");
|
|
6
7
|
|
|
7
8
|
//#region src/constants.ts
|
|
8
9
|
const CONSOLE_ICONS = {
|
|
@@ -10,7 +11,8 @@ const CONSOLE_ICONS = {
|
|
|
10
11
|
focus: "\x1B[34m➙\x1B[0m",
|
|
11
12
|
success: "\x1B[32m✔\x1B[0m",
|
|
12
13
|
warning: "\x1B[33m⚠\x1B[0m",
|
|
13
|
-
error: "\x1B[31m✖\x1B[0m"
|
|
14
|
+
error: "\x1B[31m✖\x1B[0m",
|
|
15
|
+
claude: "\x1B[35m💬\x1B[0m"
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
//#endregion
|
|
@@ -197,12 +199,13 @@ Rules:
|
|
|
197
199
|
7. Handle conditional rendering, spread props, and complex expressions
|
|
198
200
|
8. Note: New components may lack feature parity with legacy versions
|
|
199
201
|
9. Only modify code requiring changes per migration rules, and any impacted surrounding code for context.
|
|
200
|
-
10.
|
|
201
|
-
11.
|
|
202
|
-
12.
|
|
203
|
-
13.
|
|
202
|
+
10. Do not summarise the initial user request in a response.
|
|
203
|
+
11. Use glob to find files in the directory and then grep to identify files with deprecated imports.
|
|
204
|
+
12. Final result response should just be whether the migration was successful overall, or if any errors were encountered
|
|
205
|
+
13. Explain your reasoning and justification before making changes, as you edit each file. Keep it concise and succinct as only bullet points
|
|
206
|
+
14. Do not summarise the changes made after modifying a file.
|
|
204
207
|
|
|
205
|
-
Make the necessary updates to the files
|
|
208
|
+
Make the necessary updates to the files.
|
|
206
209
|
|
|
207
210
|
You'll receive:
|
|
208
211
|
- File paths/directories to search in individual queries
|
|
@@ -228,11 +231,45 @@ function generateElapsedTime(startTime) {
|
|
|
228
231
|
const seconds = elapsedTime % 60;
|
|
229
232
|
return `${hours ? `${hours}h ` : ""}${minutes ? `${minutes}m ` : ""}${seconds ? `${seconds}s` : ""}`;
|
|
230
233
|
}
|
|
234
|
+
function formatClaudeResponseContent(content) {
|
|
235
|
+
return `\x1b[2m${content.replace(/\*\*(.+?)\*\*/gu, "\x1B[1m$1\x1B[0m\x1B[2m").replace(/`(.+?)`/gu, "\x1B[32m$1\x1B[0m\x1B[2m").split("\n").map((line, index) => index === 0 ? line : ` ${line}`).join("\n")}\x1b[0m`;
|
|
236
|
+
}
|
|
237
|
+
function generateDiff(original, modified) {
|
|
238
|
+
const lines = (0, diff.createPatch)("", original, modified, "", "").trim().split("\n").slice(4).filter((line) => !line.startsWith("\"));
|
|
239
|
+
let oldLineNumber = 0;
|
|
240
|
+
let newLineNumber = 0;
|
|
241
|
+
return lines.map((line) => {
|
|
242
|
+
const trimmedLine = line.trimEnd();
|
|
243
|
+
if (trimmedLine.startsWith("@@")) {
|
|
244
|
+
const match = /@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/u.exec(trimmedLine);
|
|
245
|
+
if (match) {
|
|
246
|
+
oldLineNumber = Number.parseInt(match[1], 10);
|
|
247
|
+
newLineNumber = Number.parseInt(match[2], 10);
|
|
248
|
+
}
|
|
249
|
+
return `\x1b[36m${trimmedLine}\x1b[0m`;
|
|
250
|
+
}
|
|
251
|
+
let linePrefix = "";
|
|
252
|
+
if (trimmedLine.startsWith("+")) {
|
|
253
|
+
linePrefix = `${newLineNumber.toString().padStart(4, " ")} `;
|
|
254
|
+
newLineNumber += 1;
|
|
255
|
+
return `\x1b[32m${linePrefix}${trimmedLine}\x1b[0m`;
|
|
256
|
+
}
|
|
257
|
+
if (trimmedLine.startsWith("-")) {
|
|
258
|
+
linePrefix = `${oldLineNumber.toString().padStart(4, " ")} `;
|
|
259
|
+
oldLineNumber += 1;
|
|
260
|
+
return `\x1b[31m${linePrefix}${trimmedLine}\x1b[0m`;
|
|
261
|
+
}
|
|
262
|
+
linePrefix = `${oldLineNumber.toString().padStart(4, " ")} `;
|
|
263
|
+
oldLineNumber += 1;
|
|
264
|
+
newLineNumber += 1;
|
|
265
|
+
return `${linePrefix}${trimmedLine}`;
|
|
266
|
+
}).join("\n");
|
|
267
|
+
}
|
|
231
268
|
|
|
232
269
|
//#endregion
|
|
233
270
|
//#region src/transforms/list-item/claude.ts
|
|
234
271
|
const CLAUDE_SETTINGS_FILE = ".claude/settings.json";
|
|
235
|
-
function getQueryOptions(sessionId, isDebug) {
|
|
272
|
+
function getQueryOptions(sessionId, codemodOptions, isDebug) {
|
|
236
273
|
const claudeSettingsPath = (0, node_path.resolve)(process.env.HOME || "", CLAUDE_SETTINGS_FILE);
|
|
237
274
|
const settings = JSON.parse((0, node_fs.readFileSync)(claudeSettingsPath, "utf-8"));
|
|
238
275
|
let apiKey;
|
|
@@ -240,29 +277,33 @@ function getQueryOptions(sessionId, isDebug) {
|
|
|
240
277
|
apiKey = (0, node_child_process.execSync)(`bash ${settings.apiKeyHelper}`, { encoding: "utf-8" }).trim();
|
|
241
278
|
} catch {}
|
|
242
279
|
if (!apiKey) throw new Error("Failed to retrieve Anthropic API key. Please check your Claude Code x LLM Gateway configuration - https://transferwise.atlassian.net/wiki/x/_YUe3Q");
|
|
280
|
+
const { ANTHROPIC_CUSTOM_HEADERS, ...restEnvVars } = settings?.env || {};
|
|
243
281
|
const envVars = {
|
|
244
282
|
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: settings.env?.ANTHROPIC_DEFAULT_SONNET_MODEL,
|
|
248
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL: settings.env?.ANTHROPIC_DEFAULT_HAIKU_MODEL,
|
|
249
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: settings.env?.ANTHROPIC_DEFAULT_OPUS_MODEL,
|
|
250
|
-
API_TIMEOUT_MS: settings.env?.API_TIMEOUT_MS,
|
|
283
|
+
ANTHROPIC_CUSTOM_HEADERS,
|
|
284
|
+
...restEnvVars,
|
|
251
285
|
PATH: process.env.PATH
|
|
252
286
|
};
|
|
253
287
|
if (isDebug) {
|
|
254
288
|
const { ANTHROPIC_AUTH_TOKEN, ...restVars } = envVars;
|
|
255
|
-
console.log(`${CONSOLE_ICONS.info} Claude configuration environment variables
|
|
289
|
+
console.log(`${CONSOLE_ICONS.info} Claude configuration environment variables, excluding ANTHROPIC_AUTH_TOKEN:`);
|
|
290
|
+
console.log(restVars);
|
|
256
291
|
}
|
|
257
292
|
return {
|
|
258
293
|
resume: sessionId,
|
|
259
294
|
env: envVars,
|
|
260
|
-
permissionMode: "acceptEdits",
|
|
295
|
+
permissionMode: codemodOptions?.isDry ? void 0 : "acceptEdits",
|
|
261
296
|
systemPrompt: {
|
|
262
297
|
type: "preset",
|
|
263
298
|
preset: "claude_code",
|
|
264
299
|
append: SYSTEM_PROMPT
|
|
265
300
|
},
|
|
301
|
+
allowedTools: [
|
|
302
|
+
"Glob",
|
|
303
|
+
"Grep",
|
|
304
|
+
"Read",
|
|
305
|
+
...!codemodOptions?.isDry ? ["Write", "Edit"] : []
|
|
306
|
+
],
|
|
266
307
|
settingSources: [
|
|
267
308
|
"local",
|
|
268
309
|
"project",
|
|
@@ -271,12 +312,13 @@ function getQueryOptions(sessionId, isDebug) {
|
|
|
271
312
|
};
|
|
272
313
|
}
|
|
273
314
|
/** Initiate a new Claude session/conversation and return reusable options */
|
|
274
|
-
async function initiateClaudeSessionOptions(isDebug = false) {
|
|
315
|
+
async function initiateClaudeSessionOptions(codemodOptions, isDebug = false) {
|
|
275
316
|
console.log(`${CONSOLE_ICONS.info} Starting Claude instance - your browser may open for Okta authentication if required.`);
|
|
276
|
-
const options = getQueryOptions(void 0, isDebug);
|
|
317
|
+
const options = getQueryOptions(void 0, codemodOptions, isDebug);
|
|
318
|
+
if (isDebug) console.log(`${CONSOLE_ICONS.info} Allowed tools for this session: ${options.allowedTools?.join(", ")}`);
|
|
277
319
|
const result = (0, __anthropic_ai_claude_agent_sdk.query)({
|
|
278
320
|
options,
|
|
279
|
-
prompt: `You'll be given
|
|
321
|
+
prompt: `You'll be given file paths in additional individual queries to search in for files using deprecated Wise Design System (WDS) components. Migrate the code per the provided migration rules.`
|
|
280
322
|
});
|
|
281
323
|
for await (const message of result) switch (message.type) {
|
|
282
324
|
case "system":
|
|
@@ -289,7 +331,7 @@ async function initiateClaudeSessionOptions(isDebug = false) {
|
|
|
289
331
|
}
|
|
290
332
|
return options;
|
|
291
333
|
}
|
|
292
|
-
async function queryClaude(path, options, isDebug = false) {
|
|
334
|
+
async function queryClaude(path, options, codemodOptions, isDebug = false) {
|
|
293
335
|
const result = (0, __anthropic_ai_claude_agent_sdk.query)({
|
|
294
336
|
options,
|
|
295
337
|
prompt: path
|
|
@@ -299,14 +341,22 @@ async function queryClaude(path, options, isDebug = false) {
|
|
|
299
341
|
case "assistant":
|
|
300
342
|
for (const msg of message.message.content) switch (msg.type) {
|
|
301
343
|
case "tool_use":
|
|
302
|
-
if (msg.name === "Glob"
|
|
344
|
+
if (msg.name === "Glob") console.log(`${CONSOLE_ICONS.info} Finding all files within: ${formatPathOutput(path)}...`);
|
|
345
|
+
else if (msg.name === "Grep") console.log(`${CONSOLE_ICONS.info} Identifying files with deprecated imports: ${formatPathOutput(path)}...`);
|
|
303
346
|
else if (msg.name === "Read") console.log(`${CONSOLE_ICONS.info} Reading ${formatPathOutput(path, msg.input.file_path)}`);
|
|
304
347
|
else if ((msg.name === "Write" || msg.name === "Edit") && !modifiedFiles.includes(msg.input.file_path)) {
|
|
305
348
|
modifiedFiles.push(msg.input.file_path);
|
|
306
|
-
|
|
349
|
+
if (codemodOptions.isPrint) {
|
|
350
|
+
console.log(`${CONSOLE_ICONS.info} Changes for ${formatPathOutput(path, msg.input.file_path)}:`);
|
|
351
|
+
const diff$1 = generateDiff(msg.input.old_string, msg.input.new_string);
|
|
352
|
+
console.log(diff$1);
|
|
353
|
+
} else console.log(`${CONSOLE_ICONS.info} ${codemodOptions.isDry ? "Proposed changes for" : "Migrated"} ${formatPathOutput(path, msg.input.file_path)}`);
|
|
307
354
|
}
|
|
308
355
|
break;
|
|
309
|
-
|
|
356
|
+
case "text":
|
|
357
|
+
if (isDebug) console.log(`${CONSOLE_ICONS.claude} ${formatClaudeResponseContent(msg.text)}`);
|
|
358
|
+
break;
|
|
359
|
+
default: if (isDebug) console.log(msg);
|
|
310
360
|
}
|
|
311
361
|
break;
|
|
312
362
|
case "result":
|
|
@@ -319,11 +369,11 @@ async function queryClaude(path, options, isDebug = false) {
|
|
|
319
369
|
|
|
320
370
|
//#endregion
|
|
321
371
|
//#region src/transforms/list-item/transformer.ts
|
|
322
|
-
const transformer = async (
|
|
372
|
+
const transformer = async (codemodOptions, codemodPath, isDebug = false) => {
|
|
323
373
|
const startTime = Date.now();
|
|
324
|
-
const queryOptions = await initiateClaudeSessionOptions(isDebug);
|
|
374
|
+
const queryOptions = await initiateClaudeSessionOptions(codemodOptions, isDebug);
|
|
325
375
|
console.log(`${CONSOLE_ICONS.info} Analysing targetted paths - this may take a while...`);
|
|
326
|
-
for (const directory of targetPaths) await queryClaude(directory, queryOptions, isDebug);
|
|
376
|
+
for (const directory of codemodOptions.targetPaths) await queryClaude(directory, queryOptions, codemodOptions, isDebug);
|
|
327
377
|
console.log(`${CONSOLE_ICONS.success} Finished migrating - elapsed time: \x1b[1m${generateElapsedTime(startTime)}\x1b[0m`);
|
|
328
378
|
};
|
|
329
379
|
var transformer_default = transformer;
|
|
@@ -341,4 +391,4 @@ Object.defineProperty(exports, 'transformer_default', {
|
|
|
341
391
|
return transformer_default;
|
|
342
392
|
}
|
|
343
393
|
});
|
|
344
|
-
//# sourceMappingURL=transformer-
|
|
394
|
+
//# sourceMappingURL=transformer-BqBEjGcV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformer-BqBEjGcV.js","names":["modifiedFiles: string[]","diff"],"sources":["../src/constants.ts","../src/transforms/list-item/constants.ts","../src/transforms/list-item/helpers.ts","../src/transforms/list-item/claude.ts","../src/transforms/list-item/transformer.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', // Magenta speech bubble\n};\n","const DEPRECATED_COMPONENT_NAMES = [\n 'ActionOption',\n 'NavigationOption',\n 'NavigationOptionsList',\n 'Summary',\n 'SwitchOption',\n 'CheckboxOption',\n 'RadioOption',\n];\n\nconst MIGRATION_RULES = `Migration rules:\n# Legacy Component → ListItem Migration Guide\n\n## Universal Rules\n\n1. Wrap all \\`ListItem\\` in \\`<List>\\`\n2. \\`title\\` → \\`title\\` (direct)\n3. \\`content\\` or \\`description\\` → \\`subtitle\\`\n4. \\`disabled\\` stays on \\`ListItem\\` (not controls)\n5. Keep HTML attributes (\\`id\\`, \\`name\\`, \\`aria-label\\`), remove: \\`as\\`, \\`complex\\`, \\`showMediaAtAllSizes\\`, \\`showMediaCircle\\`, \\`isContainerAligned\\`\n\n---\n\n## ActionOption → ListItem.Button\n\n- \\`action\\` → Button children\n- \\`onClick\\` → Button \\`onClick\\`\n- Priority: default/\\`\"primary\"\\` → \\`\"primary\"\\`, \\`\"secondary\"\\` → \\`\"secondary-neutral\"\\`, \\`\"secondary-send\"\\` → \\`\"secondary\"\\`, \\`\"tertiary\"\\` → \\`\"tertiary\"\\`\n\n\\`\\`\\`tsx\n<ActionOption title=\"Title\" content=\"Text\" action=\"Click\" priority=\"secondary\" onClick={fn} />\n→\n<List><ListItem title=\"Title\" subtitle=\"Text\" control={<ListItem.Button priority=\"secondary-neutral\" onClick={fn}>Click</ListItem.Button>} /></List>\n\\`\\`\\`\n\n---\n\n## CheckboxOption → ListItem.Checkbox\n\n- \\`onChange\\`: \\`(checked: boolean)\\` → \\`(event: ChangeEvent)\\` use \\`event.target.checked\\`\n- \\`id\\`, \\`name\\` move to Checkbox\n\n\\`\\`\\`tsx\n<CheckboxOption id=\"x\" name=\"y\" title=\"Title\" content=\"Text\" checked={v} onChange={(c) => set(c)} />\n→\n<List><ListItem title=\"Title\" subtitle=\"Text\" control={<ListItem.Checkbox id=\"x\" name=\"y\" checked={v} onChange={(e) => set(e.target.checked)} />} /></List>\n\\`\\`\\`\n\n---\n\n## RadioOption → ListItem.Radio\n\n- \\`id\\`, \\`name\\`, \\`value\\`, \\`checked\\`, \\`onChange\\` move to Radio\n\n\\`\\`\\`tsx\n<RadioOption id=\"x\" name=\"y\" value=\"v\" title=\"Title\" content=\"Text\" checked={v==='v'} onChange={set} />\n→\n<List><ListItem title=\"Title\" subtitle=\"Text\" control={<ListItem.Radio id=\"x\" name=\"y\" value=\"v\" checked={v==='v'} onChange={set} />} /></List>\n\\`\\`\\`\n\n---\n\n## SwitchOption → ListItem.Switch\n\n- \\`onChange\\` → \\`onClick\\`, toggle manually\n- \\`aria-label\\` moves to Switch\n\n\\`\\`\\`tsx\n<SwitchOption title=\"Title\" content=\"Text\" checked={v} aria-label=\"Toggle\" onChange={set} />\n→\n<List><ListItem title=\"Title\" subtitle=\"Text\" control={<ListItem.Switch checked={v} aria-label=\"Toggle\" onClick={() => set(!v)} />} /></List>\n\\`\\`\\`\n\n---\n\n## NavigationOption → ListItem.Navigation\n\n- \\`onClick\\` or \\`href\\` move to Navigation\n\n\\`\\`\\`tsx\n<NavigationOption title=\"Title\" content=\"Text\" onClick={fn} />\n→\n<List><ListItem title=\"Title\" subtitle=\"Text\" control={<ListItem.Navigation onClick={fn} />} /></List>\n\\`\\`\\`\n\n---\n\n## Option → ListItem\n\n- Wrap \\`media\\` in \\`ListItem.AvatarView\\`\n\n\\`\\`\\`tsx\n<Option media={<Icon />} title=\"Title\" />\n→\n<List><ListItem title=\"Title\" media={<ListItem.AvatarView><Icon /></ListItem.AvatarView>} /></List>\n\\`\\`\\`\n\n---\n\n## Summary → ListItem\n\n**Basic:**\n\n- \\`icon\\` → wrap in \\`ListItem.AvatarView\\` with \\`size={32}\\` as \\`media\\`\n\n**Status:**\n\n- \\`Status.DONE\\` → \\`badge={{ status: 'positive' }}\\`\n- \\`Status.PENDING\\` → \\`badge={{ status: 'pending' }}\\`\n- \\`Status.NOT_DONE\\` → no badge\n\n**Action:**\n\n- \\`action.text\\` → \\`action.label\\` in \\`ListItem.AdditionalInfo\\` as \\`additionalInfo\\`\n\n**Info (requires state):**\n\n- \\`MODAL\\` → \\`ListItem.IconButton partiallyInteractive\\` + \\`<Modal>\\` in \\`control\\`\n- \\`POPOVER\\` → \\`<Popover>\\` wrapping \\`ListItem.IconButton partiallyInteractive\\` in \\`control\\`\n- Use \\`QuestionMarkCircle\\` icon\n\n\\`\\`\\`tsx\n// Basic\n<Summary title=\"T\" description=\"D\" icon={<Icon />} />\n→\n<List><ListItem title=\"T\" subtitle=\"D\" media={<ListItem.AvatarView size={32}><Icon /></ListItem.AvatarView>} /></List>\n\n// Status\n<Summary title=\"T\" description=\"D\" icon={<Icon />} status={Status.DONE} />\n→\n<List><ListItem title=\"T\" subtitle=\"D\" media={<ListItem.AvatarView size={32} badge={{status:'positive'}}><Icon /></ListItem.AvatarView>} /></List>\n\n// Action\n<Summary title=\"T\" description=\"D\" icon={<Icon />} action={{text:'Go', href:'/go'}} />\n→\n<List><ListItem title=\"T\" subtitle=\"D\" media={<ListItem.AvatarView size={32}><Icon /></ListItem.AvatarView>} additionalInfo={<ListItem.AdditionalInfo action={{label:'Go', href:'/go'}} />} /></List>\n\n// Modal (add: const [open, setOpen] = useState(false))\n<Summary title=\"T\" description=\"D\" icon={<Icon />} info={{title:'Help', content:'Text', presentation:'MODAL', 'aria-label':'Info'}} />\n→\n<List><ListItem title=\"T\" subtitle=\"D\" media={<ListItem.AvatarView size={32}><Icon /></ListItem.AvatarView>} control={<ListItem.IconButton partiallyInteractive aria-label=\"Info\" onClick={()=>setOpen(!open)}><QuestionMarkCircle /><Modal open={open} title=\"Help\" body=\"Text\" onClose={()=>setOpen(false)} /></ListItem.IconButton>} /></List>\n\n// Popover\n<Summary title=\"T\" description=\"D\" icon={<Icon />} info={{title:'Help', content:'Text', presentation:'POPOVER', 'aria-label':'Info'}} />\n→\n<List><ListItem title=\"T\" subtitle=\"D\" media={<ListItem.AvatarView size={32}><Icon /></ListItem.AvatarView>} control={<Popover title=\"Help\" content=\"Text\" onClose={()=>setOpen(false)}><ListItem.IconButton partiallyInteractive aria-label=\"Info\"><QuestionMarkCircle /></ListItem.IconButton></Popover>} /></List>\n\\`\\`\\`\n\n---\n\n## DefinitionList → Multiple ListItem\n\n- Array → individual \\`ListItem\\`s\n- \\`value\\` → \\`subtitle\\`\n- \\`key\\` → React \\`key\\` prop\n- Action type: \"Edit\"/\"Update\"/\"View\" → \\`ListItem.Button priority=\"secondary-neutral\"\\`, \"Change\"/\"Password\" → \\`ListItem.Navigation\\`, \"Copy\" → \\`ListItem.IconButton\\`\n\n\\`\\`\\`tsx\n<DefinitionList definitions={[\n {title:'T1', value:'V1', key:'k1'},\n {title:'T2', value:'V2', key:'k2', action:{label:'Edit', onClick:fn}}\n]} />\n→\n<List>\n <ListItem key=\"k1\" title=\"T1\" subtitle=\"V1\" />\n <ListItem key=\"k2\" title=\"T2\" subtitle=\"V2\" control={<ListItem.Button priority=\"secondary-neutral\" onClick={fn}>Edit</ListItem.Button>} />\n</List>\n\\`\\`\\`\n`;\n\nexport const SYSTEM_PROMPT = `Transform TypeScript/JSX code from legacy Wise Design System (WDS) components to the new ListItem component and ListItem subcomponents from '@transferwise/components'.\n\nRead and transform each file individually, instead of reading them all at the start. Only make a single edit or write per file, once you've fully processed it.\n\nRules:\n1. Ignore any files that do not contain deprecated WDS components, unless they are necessary for context.\n2. Migrate components per provided migration rules\n3. Maintain TypeScript type safety and update types to match new API\n4. Map props: handle renamed, deprecated, new required, and changed types\n5. Update imports to new WDS components and types\n6. Preserve code style, formatting, and calculated logic\n7. Handle conditional rendering, spread props, and complex expressions\n8. Note: New components may lack feature parity with legacy versions\n9. Only modify code requiring changes per migration rules, and any impacted surrounding code for context.\n10. Do not summarise the initial user request in a response.\n11. Use glob to find files in the directory and then grep to identify files with deprecated imports.\n12. Final result response should just be whether the migration was successful overall, or if any errors were encountered\n13. Explain your reasoning and justification before making changes, as you edit each file. Keep it concise and succinct as only bullet points\n14. Do not summarise the changes made after modifying a file.\n\nMake the necessary updates to the files. \n\nYou'll receive:\n- File paths/directories to search in individual queries\n- Deprecated component names at the end of this prompt\n- Migration context and rules for each deprecated component\n\nDeprecated components: ${DEPRECATED_COMPONENT_NAMES.join(', ')}.\n\n${MIGRATION_RULES}`;\n","import { createPatch } from 'diff';\n\n/** Split the path to get the relative path after the directory, and wrap with ANSI color codes */\nexport function formatPathOutput(directory: string, path?: string): string {\n return `\\x1b[32m${path ? (path.split(directory)[1] ?? path) : directory}\\x1b[0m`;\n}\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\n// Formats Claude response with ANSI codes (bold for **, green for `), indenting all lines except the first. Also wraps entire content in dim color\nexport function formatClaudeResponseContent(content: string): string {\n const formatted = content\n .replace(/\\*\\*(.+?)\\*\\*/gu, '\\x1b[1m$1\\x1b[0m\\x1b[2m')\n .replace(/`(.+?)`/gu, '\\x1b[32m$1\\x1b[0m\\x1b[2m')\n .split('\\n')\n .map((line, index) => (index === 0 ? line : ` ${line}`))\n .join('\\n');\n\n return `\\x1b[2m${formatted}\\x1b[0m`;\n}\n\n// Formats the content of a file for output, wrapping it in ANSI color codes for better visibility in the console\nexport function formatFileContentOutput(content: string): string {\n // Remove surrounding double quotes if present\n let cleanedContent = content.trim();\n if (cleanedContent.startsWith('\"') && cleanedContent.endsWith('\"')) {\n cleanedContent = cleanedContent.slice(1, -1);\n }\n\n // Remove <system-reminder> tags and their content\n cleanedContent = cleanedContent\n .replace(/<system-reminder>[\\s\\S]*?<\\/system-reminder>/gu, '')\n .trim();\n\n // Split into lines and format each line\n const lines = cleanedContent.split('\\\\n');\n const linePattern = /^(\\s*)(\\d+)(→)(.*)$/u;\n const formattedLines = lines.map((line) => {\n // Match line number and arrow pattern: \" 1→\"\n const match = linePattern.exec(line);\n if (match) {\n const [, spaces, lineNum, arrow, code] = match;\n // Gray for line numbers, cyan for arrow, white/default for code\n return `${spaces}\\x1b[90m${lineNum}\\x1b[0m\\x1b[36m${arrow}\\x1b[0m${code}`;\n }\n return line;\n });\n\n return formattedLines.join('\\n');\n}\n\n// Generates a unified diff between the original and modified strings, with ANSI color codes for additions and deletions and line numbers\nexport function generateDiff(original: string, modified: string): string {\n const diffResult = createPatch('', original, modified, '', '').trim();\n\n // Parse and colorize the diff output\n const lines = diffResult\n .split('\\n')\n .slice(4) // Skip the header lines\n .filter((line) => !line.startsWith('\\\')); // Remove \"No newline\" messages\n\n // Track current line numbers from hunk headers\n let oldLineNumber = 0;\n let newLineNumber = 0;\n\n const colouredDiff = lines\n .map((line: string) => {\n const trimmedLine = line.trimEnd();\n\n // Parse hunk header to get starting line numbers - format: @@ -oldStart,oldCount +newStart,newCount @@\n if (trimmedLine.startsWith('@@')) {\n const match = /@@ -(\\d+)(?:,\\d+)? \\+(\\d+)(?:,\\d+)? @@/u.exec(trimmedLine);\n if (match) {\n oldLineNumber = Number.parseInt(match[1], 10);\n newLineNumber = Number.parseInt(match[2], 10);\n }\n return `\\x1b[36m${trimmedLine}\\x1b[0m`; // Cyan for hunk headers\n }\n\n let linePrefix = '';\n // Green styling for additions\n if (trimmedLine.startsWith('+')) {\n linePrefix = `${newLineNumber.toString().padStart(4, ' ')} `;\n newLineNumber += 1;\n return `\\x1b[32m${linePrefix}${trimmedLine}\\x1b[0m`;\n }\n\n // Red styling for deletions\n if (trimmedLine.startsWith('-')) {\n linePrefix = `${oldLineNumber.toString().padStart(4, ' ')} `;\n oldLineNumber += 1;\n return `\\x1b[31m${linePrefix}${trimmedLine}\\x1b[0m`;\n }\n\n // Handle unchanged lines\n linePrefix = `${oldLineNumber.toString().padStart(4, ' ')} `;\n oldLineNumber += 1;\n newLineNumber += 1;\n return `${linePrefix}${trimmedLine}`;\n })\n .join('\\n');\n\n return colouredDiff;\n}\n","import { type Options, query } from '@anthropic-ai/claude-agent-sdk';\nimport { execSync } from 'child_process';\nimport { createPatch } from 'diff';\nimport { readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nimport { CONSOLE_ICONS } from '../../constants';\nimport type { CodemodOptions } from '../../controller/types';\nimport { SYSTEM_PROMPT } from './constants';\nimport {\n formatClaudeResponseContent,\n formatFileContentOutput,\n formatPathOutput,\n generateDiff,\n} from './helpers';\nimport type { ClaudeResponseToolUse, ClaudeSettings } from './types';\n\nconst CLAUDE_SETTINGS_FILE = '.claude/settings.json';\n\nexport function getQueryOptions(\n sessionId?: string,\n codemodOptions?: CodemodOptions,\n isDebug?: boolean,\n): 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) {\n throw new Error(\n 'Failed to retrieve Anthropic API key. 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 if (isDebug) {\n // Not logging the auth token and path\n const { ANTHROPIC_AUTH_TOKEN, ...restVars } = envVars;\n console.log(\n `${CONSOLE_ICONS.info} Claude configuration environment variables, excluding ANTHROPIC_AUTH_TOKEN:`,\n );\n console.log(restVars);\n }\n\n return {\n resume: sessionId,\n env: envVars,\n permissionMode: codemodOptions?.isDry ? undefined : 'acceptEdits',\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: SYSTEM_PROMPT,\n },\n allowedTools: ['Glob', 'Grep', 'Read', ...(!codemodOptions?.isDry ? ['Write', 'Edit'] : [])],\n settingSources: ['local', 'project', 'user'],\n };\n}\n\n/** Initiate a new Claude session/conversation and return reusable options */\nexport async function initiateClaudeSessionOptions(\n codemodOptions: CodemodOptions,\n isDebug = false,\n): Promise<Options> {\n console.log(\n `${CONSOLE_ICONS.info} Starting Claude instance - your browser may open for Okta authentication if required.`,\n );\n\n const options = getQueryOptions(undefined, codemodOptions, isDebug);\n\n if (isDebug) {\n console.log(\n `${CONSOLE_ICONS.info} Allowed tools for this session: ${options.allowedTools?.join(', ')}`,\n );\n }\n\n const result = query({\n options,\n prompt: `You'll be given file paths in additional individual queries to search in for files using deprecated Wise Design System (WDS) components. Migrate the code per the provided migration rules.`,\n });\n\n for await (const message of result) {\n switch (message.type) {\n case 'system':\n if (message.subtype === 'init' && !options.resume) {\n console.log(`${CONSOLE_ICONS.success} Successfully initialised Claude instance`);\n\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 console.log(\n `${CONSOLE_ICONS.error} Claude encountered an error: ${message.errors.join('\\n')}`,\n );\n }\n }\n }\n\n return options;\n}\n\nexport async function queryClaude(\n path: string,\n options: Options,\n codemodOptions: CodemodOptions,\n isDebug = false,\n) {\n const result = query({\n options,\n prompt: path,\n });\n const modifiedFiles: string[] = [];\n\n for await (const message of result) {\n switch (message.type) {\n case 'assistant':\n for (const msg of message.message.content) {\n switch (msg.type) {\n // Handles logging of tool uses to determine key stages of the migration\n case 'tool_use':\n if (msg.name === 'Glob') {\n console.log(\n `${CONSOLE_ICONS.info} Finding all files within: ${formatPathOutput(path)}...`,\n );\n } else if (msg.name === 'Grep') {\n console.log(\n `${CONSOLE_ICONS.info} Identifying files with deprecated imports: ${formatPathOutput(path)}...`,\n );\n } else if (msg.name === 'Read') {\n console.log(\n `${CONSOLE_ICONS.info} Reading ${formatPathOutput(path, (msg as ClaudeResponseToolUse).input.file_path)}`,\n );\n } else if (\n (msg.name === 'Write' || msg.name === 'Edit') &&\n !modifiedFiles.includes((msg as ClaudeResponseToolUse).input.file_path) // Safeguard against duplicate logs, where Claude may write multiple times to the same file\n ) {\n // TODO: Consider how to handle multiple writes to the same file more gracefully (logged changes won't always match final file content)\n modifiedFiles.push((msg as ClaudeResponseToolUse).input.file_path);\n\n // Generate and print out a pretty diff of changes made by Claude\n if (codemodOptions.isPrint) {\n console.log(\n `${CONSOLE_ICONS.info} Changes for ${formatPathOutput(path, (msg as ClaudeResponseToolUse).input.file_path)}:`,\n );\n const diff = generateDiff(\n (msg as ClaudeResponseToolUse).input.old_string as string,\n (msg as ClaudeResponseToolUse).input.new_string as string,\n );\n\n console.log(diff);\n } else {\n console.log(\n `${CONSOLE_ICONS.info} ${codemodOptions.isDry ? 'Proposed changes for' : 'Migrated'} ${formatPathOutput(path, (msg as ClaudeResponseToolUse).input.file_path)}`,\n );\n }\n }\n break;\n case 'text':\n // Logs Claude's textual responses in debug mode, to help with understanding justifications or errors\n if (isDebug) {\n console.log(`${CONSOLE_ICONS.claude} ${formatClaudeResponseContent(msg.text)}`);\n }\n break;\n default:\n if (isDebug) {\n console.log(msg);\n }\n }\n }\n break;\n case 'result':\n if (message.subtype === 'success') {\n // TODO: Handle case where migration failed for some files?\n console.log(\n `${CONSOLE_ICONS.success} Migrated all applicable files in ${formatPathOutput(path)}`,\n );\n } else {\n console.log(\n `${CONSOLE_ICONS.error} Claude encountered an error: ${message.errors.join('\\n').trim()}`,\n );\n }\n break;\n default:\n // console.log(message);\n }\n }\n}\n","import { CONSOLE_ICONS } from '../../constants';\nimport { assessPrerequisites } from '../../controller/helpers';\nimport type { CodemodOptions } from '../../controller/types';\nimport { initiateClaudeSessionOptions, queryClaude } from './claude';\nimport { generateElapsedTime } from './helpers';\n\nconst transformer = async (\n codemodOptions: CodemodOptions,\n codemodPath: string,\n isDebug = false,\n) => {\n const startTime = Date.now();\n\n // TODO: We need to check whether the user is connected to the VPN first before proceeding\n\n const queryOptions = await initiateClaudeSessionOptions(codemodOptions, isDebug);\n\n console.log(`${CONSOLE_ICONS.info} Analysing targetted paths - this may take a while...`);\n\n for (const directory of codemodOptions.targetPaths) {\n // const isCompliant = assessPrerequisites(directory, codemodPath);\n\n // if (isCompliant) {\n // // TODO: Potential improvement could be getting all of the file paths first -\n // // Make sure claude can still handle related files (imported components/wrapping parents)\n // // Get all files within directory, and call queryClaude for each file\n // await queryClaude(directory, queryOptions, isDebug);\n // }\n\n await queryClaude(directory, queryOptions, codemodOptions, isDebug);\n }\n\n console.log(\n `${CONSOLE_ICONS.success} Finished migrating - elapsed time: \\x1b[1m${generateElapsedTime(startTime)}\\x1b[0m`,\n );\n};\n\nexport default transformer;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wise/wds-codemods",
|
|
3
|
-
"version": "1.0.0-experimental-
|
|
3
|
+
"version": "1.0.0-experimental-0f5c549",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "Wise Payments Ltd.",
|
|
6
6
|
"repository": {
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@anthropic-ai/claude-agent-sdk": "^0.1.37",
|
|
38
38
|
"@inquirer/prompts": "^7.8.6",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
39
|
+
"diff": "^8.0.2",
|
|
40
|
+
"jscodeshift": "^17.3"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@anthropic-ai/sdk": "^0.68.0",
|