@blinkk/root 3.0.6 → 3.1.1

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 (39) hide show
  1. package/dist/build-worker.js +108 -0
  2. package/dist/build-worker.js.map +7 -0
  3. package/dist/chunk-3PWR4F2R.js +77 -0
  4. package/dist/chunk-3PWR4F2R.js.map +7 -0
  5. package/dist/{chunk-3EFECH2D.js → chunk-E4F6CMO3.js} +439 -553
  6. package/dist/chunk-E4F6CMO3.js.map +7 -0
  7. package/dist/{chunk-7HK6F5RQ.js → chunk-I3RCAIW7.js} +1 -75
  8. package/dist/chunk-I3RCAIW7.js.map +7 -0
  9. package/dist/chunk-KHO3HMX6.js +291 -0
  10. package/dist/chunk-KHO3HMX6.js.map +7 -0
  11. package/dist/chunk-M3E4RKS7.js +374 -0
  12. package/dist/chunk-M3E4RKS7.js.map +7 -0
  13. package/dist/{chunk-6NBKAR5Y.js → chunk-TM6QRBGS.js} +31 -1
  14. package/dist/chunk-TM6QRBGS.js.map +7 -0
  15. package/dist/chunk-WX62JK5E.js +81 -0
  16. package/dist/chunk-WX62JK5E.js.map +7 -0
  17. package/dist/{chunk-7PSEEE6C.js → chunk-YU22SAIG.js} +31 -317
  18. package/dist/chunk-YU22SAIG.js.map +7 -0
  19. package/dist/cli/build-page.d.ts +57 -0
  20. package/dist/cli/build-worker-pool.d.ts +46 -0
  21. package/dist/cli/build-worker.d.ts +4 -0
  22. package/dist/cli/build.d.ts +6 -0
  23. package/dist/cli.js +8 -4
  24. package/dist/core/security.d.ts +14 -0
  25. package/dist/functions.js +8 -4
  26. package/dist/functions.js.map +1 -1
  27. package/dist/middleware/common.d.ts +18 -0
  28. package/dist/middleware/compression.d.ts +12 -0
  29. package/dist/middleware/middleware.d.ts +1 -0
  30. package/dist/middleware.js +6 -1
  31. package/dist/node.js +7 -5
  32. package/dist/render/render.d.ts +15 -9
  33. package/dist/render.js +42 -95
  34. package/dist/render.js.map +2 -2
  35. package/package.json +2 -2
  36. package/dist/chunk-3EFECH2D.js.map +0 -7
  37. package/dist/chunk-6NBKAR5Y.js.map +0 -7
  38. package/dist/chunk-7HK6F5RQ.js.map +0 -7
  39. package/dist/chunk-7PSEEE6C.js.map +0 -7
@@ -1,21 +1,23 @@
1
1
  import {
2
- RouteTrie,
3
- isValidTagName,
4
- parseTagNames,
5
- transformHtml
6
- } from "./chunk-7HK6F5RQ.js";
2
+ collectPods,
3
+ createViteServer,
4
+ preactToRootJsxPlugin,
5
+ rootPodsVitePlugin
6
+ } from "./chunk-YU22SAIG.js";
7
7
  import {
8
- headersMiddleware,
9
- rootProjectMiddleware,
10
- sessionMiddleware,
11
- trailingSlashMiddleware
12
- } from "./chunk-6NBKAR5Y.js";
8
+ RouteTrie
9
+ } from "./chunk-I3RCAIW7.js";
10
+ import {
11
+ BuildAssetMap,
12
+ ElementGraph,
13
+ buildPage,
14
+ getElements,
15
+ getElementsDirs
16
+ } from "./chunk-M3E4RKS7.js";
13
17
  import {
14
18
  bundleRootConfig,
15
- collectPods,
16
19
  copyDir,
17
20
  copyGlob,
18
- createViteServer,
19
21
  dirExists,
20
22
  directoryContains,
21
23
  fileExists,
@@ -27,144 +29,35 @@ import {
27
29
  loadRootConfig,
28
30
  loadRootConfigWithDeps,
29
31
  makeDir,
30
- preactToRootJsxPlugin,
31
32
  rmDir,
32
- rootPodsVitePlugin,
33
33
  writeFile,
34
34
  writeJson
35
- } from "./chunk-7PSEEE6C.js";
35
+ } from "./chunk-KHO3HMX6.js";
36
36
  import {
37
37
  configureServerPlugins,
38
38
  getVitePlugins
39
39
  } from "./chunk-XSNCF7WU.js";
40
+ import {
41
+ compressionMiddleware,
42
+ headersMiddleware,
43
+ rootProjectMiddleware,
44
+ securityHeadersMiddleware,
45
+ sessionMiddleware,
46
+ trailingSlashMiddleware
47
+ } from "./chunk-TM6QRBGS.js";
40
48
 
41
49
  // src/cli/cli.ts
42
50
  import { Command, InvalidArgumentError } from "commander";
43
51
  import { bgGreen, black } from "kleur/colors";
44
52
 
45
53
  // src/cli/build.ts
46
- import path3 from "node:path";
47
- import { fileURLToPath } from "node:url";
54
+ import os from "node:os";
55
+ import path2 from "node:path";
56
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
48
57
  import fsExtra from "fs-extra";
49
58
  import { dim as dim2, cyan } from "kleur/colors";
50
- import glob2 from "tiny-glob";
51
- import { build as viteBuild } from "vite";
52
-
53
- // src/node/element-graph.ts
54
- import fs from "node:fs";
55
- import path from "node:path";
56
59
  import glob from "tiny-glob";
57
- import { searchForWorkspaceRoot } from "vite";
58
- var ElementGraph = class _ElementGraph {
59
- /**
60
- * Element tagName => sourceFile.
61
- */
62
- sourceFiles = {};
63
- /**
64
- * Element tagName => set of element tagName dependencies.
65
- */
66
- deps = {};
67
- constructor(sourceFiles) {
68
- this.sourceFiles = sourceFiles;
69
- }
70
- toJson() {
71
- for (const tagName in this.sourceFiles) {
72
- this.deps[tagName] ??= this.parseDepsFromSource(tagName);
73
- }
74
- return {
75
- sourceFiles: this.sourceFiles,
76
- deps: this.deps
77
- };
78
- }
79
- static fromJson(data) {
80
- const graph = new _ElementGraph(data.sourceFiles);
81
- graph.deps = data.deps;
82
- return graph;
83
- }
84
- getDeps(tagName, visited) {
85
- visited ??= /* @__PURE__ */ new Set();
86
- if (visited.has(tagName)) {
87
- return [];
88
- }
89
- visited.add(tagName);
90
- this.deps[tagName] ??= this.parseDepsFromSource(tagName);
91
- const deps = new Set(this.deps[tagName]);
92
- for (const depTagName of this.deps[tagName]) {
93
- for (const childDep of this.getDeps(depTagName, visited)) {
94
- deps.add(childDep);
95
- }
96
- }
97
- return Array.from(deps);
98
- }
99
- /**
100
- * Parses an element's source file for usage of other custom elements.
101
- */
102
- parseDepsFromSource(tagName) {
103
- const srcFile = this.sourceFiles[tagName];
104
- if (!srcFile) {
105
- throw new Error(`could not find file path for tagName <${tagName}>`);
106
- }
107
- const src = fs.readFileSync(srcFile.filePath, "utf-8");
108
- const tagNames = parseTagNames(src);
109
- const deps = /* @__PURE__ */ new Set();
110
- for (const depTagName of tagNames) {
111
- if (depTagName !== tagName && depTagName in this.sourceFiles) {
112
- deps.add(depTagName);
113
- }
114
- }
115
- return Array.from(deps);
116
- }
117
- };
118
- async function getElements(rootConfig, pods) {
119
- const rootDir = rootConfig.rootDir;
120
- const elementsDirs = getElementsDirs(rootConfig, pods);
121
- const excludePatterns = rootConfig.elements?.exclude || [];
122
- const excludeElement = (moduleId) => {
123
- return excludePatterns.some((pattern) => Boolean(moduleId.match(pattern)));
124
- };
125
- const elementFilePaths = {};
126
- for (const dirPath of elementsDirs) {
127
- if (await isDirectory(dirPath)) {
128
- const files = await glob("**/*", { cwd: dirPath });
129
- files.forEach((file) => {
130
- const parts = path.parse(file);
131
- if (isJsFile(parts.base) && isValidTagName(parts.name)) {
132
- const tagName = parts.name;
133
- const filePath = path.join(dirPath, file);
134
- const relPath = path.relative(rootDir, filePath);
135
- if (!excludeElement(relPath)) {
136
- elementFilePaths[tagName] = { filePath, relPath };
137
- }
138
- }
139
- });
140
- }
141
- }
142
- const graph = new ElementGraph(elementFilePaths);
143
- return graph;
144
- }
145
- function getElementsDirs(rootConfig, pods) {
146
- const rootDir = rootConfig.rootDir;
147
- const workspaceRoot = searchForWorkspaceRoot(rootDir);
148
- const elementsDirs = [path.join(rootDir, "elements")];
149
- const elementsInclude = rootConfig.elements?.include || [];
150
- for (const dirPath of elementsInclude) {
151
- const elementsDir = path.resolve(rootDir, dirPath);
152
- if (!directoryContains(rootDir, elementsDir)) {
153
- throw new Error(
154
- `the elements dir (${dirPath}) should be within the project's workspace (${workspaceRoot})`
155
- );
156
- }
157
- elementsDirs.push(elementsDir);
158
- }
159
- if (pods) {
160
- for (const pod of pods) {
161
- for (const dir of pod.elementsDirs) {
162
- elementsDirs.push(dir);
163
- }
164
- }
165
- }
166
- return elementsDirs;
167
- }
60
+ import { build as viteBuild } from "vite";
168
61
 
169
62
  // src/node/vite-plugin-prune-empty-chunks.ts
170
63
  import { dim } from "kleur/colors";
@@ -231,191 +124,6 @@ function removeSideEffectImport(code, fileName) {
231
124
  return code.replace(re, "");
232
125
  }
233
126
 
