@blinkk/root 3.1.1 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-E4F6CMO3.js → chunk-GK3TDYUY.js} +369 -139
- package/dist/chunk-GK3TDYUY.js.map +7 -0
- package/dist/cli/build-progress.d.ts +82 -0
- package/dist/cli/build.d.ts +8 -0
- package/dist/cli.js +1 -1
- package/dist/core/config.d.ts +41 -3
- package/dist/core.js.map +2 -2
- package/dist/functions.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-E4F6CMO3.js.map +0 -7
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
} from "./chunk-TM6QRBGS.js";
|
|
48
48
|
|
|
49
49
|
// src/cli/cli.ts
|
|
50
|
-
import { Command, InvalidArgumentError } from "commander";
|
|
50
|
+
import { Command, InvalidArgumentError, Option } from "commander";
|
|
51
51
|
import { bgGreen, black } from "kleur/colors";
|
|
52
52
|
|
|
53
53
|
// src/cli/build.ts
|
|
@@ -55,7 +55,7 @@ import os from "node:os";
|
|
|
55
55
|
import path2 from "node:path";
|
|
56
56
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
57
57
|
import fsExtra from "fs-extra";
|
|
58
|
-
import { dim as
|
|
58
|
+
import { dim as dim3, cyan as cyan2 } from "kleur/colors";
|
|
59
59
|
import glob from "tiny-glob";
|
|
60
60
|
import { build as viteBuild } from "vite";
|
|
61
61
|
|
|
@@ -142,11 +142,179 @@ async function batchAsyncCalls(data, concurrency, asyncFunction) {
|
|
|
142
142
|
return result;
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
// src/cli/build-progress.ts
|
|
146
|
+
import { cyan, dim as dim2, green } from "kleur/colors";
|
|
147
|
+
function parseBuildLogMode(value) {
|
|
148
|
+
if (value === void 0 || value === null || value === "") {
|
|
149
|
+
return "progress";
|
|
150
|
+
}
|
|
151
|
+
if (value === "progress" || value === "verbose" || value === "quiet") {
|
|
152
|
+
return value;
|
|
153
|
+
}
|
|
154
|
+
throw new Error(
|
|
155
|
+
`invalid --log value: "${value}" (expected "progress", "verbose", or "quiet")`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
function formatBytes(bytes) {
|
|
159
|
+
const k = 1024;
|
|
160
|
+
if (bytes < k) {
|
|
161
|
+
return (bytes / k).toFixed(2) + " kB";
|
|
162
|
+
}
|
|
163
|
+
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
164
|
+
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
165
|
+
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
166
|
+
}
|
|
167
|
+
function formatDuration(ms) {
|
|
168
|
+
const secs = ms / 1e3;
|
|
169
|
+
if (secs < 60) {
|
|
170
|
+
return `${secs.toFixed(1)}s`;
|
|
171
|
+
}
|
|
172
|
+
const mins = Math.floor(secs / 60);
|
|
173
|
+
const rem = Math.round(secs - mins * 60);
|
|
174
|
+
return `${mins}m${String(rem).padStart(2, "0")}s`;
|
|
175
|
+
}
|
|
176
|
+
var BAR_WIDTH = 20;
|
|
177
|
+
var BuildProgress = class {
|
|
178
|
+
total;
|
|
179
|
+
mode;
|
|
180
|
+
itemLabel;
|
|
181
|
+
outputDirLabel;
|
|
182
|
+
stream;
|
|
183
|
+
now;
|
|
184
|
+
intervalMs;
|
|
185
|
+
summaryTopN;
|
|
186
|
+
isTTY;
|
|
187
|
+
startedAt;
|
|
188
|
+
completed = 0;
|
|
189
|
+
totalBytes = 0;
|
|
190
|
+
files = [];
|
|
191
|
+
lastPrintAt = 0;
|
|
192
|
+
lastMilestone = 0;
|
|
193
|
+
ttyLineActive = false;
|
|
194
|
+
done = false;
|
|
195
|
+
constructor(options) {
|
|
196
|
+
this.total = options.total;
|
|
197
|
+
this.mode = options.mode;
|
|
198
|
+
this.itemLabel = options.itemLabel ?? "pages";
|
|
199
|
+
this.outputDirLabel = options.outputDirLabel ?? "";
|
|
200
|
+
this.stream = options.stream ?? process.stdout;
|
|
201
|
+
this.now = options.now ?? Date.now;
|
|
202
|
+
this.isTTY = !!this.stream.isTTY;
|
|
203
|
+
this.intervalMs = options.intervalMs ?? (this.isTTY ? 80 : 5e3);
|
|
204
|
+
this.summaryTopN = options.summaryTopN ?? 5;
|
|
205
|
+
this.startedAt = this.now();
|
|
206
|
+
}
|
|
207
|
+
/** Records a completed output file. */
|
|
208
|
+
add(outputFile, sizeBytes) {
|
|
209
|
+
this.completed += 1;
|
|
210
|
+
this.totalBytes += sizeBytes;
|
|
211
|
+
this.files.push({ path: outputFile, size: sizeBytes });
|
|
212
|
+
if (this.mode === "verbose") {
|
|
213
|
+
const paddedSize = formatBytes(sizeBytes).padStart(9, " ");
|
|
214
|
+
this.println(
|
|
215
|
+
` ${dim2(paddedSize)} ${dim2(this.outputDirLabel)}${cyan(outputFile)}`
|
|
216
|
+
);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (this.mode === "progress") {
|
|
220
|
+
this.maybePrintProgress();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
/** Clears any in-place progress line (call before printing errors). */
|
|
224
|
+
abort() {
|
|
225
|
+
this.clearTtyLine();
|
|
226
|
+
this.done = true;
|
|
227
|
+
}
|
|
228
|
+
/** Prints the final summary. */
|
|
229
|
+
finish() {
|
|
230
|
+
if (this.done) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
this.done = true;
|
|
234
|
+
this.clearTtyLine();
|
|
235
|
+
const elapsed = formatDuration(this.now() - this.startedAt);
|
|
236
|
+
const summary = `${this.completed} ${this.itemLabel} (${formatBytes(
|
|
237
|
+
this.totalBytes
|
|
238
|
+
)}) in ${elapsed}`;
|
|
239
|
+
this.println(` ${green("\u2713")} ${summary}`);
|
|
240
|
+
if (this.mode === "progress" && this.summaryTopN > 0) {
|
|
241
|
+
const largest = [...this.files].sort((a, b) => b.size - a.size).slice(0, this.summaryTopN);
|
|
242
|
+
if (largest.length > 0) {
|
|
243
|
+
this.println(` ${dim2(`largest ${this.itemLabel}:`)}`);
|
|
244
|
+
for (const file of largest) {
|
|
245
|
+
const paddedSize = formatBytes(file.size).padStart(9, " ");
|
|
246
|
+
this.println(
|
|
247
|
+
` ${dim2(paddedSize)} ${dim2(this.outputDirLabel)}${cyan(
|
|
248
|
+
file.path
|
|
249
|
+
)}`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
maybePrintProgress() {
|
|
256
|
+
const now = this.now();
|
|
257
|
+
if (this.isTTY) {
|
|
258
|
+
if (now - this.lastPrintAt < this.intervalMs) {
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
this.lastPrintAt = now;
|
|
262
|
+
this.renderTtyLine(now);
|
|
263
|
+
return;
|
|
264
|
+
}
|
|
265
|
+
const milestone = Math.floor(this.completed / this.total * 10);
|
|
266
|
+
if (milestone <= this.lastMilestone || this.completed === this.total) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
if (now - this.lastPrintAt < this.intervalMs) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.lastMilestone = milestone;
|
|
273
|
+
this.lastPrintAt = now;
|
|
274
|
+
const pct = Math.floor(this.completed / this.total * 100);
|
|
275
|
+
this.println(
|
|
276
|
+
` ${this.completed}/${this.total} ${this.itemLabel} (${pct}%) \xB7 ${formatBytes(this.totalBytes)} \xB7 ${formatDuration(now - this.startedAt)}${this.eta(now)}`
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
renderTtyLine(now) {
|
|
280
|
+
const ratio = this.total > 0 ? this.completed / this.total : 0;
|
|
281
|
+
const filled = Math.round(ratio * BAR_WIDTH);
|
|
282
|
+
const bar = "\u2595" + "\u2588".repeat(filled) + "\u2591".repeat(BAR_WIDTH - filled) + "\u258F";
|
|
283
|
+
const pct = String(Math.floor(ratio * 100)).padStart(3, " ");
|
|
284
|
+
const line = ` ${bar} ${pct}% \xB7 ${this.completed}/${this.total} ${this.itemLabel} \xB7 ${formatBytes(this.totalBytes)} \xB7 ${formatDuration(now - this.startedAt)}${this.eta(now)}`;
|
|
285
|
+
this.stream.write(`\r\x1B[2K${line}`);
|
|
286
|
+
this.ttyLineActive = true;
|
|
287
|
+
}
|
|
288
|
+
/** Returns an " · eta 12.3s" suffix once enough progress exists to estimate. */
|
|
289
|
+
eta(now) {
|
|
290
|
+
if (this.completed < 10 || this.completed / this.total < 0.05) {
|
|
291
|
+
return "";
|
|
292
|
+
}
|
|
293
|
+
const elapsed = now - this.startedAt;
|
|
294
|
+
const remaining = elapsed / this.completed * (this.total - this.completed);
|
|
295
|
+
return ` \xB7 eta ${formatDuration(remaining)}`;
|
|
296
|
+
}
|
|
297
|
+
clearTtyLine() {
|
|
298
|
+
if (this.ttyLineActive) {
|
|
299
|
+
this.stream.write("\r\x1B[2K");
|
|
300
|
+
this.ttyLineActive = false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
println(line) {
|
|
304
|
+
this.clearTtyLine();
|
|
305
|
+
this.stream.write(line + "\n");
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
145
309
|
// src/cli/build-worker-pool.ts
|
|
146
310
|
import path from "node:path";
|
|
147
311
|
import { fileURLToPath } from "node:url";
|
|
312
|
+
import v8 from "node:v8";
|
|
148
313
|
import { Worker } from "node:worker_threads";
|
|
149
314
|
var __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
315
|
+
var WORKER_HEAP_LIMIT_MB = Math.ceil(
|
|
316
|
+
v8.getHeapStatistics().heap_size_limit / (1024 * 1024)
|
|
317
|
+
);
|
|
150
318
|
var BuildPageError = class extends Error {
|
|
151
319
|
urlPath;
|
|
152
320
|
params;
|
|
@@ -173,7 +341,8 @@ var BuildWorker = class {
|
|
|
173
341
|
this.pool = pool;
|
|
174
342
|
this.concurrency = options.workerConcurrency;
|
|
175
343
|
this.worker = new Worker(path.resolve(__dirname, "./build-worker.js"), {
|
|
176
|
-
workerData: { rootDir: options.rootDir, mode: options.mode }
|
|
344
|
+
workerData: { rootDir: options.rootDir, mode: options.mode },
|
|
345
|
+
resourceLimits: { maxOldGenerationSizeMb: WORKER_HEAP_LIMIT_MB }
|
|
177
346
|
});
|
|
178
347
|
let onReady;
|
|
179
348
|
let onFailed;
|
|
@@ -216,10 +385,30 @@ var BuildWorker = class {
|
|
|
216
385
|
}
|
|
217
386
|
});
|
|
218
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Rejects all in-flight tasks after a worker-level failure (fatal error,
|
|
390
|
+
* crash, or non-zero exit — e.g. an OOM kill).
|
|
391
|
+
*
|
|
392
|
+
* Each task is rejected with its own `BuildPageError` so the build log
|
|
393
|
+
* names every page that was in flight when the worker died. Without this,
|
|
394
|
+
* worker deaths surface as a single generic error with no route context,
|
|
395
|
+
* making OOM crashes impossible to trace back to pages. Note the in-flight
|
|
396
|
+
* pages are the OOM *suspects*, not necessarily the cause (memory pressure
|
|
397
|
+
* is cumulative), which is why the message says "while rendering".
|
|
398
|
+
*/
|
|
219
399
|
failAll(err) {
|
|
220
400
|
const pendingTasks = Array.from(this.inFlight.values());
|
|
221
401
|
this.inFlight.clear();
|
|
222
|
-
pendingTasks.forEach(
|
|
402
|
+
pendingTasks.forEach(
|
|
403
|
+
(pending) => pending.reject(
|
|
404
|
+
new BuildPageError(
|
|
405
|
+
pending.task.urlPath,
|
|
406
|
+
pending.task.params,
|
|
407
|
+
pending.task.routeSrc,
|
|
408
|
+
`worker thread died while rendering this page (${pendingTasks.length} page(s) were in flight): ` + String(err.message || err)
|
|
409
|
+
)
|
|
410
|
+
)
|
|
411
|
+
);
|
|
223
412
|
}
|
|
224
413
|
/** Pulls tasks off the pool's queue until at max concurrency. */
|
|
225
414
|
next() {
|
|
@@ -274,18 +463,22 @@ var BuildWorkerPool = class {
|
|
|
274
463
|
|
|
275
464
|
// src/cli/build.ts
|
|
276
465
|
var __dirname2 = path2.dirname(fileURLToPath2(import.meta.url));
|
|
466
|
+
var activeLogMode = "progress";
|
|
277
467
|
async function build(rootProjectDir, options) {
|
|
278
468
|
const mode = options?.mode || "production";
|
|
279
469
|
process.env.NODE_ENV = mode;
|
|
470
|
+
activeLogMode = options?.quiet ? "quiet" : parseBuildLogMode(options?.log);
|
|
280
471
|
const rootDir = path2.resolve(rootProjectDir || process.cwd());
|
|
281
472
|
const rootConfig = await loadRootConfig(rootDir, { command: "build" });
|
|
282
473
|
const distDir = path2.join(rootDir, "dist");
|
|
283
474
|
const ssrOnly = options?.ssrOnly || false;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
475
|
+
if (activeLogMode !== "quiet") {
|
|
476
|
+
console.log();
|
|
477
|
+
console.log(`${dim3("\u2503")} project: ${rootDir}`);
|
|
478
|
+
console.log(`${dim3("\u2503")} output: ${distDir}/html`);
|
|
479
|
+
console.log(`${dim3("\u2503")} mode: ${mode}`);
|
|
480
|
+
console.log();
|
|
481
|
+
}
|
|
289
482
|
await rmDir(distDir);
|
|
290
483
|
await makeDir(distDir);
|
|
291
484
|
const pods = await collectPods(rootConfig);
|
|
@@ -341,7 +534,9 @@ async function build(rootProjectDir, options) {
|
|
|
341
534
|
...viteConfig,
|
|
342
535
|
root: rootDir,
|
|
343
536
|
mode,
|
|
344
|
-
plugins: vitePlugins
|
|
537
|
+
plugins: vitePlugins,
|
|
538
|
+
// In quiet mode, only surface vite warnings and errors.
|
|
539
|
+
logLevel: activeLogMode === "quiet" ? "warn" : viteConfig.logLevel
|
|
345
540
|
};
|
|
346
541
|
const ssrInput = {
|
|
347
542
|
render: path2.resolve(__dirname2, "./render.js")
|
|
@@ -540,7 +735,9 @@ async function build(rootProjectDir, options) {
|
|
|
540
735
|
await fsExtra.copy(assetFrom, assetTo);
|
|
541
736
|
printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
|
|
542
737
|
}
|
|
543
|
-
|
|
738
|
+
if (activeLogMode !== "quiet") {
|
|
739
|
+
console.log("\njs/css output:");
|
|
740
|
+
}
|
|
544
741
|
await Promise.all(
|
|
545
742
|
Object.keys(rootManifest).map(async (src) => {
|
|
546
743
|
const assetData = rootManifest[src];
|
|
@@ -609,10 +806,9 @@ async function build(rootProjectDir, options) {
|
|
|
609
806
|
if (!result.staticContent) {
|
|
610
807
|
addSitemapXmlItem(result.urlPath, sitemapItem, result.outFilePath);
|
|
611
808
|
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
result.outFilePath
|
|
809
|
+
progress.add(
|
|
810
|
+
result.outFilePath,
|
|
811
|
+
fileSizeBytes(path2.join(buildDir, result.outFilePath))
|
|
616
812
|
);
|
|
617
813
|
};
|
|
618
814
|
const sitemapEntries = Object.entries(sitemap).filter(([, sitemapItem]) => {
|
|
@@ -624,76 +820,100 @@ async function build(rootProjectDir, options) {
|
|
|
624
820
|
}
|
|
625
821
|
return true;
|
|
626
822
|
});
|
|
627
|
-
|
|
823
|
+
if (activeLogMode !== "quiet") {
|
|
824
|
+
console.log("\nhtml output:");
|
|
825
|
+
}
|
|
628
826
|
const concurrency = Number(options?.concurrency || 10);
|
|
629
|
-
const
|
|
827
|
+
const resolvedThreads = resolveNumThreads(
|
|
630
828
|
options?.threads,
|
|
631
829
|
sitemapEntries.length
|
|
632
830
|
);
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
831
|
+
const numThreads = resolvedThreads.count;
|
|
832
|
+
const workerConcurrency = numThreads > 0 ? Math.max(Math.ceil(concurrency / numThreads), 1) : 0;
|
|
833
|
+
if (activeLogMode !== "quiet") {
|
|
834
|
+
const threadsDesc = numThreads > 0 ? `${numThreads} workers x ${workerConcurrency} pages/worker` : `in-process, ${concurrency} concurrent pages`;
|
|
835
|
+
console.log(
|
|
836
|
+
` ${dim3(`threads: ${threadsDesc} (${resolvedThreads.source})`)}`
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
const progress = new BuildProgress({
|
|
840
|
+
total: sitemapEntries.length,
|
|
841
|
+
mode: activeLogMode,
|
|
842
|
+
itemLabel: "pages",
|
|
843
|
+
outputDirLabel: "dist/html/"
|
|
844
|
+
});
|
|
845
|
+
try {
|
|
846
|
+
if (numThreads > 0) {
|
|
847
|
+
const pool = new BuildWorkerPool({
|
|
848
|
+
numWorkers: numThreads,
|
|
849
|
+
workerConcurrency,
|
|
850
|
+
rootDir,
|
|
851
|
+
mode
|
|
852
|
+
});
|
|
853
|
+
try {
|
|
854
|
+
await pool.ready();
|
|
855
|
+
await Promise.all(
|
|
856
|
+
sitemapEntries.map(async ([urlPath, sitemapItem]) => {
|
|
857
|
+
try {
|
|
858
|
+
const result = await pool.run({
|
|
859
|
+
urlPath,
|
|
860
|
+
params: sitemapItem.params,
|
|
861
|
+
routeSrc: sitemapItem.route.src,
|
|
862
|
+
locale: sitemapItem.locale
|
|
863
|
+
});
|
|
864
|
+
onPageResult(sitemapItem, result);
|
|
865
|
+
} catch (e) {
|
|
866
|
+
if (e instanceof BuildPageError) {
|
|
867
|
+
progress.abort();
|
|
868
|
+
logBuildError(
|
|
869
|
+
{
|
|
870
|
+
route: sitemapItem.route,
|
|
871
|
+
params: sitemapItem.params,
|
|
872
|
+
urlPath
|
|
873
|
+
},
|
|
874
|
+
new Error(e.workerError)
|
|
875
|
+
);
|
|
876
|
+
}
|
|
877
|
+
throw e;
|
|
878
|
+
}
|
|
879
|
+
})
|
|
880
|
+
);
|
|
881
|
+
} finally {
|
|
882
|
+
await pool.terminate();
|
|
883
|
+
}
|
|
884
|
+
} else {
|
|
885
|
+
await batchAsyncCalls(
|
|
886
|
+
sitemapEntries,
|
|
887
|
+
concurrency,
|
|
888
|
+
async ([urlPath, sitemapItem]) => {
|
|
644
889
|
try {
|
|
645
|
-
const result = await
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
890
|
+
const result = await buildPage(
|
|
891
|
+
renderer,
|
|
892
|
+
rootConfig,
|
|
893
|
+
buildDir,
|
|
894
|
+
sitemapItem.route,
|
|
895
|
+
{ urlPath, params: sitemapItem.params }
|
|
896
|
+
);
|
|
651
897
|
onPageResult(sitemapItem, result);
|
|
652
898
|
} catch (e) {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
}
|
|
663
|
-
throw e;
|
|
899
|
+
progress.abort();
|
|
900
|
+
logBuildError(
|
|
901
|
+
{ route: sitemapItem.route, params: sitemapItem.params, urlPath },
|
|
902
|
+
e
|
|
903
|
+
);
|
|
904
|
+
throw new Error(
|
|
905
|
+
`BuildError: ${urlPath} (${sitemapItem.route.src}) failed to build.`,
|
|
906
|
+
{ cause: e }
|
|
907
|
+
);
|
|
664
908
|
}
|
|
665
|
-
}
|
|
909
|
+
}
|
|
666
910
|
);
|
|
667
|
-
} finally {
|
|
668
|
-
await pool.terminate();
|
|
669
911
|
}
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
|
|
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
|
-
);
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
);
|
|
912
|
+
} catch (e) {
|
|
913
|
+
progress.abort();
|
|
914
|
+
throw e;
|
|
696
915
|
}
|
|
916
|
+
progress.finish();
|
|
697
917
|
if (rootConfig.sitemap) {
|
|
698
918
|
const sitemapXmlBuilder = [];
|
|
699
919
|
sitemapXmlItems.sort((a, b) => a.url.localeCompare(b.url));
|
|
@@ -734,42 +954,45 @@ function isRouteFile(filepath) {
|
|
|
734
954
|
return filepath.startsWith("routes") && isJsFile(filepath);
|
|
735
955
|
}
|
|
736
956
|
var MIN_PAGES_PER_THREAD = 10;
|
|
957
|
+
var MEMORY_PER_THREAD = 1024 * 1024 * 1024;
|
|
737
958
|
function resolveNumThreads(threads, numPages) {
|
|
738
959
|
if (threads === void 0 || threads === false) {
|
|
739
|
-
return 0;
|
|
960
|
+
return { count: 0, source: "--threads not set" };
|
|
740
961
|
}
|
|
741
962
|
if (threads === true || threads === "auto") {
|
|
742
963
|
const maxByCpu = Math.max(os.availableParallelism() - 1, 1);
|
|
743
964
|
const maxByPages = Math.floor(numPages / MIN_PAGES_PER_THREAD);
|
|
744
|
-
const
|
|
965
|
+
const maxByMemory = Math.max(
|
|
966
|
+
Math.floor(os.freemem() / MEMORY_PER_THREAD) - 1,
|
|
967
|
+
1
|
|
968
|
+
);
|
|
969
|
+
const numThreads = Math.min(maxByCpu, maxByPages, maxByMemory);
|
|
970
|
+
const source = `auto = min(cpu ${maxByCpu}, pages ${maxByPages}, memory ${maxByMemory})`;
|
|
745
971
|
if (numThreads <= 1) {
|
|
746
|
-
return 0;
|
|
972
|
+
return { count: 0, source };
|
|
747
973
|
}
|
|
748
|
-
|
|
749
|
-
return numThreads;
|
|
974
|
+
return { count: numThreads, source };
|
|
750
975
|
}
|
|
751
976
|
const num = parseInt(threads);
|
|
752
977
|
if (isNaN(num) || num < 0) {
|
|
753
978
|
throw new Error(`invalid --threads value: ${threads}`);
|
|
754
979
|
}
|
|
755
|
-
return num;
|
|
980
|
+
return { count: num, source: `--threads=${num}` };
|
|
981
|
+
}
|
|
982
|
+
function fileSizeBytes(filepath) {
|
|
983
|
+
return fsExtra.statSync(filepath).size;
|
|
756
984
|
}
|
|
757
985
|
function fileSize(filepath) {
|
|
758
|
-
|
|
759
|
-
const bytes = stats.size;
|
|
760
|
-
const k = 1024;
|
|
761
|
-
if (bytes < k) {
|
|
762
|
-
return (bytes / k).toFixed(2) + " kB";
|
|
763
|
-
}
|
|
764
|
-
const units = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
765
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
766
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + units[i];
|
|
986
|
+
return formatBytes(fileSizeBytes(filepath));
|
|
767
987
|
}
|
|
768
988
|
function printFileOutput(fileSize2, outputDir, outputFile) {
|
|
989
|
+
if (activeLogMode === "quiet") {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
769
992
|
const indent = " ".repeat(2);
|
|
770
993
|
const paddedSize = fileSize2.padStart(9, " ");
|
|
771
994
|
console.log(
|
|
772
|
-
`${indent}${
|
|
995
|
+
`${indent}${dim3(paddedSize)} ${dim3(outputDir)}${cyan2(outputFile)}`
|
|
773
996
|
);
|
|
774
997
|
}
|
|
775
998
|
function sanitizeFileName(name) {
|
|
@@ -1021,7 +1244,7 @@ import path11 from "node:path";
|
|
|
1021
1244
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
1022
1245
|
import cookieParser from "cookie-parser";
|
|
1023
1246
|
import { default as express } from "express";
|
|
1024
|
-
import { dim as
|
|
1247
|
+
import { dim as dim6 } from "kleur/colors";
|
|
1025
1248
|
import sirv from "sirv";
|
|
1026
1249
|
import glob3 from "tiny-glob";
|
|
1027
1250
|
|
|
@@ -1306,7 +1529,7 @@ import { spawn as spawn3 } from "node:child_process";
|
|
|
1306
1529
|
import fs6 from "node:fs";
|
|
1307
1530
|
import path9 from "node:path";
|
|
1308
1531
|
import * as readline from "node:readline";
|
|
1309
|
-
import { dim as
|
|
1532
|
+
import { dim as dim4, green as green2, red, yellow } from "kleur/colors";
|
|
1310
1533
|
|
|
1311
1534
|
// src/secrets/manifest.ts
|
|
1312
1535
|
import fs3 from "node:fs";
|
|
@@ -2079,7 +2302,7 @@ function getGitEmail() {
|
|
|
2079
2302
|
}
|
|
2080
2303
|
|
|
2081
2304
|
// src/cli/secrets.ts
|
|
2082
|
-
var BAR =
|
|
2305
|
+
var BAR = dim4("\u2503");
|
|
2083
2306
|
var DEV_SYNC_TIMEOUT_MS = 1e4;
|
|
2084
2307
|
function registerSecretsCommands(program) {
|
|
2085
2308
|
const secrets = program.command("secrets").description(
|
|
@@ -2140,13 +2363,13 @@ async function secretsInit(opts) {
|
|
|
2140
2363
|
await writeManifest(target, manifest);
|
|
2141
2364
|
const addedGitignore = await ensureRootGitignored(rootDir);
|
|
2142
2365
|
console.log();
|
|
2143
|
-
console.log(`${BAR} ${
|
|
2366
|
+
console.log(`${BAR} ${green2("secrets:")} created ${rel(rootDir, target)}`);
|
|
2144
2367
|
if (addedGitignore) {
|
|
2145
|
-
console.log(`${BAR} added ${
|
|
2368
|
+
console.log(`${BAR} added ${dim4(".root/")} to .gitignore`);
|
|
2146
2369
|
}
|
|
2147
2370
|
await warnIfEnvNotIgnored(rootDir);
|
|
2148
2371
|
console.log(
|
|
2149
|
-
`${BAR} ${
|
|
2372
|
+
`${BAR} ${dim4("next: `root secrets set <NAME>` to store a value")}`
|
|
2150
2373
|
);
|
|
2151
2374
|
console.log();
|
|
2152
2375
|
}
|
|
@@ -2158,18 +2381,18 @@ async function secretsSet(name, opts) {
|
|
|
2158
2381
|
throw new Error("no value provided on stdin");
|
|
2159
2382
|
}
|
|
2160
2383
|
await setSecret({ rootDir, manifestFilePath, name, value: secretValue });
|
|
2161
|
-
console.log(`${BAR} ${
|
|
2384
|
+
console.log(`${BAR} ${green2("secrets:")} set ${name}`);
|
|
2162
2385
|
console.log(
|
|
2163
|
-
`${BAR} ${
|
|
2386
|
+
`${BAR} ${dim4(`commit ${rel(rootDir, manifestFilePath)} to share this change`)}`
|
|
2164
2387
|
);
|
|
2165
2388
|
}
|
|
2166
2389
|
async function secretsRm(name, opts) {
|
|
2167
2390
|
const rootDir = process.cwd();
|
|
2168
2391
|
const manifestFilePath = opts.manifest ? path9.resolve(rootDir, opts.manifest) : manifestPath(rootDir);
|
|
2169
2392
|
await removeSecret({ rootDir, manifestFilePath, name });
|
|
2170
|
-
console.log(`${BAR} ${
|
|
2393
|
+
console.log(`${BAR} ${green2("secrets:")} removed ${name}`);
|
|
2171
2394
|
console.log(
|
|
2172
|
-
`${BAR} ${
|
|
2395
|
+
`${BAR} ${dim4(`commit ${rel(rootDir, manifestFilePath)} to share this change`)}`
|
|
2173
2396
|
);
|
|
2174
2397
|
}
|
|
2175
2398
|
async function secretsPush(opts) {
|
|
@@ -2184,7 +2407,7 @@ async function secretsPush(opts) {
|
|
|
2184
2407
|
}
|
|
2185
2408
|
console.log();
|
|
2186
2409
|
console.log(
|
|
2187
|
-
`${BAR} ${
|
|
2410
|
+
`${BAR} ${green2("secrets:")} push ${names.length} value(s) from .env to "${gsmKey}":`
|
|
2188
2411
|
);
|
|
2189
2412
|
for (const name of names) {
|
|
2190
2413
|
console.log(`${BAR} ${name}`);
|
|
@@ -2227,13 +2450,13 @@ async function secretsStatus() {
|
|
|
2227
2450
|
}
|
|
2228
2451
|
console.log();
|
|
2229
2452
|
console.log(
|
|
2230
|
-
`${BAR} ${
|
|
2453
|
+
`${BAR} ${green2("secrets:")} ${resolved.site.gsmKey} ${dim4(`(${resolved.site.gcpProjectId})`)}`
|
|
2231
2454
|
);
|
|
2232
2455
|
if (resolved.shared) {
|
|
2233
|
-
console.log(`${BAR} imports ${
|
|
2456
|
+
console.log(`${BAR} imports ${dim4(resolved.shared.gsmKey)}`);
|
|
2234
2457
|
}
|
|
2235
2458
|
if (keys.length === 0) {
|
|
2236
|
-
console.log(`${BAR} ${
|
|
2459
|
+
console.log(`${BAR} ${dim4("no managed keys yet")}`);
|
|
2237
2460
|
}
|
|
2238
2461
|
for (const key of keys) {
|
|
2239
2462
|
console.log(`${BAR} ${formatStatus(key)}`);
|
|
@@ -2261,15 +2484,15 @@ async function syncSecretsOnDev(rootDir) {
|
|
|
2261
2484
|
function formatStatus(key) {
|
|
2262
2485
|
switch (key.kind) {
|
|
2263
2486
|
case "in-sync":
|
|
2264
|
-
return `${
|
|
2487
|
+
return `${green2("\u2713")} ${key.name}`;
|
|
2265
2488
|
case "remote-newer":
|
|
2266
|
-
return `${yellow("\u2193")} ${key.name} ${
|
|
2489
|
+
return `${yellow("\u2193")} ${key.name} ${dim4("(update available \u2014 run `root secrets sync`)")}`;
|
|
2267
2490
|
case "locally-edited":
|
|
2268
|
-
return `${
|
|
2491
|
+
return `${dim4("\u2022")} ${key.name} ${dim4("(locally edited)")}`;
|
|
2269
2492
|
case "conflict":
|
|
2270
|
-
return `${yellow("!")} ${key.name} ${
|
|
2493
|
+
return `${yellow("!")} ${key.name} ${dim4("(changed locally & remotely)")}`;
|
|
2271
2494
|
case "not-pulled":
|
|
2272
|
-
return `${yellow("\u2193")} ${key.name} ${
|
|
2495
|
+
return `${yellow("\u2193")} ${key.name} ${dim4("(not pulled yet)")}`;
|
|
2273
2496
|
default:
|
|
2274
2497
|
return key.name;
|
|
2275
2498
|
}
|
|
@@ -2281,13 +2504,13 @@ function printSyncSummary(result, opts = {}) {
|
|
|
2281
2504
|
}
|
|
2282
2505
|
const parts = [];
|
|
2283
2506
|
if (result.changed.length) {
|
|
2284
|
-
parts.push(
|
|
2507
|
+
parts.push(green2(`${result.changed.length} updated`));
|
|
2285
2508
|
}
|
|
2286
2509
|
if (result.removed.length) {
|
|
2287
2510
|
parts.push(`${result.removed.length} removed`);
|
|
2288
2511
|
}
|
|
2289
2512
|
if (result.kept.length) {
|
|
2290
|
-
parts.push(
|
|
2513
|
+
parts.push(dim4(`${result.kept.length} local`));
|
|
2291
2514
|
}
|
|
2292
2515
|
if (result.conflicts.length) {
|
|
2293
2516
|
parts.push(yellow(`${result.conflicts.length} conflict`));
|
|
@@ -2297,22 +2520,22 @@ function printSyncSummary(result, opts = {}) {
|
|
|
2297
2520
|
}
|
|
2298
2521
|
console.log();
|
|
2299
2522
|
console.log(
|
|
2300
|
-
`${BAR} ${
|
|
2523
|
+
`${BAR} ${green2("secrets:")} ${parts.length ? parts.join(", ") : "up to date"}`
|
|
2301
2524
|
);
|
|
2302
2525
|
for (const name of result.changed) {
|
|
2303
|
-
console.log(`${BAR} ${
|
|
2526
|
+
console.log(`${BAR} ${green2("+")} ${name}`);
|
|
2304
2527
|
}
|
|
2305
2528
|
for (const name of result.removed) {
|
|
2306
|
-
console.log(`${BAR} ${
|
|
2529
|
+
console.log(`${BAR} ${dim4("-")} ${name} ${dim4("(removed)")}`);
|
|
2307
2530
|
}
|
|
2308
2531
|
for (const name of result.overwritten) {
|
|
2309
2532
|
console.log(
|
|
2310
|
-
`${BAR} ${yellow("!")} ${name} ${
|
|
2533
|
+
`${BAR} ${yellow("!")} ${name} ${dim4("(local value replaced)")}`
|
|
2311
2534
|
);
|
|
2312
2535
|
}
|
|
2313
2536
|
for (const name of result.conflicts) {
|
|
2314
2537
|
console.log(
|
|
2315
|
-
`${BAR} ${yellow("!")} ${name} ${
|
|
2538
|
+
`${BAR} ${yellow("!")} ${name} ${dim4(
|
|
2316
2539
|
"(changed locally & remotely; keeping yours \u2014 `root secrets pull` to take remote)"
|
|
2317
2540
|
)}`
|
|
2318
2541
|
);
|
|
@@ -2334,18 +2557,18 @@ function printPushResult(result, rootDir, manifestFilePath) {
|
|
|
2334
2557
|
console.log(`${BAR} ${yellow("secrets:")} nothing to push`);
|
|
2335
2558
|
} else {
|
|
2336
2559
|
console.log(
|
|
2337
|
-
`${BAR} ${
|
|
2560
|
+
`${BAR} ${green2("secrets:")} pushed ${result.pushed.length} value(s) to "${result.gsmKey}"`
|
|
2338
2561
|
);
|
|
2339
2562
|
for (const name of result.pushed) {
|
|
2340
|
-
console.log(`${BAR} ${
|
|
2563
|
+
console.log(`${BAR} ${green2("+")} ${name}`);
|
|
2341
2564
|
}
|
|
2342
2565
|
}
|
|
2343
2566
|
for (const skip of result.skipped) {
|
|
2344
|
-
console.log(`${BAR} ${
|
|
2567
|
+
console.log(`${BAR} ${dim4("-")} ${skip.name} ${dim4(`(${skip.reason})`)}`);
|
|
2345
2568
|
}
|
|
2346
2569
|
if (result.pushed.length > 0) {
|
|
2347
2570
|
console.log(
|
|
2348
|
-
`${BAR} ${
|
|
2571
|
+
`${BAR} ${dim4(`commit ${rel(rootDir, manifestFilePath)} to share`)}`
|
|
2349
2572
|
);
|
|
2350
2573
|
}
|
|
2351
2574
|
console.log();
|
|
@@ -2371,7 +2594,7 @@ async function warnIfEnvNotIgnored(rootDir) {
|
|
|
2371
2594
|
const ignored = await isPathGitIgnored(rootDir, ".env");
|
|
2372
2595
|
if (ignored === false) {
|
|
2373
2596
|
console.log(
|
|
2374
|
-
`${BAR} ${yellow("warning:")} ${
|
|
2597
|
+
`${BAR} ${yellow("warning:")} ${dim4(".env is not git-ignored \u2014 add it to .gitignore")}`
|
|
2375
2598
|
);
|
|
2376
2599
|
}
|
|
2377
2600
|
}
|
|
@@ -2512,7 +2735,7 @@ import os2 from "node:os";
|
|
|
2512
2735
|
import path10 from "node:path";
|
|
2513
2736
|
|
|
2514
2737
|
// src/cli/startup/check-version.ts
|
|
2515
|
-
import { dim as
|
|
2738
|
+
import { dim as dim5, green as green3, yellow as yellow2 } from "kleur/colors";
|
|
2516
2739
|
var PACKAGE_NAME = "@blinkk/root";
|
|
2517
2740
|
var ONE_DAY_MS = 24 * 60 * 60 * 1e3;
|
|
2518
2741
|
var REGISTRY_TIMEOUT_MS = 3e3;
|
|
@@ -2583,10 +2806,10 @@ function parseVersion(version) {
|
|
|
2583
2806
|
return [toInt(parts[0]), toInt(parts[1]), toInt(parts[2])];
|
|
2584
2807
|
}
|
|
2585
2808
|
function printUpdateNotice(current, latest) {
|
|
2586
|
-
const bar =
|
|
2809
|
+
const bar = dim5("\u2503");
|
|
2587
2810
|
const label = yellow2(`Update available for ${PACKAGE_NAME}:`);
|
|
2588
2811
|
console.log();
|
|
2589
|
-
console.log(`${bar} ${label} ${
|
|
2812
|
+
console.log(`${bar} ${label} ${dim5(current)} \u2192 ${green3(latest)}`);
|
|
2590
2813
|
console.log();
|
|
2591
2814
|
}
|
|
2592
2815
|
|
|
@@ -2665,12 +2888,12 @@ async function dev(rootProjectDir, options) {
|
|
|
2665
2888
|
const basePath = rootConfig.base || "";
|
|
2666
2889
|
const homePagePath = rootConfig.server?.homePagePath || basePath;
|
|
2667
2890
|
console.log();
|
|
2668
|
-
console.log(`${
|
|
2669
|
-
console.log(`${
|
|
2891
|
+
console.log(`${dim6("\u2503")} project: ${rootDir}`);
|
|
2892
|
+
console.log(`${dim6("\u2503")} server: http://${host}:${port}${homePagePath}`);
|
|
2670
2893
|
if (testCmsEnabled(rootConfig)) {
|
|
2671
|
-
console.log(`${
|
|
2894
|
+
console.log(`${dim6("\u2503")} cms: http://${host}:${port}/cms/`);
|
|
2672
2895
|
}
|
|
2673
|
-
console.log(`${
|
|
2896
|
+
console.log(`${dim6("\u2503")} mode: development`);
|
|
2674
2897
|
console.log();
|
|
2675
2898
|
currentServer = server.listen(port, host);
|
|
2676
2899
|
const rootConfigDependencies = server.get(
|
|
@@ -2685,7 +2908,7 @@ async function dev(rootProjectDir, options) {
|
|
|
2685
2908
|
if (dependencies.includes(file)) {
|
|
2686
2909
|
console.log(
|
|
2687
2910
|
`
|
|
2688
|
-
${
|
|
2911
|
+
${dim6("\u2503")} root.config.ts changed. restarting server...`
|
|
2689
2912
|
);
|
|
2690
2913
|
await restart();
|
|
2691
2914
|
}
|
|
@@ -3080,7 +3303,7 @@ function testManagedVersion(service, appInfo, prefix) {
|
|
|
3080
3303
|
import path12 from "node:path";
|
|
3081
3304
|
import cookieParser2 from "cookie-parser";
|
|
3082
3305
|
import { default as express2 } from "express";
|
|
3083
|
-
import { dim as
|
|
3306
|
+
import { dim as dim7 } from "kleur/colors";
|
|
3084
3307
|
import sirv2 from "sirv";
|
|
3085
3308
|
async function preview(rootProjectDir, options) {
|
|
3086
3309
|
process.env.NODE_ENV = "development";
|
|
@@ -3089,9 +3312,9 @@ async function preview(rootProjectDir, options) {
|
|
|
3089
3312
|
const port = parseInt(process.env.PORT || "4007");
|
|
3090
3313
|
const host = options?.host || "localhost";
|
|
3091
3314
|
console.log();
|
|
3092
|
-
console.log(`${
|
|
3093
|
-
console.log(`${
|
|
3094
|
-
console.log(`${
|
|
3315
|
+
console.log(`${dim7("\u2503")} project: ${rootDir}`);
|
|
3316
|
+
console.log(`${dim7("\u2503")} server: http://${host}:${port}`);
|
|
3317
|
+
console.log(`${dim7("\u2503")} mode: preview`);
|
|
3095
3318
|
console.log();
|
|
3096
3319
|
server.listen(port, host);
|
|
3097
3320
|
}
|
|
@@ -3226,7 +3449,7 @@ function rootPreviewServer500Middleware() {
|
|
|
3226
3449
|
import path13 from "node:path";
|
|
3227
3450
|
import cookieParser3 from "cookie-parser";
|
|
3228
3451
|
import { default as express3 } from "express";
|
|
3229
|
-
import { dim as
|
|
3452
|
+
import { dim as dim8 } from "kleur/colors";
|
|
3230
3453
|
import sirv3 from "sirv";
|
|
3231
3454
|
async function start(rootProjectDir, options) {
|
|
3232
3455
|
process.env.NODE_ENV = "production";
|
|
@@ -3235,9 +3458,9 @@ async function start(rootProjectDir, options) {
|
|
|
3235
3458
|
const port = parseInt(process.env.PORT || "4007");
|
|
3236
3459
|
const host = options?.host || "localhost";
|
|
3237
3460
|
console.log();
|
|
3238
|
-
console.log(`${
|
|
3239
|
-
console.log(`${
|
|
3240
|
-
console.log(`${
|
|
3461
|
+
console.log(`${dim8("\u2503")} project: ${rootDir}`);
|
|
3462
|
+
console.log(`${dim8("\u2503")} server: http://${host}:${port}`);
|
|
3463
|
+
console.log(`${dim8("\u2503")} mode: production`);
|
|
3241
3464
|
console.log();
|
|
3242
3465
|
server.listen(port, host);
|
|
3243
3466
|
}
|
|
@@ -3403,7 +3626,14 @@ var CliRunner = class {
|
|
|
3403
3626
|
"--filter <urlPathRegex>",
|
|
3404
3627
|
'builds the url paths that match the given regex, e.g. "/products/.*"',
|
|
3405
3628
|
""
|
|
3406
|
-
).
|
|
3629
|
+
).addOption(
|
|
3630
|
+
new Option(
|
|
3631
|
+
"--log <mode>",
|
|
3632
|
+
'build log output: "progress" (default) shows a progress indicator and a final summary, "verbose" prints one line per output file, "quiet" prints only the final summary'
|
|
3633
|
+
).choices(["progress", "verbose", "quiet"])
|
|
3634
|
+
).action(
|
|
3635
|
+
(rootProjectDir, options, cmd) => build(rootProjectDir, cmd.optsWithGlobals())
|
|
3636
|
+
);
|
|
3407
3637
|
program.command("codegen [type] [name]").description("generates boilerplate code").option("--out <outdir>", "output dir").action(codegen);
|
|
3408
3638
|
program.command("create-package [path]").alias("package").description(
|
|
3409
3639
|
"creates a standalone npm package for deployment to various hosting services"
|
|
@@ -3465,4 +3695,4 @@ export {
|
|
|
3465
3695
|
createProdServer,
|
|
3466
3696
|
CliRunner
|
|
3467
3697
|
};
|
|
3468
|
-
//# sourceMappingURL=chunk-
|
|
3698
|
+
//# sourceMappingURL=chunk-GK3TDYUY.js.map
|