@wise/wds-codemods 0.0.1-experimental-c483d40 → 0.0.1-experimental-30d1a63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,73 +1,162 @@
1
1
  #!/usr/bin/env node
2
- const require_reportManualReview = require('./reportManualReview-CDdJazd3.js');
3
- const node_fs_promises = require_reportManualReview.__toESM(require("node:fs/promises"));
2
+ const require_reportManualReview = require('./reportManualReview-DQ00-OKx.js');
4
3
  const node_child_process = require_reportManualReview.__toESM(require("node:child_process"));
4
+ const node_fs_promises = require_reportManualReview.__toESM(require("node:fs/promises"));
5
5
  const node_path = require_reportManualReview.__toESM(require("node:path"));
6
6
  const node_url = require_reportManualReview.__toESM(require("node:url"));
7
- const __inquirer_prompts = require_reportManualReview.__toESM(require("@inquirer/prompts"));
8
7
  const node_fs = require_reportManualReview.__toESM(require("node:fs"));
8
+ const __inquirer_prompts = require_reportManualReview.__toESM(require("@inquirer/prompts"));
9
9
 
10
10
  //#region src/utils/getOptions.ts
11
- async function getOptions(transformFiles) {
12
- const args = process.argv.slice(2);
13
- if (args.length > 0) {
14
- const [transformFile$1, targetPath$1] = args;
15
- const dry$1 = args.includes("--dry") || args.includes("--dry-run");
16
- const print$1 = args.includes("--print");
17
- const ignorePatternIndex = args.findIndex((arg) => arg === "--ignore-pattern");
18
- let ignorePattern$1;
19
- if (ignorePatternIndex !== -1 && args.length > ignorePatternIndex + 1) ignorePattern$1 = args[ignorePatternIndex + 1];
20
- const gitignore$1 = args.includes("--gitignore");
21
- const noGitignore = args.includes("--no-gitignore");
22
- if (!transformFile$1 || !transformFiles.includes(transformFile$1)) throw new Error("Invalid transform file specified.");
23
- if (!targetPath$1) throw new Error("Target path cannot be empty.");
24
- const useGitignore = !!(gitignore$1 || !gitignore$1 && !noGitignore);
25
- return {
26
- transformFile: transformFile$1,
27
- targetPath: targetPath$1,
28
- dry: dry$1,
29
- print: print$1,
30
- ignorePattern: ignorePattern$1,
31
- gitignore: useGitignore
32
- };
11
+ /**
12
+ * if args are provided via CLI, log them to the console in
13
+ * a formatted way matching Inquirer's style
14
+ */
15
+ const logToInquirer = (label, value) => {
16
+ const checkmark = "\x1B[32m✔\x1B[0m";
17
+ const boldLabel = `\x1b[1m${label}\x1b[0m`;
18
+ const greenValue = `\x1b[32m${value}\x1b[0m`;
19
+ console.info(`${checkmark} ${boldLabel} ${greenValue}`);
20
+ };
21
+ /**
22
+ * Lets user pick from available packages to run the codemod on
23
+ */
24
+ const queryPackages = async (packages) => {
25
+ const message = "Path to run codemod on:";
26
+ const nonRootPackages = packages.filter((pkg) => pkg !== ".");
27
+ if (packages.length === 1 && nonRootPackages.length === 0) {
28
+ logToInquirer(message, packages[0]);
29
+ return packages;
30
+ }
31
+ if (nonRootPackages.length >= 1) return (0, __inquirer_prompts.checkbox)({
32
+ required: true,
33
+ message: "Select packages to transform:",
34
+ choices: nonRootPackages.map((file) => ({
35
+ name: file,
36
+ value: file,
37
+ checked: true
38
+ }))
39
+ });
40
+ };
41
+ /**
42
+ * Determine user choice between CLI arg and Inquirer prompt: codemod
43
+ */
44
+ const determineTransformer = async ({ candidate, transformFiles }) => {
45
+ const codemodMessage = "Select codemod to run:";
46
+ if (candidate && transformFiles.includes(candidate)) {
47
+ logToInquirer(codemodMessage, candidate);
48
+ return candidate;
33
49
  }
34
- const transformFile = await (0, __inquirer_prompts.select)({
35
- message: "Select a codemod transform to run:",
50
+ return (0, __inquirer_prompts.select)({
51
+ message: codemodMessage,
36
52
  choices: transformFiles.map((file) => ({
37
53
  name: file,
38
54
  value: file
39
55
  }))
40
56
  });
41
- const targetPath = await (0, __inquirer_prompts.input)({
42
- message: "Enter the target directory or file path to run codemod on:",
43
- validate: (value) => value.trim() !== "" || "Target path cannot be empty"
44
- });
45
- const dry = await (0, __inquirer_prompts.confirm)({
46
- message: "Run in dry mode (no changes written to files)?",
47
- default: true
57
+ };
58
+ /**
59
+ * Determine user choice between CLI arg and Inquirer prompt: paths/packages to process
60
+ */
61
+ const determinePaths = async ({ candidate, root, packages }) => {
62
+ const targetPaths = [];
63
+ if (candidate && (0, node_fs.existsSync)((0, node_path.join)(root, candidate))) {
64
+ logToInquirer("Path to run codemod on", candidate);
65
+ targetPaths.push(candidate);
66
+ }
67
+ if (!targetPaths.length) {
68
+ const packagesToProcess = await queryPackages(packages);
69
+ targetPaths.push(...packagesToProcess ?? []);
70
+ }
71
+ return targetPaths;
72
+ };
73
+ /**
74
+ * Determine user choice between CLI arg and Inquirer prompt: dry mode
75
+ */
76
+ const determineIsDryMode = async (args) => {
77
+ const message = "Run in dry mode (no changes written to files)?";
78
+ if (args.includes("--dry") || args.includes("--dry-run")) {
79
+ logToInquirer(message, "Yes");
80
+ return true;
81
+ }
82
+ return (0, __inquirer_prompts.confirm)({
83
+ message,
84
+ default: false
48
85
  });
49
- const print = await (0, __inquirer_prompts.confirm)({
50
- message: "Print transformed source to console?",
86
+ };
87
+ /**
88
+ * Determine user choice between CLI arg and Inquirer prompt: print to CLI
89
+ */
90
+ const determineIsPrint = async (args) => {
91
+ const message = "Print transformed source to console?";
92
+ if (args.includes("--print")) {
93
+ logToInquirer(message, "Yes");
94
+ return true;
95
+ }
96
+ return (0, __inquirer_prompts.confirm)({
97
+ message,
51
98
  default: false
52
99
  });
53
- const ignorePattern = await (0, __inquirer_prompts.input)({
54
- message: "Enter ignore pattern(s) (comma separated) or leave empty:",
55
- validate: (value) => true
100
+ };
101
+ /**
102
+ * Determine user choice between CLI arg and Inquirer prompt: ignore patterns
103
+ */
104
+ const determineIgnorePatterns = async (args) => {
105
+ const message = "Enter ignore pattern(s) (comma separated) or leave empty:";
106
+ const ignorePatternIndex = args.findIndex((arg) => arg === "--ignore-pattern");
107
+ let ignorePattern;
108
+ if (ignorePatternIndex !== -1 && args.length > ignorePatternIndex + 1) ignorePattern = args[ignorePatternIndex + 1];
109
+ if (ignorePattern) {
110
+ logToInquirer(message, ignorePattern);
111
+ return ignorePattern;
112
+ }
113
+ return (0, __inquirer_prompts.input)({
114
+ message,
115
+ validate: () => true
56
116
  });
57
- const gitignore = await (0, __inquirer_prompts.confirm)({
58
- message: "Respect .gitignore files?",
117
+ };
118
+ /**
119
+ * Determine user choice between CLI arg and Inquirer prompt: gitignore
120
+ */
121
+ const determineGitIgnore = async (args) => {
122
+ const message = "Respect .gitignore files?";
123
+ if (args.includes("--gitignore")) {
124
+ logToInquirer(message, "Yes");
125
+ return true;
126
+ }
127
+ if (args.includes("--no-gitignore")) {
128
+ logToInquirer(message, "No");
129
+ return false;
130
+ }
131
+ return (0, __inquirer_prompts.confirm)({
132
+ message,
59
133
  default: true
60
134
  });
135
+ };
136
+ async function getOptions({ transformFiles, packages, root }) {
137
+ const args = process.argv.slice(2);
138
+ const transformFile = await determineTransformer({
139
+ candidate: args[0],
140
+ transformFiles
141
+ });
142
+ const targetPaths = await determinePaths({
143
+ candidate: args[1],
144
+ packages,
145
+ root
146
+ });
147
+ const isDry = await determineIsDryMode(args);
148
+ const isPrint = await determineIsPrint(args);
149
+ const ignorePatterns = await determineIgnorePatterns(args);
150
+ const useGitIgnore = await determineGitIgnore(args);
61
151
  return {
62
152
  transformFile,
63
- targetPath,
64
- dry,
65
- print,
66
- ignorePattern,
67
- gitignore
153
+ targetPaths,
154
+ isDry,
155
+ isPrint,
156
+ ignorePatterns,
157
+ useGitIgnore
68
158
  };
69
159
  }
70
- var getOptions_default = getOptions;
71
160
 
72
161
  //#endregion
73
162
  //#region src/utils/loadTransformModules.ts
@@ -88,50 +177,108 @@ async function loadTransformModules(transformsDir) {
88
177
  transformFiles
89
178
  };
90
179
  }
91
- var loadTransformModules_default = loadTransformModules;
180
+
181
+ //#endregion
182
+ //#region src/utils/repository.ts
183
+ /**
184
+ * Finds the root of the project by looking for the `.git` directory.
185
+ */
186
+ function findProjectRoot() {
187
+ try {
188
+ const gitRoot = (0, node_child_process.execSync)("git rev-parse --show-toplevel", {
189
+ cwd: process.cwd(),
190
+ encoding: "utf8",
191
+ stdio: [
192
+ "ignore",
193
+ "pipe",
194
+ "ignore"
195
+ ]
196
+ }).trim();
197
+ return gitRoot && (0, node_fs.existsSync)(gitRoot) ? gitRoot : "";
198
+ } catch {
199
+ return "";
200
+ }
201
+ }
202
+ /**
203
+ * Quick and dirty way of determining package roots based on
204
+ * the presence of `package.json` files and them optimistically
205
+ * containing a `@transferwise/components` string.
206
+ * */
207
+ function findPackages() {
208
+ try {
209
+ const packages = (0, node_child_process.execSync)([
210
+ "find ./",
211
+ "-type f",
212
+ "-name \"package.json\"",
213
+ "-not -path \"*/node_modules/*\"",
214
+ "|",
215
+ "xargs grep -l \"@transferwise/components\""
216
+ ].join(" "), {
217
+ cwd: findProjectRoot(),
218
+ encoding: "utf8"
219
+ }).trim().split("\n").map(node_path.default.dirname);
220
+ console.log(packages);
221
+ if (packages.length === 0) throw new Error();
222
+ return packages;
223
+ } catch {
224
+ throw new Error("No suitable package roots found in the repository.");
225
+ }
226
+ }
92
227
 
93
228
  //#endregion
94
229
  //#region src/runCodemod.ts
95
230
  const currentFilePath = (0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
96
231
  const currentDirPath = node_path.default.dirname(currentFilePath);
232
+ const resetReportFile = async (reportPath) => {
233
+ try {
234
+ await node_fs_promises.default.access(reportPath);
235
+ await node_fs_promises.default.rm(reportPath);
236
+ console.debug(`Removed existing report file: ${reportPath}`);
237
+ } catch {
238
+ console.debug(`No existing report file to remove: ${reportPath}`);
239
+ }
240
+ };
241
+ const summariseReportFile = async (reportPath) => {
242
+ try {
243
+ const reportContent = await node_fs_promises.default.readFile(reportPath, "utf8");
244
+ const lines = reportContent.split("\n").filter(Boolean);
245
+ if (lines.length) console.log(`\n⚠️ ${lines.length} manual review${lines.length > 1 ? "s are" : " is"} required. See ${reportPath} for details.`);
246
+ else console.debug(`Report file exists but is empty: ${reportPath}`);
247
+ } catch {
248
+ console.debug(`No report file generated - no manual reviews needed`);
249
+ }
250
+ };
97
251
  async function runCodemod(transformsDir) {
98
252
  try {
253
+ const packages = findPackages();
254
+ const reportPath = node_path.default.resolve(process.cwd(), "codemod-report.txt");
99
255
  const resolvedTransformsDir = transformsDir ?? node_path.default.resolve(currentDirPath, "../dist/transforms");
100
256
  console.debug(`Resolved transforms directory: ${resolvedTransformsDir}`);
101
- const { transformFiles } = await loadTransformModules_default(resolvedTransformsDir);
257
+ await resetReportFile(reportPath);
258
+ const { transformFiles } = await loadTransformModules(resolvedTransformsDir);
102
259
  if (transformFiles.length === 0) throw new Error(`No transform scripts found in directory: ${resolvedTransformsDir}`);
103
- const resolvedTransformFiles = await Promise.all(transformFiles);
104
- const options = await getOptions_default(resolvedTransformFiles);
260
+ const options = await getOptions({
261
+ packages,
262
+ root: findProjectRoot(),
263
+ transformFiles: await Promise.all(transformFiles)
264
+ });
105
265
  const codemodPath = node_path.default.resolve(resolvedTransformsDir, `${options.transformFile}.js`);
106
266
  console.debug(`Resolved codemod path: ${codemodPath}`);
107
- const args = [
108
- "-t",
109
- codemodPath,
110
- options.targetPath,
111
- options.dry ? "--dry" : "",
112
- options.print ? "--print" : "",
113
- options.ignorePattern ? options.ignorePattern.split(",").map((pattern) => `--ignore-pattern=${pattern.trim()}`).join(" ") : "",
114
- options.gitignore ? "--gitignore" : ""
115
- ].filter(Boolean);
116
- const command = `npx jscodeshift ${args.join(" ")}`;
117
- console.debug(`Running: ${command}`);
118
- const reportPath = node_path.default.resolve(process.cwd(), "codemod-report.txt");
119
- try {
120
- await node_fs_promises.default.access(reportPath);
121
- await node_fs_promises.default.rm(reportPath);
122
- console.debug(`Removed existing report file: ${reportPath}`);
123
- } catch {
124
- console.debug(`No existing report file to remove: ${reportPath}`);
125
- }
126
- (0, node_child_process.execSync)(command, { stdio: "inherit" });
127
- try {
128
- const reportContent = await node_fs_promises.default.readFile(reportPath, "utf8");
129
- const lines = reportContent.split("\n").filter(Boolean);
130
- if (lines.length) console.log(`\n⚠️ ${lines.length} manual review${lines.length > 1 ? "s are" : " is"} required. See ${reportPath} for details.`);
131
- else console.debug(`Report file exists but is empty: ${reportPath}`);
132
- } catch {
133
- console.debug(`No report file generated - no manual reviews needed`);
134
- }
267
+ options.targetPaths.map((targetPath) => {
268
+ const args = [
269
+ "-t",
270
+ codemodPath,
271
+ targetPath,
272
+ options.isDry ? "--dry" : "",
273
+ options.isPrint ? "--print" : "",
274
+ options.ignorePatterns ? options.ignorePatterns.split(",").map((pattern) => `--ignore-pattern=${pattern.trim()}`).join(" ") : "",
275
+ options.useGitIgnore ? "--gitignore" : ""
276
+ ].filter(Boolean);
277
+ const command = `npx jscodeshift ${args.join(" ")}`;
278
+ console.debug(`Running: ${command}`);
279
+ return (0, node_child_process.execSync)(command, { stdio: "inherit" });
280
+ });
281
+ await summariseReportFile(reportPath);
135
282
  } catch (error) {
136
283
  if (error instanceof Error) console.error("Error running codemod:", error.message);
137
284
  else console.error("Error running codemod:", error);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["transformFile","targetPath","dry","print","ignorePattern: string | undefined","gitignore","transformModules: Record<string, unknown>","fs","path","path","loadTransformModules","getOptions","fs","error: unknown"],"sources":["../src/utils/getOptions.ts","../src/utils/loadTransformModules.ts","../src/runCodemod.ts","../src/index.ts"],"sourcesContent":["import { confirm, input, select as list } from '@inquirer/prompts';\n\nasync function getOptions(transformFiles: string[]) {\n const args = process.argv.slice(2);\n if (args.length > 0) {\n const [transformFile, targetPath] = args;\n const dry = args.includes('--dry') || args.includes('--dry-run');\n const print = args.includes('--print');\n const ignorePatternIndex = args.findIndex((arg) => arg === '--ignore-pattern');\n let ignorePattern: string | undefined;\n if (ignorePatternIndex !== -1 && args.length > ignorePatternIndex + 1) {\n ignorePattern = args[ignorePatternIndex + 1];\n }\n const gitignore = args.includes('--gitignore');\n const noGitignore = args.includes('--no-gitignore');\n\n if (!transformFile || !transformFiles.includes(transformFile)) {\n throw new Error('Invalid transform file specified.');\n }\n if (!targetPath) {\n throw new Error('Target path cannot be empty.');\n }\n\n // If both --gitignore and --no-gitignore are specified, prioritize --gitignore\n const useGitignore = !!(gitignore || (!gitignore && !noGitignore));\n\n return { transformFile, targetPath, dry, print, ignorePattern, gitignore: useGitignore };\n }\n\n const transformFile = await list({\n message: 'Select a codemod transform to run:',\n choices: transformFiles.map((file) => ({ name: file, value: file })),\n });\n\n const targetPath = await input({\n message: 'Enter the target directory or file path to run codemod on:',\n validate: (value) => value.trim() !== '' || 'Target path cannot be empty',\n });\n\n const dry = await confirm({\n message: 'Run in dry mode (no changes written to files)?',\n default: true,\n });\n\n const print = await confirm({\n message: 'Print transformed source to console?',\n default: false,\n });\n\n const ignorePattern = await input({\n message: 'Enter ignore pattern(s) (comma separated) or leave empty:',\n validate: (value) => true,\n });\n\n const gitignore = await confirm({\n message: 'Respect .gitignore files?',\n default: true,\n });\n\n return { transformFile, targetPath, dry, print, ignorePattern, gitignore };\n}\n\nexport default getOptions;\n","import { promises as fs } from 'fs';\nimport path from 'path';\n\ninterface TransformModule {\n default: {\n default: unknown;\n };\n}\n\nasync function loadTransformModules(transformsDir: string) {\n let transformModules: Record<string, unknown> = {};\n\n const files = await fs.readdir(transformsDir);\n const transformFiles = await Promise.all(\n files\n .filter((file) => file.endsWith('.js'))\n .map(async (file) => {\n const transformPath = path.join(transformsDir, file);\n const transformModule = (await import(transformPath)) as TransformModule;\n transformModules = { ...transformModules, [file]: transformModule.default.default };\n return file.replace('.js', '');\n }),\n );\n\n return { transformModules, transformFiles };\n}\n\nexport default loadTransformModules;\n","#!/usr/bin/env node\n\nimport fs from 'node:fs/promises';\n\nimport { execSync } from 'child_process';\nimport path from 'path';\nimport { fileURLToPath } from 'url';\n\nimport { getOptions, handleError, loadTransformModules } from './utils';\n\nconst currentFilePath = fileURLToPath(import.meta.url);\nconst currentDirPath = path.dirname(currentFilePath);\n\nasync function runCodemod(transformsDir?: string) {\n try {\n const resolvedTransformsDir =\n transformsDir ?? path.resolve(currentDirPath, '../dist/transforms');\n console.debug(`Resolved transforms directory: ${resolvedTransformsDir}`);\n\n const { transformFiles } = await loadTransformModules(resolvedTransformsDir);\n\n if (transformFiles.length === 0) {\n throw new Error(`No transform scripts found in directory: ${resolvedTransformsDir}`);\n }\n\n const resolvedTransformFiles = await Promise.all(transformFiles);\n const options = await getOptions(resolvedTransformFiles);\n\n const codemodPath = path.resolve(resolvedTransformsDir, `${options.transformFile}.js`);\n console.debug(`Resolved codemod path: ${codemodPath}`);\n\n const args = [\n '-t',\n codemodPath,\n options.targetPath,\n options.dry ? '--dry' : '',\n options.print ? '--print' : '',\n options.ignorePattern\n ? options.ignorePattern\n .split(',')\n .map((pattern) => `--ignore-pattern=${pattern.trim()}`)\n .join(' ')\n : '',\n options.gitignore ? '--gitignore' : '',\n ].filter(Boolean);\n\n const command = `npx jscodeshift ${args.join(' ')}`;\n\n console.debug(`Running: ${command}`);\n\n const reportPath = path.resolve(process.cwd(), 'codemod-report.txt');\n\n try {\n await fs.access(reportPath);\n await fs.rm(reportPath);\n console.debug(`Removed existing report file: ${reportPath}`);\n } catch {\n console.debug(`No existing report file to remove: ${reportPath}`);\n }\n\n execSync(command, { stdio: 'inherit' });\n\n try {\n const reportContent = await fs.readFile(reportPath, 'utf8');\n const lines = reportContent.split('\\n').filter(Boolean);\n if (lines.length) {\n console.log(\n `\\n⚠️ ${lines.length} manual review${lines.length > 1 ? 's are' : ' is'} required. See ${reportPath} for details.`,\n );\n } else {\n console.debug(`Report file exists but is empty: ${reportPath}`);\n }\n } catch {\n console.debug(`No report file generated - no manual reviews needed`);\n }\n } catch (error: unknown) {\n if (error instanceof Error) {\n console.error('Error running codemod:', error.message);\n } else {\n console.error('Error running codemod:', error);\n }\n if (process.env.NODE_ENV !== 'test') {\n process.exit(1);\n }\n }\n}\n\nexport { runCodemod };\n","#!/usr/bin/env node\nimport { runCodemod } from './runCodemod';\n\nvoid runCodemod();\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["ignorePattern: string | undefined","transformModules: Record<string, unknown>","fs","path","path","path","fs","error: unknown"],"sources":["../src/utils/getOptions.ts","../src/utils/loadTransformModules.ts","../src/utils/repository.ts","../src/runCodemod.ts","../src/index.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { checkbox, confirm, input, select as list } from '@inquirer/prompts';\n\n/**\n * if args are provided via CLI, log them to the console in\n * a formatted way matching Inquirer's style\n */\nconst logToInquirer = (label: string, value: string) => {\n const checkmark = '\\x1b[32m✔\\x1b[0m'; // Green checkmark\n const boldLabel = `\\x1b[1m${label}\\x1b[0m`; // Bold label\n const greenValue = `\\x1b[32m${value}\\x1b[0m`; // Green value\n\n console.info(`${checkmark} ${boldLabel} ${greenValue}`);\n};\n\n/**\n * Lets user pick from available packages to run the codemod on\n */\nconst queryPackages = async (packages: string[]) => {\n const message = 'Path to run codemod on:';\n const nonRootPackages = packages.filter((pkg) => pkg !== '.');\n\n // root package only\n if (packages.length === 1 && nonRootPackages.length === 0) {\n logToInquirer(message, packages[0]);\n return packages;\n }\n\n // multiple non-root packages\n if (nonRootPackages.length >= 1) {\n return checkbox({\n required: true,\n message: 'Select packages to transform:',\n choices: nonRootPackages.map((file) => ({\n name: file,\n value: file,\n checked: true,\n })),\n });\n }\n};\n\n/**\n * Determine user choice between CLI arg and Inquirer prompt: codemod\n */\nconst determineTransformer = async ({\n candidate,\n transformFiles,\n}: {\n candidate: string;\n transformFiles: string[];\n}): Promise<string> => {\n const codemodMessage = 'Select codemod to run:';\n\n if (candidate && transformFiles.includes(candidate)) {\n logToInquirer(codemodMessage, candidate);\n return candidate;\n }\n\n return list({\n message: codemodMessage,\n choices: transformFiles.map((file) => ({ name: file, value: file })),\n });\n};\n\n/**\n * Determine user choice between CLI arg and Inquirer prompt: paths/packages to process\n */\nconst determinePaths = async ({\n candidate,\n root,\n packages,\n}: {\n candidate: string;\n root: string;\n packages: string[];\n}): Promise<string[]> => {\n const targetPaths = [];\n\n if (candidate && existsSync(join(root, candidate))) {\n logToInquirer('Path to run codemod on', candidate);\n targetPaths.push(candidate);\n }\n\n if (!targetPaths.length) {\n const packagesToProcess = await queryPackages(packages);\n targetPaths.push(...(packagesToProcess ?? []));\n }\n\n return targetPaths;\n};\n\n/**\n * Determine user choice between CLI arg and Inquirer prompt: dry mode\n */\nconst determineIsDryMode = async (args: string[]) => {\n const message = 'Run in dry mode (no changes written to files)?';\n if (args.includes('--dry') || args.includes('--dry-run')) {\n logToInquirer(message, 'Yes');\n return true;\n }\n\n return confirm({ message, default: false });\n};\n\n/**\n * Determine user choice between CLI arg and Inquirer prompt: print to CLI\n */\nconst determineIsPrint = async (args: string[]) => {\n const message = 'Print transformed source to console?';\n\n if (args.includes('--print')) {\n logToInquirer(message, 'Yes');\n return true;\n }\n\n return confirm({ message, default: false });\n};\n\n/**\n * Determine user choice between CLI arg and Inquirer prompt: ignore patterns\n */\nconst determineIgnorePatterns = async (args: string[]) => {\n const message = 'Enter ignore pattern(s) (comma separated) or leave empty:';\n const ignorePatternIndex = args.findIndex((arg) => arg === '--ignore-pattern');\n\n let ignorePattern: string | undefined;\n\n if (ignorePatternIndex !== -1 && args.length > ignorePatternIndex + 1) {\n ignorePattern = args[ignorePatternIndex + 1];\n }\n\n if (ignorePattern) {\n logToInquirer(message, ignorePattern);\n return ignorePattern;\n }\n\n return input({\n message,\n validate: () => true,\n });\n};\n\n/**\n * Determine user choice between CLI arg and Inquirer prompt: gitignore\n */\nconst determineGitIgnore = async (args: string[]) => {\n const message = 'Respect .gitignore files?';\n\n if (args.includes('--gitignore')) {\n logToInquirer(message, 'Yes');\n return true;\n }\n\n if (args.includes('--no-gitignore')) {\n logToInquirer(message, 'No');\n return false;\n }\n\n return confirm({ message, default: true });\n};\n\ninterface OptionsParams {\n transformFiles: string[];\n packages: string[];\n root: string;\n}\nasync function getOptions({ transformFiles, packages, root }: OptionsParams) {\n const args = process.argv.slice(2);\n\n const transformFile = await determineTransformer({ candidate: args[0], transformFiles });\n const targetPaths = await determinePaths({ candidate: args[1], packages, root });\n const isDry = await determineIsDryMode(args);\n const isPrint = await determineIsPrint(args);\n const ignorePatterns = await determineIgnorePatterns(args);\n const useGitIgnore = await determineGitIgnore(args);\n\n return {\n transformFile,\n targetPaths,\n isDry,\n isPrint,\n ignorePatterns,\n useGitIgnore,\n };\n}\n\nexport default getOptions;\n","import { promises as fs } from 'fs';\nimport path from 'path';\n\ninterface TransformModule {\n default: {\n default: unknown;\n };\n}\n\nasync function loadTransformModules(transformsDir: string) {\n let transformModules: Record<string, unknown> = {};\n\n const files = await fs.readdir(transformsDir);\n const transformFiles = await Promise.all(\n files\n .filter((file) => file.endsWith('.js'))\n .map(async (file) => {\n const transformPath = path.join(transformsDir, file);\n const transformModule = (await import(transformPath)) as TransformModule;\n transformModules = { ...transformModules, [file]: transformModule.default.default };\n return file.replace('.js', '');\n }),\n );\n\n return { transformModules, transformFiles };\n}\n\nexport default loadTransformModules;\n","import { execSync } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport path from 'node:path';\n\n/**\n * Finds the root of the project by looking for the `.git` directory.\n */\nexport function findProjectRoot(): string {\n try {\n const gitRoot = execSync('git rev-parse --show-toplevel', {\n cwd: process.cwd(),\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n\n return gitRoot && existsSync(gitRoot) ? gitRoot : '';\n } catch {\n return '';\n }\n}\n\n/**\n * Quick and dirty way of determining package roots based on\n * the presence of `package.json` files and them optimistically\n * containing a `@transferwise/components` string.\n * */\nexport function findPackages() {\n try {\n const packages = execSync(\n [\n 'find ./',\n '-type f',\n '-name \"package.json\"',\n '-not -path \"*/node_modules/*\"',\n '|',\n 'xargs grep -l \"@transferwise/components\"',\n ].join(' '),\n {\n cwd: findProjectRoot(),\n encoding: 'utf8',\n },\n )\n .trim()\n .split('\\n')\n .map(path.dirname);\n\n console.log(packages);\n\n if (packages.length === 0) {\n throw new Error();\n }\n\n return packages;\n } catch {\n throw new Error('No suitable package roots found in the repository.');\n }\n}\n","#!/usr/bin/env node\n\nimport { execSync } from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nimport { findPackages, findProjectRoot, getOptions, loadTransformModules } from './utils';\n\nconst currentFilePath = fileURLToPath(import.meta.url);\nconst currentDirPath = path.dirname(currentFilePath);\n\nconst resetReportFile = async (reportPath: string) => {\n try {\n await fs.access(reportPath);\n await fs.rm(reportPath);\n console.debug(`Removed existing report file: ${reportPath}`);\n } catch {\n console.debug(`No existing report file to remove: ${reportPath}`);\n }\n};\n\nconst summariseReportFile = async (reportPath: string) => {\n try {\n const reportContent = await fs.readFile(reportPath, 'utf8');\n const lines = reportContent.split('\\n').filter(Boolean);\n if (lines.length) {\n console.log(\n `\\n⚠️ ${lines.length} manual review${lines.length > 1 ? 's are' : ' is'} required. See ${reportPath} for details.`,\n );\n } else {\n console.debug(`Report file exists but is empty: ${reportPath}`);\n }\n } catch {\n console.debug(`No report file generated - no manual reviews needed`);\n }\n};\n\nasync function runCodemod(transformsDir?: string) {\n try {\n const packages = findPackages();\n const reportPath = path.resolve(process.cwd(), 'codemod-report.txt');\n const resolvedTransformsDir =\n transformsDir ?? path.resolve(currentDirPath, '../dist/transforms');\n console.debug(`Resolved transforms directory: ${resolvedTransformsDir}`);\n\n await resetReportFile(reportPath);\n\n const { transformFiles } = await loadTransformModules(resolvedTransformsDir);\n if (transformFiles.length === 0) {\n throw new Error(`No transform scripts found in directory: ${resolvedTransformsDir}`);\n }\n\n const options = await getOptions({\n packages,\n root: findProjectRoot(),\n transformFiles: await Promise.all(transformFiles),\n });\n\n const codemodPath = path.resolve(resolvedTransformsDir, `${options.transformFile}.js`);\n console.debug(`Resolved codemod path: ${codemodPath}`);\n\n options.targetPaths.map((targetPath) => {\n const args = [\n '-t',\n codemodPath,\n targetPath,\n options.isDry ? '--dry' : '',\n options.isPrint ? '--print' : '',\n options.ignorePatterns\n ? options.ignorePatterns\n .split(',')\n .map((pattern) => `--ignore-pattern=${pattern.trim()}`)\n .join(' ')\n : '',\n options.useGitIgnore ? '--gitignore' : '',\n ].filter(Boolean);\n\n const command = `npx jscodeshift ${args.join(' ')}`;\n console.debug(`Running: ${command}`);\n\n return execSync(command, { stdio: 'inherit' });\n });\n\n await summariseReportFile(reportPath);\n } catch (error: unknown) {\n if (error instanceof Error) {\n console.error('Error running codemod:', error.message);\n } else {\n console.error('Error running codemod:', error);\n }\n if (process.env.NODE_ENV !== 'test') {\n process.exit(1);\n }\n }\n}\n\nexport { runCodemod };\n","#!/usr/bin/env node\nimport { runCodemod } from './runCodemod';\n\nvoid runCodemod();\n"],"mappings":"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"}
@@ -33,7 +33,6 @@ const reportManualReview = async (filePath, message) => {
33
33
  const lineInfo = lineNumber ? `:${lineNumber}` : "";
34
34
  await node_fs_promises.default.appendFile(REPORT_PATH, `[${filePath}${lineInfo}] ${cleanMessage}\n`, "utf8");
35
35
  };
36
- var reportManualReview_default = reportManualReview;
37
36
 
38
37
  //#endregion
39
38
  Object.defineProperty(exports, '__toESM', {
@@ -42,10 +41,10 @@ Object.defineProperty(exports, '__toESM', {
42
41
  return __toESM;
43
42
  }
44
43
  });
45
- Object.defineProperty(exports, 'reportManualReview_default', {
44
+ Object.defineProperty(exports, 'reportManualReview', {
46
45
  enumerable: true,
47
46
  get: function () {
48
- return reportManualReview_default;
47
+ return reportManualReview;
49
48
  }
50
49
  });
51
- //# sourceMappingURL=reportManualReview-CDdJazd3.js.map
50
+ //# sourceMappingURL=reportManualReview-DQ00-OKx.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reportManualReview-CDdJazd3.js","names":["path","fs"],"sources":["../src/utils/reportManualReview.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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,cAAcA,kBAAK,QAAQ,QAAQ,OAAO;AAEhD,MAAM,qBAAqB,OAAO,UAAkB,YAAmC;CACrF,MAAM,YAAY,iBAAiB,KAAK;CACxC,MAAM,aAAa,YAAY;CAE/B,MAAM,eAAe,QAAQ,QAAQ,iBAAiB;CACtD,MAAM,WAAW,aAAa,IAAI,eAAe;AAEjD,OAAMC,yBAAG,WAAW,aAAa,IAAI,WAAW,SAAS,IAAI,aAAa,KAAK;;AAGjF,iCAAe"}
1
+ {"version":3,"file":"reportManualReview-DQ00-OKx.js","names":["path","fs"],"sources":["../src/utils/reportManualReview.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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAIA,MAAM,cAAcA,kBAAK,QAAQ,QAAQ,OAAO;AAEhD,MAAM,qBAAqB,OAAO,UAAkB,YAAmC;CACrF,MAAM,YAAY,iBAAiB,KAAK;CACxC,MAAM,aAAa,YAAY;CAE/B,MAAM,eAAe,QAAQ,QAAQ,iBAAiB;CACtD,MAAM,WAAW,aAAa,IAAI,eAAe;AAEjD,OAAMC,yBAAG,WAAW,aAAa,IAAI,WAAW,SAAS,IAAI,aAAa,KAAK;AAChF"}
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, '__esModule', { value: true });
2
- const require_reportManualReview = require('../reportManualReview-CDdJazd3.js');
2
+ const require_reportManualReview = require('../reportManualReview-DQ00-OKx.js');
3
3
 
4
4
  //#region src/transforms/helpers/hasImport.ts
5
5
  /**
@@ -31,7 +31,6 @@ function hasImport(root, sourceValue, importName, j) {
31
31
  remove
32
32
  };
33
33
  }
34
- var hasImport_default = hasImport;
35
34
 
36
35
  //#endregion
37
36
  //#region src/transforms/helpers/iconUtils.ts
@@ -67,7 +66,6 @@ const processIconChildren = (j, children, iconImports, openingElement) => {
67
66
  if (iconChildIndex - 1 >= 0 && isWhitespaceJsxText(children[iconChildIndex - 1])) children.splice(iconChildIndex - 1, 1);
68
67
  else if (isWhitespaceJsxText(children[iconChildIndex])) children.splice(iconChildIndex, 1);
69
68
  };
70
- var iconUtils_default = processIconChildren;
71
69
 
72
70
  //#endregion
73
71
  //#region src/transforms/helpers/jsxElementUtils.ts
@@ -347,8 +345,8 @@ const transformer = (file, api, options) => {
347
345
  const root = j(file.source);
348
346
  const manualReviewIssues = [];
349
347
  const reporter = createReporter(j, manualReviewIssues);
350
- const { exists: hasButtonImport } = hasImport_default(root, "@transferwise/components", "Button", j);
351
- const { exists: hasActionButtonImport, remove: removeActionButtonImport } = hasImport_default(root, "@transferwise/components", "ActionButton", j);
348
+ const { exists: hasButtonImport } = hasImport(root, "@transferwise/components", "Button", j);
349
+ const { exists: hasActionButtonImport, remove: removeActionButtonImport } = hasImport(root, "@transferwise/components", "ActionButton", j);
352
350
  const iconImports = /* @__PURE__ */ new Set();
353
351
  root.find(j.ImportDeclaration, { source: { value: "@transferwise/icons" } }).forEach((path) => {
354
352
  path.node.specifiers?.forEach((specifier) => {
@@ -370,7 +368,7 @@ const transformer = (file, api, options) => {
370
368
  attribute: j.jsxAttribute(j.jsxIdentifier("size"), j.literal("sm")),
371
369
  name: "size"
372
370
  }]);
373
- iconUtils_default(j, path.node.children, iconImports, openingElement);
371
+ processIconChildren(j, path.node.children, iconImports, openingElement);
374
372
  if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
375
373
  const legacyPropNames = ["priority", "text"];
376
374
  const legacyProps = {};
@@ -404,7 +402,7 @@ const transformer = (file, api, options) => {
404
402
  attribute: j.jsxAttribute(j.jsxIdentifier("v2")),
405
403
  name: "v2"
406
404
  }]);
407
- iconUtils_default(j, path.node.children, iconImports, openingElement);
405
+ processIconChildren(j, path.node.children, iconImports, openingElement);
408
406
  const legacyProps = {};
409
407
  const legacyPropNames = [
410
408
  "priority",
@@ -507,13 +505,12 @@ const transformer = (file, api, options) => {
507
505
  if ((openingElement.attributes ?? []).some((attr) => attr.type === "JSXSpreadAttribute")) reporter.reportSpreadProps(path);
508
506
  });
509
507
  if (manualReviewIssues.length > 0) manualReviewIssues.forEach(async (issue) => {
510
- await require_reportManualReview.reportManualReview_default(file.path, issue);
508
+ await require_reportManualReview.reportManualReview(file.path, issue);
511
509
  });
512
510
  return root.toSource();
513
511
  };
514
- var transformer_default = transformer;
515
512
 
516
513
  //#endregion
517
- exports.default = transformer_default;
514
+ exports.default = transformer;
518
515
  exports.parser = parser;
519
516
  //# sourceMappingURL=button.js.map
@@ -1 +1 @@
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[]","hasImport","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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"}
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,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/wds-codemods",
3
- "version": "0.0.1-experimental-c483d40",
3
+ "version": "0.0.1-experimental-30d1a63",
4
4
  "license": "UNLICENSED",
5
5
  "author": "Wise Payments Ltd.",
6
6
  "repository": {
@@ -34,7 +34,7 @@
34
34
  "test:watch": "jest --watch"
35
35
  },
36
36
  "dependencies": {
37
- "@inquirer/prompts": "^7.8.4",
37
+ "@inquirer/prompts": "^7.8.3",
38
38
  "jscodeshift": "^17.3"
39
39
  },
40
40
  "devDependencies": {