UNPKG

storybook

Version:

Storybook: Develop, document, and test UI components in isolation

421 lines (409 loc) • 15 kB
import CJS_COMPAT_NODE_URL_q99y7iqlbzn from 'node:url'; import CJS_COMPAT_NODE_PATH_q99y7iqlbzn from 'node:path'; import CJS_COMPAT_NODE_MODULE_q99y7iqlbzn from "node:module"; var __filename = CJS_COMPAT_NODE_URL_q99y7iqlbzn.fileURLToPath(import.meta.url); var __dirname = CJS_COMPAT_NODE_PATH_q99y7iqlbzn.dirname(__filename); var require = CJS_COMPAT_NODE_MODULE_q99y7iqlbzn.createRequire(import.meta.url); // ------------------------------------------------------------ // end of CJS compatibility banner, injected by Storybook's esbuild configuration // ------------------------------------------------------------ import { basename, dirname, isAbsolute, join, normalize, resolve } from "./chunk-LMQEOO5W.js"; import { __name } from "./chunk-MB5KTO7X.js"; // src/core-server/mocking-utils/resolve.ts import { readFileSync as readFileSync2, realpathSync } from "node:fs"; import { createRequire } from "node:module"; import { findMockRedirect } from "@vitest/mocker/redirect"; // ../node_modules/resolve.exports/dist/index.mjs function e(e2, n2, r2) { throw new Error(r2 ? `No known conditions for "${n2}" specifier in "${e2}" package` : `Missing "${n2}" specifier in "${e2}" package`); } __name(e, "e"); function n(n2, i, o2, f) { let s, u, l = r(n2, o2), c = function(e2) { let n3 = /* @__PURE__ */ new Set(["default", ...e2.conditions || []]); return e2.unsafe || n3.add(e2.require ? "require" : "import"), e2.unsafe || n3.add(e2.browser ? "browser" : "node"), n3; }(f || {}), a = i[l]; if (void 0 === a) { let e2, n3, r2, t3; for (t3 in i) n3 && t3.length < n3.length || ("/" === t3[t3.length - 1] && l.startsWith(t3) ? (u = l.substring(t3.length), n3 = t3) : t3.length > 1 && (r2 = t3.indexOf("*", 1), ~r2 && (e2 = RegExp("^" + t3.substring(0, r2) + "(.*)" + t3.substring(1 + r2) + "$").exec(l), e2 && e2[1] && (u = e2[1], n3 = t3)))); a = i[n3]; } return a || e(n2, l), s = t(a, c), s || e(n2, l, 1), u && function(e2, n3) { let r2, t3 = 0, i2 = e2.length, o3 = /[*]/g, f2 = /[/]$/; for (; t3 < i2; t3++) e2[t3] = o3.test(r2 = e2[t3]) ? r2.replace(o3, n3) : f2.test(r2) ? r2 + n3 : r2; }(s, u), s; } __name(n, "n"); function r(e2, n2, r2) { if (e2 === n2 || "." === n2) return "."; let t3 = e2 + "/", i = t3.length, o2 = n2.slice(0, i) === t3, f = o2 ? n2.slice(i) : n2; return "#" === f[0] ? f : o2 || !r2 ? "./" === f.slice(0, 2) ? f : "./" + f : f; } __name(r, "r"); function t(e2, n2, r2) { if (e2) { if ("string" == typeof e2) return r2 && r2.add(e2), [e2]; let i, o2; if (Array.isArray(e2)) { for (o2 = r2 || /* @__PURE__ */ new Set(), i = 0; i < e2.length; i++) t(e2[i], n2, o2); if (!r2 && o2.size) return [...o2]; } else for (i in e2) if (n2.has(i)) return t(e2[i], n2, r2); } } __name(t, "t"); function o(e2, r2, t3) { let i, o2 = e2.exports; if (o2) { if ("string" == typeof o2) o2 = { ".": o2 }; else for (i in o2) { "." !== i[0] && (o2 = { ".": o2 }); break; } return n(e2.name, o2, r2 || ".", t3); } } __name(o, "o"); // src/core-server/mocking-utils/extract.ts import { readFileSync } from "node:fs"; import { generate, parser, types as t2 } from "storybook/internal/babel"; import { logger } from "storybook/internal/node-logger"; import { telemetry } from "storybook/internal/telemetry"; import { transformSync } from "esbuild"; // ../node_modules/estree-walker/src/walker.js var WalkerBase = class { static { __name(this, "WalkerBase"); } constructor() { this.should_skip = false; this.should_remove = false; this.replacement = null; this.context = { skip: /* @__PURE__ */ __name(() => this.should_skip = true, "skip"), remove: /* @__PURE__ */ __name(() => this.should_remove = true, "remove"), replace: /* @__PURE__ */ __name((node) => this.replacement = node, "replace") }; } /** * @template {Node} Parent * @param {Parent | null | undefined} parent * @param {keyof Parent | null | undefined} prop * @param {number | null | undefined} index * @param {Node} node */ replace(parent, prop, index, node) { if (parent && prop) { if (index != null) { parent[prop][index] = node; } else { parent[prop] = node; } } } /** * @template {Node} Parent * @param {Parent | null | undefined} parent * @param {keyof Parent | null | undefined} prop * @param {number | null | undefined} index */ remove(parent, prop, index) { if (parent && prop) { if (index !== null && index !== void 0) { parent[prop].splice(index, 1); } else { delete parent[prop]; } } } }; // ../node_modules/estree-walker/src/sync.js var SyncWalker = class extends WalkerBase { static { __name(this, "SyncWalker"); } /** * * @param {SyncHandler} [enter] * @param {SyncHandler} [leave] */ constructor(enter, leave) { super(); this.should_skip = false; this.should_remove = false; this.replacement = null; this.context = { skip: /* @__PURE__ */ __name(() => this.should_skip = true, "skip"), remove: /* @__PURE__ */ __name(() => this.should_remove = true, "remove"), replace: /* @__PURE__ */ __name((node) => this.replacement = node, "replace") }; this.enter = enter; this.leave = leave; } /** * @template {Node} Parent * @param {Node} node * @param {Parent | null} parent * @param {keyof Parent} [prop] * @param {number | null} [index] * @returns {Node | null} */ visit(node, parent, prop, index) { if (node) { if (this.enter) { const _should_skip = this.should_skip; const _should_remove = this.should_remove; const _replacement = this.replacement; this.should_skip = false; this.should_remove = false; this.replacement = null; this.enter.call(this.context, node, parent, prop, index); if (this.replacement) { node = this.replacement; this.replace(parent, prop, index, node); } if (this.should_remove) { this.remove(parent, prop, index); } const skipped = this.should_skip; const removed = this.should_remove; this.should_skip = _should_skip; this.should_remove = _should_remove; this.replacement = _replacement; if (skipped) return node; if (removed) return null; } let key; for (key in node) { const value = node[key]; if (value && typeof value === "object") { if (Array.isArray(value)) { const nodes = ( /** @type {Array<unknown>} */ value ); for (let i = 0; i < nodes.length; i += 1) { const item = nodes[i]; if (isNode(item)) { if (!this.visit(item, node, key, i)) { i--; } } } } else if (isNode(value)) { this.visit(value, node, key, null); } } } if (this.leave) { const _replacement = this.replacement; const _should_remove = this.should_remove; this.replacement = null; this.should_remove = false; this.leave.call(this.context, node, parent, prop, index); if (this.replacement) { node = this.replacement; this.replace(parent, prop, index, node); } if (this.should_remove) { this.remove(parent, prop, index); } const removed = this.should_remove; this.replacement = _replacement; this.should_remove = _should_remove; if (removed) return null; } } return node; } }; function isNode(value) { return value !== null && typeof value === "object" && "type" in value && typeof value.type === "string"; } __name(isNode, "isNode"); // ../node_modules/estree-walker/src/index.js function walk(ast, { enter, leave }) { const instance = new SyncWalker(enter, leave); return instance.visit(ast, null); } __name(walk, "walk"); // src/core-server/mocking-utils/extract.ts var DEFAULT_MODULE_DIRECTORIES = ["/node_modules/"]; function isModuleDirectory(path) { const normalizedPath = normalize(path); return DEFAULT_MODULE_DIRECTORIES.some((dir) => normalizedPath.includes(dir)); } __name(isModuleDirectory, "isModuleDirectory"); var babelParser = /* @__PURE__ */ __name((code) => { return parser.parse(code, { sourceType: "module", // Enable plugins to handle modern JavaScript features, including TSX. plugins: ["typescript", "jsx", "classProperties", "objectRestSpread"], errorRecovery: true }).program; }, "babelParser"); function rewriteSbMockImportCalls(code) { const ast = babelParser(code); walk(ast, { enter(node) { if (node.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "sb" && node.callee.property.type === "Identifier" && node.callee.property.name === "mock" && node.arguments.length > 0 && node.arguments[0].type === "CallExpression" && node.arguments[0].callee.type === "Import" && node.arguments[0].arguments.length === 1 && node.arguments[0].arguments[0].type === "StringLiteral") { node.arguments[0] = t2.stringLiteral(node.arguments[0].arguments[0].value); } } }); return generate(ast, {}, code); } __name(rewriteSbMockImportCalls, "rewriteSbMockImportCalls"); function extractMockCalls(options, parse, root) { try { let hasSpyTrue2 = function(objectExpression) { if (!objectExpression || !objectExpression.properties) { return false; } for (const prop of objectExpression.properties) { if (prop.type === "ObjectProperty" && (prop.key.type === "Identifier" && prop.key.name === "spy" || prop.key.type === "StringLiteral" && prop.key.value === "spy") && prop.value.type === "BooleanLiteral" && prop.value.value === true) { return true; } } return false; }; var hasSpyTrue = hasSpyTrue2; __name(hasSpyTrue2, "hasSpyTrue"); const previewConfigCode = readFileSync(options.previewConfigPath, "utf-8"); const { code: jsCode } = transformSync(previewConfigCode, { loader: "tsx", format: "esm" }); const ast = parse(jsCode); const mocks = []; walk(ast, { // @ts-expect-error - Node comes from babel async enter(node) { if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression" || node.callee.object.type !== "Identifier" || node.callee.object.name !== "sb" || node.callee.property.type !== "Identifier" || node.callee.property.name !== "mock") { return; } if (node.arguments.length === 0) { return; } let path; if (node.arguments[0].type === "StringLiteral") { path = node.arguments[0].value; } else if (node.arguments[0].type === "CallExpression" && node.arguments[0].callee.type === "Import" && node.arguments[0].arguments[0].type === "StringLiteral") { path = node.arguments[0].arguments[0].value; } else { return; } const spy = node.arguments.length > 1 && node.arguments[1].type === "ObjectExpression" && hasSpyTrue2(node.arguments[1]); const { absolutePath, redirectPath } = resolveMock(path, root, options.previewConfigPath); const pathWithoutExtension = path.replace(/\.[^/.]+$/, ""); const basenameAbsolutePath = basename(absolutePath); const basenamePath = basename(path); const pathWithoutExtensionAndBasename = basenameAbsolutePath === basenamePath ? pathWithoutExtension : path; mocks.push({ path: pathWithoutExtensionAndBasename, absolutePath, redirectPath, spy }); } }); if (!options.coreOptions?.disableTelemetry) { telemetry( "mocking", { modulesMocked: mocks.length, modulesSpied: mocks.map((mock) => mock.spy).filter(Boolean).length, modulesManuallyMocked: mocks.map((mock) => !!mock.redirectPath).filter(Boolean).length }, { configDir: options.configDir } ); } return mocks; } catch (error) { logger.debug("Error extracting mock calls", error); return []; } } __name(extractMockCalls, "extractMockCalls"); // src/core-server/mocking-utils/resolve.ts var require2 = createRequire(import.meta.url); function findPackageJson(specifier, basedir) { const packageJsonPath = require2.resolve(`${specifier}/package.json`, { paths: [basedir] }); return { path: packageJsonPath, data: JSON.parse(readFileSync2(packageJsonPath, "utf-8")) }; } __name(findPackageJson, "findPackageJson"); function resolveExternalModule(path, root) { const parts = path.split("/"); const packageName = path.startsWith("@") ? `${parts[0]}/${parts[1]}` : parts[0]; const entry = `.${path.slice(packageName.length)}`; const { path: packageJsonPath, data: pkg } = findPackageJson(packageName, root); const packageDir = dirname(packageJsonPath); if (pkg.exports) { const result = o(pkg, entry, { browser: true }); if (result) { return join(packageDir, result[0]); } } return require2.resolve(path, { paths: [root] }); } __name(resolveExternalModule, "resolveExternalModule"); function getIsExternal(path, importer) { try { return !isAbsolute(path) && isModuleDirectory(require2.resolve(path, { paths: [importer] })); } catch (e2) { return false; } } __name(getIsExternal, "getIsExternal"); function resolveMock(path, root, importer) { const isExternal = getIsExternal(path, root); const externalPath = isExternal ? path : null; const absolutePath = isExternal ? resolveExternalModule(path, root) : require2.resolve(path, { paths: [dirname(importer)] }); const normalizedAbsolutePath = resolve(absolutePath); const redirectPath = findMockRedirect(root, normalizedAbsolutePath, externalPath); return { absolutePath: normalizedAbsolutePath, redirectPath // will be null if no __mocks__ file is found }; } __name(resolveMock, "resolveMock"); function getRealPath(path, preserveSymlinks) { try { return preserveSymlinks ? realpathSync(path) : path; } catch { return path; } } __name(getRealPath, "getRealPath"); function resolveWithExtensions(path, from) { const extensions = [".js", ".ts", ".tsx", ".mjs", ".cjs", ".svelte", ".vue"]; for (const extension of extensions) { try { return require2.resolve(path + extension, { paths: [from] }); } catch (e2) { continue; } } return require2.resolve(path, { paths: [from] }); } __name(resolveWithExtensions, "resolveWithExtensions"); export { resolveExternalModule, getIsExternal, getRealPath, resolveWithExtensions, babelParser, rewriteSbMockImportCalls, extractMockCalls };