@storybook/codemod 9.2.0-alpha.2 → 10.0.0-beta.0

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/README.md CHANGED
@@ -107,3 +107,5 @@ Basic.decorators = [ ... ];
107
107
  ```
108
108
 
109
109
  The new syntax is slightly more compact, is more ergonomic, and resembles React's `displayName`/`propTypes`/`defaultProps` annotations.
110
+
111
+ Learn more about Storybook at [storybook.js.org](https://storybook.js.org/?ref=readme).
@@ -0,0 +1,133 @@
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ import {
13
+ __name
14
+ } from "./chunk-Y2LIRL6C.js";
15
+
16
+ // src/transforms/upgrade-deprecated-types.ts
17
+ import { core as babel, types as t } from "storybook/internal/babel";
18
+ import { loadCsf, printCsf } from "storybook/internal/csf-tools";
19
+ import { logger } from "storybook/internal/node-logger";
20
+ import prettier from "prettier";
21
+ var deprecatedTypes = [
22
+ "ComponentStory",
23
+ "ComponentStoryFn",
24
+ "ComponentStoryObj",
25
+ "ComponentMeta",
26
+ "Story"
27
+ ];
28
+ function migrateType(oldType) {
29
+ if (oldType === "Story" || oldType === "ComponentStory") {
30
+ return "StoryFn";
31
+ }
32
+ return oldType.replace("Component", "");
33
+ }
34
+ __name(migrateType, "migrateType");
35
+ async function transform(info, api, options) {
36
+ const csf = loadCsf(info.source, { makeTitle: /* @__PURE__ */ __name((title) => title, "makeTitle") });
37
+ const fileNode = csf._ast;
38
+ const file = new babel.File(
39
+ { filename: info.path },
40
+ { code: info.source, ast: fileNode }
41
+ );
42
+ upgradeDeprecatedTypes(file);
43
+ let output = printCsf(csf).code;
44
+ try {
45
+ output = await prettier.format(output, {
46
+ ...await prettier.resolveConfig(info.path),
47
+ filepath: info.path
48
+ });
49
+ } catch (e) {
50
+ logger.log(`Failed applying prettier to ${info.path}.`);
51
+ }
52
+ return output;
53
+ }
54
+ __name(transform, "transform");
55
+ var parser = "tsx";
56
+ function upgradeDeprecatedTypes(file) {
57
+ const importedNamespaces = /* @__PURE__ */ new Set();
58
+ const typeReferencesToUpdate = /* @__PURE__ */ new Set();
59
+ const existingImports = [];
60
+ file.path.traverse({
61
+ ImportDeclaration: /* @__PURE__ */ __name((path) => {
62
+ existingImports.push(
63
+ ...path.get("specifiers").map((specifier) => ({
64
+ name: specifier.node.local.name,
65
+ isAlias: !(specifier.isImportSpecifier() && t.isIdentifier(specifier.node.imported) && specifier.node.local.name === specifier.node.imported.name),
66
+ path: specifier
67
+ }))
68
+ );
69
+ const source = path.node.source.value;
70
+ if (!source.startsWith("@storybook")) {
71
+ return;
72
+ }
73
+ path.get("specifiers").forEach((specifier) => {
74
+ if (specifier.isImportNamespaceSpecifier()) {
75
+ importedNamespaces.add(specifier.node.local.name);
76
+ }
77
+ if (!specifier.isImportSpecifier()) {
78
+ return;
79
+ }
80
+ const imported = specifier.get("imported");
81
+ if (!imported.isIdentifier()) {
82
+ return;
83
+ }
84
+ if (deprecatedTypes.includes(imported.node.name)) {
85
+ if (imported.node.name === specifier.node.local.name) {
86
+ typeReferencesToUpdate.add(specifier.node.local.name);
87
+ }
88
+ const newType = migrateType(imported.node.name);
89
+ if (!existingImports.some((it) => it.name === newType)) {
90
+ imported.replaceWith(t.identifier(newType));
91
+ existingImports.push({ name: newType, isAlias: false, path: specifier });
92
+ } else {
93
+ const existingImport = existingImports.find((it) => it.name === newType && it.isAlias);
94
+ if (existingImport) {
95
+ throw existingImport.path.buildCodeFrameError(
96
+ "This codemod does not support local imports that are called the same as a storybook import.\nRename this local import and try again."
97
+ );
98
+ } else {
99
+ specifier.remove();
100
+ }
101
+ }
102
+ }
103
+ });
104
+ }, "ImportDeclaration")
105
+ });
106
+ file.path.traverse({
107
+ TSTypeReference: /* @__PURE__ */ __name((path) => {
108
+ const typeName = path.get("typeName");
109
+ if (typeName.isIdentifier()) {
110
+ if (typeReferencesToUpdate.has(typeName.node.name)) {
111
+ typeName.replaceWith(t.identifier(migrateType(typeName.node.name)));
112
+ }
113
+ } else if (typeName.isTSQualifiedName()) {
114
+ const namespace = typeName.get("left");
115
+ if (namespace.isIdentifier()) {
116
+ if (importedNamespaces.has(namespace.node.name)) {
117
+ const right = typeName.get("right");
118
+ if (deprecatedTypes.includes(right.node.name)) {
119
+ right.replaceWith(t.identifier(migrateType(right.node.name)));
120
+ }
121
+ }
122
+ }
123
+ }
124
+ }, "TSTypeReference")
125
+ });
126
+ }
127
+ __name(upgradeDeprecatedTypes, "upgradeDeprecatedTypes");
128
+
129
+ export {
130
+ transform,
131
+ parser,
132
+ upgradeDeprecatedTypes
133
+ };
@@ -0,0 +1,17 @@
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ var __defProp = Object.defineProperty;
13
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
14
+
15
+ export {
16
+ __name
17
+ };
package/dist/index.js CHANGED
@@ -1 +1,129 @@
1
- var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var index_exports={};__export(index_exports,{listCodemods:()=>listCodemods,runCodemod:()=>runCodemod});module.exports=__toCommonJS(index_exports);var import_node_fs=require("fs"),import_promises=require("fs/promises"),import_node_path=require("path"),import_cross_spawn=require("cross-spawn");var import_compat=require("es-toolkit/compat");function jscodeshiftToPrettierParser(parser){let parserMap={babylon:"babel",flow:"flow",ts:"typescript",tsx:"typescript"};return parser&&parserMap[parser]||"babel"}var TRANSFORM_DIR=`${__dirname}/transforms`;function listCodemods(){return(0,import_node_fs.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}`),(0,import_promises.rename)(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=(0,import_node_path.extname)(glob).slice(1);jscodeshiftToPrettierParser(extension)!=="babel"&&(inferredParser=extension)}let{globby}=await import("globby"),files=await globby([glob,"!**/node_modules","!**/dist"]),extensions=new Set(files.map(file=>(0,import_node_path.extname)(file).slice(1))),commaSeparatedExtensions=Array.from(extensions).join(",");if(logger.log(`=> Applying ${codemod}: ${files.length} files`),files.length===0){logger.log(`=> No matching files for glob: ${glob}`);return}if(!dryRun&&files.length>0){let parserArgs=inferredParser?["--parser",inferredParser]:[],result=(0,import_cross_spawn.sync)("node",[require.resolve("jscodeshift/bin/jscodeshift"),"--no-babel",`--extensions=${commaSeparatedExtensions}`,"--fail-on-error","-t",`${TRANSFORM_DIR}/${codemod}.js`,...parserArgs,...files.map(file=>`"${file}"`)],{stdio:"inherit",shell:!0});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.log(`=> Renaming ${rename}: ${files.length} files`),await Promise.all(files.map(file=>renameFile(file,new RegExp(`${from}$`),to,{logger})))}}0&&(module.exports={listCodemods,runCodemod});
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ import {
13
+ __name
14
+ } from "./_node-chunks/chunk-Y2LIRL6C.js";
15
+
16
+ // src/index.ts
17
+ import { readdirSync } from "node:fs";
18
+ import { rename as renameAsync } from "node:fs/promises";
19
+ import { extname, join } from "node:path";
20
+ import { resolvePackageDir } from "storybook/internal/common";
21
+ import { sync as spawnSync } from "cross-spawn";
22
+
23
+ // src/lib/utils.ts
24
+ import { camelCase, upperFirst } from "es-toolkit/compat";
25
+ function jscodeshiftToPrettierParser(parser) {
26
+ const parserMap = {
27
+ babylon: "babel",
28
+ flow: "flow",
29
+ ts: "typescript",
30
+ tsx: "typescript"
31
+ };
32
+ if (!parser) {
33
+ return "babel";
34
+ }
35
+ return parserMap[parser] || "babel";
36
+ }
37
+ __name(jscodeshiftToPrettierParser, "jscodeshiftToPrettierParser");
38
+
39
+ // src/index.ts
40
+ var TRANSFORM_DIR = join(resolvePackageDir("@storybook/codemod"), "dist", "transforms");
41
+ function listCodemods() {
42
+ return readdirSync(TRANSFORM_DIR).filter((fname) => fname.endsWith(".js")).map((fname) => fname.slice(0, -3));
43
+ }
44
+ __name(listCodemods, "listCodemods");
45
+ async function renameFile(file, from, to, { logger }) {
46
+ const newFile = file.replace(from, to);
47
+ logger.log(`Rename: ${file} ${newFile}`);
48
+ return renameAsync(file, newFile);
49
+ }
50
+ __name(renameFile, "renameFile");
51
+ async function runCodemod(codemod, {
52
+ glob,
53
+ logger,
54
+ dryRun,
55
+ rename,
56
+ parser
57
+ }) {
58
+ const codemods = listCodemods();
59
+ if (!codemods.includes(codemod)) {
60
+ throw new Error(`Unknown codemod ${codemod}. Run --list for options.`);
61
+ }
62
+ let renameParts = null;
63
+ if (rename) {
64
+ renameParts = rename.split(":");
65
+ if (renameParts.length !== 2) {
66
+ throw new Error(`Codemod rename: expected format "from:to", got "${rename}"`);
67
+ }
68
+ }
69
+ let inferredParser = parser;
70
+ if (!parser) {
71
+ const extension = extname(glob).slice(1);
72
+ const knownParser = jscodeshiftToPrettierParser(extension);
73
+ if (knownParser !== "babel") {
74
+ inferredParser = extension;
75
+ }
76
+ }
77
+ const { globby } = await import("globby");
78
+ const files = await globby([glob, "!**/node_modules", "!**/dist"]);
79
+ const extensions = new Set(files.map((file) => extname(file).slice(1)));
80
+ const commaSeparatedExtensions = Array.from(extensions).join(",");
81
+ logger.log(`=> Applying ${codemod}: ${files.length} files`);
82
+ if (files.length === 0) {
83
+ logger.log(`=> No matching files for glob: ${glob}`);
84
+ return;
85
+ }
86
+ if (!dryRun && files.length > 0) {
87
+ const parserArgs = inferredParser ? ["--parser", inferredParser] : [];
88
+ const result = spawnSync(
89
+ "node",
90
+ [
91
+ join(resolvePackageDir("jscodeshift"), "bin", "jscodeshift"),
92
+ // this makes sure codeshift doesn't transform our own source code with babel
93
+ // which is faster, and also makes sure the user won't see babel messages such as:
94
+ // [BABEL] Note: The code generator has deoptimised the styling of repo/node_modules/prettier/index.js as it exceeds the max of 500KB.
95
+ "--no-babel",
96
+ `--extensions=${commaSeparatedExtensions}`,
97
+ "--fail-on-error",
98
+ "-t",
99
+ `${TRANSFORM_DIR}/${codemod}.js`,
100
+ ...parserArgs,
101
+ ...files.map((file) => `"${file}"`)
102
+ ],
103
+ {
104
+ stdio: "inherit",
105
+ shell: true
106
+ }
107
+ );
108
+ if (codemod === "mdx-to-csf" && result.status === 1) {
109
+ logger.log(
110
+ "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."
111
+ );
112
+ } else if (result.status === 1) {
113
+ logger.log("Skipped renaming because of errors.");
114
+ return;
115
+ }
116
+ }
117
+ if (renameParts) {
118
+ const [from, to] = renameParts;
119
+ logger.log(`=> Renaming ${rename}: ${files.length} files`);
120
+ await Promise.all(
121
+ files.map((file) => renameFile(file, new RegExp(`${from}$`), to, { logger }))
122
+ );
123
+ }
124
+ }
125
+ __name(runCodemod, "runCodemod");
126
+ export {
127
+ listCodemods,
128
+ runCodemod
129
+ };
@@ -1,3 +1,278 @@
1
- var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var csf_2_to_3_exports={};__export(csf_2_to_3_exports,{default:()=>transform,parser:()=>parser});module.exports=__toCommonJS(csf_2_to_3_exports);var import_babel2=require("storybook/internal/babel"),import_csf_tools2=require("storybook/internal/csf-tools"),import_node_logger2=require("storybook/internal/node-logger"),import_prettier2=__toESM(require("prettier")),import_tiny_invariant=__toESM(require("tiny-invariant"));var import_babel=require("storybook/internal/babel"),import_csf_tools=require("storybook/internal/csf-tools"),import_node_logger=require("storybook/internal/node-logger"),import_prettier=__toESM(require("prettier")),deprecatedTypes=["ComponentStory","ComponentStoryFn","ComponentStoryObj","ComponentMeta","Story"];function migrateType(oldType){return oldType==="Story"||oldType==="ComponentStory"?"StoryFn":oldType.replace("Component","")}function upgradeDeprecatedTypes(file){let importedNamespaces=new Set,typeReferencesToUpdate=new Set,existingImports=[];file.path.traverse({ImportDeclaration:path=>{existingImports.push(...path.get("specifiers").map(specifier=>({name:specifier.node.local.name,isAlias:!(specifier.isImportSpecifier()&&import_babel.types.isIdentifier(specifier.node.imported)&&specifier.node.local.name===specifier.node.imported.name),path:specifier}))),path.node.source.value.startsWith("@storybook")&&path.get("specifiers").forEach(specifier=>{if(specifier.isImportNamespaceSpecifier()&&importedNamespaces.add(specifier.node.local.name),!specifier.isImportSpecifier())return;let imported=specifier.get("imported");if(imported.isIdentifier()&&deprecatedTypes.includes(imported.node.name)){imported.node.name===specifier.node.local.name&&typeReferencesToUpdate.add(specifier.node.local.name);let newType=migrateType(imported.node.name);if(!existingImports.some(it=>it.name===newType))imported.replaceWith(import_babel.types.identifier(newType)),existingImports.push({name:newType,isAlias:!1,path:specifier});else{let 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.
2
- Rename this local import and try again.`);specifier.remove()}}})}}),file.path.traverse({TSTypeReference:path=>{let typeName=path.get("typeName");if(typeName.isIdentifier())typeReferencesToUpdate.has(typeName.node.name)&&typeName.replaceWith(import_babel.types.identifier(migrateType(typeName.node.name)));else if(typeName.isTSQualifiedName()){let namespace=typeName.get("left");if(namespace.isIdentifier()&&importedNamespaces.has(namespace.node.name)){let right=typeName.get("right");deprecatedTypes.includes(right.node.name)&&right.replaceWith(import_babel.types.identifier(migrateType(right.node.name)))}}}})}var{isIdentifier,isTSTypeAnnotation,isTSTypeReference}=import_babel2.types,renameAnnotation=annotation=>annotation==="storyName"?"name":annotation,getTemplateBindVariable=init=>import_babel2.types.isCallExpression(init)&&import_babel2.types.isMemberExpression(init.callee)&&import_babel2.types.isIdentifier(init.callee.object)&&import_babel2.types.isIdentifier(init.callee.property)&&init.callee.property.name==="bind"&&(init.arguments.length===0||init.arguments.length===1&&import_babel2.types.isObjectExpression(init.arguments[0])&&init.arguments[0].properties.length===0)?init.callee.object.name:null,isStoryAnnotation=(stmt,objectExports)=>import_babel2.types.isExpressionStatement(stmt)&&import_babel2.types.isAssignmentExpression(stmt.expression)&&import_babel2.types.isMemberExpression(stmt.expression.left)&&import_babel2.types.isIdentifier(stmt.expression.left.object)&&objectExports[stmt.expression.left.object.name],getNewExport=(stmt,objectExports)=>{if(import_babel2.types.isExportNamedDeclaration(stmt)&&import_babel2.types.isVariableDeclaration(stmt.declaration)&&stmt.declaration.declarations.length===1){let decl=stmt.declaration.declarations[0];if(import_babel2.types.isVariableDeclarator(decl)&&import_babel2.types.isIdentifier(decl.id))return objectExports[decl.id.name]}return null},isReactGlobalRenderFn=(csf,storyFn)=>{if(csf._meta?.component&&import_babel2.types.isArrowFunctionExpression(storyFn)&&storyFn.params.length===1&&import_babel2.types.isJSXElement(storyFn.body)){let{openingElement}=storyFn.body;if(openingElement.selfClosing&&import_babel2.types.isJSXIdentifier(openingElement.name)&&openingElement.attributes.length===1){let attr=openingElement.attributes[0],param=storyFn.params[0];if(import_babel2.types.isJSXSpreadAttribute(attr)&&import_babel2.types.isIdentifier(attr.argument)&&import_babel2.types.isIdentifier(param)&&param.name===attr.argument.name&&csf._meta.component===openingElement.name.name)return!0}}return!1},isSimpleCSFStory=(init,annotations)=>annotations.length===0&&import_babel2.types.isArrowFunctionExpression(init)&&init.params.length===0;function removeUnusedTemplates(csf){Object.entries(csf._templates).forEach(([template,templateExpression])=>{let references=[];if(import_babel2.core.traverse(csf._ast,{Identifier:path=>{path.node.name===template&&references.push(path)}}),references.length===1){let reference=references[0];reference.parentPath?.isVariableDeclarator()&&reference.parentPath.node.init===templateExpression&&reference.parentPath.remove()}})}async function transform(info,api,options){let makeTitle=userTitle=>userTitle||"FIXME",csf=(0,import_csf_tools2.loadCsf)(info.source,{makeTitle});try{csf.parse()}catch(err){return import_node_logger2.logger.log(`Error ${err}, skipping`),info.source}let file=new import_babel2.core.File({filename:info.path},{code:info.source,ast:csf._ast}),importHelper=new StorybookImportHelper(file,info),objectExports={};Object.entries(csf._storyExports).forEach(([key,decl])=>{let annotations=Object.entries(csf._storyAnnotations[key]).map(([annotation,val])=>import_babel2.types.objectProperty(import_babel2.types.identifier(renameAnnotation(annotation)),val));if(import_babel2.types.isVariableDeclarator(decl)){let{init,id}=decl;(0,import_tiny_invariant.default)(init,"Inital value should be declared");let template=getTemplateBindVariable(init);if(!import_babel2.types.isArrowFunctionExpression(init)&&!template)return;if(isSimpleCSFStory(init,annotations)){objectExports[key]=import_babel2.types.exportNamedDeclaration(import_babel2.types.variableDeclaration("const",[import_babel2.types.variableDeclarator(importHelper.updateTypeTo(id,"StoryFn"),init)]));return}let storyFn=template?import_babel2.types.identifier(template):init,renderAnnotation=isReactGlobalRenderFn(csf,template?csf._templates[template]:storyFn)?[]:[import_babel2.types.objectProperty(import_babel2.types.identifier("render"),storyFn)];objectExports[key]=import_babel2.types.exportNamedDeclaration(import_babel2.types.variableDeclaration("const",[import_babel2.types.variableDeclarator(importHelper.updateTypeTo(id,"StoryObj"),import_babel2.types.objectExpression([...renderAnnotation,...annotations]))]))}}),csf._ast.program.body=csf._ast.program.body.reduce((acc,stmt)=>{let statement=stmt;if(isStoryAnnotation(statement,objectExports))return acc;let newExport=getNewExport(statement,objectExports);return newExport?(acc.push(newExport),acc):(acc.push(statement),acc)},[]),upgradeDeprecatedTypes(file),importHelper.removeDeprecatedStoryImport(),removeUnusedTemplates(csf);let output=(0,import_csf_tools2.printCsf)(csf).code;try{output=await import_prettier2.default.format(output,{...await import_prettier2.default.resolveConfig(info.path),filepath:info.path})}catch{import_node_logger2.logger.log(`Failed applying prettier to ${info.path}.`)}return output}var StorybookImportHelper=class{constructor(file,info){this.getAllSbImportDeclarations=file=>{let found=[];return file.path.traverse({ImportDeclaration:path=>{let source=path.node.source.value;if(source.startsWith("@storybook/csf")||!source.startsWith("@storybook"))return;path.get("specifiers").some(specifier=>{if(specifier.isImportNamespaceSpecifier())throw new Error(`This codemod does not support namespace imports for a ${path.node.source.value} package.
3
- Replace the namespace import with named imports and try again.`);if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return Array.isArray(imported)?imported.some(importedSpecifier=>importedSpecifier.isIdentifier()?["Story","StoryFn","StoryObj","Meta","ComponentStory","ComponentStoryFn","ComponentStoryObj","ComponentMeta"].includes(importedSpecifier.node.name):!1):imported.isIdentifier()?["Story","StoryFn","StoryObj","Meta","ComponentStory","ComponentStoryFn","ComponentStoryObj","ComponentMeta"].includes(imported.node.name):!1})&&found.push(path)}}),found};this.getOrAddImport=type=>{let sbImport=this.sbImportDeclarations.find(path=>path.node.importKind==="type")??this.sbImportDeclarations[0];if(sbImport==null)return;let specifiers=sbImport.get("specifiers"),importSpecifier=specifiers.find(specifier=>{if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return imported.isIdentifier()?imported.node.name===type:!1});return importSpecifier?importSpecifier.node.local.name:(specifiers[0].insertBefore(import_babel2.types.importSpecifier(import_babel2.types.identifier(type),import_babel2.types.identifier(type))),type)};this.removeDeprecatedStoryImport=()=>{this.sbImportDeclarations.flatMap(it=>it.get("specifiers")).filter(specifier=>{if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return imported.isIdentifier()?imported.node.name==="Story":!1}).forEach(path=>path.remove())};this.getAllLocalImports=()=>this.sbImportDeclarations.flatMap(it=>it.get("specifiers")).map(it=>it.node.local.name);this.updateTypeTo=(id,type)=>{if(isIdentifier(id)&&isTSTypeAnnotation(id.typeAnnotation)&&isTSTypeReference(id.typeAnnotation.typeAnnotation)&&isIdentifier(id.typeAnnotation.typeAnnotation.typeName)){let{name}=id.typeAnnotation.typeAnnotation.typeName;if(this.getAllLocalImports().includes(name)){let localTypeImport=this.getOrAddImport(type);return{...id,typeAnnotation:import_babel2.types.tsTypeAnnotation(import_babel2.types.tsTypeReference(import_babel2.types.identifier(localTypeImport??""),id.typeAnnotation.typeAnnotation.typeParameters))}}}return id};this.sbImportDeclarations=this.getAllSbImportDeclarations(file)}},parser="tsx";0&&(module.exports={parser});
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ import {
13
+ upgradeDeprecatedTypes
14
+ } from "../_node-chunks/chunk-CEWP2LBW.js";
15
+ import {
16
+ __name
17
+ } from "../_node-chunks/chunk-Y2LIRL6C.js";
18
+
19
+ // src/transforms/csf-2-to-3.ts
20
+ import { core as babel, types as t } from "storybook/internal/babel";
21
+ import { loadCsf, printCsf } from "storybook/internal/csf-tools";
22
+ import { logger } from "storybook/internal/node-logger";
23
+ import prettier from "prettier";
24
+ import invariant from "tiny-invariant";
25
+ var { isIdentifier, isTSTypeAnnotation, isTSTypeReference } = t;
26
+ var renameAnnotation = /* @__PURE__ */ __name((annotation) => {
27
+ return annotation === "storyName" ? "name" : annotation;
28
+ }, "renameAnnotation");
29
+ var getTemplateBindVariable = /* @__PURE__ */ __name((init) => t.isCallExpression(init) && t.isMemberExpression(init.callee) && t.isIdentifier(init.callee.object) && t.isIdentifier(init.callee.property) && init.callee.property.name === "bind" && (init.arguments.length === 0 || init.arguments.length === 1 && t.isObjectExpression(init.arguments[0]) && init.arguments[0].properties.length === 0) ? init.callee.object.name : null, "getTemplateBindVariable");
30
+ var isStoryAnnotation = /* @__PURE__ */ __name((stmt, objectExports) => t.isExpressionStatement(stmt) && t.isAssignmentExpression(stmt.expression) && t.isMemberExpression(stmt.expression.left) && t.isIdentifier(stmt.expression.left.object) && objectExports[stmt.expression.left.object.name], "isStoryAnnotation");
31
+ var getNewExport = /* @__PURE__ */ __name((stmt, objectExports) => {
32
+ if (t.isExportNamedDeclaration(stmt) && t.isVariableDeclaration(stmt.declaration) && stmt.declaration.declarations.length === 1) {
33
+ const decl = stmt.declaration.declarations[0];
34
+ if (t.isVariableDeclarator(decl) && t.isIdentifier(decl.id)) {
35
+ return objectExports[decl.id.name];
36
+ }
37
+ }
38
+ return null;
39
+ }, "getNewExport");
40
+ var isReactGlobalRenderFn = /* @__PURE__ */ __name((csf, storyFn) => {
41
+ if (csf._meta?.component && t.isArrowFunctionExpression(storyFn) && storyFn.params.length === 1 && t.isJSXElement(storyFn.body)) {
42
+ const { openingElement } = storyFn.body;
43
+ if (openingElement.selfClosing && t.isJSXIdentifier(openingElement.name) && openingElement.attributes.length === 1) {
44
+ const attr = openingElement.attributes[0];
45
+ const param = storyFn.params[0];
46
+ if (t.isJSXSpreadAttribute(attr) && t.isIdentifier(attr.argument) && t.isIdentifier(param) && param.name === attr.argument.name && csf._meta.component === openingElement.name.name) {
47
+ return true;
48
+ }
49
+ }
50
+ }
51
+ return false;
52
+ }, "isReactGlobalRenderFn");
53
+ var isSimpleCSFStory = /* @__PURE__ */ __name((init, annotations) => annotations.length === 0 && t.isArrowFunctionExpression(init) && init.params.length === 0, "isSimpleCSFStory");
54
+ function removeUnusedTemplates(csf) {
55
+ Object.entries(csf._templates).forEach(([template, templateExpression]) => {
56
+ const references = [];
57
+ babel.traverse(csf._ast, {
58
+ Identifier: /* @__PURE__ */ __name((path) => {
59
+ if (path.node.name === template) {
60
+ references.push(path);
61
+ }
62
+ }, "Identifier")
63
+ });
64
+ if (references.length === 1) {
65
+ const reference = references[0];
66
+ if (reference.parentPath?.isVariableDeclarator() && reference.parentPath.node.init === templateExpression) {
67
+ reference.parentPath.remove();
68
+ }
69
+ }
70
+ });
71
+ }
72
+ __name(removeUnusedTemplates, "removeUnusedTemplates");
73
+ async function transform(info, api, options) {
74
+ const makeTitle = /* @__PURE__ */ __name((userTitle) => {
75
+ return userTitle || "FIXME";
76
+ }, "makeTitle");
77
+ const csf = loadCsf(info.source, { makeTitle });
78
+ try {
79
+ csf.parse();
80
+ } catch (err) {
81
+ logger.log(`Error ${err}, skipping`);
82
+ return info.source;
83
+ }
84
+ const file = new babel.File(
85
+ { filename: info.path },
86
+ { code: info.source, ast: csf._ast }
87
+ );
88
+ const importHelper = new StorybookImportHelper(file, info);
89
+ const objectExports = {};
90
+ Object.entries(csf._storyExports).forEach(([key, decl]) => {
91
+ const annotations = Object.entries(csf._storyAnnotations[key]).map(([annotation, val]) => {
92
+ return t.objectProperty(t.identifier(renameAnnotation(annotation)), val);
93
+ });
94
+ if (t.isVariableDeclarator(decl)) {
95
+ const { init, id } = decl;
96
+ invariant(init, "Inital value should be declared");
97
+ const template = getTemplateBindVariable(init);
98
+ if (!t.isArrowFunctionExpression(init) && !template) {
99
+ return;
100
+ }
101
+ if (isSimpleCSFStory(init, annotations)) {
102
+ objectExports[key] = t.exportNamedDeclaration(
103
+ t.variableDeclaration("const", [
104
+ t.variableDeclarator(importHelper.updateTypeTo(id, "StoryFn"), init)
105
+ ])
106
+ );
107
+ return;
108
+ }
109
+ const storyFn = template ? t.identifier(template) : init;
110
+ const renderAnnotation = isReactGlobalRenderFn(
111
+ csf,
112
+ template ? csf._templates[template] : storyFn
113
+ ) ? [] : [t.objectProperty(t.identifier("render"), storyFn)];
114
+ objectExports[key] = t.exportNamedDeclaration(
115
+ t.variableDeclaration("const", [
116
+ t.variableDeclarator(
117
+ importHelper.updateTypeTo(id, "StoryObj"),
118
+ t.objectExpression([...renderAnnotation, ...annotations])
119
+ )
120
+ ])
121
+ );
122
+ }
123
+ });
124
+ csf._ast.program.body = csf._ast.program.body.reduce((acc, stmt) => {
125
+ const statement = stmt;
126
+ if (isStoryAnnotation(statement, objectExports)) {
127
+ return acc;
128
+ }
129
+ const newExport = getNewExport(statement, objectExports);
130
+ if (newExport) {
131
+ acc.push(newExport);
132
+ return acc;
133
+ }
134
+ acc.push(statement);
135
+ return acc;
136
+ }, []);
137
+ upgradeDeprecatedTypes(file);
138
+ importHelper.removeDeprecatedStoryImport();
139
+ removeUnusedTemplates(csf);
140
+ let output = printCsf(csf).code;
141
+ try {
142
+ output = await prettier.format(output, {
143
+ ...await prettier.resolveConfig(info.path),
144
+ filepath: info.path
145
+ });
146
+ } catch (e) {
147
+ logger.log(`Failed applying prettier to ${info.path}.`);
148
+ }
149
+ return output;
150
+ }
151
+ __name(transform, "transform");
152
+ var StorybookImportHelper = class {
153
+ constructor(file, info) {
154
+ this.getAllSbImportDeclarations = /* @__PURE__ */ __name((file) => {
155
+ const found = [];
156
+ file.path.traverse({
157
+ ImportDeclaration: /* @__PURE__ */ __name((path) => {
158
+ const source = path.node.source.value;
159
+ if (source.startsWith("@storybook/csf") || !source.startsWith("@storybook")) {
160
+ return;
161
+ }
162
+ const isRendererImport = path.get("specifiers").some((specifier) => {
163
+ if (specifier.isImportNamespaceSpecifier()) {
164
+ throw new Error(
165
+ `This codemod does not support namespace imports for a ${path.node.source.value} package.
166
+ Replace the namespace import with named imports and try again.`
167
+ );
168
+ }
169
+ if (!specifier.isImportSpecifier()) {
170
+ return false;
171
+ }
172
+ const imported = specifier.get("imported");
173
+ if (Array.isArray(imported)) {
174
+ return imported.some((importedSpecifier) => {
175
+ if (!importedSpecifier.isIdentifier()) {
176
+ return false;
177
+ }
178
+ return [
179
+ "Story",
180
+ "StoryFn",
181
+ "StoryObj",
182
+ "Meta",
183
+ "ComponentStory",
184
+ "ComponentStoryFn",
185
+ "ComponentStoryObj",
186
+ "ComponentMeta"
187
+ ].includes(importedSpecifier.node.name);
188
+ });
189
+ }
190
+ if (!imported.isIdentifier()) {
191
+ return false;
192
+ }
193
+ return [
194
+ "Story",
195
+ "StoryFn",
196
+ "StoryObj",
197
+ "Meta",
198
+ "ComponentStory",
199
+ "ComponentStoryFn",
200
+ "ComponentStoryObj",
201
+ "ComponentMeta"
202
+ ].includes(imported.node.name);
203
+ });
204
+ if (isRendererImport) {
205
+ found.push(path);
206
+ }
207
+ }, "ImportDeclaration")
208
+ });
209
+ return found;
210
+ }, "getAllSbImportDeclarations");
211
+ this.getOrAddImport = /* @__PURE__ */ __name((type) => {
212
+ const sbImport = this.sbImportDeclarations.find((path) => path.node.importKind === "type") ?? this.sbImportDeclarations[0];
213
+ if (sbImport == null) {
214
+ return void 0;
215
+ }
216
+ const specifiers = sbImport.get("specifiers");
217
+ const importSpecifier = specifiers.find((specifier) => {
218
+ if (!specifier.isImportSpecifier()) {
219
+ return false;
220
+ }
221
+ const imported = specifier.get("imported");
222
+ if (!imported.isIdentifier()) {
223
+ return false;
224
+ }
225
+ return imported.node.name === type;
226
+ });
227
+ if (importSpecifier) {
228
+ return importSpecifier.node.local.name;
229
+ }
230
+ specifiers[0].insertBefore(t.importSpecifier(t.identifier(type), t.identifier(type)));
231
+ return type;
232
+ }, "getOrAddImport");
233
+ this.removeDeprecatedStoryImport = /* @__PURE__ */ __name(() => {
234
+ const specifiers = this.sbImportDeclarations.flatMap((it) => it.get("specifiers"));
235
+ const storyImports = specifiers.filter((specifier) => {
236
+ if (!specifier.isImportSpecifier()) {
237
+ return false;
238
+ }
239
+ const imported = specifier.get("imported");
240
+ if (!imported.isIdentifier()) {
241
+ return false;
242
+ }
243
+ return imported.node.name === "Story";
244
+ });
245
+ storyImports.forEach((path) => path.remove());
246
+ }, "removeDeprecatedStoryImport");
247
+ this.getAllLocalImports = /* @__PURE__ */ __name(() => {
248
+ return this.sbImportDeclarations.flatMap((it) => it.get("specifiers")).map((it) => it.node.local.name);
249
+ }, "getAllLocalImports");
250
+ this.updateTypeTo = /* @__PURE__ */ __name((id, type) => {
251
+ if (isIdentifier(id) && isTSTypeAnnotation(id.typeAnnotation) && isTSTypeReference(id.typeAnnotation.typeAnnotation) && isIdentifier(id.typeAnnotation.typeAnnotation.typeName)) {
252
+ const { name } = id.typeAnnotation.typeAnnotation.typeName;
253
+ if (this.getAllLocalImports().includes(name)) {
254
+ const localTypeImport = this.getOrAddImport(type);
255
+ return {
256
+ ...id,
257
+ typeAnnotation: t.tsTypeAnnotation(
258
+ t.tsTypeReference(
259
+ t.identifier(localTypeImport ?? ""),
260
+ id.typeAnnotation.typeAnnotation.typeParameters
261
+ )
262
+ )
263
+ };
264
+ }
265
+ }
266
+ return id;
267
+ }, "updateTypeTo");
268
+ this.sbImportDeclarations = this.getAllSbImportDeclarations(file);
269
+ }
270
+ static {
271
+ __name(this, "StorybookImportHelper");
272
+ }
273
+ };
274
+ var parser = "tsx";
275
+ export {
276
+ transform as default,
277
+ parser
278
+ };
@@ -1 +1,146 @@
1
- var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var find_implicit_spies_exports={};__export(find_implicit_spies_exports,{default:()=>transform,parser:()=>parser});module.exports=__toCommonJS(find_implicit_spies_exports);var import_babel=require("storybook/internal/babel"),import_csf_tools=require("storybook/internal/csf-tools");function findImplicitSpies(path,file,keys){path.traverse({Identifier:identifier=>{!keys.includes(identifier.node.name)&&/^on[A-Z].*/.test(identifier.node.name)&&console.warn(identifier.buildCodeFrameError(`${file} Possible implicit spy found`).message)}})}function getAnnotationKeys(file,storyName,annotationName){let argKeys=[];return file.path.traverse({AssignmentExpression:path=>{let left=path.get("left");if(!left.isMemberExpression())return;let object=left.get("object");if(!(object.isIdentifier()&&object.node.name===storyName))return;let property=left.get("property"),right=path.get("right");property.isIdentifier()&&property.node.name===annotationName&&right.isObjectExpression()&&argKeys.push(...right.node.properties.flatMap(value=>import_babel.types.isObjectProperty(value)&&import_babel.types.isIdentifier(value.key)?[value.key.name]:[]))},VariableDeclarator:path=>{let id=path.get("id"),init=path.get("init");if(!(id.isIdentifier()&&id.node.name===storyName)||!init.isObjectExpression())return;let args=init.get("properties").flatMap(it=>it.isObjectProperty()?[it]:[]).find(it=>{let argKey=it.get("key");return argKey.isIdentifier()&&argKey.node.name===annotationName});if(!args)return;let argsValue=args.get("value");!argsValue||!argsValue.isObjectExpression()||argKeys.push(...argsValue.node.properties.flatMap(value=>import_babel.types.isObjectProperty(value)&&import_babel.types.isIdentifier(value.key)?[value.key.name]:[]))}}),argKeys}var getObjectExpressionKeys=node=>import_babel.types.isObjectExpression(node)?node.properties.flatMap(value=>import_babel.types.isObjectProperty(value)&&import_babel.types.isIdentifier(value.key)?[value.key.name]:[]):[];async function transform(info){let csf=(0,import_csf_tools.loadCsf)(info.source,{makeTitle:title=>title}),fileNode=csf._ast,file=new import_babel.core.File({filename:info.path},{code:info.source,ast:fileNode});csf.parse();let metaKeys=[...getObjectExpressionKeys(csf._metaAnnotations.args),...getObjectExpressionKeys(csf._metaAnnotations.argTypes)];Object.values(csf.stories).forEach(({name})=>{if(!name)return;let allKeys=[...metaKeys,...getAnnotationKeys(file,name,"args"),...getAnnotationKeys(file,name,"argTypes")];file.path.traverse({AssignmentExpression:path=>{let left=path.get("left");if(!left.isMemberExpression())return;let object=left.get("object");if(!(object.isIdentifier()&&object.node.name===name))return;let property=left.get("property");property.isIdentifier()&&property.node.name==="play"&&findImplicitSpies(path,info.path,allKeys)},VariableDeclarator:path=>{let id=path.get("id"),init=path.get("init");if(!(id.isIdentifier()&&id.node.name===name)||!init.isObjectExpression())return;let play=init.get("properties").flatMap(it=>it.isObjectProperty()?[it]:[]).find(it=>{let argKey=it.get("key");return argKey.isIdentifier()&&argKey.node.name==="play"});play&&findImplicitSpies(play,info.path,allKeys)}})})}var parser="tsx";0&&(module.exports={parser});
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ import {
13
+ __name
14
+ } from "../_node-chunks/chunk-Y2LIRL6C.js";
15
+
16
+ // src/transforms/find-implicit-spies.ts
17
+ import { core as babel, types as t } from "storybook/internal/babel";
18
+ import { loadCsf } from "storybook/internal/csf-tools";
19
+ function findImplicitSpies(path, file, keys) {
20
+ path.traverse({
21
+ Identifier: /* @__PURE__ */ __name((identifier) => {
22
+ if (!keys.includes(identifier.node.name) && /^on[A-Z].*/.test(identifier.node.name)) {
23
+ console.warn(identifier.buildCodeFrameError(`${file} Possible implicit spy found`).message);
24
+ }
25
+ }, "Identifier")
26
+ });
27
+ }
28
+ __name(findImplicitSpies, "findImplicitSpies");
29
+ function getAnnotationKeys(file, storyName, annotationName) {
30
+ const argKeys = [];
31
+ file.path.traverse({
32
+ // CSF2 play function Story.args =
33
+ AssignmentExpression: /* @__PURE__ */ __name((path) => {
34
+ const left = path.get("left");
35
+ if (!left.isMemberExpression()) {
36
+ return;
37
+ }
38
+ const object = left.get("object");
39
+ if (!(object.isIdentifier() && object.node.name === storyName)) {
40
+ return;
41
+ }
42
+ const property = left.get("property");
43
+ const right = path.get("right");
44
+ if (property.isIdentifier() && property.node.name === annotationName && right.isObjectExpression()) {
45
+ argKeys.push(
46
+ ...right.node.properties.flatMap(
47
+ (value) => t.isObjectProperty(value) && t.isIdentifier(value.key) ? [value.key.name] : []
48
+ )
49
+ );
50
+ }
51
+ }, "AssignmentExpression"),
52
+ // CSF3 const Story = {args: () => {} };
53
+ VariableDeclarator: /* @__PURE__ */ __name((path) => {
54
+ const id = path.get("id");
55
+ const init = path.get("init");
56
+ if (!(id.isIdentifier() && id.node.name === storyName) || !init.isObjectExpression()) {
57
+ return;
58
+ }
59
+ const args = init.get("properties").flatMap((it) => it.isObjectProperty() ? [it] : []).find((it) => {
60
+ const argKey = it.get("key");
61
+ return argKey.isIdentifier() && argKey.node.name === annotationName;
62
+ });
63
+ if (!args) {
64
+ return;
65
+ }
66
+ const argsValue = args.get("value");
67
+ if (!argsValue || !argsValue.isObjectExpression()) {
68
+ return;
69
+ }
70
+ argKeys.push(
71
+ ...argsValue.node.properties.flatMap(
72
+ (value) => t.isObjectProperty(value) && t.isIdentifier(value.key) ? [value.key.name] : []
73
+ )
74
+ );
75
+ }, "VariableDeclarator")
76
+ });
77
+ return argKeys;
78
+ }
79
+ __name(getAnnotationKeys, "getAnnotationKeys");
80
+ var getObjectExpressionKeys = /* @__PURE__ */ __name((node) => {
81
+ return t.isObjectExpression(node) ? node.properties.flatMap(
82
+ (value) => t.isObjectProperty(value) && t.isIdentifier(value.key) ? [value.key.name] : []
83
+ ) : [];
84
+ }, "getObjectExpressionKeys");
85
+ async function transform(info) {
86
+ const csf = loadCsf(info.source, { makeTitle: /* @__PURE__ */ __name((title) => title, "makeTitle") });
87
+ const fileNode = csf._ast;
88
+ const file = new babel.File(
89
+ { filename: info.path },
90
+ { code: info.source, ast: fileNode }
91
+ );
92
+ csf.parse();
93
+ const metaKeys = [
94
+ ...getObjectExpressionKeys(csf._metaAnnotations.args),
95
+ ...getObjectExpressionKeys(csf._metaAnnotations.argTypes)
96
+ ];
97
+ Object.values(csf.stories).forEach(({ name }) => {
98
+ if (!name) {
99
+ return;
100
+ }
101
+ const allKeys = [
102
+ ...metaKeys,
103
+ ...getAnnotationKeys(file, name, "args"),
104
+ ...getAnnotationKeys(file, name, "argTypes")
105
+ ];
106
+ file.path.traverse({
107
+ // CSF2 play function Story.play =
108
+ AssignmentExpression: /* @__PURE__ */ __name((path) => {
109
+ const left = path.get("left");
110
+ if (!left.isMemberExpression()) {
111
+ return;
112
+ }
113
+ const object = left.get("object");
114
+ if (!(object.isIdentifier() && object.node.name === name)) {
115
+ return;
116
+ }
117
+ const property = left.get("property");
118
+ if (property.isIdentifier() && property.node.name === "play") {
119
+ findImplicitSpies(path, info.path, allKeys);
120
+ }
121
+ }, "AssignmentExpression"),
122
+ // CSF3 play function: const Story = {play: () => {} };
123
+ VariableDeclarator: /* @__PURE__ */ __name((path) => {
124
+ const id = path.get("id");
125
+ const init = path.get("init");
126
+ if (!(id.isIdentifier() && id.node.name === name) || !init.isObjectExpression()) {
127
+ return;
128
+ }
129
+ const play = init.get("properties").flatMap((it) => it.isObjectProperty() ? [it] : []).find((it) => {
130
+ const argKey = it.get("key");
131
+ return argKey.isIdentifier() && argKey.node.name === "play";
132
+ });
133
+ if (play) {
134
+ findImplicitSpies(play, info.path, allKeys);
135
+ }
136
+ }, "VariableDeclarator")
137
+ });
138
+ });
139
+ return;
140
+ }
141
+ __name(transform, "transform");
142
+ var parser = "tsx";
143
+ export {
144
+ transform as default,
145
+ parser
146
+ };
@@ -1,2 +1,22 @@
1
- var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod)),__toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var upgrade_deprecated_types_exports={};__export(upgrade_deprecated_types_exports,{default:()=>transform,parser:()=>parser,upgradeDeprecatedTypes:()=>upgradeDeprecatedTypes});module.exports=__toCommonJS(upgrade_deprecated_types_exports);var import_babel=require("storybook/internal/babel"),import_csf_tools=require("storybook/internal/csf-tools"),import_node_logger=require("storybook/internal/node-logger"),import_prettier=__toESM(require("prettier")),deprecatedTypes=["ComponentStory","ComponentStoryFn","ComponentStoryObj","ComponentMeta","Story"];function migrateType(oldType){return oldType==="Story"||oldType==="ComponentStory"?"StoryFn":oldType.replace("Component","")}async function transform(info,api,options){let csf=(0,import_csf_tools.loadCsf)(info.source,{makeTitle:title=>title}),fileNode=csf._ast,file=new import_babel.core.File({filename:info.path},{code:info.source,ast:fileNode});upgradeDeprecatedTypes(file);let output=(0,import_csf_tools.printCsf)(csf).code;try{output=await import_prettier.default.format(output,{...await import_prettier.default.resolveConfig(info.path),filepath:info.path})}catch{import_node_logger.logger.log(`Failed applying prettier to ${info.path}.`)}return output}var parser="tsx";function upgradeDeprecatedTypes(file){let importedNamespaces=new Set,typeReferencesToUpdate=new Set,existingImports=[];file.path.traverse({ImportDeclaration:path=>{existingImports.push(...path.get("specifiers").map(specifier=>({name:specifier.node.local.name,isAlias:!(specifier.isImportSpecifier()&&import_babel.types.isIdentifier(specifier.node.imported)&&specifier.node.local.name===specifier.node.imported.name),path:specifier}))),path.node.source.value.startsWith("@storybook")&&path.get("specifiers").forEach(specifier=>{if(specifier.isImportNamespaceSpecifier()&&importedNamespaces.add(specifier.node.local.name),!specifier.isImportSpecifier())return;let imported=specifier.get("imported");if(imported.isIdentifier()&&deprecatedTypes.includes(imported.node.name)){imported.node.name===specifier.node.local.name&&typeReferencesToUpdate.add(specifier.node.local.name);let newType=migrateType(imported.node.name);if(!existingImports.some(it=>it.name===newType))imported.replaceWith(import_babel.types.identifier(newType)),existingImports.push({name:newType,isAlias:!1,path:specifier});else{let 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.
2
- Rename this local import and try again.`);specifier.remove()}}})}}),file.path.traverse({TSTypeReference:path=>{let typeName=path.get("typeName");if(typeName.isIdentifier())typeReferencesToUpdate.has(typeName.node.name)&&typeName.replaceWith(import_babel.types.identifier(migrateType(typeName.node.name)));else if(typeName.isTSQualifiedName()){let namespace=typeName.get("left");if(namespace.isIdentifier()&&importedNamespaces.has(namespace.node.name)){let right=typeName.get("right");deprecatedTypes.includes(right.node.name)&&right.replaceWith(import_babel.types.identifier(migrateType(right.node.name)))}}}})}0&&(module.exports={parser,upgradeDeprecatedTypes});
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ import {
13
+ parser,
14
+ transform,
15
+ upgradeDeprecatedTypes
16
+ } from "../_node-chunks/chunk-CEWP2LBW.js";
17
+ import "../_node-chunks/chunk-Y2LIRL6C.js";
18
+ export {
19
+ transform as default,
20
+ parser,
21
+ upgradeDeprecatedTypes
22
+ };
@@ -1 +1,44 @@
1
- var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __hasOwnProp=Object.prototype.hasOwnProperty;var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toCommonJS=mod=>__copyProps(__defProp({},"__esModule",{value:!0}),mod);var upgrade_hierarchy_separators_exports={};__export(upgrade_hierarchy_separators_exports,{default:()=>transformer});module.exports=__toCommonJS(upgrade_hierarchy_separators_exports);function upgradeSeparator(path){return path.replace(/[|.]/g,"/")}function transformer(file,api,options){let j=api.jscodeshift,root=j(file.source);return root.find(j.CallExpression).filter(call=>call.node.callee.name==="storiesOf").filter(call=>call.node.arguments.length>0&&["Literal","StringLiteral"].includes(call.node.arguments[0].type)).forEach(call=>{let arg0=call.node.arguments[0];arg0.value=upgradeSeparator(arg0.value)}),root.find(j.ExportDefaultDeclaration).filter(def=>def.node.declaration.properties.map(p=>p.key.name).includes("title")).forEach(def=>{def.node.declaration&&def.node.declaration.properties&&def.node.declaration.properties.forEach(p=>{p.key.name==="title"&&(p.value.value=upgradeSeparator(p.value.value))})}),root.toSource({quote:"single"})}
1
+ import CJS_COMPAT_NODE_URL_8qpor1xc9j4 from 'node:url';
2
+ import CJS_COMPAT_NODE_PATH_8qpor1xc9j4 from 'node:path';
3
+ import CJS_COMPAT_NODE_MODULE_8qpor1xc9j4 from "node:module";
4
+
5
+ var __filename = CJS_COMPAT_NODE_URL_8qpor1xc9j4.fileURLToPath(import.meta.url);
6
+ var __dirname = CJS_COMPAT_NODE_PATH_8qpor1xc9j4.dirname(__filename);
7
+ var require = CJS_COMPAT_NODE_MODULE_8qpor1xc9j4.createRequire(import.meta.url);
8
+
9
+ // ------------------------------------------------------------
10
+ // end of CJS compatibility banner, injected by Storybook's esbuild configuration
11
+ // ------------------------------------------------------------
12
+ import {
13
+ __name
14
+ } from "../_node-chunks/chunk-Y2LIRL6C.js";
15
+
16
+ // src/transforms/upgrade-hierarchy-separators.js
17
+ function upgradeSeparator(path) {
18
+ return path.replace(/[|.]/g, "/");
19
+ }
20
+ __name(upgradeSeparator, "upgradeSeparator");
21
+ function transformer(file, api, options) {
22
+ const j = api.jscodeshift;
23
+ const root = j(file.source);
24
+ root.find(j.CallExpression).filter((call) => call.node.callee.name === "storiesOf").filter(
25
+ (call) => call.node.arguments.length > 0 && ["Literal", "StringLiteral"].includes(call.node.arguments[0].type)
26
+ ).forEach((call) => {
27
+ const arg0 = call.node.arguments[0];
28
+ arg0.value = upgradeSeparator(arg0.value);
29
+ });
30
+ root.find(j.ExportDefaultDeclaration).filter((def) => def.node.declaration.properties.map((p) => p.key.name).includes("title")).forEach((def) => {
31
+ if (def.node.declaration && def.node.declaration.properties) {
32
+ def.node.declaration.properties.forEach((p) => {
33
+ if (p.key.name === "title") {
34
+ p.value.value = upgradeSeparator(p.value.value);
35
+ }
36
+ });
37
+ }
38
+ });
39
+ return root.toSource({ quote: "single" });
40
+ }
41
+ __name(transformer, "transformer");
42
+ export {
43
+ transformer as default
44
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/codemod",
3
- "version": "9.2.0-alpha.2",
3
+ "version": "10.0.0-beta.0",
4
4
  "description": "A collection of codemod scripts written with JSCodeshift",
5
5
  "keywords": [
6
6
  "storybook"
@@ -20,21 +20,18 @@
20
20
  },
21
21
  "license": "MIT",
22
22
  "sideEffects": false,
23
+ "type": "module",
23
24
  "exports": {
24
25
  ".": {
25
26
  "types": "./dist/index.d.ts",
26
- "node": "./dist/index.js",
27
- "require": "./dist/index.js"
27
+ "default": "./dist/index.js"
28
28
  },
29
- "./dist/transforms/csf-2-to-3.js": "./dist/transforms/csf-2-to-3.js",
30
- "./dist/transforms/csf-hoist-story-annotations.js": "./dist/transforms/csf-hoist-story-annotations.js",
31
- "./dist/transforms/find-implicit-spies.js": "./dist/transforms/find-implicit-spies.js",
32
- "./dist/transforms/upgrade-deprecated-types.js": "./dist/transforms/upgrade-deprecated-types.js",
33
- "./dist/transforms/upgrade-hierarchy-separators.js": "./dist/transforms/upgrade-hierarchy-separators.js",
34
- "./package.json": "./package.json"
29
+ "./package.json": "./package.json",
30
+ "./transforms/csf-2-to-3": "./dist/transforms/csf-2-to-3.js",
31
+ "./transforms/find-implicit-spies": "./dist/transforms/find-implicit-spies.js",
32
+ "./transforms/upgrade-deprecated-types": "./dist/transforms/upgrade-deprecated-types.js",
33
+ "./transforms/upgrade-hierarchy-separators": "./dist/transforms/upgrade-hierarchy-separators.js"
35
34
  },
36
- "main": "dist/index.js",
37
- "types": "dist/index.d.ts",
38
35
  "files": [
39
36
  "dist/**/*",
40
37
  "README.md",
@@ -43,8 +40,8 @@
43
40
  "!src/**/*"
44
41
  ],
45
42
  "scripts": {
46
- "check": "jiti ../../../scripts/prepare/check.ts",
47
- "prep": "jiti ../../../scripts/prepare/bundle.ts"
43
+ "check": "jiti ../../../scripts/check/check-package.ts",
44
+ "prep": "jiti ../../../scripts/build/build-package.ts"
48
45
  },
49
46
  "dependencies": {
50
47
  "@types/cross-spawn": "^6.0.6",
@@ -53,7 +50,7 @@
53
50
  "globby": "^14.0.1",
54
51
  "jscodeshift": "^0.15.1",
55
52
  "prettier": "^3.5.3",
56
- "storybook": "9.2.0-alpha.2",
53
+ "storybook": "10.0.0-beta.0",
57
54
  "tiny-invariant": "^1.3.1"
58
55
  },
59
56
  "devDependencies": {
@@ -65,17 +62,5 @@
65
62
  "publishConfig": {
66
63
  "access": "public"
67
64
  },
68
- "bundler": {
69
- "entries": [
70
- "./src/index.ts",
71
- "./src/transforms/csf-2-to-3.ts",
72
- "./src/transforms/find-implicit-spies.ts",
73
- "./src/transforms/upgrade-deprecated-types.ts",
74
- "./src/transforms/upgrade-hierarchy-separators.js"
75
- ],
76
- "formats": [
77
- "cjs"
78
- ]
79
- },
80
- "gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16"
65
+ "gitHead": "a8e7fd8a655c69780bc20b9749d2699e45beae16"
81
66
  }
@@ -1,8 +0,0 @@
1
- import { FileInfo, API } from 'jscodeshift';
2
-
3
- declare function transform(info: FileInfo, api: API, options: {
4
- parser?: string;
5
- }): Promise<string>;
6
- declare const parser = "tsx";
7
-
8
- export { transform as default, parser };
@@ -1,6 +0,0 @@
1
- import { FileInfo } from 'jscodeshift';
2
-
3
- declare function transform(info: FileInfo): Promise<void>;
4
- declare const parser = "tsx";
5
-
6
- export { transform as default, parser };
@@ -1,10 +0,0 @@
1
- import { BabelFile } from 'storybook/internal/babel';
2
- import { FileInfo, API } from 'jscodeshift';
3
-
4
- declare function transform(info: FileInfo, api: API, options: {
5
- parser?: string;
6
- }): Promise<string>;
7
- declare const parser = "tsx";
8
- declare function upgradeDeprecatedTypes(file: BabelFile): void;
9
-
10
- export { transform as default, parser, upgradeDeprecatedTypes };
@@ -1,3 +0,0 @@
1
- declare function transformer(file: any, api: any, options: any): any;
2
-
3
- export { transformer as default };