Skip to content
Merged
4 changes: 2 additions & 2 deletions MIGRATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -567,10 +567,10 @@ When setting the `core.builder` or `core.builder.name` option in the main config
In a preset:

```diff
import { dirname, join } from 'node:path';
import { dirname } from 'node:path';

const getAbsolutePath = (input) =>
dirname(require.resolve(join(input, 'package.json')));
dirname(require.resolve(`${input}/package.json`));

export const core = {
- builder: getAbsolutePath('@storybook/builder-vite'),
Expand Down
19 changes: 10 additions & 9 deletions code/core/src/shared/utils/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createRequire, register } from 'node:module';
import { win32 } from 'node:path/win32';
import { fileURLToPath, pathToFileURL } from 'node:url';

import { resolveModulePath } from 'exsolve';
import { dirname, join } from 'pathe';

/**
Expand Down Expand Up @@ -112,13 +113,13 @@ export const safeResolveModule = ({
parent?: string;
extensions?: string[];
}) => {
for (const extension of [''].concat(extensions)) {
try {
const resolvedPath = fileURLToPath(importMetaResolve(specifier + extension, parent));
if (statSync(resolvedPath).isFile()) {
return resolvedPath;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (e) {}
}
try {
const resolvedPath = resolveModulePath(specifier, {
from: parent,
extensions: [''].concat(extensions),
});
if (statSync(resolvedPath).isFile()) {
return resolvedPath;
}
} catch (e: any) {}
};
6 changes: 1 addition & 5 deletions code/core/src/telemetry/package-json.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { fileURLToPath, pathToFileURL } from 'node:url';

import * as pkg from 'empathic/package';
import { join } from 'pathe';
import type { PackageJson } from 'type-fest';

import type { Dependency } from './types';
Expand Down Expand Up @@ -34,10 +33,7 @@ export const getActualPackageJson = async (
cwd: fileURLToPath(import.meta.resolve(packageName, process.cwd())),
});
if (!resolvedPackageJsonPath) {
resolvedPackageJsonPath = import.meta.resolve(
join(packageName, 'package.json'),
process.cwd()
);
resolvedPackageJsonPath = import.meta.resolve(`${packageName}/package.json`, process.cwd());
}

const { default: packageJson } = await import(pathToFileURL(resolvedPackageJsonPath).href, {
Expand Down
1 change: 0 additions & 1 deletion code/frameworks/angular/preset.js

This file was deleted.

7 changes: 4 additions & 3 deletions code/frameworks/angular/src/preset.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import type { PresetProperty } from 'storybook/internal/types';

import type { StandaloneOptions } from './builders/utils/standalone-options';
import { fileURLToPath } from 'node:url';

export const addons: PresetProperty<'addons'> = [
import.meta.resolve('@storybook/angular/server/framework-preset-angular-cli'),
import.meta.resolve('@storybook/angular/server/framework-preset-angular-ivy'),
fileURLToPath(import.meta.resolve('@storybook/angular/server/framework-preset-angular-cli')),
fileURLToPath(import.meta.resolve('@storybook/angular/server/framework-preset-angular-ivy')),
];

export const previewAnnotations: PresetProperty<'previewAnnotations'> = async (
entries = [],
options
) => {
const config = import.meta.resolve('@storybook/angular/client/config');
const config = fileURLToPath(import.meta.resolve('@storybook/angular/client/config'));
const annotations = [...entries, config];

if ((options as any as StandaloneOptions).enableProdMode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { dirname, join } from 'node:path';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const wrapForPnp = (packageName) =>
dirname(fileURLToPath(import.meta.resolve(join(packageName, 'package.json'))));
dirname(fileURLToPath(import.meta.resolve(`${packageName}/package.json`)));

const config = {
stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export function getFieldsForGetAbsolutePathWrapper(config: ConfigFile): t.Node[]
*
* ```ts
* function getAbsolutePath(value) {
* return dirname(fileURLToPath(import.meta.resolve(join(value, 'package.json'))));
* return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`)));
* }
* ```
*/
Expand Down Expand Up @@ -162,10 +162,13 @@ export function getAbsolutePathWrapperAsCallExpression(
t.identifier('resolve')
),
[
t.callExpression(t.identifier('join'), [
t.identifier('value'),
t.stringLiteral('package.json'),
]),
t.templateLiteral(
[
t.templateElement({ raw: '' }),
t.templateElement({ raw: '/package.json' }, true),
],
[t.identifier('value')]
),
]
),
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('wrapGetAbsolutePath', () => {

expect(call[1]).toMatchInlineSnapshot(`
"import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { dirname } from "node:path";
const config = {
stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
Expand All @@ -121,7 +121,7 @@ describe('wrapGetAbsolutePath', () => {
export default config;

function getAbsolutePath(value) {
return dirname(fileURLToPath(import.meta.resolve(join(value, "package.json"))));
return dirname(fileURLToPath(import.meta.resolve(\`\${value}/package.json\`)));
}
"
`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export const wrapGetAbsolutePath: Fix<WrapGetAbsolutePathRunOptions> = {
) {
throw new CommonJsConfigNotSupportedError();
} else {
mainConfig.setImport(['dirname', 'join'], 'node:path');
mainConfig.setImport(['dirname'], 'node:path');
mainConfig.setImport(['fileURLToPath'], 'node:url');
}
Comment on lines +75 to 77

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

🧩 Analysis chain

LGTM: drop join import; keep only dirname.

Matches the new import.meta.resolve(\${value}/package.json`)` approach and avoids path-concat pitfalls.

Run to ensure no stale join(value, 'package.json') patterns remain in the repo:


🏁 Script executed:

#!/bin/bash
rg -nP -C2 '\bjoin\s*\(\s*value\s*,\s*["\']package\.json["\']\s*\)'

Length of output: 68


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Searching for exact join(value, 'package.json') patterns..."
rg -nP -C2 '\bjoin\s*\(\s*[^,)]*value\s*,\s*[\x27\x22]package\.json[\x27\x22]\s*\)' || echo "No exact matches"
echo
echo "Searching (looser) for lines that contain join(...value...package.json)..."
rg -nP -C2 'join\s*\(.*value.*package\.json' || echo "No looser matches"

Length of output: 2143


Fix remaining join(...) usage — replace with import.meta.resolve(${value}/package.json) and drop join import.

Occurrences: code/lib/create-storybook/src/generators/baseGenerator.ts — lines 410 and 417 (calls: return dirname(fileURLToPath(import.meta.resolve(join(value, 'package.json'))))).
Replace join(value, 'package.json') with ${value}/package.json inside import.meta.resolve and remove the join import.

🤖 Prompt for AI Agents
In code/lib/cli-storybook/src/automigrate/fixes/wrap-getAbsolutePath.ts around
lines 75-77 and in code/lib/create-storybook/src/generators/baseGenerator.ts at
lines ~410 and ~417, replace the use of join(value, 'package.json') inside
import.meta.resolve with a template literal `${value}/package.json`, and remove
any import of join from the module; specifically update the two calls that
currently do fileURLToPath(import.meta.resolve(join(value, 'package.json'))) to
use fileURLToPath(import.meta.resolve(`${value}/package.json`)) and delete the
join import and any dead code references.

mainConfig.setBodyDeclaration(
Expand Down
6 changes: 3 additions & 3 deletions code/lib/create-storybook/src/generators/baseGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -399,22 +399,22 @@ export async function baseGenerator(
if (addMainFile) {
const prefixes = shouldApplyRequireWrapperOnPackageNames
? [
'import { join, dirname } from "path"',
'import { dirname } from "path"',
'import { fileURLToPath } from "url"',
language === SupportedLanguage.JAVASCRIPT
? dedent`/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value) {
return dirname(fileURLToPath(import.meta.resolve(join(value, 'package.json'))))
return dirname(fileURLToPath(import.meta.resolve(\`\${value}/package.json\`)))
}`
: dedent`/**
* This function is used to resolve the absolute path of a package.
* It is needed in projects that use Yarn PnP or are set up within a monorepo.
*/
function getAbsolutePath(value: string): any {
return dirname(fileURLToPath(import.meta.resolve(join(value, 'package.json'))))
return dirname(fileURLToPath(import.meta.resolve(\`\${value}/package.json\`)))
}`,
]
: [];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
```js filename=".storybook/main.js" renderer="common" language="js"
import { dirname, join } from 'node:path';
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';

const getAbsolutePath = (packageName) =>
dirname(fileURLToPath(import.meta.resolve(join(packageName, 'package.json'))));
dirname(fileURLToPath(import.meta.resolve(`${packageName}/package.json`)));

export default {
framework: {
Expand All @@ -27,7 +27,7 @@ import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';

const getAbsolutePath = (packageName: string) =>
dirname(fileURLToPath(import.meta.resolve(join(packageName, 'package.json'))));
dirname(fileURLToPath(import.meta.resolve(`${packageName}/package.json`)));

const config: StorybookConfig = {
framework: {
Expand Down
44 changes: 25 additions & 19 deletions test-storybooks/yarn-pnp/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
"stories": [
"../src/**/*.mdx",
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
],
"addons": [
"@chromatic-com/storybook",
"@storybook/addon-docs",
"@storybook/addon-a11y",
"@storybook/addon-vitest"
],
"framework": {
"name": "@storybook/react-vite",
"options": {}
}
};
export default config;
import { fileURLToPath } from "node:url";
import { dirname } from "node:path";
import type { StorybookConfig } from '@storybook/react-vite';

const config: StorybookConfig = {
"stories": [
"../src/**/*.mdx",
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
],
"addons": [
getAbsolutePath("@chromatic-com/storybook"),
getAbsolutePath("@storybook/addon-docs"),
getAbsolutePath("@storybook/addon-a11y"),
getAbsolutePath("@storybook/addon-vitest")
],
"framework": {
"name": getAbsolutePath("@storybook/react-vite"),
"options": {}
}
};
export default config;

function getAbsolutePath(value: string): any {
return dirname(fileURLToPath(import.meta.resolve(`${value}/package.json`)));
}