diff --git a/CHANGELOG.md b/CHANGELOG.md index dd75af133731..f3e13bedee71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## 8.3.5 + +- CLI: Update the React Native init to include v8 dependencies - [#29273](https://github.com/storybookjs/storybook/pull/29273), thanks @dannyhw! +- Vitest plugin: Fix renamed export stories - [#29250](https://github.com/storybookjs/storybook/pull/29250), thanks @shilman! + ## 8.3.4 - Addon Test: Support story name as test description - [#29147](https://github.com/storybookjs/storybook/pull/29147), thanks @InfiniteXyy! diff --git a/CHANGELOG.prerelease.md b/CHANGELOG.prerelease.md index 40c0aa95376f..8c9a74c850e4 100644 --- a/CHANGELOG.prerelease.md +++ b/CHANGELOG.prerelease.md @@ -1,3 +1,8 @@ +## 8.4.0-alpha.5 + +- Core: Migrate from `express` to `polka` - [#29230](https://github.com/storybookjs/storybook/pull/29230), thanks @43081j! +- Core: Remove dependence on `file-system-cache` - [#29256](https://github.com/storybookjs/storybook/pull/29256), thanks @ndelangen! + ## 8.4.0-alpha.4 - Blocks: Prebundle `es-toolkit` - [#29259](https://github.com/storybookjs/storybook/pull/29259), thanks @JReinhold! diff --git a/code/__mocks__/fs.ts b/code/__mocks__/fs.ts index 50e34e8e4ca1..f617d31141f6 100644 --- a/code/__mocks__/fs.ts +++ b/code/__mocks__/fs.ts @@ -19,6 +19,7 @@ export const realpathSync = vi.fn(); export const readdir = vi.fn(); export const readdirSync = vi.fn(); export const readlinkSync = vi.fn(); +export const mkdirSync = vi.fn(); export default { __setMockFiles, @@ -29,4 +30,5 @@ export default { readdir, readdirSync, readlinkSync, + mkdirSync, }; diff --git a/code/builders/builder-vite/package.json b/code/builders/builder-vite/package.json index b9bff0b1c02a..dc7e9dd9c6b7 100644 --- a/code/builders/builder-vite/package.json +++ b/code/builders/builder-vite/package.json @@ -47,15 +47,15 @@ "@types/find-cache-dir": "^3.2.1", "browser-assert": "^1.2.1", "es-module-lexer": "^1.5.0", - "express": "^4.19.2", "find-cache-dir": "^3.0.0", "magic-string": "^0.30.0", "ts-dedent": "^2.0.0" }, "devDependencies": { - "@types/express": "^4.17.21", "@types/node": "^22.0.0", "glob": "^10.0.0", + "polka": "^1.0.0-next.28", + "sirv": "^2.0.4", "slash": "^5.0.0", "typescript": "^5.3.2", "vite": "^4.0.4" diff --git a/code/builders/builder-vite/src/index.ts b/code/builders/builder-vite/src/index.ts index 0962e1676e4e..9ab66f2771d0 100644 --- a/code/builders/builder-vite/src/index.ts +++ b/code/builders/builder-vite/src/index.ts @@ -3,10 +3,9 @@ import { cp, readFile } from 'node:fs/promises'; import { join, parse } from 'node:path'; import { NoStatsForViteDevError } from 'storybook/internal/server-errors'; -import type { Options } from 'storybook/internal/types'; +import type { Middleware, Options } from 'storybook/internal/types'; -import type { RequestHandler } from 'express'; -import express from 'express'; +import sirv from 'sirv'; import { corePath } from 'storybook/core-path'; import type { ViteDevServer } from 'vite'; @@ -20,16 +19,18 @@ export { hasVitePlugins } from './utils/has-vite-plugins'; export * from './types'; -function iframeMiddleware(options: Options, server: ViteDevServer): RequestHandler { +function iframeMiddleware(options: Options, server: ViteDevServer): Middleware { return async (req, res, next) => { - if (!req.url.match(/^\/iframe\.html($|\?)/)) { + if (!req.url || !req.url.match(/^\/iframe\.html($|\?)/)) { next(); return; } + // the base isn't used for anything, but it's required by the URL constructor + const url = new URL(req.url, 'http://localhost:6006'); // We need to handle `html-proxy` params for style tag HMR https://github.com/storybookjs/builder-vite/issues/266#issuecomment-1055677865 // e.g. /iframe.html?html-proxy&index=0.css - if (req.query['html-proxy'] !== undefined) { + if (url.searchParams.has('html-proxy')) { next(); return; } @@ -40,7 +41,9 @@ function iframeMiddleware(options: Options, server: ViteDevServer): RequestHandl const generated = await transformIframeHtml(indexHtml, options); const transformed = await server.transformIndexHtml('/iframe.html', generated); res.setHeader('Content-Type', 'text/html'); - res.status(200).send(transformed); + res.statusCode = 200; + res.write(transformed); + res.end(); }; } @@ -59,10 +62,14 @@ export const start: ViteBuilder['start'] = async ({ server = await createViteServer(options as Options, devServer); const previewResolvedDir = join(corePath, 'dist/preview'); - const previewDirOrigin = previewResolvedDir; - - router.use(`/sb-preview`, express.static(previewDirOrigin, { immutable: true, maxAge: '5m' })); - + router.use( + '/sb-preview', + sirv(previewResolvedDir, { + maxAge: 300000, + dev: true, + immutable: true, + }) + ); router.use(iframeMiddleware(options as Options, server)); router.use(server.middlewares); @@ -81,10 +88,8 @@ export const build: ViteBuilder['build'] = async ({ options }) => { const viteCompilation = viteBuild(options as Options); const previewResolvedDir = join(corePath, 'dist/preview'); - const previewDirOrigin = previewResolvedDir; const previewDirTarget = join(options.outputDir || '', `sb-preview`); - - const previewFiles = cp(previewDirOrigin, previewDirTarget, { + const previewFiles = cp(previewResolvedDir, previewDirTarget, { filter: (src) => { const { ext } = parse(src); if (ext) { diff --git a/code/builders/builder-vite/src/list-stories.ts b/code/builders/builder-vite/src/list-stories.ts index 5eefb9b8fb74..d5b417f2553c 100644 --- a/code/builders/builder-vite/src/list-stories.ts +++ b/code/builders/builder-vite/src/list-stories.ts @@ -3,6 +3,7 @@ import { isAbsolute, join } from 'node:path'; import { commonGlobOptions, normalizeStories } from 'storybook/internal/common'; import type { Options } from 'storybook/internal/types'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import slash from 'slash'; diff --git a/code/builders/builder-vite/src/plugins/code-generator-plugin.ts b/code/builders/builder-vite/src/plugins/code-generator-plugin.ts index 77509b97cf93..79dba3844060 100644 --- a/code/builders/builder-vite/src/plugins/code-generator-plugin.ts +++ b/code/builders/builder-vite/src/plugins/code-generator-plugin.ts @@ -50,7 +50,7 @@ export function codeGeneratorPlugin(options: Options): Plugin { }, config(config, { command }) { // If we are building the static distribution, add iframe.html as an entry. - // In development mode, it's not an entry - instead, we use an express middleware + // In development mode, it's not an entry - instead, we use a middleware // to serve iframe.html. The reason is that Vite's dev server (at the time of writing) // does not support virtual files as entry points. if (command === 'build') { diff --git a/code/builders/builder-webpack5/package.json b/code/builders/builder-webpack5/package.json index e6f8716ffc4f..0c122fc4a33a 100644 --- a/code/builders/builder-webpack5/package.json +++ b/code/builders/builder-webpack5/package.json @@ -72,7 +72,6 @@ "constants-browserify": "^1.0.0", "css-loader": "^6.7.1", "es-module-lexer": "^1.5.0", - "express": "^4.19.2", "fork-ts-checker-webpack-plugin": "^8.0.0", "html-webpack-plugin": "^5.5.0", "magic-string": "^0.30.5", @@ -95,6 +94,7 @@ "@types/terser-webpack-plugin": "^5.2.0", "@types/webpack-hot-middleware": "^2.25.6", "pretty-hrtime": "^1.0.3", + "sirv": "^2.0.4", "slash": "^5.0.0", "typescript": "^5.3.2" }, diff --git a/code/builders/builder-webpack5/src/index.ts b/code/builders/builder-webpack5/src/index.ts index ffc11812562b..a8af6e699ad4 100644 --- a/code/builders/builder-webpack5/src/index.ts +++ b/code/builders/builder-webpack5/src/index.ts @@ -12,8 +12,8 @@ import type { Builder, Options } from 'storybook/internal/types'; import { checkWebpackVersion } from '@storybook/core-webpack'; -import express from 'express'; import prettyTime from 'pretty-hrtime'; +import sirv from 'sirv'; import { corePath } from 'storybook/core-path'; import type { Configuration, Stats, StatsOptions } from 'webpack'; import webpack, { ProgressPlugin } from 'webpack'; @@ -137,7 +137,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({ } yield; - const modulesCount = (await options.cache?.get('modulesCount').catch(() => {})) || 1000; + const modulesCount = await options.cache?.get('modulesCount', 1000); let totalModules: number; let value = 0; @@ -147,7 +147,7 @@ const starter: StarterFunction = async function* starterGeneratorFn({ const progress = { value, message: message.charAt(0).toUpperCase() + message.slice(1) }; if (message === 'building') { // arg3 undefined in webpack5 - const counts = (arg3 && arg3.match(/(\d+)\/(\d+)/)) || []; + const counts = (arg3 && arg3.match(/entries (\d+)\/(\d+)/)) || []; const complete = parseInt(counts[1], 10); const total = parseInt(counts[2], 10); if (!Number.isNaN(complete) && !Number.isNaN(total)) { @@ -180,10 +180,14 @@ const starter: StarterFunction = async function* starterGeneratorFn({ compilation = webpackDevMiddleware(compiler, middlewareOptions); const previewResolvedDir = join(corePath, 'dist/preview'); - const previewDirOrigin = previewResolvedDir; - - router.use(`/sb-preview`, express.static(previewDirOrigin, { immutable: true, maxAge: '5m' })); - + router.use( + '/sb-preview', + sirv(previewResolvedDir, { + maxAge: 300000, + dev: true, + immutable: true, + }) + ); router.use(compilation); router.use(webpackHotMiddleware(compiler, { log: false })); @@ -289,10 +293,8 @@ const builder: BuilderFunction = async function* builderGeneratorFn({ startTime, }); const previewResolvedDir = join(corePath, 'dist/preview'); - const previewDirOrigin = previewResolvedDir; const previewDirTarget = join(options.outputDir || '', `sb-preview`); - - const previewFiles = cp(previewDirOrigin, previewDirTarget, { + const previewFiles = cp(previewResolvedDir, previewDirTarget, { filter: (src) => { const { ext } = parse(src); if (ext) { diff --git a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts index ea8b55d4973c..763f2bf15646 100644 --- a/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts +++ b/code/builders/builder-webpack5/src/preview/iframe-webpack.config.ts @@ -72,7 +72,7 @@ export default async ( docsOptions, entries, nonNormalizedStories, - modulesCount = 1000, + modulesCount, build, tagsOptions, ] = await Promise.all([ @@ -86,7 +86,7 @@ export default async ( presets.apply('docs'), presets.apply('entries', []), presets.apply('stories', []), - options.cache?.get('modulesCount').catch(() => {}), + options.cache?.get('modulesCount', 1000), options.presets.apply('build'), presets.apply('tags', {}), ]); diff --git a/code/core/package.json b/code/core/package.json index 9a8dff954fdb..09a26d547178 100644 --- a/code/core/package.json +++ b/code/core/package.json @@ -278,12 +278,10 @@ }, "dependencies": { "@storybook/csf": "^0.1.11", - "@types/express": "^4.17.21", "better-opn": "^3.0.2", "browser-assert": "^1.2.1", "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0", "esbuild-register": "^3.5.0", - "express": "^4.19.2", "jsdoc-type-pratt-parser": "^4.0.0", "process": "^0.11.10", "recast": "^0.23.5", @@ -307,6 +305,7 @@ "@emotion/use-insertion-effect-with-fallbacks": "^1.0.1", "@fal-works/esbuild-plugin-global-externals": "^2.1.2", "@ndelangen/get-tarball": "^3.0.7", + "@polka/compression": "^1.0.0-next.28", "@popperjs/core": "^2.6.0", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-scroll-area": "1.2.0-rc.7", @@ -316,7 +315,6 @@ "@storybook/icons": "^1.2.10", "@tanstack/react-virtual": "^3.3.0", "@testing-library/react": "^14.0.0", - "@types/compression": "^1.7.0", "@types/cross-spawn": "^6.0.2", "@types/detect-port": "^1.3.0", "@types/diff": "^5.0.9", @@ -346,7 +344,6 @@ "cli-table3": "^0.6.1", "commander": "^12.1.0", "comment-parser": "^1.4.1", - "compression": "^1.7.4", "copy-to-clipboard": "^3.3.1", "cross-spawn": "^7.0.3", "css": "^3.0.0", @@ -362,10 +359,8 @@ "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0", "esbuild-plugin-alias": "^0.2.1", "execa": "^8.0.1", - "express": "^4.19.2", "fd-package-json": "^1.2.0", "fetch-retry": "^6.0.0", - "file-system-cache": "^2.4.4", "find-cache-dir": "^5.0.0", "find-up": "^7.0.0", "flush-promises": "^1.0.2", @@ -387,6 +382,7 @@ "picomatch": "^2.3.0", "picoquery": "^1.4.0", "polished": "^4.2.2", + "polka": "^1.0.0-next.28", "prettier": "^3.2.5", "pretty-hrtime": "^1.0.3", "prompts": "^2.4.0", @@ -402,6 +398,7 @@ "react-transition-group": "^4.4.5", "require-from-string": "^2.0.2", "resolve-from": "^5.0.0", + "sirv": "^2.0.4", "slash": "^5.0.0", "source-map": "^0.7.4", "store2": "^2.14.2", diff --git a/code/core/src/builder-manager/index.ts b/code/core/src/builder-manager/index.ts index b068caf206c7..faad0a288acf 100644 --- a/code/core/src/builder-manager/index.ts +++ b/code/core/src/builder-manager/index.ts @@ -9,7 +9,7 @@ import { logger } from '@storybook/core/node-logger'; import { globalExternals } from '@fal-works/esbuild-plugin-global-externals'; import { pnpPlugin } from '@yarnpkg/esbuild-plugin-pnp'; import aliasPlugin from 'esbuild-plugin-alias'; -import express from 'express'; +import sirv from 'sirv'; import type { BuilderBuildResult, @@ -26,6 +26,7 @@ import { wrapManagerEntries } from './utils/managerEntries'; import { safeResolve } from './utils/safeResolve'; import { getTemplatePath, renderHTML } from './utils/template'; +const isRootPath = /^\/($|\?)/; let compilation: Compilation; let asyncIterator: ReturnType | ReturnType; @@ -165,8 +166,22 @@ const starter: StarterFunction = async function* starterGeneratorFn({ 'manager' ); - router.use(`/sb-addons`, express.static(addonsDir, { immutable: true, maxAge: '5m' })); - router.use(`/sb-manager`, express.static(coreDirOrigin, { immutable: true, maxAge: '5m' })); + router.use( + '/sb-addons', + sirv(addonsDir, { + maxAge: 300000, + dev: true, + immutable: true, + }) + ); + router.use( + '/sb-manager', + sirv(coreDirOrigin, { + maxAge: 300000, + dev: true, + immutable: true, + }) + ); const { cssFiles, jsFiles } = await readOrderedFiles(addonsDir, compilation?.outputFiles); @@ -193,15 +208,19 @@ const starter: StarterFunction = async function* starterGeneratorFn({ yield; - router.use(`/`, ({ path }, res, next) => { - if (path === '/') { - res.status(200).send(html); + router.use('/', ({ url }, res, next) => { + if (url && isRootPath.test(url)) { + res.statusCode = 200; + res.write(html); + res.end(); } else { next(); } }); - router.use(`/index.html`, ({ path }, res) => { - res.status(200).send(html); + router.use(`/index.html`, (req, res) => { + res.statusCode = 200; + res.write(html); + res.end(); }); return { @@ -250,7 +269,6 @@ const builder: BuilderFunction = async function* builderGeneratorFn({ startTime, // TODO: this doesn't watch, we should change this to use the esbuild watch API: https://esbuild.github.io/api/#watch compilation = await instance({ ...config, - minify: true, }); diff --git a/code/core/src/cli/detect.test.ts b/code/core/src/cli/detect.test.ts index 95c1b126dca3..ea7f8139fda3 100644 --- a/code/core/src/cli/detect.test.ts +++ b/code/core/src/cli/detect.test.ts @@ -24,6 +24,7 @@ vi.mock('fs', () => ({ readdirSync: vi.fn(), readlinkSync: vi.fn(), default: vi.fn(), + mkdirSync: vi.fn(), })); vi.mock('@storybook/core/node-logger'); diff --git a/code/core/src/cli/dev.ts b/code/core/src/cli/dev.ts index 6d05f140fa38..26ff6250f3a8 100644 --- a/code/core/src/cli/dev.ts +++ b/code/core/src/cli/dev.ts @@ -44,14 +44,16 @@ export const dev = async (cliOptions: CLIOptions) => { const packageJson = await findPackage(__dirname); invariant(packageJson, 'Failed to find the closest package.json file.'); + type Options = Parameters[0]; + const options = { ...cliOptions, configDir: cliOptions.configDir || './.storybook', configType: 'DEVELOPMENT', ignorePreview: !!cliOptions.previewUrl && !cliOptions.forceBuildPreview, - cache, + cache: cache as any, packageJson, - } as Parameters[0]; + } as Options; await withTelemetry( 'dev', diff --git a/code/core/src/common/js-package-manager/JsPackageManager.ts b/code/core/src/common/js-package-manager/JsPackageManager.ts index 5b0bdde0fdb6..21f870852d4d 100644 --- a/code/core/src/common/js-package-manager/JsPackageManager.ts +++ b/code/core/src/common/js-package-manager/JsPackageManager.ts @@ -2,8 +2,8 @@ import { existsSync, readFileSync } from 'node:fs'; import { readFile, writeFile } from 'node:fs/promises'; import { dirname, resolve } from 'node:path'; -import type { CommonOptions } from 'execa'; -import { execaCommand, execaCommandSync } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies +import { type CommonOptions, execaCommand, execaCommandSync } from 'execa'; import picocolors from 'picocolors'; import { gt, satisfies } from 'semver'; import invariant from 'tiny-invariant'; diff --git a/code/core/src/common/utils/file-cache.ts b/code/core/src/common/utils/file-cache.ts index de65cc988383..590ddf60d608 100644 --- a/code/core/src/common/utils/file-cache.ts +++ b/code/core/src/common/utils/file-cache.ts @@ -1,11 +1,158 @@ -import * as fsc from 'file-system-cache'; +/** This file is a modified copy from https://git.nfp.is/TheThing/fs-cache-fast */ +import { createHash, randomBytes } from 'node:crypto'; +import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'; +import { readFile, readdir, rm, writeFile } from 'node:fs/promises'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; -// @ts-expect-error (needed due to it's use of `exports.default`) -const Cache = (fsc.default.default || fsc.default) as typeof fsc.default; +interface FileSystemCacheOptions { + ns?: string; + prefix?: string; + hash_alg?: string; + basePath?: string; + ttl?: number; +} + +interface CacheItem { + key: string; + content?: any; + value?: any; +} + +interface CacheSetOptions { + ttl?: number; + encoding?: BufferEncoding; +} + +export class FileSystemCache { + private prefix: string; + + private hash_alg: string; + + private cache_dir: string; + + private ttl: number; + + constructor(options: FileSystemCacheOptions = {}) { + this.prefix = (options.ns || options.prefix || '') + '-'; + this.hash_alg = options.hash_alg || 'md5'; + this.cache_dir = + options.basePath || join(tmpdir(), randomBytes(15).toString('base64').replace(/\//g, '-')); + this.ttl = options.ttl || 0; + createHash(this.hash_alg); // Verifies hash algorithm is available + mkdirSync(this.cache_dir, { recursive: true }); + } + + private generateHash(name: string): string { + return join(this.cache_dir, this.prefix + createHash(this.hash_alg).update(name).digest('hex')); + } + + private isExpired(parsed: { ttl?: number }, now: number): boolean { + return parsed.ttl != null && now > parsed.ttl; + } + + private parseCacheData(data: string, fallback: T | null): T | null { + const parsed = JSON.parse(data); + return this.isExpired(parsed, Date.now()) ? fallback : (parsed.content as T); + } -export type Options = Parameters['0']; -export type FileSystemCache = ReturnType; + private parseSetData(key: string, data: T, opts: CacheSetOptions = {}): string { + const ttl = opts.ttl ?? this.ttl; + return JSON.stringify({ key, content: data, ...(ttl && { ttl: Date.now() + ttl * 1000 }) }); + } + + public async get(name: string, fallback?: T): Promise { + try { + const data = await readFile(this.generateHash(name), 'utf8'); + return this.parseCacheData(data, fallback) as T; + } catch { + return fallback as T; + } + } + + public getSync(name: string, fallback?: T): T { + try { + const data = readFileSync(this.generateHash(name), 'utf8'); + return this.parseCacheData(data, fallback) as T; + } catch { + return fallback as T; + } + } + + public async set( + name: string, + data: T, + orgOpts: CacheSetOptions | number = {} + ): Promise { + const opts: CacheSetOptions = typeof orgOpts === 'number' ? { ttl: orgOpts } : orgOpts; + await writeFile(this.generateHash(name), this.parseSetData(name, data, opts), { + encoding: opts.encoding || 'utf8', + }); + } + + public setSync(name: string, data: T, orgOpts: CacheSetOptions | number = {}): void { + const opts: CacheSetOptions = typeof orgOpts === 'number' ? { ttl: orgOpts } : orgOpts; + writeFileSync(this.generateHash(name), this.parseSetData(name, data, opts), { + encoding: opts.encoding || 'utf8', + }); + } + + public async setMany(items: CacheItem[], options?: CacheSetOptions): Promise { + await Promise.all(items.map((item) => this.set(item.key, item.content ?? item.value, options))); + } + + public setManySync(items: CacheItem[], options?: CacheSetOptions): void { + items.forEach((item) => this.setSync(item.key, item.content ?? item.value, options)); + } + + public async remove(name: string): Promise { + await rm(this.generateHash(name), { force: true }); + } + + public removeSync(name: string): void { + rmSync(this.generateHash(name), { force: true }); + } + + public async clear(): Promise { + const files = await readdir(this.cache_dir); + await Promise.all( + files + .filter((f) => f.startsWith(this.prefix)) + .map((f) => rm(join(this.cache_dir, f), { force: true })) + ); + } + + public clearSync(): void { + readdirSync(this.cache_dir) + .filter((f) => f.startsWith(this.prefix)) + .forEach((f) => rmSync(join(this.cache_dir, f), { force: true })); + } + + public async getAll(): Promise { + const now = Date.now(); + const files = await readdir(this.cache_dir); + const items = await Promise.all( + files + .filter((f) => f.startsWith(this.prefix)) + .map((f) => readFile(join(this.cache_dir, f), 'utf8')) + ); + return items + .map((data) => JSON.parse(data)) + .filter((entry) => entry.content && !this.isExpired(entry, now)); + } + + public async load(): Promise<{ files: CacheItem[] }> { + const res = await this.getAll(); + return { + files: res.map((entry) => ({ + path: this.generateHash(entry.key), + value: entry.content, + key: entry.key, + })), + }; + } +} -export function createFileSystemCache(options: Options): FileSystemCache { - return Cache(options); +export function createFileSystemCache(options: FileSystemCacheOptions): FileSystemCache { + return new FileSystemCache(options); } diff --git a/code/core/src/common/utils/validate-configuration-files.ts b/code/core/src/common/utils/validate-configuration-files.ts index 3e35a6f2bafb..ccd0dba864ea 100644 --- a/code/core/src/common/utils/validate-configuration-files.ts +++ b/code/core/src/common/utils/validate-configuration-files.ts @@ -3,6 +3,7 @@ import { resolve } from 'node:path'; import { once } from '@storybook/core/node-logger'; import { MainFileMissingError } from '@storybook/core/server-errors'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import slash from 'slash'; import { dedent } from 'ts-dedent'; diff --git a/code/core/src/core-server/dev-server.ts b/code/core/src/core-server/dev-server.ts index cdf1027d1872..325d33366514 100644 --- a/code/core/src/core-server/dev-server.ts +++ b/code/core/src/core-server/dev-server.ts @@ -4,8 +4,8 @@ import type { Options } from '@storybook/core/types'; import { logger } from '@storybook/core/node-logger'; import { MissingBuilderError } from '@storybook/core/server-errors'; -import compression from 'compression'; -import express from 'express'; +import compression from '@polka/compression'; +import polka from 'polka'; import invariant from 'tiny-invariant'; import type { StoryIndexGenerator } from './utils/StoryIndexGenerator'; @@ -17,19 +17,13 @@ import { getAccessControlMiddleware } from './utils/getAccessControlMiddleware'; import { getStoryIndexGenerator } from './utils/getStoryIndexGenerator'; import { getMiddleware } from './utils/middleware'; import { openInBrowser } from './utils/open-in-browser'; -import { router } from './utils/router'; import { getServerAddresses } from './utils/server-address'; import { getServer } from './utils/server-init'; import { useStatics } from './utils/server-statics'; export async function storybookDevServer(options: Options) { - const app = express(); - - const [server, features, core] = await Promise.all([ - getServer(app, options), - options.presets.apply('features'), - options.presets.apply('core'), - ]); + const [server, core] = await Promise.all([getServer(options), options.presets.apply('core')]); + const app = polka({ server }); const serverChannel = await options.presets.apply( 'experimental_serverChannel', @@ -39,7 +33,7 @@ export async function storybookDevServer(options: Options) { let indexError: Error | undefined; // try get index generator, if failed, send telemetry without storyCount, then rethrow the error const initializedStoryIndexGenerator: Promise = - getStoryIndexGenerator(features ?? {}, options, serverChannel).catch((err) => { + getStoryIndexGenerator(app, options, serverChannel).catch((err) => { indexError = err; return undefined; }); @@ -53,20 +47,13 @@ export async function storybookDevServer(options: Options) { app.use(getAccessControlMiddleware(core?.crossOriginIsolated ?? false)); app.use(getCachingMiddleware()); - getMiddleware(options.configDir)(router); - - app.use(router); + getMiddleware(options.configDir)(app); const { port, host, initialPath } = options; invariant(port, 'expected options to have a port'); const proto = options.https ? 'https' : 'http'; const { address, networkAddress } = getServerAddresses(port, host, proto, initialPath); - const listening = new Promise((resolve, reject) => { - // @ts-expect-error (Following line doesn't match TypeScript signature at all 🤔) - server.listen({ port, host }, (error: Error) => (error ? reject(error) : resolve())); - }); - if (!core?.builder) { throw new MissingBuilderError(); } @@ -76,7 +63,7 @@ export async function storybookDevServer(options: Options) { const [previewBuilder, managerBuilder] = await Promise.all([ getPreviewBuilder(builderName, options.configDir), getManagerBuilder(), - useStatics(router, options), + useStatics(app, options), ]); if (options.debugWebpack) { @@ -86,7 +73,7 @@ export async function storybookDevServer(options: Options) { const managerResult = await managerBuilder.start({ startTime: process.hrtime(), options, - router, + router: app, server, channel: serverChannel, }); @@ -101,7 +88,7 @@ export async function storybookDevServer(options: Options) { .start({ startTime: process.hrtime(), options, - router, + router: app, server, channel: serverChannel, }) @@ -123,12 +110,17 @@ export async function storybookDevServer(options: Options) { // this is a preview route, the builder has to be started before we can serve it // this handler keeps request to that route pending until the builder is ready to serve it, preventing a 404 - router.get('/iframe.html', (req, res, next) => { + app.use('/iframe.html', (req, res, next) => { // We need to catch here or node will treat any errors thrown by `previewStarted` as // unhandled and exit (even though they are very much handled below) previewStarted.catch(() => {}).then(() => next()); }); + const listening = new Promise((resolve, reject) => { + server.once('error', reject); + app.listen({ port, host }, resolve); + }); + await Promise.all([initializedStoryIndexGenerator, listening]).then(async ([indexGenerator]) => { if (indexGenerator && !options.ci && !options.smokeTest && options.open) { openInBrowser(host ? networkAddress : address); @@ -143,7 +135,7 @@ export async function storybookDevServer(options: Options) { const previewResult = await previewStarted; // Now the preview has successfully started, we can count this as a 'dev' event. - doTelemetry(core, initializedStoryIndexGenerator, options); + doTelemetry(app, core, initializedStoryIndexGenerator, options); return { previewResult, managerResult, address, networkAddress }; } diff --git a/code/core/src/core-server/utils/StoryIndexGenerator.ts b/code/core/src/core-server/utils/StoryIndexGenerator.ts index aed65a46bf6b..164613d7e4c2 100644 --- a/code/core/src/core-server/utils/StoryIndexGenerator.ts +++ b/code/core/src/core-server/utils/StoryIndexGenerator.ts @@ -130,6 +130,7 @@ export class StoryIndexGenerator { const fullGlob = slash(join(specifier.directory, specifier.files)); // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby } = await import('globby'); const files = await globby(fullGlob, { diff --git a/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts b/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts index f1342ad48a9a..87fe8317ea35 100644 --- a/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts +++ b/code/core/src/core-server/utils/__tests__/remove-mdx-stories.test.ts @@ -5,6 +5,7 @@ import { describe, expect, it, vi } from 'vitest'; import { normalizeStoriesEntry } from '@storybook/core/common'; import { type StoriesEntry } from '@storybook/core/types'; +// eslint-disable-next-line depend/ban-dependencies import { glob as globOriginal } from 'glob'; import slash from 'slash'; diff --git a/code/core/src/core-server/utils/doTelemetry.ts b/code/core/src/core-server/utils/doTelemetry.ts index 534d409765e0..0e9b48b8c8f5 100644 --- a/code/core/src/core-server/utils/doTelemetry.ts +++ b/code/core/src/core-server/utils/doTelemetry.ts @@ -1,16 +1,17 @@ import { getPrecedingUpgrade, telemetry } from '@storybook/core/telemetry'; import type { CoreConfig, Options } from '@storybook/core/types'; +import type Polka from 'polka'; import invariant from 'tiny-invariant'; import { sendTelemetryError } from '../withTelemetry'; import type { StoryIndexGenerator } from './StoryIndexGenerator'; import { useStorybookMetadata } from './metadata'; -import { router } from './router'; import { summarizeIndex } from './summarizeIndex'; import { versionStatus } from './versionStatus'; export async function doTelemetry( + app: Polka.Polka, core: CoreConfig, initializedStoryIndexGenerator: Promise, options: Options @@ -52,6 +53,6 @@ export async function doTelemetry( } if (!core?.disableProjectJson) { - useStorybookMetadata(router, options.configDir); + useStorybookMetadata(app, options.configDir); } } diff --git a/code/core/src/core-server/utils/get-caching-middleware.ts b/code/core/src/core-server/utils/get-caching-middleware.ts index d01cb3e5e922..88cc96c2ae70 100644 --- a/code/core/src/core-server/utils/get-caching-middleware.ts +++ b/code/core/src/core-server/utils/get-caching-middleware.ts @@ -1,8 +1,8 @@ -import type { RequestHandler } from 'express'; +import type { Middleware } from '../../types'; -export function getCachingMiddleware(): RequestHandler { +export function getCachingMiddleware(): Middleware { return (req, res, next) => { - res.header('Cache-Control', 'no-store'); + res.setHeader('Cache-Control', 'no-store'); next(); }; } diff --git a/code/core/src/core-server/utils/getAccessControlMiddleware.ts b/code/core/src/core-server/utils/getAccessControlMiddleware.ts index 9eb8851e6a5c..0b5c3428b842 100644 --- a/code/core/src/core-server/utils/getAccessControlMiddleware.ts +++ b/code/core/src/core-server/utils/getAccessControlMiddleware.ts @@ -1,16 +1,16 @@ -import type { RequestHandler } from 'express'; +import type { Middleware } from '../../types'; -export function getAccessControlMiddleware(crossOriginIsolated: boolean): RequestHandler { +export function getAccessControlMiddleware(crossOriginIsolated: boolean): Middleware { return (req, res, next) => { - res.header('Access-Control-Allow-Origin', '*'); - res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); + res.setHeader('Access-Control-Allow-Origin', '*'); + res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); // These headers are required to enable SharedArrayBuffer // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer if (crossOriginIsolated) { // These headers are required to enable SharedArrayBuffer // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer - res.header('Cross-Origin-Opener-Policy', 'same-origin'); - res.header('Cross-Origin-Embedder-Policy', 'require-corp'); + res.setHeader('Cross-Origin-Opener-Policy', 'same-origin'); + res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp'); } next(); }; diff --git a/code/core/src/core-server/utils/getStoryIndexGenerator.ts b/code/core/src/core-server/utils/getStoryIndexGenerator.ts index 6e5e4960b132..d91373d825cf 100644 --- a/code/core/src/core-server/utils/getStoryIndexGenerator.ts +++ b/code/core/src/core-server/utils/getStoryIndexGenerator.ts @@ -1,15 +1,14 @@ import { normalizeStories } from '@storybook/core/common'; import type { DocsOptions, Options } from '@storybook/core/types'; +import type Polka from 'polka'; + import { StoryIndexGenerator } from './StoryIndexGenerator'; import type { ServerChannel } from './get-server-channel'; -import { router } from './router'; import { useStoriesJson } from './stories-json'; export async function getStoryIndexGenerator( - features: { - argTypeTargetsV7?: boolean; - }, + app: Polka.Polka, options: Options, serverChannel: ServerChannel ): Promise { @@ -34,7 +33,7 @@ export async function getStoryIndexGenerator( const initializedStoryIndexGenerator = generator.initialize().then(() => generator); useStoriesJson({ - router, + app, initializedStoryIndexGenerator, normalizedStories, serverChannel, diff --git a/code/core/src/core-server/utils/metadata.ts b/code/core/src/core-server/utils/metadata.ts index a617b3e1f52c..a9a2ebb337ba 100644 --- a/code/core/src/core-server/utils/metadata.ts +++ b/code/core/src/core-server/utils/metadata.ts @@ -2,7 +2,7 @@ import { writeFile } from 'node:fs/promises'; import { getStorybookMetadata } from '@storybook/core/telemetry'; -import type { Request, Response, Router } from 'express'; +import type Polka from 'polka'; export async function extractStorybookMetadata(outputFile: string, configDir: string) { const storybookMetadata = await getStorybookMetadata(configDir); @@ -10,10 +10,11 @@ export async function extractStorybookMetadata(outputFile: string, configDir: st await writeFile(outputFile, JSON.stringify(storybookMetadata)); } -export function useStorybookMetadata(router: Router, configDir?: string) { - router.use('/project.json', async (req: Request, res: Response) => { +export function useStorybookMetadata(app: Polka.Polka, configDir?: string) { + app.use('/project.json', async (req, res) => { const storybookMetadata = await getStorybookMetadata(configDir); - res.header('Content-Type', 'application/json'); - res.send(JSON.stringify(storybookMetadata)); + res.setHeader('Content-Type', 'application/json'); + res.write(JSON.stringify(storybookMetadata)); + res.end(); }); } diff --git a/code/core/src/core-server/utils/remove-mdx-entries.ts b/code/core/src/core-server/utils/remove-mdx-entries.ts index f71488712a49..da431155016a 100644 --- a/code/core/src/core-server/utils/remove-mdx-entries.ts +++ b/code/core/src/core-server/utils/remove-mdx-entries.ts @@ -3,6 +3,7 @@ import { isAbsolute, join, relative } from 'node:path'; import { commonGlobOptions, normalizeStories } from '@storybook/core/common'; import type { Options, StoriesEntry } from '@storybook/core/types'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import slash from 'slash'; diff --git a/code/core/src/core-server/utils/router.ts b/code/core/src/core-server/utils/router.ts deleted file mode 100644 index 894388991b5f..000000000000 --- a/code/core/src/core-server/utils/router.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { Router } from 'express'; - -// @ts-expect-error (Converted from ts-ignore) - -export const router: Router = new Router(); diff --git a/code/core/src/core-server/utils/search-files.ts b/code/core/src/core-server/utils/search-files.ts index b0e743895aa9..723f74341b34 100644 --- a/code/core/src/core-server/utils/search-files.ts +++ b/code/core/src/core-server/utils/search-files.ts @@ -31,6 +31,7 @@ export async function searchFiles({ fileExtensions?: string[]; }): Promise { // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby, isDynamicPattern } = await import('globby'); const hasSearchSpecialGlobChars = isDynamicPattern(searchQuery, { cwd }); diff --git a/code/core/src/core-server/utils/server-init.ts b/code/core/src/core-server/utils/server-init.ts index 60710cb19cfb..d06c3421e7bc 100644 --- a/code/core/src/core-server/utils/server-init.ts +++ b/code/core/src/core-server/utils/server-init.ts @@ -2,21 +2,17 @@ import { readFile } from 'node:fs/promises'; import { logger } from '@storybook/core/node-logger'; -import type { Express } from 'express'; import http from 'http'; import https from 'https'; -export async function getServer( - app: Express, - options: { - https?: boolean; - sslCert?: string; - sslKey?: string; - sslCa?: string[]; - } -) { +export async function getServer(options: { + https?: boolean; + sslCert?: string; + sslKey?: string; + sslCa?: string[]; +}) { if (!options.https) { - return http.createServer(app); + return http.createServer(); } if (!options.sslCert) { @@ -35,5 +31,5 @@ export async function getServer( key: await readFile(options.sslKey, { encoding: 'utf8' }), }; - return https.createServer(sslOptions, app); + return https.createServer(sslOptions); } diff --git a/code/core/src/core-server/utils/server-statics.ts b/code/core/src/core-server/utils/server-statics.ts index b6bc406923e8..3e21b4a3ea58 100644 --- a/code/core/src/core-server/utils/server-statics.ts +++ b/code/core/src/core-server/utils/server-statics.ts @@ -6,22 +6,19 @@ import type { Options } from '@storybook/core/types'; import { logger } from '@storybook/core/node-logger'; -import type { Router } from 'express'; -import express from 'express'; import picocolors from 'picocolors'; +import type Polka from 'polka'; +import sirv from 'sirv'; import { dedent } from 'ts-dedent'; -export async function useStatics(router: Router, options: Options) { +export async function useStatics(app: Polka.Polka, options: Options): Promise { const staticDirs = (await options.presets.apply('staticDirs')) ?? []; const faviconPath = await options.presets.apply('favicon'); - const statics = [ - ...staticDirs.map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`)), - ]; - - if (statics && statics.length > 0) { - await Promise.all( - statics.map(async (dir) => { + await Promise.all( + staticDirs + .map((dir) => (typeof dir === 'string' ? dir : `${dir.from}:${dir.to}`)) + .map(async (dir) => { try { const normalizedDir = staticDirs && !isAbsolute(dir) @@ -40,17 +37,30 @@ export async function useStatics(router: Router, options: Options) { ); } - router.use(targetEndpoint, express.static(staticPath, { index: false })); + app.use( + targetEndpoint, + sirv(staticPath, { + dev: true, + etag: true, + extensions: [], + }) + ); } catch (e) { if (e instanceof Error) { logger.warn(e.message); } } }) - ); - } + ); - router.get(`/${basename(faviconPath)}`, (req, res) => res.sendFile(faviconPath)); + app.get( + `/${basename(faviconPath)}`, + sirv(faviconPath, { + dev: true, + etag: true, + extensions: [], + }) + ); } export const parseStaticDir = async (arg: string) => { diff --git a/code/core/src/core-server/utils/stories-json.test.ts b/code/core/src/core-server/utils/stories-json.test.ts index 3faa5da2fe19..4868c149b724 100644 --- a/code/core/src/core-server/utils/stories-json.test.ts +++ b/code/core/src/core-server/utils/stories-json.test.ts @@ -7,7 +7,7 @@ import { normalizeStoriesEntry } from '@storybook/core/common'; import { STORY_INDEX_INVALIDATED } from '@storybook/core/core-events'; import { debounce } from 'es-toolkit/compat'; -import type { Request, Response, Router } from 'express'; +import type Polka from 'polka'; import Watchpack from 'watchpack'; import { csfIndexer } from '../presets/common-preset'; @@ -58,30 +58,30 @@ const getInitializedStoryIndexGenerator = async ( describe('useStoriesJson', () => { const use = vi.fn(); - const router: Router = { use } as any; - const send = vi.fn(); + const app: Polka.Polka = { use } as any; + const end = vi.fn(); const write = vi.fn(); - const response: Response = { + const response: Polka.Response = { header: vi.fn(), - send, + send: vi.fn(), status: vi.fn(), setHeader: vi.fn(), flushHeaders: vi.fn(), write, flush: vi.fn(), - end: vi.fn(), + end, on: vi.fn(), } as any; beforeEach(async () => { use.mockClear(); - send.mockClear(); + end.mockClear(); write.mockClear(); vi.mocked(debounce).mockImplementation((cb) => cb as any); Watchpack.mockClear(); }); - const request: Request = { + const request: Polka.Request = { headers: { accept: 'application/json' }, } as any; @@ -90,7 +90,7 @@ describe('useStoriesJson', () => { const mockServerChannel = { emit: vi.fn() } as any as ServerChannel; console.time('useStoriesJson'); useStoriesJson({ - router, + app, serverChannel: mockServerChannel, workingDir, normalizedStories, @@ -105,8 +105,8 @@ describe('useStoriesJson', () => { await route(request, response); console.timeEnd('route'); - expect(send).toHaveBeenCalledTimes(1); - expect(JSON.parse(send.mock.calls[0][0])).toMatchInlineSnapshot(` + expect(end).toHaveBeenCalledTimes(1); + expect(JSON.parse(end.mock.calls[0][0])).toMatchInlineSnapshot(` { "entries": { "a--metaof": { @@ -368,7 +368,7 @@ describe('useStoriesJson', () => { const mockServerChannel = { emit: vi.fn() } as any as ServerChannel; useStoriesJson({ - router, + app, serverChannel: mockServerChannel, workingDir, normalizedStories, @@ -379,14 +379,14 @@ describe('useStoriesJson', () => { const route = use.mock.calls[0][1]; const firstPromise = route(request, response); - const secondResponse = { ...response, send: vi.fn(), status: vi.fn() }; + const secondResponse = { ...response, end: vi.fn(), status: vi.fn() }; const secondPromise = route(request, secondResponse); await Promise.all([firstPromise, secondPromise]); - expect(send).toHaveBeenCalledTimes(1); - expect(response.status).not.toEqual(500); - expect(secondResponse.send).toHaveBeenCalledTimes(1); + expect(end).toHaveBeenCalledTimes(1); + expect(response.statusCode).not.toEqual(500); + expect(secondResponse.end).toHaveBeenCalledTimes(1); expect(secondResponse.status).not.toEqual(500); }); }); @@ -394,13 +394,13 @@ describe('useStoriesJson', () => { describe('SSE endpoint', () => { beforeEach(() => { use.mockClear(); - send.mockClear(); + end.mockClear(); }); it('sends invalidate events', async () => { const mockServerChannel = { emit: vi.fn() } as any as ServerChannel; useStoriesJson({ - router, + app, serverChannel: mockServerChannel, workingDir, normalizedStories, @@ -434,7 +434,7 @@ describe('useStoriesJson', () => { it('only sends one invalidation when multiple event listeners are listening', async () => { const mockServerChannel = { emit: vi.fn() } as any as ServerChannel; useStoriesJson({ - router, + app, serverChannel: mockServerChannel, workingDir, normalizedStories, @@ -476,7 +476,7 @@ describe('useStoriesJson', () => { const mockServerChannel = { emit: vi.fn() } as any as ServerChannel; useStoriesJson({ - router, + app, serverChannel: mockServerChannel, workingDir, normalizedStories, diff --git a/code/core/src/core-server/utils/stories-json.ts b/code/core/src/core-server/utils/stories-json.ts index 3426aa689de1..a33e12eb0393 100644 --- a/code/core/src/core-server/utils/stories-json.ts +++ b/code/core/src/core-server/utils/stories-json.ts @@ -6,7 +6,7 @@ import type { NormalizedStoriesSpecifier, StoryIndex } from '@storybook/core/typ import { STORY_INDEX_INVALIDATED } from '@storybook/core/core-events'; import { debounce } from 'es-toolkit/compat'; -import type { Request, Response, Router } from 'express'; +import type Polka from 'polka'; import type { StoryIndexGenerator } from './StoryIndexGenerator'; import type { ServerChannel } from './get-server-channel'; @@ -26,14 +26,14 @@ export async function extractStoriesJson( } export function useStoriesJson({ - router, + app, initializedStoryIndexGenerator, workingDir = process.cwd(), configDir, serverChannel, normalizedStories, }: { - router: Router; + app: Polka.Polka; initializedStoryIndexGenerator: Promise; serverChannel: ServerChannel; workingDir?: string; @@ -58,15 +58,15 @@ export function useStoriesJson({ }); } - router.use('/index.json', async (req: Request, res: Response) => { + app.use('/index.json', async (req, res) => { try { const generator = await initializedStoryIndexGenerator; const index = await generator.getIndex(); - res.header('Content-Type', 'application/json'); - res.send(JSON.stringify(index)); + res.setHeader('Content-Type', 'application/json'); + res.end(JSON.stringify(index)); } catch (err) { - res.status(500); - res.send(err instanceof Error ? err.toString() : String(err)); + res.statusCode = 500; + res.end(err instanceof Error ? err.toString() : String(err)); } }); } diff --git a/code/core/src/core-server/utils/watch-story-specifiers.ts b/code/core/src/core-server/utils/watch-story-specifiers.ts index b320520dc9a4..6fa8d3e83a6f 100644 --- a/code/core/src/core-server/utils/watch-story-specifiers.ts +++ b/code/core/src/core-server/utils/watch-story-specifiers.ts @@ -97,6 +97,7 @@ export function watchStorySpecifiers( ); // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby } = await import('globby'); // glob only supports forward slashes diff --git a/code/core/src/telemetry/get-portable-stories-usage.ts b/code/core/src/telemetry/get-portable-stories-usage.ts index e328a3283c57..cd9da7f4f589 100644 --- a/code/core/src/telemetry/get-portable-stories-usage.ts +++ b/code/core/src/telemetry/get-portable-stories-usage.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; import { createFileSystemCache, resolvePathInStorybookCache } from '../common'; diff --git a/code/core/src/types/modules/core-common.ts b/code/core/src/types/modules/core-common.ts index 8e71a4cadb2a..dbdabe22122c 100644 --- a/code/core/src/types/modules/core-common.ts +++ b/code/core/src/types/modules/core-common.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/naming-convention */ -import type { Router } from 'express'; -import type { FileSystemCache } from 'file-system-cache'; // should be node:http, but that caused the ui/manager to fail to build, might be able to switch this back once ui/manager is in the core -import type { Server } from 'http'; -import type * as telejson from 'telejson'; +import type { Server as HttpServer, IncomingMessage, ServerResponse } from 'http'; +import type { Server as NetServer } from 'net'; +import type { Options as TelejsonOptions } from 'telejson'; import type { PackageJson as PackageJsonFromTypeFest } from 'type-fest'; +import type { FileSystemCache } from '../../common/utils/file-cache'; import type { Indexer, StoriesEntry } from './indexer'; /** ⚠️ This file contains internal WIP types they MUST NOT be exported outside this package for now! */ @@ -26,7 +26,7 @@ export interface CoreConfig { }; renderer?: RendererName; disableWebpackDefaults?: boolean; - channelOptions?: Partial; + channelOptions?: Partial; /** Disables the generation of project.json, a file containing Storybook metadata */ disableProjectJson?: boolean; /** @@ -156,7 +156,7 @@ export interface LoadOptions { configDir?: string; cacheKey?: string; ignorePreview?: boolean; - extendServer?: (server: Server) => void; + extendServer?: (server: HttpServer) => void; } export interface CLIOptions { @@ -211,13 +211,37 @@ export type Options = LoadOptions & CLIOptions & BuilderOptions & { build?: TestBuildConfig }; +// A minimal version of Polka's interface to avoid exposing internal implementation details +export type Middleware = ( + req: T & IncomingMessage, + res: ServerResponse, + next: (err?: string | Error) => Promise | void +) => Promise | void; + +interface ServerApp { + server: NetServer; + + use(pattern: RegExp | string, ...handlers: Middleware[]): this; + use(...handlers: Middleware[]): this; + + get(pattern: RegExp | string, ...handlers: Middleware[]): this; + post(pattern: RegExp | string, ...handlers: Middleware[]): this; + put(pattern: RegExp | string, ...handlers: Middleware[]): this; + patch(pattern: RegExp | string, ...handlers: Middleware[]): this; + delete(pattern: RegExp | string, ...handlers: Middleware[]): this; + head(pattern: RegExp | string, ...handlers: Middleware[]): this; + options(pattern: RegExp | string, ...handlers: Middleware[]): this; + connect(pattern: RegExp | string, ...handlers: Middleware[]): this; + trace(pattern: RegExp | string, ...handlers: Middleware[]): this; +} + export interface Builder { getConfig: (options: Options) => Promise; start: (args: { options: Options; startTime: ReturnType; - router: Router; - server: Server; + router: ServerApp; + server: HttpServer; channel: ServerChannel; }) => Promise = { async check() { // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby } = await import('globby'); const storiesMdxFiles = await globby('./!(node_modules)**/*.(story|stories).mdx'); diff --git a/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts b/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts index 8369f8896ef3..41fc1b4a3a0b 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/mdx-gfm.ts @@ -47,6 +47,7 @@ export const mdxgfm: Fix = { } // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby } = await import('globby'); const files = await globby(pattern, commonGlobOptions(pattern)); diff --git a/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts b/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts index 55e36258c9cd..217b3dcacb93 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/mdx-to-csf.ts @@ -2,6 +2,7 @@ import type { StoriesEntry } from 'storybook/internal/types'; import { runCodemod } from '@storybook/codemod'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import picocolors from 'picocolors'; import { prompt } from 'prompts'; diff --git a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts index 9b5892b51a32..8eda42d9b9ba 100644 --- a/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts +++ b/code/lib/cli-storybook/src/automigrate/fixes/missing-storybook-dependencies.ts @@ -70,6 +70,7 @@ export const missingStorybookDependencies: Fix { if (!hasTSDependency) { // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby } = await import('globby'); const files = await globby(['**/*.@(ts|tsx)', '!**/node_modules', '!**/*.d.ts']); diff --git a/code/lib/codemod/src/index.ts b/code/lib/codemod/src/index.ts index ec80bd250d3f..80bc90932918 100644 --- a/code/lib/codemod/src/index.ts +++ b/code/lib/codemod/src/index.ts @@ -65,6 +65,7 @@ export async function runCodemod( } // Dynamically import globby because it is a pure ESM module + // eslint-disable-next-line depend/ban-dependencies const { globby } = await import('globby'); const files = await globby([glob, '!**/node_modules', '!**/dist']); diff --git a/code/lib/create-storybook/src/generators/baseGenerator.ts b/code/lib/create-storybook/src/generators/baseGenerator.ts index b1aea02b11e1..1a44e3ba272b 100644 --- a/code/lib/create-storybook/src/generators/baseGenerator.ts +++ b/code/lib/create-storybook/src/generators/baseGenerator.ts @@ -11,6 +11,7 @@ import type { JsPackageManager } from 'storybook/internal/common'; import { getPackageDetails, versions as packageVersions } from 'storybook/internal/common'; import type { SupportedFrameworks } from 'storybook/internal/types'; +// eslint-disable-next-line depend/ban-dependencies import ora from 'ora'; import invariant from 'tiny-invariant'; import { dedent } from 'ts-dedent'; diff --git a/code/lib/create-storybook/src/scaffold-new-project.ts b/code/lib/create-storybook/src/scaffold-new-project.ts index f41d9c876010..c07ff8c9fba4 100644 --- a/code/lib/create-storybook/src/scaffold-new-project.ts +++ b/code/lib/create-storybook/src/scaffold-new-project.ts @@ -7,6 +7,7 @@ import { GenerateNewProjectOnInitError } from 'storybook/internal/server-errors' import { telemetry } from 'storybook/internal/telemetry'; import boxen from 'boxen'; +// eslint-disable-next-line depend/ban-dependencies import execa from 'execa'; import picocolors from 'picocolors'; import prompts from 'prompts'; diff --git a/code/package.json b/code/package.json index dd66a8428ae6..e441ef956340 100644 --- a/code/package.json +++ b/code/package.json @@ -168,7 +168,6 @@ "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.5.2", "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@types/express": "^4.17.21", "@types/mock-require": "^2.0.3", "@types/node": "^22.0.0", "@types/react": "^18.0.37", @@ -191,6 +190,7 @@ "esbuild-plugin-alias": "^0.2.1", "eslint": "^8.56.0", "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-depend": "^0.11.0", "eslint-plugin-local-rules": "portal:../scripts/eslint-plugin-local-rules", "eslint-plugin-playwright": "^1.6.2", "eslint-plugin-storybook": "^0.8.0", @@ -293,5 +293,6 @@ "Dependency Upgrades" ] ] - } + }, + "deferredNextVersion": "8.4.0-alpha.5" } diff --git a/code/yarn.lock b/code/yarn.lock index 1b04c78853dc..2c6f7244e415 100644 --- a/code/yarn.lock +++ b/code/yarn.lock @@ -4656,6 +4656,20 @@ __metadata: languageName: node linkType: hard +"@polka/compression@npm:^1.0.0-next.28": + version: 1.0.0-next.28 + resolution: "@polka/compression@npm:1.0.0-next.28" + checksum: 10c0/e55912f0a8d5dfcda6f7eb9b8d87cc65782a652003f47e7caf0bd88d81f5c280d9a8310441ee34e2774662ed39369e4f9d5fdb3f3a6adc8f18bc1ee97245fff3 + languageName: node + linkType: hard + +"@polka/url@npm:^1.0.0-next.21": + version: 1.0.0-next.28 + resolution: "@polka/url@npm:1.0.0-next.28" + checksum: 10c0/acc5ea62597e4da2fb42dbee02749d07f102ae7d6d2c966bf7e423c79cd65d1621da305af567e6e7c232f3b565e242d1ec932cbb3dcc0db1508d02e9a2cafa2e + languageName: node + linkType: hard + "@polka/url@npm:^1.0.0-next.24": version: 1.0.0-next.25 resolution: "@polka/url@npm:1.0.0-next.25" @@ -5791,15 +5805,15 @@ __metadata: resolution: "@storybook/builder-vite@workspace:builders/builder-vite" dependencies: "@storybook/csf-plugin": "workspace:*" - "@types/express": "npm:^4.17.21" "@types/find-cache-dir": "npm:^3.2.1" "@types/node": "npm:^22.0.0" browser-assert: "npm:^1.2.1" es-module-lexer: "npm:^1.5.0" - express: "npm:^4.19.2" find-cache-dir: "npm:^3.0.0" glob: "npm:^10.0.0" magic-string: "npm:^0.30.0" + polka: "npm:^1.0.0-next.28" + sirv: "npm:^2.0.4" slash: "npm:^5.0.0" ts-dedent: "npm:^2.0.0" typescript: "npm:^5.3.2" @@ -5836,7 +5850,6 @@ __metadata: constants-browserify: "npm:^1.0.0" css-loader: "npm:^6.7.1" es-module-lexer: "npm:^1.5.0" - express: "npm:^4.19.2" fork-ts-checker-webpack-plugin: "npm:^8.0.0" html-webpack-plugin: "npm:^5.5.0" magic-string: "npm:^0.30.5" @@ -5844,6 +5857,7 @@ __metadata: pretty-hrtime: "npm:^1.0.3" process: "npm:^0.11.10" semver: "npm:^7.3.7" + sirv: "npm:^2.0.4" slash: "npm:^5.0.0" style-loader: "npm:^3.3.1" terser-webpack-plugin: "npm:^5.3.1" @@ -6015,6 +6029,7 @@ __metadata: "@emotion/use-insertion-effect-with-fallbacks": "npm:^1.0.1" "@fal-works/esbuild-plugin-global-externals": "npm:^2.1.2" "@ndelangen/get-tarball": "npm:^3.0.7" + "@polka/compression": "npm:^1.0.0-next.28" "@popperjs/core": "npm:^2.6.0" "@radix-ui/react-dialog": "npm:^1.0.5" "@radix-ui/react-scroll-area": "npm:1.2.0-rc.7" @@ -6025,12 +6040,10 @@ __metadata: "@storybook/icons": "npm:^1.2.10" "@tanstack/react-virtual": "npm:^3.3.0" "@testing-library/react": "npm:^14.0.0" - "@types/compression": "npm:^1.7.0" "@types/cross-spawn": "npm:^6.0.2" "@types/detect-port": "npm:^1.3.0" "@types/diff": "npm:^5.0.9" "@types/ejs": "npm:^3.1.1" - "@types/express": "npm:^4.17.21" "@types/find-cache-dir": "npm:^5.0.0" "@types/js-yaml": "npm:^4.0.5" "@types/node": "npm:^22.0.0" @@ -6058,7 +6071,6 @@ __metadata: cli-table3: "npm:^0.6.1" commander: "npm:^12.1.0" comment-parser: "npm:^1.4.1" - compression: "npm:^1.7.4" copy-to-clipboard: "npm:^3.3.1" cross-spawn: "npm:^7.0.3" css: "npm:^3.0.0" @@ -6075,10 +6087,8 @@ __metadata: esbuild-plugin-alias: "npm:^0.2.1" esbuild-register: "npm:^3.5.0" execa: "npm:^8.0.1" - express: "npm:^4.19.2" fd-package-json: "npm:^1.2.0" fetch-retry: "npm:^6.0.0" - file-system-cache: "npm:^2.4.4" find-cache-dir: "npm:^5.0.0" find-up: "npm:^7.0.0" flush-promises: "npm:^1.0.2" @@ -6101,6 +6111,7 @@ __metadata: picomatch: "npm:^2.3.0" picoquery: "npm:^1.4.0" polished: "npm:^4.2.2" + polka: "npm:^1.0.0-next.28" prettier: "npm:^3.2.5" pretty-hrtime: "npm:^1.0.3" process: "npm:^0.11.10" @@ -6119,6 +6130,7 @@ __metadata: require-from-string: "npm:^2.0.2" resolve-from: "npm:^5.0.0" semver: "npm:^7.6.2" + sirv: "npm:^2.0.4" slash: "npm:^5.0.0" source-map: "npm:^0.7.4" store2: "npm:^2.14.2" @@ -6868,7 +6880,6 @@ __metadata: "@testing-library/react": "npm:^16.0.0" "@testing-library/user-event": "npm:^14.5.2" "@trivago/prettier-plugin-sort-imports": "npm:^4.3.0" - "@types/express": "npm:^4.17.21" "@types/mock-require": "npm:^2.0.3" "@types/node": "npm:^22.0.0" "@types/react": "npm:^18.0.37" @@ -6891,6 +6902,7 @@ __metadata: esbuild-plugin-alias: "npm:^0.2.1" eslint: "npm:^8.56.0" eslint-import-resolver-typescript: "npm:^3.6.1" + eslint-plugin-depend: "npm:^0.11.0" eslint-plugin-local-rules: "portal:../scripts/eslint-plugin-local-rules" eslint-plugin-playwright: "npm:^1.6.2" eslint-plugin-storybook: "npm:^0.8.0" @@ -7648,15 +7660,6 @@ __metadata: languageName: node linkType: hard -"@types/compression@npm:^1.7.0": - version: 1.7.5 - resolution: "@types/compression@npm:1.7.5" - dependencies: - "@types/express": "npm:*" - checksum: 10c0/3818f3d10cede38a835b40b80c341eae162aef1691f2e8f81178a77dbc109f04234cf760b6066eaa06ecbb1da143433c00db2fd9999198b76cd5a193e1d09675 - languageName: node - linkType: hard - "@types/concat-stream@npm:^2.0.0": version: 2.0.3 resolution: "@types/concat-stream@npm:2.0.3" @@ -7807,7 +7810,7 @@ __metadata: languageName: node linkType: hard -"@types/express@npm:*, @types/express@npm:^4.17.13, @types/express@npm:^4.17.21": +"@types/express@npm:*, @types/express@npm:^4.17.13": version: 4.17.21 resolution: "@types/express@npm:4.17.21" dependencies: @@ -7844,16 +7847,6 @@ __metadata: languageName: node linkType: hard -"@types/fs-extra@npm:11.0.1": - version: 11.0.1 - resolution: "@types/fs-extra@npm:11.0.1" - dependencies: - "@types/jsonfile": "npm:*" - "@types/node": "npm:*" - checksum: 10c0/a65f1fae47849fe1a17441dcabc9400390303405972ff3cbb3578746cea8916b23d5e7652bf57a87767f75a9b2f37caac499b78b5230ae08fef0ba58b34c3a85 - languageName: node - linkType: hard - "@types/fs-extra@npm:^5.0.5": version: 5.1.0 resolution: "@types/fs-extra@npm:5.1.0" @@ -7988,15 +7981,6 @@ __metadata: languageName: node linkType: hard -"@types/jsonfile@npm:*": - version: 6.1.2 - resolution: "@types/jsonfile@npm:6.1.2" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/c2943f9bfa7867b33fb362b88a932efdc00e9e5f2762b6ef912617cb0a3e3221a98920f8976a4cf817aa576e03d28a25391236e9644e2ebe648081b08df62ef5 - languageName: node - linkType: hard - "@types/loader-utils@npm:^2.0.5": version: 2.0.6 resolution: "@types/loader-utils@npm:2.0.6" @@ -8164,15 +8148,6 @@ __metadata: languageName: node linkType: hard -"@types/ramda@npm:0.29.3": - version: 0.29.3 - resolution: "@types/ramda@npm:0.29.3" - dependencies: - types-ramda: "npm:^0.29.4" - checksum: 10c0/9c62a4600f5df5e65a01ffe4a470500c98f7c0d093fde47e0d4257675f1ec50effe4696cb004a6b53227948db67ea26a2345dbc91819ecc868105c0f64cecd1e - languageName: node - linkType: hard - "@types/range-parser@npm:*": version: 1.2.5 resolution: "@types/range-parser@npm:1.2.5" @@ -14336,6 +14311,17 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-depend@npm:^0.11.0": + version: 0.11.0 + resolution: "eslint-plugin-depend@npm:0.11.0" + dependencies: + fd-package-json: "npm:^1.2.0" + module-replacements: "npm:^2.1.0" + semver: "npm:^7.6.3" + checksum: 10c0/64baf4d4f5d406efa1f13bda723ff0eb5fe4cee0ae8c3679fcdfccb4d7ba3a9472416fa3c54d75f1bde3e0123e55a85774662484a5b0355812f21a8968ee784a + languageName: node + linkType: hard + "eslint-plugin-eslint-comments@npm:^3.2.0": version: 3.2.0 resolution: "eslint-plugin-eslint-comments@npm:3.2.0" @@ -15009,7 +14995,7 @@ __metadata: languageName: node linkType: hard -"express@npm:^4.17.3, express@npm:^4.19.2": +"express@npm:^4.17.3": version: 4.19.2 resolution: "express@npm:4.19.2" dependencies: @@ -15268,18 +15254,6 @@ __metadata: languageName: node linkType: hard -"file-system-cache@npm:^2.4.4": - version: 2.4.4 - resolution: "file-system-cache@npm:2.4.4" - dependencies: - "@types/fs-extra": "npm:11.0.1" - "@types/ramda": "npm:0.29.3" - fs-extra: "npm:11.1.1" - ramda: "npm:0.29.0" - checksum: 10c0/274bd9c2f8f81d0c3b2cc0d077807c969b48cac4857ae77f87b4b480548252aa42d3a43b3e9d4bb54df567eb70f0c384782514fcea74b78765543e9496e27e2d - languageName: node - linkType: hard - "filelist@npm:^1.0.4": version: 1.0.4 resolution: "filelist@npm:1.0.4" @@ -15723,17 +15697,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:11.1.1": - version: 11.1.1 - resolution: "fs-extra@npm:11.1.1" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/a2480243d7dcfa7d723c5f5b24cf4eba02a6ccece208f1524a2fbde1c629492cfb9a59e4b6d04faff6fbdf71db9fdc8ef7f396417a02884195a625f5d8dc9427 - languageName: node - linkType: hard - "fs-extra@npm:^10.0.0, fs-extra@npm:^10.1.0": version: 10.1.0 resolution: "fs-extra@npm:10.1.0" @@ -21040,6 +21003,13 @@ __metadata: languageName: node linkType: hard +"module-replacements@npm:^2.1.0": + version: 2.5.0 + resolution: "module-replacements@npm:2.5.0" + checksum: 10c0/7fcbcb19151778a2f2fa70b7bffb134bb8922b2306e2a0d7b4a863467a9d6d9d5fed537763c43272e22b69dbddaf1610746b42a68b4663aa225e85f9ae9b03c8 + languageName: node + linkType: hard + "mri@npm:^1.1.0, mri@npm:^1.2.0": version: 1.2.0 resolution: "mri@npm:1.2.0" @@ -22804,6 +22774,16 @@ __metadata: languageName: node linkType: hard +"polka@npm:^1.0.0-next.28": + version: 1.0.0-next.28 + resolution: "polka@npm:1.0.0-next.28" + dependencies: + "@polka/url": "npm:^1.0.0-next.21" + trouter: "npm:^4.0.0" + checksum: 10c0/206bab3eb1c3c44c2fba9704d998b144ec36c4852b0b97192a1fd3953f215b739e2286852492c13dcc9faecea0f7825a76356d6eef7e02afd6a800d1dbb84ead + languageName: node + linkType: hard + "popper.js@npm:^1.16.0": version: 1.16.1 resolution: "popper.js@npm:1.16.1" @@ -23614,13 +23594,6 @@ __metadata: languageName: node linkType: hard -"ramda@npm:0.29.0": - version: 0.29.0 - resolution: "ramda@npm:0.29.0" - checksum: 10c0/b00eaaf1c62b06a99affa1d583e256bd65ad27ab9d0ef512f55d7d93b842e7cd244a4a09179f61fdd8548362e409323867a2b0477cbd0626b5644eb6ac7c53da - languageName: node - linkType: hard - "randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": version: 2.1.0 resolution: "randombytes@npm:2.1.0" @@ -24322,6 +24295,13 @@ __metadata: languageName: node linkType: hard +"regexparam@npm:^3.0.0": + version: 3.0.0 + resolution: "regexparam@npm:3.0.0" + checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459 + languageName: node + linkType: hard + "regexpp@npm:^3.2.0": version: 3.2.0 resolution: "regexpp@npm:3.2.0" @@ -27276,6 +27256,15 @@ __metadata: languageName: node linkType: hard +"trouter@npm:^4.0.0": + version: 4.0.0 + resolution: "trouter@npm:4.0.0" + dependencies: + regexparam: "npm:^3.0.0" + checksum: 10c0/e27326a831187c6a47a72b62212364e3f88247fa2a8723e5030e14a0002b69756fb51f97efbda2466deb05f4a78ecb83c2a1a7b343e9659cbfb3f370156f1e12 + languageName: node + linkType: hard + "try-catch@npm:^3.0.0": version: 3.0.1 resolution: "try-catch@npm:3.0.1" @@ -27377,13 +27366,6 @@ __metadata: languageName: node linkType: hard -"ts-toolbelt@npm:^9.6.0": - version: 9.6.0 - resolution: "ts-toolbelt@npm:9.6.0" - checksum: 10c0/838f9a2f0fe881d5065257a23b402c41315b33ff987b73db3e2b39fcb70640c4c7220e1ef118ed5676763543724fdbf4eda7b0e2c17acb667ed1401336af9f8c - languageName: node - linkType: hard - "tsconfig-paths-webpack-plugin@npm:^4.0.1": version: 4.1.0 resolution: "tsconfig-paths-webpack-plugin@npm:4.1.0" @@ -27567,15 +27549,6 @@ __metadata: languageName: node linkType: hard -"types-ramda@npm:^0.29.4": - version: 0.29.10 - resolution: "types-ramda@npm:0.29.10" - dependencies: - ts-toolbelt: "npm:^9.6.0" - checksum: 10c0/cc6439341a60a4f2b49e1ac447c8a0279f161464fd0a204abaa57e90e101772c0b1adc185a7c0715c3836c19594a9ec268c1e5c4394d0e409cb71d141def3963 - languageName: node - linkType: hard - "typescript@npm:^3.8.3": version: 3.9.10 resolution: "typescript@npm:3.9.10" diff --git a/docs/versions/next.json b/docs/versions/next.json index ab225ca861a5..d74fdfbac9b2 100644 --- a/docs/versions/next.json +++ b/docs/versions/next.json @@ -1 +1 @@ -{"version":"8.4.0-alpha.4","info":{"plain":"- Blocks: Prebundle `es-toolkit` - [#29259](https://github.com/storybookjs/storybook/pull/29259), thanks @JReinhold!\n- CLI: Update the React Native init to include v8 dependencies - [#29273](https://github.com/storybookjs/storybook/pull/29273), thanks @dannyhw!\n- Core: Upgrade `esbuild`, broadening version range - [#29254](https://github.com/storybookjs/storybook/pull/29254), thanks @ndelangen!\n- Vitest plugin: Fix renamed export stories - [#29250](https://github.com/storybookjs/storybook/pull/29250), thanks @shilman!"}} +{"version":"8.4.0-alpha.5","info":{"plain":"- Core: Migrate from `express` to `polka` - [#29230](https://github.com/storybookjs/storybook/pull/29230), thanks @43081j!\n- Core: Remove dependence on `file-system-cache` - [#29256](https://github.com/storybookjs/storybook/pull/29256), thanks @ndelangen!"}} diff --git a/scripts/.eslintrc.cjs b/scripts/.eslintrc.cjs index 2af8b19b61c1..b49fe70944d0 100644 --- a/scripts/.eslintrc.cjs +++ b/scripts/.eslintrc.cjs @@ -1,6 +1,11 @@ module.exports = { root: true, - extends: ['@storybook/eslint-config-storybook', 'plugin:storybook/recommended'], + extends: [ + // + '@storybook/eslint-config-storybook', + 'plugin:storybook/recommended', + 'plugin:depend/recommended' + ], parserOptions: { tsconfigRootDir: __dirname, project: ['./tsconfig.json'], @@ -11,6 +16,9 @@ module.exports = { '@typescript-eslint/consistent-type-imports': ['error', { disallowTypeAnnotations: false }], 'no-use-before-define': 'off', 'eslint-comments/disable-enable-pair': ['error', { allowWholeFile: true }], + "depend/ban-dependencies": ["error", { + "modules": ["lodash", "chalk", "qs", "handlebars", "fs-extra"] + }] }, overrides: [ { diff --git a/scripts/bench/utils.ts b/scripts/bench/utils.ts index 1bd3a3f849ae..673fb56c4360 100644 --- a/scripts/bench/utils.ts +++ b/scripts/bench/utils.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { ensureDir, readJSON, readdir, writeJSON } from 'fs-extra'; import { join } from 'path'; import type { Page } from 'playwright-core'; diff --git a/scripts/build-package.ts b/scripts/build-package.ts index 96ddb84c2fbc..ee6cf109cbe8 100644 --- a/scripts/build-package.ts +++ b/scripts/build-package.ts @@ -1,5 +1,7 @@ import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { readJSON } from 'fs-extra'; import { posix, resolve, sep } from 'path'; import picocolors from 'picocolors'; @@ -9,7 +11,7 @@ import windowSize from 'window-size'; import { getWorkspaces } from './utils/workspace'; async function run() { - const packages = await getWorkspaces(); + const packages = (await getWorkspaces()).filter(({ name }) => name !== '@storybook/root'); const packageTasks = packages .map((pkg) => { let suffix = pkg.name.replace('@storybook/', ''); diff --git a/scripts/check-package.ts b/scripts/check-package.ts index 8b9c49985fb5..035ae8a74ec6 100644 --- a/scripts/check-package.ts +++ b/scripts/check-package.ts @@ -2,7 +2,9 @@ // without having to build dts files for all packages in the monorepo. // It is not implemented yet for angular, svelte and vue. import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { readJSON } from 'fs-extra'; import { resolve } from 'path'; import picocolors from 'picocolors'; diff --git a/scripts/combine-compodoc.ts b/scripts/combine-compodoc.ts index eefc905fc132..7b934854d015 100755 --- a/scripts/combine-compodoc.ts +++ b/scripts/combine-compodoc.ts @@ -1,8 +1,11 @@ // Compodoc does not follow symlinks (it ignores them and their contents entirely) // So, we need to run a separate compodoc process on every symlink inside the project, // then combine the results into one large documentation.json +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { lstat, readFile, realpath, writeFile } from 'fs-extra'; +// eslint-disable-next-line depend/ban-dependencies import { globSync } from 'glob'; import { join, resolve } from 'path'; diff --git a/scripts/dangerfile.ts b/scripts/dangerfile.ts index 93382ae441cf..961d77cbd2f8 100644 --- a/scripts/dangerfile.ts +++ b/scripts/dangerfile.ts @@ -4,8 +4,11 @@ import { danger, fail } from 'danger'; execSync('npm install lodash'); +// eslint-disable-next-line depend/ban-dependencies const flatten = require('lodash/flatten.js'); +// eslint-disable-next-line depend/ban-dependencies const intersection = require('lodash/intersection.js'); +// eslint-disable-next-line depend/ban-dependencies const isEmpty = require('lodash/isEmpty.js'); const pkg = require('../code/package.json'); diff --git a/scripts/event-log-collector.ts b/scripts/event-log-collector.ts index f3ad10700887..1e4a656960b1 100644 --- a/scripts/event-log-collector.ts +++ b/scripts/event-log-collector.ts @@ -1,9 +1,10 @@ -import express from 'express'; +import { json } from '@polka/parse'; +import polka from 'polka'; const PORT = process.env.PORT || 6007; -const server = express(); -server.use(express.json()); +const server = polka(); +server.use(json()); const events: Record[] = []; server.post('/event-log', (req, res) => { @@ -14,7 +15,7 @@ server.post('/event-log', (req, res) => { server.get('/event-log', (_req, res) => { console.log(`Sending ${events.length} events`); - res.json(events); + res.end(JSON.stringify(events)); }); server.listen(PORT, () => { diff --git a/scripts/get-report-message.ts b/scripts/get-report-message.ts index 4774bc0f8ca2..60f556b91014 100644 --- a/scripts/get-report-message.ts +++ b/scripts/get-report-message.ts @@ -1,4 +1,6 @@ +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { readJson } from 'fs-extra'; import { join } from 'path'; diff --git a/scripts/get-template.ts b/scripts/get-template.ts index 728632392489..cb351eab0410 100644 --- a/scripts/get-template.ts +++ b/scripts/get-template.ts @@ -1,4 +1,5 @@ import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { pathExists, readFile } from 'fs-extra'; import { readdir } from 'fs/promises'; import picocolors from 'picocolors'; diff --git a/scripts/knip.config.ts b/scripts/knip.config.ts index ef23f8c556bd..c57b570a8ac0 100644 --- a/scripts/knip.config.ts +++ b/scripts/knip.config.ts @@ -1,5 +1,6 @@ import { join, relative } from 'node:path'; +// eslint-disable-next-line depend/ban-dependencies import fg from 'fast-glob'; import type { KnipConfig } from 'knip'; import { match } from 'minimatch'; diff --git a/scripts/package.json b/scripts/package.json index d38128434b76..d7c89c37cb20 100644 --- a/scripts/package.json +++ b/scripts/package.json @@ -64,6 +64,7 @@ "@nx/workspace": "18.0.6", "@octokit/graphql": "^5.0.5", "@octokit/request": "^8.1.2", + "@polka/parse": "^1.0.0-next.28", "@storybook/eslint-config-storybook": "^4.0.0", "@storybook/linter-config": "^4.0.0", "@testing-library/dom": "^10.4.0", @@ -75,7 +76,6 @@ "@types/detect-port": "^1.3.5", "@types/ejs": "^3.1.5", "@types/escodegen": "^0.0.6", - "@types/express": "^4.17.21", "@types/fs-extra": "^11.0.4", "@types/http-server": "^0.12.4", "@types/jest": "^29.5.12", @@ -112,6 +112,7 @@ "eslint": "^8.57.0", "eslint-config-airbnb-typescript": "^18.0.0", "eslint-config-prettier": "^9.1.0", + "eslint-plugin-depend": "^0.11.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-file-progress": "^1.4.0", "eslint-plugin-html": "^8.1.1", @@ -123,7 +124,6 @@ "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-storybook": "^0.8.0", "execa": "^6.1.0", - "express": "^4.19.2", "fast-folder-size": "^2.2.0", "fast-glob": "^3.3.2", "find-up": "^5.0.0", @@ -146,6 +146,7 @@ "picocolors": "^1.1.0", "playwright": "1.46.0", "playwright-core": "1.46.0", + "polka": "^1.0.0-next.28", "prettier": "^3.3.2", "prettier-plugin-brace-style": "^0.6.2", "prettier-plugin-css-order": "^2.1.2", diff --git a/scripts/prepare/addon-bundle.ts b/scripts/prepare/addon-bundle.ts index fa5e14a0e4c4..16683ea38ff2 100755 --- a/scripts/prepare/addon-bundle.ts +++ b/scripts/prepare/addon-bundle.ts @@ -3,7 +3,9 @@ import { builtinModules } from 'node:module'; import type { Metafile } from 'esbuild'; import aliasPlugin from 'esbuild-plugin-alias'; +// eslint-disable-next-line depend/ban-dependencies import * as fs from 'fs-extra'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import { dirname, join, parse, posix, relative, sep } from 'path'; import slash from 'slash'; diff --git a/scripts/prepare/bundle.ts b/scripts/prepare/bundle.ts index 4651774257c8..d3a671034d17 100755 --- a/scripts/prepare/bundle.ts +++ b/scripts/prepare/bundle.ts @@ -3,7 +3,9 @@ import { dirname, join, parse, posix, relative, resolve, sep } from 'node:path'; import type { Metafile } from 'esbuild'; import aliasPlugin from 'esbuild-plugin-alias'; +// eslint-disable-next-line depend/ban-dependencies import * as fs from 'fs-extra'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import slash from 'slash'; import { dedent } from 'ts-dedent'; diff --git a/scripts/prepare/check.ts b/scripts/prepare/check.ts index dbf09429492b..0462b6094464 100755 --- a/scripts/prepare/check.ts +++ b/scripts/prepare/check.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import fs from 'fs-extra'; import { join } from 'path'; import ts from 'typescript'; diff --git a/scripts/prepare/tools.ts b/scripts/prepare/tools.ts index eb4214a945ba..d2c58b420833 100644 --- a/scripts/prepare/tools.ts +++ b/scripts/prepare/tools.ts @@ -5,7 +5,9 @@ import * as process from 'node:process'; import { globalExternals } from '@fal-works/esbuild-plugin-global-externals'; import { spawn } from 'cross-spawn'; import * as esbuild from 'esbuild'; +// eslint-disable-next-line depend/ban-dependencies import { readJson } from 'fs-extra'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import limit from 'p-limit'; import picocolors from 'picocolors'; diff --git a/scripts/prepare/tsc.ts b/scripts/prepare/tsc.ts index 6a6aba2643bd..af6b39e15050 100755 --- a/scripts/prepare/tsc.ts +++ b/scripts/prepare/tsc.ts @@ -1,4 +1,6 @@ +// eslint-disable-next-line depend/ban-dependencies import { emptyDir, move, readJson } from 'fs-extra'; +// eslint-disable-next-line depend/ban-dependencies import { globSync } from 'glob'; import { join } from 'path'; import * as ts from 'typescript'; diff --git a/scripts/release/__tests__/is-pr-frozen.test.ts b/scripts/release/__tests__/is-pr-frozen.test.ts index 681069af7256..27baeaa4a723 100644 --- a/scripts/release/__tests__/is-pr-frozen.test.ts +++ b/scripts/release/__tests__/is-pr-frozen.test.ts @@ -3,6 +3,7 @@ import { join } from 'node:path'; import { describe, expect, it, vi } from 'vitest'; +// eslint-disable-next-line depend/ban-dependencies import * as fsExtraImp from 'fs-extra'; import * as simpleGitImp from 'simple-git'; diff --git a/scripts/release/__tests__/version.test.ts b/scripts/release/__tests__/version.test.ts index 3572e4cb76ee..58dd785c0284 100644 --- a/scripts/release/__tests__/version.test.ts +++ b/scripts/release/__tests__/version.test.ts @@ -3,7 +3,9 @@ import { join } from 'node:path'; import { describe, expect, it, vi } from 'vitest'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import * as fsExtraImp from 'fs-extra'; import type * as MockedFSToExtra from '../../../code/__mocks__/fs-extra'; diff --git a/scripts/release/__tests__/write-changelog.test.ts b/scripts/release/__tests__/write-changelog.test.ts index f0346066b26c..59e1ccb6fd60 100644 --- a/scripts/release/__tests__/write-changelog.test.ts +++ b/scripts/release/__tests__/write-changelog.test.ts @@ -3,6 +3,7 @@ import { join } from 'node:path'; import { beforeEach, describe, expect, it, vi } from 'vitest'; +// eslint-disable-next-line depend/ban-dependencies import * as fsExtraImp from 'fs-extra'; import { dedent } from 'ts-dedent'; diff --git a/scripts/release/get-changelog-from-file.ts b/scripts/release/get-changelog-from-file.ts index 354605e04644..de8bc4e386e9 100644 --- a/scripts/release/get-changelog-from-file.ts +++ b/scripts/release/get-changelog-from-file.ts @@ -2,6 +2,7 @@ import { join } from 'node:path'; import { setOutput } from '@actions/core'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { readFile } from 'fs-extra'; import picocolors from 'picocolors'; import semver from 'semver'; diff --git a/scripts/release/get-current-version.ts b/scripts/release/get-current-version.ts index 8530f6cf9646..b0133cf03f7f 100644 --- a/scripts/release/get-current-version.ts +++ b/scripts/release/get-current-version.ts @@ -1,6 +1,7 @@ import { join } from 'node:path'; import { setOutput } from '@actions/core'; +// eslint-disable-next-line depend/ban-dependencies import { readJson } from 'fs-extra'; import picocolors from 'picocolors'; diff --git a/scripts/release/is-pr-frozen.ts b/scripts/release/is-pr-frozen.ts index d8c80708fc71..e198e89d8202 100644 --- a/scripts/release/is-pr-frozen.ts +++ b/scripts/release/is-pr-frozen.ts @@ -2,6 +2,7 @@ import { join } from 'node:path'; import { setOutput } from '@actions/core'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { readJson } from 'fs-extra'; import picocolors from 'picocolors'; diff --git a/scripts/release/label-patches.ts b/scripts/release/label-patches.ts index c1d8fa945e11..0ddbd60af981 100644 --- a/scripts/release/label-patches.ts +++ b/scripts/release/label-patches.ts @@ -1,4 +1,5 @@ import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import ora from 'ora'; import { v4 as uuidv4 } from 'uuid'; diff --git a/scripts/release/pick-patches.ts b/scripts/release/pick-patches.ts index d25667cc4974..54dc6a21b2bb 100644 --- a/scripts/release/pick-patches.ts +++ b/scripts/release/pick-patches.ts @@ -1,5 +1,6 @@ import { setOutput } from '@actions/core'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import ora from 'ora'; import picocolors from 'picocolors'; import invariant from 'tiny-invariant'; diff --git a/scripts/release/publish.ts b/scripts/release/publish.ts index 83839dd4a003..f2054d93398e 100644 --- a/scripts/release/publish.ts +++ b/scripts/release/publish.ts @@ -1,7 +1,9 @@ import { join } from 'node:path'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { readJson } from 'fs-extra'; import pRetry from 'p-retry'; import picocolors from 'picocolors'; diff --git a/scripts/release/version.ts b/scripts/release/version.ts index bdaef52fa18e..7d18b99aeca5 100644 --- a/scripts/release/version.ts +++ b/scripts/release/version.ts @@ -2,7 +2,9 @@ import { join } from 'node:path'; import { setOutput } from '@actions/core'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { readFile, readJson, writeFile, writeJson } from 'fs-extra'; import picocolors from 'picocolors'; import semver from 'semver'; diff --git a/scripts/release/write-changelog.ts b/scripts/release/write-changelog.ts index 59e0d3273958..9e8b1e342cb2 100644 --- a/scripts/release/write-changelog.ts +++ b/scripts/release/write-changelog.ts @@ -1,6 +1,7 @@ import { join } from 'node:path'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { readFile, writeFile, writeJson } from 'fs-extra'; import picocolors from 'picocolors'; import semver from 'semver'; diff --git a/scripts/reset.js b/scripts/reset.js index ed93cbce800b..d9049633d2bc 100644 --- a/scripts/reset.js +++ b/scripts/reset.js @@ -1,6 +1,7 @@ import { spawn } from 'node:child_process'; import { appendFile, writeFileSync } from 'node:fs'; +// eslint-disable-next-line depend/ban-dependencies import { remove } from 'fs-extra'; import trash from 'trash'; diff --git a/scripts/run-registry.ts b/scripts/run-registry.ts index 825788b24f51..5f179501583d 100755 --- a/scripts/run-registry.ts +++ b/scripts/run-registry.ts @@ -5,7 +5,9 @@ import type { Server } from 'node:http'; import { join, resolve as resolvePath } from 'node:path'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { execa, execaSync } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { pathExists, readJSON, remove } from 'fs-extra'; import pLimit from 'p-limit'; import picocolors from 'picocolors'; diff --git a/scripts/sandbox/generate.ts b/scripts/sandbox/generate.ts index d92696383699..495d142c0196 100755 --- a/scripts/sandbox/generate.ts +++ b/scripts/sandbox/generate.ts @@ -1,7 +1,10 @@ import * as ghActions from '@actions/core'; import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import type { Options as ExecaOptions } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies import { copy, emptyDir, ensureDir, move, remove, rename, writeFile } from 'fs-extra'; import pLimit from 'p-limit'; import { join, relative } from 'path'; diff --git a/scripts/sandbox/publish.ts b/scripts/sandbox/publish.ts index 7ddb549c3900..f83048dff5cd 100755 --- a/scripts/sandbox/publish.ts +++ b/scripts/sandbox/publish.ts @@ -1,7 +1,10 @@ import { program } from 'commander'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; import { existsSync } from 'fs'; +// eslint-disable-next-line depend/ban-dependencies import { copy, emptyDir, remove, writeFile } from 'fs-extra'; +// eslint-disable-next-line depend/ban-dependencies import { glob } from 'glob'; import { dirname, join, relative } from 'path'; diff --git a/scripts/sandbox/utils/git.ts b/scripts/sandbox/utils/git.ts index 17022db63fca..2ea8b89f29b4 100644 --- a/scripts/sandbox/utils/git.ts +++ b/scripts/sandbox/utils/git.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; import invariant from 'tiny-invariant'; diff --git a/scripts/sandbox/utils/template.ts b/scripts/sandbox/utils/template.ts index 11b6c1e86d5a..825cd6e58641 100644 --- a/scripts/sandbox/utils/template.ts +++ b/scripts/sandbox/utils/template.ts @@ -1,4 +1,5 @@ import { render } from 'ejs'; +// eslint-disable-next-line depend/ban-dependencies import { readFile } from 'fs-extra'; import prettier from 'prettier'; diff --git a/scripts/sandbox/utils/yarn.ts b/scripts/sandbox/utils/yarn.ts index a2d579b2cde0..8f4163256a08 100644 --- a/scripts/sandbox/utils/yarn.ts +++ b/scripts/sandbox/utils/yarn.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { move, remove } from 'fs-extra'; import { join } from 'path'; diff --git a/scripts/strict-ts.ts b/scripts/strict-ts.ts index 990cbe866ccf..bf0710f5a583 100644 --- a/scripts/strict-ts.ts +++ b/scripts/strict-ts.ts @@ -1,6 +1,7 @@ import { existsSync, readFileSync } from 'node:fs'; import { dirname, join } from 'node:path'; +// eslint-disable-next-line depend/ban-dependencies import glob from 'fast-glob'; import JSON5 from 'json5'; diff --git a/scripts/task.ts b/scripts/task.ts index 905b53b82cae..9a28f8e79546 100644 --- a/scripts/task.ts +++ b/scripts/task.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { outputFile, pathExists, readFile } from 'fs-extra'; import type { TestCase } from 'junit-xml'; import { getJunitXml } from 'junit-xml'; diff --git a/scripts/tasks/build.ts b/scripts/tasks/build.ts index 4a74dcba1f55..796532e2bc0c 100644 --- a/scripts/tasks/build.ts +++ b/scripts/tasks/build.ts @@ -1,4 +1,5 @@ import dirSize from 'fast-folder-size'; +// eslint-disable-next-line depend/ban-dependencies import { pathExists } from 'fs-extra'; import { join } from 'path'; import { promisify } from 'util'; diff --git a/scripts/tasks/compile.ts b/scripts/tasks/compile.ts index 2fe631c5f615..bb0bf918812a 100644 --- a/scripts/tasks/compile.ts +++ b/scripts/tasks/compile.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { readFile } from 'fs-extra'; import { resolve } from 'path'; diff --git a/scripts/tasks/generate.ts b/scripts/tasks/generate.ts index 3e1b0ddc5bc3..5736803a551d 100644 --- a/scripts/tasks/generate.ts +++ b/scripts/tasks/generate.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { pathExists, remove } from 'fs-extra'; import { join } from 'path'; diff --git a/scripts/tasks/install.ts b/scripts/tasks/install.ts index 90342845687e..0299c18d2fe4 100644 --- a/scripts/tasks/install.ts +++ b/scripts/tasks/install.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { pathExists, remove } from 'fs-extra'; import { join } from 'path'; diff --git a/scripts/tasks/publish.ts b/scripts/tasks/publish.ts index d83ffb9272b2..987286207dd1 100644 --- a/scripts/tasks/publish.ts +++ b/scripts/tasks/publish.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { pathExists } from 'fs-extra'; import { resolve } from 'path'; diff --git a/scripts/tasks/sandbox-parts.ts b/scripts/tasks/sandbox-parts.ts index a2df1e8e1691..78f8dad696cc 100644 --- a/scripts/tasks/sandbox-parts.ts +++ b/scripts/tasks/sandbox-parts.ts @@ -1,6 +1,7 @@ // This file requires many imports from `../code`, which requires both an install and bootstrap of // the repo to work properly. So we load it async in the task runner *after* those steps. import { isFunction } from 'es-toolkit'; +// eslint-disable-next-line depend/ban-dependencies import { copy, ensureDir, diff --git a/scripts/tasks/sandbox.ts b/scripts/tasks/sandbox.ts index 93d5cf823c93..5b3494d9955f 100644 --- a/scripts/tasks/sandbox.ts +++ b/scripts/tasks/sandbox.ts @@ -1,4 +1,5 @@ import dirSize from 'fast-folder-size'; +// eslint-disable-next-line depend/ban-dependencies import { pathExists, remove } from 'fs-extra'; import { join } from 'path'; import { promisify } from 'util'; diff --git a/scripts/upload-bench.ts b/scripts/upload-bench.ts index 9766079b9dc8..48e5fa618896 100644 --- a/scripts/upload-bench.ts +++ b/scripts/upload-bench.ts @@ -1,4 +1,5 @@ import { BigQuery } from '@google-cloud/bigquery'; +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; import { join } from 'path'; diff --git a/scripts/utils/exec.ts b/scripts/utils/exec.ts index c12c9eea2f9f..a4a77ebd2244 100644 --- a/scripts/utils/exec.ts +++ b/scripts/utils/exec.ts @@ -1,5 +1,5 @@ -import type { ExecaChildProcess, Options } from 'execa'; -import { execa } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies +import { type ExecaChildProcess, type Options, execa } from 'execa'; import picocolors from 'picocolors'; const logger = console; diff --git a/scripts/utils/filterExistsInCodeDir.ts b/scripts/utils/filterExistsInCodeDir.ts index 7a22fdf8d2f2..673148f916eb 100644 --- a/scripts/utils/filterExistsInCodeDir.ts +++ b/scripts/utils/filterExistsInCodeDir.ts @@ -1,5 +1,6 @@ import { join, resolve } from 'node:path'; +// eslint-disable-next-line depend/ban-dependencies import { pathExists } from 'fs-extra'; import { CODE_DIRECTORY } from './constants'; diff --git a/scripts/utils/package-json.ts b/scripts/utils/package-json.ts index cc88350ddfaa..16bdb67f7078 100644 --- a/scripts/utils/package-json.ts +++ b/scripts/utils/package-json.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { readJSON, writeJSON } from 'fs-extra'; import { join } from 'path'; diff --git a/scripts/utils/paths.ts b/scripts/utils/paths.ts index 36db99f4e093..7253fdff740c 100644 --- a/scripts/utils/paths.ts +++ b/scripts/utils/paths.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { pathExists } from 'fs-extra'; import { join } from 'path'; diff --git a/scripts/utils/serve.ts b/scripts/utils/serve.ts deleted file mode 100644 index 98ba1da21c63..000000000000 --- a/scripts/utils/serve.ts +++ /dev/null @@ -1,14 +0,0 @@ -import express from 'express'; -import type { Server } from 'http'; -import serveStatic from 'serve-static'; - -export const serve = async (location: string, port: string): Promise => { - return new Promise((resolve) => { - const app = express(); - - app.use(serveStatic(location)); - const server = app.listen(port, () => { - resolve(server); - }); - }); -}; diff --git a/scripts/utils/workspace.ts b/scripts/utils/workspace.ts index 98a0164ec5ac..fcba0311b09d 100644 --- a/scripts/utils/workspace.ts +++ b/scripts/utils/workspace.ts @@ -1,3 +1,4 @@ +// eslint-disable-next-line depend/ban-dependencies import { execaCommand } from 'execa'; import memoize from 'memoizerific'; diff --git a/scripts/utils/yarn.ts b/scripts/utils/yarn.ts index 0b8147dfa983..1f78e58162c5 100644 --- a/scripts/utils/yarn.ts +++ b/scripts/utils/yarn.ts @@ -1,5 +1,6 @@ import { join } from 'node:path'; +// eslint-disable-next-line depend/ban-dependencies import { pathExists, readJSON, writeJSON } from 'fs-extra'; // TODO -- should we generate this file a second time outside of CLI? diff --git a/scripts/vite-ecosystem-ci/before-test.js b/scripts/vite-ecosystem-ci/before-test.js index 93da3f28519b..35ba21734d06 100644 --- a/scripts/vite-ecosystem-ci/before-test.js +++ b/scripts/vite-ecosystem-ci/before-test.js @@ -8,7 +8,8 @@ import { readFile, writeFile } from 'node:fs/promises'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; -import { execa, execaCommand } from 'execa'; +// eslint-disable-next-line depend/ban-dependencies +import { execaCommand } from 'execa'; const filename = fileURLToPath(import.meta.url); // eslint-disable-next-line no-underscore-dangle, @typescript-eslint/naming-convention diff --git a/scripts/yarn.lock b/scripts/yarn.lock index a17539cb16d5..5f52272a0427 100644 --- a/scripts/yarn.lock +++ b/scripts/yarn.lock @@ -1301,6 +1301,20 @@ __metadata: languageName: node linkType: hard +"@polka/parse@npm:^1.0.0-next.28": + version: 1.0.0-next.28 + resolution: "@polka/parse@npm:1.0.0-next.28" + checksum: 10c0/42c53dfdc4b39a3b516fbd4358b2472b22f36e6038e25d463afb3f133fb1d5af84d7eb4d245ab66bc5793d6414299fdd9093803e5214e560f0693f2176fc58b6 + languageName: node + linkType: hard + +"@polka/url@npm:^1.0.0-next.21": + version: 1.0.0-next.28 + resolution: "@polka/url@npm:1.0.0-next.28" + checksum: 10c0/acc5ea62597e4da2fb42dbee02749d07f102ae7d6d2c966bf7e423c79cd65d1621da305af567e6e7c232f3b565e242d1ec932cbb3dcc0db1508d02e9a2cafa2e + languageName: node + linkType: hard + "@rollup/rollup-android-arm-eabi@npm:4.21.0": version: 4.21.0 resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.0" @@ -1527,6 +1541,7 @@ __metadata: "@nx/workspace": "npm:18.0.6" "@octokit/graphql": "npm:^5.0.5" "@octokit/request": "npm:^8.1.2" + "@polka/parse": "npm:^1.0.0-next.28" "@storybook/eslint-config-storybook": "npm:^4.0.0" "@storybook/linter-config": "npm:^4.0.0" "@testing-library/dom": "npm:^10.4.0" @@ -1538,7 +1553,6 @@ __metadata: "@types/detect-port": "npm:^1.3.5" "@types/ejs": "npm:^3.1.5" "@types/escodegen": "npm:^0.0.6" - "@types/express": "npm:^4.17.21" "@types/fs-extra": "npm:^11.0.4" "@types/http-server": "npm:^0.12.4" "@types/jest": "npm:^29.5.12" @@ -1576,6 +1590,7 @@ __metadata: eslint: "npm:^8.57.0" eslint-config-airbnb-typescript: "npm:^18.0.0" eslint-config-prettier: "npm:^9.1.0" + eslint-plugin-depend: "npm:^0.11.0" eslint-plugin-eslint-comments: "npm:^3.2.0" eslint-plugin-file-progress: "npm:^1.4.0" eslint-plugin-html: "npm:^8.1.1" @@ -1587,7 +1602,6 @@ __metadata: eslint-plugin-react-hooks: "npm:^4.6.2" eslint-plugin-storybook: "npm:^0.8.0" execa: "npm:^6.1.0" - express: "npm:^4.19.2" fast-folder-size: "npm:^2.2.0" fast-glob: "npm:^3.3.2" find-up: "npm:^5.0.0" @@ -1611,6 +1625,7 @@ __metadata: picocolors: "npm:^1.1.0" playwright: "npm:1.46.0" playwright-core: "npm:1.46.0" + polka: "npm:^1.0.0-next.28" prettier: "npm:^3.3.2" prettier-plugin-brace-style: "npm:^0.6.2" prettier-plugin-css-order: "npm:^2.1.2" @@ -1770,16 +1785,6 @@ __metadata: languageName: node linkType: hard -"@types/body-parser@npm:*": - version: 1.19.4 - resolution: "@types/body-parser@npm:1.19.4" - dependencies: - "@types/connect": "npm:*" - "@types/node": "npm:*" - checksum: 10c0/bec2b8a97861a960ee415f7ab3c2aeb7f4d779fd364d27ddee46057897ea571735f1f854f5ee41682964315d4e3699f62427998b9c21851d773398ef535f0612 - languageName: node - linkType: hard - "@types/concat-stream@npm:^2.0.0": version: 2.0.1 resolution: "@types/concat-stream@npm:2.0.1" @@ -1853,30 +1858,6 @@ __metadata: languageName: node linkType: hard -"@types/express-serve-static-core@npm:^4.17.33": - version: 4.17.39 - resolution: "@types/express-serve-static-core@npm:4.17.39" - dependencies: - "@types/node": "npm:*" - "@types/qs": "npm:*" - "@types/range-parser": "npm:*" - "@types/send": "npm:*" - checksum: 10c0/b23b005fddd2ba3f7142ec9713f06b5582c7712cdf99c3419d3972364903b348a103c3264d9a761d6497140e3b89bd416454684c4bdeff206b4c59b86e96428a - languageName: node - linkType: hard - -"@types/express@npm:^4.17.21": - version: 4.17.21 - resolution: "@types/express@npm:4.17.21" - dependencies: - "@types/body-parser": "npm:*" - "@types/express-serve-static-core": "npm:^4.17.33" - "@types/qs": "npm:*" - "@types/serve-static": "npm:*" - checksum: 10c0/12e562c4571da50c7d239e117e688dc434db1bac8be55613294762f84fd77fbd0658ccd553c7d3ab02408f385bc93980992369dd30e2ecd2c68c358e6af8fabf - languageName: node - linkType: hard - "@types/fs-extra@npm:^11.0.4": version: 11.0.4 resolution: "@types/fs-extra@npm:11.0.4" @@ -2098,20 +2079,6 @@ __metadata: languageName: node linkType: hard -"@types/qs@npm:*": - version: 6.9.9 - resolution: "@types/qs@npm:6.9.9" - checksum: 10c0/aede2a4181a49ae8548a1354bac3f8235cb0c5aab066b10875a3e68e88a199e220f4284e7e2bb75a3c18e5d4ff6abe1a6ce0389ef31b63952cc45e0f4d885ba0 - languageName: node - linkType: hard - -"@types/range-parser@npm:*": - version: 1.2.6 - resolution: "@types/range-parser@npm:1.2.6" - checksum: 10c0/46e7fffc54cdacc8fb0cd576f8f9a6436453f0176205d6ec55434a460c7677e78e688673426d5db5e480501b2943ba08a16ececa3a354c222093551c7217fb8f - languageName: node - linkType: hard - "@types/react-dom@npm:^18.3.0": version: 18.3.0 resolution: "@types/react-dom@npm:18.3.0" @@ -2155,7 +2122,7 @@ __metadata: languageName: node linkType: hard -"@types/serve-static@npm:*, @types/serve-static@npm:^1.15.7": +"@types/serve-static@npm:^1.15.7": version: 1.15.7 resolution: "@types/serve-static@npm:1.15.7" dependencies: @@ -5517,6 +5484,17 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-depend@npm:^0.11.0": + version: 0.11.0 + resolution: "eslint-plugin-depend@npm:0.11.0" + dependencies: + fd-package-json: "npm:^1.2.0" + module-replacements: "npm:^2.1.0" + semver: "npm:^7.6.3" + checksum: 10c0/64baf4d4f5d406efa1f13bda723ff0eb5fe4cee0ae8c3679fcdfccb4d7ba3a9472416fa3c54d75f1bde3e0123e55a85774662484a5b0355812f21a8968ee784a + languageName: node + linkType: hard + "eslint-plugin-eslint-comments@npm:^3.2.0": version: 3.2.0 resolution: "eslint-plugin-eslint-comments@npm:3.2.0" @@ -6016,7 +5994,7 @@ __metadata: languageName: node linkType: hard -"express@npm:4.19.2, express@npm:^4.19.2": +"express@npm:4.19.2": version: 4.19.2 resolution: "express@npm:4.19.2" dependencies: @@ -6182,6 +6160,15 @@ __metadata: languageName: node linkType: hard +"fd-package-json@npm:^1.2.0": + version: 1.2.0 + resolution: "fd-package-json@npm:1.2.0" + dependencies: + walk-up-path: "npm:^3.0.1" + checksum: 10c0/712a78a12bd8ec8482867b26bbcb2ff1dca9b096a416150c138e1512f1879c6d23dfb41b03b8e9226afc1e58a35df4738e9f9ae57032ff1dbbae75acfb70343b + languageName: node + linkType: hard + "fd-slicer@npm:~1.1.0": version: 1.1.0 resolution: "fd-slicer@npm:1.1.0" @@ -9820,6 +9807,13 @@ __metadata: languageName: node linkType: hard +"module-replacements@npm:^2.1.0": + version: 2.5.0 + resolution: "module-replacements@npm:2.5.0" + checksum: 10c0/7fcbcb19151778a2f2fa70b7bffb134bb8922b2306e2a0d7b4a863467a9d6d9d5fed537763c43272e22b69dbddaf1610746b42a68b4663aa225e85f9ae9b03c8 + languageName: node + linkType: hard + "mount-point@npm:^3.0.0": version: 3.0.0 resolution: "mount-point@npm:3.0.0" @@ -10968,6 +10962,16 @@ __metadata: languageName: node linkType: hard +"polka@npm:^1.0.0-next.28": + version: 1.0.0-next.28 + resolution: "polka@npm:1.0.0-next.28" + dependencies: + "@polka/url": "npm:^1.0.0-next.21" + trouter: "npm:^4.0.0" + checksum: 10c0/206bab3eb1c3c44c2fba9704d998b144ec36c4852b0b97192a1fd3953f215b739e2286852492c13dcc9faecea0f7825a76356d6eef7e02afd6a800d1dbb84ead + languageName: node + linkType: hard + "portfinder@npm:^1.0.28": version: 1.0.32 resolution: "portfinder@npm:1.0.32" @@ -11627,6 +11631,13 @@ __metadata: languageName: node linkType: hard +"regexparam@npm:^3.0.0": + version: 3.0.0 + resolution: "regexparam@npm:3.0.0" + checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459 + languageName: node + linkType: hard + "remark-cli@npm:^12.0.0, remark-cli@npm:^12.0.1": version: 12.0.1 resolution: "remark-cli@npm:12.0.1" @@ -12381,6 +12392,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.6.3": + version: 7.6.3 + resolution: "semver@npm:7.6.3" + bin: + semver: bin/semver.js + checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf + languageName: node + linkType: hard + "send@npm:0.18.0": version: 0.18.0 resolution: "send@npm:0.18.0" @@ -13500,6 +13520,15 @@ __metadata: languageName: node linkType: hard +"trouter@npm:^4.0.0": + version: 4.0.0 + resolution: "trouter@npm:4.0.0" + dependencies: + regexparam: "npm:^3.0.0" + checksum: 10c0/e27326a831187c6a47a72b62212364e3f88247fa2a8723e5030e14a0002b69756fb51f97efbda2466deb05f4a78ecb83c2a1a7b343e9659cbfb3f370156f1e12 + languageName: node + linkType: hard + "try-catch@npm:^3.0.0": version: 3.0.1 resolution: "try-catch@npm:3.0.1"