@qwik.dev/router 2.0.0-beta.39 → 2.0.0-beta.40

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.
Files changed (40) hide show
  1. package/lib/adapters/azure-swa/vite/index.mjs +45 -54
  2. package/lib/adapters/bun-server/vite/index.mjs +16 -22
  3. package/lib/adapters/cloud-run/vite/index.mjs +15 -19
  4. package/lib/adapters/cloudflare-pages/vite/index.mjs +46 -67
  5. package/lib/adapters/deno-server/vite/index.mjs +25 -39
  6. package/lib/adapters/netlify-edge/vite/index.mjs +50 -76
  7. package/lib/adapters/node-server/vite/index.mjs +16 -22
  8. package/lib/adapters/shared/vite/index.mjs +271 -360
  9. package/lib/adapters/ssg/vite/index.mjs +11 -15
  10. package/lib/adapters/vercel-edge/vite/index.mjs +74 -95
  11. package/lib/chunks/dev-preloaded-route-loader.mjs +2 -3
  12. package/lib/chunks/format.mjs +16 -23
  13. package/lib/chunks/fs.mjs +93 -106
  14. package/lib/chunks/head.qwik.mjs +1174 -1382
  15. package/lib/chunks/http-error.qwik.mjs +20 -28
  16. package/lib/chunks/pathname.mjs +50 -69
  17. package/lib/chunks/request-body-limit.mjs +25 -35
  18. package/lib/chunks/request-path.mjs +44 -55
  19. package/lib/chunks/routes.mjs +20 -41
  20. package/lib/chunks/server-error.mjs +15 -18
  21. package/lib/chunks/system.mjs +258 -326
  22. package/lib/chunks/url.mjs +56 -58
  23. package/lib/chunks/user-response.mjs +1616 -1804
  24. package/lib/chunks/worker-thread.mjs +254 -307
  25. package/lib/index.qwik.mjs +1637 -1918
  26. package/lib/middleware/aws-lambda/index.mjs +44 -52
  27. package/lib/middleware/azure-swa/index.mjs +85 -94
  28. package/lib/middleware/bun/index.mjs +118 -138
  29. package/lib/middleware/cloudflare-pages/index.mjs +83 -96
  30. package/lib/middleware/deno/index.mjs +104 -125
  31. package/lib/middleware/firebase/index.mjs +21 -25
  32. package/lib/middleware/netlify-edge/index.mjs +63 -71
  33. package/lib/middleware/node/index.mjs +297 -357
  34. package/lib/middleware/request-handler/index.mjs +110 -133
  35. package/lib/middleware/vercel-edge/index.mjs +82 -98
  36. package/lib/service-worker/index.mjs +12 -3
  37. package/lib/ssg/index.mjs +249 -289
  38. package/lib/vite/index.mjs +2344 -3030
  39. package/package.json +5 -5
  40. package/lib/chunks/use-functions.qwik.mjs +0 -23
