UNPKG

@storybook/react-native

Version:

A better way to develop React Native Components for your app

327 lines (321 loc) 11.8 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __commonJS = (cb, mod) => function __require() { return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // scripts/common.js var require_common = __commonJS({ "scripts/common.js"(exports2, module2) { var { globToRegexp } = require("storybook/internal/common"); var path2 = require("path"); var fs = require("fs"); var cwd2 = process.cwd(); var toRequireContext = (specifier) => { const { directory, files } = specifier; const match = globToRegexp(`./${files}`); return { path: directory, recursive: files.includes("**") || files.split("/").length > 1, match }; }; var supportedExtensions = ["js", "jsx", "ts", "tsx", "cjs", "mjs"]; function getFilePathExtension({ configPath }, fileName) { for (const ext of supportedExtensions) { const filePath = path2.resolve(cwd2, configPath, `${fileName}.${ext}`); if (fs.existsSync(filePath)) { return ext; } } return null; } function getFilePathWithExtension2({ configPath }, fileName) { for (const ext of supportedExtensions) { const filePath = path2.resolve(cwd2, configPath, `${fileName}.${ext}`); if (fs.existsSync(filePath)) { return filePath; } } return null; } function ensureRelativePathHasDot2(relativePath) { return relativePath.startsWith(".") ? relativePath : `./${relativePath}`; } function getPreviewExists({ configPath }) { return !!getFilePathExtension({ configPath }, "preview"); } function resolveAddonFile(addon, file, extensions = ["js", "mjs", "ts"], configPath) { if (!addon || typeof addon !== "string") return null; const resolvePaths = { paths: [cwd2] }; try { const basePath = `${addon}/${file}`; require.resolve(basePath, resolvePaths); return basePath; } catch (_error) { } for (const ext of extensions) { try { const filePath = `${addon}/${file}.${ext}`; require.resolve(filePath, resolvePaths); return filePath; } catch (_error) { } } if (addon.startsWith("./") || addon.startsWith("../")) { try { const extension = getFilePathExtension({ configPath }, `${addon}/${file}`); if (extension) { return `${addon}/${file}`; } } catch (_error) { } } return null; } function getAddonName(addon) { if (typeof addon === "string") return addon; if (typeof addon === "object" && addon.name && typeof addon.name === "string") return addon.name; console.error("Invalid addon configuration", addon); return null; } module2.exports = { toRequireContext, getFilePathExtension, ensureRelativePathHasDot: ensureRelativePathHasDot2, getPreviewExists, resolveAddonFile, getAddonName, getFilePathWithExtension: getFilePathWithExtension2 }; } }); // src/node.ts var node_exports = {}; __export(node_exports, { buildIndex: () => buildIndex, createChannelServer: () => createChannelServer }); module.exports = __toCommonJS(node_exports); // src/metro/channelServer.ts var import_ws = require("ws"); var import_node_http = require("http"); // src/metro/buildIndex.ts var import_common = require("storybook/internal/common"); var import_node_fs = require("fs"); var import_glob = require("glob"); var import_path = __toESM(require("path")); var import_csf_tools = require("storybook/internal/csf-tools"); var import_csf = require("storybook/internal/csf"); var import_preview_api = require("storybook/internal/preview-api"); var import_common2 = __toESM(require_common()); var cwd = process.cwd(); var makeTitle = (fileName, specifier, userTitle) => { const title = (0, import_preview_api.userOrAutoTitleFromSpecifier)(fileName, specifier, userTitle); if (title) { return title.replace("./", ""); } else if (userTitle) { return userTitle.replace("./", ""); } else { console.error("Could not generate title!!"); process.exit(1); } }; function ensureRelativePathHasDot(relativePath) { return relativePath.startsWith(".") ? relativePath : `./${relativePath}`; } async function buildIndex({ configPath }) { const main = await (0, import_common.loadMainConfig)({ configDir: configPath, cwd }); if (!main.stories || !Array.isArray(main.stories)) { throw new Error("No stories found"); } const storiesSpecifiers = (0, import_common.normalizeStories)(main.stories, { configDir: configPath, workingDir: cwd }); const specifierStoryPaths = storiesSpecifiers.map((specifier) => { return (0, import_glob.sync)(specifier.files, { cwd: import_path.default.resolve(process.cwd(), specifier.directory), absolute: true, // default to always ignore (exclude) anything in node_modules ignore: ["**/node_modules"] }).map((storyPath) => { const normalizePathForWindows = (str) => import_path.default.sep === "\\" ? str.replace(/\\/g, "/") : str; return normalizePathForWindows(storyPath); }); }); const csfStories = specifierStoryPaths.reduce( (acc, specifierStoryPathList, specifierIndex) => { const paths = specifierStoryPathList.map((storyPath) => { const code = (0, import_node_fs.readFileSync)(storyPath, { encoding: "utf-8" }).toString(); const relativePath = ensureRelativePathHasDot(import_path.default.posix.relative(cwd, storyPath)); return { result: (0, import_csf_tools.loadCsf)(code, { fileName: storyPath, makeTitle: (userTitle) => makeTitle(relativePath, storiesSpecifiers[specifierIndex], userTitle) }).parse(), specifier: storiesSpecifiers[specifierIndex], fileName: relativePath }; }); return [...acc, ...paths]; }, new Array() ); const index = { v: 5, entries: {} }; for (const { result, specifier, fileName } of csfStories) { const { meta, stories } = result; if (stories && stories.length > 0) { for (const story of stories) { const id = (0, import_csf.toId)(meta.title, story.name); index.entries[id] = { type: "story", subtype: "story", id, name: story.name, title: meta.title, importPath: `${specifier.directory}/${import_path.default.posix.relative(specifier.directory, fileName)}`, tags: ["story"] }; } } else { console.log(`No stories found for ${fileName}`); } } try { const previewPath = (0, import_common2.getFilePathWithExtension)({ configPath }, "preview"); const previewSourceCode = (0, import_node_fs.readFileSync)(previewPath, { encoding: "utf-8" }).toString(); const storySort = (0, import_csf_tools.getStorySortParameter)(previewSourceCode); const sortableStories = Object.values(index.entries); (0, import_preview_api.sortStoriesV7)( sortableStories, storySort, sortableStories.map((entry) => entry.importPath) ); const sorted = sortableStories.reduce( (acc, item) => { acc[item.id] = item; return acc; }, {} ); return { v: 5, entries: sorted }; } catch { console.warn("Failed to sort stories, using unordered index"); return index; } } // src/metro/channelServer.ts function createChannelServer({ port = 7007, host = void 0, configPath }) { const httpServer = (0, import_node_http.createServer)(async (req, res) => { if (req.method === "OPTIONS") { res.writeHead(204); res.end(); return; } if (req.method === "GET" && req.url === "/index.json") { try { const index = await buildIndex({ configPath }); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify(index)); } catch (error) { console.error("Failed to build index:", error); res.writeHead(500, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Failed to build story index" })); } return; } if (req.method === "POST" && req.url === "/send-event") { let body = ""; req.on("data", (chunk) => { body += chunk.toString(); }); req.on("end", () => { try { const json = JSON.parse(body); wss.clients.forEach((wsClient) => wsClient.send(JSON.stringify(json))); res.writeHead(200, { "Content-Type": "application/json" }); res.end(JSON.stringify({ success: true })); } catch (error) { console.error("Failed to parse event:", error); res.writeHead(400, { "Content-Type": "application/json" }); res.end(JSON.stringify({ success: false, error: "Invalid JSON" })); } }); return; } res.writeHead(404, { "Content-Type": "application/json" }); res.end(JSON.stringify({ error: "Not found" })); }); const wss = new import_ws.WebSocketServer({ server: httpServer }); wss.on("error", () => { }); setInterval(function ping() { wss.clients.forEach(function each(client) { if (client.readyState === import_ws.WebSocket.OPEN) { client.send(JSON.stringify({ type: "ping", args: [] })); } }); }, 1e4); wss.on("connection", function connection(ws) { console.log("WebSocket connection established"); ws.on("error", console.error); ws.on("message", function message(data) { try { const json = JSON.parse(data.toString()); wss.clients.forEach((wsClient) => wsClient.send(JSON.stringify(json))); } catch (error) { console.error(error); } }); }); httpServer.on("error", (error) => { if (error.code === "EADDRINUSE") { console.warn( `[Storybook] Port ${port} is already in use. The channel server will not start. Another instance may already be running.` ); } else { console.error(`[Storybook] Channel server error:`, error); } }); httpServer.listen(port, host, () => { console.log(`WebSocket server listening on ${host ?? "localhost"}:${port}`); }); return wss; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { buildIndex, createChannelServer });