Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release: Prerelease 8.5.0-alpha.2 #29508

Merged
merged 58 commits into from
Nov 2, 2024
Merged
Changes from 6 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
96af77f
Chore: Fix path to sandbox template file
tobiasdiez Aug 23, 2024
d782224
Chore: Fix moving sandbox from temporary dir to another partition
tobiasdiez Aug 23, 2024
da4975b
Chore: Add output of errors during yarn setup in sandbox
tobiasdiez Aug 23, 2024
9e1084d
Chore: Yarn setup in sandbox works on Windows now
tobiasdiez Aug 23, 2024
fd4b309
Merge branch 'next' into sandbox-improv
tobiasdiez Aug 31, 2024
71c29c6
Merge branch 'next' into sandbox-improv
tobiasdiez Sep 6, 2024
987feb4
SvelteKIT: Support ESM for Vitest test runs
valentinpalkovic Sep 19, 2024
395173f
Next.js: Update dependencies
Oct 2, 2024
d0fb8a5
Merge remote-tracking branch 'origin/next' into next
Oct 2, 2024
ef6e2ce
feat: bun support with npm fallback
stephenjason89 Oct 2, 2024
9af7980
Merge branch 'next' into next
HoncharenkoZhenya Oct 3, 2024
5ec554a
Merge branch 'next' into sandbox-improv
tobiasdiez Oct 4, 2024
7937702
Merge branch 'next' into next
HoncharenkoZhenya Oct 4, 2024
55d22d6
Chore: gracefully handle empty folders on dev machines
tobiasdiez Oct 7, 2024
f3a2521
Merge branch 'next' into next
HoncharenkoZhenya Oct 8, 2024
5a4d779
Merge branch 'next' into next
HoncharenkoZhenya Oct 9, 2024
7bf0947
Merge branch 'next' into next
HoncharenkoZhenya Oct 10, 2024
11e4cb9
Merge branch 'next' into next
HoncharenkoZhenya Oct 11, 2024
05a44c8
Merge branch 'next' into next
HoncharenkoZhenya Oct 13, 2024
dd72ea8
Merge branch 'next' into next
HoncharenkoZhenya Oct 14, 2024
c0003af
Merge branch 'next' into next
HoncharenkoZhenya Oct 18, 2024
984d118
Merge branch 'next' into next
HoncharenkoZhenya Oct 19, 2024
c34b32f
Merge branch 'next' into next
HoncharenkoZhenya Oct 21, 2024
9b6a437
Merge branch 'next' into next
HoncharenkoZhenya Oct 22, 2024
35ca913
Merge branch 'next' into next
HoncharenkoZhenya Oct 24, 2024
bebaa3b
Ensure consistent absolute path for Next.js-bundled react and react-dom
sentience Oct 24, 2024
6d78a22
Merge branch 'next' into next
HoncharenkoZhenya Oct 28, 2024
3095d0c
Merge remote-tracking branch 'origin/next' into pr/tobiasdiez/28965
valentinpalkovic Oct 28, 2024
ee5a4f6
Refactor sandbox generate script to remove temporary directory
valentinpalkovic Oct 28, 2024
c9350ee
Merge remote-tracking branch 'origin/next' into pr/stephenjason89/29267
valentinpalkovic Oct 28, 2024
8773f66
Refactor: Remove unused getNpmVersion method from BUNProxy and NPMProxy
valentinpalkovic Oct 28, 2024
d499768
Refactor: Add support for BUN package manager
valentinpalkovic Oct 28, 2024
1523974
Refactor: Update BUNProxy to support remote run command
valentinpalkovic Oct 28, 2024
c56ec94
Merge remote-tracking branch 'origin/next' into pr/tobiasdiez/29287
valentinpalkovic Oct 30, 2024
cb540e4
Fix spelling in comment
sentience Oct 31, 2024
e8a9166
Enable scopedResolve to accept script file references
sentience Oct 31, 2024
e9ee80d
Merge remote-tracking branch 'origin/next' into fix-nextjs-react-path…
sentience Oct 31, 2024
0d6c4e0
Only render the TestingModule component in development mode
yannbf Oct 31, 2024
4632519
Merge branch 'next' into yann/hide-testing-module-on-prod
yannbf Oct 31, 2024
e763421
refactor logic
yannbf Oct 31, 2024
01c02bc
Merge branch 'yann/hide-testing-module-on-prod' of github.com:storybo…
yannbf Oct 31, 2024
54c8712
refactor
yannbf Oct 31, 2024
4b49438
Add capability for groups to TooltipLinkList, use it for main menu an…
ghengeveld Nov 1, 2024
18b4710
Indent all groups together
ghengeveld Nov 1, 2024
4c0ac6f
Merge pull request #29287 from tobiasdiez/oldDir
valentinpalkovic Nov 1, 2024
fb79a2b
Merge pull request #29267 from stephenjason89/feat/bun-compatibility
valentinpalkovic Nov 1, 2024
db6bb01
Merge pull request #28965 from tobiasdiez/sandbox-improv
valentinpalkovic Nov 1, 2024
6c829c5
Merge pull request #29444 from sentience/fix-nextjs-react-paths-in-mo…
valentinpalkovic Nov 1, 2024
bc837ac
Merge pull request #29264 from HoncharenkoZhenya/next
valentinpalkovic Nov 1, 2024
f85d62c
Merge branch 'next' into valentin/fix-svelte-vite-plugin
valentinpalkovic Nov 1, 2024
3b5851a
Merge pull request #29157 from storybookjs/valentin/fix-svelte-vite-p…
valentinpalkovic Nov 1, 2024
b02bc0a
Update TagsFilterPanel to use link groups
ghengeveld Nov 1, 2024
6663c5e
Update CHANGELOG.md for v8.4.1 [skip ci]
storybook-bot Nov 1, 2024
46e37f1
Merge pull request #29501 from storybookjs/yann/hide-testing-module-o…
yannbf Nov 1, 2024
5a4322c
Merge pull request #29507 from storybookjs/dropdown-menu-groups
ghengeveld Nov 1, 2024
a10154e
CLI: Fix Solid init by installing `@storybook/test`
shilman Nov 2, 2024
d130f0c
Merge pull request #29514 from storybookjs/shilman/fix-solid-init
shilman Nov 2, 2024
2a0de12
Write changelog for 8.5.0-alpha.2 [skip ci]
storybook-bot Nov 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/addons/themes/postinstall.js
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ const PACKAGE_MANAGER_TO_COMMAND = {
pnpm: ['pnpm', 'dlx'],
yarn1: ['npx'],
yarn2: ['yarn', 'dlx'],
bun: ['bunx'],
};

