@storybook/codemod 7.0.0-beta.56 → 7.0.0-beta.58

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
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_prettier2=__toESM(require("prettier")),t2=__toESM(require("@babel/types")),import_types=require("@babel/types"),import_csf_tools2=require("@storybook/csf-tools"),babel2=__toESM(require("@babel/core")),recast2=__toESM(require("recast"));var import_prettier=__toESM(require("prettier")),babel=__toESM(require("@babel/core")),import_csf_tools=require("@storybook/csf-tools"),recast=__toESM(require("recast")),t=__toESM(require("@babel/types"));var 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()&&t.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(t.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(t.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(t.identifier(migrateType(right.node.name)))}}}})}var logger=console,renameAnnotation=annotation=>annotation==="storyName"?"name":annotation,getTemplateBindVariable=init=>t2.isCallExpression(init)&&t2.isMemberExpression(init.callee)&&t2.isIdentifier(init.callee.object)&&t2.isIdentifier(init.callee.property)&&init.callee.property.name==="bind"&&(init.arguments.length===0||init.arguments.length===1&&t2.isObjectExpression(init.arguments[0])&&init.arguments[0].properties.length===0)?init.callee.object.name:null,isStoryAnnotation=(stmt,objectExports)=>t2.isExpressionStatement(stmt)&&t2.isAssignmentExpression(stmt.expression)&&t2.isMemberExpression(stmt.expression.left)&&t2.isIdentifier(stmt.expression.left.object)&&objectExports[stmt.expression.left.object.name],isTemplateDeclaration=(stmt,templates)=>t2.isVariableDeclaration(stmt)&&stmt.declarations.length===1&&t2.isIdentifier(stmt.declarations[0].id)&&templates[stmt.declarations[0].id.name],getNewExport=(stmt,objectExports)=>{if(t2.isExportNamedDeclaration(stmt)&&t2.isVariableDeclaration(stmt.declaration)&&stmt.declaration.declarations.length===1){let decl=stmt.declaration.declarations[0];if(t2.isVariableDeclarator(decl)&&t2.isIdentifier(decl.id))return objectExports[decl.id.name]}return null},isReactGlobalRenderFn=(csf,storyFn)=>{var _a;if((_a=csf._meta)!=null&&_a.component&&t2.isArrowFunctionExpression(storyFn)&&storyFn.params.length===1&&t2.isJSXElement(storyFn.body)){let{openingElement}=storyFn.body;if(openingElement.selfClosing&&t2.isJSXIdentifier(openingElement.name)&&openingElement.attributes.length===1){let attr=openingElement.attributes[0],param=storyFn.params[0];if(t2.isJSXSpreadAttribute(attr)&&t2.isIdentifier(attr.argument)&&t2.isIdentifier(param)&&param.name===attr.argument.name&&csf._meta.component===openingElement.name.name)return!0}}return!1},isSimpleCSFStory=(init,annotations)=>annotations.length===0&&t2.isArrowFunctionExpression(init)&&init.params.length===0;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 logger.log(`Error ${err}, skipping`),info.source}let file=new babel2.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])=>t2.objectProperty(t2.identifier(renameAnnotation(annotation)),val));if(t2.isVariableDeclarator(decl)){let{init,id}=decl,template=getTemplateBindVariable(init);if(!t2.isArrowFunctionExpression(init)&&!template)return;if(isSimpleCSFStory(init,annotations)){objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryFn"),init)]));return}let storyFn=template&&csf._templates[template];storyFn||(storyFn=init);let renderAnnotation=isReactGlobalRenderFn(csf,storyFn)?[]:[t2.objectProperty(t2.identifier("render"),storyFn)];objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryObj"),t2.objectExpression([...renderAnnotation,...annotations]))]))}}),importHelper.removeDeprecatedStoryImport(),csf._ast.program.body=csf._ast.program.body.reduce((acc,stmt)=>{if(isStoryAnnotation(stmt,objectExports)||isTemplateDeclaration(stmt,csf._templates))return acc;let newExport=getNewExport(stmt,objectExports);return newExport?(acc.push(newExport),acc):(acc.push(stmt),acc)},[]),upgradeDeprecatedTypes(file);let output=recast2.print(csf._ast,{}).code;try{let prettierConfig=import_prettier2.default.resolveConfig.sync(".",{editorconfig:!0})||{printWidth:100,tabWidth:2,bracketSpacing:!0,trailingComma:"es5",singleQuote:!0};output=import_prettier2.default.format(output,{...prettierConfig,filepath:info.path})}catch{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 path.buildCodeFrameError(`This codemod does not support namespace imports for a ${path.node.source.value} package.
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(t.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(t.identifier(migrateType(right.node.name)))}}}})}var logger=console,renameAnnotation=annotation=>annotation==="storyName"?"name":annotation,getTemplateBindVariable=init=>t2.isCallExpression(init)&&t2.isMemberExpression(init.callee)&&t2.isIdentifier(init.callee.object)&&t2.isIdentifier(init.callee.property)&&init.callee.property.name==="bind"&&(init.arguments.length===0||init.arguments.length===1&&t2.isObjectExpression(init.arguments[0])&&init.arguments[0].properties.length===0)?init.callee.object.name:null,isStoryAnnotation=(stmt,objectExports)=>t2.isExpressionStatement(stmt)&&t2.isAssignmentExpression(stmt.expression)&&t2.isMemberExpression(stmt.expression.left)&&t2.isIdentifier(stmt.expression.left.object)&&objectExports[stmt.expression.left.object.name],isTemplateDeclaration=(stmt,templates)=>t2.isVariableDeclaration(stmt)&&stmt.declarations.length===1&&t2.isIdentifier(stmt.declarations[0].id)&&templates[stmt.declarations[0].id.name],getNewExport=(stmt,objectExports)=>{if(t2.isExportNamedDeclaration(stmt)&&t2.isVariableDeclaration(stmt.declaration)&&stmt.declaration.declarations.length===1){let decl=stmt.declaration.declarations[0];if(t2.isVariableDeclarator(decl)&&t2.isIdentifier(decl.id))return objectExports[decl.id.name]}return null},isReactGlobalRenderFn=(csf,storyFn)=>{var _a;if((_a=csf._meta)!=null&&_a.component&&t2.isArrowFunctionExpression(storyFn)&&storyFn.params.length===1&&t2.isJSXElement(storyFn.body)){let{openingElement}=storyFn.body;if(openingElement.selfClosing&&t2.isJSXIdentifier(openingElement.name)&&openingElement.attributes.length===1){let attr=openingElement.attributes[0],param=storyFn.params[0];if(t2.isJSXSpreadAttribute(attr)&&t2.isIdentifier(attr.argument)&&t2.isIdentifier(param)&&param.name===attr.argument.name&&csf._meta.component===openingElement.name.name)return!0}}return!1},isSimpleCSFStory=(init,annotations)=>annotations.length===0&&t2.isArrowFunctionExpression(init)&&init.params.length===0;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 logger.log(`Error ${err}, skipping`),info.source}let file=new babel2.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])=>t2.objectProperty(t2.identifier(renameAnnotation(annotation)),val));if(t2.isVariableDeclarator(decl)){let{init,id}=decl,template=getTemplateBindVariable(init);if(!t2.isArrowFunctionExpression(init)&&!template)return;if(isSimpleCSFStory(init,annotations)){objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryFn"),init)]));return}let storyFn=template&&csf._templates[template];storyFn||(storyFn=init);let renderAnnotation=isReactGlobalRenderFn(csf,storyFn)?[]:[t2.objectProperty(t2.identifier("render"),storyFn)];objectExports[key]=t2.exportNamedDeclaration(t2.variableDeclaration("const",[t2.variableDeclarator(importHelper.updateTypeTo(id,"StoryObj"),t2.objectExpression([...renderAnnotation,...annotations]))]))}}),importHelper.removeDeprecatedStoryImport(),csf._ast.program.body=csf._ast.program.body.reduce((acc,stmt)=>{let statement=stmt;if(isStoryAnnotation(statement,objectExports)||isTemplateDeclaration(statement,csf._templates))return acc;let newExport=getNewExport(statement,objectExports);return newExport?(acc.push(newExport),acc):(acc.push(statement),acc)},[]),upgradeDeprecatedTypes(file);let output=recast2.print(csf._ast,{}).code;try{let prettierConfig=import_prettier2.default.resolveConfig.sync(".",{editorconfig:!0})||{printWidth:100,tabWidth:2,bracketSpacing:!0,trailingComma:"es5",singleQuote:!0};output=import_prettier2.default.format(output,{...prettierConfig,filepath:info.path})}catch{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
3
  Replace the namespace import with named imports and try again.`);if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return 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"),importSpecifier2=specifiers.find(specifier=>{if(!specifier.isImportSpecifier())return!1;let imported=specifier.get("imported");return imported.isIdentifier()?imported.node.name===type:!1});return importSpecifier2?importSpecifier2.node.local.name:(specifiers[0].insertBefore(t2.importSpecifier(t2.identifier(type),t2.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((0,import_types.isIdentifier)(id)&&(0,import_types.isTSTypeAnnotation)(id.typeAnnotation)&&(0,import_types.isTSTypeReference)(id.typeAnnotation.typeAnnotation)&&(0,import_types.isIdentifier)(id.typeAnnotation.typeAnnotation.typeName)){let{name}=id.typeAnnotation.typeAnnotation.typeName;if(this.getAllLocalImports().includes(name)){let localTypeImport=this.getOrAddImport(type);return{...id,typeAnnotation:t2.tsTypeAnnotation(t2.tsTypeReference(t2.identifier(localTypeImport),id.typeAnnotation.typeAnnotation.typeParameters))}}}return id};this.sbImportDeclarations=this.getAllSbImportDeclarations(file)}},parser="tsx";0&&(module.exports={parser});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@storybook/codemod",
3
- "version": "7.0.0-beta.56",
3
+ "version": "7.0.0-beta.58",
4
4
  "description": "A collection of codemod scripts written with JSCodeshift",
5
5
  "keywords": [
6
6
  "storybook"
@@ -45,20 +45,19 @@
45
45
  "prep": "../../../scripts/prepare/bundle.ts"
46
46
  },
47
47
  "dependencies": {
48
- "@babel/core": "^7.20.2",
49
- "@babel/preset-env": "^7.20.2",
50
- "@babel/types": "^7.20.7",
48
+ "@babel/core": "~7.21.0",
49
+ "@babel/preset-env": "~7.20.2",
50
+ "@babel/types": "~7.21.2",
51
51
  "@storybook/csf": "next",
52
- "@storybook/csf-tools": "7.0.0-beta.56",
53
- "@storybook/node-logger": "7.0.0-beta.56",
54
- "@storybook/types": "7.0.0-beta.56",
52
+ "@storybook/csf-tools": "7.0.0-beta.58",
53
+ "@storybook/node-logger": "7.0.0-beta.58",
54
+ "@storybook/types": "7.0.0-beta.58",
55
55
  "cross-spawn": "^7.0.3",
56
56
  "globby": "^11.0.2",
57
57
  "jscodeshift": "^0.14.0",
58
58
  "lodash": "^4.17.21",
59
59
  "prettier": "^2.8.0",
60
- "recast": "^0.23.1",
61
- "util": "^0.12.4"
60
+ "recast": "^0.23.1"
62
61
  },
63
62
  "devDependencies": {
64
63
  "@types/jscodeshift": "^0.11.6",
@@ -74,6 +73,7 @@
74
73
  "unist-util-is": "^5.2.0",
75
74
  "unist-util-select": "^4.0.3",
76
75
  "unist-util-visit": "^4.1.2",
76
+ "util": "^0.12.4",
77
77
  "vfile": "^5.3.7"
78
78
  },
79
79
  "publishConfig": {
@@ -97,5 +97,5 @@
97
97
  "cjs"
98
98
  ]
99
99
  },
