@gdansk/vite 0.2.7 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{ssr-CdtNxu-g.js → ssr-C8ohTGoc.js} +15 -6
- package/dist/assets/ssr-C8ohTGoc.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/runtime.js +2 -1
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
- package/types/types.d.ts +2 -0
- package/dist/assets/ssr-CdtNxu-g.js.map +0 -1
|
@@ -5,7 +5,7 @@ import { build, loadConfigFromFile, mergeConfig, normalizePath } from "vite";
|
|
|
5
5
|
function resolveOptions(options = {}, configRoot) {
|
|
6
6
|
const root = resolve(configRoot ?? options.root ?? process.cwd());
|
|
7
7
|
const widgetsRoot = options.widgetsRoot ?? "widgets";
|
|
8
|
-
const outDir = "
|
|
8
|
+
const outDir = options.assets ?? "assets";
|
|
9
9
|
const generatedDir = "dist-src";
|
|
10
10
|
const host = options.host ?? "127.0.0.1";
|
|
11
11
|
return {
|
|
@@ -423,7 +423,8 @@ async function processSSRRequest({ assetOrigin, manifest, render, requestBody, v
|
|
|
423
423
|
};
|
|
424
424
|
try {
|
|
425
425
|
const response = validateRenderResponse(await Promise.resolve(render(widget.key)));
|
|
426
|
-
const
|
|
426
|
+
const assetBaseUrl = payload.assetBaseUrl;
|
|
427
|
+
const head = viteServer ? [...collectCSSFromModuleGraph(viteServer, widget.entry), ...response.head] : [...createProductionCssHead(assetBaseUrl, assetOrigin, manifest, widget.key), ...response.head];
|
|
427
428
|
return {
|
|
428
429
|
payload: {
|
|
429
430
|
body: response.body,
|
|
@@ -455,11 +456,19 @@ function validateRenderResponse(result) {
|
|
|
455
456
|
head
|
|
456
457
|
};
|
|
457
458
|
}
|
|
458
|
-
function createProductionCssHead(assetOrigin, manifest, widgetKey) {
|
|
459
|
-
if (!assetOrigin || !manifest) return [];
|
|
459
|
+
function createProductionCssHead(assetBaseUrl, assetOrigin, manifest, widgetKey) {
|
|
460
|
+
if (!assetBaseUrl && !assetOrigin || !manifest) return [];
|
|
460
461
|
const widget = manifest.widgets[widgetKey];
|
|
461
462
|
if (!widget) throw new Error(`Widget "${widgetKey}" is not present in the production manifest`);
|
|
462
|
-
return widget.css.map((href) =>
|
|
463
|
+
return widget.css.map((href) => {
|
|
464
|
+
if (assetBaseUrl) return `<link rel="stylesheet" href="${assetBaseUrl}/${stripOutDirPrefix(manifest.outDir, href)}">`;
|
|
465
|
+
return `<link rel="stylesheet" href="${assetOrigin}/${href.replace(/^\/+/, "")}">`;
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
function stripOutDirPrefix(outDir, href) {
|
|
469
|
+
const normalized = href.replace(/^\/+/, "");
|
|
470
|
+
const prefix = `${outDir.replace(/^\/+|\/+$/g, "")}/`;
|
|
471
|
+
return normalized.startsWith(prefix) ? normalized.slice(prefix.length) : normalized;
|
|
463
472
|
}
|
|
464
473
|
function createErrorResponse(error, type) {
|
|
465
474
|
return { error: {
|
|
@@ -490,4 +499,4 @@ function writeJson(res, status, payload) {
|
|
|
490
499
|
//#endregion
|
|
491
500
|
export { resolveViteOrigin as a, readManifest as c, resolveOptions as d, processSSRRequest as i, loadUserViteConfig as l, importRenderFunction as n, buildWidgets as o, installDevSSRMiddleware as r, createBuildConfig as s, HEALTH_ENDPOINT as t, prepareProject as u };
|
|
492
501
|
|
|
493
|
-
//# sourceMappingURL=ssr-
|
|
502
|
+
//# sourceMappingURL=ssr-C8ohTGoc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ssr-C8ohTGoc.js","names":[],"sources":["../../src/context.ts","../../src/build.ts","../../src/css.ts","../../src/ssr.ts"],"sourcesContent":["import { access, glob as globIterate, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\n\nimport { loadConfigFromFile, mergeConfig } from \"vite\";\nimport type { InlineConfig, Plugin, PluginOption } from \"vite\";\n\nimport type {\n GdanskPreparedProject,\n GdanskPluginOptions,\n LoadedProjectConfig,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nexport function resolveOptions(options: GdanskPluginOptions = {}, configRoot?: string): ResolvedGdanskOptions {\n const root = resolve(configRoot ?? options.root ?? process.cwd());\n const widgetsRoot = options.widgetsRoot ?? \"widgets\";\n const outDir = options.assets ?? \"assets\";\n const generatedDir = \"dist-src\";\n const host = options.host ?? \"127.0.0.1\";\n const ssrEndpoint = \"/ssr\";\n\n return {\n generatedDir,\n generatedDirPath: resolve(root, generatedDir),\n host,\n outDir,\n outDirPath: resolve(root, outDir),\n root,\n ssrEndpoint,\n port: options.port ?? 13714,\n widgetsRoot,\n widgetsRootPath: resolve(root, widgetsRoot),\n };\n}\n\nasync function globPaths(pattern: string, options: { absolute?: boolean; cwd: string }): Promise<string[]> {\n const { cwd, absolute = false } = options;\n const matches: string[] = [];\n for await (const entry of globIterate(pattern, { cwd })) {\n matches.push(absolute ? resolve(cwd, entry) : entry);\n }\n return matches;\n}\n\nexport async function discoverWidgets(options: ResolvedGdanskOptions): Promise<WidgetDefinition[]> {\n const entries = await globPaths(\"**/widget.{tsx,jsx}\", {\n cwd: options.widgetsRootPath,\n });\n\n return entries.sort().map((entry) => {\n const widgetPath = toPosixPath(entry);\n const key = toPosixPath(dirname(widgetPath));\n const clientSource = toPosixPath(join(options.generatedDir, key, \"client.tsx\"));\n\n return {\n clientCss: toPosixPath(join(options.outDir, key, \"client.css\")),\n clientDevEntry: toPublicPath(clientSource),\n clientEntry: toPosixPath(join(options.outDir, key, \"client.js\")),\n clientSource: resolve(options.root, clientSource),\n entry: resolve(options.widgetsRootPath, entry),\n key,\n widgetPath,\n };\n });\n}\n\nexport async function loadUserViteConfig(\n options: ResolvedGdanskOptions,\n command: \"build\" | \"serve\",\n): Promise<LoadedProjectConfig> {\n const loaded = await loadConfigFromFile(\n {\n command,\n mode: command === \"build\" ? \"production\" : \"development\",\n },\n undefined,\n options.root,\n );\n const loadedConfig = loaded?.config ?? ({} satisfies InlineConfig);\n const { plugins: _, ...configWithoutPlugins } = loadedConfig;\n\n const plugins = (await normalizePlugins(loadedConfig.plugins)).filter((plugin) => plugin.name !== \"@gdansk/vite\");\n\n return mergeConfig(configWithoutPlugins, {\n plugins,\n root: options.root,\n } satisfies InlineConfig);\n}\n\nexport async function prepareProject(options: ResolvedGdanskOptions): Promise<GdanskPreparedProject> {\n const widgets = await discoverWidgets(options);\n await Promise.all(widgets.map((widget) => writeClientEntry(widget)));\n\n const ssrEntry = resolve(options.generatedDirPath, \"__gdansk_ssr__.ts\");\n await writeSSRRenderEntry(ssrEntry, widgets);\n\n return {\n ssrEntry,\n widgets,\n };\n}\n\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function toPosixPath(path: string): string {\n return path.split(sep).join(\"/\");\n}\n\nfunction createImportPath(from: string, to: string): string {\n const relativePath = toPosixPath(relative(dirname(from), to));\n return relativePath.startsWith(\".\") ? relativePath : `./${relativePath}`;\n}\n\nasync function normalizePlugins(plugins: PluginOption | PluginOption[] | undefined): Promise<Plugin[]> {\n if (!plugins) {\n return [];\n }\n\n const entries = Array.isArray(plugins) ? plugins : [plugins];\n const normalized: Plugin[] = [];\n\n for (const entry of entries) {\n const plugin = await entry;\n\n if (!plugin) {\n continue;\n }\n\n if (Array.isArray(plugin)) {\n normalized.push(...(await normalizePlugins(plugin)));\n continue;\n }\n\n normalized.push(plugin);\n }\n\n return normalized;\n}\n\nfunction toPublicPath(path: string): string {\n return `/${path.replace(/^\\/+/, \"\")}`;\n}\n\nasync function writeClientEntry(widget: WidgetDefinition): Promise<void> {\n const sourceImport = createImportPath(widget.clientSource, widget.entry);\n\n await mkdir(dirname(widget.clientSource), { recursive: true });\n await writeFile(\n widget.clientSource,\n [\n 'import React from \"react\";',\n 'import { createRoot, hydrateRoot } from \"react-dom/client\";',\n `import App from \"${sourceImport}\";`,\n \"\",\n 'const root = document.getElementById(\"root\");',\n \"\",\n \"if (!root) {\",\n \" throw new Error('Gdansk expected a #root element for widget hydration.');\",\n \"}\",\n \"\",\n \"const element = (\",\n \" <React.StrictMode>\",\n \" <App />\",\n \" </React.StrictMode>\",\n \");\",\n \"\",\n \"if (root.hasChildNodes()) {\",\n \" hydrateRoot(root, element);\",\n \"} else {\",\n \" createRoot(root).render(element);\",\n \"}\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n\nasync function writeSSRRenderEntry(path: string, widgets: WidgetDefinition[]): Promise<void> {\n const imports = widgets.map((widget, index) => {\n const specifier = createImportPath(path, widget.entry);\n return `import Widget${index} from \"${specifier}\";`;\n });\n\n const widgetEntries = widgets.map((widget, index) => ` ${JSON.stringify(widget.key)}: Widget${index},`);\n\n await mkdir(dirname(path), { recursive: true });\n await writeFile(\n path,\n [\n 'import { createElement } from \"react\";',\n 'import { renderToString } from \"react-dom/server\";',\n ...imports,\n \"\",\n \"const widgets = {\",\n ...widgetEntries,\n \"} as const;\",\n \"\",\n \"export default async function renderWidget(widgetKey: string) {\",\n \" const component = widgets[widgetKey as keyof typeof widgets];\",\n \"\",\n \" if (!component) {\",\n \" throw new Error(`Unknown widget: ${widgetKey}`);\",\n \" }\",\n \"\",\n \" return {\",\n \" body: renderToString(createElement(component)),\",\n \" head: [],\",\n \" };\",\n \"}\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n","import { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, relative, resolve } from \"node:path\";\n\nimport { build, mergeConfig } from \"vite\";\nimport type { UserConfig } from \"vite\";\n\nimport { pathExists, toPosixPath } from \"./context\";\nimport type {\n GdanskManifest,\n GdanskPreparedProject,\n LoadedProjectConfig,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nconst CLIENT_MANIFEST_FILE = \".gdansk-client-manifest.json\";\nconst SERVER_BUNDLE = \"ssr.js\";\n\ntype ViteManifestEntry = {\n css?: string[];\n file: string;\n};\n\nexport function createBuildConfig(options: ResolvedGdanskOptions, prepared: GdanskPreparedProject): UserConfig {\n return {\n appType: \"custom\",\n builder: {\n sharedPlugins: true,\n async buildApp(builder) {\n if (prepared.widgets.length > 0) {\n await builder.build(builder.environments.client);\n }\n\n await builder.build(builder.environments.ssr);\n await finalizeBuildOutputs(options, prepared.widgets);\n },\n },\n build: {\n copyPublicDir: false,\n emptyOutDir: true,\n outDir: options.outDir,\n sourcemap: true,\n },\n environments: {\n client: {\n build: createClientBuildOptions(options, prepared),\n },\n ssr: {\n consumer: \"server\",\n build: createSSRBuildOptions(options, prepared),\n },\n },\n };\n}\n\nexport async function buildWidgets(\n options: ResolvedGdanskOptions,\n prepared: GdanskPreparedProject,\n config: LoadedProjectConfig = {},\n): Promise<GdanskManifest> {\n await rm(options.outDirPath, { force: true, recursive: true });\n await mkdir(options.outDirPath, { recursive: true });\n\n if (prepared.widgets.length > 0) {\n await build(\n mergeConfig(config, {\n appType: \"custom\",\n build: createClientBuildOptions(options, prepared),\n configFile: false,\n root: options.root,\n }),\n );\n }\n\n await build(\n mergeConfig(config, {\n appType: \"custom\",\n build: createSSRBuildOptions(options, prepared),\n configFile: false,\n root: options.root,\n }),\n );\n\n return finalizeBuildOutputs(options, prepared.widgets);\n}\n\nexport async function readManifest(path: string): Promise<GdanskManifest> {\n return JSON.parse(await readFile(path, \"utf8\")) as GdanskManifest;\n}\n\nfunction createClientBuildOptions(\n options: ResolvedGdanskOptions,\n prepared: GdanskPreparedProject,\n): UserConfig[\"build\"] {\n const inputs =\n prepared.widgets.length > 0\n ? Object.fromEntries(prepared.widgets.map((widget) => [widget.key, widget.clientSource]))\n : { __gdansk_empty__: prepared.ssrEntry };\n\n return {\n copyPublicDir: false,\n cssCodeSplit: true,\n emptyOutDir: true,\n manifest: CLIENT_MANIFEST_FILE,\n outDir: options.outDir,\n rollupOptions: {\n input: inputs,\n output: {\n assetFileNames: (assetInfo: { names?: string[]; originalFileNames?: string[] }) =>\n resolveClientAssetPath(options, prepared.widgets, assetInfo),\n chunkFileNames: \"chunks/[name]-[hash].js\",\n entryFileNames: ({ name }) => `${name}/client.js`,\n },\n },\n sourcemap: true,\n };\n}\n\nfunction createSSRBuildOptions(options: ResolvedGdanskOptions, prepared: GdanskPreparedProject): UserConfig[\"build\"] {\n return {\n copyPublicDir: false,\n emptyOutDir: false,\n outDir: options.outDir,\n rollupOptions: {\n input: prepared.ssrEntry,\n output: {\n chunkFileNames: \"chunks/[name]-[hash].js\",\n entryFileNames: SERVER_BUNDLE,\n },\n },\n sourcemap: true,\n ssr: prepared.ssrEntry,\n };\n}\n\nasync function finalizeBuildOutputs(\n options: ResolvedGdanskOptions,\n widgets: WidgetDefinition[],\n): Promise<GdanskManifest> {\n const clientManifest = await readClientManifest(resolve(options.outDirPath, CLIENT_MANIFEST_FILE));\n\n const manifest: GdanskManifest = {\n outDir: options.outDir,\n root: options.root,\n server: toPosixPath(`${options.outDir}/${SERVER_BUNDLE}`),\n widgets: Object.fromEntries(\n await Promise.all(\n widgets.map(async (widget) => {\n const manifestEntry = getClientManifestEntry(options, widget, clientManifest);\n const fallbackCss = (await pathExists(resolve(options.root, widget.clientCss))) ? [widget.clientCss] : [];\n\n return [\n widget.key,\n {\n client: manifestEntry ? toBuildPath(options, manifestEntry.file) : widget.clientEntry,\n css: manifestEntry?.css?.map((href) => toBuildPath(options, href)) ?? fallbackCss,\n entry: widget.widgetPath,\n },\n ];\n }),\n ),\n ),\n };\n\n await rm(resolve(options.outDirPath, CLIENT_MANIFEST_FILE), { force: true });\n await writeJson(resolve(options.outDirPath, \"manifest.json\"), manifest);\n await writeProductionServer(options);\n\n return manifest;\n}\n\nfunction getClientManifestEntry(\n options: ResolvedGdanskOptions,\n widget: WidgetDefinition,\n manifest: Record<string, ViteManifestEntry>,\n): ViteManifestEntry | undefined {\n const key = toPosixPath(relative(options.root, widget.clientSource));\n return manifest[key];\n}\n\nasync function readClientManifest(path: string): Promise<Record<string, ViteManifestEntry>> {\n if (!(await pathExists(path))) {\n return {};\n }\n\n return JSON.parse(await readFile(path, \"utf8\")) as Record<string, ViteManifestEntry>;\n}\n\nfunction resolveClientAssetPath(\n options: ResolvedGdanskOptions,\n widgets: WidgetDefinition[],\n assetInfo: { names?: string[]; originalFileNames?: string[] },\n): string {\n const fileName = assetInfo.names?.[0] ?? assetInfo.originalFileNames?.[0] ?? \"\";\n\n if (!fileName.endsWith(\".css\")) {\n return \"assets/[name]-[hash][extname]\";\n }\n\n const originalFileName = assetInfo.originalFileNames?.[0];\n const widget = originalFileName ? findWidgetForAsset(options, widgets, originalFileName) : undefined;\n\n if (!widget) {\n return \"assets/[name]-[hash][extname]\";\n }\n\n return toOutputPath(options, widget.clientCss);\n}\n\nfunction findWidgetForAsset(\n options: ResolvedGdanskOptions,\n widgets: WidgetDefinition[],\n originalFileName: string,\n): WidgetDefinition | undefined {\n const normalized = toPosixPath(originalFileName);\n\n return widgets.find((widget) => {\n const relativeClientSource = toPosixPath(relative(options.root, widget.clientSource));\n return normalized === widget.clientSource || normalized === relativeClientSource;\n });\n}\n\nasync function writeJson(path: string, value: unknown): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction toOutputPath(options: ResolvedGdanskOptions, path: string): string {\n const prefix = `${options.outDir}/`;\n\n if (path.startsWith(prefix)) {\n return path.slice(prefix.length);\n }\n\n return path;\n}\n\nfunction toBuildPath(options: ResolvedGdanskOptions, path: string): string {\n return path.startsWith(`${options.outDir}/`) ? path : `${options.outDir}/${path.replace(/^\\/+/, \"\")}`;\n}\n\nasync function writeProductionServer(options: ResolvedGdanskOptions): Promise<void> {\n const path = resolve(options.outDirPath, \"server.js\");\n const runtimeModuleUrl = new URL(\"../runtime.js\", import.meta.url).href;\n const runtimeOptions = {\n host: options.host,\n port: options.port,\n widgetsRoot: options.widgetsRoot,\n };\n\n await writeFile(\n path,\n [\n 'import { dirname, resolve } from \"node:path\";',\n 'import { fileURLToPath } from \"node:url\";',\n `import { createGdanskRuntime } from \"${runtimeModuleUrl}\";`,\n \"\",\n \"const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');\",\n `const runtime = await createGdanskRuntime({ ...${JSON.stringify(runtimeOptions)}, root });`,\n \"await runtime.startProductionServer();\",\n \"await new Promise(() => {});\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n","import type { EnvironmentModuleNode, ViteDevServer } from \"vite\";\nimport { normalizePath } from \"vite\";\n\nexport function collectCSSFromModuleGraph(server: ViteDevServer, entry: string): string[] {\n const entryModule = resolveEntryModule(server, entry);\n\n if (!entryModule) {\n return [];\n }\n\n const cssModules = collectCSSModules(entryModule);\n\n if (cssModules.length === 0) {\n return [];\n }\n\n const origin = resolveViteOrigin(server);\n const base = server.config.base === \"/\" ? \"\" : server.config.base.replace(/\\/$/, \"\");\n\n return cssModules.map(({ id, url }) => {\n const devId = id ? ` data-vite-dev-id=\"${id}\"` : \"\";\n return `<link rel=\"stylesheet\" href=\"${origin}${base}${url}\"${devId}>`;\n });\n}\n\nexport function resolveViteOrigin(server: ViteDevServer): string {\n const origin = server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0];\n\n if (origin) {\n return new URL(origin).origin;\n }\n\n const protocol = server.config.server.https ? \"https\" : \"http\";\n return `${protocol}://${server.config.server.host ?? \"127.0.0.1\"}:${server.config.server.port ?? 5173}`;\n}\n\nfunction collectCSSModules(entryModule: EnvironmentModuleNode): Array<{ id: string | null; url: string }> {\n const cssModules: Array<{ id: string | null; url: string }> = [];\n const visited = new Set<EnvironmentModuleNode>();\n\n const walk = (mod: EnvironmentModuleNode): void => {\n if (visited.has(mod)) {\n return;\n }\n\n visited.add(mod);\n\n if (isCssRequest(mod.url)) {\n cssModules.push({ id: mod.id, url: mod.url });\n return;\n }\n\n for (const imported of mod.importedModules) {\n walk(imported);\n }\n };\n\n walk(entryModule);\n\n return cssModules;\n}\n\nfunction isCssRequest(url: string): boolean {\n return /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/.test(url);\n}\n\nfunction resolveEntryModule(server: ViteDevServer, entry: string): EnvironmentModuleNode | undefined {\n const moduleGraph = server.environments.ssr.moduleGraph;\n const normalized = normalizePath(entry);\n\n return moduleGraph.getModuleById(normalized) ?? moduleGraph.getModuleById(entry);\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { ViteDevServer } from \"vite\";\n\nimport { collectCSSFromModuleGraph } from \"./css\";\nimport type {\n GdanskManifest,\n GdanskRenderFunction,\n GdanskRenderRequest,\n GdanskRenderResponse,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nexport const HEALTH_ENDPOINT = \"/health\";\n\ntype GdanskErrorResponse = {\n error: {\n message: string;\n type: \"invalid_json\" | \"invalid_request\" | \"render_error\" | \"unknown_widget\";\n };\n};\n\ntype GdanskResponsePayload = GdanskErrorResponse | GdanskRenderResponse;\n\ntype ProcessSSRRequestOptions = {\n assetOrigin?: string;\n manifest?: GdanskManifest;\n render: GdanskRenderFunction;\n requestBody: string;\n viteServer?: ViteDevServer;\n widgets: WidgetDefinition[];\n};\n\ntype ProcessSSRRequestResult = {\n payload: GdanskResponsePayload;\n status: 200 | 400 | 404 | 500;\n};\n\ntype InstallDevSSRMiddlewareOptions = {\n options: ResolvedGdanskOptions;\n server: ViteDevServer;\n ssrEntry: string;\n widgets: WidgetDefinition[];\n};\n\nexport function installDevSSRMiddleware({ options, server, ssrEntry, widgets }: InstallDevSSRMiddlewareOptions): void {\n server.middlewares.use(HEALTH_ENDPOINT, (req, res, next) => {\n if (req.method !== \"GET\") {\n next();\n return;\n }\n\n writeJson(res, 200, { status: \"OK\" });\n });\n\n server.middlewares.use(options.ssrEndpoint, async (req, res, next) => {\n if (req.method !== \"POST\") {\n next();\n return;\n }\n\n try {\n const requestBody = await readRequestBody(req);\n const render = await loadRenderFunction(server, ssrEntry);\n const result = await processSSRRequest({\n render,\n requestBody,\n viteServer: server,\n widgets,\n });\n\n writeJson(res, result.status, result.payload);\n } catch (error) {\n writeJson(res, 500, createErrorResponse(error, \"render_error\"));\n }\n });\n\n server.config.logger.info(`Gdansk SSR dev endpoint: ${options.ssrEndpoint}`);\n\n server.httpServer?.once(\"listening\", () => {\n server.config.logger.info(\"Warming up Gdansk SSR module graph...\");\n\n server\n .ssrLoadModule(ssrEntry)\n .then(() => server.config.logger.info(\"Gdansk SSR module graph warmed up\"))\n .catch((error) => {\n server.config.logger.warn(`Failed to warm up Gdansk SSR module graph: ${getErrorMessage(error)}`);\n });\n });\n}\n\nexport async function importRenderFunction(path: string): Promise<GdanskRenderFunction> {\n const module = (await import(path)) as { default?: unknown };\n return resolveRenderFunction(module.default, path);\n}\n\nexport async function processSSRRequest({\n assetOrigin,\n manifest,\n render,\n requestBody,\n viteServer,\n widgets,\n}: ProcessSSRRequestOptions): Promise<ProcessSSRRequestResult> {\n let payload: GdanskRenderRequest;\n\n try {\n payload = JSON.parse(requestBody) as GdanskRenderRequest;\n } catch (error) {\n return {\n payload: createErrorResponse(error, \"invalid_json\"),\n status: 400,\n };\n }\n\n const widgetKey = payload.widget ?? payload.component;\n\n if (!widgetKey) {\n return {\n payload: createErrorResponse('Request body must include \"widget\" or \"component\"', \"invalid_request\"),\n status: 400,\n };\n }\n\n const widget = widgets.find((candidate) => candidate.key === widgetKey);\n\n if (!widget) {\n return {\n payload: createErrorResponse(`Unknown widget: ${widgetKey}`, \"unknown_widget\"),\n status: 404,\n };\n }\n\n try {\n const rendered = await Promise.resolve(render(widget.key));\n const response = validateRenderResponse(rendered);\n const assetBaseUrl = payload.assetBaseUrl;\n const head = viteServer\n ? [...collectCSSFromModuleGraph(viteServer, widget.entry), ...response.head]\n : [...createProductionCssHead(assetBaseUrl, assetOrigin, manifest, widget.key), ...response.head];\n\n return {\n payload: {\n body: response.body,\n head,\n },\n status: 200,\n };\n } catch (error) {\n return {\n payload: createErrorResponse(error, \"render_error\"),\n status: 500,\n };\n }\n}\n\nasync function loadRenderFunction(server: ViteDevServer, entry: string): Promise<GdanskRenderFunction> {\n const module = (await server.ssrLoadModule(entry)) as { default?: unknown };\n return resolveRenderFunction(module.default, entry);\n}\n\nfunction resolveRenderFunction(candidate: unknown, entry: string): GdanskRenderFunction {\n if (typeof candidate !== \"function\") {\n throw new Error(`SSR entry \"${entry}\" must export a render function`);\n }\n\n return candidate as GdanskRenderFunction;\n}\n\nfunction validateRenderResponse(result: unknown): GdanskRenderResponse {\n if (!result || typeof result !== \"object\") {\n throw new Error(\"SSR render must return { head: string[], body: string }\");\n }\n\n const body = Reflect.get(result, \"body\");\n const head = Reflect.get(result, \"head\");\n\n if (typeof body !== \"string\" || !Array.isArray(head) || !head.every((value) => typeof value === \"string\")) {\n throw new Error(\"SSR render must return { head: string[], body: string }\");\n }\n\n return {\n body,\n head,\n };\n}\n\nfunction createProductionCssHead(\n assetBaseUrl: string | undefined,\n assetOrigin: string | undefined,\n manifest: GdanskManifest | undefined,\n widgetKey: string,\n): string[] {\n if ((!assetBaseUrl && !assetOrigin) || !manifest) {\n return [];\n }\n\n const widget = manifest.widgets[widgetKey];\n\n if (!widget) {\n throw new Error(`Widget \"${widgetKey}\" is not present in the production manifest`);\n }\n\n return widget.css.map((href) => {\n if (assetBaseUrl) {\n return `<link rel=\"stylesheet\" href=\"${assetBaseUrl}/${stripOutDirPrefix(manifest.outDir, href)}\">`;\n }\n\n return `<link rel=\"stylesheet\" href=\"${assetOrigin}/${href.replace(/^\\/+/, \"\")}\">`;\n });\n}\n\nfunction stripOutDirPrefix(outDir: string, href: string): string {\n const normalized = href.replace(/^\\/+/, \"\");\n const prefix = `${outDir.replace(/^\\/+|\\/+$/g, \"\")}/`;\n\n return normalized.startsWith(prefix) ? normalized.slice(prefix.length) : normalized;\n}\n\nfunction createErrorResponse(error: unknown, type: GdanskErrorResponse[\"error\"][\"type\"]): GdanskErrorResponse {\n return {\n error: {\n message: getErrorMessage(error),\n type,\n },\n };\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction readRequestBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = \"\";\n\n req.on(\"data\", (chunk) => {\n data += chunk;\n });\n req.on(\"end\", () => {\n resolve(data);\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction writeJson(res: ServerResponse, status: number, payload: unknown): void {\n res.statusCode = status;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify(payload));\n}\n"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveViteOrigin, d as resolveOptions, r as installDevSSRMiddleware, s as createBuildConfig, u as prepareProject } from "./assets/ssr-
|
|
1
|
+
import { a as resolveViteOrigin, d as resolveOptions, r as installDevSSRMiddleware, s as createBuildConfig, u as prepareProject } from "./assets/ssr-C8ohTGoc.js";
|
|
2
2
|
//#region src/plugin.ts
|
|
3
3
|
function gdansk(options = {}) {
|
|
4
4
|
let prepared;
|
package/dist/runtime.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as resolveViteOrigin, c as readManifest, d as resolveOptions, i as processSSRRequest, l as loadUserViteConfig, n as importRenderFunction, o as buildWidgets, r as installDevSSRMiddleware, t as HEALTH_ENDPOINT, u as prepareProject } from "./assets/ssr-
|
|
1
|
+
import { a as resolveViteOrigin, c as readManifest, d as resolveOptions, i as processSSRRequest, l as loadUserViteConfig, n as importRenderFunction, o as buildWidgets, r as installDevSSRMiddleware, t as HEALTH_ENDPOINT, u as prepareProject } from "./assets/ssr-C8ohTGoc.js";
|
|
2
2
|
import { stat } from "node:fs/promises";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { createServer, mergeConfig } from "vite";
|
|
@@ -24,6 +24,7 @@ async function startGdanskServer(options) {
|
|
|
24
24
|
});
|
|
25
25
|
app.use(`${outDirPrefix}/*`, serveStatic({
|
|
26
26
|
onFound: (_, c) => {
|
|
27
|
+
c.header("Access-Control-Allow-Origin", "*");
|
|
27
28
|
c.header("Cache-Control", "public, max-age=31536000, immutable");
|
|
28
29
|
},
|
|
29
30
|
root: options.options.root
|
package/dist/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","names":["#manifest","#server","#viteServer","#prepared"],"sources":["../src/server.ts","../src/runtime.ts"],"sourcesContent":["import { serve } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { Hono } from \"hono\";\n\nimport { HEALTH_ENDPOINT, processSSRRequest } from \"./ssr\";\nimport type { GdanskServerHandle, GdanskServerOptions } from \"./types\";\n\nexport async function startGdanskServer(options: GdanskServerOptions): Promise<GdanskServerHandle> {\n const app = new Hono();\n const outDirPrefix = `/${options.options.outDir.replace(/^\\/+/, \"\")}`;\n\n app.get(HEALTH_ENDPOINT, (c) => c.json({ status: \"OK\" }));\n\n app.post(options.options.ssrEndpoint, async (c) => {\n const requestBody = await c.req.text();\n const result = await processSSRRequest({\n assetOrigin: new URL(c.req.url).origin,\n manifest: options.manifest,\n render: options.render,\n requestBody,\n widgets: options.widgets,\n });\n\n return c.json(result.payload, result.status);\n });\n\n app.use(\n `${outDirPrefix}/*`,\n serveStatic({\n onFound: (_, c) => {\n c.header(\"Cache-Control\", \"public, max-age=31536000, immutable\");\n },\n root: options.options.root,\n }),\n );\n\n let resolvedPort = options.options.port;\n\n const server = await new Promise<ReturnType<typeof serve>>((resolveServer) => {\n const instance = serve(\n {\n fetch: app.fetch,\n hostname: options.options.host,\n port: options.options.port,\n },\n (info) => {\n resolvedPort = info.port;\n resolveServer(instance);\n },\n );\n });\n\n const origin = `http://${options.options.host}:${resolvedPort}`;\n\n return {\n close: () =>\n new Promise<void>((resolveClose, rejectClose) => {\n server.close((error) => {\n if (error) {\n rejectClose(error);\n return;\n }\n\n resolveClose();\n });\n }),\n origin,\n port: resolvedPort,\n };\n}\n","import { stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { createServer, mergeConfig } from \"vite\";\n\nimport { buildWidgets, readManifest } from \"./build\";\nimport { loadUserViteConfig, prepareProject, resolveOptions } from \"./context\";\nimport { resolveViteOrigin } from \"./css\";\nimport { startGdanskServer } from \"./server\";\nimport { installDevSSRMiddleware, importRenderFunction } from \"./ssr\";\nimport type {\n GdanskManifest,\n GdanskPluginOptions,\n GdanskPreparedProject,\n GdanskRuntime,\n GdanskRuntimeMetadata,\n GdanskServerHandle,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nexport async function createGdanskRuntime(options: GdanskPluginOptions = {}): Promise<GdanskRuntime> {\n const resolved = resolveOptions(options);\n const runtime = new GdanskRuntimeImpl(resolved);\n await runtime.refreshWidgets();\n return runtime;\n}\n\nclass GdanskRuntimeImpl implements GdanskRuntime {\n readonly manifestPath: string;\n readonly options: ResolvedGdanskOptions;\n widgets: WidgetDefinition[] = [];\n\n #manifest?: GdanskManifest;\n #prepared?: GdanskPreparedProject;\n #server?: GdanskServerHandle;\n #viteServer?: Awaited<ReturnType<typeof createServer>>;\n\n constructor(options: ResolvedGdanskOptions) {\n this.manifestPath = `${options.outDirPath}/manifest.json`;\n this.options = options;\n }\n\n async build(): Promise<GdanskManifest> {\n const prepared = await this.prepare();\n const config = await loadUserViteConfig(this.options, \"build\");\n\n this.#manifest = await buildWidgets(this.options, prepared, config);\n\n return this.#manifest;\n }\n\n async close(): Promise<void> {\n await this.#server?.close();\n this.#server = undefined;\n\n await this.#viteServer?.close();\n this.#viteServer = undefined;\n }\n\n async refreshWidgets(): Promise<void> {\n const prepared = await this.prepare();\n this.widgets = prepared.widgets;\n }\n\n async startDev(): Promise<GdanskRuntimeMetadata> {\n await this.close();\n const prepared = await this.prepare();\n const config = await loadUserViteConfig(this.options, \"serve\");\n\n this.#viteServer = await createServer(\n mergeConfig(config, {\n appType: \"custom\",\n configFile: false,\n root: this.options.root,\n server: {\n host: this.options.host,\n port: this.options.port,\n strictPort: true,\n },\n }),\n );\n\n installDevSSRMiddleware({\n options: this.options,\n server: this.#viteServer,\n ssrEntry: prepared.ssrEntry,\n widgets: prepared.widgets,\n });\n\n await this.#viteServer.listen();\n\n const origin = resolveViteOrigin(this.#viteServer);\n\n return {\n assetOrigin: origin,\n mode: \"development\",\n ssrEndpoint: this.options.ssrEndpoint,\n ssrOrigin: origin,\n viteOrigin: origin,\n widgets: Object.fromEntries(\n prepared.widgets.map((widget) => [widget.key, { clientPath: widget.clientDevEntry }]),\n ),\n };\n }\n\n async startProductionServer(): Promise<GdanskRuntimeMetadata> {\n await this.close();\n const prepared = await this.prepare();\n\n this.#manifest = this.#manifest ?? (await this.loadOrBuildManifest());\n this.#server = await startGdanskServer({\n manifest: this.#manifest,\n options: this.options,\n render: await loadServerRenderFunction(this.options, this.#manifest.server),\n widgets: prepared.widgets,\n });\n\n return {\n assetOrigin: this.#server.origin,\n mode: \"production\",\n ssrEndpoint: this.options.ssrEndpoint,\n ssrOrigin: this.#server.origin,\n viteOrigin: null,\n widgets: Object.fromEntries(\n Object.entries(this.#manifest.widgets).map(([key, widget]) => [key, { clientPath: `/${widget.client}` }]),\n ),\n };\n }\n\n async loadOrBuildManifest(): Promise<GdanskManifest> {\n try {\n return await readManifest(this.manifestPath);\n } catch {\n return this.build();\n }\n }\n\n async prepare(): Promise<GdanskPreparedProject> {\n this.#prepared = await prepareProject(this.options);\n this.widgets = this.#prepared.widgets;\n return this.#prepared;\n }\n}\n\nasync function loadServerRenderFunction(options: ResolvedGdanskOptions, serverEntry: string) {\n const path = resolveServerPath(options, serverEntry);\n const modified = await stat(path);\n return importRenderFunction(`${pathToFileURL(path).href}?t=${modified.mtimeMs}`);\n}\n\nfunction resolveServerPath(options: ResolvedGdanskOptions, serverEntry: string): string {\n return resolve(options.root, serverEntry);\n}\n"],"mappings":";;;;;;;;;AAOA,eAAsB,kBAAkB,SAA2D;CACjG,MAAM,MAAM,IAAI,MAAM;CACtB,MAAM,eAAe,IAAI,QAAQ,QAAQ,OAAO,QAAQ,QAAQ,GAAG;AAEnE,KAAI,IAAI,kBAAkB,MAAM,EAAE,KAAK,EAAE,QAAQ,MAAM,CAAC,CAAC;AAEzD,KAAI,KAAK,QAAQ,QAAQ,aAAa,OAAO,MAAM;EACjD,MAAM,cAAc,MAAM,EAAE,IAAI,MAAM;EACtC,MAAM,SAAS,MAAM,kBAAkB;GACrC,aAAa,IAAI,IAAI,EAAE,IAAI,IAAI,CAAC;GAChC,UAAU,QAAQ;GAClB,QAAQ,QAAQ;GAChB;GACA,SAAS,QAAQ;GAClB,CAAC;AAEF,SAAO,EAAE,KAAK,OAAO,SAAS,OAAO,OAAO;GAC5C;AAEF,KAAI,IACF,GAAG,aAAa,KAChB,YAAY;EACV,UAAU,GAAG,MAAM;AACjB,KAAE,OAAO,iBAAiB,sCAAsC;;EAElE,MAAM,QAAQ,QAAQ;EACvB,CAAC,CACH;CAED,IAAI,eAAe,QAAQ,QAAQ;CAEnC,MAAM,SAAS,MAAM,IAAI,SAAmC,kBAAkB;EAC5E,MAAM,WAAW,MACf;GACE,OAAO,IAAI;GACX,UAAU,QAAQ,QAAQ;GAC1B,MAAM,QAAQ,QAAQ;GACvB,GACA,SAAS;AACR,kBAAe,KAAK;AACpB,iBAAc,SAAS;IAE1B;GACD;AAIF,QAAO;EACL,aACE,IAAI,SAAe,cAAc,gBAAgB;AAC/C,UAAO,OAAO,UAAU;AACtB,QAAI,OAAO;AACT,iBAAY,MAAM;AAClB;;AAGF,kBAAc;KACd;IACF;EACJ,QAda,UAAU,QAAQ,QAAQ,KAAK,GAAG;EAe/C,MAAM;EACP;;;;
|
|
1
|
+
{"version":3,"file":"runtime.js","names":["#manifest","#server","#viteServer","#prepared"],"sources":["../src/server.ts","../src/runtime.ts"],"sourcesContent":["import { serve } from \"@hono/node-server\";\nimport { serveStatic } from \"@hono/node-server/serve-static\";\nimport { Hono } from \"hono\";\n\nimport { HEALTH_ENDPOINT, processSSRRequest } from \"./ssr\";\nimport type { GdanskServerHandle, GdanskServerOptions } from \"./types\";\n\nexport async function startGdanskServer(options: GdanskServerOptions): Promise<GdanskServerHandle> {\n const app = new Hono();\n const outDirPrefix = `/${options.options.outDir.replace(/^\\/+/, \"\")}`;\n\n app.get(HEALTH_ENDPOINT, (c) => c.json({ status: \"OK\" }));\n\n app.post(options.options.ssrEndpoint, async (c) => {\n const requestBody = await c.req.text();\n const result = await processSSRRequest({\n assetOrigin: new URL(c.req.url).origin,\n manifest: options.manifest,\n render: options.render,\n requestBody,\n widgets: options.widgets,\n });\n\n return c.json(result.payload, result.status);\n });\n\n app.use(\n `${outDirPrefix}/*`,\n serveStatic({\n onFound: (_, c) => {\n c.header(\"Access-Control-Allow-Origin\", \"*\");\n c.header(\"Cache-Control\", \"public, max-age=31536000, immutable\");\n },\n root: options.options.root,\n }),\n );\n\n let resolvedPort = options.options.port;\n\n const server = await new Promise<ReturnType<typeof serve>>((resolveServer) => {\n const instance = serve(\n {\n fetch: app.fetch,\n hostname: options.options.host,\n port: options.options.port,\n },\n (info) => {\n resolvedPort = info.port;\n resolveServer(instance);\n },\n );\n });\n\n const origin = `http://${options.options.host}:${resolvedPort}`;\n\n return {\n close: () =>\n new Promise<void>((resolveClose, rejectClose) => {\n server.close((error) => {\n if (error) {\n rejectClose(error);\n return;\n }\n\n resolveClose();\n });\n }),\n origin,\n port: resolvedPort,\n };\n}\n","import { stat } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport { createServer, mergeConfig } from \"vite\";\n\nimport { buildWidgets, readManifest } from \"./build\";\nimport { loadUserViteConfig, prepareProject, resolveOptions } from \"./context\";\nimport { resolveViteOrigin } from \"./css\";\nimport { startGdanskServer } from \"./server\";\nimport { installDevSSRMiddleware, importRenderFunction } from \"./ssr\";\nimport type {\n GdanskManifest,\n GdanskPluginOptions,\n GdanskPreparedProject,\n GdanskRuntime,\n GdanskRuntimeMetadata,\n GdanskServerHandle,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nexport async function createGdanskRuntime(options: GdanskPluginOptions = {}): Promise<GdanskRuntime> {\n const resolved = resolveOptions(options);\n const runtime = new GdanskRuntimeImpl(resolved);\n await runtime.refreshWidgets();\n return runtime;\n}\n\nclass GdanskRuntimeImpl implements GdanskRuntime {\n readonly manifestPath: string;\n readonly options: ResolvedGdanskOptions;\n widgets: WidgetDefinition[] = [];\n\n #manifest?: GdanskManifest;\n #prepared?: GdanskPreparedProject;\n #server?: GdanskServerHandle;\n #viteServer?: Awaited<ReturnType<typeof createServer>>;\n\n constructor(options: ResolvedGdanskOptions) {\n this.manifestPath = `${options.outDirPath}/manifest.json`;\n this.options = options;\n }\n\n async build(): Promise<GdanskManifest> {\n const prepared = await this.prepare();\n const config = await loadUserViteConfig(this.options, \"build\");\n\n this.#manifest = await buildWidgets(this.options, prepared, config);\n\n return this.#manifest;\n }\n\n async close(): Promise<void> {\n await this.#server?.close();\n this.#server = undefined;\n\n await this.#viteServer?.close();\n this.#viteServer = undefined;\n }\n\n async refreshWidgets(): Promise<void> {\n const prepared = await this.prepare();\n this.widgets = prepared.widgets;\n }\n\n async startDev(): Promise<GdanskRuntimeMetadata> {\n await this.close();\n const prepared = await this.prepare();\n const config = await loadUserViteConfig(this.options, \"serve\");\n\n this.#viteServer = await createServer(\n mergeConfig(config, {\n appType: \"custom\",\n configFile: false,\n root: this.options.root,\n server: {\n host: this.options.host,\n port: this.options.port,\n strictPort: true,\n },\n }),\n );\n\n installDevSSRMiddleware({\n options: this.options,\n server: this.#viteServer,\n ssrEntry: prepared.ssrEntry,\n widgets: prepared.widgets,\n });\n\n await this.#viteServer.listen();\n\n const origin = resolveViteOrigin(this.#viteServer);\n\n return {\n assetOrigin: origin,\n mode: \"development\",\n ssrEndpoint: this.options.ssrEndpoint,\n ssrOrigin: origin,\n viteOrigin: origin,\n widgets: Object.fromEntries(\n prepared.widgets.map((widget) => [widget.key, { clientPath: widget.clientDevEntry }]),\n ),\n };\n }\n\n async startProductionServer(): Promise<GdanskRuntimeMetadata> {\n await this.close();\n const prepared = await this.prepare();\n\n this.#manifest = this.#manifest ?? (await this.loadOrBuildManifest());\n this.#server = await startGdanskServer({\n manifest: this.#manifest,\n options: this.options,\n render: await loadServerRenderFunction(this.options, this.#manifest.server),\n widgets: prepared.widgets,\n });\n\n return {\n assetOrigin: this.#server.origin,\n mode: \"production\",\n ssrEndpoint: this.options.ssrEndpoint,\n ssrOrigin: this.#server.origin,\n viteOrigin: null,\n widgets: Object.fromEntries(\n Object.entries(this.#manifest.widgets).map(([key, widget]) => [key, { clientPath: `/${widget.client}` }]),\n ),\n };\n }\n\n async loadOrBuildManifest(): Promise<GdanskManifest> {\n try {\n return await readManifest(this.manifestPath);\n } catch {\n return this.build();\n }\n }\n\n async prepare(): Promise<GdanskPreparedProject> {\n this.#prepared = await prepareProject(this.options);\n this.widgets = this.#prepared.widgets;\n return this.#prepared;\n }\n}\n\nasync function loadServerRenderFunction(options: ResolvedGdanskOptions, serverEntry: string) {\n const path = resolveServerPath(options, serverEntry);\n const modified = await stat(path);\n return importRenderFunction(`${pathToFileURL(path).href}?t=${modified.mtimeMs}`);\n}\n\nfunction resolveServerPath(options: ResolvedGdanskOptions, serverEntry: string): string {\n return resolve(options.root, serverEntry);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/types/types.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { InlineConfig, UserConfig } from "vite";
|
|
2
2
|
export interface GdanskPluginOptions {
|
|
3
|
+
assets?: string;
|
|
3
4
|
root?: string;
|
|
4
5
|
widgetsRoot?: string;
|
|
5
6
|
host?: string;
|
|
@@ -49,6 +50,7 @@ export interface GdanskRuntimeWidget {
|
|
|
49
50
|
clientPath: string;
|
|
50
51
|
}
|
|
51
52
|
export interface GdanskRenderRequest {
|
|
53
|
+
assetBaseUrl?: string;
|
|
52
54
|
component?: string;
|
|
53
55
|
widget?: string;
|
|
54
56
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-CdtNxu-g.js","names":[],"sources":["../../src/context.ts","../../src/build.ts","../../src/css.ts","../../src/ssr.ts"],"sourcesContent":["import { access, glob as globIterate, mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname, join, relative, resolve, sep } from \"node:path\";\n\nimport { loadConfigFromFile, mergeConfig } from \"vite\";\nimport type { InlineConfig, Plugin, PluginOption } from \"vite\";\n\nimport type {\n GdanskPreparedProject,\n GdanskPluginOptions,\n LoadedProjectConfig,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nexport function resolveOptions(options: GdanskPluginOptions = {}, configRoot?: string): ResolvedGdanskOptions {\n const root = resolve(configRoot ?? options.root ?? process.cwd());\n const widgetsRoot = options.widgetsRoot ?? \"widgets\";\n const outDir = \"dist\";\n const generatedDir = \"dist-src\";\n const host = options.host ?? \"127.0.0.1\";\n const ssrEndpoint = \"/ssr\";\n\n return {\n generatedDir,\n generatedDirPath: resolve(root, generatedDir),\n host,\n outDir,\n outDirPath: resolve(root, outDir),\n root,\n ssrEndpoint,\n port: options.port ?? 13714,\n widgetsRoot,\n widgetsRootPath: resolve(root, widgetsRoot),\n };\n}\n\nasync function globPaths(pattern: string, options: { absolute?: boolean; cwd: string }): Promise<string[]> {\n const { cwd, absolute = false } = options;\n const matches: string[] = [];\n for await (const entry of globIterate(pattern, { cwd })) {\n matches.push(absolute ? resolve(cwd, entry) : entry);\n }\n return matches;\n}\n\nexport async function discoverWidgets(options: ResolvedGdanskOptions): Promise<WidgetDefinition[]> {\n const entries = await globPaths(\"**/widget.{tsx,jsx}\", {\n cwd: options.widgetsRootPath,\n });\n\n return entries.sort().map((entry) => {\n const widgetPath = toPosixPath(entry);\n const key = toPosixPath(dirname(widgetPath));\n const clientSource = toPosixPath(join(options.generatedDir, key, \"client.tsx\"));\n\n return {\n clientCss: toPosixPath(join(options.outDir, key, \"client.css\")),\n clientDevEntry: toPublicPath(clientSource),\n clientEntry: toPosixPath(join(options.outDir, key, \"client.js\")),\n clientSource: resolve(options.root, clientSource),\n entry: resolve(options.widgetsRootPath, entry),\n key,\n widgetPath,\n };\n });\n}\n\nexport async function loadUserViteConfig(\n options: ResolvedGdanskOptions,\n command: \"build\" | \"serve\",\n): Promise<LoadedProjectConfig> {\n const loaded = await loadConfigFromFile(\n {\n command,\n mode: command === \"build\" ? \"production\" : \"development\",\n },\n undefined,\n options.root,\n );\n const loadedConfig = loaded?.config ?? ({} satisfies InlineConfig);\n const { plugins: _, ...configWithoutPlugins } = loadedConfig;\n\n const plugins = (await normalizePlugins(loadedConfig.plugins)).filter((plugin) => plugin.name !== \"@gdansk/vite\");\n\n return mergeConfig(configWithoutPlugins, {\n plugins,\n root: options.root,\n } satisfies InlineConfig);\n}\n\nexport async function prepareProject(options: ResolvedGdanskOptions): Promise<GdanskPreparedProject> {\n const widgets = await discoverWidgets(options);\n await Promise.all(widgets.map((widget) => writeClientEntry(widget)));\n\n const ssrEntry = resolve(options.generatedDirPath, \"__gdansk_ssr__.ts\");\n await writeSSRRenderEntry(ssrEntry, widgets);\n\n return {\n ssrEntry,\n widgets,\n };\n}\n\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function toPosixPath(path: string): string {\n return path.split(sep).join(\"/\");\n}\n\nfunction createImportPath(from: string, to: string): string {\n const relativePath = toPosixPath(relative(dirname(from), to));\n return relativePath.startsWith(\".\") ? relativePath : `./${relativePath}`;\n}\n\nasync function normalizePlugins(plugins: PluginOption | PluginOption[] | undefined): Promise<Plugin[]> {\n if (!plugins) {\n return [];\n }\n\n const entries = Array.isArray(plugins) ? plugins : [plugins];\n const normalized: Plugin[] = [];\n\n for (const entry of entries) {\n const plugin = await entry;\n\n if (!plugin) {\n continue;\n }\n\n if (Array.isArray(plugin)) {\n normalized.push(...(await normalizePlugins(plugin)));\n continue;\n }\n\n normalized.push(plugin);\n }\n\n return normalized;\n}\n\nfunction toPublicPath(path: string): string {\n return `/${path.replace(/^\\/+/, \"\")}`;\n}\n\nasync function writeClientEntry(widget: WidgetDefinition): Promise<void> {\n const sourceImport = createImportPath(widget.clientSource, widget.entry);\n\n await mkdir(dirname(widget.clientSource), { recursive: true });\n await writeFile(\n widget.clientSource,\n [\n 'import React from \"react\";',\n 'import { createRoot, hydrateRoot } from \"react-dom/client\";',\n `import App from \"${sourceImport}\";`,\n \"\",\n 'const root = document.getElementById(\"root\");',\n \"\",\n \"if (!root) {\",\n \" throw new Error('Gdansk expected a #root element for widget hydration.');\",\n \"}\",\n \"\",\n \"const element = (\",\n \" <React.StrictMode>\",\n \" <App />\",\n \" </React.StrictMode>\",\n \");\",\n \"\",\n \"if (root.hasChildNodes()) {\",\n \" hydrateRoot(root, element);\",\n \"} else {\",\n \" createRoot(root).render(element);\",\n \"}\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n\nasync function writeSSRRenderEntry(path: string, widgets: WidgetDefinition[]): Promise<void> {\n const imports = widgets.map((widget, index) => {\n const specifier = createImportPath(path, widget.entry);\n return `import Widget${index} from \"${specifier}\";`;\n });\n\n const widgetEntries = widgets.map((widget, index) => ` ${JSON.stringify(widget.key)}: Widget${index},`);\n\n await mkdir(dirname(path), { recursive: true });\n await writeFile(\n path,\n [\n 'import { createElement } from \"react\";',\n 'import { renderToString } from \"react-dom/server\";',\n ...imports,\n \"\",\n \"const widgets = {\",\n ...widgetEntries,\n \"} as const;\",\n \"\",\n \"export default async function renderWidget(widgetKey: string) {\",\n \" const component = widgets[widgetKey as keyof typeof widgets];\",\n \"\",\n \" if (!component) {\",\n \" throw new Error(`Unknown widget: ${widgetKey}`);\",\n \" }\",\n \"\",\n \" return {\",\n \" body: renderToString(createElement(component)),\",\n \" head: [],\",\n \" };\",\n \"}\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n","import { mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { dirname, relative, resolve } from \"node:path\";\n\nimport { build, mergeConfig } from \"vite\";\nimport type { UserConfig } from \"vite\";\n\nimport { pathExists, toPosixPath } from \"./context\";\nimport type {\n GdanskManifest,\n GdanskPreparedProject,\n LoadedProjectConfig,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nconst CLIENT_MANIFEST_FILE = \".gdansk-client-manifest.json\";\nconst SERVER_BUNDLE = \"ssr.js\";\n\ntype ViteManifestEntry = {\n css?: string[];\n file: string;\n};\n\nexport function createBuildConfig(options: ResolvedGdanskOptions, prepared: GdanskPreparedProject): UserConfig {\n return {\n appType: \"custom\",\n builder: {\n sharedPlugins: true,\n async buildApp(builder) {\n if (prepared.widgets.length > 0) {\n await builder.build(builder.environments.client);\n }\n\n await builder.build(builder.environments.ssr);\n await finalizeBuildOutputs(options, prepared.widgets);\n },\n },\n build: {\n copyPublicDir: false,\n emptyOutDir: true,\n outDir: options.outDir,\n sourcemap: true,\n },\n environments: {\n client: {\n build: createClientBuildOptions(options, prepared),\n },\n ssr: {\n consumer: \"server\",\n build: createSSRBuildOptions(options, prepared),\n },\n },\n };\n}\n\nexport async function buildWidgets(\n options: ResolvedGdanskOptions,\n prepared: GdanskPreparedProject,\n config: LoadedProjectConfig = {},\n): Promise<GdanskManifest> {\n await rm(options.outDirPath, { force: true, recursive: true });\n await mkdir(options.outDirPath, { recursive: true });\n\n if (prepared.widgets.length > 0) {\n await build(\n mergeConfig(config, {\n appType: \"custom\",\n build: createClientBuildOptions(options, prepared),\n configFile: false,\n root: options.root,\n }),\n );\n }\n\n await build(\n mergeConfig(config, {\n appType: \"custom\",\n build: createSSRBuildOptions(options, prepared),\n configFile: false,\n root: options.root,\n }),\n );\n\n return finalizeBuildOutputs(options, prepared.widgets);\n}\n\nexport async function readManifest(path: string): Promise<GdanskManifest> {\n return JSON.parse(await readFile(path, \"utf8\")) as GdanskManifest;\n}\n\nfunction createClientBuildOptions(\n options: ResolvedGdanskOptions,\n prepared: GdanskPreparedProject,\n): UserConfig[\"build\"] {\n const inputs =\n prepared.widgets.length > 0\n ? Object.fromEntries(prepared.widgets.map((widget) => [widget.key, widget.clientSource]))\n : { __gdansk_empty__: prepared.ssrEntry };\n\n return {\n copyPublicDir: false,\n cssCodeSplit: true,\n emptyOutDir: true,\n manifest: CLIENT_MANIFEST_FILE,\n outDir: options.outDir,\n rollupOptions: {\n input: inputs,\n output: {\n assetFileNames: (assetInfo: { names?: string[]; originalFileNames?: string[] }) =>\n resolveClientAssetPath(options, prepared.widgets, assetInfo),\n chunkFileNames: \"chunks/[name]-[hash].js\",\n entryFileNames: ({ name }) => `${name}/client.js`,\n },\n },\n sourcemap: true,\n };\n}\n\nfunction createSSRBuildOptions(options: ResolvedGdanskOptions, prepared: GdanskPreparedProject): UserConfig[\"build\"] {\n return {\n copyPublicDir: false,\n emptyOutDir: false,\n outDir: options.outDir,\n rollupOptions: {\n input: prepared.ssrEntry,\n output: {\n chunkFileNames: \"chunks/[name]-[hash].js\",\n entryFileNames: SERVER_BUNDLE,\n },\n },\n sourcemap: true,\n ssr: prepared.ssrEntry,\n };\n}\n\nasync function finalizeBuildOutputs(\n options: ResolvedGdanskOptions,\n widgets: WidgetDefinition[],\n): Promise<GdanskManifest> {\n const clientManifest = await readClientManifest(resolve(options.outDirPath, CLIENT_MANIFEST_FILE));\n\n const manifest: GdanskManifest = {\n outDir: options.outDir,\n root: options.root,\n server: toPosixPath(`${options.outDir}/${SERVER_BUNDLE}`),\n widgets: Object.fromEntries(\n await Promise.all(\n widgets.map(async (widget) => {\n const manifestEntry = getClientManifestEntry(options, widget, clientManifest);\n const fallbackCss = (await pathExists(resolve(options.root, widget.clientCss))) ? [widget.clientCss] : [];\n\n return [\n widget.key,\n {\n client: manifestEntry ? toBuildPath(options, manifestEntry.file) : widget.clientEntry,\n css: manifestEntry?.css?.map((href) => toBuildPath(options, href)) ?? fallbackCss,\n entry: widget.widgetPath,\n },\n ];\n }),\n ),\n ),\n };\n\n await rm(resolve(options.outDirPath, CLIENT_MANIFEST_FILE), { force: true });\n await writeJson(resolve(options.outDirPath, \"manifest.json\"), manifest);\n await writeProductionServer(options);\n\n return manifest;\n}\n\nfunction getClientManifestEntry(\n options: ResolvedGdanskOptions,\n widget: WidgetDefinition,\n manifest: Record<string, ViteManifestEntry>,\n): ViteManifestEntry | undefined {\n const key = toPosixPath(relative(options.root, widget.clientSource));\n return manifest[key];\n}\n\nasync function readClientManifest(path: string): Promise<Record<string, ViteManifestEntry>> {\n if (!(await pathExists(path))) {\n return {};\n }\n\n return JSON.parse(await readFile(path, \"utf8\")) as Record<string, ViteManifestEntry>;\n}\n\nfunction resolveClientAssetPath(\n options: ResolvedGdanskOptions,\n widgets: WidgetDefinition[],\n assetInfo: { names?: string[]; originalFileNames?: string[] },\n): string {\n const fileName = assetInfo.names?.[0] ?? assetInfo.originalFileNames?.[0] ?? \"\";\n\n if (!fileName.endsWith(\".css\")) {\n return \"assets/[name]-[hash][extname]\";\n }\n\n const originalFileName = assetInfo.originalFileNames?.[0];\n const widget = originalFileName ? findWidgetForAsset(options, widgets, originalFileName) : undefined;\n\n if (!widget) {\n return \"assets/[name]-[hash][extname]\";\n }\n\n return toOutputPath(options, widget.clientCss);\n}\n\nfunction findWidgetForAsset(\n options: ResolvedGdanskOptions,\n widgets: WidgetDefinition[],\n originalFileName: string,\n): WidgetDefinition | undefined {\n const normalized = toPosixPath(originalFileName);\n\n return widgets.find((widget) => {\n const relativeClientSource = toPosixPath(relative(options.root, widget.clientSource));\n return normalized === widget.clientSource || normalized === relativeClientSource;\n });\n}\n\nasync function writeJson(path: string, value: unknown): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, `${JSON.stringify(value, null, 2)}\\n`);\n}\n\nfunction toOutputPath(options: ResolvedGdanskOptions, path: string): string {\n const prefix = `${options.outDir}/`;\n\n if (path.startsWith(prefix)) {\n return path.slice(prefix.length);\n }\n\n return path;\n}\n\nfunction toBuildPath(options: ResolvedGdanskOptions, path: string): string {\n return path.startsWith(`${options.outDir}/`) ? path : `${options.outDir}/${path.replace(/^\\/+/, \"\")}`;\n}\n\nasync function writeProductionServer(options: ResolvedGdanskOptions): Promise<void> {\n const path = resolve(options.outDirPath, \"server.js\");\n const runtimeModuleUrl = new URL(\"../runtime.js\", import.meta.url).href;\n const runtimeOptions = {\n host: options.host,\n port: options.port,\n widgetsRoot: options.widgetsRoot,\n };\n\n await writeFile(\n path,\n [\n 'import { dirname, resolve } from \"node:path\";',\n 'import { fileURLToPath } from \"node:url\";',\n `import { createGdanskRuntime } from \"${runtimeModuleUrl}\";`,\n \"\",\n \"const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');\",\n `const runtime = await createGdanskRuntime({ ...${JSON.stringify(runtimeOptions)}, root });`,\n \"await runtime.startProductionServer();\",\n \"await new Promise(() => {});\",\n \"\",\n ].join(\"\\n\"),\n );\n}\n","import type { EnvironmentModuleNode, ViteDevServer } from \"vite\";\nimport { normalizePath } from \"vite\";\n\nexport function collectCSSFromModuleGraph(server: ViteDevServer, entry: string): string[] {\n const entryModule = resolveEntryModule(server, entry);\n\n if (!entryModule) {\n return [];\n }\n\n const cssModules = collectCSSModules(entryModule);\n\n if (cssModules.length === 0) {\n return [];\n }\n\n const origin = resolveViteOrigin(server);\n const base = server.config.base === \"/\" ? \"\" : server.config.base.replace(/\\/$/, \"\");\n\n return cssModules.map(({ id, url }) => {\n const devId = id ? ` data-vite-dev-id=\"${id}\"` : \"\";\n return `<link rel=\"stylesheet\" href=\"${origin}${base}${url}\"${devId}>`;\n });\n}\n\nexport function resolveViteOrigin(server: ViteDevServer): string {\n const origin = server.resolvedUrls?.local[0] ?? server.resolvedUrls?.network[0];\n\n if (origin) {\n return new URL(origin).origin;\n }\n\n const protocol = server.config.server.https ? \"https\" : \"http\";\n return `${protocol}://${server.config.server.host ?? \"127.0.0.1\"}:${server.config.server.port ?? 5173}`;\n}\n\nfunction collectCSSModules(entryModule: EnvironmentModuleNode): Array<{ id: string | null; url: string }> {\n const cssModules: Array<{ id: string | null; url: string }> = [];\n const visited = new Set<EnvironmentModuleNode>();\n\n const walk = (mod: EnvironmentModuleNode): void => {\n if (visited.has(mod)) {\n return;\n }\n\n visited.add(mod);\n\n if (isCssRequest(mod.url)) {\n cssModules.push({ id: mod.id, url: mod.url });\n return;\n }\n\n for (const imported of mod.importedModules) {\n walk(imported);\n }\n };\n\n walk(entryModule);\n\n return cssModules;\n}\n\nfunction isCssRequest(url: string): boolean {\n return /\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/.test(url);\n}\n\nfunction resolveEntryModule(server: ViteDevServer, entry: string): EnvironmentModuleNode | undefined {\n const moduleGraph = server.environments.ssr.moduleGraph;\n const normalized = normalizePath(entry);\n\n return moduleGraph.getModuleById(normalized) ?? moduleGraph.getModuleById(entry);\n}\n","import type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { ViteDevServer } from \"vite\";\n\nimport { collectCSSFromModuleGraph } from \"./css\";\nimport type {\n GdanskManifest,\n GdanskRenderFunction,\n GdanskRenderRequest,\n GdanskRenderResponse,\n ResolvedGdanskOptions,\n WidgetDefinition,\n} from \"./types\";\n\nexport const HEALTH_ENDPOINT = \"/health\";\n\ntype GdanskErrorResponse = {\n error: {\n message: string;\n type: \"invalid_json\" | \"invalid_request\" | \"render_error\" | \"unknown_widget\";\n };\n};\n\ntype GdanskResponsePayload = GdanskErrorResponse | GdanskRenderResponse;\n\ntype ProcessSSRRequestOptions = {\n assetOrigin?: string;\n manifest?: GdanskManifest;\n render: GdanskRenderFunction;\n requestBody: string;\n viteServer?: ViteDevServer;\n widgets: WidgetDefinition[];\n};\n\ntype ProcessSSRRequestResult = {\n payload: GdanskResponsePayload;\n status: 200 | 400 | 404 | 500;\n};\n\ntype InstallDevSSRMiddlewareOptions = {\n options: ResolvedGdanskOptions;\n server: ViteDevServer;\n ssrEntry: string;\n widgets: WidgetDefinition[];\n};\n\nexport function installDevSSRMiddleware({ options, server, ssrEntry, widgets }: InstallDevSSRMiddlewareOptions): void {\n server.middlewares.use(HEALTH_ENDPOINT, (req, res, next) => {\n if (req.method !== \"GET\") {\n next();\n return;\n }\n\n writeJson(res, 200, { status: \"OK\" });\n });\n\n server.middlewares.use(options.ssrEndpoint, async (req, res, next) => {\n if (req.method !== \"POST\") {\n next();\n return;\n }\n\n try {\n const requestBody = await readRequestBody(req);\n const render = await loadRenderFunction(server, ssrEntry);\n const result = await processSSRRequest({\n render,\n requestBody,\n viteServer: server,\n widgets,\n });\n\n writeJson(res, result.status, result.payload);\n } catch (error) {\n writeJson(res, 500, createErrorResponse(error, \"render_error\"));\n }\n });\n\n server.config.logger.info(`Gdansk SSR dev endpoint: ${options.ssrEndpoint}`);\n\n server.httpServer?.once(\"listening\", () => {\n server.config.logger.info(\"Warming up Gdansk SSR module graph...\");\n\n server\n .ssrLoadModule(ssrEntry)\n .then(() => server.config.logger.info(\"Gdansk SSR module graph warmed up\"))\n .catch((error) => {\n server.config.logger.warn(`Failed to warm up Gdansk SSR module graph: ${getErrorMessage(error)}`);\n });\n });\n}\n\nexport async function importRenderFunction(path: string): Promise<GdanskRenderFunction> {\n const module = (await import(path)) as { default?: unknown };\n return resolveRenderFunction(module.default, path);\n}\n\nexport async function processSSRRequest({\n assetOrigin,\n manifest,\n render,\n requestBody,\n viteServer,\n widgets,\n}: ProcessSSRRequestOptions): Promise<ProcessSSRRequestResult> {\n let payload: GdanskRenderRequest;\n\n try {\n payload = JSON.parse(requestBody) as GdanskRenderRequest;\n } catch (error) {\n return {\n payload: createErrorResponse(error, \"invalid_json\"),\n status: 400,\n };\n }\n\n const widgetKey = payload.widget ?? payload.component;\n\n if (!widgetKey) {\n return {\n payload: createErrorResponse('Request body must include \"widget\" or \"component\"', \"invalid_request\"),\n status: 400,\n };\n }\n\n const widget = widgets.find((candidate) => candidate.key === widgetKey);\n\n if (!widget) {\n return {\n payload: createErrorResponse(`Unknown widget: ${widgetKey}`, \"unknown_widget\"),\n status: 404,\n };\n }\n\n try {\n const rendered = await Promise.resolve(render(widget.key));\n const response = validateRenderResponse(rendered);\n const head = viteServer\n ? [...collectCSSFromModuleGraph(viteServer, widget.entry), ...response.head]\n : [...createProductionCssHead(assetOrigin, manifest, widget.key), ...response.head];\n\n return {\n payload: {\n body: response.body,\n head,\n },\n status: 200,\n };\n } catch (error) {\n return {\n payload: createErrorResponse(error, \"render_error\"),\n status: 500,\n };\n }\n}\n\nasync function loadRenderFunction(server: ViteDevServer, entry: string): Promise<GdanskRenderFunction> {\n const module = (await server.ssrLoadModule(entry)) as { default?: unknown };\n return resolveRenderFunction(module.default, entry);\n}\n\nfunction resolveRenderFunction(candidate: unknown, entry: string): GdanskRenderFunction {\n if (typeof candidate !== \"function\") {\n throw new Error(`SSR entry \"${entry}\" must export a render function`);\n }\n\n return candidate as GdanskRenderFunction;\n}\n\nfunction validateRenderResponse(result: unknown): GdanskRenderResponse {\n if (!result || typeof result !== \"object\") {\n throw new Error(\"SSR render must return { head: string[], body: string }\");\n }\n\n const body = Reflect.get(result, \"body\");\n const head = Reflect.get(result, \"head\");\n\n if (typeof body !== \"string\" || !Array.isArray(head) || !head.every((value) => typeof value === \"string\")) {\n throw new Error(\"SSR render must return { head: string[], body: string }\");\n }\n\n return {\n body,\n head,\n };\n}\n\nfunction createProductionCssHead(\n assetOrigin: string | undefined,\n manifest: GdanskManifest | undefined,\n widgetKey: string,\n): string[] {\n if (!assetOrigin || !manifest) {\n return [];\n }\n\n const widget = manifest.widgets[widgetKey];\n\n if (!widget) {\n throw new Error(`Widget \"${widgetKey}\" is not present in the production manifest`);\n }\n\n return widget.css.map((href) => `<link rel=\"stylesheet\" href=\"${assetOrigin}/${href.replace(/^\\/+/, \"\")}\">`);\n}\n\nfunction createErrorResponse(error: unknown, type: GdanskErrorResponse[\"error\"][\"type\"]): GdanskErrorResponse {\n return {\n error: {\n message: getErrorMessage(error),\n type,\n },\n };\n}\n\nfunction getErrorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction readRequestBody(req: IncomingMessage): Promise<string> {\n return new Promise((resolve, reject) => {\n let data = \"\";\n\n req.on(\"data\", (chunk) => {\n data += chunk;\n });\n req.on(\"end\", () => {\n resolve(data);\n });\n req.on(\"error\", reject);\n });\n}\n\nfunction writeJson(res: ServerResponse, status: number, payload: unknown): void {\n res.statusCode = status;\n res.setHeader(\"Content-Type\", \"application/json\");\n res.end(JSON.stringify(payload));\n}\n"],"mappings":"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"}
|