234
- // src/render/asset-map/build-asset-map.ts
235
- import fs2 from "node:fs";
236
- import path2 from "node:path";
237
- var BuildAssetMap = class _BuildAssetMap {
238
- rootConfig;
239
- srcToAsset;
240
- constructor(rootConfig) {
241
- this.rootConfig = rootConfig;
242
- this.srcToAsset = /* @__PURE__ */ new Map();
243
- }
244
- async get(src) {
245
- const asset = this.srcToAsset.get(src);
246
- if (asset) {
247
- return asset;
248
- }
249
- const realSrc = realPathRelativeTo(this.rootConfig.rootDir, src);
250
- if (realSrc !== src) {
251
- const asset2 = this.srcToAsset.get(realSrc);
252
- if (asset2) {
253
- return asset2;
254
- }
255
- }
256
- console.log(`could not find build asset: ${src}`);
257
- return null;
258
- }
259
- add(asset) {
260
- this.srcToAsset.set(asset.src, asset);
261
- }
262
- toJson() {
263
- const result = {};
264
- for (const src of this.srcToAsset.keys()) {
265
- result[src] = this.srcToAsset.get(src).toJson();
266
- }
267
- return result;
268
- }
269
- static fromViteManifest(rootConfig, clientManifest, elementsGraph, podRoutes = []) {
270
- const assetMap = new _BuildAssetMap(rootConfig);
271
- const elementFiles = /* @__PURE__ */ new Set();
272
- Object.values(elementsGraph.sourceFiles).forEach((elementSource) => {
273
- elementFiles.add(elementSource.relPath);
274
- const realSrc = realPathRelativeTo(
275
- rootConfig.rootDir,
276
- elementSource.relPath
277
- );
278
- if (realSrc !== elementSource.filePath) {
279
- elementFiles.add(realSrc);
280
- }
281
- });
282
- Object.keys(clientManifest).forEach((manifestKey) => {
283
- const src = manifestKey;
284
- const manifestChunk = clientManifest[manifestKey];
285
- const isElement = elementFiles.has(src);
286
- const assetUrl = src.startsWith("routes/") && isJsFile(src) ? "" : `/${manifestChunk.file}`;
287
- const assetData = {
288
- src,
289
- assetUrl,
290
- importedModules: manifestChunk.imports || [],
291
- importedCss: (manifestChunk.css || []).map((relPath) => `/${relPath}`),
292
- isElement
293
- };
294
- assetMap.add(new BuildAsset(assetMap, assetData));
295
- });
296
- podRoutes.forEach((podRoute) => {
297
- if (assetMap.srcToAsset.has(podRoute.src)) {
298
- return;
299
- }
300
- const relPath = path2.relative(rootConfig.rootDir, podRoute.filePath).replace(/\\/g, "/");
301
- const realPath = realPathRelativeTo(rootConfig.rootDir, relPath).replace(
302
- /\\/g,
303
- "/"
304
- );
305
- const candidateKeys = [relPath, realPath];
306
- for (const key of candidateKeys) {
307
- const asset = assetMap.srcToAsset.get(key);
308
- if (asset) {
309
- assetMap.add(
310
- new BuildAsset(assetMap, {
311
- ...asset.toJson(),
312
- src: podRoute.src,
313
- assetUrl: ""
314
- })
315
- );
316
- break;
317
- }
318
- }
319
- });
320
- return assetMap;
321
- }
322
- static fromRootManifest(rootConfig, rootManifest) {
323
- const assetMap = new _BuildAssetMap(rootConfig);
324
- Object.keys(rootManifest).forEach((moduleId) => {
325
- const assetData = rootManifest[moduleId];
326
- assetMap.add(new BuildAsset(assetMap, assetData));
327
- });
328
- return assetMap;
329
- }
330
- };
331
- function realPathRelativeTo(rootDir, src) {
332
- const fullPath = path2.resolve(rootDir, src);
333
- if (!fs2.existsSync(fullPath)) {
334
- return src;
335
- }
336
- const realpath = fs2.realpathSync(path2.resolve(rootDir, src));
337
- return path2.relative(rootDir, realpath);
338
- }
339
- var BuildAsset = class {
340
- src;
341
- assetUrl;
342
- assetMap;
343
- importedModules;
344
- importedCss;
345
- isElement;
346
- constructor(assetMap, assetData) {
347
- this.assetMap = assetMap;
348
- this.src = assetData.src;
349
- this.assetUrl = assetData.assetUrl;
350
- this.importedModules = assetData.importedModules;
351
- this.importedCss = assetData.importedCss;
352
- this.isElement = assetData.isElement;
353
- }
354
- async getCssDeps() {
355
- const visited = /* @__PURE__ */ new Set();
356
- const deps = /* @__PURE__ */ new Set();
357
- await this.collectCss(this, deps, visited);
358
- return Array.from(deps);
359
- }
360
- async getJsDeps() {
361
- const visited = /* @__PURE__ */ new Set();
362
- const deps = /* @__PURE__ */ new Set();
363
- await this.collectJs(this, deps, visited);
364
- return Array.from(deps);
365
- }
366
- async collectJs(asset, urls, visited) {
367
- if (!asset) {
368
- return;
369
- }
370
- if (!asset.src) {
371
- return;
372
- }
373
- if (visited.has(asset.src)) {
374
- return;
375
- }
376
- visited.add(asset.src);
377
- if (asset.isElement) {
378
- urls.add(asset.assetUrl);
379
- }
380
- await Promise.all(
381
- asset.importedModules.map(async (src) => {
382
- const importedAsset = await this.assetMap.get(src);
383
- this.collectJs(importedAsset, urls, visited);
384
- })
385
- );
386
- }
387
- async collectCss(asset, urls, visited) {
388
- if (!asset) {
389
- return;
390
- }
391
- if (!asset.src) {
392
- return;
393
- }
394
- if (visited.has(asset.src)) {
395
- return;
396
- }
397
- visited.add(asset.src);
398
- if (asset.importedCss) {
399
- asset.importedCss.forEach((cssUrl) => urls.add(cssUrl));
400
- }
401
- await Promise.all(
402
- asset.importedModules.map(async (moduleId) => {
403
- const importedAsset = await this.assetMap.get(moduleId);
404
- this.collectCss(importedAsset, urls, visited);
405
- })
406
- );
407
- }
408
- toJson() {
409
- return {
410
- src: this.src,
411
- assetUrl: this.assetUrl,
412
- importedModules: this.importedModules,
413
- importedCss: this.importedCss,
414
- isElement: this.isElement
415
- };
416
- }
417
- };
418
-
419
127
  // src/utils/batch.ts
