@storybook/codemod
Version:
A collection of codemod scripts written with JSCodeshift
134 lines (129 loc) • 4.88 kB
JavaScript
import CJS_COMPAT_NODE_URL_9smq7eu765a from 'node:url';
import CJS_COMPAT_NODE_PATH_9smq7eu765a from 'node:path';
import CJS_COMPAT_NODE_MODULE_9smq7eu765a from "node:module";
var __filename = CJS_COMPAT_NODE_URL_9smq7eu765a.fileURLToPath(import.meta.url);
var __dirname = CJS_COMPAT_NODE_PATH_9smq7eu765a.dirname(__filename);
var require = CJS_COMPAT_NODE_MODULE_9smq7eu765a.createRequire(import.meta.url);
// ------------------------------------------------------------
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
// ------------------------------------------------------------
import {
__name
} from "./chunk-HVEWKEW6.js";
// src/transforms/upgrade-deprecated-types.ts
import { core as babel, types as t } from "storybook/internal/babel";
import { loadCsf, printCsf } from "storybook/internal/csf-tools";
import { logger } from "storybook/internal/node-logger";
import prettier from "prettier";
var deprecatedTypes = [
"ComponentStory",
"ComponentStoryFn",
"ComponentStoryObj",
"ComponentMeta",
"Story"
];
function migrateType(oldType) {
if (oldType === "Story" || oldType === "ComponentStory") {
return "StoryFn";
}
return oldType.replace("Component", "");
}
__name(migrateType, "migrateType");
async function transform(info, api, options) {
const csf = loadCsf(info.source, { makeTitle: /* @__PURE__ */ __name((title) => title, "makeTitle") });
const fileNode = csf._ast;
const file = new babel.File(
{ filename: info.path },
{ code: info.source, ast: fileNode }
);
upgradeDeprecatedTypes(file);
let output = printCsf(csf).code;
try {
output = await prettier.format(output, {
...await prettier.resolveConfig(info.path),
filepath: info.path
});
} catch (e) {
logger.log(`Failed applying prettier to ${info.path}.`);
}
return output;
}
__name(transform, "transform");
var parser = "tsx";
function upgradeDeprecatedTypes(file) {
const importedNamespaces = /* @__PURE__ */ new Set();
const typeReferencesToUpdate = /* @__PURE__ */ new Set();
const existingImports = [];
file.path.traverse({
ImportDeclaration: /* @__PURE__ */ __name((path) => {
existingImports.push(
...path.get("specifiers").map((specifier) => ({
name: specifier.node.local.name,
isAlias: !(specifier.isImportSpecifier() && t.isIdentifier(specifier.node.imported) && specifier.node.local.name === specifier.node.imported.name),
path: specifier
}))
);
const source = path.node.source.value;
if (!source.startsWith("@storybook")) {
return;
}
path.get("specifiers").forEach((specifier) => {
if (specifier.isImportNamespaceSpecifier()) {
importedNamespaces.add(specifier.node.local.name);
}
if (!specifier.isImportSpecifier()) {
return;
}
const imported = specifier.get("imported");
if (!imported.isIdentifier()) {
return;
}
if (deprecatedTypes.includes(imported.node.name)) {
if (imported.node.name === specifier.node.local.name) {
typeReferencesToUpdate.add(specifier.node.local.name);
}
const newType = migrateType(imported.node.name);
if (!existingImports.some((it) => it.name === newType)) {
imported.replaceWith(t.identifier(newType));
existingImports.push({ name: newType, isAlias: false, path: specifier });
} else {
const existingImport = existingImports.find((it) => it.name === newType && it.isAlias);
if (existingImport) {
throw existingImport.path.buildCodeFrameError(
"This codemod does not support local imports that are called the same as a storybook import.\nRename this local import and try again."
);
} else {
specifier.remove();
}
}
}
});
}, "ImportDeclaration")
});
file.path.traverse({
TSTypeReference: /* @__PURE__ */ __name((path) => {
const typeName = path.get("typeName");
if (typeName.isIdentifier()) {
if (typeReferencesToUpdate.has(typeName.node.name)) {
typeName.replaceWith(t.identifier(migrateType(typeName.node.name)));
}
} else if (typeName.isTSQualifiedName()) {
const namespace = typeName.get("left");
if (namespace.isIdentifier()) {
if (importedNamespaces.has(namespace.node.name)) {
const right = typeName.get("right");
if (deprecatedTypes.includes(right.node.name)) {
right.replaceWith(t.identifier(migrateType(right.node.name)));
}
}
}
}
}, "TSTypeReference")
});
}
__name(upgradeDeprecatedTypes, "upgradeDeprecatedTypes");
export {
transform,
parser,
upgradeDeprecatedTypes
};