cajonzero 0.1.2 → 0.1.3
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/README.md +42 -3
- package/dist/bin/cj0.js +14243 -47
- package/dist/{config-BOzAyP7m.d.ts → config-B32NDXlr.d.ts} +1 -1
- package/dist/core.d.ts +15 -7
- package/dist/core.js +319 -157
- package/dist/index.d.ts +5 -5
- package/dist/index.js +184 -22
- package/dist/{providers-BX7e4pNW.d.ts → providers-BwJKzGkd.d.ts} +17 -0
- package/dist/scaffold.d.ts +67 -3
- package/dist/scaffold.js +293 -32
- package/dist/serve.d.ts +1 -1
- package/dist/serve.js +325 -163
- package/dist/ui/assets/index-CNHWg0_t.js +4404 -0
- package/dist/ui/assets/{main-BeABKxzY.js → main-DTcEV4JE.js} +16 -16
- package/dist/ui/index.html +1 -1
- package/package.json +4 -4
- package/dist/ui/assets/index-CaAHje8X.js +0 -4404
package/dist/scaffold.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { readFileSync, existsSync, statSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
2
|
-
import
|
|
1
|
+
import { readFileSync, existsSync, statSync, mkdirSync, writeFileSync, renameSync, rmSync, cpSync, readdirSync } from 'fs';
|
|
2
|
+
import path3 from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
|
-
import { randomBytes } from 'crypto';
|
|
4
|
+
import { randomBytes, createHash } from 'crypto';
|
|
5
|
+
import { createRequire } from 'module';
|
|
5
6
|
|
|
6
7
|
// src/scaffold/templates.ts
|
|
7
8
|
var SCAFFOLD_ENTRY_PATH = "src/index.ts";
|
|
@@ -71,7 +72,7 @@ var SCAFFOLD_CONFIG_CONTENT = `${JSON.stringify(
|
|
|
71
72
|
`;
|
|
72
73
|
var SCAFFOLD_MAPS_CONTENT = `${JSON.stringify({ version: 1, maps: [] }, null, 2)}
|
|
73
74
|
`;
|
|
74
|
-
var
|
|
75
|
+
var PREPARE_ASSETS = "cj0 worker prepare";
|
|
75
76
|
function packageJson(options) {
|
|
76
77
|
const manifest = {
|
|
77
78
|
name: options.packageName,
|
|
@@ -79,12 +80,14 @@ function packageJson(options) {
|
|
|
79
80
|
private: true,
|
|
80
81
|
type: "module",
|
|
81
82
|
scripts: {
|
|
82
|
-
dev: `${
|
|
83
|
-
build: `${
|
|
84
|
-
|
|
83
|
+
dev: `${PREPARE_ASSETS} && wrangler dev`,
|
|
84
|
+
build: `${PREPARE_ASSETS} && cj0 worker build-seed && wrangler deploy --dry-run`,
|
|
85
|
+
// Deploy always rebuilds: map content can change without `version` being
|
|
86
|
+
// bumped, and the room prefers the pack over the live CDN graph.
|
|
87
|
+
deploy: `${PREPARE_ASSETS} && cj0 worker build-seed --force && wrangler deploy`,
|
|
85
88
|
// `prepare` also runs after `npm install`, so a plain install leaves a
|
|
86
|
-
// ready-to-deploy project.
|
|
87
|
-
prepare:
|
|
89
|
+
// ready-to-deploy project. Seed packs are network work and stay out of it.
|
|
90
|
+
prepare: PREPARE_ASSETS
|
|
88
91
|
},
|
|
89
92
|
dependencies: {
|
|
90
93
|
cajonzero: options.cajonzeroRange,
|
|
@@ -113,6 +116,8 @@ function wranglerConfig(options) {
|
|
|
113
116
|
" // cajonzero ships the built assets into this directory.",
|
|
114
117
|
' "assets": {',
|
|
115
118
|
' "directory": "dist/ui",',
|
|
119
|
+
" // Binding so the room can read seed packs bundled at deploy time.",
|
|
120
|
+
' "binding": "ASSETS",',
|
|
116
121
|
" // History routing: deep links (/play/x, /admin/bans) boot index.html.",
|
|
117
122
|
' "not_found_handling": "single-page-application",',
|
|
118
123
|
' "run_worker_first": ["/api/*", "/runtime/*"]',
|
|
@@ -163,17 +168,18 @@ function readme(options) {
|
|
|
163
168
|
"",
|
|
164
169
|
"```bash",
|
|
165
170
|
"npm install",
|
|
166
|
-
"npx cj0 setup # \u4EA4\u4E92\u5F0F\u914D\u7F6E
|
|
171
|
+
"npx cj0 setup # \u4EA4\u4E92\u5F0F\u914D\u7F6E ENV + KV namespace",
|
|
167
172
|
"npm run dev # http://localhost:8787",
|
|
168
173
|
"```",
|
|
169
174
|
"",
|
|
170
175
|
"## \u73AF\u5883\u53D8\u91CF",
|
|
171
176
|
"",
|
|
172
177
|
"`cj0 setup` \u628A\u975E\u5BC6\u94A5\u5199\u5165 `wrangler.jsonc` \u7684 `vars`\uFF0C\u628A\u5BC6\u94A5\u5199\u5165 `.dev.vars`\uFF08\u672C\u5730\uFF09\u3002",
|
|
173
|
-
"\
|
|
178
|
+
"KV namespace \u4E5F\u7531 `cj0 setup` \u914D\u7F6E\uFF1A\u56DE\u8F66\u4F1A\u81EA\u52A8\u8C03\u7528 wrangler \u521B\u5EFA\u5E76\u5199\u56DE id\uFF08\u9700\u5148\u767B\u5F55\uFF09\uFF0C",
|
|
179
|
+
"\u4E5F\u53EF\u4EE5\u7C98\u8D34\u5DF2\u6709 id\u3002\u79BB\u7EBF\u65F6\u624B\u52A8\u8FD0\u884C\uFF1A",
|
|
174
180
|
"",
|
|
175
181
|
"```bash",
|
|
176
|
-
"npx wrangler kv namespace create
|
|
182
|
+
"npx wrangler kv namespace create <name> --update-config --binding CAJONZERO_KV",
|
|
177
183
|
"npx wrangler secret put CAJONZERO_SESSION_SECRET",
|
|
178
184
|
"npx wrangler secret put BOX_PLAY_ADMIN_TOKEN",
|
|
179
185
|
"```",
|
|
@@ -264,7 +270,7 @@ function readCajonzeroPackage(manifestPath) {
|
|
|
264
270
|
return { version, wranglerRange, unstorageRange };
|
|
265
271
|
}
|
|
266
272
|
function toPackageName(folder) {
|
|
267
|
-
const base =
|
|
273
|
+
const base = path3.basename(folder);
|
|
268
274
|
const slug = base.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[-._]+/, "").replace(/[-._]+$/, "");
|
|
269
275
|
return slug.length > 0 ? slug : "cajonzero-app";
|
|
270
276
|
}
|
|
@@ -279,7 +285,7 @@ function createProject(folder, options = {}) {
|
|
|
279
285
|
throw new ScaffoldError("INVALID_TARGET", "create requires a target folder");
|
|
280
286
|
}
|
|
281
287
|
const cwd = options.cwd ?? process.cwd();
|
|
282
|
-
const target =
|
|
288
|
+
const target = path3.resolve(cwd, name);
|
|
283
289
|
if (existsSync(target) && !statSync(target).isDirectory()) {
|
|
284
290
|
throw new ScaffoldError("INVALID_TARGET", `target exists and is not a directory: ${target}`);
|
|
285
291
|
}
|
|
@@ -302,8 +308,8 @@ function createProject(folder, options = {}) {
|
|
|
302
308
|
});
|
|
303
309
|
mkdirSync(target, { recursive: true });
|
|
304
310
|
for (const file of files) {
|
|
305
|
-
const fullPath =
|
|
306
|
-
mkdirSync(
|
|
311
|
+
const fullPath = path3.join(target, file.path);
|
|
312
|
+
mkdirSync(path3.dirname(fullPath), { recursive: true });
|
|
307
313
|
writeFileSync(fullPath, file.content, "utf8");
|
|
308
314
|
}
|
|
309
315
|
return { target, files: files.map((file) => file.path) };
|
|
@@ -388,6 +394,13 @@ var SETUP_FIELDS = [
|
|
|
388
394
|
required: true,
|
|
389
395
|
hint: "\u7559\u7A7A\u81EA\u52A8\u751F\u6210\uFF1B\u672C\u5730\u5199\u5165 .dev.vars"
|
|
390
396
|
},
|
|
397
|
+
{
|
|
398
|
+
name: "CAJONZERO_KV_ID",
|
|
399
|
+
label: "KV namespace id",
|
|
400
|
+
kind: "kv",
|
|
401
|
+
required: true,
|
|
402
|
+
hint: "\u56DE\u8F66\u81EA\u52A8\u521B\u5EFA\uFF08\u9700 wrangler \u767B\u5F55\uFF09\u6216\u7C98\u8D34\u5DF2\u6709 id"
|
|
403
|
+
},
|
|
391
404
|
{
|
|
392
405
|
name: "CAJONZERO_ENV",
|
|
393
406
|
label: "\u90E8\u7F72\u540D\u79F0",
|
|
@@ -435,10 +448,11 @@ function serializeDevVars(values) {
|
|
|
435
448
|
return `${lines.join("\n")}
|
|
436
449
|
`;
|
|
437
450
|
}
|
|
438
|
-
function
|
|
439
|
-
const
|
|
451
|
+
function findKeyBlock(raw, key, openChar) {
|
|
452
|
+
const closeChar = openChar === "{" ? "}" : "]";
|
|
453
|
+
const match = new RegExp(`"${key}"\\s*:\\s*\\${openChar}`).exec(raw);
|
|
440
454
|
if (match === null) return null;
|
|
441
|
-
const open = raw.indexOf(
|
|
455
|
+
const open = raw.indexOf(openChar, match.index);
|
|
442
456
|
let depth = 0;
|
|
443
457
|
let inString = false;
|
|
444
458
|
let escaped = false;
|
|
@@ -451,8 +465,8 @@ function findVarsBlock(raw) {
|
|
|
451
465
|
continue;
|
|
452
466
|
}
|
|
453
467
|
if (ch === '"') inString = true;
|
|
454
|
-
else if (ch ===
|
|
455
|
-
else if (ch ===
|
|
468
|
+
else if (ch === openChar) depth += 1;
|
|
469
|
+
else if (ch === closeChar) {
|
|
456
470
|
depth -= 1;
|
|
457
471
|
if (depth === 0) {
|
|
458
472
|
const lineStart = raw.lastIndexOf("\n", match.index) + 1;
|
|
@@ -463,7 +477,10 @@ function findVarsBlock(raw) {
|
|
|
463
477
|
}
|
|
464
478
|
return null;
|
|
465
479
|
}
|
|
466
|
-
function
|
|
480
|
+
function findVarsBlock(raw) {
|
|
481
|
+
return findKeyBlock(raw, "vars", "{");
|
|
482
|
+
}
|
|
483
|
+
function stripJsoncComments(text) {
|
|
467
484
|
let out = "";
|
|
468
485
|
let inString = false;
|
|
469
486
|
let escaped = false;
|
|
@@ -494,13 +511,95 @@ function parseJsoncObject(text) {
|
|
|
494
511
|
}
|
|
495
512
|
out += ch;
|
|
496
513
|
}
|
|
497
|
-
|
|
514
|
+
return out;
|
|
515
|
+
}
|
|
516
|
+
function parseJsonc(text) {
|
|
498
517
|
try {
|
|
499
|
-
const
|
|
500
|
-
return
|
|
518
|
+
const clean = text.replace(/^\uFEFF/, "");
|
|
519
|
+
return JSON.parse(stripJsoncComments(clean).replace(/,(\s*[}\]])/g, "$1"));
|
|
501
520
|
} catch {
|
|
502
|
-
return
|
|
521
|
+
return void 0;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function parseJsoncObject(text) {
|
|
525
|
+
const parsed = parseJsonc(text);
|
|
526
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
|
|
527
|
+
}
|
|
528
|
+
function parseJsoncArray(text) {
|
|
529
|
+
const parsed = parseJsonc(text);
|
|
530
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
531
|
+
}
|
|
532
|
+
function escapeRegExp(text) {
|
|
533
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
534
|
+
}
|
|
535
|
+
function findBindingObject(raw, block, binding) {
|
|
536
|
+
const bindingPattern = new RegExp(`"binding"\\s*:\\s*"${escapeRegExp(binding)}"`);
|
|
537
|
+
const stack = [];
|
|
538
|
+
let inString = false;
|
|
539
|
+
let escaped = false;
|
|
540
|
+
for (let i = block.open; i <= block.close; i += 1) {
|
|
541
|
+
const ch = raw[i];
|
|
542
|
+
if (inString) {
|
|
543
|
+
if (escaped) escaped = false;
|
|
544
|
+
else if (ch === "\\") escaped = true;
|
|
545
|
+
else if (ch === '"') inString = false;
|
|
546
|
+
continue;
|
|
547
|
+
}
|
|
548
|
+
if (ch === '"') inString = true;
|
|
549
|
+
else if (ch === "{") stack.push(i);
|
|
550
|
+
else if (ch === "}") {
|
|
551
|
+
const start = stack.pop();
|
|
552
|
+
if (start !== void 0 && bindingPattern.test(raw.slice(start, i + 1))) {
|
|
553
|
+
const lineStart = raw.lastIndexOf("\n", start) + 1;
|
|
554
|
+
const indent = /^\s*/.exec(raw.slice(lineStart, start))?.[0] ?? " ";
|
|
555
|
+
return { start, end: i + 1, indent };
|
|
556
|
+
}
|
|
557
|
+
}
|
|
503
558
|
}
|
|
559
|
+
return null;
|
|
560
|
+
}
|
|
561
|
+
function readWranglerKvNamespaceId(raw, binding = "CAJONZERO_KV") {
|
|
562
|
+
const block = findKeyBlock(raw, "kv_namespaces", "[");
|
|
563
|
+
if (block === null) return void 0;
|
|
564
|
+
const entries = parseJsoncArray(raw.slice(block.open, block.close + 1));
|
|
565
|
+
for (const entry of entries) {
|
|
566
|
+
if (typeof entry !== "object" || entry === null) continue;
|
|
567
|
+
const record = entry;
|
|
568
|
+
if (record["binding"] !== binding) continue;
|
|
569
|
+
const id = record["id"];
|
|
570
|
+
return typeof id === "string" && id.length > 0 ? id : void 0;
|
|
571
|
+
}
|
|
572
|
+
return void 0;
|
|
573
|
+
}
|
|
574
|
+
function setWranglerKvNamespaceId(raw, binding, id) {
|
|
575
|
+
const block = findKeyBlock(raw, "kv_namespaces", "[");
|
|
576
|
+
if (block !== null) {
|
|
577
|
+
const entry = findBindingObject(raw, block, binding);
|
|
578
|
+
if (entry !== null) {
|
|
579
|
+
const entryText = raw.slice(entry.start, entry.end);
|
|
580
|
+
const nextEntry = /"id"\s*:/.test(entryText) ? entryText.replace(/("id"\s*:\s*)"(?:[^"\\]|\\.)*"/, `$1${JSON.stringify(id)}`) : entryText.replace(
|
|
581
|
+
/("binding"\s*:\s*"(?:[^"\\]|\\.)*")/,
|
|
582
|
+
`$1,
|
|
583
|
+
${entry.indent}"id": ${JSON.stringify(id)}`
|
|
584
|
+
);
|
|
585
|
+
return raw.slice(0, entry.start) + nextEntry + raw.slice(entry.end);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
const existing = block === null ? [] : parseJsoncArray(raw.slice(block.open, block.close + 1));
|
|
589
|
+
const filtered = existing.filter(
|
|
590
|
+
(entry) => !(typeof entry === "object" && entry !== null && entry["binding"] === binding)
|
|
591
|
+
);
|
|
592
|
+
const indent = block?.indent ?? " ";
|
|
593
|
+
const arrayText = JSON.stringify([...filtered, { binding, id }], null, 2).split("\n").map((line, index) => index === 0 ? line : `${indent}${line}`).join("\n");
|
|
594
|
+
if (block !== null) {
|
|
595
|
+
return raw.slice(0, block.open) + arrayText + raw.slice(block.close + 1);
|
|
596
|
+
}
|
|
597
|
+
const close = raw.lastIndexOf("}");
|
|
598
|
+
if (close < 0) throw new Error("wrangler config is not a JSON object");
|
|
599
|
+
const body = raw.slice(0, close).trimEnd();
|
|
600
|
+
const separator = body.endsWith("{") || body.endsWith(",") ? "\n" : ",\n";
|
|
601
|
+
return `${body}${separator}${indent}"kv_namespaces": ${arrayText}
|
|
602
|
+
${raw.slice(close)}`;
|
|
504
603
|
}
|
|
505
604
|
function setWranglerVars(raw, vars) {
|
|
506
605
|
const managed = new Set(SETUP_FIELDS.filter((f) => f.kind === "var").map((f) => f.name));
|
|
@@ -543,26 +642,33 @@ function readSetupValues(cwd, configPath, devVarsPath) {
|
|
|
543
642
|
if (typeof value === "string") out[key] = value;
|
|
544
643
|
}
|
|
545
644
|
}
|
|
645
|
+
const kvId = readWranglerKvNamespaceId(raw);
|
|
646
|
+
if (kvId !== void 0 && kvId !== SCAFFOLD_KV_PLACEHOLDER_ID) {
|
|
647
|
+
out["CAJONZERO_KV_ID"] = kvId;
|
|
648
|
+
}
|
|
546
649
|
}
|
|
547
650
|
return out;
|
|
548
651
|
}
|
|
549
652
|
function applySetup(options) {
|
|
550
653
|
const cwd = options.cwd ?? process.cwd();
|
|
551
|
-
const configPath =
|
|
552
|
-
const devVarsPath =
|
|
654
|
+
const configPath = path3.resolve(cwd, options.configPath ?? "wrangler.jsonc");
|
|
655
|
+
const devVarsPath = path3.join(path3.dirname(configPath), ".dev.vars");
|
|
553
656
|
if (!existsSync(configPath)) {
|
|
554
|
-
throw new Error(`\u627E\u4E0D\u5230 ${
|
|
657
|
+
throw new Error(`\u627E\u4E0D\u5230 ${path3.basename(configPath)}\uFF0C\u8BF7\u5728 cj0 create \u751F\u6210\u7684\u9879\u76EE\u76EE\u5F55\u4E2D\u8FD0\u884C`);
|
|
555
658
|
}
|
|
556
659
|
const vars = {};
|
|
557
660
|
const secrets = {};
|
|
661
|
+
let kvId;
|
|
558
662
|
for (const field of SETUP_FIELDS) {
|
|
559
663
|
const value = options.values[field.name]?.trim();
|
|
560
664
|
if (value === void 0 || value.length === 0) continue;
|
|
561
665
|
if (field.kind === "secret") secrets[field.name] = value;
|
|
666
|
+
else if (field.kind === "kv") kvId = value;
|
|
562
667
|
else vars[field.name] = value;
|
|
563
668
|
}
|
|
564
669
|
const raw = readFileSync(configPath, "utf8");
|
|
565
|
-
|
|
670
|
+
let next = setWranglerVars(raw, vars);
|
|
671
|
+
if (kvId !== void 0) next = setWranglerKvNamespaceId(next, "CAJONZERO_KV", kvId);
|
|
566
672
|
if (next !== raw) writeFileSync(configPath, next, "utf8");
|
|
567
673
|
const existingDev = existsSync(devVarsPath) ? parseDevVars(readFileSync(devVarsPath, "utf8")) : {};
|
|
568
674
|
const managedSecrets = new Set(
|
|
@@ -574,9 +680,164 @@ function applySetup(options) {
|
|
|
574
680
|
}
|
|
575
681
|
Object.assign(mergedDev, secrets);
|
|
576
682
|
writeFileSync(devVarsPath, serializeDevVars(mergedDev), "utf8");
|
|
577
|
-
return { configPath, devVarsPath, vars, secrets };
|
|
683
|
+
return { configPath, devVarsPath, vars, secrets, ...kvId !== void 0 ? { kvId } : {} };
|
|
684
|
+
}
|
|
685
|
+
var ASSETS_STAMP_FILE = ".cajonzero-assets.json";
|
|
686
|
+
var ASSETS_SEED_DIR = "seed";
|
|
687
|
+
var DEFAULT_CONFIG = "wrangler.jsonc";
|
|
688
|
+
function resolvePackageRoot() {
|
|
689
|
+
try {
|
|
690
|
+
return path3.dirname(createRequire(import.meta.url).resolve("cajonzero/package.json"));
|
|
691
|
+
} catch {
|
|
692
|
+
return path3.dirname(fileURLToPath(new URL("../../package.json", import.meta.url)));
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
function readPackageVersion(root) {
|
|
696
|
+
try {
|
|
697
|
+
const parsed = JSON.parse(readFileSync(path3.join(root, "package.json"), "utf8"));
|
|
698
|
+
return typeof parsed.version === "string" ? parsed.version : void 0;
|
|
699
|
+
} catch {
|
|
700
|
+
return void 0;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
function readWranglerAssetsDirectory(configPath) {
|
|
704
|
+
if (!existsSync(configPath)) {
|
|
705
|
+
throw new Error(`\u627E\u4E0D\u5230 ${path3.basename(configPath)}\uFF0C\u8BF7\u5728 cj0 create \u751F\u6210\u7684\u9879\u76EE\u76EE\u5F55\u4E2D\u8FD0\u884C`);
|
|
706
|
+
}
|
|
707
|
+
const ext = path3.extname(configPath).toLowerCase();
|
|
708
|
+
if (ext !== ".json" && ext !== ".jsonc") {
|
|
709
|
+
throw new Error(
|
|
710
|
+
`\u4E0D\u652F\u6301\u8BFB\u53D6 ${path3.basename(configPath)}\uFF08\u53EA\u652F\u6301 JSON/JSONC wrangler \u914D\u7F6E\uFF1B\u7528 --assets \u6307\u5B9A\u76EE\u5F55\uFF09`
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
const parsed = parseJsoncObject(readFileSync(configPath, "utf8"));
|
|
714
|
+
const assets = parsed["assets"];
|
|
715
|
+
if (typeof assets === "object" && assets !== null && !Array.isArray(assets)) {
|
|
716
|
+
const directory = assets["directory"];
|
|
717
|
+
if (typeof directory === "string" && directory.length > 0) return directory;
|
|
718
|
+
}
|
|
719
|
+
return void 0;
|
|
720
|
+
}
|
|
721
|
+
function fingerprintTree(dir) {
|
|
722
|
+
const entries = [];
|
|
723
|
+
const walk = (relative) => {
|
|
724
|
+
const absolute = relative.length === 0 ? dir : path3.join(dir, relative);
|
|
725
|
+
for (const entry of readdirSync(absolute, { withFileTypes: true })) {
|
|
726
|
+
if (entry.name === ASSETS_STAMP_FILE) continue;
|
|
727
|
+
const child = relative.length === 0 ? entry.name : `${relative}/${entry.name}`;
|
|
728
|
+
if (entry.isDirectory()) walk(child);
|
|
729
|
+
else if (entry.isFile()) entries.push(child);
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
walk("");
|
|
733
|
+
entries.sort();
|
|
734
|
+
const hash = createHash("sha256");
|
|
735
|
+
let bytes = 0;
|
|
736
|
+
for (const relative of entries) {
|
|
737
|
+
const content = readFileSync(path3.join(dir, relative));
|
|
738
|
+
bytes += content.length;
|
|
739
|
+
hash.update(relative);
|
|
740
|
+
hash.update("\0");
|
|
741
|
+
hash.update(content);
|
|
742
|
+
hash.update("\0");
|
|
743
|
+
}
|
|
744
|
+
return { files: entries.length, bytes, hash: hash.digest("hex") };
|
|
745
|
+
}
|
|
746
|
+
function readStamp(targetDir) {
|
|
747
|
+
try {
|
|
748
|
+
const parsed = JSON.parse(
|
|
749
|
+
readFileSync(path3.join(targetDir, ASSETS_STAMP_FILE), "utf8")
|
|
750
|
+
);
|
|
751
|
+
if (parsed.version !== 1 || typeof parsed.fingerprint !== "string") return void 0;
|
|
752
|
+
return { version: 1, fingerprint: parsed.fingerprint, packageVersion: parsed.packageVersion };
|
|
753
|
+
} catch {
|
|
754
|
+
return void 0;
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
function assertSafeTarget(targetDir, sourceDir, configDir) {
|
|
758
|
+
const contains = (parent, child) => child === parent || child.startsWith(`${parent}${path3.sep}`);
|
|
759
|
+
if (targetDir === path3.parse(targetDir).root) {
|
|
760
|
+
throw new Error(`\u62D2\u7EDD\u628A\u6587\u4EF6\u7CFB\u7EDF\u6839\u76EE\u5F55\u4F5C\u4E3A assets \u76EE\u5F55\uFF1A${targetDir}`);
|
|
761
|
+
}
|
|
762
|
+
if (contains(targetDir, configDir) || contains(targetDir, sourceDir) || contains(sourceDir, targetDir)) {
|
|
763
|
+
throw new Error(`assets \u76EE\u5F55\u4E0D\u80FD\u5305\u542B\u9879\u76EE\u914D\u7F6E/cajonzero \u8D44\u6E90\u76EE\u5F55\uFF1A${targetDir}`);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
async function prepareWorkerAssets(options = {}) {
|
|
767
|
+
const cwd = options.cwd ?? process.cwd();
|
|
768
|
+
const configPath = path3.resolve(cwd, options.configPath ?? DEFAULT_CONFIG);
|
|
769
|
+
const configDir = path3.dirname(configPath);
|
|
770
|
+
const packageRoot = resolvePackageRoot();
|
|
771
|
+
const sourceDir = path3.resolve(options.sourceDir ?? path3.join(packageRoot, "dist", "ui"));
|
|
772
|
+
if (!existsSync(sourceDir)) {
|
|
773
|
+
throw new Error(
|
|
774
|
+
`cajonzero \u7684 UI \u8D44\u6E90\u7F3A\u5931\uFF1A${sourceDir}\uFF08\u8BF7\u91CD\u65B0\u5B89\u88C5 cajonzero\uFF0C\u6216\u5728\u6E90\u7801\u4ED3\u5E93\u5148 npm run build\uFF09`
|
|
775
|
+
);
|
|
776
|
+
}
|
|
777
|
+
const configured = options.assetsDir ?? readWranglerAssetsDirectory(configPath);
|
|
778
|
+
if (configured === void 0) {
|
|
779
|
+
throw new Error(
|
|
780
|
+
`${path3.basename(configPath)} \u672A\u914D\u7F6E assets.directory\uFF1B\u7528 --assets <dir> \u6307\u5B9A\u8F93\u51FA\u76EE\u5F55`
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
const targetDir = path3.resolve(configDir, configured);
|
|
784
|
+
assertSafeTarget(targetDir, sourceDir, configDir);
|
|
785
|
+
const source = fingerprintTree(sourceDir);
|
|
786
|
+
const stamp = readStamp(targetDir);
|
|
787
|
+
if (!options.force && stamp?.fingerprint === source.hash && existsSync(targetDir)) {
|
|
788
|
+
return {
|
|
789
|
+
sourceDir,
|
|
790
|
+
targetDir,
|
|
791
|
+
fingerprint: source.hash,
|
|
792
|
+
copied: false,
|
|
793
|
+
files: source.files,
|
|
794
|
+
bytes: source.bytes
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
const seedDir = path3.join(targetDir, ASSETS_SEED_DIR);
|
|
798
|
+
const seedBackup = `${targetDir}.${ASSETS_SEED_DIR}-backup`;
|
|
799
|
+
if (!existsSync(seedDir) && existsSync(seedBackup)) {
|
|
800
|
+
mkdirSync(path3.dirname(seedDir), { recursive: true });
|
|
801
|
+
renameSync(seedBackup, seedDir);
|
|
802
|
+
}
|
|
803
|
+
let hasSeed = false;
|
|
804
|
+
if (existsSync(seedDir)) {
|
|
805
|
+
rmSync(seedBackup, { recursive: true, force: true });
|
|
806
|
+
renameSync(seedDir, seedBackup);
|
|
807
|
+
hasSeed = true;
|
|
808
|
+
}
|
|
809
|
+
try {
|
|
810
|
+
rmSync(targetDir, { recursive: true, force: true });
|
|
811
|
+
mkdirSync(targetDir, { recursive: true });
|
|
812
|
+
cpSync(sourceDir, targetDir, {
|
|
813
|
+
recursive: true,
|
|
814
|
+
force: true,
|
|
815
|
+
filter: (from) => path3.basename(from) !== ASSETS_STAMP_FILE
|
|
816
|
+
});
|
|
817
|
+
} finally {
|
|
818
|
+
if (hasSeed && existsSync(seedBackup)) {
|
|
819
|
+
mkdirSync(targetDir, { recursive: true });
|
|
820
|
+
rmSync(seedDir, { recursive: true, force: true });
|
|
821
|
+
renameSync(seedBackup, seedDir);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
const next = {
|
|
825
|
+
version: 1,
|
|
826
|
+
fingerprint: source.hash,
|
|
827
|
+
packageVersion: readPackageVersion(packageRoot)
|
|
828
|
+
};
|
|
829
|
+
writeFileSync(path3.join(targetDir, ASSETS_STAMP_FILE), `${JSON.stringify(next, null, 2)}
|
|
830
|
+
`, "utf8");
|
|
831
|
+
return {
|
|
832
|
+
sourceDir,
|
|
833
|
+
targetDir,
|
|
834
|
+
fingerprint: source.hash,
|
|
835
|
+
copied: true,
|
|
836
|
+
files: source.files,
|
|
837
|
+
bytes: source.bytes
|
|
838
|
+
};
|
|
578
839
|
}
|
|
579
840
|
|
|
580
|
-
export { SCAFFOLD_COMPATIBILITY_DATE, SCAFFOLD_CONFIG_CONTENT, SCAFFOLD_ENTRY_CONTENT, SCAFFOLD_ENTRY_PATH, SCAFFOLD_KV_PLACEHOLDER_ID, SCAFFOLD_MAPS_CONTENT, SETUP_FIELDS, ScaffoldError, applySetup, buildScaffoldFiles, createProject, generateAdminToken, generateSecret, parseDevVars, readCajonzeroPackage, readSetupValues, serializeDevVars, setWranglerVars, suggestedValue, toPackageName };
|
|
841
|
+
export { ASSETS_SEED_DIR, ASSETS_STAMP_FILE, SCAFFOLD_COMPATIBILITY_DATE, SCAFFOLD_CONFIG_CONTENT, SCAFFOLD_ENTRY_CONTENT, SCAFFOLD_ENTRY_PATH, SCAFFOLD_KV_PLACEHOLDER_ID, SCAFFOLD_MAPS_CONTENT, SETUP_FIELDS, ScaffoldError, applySetup, buildScaffoldFiles, createProject, generateAdminToken, generateSecret, parseDevVars, parseJsoncObject, prepareWorkerAssets, readCajonzeroPackage, readSetupValues, readWranglerAssetsDirectory, readWranglerKvNamespaceId, serializeDevVars, setWranglerKvNamespaceId, setWranglerVars, suggestedValue, toPackageName };
|
|
581
842
|
//# sourceMappingURL=scaffold.js.map
|
|
582
843
|
//# sourceMappingURL=scaffold.js.map
|
package/dist/serve.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExecutionContext } from 'hono';
|
|
2
|
-
import { R as Room, D as DurableObjectNamespace, b as Env } from './providers-
|
|
2
|
+
import { R as Room, D as DurableObjectNamespace, b as Env } from './providers-BwJKzGkd.js';
|
|
3
3
|
import { StorageSource, EnvProvider, SettingDefaults } from './core.js';
|
|
4
4
|
import 'unstorage';
|
|
5
5
|
import 'gl-matrix';
|