420
128
  async function batchAsyncCalls(data, concurrency, asyncFunction) {
421
129
  const result = new Array(data.length);
@@ -434,14 +142,144 @@ async function batchAsyncCalls(data, concurrency, asyncFunction) {
434
142
  return result;
435
143
  }
436
144
 
145
+ // src/cli/build-worker-pool.ts
146
+ import path from "node:path";
147
+ import { fileURLToPath } from "node:url";
148
+ import { Worker } from "node:worker_threads";
149
+ var __dirname = path.dirname(fileURLToPath(import.meta.url));
150
+ var BuildPageError = class extends Error {
151
+ urlPath;
152
+ params;
153
+ routeSrc;
154
+ workerError;
155
+ constructor(urlPath, params, routeSrc, workerError) {
156
+ super(
157
+ `BuildError: ${urlPath} (${routeSrc || "unknown route"}) failed to build.`
158
+ );
159
+ this.urlPath = urlPath;
160
+ this.params = params;
161
+ this.routeSrc = routeSrc;
162
+ this.workerError = workerError;
163
+ }
164
+ };
165
+ var BuildWorker = class {
166
+ worker;
167
+ pool;
168
+ concurrency;
169
+ inFlight = /* @__PURE__ */ new Map();
170
+ isReady = false;
171
+ ready;
172
+ constructor(pool, options) {
173
+ this.pool = pool;
174
+ this.concurrency = options.workerConcurrency;
175
+ this.worker = new Worker(path.resolve(__dirname, "./build-worker.js"), {
176
+ workerData: { rootDir: options.rootDir, mode: options.mode }
177
+ });
178
+ let onReady;
179
+ let onFailed;
180
+ this.ready = new Promise((resolve, reject) => {
181
+ onReady = resolve;
182
+ onFailed = reject;
183
+ });
184
+ this.worker.on("message", (msg) => {
185
+ if (msg.type === "ready") {
186
+ this.isReady = true;
187
+ onReady();
188
+ this.next();
189
+ } else if (msg.type === "result") {
190
+ const pending = this.inFlight.get(msg.id);
191
+ this.inFlight.delete(msg.id);
192
+ pending?.resolve(msg.result);
193
+ this.next();
194
+ } else if (msg.type === "error") {
195
+ const pending = this.inFlight.get(msg.id);
196
+ this.inFlight.delete(msg.id);
197
+ pending?.reject(
198
+ new BuildPageError(msg.urlPath, msg.params, msg.routeSrc, msg.error)
199
+ );
200
+ this.next();
201
+ } else if (msg.type === "fatal") {
202
+ const err = new Error(`build worker failed: ${msg.error}`);
203
+ onFailed(err);
204
+ this.failAll(err);
205
+ }
206
+ });
207
+ this.worker.on("error", (err) => {
208
+ onFailed(err);
209
+ this.failAll(err);
210
+ });
211
+ this.worker.on("exit", (code) => {
212
+ if (code !== 0) {
213
+ const err = new Error(`build worker exited with code ${code}`);
214
+ onFailed(err);
215
+ this.failAll(err);
216
+ }
217
+ });
218
+ }
219
+ failAll(err) {
220
+ const pendingTasks = Array.from(this.inFlight.values());
221
+ this.inFlight.clear();
222
+ pendingTasks.forEach((pending) => pending.reject(err));
223
+ }
224
+ /** Pulls tasks off the pool's queue until at max concurrency. */
225
+ next() {
226
+ if (!this.isReady) {
227
+ return;
228
+ }
229
+ while (this.inFlight.size < this.concurrency) {
230
+ const pending = this.pool.dequeue();
231
+ if (!pending) {
232
+ return;
233
+ }
234
+ this.inFlight.set(pending.id, pending);
235
+ const req = {
236
+ type: "render",
237
+ id: pending.id,
238
+ task: pending.task
239
+ };
240
+ this.worker.postMessage(req);
241
+ }
242
+ }
243
+ async terminate() {
244
+ await this.worker.terminate();
245
+ }
246
+ };
247
+ var BuildWorkerPool = class {
248
+ workers = [];
249
+ queue = [];
250
+ nextTaskId = 0;
251
+ constructor(options) {
252
+ for (let i = 0; i < options.numWorkers; i++) {
253
+ this.workers.push(new BuildWorker(this, options));
254
+ }
255
+ }
256
+ /** Waits for all workers to finish initializing. */
257
+ async ready() {
258
+ await Promise.all(this.workers.map((worker) => worker.ready));
259
+ }
260
+ /** Schedules a page build and resolves when the page finishes. */
261
+ run(task) {
262
+ return new Promise((resolve, reject) => {
263
+ this.queue.push({ id: this.nextTaskId++, task, resolve, reject });
264
+ this.workers.forEach((worker) => worker.next());
265
+ });
266
+ }
267
+ dequeue() {
268
+ return this.queue.shift();
269
+ }
270
+ async terminate() {
271
+ await Promise.all(this.workers.map((worker) => worker.terminate()));
272
+ }
273
+ };
274
+
437
275
  // src/cli/build.ts
438
- var __dirname = path3.dirname(fileURLToPath(import.meta.url));
276
+ var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
439
277
  async function build(rootProjectDir, options) {
440
278
  const mode = options?.mode || "production";
441
279
  process.env.NODE_ENV = mode;
442
- const rootDir = path3.resolve(rootProjectDir || process.cwd());
280
+ const rootDir = path2.resolve(rootProjectDir || process.cwd());
443
281
  const rootConfig = await loadRootConfig(rootDir, { command: "build" });
444
- const distDir = path3.join(rootDir, "dist");
282
+ const distDir = path2.join(rootDir, "dist");
445
283
  const ssrOnly = options?.ssrOnly || false;
446
284
  console.log();
447
285
  console.log(`${dim2("\u2503")} project: ${rootDir}`);
@@ -452,12 +290,12 @@ async function build(rootProjectDir, options) {
452
290
  await makeDir(distDir);
453
291
  const pods = await collectPods(rootConfig);
454
292
  const routeFiles = [];
455
- if (await isDirectory(path3.join(rootDir, "routes"))) {
456
- const pageFiles = await glob2("routes/**/*", { cwd: rootDir });
293
+ if (await isDirectory(path2.join(rootDir, "routes"))) {
294
+ const pageFiles = await glob("routes/**/*", { cwd: rootDir });
457
295
  pageFiles.forEach((file) => {
458
- const parts = path3.parse(file);
296
+ const parts = path2.parse(file);
459
297
  if (!parts.name.startsWith("_") && isJsFile(parts.base)) {
460
- routeFiles.push(path3.resolve(rootDir, file));
298
+ routeFiles.push(path2.resolve(rootDir, file));
461
299
  }
462
300
  });
463
301
  }
@@ -471,12 +309,12 @@ async function build(rootProjectDir, options) {
471
309
  return sourceFile.filePath;
472
310
  });
473
311
  const bundleScripts = [];
474
- if (await isDirectory(path3.join(rootDir, "bundles"))) {
475
- const bundleFiles = await glob2("bundles/*", { cwd: rootDir });
312
+ if (await isDirectory(path2.join(rootDir, "bundles"))) {
313
+ const bundleFiles = await glob("bundles/*", { cwd: rootDir });
476
314
  bundleFiles.forEach((file) => {
477
- const parts = path3.parse(file);
315
+ const parts = path2.parse(file);
478
316
  if (isJsFile(parts.base)) {
479
- bundleScripts.push(path3.resolve(rootDir, file));
317
+ bundleScripts.push(path2.resolve(rootDir, file));
480
318
  }
481
319
  });
482
320
  }
@@ -506,7 +344,7 @@ async function build(rootProjectDir, options) {
506
344
  plugins: vitePlugins
507
345
  };
508
346
  const ssrInput = {
509
- render: path3.resolve(__dirname, "./render.js")
347
+ render: path2.resolve(__dirname2, "./render.js")
510
348
  };
511
349
  rootPlugins.forEach((plugin) => {
512
350
  if (plugin.ssrInput) {
@@ -537,7 +375,7 @@ async function build(rootProjectDir, options) {
537
375
  sanitizeFileName
538
376
  }
539
377
  },
540
- outDir: path3.join(distDir, "server"),
378
+ outDir: path2.join(distDir, "server"),
541
379
  ssr: true,
542
380
  ssrManifest: false,
543
381
  cssCodeSplit: true,
@@ -570,7 +408,7 @@ async function build(rootProjectDir, options) {
570
408
  ...viteConfig?.build?.rolldownOptions?.output
571
409
  }
572
410
  },
573
- outDir: path3.join(distDir, ".build/routes"),
411
+ outDir: path2.join(distDir, ".build/routes"),
574
412
  ssr: true,
575
413
  ssrManifest: false,
576
414
  ssrEmitAssets: true,
@@ -601,7 +439,7 @@ async function build(rootProjectDir, options) {
601
439
  ...viteConfig?.build?.rolldownOptions?.output
602
440
  }
603
441
  },
604
- outDir: path3.join(distDir, ".build/client"),
442
+ outDir: path2.join(distDir, ".build/client"),
605
443
  ssr: false,
606
444
  ssrManifest: false,
607
445
  manifest: true,
@@ -614,21 +452,21 @@ async function build(rootProjectDir, options) {
614
452
  });
615
453
  } else {
616
454
  await writeFile(
617
- path3.join(distDir, ".build/client/.vite/manifest.json"),
455
+ path2.join(distDir, ".build/client/.vite/manifest.json"),
618
456
  "{}"
619
457
  );
620
458
  }
621
- await bundleRootConfig(rootDir, path3.join(distDir, "root.config.js"));
459
+ await bundleRootConfig(rootDir, path2.join(distDir, "root.config.js"));
622
460
  await copyGlob(
623
461
  "**/*.css",
624
- path3.join(distDir, ".build/routes"),
625
- path3.join(distDir, ".build/client")
462
+ path2.join(distDir, ".build/routes"),
463
+ path2.join(distDir, ".build/client")
626
464
  );
627
465
  const routesManifest = await loadJson(
628
- path3.join(distDir, ".build/routes/.vite/manifest.json")
466
+ path2.join(distDir, ".build/routes/.vite/manifest.json")
629
467
  );
630
468
  const clientManifest = await loadJson(
631
- path3.join(distDir, ".build/client/.vite/manifest.json")
469
+ path2.join(distDir, ".build/client/.vite/manifest.json")
632
470
  );
633
471
  function collectRouteCss(asset, cssDeps, visited) {
634
472
  if (!asset || !asset.file || visited.has(asset.file)) {
@@ -671,17 +509,17 @@ async function build(rootProjectDir, options) {
671
509
  );
672
510
  const rootManifest = assetMap.toJson();
673
511
  await writeFile(
674
- path3.join(distDir, ".root/manifest.json"),
512
+ path2.join(distDir, ".root/manifest.json"),
675
513
  JSON.stringify(rootManifest, null, 2)
676
514
  );
677
515
  const elementGraphJson = elementGraph.toJson();
678
516
  await writeFile(
679
- path3.join(distDir, ".root/elements.json"),
517
+ path2.join(distDir, ".root/elements.json"),
680
518
  JSON.stringify(elementGraphJson, null, 2)
681
519
  );
682
- const buildDir = path3.join(distDir, "html");
683
- const publicDir = path3.join(rootDir, "public");
684
- if (fsExtra.existsSync(path3.join(rootDir, "public"))) {
520
+ const buildDir = path2.join(distDir, "html");
521
+ const publicDir = path2.join(rootDir, "public");
522
+ if (fsExtra.existsSync(path2.join(rootDir, "public"))) {
685
523
  fsExtra.copySync(publicDir, buildDir, { dereference: true });
686
524
  } else {
687
525
  await makeDir(buildDir);
@@ -693,8 +531,8 @@ async function build(rootProjectDir, options) {
693
531
  }
694
532
  seenAssets.add(assetUrl);
695
533
  const assetRelPath = assetUrl.slice(1);
696
- const assetFrom = path3.join(distDir, ".build/client", assetRelPath);
697
- const assetTo = path3.join(buildDir, assetRelPath);
534
+ const assetFrom = path2.join(distDir, ".build/client", assetRelPath);
535
+ const assetTo = path2.join(buildDir, assetRelPath);
698
536
  if (!await fileExists(assetFrom)) {
699
537
  console.log(`${assetFrom} does not exist`);
700
538
  return;
@@ -724,7 +562,7 @@ async function build(rootProjectDir, options) {
724
562
  })
725
563
  );
726
564
  if (!ssrOnly) {
727
- const render = await import(path3.join(distDir, "server/render.js"));
565
+ const render = await import(path2.join(distDir, "server/render.js"));
728
566
  const renderer = new render.Renderer(rootConfig, { assetMap, elementGraph });
729
567
  let sitemap = await renderer.getSitemap();
730
568
  if (options?.filter) {
@@ -744,92 +582,118 @@ async function build(rootProjectDir, options) {
744
582
  );
745
583
  }
746
584
  const domain = rootConfig.domain;
747
- console.log("\nhtml output:");
748
- const batchSize = Number(options?.concurrency || 10);
749
- await batchAsyncCalls(
750
- Object.entries(sitemap),
751
- batchSize,
752
- async ([urlPath, sitemapItem]) => {
753
- if (rootConfig.build?.excludeDefaultLocaleFromIntlPaths) {
754
- const defaultLocale = rootConfig.i18n?.defaultLocale || "en";
755
- if (sitemapItem.locale === defaultLocale) {
756
- return;
757
- }
585
+ const addSitemapXmlItem = (urlPath, sitemapItem, outFilePath) => {
586
+ if (!rootConfig.sitemap || !outFilePath.endsWith("index.html")) {
587
+ return;
588
+ }
589
+ const sitemapXmlItem = {
590
+ url: `${domain}${urlPath}`,
591
+ locale: sitemapItem.locale,
592
+ alts: []
593
+ };
594
+ sitemapXmlItems.push(sitemapXmlItem);
595
+ if (sitemapItem.alts) {
596
+ Object.entries(sitemapItem.alts).forEach(([altLocale, item]) => {
597
+ sitemapXmlItem.alts.push({
598
+ url: `${domain}${item.urlPath}`,
599
+ locale: altLocale,
600
+ hreflang: item.hrefLang
601
+ });
602
+ });
603
+ }
604
+ };
605
+ const onPageResult = (sitemapItem, result) => {
606
+ if (result.notFound || !result.outFilePath) {
607
+ return;
608
+ }
609
+ if (!result.staticContent) {
610
+ addSitemapXmlItem(result.urlPath, sitemapItem, result.outFilePath);
611
+ }
612
+ printFileOutput(
613
+ fileSize(path2.join(buildDir, result.outFilePath)),
614
+ "dist/html/",
615
+ result.outFilePath
616
+ );
617
+ };
618
+ const sitemapEntries = Object.entries(sitemap).filter(([, sitemapItem]) => {
619
+ if (rootConfig.build?.excludeDefaultLocaleFromIntlPaths) {
620
+ const defaultLocale = rootConfig.i18n?.defaultLocale || "en";
621
+ if (sitemapItem.locale === defaultLocale) {
622
+ return false;
758
623
  }
759
- try {
760
- const routeModule = sitemapItem.route.module;
761
- if (routeModule.getStaticContent) {
762
- let props;
763
- if (routeModule.getStaticProps) {
764
- props = await routeModule.getStaticProps({
765
- rootConfig,
766
- params: sitemapItem.params
624
+ }
625
+ return true;
626
+ });
627
+ console.log("\nhtml output:");
628
+ const concurrency = Number(options?.concurrency || 10);
629
+ const numThreads = resolveNumThreads(
630
+ options?.threads,
631
+ sitemapEntries.length
632
+ );
633
+ if (numThreads > 0) {
634
+ const pool = new BuildWorkerPool({
635
+ numWorkers: numThreads,
636
+ workerConcurrency: Math.max(Math.ceil(concurrency / numThreads), 1),
637
+ rootDir,
638
+ mode
639
+ });
640
+ try {
641
+ await pool.ready();
642
+ await Promise.all(
643
+ sitemapEntries.map(async ([urlPath, sitemapItem]) => {
644
+ try {
645
+ const result = await pool.run({
646
+ urlPath,
647
+ params: sitemapItem.params,
648
+ routeSrc: sitemapItem.route.src,
649
+ locale: sitemapItem.locale
767
650
  });
768
- if (props?.notFound) {
769
- return;
651
+ onPageResult(sitemapItem, result);
652
+ } catch (e) {
653
+ if (e instanceof BuildPageError) {
654
+ logBuildError(
655
+ {
656
+ route: sitemapItem.route,
657
+ params: sitemapItem.params,
658
+ urlPath
659
+ },
660
+ new Error(e.workerError)
661
+ );
770
662
  }
771
- } else {
772
- props = { rootConfig, params: sitemapItem.params };
773
- }
774
- const result = await routeModule.getStaticContent(props);
775
- let body;
776
- if (typeof result === "string") {
777
- body = result;
778
- } else if (result && typeof result === "object") {
779
- body = result.body;
780
- } else {
781
- body = "";
782
- }
783
- const outFilePath2 = urlPath.slice(1);
784
- const outPath2 = path3.join(buildDir, outFilePath2);
785
- await makeDir(path3.dirname(outPath2));
786
- await writeFile(outPath2, normalizeLineEndings(body));
787
- printFileOutput(fileSize(outPath2), "dist/html/", outFilePath2);
788
- return;
789
- }
790
- const data = await renderer.renderRoute(sitemapItem.route, {
791
- routeParams: sitemapItem.params
792
- });
793
- if (data.notFound) {
794
- return;
795
- }
796
- let outFilePath = path3.join(urlPath.slice(1), "index.html");
797
- if (outFilePath.endsWith("404/index.html")) {
798
- outFilePath = outFilePath.replace("404/index.html", "404.html");
799
- }
800
- const outPath = path3.join(buildDir, outFilePath);
801
- if (rootConfig.sitemap && outFilePath.endsWith("index.html")) {
802
- const sitemapXmlItem = {
803
- url: `${domain}${urlPath}`,
804
- locale: sitemapItem.locale,
805
- alts: []
806
- };
807
- sitemapXmlItems.push(sitemapXmlItem);
808
- if (sitemapItem.alts) {
809
- Object.entries(sitemapItem.alts).forEach(([altLocale, item]) => {
810
- sitemapXmlItem.alts.push({
811
- url: `${domain}${item.urlPath}`,
812
- locale: altLocale,
813
- hreflang: item.hrefLang
814
- });
815
- });
663
+ throw e;
816
664
  }
665
+ })
666
+ );
667
+ } finally {
668
+ await pool.terminate();
669
+ }
670
+ } else {
671
+ await batchAsyncCalls(
672
+ sitemapEntries,
673
+ concurrency,
674
+ async ([urlPath, sitemapItem]) => {
675
+ try {
676
+ const result = await buildPage(
677
+ renderer,
678
+ rootConfig,
679
+ buildDir,
680
+ sitemapItem.route,
681
+ { urlPath, params: sitemapItem.params }
682
+ );
683
+ onPageResult(sitemapItem, result);
684
+ } catch (e) {
685
+ logBuildError(
686
+ { route: sitemapItem.route, params: sitemapItem.params, urlPath },
687
+ e
688
+ );
689
+ throw new Error(
690
+ `BuildError: ${urlPath} (${sitemapItem.route.src}) failed to build.`,
691
+ { cause: e }
692
+ );
817
693
  }
818
- const html = await transformHtml(data.html || "", rootConfig);
819
- await writeFile(outPath, normalizeLineEndings(html));
820
- printFileOutput(fileSize(outPath), "dist/html/", outFilePath);
821
- } catch (e) {
822
- logBuildError(
823
- { route: sitemapItem.route, params: sitemapItem.params, urlPath },
824
- e
825
- );
826
- throw new Error(
827
- `BuildError: ${urlPath} (${sitemapItem.route.src}) failed to build.`,
828
- { cause: e }
829
- );
830
694
  }
831
- }
832
- );
695
+ );
696
+ }
833
697
  if (rootConfig.sitemap) {
834
698
  const sitemapXmlBuilder = [];
835
699
  sitemapXmlItems.sort((a, b) => a.url.localeCompare(b.url));
@@ -855,7 +719,7 @@ async function build(rootProjectDir, options) {
855
719
  "</urlset>"
856
720
  ];
857
721
  const sitemapXml = sitemapXmlLines.join("\n");
858
- const outPath = path3.join(buildDir, "sitemap.xml");
722
+ const outPath = path2.join(buildDir, "sitemap.xml");
859
723
  await writeFile(outPath, sitemapXml);
860
724
  printFileOutput(fileSize(outPath), "dist/html/", "sitemap.xml");
861
725
  }
@@ -869,6 +733,27 @@ async function build(rootProjectDir, options) {
869
733
  function isRouteFile(filepath) {
870
734
  return filepath.startsWith("routes") && isJsFile(filepath);
871
735
  }
736
+ var MIN_PAGES_PER_THREAD = 10;
737
+ function resolveNumThreads(threads, numPages) {
738
+ if (threads === void 0 || threads === false) {
739
+ return 0;
740
+ }
741
+ if (threads === true || threads === "auto") {
742
+ const maxByCpu = Math.max(os.availableParallelism() - 1, 1);
743
+ const maxByPages = Math.floor(numPages / MIN_PAGES_PER_THREAD);
744
+ const numThreads = Math.min(maxByCpu, maxByPages);
745
+ if (numThreads <= 1) {
746
+ return 0;
747
+ }
748
+ console.log(`rendering with ${numThreads} worker threads`);
749
+ return numThreads;
750
+ }
751
+ const num = parseInt(threads);
752
+ if (isNaN(num) || num < 0) {
753
+ throw new Error(`invalid --threads value: ${threads}`);
754
+ }
755
+ return num;
756
+ }
872
757
  function fileSize(filepath) {
873
758
  const stats = fsExtra.statSync(filepath);
874
759
  const bytes = stats.size;
@@ -917,18 +802,15 @@ function formatParams(params) {
917
802
  return ` ${key}: ${value}`;
918
803
  }).join("\n");
919
804
  }
920
- function normalizeLineEndings(str) {
921
- return str.replace(/\r\n?/g, "\n");
922
- }
923
805
 
924
806
  // src/cli/codegen.ts
925
- import { promises as fs3 } from "node:fs";
926
- import path4 from "node:path";
927
- import { fileURLToPath as fileURLToPath2 } from "node:url";
928
- import glob3 from "tiny-glob";
929
- var __dirname2 = path4.dirname(fileURLToPath2(import.meta.url));
807
+ import { promises as fs } from "node:fs";
808
+ import path3 from "node:path";
809
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
810
+ import glob2 from "tiny-glob";
811
+ var __dirname3 = path3.dirname(fileURLToPath3(import.meta.url));
930
812
  async function codegen(type, name, options) {
931
- const rootDir = path4.resolve(process.cwd());
813
+ const rootDir = path3.resolve(process.cwd());
932
814
  const project = new Project(rootDir);
933
815
  await project.generateCode(type, name, options);
934
816
  }
@@ -938,8 +820,8 @@ var Project = class {
938
820
  constructor(rootDir) {
939
821
  this.rootDir = rootDir;
940
822
  this.tplDirs = [
941
- path4.join(rootDir, "codegen"),
942
- path4.join(__dirname2, "../codegen")
823
+ path3.join(rootDir, "codegen"),
824
+ path3.join(__dirname3, "../codegen")
943
825
  ];
944
826
  }
945
827
  async generateCode(type, name, options) {
@@ -949,7 +831,7 @@ var Project = class {
949
831
  return;
950
832
  }
951
833
  const outname = options?.out || `${type}s`;
952
- const outdir = path4.join(this.rootDir, outname, name);
834
+ const outdir = path3.join(this.rootDir, outname, name);
953
835
  if (await dirExists(outdir)) {
954
836
  await rmDir(outdir);
955
837
  }
@@ -958,7 +840,7 @@ var Project = class {
958
840
  const tpl = await files[tplName].read();
959
841
  const content = tpl.replaceAll("[[name]]", name).replaceAll("[[name:camel_upper]]", toCamelCaseUpper(name));
960
842
  const filename = tplName.replace("[name]", name);
961
- const filepath = path4.join(outdir, filename);
843
+ const filepath = path3.join(outdir, filename);
962
844
  await writeFile(filepath, content);
963
845
  console.log(`saved ${filepath}`);
964
846
  }
@@ -969,7 +851,7 @@ var Project = class {
969
851
  */
970
852
  async loadFiles(type) {
971
853
  for (const tplDir of this.tplDirs) {
972
- const typeDir = path4.join(tplDir, type);
854
+ const typeDir = path3.join(tplDir, type);
973
855
  if (await dirExists(typeDir)) {
974
856
  return this.loadTplFiles(typeDir);
975
857
  }
@@ -981,12 +863,12 @@ var Project = class {
981
863
  */
982
864
  async loadTplFiles(dirpath) {
983
865
  const tplFiles = {};
984
- const files = await glob3("*.tpl", { cwd: dirpath });
866
+ const files = await glob2("*.tpl", { cwd: dirpath });
985
867
  for (const filename of files) {
986
- const filepath = path4.join(dirpath, filename);
868
+ const filepath = path3.join(dirpath, filename);
987
869
  const name = filename.slice(0, -4);
988
870
  tplFiles[name] = {
989
- read: () => fs3.readFile(filepath, "utf-8")
871
+ read: () => fs.readFile(filepath, "utf-8")
990
872
  };
991
873
  }
992
874
  return tplFiles;
@@ -1002,23 +884,23 @@ function toTitleCase(str) {
1002
884
  }
1003
885
 
1004
886
  // src/cli/create-package.ts
1005
- import { promises as fs4 } from "node:fs";
1006
- import path5 from "node:path";
887
+ import { promises as fs2 } from "node:fs";
888
+ import path4 from "node:path";
1007
889
  import { build as esbuild } from "esbuild";
1008
890
  async function createPackage(rootProjectDir, options) {
1009
891
  const mode = options?.mode || "production";
1010
892
  process.env.NODE_ENV = mode;
1011
- const rootDir = path5.resolve(rootProjectDir || process.cwd());
1012
- const distDir = path5.join(rootDir, "dist");
893
+ const rootDir = path4.resolve(rootProjectDir || process.cwd());
894
+ const distDir = path4.join(rootDir, "dist");
1013
895
  const target = options?.target || await getDefaultTarget(rootDir);
1014
- const outDir = path5.resolve(options?.out || target || "out");
896
+ const outDir = path4.resolve(options?.out || target || "out");
1015
897
  await build(rootProjectDir, { ssrOnly: true, mode });
1016
898
  await rmDir(outDir);
1017
899
  await makeDir(outDir);
1018
- await copyDir(distDir, path5.resolve(outDir, "dist"));
1019
- const collectionsDir = path5.resolve(rootDir, "collections");
900
+ await copyDir(distDir, path4.resolve(outDir, "dist"));
901
+ const collectionsDir = path4.resolve(rootDir, "collections");
1020
902
  if (await dirExists(collectionsDir)) {
1021
- await copyDir(collectionsDir, path5.join(outDir, "collections"));
903
+ await copyDir(collectionsDir, path4.join(outDir, "collections"));
1022
904
  }
1023
905
  const packageJson = await generatePackageJson(rootDir, options);
1024
906
  if (options?.version && packageJson.dependencies) {
@@ -1033,21 +915,21 @@ async function createPackage(rootProjectDir, options) {
1033
915
  }
1034
916
  }
1035
917
  if (target === "appengine") {
1036
- const appYamlPath = options?.appYaml || path5.join(rootDir, "app.yaml");
918
+ const appYamlPath = options?.appYaml || path4.join(rootDir, "app.yaml");
1037
919
  await onAppEngine({ packageJson, outDir, appYamlPath });
1038
920
  } else if (target === "firebase") {
1039
921
  await onFirebase({ rootDir, packageJson, outDir });
1040
922
  }
1041
- await writeJson(path5.resolve(outDir, "package.json"), packageJson);
923
+ await writeJson(path4.resolve(outDir, "package.json"), packageJson);
1042
924
  console.log("done!");
1043
925
  console.log(`saved package to ${outDir}`);
1044
926
  }
1045
927
  async function getDefaultTarget(rootDir) {
1046
- const firebaseConfigPath = path5.resolve(rootDir, "firebase.json");
928
+ const firebaseConfigPath = path4.resolve(rootDir, "firebase.json");
1047
929
  if (await fileExists(firebaseConfigPath)) {
1048
930
  return "firebase";
1049
931
  }
1050
- const appEngineConfigPath = path5.resolve(rootDir, "app.yaml");
932
+ const appEngineConfigPath = path4.resolve(rootDir, "app.yaml");
1051
933
  if (await fileExists(appEngineConfigPath)) {
1052
934
  return "appengine";
1053
935
  }
@@ -1055,7 +937,7 @@ async function getDefaultTarget(rootDir) {
1055
937
  }
1056
938
  async function generatePackageJson(rootDir, options) {
1057
939
  const packageJson = await loadJson(
1058
- path5.resolve(rootDir, "package.json")
940
+ path4.resolve(rootDir, "package.json")
1059
941
  );
1060
942
  const allDeps = flattenPackageDepsFromMonorepo(rootDir);
1061
943
  packageJson.dependencies ??= {};
@@ -1082,7 +964,7 @@ async function generatePackageJson(rootDir, options) {
1082
964
  async function onAppEngine(options) {
1083
965
  const { outDir, packageJson, appYamlPath } = options;
1084
966
  if (await fileExists(appYamlPath)) {
1085
- await fs4.copyFile(appYamlPath, path5.resolve(outDir, "app.yaml"));
967
+ await fs2.copyFile(appYamlPath, path4.resolve(outDir, "app.yaml"));
1086
968
  }
1087
969
  if (packageJson.scripts?.start) {
1088
970
  packageJson.scripts = { start: packageJson.scripts.start };
@@ -1092,11 +974,11 @@ async function onAppEngine(options) {
1092
974
  }
1093
975
  async function onFirebase(options) {
1094
976
  const { rootDir, outDir, packageJson } = options;
1095
- const outBasename = path5.basename(outDir);
977
+ const outBasename = path4.basename(outDir);
1096
978
  if (outBasename === "functions") {
1097
- const indexTsFile = path5.resolve(rootDir, "index.ts");
979
+ const indexTsFile = path4.resolve(rootDir, "index.ts");
1098
980
  if (await fileExists(indexTsFile)) {
1099
- await bundleTsFile(indexTsFile, path5.resolve(outDir, "index.js"));
981
+ await bundleTsFile(indexTsFile, path4.resolve(outDir, "index.js"));
1100
982
  }
1101
983
  }
1102
984
  if (packageJson.scripts?.start) {
@@ -1121,7 +1003,7 @@ async function bundleTsFile(srcPath, outPath) {
1121
1003
  setup(build2) {
1122
1004
  build2.onResolve({ filter: /.*/ }, (args) => {
1123
1005
  const id = args.path;
1124
- if (id[0] !== "." && !path5.isAbsolute(id)) {
1006
+ if (id[0] !== "." && !path4.isAbsolute(id)) {
1125
1007
  return {
1126
1008
  external: true
1127
1009
  };
@@ -1135,13 +1017,13 @@ async function bundleTsFile(srcPath, outPath) {
1135
1017
  }
1136
1018
 
1137
1019
  // src/cli/dev.ts
1138
- import path12 from "node:path";
1139
- import { fileURLToPath as fileURLToPath3 } from "node:url";
1020
+ import path11 from "node:path";
1021
+ import { fileURLToPath as fileURLToPath4 } from "node:url";
1140
1022
  import cookieParser from "cookie-parser";
1141
1023
  import { default as express } from "express";
1142
1024
  import { dim as dim5 } from "kleur/colors";
1143
1025
  import sirv from "sirv";
1144
- import glob4 from "tiny-glob";
1026
+ import glob3 from "tiny-glob";
1145
1027
 
1146
1028
  // src/middleware/hooks.ts
1147
1029
  function hooksMiddleware() {
@@ -1229,8 +1111,8 @@ function testIsRedirectValid(url) {
1229
1111
  }
1230
1112
 
1231
1113
  // src/render/asset-map/dev-asset-map.ts
1232
- import path6 from "node:path";
1233
- import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
1114
+ import path5 from "node:path";
1115
+ import { searchForWorkspaceRoot } from "vite";
1234
1116
  var DevServerAssetMap = class {
1235
1117
  rootConfig;
1236
1118
  moduleGraph;
@@ -1239,7 +1121,7 @@ var DevServerAssetMap = class {
1239
1121
  this.moduleGraph = moduleGraph;
1240
1122
  }
1241
1123
  async get(src) {
1242
- const file = path6.resolve(this.rootConfig.rootDir, src);
1124
+ const file = path5.resolve(this.rootConfig.rootDir, src);
1243
1125
  const viteModules = this.moduleGraph.getModulesByFile(file);
1244
1126
  if (viteModules && viteModules.size > 0) {
1245
1127
  const [viteModule] = viteModules;
@@ -1257,7 +1139,7 @@ var DevServerAssetMap = class {
1257
1139
  getJsDeps: async () => [assetUrl]
1258
1140
  };
1259
1141
  }
1260
- const workspaceRoot = searchForWorkspaceRoot2(this.rootConfig.rootDir);
1142
+ const workspaceRoot = searchForWorkspaceRoot(this.rootConfig.rootDir);
1261
1143
  if (await directoryContains(workspaceRoot, file)) {
1262
1144
  const assetUrl = `/@fs/${file}`;
1263
1145
  return {
@@ -1271,7 +1153,7 @@ var DevServerAssetMap = class {
1271
1153
  return null;
1272
1154
  }
1273
1155
  filePathToSrc(file) {
1274
- return path6.relative(this.rootConfig.rootDir, file);
1156
+ return path5.relative(this.rootConfig.rootDir, file);
1275
1157
  }
1276
1158
  };
1277
1159
  var DevServerAsset = class _DevServerAsset {
@@ -1313,7 +1195,7 @@ var DevServerAsset = class _DevServerAsset {
1313
1195
  return;
1314
1196
  }
1315
1197
  visited.add(asset.moduleId);
1316
- const parts = path6.parse(asset.assetUrl);
1198
+ const parts = path5.parse(asset.assetUrl);
1317
1199
  if ([".js", ".jsx", ".ts", ".tsx"].includes(parts.ext) && asset.moduleId.includes("/elements/")) {
1318
1200
  urls.add(asset.assetUrl);
1319
1201
  }
@@ -1340,7 +1222,7 @@ var DevServerAsset = class _DevServerAsset {
1340
1222
  }
1341
1223
  visited.add(asset.assetUrl);
1342
1224
  if (asset.src.endsWith(".scss")) {
1343
- const parts = path6.parse(asset.src);
1225
+ const parts = path5.parse(asset.src);
1344
1226
  if (!parts.name.startsWith("_")) {
1345
1227
  urls.add(asset.assetUrl);
1346
1228
  }
@@ -1421,19 +1303,19 @@ function getSessionCookieSecret(rootConfig, rootDir) {
1421
1303
 
1422
1304
  // src/cli/secrets.ts
1423
1305
  import { spawn as spawn3 } from "node:child_process";
1424
- import fs8 from "node:fs";
1425
- import path10 from "node:path";
1306
+ import fs6 from "node:fs";
1307
+ import path9 from "node:path";
1426
1308
  import * as readline from "node:readline";
1427
1309
  import { dim as dim3, green, red, yellow } from "kleur/colors";
1428
1310
 
1429
1311
  // src/secrets/manifest.ts
1430
- import fs5 from "node:fs";
1431
- import path7 from "node:path";
1312
+ import fs3 from "node:fs";
1313
+ import path6 from "node:path";
1432
1314
  var MANIFEST_FILENAME = ".root.secrets.json";
1433
1315
  var GSM_KEY_RE = /^[A-Za-z0-9_-]{1,255}$/;
1434
1316
  var ENV_NAME_RE = /^[A-Za-z0-9_]+$/;
1435
1317
  function manifestPath(dir) {
1436
- return path7.join(dir, MANIFEST_FILENAME);
1318
+ return path6.join(dir, MANIFEST_FILENAME);
1437
1319
  }
1438
1320
  function isValidEnvName(name) {
1439
1321
  return ENV_NAME_RE.test(name);
@@ -1441,7 +1323,7 @@ function isValidEnvName(name) {
1441
1323
  async function readManifest(filePath) {
1442
1324
  let raw;
1443
1325
  try {
1444
- raw = await fs5.promises.readFile(filePath, "utf8");
1326
+ raw = await fs3.promises.readFile(filePath, "utf8");
1445
1327
  } catch (err) {
1446
1328
  if (err.code === "ENOENT") {
1447
1329
  return null;
@@ -1468,8 +1350,8 @@ async function writeManifest(filePath, manifest) {
1468
1350
  ...manifest.import ? { import: manifest.import } : {},
1469
1351
  secrets: sortedSecrets
1470
1352
  };
1471
- await fs5.promises.mkdir(path7.dirname(filePath), { recursive: true });
1472
- await fs5.promises.writeFile(
1353
+ await fs3.promises.mkdir(path6.dirname(filePath), { recursive: true });
1354
+ await fs3.promises.writeFile(
1473
1355
  filePath,
1474
1356
  JSON.stringify(ordered, null, 2) + "\n",
1475
1357
  "utf8"
@@ -1497,7 +1379,7 @@ async function resolveManagedKeys(rootDir) {
1497
1379
  }
1498
1380
  let shared;
1499
1381
  if (site.import) {
1500
- const sharedPath = path7.resolve(rootDir, site.import.manifest);
1382
+ const sharedPath = path6.resolve(rootDir, site.import.manifest);
1501
1383
  const loaded = await readManifest(sharedPath);
1502
1384
  if (!loaded) {
1503
1385
  throw new Error(`imported manifest not found: ${sharedPath}`);
@@ -1624,16 +1506,16 @@ function validateManifest(value, filePath) {
1624
1506
 
1625
1507
  // src/secrets/secrets.ts
1626
1508
  import { spawn as spawn2 } from "node:child_process";
1627
- import fs7 from "node:fs";
1628
- import path9 from "node:path";
1509
+ import fs5 from "node:fs";
1510
+ import path8 from "node:path";
1629
1511
 
1630
1512
  // src/secrets/env-file.ts
1631
- import fs6 from "node:fs";
1632
- import path8 from "node:path";
1513
+ import fs4 from "node:fs";
1514
+ import path7 from "node:path";
1633
1515
  import dotenv from "dotenv";
1634
1516
  async function readEnvFile(envPath2) {
1635
1517
  try {
1636
- return await fs6.promises.readFile(envPath2, "utf8");
1518
+ return await fs4.promises.readFile(envPath2, "utf8");
1637
1519
  } catch (err) {
1638
1520
  if (err.code === "ENOENT") {
1639
1521
  return "";
@@ -1642,11 +1524,11 @@ async function readEnvFile(envPath2) {
1642
1524
  }
1643
1525
  }
1644
1526
  async function writeEnvFile(envPath2, content) {
1645
- const dir = path8.dirname(envPath2);
1646
- await fs6.promises.mkdir(dir, { recursive: true });
1647
- const tmp = path8.join(dir, `.env.tmp-${process.pid}-${Date.now()}`);
1648
- await fs6.promises.writeFile(tmp, content, "utf8");
1649
- await fs6.promises.rename(tmp, envPath2);
1527
+ const dir = path7.dirname(envPath2);
1528
+ await fs4.promises.mkdir(dir, { recursive: true });
1529
+ const tmp = path7.join(dir, `.env.tmp-${process.pid}-${Date.now()}`);
1530
+ await fs4.promises.writeFile(tmp, content, "utf8");
1531
+ await fs4.promises.rename(tmp, envPath2);
1650
1532
  }
1651
1533
  function parseEnv(content) {
1652
1534
  return dotenv.parse(content);
@@ -1864,10 +1746,10 @@ function hashValue(salt, value) {
1864
1746
  // src/secrets/secrets.ts
1865
1747
  var STATE_FILENAME = "secrets-sync.json";
1866
1748
  function localStatePath(rootDir) {
1867
- return path9.join(rootDir, ".root", STATE_FILENAME);
1749
+ return path8.join(rootDir, ".root", STATE_FILENAME);
1868
1750
  }
1869
1751
  function envPath(rootDir) {
1870
- return path9.join(rootDir, ".env");
1752
+ return path8.join(rootDir, ".env");
1871
1753
  }
1872
1754
  var inFlight = /* @__PURE__ */ new Map();
1873
1755
  function syncSecrets(options) {
@@ -2093,7 +1975,7 @@ async function pushEnvToSecrets(options) {
2093
1975
  };
2094
1976
  }
2095
1977
  async function sharedImportedNames(rootDir, manifestFilePath) {
2096
- if (path9.resolve(manifestFilePath) !== path9.resolve(manifestPath(rootDir))) {
1978
+ if (path8.resolve(manifestFilePath) !== path8.resolve(manifestPath(rootDir))) {
2097
1979
  return /* @__PURE__ */ new Set();
2098
1980
  }
2099
1981
  try {
@@ -2156,7 +2038,7 @@ function isSyncDisabledByEnv() {
2156
2038
  }
2157
2039
  async function readLocalState(rootDir) {
2158
2040
  try {
2159
- const raw = await fs7.promises.readFile(localStatePath(rootDir), "utf8");
2041
+ const raw = await fs5.promises.readFile(localStatePath(rootDir), "utf8");
2160
2042
  const parsed = JSON.parse(raw);
2161
2043
  if (parsed && typeof parsed === "object" && typeof parsed.salt === "string" && parsed.secrets && typeof parsed.secrets === "object") {
2162
2044
  return {
@@ -2170,8 +2052,8 @@ async function readLocalState(rootDir) {
2170
2052
  }
2171
2053
  async function writeLocalState(rootDir, state) {
2172
2054
  const file = localStatePath(rootDir);
2173
- await fs7.promises.mkdir(path9.dirname(file), { recursive: true });
2174
- await fs7.promises.writeFile(
2055
+ await fs5.promises.mkdir(path8.dirname(file), { recursive: true });
2056
+ await fs5.promises.writeFile(
2175
2057
  file,
2176
2058
  JSON.stringify(state, null, 2) + "\n",
2177
2059
  "utf8"
@@ -2237,7 +2119,7 @@ function registerSecretsCommands(program) {
2237
2119
  }
2238
2120
  async function secretsInit(opts) {
2239
2121
  const rootDir = process.cwd();
2240
- const target = opts.manifest ? path10.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2122
+ const target = opts.manifest ? path9.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2241
2123
  if (await readManifest(target)) {
2242
2124
  console.log(
2243
2125
  `${BAR} ${yellow("secrets:")} manifest already exists at ${rel(rootDir, target)}`
@@ -2270,7 +2152,7 @@ async function secretsInit(opts) {
2270
2152
  }
2271
2153
  async function secretsSet(name, opts) {
2272
2154
  const rootDir = process.cwd();
2273
- const manifestFilePath = opts.manifest ? path10.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2155
+ const manifestFilePath = opts.manifest ? path9.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2274
2156
  const secretValue = await readSecretValue(name);
2275
2157
  if (!secretValue) {
2276
2158
  throw new Error("no value provided on stdin");
@@ -2283,7 +2165,7 @@ async function secretsSet(name, opts) {
2283
2165
  }
2284
2166
  async function secretsRm(name, opts) {
2285
2167
  const rootDir = process.cwd();
2286
- const manifestFilePath = opts.manifest ? path10.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2168
+ const manifestFilePath = opts.manifest ? path9.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2287
2169
  await removeSecret({ rootDir, manifestFilePath, name });
2288
2170
  console.log(`${BAR} ${green("secrets:")} removed ${name}`);
2289
2171
  console.log(
@@ -2292,7 +2174,7 @@ async function secretsRm(name, opts) {
2292
2174
  }
2293
2175
  async function secretsPush(opts) {
2294
2176
  const rootDir = process.cwd();
2295
- const manifestFilePath = opts.manifest ? path10.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2177
+ const manifestFilePath = opts.manifest ? path9.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
2296
2178
  const only = opts.keys ? opts.keys.split(",").map((k) => k.trim()).filter(Boolean) : void 0;
2297
2179
  const confirm = opts.yes ? void 0 : async (names, gsmKey) => {
2298
2180
  if (!process.stdin.isTTY) {
@@ -2470,10 +2352,10 @@ function printPushResult(result, rootDir, manifestFilePath) {
2470
2352
  }
2471
2353
  async function ensureRootGitignored(rootDir) {
2472
2354
  const gitRoot = await gitToplevel(rootDir) ?? rootDir;
2473
- const gitignore = path10.join(gitRoot, ".gitignore");
2355
+ const gitignore = path9.join(gitRoot, ".gitignore");
2474
2356
  let content = "";
2475
2357
  try {
2476
- content = await fs8.promises.readFile(gitignore, "utf8");
2358
+ content = await fs6.promises.readFile(gitignore, "utf8");
2477
2359
  } catch {
2478
2360
  }
2479
2361
  const lines = content.split(/\r?\n/).map((line) => line.trim());
@@ -2481,7 +2363,7 @@ async function ensureRootGitignored(rootDir) {
2481
2363
  return false;
2482
2364
  }
2483
2365
  const prefix = content && !content.endsWith("\n") ? "\n" : "";
2484
- await fs8.promises.writeFile(gitignore, `${content}${prefix}.root/
2366
+ await fs6.promises.writeFile(gitignore, `${content}${prefix}.root/
2485
2367
  `, "utf8");
2486
2368
  return true;
2487
2369
  }
@@ -2609,7 +2491,7 @@ function withTimeout(promise, ms) {
2609
2491
  });
2610
2492
  }
2611
2493
  function rel(rootDir, filePath) {
2612
- return path10.relative(rootDir, filePath) || path10.basename(filePath);
2494
+ return path9.relative(rootDir, filePath) || path9.basename(filePath);
2613
2495
  }
2614
2496
  function firstLine(text) {
2615
2497
  return String(text).split("\n")[0];
@@ -2626,8 +2508,8 @@ function action(fn) {
2626
2508
  }
2627
2509
 
2628
2510
  // src/cli/startup/startup-tasks.ts
2629
- import os from "node:os";
2630
- import path11 from "node:path";
2511
+ import os2 from "node:os";
2512
+ import path10 from "node:path";
2631
2513
 
2632
2514
  // src/cli/startup/check-version.ts
2633
2515
  import { dim as dim4, green as green2, yellow as yellow2 } from "kleur/colors";
@@ -2710,7 +2592,7 @@ function printUpdateNotice(current, latest) {
2710
2592
 
2711
2593
  // src/cli/startup/startup-tasks.ts
2712
2594
  var STARTUP_TASKS = [checkVersionTask];
2713
- var STATE_FILE = path11.join(os.homedir(), ".root", "startup-tasks.json");
2595
+ var STATE_FILE = path10.join(os2.homedir(), ".root", "startup-tasks.json");
2714
2596
  async function runStartupTasks(ctx) {
2715
2597
  try {
2716
2598
  const state = await readState();
@@ -2761,13 +2643,13 @@ async function writeState(state) {
2761
2643
  }
2762
2644
 
2763
2645
  // src/cli/dev.ts
2764
- var __dirname3 = path12.dirname(fileURLToPath3(import.meta.url));
2646
+ var __dirname4 = path11.dirname(fileURLToPath4(import.meta.url));
2765
2647
  var DEV_SERVER_404_LOG_IGNORE_PATHS = /* @__PURE__ */ new Set([
2766
2648
  "/.well-known/appspecific/com.chrome.devtools.json"
2767
2649
  ]);
2768
2650
  async function dev(rootProjectDir, options) {
2769
2651
  process.env.NODE_ENV = "development";
2770
- const rootDir = path12.resolve(rootProjectDir || process.cwd());
2652
+ const rootDir = path11.resolve(rootProjectDir || process.cwd());
2771
2653
  const defaultPort = parseInt(process.env.PORT || "4007");
2772
2654
  const host = options?.host || "localhost";
2773
2655
  const port = await findOpenPort(defaultPort, defaultPort + 10);
@@ -2795,7 +2677,7 @@ async function dev(rootProjectDir, options) {
2795
2677
  "rootConfigDependencies"
2796
2678
  );
2797
2679
  const dependencies = [
2798
- path12.resolve(rootDir, "root.config.ts"),
2680
+ path11.resolve(rootDir, "root.config.ts"),
2799
2681
  ...rootConfigDependencies
2800
2682
  ];
2801
2683
  viteServer.watcher.add(dependencies);
@@ -2823,7 +2705,7 @@ ${dim5("\u2503")} root.config.ts changed. restarting server...`
2823
2705
  await start2();
2824
2706
  }
2825
2707
  async function createDevServer(options) {
2826
- const rootDir = path12.resolve(options?.rootDir || process.cwd());
2708
+ const rootDir = path11.resolve(options?.rootDir || process.cwd());
2827
2709
  const { rootConfig, dependencies } = await loadRootConfigWithDeps(rootDir, {
2828
2710
  command: "dev"
2829
2711
  });
@@ -2838,6 +2720,7 @@ async function createDevServer(options) {
2838
2720
  });
2839
2721
  server.set("viteServer", viteServer);
2840
2722
  server.use(rootProjectMiddleware({ rootConfig }));
2723
+ server.use(securityHeadersMiddleware({ rootConfig }));
2841
2724
  server.use(viteMiddleware);
2842
2725
  server.use(hooksMiddleware());
2843
2726
  const sessionCookieSecret = getSessionCookieSecret(rootConfig, rootDir);
@@ -2859,7 +2742,7 @@ async function createDevServer(options) {
2859
2742
  if (rootConfig.server?.headers) {
2860
2743
  server.use(headersMiddleware({ rootConfig }));
2861
2744
  }
2862
- const publicDir = path12.join(rootDir, "public");
2745
+ const publicDir = path11.join(rootDir, "public");
2863
2746
  if (await dirExists(publicDir)) {
2864
2747
  server.use(rootPublicDirMiddleware({ publicDir, viteServer }));
2865
2748
  }
@@ -2887,10 +2770,10 @@ async function createViteMiddleware(options) {
2887
2770
  return sourceFile.relPath;
2888
2771
  });
2889
2772
  const bundleScripts = [];
2890
- if (await isDirectory(path12.join(rootDir, "bundles"))) {
2891
- const bundleFiles = await glob4("bundles/*", { cwd: rootDir });
2773
+ if (await isDirectory(path11.join(rootDir, "bundles"))) {
2774
+ const bundleFiles = await glob3("bundles/*", { cwd: rootDir });
2892
2775
  bundleFiles.forEach((file) => {
2893
- const parts = path12.parse(file);
2776
+ const parts = path11.parse(file);
2894
2777
  if (isJsFile(parts.base)) {
2895
2778
  bundleScripts.push(file);
2896
2779
  }
@@ -2907,7 +2790,7 @@ async function createViteMiddleware(options) {
2907
2790
  optimizeDeps
2908
2791
  });
2909
2792
  function isInElementsDir(changedFilePath) {
2910
- const filePath = path12.resolve(changedFilePath);
2793
+ const filePath = path11.resolve(changedFilePath);
2911
2794
  const elementsDirs = getElementsDirs(rootConfig, pods);
2912
2795
  return elementsDirs.some((dirPath) => filePath.startsWith(dirPath));
2913
2796
  }
@@ -2926,7 +2809,7 @@ async function createViteMiddleware(options) {
2926
2809
  const viteMiddleware = async (req, res, next) => {
2927
2810
  try {
2928
2811
  req.viteServer = viteServer;
2929
- const renderModulePath = path12.resolve(__dirname3, "./render.js");
2812
+ const renderModulePath = path11.resolve(__dirname4, "./render.js");
2930
2813
  const render = await viteServer.ssrLoadModule(
2931
2814
  renderModulePath
2932
2815
  );
@@ -2950,7 +2833,7 @@ function rootPublicDirMiddleware(options) {
2950
2833
  handler = sirv(publicDir, sirvOptions);
2951
2834
  }, 1e3);
2952
2835
  function isInPublicDir(changedFilePath) {
2953
- const filePath = path12.resolve(changedFilePath);
2836
+ const filePath = path11.resolve(changedFilePath);
2954
2837
  return filePath.startsWith(publicDir);
2955
2838
  }
2956
2839
  const watcher = options.viteServer.watcher;
@@ -2982,7 +2865,7 @@ function rootDevServer404Middleware() {
2982
2865
  }
2983
2866
  if (req.renderer) {
2984
2867
  const url = req.path;
2985
- const ext = path12.extname(url);
2868
+ const ext = path11.extname(url);
2986
2869
  if (!ext) {
2987
2870
  const renderer = req.renderer;
2988
2871
  const data = await renderer.renderDevServer404(req);
@@ -3000,7 +2883,7 @@ function rootDevServer500Middleware() {
3000
2883
  console.error(String(err.stack || err));
3001
2884
  if (req.renderer) {
3002
2885
  const url = req.path;
3003
- const ext = path12.extname(url);
2886
+ const ext = path11.extname(url);
3004
2887
  if (!ext) {
3005
2888
  const renderer = req.renderer;
3006
2889
  const data = await renderer.renderDevServer500(req, err);
@@ -3026,7 +2909,7 @@ function debounce(fn, timeout) {
3026
2909
 
3027
2910
  // src/cli/gae-deploy.ts
3028
2911
  import { execSync } from "node:child_process";
3029
- import fs9 from "node:fs";
2912
+ import fs7 from "node:fs";
3030
2913
  import yaml from "js-yaml";
3031
2914
  async function gaeDeploy(appDir, options) {
3032
2915
  if (!appDir) {
@@ -3040,10 +2923,10 @@ async function gaeDeploy(appDir, options) {
3040
2923
  }
3041
2924
  process.chdir(appDir);
3042
2925
  const appYamlPath = "app.yaml";
3043
- if (!fs9.existsSync(appYamlPath)) {
2926
+ if (!fs7.existsSync(appYamlPath)) {
3044
2927
  throw new Error(`[gae-deplopy] Missing: ${appYamlPath}`);
3045
2928
  }
3046
- const appYaml = yaml.load(fs9.readFileSync(appYamlPath, "utf8"));
2929
+ const appYaml = yaml.load(fs7.readFileSync(appYamlPath, "utf8"));
3047
2930
  const service = appYaml.service;
3048
2931
  if (!service) {
3049
2932
  throw new Error(
@@ -3069,7 +2952,7 @@ async function gaeDeploy(appDir, options) {
3069
2952
  { stdio: "inherit" }
3070
2953
  );
3071
2954
  if (backupAppYaml) {
3072
- fs9.copyFileSync(backupAppYaml, "app.yaml");
2955
+ fs7.copyFileSync(backupAppYaml, "app.yaml");
3073
2956
  }
3074
2957
  if (options?.healthcheckUrl) {
3075
2958
  const healthcheckPassed = await testHealth(
@@ -3156,8 +3039,8 @@ function testIsEnvPlaceholder(envValue) {
3156
3039
  }
3157
3040
  function updateAppYamlEnv(appYamlPath, appYaml) {
3158
3041
  const backupAppYaml = `${appYamlPath}.bak`;
3159
- fs9.copyFileSync(appYamlPath, backupAppYaml);
3160
- let content = fs9.readFileSync(appYamlPath, "utf8");
3042
+ fs7.copyFileSync(appYamlPath, backupAppYaml);
3043
+ let content = fs7.readFileSync(appYamlPath, "utf8");
3161
3044
  const envVars = appYaml.env_variables;
3162
3045
  Object.entries(envVars).forEach(([envVar, envValue]) => {
3163
3046
  if (testIsEnvPlaceholder(envValue)) {
@@ -3170,7 +3053,7 @@ function updateAppYamlEnv(appYamlPath, appYaml) {
3170
3053
  }
3171
3054
  }
3172
3055
  });
3173
- fs9.writeFileSync(appYamlPath, content, "utf8");
3056
+ fs7.writeFileSync(appYamlPath, content, "utf8");
3174
3057
  return backupAppYaml;
3175
3058
  }
3176
3059
  function getTimestamp() {
@@ -3194,15 +3077,14 @@ function testManagedVersion(service, appInfo, prefix) {
3194
3077
  }
3195
3078
 
3196
3079
  // src/cli/preview.ts
3197
- import path13 from "node:path";
3198
- import compression from "compression";
3080
+ import path12 from "node:path";
3199
3081
  import cookieParser2 from "cookie-parser";
3200
3082
  import { default as express2 } from "express";
3201
3083
  import { dim as dim6 } from "kleur/colors";
3202
3084
  import sirv2 from "sirv";
3203
3085
  async function preview(rootProjectDir, options) {
3204
3086
  process.env.NODE_ENV = "development";
3205
- const rootDir = path13.resolve(rootProjectDir || process.cwd());
3087
+ const rootDir = path12.resolve(rootProjectDir || process.cwd());
3206
3088
  const server = await createPreviewServer({ rootDir });
3207
3089
  const port = parseInt(process.env.PORT || "4007");
3208
3090
  const host = options?.host || "localhost";
@@ -3216,11 +3098,12 @@ async function preview(rootProjectDir, options) {
3216
3098
  async function createPreviewServer(options) {
3217
3099
  const rootDir = options.rootDir;
3218
3100
  const rootConfig = await loadBundledConfig(rootDir, { command: "preview" });
3219
- const distDir = path13.join(rootDir, "dist");
3101
+ const distDir = path12.join(rootDir, "dist");
3220
3102
  const server = express2();
3221
3103
  server.disable("x-powered-by");
3222
- server.use(compression());
3104
+ server.use(compressionMiddleware());
3223
3105
  server.use(rootProjectMiddleware({ rootConfig }));
3106
+ server.use(securityHeadersMiddleware({ rootConfig }));
3224
3107
  server.use(await rootPreviewRendererMiddleware({ rootConfig, distDir }));
3225
3108
  server.use(hooksMiddleware());
3226
3109
  const sessionCookieSecret = getSessionCookieSecret(rootConfig, rootDir);
@@ -3242,7 +3125,7 @@ async function createPreviewServer(options) {
3242
3125
  if (rootConfig.server?.headers) {
3243
3126
  server.use(headersMiddleware({ rootConfig }));
3244
3127
  }
3245
- const publicDir = path13.join(distDir, "html");
3128
+ const publicDir = path12.join(distDir, "html");
3246
3129
  server.use(sirv2(publicDir, { dev: false }));
3247
3130
  server.use(trailingSlashMiddleware({ rootConfig }));
3248
3131
  server.use(rootPreviewServerMiddleware());
@@ -3261,14 +3144,14 @@ async function createPreviewServer(options) {
3261
3144
  }
3262
3145
  async function rootPreviewRendererMiddleware(options) {
3263
3146
  const { distDir, rootConfig } = options;
3264
- const render = await import(path13.join(distDir, "server/render.js"));
3265
- const manifestPath2 = path13.join(distDir, ".root/manifest.json");
3147
+ const render = await import(path12.join(distDir, "server/render.js"));
3148
+ const manifestPath2 = path12.join(distDir, ".root/manifest.json");
3266
3149
  if (!await fileExists(manifestPath2)) {
3267
3150
  throw new Error(
3268
3151
  `could not find ${manifestPath2}. run \`root build\` before \`root preview\`.`
3269
3152
  );
3270
3153
  }
3271
- const elementGraphJsonPath = path13.join(distDir, ".root/elements.json");
3154
+ const elementGraphJsonPath = path12.join(distDir, ".root/elements.json");
3272
3155
  if (!await fileExists(elementGraphJsonPath)) {
3273
3156
  throw new Error(
3274
3157
  `could not find ${elementGraphJsonPath}. run \`root build\` before \`root preview\`.`
@@ -3308,7 +3191,7 @@ function rootPreviewServer404Middleware() {
3308
3191
  console.error(`\u2753 404 ${req.originalUrl}`);
3309
3192
  if (req.renderer) {
3310
3193
  const url = req.path;
3311
- const ext = path13.extname(url);
3194
+ const ext = path12.extname(url);
3312
3195
  if (!ext) {
3313
3196
  const renderer = req.renderer;
3314
3197
  const data = await renderer.render404({ currentPath: url });
@@ -3326,7 +3209,7 @@ function rootPreviewServer500Middleware() {
3326
3209
  console.error(String(err.stack || err));
3327
3210
  if (req.renderer) {
3328
3211
  const url = req.path;
3329
- const ext = path13.extname(url);
3212
+ const ext = path12.extname(url);
3330
3213
  if (!ext) {
3331
3214
  const renderer = req.renderer;
3332
3215
  const data = await renderer.renderDevServer500(req, err);
@@ -3340,15 +3223,14 @@ function rootPreviewServer500Middleware() {
3340
3223
  }
3341
3224
 
3342
3225
  // src/cli/start.ts
3343
- import path14 from "node:path";
3344
- import compression2 from "compression";
3226
+ import path13 from "node:path";
3345
3227
  import cookieParser3 from "cookie-parser";
3346
3228
  import { default as express3 } from "express";
3347
3229
  import { dim as dim7 } from "kleur/colors";
3348
3230
  import sirv3 from "sirv";
3349
3231
  async function start(rootProjectDir, options) {
3350
3232
  process.env.NODE_ENV = "production";
3351
- const rootDir = path14.resolve(rootProjectDir || process.cwd());
3233
+ const rootDir = path13.resolve(rootProjectDir || process.cwd());
3352
3234
  const server = await createProdServer({ rootDir });
3353
3235
  const port = parseInt(process.env.PORT || "4007");
3354
3236
  const host = options?.host || "localhost";
@@ -3362,11 +3244,12 @@ async function start(rootProjectDir, options) {
3362
3244
  async function createProdServer(options) {
3363
3245
  const rootDir = options.rootDir;
3364
3246
  const rootConfig = await loadBundledConfig(rootDir, { command: "start" });
3365
- const distDir = path14.join(rootDir, "dist");
3247
+ const distDir = path13.join(rootDir, "dist");
3366
3248
  const server = express3();
3367
3249
  server.disable("x-powered-by");
3368
- server.use(compression2());
3250
+ server.use(compressionMiddleware());
3369
3251
  server.use(rootProjectMiddleware({ rootConfig }));
3252
+ server.use(securityHeadersMiddleware({ rootConfig }));
3370
3253
  server.use(await rootProdRendererMiddleware({ rootConfig, distDir }));
3371
3254
  server.use(hooksMiddleware());
3372
3255
  const sessionCookieSecret = getSessionCookieSecret(rootConfig, rootDir);
@@ -3388,7 +3271,7 @@ async function createProdServer(options) {
3388
3271
  if (rootConfig.server?.headers) {
3389
3272
  server.use(headersMiddleware({ rootConfig }));
3390
3273
  }
3391
- const publicDir = path14.join(distDir, "html");
3274
+ const publicDir = path13.join(distDir, "html");
3392
3275
  server.use(sirv3(publicDir, { dev: false }));
3393
3276
  server.use(trailingSlashMiddleware({ rootConfig }));
3394
3277
  server.use(rootProdServerMiddleware());
@@ -3407,14 +3290,14 @@ async function createProdServer(options) {
3407
3290
  }
3408
3291
  async function rootProdRendererMiddleware(options) {
3409
3292
  const { distDir, rootConfig } = options;
3410
- const render = await import(path14.join(distDir, "server/render.js"));
3411
- const manifestPath2 = path14.join(distDir, ".root/manifest.json");
3293
+ const render = await import(path13.join(distDir, "server/render.js"));
3294
+ const manifestPath2 = path13.join(distDir, ".root/manifest.json");
3412
3295
  if (!await fileExists(manifestPath2)) {
3413
3296
  throw new Error(
3414
3297
  `could not find ${manifestPath2}. run \`root build\` before \`root start\`.`
3415
3298
  );
3416
3299
  }
3417
- const elementGraphJsonPath = path14.join(distDir, ".root/elements.json");
3300
+ const elementGraphJsonPath = path13.join(distDir, ".root/elements.json");
3418
3301
  if (!await fileExists(elementGraphJsonPath)) {
3419
3302
  throw new Error(
3420
3303
  `could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
@@ -3454,7 +3337,7 @@ function rootProdServer404Middleware() {
3454
3337
  console.error(`\u2753 404 ${req.originalUrl}`);
3455
3338
  if (req.renderer) {
3456
3339
  const url = req.path;
3457
- const ext = path14.extname(url);
3340
+ const ext = path13.extname(url);
3458
3341
  if (!ext) {
3459
3342
  const renderer = req.renderer;
3460
3343
  const data = await renderer.render404({ currentPath: url });
@@ -3472,7 +3355,7 @@ function rootProdServer500Middleware() {
3472
3355
  console.error(String(err.stack || err));
3473
3356
  if (req.renderer) {
3474
3357
  const url = req.path;
3475
- const ext = path14.extname(url);
3358
+ const ext = path13.extname(url);
3476
3359
  if (!ext) {
3477
3360
  const renderer = req.renderer;
3478
3361
  const data = await renderer.renderError(err);
@@ -3513,6 +3396,9 @@ var CliRunner = class {
3513
3396
  "-c, --concurrency <num>",
3514
3397
  "number of files to build concurrently",
3515
3398
  "10"
3399
+ ).option(
3400
+ "--threads [num]",
3401
+ 'renders pages using worker threads; pass a number for exactly N workers, or omit the value (or pass "auto") to pick based on cpu cores and page count'
3516
3402
  ).option(
3517
3403
  "--filter <urlPathRegex>",
3518
3404
  'builds the url paths that match the given regex, e.g. "/products/.*"',
@@ -3579,4 +3465,4 @@ export {
3579
3465
  createProdServer,
3580
3466
  CliRunner
3581
3467
  };
3582
- //# sourceMappingURL=chunk-3EFECH2D.js.map
3468
+ //# sourceMappingURL=chunk-E4F6CMO3.js.map