@wise/wds-codemods 0.0.1-experimental-cbae00f โ†’ 0.0.1-experimental-926a862

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.
Files changed (60) hide show
  1. package/dist/index.js +133 -135
  2. package/dist/index.js.map +1 -1
  3. package/dist/reportManualReview-DQ00-OKx.js +50 -0
  4. package/dist/reportManualReview-DQ00-OKx.js.map +1 -0
  5. package/dist/transforms/button.js +493 -566
  6. package/dist/transforms/button.js.map +1 -1
  7. package/package.json +19 -14
  8. package/.changeset/better-impalas-drop.md +0 -5
  9. package/.changeset/config.json +0 -13
  10. package/.changeset/quick-mails-joke.md +0 -128
  11. package/.github/CODEOWNERS +0 -1
  12. package/.github/actions/bootstrap/action.yml +0 -49
  13. package/.github/actions/commitlint/action.yml +0 -27
  14. package/.github/actions/test/action.yml +0 -23
  15. package/.github/workflows/cd-cd.yml +0 -127
  16. package/.github/workflows/renovate.yml +0 -16
  17. package/.husky/commit-msg +0 -1
  18. package/.husky/pre-commit +0 -1
  19. package/.nvmrc +0 -1
  20. package/.prettierignore +0 -1
  21. package/.prettierrc.js +0 -5
  22. package/DEVELOPER.md +0 -783
  23. package/babel.config.js +0 -28
  24. package/commitlint.config.js +0 -3
  25. package/dist/index.d.ts +0 -1
  26. package/dist/transforms/button.d.ts +0 -16
  27. package/eslint.config.js +0 -15
  28. package/jest.config.js +0 -9
  29. package/mkdocs.yml +0 -4
  30. package/renovate.json +0 -9
  31. package/scripts/build.sh +0 -10
  32. package/src/__tests__/runCodemod.test.ts +0 -96
  33. package/src/index.ts +0 -4
  34. package/src/runCodemod.ts +0 -88
  35. package/src/transforms/button/__tests__/button.test.tsx +0 -153
  36. package/src/transforms/button/button.ts +0 -418
  37. package/src/transforms/helpers/__tests__/createTestTransform.test.ts +0 -27
  38. package/src/transforms/helpers/__tests__/hasImport.test.ts +0 -52
  39. package/src/transforms/helpers/__tests__/iconUtils.test.ts +0 -207
  40. package/src/transforms/helpers/__tests__/jsxElementUtils.test.ts +0 -130
  41. package/src/transforms/helpers/__tests__/jsxReportingUtils.test.ts +0 -265
  42. package/src/transforms/helpers/createTestTransform.ts +0 -18
  43. package/src/transforms/helpers/hasImport.ts +0 -60
  44. package/src/transforms/helpers/iconUtils.ts +0 -87
  45. package/src/transforms/helpers/index.ts +0 -5
  46. package/src/transforms/helpers/jsxElementUtils.ts +0 -67
  47. package/src/transforms/helpers/jsxReportingUtils.ts +0 -224
  48. package/src/utils/__tests__/getOptions.test.ts +0 -170
  49. package/src/utils/__tests__/handleError.test.ts +0 -18
  50. package/src/utils/__tests__/loadTransformModules.test.ts +0 -51
  51. package/src/utils/__tests__/reportManualReview.test.ts +0 -42
  52. package/src/utils/getOptions.ts +0 -63
  53. package/src/utils/handleError.ts +0 -6
  54. package/src/utils/index.ts +0 -4
  55. package/src/utils/loadTransformModules.ts +0 -28
  56. package/src/utils/reportManualReview.ts +0 -17
  57. package/test-button.tsx +0 -230
  58. package/test-file.js +0 -2
  59. package/tsconfig.json +0 -14
  60. package/tsup.config.js +0 -13
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/reportManualReview.ts","../../src/transforms/helpers/hasImport.ts","../../src/transforms/helpers/iconUtils.ts","../../src/transforms/helpers/jsxElementUtils.ts","../../src/transforms/helpers/jsxReportingUtils.ts","../../src/transforms/button/button.ts"],"sourcesContent":["import fs from 'node:fs/promises';\n\nimport path from 'path';\n\nconst REPORT_PATH = path.resolve(process.cwd(), 'codemod-report.txt');\n\nconst reportManualReview = async (filePath: string, message: string): Promise<void> => {\n const lineMatch = /at line (\\d+)/u.exec(message);\n const lineNumber = lineMatch?.[1];\n\n const cleanMessage = message.replace(/ at line \\d+/u, '');\n const lineInfo = lineNumber ? `:${lineNumber}` : '';\n\n await fs.appendFile(REPORT_PATH, `[${filePath}${lineInfo}] ${cleanMessage}\\n`, 'utf8');\n};\n\nexport default reportManualReview;\n","import type { Collection, JSCodeshift } from 'jscodeshift';\n\n/**\n * Checks if a specific import exists in the given root collection and provides\n * a method to remove it if found.\n */\nfunction hasImport(\n root: Collection,\n sourceValue: string,\n importName: string,\n j: JSCodeshift,\n): { exists: boolean; remove: () => void } {\n const importDeclarations = root.find(j.ImportDeclaration, {\n source: { value: sourceValue },\n });\n\n if (importDeclarations.size() === 0) {\n return {\n exists: false,\n remove: () => {},\n };\n }\n\n const namedImport = importDeclarations.find(j.ImportSpecifier, {\n imported: { name: importName },\n });\n\n const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, {\n local: { name: importName },\n });\n\n const exists = namedImport.size() > 0 || defaultImport.size() > 0;\n\n const remove = () => {\n importDeclarations.forEach((path) => {\n const filteredSpecifiers =\n path.node.specifiers?.filter((specifier) => {\n if (specifier.type === 'ImportSpecifier' && specifier.imported.name === importName) {\n return false;\n }\n if (specifier.type === 'ImportDefaultSpecifier' && specifier.local?.name === importName) {\n return false;\n }\n return true;\n }) ?? [];\n\n if (filteredSpecifiers.length === 0) {\n path.prune();\n } else {\n j(path).replaceWith(\n j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind),\n );\n }\n });\n };\n\n return { exists, remove };\n}\n\nexport default hasImport;\n","import type { JSCodeshift, JSXElement, JSXExpressionContainer } from 'jscodeshift';\n\n/**\n * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.\n * This is specific to icon handling but can be reused in codemods dealing with icon children.\n */\nconst processIconChildren = (\n j: JSCodeshift,\n children: (JSXElement | JSXExpressionContainer | unknown)[] | undefined,\n iconImports: Set<string>,\n openingElement: JSXElement['openingElement'],\n) => {\n if (!children || !openingElement.attributes) return;\n\n const unwrapJsxElement = (node: unknown): JSXElement | unknown => {\n if (\n typeof node === 'object' &&\n node !== null &&\n 'type' in node &&\n node.type === 'JSXExpressionContainer' &&\n j.JSXElement.check((node as JSXExpressionContainer).expression)\n ) {\n return (node as JSXExpressionContainer).expression;\n }\n return node;\n };\n\n const totalChildren = children.length;\n\n // Find index of icon child\n const iconChildIndex = children.findIndex((child) => {\n const unwrapped = unwrapJsxElement(child);\n return (\n j.JSXElement.check(unwrapped) &&\n unwrapped.openingElement.name.type === 'JSXIdentifier' &&\n iconImports.has(unwrapped.openingElement.name.name)\n );\n });\n\n if (iconChildIndex === -1) return;\n\n const iconChild = unwrapJsxElement(children[iconChildIndex]) as JSXElement;\n\n if (!iconChild || iconChild.openingElement.name.type !== 'JSXIdentifier') return;\n\n const iconName = iconChild.openingElement.name.name;\n\n // Determine if icon is closer to start or end\n const distanceToStart = iconChildIndex;\n const distanceToEnd = totalChildren - 1 - iconChildIndex;\n const iconPropName = distanceToStart <= distanceToEnd ? 'addonStart' : 'addonEnd';\n\n // Build: { type: 'icon', value: <IconName /> }\n const iconObject = j.objectExpression([\n j.property('init', j.identifier('type'), j.literal('icon')),\n j.property('init', j.identifier('value'), iconChild),\n ]);\n const iconProp = j.jsxAttribute(\n j.jsxIdentifier(iconPropName),\n j.jsxExpressionContainer(iconObject),\n );\n\n openingElement.attributes.push(iconProp);\n\n // Remove the icon child\n children.splice(iconChildIndex, 1);\n\n // Helper to check if a child is whitespace-only JSXText\n const isWhitespaceJsxText = (node: unknown): boolean => {\n return (\n typeof node === 'object' &&\n node !== null &&\n (node as { type?: unknown }).type === 'JSXText' &&\n typeof (node as { value?: string }).value === 'string' &&\n (node as { value?: string }).value!.trim() === ''\n );\n };\n\n // Remove adjacent whitespace-only JSXText node if any\n if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) {\n children.splice(iconChildIndex - 1, 1);\n } else if (isWhitespaceJsxText(children[iconChildIndex])) {\n children.splice(iconChildIndex, 1);\n }\n};\n\nexport default processIconChildren;\n","import type {\n JSCodeshift,\n JSXAttribute,\n JSXElement,\n JSXIdentifier,\n JSXMemberExpression,\n JSXNamespacedName,\n JSXSpreadAttribute,\n} from 'jscodeshift';\n\n/**\n * Rename a JSX element name if it is a JSXIdentifier.\n */\nexport const setNameIfJSXIdentifier = (\n elementName: JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined,\n newName: string,\n): JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined => {\n if (elementName && elementName.type === 'JSXIdentifier') {\n return { ...elementName, name: newName };\n }\n return elementName;\n};\n\n/**\n * Check if a list of attributes contains a specific attribute by name.\n */\nexport const hasAttribute = (\n attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined,\n attributeName: string,\n): boolean => {\n return (\n Array.isArray(attributes) &&\n attributes.some(\n (attr): attr is JSXAttribute =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === attributeName,\n )\n );\n};\n\n/**\n * Check if a JSX element's openingElement has a specific attribute.\n */\nexport const hasAttributeOnElement = (\n element: JSXElement['openingElement'],\n attributeName: string,\n): boolean => {\n return hasAttribute(element.attributes, attributeName);\n};\n\n/**\n * Add specified attributes to a JSX element's openingElement if they are not already present.\n */\nexport const addAttributesIfMissing = (\n j: JSCodeshift,\n openingElement: JSXElement['openingElement'],\n attributesToAdd: { attribute: JSXAttribute; name: string }[],\n) => {\n if (!Array.isArray(openingElement.attributes)) return;\n const attrs = openingElement.attributes;\n attributesToAdd.forEach(({ attribute, name }) => {\n if (!hasAttributeOnElement(openingElement, name)) {\n attrs.push(attribute);\n }\n });\n};\n","import type { ASTPath, JSCodeshift, JSXAttribute, JSXElement, Node } from 'jscodeshift';\n\nexport interface ReporterOptions {\n jscodeshift: JSCodeshift;\n issues: string[];\n}\n\n/**\n * CodemodReporter is a utility class for reporting issues found during codemod transformations.\n * It provides methods to report issues related to JSX elements, props, and attributes.\n *\n * @example\n * ```typescript\n * const issues: string[] = [];\n * const reporter = createReporter(j, issues);\n *\n * // Report a deprecated prop\n * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant=\"text\"');\n *\n * // Report complex expression that needs review\n * reporter.reportAmbiguousExpression(element, 'size');\n *\n * // Auto-detect common issues\n * reporter.reportAttributeIssues(element);\n * ```\n */\nexport class CodemodReporter {\n private readonly j: JSCodeshift;\n private readonly issues: string[];\n\n constructor(options: ReporterOptions) {\n this.j = options.jscodeshift;\n this.issues = options.issues;\n }\n\n /**\n * Reports an issue with a JSX element\n */\n reportElement(element: JSXElement | ASTPath<JSXElement>, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);\n }\n\n /**\n * Reports an issue with a specific prop\n */\n reportProp(element: JSXElement | ASTPath<JSXElement>, propName: string, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${reason}.`,\n );\n }\n\n /**\n * Reports an issue with a JSX attribute directly\n */\n reportAttribute(\n attr: JSXAttribute,\n element: JSXElement | ASTPath<JSXElement>,\n reason?: string,\n ): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const propName = this.getAttributeName(attr);\n const line = this.getLineNumber(attr) || this.getLineNumber(node);\n\n const defaultReason = this.getAttributeReason(attr);\n const finalReason = reason || defaultReason;\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${finalReason}.`,\n );\n }\n\n /**\n * Reports spread props on an element\n */\n reportSpreadProps(element: JSXElement | ASTPath<JSXElement>): void {\n this.reportElement(element, 'contains spread props that need manual review');\n }\n\n /**\n * Reports conflicting prop and children\n */\n reportPropWithChildren(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(\n element,\n propName,\n `conflicts with children - both \"${propName}\" prop and children are present`,\n );\n }\n\n /**\n * Reports unsupported prop value\n */\n reportUnsupportedValue(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n value: string,\n ): void {\n this.reportProp(element, propName, `has unsupported value \"${value}\"`);\n }\n\n /**\n * Reports ambiguous expression in prop\n */\n reportAmbiguousExpression(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'contains a complex expression that needs manual review');\n }\n\n /**\n * Reports ambiguous children (like dynamic icons)\n */\n reportAmbiguousChildren(element: JSXElement | ASTPath<JSXElement>, childType = 'content'): void {\n this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);\n }\n\n /**\n * Reports deprecated prop usage\n */\n reportDeprecatedProp(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n alternative?: string,\n ): void {\n const suggestion = alternative ? ` Use ${alternative} instead` : '';\n this.reportProp(element, propName, `is deprecated${suggestion}`);\n }\n\n /**\n * Reports missing required prop\n */\n reportMissingRequiredProp(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'is required but missing');\n }\n\n /**\n * Reports conflicting props\n */\n reportConflictingProps(element: JSXElement | ASTPath<JSXElement>, propNames: string[]): void {\n const propList = propNames.map((name) => `\"${name}\"`).join(', ');\n this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);\n }\n\n /**\n * Auto-detects and reports common attribute issues\n */\n reportAttributeIssues(element: JSXElement | ASTPath<JSXElement>): void {\n const node = this.getNode(element);\n const { attributes } = node.openingElement;\n\n if (!attributes) return;\n\n // Check for spread props\n if (attributes.some((attr) => attr.type === 'JSXSpreadAttribute')) {\n this.reportSpreadProps(element);\n }\n\n // Check for complex expressions in attributes\n attributes.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.value?.type === 'JSXExpressionContainer') {\n this.reportAttribute(attr, element);\n }\n });\n }\n\n // Private helper methods\n private getNode(element: JSXElement | ASTPath<JSXElement>): JSXElement {\n return 'node' in element ? element.node : element;\n }\n\n private getComponentName(node: JSXElement): string {\n const { name } = node.openingElement;\n if (name.type === 'JSXIdentifier') {\n return name.name;\n }\n // Handle JSXMemberExpression, JSXNamespacedName, etc.\n return this.j(name).toSource();\n }\n\n private getLineNumber(node: JSXElement | JSXAttribute | Node): string {\n return node.loc?.start.line?.toString() || 'unknown';\n }\n\n private getAttributeName(attr: JSXAttribute): string {\n if (attr.name.type === 'JSXIdentifier') {\n return attr.name.name;\n }\n return this.j(attr.name).toSource();\n }\n\n private getAttributeReason(attr: JSXAttribute): string {\n if (!attr.value) return 'has no value';\n\n if (attr.value.type === 'JSXExpressionContainer') {\n const expr = attr.value.expression;\n const expressionType = expr.type.replace('Expression', '').toLowerCase();\n\n // Show actual value for simple cases\n if (expr.type === 'Identifier' || expr.type === 'MemberExpression') {\n const valueText = this.j(expr).toSource();\n return `contains a ${expressionType} (${valueText})`;\n }\n\n return `contains a complex ${expressionType} expression`;\n }\n\n return 'needs manual review';\n }\n\n private addIssue(message: string): void {\n this.issues.push(message);\n }\n}\n\nexport const createReporter = (j: JSCodeshift, issues: string[]): CodemodReporter => {\n return new CodemodReporter({ jscodeshift: j, issues });\n};\n","import type { API, FileInfo, JSCodeshift, JSXIdentifier, Options } from 'jscodeshift';\n\nimport reportManualReview from '../../utils/reportManualReview';\nimport hasImport from '../helpers/hasImport';\nimport processIconChildren from '../helpers/iconUtils';\nimport {\n addAttributesIfMissing,\n hasAttributeOnElement,\n setNameIfJSXIdentifier,\n} from '../helpers/jsxElementUtils';\nimport { createReporter } from '../helpers/jsxReportingUtils';\n\nexport const parser = 'tsx';\n\ninterface LegacyProps {\n priority?: string;\n size?: string;\n type?: string;\n htmlType?: string;\n sentiment?: string;\n [key: string]: unknown;\n}\n\nconst priorityMapping: Record<string, Record<string, string>> = {\n accent: {\n primary: 'primary',\n secondary: 'secondary-neutral',\n tertiary: 'tertiary',\n },\n positive: {\n primary: 'primary',\n secondary: 'secondary-neutral',\n tertiary: 'secondary-neutral',\n },\n negative: {\n primary: 'primary',\n secondary: 'secondary',\n tertiary: 'secondary',\n },\n};\n\nconst sizeMap: Record<string, string> = {\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n MEDIUM: 'md',\n LARGE: 'lg',\n EXTRA_LARGE: 'xl',\n xs: 'sm',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'xl',\n};\n\nconst resolveSize = (size?: string): string | undefined => {\n if (!size) return size;\n const match = /^Size\\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u.exec(size);\n if (match) {\n return sizeMap[match[1]];\n }\n return sizeMap[size] || size;\n};\n\nconst resolvePriority = (type?: string, priority?: string): string | undefined => {\n if (type && priority) {\n return priorityMapping[type]?.[priority] || priority;\n }\n return priority;\n};\n\nconst resolveType = (type?: string, htmlType?: string): string | null => {\n if (htmlType) {\n return htmlType;\n }\n\n const legacyButtonTypes = [\n 'accent',\n 'negative',\n 'positive',\n 'primary',\n 'pay',\n 'secondary',\n 'danger',\n 'link',\n ];\n return type && legacyButtonTypes.includes(type) ? type : null;\n};\n\nconst convertEnumValue = (value?: string): string | undefined => {\n if (!value) return value;\n const strippedValue = value.replace(/^['\"]|['\"]$/gu, '');\n const enumMapping: Record<string, string> = {\n 'Priority.SECONDARY': 'secondary',\n 'Priority.PRIMARY': 'primary',\n 'Priority.TERTIARY': 'tertiary',\n 'ControlType.NEGATIVE': 'negative',\n 'ControlType.POSITIVE': 'positive',\n 'ControlType.ACCENT': 'accent',\n };\n return enumMapping[strippedValue] || strippedValue;\n};\n\n/**\n * This transform function modifies the Button and ActionButton components from the @transferwise/components library.\n * It updates the ActionButton component to use the Button component with specific attributes and mappings.\n * It also processes icon children and removes legacy props.\n *\n * @param {FileInfo} file - The file information object.\n * @param {API} api - The API object for jscodeshift.\n * @param {Options} options - The options object for jscodeshift.\n * @returns {string} - The transformed source code.\n */\nconst transformer = (file: FileInfo, api: API, options: Options) => {\n const j: JSCodeshift = api.jscodeshift;\n const root = j(file.source);\n const manualReviewIssues: string[] = [];\n\n // Create reporter instance\n const reporter = createReporter(j, manualReviewIssues);\n\n const { exists: hasButtonImport } = hasImport(root, '@transferwise/components', 'Button', j);\n const { exists: hasActionButtonImport, remove: removeActionButtonImport } = hasImport(\n root,\n '@transferwise/components',\n 'ActionButton',\n j,\n );\n\n const iconImports = new Set<string>();\n root.find(j.ImportDeclaration, { source: { value: '@transferwise/icons' } }).forEach((path) => {\n path.node.specifiers?.forEach((specifier) => {\n if (\n (specifier.type === 'ImportDefaultSpecifier' || specifier.type === 'ImportSpecifier') &&\n specifier.local\n ) {\n const localName = (specifier.local as { name: string }).name;\n iconImports.add(localName);\n }\n });\n });\n\n if (hasActionButtonImport) {\n root.findJSXElements('ActionButton').forEach((path) => {\n const { openingElement, closingElement } = path.node;\n\n openingElement.name = setNameIfJSXIdentifier(openingElement.name, 'Button')!;\n if (closingElement) {\n closingElement.name = setNameIfJSXIdentifier(closingElement.name, 'Button')!;\n }\n\n addAttributesIfMissing(j, openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n { attribute: j.jsxAttribute(j.jsxIdentifier('size'), j.literal('sm')), name: 'size' },\n ]);\n\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n\n const legacyPropNames = ['priority', 'text'];\n const legacyProps: LegacyProps = {};\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name && attr.name.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n reporter.reportAttribute(attr, path);\n }\n }\n }\n }\n });\n\n const hasTextProp = openingElement.attributes?.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === 'text',\n );\n const hasChildren = path.node.children?.some(\n (child) =>\n (child.type === 'JSXText' && child.value.trim() !== '') ||\n child.type === 'JSXElement' ||\n child.type === 'JSXExpressionContainer',\n );\n\n if (hasTextProp && hasChildren) {\n reporter.reportPropWithChildren(path, 'text');\n }\n\n (path.node.children || []).forEach((child) => {\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression;\n if (\n expr.type === 'ConditionalExpression' ||\n expr.type === 'CallExpression' ||\n expr.type === 'Identifier' ||\n expr.type === 'MemberExpression'\n ) {\n reporter.reportAmbiguousChildren(path, 'icon');\n }\n }\n });\n });\n\n removeActionButtonImport();\n }\n\n if (hasButtonImport) {\n root.findJSXElements('Button').forEach((path) => {\n const { openingElement } = path.node;\n\n if (hasAttributeOnElement(openingElement, 'v2')) return;\n\n addAttributesIfMissing(j, openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n ]);\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n const legacyProps: LegacyProps = {};\n const legacyPropNames = ['priority', 'size', 'type', 'htmlType', 'sentiment'];\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name && attr.name.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n legacyProps[name] = convertEnumValue(String(j(attr.value.expression).toSource()));\n }\n } else {\n legacyProps[name] = undefined;\n }\n }\n }\n });\n\n if (openingElement.attributes) {\n openingElement.attributes = openingElement.attributes.filter(\n (attr) =>\n !(\n attr.type === 'JSXAttribute' &&\n attr.name &&\n legacyPropNames.includes((attr.name as JSXIdentifier).name)\n ),\n );\n }\n\n if ('size' in legacyProps) {\n const rawValue = legacyProps.size;\n const resolved = resolveSize(rawValue);\n const supportedSizes = ['xs', 'sm', 'md', 'lg', 'xl'];\n\n if (\n typeof rawValue === 'string' &&\n typeof resolved === 'string' &&\n supportedSizes.includes(resolved)\n ) {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('size'), j.literal(resolved)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'size', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'size');\n }\n }\n\n if ('priority' in legacyProps) {\n const rawValue = legacyProps.priority;\n const converted = convertEnumValue(rawValue);\n const mapped = resolvePriority(legacyProps.type, converted);\n const supportedPriorities = ['primary', 'secondary', 'tertiary', 'secondary-neutral'];\n\n if (\n typeof rawValue === 'string' &&\n typeof mapped === 'string' &&\n supportedPriorities.includes(mapped)\n ) {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('priority'), j.literal(mapped)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'priority', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'priority');\n }\n }\n\n if ('type' in legacyProps || 'htmlType' in legacyProps) {\n const rawType = legacyProps.type;\n const rawHtmlType = legacyProps.htmlType;\n\n const resolvedType =\n typeof rawType === 'string'\n ? rawType\n : rawType && typeof rawType === 'object'\n ? convertEnumValue(j(rawType).toSource())\n : undefined;\n\n const resolved = resolveType(resolvedType, rawHtmlType);\n\n const supportedTypes = [\n 'accent',\n 'negative',\n 'positive',\n 'primary',\n 'pay',\n 'secondary',\n 'danger',\n 'link',\n 'submit',\n 'button',\n 'reset',\n ];\n\n if (typeof resolved === 'string' && supportedTypes.includes(resolved)) {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('type'), j.literal(resolved)),\n );\n\n if (resolved === 'negative') {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n }\n } else if (typeof rawType === 'string' || typeof rawHtmlType === 'string') {\n reporter.reportUnsupportedValue(path, 'type', rawType ?? rawHtmlType ?? '');\n } else if (rawType !== undefined || rawHtmlType !== undefined) {\n reporter.reportAmbiguousExpression(path, 'type');\n }\n }\n\n if ('sentiment' in legacyProps) {\n const rawValue = legacyProps.sentiment;\n if (rawValue === 'negative') {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'sentiment', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'sentiment');\n }\n }\n\n let asIndex = -1;\n let asValue: string | null = null;\n let hrefExists = false;\n let asAmbiguous = false;\n let hrefAmbiguous = false;\n\n openingElement.attributes?.forEach((attr, index) => {\n if (attr.type === 'JSXAttribute' && attr.name) {\n if (attr.name.name === 'as') {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n asValue = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n asAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n asIndex = index;\n }\n\n if (attr.name.name === 'href') {\n hrefExists = true;\n if (attr.value && attr.value.type !== 'StringLiteral') {\n hrefAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n }\n });\n\n if (asValue && asValue !== 'a') {\n reporter.reportUnsupportedValue(path, 'as', asValue);\n }\n\n if (asValue === 'a') {\n if (asIndex !== -1) {\n openingElement.attributes = openingElement.attributes?.filter(\n (_, idx) => idx !== asIndex,\n );\n }\n if (!hrefExists) {\n openingElement.attributes = [\n ...(openingElement.attributes ?? []),\n j.jsxAttribute(j.jsxIdentifier('href'), j.literal('#')),\n ];\n }\n }\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n });\n }\n\n if (manualReviewIssues.length > 0) {\n manualReviewIssues.forEach(async (issue) => {\n await reportManualReview(file.path, issue);\n });\n }\n\n return root.toSource();\n};\n\nexport default transformer;\n"],"mappings":"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","names":["path","path"]}
1
+ {"version":3,"file":"button.js","names":["priorityMapping: Record<string, Record<string, string>>","sizeMap: Record<string, string>","enumMapping: Record<string, string>","j: JSCodeshift","manualReviewIssues: string[]","legacyProps: LegacyProps","asValue: string | null","reportManualReview"],"sources":["../../src/transforms/helpers/hasImport.ts","../../src/transforms/helpers/iconUtils.ts","../../src/transforms/helpers/jsxElementUtils.ts","../../src/transforms/helpers/jsxReportingUtils.ts","../../src/transforms/button/transformer.ts"],"sourcesContent":["import type { Collection, JSCodeshift } from 'jscodeshift';\n\n/**\n * Checks if a specific import exists in the given root collection and provides\n * a method to remove it if found.\n */\nfunction hasImport(\n root: Collection,\n sourceValue: string,\n importName: string,\n j: JSCodeshift,\n): { exists: boolean; remove: () => void } {\n const importDeclarations = root.find(j.ImportDeclaration, {\n source: { value: sourceValue },\n });\n\n if (importDeclarations.size() === 0) {\n return {\n exists: false,\n remove: () => {},\n };\n }\n\n const namedImport = importDeclarations.find(j.ImportSpecifier, {\n imported: { name: importName },\n });\n\n const defaultImport = importDeclarations.find(j.ImportDefaultSpecifier, {\n local: { name: importName },\n });\n\n const exists = namedImport.size() > 0 || defaultImport.size() > 0;\n\n const remove = () => {\n importDeclarations.forEach((path) => {\n const filteredSpecifiers =\n path.node.specifiers?.filter((specifier) => {\n if (specifier.type === 'ImportSpecifier' && specifier.imported.name === importName) {\n return false;\n }\n if (specifier.type === 'ImportDefaultSpecifier' && specifier.local?.name === importName) {\n return false;\n }\n return true;\n }) ?? [];\n\n if (filteredSpecifiers.length === 0) {\n path.prune();\n } else {\n j(path).replaceWith(\n j.importDeclaration(filteredSpecifiers, path.node.source, path.node.importKind),\n );\n }\n });\n };\n\n return { exists, remove };\n}\n\nexport default hasImport;\n","import type { JSCodeshift, JSXElement, JSXExpressionContainer } from 'jscodeshift';\n\n/**\n * Process children of a JSX element to detect icon components and add iconStart or iconEnd attributes accordingly.\n * This is specific to icon handling but can be reused in codemods dealing with icon children.\n */\nconst processIconChildren = (\n j: JSCodeshift,\n children: (JSXElement | JSXExpressionContainer | unknown)[] | undefined,\n iconImports: Set<string>,\n openingElement: JSXElement['openingElement'],\n) => {\n if (!children || !openingElement.attributes) return;\n\n const unwrapJsxElement = (node: unknown): JSXElement | unknown => {\n if (\n typeof node === 'object' &&\n node !== null &&\n 'type' in node &&\n node.type === 'JSXExpressionContainer' &&\n j.JSXElement.check((node as JSXExpressionContainer).expression)\n ) {\n return (node as JSXExpressionContainer).expression;\n }\n return node;\n };\n\n const totalChildren = children.length;\n\n // Find index of icon child\n const iconChildIndex = children.findIndex((child) => {\n const unwrapped = unwrapJsxElement(child);\n return (\n j.JSXElement.check(unwrapped) &&\n unwrapped.openingElement.name.type === 'JSXIdentifier' &&\n iconImports.has(unwrapped.openingElement.name.name)\n );\n });\n\n if (iconChildIndex === -1) return;\n\n const iconChild = unwrapJsxElement(children[iconChildIndex]) as JSXElement;\n\n if (!iconChild || iconChild.openingElement.name.type !== 'JSXIdentifier') return;\n\n const iconName = iconChild.openingElement.name.name;\n\n // Determine if icon is closer to start or end\n const distanceToStart = iconChildIndex;\n const distanceToEnd = totalChildren - 1 - iconChildIndex;\n const iconPropName = distanceToStart <= distanceToEnd ? 'addonStart' : 'addonEnd';\n\n // Build: { type: 'icon', value: <IconName /> }\n const iconObject = j.objectExpression([\n j.property('init', j.identifier('type'), j.literal('icon')),\n j.property('init', j.identifier('value'), iconChild),\n ]);\n const iconProp = j.jsxAttribute(\n j.jsxIdentifier(iconPropName),\n j.jsxExpressionContainer(iconObject),\n );\n\n openingElement.attributes.push(iconProp);\n\n // Remove the icon child\n children.splice(iconChildIndex, 1);\n\n // Helper to check if a child is whitespace-only JSXText\n const isWhitespaceJsxText = (node: unknown): boolean => {\n return (\n typeof node === 'object' &&\n node !== null &&\n (node as { type?: unknown }).type === 'JSXText' &&\n typeof (node as { value?: string }).value === 'string' &&\n (node as { value?: string }).value!.trim() === ''\n );\n };\n\n // Remove adjacent whitespace-only JSXText node if any\n if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) {\n children.splice(iconChildIndex - 1, 1);\n } else if (isWhitespaceJsxText(children[iconChildIndex])) {\n children.splice(iconChildIndex, 1);\n }\n};\n\nexport default processIconChildren;\n","import type {\n JSCodeshift,\n JSXAttribute,\n JSXElement,\n JSXIdentifier,\n JSXMemberExpression,\n JSXNamespacedName,\n JSXSpreadAttribute,\n} from 'jscodeshift';\n\n/**\n * Rename a JSX element name if it is a JSXIdentifier.\n */\nexport const setNameIfJSXIdentifier = (\n elementName: JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined,\n newName: string,\n): JSXIdentifier | JSXNamespacedName | JSXMemberExpression | undefined => {\n if (elementName && elementName.type === 'JSXIdentifier') {\n return { ...elementName, name: newName };\n }\n return elementName;\n};\n\n/**\n * Check if a list of attributes contains a specific attribute by name.\n */\nexport const hasAttribute = (\n attributes: (JSXAttribute | JSXSpreadAttribute)[] | undefined,\n attributeName: string,\n): boolean => {\n return (\n Array.isArray(attributes) &&\n attributes.some(\n (attr): attr is JSXAttribute =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === attributeName,\n )\n );\n};\n\n/**\n * Check if a JSX element's openingElement has a specific attribute.\n */\nexport const hasAttributeOnElement = (\n element: JSXElement['openingElement'],\n attributeName: string,\n): boolean => {\n return hasAttribute(element.attributes, attributeName);\n};\n\n/**\n * Add specified attributes to a JSX element's openingElement if they are not already present.\n */\nexport const addAttributesIfMissing = (\n j: JSCodeshift,\n openingElement: JSXElement['openingElement'],\n attributesToAdd: { attribute: JSXAttribute; name: string }[],\n) => {\n if (!Array.isArray(openingElement.attributes)) return;\n const attrs = openingElement.attributes;\n attributesToAdd.forEach(({ attribute, name }) => {\n if (!hasAttributeOnElement(openingElement, name)) {\n attrs.push(attribute);\n }\n });\n};\n","import type { ASTPath, JSCodeshift, JSXAttribute, JSXElement, Node } from 'jscodeshift';\n\nexport interface ReporterOptions {\n jscodeshift: JSCodeshift;\n issues: string[];\n}\n\n/**\n * CodemodReporter is a utility class for reporting issues found during codemod transformations.\n * It provides methods to report issues related to JSX elements, props, and attributes.\n *\n * @example\n * ```typescript\n * const issues: string[] = [];\n * const reporter = createReporter(j, issues);\n *\n * // Report a deprecated prop\n * reporter.reportDeprecatedProp(buttonElement, 'flat', 'variant=\"text\"');\n *\n * // Report complex expression that needs review\n * reporter.reportAmbiguousExpression(element, 'size');\n *\n * // Auto-detect common issues\n * reporter.reportAttributeIssues(element);\n * ```\n */\nexport class CodemodReporter {\n private readonly j: JSCodeshift;\n private readonly issues: string[];\n\n constructor(options: ReporterOptions) {\n this.j = options.jscodeshift;\n this.issues = options.issues;\n }\n\n /**\n * Reports an issue with a JSX element\n */\n reportElement(element: JSXElement | ASTPath<JSXElement>, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(`Manual review required: <${componentName}> at line ${line} ${reason}.`);\n }\n\n /**\n * Reports an issue with a specific prop\n */\n reportProp(element: JSXElement | ASTPath<JSXElement>, propName: string, reason: string): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const line = this.getLineNumber(node);\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${reason}.`,\n );\n }\n\n /**\n * Reports an issue with a JSX attribute directly\n */\n reportAttribute(\n attr: JSXAttribute,\n element: JSXElement | ASTPath<JSXElement>,\n reason?: string,\n ): void {\n const node = this.getNode(element);\n const componentName = this.getComponentName(node);\n const propName = this.getAttributeName(attr);\n const line = this.getLineNumber(attr) || this.getLineNumber(node);\n\n const defaultReason = this.getAttributeReason(attr);\n const finalReason = reason || defaultReason;\n\n this.addIssue(\n `Manual review required: prop \"${propName}\" on <${componentName}> at line ${line} ${finalReason}.`,\n );\n }\n\n /**\n * Reports spread props on an element\n */\n reportSpreadProps(element: JSXElement | ASTPath<JSXElement>): void {\n this.reportElement(element, 'contains spread props that need manual review');\n }\n\n /**\n * Reports conflicting prop and children\n */\n reportPropWithChildren(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(\n element,\n propName,\n `conflicts with children - both \"${propName}\" prop and children are present`,\n );\n }\n\n /**\n * Reports unsupported prop value\n */\n reportUnsupportedValue(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n value: string,\n ): void {\n this.reportProp(element, propName, `has unsupported value \"${value}\"`);\n }\n\n /**\n * Reports ambiguous expression in prop\n */\n reportAmbiguousExpression(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'contains a complex expression that needs manual review');\n }\n\n /**\n * Reports ambiguous children (like dynamic icons)\n */\n reportAmbiguousChildren(element: JSXElement | ASTPath<JSXElement>, childType = 'content'): void {\n this.reportElement(element, `contains ambiguous ${childType} that needs manual review`);\n }\n\n /**\n * Reports deprecated prop usage\n */\n reportDeprecatedProp(\n element: JSXElement | ASTPath<JSXElement>,\n propName: string,\n alternative?: string,\n ): void {\n const suggestion = alternative ? ` Use ${alternative} instead` : '';\n this.reportProp(element, propName, `is deprecated${suggestion}`);\n }\n\n /**\n * Reports missing required prop\n */\n reportMissingRequiredProp(element: JSXElement | ASTPath<JSXElement>, propName: string): void {\n this.reportProp(element, propName, 'is required but missing');\n }\n\n /**\n * Reports conflicting props\n */\n reportConflictingProps(element: JSXElement | ASTPath<JSXElement>, propNames: string[]): void {\n const propList = propNames.map((name) => `\"${name}\"`).join(', ');\n this.reportElement(element, `has conflicting props: ${propList} cannot be used together`);\n }\n\n /**\n * Auto-detects and reports common attribute issues\n */\n reportAttributeIssues(element: JSXElement | ASTPath<JSXElement>): void {\n const node = this.getNode(element);\n const { attributes } = node.openingElement;\n\n if (!attributes) return;\n\n // Check for spread props\n if (attributes.some((attr) => attr.type === 'JSXSpreadAttribute')) {\n this.reportSpreadProps(element);\n }\n\n // Check for complex expressions in attributes\n attributes.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.value?.type === 'JSXExpressionContainer') {\n this.reportAttribute(attr, element);\n }\n });\n }\n\n // Private helper methods\n private getNode(element: JSXElement | ASTPath<JSXElement>): JSXElement {\n return 'node' in element ? element.node : element;\n }\n\n private getComponentName(node: JSXElement): string {\n const { name } = node.openingElement;\n if (name.type === 'JSXIdentifier') {\n return name.name;\n }\n // Handle JSXMemberExpression, JSXNamespacedName, etc.\n return this.j(name).toSource();\n }\n\n private getLineNumber(node: JSXElement | JSXAttribute | Node): string {\n return node.loc?.start.line?.toString() || 'unknown';\n }\n\n private getAttributeName(attr: JSXAttribute): string {\n if (attr.name.type === 'JSXIdentifier') {\n return attr.name.name;\n }\n return this.j(attr.name).toSource();\n }\n\n private getAttributeReason(attr: JSXAttribute): string {\n if (!attr.value) return 'has no value';\n\n if (attr.value.type === 'JSXExpressionContainer') {\n const expr = attr.value.expression;\n const expressionType = expr.type.replace('Expression', '').toLowerCase();\n\n // Show actual value for simple cases\n if (expr.type === 'Identifier' || expr.type === 'MemberExpression') {\n const valueText = this.j(expr).toSource();\n return `contains a ${expressionType} (${valueText})`;\n }\n\n return `contains a complex ${expressionType} expression`;\n }\n\n return 'needs manual review';\n }\n\n private addIssue(message: string): void {\n this.issues.push(message);\n }\n}\n\nexport const createReporter = (j: JSCodeshift, issues: string[]): CodemodReporter => {\n return new CodemodReporter({ jscodeshift: j, issues });\n};\n","import type { API, FileInfo, JSCodeshift, JSXIdentifier, Options } from 'jscodeshift';\n\nimport reportManualReview from '../../utils/reportManualReview';\nimport hasImport from '../helpers/hasImport';\nimport processIconChildren from '../helpers/iconUtils';\nimport {\n addAttributesIfMissing,\n hasAttributeOnElement,\n setNameIfJSXIdentifier,\n} from '../helpers/jsxElementUtils';\nimport { createReporter } from '../helpers/jsxReportingUtils';\n\nexport const parser = 'tsx';\n\ninterface LegacyProps {\n priority?: string;\n size?: string;\n type?: string;\n htmlType?: string;\n sentiment?: string;\n [key: string]: unknown;\n}\n\nconst priorityMapping: Record<string, Record<string, string>> = {\n accent: {\n primary: 'primary',\n secondary: 'secondary-neutral',\n tertiary: 'tertiary',\n },\n positive: {\n primary: 'primary',\n secondary: 'secondary-neutral',\n tertiary: 'secondary-neutral',\n },\n negative: {\n primary: 'primary',\n secondary: 'secondary',\n tertiary: 'secondary',\n },\n};\n\nconst sizeMap: Record<string, string> = {\n EXTRA_SMALL: 'xs',\n SMALL: 'sm',\n MEDIUM: 'md',\n LARGE: 'lg',\n EXTRA_LARGE: 'xl',\n xs: 'sm',\n sm: 'sm',\n md: 'md',\n lg: 'lg',\n xl: 'xl',\n};\n\nconst resolveSize = (size?: string): string | undefined => {\n if (!size) return size;\n const match = /^Size\\.(EXTRA_SMALL|SMALL|MEDIUM|LARGE|EXTRA_LARGE)$/u.exec(size);\n if (match) {\n return sizeMap[match[1]];\n }\n return sizeMap[size] || size;\n};\n\nconst resolvePriority = (type?: string, priority?: string): string | undefined => {\n if (type && priority) {\n return priorityMapping[type]?.[priority] || priority;\n }\n return priority;\n};\n\nconst resolveType = (type?: string, htmlType?: string): string | null => {\n if (htmlType) {\n return htmlType;\n }\n\n const legacyButtonTypes = [\n 'accent',\n 'negative',\n 'positive',\n 'primary',\n 'pay',\n 'secondary',\n 'danger',\n 'link',\n ];\n return type && legacyButtonTypes.includes(type) ? type : null;\n};\n\nconst convertEnumValue = (value?: string): string | undefined => {\n if (!value) return value;\n const strippedValue = value.replace(/^['\"]|['\"]$/gu, '');\n const enumMapping: Record<string, string> = {\n 'Priority.SECONDARY': 'secondary',\n 'Priority.PRIMARY': 'primary',\n 'Priority.TERTIARY': 'tertiary',\n 'ControlType.NEGATIVE': 'negative',\n 'ControlType.POSITIVE': 'positive',\n 'ControlType.ACCENT': 'accent',\n };\n return enumMapping[strippedValue] || strippedValue;\n};\n\n/**\n * This transform function modifies the Button and ActionButton components from the @transferwise/components library.\n * It updates the ActionButton component to use the Button component with specific attributes and mappings.\n * It also processes icon children and removes legacy props.\n *\n * @param {FileInfo} file - The file information object.\n * @param {API} api - The API object for jscodeshift.\n * @param {Options} options - The options object for jscodeshift.\n * @returns {string} - The transformed source code.\n */\nconst transformer = (file: FileInfo, api: API, options: Options) => {\n const j: JSCodeshift = api.jscodeshift;\n const root = j(file.source);\n const manualReviewIssues: string[] = [];\n\n // Create reporter instance\n const reporter = createReporter(j, manualReviewIssues);\n\n const { exists: hasButtonImport } = hasImport(root, '@transferwise/components', 'Button', j);\n const { exists: hasActionButtonImport, remove: removeActionButtonImport } = hasImport(\n root,\n '@transferwise/components',\n 'ActionButton',\n j,\n );\n\n const iconImports = new Set<string>();\n root.find(j.ImportDeclaration, { source: { value: '@transferwise/icons' } }).forEach((path) => {\n path.node.specifiers?.forEach((specifier) => {\n if (\n (specifier.type === 'ImportDefaultSpecifier' || specifier.type === 'ImportSpecifier') &&\n specifier.local\n ) {\n const localName = (specifier.local as { name: string }).name;\n iconImports.add(localName);\n }\n });\n });\n\n if (hasActionButtonImport) {\n root.findJSXElements('ActionButton').forEach((path) => {\n const { openingElement, closingElement } = path.node;\n\n openingElement.name = setNameIfJSXIdentifier(openingElement.name, 'Button')!;\n if (closingElement) {\n closingElement.name = setNameIfJSXIdentifier(closingElement.name, 'Button')!;\n }\n\n addAttributesIfMissing(j, openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n { attribute: j.jsxAttribute(j.jsxIdentifier('size'), j.literal('sm')), name: 'size' },\n ]);\n\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n\n const legacyPropNames = ['priority', 'text'];\n const legacyProps: LegacyProps = {};\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name && attr.name.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n reporter.reportAttribute(attr, path);\n }\n }\n }\n }\n });\n\n const hasTextProp = openingElement.attributes?.some(\n (attr) =>\n attr.type === 'JSXAttribute' &&\n attr.name.type === 'JSXIdentifier' &&\n attr.name.name === 'text',\n );\n const hasChildren = path.node.children?.some(\n (child) =>\n (child.type === 'JSXText' && child.value.trim() !== '') ||\n child.type === 'JSXElement' ||\n child.type === 'JSXExpressionContainer',\n );\n\n if (hasTextProp && hasChildren) {\n reporter.reportPropWithChildren(path, 'text');\n }\n\n (path.node.children || []).forEach((child) => {\n if (child.type === 'JSXExpressionContainer') {\n const expr = child.expression;\n if (\n expr.type === 'ConditionalExpression' ||\n expr.type === 'CallExpression' ||\n expr.type === 'Identifier' ||\n expr.type === 'MemberExpression'\n ) {\n reporter.reportAmbiguousChildren(path, 'icon');\n }\n }\n });\n });\n\n removeActionButtonImport();\n }\n\n if (hasButtonImport) {\n root.findJSXElements('Button').forEach((path) => {\n const { openingElement } = path.node;\n\n if (hasAttributeOnElement(openingElement, 'v2')) return;\n\n addAttributesIfMissing(j, openingElement, [\n { attribute: j.jsxAttribute(j.jsxIdentifier('v2')), name: 'v2' },\n ]);\n processIconChildren(j, path.node.children, iconImports, openingElement);\n\n const legacyProps: LegacyProps = {};\n const legacyPropNames = ['priority', 'size', 'type', 'htmlType', 'sentiment'];\n\n openingElement.attributes?.forEach((attr) => {\n if (attr.type === 'JSXAttribute' && attr.name && attr.name.type === 'JSXIdentifier') {\n const { name } = attr.name;\n if (legacyPropNames.includes(name)) {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n legacyProps[name] = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n legacyProps[name] = convertEnumValue(String(j(attr.value.expression).toSource()));\n }\n } else {\n legacyProps[name] = undefined;\n }\n }\n }\n });\n\n if (openingElement.attributes) {\n openingElement.attributes = openingElement.attributes.filter(\n (attr) =>\n !(\n attr.type === 'JSXAttribute' &&\n attr.name &&\n legacyPropNames.includes((attr.name as JSXIdentifier).name)\n ),\n );\n }\n\n if ('size' in legacyProps) {\n const rawValue = legacyProps.size;\n const resolved = resolveSize(rawValue);\n const supportedSizes = ['xs', 'sm', 'md', 'lg', 'xl'];\n\n if (\n typeof rawValue === 'string' &&\n typeof resolved === 'string' &&\n supportedSizes.includes(resolved)\n ) {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('size'), j.literal(resolved)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'size', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'size');\n }\n }\n\n if ('priority' in legacyProps) {\n const rawValue = legacyProps.priority;\n const converted = convertEnumValue(rawValue);\n const mapped = resolvePriority(legacyProps.type, converted);\n const supportedPriorities = ['primary', 'secondary', 'tertiary', 'secondary-neutral'];\n\n if (\n typeof rawValue === 'string' &&\n typeof mapped === 'string' &&\n supportedPriorities.includes(mapped)\n ) {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('priority'), j.literal(mapped)),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'priority', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'priority');\n }\n }\n\n if ('type' in legacyProps || 'htmlType' in legacyProps) {\n const rawType = legacyProps.type;\n const rawHtmlType = legacyProps.htmlType;\n\n const resolvedType =\n typeof rawType === 'string'\n ? rawType\n : rawType && typeof rawType === 'object'\n ? convertEnumValue(j(rawType).toSource())\n : undefined;\n\n const resolved = resolveType(resolvedType, rawHtmlType);\n\n const supportedTypes = [\n 'accent',\n 'negative',\n 'positive',\n 'primary',\n 'pay',\n 'secondary',\n 'danger',\n 'link',\n 'submit',\n 'button',\n 'reset',\n ];\n\n if (typeof resolved === 'string' && supportedTypes.includes(resolved)) {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('type'), j.literal(resolved)),\n );\n\n if (resolved === 'negative') {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n }\n } else if (typeof rawType === 'string' || typeof rawHtmlType === 'string') {\n reporter.reportUnsupportedValue(path, 'type', rawType ?? rawHtmlType ?? '');\n } else if (rawType !== undefined || rawHtmlType !== undefined) {\n reporter.reportAmbiguousExpression(path, 'type');\n }\n }\n\n if ('sentiment' in legacyProps) {\n const rawValue = legacyProps.sentiment;\n if (rawValue === 'negative') {\n openingElement.attributes?.push(\n j.jsxAttribute(j.jsxIdentifier('sentiment'), j.literal('negative')),\n );\n } else if (typeof rawValue === 'string') {\n reporter.reportUnsupportedValue(path, 'sentiment', rawValue);\n } else if (rawValue !== undefined) {\n reporter.reportAmbiguousExpression(path, 'sentiment');\n }\n }\n\n let asIndex = -1;\n let asValue: string | null = null;\n let hrefExists = false;\n let asAmbiguous = false;\n let hrefAmbiguous = false;\n\n openingElement.attributes?.forEach((attr, index) => {\n if (attr.type === 'JSXAttribute' && attr.name) {\n if (attr.name.name === 'as') {\n if (attr.value) {\n if (attr.value.type === 'StringLiteral') {\n asValue = attr.value.value;\n } else if (attr.value.type === 'JSXExpressionContainer') {\n asAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n asIndex = index;\n }\n\n if (attr.name.name === 'href') {\n hrefExists = true;\n if (attr.value && attr.value.type !== 'StringLiteral') {\n hrefAmbiguous = true;\n reporter.reportAttribute(attr, path);\n }\n }\n }\n });\n\n if (asValue && asValue !== 'a') {\n reporter.reportUnsupportedValue(path, 'as', asValue);\n }\n\n if (asValue === 'a') {\n if (asIndex !== -1) {\n openingElement.attributes = openingElement.attributes?.filter(\n (_, idx) => idx !== asIndex,\n );\n }\n if (!hrefExists) {\n openingElement.attributes = [\n ...(openingElement.attributes ?? []),\n j.jsxAttribute(j.jsxIdentifier('href'), j.literal('#')),\n ];\n }\n }\n\n if ((openingElement.attributes ?? []).some((attr) => attr.type === 'JSXSpreadAttribute')) {\n reporter.reportSpreadProps(path);\n }\n });\n }\n\n if (manualReviewIssues.length > 0) {\n manualReviewIssues.forEach(async (issue) => {\n await reportManualReview(file.path, issue);\n });\n }\n\n return root.toSource();\n};\n\nexport default transformer;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,24 +1,28 @@
1
1
  {
2
2
  "name": "@wise/wds-codemods",
3
- "version": "0.0.1-experimental-cbae00f",
3
+ "version": "0.0.1-experimental-926a862",
4
4
  "license": "UNLICENSED",
5
5
  "author": "Wise Payments Ltd.",
6
- "type": "module",
7
6
  "repository": {
8
7
  "fullname": "transferwise/neptune-tokens",
9
8
  "type": "git",
10
9
  "url": "git+https://github.com/transferwise/neptune-tokens.git"
11
10
  },
12
11
  "description": "Codemods for Wise Design System",
13
- "main": "dist/index.js",
12
+ "main": "./dist/index.js",
14
13
  "bin": {
15
14
  "wds-codemods": "dist/index.js"
16
15
  },
16
+ "files": [
17
+ "dist/",
18
+ "README.md",
19
+ "package.json"
20
+ ],
17
21
  "scripts": {
18
- "build": "bash scripts/build.sh",
22
+ "build": "tsdown",
19
23
  "changeset": "changeset",
20
24
  "lint": "pnpm run lint:js+ts && pnpm run lint:format",
21
- "lint:js+ts": "eslint '**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}'",
25
+ "lint:js+ts": "eslint '**/*.{js,jsx,mjs,cjs,ts,tsx,mts,cts}' --concurrency=auto",
22
26
  "lint:format": "prettier \"**/*\" --check --ignore-unknown",
23
27
  "lint:types": "tsc --noEmit",
24
28
  "lint:fix": "pnpm run lint:fix:js+ts && pnpm run lint:fix:format",
@@ -30,7 +34,7 @@
30
34
  "test:watch": "jest --watch"
31
35
  },
32
36
  "dependencies": {
33
- "@inquirer/prompts": "^7.8.4",
37
+ "@inquirer/prompts": "^7.8.3",
34
38
  "jscodeshift": "^17.3"
35
39
  },
36
40
  "devDependencies": {
@@ -43,25 +47,26 @@
43
47
  "@commitlint/cli": "^19.8.1",
44
48
  "@commitlint/config-conventional": "^19.8.1",
45
49
  "@inquirer/testing": "^2.1.49",
46
- "@jest/globals": "^29.7.0",
47
- "@types/jest": "^29.5.14",
50
+ "@jest/globals": "^30.0.5",
51
+ "@types/jest": "^30.0.0",
48
52
  "@types/jscodeshift": "^17.3.0",
49
- "@types/node": "^22.17.2",
53
+ "@types/node": "^24.3.0",
50
54
  "@types/semver": "^7.7.0",
51
- "@wise/eslint-config": "^12.3.0",
52
- "babel-jest": "^29.7.0",
55
+ "@wise/eslint-config": "^13.1.0",
56
+ "babel-jest": "^30.0.5",
53
57
  "babel-plugin-transform-import-meta": "^2.3.3",
58
+ "eslint": "^9.34.0",
54
59
  "husky": "^9.1.7",
55
- "jest": "^29.7.0",
60
+ "jest": "^30.0.5",
56
61
  "prettier": "^3.6.2",
57
62
  "semver": "^7.7.2",
58
63
  "ts-jest": "^29.4.1",
59
64
  "ts-node": "^10.9.2",
60
- "tsup": "^8.5.0",
65
+ "tsdown": "^0.14.1",
61
66
  "typescript": "^5.9.2"
62
67
  },
63
68
  "publishConfig": {
64
69
  "access": "public"
65
70
  },
66
- "packageManager": "pnpm@9.15.9+sha512.68046141893c66fad01c079231128e9afb89ef87e2691d69e4d40eee228988295fd4682181bae55b58418c3a253bde65a505ec7c5f9403ece5cc3cd37dcf2531"
71
+ "packageManager": "pnpm@10.15.0+sha256.84c19e788d7d7ee248e4a6b7152f8ebba0f4fe7380a5f443ca17d76c030052d2"
67
72
  }
@@ -1,5 +0,0 @@
1
- ---
2
- '@wise/wds-codemods': patch
3
- ---
4
-
5
- NPM release setup
@@ -1,13 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
3
- "changelog": ["@changesets/changelog-github", { "repo": "transferwise/wds-codemods" }],
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "public",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "minor",
10
- "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
11
- "onlyUpdatePeerDependentsWhenOutOfRange": true
12
- }
13
- }
@@ -1,128 +0,0 @@
1
- ---
2
- '@wise/wds-codemods': major
3
- ---
4
-
5
- # ๐ŸŽ‰ @wise/wds-codemods@1.0.0 - Initial Release
6
-
7
- Welcome to the first major release of WDS Codemods! This comprehensive toolkit provides automated migration support for Wise Design System components, making it easy to upgrade your codebase to the latest component versions.
8
-
9
- ## โœจ Core Features
10
-
11
- ### ๐Ÿ”ง Transform Engine
12
-
13
- - **Interactive CLI**: Choose transforms and configure options with an intuitive command-line interface
14
- - **Dry Run Mode**: Preview changes before applying them to your codebase
15
- - **Monorepo Support**: Built-in support for monorepo package structures with automatic package detection
16
- - **Smart Package Detection**: Automatically detects package versions in both `package.json` dependencies and `node_modules`
17
- - **Comprehensive Reporting**: Generates detailed reports for manual review items that require developer attention
18
-
19
- ### ๐ŸŽฏ Button Component Transform
20
-
21
- - **ActionButton Migration**: Automatically converts deprecated `ActionButton` components to modern `Button` with `v2` prop
22
- - **Legacy Prop Migration**: Transforms legacy props (`priority`, `size`, `type`, `htmlType`, `sentiment`) to new API
23
- - **Enum Value Conversion**: Converts enum values (e.g., `Priority.PRIMARY`, `Size.LARGE`) to string literals
24
- - **Icon Integration**: Intelligently processes icon children and converts them to `addonStart`/`addonEnd` props
25
- - **Link Button Handling**: Properly migrates `as="a"` usage with automatic `href` management
26
- - **Smart Size Mapping**: Maps legacy size values to new design tokens (`xs`, `sm`, `md`, `lg`, `xl`)
27
-
28
- ### ๐Ÿ›ก๏ธ Robust Validation & Safety
29
-
30
- - **Package Version Validation**: Ensures transforms only run when target packages are present and meet version requirements
31
- - **TypeScript & JSX Support**: Full support for TypeScript and JSX syntax parsing
32
- - **Expression Analysis**: Handles complex expressions, conditionals, and dynamic values with appropriate fallbacks
33
- - **Gitignore Integration**: Respects `.gitignore` patterns to avoid processing unnecessary files
34
- - **Caching System**: Intelligent caching for package version checks to improve performance
35
-
36
- ### ๐Ÿ“Š Advanced Reporting
37
-
38
- - **Manual Review Detection**: Identifies code patterns that require human attention
39
- - **Line-by-Line Reporting**: Precise location reporting for manual review items
40
- - **Issue Classification**: Categorizes issues by type (deprecated props, unsupported values, ambiguous expressions)
41
- - **Batch Processing**: Handles multiple files and provides comprehensive summary reports
42
-
43
- ## ๐Ÿš€ Usage Examples
44
-
45
- ### Basic Usage
46
-
47
- ```bash
48
- npx @wise/wds-codemods
49
- ```
50
-
51
- ### Advanced Usage
52
-
53
- ```bash
54
- # Run specific transform on a directory
55
- npx @wise/wds-codemods button ./src --dry
56
-
57
- # Target monorepo packages
58
- npx @wise/wds-codemods button ./packages --monorepo
59
-
60
- # Custom ignore patterns
61
- npx @wise/wds-codemods button ./src --ignore-pattern "**/*.test.tsx,**/stories/**"
62
- ```
63
-
64
- ## ๐Ÿ“‹ Supported Transforms
65
-
66
- ### Button Transform (`button`)
67
-
68
- Migrates Button and ActionButton components from `@transferwise/components` v46.5.0+
69
-
70
- **Transformations include:**
71
-
72
- - โœ… `ActionButton` โ†’ `Button` with `v2` prop
73
- - โœ… Legacy prop migrations (`priority`, `size`, `type`, etc.)
74
- - โœ… Enum value conversions
75
- - โœ… Icon children processing
76
- - โœ… Link button handling (`as="a"` โ†’ proper href management)
77
- - โœ… Sentiment mapping (`type="negative"` โ†’ `sentiment="negative"`)
78
-
79
- ## ๐Ÿ—๏ธ Architecture Highlights
80
-
81
- ### Modular Design
82
-
83
- - **Transform System**: Extensible architecture for adding new component transforms
84
- - **Helper Utilities**: Reusable utilities for JSX manipulation, reporting, and validation
85
- - **Package Detection**: Multi-strategy package version detection (dependencies + node_modules)
86
- - **Test Infrastructure**: Comprehensive testing utilities for transform development
87
-
88
- ### Developer Experience
89
-
90
- - **Type Safety**: Full TypeScript support with proper type definitions
91
- - **Error Handling**: Graceful error handling with helpful error messages
92
- - **Debug Support**: Extensive debug logging for troubleshooting
93
- - **Extensible**: Easy to add new transforms and extend existing functionality
94
-
95
- ## ๐Ÿงช Quality Assurance
96
-
97
- This release includes:
98
-
99
- - โœ… **100% Test Coverage** for core utilities and transforms
100
- - โœ… **End-to-End Testing** with real-world code examples
101
- - โœ… **Edge Case Handling** for complex expressions and unusual patterns
102
- - โœ… **Performance Optimization** with intelligent caching and batching
103
- - โœ… **Memory Management** for large codebases
104
-
105
- ## ๐Ÿ”ฎ What's Next?
106
-
107
- This foundation enables:
108
-
109
- - ๐ŸŽฏ Additional component transforms (Forms, Navigation, etc.)
110
- - ๐Ÿš€ Enhanced reporting and analytics
111
- - ๐Ÿ”ง IDE integrations and tooling
112
- - ๐Ÿ“ฑ Support for additional package managers
113
- - ๐ŸŒ Community contributions and extensibility
114
-
115
- ## ๐Ÿ™ Getting Started
116
-
117
- 1. Install the package: `npm install -D @wise/wds-codemods`
118
- 2. Run your first transform: `npx @wise/wds-codemods`
119
- 3. Review the generated `codemod-report.txt` for any manual review items
120
- 4. Commit your changes and enjoy your modernized codebase!
121
-
122
- ---
123
-
124
- **Breaking Changes**: This is the initial release, so no breaking changes from previous versions.
125
-
126
- **Migration Guide**: See our documentation for detailed migration examples and best practices.
127
-
128
- Ready to modernize your Wise Design System components? Let's go! ๐Ÿš€
@@ -1 +0,0 @@
1
- * @transferwise/design-system-web
@@ -1,49 +0,0 @@
1
- name: 'Bootstrap'
2
- description: 'Set up Node.js and install dependencies'
3
-
4
- inputs:
5
- github-token:
6
- description: 'GitHub token for authentication'
7
- required: true
8
- npm-token-automation:
9
- description: 'NPM token for authentication'
10
- required: false
11
-
12
- runs:
13
- using: 'composite'
14
- steps:
15
- - name: Setup Node.js
16
- uses: actions/setup-node@v4
17
- with:
18
- node-version-file: '.nvmrc'
19
- registry-url: 'https://registry.npmjs.org'
20
-
21
- - name: Setup pnpm
22
- uses: pnpm/action-setup@v4
23
-
24
- - name: Configure npm registry
25
- shell: bash
26
- run: |
27
- echo "registry=https://registry.npmjs.org/" > .npmrc
28
- echo "//registry.npmjs.org/:_authToken=${{ inputs.npm-token-automation }}" >> .npmrc
29
- env:
30
- NODE_AUTH_TOKEN: ${{ inputs.npm-token-automation }}
31
-
32
- - name: Get pnpm store directory
33
- shell: bash
34
- run: |
35
- echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
36
-
37
- - name: Setup pnpm cache
38
- uses: actions/cache@v4
39
- with:
40
- path: ${{ env.STORE_PATH }}
41
- key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
42
- restore-keys: |
43
- ${{ runner.os }}-pnpm-store-
44
-
45
- - name: Install dependencies
46
- shell: bash
47
- run: pnpm install --frozen-lockfile
48
- env:
49
- NODE_AUTH_TOKEN: ${{ inputs.npm-token-automation }}
@@ -1,27 +0,0 @@
1
- name: Commitlint
2
- description: 'Lint all commit messages for the project'
3
-
4
- inputs:
5
- github-token:
6
- required: true
7
- description: 'secrets.GITHUB_TOKEN'
8
-
9
- runs:
10
- using: composite
11
- steps:
12
- - name: ๐Ÿ” Mark repo directory as safe for git # https://github.blog/2022-04-12-git-security-vulnerability-announced/
13
- run: git config --global --add safe.directory $GITHUB_WORKSPACE
14
- shell: bash
15
-
16
- - name: ๐Ÿ› ๏ธ Bootstrap dependencies
17
- uses: ./.github/actions/bootstrap
18
- with:
19
- github-token: ${{ inputs.github-token }}
20
-
21
- - name: Fetch full commit history
22
- run: git fetch --unshallow
23
- shell: bash
24
-
25
- - name: Run Commitlint
26
- run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose
27
- shell: bash
@@ -1,23 +0,0 @@
1
- name: Test
2
- description: 'Run all tests for the project'
3
-
4
- inputs:
5
- github-token:
6
- required: true
7
- description: 'secrets.GITHUB_TOKEN'
8
-
9
- runs:
10
- using: composite
11
- steps:
12
- - name: ๐Ÿ” Mark repo directory as safe for git # https://github.blog/2022-04-12-git-security-vulnerability-announced/
13
- run: git config --global --add safe.directory $GITHUB_WORKSPACE
14
- shell: bash
15
-
16
- - name: ๐Ÿ› ๏ธ Bootstrap dependencies
17
- uses: ./.github/actions/bootstrap
18
- with:
19
- github-token: ${{ inputs.github-token }}
20
-
21
- - name: ๐Ÿงช Run tests
22
- run: pnpm run test
23
- shell: bash