UNPKG

@storybook/react-native

Version:

A better way to develop React Native Components for your app

272 lines (262 loc) 9.74 kB
const require_chunk = require("./chunk-Ble4zEEl.js"); const require_buildIndex = require("./buildIndex-l9rzAl79.js"); //#region scripts/require-interop.js var require_require_interop = /* @__PURE__ */ require_chunk.__commonJSMin(((exports, module) => { let registered = false; function interopRequireDefault(filePath) { const hasEsbuildBeenRegistered = !!require("module")._extensions[".ts"]; if (registered === false && !hasEsbuildBeenRegistered) { const { register } = require("esbuild-register/dist/node"); registered = true; register({ target: `node${process.version.slice(1)}`, format: "cjs", hookIgnoreNodeModules: true, keepNames: true, tsconfigRaw: `{ "compilerOptions": { "strict": false, "skipLibCheck": true, }, }` }); } const result = require(filePath); return typeof result === "object" && result !== null && typeof result.default !== "undefined" ? result.default : result; } module.exports = { interopRequireDefault }; })); //#endregion //#region scripts/generate.js var require_generate = /* @__PURE__ */ require_chunk.__commonJSMin(((exports, module) => { const { toRequireContext, ensureRelativePathHasDot, getPreviewExists, resolveAddonFile, getAddonName } = require_buildIndex.require_common(); const { normalizeStories, globToRegexp, loadMainConfig, getInterpretedFile } = require("storybook/internal/common"); const { interopRequireDefault } = require_require_interop(); const fs = require("fs"); const { networkInterfaces } = require("node:os"); const path = require("path"); const cwd = process.cwd(); const MAIN_ADDONS_DEPRECATION_URL = "https://github.com/storybookjs/react-native/blob/main/MIGRATION.md#deprecating-addons-in-rnstorybook-main"; /** * @param {{ addons?: unknown[] }} main * @param {string} configPath * * @todo Remove support for `main.addons` in a future major version. */ function warnDeprecatedMainAddonsField(main, configPath) { const addons = main.addons ?? []; if (addons.length === 0) return; const names = addons.map((addon) => getAddonName(addon)).filter((name) => typeof name === "string"); const list = [...new Set(names)].join(", "); console.warn(`[Storybook React Native] The \`addons\` field in your main config (${configPath}) is deprecated and will be removed in a future major version.\nMove every entry to \`deviceAddons\` instead. That includes on-device UI packages (\`@storybook/addon-ondevice-*\`), other addons you bundle with the app (for example storybook-addon-deep-controls), and local paths such as ./my-addon.\n` + (list ? `Still listed under \`addons\`: ${list}.\n` : "") + `Details: ${MAIN_ADDONS_DEPRECATION_URL}`); } const loadMain = async ({ configPath, cwd }) => { try { return await loadMainConfig({ configDir: configPath, cwd }); } catch { console.error("Error loading main config, trying fallback"); } const mainPath = getInterpretedFile(path.resolve(cwd, configPath, "main")); if (!mainPath) throw new Error(`Main config file not found in ${path.resolve(cwd, configPath)}`); return interopRequireDefault(mainPath); }; /** * Get the local IP address of the machine. * @returns The local IP address of the machine. */ function getLocalIPAddress() { const nets = networkInterfaces(); for (const name of Object.keys(nets)) for (const net of nets[name]) { const familyV4Value = typeof net.family === "string" ? "IPv4" : 4; if (net.family === familyV4Value && !net.internal) return net.address; } return "0.0.0.0"; } /** * @param {{ * configPath: string; * useJs?: boolean; * docTools?: boolean; * host?: string; * port?: number; * secured?: boolean; * disableUI?: boolean; * }} generateOptions */ async function generate(generateOptions) { const { configPath, useJs = false, docTools = true, host = void 0, port = void 0, secured = false, disableUI = false } = generateOptions; const channelHost = host === "auto" ? getLocalIPAddress() : host; const storybookRequiresLocation = path.resolve(cwd, configPath, `storybook.requires.${useJs ? "js" : "ts"}`); const main = await loadMain({ configPath, cwd }); warnDeprecatedMainAddonsField(main, configPath); const normalizedStories = normalizeStories(main.stories, { configDir: configPath, workingDir: cwd }).map((specifier) => { const reg = globToRegexp(`./${specifier.files}`); const { path: p, recursive: r, match: m } = toRequireContext(specifier); const pathToStory = ensureRelativePathHasDot(path.posix.relative(configPath, p)); return `{ titlePrefix: "${specifier.titlePrefix}", directory: "${specifier.directory}", files: "${specifier.files}", importPathMatcher: /${reg.source}/, req: require.context( '${pathToStory}', ${r}, ${m} ), }`; }); const registeredAddons = []; const allAddons = [...main.addons ?? [], ...main.deviceAddons ?? []]; for (const addon of allAddons) { const registerPath = resolveAddonFile(getAddonName(addon), "register", [ "js", "mjs", "jsx", "ts", "tsx" ], configPath); if (registerPath) registeredAddons.push(`import "${registerPath}";`); } const docToolsAnnotation = "require(\"@storybook/react-native/preview\")"; const enhancers = []; if (docTools) enhancers.push(docToolsAnnotation); for (const addon of allAddons) { const previewPath = resolveAddonFile(getAddonName(addon), "preview", [ "js", "mjs", "jsx", "ts", "tsx" ], configPath); if (previewPath) { enhancers.push(`require('${previewPath}')`); continue; } } let options = ""; let optionsVar = ""; const reactNativeOptions = main.reactNative ?? {}; if (disableUI) reactNativeOptions.disableUI = true; if (reactNativeOptions && typeof reactNativeOptions === "object") { optionsVar = `const options = ${JSON.stringify(reactNativeOptions, null, 2)}`; options = "options"; } let featuresAssignment = ""; const features = main.features; if (features && typeof features === "object") { const featureEntries = Object.entries(features).filter(([, value]) => typeof value === "boolean"); if (featureEntries.length > 0) featuresAssignment = featureEntries.map(([key, value]) => `globalThis.FEATURES.${key} = ${value};`).join("\n"); } if (getPreviewExists({ configPath })) enhancers.unshift("require('./preview')"); const annotations = `[ ${enhancers.join(",\n ")} ]`; const hasWebsocketConfig = host !== void 0 || port !== void 0 || secured; const websocketAssignmentLines = []; if (channelHost) websocketAssignmentLines.push(`host: '${channelHost}',`); if (hasWebsocketConfig) { websocketAssignmentLines.push(`port: ${port ?? 7007},`); websocketAssignmentLines.push(`secured: ${Boolean(secured)},`); } const fileContent = `/* do not change this file, it is auto generated by storybook. */ ${useJs ? "" : "/// <reference types=\"@storybook/react-native/metro-env\" />\n"}import { start, updateView${useJs ? "" : ", View, type Features"} } from '@storybook/react-native'; ${registeredAddons.join("\n")} const normalizedStories = [ ${normalizedStories.join(",\n ")} ]; ${useJs ? "" : ` declare global { var view: View; var STORIES: typeof normalizedStories; var STORYBOOK_WEBSOCKET: | { host?: string; port?: number; secured?: boolean } | undefined; var FEATURES: Features; } `} const annotations = ${annotations}; globalThis.STORIES = normalizedStories; ${hasWebsocketConfig ? `globalThis.STORYBOOK_WEBSOCKET = { ${websocketAssignmentLines.join("\n ")} };` : ""} module?.hot?.accept?.(); ${featuresAssignment ? `\n${featuresAssignment}\n` : ""} ${optionsVar} if (!globalThis.view) { globalThis.view = start({ annotations, storyEntries: normalizedStories, ${options ? ` ${options},` : ""} }); } else { updateView(globalThis.view, annotations, normalizedStories${options ? `, ${options}` : ""}); } export const view${useJs ? "" : ": View"} = globalThis.view; `; fs.writeFileSync(storybookRequiresLocation, fileContent, { encoding: "utf8", flag: "w" }); } module.exports = { generate }; })); //#endregion //#region src/env-tools.ts function envVariableToBoolean(value, defaultValue = false) { switch (value) { case "true": return true; case "false": return false; default: return !!defaultValue; } } function envVariableToString(value, defaultValue) { return value ?? defaultValue; } function envVariableToNumber(value, defaultValue) { const parsed = parseInt(value ?? "", 10); if (!isNaN(parsed)) return parsed; return defaultValue; } function loadWebsocketEnvOverrides(websockets) { const envHost = envVariableToString(process.env.STORYBOOK_WS_HOST, websockets === "auto" ? void 0 : websockets?.host ?? void 0); const envPort = envVariableToNumber(process.env.STORYBOOK_WS_PORT, websockets === "auto" ? 7007 : websockets?.port ?? 7007); const envSecured = envVariableToBoolean(process.env.STORYBOOK_WS_SECURED); if (websockets === void 0 && !envHost) return { host: void 0, port: void 0, secured: false }; const config = websockets === "auto" || websockets === void 0 ? {} : { ...websockets }; if (envHost) config.host = envHost; if (envPort) config.port = envPort; if (envSecured) config.secured = true; return config; } //#endregion Object.defineProperty(exports, "envVariableToBoolean", { enumerable: true, get: function() { return envVariableToBoolean; } }); Object.defineProperty(exports, "loadWebsocketEnvOverrides", { enumerable: true, get: function() { return loadWebsocketEnvOverrides; } }); Object.defineProperty(exports, "require_generate", { enumerable: true, get: function() { return require_generate; } });