|
1 | | -import { resolveExpression } from 'storybook/internal/babel'; |
| 1 | +import { |
| 2 | + getConfigObjectFromMergeArg, |
| 3 | + getEffectiveMergeConfigCall, |
| 4 | + getTargetConfigObject, |
| 5 | + isDefineConfigLike, |
| 6 | + resolveExpression, |
| 7 | +} from 'storybook/internal/babel'; |
2 | 8 | import type { BabelFile, types as t } from 'storybook/internal/babel'; |
3 | 9 |
|
4 | 10 | import { normalize } from 'pathe'; |
@@ -69,57 +75,6 @@ const mergeProperties = ( |
69 | 75 | } |
70 | 76 | }; |
71 | 77 |
|
72 | | -/** |
73 | | - * Returns true if the identifier is a local alias for `defineConfig`/`defineProject` imported from |
74 | | - * either `vitest/config` or `vite`. |
75 | | - */ |
76 | | -const isImportedDefineConfigLikeIdentifier = (localName: string, ast: BabelFile['ast']): boolean => |
77 | | - ast.program.body.some( |
78 | | - (node): boolean => |
79 | | - node.type === 'ImportDeclaration' && |
80 | | - (node.source.value === 'vitest/config' || node.source.value === 'vite') && |
81 | | - node.specifiers.some( |
82 | | - (specifier) => |
83 | | - specifier.type === 'ImportSpecifier' && |
84 | | - specifier.local.type === 'Identifier' && |
85 | | - specifier.local.name === localName && |
86 | | - specifier.imported.type === 'Identifier' && |
87 | | - (specifier.imported.name === 'defineConfig' || |
88 | | - specifier.imported.name === 'defineProject') |
89 | | - ) |
90 | | - ); |
91 | | - |
92 | | -/** Returns true if the call expression is a defineConfig or defineProject call (including aliases). */ |
93 | | -const isDefineConfigLike = (node: t.CallExpression, ast: BabelFile['ast']): boolean => |
94 | | - node.callee.type === 'Identifier' && |
95 | | - (node.callee.name === 'defineConfig' || |
96 | | - node.callee.name === 'defineProject' || |
97 | | - isImportedDefineConfigLikeIdentifier(node.callee.name, ast)); |
98 | | - |
99 | | -/** |
100 | | - * Resolves a mergeConfig argument to a config object expression when possible. Supports both direct |
101 | | - * object args and wrapped forms like `defineConfig({ ... })`. |
102 | | - */ |
103 | | -const getConfigObjectFromMergeArg = ( |
104 | | - arg: t.Expression, |
105 | | - ast: BabelFile['ast'] |
106 | | -): t.ObjectExpression | null => { |
107 | | - const resolved = resolveExpression(arg, ast); |
108 | | - if (!resolved) { |
109 | | - return null; |
110 | | - } |
111 | | - |
112 | | - if (resolved.type === 'ObjectExpression') { |
113 | | - return resolved; |
114 | | - } |
115 | | - |
116 | | - if (resolved.type === 'CallExpression' && resolved.arguments[0]?.type === 'ObjectExpression') { |
117 | | - return resolved.arguments[0] as t.ObjectExpression; |
118 | | - } |
119 | | - |
120 | | - return null; |
121 | | -}; |
122 | | - |
123 | 78 | /** |
124 | 79 | * Resolves the value of a `test` ObjectProperty to an ObjectExpression. Handles both inline objects |
125 | 80 | * and shorthand identifier references, e.g.: `{ test: { ... } }` → returns the inline |
@@ -368,69 +323,6 @@ const mergeTemplateIntoConfigObject = ( |
368 | 323 | mergeProperties(properties, targetConfigObject.properties); |
369 | 324 | }; |
370 | 325 |
|
371 | | -/** |
372 | | - * Extracts the effective mergeConfig call from a declaration, handling wrappers: |
373 | | - * |
374 | | - * - TypeScript type annotations (as X, satisfies X) |
375 | | - * - DefineConfig(mergeConfig(...)) outer wrapper |
376 | | - * - Variable references (export default config where config = mergeConfig(...)) |
377 | | - */ |
378 | | -const getEffectiveMergeConfigCall = ( |
379 | | - decl: t.Expression | t.Declaration, |
380 | | - ast: BabelFile['ast'] |
381 | | -): t.CallExpression | null => { |
382 | | - const resolved = resolveExpression(decl, ast); |
383 | | - if (!resolved || resolved.type !== 'CallExpression') { |
384 | | - return null; |
385 | | - } |
386 | | - |
387 | | - // Handle defineConfig(mergeConfig(...)) – arg may itself be wrapped in a TS type expression |
388 | | - if (isDefineConfigLike(resolved, ast) && resolved.arguments.length > 0) { |
389 | | - const innerArg = resolveExpression(resolved.arguments[0] as t.Expression, ast); |
390 | | - if ( |
391 | | - innerArg?.type === 'CallExpression' && |
392 | | - innerArg.callee.type === 'Identifier' && |
393 | | - innerArg.callee.name === 'mergeConfig' |
394 | | - ) { |
395 | | - return innerArg; |
396 | | - } |
397 | | - } |
398 | | - |
399 | | - // Handle mergeConfig(...) directly |
400 | | - if (resolved.callee.type === 'Identifier' && resolved.callee.name === 'mergeConfig') { |
401 | | - return resolved; |
402 | | - } |
403 | | - |
404 | | - return null; |
405 | | -}; |
406 | | - |
407 | | -/** |
408 | | - * Resolves the target's default export to the actual config object expression we can merge into. |
409 | | - * Handles: export default defineConfig({}), export default defineProject({}), export default {}, |
410 | | - * and export default config (where config is a variable holding one of those), as well as |
411 | | - * TypeScript type annotations on the declaration. |
412 | | - */ |
413 | | -const getTargetConfigObject = ( |
414 | | - target: BabelFile['ast'], |
415 | | - exportDefault: t.ExportDefaultDeclaration |
416 | | -): t.ObjectExpression | null => { |
417 | | - const resolved = resolveExpression(exportDefault.declaration, target); |
418 | | - if (!resolved) { |
419 | | - return null; |
420 | | - } |
421 | | - if (resolved.type === 'ObjectExpression') { |
422 | | - return resolved; |
423 | | - } |
424 | | - if ( |
425 | | - resolved.type === 'CallExpression' && |
426 | | - isDefineConfigLike(resolved, target) && |
427 | | - resolved.arguments[0]?.type === 'ObjectExpression' |
428 | | - ) { |
429 | | - return resolved.arguments[0] as t.ObjectExpression; |
430 | | - } |
431 | | - return null; |
432 | | -}; |
433 | | - |
434 | 326 | /** |
435 | 327 | * Merges a source Vitest configuration AST into a target configuration AST. |
436 | 328 | * |
|
0 commit comments