@wise/wds-codemods 0.0.1-experimental-30d1a63 → 0.0.1-experimental-3e28ce1

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
@@ -275,6 +275,7 @@ async function runCodemod(transformsDir) {
275
275
  options.useGitIgnore ? "--gitignore" : ""
276
276
  ].filter(Boolean);
277
277
  const command = `npx jscodeshift ${args.join(" ")}`;
278
+ console.info(`⚙️ \x1b[1mProcessing:\x1b[0m \x1b[32m${targetPath}\x1b[0m`);
278
279
  console.debug(`Running: ${command}`);
279
280
  return (0, node_child_process.execSync)(command, { stdio: "inherit" });
280
281
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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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"}
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.info(`⚙️ \\x1b[1mProcessing:\\x1b[0m \\x1b[32m${targetPath}\\x1b[0m`);\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/wds-codemods",
3
- "version": "0.0.1-experimental-30d1a63",
3
+ "version": "0.0.1-experimental-3e28ce1",
4
4
  "license": "UNLICENSED",
5
5
  "author": "Wise Payments Ltd.",
6
6
  "repository": {