From 25a90ab365f0acdc126881075d3b61a22b2e8f30 Mon Sep 17 00:00:00 2001 From: Valentin Palkovic Date: Sun, 3 May 2026 21:06:08 +0200 Subject: [PATCH] maintenance: remove `parser` re-export from `storybook/internal/babel` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `storybook/internal/babel` re-exported the entire `@babel/parser` namespace as `parser`, leaking the upstream API into the public surface of `storybook/internal`. Replace it with two thin helpers in `babel/babelParse.ts`: - `parseAst(code, options)` — wraps `parser.parse` - `parseAstExpression(code, options)` — wraps `parser.parseExpression` Both helpers preserve the single-Babel-version guarantee: callers go through the bundled `storybook/internal/babel` entry instead of pulling in their own `@babel/parser` copy. Migrated all four `parser` consumers: - `core/src/mocking-utils/extract.ts` - `core/src/core-server/utils/save-story/valueToAST.ts` - `core/src/core-server/utils/parser/generic-parser.ts` - `lib/cli-storybook/src/codemod/helpers/csf-factories-utils.test.ts` Also remove `babelParseExpression` from `babelParse.ts` — it had zero callers in the repo and is superseded by `parseAstExpression`. Co-Authored-By: Claude Sonnet 4.6 --- code/core/src/babel/babelParse.ts | 18 +++++++++++++++--- code/core/src/babel/index.ts | 2 -- .../core-server/utils/parser/generic-parser.ts | 4 ++-- .../core-server/utils/save-story/valueToAST.ts | 4 ++-- code/core/src/mocking-utils/extract.ts | 4 ++-- .../helpers/csf-factories-utils.test.ts | 4 ++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/code/core/src/babel/babelParse.ts b/code/core/src/babel/babelParse.ts index 3cfcd5f810a8..1e540103c1ea 100644 --- a/code/core/src/babel/babelParse.ts +++ b/code/core/src/babel/babelParse.ts @@ -49,6 +49,18 @@ export const babelPrint = (ast: ASTNode): string => { }).code; }; -export const babelParseExpression = (code: string): parser.ParseResult => { - return parser.parseExpression(code, parserOptions); -}; +/** + * Thin wrapper around `@babel/parser`'s `parse` so callers do not have to import the parser + * namespace directly. Use this for parsing arbitrary source files; for recast-compatible parsing + * (source-preserving transforms) use {@link babelParse} instead. + */ +export const parseAst = ( + code: string, + options?: parser.ParserOptions +): parser.ParseResult => parser.parse(code, options); + +/** Thin wrapper around `@babel/parser`'s `parseExpression`. */ +export const parseAstExpression = ( + code: string, + options?: parser.ParserOptions +): parser.ParseResult => parser.parseExpression(code, options); diff --git a/code/core/src/babel/index.ts b/code/core/src/babel/index.ts index 59650a0f070f..045e0440ede5 100644 --- a/code/core/src/babel/index.ts +++ b/code/core/src/babel/index.ts @@ -8,7 +8,6 @@ import * as core from '@babel/core'; // @ts-expect-error File is not yet exposed, see https://github.com/babel/babel/issues/11350#issuecomment-644118606 import { File } from '@babel/core'; import bg from '@babel/generator'; -import * as parser from '@babel/parser'; import bt from '@babel/traverse'; import * as types from '@babel/types'; import * as recast from 'recast'; @@ -38,7 +37,6 @@ export { generate, traverse, types, - parser, transformSync, BabelFileClass, diff --git a/code/core/src/core-server/utils/parser/generic-parser.ts b/code/core/src/core-server/utils/parser/generic-parser.ts index 02ca96dc7eb3..b50411a3fed4 100644 --- a/code/core/src/core-server/utils/parser/generic-parser.ts +++ b/code/core/src/core-server/utils/parser/generic-parser.ts @@ -1,4 +1,4 @@ -import { parser, types as t } from 'storybook/internal/babel'; +import { parseAst, types as t } from 'storybook/internal/babel'; import type { Parser, ParserResult } from './types.ts'; @@ -11,7 +11,7 @@ export class GenericParser implements Parser { * @returns The exports of the file */ async parse(content: string): Promise { - const ast = parser.parse(content, { + const ast = parseAst(content, { allowImportExportEverywhere: true, allowAwaitOutsideFunction: true, allowNewTargetOutsideFunction: true, diff --git a/code/core/src/core-server/utils/save-story/valueToAST.ts b/code/core/src/core-server/utils/save-story/valueToAST.ts index 72fe823aad31..f6d9dcb18f2e 100644 --- a/code/core/src/core-server/utils/save-story/valueToAST.ts +++ b/code/core/src/core-server/utils/save-story/valueToAST.ts @@ -1,4 +1,4 @@ -import { parser, types as t } from 'storybook/internal/babel'; +import { parseAst, types as t } from 'storybook/internal/babel'; export function valueToAST(literal: T): any { if (literal === null) { @@ -6,7 +6,7 @@ export function valueToAST(literal: T): any { } switch (typeof literal) { case 'function': - const ast = parser.parse(literal.toString(), { + const ast = parseAst(literal.toString(), { allowReturnOutsideFunction: true, allowSuperOutsideMethod: true, }); diff --git a/code/core/src/mocking-utils/extract.ts b/code/core/src/mocking-utils/extract.ts index 3c051c1fa947..de3d5f2df96b 100644 --- a/code/core/src/mocking-utils/extract.ts +++ b/code/core/src/mocking-utils/extract.ts @@ -1,6 +1,6 @@ import { readFileSync } from 'node:fs'; -import { generate, parser, types as t } from 'storybook/internal/babel'; +import { generate, parseAst, types as t } from 'storybook/internal/babel'; import { logger } from 'storybook/internal/node-logger'; import { telemetry } from 'storybook/internal/telemetry'; import type { CoreConfig } from 'storybook/internal/types'; @@ -42,7 +42,7 @@ interface ExtractMockCallsOptions { * @returns The parsed code. */ export const babelParser = (code: string) => { - return parser.parse(code, { + return parseAst(code, { sourceType: 'module', // Enable plugins to handle modern JavaScript features, including TSX. plugins: ['typescript', 'jsx', 'classProperties', 'objectRestSpread'], diff --git a/code/lib/cli-storybook/src/codemod/helpers/csf-factories-utils.test.ts b/code/lib/cli-storybook/src/codemod/helpers/csf-factories-utils.test.ts index af09ba0b9e01..c1480954f910 100644 --- a/code/lib/cli-storybook/src/codemod/helpers/csf-factories-utils.test.ts +++ b/code/lib/cli-storybook/src/codemod/helpers/csf-factories-utils.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest'; import { types as t } from 'storybook/internal/babel'; -import { generate, parser } from 'storybook/internal/babel'; +import { generate, parseAst } from 'storybook/internal/babel'; import { cleanupTypeImports, @@ -23,7 +23,7 @@ expect.addSnapshotSerializer({ }); function parseCodeToProgramNode(code: string): t.Program { - return parser.parse(code, { sourceType: 'unambiguous', plugins: ['typescript'] }).program; + return parseAst(code, { sourceType: 'unambiguous', plugins: ['typescript'] }).program; } function generateCodeFromAST(node: t.Program) {