const selectPackageManagerCommand = (packageManager) => PACKAGE_MANAGER_TO_COMMAND[packageManager];
332 changes: 332 additions & 0 deletions code/core/src/common/js-package-manager/BUNProxy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,332 @@
import { existsSync, readFileSync } from 'node:fs';
import { platform } from 'node:os';
import { join } from 'node:path';

import { logger } from '@storybook/core/node-logger';
import { FindPackageVersionsError } from '@storybook/core/server-errors';

import { findUp } from 'find-up';
import sort from 'semver/functions/sort.js';
import { dedent } from 'ts-dedent';

import { createLogStream } from '../utils/cli';
import { JsPackageManager } from './JsPackageManager';
import type { PackageJson } from './PackageJson';
import type { InstallationMetadata, PackageMetadata } from './types';

type NpmDependency = {
version: string;
resolved?: string;
overridden?: boolean;
dependencies?: NpmDependencies;
};

type NpmDependencies = {
[key: string]: NpmDependency;
};

export type NpmListOutput = {
dependencies: NpmDependencies;
};

const NPM_ERROR_REGEX = /npm ERR! code (\w+)/;
const NPM_ERROR_CODES = {
E401: 'Authentication failed or is required.',
E403: 'Access to the resource is forbidden.',
E404: 'Requested resource not found.',
EACCES: 'Permission issue.',
EAI_FAIL: 'DNS lookup failed.',
EBADENGINE: 'Engine compatibility check failed.',
EBADPLATFORM: 'Platform not supported.',
ECONNREFUSED: 'Connection refused.',
ECONNRESET: 'Connection reset.',
EEXIST: 'File or directory already exists.',
EINVALIDTYPE: 'Invalid type encountered.',
EISGIT: 'Git operation failed or conflicts with an existing file.',
EJSONPARSE: 'Error parsing JSON data.',
EMISSINGARG: 'Required argument missing.',
ENEEDAUTH: 'Authentication needed.',
ENOAUDIT: 'No audit available.',
ENOENT: 'File or directory does not exist.',
ENOGIT: 'Git not found or failed to run.',
ENOLOCK: 'Lockfile missing.',
ENOSPC: 'Insufficient disk space.',
ENOTFOUND: 'Resource not found.',
EOTP: 'One-time password required.',
EPERM: 'Permission error.',
EPUBLISHCONFLICT: 'Conflict during package publishing.',
ERESOLVE: 'Dependency resolution error.',
EROFS: 'File system is read-only.',
ERR_SOCKET_TIMEOUT: 'Socket timed out.',
ETARGET: 'Package target not found.',
ETIMEDOUT: 'Operation timed out.',
ETOOMANYARGS: 'Too many arguments provided.',
EUNKNOWNTYPE: 'Unknown type encountered.',
};

