diff --git a/packages/codemods/eslint.config.mjs b/packages/codemods/eslint.config.mjs new file mode 100644 index 000000000..14b83e41f --- /dev/null +++ b/packages/codemods/eslint.config.mjs @@ -0,0 +1,3 @@ +import { suspensiveTypeScriptConfig } from '@suspensive/eslint-config' + +export default [...suspensiveTypeScriptConfig] diff --git a/packages/codemods/package.json b/packages/codemods/package.json new file mode 100644 index 000000000..2ab123576 --- /dev/null +++ b/packages/codemods/package.json @@ -0,0 +1,51 @@ +{ + "name": "@suspensive/codemods", + "version": "0.1.0", + "description": "Codemods for @suspensive.", + "keywords": [ + "suspensive", + "codemods" + ], + "homepage": "https://suspensive.org", + "bugs": "https://github.com/toss/suspensive/issues", + "repository": { + "type": "git", + "url": "git+https://github.com/toss/suspensive.git", + "directory": "packages/codemods" + }, + "license": "MIT", + "author": "Gwansik Kim & Jonghyeon Ko ", + "sideEffects": false, + "type": "module", + "files": [ + "dist" + ], + "scripts": { + "build": "tsup", + "ci:attw": "attw --pack", + "ci:eslint": "eslint \"**/*.{ts,tsx,cts,mts}\"", + "ci:publint": "publint --strict", + "ci:test": "vitest run --coverage --typecheck", + "ci:type": "tsc --noEmit", + "clean": "rimraf ./dist && rimraf ./coverage", + "prepack": "pnpm build", + "test:ui": "vitest --ui --coverage --typecheck" + }, + "bin": "dist/suspensive-codemod.cjs", + "dependencies": { + "commander": "^12.1.0", + "execa": "^4.1.0", + "jscodeshift": "^17.0.0", + "prompts": "^2.4.2" + }, + "devDependencies": { + "@commander-js/extra-typings": "^12.1.0", + "@suspensive/eslint-config": "workspace:*", + "@suspensive/tsconfig": "workspace:*", + "@types/jscodeshift": "^0.12.0", + "@types/prompts": "^2.4.9" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/codemods/src/suspensive-codemod.ts b/packages/codemods/src/suspensive-codemod.ts new file mode 100644 index 000000000..7376bad21 --- /dev/null +++ b/packages/codemods/src/suspensive-codemod.ts @@ -0,0 +1,17 @@ +#!/usr/bin/env node + +import { Command } from 'commander' +import packageJson from '../package.json' +import { transformRunner } from './transformRunner' + +const program = new Command(packageJson.name) + +program + .description(packageJson.description) + .version(packageJson.version, '-v, --version', 'Output the current version of @suspensive/codemods') + .argument('[codemod]', 'Codemod slug to run.') + .argument('[path]', 'Path to source directory') + .usage('[codemod] [path]') + .action(transformRunner) + +program.parse(process.argv) diff --git a/packages/codemods/src/transformRunner.ts b/packages/codemods/src/transformRunner.ts new file mode 100644 index 000000000..5770cafd8 --- /dev/null +++ b/packages/codemods/src/transformRunner.ts @@ -0,0 +1,115 @@ +import { join } from 'node:path' +import execa from 'execa' +import prompts from 'prompts' +import { jscodeshiftExecutable, onCancel } from './utils' + +export const TRANSFORMER_INQUIRER_CHOICES = [ + { + title: 'react-query-import', + description: 'Safely migrate @tanstack/react-query', + }, +] + +export const transformerDirectory = join(__dirname, '../', 'dist', 'transforms') + +export async function transformRunner(transform: string, path: string) { + let transformer = transform + let directory = path + + if (transform && !TRANSFORMER_INQUIRER_CHOICES.find((x) => x.title === transform)) { + console.error('Invalid transform choice, pick one of:') + console.error(TRANSFORMER_INQUIRER_CHOICES.map((x) => '- ' + x.title).join('\n')) + process.exit(1) + } + + if (!transform) { + const res = await prompts( + { + type: 'select', + name: 'transformer', + message: 'Which transform would you like to apply?', + choices: TRANSFORMER_INQUIRER_CHOICES.reverse().map(({ title, description }) => { + return { + title, + description, + value: title, + } + }), + }, + { onCancel } + ) + + transformer = res.transformer as string + } + + if (!path) { + const res = await prompts( + { + type: 'text', + name: 'path', + message: 'On which files or directory should the codemods be applied?', + initial: '.', + }, + { onCancel } + ) + + directory = res.path as string + } + + let args = [] + + args.push('--no-babel') + args.push('--ignore-pattern=**/node_modules/**') + args.push('--ignore-pattern=**/.next/**') + args.push('--extensions=tsx,ts,jsx,js') + args.push('--parser=ts') + + args = args.concat(['--transform', join(transformerDirectory, `${transformer}.cjs`)]) + args.push(directory) + + console.log(`jscodeshift ${args.join(' ')}`) + + const execaChildProcess = execa(jscodeshiftExecutable, args, { + env: process.stdout.isTTY ? { FORCE_COLOR: 'true' } : {}, + }) + + // "\n" + "a\n" + "b\n" + let lastThreeLineBreaks = '' + + if (execaChildProcess.stdout) { + execaChildProcess.stdout.pipe(process.stdout) + execaChildProcess.stderr?.pipe(process.stderr) + + // The last two lines contain the successful transformation count as "N ok". + // To save memory, we "slide the window" to keep only the last three line breaks. + // We save three line breaks because the EOL is always "\n". + execaChildProcess.stdout.on('data', (chunk: Buffer) => { + lastThreeLineBreaks += chunk.toString('utf-8') + + let cutoff = lastThreeLineBreaks.length + + // Note: the stdout ends with "\n". + // "foo\n" + "bar\n" + "baz\n" -> "\nbar\nbaz\n" + // "\n" + "foo\n" + "bar\n" -> "\nfoo\nbar\n" + + for (let i = 0; i < 3; i++) { + cutoff = lastThreeLineBreaks.lastIndexOf('\n', cutoff) - 1 + } + + if (cutoff > 0 && cutoff < lastThreeLineBreaks.length) { + lastThreeLineBreaks = lastThreeLineBreaks.slice(cutoff + 1) + } + }) + } + + try { + const result = await execaChildProcess + + if (result.failed) { + throw new Error(`jscodeshift exited with code ${result.exitCode}`) + } + } catch (error) { + console.error(error) + process.exit(1) + } +} diff --git a/packages/codemods/src/transforms/react-query-import.ts b/packages/codemods/src/transforms/react-query-import.ts new file mode 100644 index 000000000..f8ba1b984 --- /dev/null +++ b/packages/codemods/src/transforms/react-query-import.ts @@ -0,0 +1,59 @@ +import type j from 'jscodeshift' +import { createParserFromPath } from '../utils' + +const IMPORT_TO_CHANGE = [ + 'useSuspenseQuery', + 'UseSuspenseQueryResult', + 'UseSuspenseQueryOptions', + 'useSuspenseQueries', + 'SuspenseQueriesResults', + 'SuspenseQueriesOptions', + 'useSuspenseInfiniteQuery', + 'UseSuspenseInfiniteQueryResult', + 'UseSuspenseInfiniteQueryOptions', + 'usePrefetchQuery', + 'queryOptions', + 'infiniteQueryOption', +] + +export default function transformer(file: j.FileInfo) { + const j = createParserFromPath(file.path) + const root = j(file.source) + + root + .find(j.ImportDeclaration, { + source: { + value: '@suspensive/react-query', + }, + }) + .forEach((path) => { + const importSpecifiers = path.node.specifiers || [] + + const importNamesToChange = importSpecifiers.filter((specifier) => + IMPORT_TO_CHANGE.includes(specifier.local?.name ?? '') + ) + const importsNamesRemained = importSpecifiers.filter( + (specifier) => !IMPORT_TO_CHANGE.includes(specifier.local?.name ?? '') + ) + + if (importNamesToChange.length > 0) { + const newImportStatement = j.importDeclaration(importNamesToChange, j.stringLiteral('@tanstack/react-query')) + path.insertBefore(newImportStatement) + } + if (importsNamesRemained.length > 0) { + const remainingSpecifiers = importSpecifiers.filter( + (specifier) => !IMPORT_TO_CHANGE.includes(specifier.local?.name ?? '') + ) + + const suspensiveReactQueryRemainImportsStatement = j.importDeclaration( + remainingSpecifiers, + j.stringLiteral('@suspensive/react-query') + ) + path.insertBefore(suspensiveReactQueryRemainImportsStatement) + } + j(path).remove() + }) + .toSource() + + return root.toSource() +} diff --git a/packages/codemods/src/utils.ts b/packages/codemods/src/utils.ts new file mode 100644 index 000000000..f09b16ae5 --- /dev/null +++ b/packages/codemods/src/utils.ts @@ -0,0 +1,34 @@ +import j from 'jscodeshift' +// @ts-expect-error: Declaration files are not included +import babylonParse from 'jscodeshift/parser/babylon' +// @ts-expect-error: Declaration files are not included +import tsOptions from 'jscodeshift/parser/tsOptions' + +export const jscodeshiftExecutable = require.resolve('.bin/jscodeshift') + +export function onCancel() { + process.exit(1) +} + +export function createParserFromPath(filePath: string): j.JSCodeshift { + const isDeclarationFile = /\.d\.(m|c)?ts$/.test(filePath) + if (isDeclarationFile) { + return j.withParser( + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-call + babylonParse({ + ...tsOptions, + plugins: [ + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + ...tsOptions.plugins.filter((plugin: string) => plugin !== 'typescript'), + ['typescript', { dts: true }], + ], + }) + ) + } + + // jsx is allowed in .js files, feed them into the tsx parser. + // tsx parser :.js, .jsx, .tsx + // ts parser: .ts, .mts, .cts + const isTsFile = /\.(m|c)?.ts$/.test(filePath) + return isTsFile ? j.withParser('ts') : j.withParser('tsx') +} diff --git a/packages/codemods/tsconfig.json b/packages/codemods/tsconfig.json new file mode 100644 index 000000000..6e028cfdc --- /dev/null +++ b/packages/codemods/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "@suspensive/tsconfig/base.json", + "compilerOptions": { + "types": ["vitest/globals"] + }, + "include": ["**/*.ts"] +} diff --git a/packages/codemods/tsup.config.ts b/packages/codemods/tsup.config.ts new file mode 100644 index 000000000..85dc7db4e --- /dev/null +++ b/packages/codemods/tsup.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + format: 'cjs', + target: ['node18'], + entry: ['src/**/*.{ts,tsx}', '!**/*.{spec,test,test-d,bench}.*'], + outDir: 'dist', + external: ['.bin/jscodeshift'], +}) diff --git a/packages/codemods/vitest.config.ts b/packages/codemods/vitest.config.ts new file mode 100644 index 000000000..216f17608 --- /dev/null +++ b/packages/codemods/vitest.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config' +import packageJson from './package.json' + +export default defineConfig({ + test: { + name: packageJson.name, + dir: './src', + globals: true, + coverage: { + provider: 'istanbul', + }, + }, +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67dd6393d..f356cf2ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -494,6 +494,37 @@ importers: specifier: ^15.10.0 version: 15.10.0 + packages/codemods: + dependencies: + commander: + specifier: ^12.1.0 + version: 12.1.0 + execa: + specifier: ^4.1.0 + version: 4.1.0 + jscodeshift: + specifier: ^17.0.0 + version: 17.0.0(@babel/preset-env@7.25.0(@babel/core@7.25.2)) + prompts: + specifier: ^2.4.2 + version: 2.4.2 + devDependencies: + '@commander-js/extra-typings': + specifier: ^12.1.0 + version: 12.1.0(commander@12.1.0) + '@suspensive/eslint-config': + specifier: workspace:* + version: link:../../configs/eslint-config + '@suspensive/tsconfig': + specifier: workspace:* + version: link:../../configs/tsconfig + '@types/jscodeshift': + specifier: ^0.12.0 + version: 0.12.0 + '@types/prompts': + specifier: ^2.4.9 + version: 2.4.9 + packages/jotai: devDependencies: '@suspensive/eslint-config': @@ -598,9 +629,6 @@ importers: packages/react-query: dependencies: - '@commander-js/extra-typings': - specifier: ^12.1.0 - version: 12.1.0(commander@12.1.0) '@suspensive/react-query-4': specifier: workspace:^2.18.4 version: link:../react-query-4 @@ -614,6 +642,9 @@ importers: specifier: ^12.1.0 version: 12.1.0 devDependencies: + '@commander-js/extra-typings': + specifier: ^12.1.0 + version: 12.1.0(commander@12.1.0) '@suspensive/eslint-config': specifier: workspace:* version: link:../../configs/eslint-config @@ -3584,6 +3615,9 @@ packages: '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + '@types/jscodeshift@0.12.0': + resolution: {integrity: sha512-Jr2fQbEoDmjwEa92TreR/mX2t9iAaY/l5P/GKezvK4BodXahex60PDLXaQR0vAgP0KfCzc1CivHusQB9NhzX8w==} + '@types/jsdom@20.0.1': resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} @@ -3635,6 +3669,9 @@ packages: '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + '@types/prompts@2.4.9': + resolution: {integrity: sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==} + '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -4219,10 +4256,18 @@ packages: resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} engines: {node: '>=12'} + ast-types@0.14.2: + resolution: {integrity: sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==} + engines: {node: '>=4'} + ast-types@0.15.2: resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==} engines: {node: '>=4'} + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + astral-regex@1.0.0: resolution: {integrity: sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==} engines: {node: '>=4'} @@ -6054,6 +6099,10 @@ packages: resolution: {integrity: sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==} engines: {node: '>=6'} + execa@4.1.0: + resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} + engines: {node: '>=10'} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} @@ -6443,6 +6492,10 @@ packages: resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==} engines: {node: '>=6'} + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -6806,6 +6859,10 @@ packages: human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} + human-signals@1.1.1: + resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} + engines: {node: '>=8.12.0'} + human-signals@2.1.0: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} @@ -7475,6 +7532,16 @@ packages: peerDependencies: '@babel/preset-env': ^7.1.6 + jscodeshift@17.0.0: + resolution: {integrity: sha512-Af+MFsNwLSVO+t4kKjJdJKh6iNbNHfDfFGdyltJ2wUFN3furgbvHguJmB85iou+fY7wbHgI8eiEKpp6doGgtKg==} + engines: {node: '>=16'} + hasBin: true + peerDependencies: + '@babel/preset-env': ^7.1.6 + peerDependenciesMeta: + '@babel/preset-env': + optional: true + jsdoc-type-pratt-parser@4.1.0: resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} engines: {node: '>=12.0.0'} @@ -9519,10 +9586,18 @@ packages: readline@1.3.0: resolution: {integrity: sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==} + recast@0.20.5: + resolution: {integrity: sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==} + engines: {node: '>= 4'} + recast@0.21.5: resolution: {integrity: sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==} engines: {node: '>= 4'} + recast@0.23.9: + resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} + engines: {node: '>= 4'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -10456,6 +10531,10 @@ packages: resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} engines: {node: '>=6.0.0'} + temp@0.9.4: + resolution: {integrity: sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==} + engines: {node: '>=6.0.0'} + tempy@0.3.0: resolution: {integrity: sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ==} engines: {node: '>=8'} @@ -10536,6 +10615,9 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -11374,6 +11456,10 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + ws@6.2.3: resolution: {integrity: sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==} peerDependencies: @@ -11791,17 +11877,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-module-transforms@7.25.0(@babel/core@7.25.2)': - dependencies: - '@babel/core': 7.25.2 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - '@babel/traverse': 7.25.0 - transitivePeerDependencies: - - supports-color - optional: true - '@babel/helper-module-transforms@7.25.2(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 @@ -12272,7 +12347,6 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - optional: true '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.24.9)': dependencies: @@ -12327,7 +12401,6 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - optional: true '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.9)': dependencies: @@ -12349,7 +12422,6 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - optional: true '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.9)': dependencies: @@ -12393,7 +12465,6 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - optional: true '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.9)': dependencies: @@ -12426,7 +12497,6 @@ snapshots: dependencies: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 - optional: true '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.9)': dependencies: @@ -12529,7 +12599,6 @@ snapshots: '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.24.9)': dependencies: @@ -12690,7 +12759,6 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.25.2) - optional: true '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.24.9)': dependencies: @@ -12796,7 +12864,7 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.24.8(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 - '@babel/helper-module-transforms': 7.25.0(@babel/core@7.24.9) + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.24.9) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-simple-access': 7.24.7 transitivePeerDependencies: @@ -12805,12 +12873,11 @@ snapshots: '@babel/plugin-transform-modules-commonjs@7.24.8(@babel/core@7.25.2)': dependencies: '@babel/core': 7.25.2 - '@babel/helper-module-transforms': 7.25.0(@babel/core@7.25.2) + '@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2) '@babel/helper-plugin-utils': 7.24.8 '@babel/helper-simple-access': 7.24.7 transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-modules-systemjs@7.25.0(@babel/core@7.24.9)': dependencies: @@ -12885,7 +12952,6 @@ snapshots: '@babel/core': 7.25.2 '@babel/helper-plugin-utils': 7.24.8 '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.25.2) - optional: true '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.24.9)': dependencies: @@ -12964,7 +13030,6 @@ snapshots: '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.24.9)': dependencies: @@ -12992,7 +13057,6 @@ snapshots: '@babel/helper-plugin-utils': 7.24.8 transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.24.9)': dependencies: @@ -13222,7 +13286,6 @@ snapshots: '@babel/plugin-syntax-typescript': 7.24.7(@babel/core@7.25.2) transitivePeerDependencies: - supports-color - optional: true '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.24.9)': dependencies: @@ -13460,6 +13523,13 @@ snapshots: '@babel/helper-validator-option': 7.24.8 '@babel/plugin-transform-flow-strip-types': 7.24.7(@babel/core@7.24.9) + '@babel/preset-flow@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-validator-option': 7.24.8 + '@babel/plugin-transform-flow-strip-types': 7.24.7(@babel/core@7.25.2) + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 @@ -13498,6 +13568,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/preset-typescript@7.24.7(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + '@babel/helper-plugin-utils': 7.24.8 + '@babel/helper-validator-option': 7.24.8 + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-typescript': 7.24.8(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color + '@babel/register@7.24.6(@babel/core@7.24.9)': dependencies: '@babel/core': 7.24.9 @@ -13507,6 +13588,15 @@ snapshots: pirates: 4.0.6 source-map-support: 0.5.21 + '@babel/register@7.24.6(@babel/core@7.25.2)': + dependencies: + '@babel/core': 7.25.2 + clone-deep: 4.0.1 + find-cache-dir: 2.1.0 + make-dir: 2.1.0 + pirates: 4.0.6 + source-map-support: 0.5.21 + '@babel/regjsgen@0.8.0': {} '@babel/runtime@7.25.0': @@ -14664,7 +14754,7 @@ snapshots: rimraf: 2.6.3 sudo-prompt: 8.2.5 tmp: 0.0.33 - tslib: 2.6.3 + tslib: 2.7.0 transitivePeerDependencies: - supports-color @@ -16496,6 +16586,11 @@ snapshots: dependencies: '@types/istanbul-lib-report': 3.0.3 + '@types/jscodeshift@0.12.0': + dependencies: + ast-types: 0.14.2 + recast: 0.20.5 + '@types/jsdom@20.0.1': dependencies: '@types/node': 20.16.10 @@ -16548,6 +16643,11 @@ snapshots: '@types/parse-json@4.0.2': {} + '@types/prompts@2.4.9': + dependencies: + '@types/node': 20.16.10 + kleur: 3.0.3 + '@types/prop-types@15.7.12': {} '@types/qs@6.9.15': {} @@ -17222,10 +17322,18 @@ snapshots: assertion-error@2.0.1: {} + ast-types@0.14.2: + dependencies: + tslib: 2.7.0 + ast-types@0.15.2: dependencies: tslib: 2.7.0 + ast-types@0.16.1: + dependencies: + tslib: 2.7.0 + astral-regex@1.0.0: {} astring@1.8.6: {} @@ -19465,6 +19573,18 @@ snapshots: signal-exit: 3.0.7 strip-eof: 1.0.0 + execa@4.1.0: + dependencies: + cross-spawn: 7.0.3 + get-stream: 5.2.0 + human-signals: 1.1.1 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + execa@5.1.1: dependencies: cross-spawn: 7.0.3 @@ -19949,6 +20069,10 @@ snapshots: dependencies: pump: 3.0.0 + get-stream@5.2.0: + dependencies: + pump: 3.0.0 + get-stream@6.0.1: {} get-stream@8.0.1: {} @@ -20096,7 +20220,7 @@ snapshots: graphql-tag@2.12.6(graphql@15.8.0): dependencies: graphql: 15.8.0 - tslib: 2.6.3 + tslib: 2.7.0 graphql@15.8.0: {} @@ -20455,6 +20579,8 @@ snapshots: human-id@1.0.2: {} + human-signals@1.1.1: {} + human-signals@2.1.0: {} human-signals@5.0.0: {} @@ -21307,6 +21433,31 @@ snapshots: - supports-color optional: true + jscodeshift@17.0.0(@babel/preset-env@7.25.0(@babel/core@7.25.2)): + dependencies: + '@babel/core': 7.25.2 + '@babel/parser': 7.25.6 + '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-optional-chaining': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.25.2) + '@babel/preset-flow': 7.24.7(@babel/core@7.25.2) + '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) + '@babel/register': 7.24.6(@babel/core@7.25.2) + flow-parser: 0.241.0 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + neo-async: 2.6.2 + picocolors: 1.1.0 + recast: 0.23.9 + temp: 0.9.4 + write-file-atomic: 5.0.1 + optionalDependencies: + '@babel/preset-env': 7.25.0(@babel/core@7.25.2) + transitivePeerDependencies: + - supports-color + jsdoc-type-pratt-parser@4.1.0: {} jsdom@20.0.3: @@ -23864,6 +24015,13 @@ snapshots: readline@1.3.0: {} + recast@0.20.5: + dependencies: + ast-types: 0.14.2 + esprima: 4.0.1 + source-map: 0.6.1 + tslib: 2.7.0 + recast@0.21.5: dependencies: ast-types: 0.15.2 @@ -23871,6 +24029,14 @@ snapshots: source-map: 0.6.1 tslib: 2.7.0 + recast@0.23.9: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.7.0 + redent@3.0.0: dependencies: indent-string: 4.0.0 @@ -24986,6 +25152,11 @@ snapshots: dependencies: rimraf: 2.6.3 + temp@0.9.4: + dependencies: + mkdirp: 0.5.6 + rimraf: 2.6.3 + tempy@0.3.0: dependencies: temp-dir: 1.0.0 @@ -25075,6 +25246,8 @@ snapshots: thunky@1.1.0: {} + tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} tinyexec@0.3.0: {} @@ -26030,6 +26203,11 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + ws@6.2.3: dependencies: async-limiter: 1.0.1