UNPKG

@storybook/codemod

Version:

A collection of codemod scripts written with JSCodeshift

104 lines (98 loc) 4.17 kB
import CJS_COMPAT_NODE_URL_94b6aurt4b from 'node:url'; import CJS_COMPAT_NODE_PATH_94b6aurt4b from 'node:path'; import CJS_COMPAT_NODE_MODULE_94b6aurt4b from "node:module"; var __filename = CJS_COMPAT_NODE_URL_94b6aurt4b.fileURLToPath(import.meta.url); var __dirname = CJS_COMPAT_NODE_PATH_94b6aurt4b.dirname(__filename); var require = CJS_COMPAT_NODE_MODULE_94b6aurt4b.createRequire(import.meta.url); // ------------------------------------------------------------ // end of CJS compatibility banner, injected by Storybook's esbuild configuration // ------------------------------------------------------------ // src/index.ts import { readdirSync } from "node:fs"; import { rename as renameAsync } from "node:fs/promises"; import { extname, join } from "node:path"; import { resolvePackageDir } from "storybook/internal/common"; import { sync as spawnSync } from "cross-spawn"; import { glob as tinyglobby } from "tinyglobby"; // src/lib/utils.ts import { camelCase, upperFirst } from "es-toolkit/string"; function jscodeshiftToPrettierParser(parser) { let parserMap = { babylon: "babel", flow: "flow", ts: "typescript", tsx: "typescript" }; return parser && parserMap[parser] || "babel"; } // src/index.ts var TRANSFORM_DIR = join(resolvePackageDir("@storybook/codemod"), "dist", "transforms"); function listCodemods() { return readdirSync(TRANSFORM_DIR).filter((fname) => fname.endsWith(".js")).map((fname) => fname.slice(0, -3)); } async function renameFile(file, from, to, { logger }) { let newFile = file.replace(from, to); return logger.log(`Rename: ${file} ${newFile}`), renameAsync(file, newFile); } async function runCodemod(codemod, { glob, logger, dryRun, rename, parser }) { if (!listCodemods().includes(codemod)) throw new Error(`Unknown codemod ${codemod}. Run --list for options.`); let renameParts = null; if (rename && (renameParts = rename.split(":"), renameParts.length !== 2)) throw new Error(`Codemod rename: expected format "from:to", got "${rename}"`); let inferredParser = parser; if (!parser) { let extension = extname(glob).slice(1); jscodeshiftToPrettierParser(extension) !== "babel" && (inferredParser = extension); } let files = await tinyglobby([glob, "!**/node_modules", "!**/dist"]), extensions = new Set(files.map((file) => extname(file).slice(1))), commaSeparatedExtensions = Array.from(extensions).join(","); if (logger.step(`Applying ${codemod}: ${files.length} files`), files.length === 0) { logger.step(`No matching files for glob: ${glob}`); return; } if (!dryRun && files.length > 0) { let parserArgs = inferredParser ? ["--parser", inferredParser] : [], result = spawnSync( "node", [ join(resolvePackageDir("jscodeshift"), "bin", "jscodeshift"), // this makes sure codeshift doesn't transform our own source code with babel // which is faster, and also makes sure the user won't see babel messages such as: // [BABEL] Note: The code generator has deoptimised the styling of repo/node_modules/prettier/index.js as it exceeds the max of 500KB. "--no-babel", `--extensions=${commaSeparatedExtensions}`, "--fail-on-error", "-t", `${TRANSFORM_DIR}/${codemod}.js`, ...parserArgs, ...files.map((file) => `"${file}"`) ], { stdio: "inherit" } ); if (codemod === "mdx-to-csf" && result.status === 1) logger.log( "The codemod was not able to transform the files mentioned above. We have renamed the files to .mdx.broken. Please check the files and rename them back to .mdx after you have either manually transformed them to mdx + csf or fixed the issues so that the codemod can transform them." ); else if (result.status === 1) { logger.log("Skipped renaming because of errors."); return; } } if (renameParts) { let [from, to] = renameParts; logger.step(`Renaming ${rename}: ${files.length} files`), await Promise.all( files.map((file) => renameFile(file, new RegExp(`${from}$`), to, { logger })) ); } } export { listCodemods, runCodemod };