100
- "gitHead": "26815b0ea07f3800cc514cccd242c8ab1f428b8c"
100
+ "gitHead": "a447c4d622b3c1010459047df9c8b7022e76a10d"
101
101
  }
@@ -235,11 +235,6 @@ describe('csf-2-to-3', () => {
235
235
  ).toThrowErrorMatchingInlineSnapshot(`
236
236
  This codemod does not support namespace imports for a @storybook/react package.
237
237
  Replace the namespace import with named imports and try again.
238
- > 1 | import * as SB from '@storybook/react';
239
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
240
- 2 | import { CatProps } from './Cat';
241
- 3 |
242
- 4 | const meta = { title: 'Cat', component: Cat } as Meta<CatProps>
243
238
  `);
244
239
  });
245
240
  it('should keep local names', () => {
@@ -140,7 +140,7 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
140
140
  // Remove the render function when we can hoist the template
141
141
  // const Template = (args) => <Cat {...args} />;
142
142
  // export const A = Template.bind({});
143
- let storyFn = template && csf._templates[template];
143
+ let storyFn: t.Expression = template && (csf._templates[template] as any as t.Expression);
144
144
  if (!storyFn) {
145
145
  storyFn = init;
146
146
  }
@@ -163,20 +163,24 @@ export default function transform(info: FileInfo, api: API, options: { parser?:
163
163
  importHelper.removeDeprecatedStoryImport();
164
164
 
165
165
  csf._ast.program.body = csf._ast.program.body.reduce((acc, stmt) => {
166
+ const statement = stmt as t.Statement;
166
167
  // remove story annotations & template declarations
167
- if (isStoryAnnotation(stmt, objectExports) || isTemplateDeclaration(stmt, csf._templates)) {
168
+ if (
169
+ isStoryAnnotation(statement, objectExports) ||
170
+ isTemplateDeclaration(statement, csf._templates)
171
+ ) {
168
172
  return acc;
169
173
  }
170
174
 
171
175
  // replace story exports with new object exports
172
- const newExport = getNewExport(stmt, objectExports);
176
+ const newExport = getNewExport(statement, objectExports);
173
177
  if (newExport) {
174
178
  acc.push(newExport);
175
179
  return acc;
176
180
  }
177
181
 
178
182
  // include unknown statements
179
- acc.push(stmt);
183
+ acc.push(statement);
180
184
  return acc;
181
185
  }, []);
182
186
 
@@ -221,7 +225,11 @@ class StorybookImportHelper {
221
225
  if (source.startsWith('@storybook/csf') || !source.startsWith('@storybook')) return;
222
226
  const isRendererImport = path.get('specifiers').some((specifier) => {
223
227
  if (specifier.isImportNamespaceSpecifier()) {
224
- throw path.buildCodeFrameError(
228
+ // throw path.buildCodeFrameError(
229
+ // `This codemod does not support namespace imports for a ${path.node.source.value} package.\n` +
230
+ // 'Replace the namespace import with named imports and try again.'
231
+ // );
232
+ throw new Error(
225
233
  `This codemod does not support namespace imports for a ${path.node.source.value} package.\n` +
226
234
  'Replace the namespace import with named imports and try again.'
227
235
  );
@@ -179,7 +179,10 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
179
179
  return [t.objectProperty(t.identifier(attribute.name), t.stringLiteral(attribute.value))];
180
180
  }
181
181
  return [
182
- t.objectProperty(t.identifier(attribute.name), babelParseExpression(attribute.value.value)),
182
+ t.objectProperty(
183
+ t.identifier(attribute.name),
184
+ babelParseExpression(attribute.value.value) as any as t.Expression
185
+ ),
183
186
  ];
184
187
  }
185
188
  return [];
@@ -216,7 +219,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
216
219
  return t.arrowFunctionExpression([], t.stringLiteral(child.value));
217
220
  }
218
221
  if (child.type === 'mdxFlowExpression' || child.type === 'mdxTextExpression') {
219
- const expression = babelParseExpression(child.value);
222
+ const expression = babelParseExpression(child.value) as any as t.Expression;
220
223
 
221
224
  // Recreating those lines: https://github.com/storybookjs/mdx1-csf/blob/f408fc97e9a63097ca1ee577df9315a3cccca975/src/sb-mdx-plugin.ts#L185-L198
222
225
  const BIND_REGEX = /\.bind\(.*\)/;
@@ -234,7 +237,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
234
237
 
235
238
  const expression = babelParseExpression(
236
239
  mdxProcessor.stringify({ type: 'root', children: [child] })
237
- );
240
+ ) as any as t.Expression;
238
241
  return t.arrowFunctionExpression([], expression);
239
242
  }
240
243
 
@@ -272,7 +275,7 @@ export function transform(source: string, baseName: string): [mdx: string, csf:
272
275
  return [
273
276
  t.objectProperty(
274
277
  t.identifier(attribute.name),
275
- babelParseExpression(attribute.value.value)
278
+ babelParseExpression(attribute.value.value) as any as t.Expression
276
279
  ),
277
280
  ];
278
281
  }