package/lib/ssg/index.mjs CHANGED
@@ -1,297 +1,257 @@
1
- import { bold, green, dim, red, magenta } from 'kleur/colors';
2
- import { relative } from 'node:path';
3
- import { m as msToString } from '../chunks/format.mjs';
4
- import { e as ensureSlash, g as getPathnameForDynamicRoute } from '../chunks/pathname.mjs';
5
- import { c as createRouteTester } from '../chunks/routes.mjs';
6
-
1
+ import { n as getPathnameForDynamicRoute, t as ensureSlash } from "../chunks/pathname.mjs";
2
+ import { r as msToString } from "../chunks/format.mjs";
3
+ import { t as createRouteTester } from "../chunks/routes.mjs";
4
+ import { relative } from "node:path";
5
+ import { bold, dim, green, magenta, red } from "kleur/colors";
7
6
  function validateOptions(opts) {
8
- if (!opts.qwikRouterConfig) {
9
- throw new Error(`Missing "qwikRouterConfig" option`);
10
- }
11
- let siteOrigin = opts.origin;
12
- if (typeof siteOrigin !== "string" || siteOrigin.trim().length === 0) {
13
- throw new Error(`Missing "origin" option`);
14
- }
15
- siteOrigin = siteOrigin.trim();
16
- if (!/:\/\//.test(siteOrigin) || siteOrigin.startsWith("://")) {
17
- throw new Error(`"origin" must start with a valid protocol, such as "https://" or "http://", received "${siteOrigin}"`);
18
- }
19
- try {
20
- new URL(siteOrigin);
21
- } catch (e) {
22
- throw new Error(`Invalid "origin"`, {
23
- cause: e
24
- });
25
- }
7
+ if (!opts.qwikRouterConfig) throw new Error(`Missing "qwikRouterConfig" option`);
8
+ let siteOrigin = opts.origin;
9
+ if (typeof siteOrigin !== "string" || siteOrigin.trim().length === 0) throw new Error(`Missing "origin" option`);
10
+ siteOrigin = siteOrigin.trim();
11
+ if (!/:\/\//.test(siteOrigin) || siteOrigin.startsWith("://")) throw new Error(`"origin" must start with a valid protocol, such as "https://" or "http://", received "${siteOrigin}"`);
12
+ try {
13
+ new URL(siteOrigin);
14
+ } catch (e) {
15
+ throw new Error(`Invalid "origin"`, { cause: e });
16
+ }
26
17
  }
27
18
  async function mainThread(sys) {
28
- const opts = sys.getOptions();
29
- validateOptions(opts);
30
- const main = await sys.createMainProcess();
31
- const log = await sys.createLogger();
32
- log.info("\n" + bold(green("Starting Qwik Router SSG...")));
33
- const qwikRouterConfig = opts.qwikRouterConfig;
34
- const renderTimeout = 3e4;
35
- const queue = [];
36
- const active = /* @__PURE__ */ new Set();
37
- const routes = qwikRouterConfig.routes;
38
- const trailingSlash = !!qwikRouterConfig.trailingSlash;
39
- const includeRoute = createRouteTester(opts.basePathname || "/", opts.include, opts.exclude);
40
- return new Promise((resolve, reject) => {
41
- try {
42
- const timer = sys.createTimer();
43
- const generatorResult = {
44
- duration: 0,
45
- rendered: 0,
46
- errors: 0,
47
- staticPaths: []
48
- };
49
- let isCompleted = false;
50
- let isRoutesLoaded = false;
51
- const completed = async () => {
52
- const closePromise = main.close();
53
- generatorResult.duration = timer();
54
- if (generatorResult.errors === 0) {
55
- log.info(`
56
- ${green("SSG results")}`);
57
- if (generatorResult.rendered > 0) {
58
- log.info(`- Generated: ${dim(`${generatorResult.rendered} page${generatorResult.rendered === 1 ? "" : "s"}`)}`);
59
- }
60
- log.info(`- Duration: ${dim(msToString(generatorResult.duration))}`);
61
- const total = generatorResult.rendered + generatorResult.errors;
62
- if (total > 0) {
63
- log.info(`- Average: ${dim(msToString(generatorResult.duration / total) + " per page")}`);
64
- }
65
- log.info(``);
66
- }
67
- closePromise.then(() => {
68
- setTimeout(() => resolve(generatorResult));
69
- }).catch(reject);
70
- };
71
- const next = () => {
72
- while (!isCompleted && main.hasAvailableWorker() && queue.length > 0) {
73
- const staticRoute = queue.shift();
74
- if (staticRoute) {
75
- render(staticRoute).catch((e) => {
76
- console.error(`render failed for ${staticRoute.pathname}`, e);
77
- });
78
- }
79
- }
80
- if (!isCompleted && isRoutesLoaded && queue.length === 0 && active.size === 0) {
81
- isCompleted = true;
82
- completed().catch((e) => {
83
- console.error("SSG completion failed", e);
84
- });
85
- }
86
- };
87
- let isPendingDrain = false;
88
- const flushQueue = () => {
89
- if (!isPendingDrain) {
90
- isPendingDrain = true;
91
- setTimeout(() => {
92
- isPendingDrain = false;
93
- next();
94
- });
95
- }
96
- };
97
- const render = async (staticRoute) => {
98
- try {
99
- active.add(staticRoute.pathname);
100
- log.debug(`render start: ${staticRoute.pathname}`);
101
- const result = await Promise.race([
102
- main.render({
103
- type: "render",
104
- ...staticRoute
105
- }),
106
- new Promise((_, reject2) => setTimeout(() => reject2(new Error(`SSG render timed out after ${renderTimeout}ms`)), renderTimeout))
107
- ]);
108
- active.delete(staticRoute.pathname);
109
- log.debug(`render done: ${staticRoute.pathname}`);
110
- if (result.error) {
111
- const err = new Error(result.error.message);
112
- err.stack = result.error.stack;
113
- log.error(`
114
- ${bold(red(`!!! ${result.pathname}: Error during SSG`))}`);
115
- log.error(red(err.message));
116
- log.error(` Pathname: ${magenta(staticRoute.pathname)}`);
117
- if (err.stack) {
118
- log.error(dim(err.stack));
119
- }
120
- generatorResult.errors++;
121
- }
122
- if (result.filePath != null) {
123
- generatorResult.rendered++;
124
- generatorResult.staticPaths.push(result.pathname);
125
- const base = opts.rootDir ?? opts.outDir;
126
- const path = relative(base, result.filePath);
127
- const lastSlash = path.lastIndexOf("/");
128
- log.info(`${dim(path.slice(0, lastSlash + 1))}${path.slice(lastSlash + 1)}`);
129
- }
130
- flushQueue();
131
- } catch (e) {
132
- console.error(`render failed for ${staticRoute.pathname}`, e);
133
- isCompleted = true;
134
- reject(e);
135
- }
136
- };
137
- const addToQueue = (pathname, params) => {
138
- if (pathname) {
139
- pathname = new URL(pathname, `https://qwik.dev`).pathname;
140
- if (pathname !== opts.basePathname) {
141
- if (trailingSlash) {
142
- if (!pathname.endsWith("/")) {
143
- const segments = pathname.split("/");
144
- const lastSegment = segments[segments.length - 1];
145
- if (!lastSegment.includes(".")) {
146
- pathname = ensureSlash(pathname);
147
- }
148
- }
149
- } else {
150
- if (pathname.endsWith("/")) {
151
- pathname = pathname.slice(0, pathname.length - 1);
152
- }
153
- }
154
- }
155
- if (includeRoute(pathname) && !queue.some((s) => s.pathname === pathname)) {
156
- queue.push({
157
- pathname,
158
- params
159
- });
160
- flushQueue();
161
- }
162
- }
163
- };
164
- const traverseRouteTree = async (node, pathParts, basePathname, ancestorLoaders) => {
165
- const currentLoaders = node._L ? [
166
- ...ancestorLoaders,
167
- node._L
168
- ] : ancestorLoaders;
169
- const index = node._I;
170
- if (index) {
171
- const pageLoaders = Array.isArray(index) ? index : [
172
- ...currentLoaders,
173
- index
174
- ];
175
- const joinedParts = pathParts.join("/");
176
- const originalPathname = basePathname + (joinedParts ? ensureSlash(joinedParts) : "");
177
- const paramNames = pathParts.filter((p) => p.startsWith("[") && p.endsWith("]")).map((p) => p.startsWith("[...") ? p.slice(4, -1) : p.slice(1, -1));
178
- if (paramNames.length === 0) {
179
- addToQueue(originalPathname, void 0);
180
- } else {
181
- const pageLoader = pageLoaders[pageLoaders.length - 1];
182
- if (typeof pageLoader === "function") {
183
- const pageModule = await pageLoader();
184
- if (typeof pageModule.onStaticGenerate === "function") {
185
- const staticGenerate = await pageModule.onStaticGenerate({
186
- env: {
187
- get(key) {
188
- return sys.getEnv(key);
189
- }
190
- }
191
- });
192
- if (Array.isArray(staticGenerate.params)) {
193
- for (const params of staticGenerate.params) {
194
- const pathname = getPathnameForDynamicRoute(originalPathname, paramNames, params);
195
- addToQueue(pathname, params);
196
- }
197
- }
198
- }
199
- }
200
- }
201
- }
202
- if (node._4 || node._E) {
203
- const isStaticDir = !pathParts.some((p) => p.startsWith("["));
204
- if (isStaticDir) {
205
- const joinedParts = pathParts.join("/");
206
- const dirPathname = basePathname + (joinedParts ? ensureSlash(joinedParts) : "");
207
- addToQueue(dirPathname + "404.html", void 0);
208
- }
209
- }
210
- if (node._M) {
211
- for (const group of node._M) {
212
- await traverseRouteTree(group, pathParts, basePathname, currentLoaders);
213
- }
214
- }
215
- if (node._W && typeof node._W === "object") {
216
- const childNode = node._W;
217
- const paramName = childNode._P;
218
- const pathPart = paramName ? `[${paramName}]` : "[param]";
219
- await traverseRouteTree(childNode, [
220
- ...pathParts,
221
- pathPart
222
- ], basePathname, currentLoaders);
223
- }
224
- if (node._A && typeof node._A === "object") {
225
- const childNode = node._A;
226
- const paramName = childNode._P;
227
- const pathPart = paramName ? `[...${paramName}]` : "[...rest]";
228
- await traverseRouteTree(childNode, [
229
- ...pathParts,
230
- pathPart
231
- ], basePathname, currentLoaders);
232
- }
233
- for (const [key, child] of Object.entries(node)) {
234
- if (key.charCodeAt(0) === 95) {
235
- continue;
236
- }
237
- const childNode = child;
238
- await traverseRouteTree(childNode, [
239
- ...pathParts,
240
- key
241
- ], basePathname, currentLoaders);
242
- }
243
- };
244
- const loadStaticRoutes = async () => {
245
- log.debug("traversing route tree...");
246
- await traverseRouteTree(routes, [], "/", []);
247
- log.debug(`route tree traversed, ${queue.length} routes queued, ${active.size} active`);
248
- isRoutesLoaded = true;
249
- flushQueue();
250
- };
251
- loadStaticRoutes().catch((e) => {
252
- console.error("SSG route loading failed", e);
253
- reject(e);
254
- });
255
- } catch (e) {
256
- console.error("SSG main thread failed", e);
257
- reject(e);
258
- }
259
- });
19
+ const opts = sys.getOptions();
20
+ validateOptions(opts);
21
+ const main = await sys.createMainProcess();
22
+ const log = await sys.createLogger();
23
+ log.info("\n" + bold(green("Starting Qwik Router SSG...")));
24
+ const qwikRouterConfig = opts.qwikRouterConfig;
25
+ const renderTimeout = 3e4;
26
+ const queue = [];
27
+ const active = /* @__PURE__ */ new Set();
28
+ const routes = qwikRouterConfig.routes;
29
+ const trailingSlash = !!qwikRouterConfig.trailingSlash;
30
+ const includeRoute = createRouteTester(opts.basePathname || "/", opts.include, opts.exclude);
31
+ return new Promise((resolve, reject) => {
32
+ try {
33
+ const timer = sys.createTimer();
34
+ const generatorResult = {
35
+ duration: 0,
36
+ rendered: 0,
37
+ errors: 0,
38
+ staticPaths: []
39
+ };
40
+ let isCompleted = false;
41
+ let isRoutesLoaded = false;
42
+ const completed = async () => {
43
+ const closePromise = main.close();
44
+ generatorResult.duration = timer();
45
+ if (generatorResult.errors === 0) {
46
+ log.info(`\n${green("SSG results")}`);
47
+ if (generatorResult.rendered > 0) log.info(`- Generated: ${dim(`${generatorResult.rendered} page${generatorResult.rendered === 1 ? "" : "s"}`)}`);
48
+ log.info(`- Duration: ${dim(msToString(generatorResult.duration))}`);
49
+ const total = generatorResult.rendered + generatorResult.errors;
50
+ if (total > 0) log.info(`- Average: ${dim(msToString(generatorResult.duration / total) + " per page")}`);
51
+ log.info(``);
52
+ }
53
+ closePromise.then(() => {
54
+ setTimeout(() => resolve(generatorResult));
55
+ }).catch(reject);
56
+ };
57
+ const next = () => {
58
+ while (!isCompleted && main.hasAvailableWorker() && queue.length > 0) {
59
+ const staticRoute = queue.shift();
60
+ if (staticRoute) render(staticRoute).catch((e) => {
61
+ console.error(`render failed for ${staticRoute.pathname}`, e);
62
+ });
63
+ }
64
+ if (!isCompleted && isRoutesLoaded && queue.length === 0 && active.size === 0) {
65
+ isCompleted = true;
66
+ completed().catch((e) => {
67
+ console.error("SSG completion failed", e);
68
+ });
69
+ }
70
+ };
71
+ let isPendingDrain = false;
72
+ const flushQueue = () => {
73
+ if (!isPendingDrain) {
74
+ isPendingDrain = true;
75
+ setTimeout(() => {
76
+ isPendingDrain = false;
77
+ next();
78
+ });
79
+ }
80
+ };
81
+ const render = async (staticRoute) => {
82
+ try {
83
+ active.add(staticRoute.pathname);
84
+ log.debug(`render start: ${staticRoute.pathname}`);
85
+ const result = await Promise.race([main.render({
86
+ type: "render",
87
+ ...staticRoute
88
+ }), new Promise((_, reject) => setTimeout(() => reject(/* @__PURE__ */ new Error(`SSG render timed out after ${renderTimeout}ms`)), renderTimeout))]);
89
+ active.delete(staticRoute.pathname);
90
+ log.debug(`render done: ${staticRoute.pathname}`);
91
+ if (result.error) {
92
+ const err = new Error(result.error.message);
93
+ err.stack = result.error.stack;
94
+ log.error(`\n${bold(red(`!!! ${result.pathname}: Error during SSG`))}`);
95
+ log.error(red(err.message));
96
+ log.error(` Pathname: ${magenta(staticRoute.pathname)}`);
97
+ if (err.stack) log.error(dim(err.stack));
98
+ generatorResult.errors++;
99
+ }
100
+ if (result.filePath != null) {
101
+ generatorResult.rendered++;
102
+ generatorResult.staticPaths.push(result.pathname);
103
+ const base = opts.rootDir ?? opts.outDir;
104
+ const path = relative(base, result.filePath);
105
+ const lastSlash = path.lastIndexOf("/");
106
+ log.info(`${dim(path.slice(0, lastSlash + 1))}${path.slice(lastSlash + 1)}`);
107
+ }
108
+ flushQueue();
109
+ } catch (e) {
110
+ console.error(`render failed for ${staticRoute.pathname}`, e);
111
+ isCompleted = true;
112
+ reject(e);
113
+ }
114
+ };
115
+ const addToQueue = (pathname, params) => {
116
+ if (pathname) {
117
+ pathname = new URL(pathname, `https://qwik.dev`).pathname;
118
+ if (pathname !== opts.basePathname) {
119
+ if (trailingSlash) {
120
+ if (!pathname.endsWith("/")) {
121
+ const segments = pathname.split("/");
122
+ if (!segments[segments.length - 1].includes(".")) pathname = ensureSlash(pathname);
123
+ }
124
+ } else if (pathname.endsWith("/")) pathname = pathname.slice(0, pathname.length - 1);
125
+ }
126
+ if (includeRoute(pathname) && !queue.some((s) => s.pathname === pathname)) {
127
+ queue.push({
128
+ pathname,
129
+ params
130
+ });
131
+ flushQueue();
132
+ }
133
+ }
134
+ };
135
+ /**
136
+ * Traverse the route tree and call the callback for each route that has module loaders.
137
+ * Reconstructs the original pathname and param names from the tree path. Accumulates _L
138
+ * layout loaders from ancestors during traversal.
139
+ */ const traverseRouteTree = async (node, pathParts, basePathname, ancestorLoaders) => {
140
+ const currentLoaders = node._L ? [...ancestorLoaders, node._L] : ancestorLoaders;
141
+ const index = node._I;
142
+ if (index) {
143
+ const pageLoaders = Array.isArray(index) ? index : [...currentLoaders, index];
144
+ const joinedParts = pathParts.join("/");
145
+ const originalPathname = basePathname + (joinedParts ? ensureSlash(joinedParts) : "");
146
+ const paramNames = pathParts.filter((p) => p.startsWith("[") && p.endsWith("]")).map((p) => p.startsWith("[...") ? p.slice(4, -1) : p.slice(1, -1));
147
+ if (paramNames.length === 0) addToQueue(originalPathname, void 0);
148
+ else {
149
+ const pageLoader = pageLoaders[pageLoaders.length - 1];
150
+ if (typeof pageLoader === "function") {
151
+ const pageModule = await pageLoader();
152
+ if (typeof pageModule.onStaticGenerate === "function") {
153
+ const staticGenerate = await pageModule.onStaticGenerate({ env: { get(key) {
154
+ return sys.getEnv(key);
155
+ } } });
156
+ if (Array.isArray(staticGenerate.params)) for (const params of staticGenerate.params) {
157
+ const pathname = getPathnameForDynamicRoute(originalPathname, paramNames, params);
158
+ addToQueue(pathname, params);
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ if (node._4 || node._E) {
165
+ if (!pathParts.some((p) => p.startsWith("["))) {
166
+ const joinedParts = pathParts.join("/");
167
+ const dirPathname = basePathname + (joinedParts ? ensureSlash(joinedParts) : "");
168
+ addToQueue(dirPathname + "404.html", void 0);
169
+ }
170
+ }
171
+ if (node._M) for (const group of node._M) await traverseRouteTree(group, pathParts, basePathname, currentLoaders);
172
+ if (node._W && typeof node._W === "object") {
173
+ const childNode = node._W;
174
+ const paramName = childNode._P;
175
+ const pathPart = paramName ? `[${paramName}]` : "[param]";
176
+ await traverseRouteTree(childNode, [...pathParts, pathPart], basePathname, currentLoaders);
177
+ }
178
+ if (node._A && typeof node._A === "object") {
179
+ const childNode = node._A;
180
+ const paramName = childNode._P;
181
+ const pathPart = paramName ? `[...${paramName}]` : "[...rest]";
182
+ await traverseRouteTree(childNode, [...pathParts, pathPart], basePathname, currentLoaders);
183
+ }
184
+ for (const [key, child] of Object.entries(node)) {
185
+ if (key.charCodeAt(0) === 95) continue;
186
+ await traverseRouteTree(child, [...pathParts, key], basePathname, currentLoaders);
187
+ }
188
+ };
189
+ const loadStaticRoutes = async () => {
190
+ log.debug("traversing route tree...");
191
+ await traverseRouteTree(routes, [], "/", []);
192
+ log.debug(`route tree traversed, ${queue.length} routes queued, ${active.size} active`);
193
+ isRoutesLoaded = true;
194
+ flushQueue();
195
+ };
196
+ loadStaticRoutes().catch((e) => {
197
+ console.error("SSG route loading failed", e);
198
+ reject(e);
199
+ });
200
+ } catch (e) {
201
+ console.error("SSG main thread failed", e);
202
+ reject(e);
203
+ }
204
+ });
260
205
  }
261
-
262
- async function generate(opts) {
263
- const { createSystem } = await import('../chunks/system.mjs');
264
- const sys = await createSystem(opts);
265
- return mainThread(sys);
206
+ /**
207
+ * Use this function when SSG should be generated from another module, such as a Vite plugin. This
208
+ * function's should be passed the paths of the entry module and Qwik Router Plan.
209
+ *
210
+ * @public
211
+ */ async function generate(opts) {
212
+ const { createSystem } = await import("../chunks/system.mjs");
213
+ return mainThread(await createSystem(opts));
266
214
  }
267
- async function runSsg(opts) {
268
- try {
269
- const result = await generate(opts);
270
- const fs = await import('node:fs');
271
- const { join } = await import('node:path');
272
- const staticPathsFile = join(opts.outDir, "_static-paths.json");
273
- await fs.promises.writeFile(staticPathsFile, JSON.stringify(result.staticPaths));
274
- if (result.errors > 0) {
275
- console.error(`SSG completed with ${result.errors} error(s)`);
276
- process.exit(1);
277
- }
278
- process.exit(0);
279
- } catch (e) {
280
- console.error("SSG failed:", e);
281
- process.exit(1);
282
- }
215
+ /**
216
+ * Run SSG as a standalone process. Writes `_static-paths.json` to `outDir` and exits with code 0 on
217
+ * success, 1 on error.
218
+ *
219
+ * Intended to be called from a generated `run-ssg.js` wrapper that provides render/config.
220
+ *
221
+ * @public
222
+ */ async function runSsg(opts) {
223
+ try {
224
+ const result = await generate(opts);
225
+ const fs = await import("node:fs");
226
+ const { join } = await import("node:path");
227
+ const staticPathsFile = join(opts.outDir, "_static-paths.json");
228
+ await fs.promises.writeFile(staticPathsFile, JSON.stringify(result.staticPaths));
229
+ if (result.errors > 0) {
230
+ console.error(`SSG completed with ${result.errors} error(s)`);
231
+ process.exit(1);
232
+ }
233
+ process.exit(0);
234
+ } catch (e) {
235
+ console.error("SSG failed:", e);
236
+ process.exit(1);
237
+ }
283
238
  }
284
- async function startWorker(opts) {
285
- const { workerData } = await import('node:worker_threads');
286
- const mergedOpts = {
287
- ...workerData,
288
- render: opts.render,
289
- qwikRouterConfig: opts.qwikRouterConfig
290
- };
291
- const { createSystem } = await import('../chunks/system.mjs');
292
- const { workerThread } = await import('../chunks/worker-thread.mjs');
293
- const sys = await createSystem(mergedOpts, workerData?.threadId);
294
- await workerThread(sys);
239
+ /**
240
+ * Bootstrap a worker thread for SSG rendering. Called from the generated `run-ssg.js` when it
241
+ * detects it's running as a worker thread.
242
+ *
243
+ * @param opts - Must include `render` and `qwikRouterConfig` (imported by the worker entry). The
244
+ * remaining serializable options come from `workerData`.
245
+ * @public
246
+ */ async function startWorker(opts) {
247
+ const { workerData } = await import("node:worker_threads");
248
+ const mergedOpts = {
249
+ ...workerData,
250
+ render: opts.render,
251
+ qwikRouterConfig: opts.qwikRouterConfig
252
+ };
253
+ const { createSystem } = await import("../chunks/system.mjs");
254
+ const { workerThread } = await import("../chunks/worker-thread.mjs");
255
+ await workerThread(await createSystem(mergedOpts, workerData?.threadId));
295
256
  }
296
-
297
257
  export { generate, runSsg, startWorker };