@wise/wds-codemods 1.0.0-experimental-0576f11 → 1.0.0-experimental-96ec24b
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-RWhTD5Is.js → helpers-CghwwYSg.js} +3 -6
- package/dist/{helpers-RWhTD5Is.js.map → helpers-CghwwYSg.js.map} +1 -1
- package/dist/index.js +29 -24
- package/dist/index.js.map +1 -1
- package/dist/transforms/button/transformer.js +1 -1
- package/package.json +2 -4
- package/dist/transformer-CzKcQEmu.js +0 -284
- package/dist/transformer-CzKcQEmu.js.map +0 -1
- package/dist/transforms/list-item/config.json +0 -6
- package/dist/transforms/list-item/transformer.js +0 -3
package/dist/index.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const require_helpers = require('./helpers-
|
|
3
|
-
const require_transformer = require('./transformer-CzKcQEmu.js');
|
|
2
|
+
const require_helpers = require('./helpers-CghwwYSg.js');
|
|
4
3
|
let node_child_process = require("node:child_process");
|
|
5
4
|
let node_fs_promises = require("node:fs/promises");
|
|
6
5
|
node_fs_promises = require_helpers.__toESM(node_fs_promises);
|
|
@@ -13,41 +12,48 @@ let __inquirer_prompts = require("@inquirer/prompts");
|
|
|
13
12
|
let isDebug = false;
|
|
14
13
|
const currentFilePath = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
|
|
15
14
|
const currentDirPath = node_path.default.dirname(currentFilePath);
|
|
15
|
+
const ICONS = {
|
|
16
|
+
info: "\x1B[34mℹ\x1B[0m",
|
|
17
|
+
focus: "\x1B[34m➙\x1B[0m",
|
|
18
|
+
success: "\x1B[32m✔\x1B[0m",
|
|
19
|
+
warning: "\x1B[33m⚠\x1B[0m",
|
|
20
|
+
error: "\x1B[31m✖\x1B[0m"
|
|
21
|
+
};
|
|
16
22
|
const resetReportFile = async (reportPath) => {
|
|
17
23
|
try {
|
|
18
24
|
await node_fs_promises.default.access(reportPath);
|
|
19
25
|
await node_fs_promises.default.rm(reportPath);
|
|
20
|
-
console.debug(`${
|
|
26
|
+
console.debug(`${ICONS.info} Removed existing report file${isDebug ? `: ${reportPath}` : "."}`);
|
|
21
27
|
} catch {
|
|
22
|
-
console.debug(`${
|
|
28
|
+
console.debug(`${ICONS.info} No existing report file to remove${isDebug ? `: ${reportPath}` : "."}`);
|
|
23
29
|
}
|
|
24
30
|
};
|
|
25
31
|
const summariseReportFile = async (reportPath) => {
|
|
26
32
|
try {
|
|
27
33
|
const lines = (await node_fs_promises.default.readFile(reportPath, "utf8")).split("\n").filter(Boolean);
|
|
28
|
-
if (lines.length) console.debug(`\n
|
|
29
|
-
else console.debug(`${
|
|
34
|
+
if (lines.length) console.debug(`\n⚠️ ${lines.length} manual review${lines.length > 1 ? "s are" : " is"} required. See ${reportPath} for details.`);
|
|
35
|
+
else console.debug(`${ICONS.info} Report file exists but is empty${isDebug ? `: ${reportPath}` : "."}`);
|
|
30
36
|
} catch {
|
|
31
|
-
console.debug(`${
|
|
37
|
+
console.debug(`${ICONS.info} No report file generated - no manual reviews needed`);
|
|
32
38
|
}
|
|
33
39
|
};
|
|
34
|
-
const log = (label, value) => {
|
|
35
|
-
if (typeof require_helpers.logToInquirer === "function") require_helpers.logToInquirer(label, value || "");
|
|
36
|
-
else console.info(label, value || "");
|
|
37
|
-
};
|
|
38
40
|
async function runCodemod(transformsDir) {
|
|
39
|
-
const args = process.argv.slice(2);
|
|
40
|
-
const candidate = args[0];
|
|
41
|
-
isDebug = args.includes("--debug");
|
|
42
41
|
try {
|
|
42
|
+
const args = process.argv.slice(2);
|
|
43
|
+
const candidate = args[0];
|
|
44
|
+
isDebug = args.includes("--debug");
|
|
43
45
|
const packages = require_helpers.findPackages();
|
|
44
46
|
const reportPath = node_path.default.resolve(require_helpers.findProjectRoot(), "codemod-report.txt");
|
|
45
47
|
const resolvedTransformsDir = transformsDir ?? node_path.default.resolve(currentDirPath, "../dist/transforms");
|
|
46
|
-
if (isDebug) console.debug(`${
|
|
48
|
+
if (isDebug) console.debug(`${ICONS.info} Resolved transforms directory: ${resolvedTransformsDir}`);
|
|
47
49
|
await resetReportFile(reportPath);
|
|
48
50
|
const { transformFiles } = await require_helpers.loadTransformModules_default(resolvedTransformsDir);
|
|
49
51
|
const resolvedTransformNames = await Promise.all(transformFiles);
|
|
50
|
-
if (resolvedTransformNames.length === 0) throw new Error(`${
|
|
52
|
+
if (resolvedTransformNames.length === 0) throw new Error(`${ICONS.error} No transform scripts found${isDebug ? ` in: ${resolvedTransformsDir}` : "."}`);
|
|
53
|
+
const log = (label, value) => {
|
|
54
|
+
if (typeof require_helpers.logToInquirer === "function") require_helpers.logToInquirer(label, value);
|
|
55
|
+
else console.info(label, value);
|
|
56
|
+
};
|
|
51
57
|
let transformFile;
|
|
52
58
|
if (candidate && resolvedTransformNames.includes(candidate)) {
|
|
53
59
|
log("Select codemod to run:", candidate);
|
|
@@ -63,7 +69,7 @@ async function runCodemod(transformsDir) {
|
|
|
63
69
|
log("Selected codemod:", transformFile);
|
|
64
70
|
}
|
|
65
71
|
const codemodPath = node_path.default.resolve(resolvedTransformsDir, transformFile, "transformer.js");
|
|
66
|
-
if (isDebug) console.debug(`${
|
|
72
|
+
if (isDebug) console.debug(`${ICONS.info} Resolved codemod path: ${codemodPath}`);
|
|
67
73
|
const promptAnswers = await require_helpers.runTransformPrompts(codemodPath);
|
|
68
74
|
const options = await require_helpers.getOptions_default({
|
|
69
75
|
packages,
|
|
@@ -71,9 +77,8 @@ async function runCodemod(transformsDir) {
|
|
|
71
77
|
transformFiles: resolvedTransformNames,
|
|
72
78
|
preselectedTransformFile: transformFile
|
|
73
79
|
});
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
console.info(`${require_transformer.CONSOLE_ICONS.focus} \x1b[1mProcessing:\x1b[0m \x1b[32m${targetPath}\x1b[0m`);
|
|
80
|
+
options.targetPaths.map((targetPath) => {
|
|
81
|
+
console.info(`${ICONS.focus} \x1b[1mProcessing:\x1b[0m \x1b[32m${targetPath}\x1b[0m`);
|
|
77
82
|
if (require_helpers.assessPrerequisites(targetPath, codemodPath)) {
|
|
78
83
|
const answerArgs = Object.entries(promptAnswers).map(([promptName, answerValue]) => `--${promptName}=${String(answerValue)}`);
|
|
79
84
|
const command = `npx jscodeshift ${[
|
|
@@ -86,14 +91,14 @@ async function runCodemod(transformsDir) {
|
|
|
86
91
|
options.useGitIgnore ? "--gitignore" : "",
|
|
87
92
|
...answerArgs
|
|
88
93
|
].filter(Boolean).join(" ")}`;
|
|
89
|
-
if (isDebug) console.debug(`${
|
|
94
|
+
if (isDebug) console.debug(`${ICONS.info} Running: ${command}`);
|
|
90
95
|
return (0, node_child_process.execSync)(command, { stdio: "inherit" });
|
|
91
96
|
}
|
|
92
|
-
})
|
|
97
|
+
});
|
|
93
98
|
await summariseReportFile(reportPath);
|
|
94
99
|
} catch (error) {
|
|
95
|
-
if (error instanceof Error) console.error(`${
|
|
96
|
-
else console.error(`${
|
|
100
|
+
if (error instanceof Error) console.error(`${ICONS.error} Error running codemod:`, error.message);
|
|
101
|
+
else console.error(`${ICONS.error} Error running codemod:`, error);
|
|
97
102
|
if (process.env.NODE_ENV !== "test") process.exit(1);
|
|
98
103
|
}
|
|
99
104
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["path","fs","
|
|
1
|
+
{"version":3,"file":"index.js","names":["path","fs","findPackages","findProjectRoot","loadTransformModules","logToInquirer","transformFile: string","runTransformPrompts","getOptions","assessPrerequisites","error: unknown"],"sources":["../src/controller/index.ts","../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { execSync } from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { select as list } from '@inquirer/prompts';\n\nimport {\n assessPrerequisites,\n findPackages,\n findProjectRoot,\n getOptions,\n loadTransformModules,\n logToInquirer,\n runTransformPrompts,\n} from './helpers';\n\nlet isDebug = false;\nconst currentFilePath = fileURLToPath(import.meta.url);\nconst currentDirPath = path.dirname(currentFilePath);\nconst 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};\n\nconst resetReportFile = async (reportPath: string) => {\n try {\n await fs.access(reportPath);\n await fs.rm(reportPath);\n console.debug(`${ICONS.info} Removed existing report file${isDebug ? `: ${reportPath}` : '.'}`);\n } catch {\n console.debug(\n `${ICONS.info} No existing report file to remove${isDebug ? `: ${reportPath}` : '.'}`,\n );\n }\n};\n\nconst summariseReportFile = async (reportPath: string) => {\n try {\n const reportContent = await fs.readFile(reportPath, 'utf8');\n const lines = reportContent.split('\\n').filter(Boolean);\n if (lines.length) {\n console.debug(\n `\\n⚠️ ${lines.length} manual review${lines.length > 1 ? 's are' : ' is'} required. See ${reportPath} for details.`,\n );\n } else {\n console.debug(\n `${ICONS.info} Report file exists but is empty${isDebug ? `: ${reportPath}` : '.'}`,\n );\n }\n } catch {\n console.debug(`${ICONS.info} No report file generated - no manual reviews needed`);\n }\n};\n\nasync function runCodemod(transformsDir?: string) {\n try {\n const args = process.argv.slice(2);\n const candidate = args[0];\n isDebug = args.includes('--debug');\n const packages = findPackages();\n const reportPath = path.resolve(findProjectRoot(), 'codemod-report.txt');\n const resolvedTransformsDir =\n transformsDir ?? path.resolve(currentDirPath, '../dist/transforms');\n\n if (isDebug) {\n console.debug(`${ICONS.info} Resolved transforms directory: ${resolvedTransformsDir}`);\n }\n\n await resetReportFile(reportPath);\n\n const { transformFiles } = await loadTransformModules(resolvedTransformsDir);\n\n const resolvedTransformNames = await Promise.all(transformFiles);\n if (resolvedTransformNames.length === 0) {\n throw new Error(\n `${ICONS.error} No transform scripts found${isDebug ? ` in: ${resolvedTransformsDir}` : '.'}`,\n );\n }\n\n const log = (label: string, value: string): void => {\n if (typeof logToInquirer === 'function') {\n logToInquirer(label, value);\n } else {\n console.info(label, value);\n }\n };\n\n let transformFile: string;\n\n if (candidate && resolvedTransformNames.includes(candidate)) {\n log('Select codemod to run:', candidate);\n transformFile = candidate;\n } else {\n transformFile = await list({\n message: 'Select codemod to run:',\n choices: resolvedTransformNames.map((name) => ({ name, value: name })),\n });\n log('Selected codemod:', transformFile);\n }\n\n const codemodPath = path.resolve(resolvedTransformsDir, transformFile, 'transformer.js');\n if (isDebug) {\n console.debug(`${ICONS.info} Resolved codemod path: ${codemodPath}`);\n }\n\n const promptAnswers = await runTransformPrompts(codemodPath);\n\n const options = await getOptions({\n packages,\n root: findProjectRoot(),\n transformFiles: resolvedTransformNames,\n preselectedTransformFile: transformFile,\n });\n\n options.targetPaths.map((targetPath) => {\n console.info(`${ICONS.focus} \\x1b[1mProcessing:\\x1b[0m \\x1b[32m${targetPath}\\x1b[0m`);\n\n const isCompliant = assessPrerequisites(targetPath, codemodPath);\n if (isCompliant) {\n const answerArgs = Object.entries(promptAnswers).map(\n ([promptName, answerValue]) => `--${promptName}=${String(answerValue)}`,\n );\n\n const argsList = [\n '-t',\n codemodPath,\n targetPath,\n options.isDry ? '--dry' : '',\n options.isPrint ? '--print' : '',\n options.ignorePatterns\n ? options.ignorePatterns\n .split(',')\n .map((pattern) => `--ignore-pattern=${pattern.trim()}`)\n .join(' ')\n : '',\n options.useGitIgnore ? '--gitignore' : '',\n ...answerArgs,\n ].filter(Boolean);\n\n const command = `npx jscodeshift ${argsList.join(' ')}`;\n if (isDebug) {\n console.debug(`${ICONS.info} Running: ${command}`);\n }\n return execSync(command, { stdio: 'inherit' });\n }\n return undefined;\n });\n\n await summariseReportFile(reportPath);\n } catch (error: unknown) {\n if (error instanceof Error) {\n console.error(`${ICONS.error} Error running codemod:`, error.message);\n } else {\n console.error(`${ICONS.error} Error running codemod:`, error);\n }\n if (process.env.NODE_ENV !== 'test') {\n process.exit(1);\n }\n }\n}\n\nexport { runCodemod };\n","#!/usr/bin/env node\nimport { runCodemod } from './controller';\n\nvoid runCodemod();\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-96ec24b",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "Wise Payments Ltd.",
|
|
6
6
|
"repository": {
|
|
@@ -34,12 +34,10 @@
|
|
|
34
34
|
"test:watch": "jest --watch"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@anthropic-ai/claude-agent-sdk": "^0.1.30",
|
|
38
37
|
"@inquirer/prompts": "^7.8.6",
|
|
39
38
|
"jscodeshift": "^17.3"
|
|
40
39
|
},
|
|
41
40
|
"devDependencies": {
|
|
42
|
-
"@anthropic-ai/sdk": "^0.68.0",
|
|
43
41
|
"@babel/core": "^7.28.4",
|
|
44
42
|
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
|
45
43
|
"@babel/preset-env": "^7.28.3",
|
|
@@ -50,7 +48,7 @@
|
|
|
50
48
|
"@commitlint/config-conventional": "^20.0.0",
|
|
51
49
|
"@inquirer/testing": "^2.1.50",
|
|
52
50
|
"@jest/globals": "^30.1.2",
|
|
53
|
-
"@transferwise/components": "^46.
|
|
51
|
+
"@transferwise/components": "^46.115.0",
|
|
54
52
|
"@types/jest": "^30.0.0",
|
|
55
53
|
"@types/jscodeshift": "^17.3.0",
|
|
56
54
|
"@types/node": "^24.4.0",
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
const require_helpers = require('./helpers-RWhTD5Is.js');
|
|
2
|
-
let node_child_process = require("node:child_process");
|
|
3
|
-
let node_path = require("node:path");
|
|
4
|
-
let __anthropic_ai_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
5
|
-
let node_fs = require("node:fs");
|
|
6
|
-
|
|
7
|
-
//#region src/constants.ts
|
|
8
|
-
const CONSOLE_ICONS = {
|
|
9
|
-
info: "\x1B[34mℹ\x1B[0m",
|
|
10
|
-
focus: "\x1B[34m➙\x1B[0m",
|
|
11
|
-
success: "\x1B[32m✔\x1B[0m",
|
|
12
|
-
warning: "\x1B[33m⚠\x1B[0m",
|
|
13
|
-
error: "\x1B[31m✖\x1B[0m"
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
//#endregion
|
|
17
|
-
//#region src/transforms/list-item/constants.ts
|
|
18
|
-
const DEPRECATED_COMPONENT_NAMES = [
|
|
19
|
-
"ActionOption",
|
|
20
|
-
"NavigationOption",
|
|
21
|
-
"NavigationOptionsList",
|
|
22
|
-
"Summary",
|
|
23
|
-
"SwitchOption",
|
|
24
|
-
"CheckboxOption",
|
|
25
|
-
"RadioOption"
|
|
26
|
-
];
|
|
27
|
-
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'.
|
|
28
|
-
|
|
29
|
-
Rules:
|
|
30
|
-
1. Ignore any files that do not contain deprecated WDS components, unless they are necessary for context.
|
|
31
|
-
2. Migrate components per provided migration rules
|
|
32
|
-
3. Maintain TypeScript type safety and update types to match new API
|
|
33
|
-
4. Map props: handle renamed, deprecated, new required, and changed types
|
|
34
|
-
5. Update imports to new WDS components and types
|
|
35
|
-
6. Preserve code style, formatting, and calculated logic
|
|
36
|
-
7. Handle conditional rendering, spread props, and complex expressions
|
|
37
|
-
8. Note: New components may lack feature parity with legacy versions
|
|
38
|
-
|
|
39
|
-
You'll receive:
|
|
40
|
-
- File paths/directories to search
|
|
41
|
-
- Deprecated component names at the end of this prompt
|
|
42
|
-
- Migration context and rules for each deprecated component
|
|
43
|
-
|
|
44
|
-
Only modify code requiring changes per migration rules. Make the necessary updates to the files and do not respond with any explanations or reasoning.
|
|
45
|
-
|
|
46
|
-
Deprecated components: ${DEPRECATED_COMPONENT_NAMES.join(", ")}.
|
|
47
|
-
|
|
48
|
-
Migration rules:
|
|
49
|
-
# Legacy Component → ListItem Migration Guide
|
|
50
|
-
|
|
51
|
-
## Universal Rules
|
|
52
|
-
|
|
53
|
-
1. Wrap all \`ListItem\` in \`<List>\`
|
|
54
|
-
2. \`title\` → \`title\` (direct)
|
|
55
|
-
3. \`content\` or \`description\` → \`subtitle\`
|
|
56
|
-
4. \`disabled\` stays on \`ListItem\` (not controls)
|
|
57
|
-
5. Keep HTML attributes (\`id\`, \`name\`, \`aria-label\`), remove: \`as\`, \`complex\`, \`showMediaAtAllSizes\`, \`showMediaCircle\`, \`isContainerAligned\`
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## ActionOption → ListItem.Button
|
|
62
|
-
|
|
63
|
-
- \`action\` → Button children
|
|
64
|
-
- \`onClick\` → Button \`onClick\`
|
|
65
|
-
- Priority: default/\`"primary"\` → \`"primary"\`, \`"secondary"\` → \`"secondary-neutral"\`, \`"secondary-send"\` → \`"secondary"\`, \`"tertiary"\` → \`"tertiary"\`
|
|
66
|
-
|
|
67
|
-
\`\`\`tsx
|
|
68
|
-
<ActionOption title="Title" content="Text" action="Click" priority="secondary" onClick={fn} />
|
|
69
|
-
→
|
|
70
|
-
<List><ListItem title="Title" subtitle="Text" control={<ListItem.Button priority="secondary-neutral" onClick={fn}>Click</ListItem.Button>} /></List>
|
|
71
|
-
\`\`\`
|
|
72
|
-
|
|
73
|
-
---
|
|
74
|
-
|
|
75
|
-
## CheckboxOption → ListItem.Checkbox
|
|
76
|
-
|
|
77
|
-
- \`onChange\`: \`(checked: boolean)\` → \`(event: ChangeEvent)\` use \`event.target.checked\`
|
|
78
|
-
- \`id\`, \`name\` move to Checkbox
|
|
79
|
-
|
|
80
|
-
\`\`\`tsx
|
|
81
|
-
<CheckboxOption id="x" name="y" title="Title" content="Text" checked={v} onChange={(c) => set(c)} />
|
|
82
|
-
→
|
|
83
|
-
<List><ListItem title="Title" subtitle="Text" control={<ListItem.Checkbox id="x" name="y" checked={v} onChange={(e) => set(e.target.checked)} />} /></List>
|
|
84
|
-
\`\`\`
|
|
85
|
-
|
|
86
|
-
---
|
|
87
|
-
|
|
88
|
-
## RadioOption → ListItem.Radio
|
|
89
|
-
|
|
90
|
-
- \`id\`, \`name\`, \`value\`, \`checked\`, \`onChange\` move to Radio
|
|
91
|
-
|
|
92
|
-
\`\`\`tsx
|
|
93
|
-
<RadioOption id="x" name="y" value="v" title="Title" content="Text" checked={v==='v'} onChange={set} />
|
|
94
|
-
→
|
|
95
|
-
<List><ListItem title="Title" subtitle="Text" control={<ListItem.Radio id="x" name="y" value="v" checked={v==='v'} onChange={set} />} /></List>
|
|
96
|
-
\`\`\`
|
|
97
|
-
|
|
98
|
-
---
|
|
99
|
-
|
|
100
|
-
## SwitchOption → ListItem.Switch
|
|
101
|
-
|
|
102
|
-
- \`onChange\` → \`onClick\`, toggle manually
|
|
103
|
-
- \`aria-label\` moves to Switch
|
|
104
|
-
|
|
105
|
-
\`\`\`tsx
|
|
106
|
-
<SwitchOption title="Title" content="Text" checked={v} aria-label="Toggle" onChange={set} />
|
|
107
|
-
→
|
|
108
|
-
<List><ListItem title="Title" subtitle="Text" control={<ListItem.Switch checked={v} aria-label="Toggle" onClick={() => set(!v)} />} /></List>
|
|
109
|
-
\`\`\`
|
|
110
|
-
|
|
111
|
-
---
|
|
112
|
-
|
|
113
|
-
## NavigationOption → ListItem.Navigation
|
|
114
|
-
|
|
115
|
-
- \`onClick\` or \`href\` move to Navigation
|
|
116
|
-
|
|
117
|
-
\`\`\`tsx
|
|
118
|
-
<NavigationOption title="Title" content="Text" onClick={fn} />
|
|
119
|
-
→
|
|
120
|
-
<List><ListItem title="Title" subtitle="Text" control={<ListItem.Navigation onClick={fn} />} /></List>
|
|
121
|
-
\`\`\`
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## Option → ListItem
|
|
126
|
-
|
|
127
|
-
- Wrap \`media\` in \`ListItem.AvatarView\`
|
|
128
|
-
|
|
129
|
-
\`\`\`tsx
|
|
130
|
-
<Option media={<Icon />} title="Title" />
|
|
131
|
-
→
|
|
132
|
-
<List><ListItem title="Title" media={<ListItem.AvatarView><Icon /></ListItem.AvatarView>} /></List>
|
|
133
|
-
\`\`\`
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
## Summary → ListItem
|
|
138
|
-
|
|
139
|
-
**Basic:**
|
|
140
|
-
|
|
141
|
-
- \`icon\` → wrap in \`ListItem.AvatarView\` with \`size={32}\` as \`media\`
|
|
142
|
-
|
|
143
|
-
**Status:**
|
|
144
|
-
|
|
145
|
-
- \`Status.DONE\` → \`badge={{ status: 'positive' }}\`
|
|
146
|
-
- \`Status.PENDING\` → \`badge={{ status: 'pending' }}\`
|
|
147
|
-
- \`Status.NOT_DONE\` → no badge
|
|
148
|
-
|
|
149
|
-
**Action:**
|
|
150
|
-
|
|
151
|
-
- \`action.text\` → \`action.label\` in \`ListItem.AdditionalInfo\` as \`additionalInfo\`
|
|
152
|
-
|
|
153
|
-
**Info (requires state):**
|
|
154
|
-
|
|
155
|
-
- \`MODAL\` → \`ListItem.IconButton partiallyInteractive\` + \`<Modal>\` in \`control\`
|
|
156
|
-
- \`POPOVER\` → \`<Popover>\` wrapping \`ListItem.IconButton partiallyInteractive\` in \`control\`
|
|
157
|
-
- Use \`QuestionMarkCircle\` icon
|
|
158
|
-
|
|
159
|
-
\`\`\`tsx
|
|
160
|
-
// Basic
|
|
161
|
-
<Summary title="T" description="D" icon={<Icon />} />
|
|
162
|
-
→
|
|
163
|
-
<List><ListItem title="T" subtitle="D" media={<ListItem.AvatarView size={32}><Icon /></ListItem.AvatarView>} /></List>
|
|
164
|
-
|
|
165
|
-
// Status
|
|
166
|
-
<Summary title="T" description="D" icon={<Icon />} status={Status.DONE} />
|
|
167
|
-
→
|
|
168
|
-
<List><ListItem title="T" subtitle="D" media={<ListItem.AvatarView size={32} badge={{status:'positive'}}><Icon /></ListItem.AvatarView>} /></List>
|
|
169
|
-
|
|
170
|
-
// Action
|
|
171
|
-
<Summary title="T" description="D" icon={<Icon />} action={{text:'Go', href:'/go'}} />
|
|
172
|
-
→
|
|
173
|
-
<List><ListItem title="T" subtitle="D" media={<ListItem.AvatarView size={32}><Icon /></ListItem.AvatarView>} additionalInfo={<ListItem.AdditionalInfo action={{label:'Go', href:'/go'}} />} /></List>
|
|
174
|
-
|
|
175
|
-
// Modal (add: const [open, setOpen] = useState(false))
|
|
176
|
-
<Summary title="T" description="D" icon={<Icon />} info={{title:'Help', content:'Text', presentation:'MODAL', 'aria-label':'Info'}} />
|
|
177
|
-
→
|
|
178
|
-
<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>
|
|
179
|
-
|
|
180
|
-
// Popover
|
|
181
|
-
<Summary title="T" description="D" icon={<Icon />} info={{title:'Help', content:'Text', presentation:'POPOVER', 'aria-label':'Info'}} />
|
|
182
|
-
→
|
|
183
|
-
<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>
|
|
184
|
-
\`\`\`
|
|
185
|
-
|
|
186
|
-
---
|
|
187
|
-
|
|
188
|
-
## DefinitionList → Multiple ListItem
|
|
189
|
-
|
|
190
|
-
- Array → individual \`ListItem\`s
|
|
191
|
-
- \`value\` → \`subtitle\`
|
|
192
|
-
- \`key\` → React \`key\` prop
|
|
193
|
-
- Action type: "Edit"/"Update"/"View" → \`ListItem.Button priority="secondary-neutral"\`, "Change"/"Password" → \`ListItem.Navigation\`, "Copy" → \`ListItem.IconButton\`
|
|
194
|
-
|
|
195
|
-
\`\`\`tsx
|
|
196
|
-
<DefinitionList definitions={[
|
|
197
|
-
{title:'T1', value:'V1', key:'k1'},
|
|
198
|
-
{title:'T2', value:'V2', key:'k2', action:{label:'Edit', onClick:fn}}
|
|
199
|
-
]} />
|
|
200
|
-
→
|
|
201
|
-
<List>
|
|
202
|
-
<ListItem key="k1" title="T1" subtitle="V1" />
|
|
203
|
-
<ListItem key="k2" title="T2" subtitle="V2" control={<ListItem.Button priority="secondary-neutral" onClick={fn}>Edit</ListItem.Button>} />
|
|
204
|
-
</List>
|
|
205
|
-
\`\`\`
|
|
206
|
-
`;
|
|
207
|
-
|
|
208
|
-
//#endregion
|
|
209
|
-
//#region src/transforms/list-item/claude.ts
|
|
210
|
-
const CLAUDE_SETTINGS_FILE = ".claude/settings.json";
|
|
211
|
-
function getQueryOptions(isDebug = false) {
|
|
212
|
-
const claudeSettingsPath = (0, node_path.resolve)(process.env.HOME || "", CLAUDE_SETTINGS_FILE);
|
|
213
|
-
const settings = JSON.parse((0, node_fs.readFileSync)(claudeSettingsPath, "utf-8"));
|
|
214
|
-
let apiKey;
|
|
215
|
-
try {
|
|
216
|
-
apiKey = (0, node_child_process.execSync)(`bash ${settings.apiKeyHelper}`, { encoding: "utf-8" }).trim();
|
|
217
|
-
} catch {}
|
|
218
|
-
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");
|
|
219
|
-
return {
|
|
220
|
-
env: {
|
|
221
|
-
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
222
|
-
ANTHROPIC_BASE_URL: settings?.env?.ANTHROPIC_BASE_URL,
|
|
223
|
-
ANTHROPIC_CUSTOM_HEADERS: settings?.env?.ANTHROPIC_CUSTOM_HEADERS,
|
|
224
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL: settings.env?.ANTHROPIC_DEFAULT_SONNET_MODEL,
|
|
225
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL: settings.env?.ANTHROPIC_DEFAULT_HAIKU_MODEL,
|
|
226
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL: settings.env?.ANTHROPIC_DEFAULT_OPUS_MODEL,
|
|
227
|
-
API_TIMEOUT_MS: settings.env?.API_TIMEOUT_MS,
|
|
228
|
-
PATH: process.env.PATH
|
|
229
|
-
},
|
|
230
|
-
permissionMode: "acceptEdits",
|
|
231
|
-
systemPrompt: {
|
|
232
|
-
type: "preset",
|
|
233
|
-
preset: "claude_code",
|
|
234
|
-
append: SYSTEM_PROMPT
|
|
235
|
-
},
|
|
236
|
-
settingSources: [
|
|
237
|
-
"local",
|
|
238
|
-
"project",
|
|
239
|
-
"user"
|
|
240
|
-
]
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
//#endregion
|
|
245
|
-
//#region src/transforms/list-item/transformer.ts
|
|
246
|
-
const transformer = async (targetPaths, isDebug = false) => {
|
|
247
|
-
console.log(`${CONSOLE_ICONS.info} Starting Claude instance...`);
|
|
248
|
-
const result = (0, __anthropic_ai_claude_agent_sdk.query)({
|
|
249
|
-
options: getQueryOptions(isDebug),
|
|
250
|
-
prompt: `Here are the directories to search in: ${targetPaths.join(", ")}.
|
|
251
|
-
In addition to making the required file changes for every relevant file, only respond with the file path/name and number of lines changed per file - e.g. "<directory/filename> - 5 lines changed".
|
|
252
|
-
If no changes are made for a file, respond with "<directory/filename> - No changes required". If all files require no changes, return only the same format still with nothing else.`
|
|
253
|
-
});
|
|
254
|
-
for await (const message of result) switch (message.type) {
|
|
255
|
-
case "system":
|
|
256
|
-
if (message.subtype === "init") {
|
|
257
|
-
console.log(`${CONSOLE_ICONS.success} Initialised Claude instance`);
|
|
258
|
-
console.log(`${CONSOLE_ICONS.info} Claude is processing the files... This may take a while.`);
|
|
259
|
-
}
|
|
260
|
-
break;
|
|
261
|
-
case "result":
|
|
262
|
-
if (message.subtype === "success") console.log(`${CONSOLE_ICONS.success} ${message.result.split("\n").join(`\n${CONSOLE_ICONS.success} `)}`);
|
|
263
|
-
else console.log(`${CONSOLE_ICONS.error} Claude encountered an error: ${message.errors.join("\n")}`);
|
|
264
|
-
break;
|
|
265
|
-
default: break;
|
|
266
|
-
}
|
|
267
|
-
console.log(`${CONSOLE_ICONS.success} Finished receiving messages from Claude.`);
|
|
268
|
-
};
|
|
269
|
-
var transformer_default = transformer;
|
|
270
|
-
|
|
271
|
-
//#endregion
|
|
272
|
-
Object.defineProperty(exports, 'CONSOLE_ICONS', {
|
|
273
|
-
enumerable: true,
|
|
274
|
-
get: function () {
|
|
275
|
-
return CONSOLE_ICONS;
|
|
276
|
-
}
|
|
277
|
-
});
|
|
278
|
-
Object.defineProperty(exports, 'transformer_default', {
|
|
279
|
-
enumerable: true,
|
|
280
|
-
get: function () {
|
|
281
|
-
return transformer_default;
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
//# sourceMappingURL=transformer-CzKcQEmu.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"transformer-CzKcQEmu.js","names":[],"sources":["../src/constants.ts","../src/transforms/list-item/constants.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};\n","const DEPRECATED_COMPONENT_NAMES = [\n 'ActionOption',\n 'NavigationOption',\n 'NavigationOptionsList',\n 'Summary',\n 'SwitchOption',\n 'CheckboxOption',\n 'RadioOption',\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\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\n\nYou'll receive:\n- File paths/directories to search\n- Deprecated component names at the end of this prompt\n- Migration context and rules for each deprecated component\n\nOnly modify code requiring changes per migration rules. Make the necessary updates to the files and do not respond with any explanations or reasoning.\n\nDeprecated components: ${DEPRECATED_COMPONENT_NAMES.join(', ')}.\n\nMigration 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","import type { Options } from '@anthropic-ai/claude-agent-sdk';\nimport { execSync } from 'child_process';\nimport { readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nimport { SYSTEM_PROMPT } from './constants';\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\nconst CLAUDE_SETTINGS_FILE = '.claude/settings.json';\n\nexport function getQueryOptions(isDebug = false): 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 envVars = {\n ANTHROPIC_AUTH_TOKEN: apiKey,\n ANTHROPIC_BASE_URL: settings?.env?.ANTHROPIC_BASE_URL,\n ANTHROPIC_CUSTOM_HEADERS: settings?.env?.ANTHROPIC_CUSTOM_HEADERS,\n ANTHROPIC_DEFAULT_SONNET_MODEL: settings.env?.ANTHROPIC_DEFAULT_SONNET_MODEL,\n ANTHROPIC_DEFAULT_HAIKU_MODEL: settings.env?.ANTHROPIC_DEFAULT_HAIKU_MODEL,\n ANTHROPIC_DEFAULT_OPUS_MODEL: settings.env?.ANTHROPIC_DEFAULT_OPUS_MODEL,\n API_TIMEOUT_MS: settings.env?.API_TIMEOUT_MS,\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 // console.debug(`${CONSOLE_ICONS.info} Resolved Claude environment variables:`, JSON.stringify(envVars));\n // }\n\n return {\n env: envVars,\n permissionMode: 'acceptEdits',\n systemPrompt: {\n type: 'preset',\n preset: 'claude_code',\n append: SYSTEM_PROMPT,\n },\n settingSources: ['local', 'project', 'user'],\n };\n}\n","import { query } from '@anthropic-ai/claude-agent-sdk';\n\nimport { CONSOLE_ICONS } from '../../constants';\nimport { getQueryOptions } from './claude';\n\nconst transformer = async (targetPaths: string[], isDebug = false) => {\n // TODO: We need to confirm you're connected to the VPN\n console.log(`${CONSOLE_ICONS.info} Starting Claude instance...`);\n\n const result = query({\n options: getQueryOptions(isDebug),\n prompt: `Here are the directories to search in: ${targetPaths.join(', ')}.\n In addition to making the required file changes for every relevant file, only respond with the file path/name and number of lines changed per file - e.g. \"<directory/filename> - 5 lines changed\".\n If no changes are made for a file, respond with \"<directory/filename> - No changes required\". If all files require no changes, return only the same format still with nothing else.`,\n });\n\n // TODO: Ensure we're handling all potential types of messages here.\n for await (const message of result) {\n switch (message.type) {\n case 'system':\n if (message.subtype === 'init') {\n console.log(`${CONSOLE_ICONS.success} Initialised Claude instance`);\n console.log(\n `${CONSOLE_ICONS.info} Claude is processing the files... This may take a while.`,\n );\n }\n break;\n\n case 'result':\n if (message.subtype === 'success') {\n console.log(\n `${CONSOLE_ICONS.success} ${message.result.split('\\n').join(`\\n${CONSOLE_ICONS.success} `)}`,\n );\n } else {\n console.log(\n `${CONSOLE_ICONS.error} Claude encountered an error: ${message.errors.join('\\n')}`,\n );\n }\n\n break;\n default:\n // console.log(JSON.stringify(message));\n break;\n }\n }\n\n console.log(`${CONSOLE_ICONS.success} Finished receiving messages from Claude.`);\n};\n\nexport default transformer;\n"],"mappings":";;;;;;;AAAA,MAAa,gBAAgB;CAC3B,MAAM;CACN,OAAO;CACP,SAAS;CACT,SAAS;CACT,OAAO;CACR;;;;ACND,MAAM,6BAA6B;CACjC;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAa,gBAAgB;;;;;;;;;;;;;;;;;;;yBAmBJ,2BAA2B,KAAK,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACR/D,MAAM,uBAAuB;AAE7B,SAAgB,gBAAgB,UAAU,OAAgB;CAExD,MAAM,4CAA6B,QAAQ,IAAI,QAAQ,IAAI,qBAAqB;CAChF,MAAM,WAAW,KAAK,gCAAmB,oBAAoB,QAAQ,CAAC;CAGtE,IAAI;AACJ,KAAI;AACF,4CAAkB,QAAQ,SAAS,gBAAgB,EACjD,UAAU,SACX,CAAC,CAAC,MAAM;SACH;AAER,KAAI,CAAC,OACH,OAAM,IAAI,MACR,qJACD;AAkBH,QAAO;EACL,KAhBc;GACd,sBAAsB;GACtB,oBAAoB,UAAU,KAAK;GACnC,0BAA0B,UAAU,KAAK;GACzC,gCAAgC,SAAS,KAAK;GAC9C,+BAA+B,SAAS,KAAK;GAC7C,8BAA8B,SAAS,KAAK;GAC5C,gBAAgB,SAAS,KAAK;GAC9B,MAAM,QAAQ,IAAI;GACnB;EAQC,gBAAgB;EAChB,cAAc;GACZ,MAAM;GACN,QAAQ;GACR,QAAQ;GACT;EACD,gBAAgB;GAAC;GAAS;GAAW;GAAO;EAC7C;;;;;AC7DH,MAAM,cAAc,OAAO,aAAuB,UAAU,UAAU;AAEpE,SAAQ,IAAI,GAAG,cAAc,KAAK,8BAA8B;CAEhE,MAAM,oDAAe;EACnB,SAAS,gBAAgB,QAAQ;EACjC,QAAQ,0CAA0C,YAAY,KAAK,KAAK,CAAC;;;EAG1E,CAAC;AAGF,YAAW,MAAM,WAAW,OAC1B,SAAQ,QAAQ,MAAhB;EACE,KAAK;AACH,OAAI,QAAQ,YAAY,QAAQ;AAC9B,YAAQ,IAAI,GAAG,cAAc,QAAQ,8BAA8B;AACnE,YAAQ,IACN,GAAG,cAAc,KAAK,2DACvB;;AAEH;EAEF,KAAK;AACH,OAAI,QAAQ,YAAY,UACtB,SAAQ,IACN,GAAG,cAAc,QAAQ,GAAG,QAAQ,OAAO,MAAM,KAAK,CAAC,KAAK,KAAK,cAAc,QAAQ,GAAG,GAC3F;OAED,SAAQ,IACN,GAAG,cAAc,MAAM,gCAAgC,QAAQ,OAAO,KAAK,KAAK,GACjF;AAGH;EACF,QAEE;;AAIN,SAAQ,IAAI,GAAG,cAAc,QAAQ,2CAA2C;;AAGlF,0BAAe"}
|