@wise/wds-codemods 1.0.0-experimental-601f194 → 1.0.0-experimental-49d2d08

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformer-DnE3TyyV.js","names":["modifiedFiles: string[]","findFilesWithImports","assessPrerequisites"],"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};\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. Provide only the transformed code as output, without explanations or additional text\n11. Do not summarise the initial user request in a response.\n12. Use glob or grep tool usage to find the files with deprecated components.\n13. Final result response should just be whether the migration was successful overall, or if any errors were encountered\n\nMake the necessary updates to the files and do not respond with any explanations or reasoning. \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","/** 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","import { type Options, query } from '@anthropic-ai/claude-agent-sdk';\nimport { execSync } from 'child_process';\nimport { readFileSync } from 'fs';\nimport { resolve } from 'path';\n\nimport { CONSOLE_ICONS } from '../../constants';\nimport { SYSTEM_PROMPT } from './constants';\nimport { formatPathOutput } from './helpers';\nimport type { ClaudeResponseToolUse, ClaudeSettings } from './types';\n\nconst CLAUDE_SETTINGS_FILE = '.claude/settings.json';\n\nexport function getQueryOptions(sessionId?: string, isDebug?: boolean): 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 resume: sessionId,\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\n// Initiate a new Claude session/conversation and return reusable session ID\nexport async function initiateClaudeSessionOptions(isDebug = false): 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, isDebug);\n const result = query({\n options,\n prompt: `You'll be given directories 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 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(path: string, options: Options, isDebug = false) {\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' || msg.name === 'Grep') {\n console.log(\n `${CONSOLE_ICONS.focus} Processing directory: ${formatPathOutput(path)}...`,\n );\n // NOTE: Possibly want to only log reading files when in debug mode, to reduce noise\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 modifiedFiles.push((msg as ClaudeResponseToolUse).input.file_path);\n console.log(\n `${CONSOLE_ICONS.info} Migrated ${formatPathOutput(path, (msg as ClaudeResponseToolUse).input.file_path)}`,\n );\n }\n break;\n default:\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 }\n }\n}\n","import { CONSOLE_ICONS } from '../../constants';\nimport { assessPrerequisites } from '../../controller/helpers';\nimport { findFilesWithImports } from '../../helpers';\nimport { initiateClaudeSessionOptions, queryClaude } from './claude';\nimport { generateElapsedTime } from './helpers';\n\nconst SRC = '@transferwise/components';\nconst COMPONENTS = [\n 'ActionOption',\n 'RadioOption',\n 'CheckboxOption',\n 'NavigationOption',\n 'Summary',\n 'DefinitionList',\n 'NavigationOptionList',\n];\n\nconst transformer = async (targetPaths: string[], codemodPath: string, isDebug = false) => {\n const startTime = Date.now();\n\n // TODO: We need to check whether the user is connected to the VPN\n\n const queryOptions = await initiateClaudeSessionOptions(isDebug);\n\n console.log(`${CONSOLE_ICONS.info} Analysing targetted paths - this may take a while...`);\n\n const files = findFilesWithImports(targetPaths, SRC, COMPONENTS);\n\n if (files.length === 0) {\n console.log(`${CONSOLE_ICONS.info} No files with List Item-related imports found. Skipping.`);\n } else {\n for (const filePath of files) {\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 if (assessPrerequisites(filePath, codemodPath)) {\n await queryClaude(filePath, queryOptions, isDebug);\n }\n }\n\n // await queryClaude(directory, queryOptions, 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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"}
@@ -1,353 +1,6 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
- const require_helpers = require('../../helpers-RWhTD5Is.js');
2
+ const require_helpers = require('../../helpers-59xSDDPO.js');
3
3
 
4
- //#region src/helpers/addImport.ts
5
- /**
6
- * Adds a named import if it doesn't already exist.
7
- */
8
- function addImport(root, sourceValue, importName, j) {
9
- const existingImports = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
10
- if (existingImports.size() > 0) {
11
- if (existingImports.find(j.ImportSpecifier, { imported: { name: importName } }).size() > 0) return;
12
- existingImports.forEach((path) => {
13
- if (path.node.specifiers) path.node.specifiers.push(j.importSpecifier(j.identifier(importName)));
14
- });
15
- } else {
16
- const newImport = j.importDeclaration([j.importSpecifier(j.identifier(importName))], j.literal(sourceValue));
17
- const firstImport = root.find(j.ImportDeclaration).at(0);
18
- if (firstImport.size() > 0) firstImport.insertBefore(newImport);
19
- else {
20
- const program = root.find(j.Program);
21
- if (program.size() > 0) program.get("body", 0).insertBefore(newImport);
22
- }
23
- }
24
- }
25
- var addImport_default = addImport;
26
-
27
- //#endregion
28
- //#region src/helpers/hasImport.ts
29
- /**
30
- * Checks if a specific import exists in the given root collection and provides
31
- * a method to remove it if found.
32
- */
33
- function hasImport(root, sourceValue, importName, j) {
34
- const importDeclarations = root.find(j.ImportDeclaration, { source: { value: sourceValue } });
35
- /**
36
- * Finds all ImportSpecifier nodes that expose `importName` but
37
- * from a different source than `sourceValue`.
38
- */
39
- const conflictingImports = (() => {
40
- const result = [];
41
- root.find(j.ImportDeclaration).filter((path) => path.node.source.value !== sourceValue).forEach((path) => {
42
- for (const specifier of path.node.specifiers ?? []) if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName && specifier.local?.name === importName) result.push(specifier);
43
- });
44
- return result;
45
- })();
46
- if (importDeclarations.size() === 0) return {
47
- exists: false,
48
- remove: () => {},
49
- resolvedName: importName,
50
- conflictingImports
51
- };
52
- const namedImport = importDeclarations.find(j.ImportSpecifier, { imported: { name: importName } });
53
- const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, { local: { name: importName } });
54
- const aliasImport = importDeclarations.find(j.ImportSpecifier).filter((path) => {
55
- return path.node.imported.name === importName && path.node.imported.name !== path.node.local?.name;
56
- });
57
- const exists = namedImport.size() > 0 || defaultImport.size() > 0;
58
- const resolveName = () => {
59
- if (aliasImport.size() > 0) {
60
- const localName = aliasImport.get(0).node.local?.name;
61
- if (typeof localName === "string") return localName;
62
- if (localName && typeof localName === "object" && "name" in localName && typeof localName.name === "string") return localName.name;
63
- return importName;
64
- }
65
- return importName;
66
- };
67
- const remove = () => {
68
- importDeclarations.forEach((path) => {
69
- const filteredSpecifiers = path.node.specifiers?.filter((specifier) => {
70
- if (specifier.type === "ImportSpecifier" && specifier.imported.name === importName) return false;
71
- if (specifier.type === "ImportDefaultSpecifier" && specifier.local?.name === importName) return false;
72
- return true;
73
- }) ?? [];
74
- if (filteredSpecifiers.length === 0) path.prune();
75
- else j(path).replaceWith(j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind));
76
- });
77
- };
78
- return {
79
- exists,
80
- remove,
81
- aliases: aliasImport,
82
- resolvedName: resolveName(),
83
- conflictingImports
84
- };
85
- }
86
- var hasImport_default = hasImport;
87
-
88
- //#endregion
89
- //#region src/helpers/iconUtils.ts
90
- /**
91
- * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.
92
- * This is specific to icon handling but can be reused in codemods dealing with icon children.
93
- */
94
- const processIconChildren = (j, children, iconImports, openingElement) => {
95
- if (!children || !openingElement.attributes) return;
96
- const unwrapJsxElement = (node) => {
97
- if (typeof node === "object" && node !== null && "type" in node && node.type === "JSXExpressionContainer" && j.JSXElement.check(node.expression)) return node.expression;
98
- return node;
99
- };
100
- const totalChildren = children.length;
101
- const iconChildIndex = children.findIndex((child) => {
102
- const unwrapped = unwrapJsxElement(child);
103
- return j.JSXElement.check(unwrapped) && unwrapped.openingElement.name.type === "JSXIdentifier" && iconImports.has(unwrapped.openingElement.name.name);
104
- });
105
- if (iconChildIndex === -1) return;
106
- const iconChild = unwrapJsxElement(children[iconChildIndex]);
107
- if (!iconChild || iconChild.openingElement.name.type !== "JSXIdentifier") return;
108
- iconChild.openingElement.name.name;
109
- const iconPropName = iconChildIndex <= totalChildren - 1 - iconChildIndex ? "addonStart" : "addonEnd";
110
- const iconObject = j.objectExpression([j.property("init", j.identifier("type"), j.literal("icon")), j.property("init", j.identifier("value"), iconChild)]);
111
- const iconProp = j.jsxAttribute(j.jsxIdentifier(iconPropName), j.jsxExpressionContainer(iconObject));
112
- openingElement.attributes.push(iconProp);
113
- children.splice(iconChildIndex, 1);
114
- const isWhitespaceJsxText = (node) => {
115
- return typeof node === "object" && node !== null && node.type === "JSXText" && typeof node.value === "string" && node.value.trim() === "";
116
- };
117
- if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) children.splice(iconChildIndex - 1, 1);
118
- else if (isWhitespaceJsxText(children[iconChildIndex])) children.splice(iconChildIndex, 1);
119
- };
120
- var iconUtils_default = processIconChildren;
121
-
122
- //#endregion
123
- //#region src/helpers/jsxElementUtils.ts
124
- /**
125
- * Rename a JSX element name if it is a JSXIdentifier.
126
- */
127
- const setNameIfJSXIdentifier = (elementName, newName) => {
128
- if (elementName && elementName.type === "JSXIdentifier") return {
129
- ...elementName,
130
- name: newName
131
- };
132
- return elementName;
133
- };
134
- /**
135
- * Check if a list of attributes contains a specific attribute by name.
136
- */
137
- const hasAttribute = (attributes, attributeName) => {
138
- return Array.isArray(attributes) && attributes.some((attr) => attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
139
- };
140
- /**
141
- * Check if a JSX element's openingElement has a specific attribute.
142
- */
143
- const hasAttributeOnElement = (element, attributeName) => {
144
- return hasAttribute(element.attributes, attributeName);
145
- };
146
- /**
147
- * Add specified attributes to a JSX element's openingElement if they are not already present.
148
- */
149
- const addAttributesIfMissing = (j, openingElement, attributesToAdd) => {
150
- if (!Array.isArray(openingElement.attributes)) return;
151
- const attrs = openingElement.attributes;
152
- attributesToAdd.forEach(({ attribute, name }) => {
153
- if (!hasAttributeOnElement(openingElement, name)) attrs.push(attribute);
154
- });
155
- };
156
- /**
157
- * Returns a collection of JSX elements that match the specified
158
- * exported name or names of the found aliases.
159
- */
160
- const findJSXElementsByName = (root, j) => (exportedName, aliases) => {
161
- const aliasNames = aliases?.size() ? aliases.paths().map((path) => path.node.local?.name) : [];
162
- return root.find(j.JSXElement).filter((path) => {
163
- const { name } = path.node.openingElement;
164
- return name.type === "JSXIdentifier" && (name.name === exportedName || aliasNames.includes(name.name));
165
- });
166
- };
167
- /**
168
- * Removes an attribute by name from a JSX element's openingElement.
169
- */
170
- const removeAttributeByName = (j, openingElement, attributeName) => {
171
- if (!Array.isArray(openingElement.attributes)) return;
172
- openingElement.attributes = openingElement.attributes.filter((attr) => {
173
- return !(attr.type === "JSXAttribute" && attr.name.type === "JSXIdentifier" && attr.name.name === attributeName);
174
- });
175
- };
176
-
177
- //#endregion
178
- //#region src/helpers/jsxReportingUtils.ts
179
- /**
180
- * CodemodReporter is a utility class for reporting issues found during codemod transformations.
181
- * It provides methods to report issues related to JSX elements, props, and attributes.
182
- *
183
- * @example
184
- * ```typescript
185
- * const issues: string[] = [];
186
- * const reporter = createReporter(j, issues);
187
- *
188
- * // Report a deprecated prop
189
- * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant="text"');
190
- *
191
- * // Report complex expression that needs review
192
- * reporter.reportAmbiguousExpression(element, 'size');
193
- *
194
- * // Auto-detect common issues
195
- * reporter.reportAttributeIssues(element);
196
- * ```
197
- */
198
- var CodemodReporter = class {
199
- j;
200
- issues;
201
- constructor(options) {
202
- this.j = options.jscodeshift;
203
- this.issues = options.issues;
204
- }
205
- /**
206
- * Reports an issue with a JSX element
207
- */
208
- reportElement(element, reason) {
209
- const node = this.getNode(element);
210
- const componentName = this.getComponentName(node);
211
- const line = this.getLineNumber(node);
212
- this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);
213
- }
214
- /**
215
- * Reports an issue with a specific prop
216
- */
217
- reportProp(element, propName, reason) {
218
- const node = this.getNode(element);
219
- const componentName = this.getComponentName(node);
220
- const line = this.getLineNumber(node);
221
- this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${reason}.`);
222
- }
223
- /**
224
- * Reports an issue with a JSX attribute directly
225
- */
226
- reportAttribute(attr, element, reason) {
227
- const node = this.getNode(element);
228
- const componentName = this.getComponentName(node);
229
- const propName = this.getAttributeName(attr);
230
- const line = this.getLineNumber(attr) || this.getLineNumber(node);
231
- const defaultReason = this.getAttributeReason(attr);
232
- const finalReason = reason || defaultReason;
233
- this.addIssue(`Manual review required: prop "${propName}" on <${componentName}> at line ${line} ${finalReason}.`);
234
- }
235
- /**
236
- * Reports spread props on an element
237
- */
238
- reportSpreadProps(element) {
239
- this.reportElement(element, "contains spread props that need manual review");
240
- }
241
- /**
242
- * Reports conflicting prop and children
243
- */
244
- reportPropWithChildren(element, propName) {
245
- this.reportProp(element, propName, `conflicts with children - both "${propName}" prop and children are present`);
246
- }
247
- /**
248
- * Reports unsupported prop value
249
- */
250
- reportUnsupportedValue(element, propName, value) {
251
- this.reportProp(element, propName, `has unsupported value "${value}"`);
252
- }
253
- /**
254
- * Reports ambiguous expression in prop
255
- */
256
- reportAmbiguousExpression(element, propName) {
257
- this.reportProp(element, propName, "contains a complex expression that needs manual review");
258
- }
259
- /**
260
- * Reports ambiguous children (like dynamic icons)
261
- */
262
- reportAmbiguousChildren(element, childType = "content") {
263
- this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);
264
- }
265
- /**
266
- * Reports deprecated prop usage
267
- */
268
- reportDeprecatedProp(element, propName, alternative) {
269
- const suggestion = alternative ? ` Use ${alternative} instead` : "";
270
- this.reportProp(element, propName, `is deprecated${suggestion}`);
271
- }
272
- /**
273
- * Reports missing required prop
274
- */
275
- reportMissingRequiredProp(element, propName) {
276
- this.reportProp(element, propName, "is required but missing");
277
- }
278
- /**
279
- * Reports conflicting props
280
- */
281
- reportConflictingProps(element, propNames) {
282
- const propList = propNames.map((name) => `"${name}"`).join(", ");
283
- this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);
284
- }
285
- /**
286
- * Auto-detects and reports common attribute issues
287
- */
288
- reportAttributeIssues(element) {
289
- const { attributes } = this.getNode(element).openingElement;
290
- if (!attributes) return;
291
- if (attributes.some((attr) => attr.type === "JSXSpreadAttribute")) this.reportSpreadProps(element);
292
- attributes.forEach((attr) => {
293
- if (attr.type === "JSXAttribute" && attr.value?.type === "JSXExpressionContainer") this.reportAttribute(attr, element);
294
- });
295
- }
296
- /**
297
- * Finds and reports instances of components that are under an alias (imported with a different name)
298
- */
299
- reportAliases(element) {
300
- this.reportElement(element, "is used via an import alias and needs manual review");
301
- }
302
- /**
303
- * Finds and reports instances of non-DS import declarations that conflict with the component name
304
- */
305
- reportConflictingImports(node) {
306
- this.addIssue(`Manual review required: Non-WDS package resulting in an import conflict at line ${this.getLineNumber(node)}.`);
307
- }
308
- /**
309
- * Reports enum usage for future conversion tracking
310
- */
311
- reportEnumUsage(element, propName, enumValue) {
312
- this.reportProp(element, propName, `uses enum value "${enumValue}" which has been preserved but should be migrated to a string literal in the future`);
313
- }
314
- getNode(element) {
315
- return "node" in element ? element.node : element;
316
- }
317
- getComponentName(node) {
318
- const { name } = node.openingElement;
319
- if (name.type === "JSXIdentifier") return name.name;
320
- return this.j(name).toSource();
321
- }
322
- getLineNumber(node) {
323
- return node.loc?.start.line?.toString() || "unknown";
324
- }
325
- getAttributeName(attr) {
326
- if (attr.name.type === "JSXIdentifier") return attr.name.name;
327
- return this.j(attr.name).toSource();
328
- }
329
- getAttributeReason(attr) {
330
- if (!attr.value) return "has no value";
331
- if (attr.value.type === "JSXExpressionContainer") {
332
- const expr = attr.value.expression;
333
- const expressionType = expr.type.replace("Expression", "").toLowerCase();
334
- if (expr.type === "Identifier" || expr.type === "MemberExpression") return `contains a ${expressionType} (${this.j(expr).toSource()})`;
335
- return `contains a complex ${expressionType} expression`;
336
- }
337
- return "needs manual review";
338
- }
339
- addIssue(message) {
340
- this.issues.push(message);
341
- }
342
- };
343
- const createReporter = (j, issues) => {
344
- return new CodemodReporter({
345
- jscodeshift: j,
346
- issues
347
- });
348
- };
349
-
350
- //#endregion
351
4
  //#region src/transforms/button/transformer.ts
352
5
  const parser = "tsx";
353
6
  const buildPriorityMapping = (opts) => {
@@ -482,10 +135,10 @@ const transformer = (file, api, options) => {
482
135
  if (type && priority) return priorityMapping[type]?.[priority] || priority;
483
136
  return priority;
484
137
  };
485
- const reporter = createReporter(j, manualReviewIssues);
486
- const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } = hasImport_default(root, "@transferwise/components", "Button", j);
138
+ const reporter = require_helpers.createReporter(j, manualReviewIssues);
139
+ const { exists: hasButtonImport, aliases: buttonAliases, resolvedName: buttonName, conflictingImports: conflictingButtonImport } = require_helpers.hasImport_default(root, "@transferwise/components", "Button", j);
487
140
  if (conflictingButtonImport.length) conflictingButtonImport.forEach((node) => reporter.reportConflictingImports(node));
488
- const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } = hasImport_default(root, "@transferwise/components", "ActionButton", j);
141
+ const { exists: hasActionButtonImport, remove: removeActionButtonImport, aliases: actionButtonAliases } = require_helpers.hasImport_default(root, "@transferwise/components", "ActionButton", j);
489
142
  if (!hasButtonImport && !hasActionButtonImport) return file.source;
490
143
  const iconImports = /* @__PURE__ */ new Set();
491
144
  root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path) => {
@@ -497,12 +150,12 @@ const transformer = (file, api, options) => {
497
150
  });
498
151
  });
499
152
  if (hasActionButtonImport) {
500
- if (!hasButtonImport) addImport_default(root, "@transferwise/components", "Button", j);
501
- findJSXElementsByName(root, j)("ActionButton", actionButtonAliases).forEach((path) => {
153
+ if (!hasButtonImport) require_helpers.addImport_default(root, "@transferwise/components", "Button", j);
154
+ require_helpers.findJSXElementsByName(root, j)("ActionButton", actionButtonAliases).forEach((path) => {
502
155
  const { openingElement, closingElement } = path.node;
503
- openingElement.name = setNameIfJSXIdentifier(openingElement.name, buttonName);
504
- if (closingElement) closingElement.name = setNameIfJSXIdentifier(closingElement.name, buttonName);
505
- iconUtils_default(j, path.node.children, iconImports, openingElement);
156
+ openingElement.name = require_helpers.setNameIfJSXIdentifier(openingElement.name, buttonName);
157
+ if (closingElement) closingElement.name = require_helpers.setNameIfJSXIdentifier(closingElement.name, buttonName);
158
+ require_helpers.iconUtils_default(j, path.node.children, iconImports, openingElement);
506
159
  if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
507
160
  const legacyPropNames = [
508
161
  "priority",
@@ -525,7 +178,7 @@ const transformer = (file, api, options) => {
525
178
  const hasChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXExpressionContainer") || path.node.children && path.node.children?.length > 0;
526
179
  if (hasTextProp && hasChildren) reporter.reportPropWithChildren(path, "text");
527
180
  else if (hasTextProp && !hasChildren && openingElement.selfClosing) path.replace(j.jsxElement(j.jsxOpeningElement(openingElement.name, openingElement.attributes), j.jsxClosingElement(openingElement.name), [j.jsxText(legacyProps.text || "")]));
528
- addAttributesIfMissing(j, path.node.openingElement, [{
181
+ require_helpers.addAttributesIfMissing(j, path.node.openingElement, [{
529
182
  attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
530
183
  name: "v2"
531
184
  }, {
@@ -541,17 +194,17 @@ const transformer = (file, api, options) => {
541
194
  });
542
195
  removeActionButtonImport();
543
196
  }
544
- if (hasButtonImport) findJSXElementsByName(root, j)("Button", buttonAliases).forEach((path) => {
197
+ if (hasButtonImport) require_helpers.findJSXElementsByName(root, j)("Button", buttonAliases).forEach((path) => {
545
198
  const { openingElement } = path.node;
546
- if (hasAttributeOnElement(openingElement, "v2")) return;
199
+ if (require_helpers.hasAttributeOnElement(openingElement, "v2")) return;
547
200
  const hasJSXChildren = path.node.children?.some((child) => child.type === "JSXText" && child.value.trim() !== "" || child.type === "JSXElement" || child.type === "JSXFragment" && child.children && child.children.length > 0 || child.type === "JSXExpressionContainer" && child.expression.type !== "JSXEmptyExpression");
548
201
  const hasChildrenAsProp = openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name?.type === "JSXIdentifier" && attr.name.name === "children");
549
202
  if (!hasJSXChildren && !hasChildrenAsProp) return;
550
- addAttributesIfMissing(j, openingElement, [{
203
+ require_helpers.addAttributesIfMissing(j, openingElement, [{
551
204
  attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
552
205
  name: "v2"
553
206
  }]);
554
- iconUtils_default(j, path.node.children, iconImports, openingElement);
207
+ require_helpers.iconUtils_default(j, path.node.children, iconImports, openingElement);
555
208
  const legacyProps = {};
556
209
  const legacyPropNames = [
557
210
  "priority",
@@ -587,7 +240,7 @@ const transformer = (file, api, options) => {
587
240
  "lg",
588
241
  "xl"
589
242
  ].includes(resolved)) {
590
- removeAttributeByName(j, openingElement, "size");
243
+ require_helpers.removeAttributeByName(j, openingElement, "size");
591
244
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("size"), j.literal(resolved)));
592
245
  } else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "size", rawValue);
593
246
  else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "size");
@@ -612,7 +265,7 @@ const transformer = (file, api, options) => {
612
265
  "tertiary",
613
266
  "secondary-neutral"
614
267
  ].includes(mapped)) {
615
- removeAttributeByName(j, openingElement, "priority");
268
+ require_helpers.removeAttributeByName(j, openingElement, "priority");
616
269
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(mapped)));
617
270
  } else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "priority", rawValue);
618
271
  else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "priority");
@@ -644,20 +297,20 @@ const transformer = (file, api, options) => {
644
297
  "reset"
645
298
  ];
646
299
  if (resolvedType === "negative" && isControlTypeEnum) {
647
- removeAttributeByName(j, openingElement, "type");
648
- if (hasAttributeOnElement(openingElement, "sentiment")) removeAttributeByName(j, openingElement, "sentiment");
649
- addAttributesIfMissing(j, openingElement, [{
300
+ require_helpers.removeAttributeByName(j, openingElement, "type");
301
+ if (require_helpers.hasAttributeOnElement(openingElement, "sentiment")) require_helpers.removeAttributeByName(j, openingElement, "sentiment");
302
+ require_helpers.addAttributesIfMissing(j, openingElement, [{
650
303
  attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
651
304
  name: "priority"
652
305
  }]);
653
306
  if (rawType) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.jsxExpressionContainer(j.identifier(rawType))));
654
307
  } else if (resolvedType === "negative" && !isTypeEnum) {
655
- removeAttributeByName(j, openingElement, "type");
656
- if (hasAttributeOnElement(openingElement, "sentiment")) removeAttributeByName(j, openingElement, "sentiment");
308
+ require_helpers.removeAttributeByName(j, openingElement, "type");
309
+ if (require_helpers.hasAttributeOnElement(openingElement, "sentiment")) require_helpers.removeAttributeByName(j, openingElement, "sentiment");
657
310
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
658
311
  } else if (isControlTypeEnum && resolvedType && ["positive", "accent"].includes(resolvedType)) {
659
- removeAttributeByName(j, openingElement, "type");
660
- addAttributesIfMissing(j, openingElement, [{
312
+ require_helpers.removeAttributeByName(j, openingElement, "type");
313
+ require_helpers.addAttributesIfMissing(j, openingElement, [{
661
314
  attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
662
315
  name: "priority"
663
316
  }]);
@@ -665,21 +318,21 @@ const transformer = (file, api, options) => {
665
318
  if (resolvedType && typeof resolvedType === "string" && legacyButtonTypes.includes(resolvedType) && !isTypeEnum) {
666
319
  const consistentConversion = getConsistentTypeConversions(resolvedType);
667
320
  if (consistentConversion) {
668
- removeAttributeByName(j, openingElement, "type");
669
- removeAttributeByName(j, openingElement, "priority");
670
- removeAttributeByName(j, openingElement, "sentiment");
321
+ require_helpers.removeAttributeByName(j, openingElement, "type");
322
+ require_helpers.removeAttributeByName(j, openingElement, "priority");
323
+ require_helpers.removeAttributeByName(j, openingElement, "sentiment");
671
324
  if (consistentConversion.priority) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("priority"), j.literal(consistentConversion.priority)));
672
325
  if (consistentConversion.sentiment) openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal(consistentConversion.sentiment)));
673
326
  } else {
674
- removeAttributeByName(j, openingElement, "type");
675
- addAttributesIfMissing(j, openingElement, [{
327
+ require_helpers.removeAttributeByName(j, openingElement, "type");
328
+ require_helpers.addAttributesIfMissing(j, openingElement, [{
676
329
  attribute: j.jsxAttribute(j.jsxIdentifier("priority"), j.literal("primary")),
677
330
  name: "priority"
678
331
  }]);
679
332
  }
680
333
  } else if (isTypeEnum) {}
681
334
  if (typeof finalHtmlType === "string" && htmlTypes.includes(finalHtmlType)) {
682
- removeAttributeByName(j, openingElement, "htmlType");
335
+ require_helpers.removeAttributeByName(j, openingElement, "htmlType");
683
336
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("type"), j.literal(finalHtmlType)));
684
337
  } else if (typeof rawType === "string" || typeof rawHtmlType === "string") {
685
338
  const valueToCheck = rawType ?? rawHtmlType ?? "";
@@ -698,7 +351,7 @@ const transformer = (file, api, options) => {
698
351
  if (!openingElement.attributes?.some((attr) => attr.type === "JSXAttribute" && attr.name && attr.name.name === "sentiment")) {
699
352
  const rawValue = legacyProps.sentiment;
700
353
  if (rawValue === "negative") {
701
- removeAttributeByName(j, openingElement, "sentiment");
354
+ require_helpers.removeAttributeByName(j, openingElement, "sentiment");
702
355
  openingElement.attributes?.push(j.jsxAttribute(j.jsxIdentifier("sentiment"), j.literal("negative")));
703
356
  } else if (typeof rawValue === "string") reporter.reportUnsupportedValue(path, "sentiment", rawValue);
704
357
  else if (rawValue !== void 0) reporter.reportAmbiguousExpression(path, "sentiment");