export class BUNProxy extends JsPackageManager {
readonly type = 'bun';

installArgs: string[] | undefined;

async initPackageJson() {
await this.executeCommand({ command: 'bun', args: ['init'] });
}

getRunStorybookCommand(): string {
return 'bun run storybook';
}

getRunCommand(command: string): string {
return `bun run ${command}`;
}

getRemoteRunCommand(): string {
return 'bunx';
}

public async getPackageJSON(
packageName: string,
basePath = this.cwd
): Promise<PackageJson | null> {
const packageJsonPath = await findUp(
(dir) => {
const possiblePath = join(dir, 'node_modules', packageName, 'package.json');
return existsSync(possiblePath) ? possiblePath : undefined;
},
{ cwd: basePath }
);

if (!packageJsonPath) {
return null;
}

const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
return packageJson;
}

getInstallArgs(): string[] {
if (!this.installArgs) {
this.installArgs = [];
}
return this.installArgs;
}

public runPackageCommandSync(
command: string,
args: string[],
cwd?: string,
stdio?: 'pipe' | 'inherit'
): string {
return this.executeCommandSync({
command: 'bun',
args: ['run', command, ...args],
cwd,
stdio,
});
}

public async runPackageCommand(command: string, args: string[], cwd?: string): Promise<string> {
return this.executeCommand({
command: 'bun',
args: ['run', command, ...args],
cwd,
});
}

public async findInstallations(pattern: string[], { depth = 99 }: { depth?: number } = {}) {
const exec = async ({ packageDepth }: { packageDepth: number }) => {
const pipeToNull = platform() === 'win32' ? '2>NUL' : '2>/dev/null';
return this.executeCommand({
command: 'npm',
args: ['ls', '--json', `--depth=${packageDepth}`, pipeToNull],
env: {
FORCE_COLOR: 'false',
},
});
};

try {
const commandResult = await exec({ packageDepth: depth });
const parsedOutput = JSON.parse(commandResult);

return this.mapDependencies(parsedOutput, pattern);
} catch (e) {
// when --depth is higher than 0, npm can return a non-zero exit code
// in case the user's project has peer dependency issues. So we try again with no depth
try {
const commandResult = await exec({ packageDepth: 0 });
const parsedOutput = JSON.parse(commandResult);

return this.mapDependencies(parsedOutput, pattern);
} catch (err) {
logger.warn(`An issue occurred while trying to find dependencies metadata using npm.`);
return undefined;
}
}
}

protected getResolutions(packageJson: PackageJson, versions: Record<string, string>) {
return {
overrides: {
...packageJson.overrides,
...versions,
},
};
}

protected async runInstall() {
await this.executeCommand({
command: 'bun',
args: ['install', ...this.getInstallArgs()],
stdio: 'inherit',
});
}

public async getRegistryURL() {
const res = await this.executeCommand({
command: 'npm',
// "npm config" commands are not allowed in workspaces per default
// https://github.com/npm/cli/issues/6099#issuecomment-1847584792
args: ['config', 'get', 'registry', '-ws=false', '-iwr'],
});
const url = res.trim();
return url === 'undefined' ? undefined : url;
}

protected async runAddDeps(dependencies: string[], installAsDevDependencies: boolean) {
const { logStream, readLogFile, moveLogFile, removeLogFile } = await createLogStream();
let args = [...dependencies];

if (installAsDevDependencies) {
args = ['-D', ...args];
}

try {
await this.executeCommand({
command: 'bun',
args: ['add', ...args, ...this.getInstallArgs()],
stdio: process.env.CI ? 'inherit' : ['ignore', logStream, logStream],
});
} catch (err) {
const stdout = await readLogFile();

const errorMessage = this.parseErrorFromLogs(stdout);

await moveLogFile();

throw new Error(
dedent`${errorMessage}

Please check the logfile generated at ./storybook.log for troubleshooting and try again.`
);
}

await removeLogFile();
}

protected async runRemoveDeps(dependencies: string[]) {
const args = [...dependencies];

await this.executeCommand({
command: 'bun',
args: ['remove', ...args, ...this.getInstallArgs()],
stdio: 'inherit',
});
}

protected async runGetVersions<T extends boolean>(
packageName: string,
fetchAllVersions: T
): Promise<T extends true ? string[] : string> {
const args = [fetchAllVersions ? 'versions' : 'version', '--json'];
try {
const commandResult = await this.executeCommand({
command: 'npm',
args: ['info', packageName, ...args],
});

const parsedOutput = JSON.parse(commandResult);

if (parsedOutput.error?.summary) {
// this will be handled in the catch block below
throw parsedOutput.error.summary;
}

return parsedOutput;
} catch (error) {
throw new FindPackageVersionsError({
error,
packageManager: 'NPM',
packageName,
});
Comment on lines +259 to +262
Copy link
Contributor

Choose a reason for hiding this comment

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

logic: Error message shows NPM as package manager even though this is the Bun proxy. Should show Bun instead.

}
}

/**
* @param input The output of `npm ls --json`
* @param pattern A list of package names to filter the result. * can be used as a placeholder
*/
protected mapDependencies(input: NpmListOutput, pattern: string[]): InstallationMetadata {
const acc: Record<string, PackageMetadata[]> = {};
const existingVersions: Record<string, string[]> = {};
const duplicatedDependencies: Record<string, string[]> = {};

const recurse = ([name, packageInfo]: [string, NpmDependency]): void => {
// transform pattern into regex where `*` is replaced with `.*`
if (!name || !pattern.some((p) => new RegExp(`^${p.replace(/\*/g, '.*')}$`).test(name))) {
return;
}

const value = {
version: packageInfo.version,
location: '',
};

if (!existingVersions[name]?.includes(value.version)) {
if (acc[name]) {
acc[name].push(value);
} else {
acc[name] = [value];
}
existingVersions[name] = sort([...(existingVersions[name] || []), value.version]);

if (existingVersions[name].length > 1) {
duplicatedDependencies[name] = existingVersions[name];
}
}

if (packageInfo.dependencies) {
Object.entries(packageInfo.dependencies).forEach(recurse);
}
};

Object.entries(input.dependencies).forEach(recurse);

return {
dependencies: acc,
duplicatedDependencies,
infoCommand: 'npm ls --depth=1',
dedupeCommand: 'npm dedupe',
Comment on lines +309 to +310
Copy link
Contributor

Choose a reason for hiding this comment

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

style: Info and dedupe commands show npm commands but should reflect Bun equivalents if they exist

};
}

public parseErrorFromLogs(logs: string): string {
let finalMessage = 'NPM error';
const match = logs.match(NPM_ERROR_REGEX);

if (match) {
const errorCode = match[1] as keyof typeof NPM_ERROR_CODES;
if (errorCode) {
finalMessage = `${finalMessage} ${errorCode}`;
}

const errorMessage = NPM_ERROR_CODES[errorCode];
if (errorMessage) {
finalMessage = `${finalMessage} - ${errorMessage}`;
}
}

return finalMessage.trim();
}
}
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ import type { InstallationMetadata } from './types';

const logger = console;

export type PackageManagerName = 'npm' | 'yarn1' | 'yarn2' | 'pnpm';
export type PackageManagerName = 'npm' | 'yarn1' | 'yarn2' | 'pnpm' | 'bun';

type StorybookPackage = keyof typeof storybookPackagesVersions;

Loading