@plume-press/cli 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.mjs +181 -445
- package/dist/local.mjs +7 -37
- package/dist/schema.d.ts +1 -7
- package/dist/schema.mjs +6 -19
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -3494,15 +3494,15 @@ var init_schemas = __esm({
|
|
|
3494
3494
|
const syms = normalized.symbolKeys;
|
|
3495
3495
|
const doc = new Doc(["payload", "ctx"], { shape, inst, memo: memo2, syms });
|
|
3496
3496
|
const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
3497
|
-
const prefixStr = (
|
|
3498
|
-
let ${
|
|
3499
|
-
for (let i = 0; i < ${
|
|
3500
|
-
const iss = ${
|
|
3497
|
+
const prefixStr = (id2, k) => `
|
|
3498
|
+
let ${id2}_ab = false;
|
|
3499
|
+
for (let i = 0; i < ${id2}.issues.length; i++) {
|
|
3500
|
+
const iss = ${id2}.issues[i];
|
|
3501
3501
|
iss.path = iss.path ? [${k}, ...iss.path] : [${k}];
|
|
3502
3502
|
payload.issues.push(iss);
|
|
3503
|
-
if (iss.continue !== true) ${
|
|
3503
|
+
if (iss.continue !== true) ${id2}_ab = true;
|
|
3504
3504
|
}
|
|
3505
|
-
if (${
|
|
3505
|
+
if (${id2}_ab && ctx && ctx.abortEarly) {
|
|
3506
3506
|
payload.value = newResult;
|
|
3507
3507
|
return payload;
|
|
3508
3508
|
}`;
|
|
@@ -3516,34 +3516,34 @@ var init_schemas = __esm({
|
|
|
3516
3516
|
for (const key3 of normalized.allKeys) {
|
|
3517
3517
|
if (key3 === "__proto__")
|
|
3518
3518
|
continue;
|
|
3519
|
-
const
|
|
3519
|
+
const id2 = ids2[key3];
|
|
3520
3520
|
const k = typeof key3 === "symbol" ? `syms[${syms.indexOf(key3)}]` : esc(key3);
|
|
3521
3521
|
const isPresent = `${k} in input`;
|
|
3522
3522
|
const schema3 = shape[key3];
|
|
3523
3523
|
const optin = schema3?._zod?.optin;
|
|
3524
3524
|
const isOptionalIn = optin !== void 0;
|
|
3525
3525
|
const isOptionalOut = schema3?._zod?.optout === "optional";
|
|
3526
|
-
doc.write(`const ${
|
|
3526
|
+
doc.write(`const ${id2} = ${parseStr(k)};`);
|
|
3527
3527
|
if (isOptionalIn && isOptionalOut) {
|
|
3528
|
-
const assign = optin === "optional" ? `${
|
|
3528
|
+
const assign = optin === "optional" ? `${id2}_present` : `${id2}.value !== undefined || ${id2}_present`;
|
|
3529
3529
|
doc.write(`
|
|
3530
|
-
const ${
|
|
3531
|
-
if (!${
|
|
3532
|
-
if (${
|
|
3530
|
+
const ${id2}_present = ${isPresent};
|
|
3531
|
+
if (!${id2}.issues.length || ${id2}_present) {
|
|
3532
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
3533
3533
|
}
|
|
3534
3534
|
|
|
3535
3535
|
if (${assign}) {
|
|
3536
|
-
newResult[${k}] = ${
|
|
3536
|
+
newResult[${k}] = ${id2}.value;
|
|
3537
3537
|
}
|
|
3538
3538
|
}
|
|
3539
3539
|
|
|
3540
3540
|
`);
|
|
3541
3541
|
} else if (!isOptionalIn) {
|
|
3542
3542
|
doc.write(`
|
|
3543
|
-
const ${
|
|
3544
|
-
if (${
|
|
3543
|
+
const ${id2}_present = ${isPresent};
|
|
3544
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
3545
3545
|
}
|
|
3546
|
-
if (!${
|
|
3546
|
+
if (!${id2}_present && !${id2}.issues.length) {
|
|
3547
3547
|
payload.issues.push({
|
|
3548
3548
|
code: "invalid_type",
|
|
3549
3549
|
expected: "nonoptional",
|
|
@@ -3556,22 +3556,22 @@ var init_schemas = __esm({
|
|
|
3556
3556
|
}
|
|
3557
3557
|
}
|
|
3558
3558
|
|
|
3559
|
-
if (${
|
|
3560
|
-
newResult[${k}] = ${
|
|
3559
|
+
if (${id2}_present) {
|
|
3560
|
+
newResult[${k}] = ${id2}.value;
|
|
3561
3561
|
}
|
|
3562
3562
|
|
|
3563
3563
|
`);
|
|
3564
3564
|
} else {
|
|
3565
3565
|
doc.write(`
|
|
3566
|
-
if (${
|
|
3566
|
+
if (${id2}.issues.length) {${prefixStr(id2, k)}
|
|
3567
3567
|
}
|
|
3568
3568
|
`);
|
|
3569
3569
|
if (optin === "defaulted") {
|
|
3570
|
-
doc.write(`newResult[${k}] = ${
|
|
3570
|
+
doc.write(`newResult[${k}] = ${id2}.value;`);
|
|
3571
3571
|
} else {
|
|
3572
3572
|
doc.write(`
|
|
3573
|
-
if (${
|
|
3574
|
-
newResult[${k}] = ${
|
|
3573
|
+
if (${id2}.value !== undefined || ${isPresent}) {
|
|
3574
|
+
newResult[${k}] = ${id2}.value;
|
|
3575
3575
|
}
|
|
3576
3576
|
`);
|
|
3577
3577
|
}
|
|
@@ -4537,7 +4537,7 @@ function isRef(value) {
|
|
|
4537
4537
|
function cloneIssues(issues) {
|
|
4538
4538
|
return issues.map((iss) => iss.path ? { ...iss, path: iss.path.slice() } : { ...iss });
|
|
4539
4539
|
}
|
|
4540
|
-
function isRecursive(inst, stack,
|
|
4540
|
+
function isRecursive(inst, stack, resolve7) {
|
|
4541
4541
|
const cached2 = recursive.get(inst);
|
|
4542
4542
|
if (cached2 !== void 0)
|
|
4543
4543
|
return cached2 ? PROVEN : NONE;
|
|
@@ -4547,7 +4547,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
4547
4547
|
let result = NONE;
|
|
4548
4548
|
const check2 = (child) => {
|
|
4549
4549
|
if (result !== PROVEN && child?._zod) {
|
|
4550
|
-
const answer = isRecursive(child, stack,
|
|
4550
|
+
const answer = isRecursive(child, stack, resolve7);
|
|
4551
4551
|
if (answer > result)
|
|
4552
4552
|
result = answer;
|
|
4553
4553
|
}
|
|
@@ -4558,7 +4558,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
4558
4558
|
const desc = Object.getOwnPropertyDescriptor(sh, key3);
|
|
4559
4559
|
if (spread && !desc.enumerable)
|
|
4560
4560
|
continue;
|
|
4561
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
4561
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve7) : NONE;
|
|
4562
4562
|
if (child > answer)
|
|
4563
4563
|
answer = child;
|
|
4564
4564
|
}
|
|
@@ -4622,7 +4622,7 @@ function isRecursive(inst, stack, resolve8) {
|
|
|
4622
4622
|
break;
|
|
4623
4623
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
4624
4624
|
case "lazy": {
|
|
4625
|
-
const inner = def._cachedInner ?? (
|
|
4625
|
+
const inner = def._cachedInner ?? (resolve7 ? inst._zod.innerType : void 0);
|
|
4626
4626
|
merge3(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
4627
4627
|
break;
|
|
4628
4628
|
}
|
|
@@ -15669,26 +15669,26 @@ function extractDefs(ctx, schema3) {
|
|
|
15669
15669
|
return;
|
|
15670
15670
|
const idToSchema = /* @__PURE__ */ new Map();
|
|
15671
15671
|
for (const entry of ctx.seen.entries()) {
|
|
15672
|
-
const
|
|
15673
|
-
if (
|
|
15674
|
-
const existing = idToSchema.get(
|
|
15672
|
+
const id2 = ctx.metadataRegistry.get(entry[0])?.id;
|
|
15673
|
+
if (id2) {
|
|
15674
|
+
const existing = idToSchema.get(id2);
|
|
15675
15675
|
if (existing && existing !== entry[0]) {
|
|
15676
|
-
throw new Error(`Duplicate schema id "${
|
|
15676
|
+
throw new Error(`Duplicate schema id "${id2}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
|
|
15677
15677
|
}
|
|
15678
|
-
idToSchema.set(
|
|
15678
|
+
idToSchema.set(id2, entry[0]);
|
|
15679
15679
|
}
|
|
15680
15680
|
}
|
|
15681
15681
|
const makeURI = (entry) => {
|
|
15682
15682
|
const defsSegment = ctx.target === "draft-2020-12" ? "$defs" : "definitions";
|
|
15683
15683
|
if (ctx.external) {
|
|
15684
15684
|
const externalId = ctx.external.registry.get(entry[0])?.id;
|
|
15685
|
-
const uriGenerator = ctx.external.uri ?? ((
|
|
15685
|
+
const uriGenerator = ctx.external.uri ?? ((id3) => id3);
|
|
15686
15686
|
if (externalId) {
|
|
15687
15687
|
return { ref: uriGenerator(externalId) };
|
|
15688
15688
|
}
|
|
15689
|
-
const
|
|
15690
|
-
entry[1].defId =
|
|
15691
|
-
return { defId:
|
|
15689
|
+
const id2 = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
|
|
15690
|
+
entry[1].defId = id2;
|
|
15691
|
+
return { defId: id2, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id2)}` };
|
|
15692
15692
|
}
|
|
15693
15693
|
const uriPrefix = `#`;
|
|
15694
15694
|
const defUriPrefix = `${uriPrefix}/${defsSegment}/`;
|
|
@@ -15736,8 +15736,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15736
15736
|
continue;
|
|
15737
15737
|
}
|
|
15738
15738
|
}
|
|
15739
|
-
const
|
|
15740
|
-
if (
|
|
15739
|
+
const id2 = ctx.metadataRegistry.get(entry[0])?.id;
|
|
15740
|
+
if (id2) {
|
|
15741
15741
|
extractToDef(entry);
|
|
15742
15742
|
continue;
|
|
15743
15743
|
}
|
|
@@ -15968,10 +15968,10 @@ function finalize(ctx, schema3) {
|
|
|
15968
15968
|
} else {
|
|
15969
15969
|
}
|
|
15970
15970
|
if (ctx.external?.uri) {
|
|
15971
|
-
const
|
|
15972
|
-
if (!
|
|
15971
|
+
const id2 = ctx.external.registry.get(schema3)?.id;
|
|
15972
|
+
if (!id2)
|
|
15973
15973
|
throw new Error("Schema is missing an `id` property");
|
|
15974
|
-
result.$id = ctx.external.uri(
|
|
15974
|
+
result.$id = ctx.external.uri(id2);
|
|
15975
15975
|
}
|
|
15976
15976
|
assignProps(result, root3.defId ? root3.schema : root3.def ?? root3.schema);
|
|
15977
15977
|
const rootMetaId = ctx.metadataRegistry.get(schema3)?.id;
|
|
@@ -16157,7 +16157,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
|
|
|
16157
16157
|
const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
|
|
16158
16158
|
if (!numericType && !values?.some((v) => typeof v === "number"))
|
|
16159
16159
|
return json2;
|
|
16160
|
-
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id:
|
|
16160
|
+
const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id: id2, ...rest } = json2;
|
|
16161
16161
|
if (rest.enum)
|
|
16162
16162
|
rest.enum = rest.enum.map((v) => typeof v === "number" ? String(v) : v);
|
|
16163
16163
|
else if (typeof rest.const === "number")
|
|
@@ -29711,9 +29711,9 @@ var init_parser = __esm({
|
|
|
29711
29711
|
}
|
|
29712
29712
|
//Special elements
|
|
29713
29713
|
/** @protected */
|
|
29714
|
-
_isSpecialElement(element4,
|
|
29714
|
+
_isSpecialElement(element4, id2) {
|
|
29715
29715
|
const ns = this.treeAdapter.getNamespaceURI(element4);
|
|
29716
|
-
return SPECIAL_ELEMENTS[ns].has(
|
|
29716
|
+
return SPECIAL_ELEMENTS[ns].has(id2);
|
|
29717
29717
|
}
|
|
29718
29718
|
/** @internal */
|
|
29719
29719
|
onCharacter(token) {
|
|
@@ -32323,8 +32323,8 @@ function zwitch(key3, options2) {
|
|
|
32323
32323
|
let fn = one3.invalid;
|
|
32324
32324
|
const handlers = one3.handlers;
|
|
32325
32325
|
if (value && own4.call(value, key3)) {
|
|
32326
|
-
const
|
|
32327
|
-
fn = own4.call(handlers,
|
|
32326
|
+
const id2 = String(value[key3]);
|
|
32327
|
+
fn = own4.call(handlers, id2) ? handlers[id2] : one3.unknown;
|
|
32328
32328
|
}
|
|
32329
32329
|
if (fn) {
|
|
32330
32330
|
return fn.call(this, value, ...parameters);
|
|
@@ -33975,7 +33975,7 @@ var init_lib18 = __esm({
|
|
|
33975
33975
|
assertParser("process", this.parser || this.Parser);
|
|
33976
33976
|
assertCompiler("process", this.compiler || this.Compiler);
|
|
33977
33977
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
33978
|
-
function executor(
|
|
33978
|
+
function executor(resolve7, reject) {
|
|
33979
33979
|
const realFile = vfile(file2);
|
|
33980
33980
|
const parseTree = (
|
|
33981
33981
|
/** @type {HeadTree extends undefined ? Node : HeadTree} */
|
|
@@ -34006,8 +34006,8 @@ var init_lib18 = __esm({
|
|
|
34006
34006
|
function realDone(error62, file3) {
|
|
34007
34007
|
if (error62 || !file3) {
|
|
34008
34008
|
reject(error62);
|
|
34009
|
-
} else if (
|
|
34010
|
-
|
|
34009
|
+
} else if (resolve7) {
|
|
34010
|
+
resolve7(file3);
|
|
34011
34011
|
} else {
|
|
34012
34012
|
ok(done, "`done` is defined if `resolve` is not");
|
|
34013
34013
|
done(void 0, file3);
|
|
@@ -34109,7 +34109,7 @@ var init_lib18 = __esm({
|
|
|
34109
34109
|
file2 = void 0;
|
|
34110
34110
|
}
|
|
34111
34111
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
34112
|
-
function executor(
|
|
34112
|
+
function executor(resolve7, reject) {
|
|
34113
34113
|
ok(
|
|
34114
34114
|
typeof file2 !== "function",
|
|
34115
34115
|
"`file` can\u2019t be a `done` anymore, we checked"
|
|
@@ -34123,8 +34123,8 @@ var init_lib18 = __esm({
|
|
|
34123
34123
|
);
|
|
34124
34124
|
if (error62) {
|
|
34125
34125
|
reject(error62);
|
|
34126
|
-
} else if (
|
|
34127
|
-
|
|
34126
|
+
} else if (resolve7) {
|
|
34127
|
+
resolve7(resultingTree);
|
|
34128
34128
|
} else {
|
|
34129
34129
|
ok(done, "`done` is defined if `resolve` is not");
|
|
34130
34130
|
done(void 0, resultingTree, file3);
|
|
@@ -34365,18 +34365,18 @@ function normalizeYouTubeEmbedUrl(value) {
|
|
|
34365
34365
|
if (url2.protocol !== "https:" || url2.username || url2.password || url2.port || url2.hash)
|
|
34366
34366
|
return null;
|
|
34367
34367
|
const host = url2.hostname;
|
|
34368
|
-
let
|
|
34368
|
+
let id2 = null;
|
|
34369
34369
|
if (host === "youtube.com" || host === "www.youtube.com") {
|
|
34370
34370
|
if (url2.pathname !== "/watch") return null;
|
|
34371
34371
|
const values = url2.searchParams.getAll("v");
|
|
34372
34372
|
if (values.length !== 1) return null;
|
|
34373
|
-
|
|
34373
|
+
id2 = values[0] ?? null;
|
|
34374
34374
|
} else if (host === "youtu.be") {
|
|
34375
|
-
|
|
34375
|
+
id2 = /^\/([A-Za-z0-9_-]{11})$/.exec(url2.pathname)?.[1] ?? null;
|
|
34376
34376
|
} else if (host === "youtube-nocookie.com" || host === "www.youtube-nocookie.com") {
|
|
34377
|
-
|
|
34377
|
+
id2 = /^\/embed\/([A-Za-z0-9_-]{11})$/.exec(url2.pathname)?.[1] ?? null;
|
|
34378
34378
|
}
|
|
34379
|
-
return
|
|
34379
|
+
return id2 && YOUTUBE_ID.test(id2) ? `${EMBED_PREFIX}${id2}` : null;
|
|
34380
34380
|
}
|
|
34381
34381
|
function videoNode(src) {
|
|
34382
34382
|
return {
|
|
@@ -34400,19 +34400,19 @@ function videoNode(src) {
|
|
|
34400
34400
|
]
|
|
34401
34401
|
};
|
|
34402
34402
|
}
|
|
34403
|
-
function imageNode(
|
|
34403
|
+
function imageNode(id2, alt) {
|
|
34404
34404
|
return {
|
|
34405
34405
|
type: "element",
|
|
34406
34406
|
tagName: "img",
|
|
34407
|
-
properties: { "data-plume-asset-id":
|
|
34407
|
+
properties: { "data-plume-asset-id": id2.toLowerCase(), alt },
|
|
34408
34408
|
children: []
|
|
34409
34409
|
};
|
|
34410
34410
|
}
|
|
34411
34411
|
function imageReference(node2) {
|
|
34412
34412
|
const properties2 = node2.properties ?? {};
|
|
34413
|
-
const
|
|
34413
|
+
const id2 = properties2["data-plume-asset-id"] ?? properties2.dataPlumeAssetId;
|
|
34414
34414
|
const alt = properties2.alt;
|
|
34415
|
-
return typeof
|
|
34415
|
+
return typeof id2 === "string" && ASSET_ID.test(id2) && typeof alt === "string" && alt.length <= 1024 ? { id: id2.toLowerCase(), alt } : null;
|
|
34416
34416
|
}
|
|
34417
34417
|
function normalizedChildren(node2) {
|
|
34418
34418
|
const output2 = [];
|
|
@@ -34656,13 +34656,6 @@ function named(value, path) {
|
|
|
34656
34656
|
);
|
|
34657
34657
|
}
|
|
34658
34658
|
function defineSchema(schema3) {
|
|
34659
|
-
return checkSchema(schema3);
|
|
34660
|
-
}
|
|
34661
|
-
function readStoredSchema(schema3, ignored = () => {
|
|
34662
|
-
}) {
|
|
34663
|
-
return checkSchema(schema3, ignored);
|
|
34664
|
-
}
|
|
34665
|
-
function checkSchema(schema3, ignoredPreviewPath) {
|
|
34666
34659
|
canonicalJson(schema3);
|
|
34667
34660
|
assert2(object2(schema3), "expected object");
|
|
34668
34661
|
allowedKeys(schema3, ["collections", "singletons"], "schema");
|
|
@@ -34796,16 +34789,11 @@ function checkSchema(schema3, ignoredPreviewPath) {
|
|
|
34796
34789
|
entities.add(entityName);
|
|
34797
34790
|
validateFields2(entity2.fields, entityName, false);
|
|
34798
34791
|
if ("previewPath" in entity2)
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34803
|
-
|
|
34804
|
-
);
|
|
34805
|
-
} catch (error62) {
|
|
34806
|
-
if (!ignoredPreviewPath) throw error62;
|
|
34807
|
-
ignoredPreviewPath(error62.message);
|
|
34808
|
-
}
|
|
34792
|
+
validatePreviewPath(
|
|
34793
|
+
entityName,
|
|
34794
|
+
entity2.previewPath,
|
|
34795
|
+
isCollection ? entity2.fields : null
|
|
34796
|
+
);
|
|
34809
34797
|
}
|
|
34810
34798
|
return schema3;
|
|
34811
34799
|
}
|
|
@@ -34842,7 +34830,7 @@ function validatePreviewPath(entity2, path, fields) {
|
|
|
34842
34830
|
);
|
|
34843
34831
|
}
|
|
34844
34832
|
async function schemaHash(schema3) {
|
|
34845
|
-
|
|
34833
|
+
defineSchema(schema3);
|
|
34846
34834
|
const bytes2 = new TextEncoder().encode(
|
|
34847
34835
|
canonicalJson(schema3)
|
|
34848
34836
|
);
|
|
@@ -34927,14 +34915,14 @@ function validateValue(field, v, path, publication, report) {
|
|
|
34927
34915
|
break;
|
|
34928
34916
|
}
|
|
34929
34917
|
case "reference": {
|
|
34930
|
-
const
|
|
34918
|
+
const id2 = (item, itemPath) => {
|
|
34931
34919
|
if (typeof item !== "string")
|
|
34932
34920
|
report(itemPath, "type", "Expected record ID");
|
|
34933
34921
|
else if (item.trim() === "")
|
|
34934
34922
|
report(itemPath, "format", "Record ID cannot be empty");
|
|
34935
34923
|
};
|
|
34936
|
-
if (field.multiple) distinct("record ID array",
|
|
34937
|
-
else
|
|
34924
|
+
if (field.multiple) distinct("record ID array", id2);
|
|
34925
|
+
else id2(v, path);
|
|
34938
34926
|
break;
|
|
34939
34927
|
}
|
|
34940
34928
|
case "link":
|
|
@@ -35030,7 +35018,7 @@ function stripNullFields(fields, data) {
|
|
|
35030
35018
|
}
|
|
35031
35019
|
function referenceIds(value) {
|
|
35032
35020
|
if (typeof value === "string") return [value];
|
|
35033
|
-
return Array.isArray(value) ? value.filter((
|
|
35021
|
+
return Array.isArray(value) ? value.filter((id2) => typeof id2 === "string") : [];
|
|
35034
35022
|
}
|
|
35035
35023
|
function dropMissingReferences(fields, data, exists) {
|
|
35036
35024
|
let changed = false;
|
|
@@ -35039,7 +35027,7 @@ function dropMissingReferences(fields, data, exists) {
|
|
|
35039
35027
|
const value = result[field.name];
|
|
35040
35028
|
if (field.kind === "reference" && !field.required && value != null) {
|
|
35041
35029
|
const ids2 = referenceIds(value);
|
|
35042
|
-
const kept = ids2.filter((
|
|
35030
|
+
const kept = ids2.filter((id2) => exists(field.collection, id2));
|
|
35043
35031
|
if (kept.length === ids2.length) continue;
|
|
35044
35032
|
changed = true;
|
|
35045
35033
|
if (Array.isArray(value) && kept.length) result[field.name] = kept;
|
|
@@ -35280,7 +35268,7 @@ async function validateSnapshot(input2, preparation, options2) {
|
|
|
35280
35268
|
"",
|
|
35281
35269
|
"Normalized content exceeds the validation size limit."
|
|
35282
35270
|
);
|
|
35283
|
-
const exists = (collection,
|
|
35271
|
+
const exists = (collection, id2) => lookup.has(key2(collection, id2));
|
|
35284
35272
|
for (const record3 of records) {
|
|
35285
35273
|
const resolved = dropMissingReferences(
|
|
35286
35274
|
entities.get(record3.collection)?.fields ?? [],
|
|
@@ -35351,8 +35339,8 @@ async function validateSnapshot(input2, preparation, options2) {
|
|
|
35351
35339
|
if (value === void 0 || value === null) continue;
|
|
35352
35340
|
const path = `${prefix}.${field.name}`;
|
|
35353
35341
|
if (field.kind === "reference") {
|
|
35354
|
-
for (const
|
|
35355
|
-
const target = lookup.get(key2(field.collection,
|
|
35342
|
+
for (const id2 of referenceIds(value)) {
|
|
35343
|
+
const target = lookup.get(key2(field.collection, id2));
|
|
35356
35344
|
if (!target)
|
|
35357
35345
|
fail(
|
|
35358
35346
|
"INVALID_REFERENCE",
|
|
@@ -35451,7 +35439,7 @@ var init_baseline = __esm({
|
|
|
35451
35439
|
external_exports.strictObject({
|
|
35452
35440
|
collection: external_exports.string().regex(/^[A-Za-z][A-Za-z0-9_]*$/).max(100),
|
|
35453
35441
|
recordId: external_exports.string().min(1).max(256).refine(
|
|
35454
|
-
(
|
|
35442
|
+
(id2) => id2.trim().length > 0 && id2 !== "." && id2 !== ".." && Array.from(id2).every(
|
|
35455
35443
|
(character) => character.charCodeAt(0) >= 32 && character.charCodeAt(0) !== 127
|
|
35456
35444
|
)
|
|
35457
35445
|
),
|
|
@@ -35461,7 +35449,7 @@ var init_baseline = __esm({
|
|
|
35461
35449
|
).max(maximumRecords)
|
|
35462
35450
|
});
|
|
35463
35451
|
bytes = (value) => new TextEncoder().encode(value).byteLength;
|
|
35464
|
-
key2 = (collection,
|
|
35452
|
+
key2 = (collection, id2) => JSON.stringify([collection, id2]);
|
|
35465
35453
|
compareRecords = (a, b) => a.collection < b.collection ? -1 : a.collection > b.collection ? 1 : a.recordId < b.recordId ? -1 : a.recordId > b.recordId ? 1 : 0;
|
|
35466
35454
|
}
|
|
35467
35455
|
});
|
|
@@ -35884,7 +35872,9 @@ async function runLocalPrepare(options2) {
|
|
|
35884
35872
|
"Finish starting this Update before preparing it."
|
|
35885
35873
|
);
|
|
35886
35874
|
await verifyCheckout(resolve(options2.cwd), inspect2, input2);
|
|
35887
|
-
const localSchema = await
|
|
35875
|
+
const localSchema = await stat(
|
|
35876
|
+
resolve(options2.cwd, "plume.schema.ts")
|
|
35877
|
+
).catch(() => null) ? await loadCheckoutSchema(resolve(options2.cwd)) : defineSchema({ collections: [] });
|
|
35888
35878
|
if (await schemaHash(localSchema) !== inspect2.schemaHash)
|
|
35889
35879
|
throw new PlumeToolError(
|
|
35890
35880
|
"SCHEMA_MISMATCH",
|
|
@@ -36281,23 +36271,6 @@ async function safePath(cwd, create2) {
|
|
|
36281
36271
|
);
|
|
36282
36272
|
return path;
|
|
36283
36273
|
}
|
|
36284
|
-
function addTimestamps(db) {
|
|
36285
|
-
const missing = () => !db.prepare("PRAGMA table_info(local_records)").all().some((column) => column.name === "created_at");
|
|
36286
|
-
if (!missing() && !db.prepare(
|
|
36287
|
-
"SELECT 1 FROM local_records WHERE created_at IS NULL OR updated_at IS NULL LIMIT 1"
|
|
36288
|
-
).get())
|
|
36289
|
-
return;
|
|
36290
|
-
transaction(db, () => {
|
|
36291
|
-
if (missing()) {
|
|
36292
|
-
db.exec("ALTER TABLE local_records ADD COLUMN created_at INTEGER");
|
|
36293
|
-
db.exec("ALTER TABLE local_records ADD COLUMN updated_at INTEGER");
|
|
36294
|
-
}
|
|
36295
|
-
const now = Date.now();
|
|
36296
|
-
db.prepare(
|
|
36297
|
-
"UPDATE local_records SET created_at = coalesce(created_at, ?), updated_at = coalesce(updated_at, created_at, ?) WHERE created_at IS NULL OR updated_at IS NULL"
|
|
36298
|
-
).run(now, now);
|
|
36299
|
-
});
|
|
36300
|
-
}
|
|
36301
36274
|
function meta3(db) {
|
|
36302
36275
|
return db.prepare("SELECT schema, revision FROM local_meta WHERE id = 1").get();
|
|
36303
36276
|
}
|
|
@@ -36323,11 +36296,11 @@ function entity(schema3, name3) {
|
|
|
36323
36296
|
if (singleton) return { fields: singleton.fields, singleton: true };
|
|
36324
36297
|
throw new Error(`Unknown collection or singleton: ${name3}`);
|
|
36325
36298
|
}
|
|
36326
|
-
function identity(schema3, name3,
|
|
36299
|
+
function identity(schema3, name3, id2) {
|
|
36327
36300
|
const found = entity(schema3, name3);
|
|
36328
|
-
if (typeof
|
|
36301
|
+
if (typeof id2 !== "string" || id2.trim() === "")
|
|
36329
36302
|
throw new Error("Record ID cannot be empty.");
|
|
36330
|
-
if (found.singleton &&
|
|
36303
|
+
if (found.singleton && id2 !== "singleton")
|
|
36331
36304
|
throw new Error('Singleton records must use the ID "singleton".');
|
|
36332
36305
|
return found.fields;
|
|
36333
36306
|
}
|
|
@@ -36351,8 +36324,8 @@ function validateSnapshot2(schema3, all3, changed) {
|
|
|
36351
36324
|
const value = record3[field.name];
|
|
36352
36325
|
const fieldPath = path ? `${path}.${field.name}` : field.name;
|
|
36353
36326
|
if (field.kind === "reference")
|
|
36354
|
-
for (const
|
|
36355
|
-
retainedReferences.add(`${fieldPath}\0${
|
|
36327
|
+
for (const id2 of referenceIds(value))
|
|
36328
|
+
retainedReferences.add(`${fieldPath}\0${id2}`);
|
|
36356
36329
|
else if (field.kind === "list" && Array.isArray(value))
|
|
36357
36330
|
for (const item of value)
|
|
36358
36331
|
collectReferences2(field.fields, item, fieldPath);
|
|
@@ -36363,9 +36336,9 @@ function validateSnapshot2(schema3, all3, changed) {
|
|
|
36363
36336
|
if (value === void 0 || value === null) continue;
|
|
36364
36337
|
const fieldPath = path ? `${path}.${field.name}` : field.name;
|
|
36365
36338
|
if (field.kind === "reference") {
|
|
36366
|
-
for (const
|
|
36367
|
-
const target = lookup.get(`${field.collection}\0${
|
|
36368
|
-
const unchangedMissing = !field.required && (!changedRow || retainedReferences.has(`${fieldPath}\0${
|
|
36339
|
+
for (const id2 of referenceIds(value)) {
|
|
36340
|
+
const target = lookup.get(`${field.collection}\0${id2}`);
|
|
36341
|
+
const unchangedMissing = !field.required && (!changedRow || retainedReferences.has(`${fieldPath}\0${id2}`));
|
|
36369
36342
|
if (!target && !unchangedMissing)
|
|
36370
36343
|
throw new Error(
|
|
36371
36344
|
`Missing reference at ${row.collection}/${row.record_id}.${fieldPath}.`
|
|
@@ -36468,12 +36441,12 @@ function fromRow(row, schema3, lookup) {
|
|
|
36468
36441
|
for (const field of fields) {
|
|
36469
36442
|
const value = record3[field.name];
|
|
36470
36443
|
if (field.kind === "reference" && !field.required) {
|
|
36471
|
-
const exists = (
|
|
36444
|
+
const exists = (id2) => lookup.has(`${field.collection}\0${id2}`);
|
|
36472
36445
|
if (typeof value === "string" && !exists(value))
|
|
36473
36446
|
record3[field.name] = null;
|
|
36474
36447
|
else if (Array.isArray(value))
|
|
36475
36448
|
record3[field.name] = value.map(
|
|
36476
|
-
(
|
|
36449
|
+
(id2) => typeof id2 === "string" && exists(id2) ? id2 : null
|
|
36477
36450
|
);
|
|
36478
36451
|
} else if (field.kind === "list" && Array.isArray(value))
|
|
36479
36452
|
for (const item of value)
|
|
@@ -36503,7 +36476,6 @@ async function open2(path, expected) {
|
|
|
36503
36476
|
db.exec("PRAGMA busy_timeout = 5000");
|
|
36504
36477
|
const stored = meta3(db);
|
|
36505
36478
|
if (!stored) throw new Error("Local content database is not initialized.");
|
|
36506
|
-
addTimestamps(db);
|
|
36507
36479
|
let schema3 = defineSchema(JSON.parse(stored.schema));
|
|
36508
36480
|
if (expected && canonicalJson(schema3) !== canonicalJson(expected))
|
|
36509
36481
|
throw new Error(
|
|
@@ -36692,7 +36664,7 @@ async function openLocalStore(input2) {
|
|
|
36692
36664
|
"CREATE TABLE local_meta (id INTEGER PRIMARY KEY CHECK(id = 1), schema TEXT NOT NULL, revision INTEGER NOT NULL)"
|
|
36693
36665
|
);
|
|
36694
36666
|
db.exec(
|
|
36695
|
-
"CREATE TABLE local_records (collection TEXT NOT NULL, record_id TEXT NOT NULL, data TEXT NOT NULL, visibility TEXT NOT NULL CHECK(visibility IN ('draft', 'public')), created_at INTEGER, updated_at INTEGER, PRIMARY KEY(collection, record_id))"
|
|
36667
|
+
"CREATE TABLE local_records (collection TEXT NOT NULL, record_id TEXT NOT NULL, data TEXT NOT NULL, visibility TEXT NOT NULL CHECK(visibility IN ('draft', 'public')), created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL, PRIMARY KEY(collection, record_id))"
|
|
36696
36668
|
);
|
|
36697
36669
|
db.prepare(
|
|
36698
36670
|
"INSERT INTO local_meta (id, schema, revision) VALUES (1, ?, 0)"
|
|
@@ -36731,7 +36703,7 @@ var init_package = __esm({
|
|
|
36731
36703
|
"packages/sdk/package.json"() {
|
|
36732
36704
|
package_default = {
|
|
36733
36705
|
name: "@plume-press/sdk",
|
|
36734
|
-
version: "0.
|
|
36706
|
+
version: "0.3.0",
|
|
36735
36707
|
private: true,
|
|
36736
36708
|
license: "MIT",
|
|
36737
36709
|
type: "module",
|
|
@@ -36758,7 +36730,7 @@ var init_package2 = __esm({
|
|
|
36758
36730
|
"packages/cli/package.json"() {
|
|
36759
36731
|
package_default2 = {
|
|
36760
36732
|
name: "@plume-press/cli",
|
|
36761
|
-
version: "0.
|
|
36733
|
+
version: "0.6.0",
|
|
36762
36734
|
private: true,
|
|
36763
36735
|
license: "MIT",
|
|
36764
36736
|
type: "module",
|
|
@@ -36793,11 +36765,11 @@ __export(local_exports, {
|
|
|
36793
36765
|
PlumeLocalError: () => PlumeLocalError,
|
|
36794
36766
|
localHelp: () => localHelp,
|
|
36795
36767
|
runLocalCommand: () => runLocalCommand,
|
|
36796
|
-
runLocalInit: () =>
|
|
36768
|
+
runLocalInit: () => runLocalInit
|
|
36797
36769
|
});
|
|
36798
|
-
import { constants as
|
|
36799
|
-
import { lstat as lstat3, mkdir as mkdir3, open as
|
|
36800
|
-
import { resolve as
|
|
36770
|
+
import { constants as constants2 } from "node:fs";
|
|
36771
|
+
import { lstat as lstat3, mkdir as mkdir3, open as open3 } from "node:fs/promises";
|
|
36772
|
+
import { resolve as resolve5 } from "node:path";
|
|
36801
36773
|
function assertRuntime() {
|
|
36802
36774
|
const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
|
|
36803
36775
|
if (major < 22 || major === 22 && minor < 13)
|
|
@@ -36836,9 +36808,9 @@ async function writeAbsent(path, content2) {
|
|
|
36836
36808
|
if (kind !== "missing")
|
|
36837
36809
|
throw new PlumeLocalError("UNSAFE_PATH", `${path} must be a regular file.`);
|
|
36838
36810
|
try {
|
|
36839
|
-
const handle2 = await
|
|
36811
|
+
const handle2 = await open3(
|
|
36840
36812
|
path,
|
|
36841
|
-
|
|
36813
|
+
constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW,
|
|
36842
36814
|
420
|
|
36843
36815
|
);
|
|
36844
36816
|
try {
|
|
@@ -36855,7 +36827,7 @@ async function writeAbsent(path, content2) {
|
|
|
36855
36827
|
}
|
|
36856
36828
|
}
|
|
36857
36829
|
async function ignoreLocalDatabase(cwd) {
|
|
36858
|
-
const path =
|
|
36830
|
+
const path = resolve5(cwd, ".gitignore");
|
|
36859
36831
|
const kind = await inspect(path);
|
|
36860
36832
|
if (kind !== "missing" && kind !== "file")
|
|
36861
36833
|
throw new PlumeLocalError(
|
|
@@ -36864,9 +36836,9 @@ async function ignoreLocalDatabase(cwd) {
|
|
|
36864
36836
|
);
|
|
36865
36837
|
let handle2;
|
|
36866
36838
|
try {
|
|
36867
|
-
handle2 = await
|
|
36839
|
+
handle2 = await open3(
|
|
36868
36840
|
path,
|
|
36869
|
-
|
|
36841
|
+
constants2.O_RDWR | constants2.O_CREAT | constants2.O_NOFOLLOW,
|
|
36870
36842
|
420
|
|
36871
36843
|
);
|
|
36872
36844
|
if (!(await handle2.stat()).isFile())
|
|
@@ -36885,11 +36857,11 @@ async function ignoreLocalDatabase(cwd) {
|
|
|
36885
36857
|
}
|
|
36886
36858
|
}
|
|
36887
36859
|
async function pinPlumePackages(cwd) {
|
|
36888
|
-
const path =
|
|
36860
|
+
const path = resolve5(cwd, "package.json");
|
|
36889
36861
|
if (await inspect(path) === "missing") return null;
|
|
36890
36862
|
let handle2;
|
|
36891
36863
|
try {
|
|
36892
|
-
handle2 = await
|
|
36864
|
+
handle2 = await open3(path, constants2.O_RDWR | constants2.O_NOFOLLOW);
|
|
36893
36865
|
if (!(await handle2.stat()).isFile()) throw new Error();
|
|
36894
36866
|
const text3 = await handle2.readFile({ encoding: "utf8" });
|
|
36895
36867
|
let manifest;
|
|
@@ -36940,20 +36912,20 @@ async function pinPlumePackages(cwd) {
|
|
|
36940
36912
|
await handle2?.close();
|
|
36941
36913
|
}
|
|
36942
36914
|
}
|
|
36943
|
-
async function
|
|
36915
|
+
async function runLocalInit(cwd) {
|
|
36944
36916
|
assertRuntime();
|
|
36945
|
-
const root3 =
|
|
36946
|
-
const schemaPath =
|
|
36947
|
-
const plumePath =
|
|
36948
|
-
const agentsPath =
|
|
36949
|
-
const skillsPath =
|
|
36950
|
-
const skillPath =
|
|
36951
|
-
if (await inspect(
|
|
36917
|
+
const root3 = resolve5(cwd);
|
|
36918
|
+
const schemaPath = resolve5(root3, "plume.schema.ts");
|
|
36919
|
+
const plumePath = resolve5(root3, ".plume");
|
|
36920
|
+
const agentsPath = resolve5(root3, ".agents");
|
|
36921
|
+
const skillsPath = resolve5(agentsPath, "skills");
|
|
36922
|
+
const skillPath = resolve5(skillsPath, "plume-local");
|
|
36923
|
+
if (await inspect(resolve5(root3, "plume.lock")) !== "missing")
|
|
36952
36924
|
throw new PlumeLocalError(
|
|
36953
36925
|
"CONFLICTING_CONTENT_SOURCE",
|
|
36954
36926
|
"plume.lock binds this checkout to a hosted Site. Local initialization requires a separate project folder."
|
|
36955
36927
|
);
|
|
36956
|
-
for (const path of [schemaPath,
|
|
36928
|
+
for (const path of [schemaPath, resolve5(root3, ".gitignore")]) {
|
|
36957
36929
|
const kind = await inspect(path);
|
|
36958
36930
|
if (kind === "directory")
|
|
36959
36931
|
throw new PlumeLocalError(
|
|
@@ -36966,13 +36938,13 @@ async function runLocalInit2(cwd) {
|
|
|
36966
36938
|
if (kind === "file")
|
|
36967
36939
|
throw new PlumeLocalError("UNSAFE_PATH", `${path} must be a directory.`);
|
|
36968
36940
|
}
|
|
36969
|
-
const existingDatabase = await inspect(
|
|
36941
|
+
const existingDatabase = await inspect(resolve5(plumePath, "local.sqlite"));
|
|
36970
36942
|
if (existingDatabase === "directory")
|
|
36971
36943
|
throw new PlumeLocalError(
|
|
36972
36944
|
"UNSAFE_PATH",
|
|
36973
36945
|
"local.sqlite must be a regular file."
|
|
36974
36946
|
);
|
|
36975
|
-
const existingSkill = await inspect(
|
|
36947
|
+
const existingSkill = await inspect(resolve5(skillPath, "SKILL.md"));
|
|
36976
36948
|
if (existingSkill === "directory")
|
|
36977
36949
|
throw new PlumeLocalError(
|
|
36978
36950
|
"UNSAFE_PATH",
|
|
@@ -36990,7 +36962,7 @@ async function runLocalInit2(cwd) {
|
|
|
36990
36962
|
await ensureDirectory(agentsPath);
|
|
36991
36963
|
await ensureDirectory(skillsPath);
|
|
36992
36964
|
await ensureDirectory(skillPath);
|
|
36993
|
-
const skillCreated = await writeAbsent(
|
|
36965
|
+
const skillCreated = await writeAbsent(resolve5(skillPath, "SKILL.md"), SKILL);
|
|
36994
36966
|
const packages = await pinPlumePackages(root3);
|
|
36995
36967
|
return {
|
|
36996
36968
|
database: ".plume/local.sqlite",
|
|
@@ -37041,7 +37013,7 @@ async function runLocalCommand(args, cwd) {
|
|
|
37041
37013
|
].includes(args[1] ?? ""))
|
|
37042
37014
|
throw new PlumeLocalError("INVALID_INPUT", localHelp);
|
|
37043
37015
|
const action = args[1];
|
|
37044
|
-
const schema3 = await loadCheckoutSchema(
|
|
37016
|
+
const schema3 = await loadCheckoutSchema(resolve5(cwd));
|
|
37045
37017
|
if (action === "schema") {
|
|
37046
37018
|
return await applyLocalSchema({ cwd, schema: schema3 });
|
|
37047
37019
|
}
|
|
@@ -37172,10 +37144,10 @@ init_src();
|
|
|
37172
37144
|
init_protocol();
|
|
37173
37145
|
init_zod();
|
|
37174
37146
|
import { spawn } from "node:child_process";
|
|
37175
|
-
import { randomUUID as
|
|
37176
|
-
import { lstat as lstat4, mkdir as mkdir4, open as
|
|
37177
|
-
import { constants as
|
|
37178
|
-
import { resolve as
|
|
37147
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
37148
|
+
import { lstat as lstat4, mkdir as mkdir4, open as open4, rename as rename2, rm as rm3, writeFile as writeFile2 } from "node:fs/promises";
|
|
37149
|
+
import { constants as constants3 } from "node:os";
|
|
37150
|
+
import { resolve as resolve6 } from "node:path";
|
|
37179
37151
|
import { pathToFileURL as pathToFileURL2 } from "node:url";
|
|
37180
37152
|
import { createJiti as createJiti2 } from "jiti";
|
|
37181
37153
|
|
|
@@ -37219,8 +37191,8 @@ var statusLabels = {
|
|
|
37219
37191
|
merged: "Published",
|
|
37220
37192
|
closed: "Closed"
|
|
37221
37193
|
};
|
|
37222
|
-
function updateLabel(
|
|
37223
|
-
const timestamp2 = Number.parseInt(
|
|
37194
|
+
function updateLabel(id2) {
|
|
37195
|
+
const timestamp2 = Number.parseInt(id2.replaceAll("-", "").slice(0, 12), 16);
|
|
37224
37196
|
return Number.isFinite(timestamp2) ? `Update \xB7 ${new Intl.DateTimeFormat("en", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", timeZone: "Europe/Prague" }).format(timestamp2)}` : "Update";
|
|
37225
37197
|
}
|
|
37226
37198
|
function clock(at) {
|
|
@@ -37605,13 +37577,13 @@ async function getItem(ctx, session, collection, recordId) {
|
|
|
37605
37577
|
true
|
|
37606
37578
|
);
|
|
37607
37579
|
}
|
|
37608
|
-
var missingItem = (collection,
|
|
37580
|
+
var missingItem = (collection, id2) => new PlumeToolError(
|
|
37609
37581
|
"NOT_FOUND",
|
|
37610
|
-
`There is no Item ${printable(
|
|
37582
|
+
`There is no Item ${printable(id2)} in ${collection} in this Update. List them with plume items list ${collection}.`
|
|
37611
37583
|
);
|
|
37612
|
-
function savedLines(verb, collection,
|
|
37584
|
+
function savedLines(verb, collection, id2, session, issues) {
|
|
37613
37585
|
return [
|
|
37614
|
-
`${verb} ${collection}/${printable(
|
|
37586
|
+
`${verb} ${collection}/${printable(id2)} in ${updateLabel(session.updateId)}. The website has not been published.`,
|
|
37615
37587
|
...issues.length ? [
|
|
37616
37588
|
"Before publishing:",
|
|
37617
37589
|
...issues.map(
|
|
@@ -37646,7 +37618,7 @@ var count = (value, name3, fallback) => {
|
|
|
37646
37618
|
return Number(value);
|
|
37647
37619
|
};
|
|
37648
37620
|
var footer = `Set PLUME_ENDPOINT to your Plume address and PLUME_DEVELOPER_TOKEN to developer access for one Update (Plume: Settings \u203A Repository \u203A Developer access). Add --json for one JSON object: {"ok":true,"result":\u2026} or {"ok":false,"error":{"code","message","details"}}.
|
|
37649
|
-
Exit codes: 0 done \xB7 1 Plume refused or the request failed (the message says why) \xB7 2 wrong usage \xB7 3 someone else is editing this
|
|
37621
|
+
Exit codes: 0 done \xB7 1 Plume refused or the request failed (the message says why) \xB7 2 wrong usage \xB7 3 someone else is editing this Update`;
|
|
37650
37622
|
async function status(ctx, args) {
|
|
37651
37623
|
const options2 = parse6(args);
|
|
37652
37624
|
if (options2.positional.length)
|
|
@@ -37849,26 +37821,26 @@ async function items(ctx, args) {
|
|
|
37849
37821
|
return exitCodes.done;
|
|
37850
37822
|
}
|
|
37851
37823
|
const named2 = rest[0] !== void 0 && !/^[A-Za-z][A-Za-z0-9_]*:?=/.test(rest[0]) ? rest.shift() : void 0;
|
|
37852
|
-
const
|
|
37853
|
-
if (!
|
|
37824
|
+
const id2 = named2 ?? (singleton ? "singleton" : sub === "create" ? uuidv72() : void 0);
|
|
37825
|
+
if (!id2)
|
|
37854
37826
|
throw new UsageError(`Name the Item: plume items ${sub} ${name3} <id>.`);
|
|
37855
37827
|
if (sub === "get") {
|
|
37856
37828
|
if (rest.length)
|
|
37857
37829
|
throw new UsageError(
|
|
37858
37830
|
"plume items get takes a Collection and an Item ID."
|
|
37859
37831
|
);
|
|
37860
|
-
const { record: record3 } = await getItem(ctx, session, name3,
|
|
37861
|
-
if (!record3) throw missingItem(name3,
|
|
37832
|
+
const { record: record3 } = await getItem(ctx, session, name3, id2);
|
|
37833
|
+
if (!record3) throw missingItem(name3, id2);
|
|
37862
37834
|
emit(
|
|
37863
37835
|
ctx,
|
|
37864
37836
|
{
|
|
37865
37837
|
collection: name3,
|
|
37866
|
-
id:
|
|
37838
|
+
id: id2,
|
|
37867
37839
|
visibility: record3.visibility,
|
|
37868
37840
|
data: record3.data
|
|
37869
37841
|
},
|
|
37870
37842
|
() => [
|
|
37871
|
-
`${name3}/${printable(
|
|
37843
|
+
`${name3}/${printable(id2)} \xB7 ${visibilityLabel(record3.visibility)}`,
|
|
37872
37844
|
...entity2.fields.map(
|
|
37873
37845
|
(field) => `${field.name}: ${showValue(record3.data[field.name])}`
|
|
37874
37846
|
),
|
|
@@ -37883,8 +37855,8 @@ async function items(ctx, args) {
|
|
|
37883
37855
|
throw new UsageError(
|
|
37884
37856
|
"plume items delete takes a Collection and an Item ID."
|
|
37885
37857
|
);
|
|
37886
|
-
const before2 = await getItem(ctx, session, name3,
|
|
37887
|
-
if (!before2.record) throw missingItem(name3,
|
|
37858
|
+
const before2 = await getItem(ctx, session, name3, id2);
|
|
37859
|
+
if (!before2.record) throw missingItem(name3, id2);
|
|
37888
37860
|
const lease2 = await control(ctx, session);
|
|
37889
37861
|
await write(
|
|
37890
37862
|
(operation2) => call(
|
|
@@ -37897,7 +37869,7 @@ async function items(ctx, args) {
|
|
|
37897
37869
|
expectedVersionId: before2.versionId,
|
|
37898
37870
|
expectedRevision: before2.revision,
|
|
37899
37871
|
collection: name3,
|
|
37900
|
-
recordId:
|
|
37872
|
+
recordId: id2,
|
|
37901
37873
|
...operation2
|
|
37902
37874
|
},
|
|
37903
37875
|
external_exports.unknown()
|
|
@@ -37905,8 +37877,8 @@ async function items(ctx, args) {
|
|
|
37905
37877
|
);
|
|
37906
37878
|
emit(
|
|
37907
37879
|
ctx,
|
|
37908
|
-
{ deleted: true, collection: name3, id:
|
|
37909
|
-
() => `Deleted ${name3}/${printable(
|
|
37880
|
+
{ deleted: true, collection: name3, id: id2 },
|
|
37881
|
+
() => `Deleted ${name3}/${printable(id2)} from ${updateLabel(session.updateId)}. The published version keeps it until this Update is published.`
|
|
37910
37882
|
);
|
|
37911
37883
|
return exitCodes.done;
|
|
37912
37884
|
}
|
|
@@ -37916,14 +37888,14 @@ async function items(ctx, args) {
|
|
|
37916
37888
|
const patch3 = file2 ? await readData(ctx, file2) : assignments(entity2.fields, rest);
|
|
37917
37889
|
if (sub === "set" && !Object.keys(patch3).length && !visible && !hidden)
|
|
37918
37890
|
throw new UsageError(
|
|
37919
|
-
`Nothing to change. Example: plume items set ${name3} ${printable(
|
|
37891
|
+
`Nothing to change. Example: plume items set ${name3} ${printable(id2)} title="New title".`
|
|
37920
37892
|
);
|
|
37921
|
-
const before = await getItem(ctx, session, name3,
|
|
37922
|
-
if (sub === "set" && !before.record) throw missingItem(name3,
|
|
37893
|
+
const before = await getItem(ctx, session, name3, id2);
|
|
37894
|
+
if (sub === "set" && !before.record) throw missingItem(name3, id2);
|
|
37923
37895
|
if (sub === "create" && before.record)
|
|
37924
37896
|
throw new PlumeToolError(
|
|
37925
37897
|
"ALREADY_EXISTS",
|
|
37926
|
-
`${name3}/${printable(
|
|
37898
|
+
`${name3}/${printable(id2)} already exists. Change it with plume items set ${name3} ${printable(id2)} field=value.`
|
|
37927
37899
|
);
|
|
37928
37900
|
const defaults = Object.fromEntries(
|
|
37929
37901
|
entity2.fields.filter((field) => field.default !== void 0).map((field) => [field.name, field.default])
|
|
@@ -37942,7 +37914,7 @@ async function items(ctx, args) {
|
|
|
37942
37914
|
expectedVersionId: before.versionId,
|
|
37943
37915
|
expectedRevision: before.revision,
|
|
37944
37916
|
collection: name3,
|
|
37945
|
-
recordId:
|
|
37917
|
+
recordId: id2,
|
|
37946
37918
|
data,
|
|
37947
37919
|
visibility,
|
|
37948
37920
|
fullReplacement: true,
|
|
@@ -37954,11 +37926,11 @@ async function items(ctx, args) {
|
|
|
37954
37926
|
const issues = saved.issues;
|
|
37955
37927
|
emit(
|
|
37956
37928
|
ctx,
|
|
37957
|
-
{ saved: true, collection: name3, id:
|
|
37929
|
+
{ saved: true, collection: name3, id: id2, visibility, issues },
|
|
37958
37930
|
() => savedLines(
|
|
37959
37931
|
sub === "create" ? `Created (${visibilityLabel(visibility)})` : "Saved",
|
|
37960
37932
|
name3,
|
|
37961
|
-
|
|
37933
|
+
id2,
|
|
37962
37934
|
session,
|
|
37963
37935
|
issues
|
|
37964
37936
|
)
|
|
@@ -38205,7 +38177,7 @@ async function takeControl(ctx, args) {
|
|
|
38205
38177
|
emit(
|
|
38206
38178
|
ctx,
|
|
38207
38179
|
{ editing: true },
|
|
38208
|
-
() => `You have editing control of this
|
|
38180
|
+
() => `You have editing control of this Update. Whoever held it can no longer save until they take it back. It lapses ${LEASE_SECONDS} seconds after your last command.`
|
|
38209
38181
|
);
|
|
38210
38182
|
return exitCodes.done;
|
|
38211
38183
|
}
|
|
@@ -38233,7 +38205,7 @@ async function release(ctx, args) {
|
|
|
38233
38205
|
emit(
|
|
38234
38206
|
ctx,
|
|
38235
38207
|
{ released },
|
|
38236
|
-
() => released ? "Editing control released. Someone else can edit this
|
|
38208
|
+
() => released ? "Editing control released. Someone else can edit this Update now." : "This checkout doesn\u2019t hold editing control."
|
|
38237
38209
|
);
|
|
38238
38210
|
return exitCodes.done;
|
|
38239
38211
|
}
|
|
@@ -38318,11 +38290,11 @@ Example:
|
|
|
38318
38290
|
},
|
|
38319
38291
|
"take-control": {
|
|
38320
38292
|
summary: "Take editing control from whoever holds it",
|
|
38321
|
-
help: `plume take-control \u2014 take editing control of this
|
|
38293
|
+
help: `plume take-control \u2014 take editing control of this Update.
|
|
38322
38294
|
|
|
38323
38295
|
Usage: plume take-control [--json]
|
|
38324
38296
|
|
|
38325
|
-
Only one person or agent edits
|
|
38297
|
+
Only one person or agent edits an Update at a time. Taking control stops whoever holds it (in Plume or another checkout) from saving; as an Admin, you may. Use it when plume says someone else is editing and you've checked they're done, or ask them to hand it over in Plume.
|
|
38326
38298
|
|
|
38327
38299
|
Example:
|
|
38328
38300
|
plume take-control`,
|
|
@@ -38359,7 +38331,7 @@ function explain(error62, ctx) {
|
|
|
38359
38331
|
const since = holder?.since ? `, since ${clock(holder.since)}` : "";
|
|
38360
38332
|
return {
|
|
38361
38333
|
...base2,
|
|
38362
|
-
message: holder?.you ? `You are editing this
|
|
38334
|
+
message: holder?.you ? `You are editing this Update in another session (a browser tab or another checkout${since}). Finish there, or run plume take-control.` : `Someone else is editing this Update in Plume (${printable(holder?.name ?? "another person")}${since}). Ask them to hand it over in Plume, try again when they\u2019re done, or run plume take-control.`,
|
|
38363
38335
|
exit: exitCodes.busy
|
|
38364
38336
|
};
|
|
38365
38337
|
}
|
|
@@ -38764,14 +38736,15 @@ var remoteHelp = (branch) => ({
|
|
|
38764
38736
|
SETUP_UNAVAILABLE: "Plume cannot reach this Site's GitHub connection or content storage right now. Check the Site's setup in Plume, then run plume connect again. Nothing was transferred.",
|
|
38765
38737
|
SCHEMA_UNSUPPORTED: `Plume cannot read plume.schema.ts on branch ${branch}. The committed plume.schema.ts must be an inline \`export const schema = defineSchema({...})\` declaration with no imports besides defineSchema and no computed values. Push that form to ${branch}, then run plume connect again.`,
|
|
38766
38738
|
SCHEMA_MISMATCH: `plume.schema.ts on branch ${branch} does not match this checkout's committed schema, or the schema of the pending transfer. Push the matching plume.schema.ts to ${branch}, then run plume connect again.`,
|
|
38767
|
-
CMS_NOT_READY: `Branch ${branch} has no plume.lock for this Site and schema
|
|
38739
|
+
CMS_NOT_READY: `Branch ${branch} has no plume.lock for this Site and schema yet. Publish an Update in Plume that adds this plume.schema.ts, then run plume connect again.`,
|
|
38768
38740
|
TRANSFER_PENDING: "Plume is holding a pending transfer for this Site. Run plume connect again to resume it.",
|
|
38769
38741
|
NO_PENDING_TRANSFER: "Plume has no pending transfer for this Site any more. Run plume connect again to check its current state.",
|
|
38742
|
+
UPDATE_OPEN: "An Update is open on this Site. Publish or discard the open Update in Plume, then run plume connect again.",
|
|
38770
38743
|
ALREADY_TRANSFERRED: "This Site already has hosted content or a completed initial transfer, so local content can no longer be transferred. Edit content in Plume, or run plume connect again and choose schema only.",
|
|
38771
38744
|
TRANSFER_CHANGED: `Branch ${branch} no longer holds the plume.lock and plume.schema.ts the pending transfer started from. Restore them on ${branch}, then run plume connect again to resume. Hosted editing waits until then.`,
|
|
38772
38745
|
TRANSFER_INTERRUPTED: "Plume could not finish the transfer and kept it pending. Run plume connect again to resume it.",
|
|
38773
38746
|
GITHUB_ACCESS: `Plume cannot use the connected GitHub repository (suspended or missing App installation, missing permissions, or a renamed/deleted repository). Repair the GitHub connection in this Site's setup in Plume, then run plume connect again.`,
|
|
38774
|
-
SITE_BUSY: "Someone
|
|
38747
|
+
SITE_BUSY: "Someone is editing an Update on this Site in Plume. Wait for their session to end, then run plume connect again."
|
|
38775
38748
|
});
|
|
38776
38749
|
async function runConnect(options2) {
|
|
38777
38750
|
const cwd = await realpath2(resolve4(options2.cwd));
|
|
@@ -38983,210 +38956,12 @@ Waiting for browser approval\u2026
|
|
|
38983
38956
|
|
|
38984
38957
|
// packages/cli/src/index.ts
|
|
38985
38958
|
init_developer();
|
|
38986
|
-
|
|
38987
|
-
// packages/cli/src/init.ts
|
|
38988
|
-
init_src();
|
|
38989
|
-
init_protocol();
|
|
38990
|
-
init_zod();
|
|
38991
|
-
init_developer();
|
|
38992
|
-
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
38993
|
-
import { constants as constants2 } from "node:fs";
|
|
38994
|
-
import { link, open as open3, realpath as realpath3, unlink } from "node:fs/promises";
|
|
38995
|
-
import { resolve as resolve5 } from "node:path";
|
|
38996
|
-
var id2 = external_exports.uuidv7().refine((value) => value === value.toLowerCase());
|
|
38997
|
-
var repositorySchema = external_exports.object({
|
|
38998
|
-
owner: external_exports.string().min(1),
|
|
38999
|
-
name: external_exports.string().min(1),
|
|
39000
|
-
integrationBranch: external_exports.string().min(1)
|
|
39001
|
-
}).strict();
|
|
39002
|
-
var receiptSchema2 = external_exports.object({ binding: contentBindingSchema, repository: repositorySchema }).strict();
|
|
39003
|
-
var MAX_LOCK_BYTES = 16 * 1024;
|
|
39004
|
-
async function existingLock(path) {
|
|
39005
|
-
try {
|
|
39006
|
-
const handle2 = await open3(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
|
|
39007
|
-
try {
|
|
39008
|
-
const stat2 = await handle2.stat();
|
|
39009
|
-
if (!stat2.isFile() || stat2.size > MAX_LOCK_BYTES) throw new Error();
|
|
39010
|
-
const value = JSON.parse(
|
|
39011
|
-
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
39012
|
-
await handle2.readFile()
|
|
39013
|
-
)
|
|
39014
|
-
);
|
|
39015
|
-
return contentBindingSchema.parse(value);
|
|
39016
|
-
} finally {
|
|
39017
|
-
await handle2.close();
|
|
39018
|
-
}
|
|
39019
|
-
} catch (error62) {
|
|
39020
|
-
if (error62.code === "ENOENT") return null;
|
|
39021
|
-
throw new PlumeToolError(
|
|
39022
|
-
"LOCK_CONFLICT",
|
|
39023
|
-
"plume.lock exists but is invalid or unsafe. Inspect it before initializing."
|
|
39024
|
-
);
|
|
39025
|
-
}
|
|
39026
|
-
}
|
|
39027
|
-
function sameBinding(left, right) {
|
|
39028
|
-
return left.siteId === right.siteId && left.contentVersionId === right.contentVersionId && left.schemaHash === right.schemaHash;
|
|
39029
|
-
}
|
|
39030
|
-
async function createLock(path, binding) {
|
|
39031
|
-
const temp = `${path}.${randomUUID2()}.tmp`;
|
|
39032
|
-
try {
|
|
39033
|
-
const handle2 = await open3(temp, "wx", 384);
|
|
39034
|
-
try {
|
|
39035
|
-
await handle2.writeFile(`${JSON.stringify(binding, null, 2)}
|
|
39036
|
-
`);
|
|
39037
|
-
await handle2.sync();
|
|
39038
|
-
} finally {
|
|
39039
|
-
await handle2.close();
|
|
39040
|
-
}
|
|
39041
|
-
await link(temp, path);
|
|
39042
|
-
} catch (error62) {
|
|
39043
|
-
if (error62.code === "EEXIST") {
|
|
39044
|
-
const current = await existingLock(path);
|
|
39045
|
-
if (current && sameBinding(current, binding)) return;
|
|
39046
|
-
throw new PlumeToolError(
|
|
39047
|
-
"LOCK_CONFLICT",
|
|
39048
|
-
"plume.lock changed during initialization. Inspect it before retrying."
|
|
39049
|
-
);
|
|
39050
|
-
}
|
|
39051
|
-
throw new PlumeToolError(
|
|
39052
|
-
"LOCK_WRITE_FAILED",
|
|
39053
|
-
"Could not create plume.lock. Inspect the checkout and retry initialization."
|
|
39054
|
-
);
|
|
39055
|
-
} finally {
|
|
39056
|
-
await unlink(temp).catch(() => void 0);
|
|
39057
|
-
}
|
|
39058
|
-
}
|
|
39059
|
-
async function runLocalInit(options2) {
|
|
39060
|
-
const parsedId = id2.safeParse(options2.siteId);
|
|
39061
|
-
if (!parsedId.success)
|
|
39062
|
-
throw new PlumeToolError(
|
|
39063
|
-
"INVALID_INPUT",
|
|
39064
|
-
"Pass a lowercase UUIDv7 Site ID with --site."
|
|
39065
|
-
);
|
|
39066
|
-
const cwd = resolve5(options2.cwd);
|
|
39067
|
-
const root3 = await git(cwd, "rev-parse", "--show-toplevel");
|
|
39068
|
-
if (await realpath3(root3) !== await realpath3(cwd))
|
|
39069
|
-
throw new PlumeToolError(
|
|
39070
|
-
"CHECKOUT_MISMATCH",
|
|
39071
|
-
"Run plume init from the connected repository root."
|
|
39072
|
-
);
|
|
39073
|
-
const repository = githubRepository(
|
|
39074
|
-
await git(cwd, "config", "--get", "remote.origin.url")
|
|
39075
|
-
);
|
|
39076
|
-
if (!repository)
|
|
39077
|
-
throw new PlumeToolError(
|
|
39078
|
-
"CHECKOUT_MISMATCH",
|
|
39079
|
-
"The origin must be a GitHub HTTPS or SSH repository URL."
|
|
39080
|
-
);
|
|
39081
|
-
const schema3 = await loadCheckoutSchema(cwd);
|
|
39082
|
-
const hash2 = await schemaHash(schema3);
|
|
39083
|
-
const lockPath = resolve5(cwd, "plume.lock");
|
|
39084
|
-
const prior = await existingLock(lockPath);
|
|
39085
|
-
if (prior && (prior.siteId !== parsedId.data || prior.schemaHash !== hash2))
|
|
39086
|
-
throw new PlumeToolError(
|
|
39087
|
-
"LOCK_CONFLICT",
|
|
39088
|
-
"plume.lock targets another Site or schema. Inspect it before initializing."
|
|
39089
|
-
);
|
|
39090
|
-
const url2 = developerUrl(options2.endpoint, "api/developer/initialize");
|
|
39091
|
-
if (!/^plume_setup_[a-f0-9]{64}$/.test(options2.token))
|
|
39092
|
-
throw new PlumeToolError(
|
|
39093
|
-
"INVALID_CONFIGURATION",
|
|
39094
|
-
"Set PLUME_SETUP_TOKEN to a valid setup credential."
|
|
39095
|
-
);
|
|
39096
|
-
const body3 = JSON.stringify({ siteId: parsedId.data, schema: schema3, repository });
|
|
39097
|
-
if (Buffer.byteLength(body3, "utf8") > 512 * 1024)
|
|
39098
|
-
throw new PlumeToolError(
|
|
39099
|
-
"INVALID_SCHEMA",
|
|
39100
|
-
"The schema exceeds the initialization request limit."
|
|
39101
|
-
);
|
|
39102
|
-
let response;
|
|
39103
|
-
try {
|
|
39104
|
-
response = await fetch(url2, {
|
|
39105
|
-
method: "POST",
|
|
39106
|
-
headers: {
|
|
39107
|
-
"content-type": "application/json",
|
|
39108
|
-
authorization: `Bearer ${options2.token}`
|
|
39109
|
-
},
|
|
39110
|
-
body: body3,
|
|
39111
|
-
redirect: "error",
|
|
39112
|
-
cache: "no-store",
|
|
39113
|
-
credentials: "omit",
|
|
39114
|
-
signal: AbortSignal.timeout(15e3)
|
|
39115
|
-
});
|
|
39116
|
-
} catch {
|
|
39117
|
-
throw new PlumeToolError(
|
|
39118
|
-
"REQUEST_FAILED",
|
|
39119
|
-
"Initialization may have completed remotely. Rerun plume init with the same Site and schema to recover."
|
|
39120
|
-
);
|
|
39121
|
-
}
|
|
39122
|
-
if (!response.ok) {
|
|
39123
|
-
let code = "REMOTE_ERROR";
|
|
39124
|
-
try {
|
|
39125
|
-
const remote = await boundedJson(response, 16 * 1024);
|
|
39126
|
-
if (remote && typeof remote === "object" && "error" in remote) {
|
|
39127
|
-
const error62 = remote.error;
|
|
39128
|
-
if (error62 && typeof error62 === "object" && "code" in error62 && typeof error62.code === "string" && /^[A-Z_]{1,40}$/.test(error62.code))
|
|
39129
|
-
code = error62.code;
|
|
39130
|
-
}
|
|
39131
|
-
} catch {
|
|
39132
|
-
}
|
|
39133
|
-
throw new PlumeToolError(
|
|
39134
|
-
code,
|
|
39135
|
-
`Initialization was rejected (HTTP ${response.status}). Check Site access and connected repository.`
|
|
39136
|
-
);
|
|
39137
|
-
}
|
|
39138
|
-
let receipt;
|
|
39139
|
-
try {
|
|
39140
|
-
receipt = receiptSchema2.parse(await boundedJson(response, 16 * 1024));
|
|
39141
|
-
} catch {
|
|
39142
|
-
throw new PlumeToolError(
|
|
39143
|
-
"INVALID_RESPONSE",
|
|
39144
|
-
"Initialization may have completed remotely, but its receipt was invalid. Rerun with the same Site and schema."
|
|
39145
|
-
);
|
|
39146
|
-
}
|
|
39147
|
-
if (receipt.binding.siteId !== parsedId.data || receipt.binding.schemaHash !== hash2 || receipt.repository.owner.toLowerCase() !== repository.owner.toLowerCase() || receipt.repository.name.toLowerCase() !== repository.name.toLowerCase() || prior && !sameBinding(prior, receipt.binding))
|
|
39148
|
-
throw new PlumeToolError(
|
|
39149
|
-
"INVALID_RESPONSE",
|
|
39150
|
-
"The initialization receipt does not match this Site, schema, repository, or existing lock."
|
|
39151
|
-
);
|
|
39152
|
-
if (await schemaHash(await loadCheckoutSchema(cwd)) !== hash2)
|
|
39153
|
-
throw new PlumeToolError(
|
|
39154
|
-
"SCHEMA_MISMATCH",
|
|
39155
|
-
"plume.schema.ts changed during initialization. Restore it or rerun with the new schema."
|
|
39156
|
-
);
|
|
39157
|
-
const currentRepository = githubRepository(
|
|
39158
|
-
await git(cwd, "config", "--get", "remote.origin.url")
|
|
39159
|
-
);
|
|
39160
|
-
if (!currentRepository || currentRepository.owner.toLowerCase() !== repository.owner.toLowerCase() || currentRepository.name.toLowerCase() !== repository.name.toLowerCase())
|
|
39161
|
-
throw new PlumeToolError(
|
|
39162
|
-
"CHECKOUT_MISMATCH",
|
|
39163
|
-
"The origin changed during initialization. Restore it or rerun."
|
|
39164
|
-
);
|
|
39165
|
-
if (prior) {
|
|
39166
|
-
const current = await existingLock(lockPath);
|
|
39167
|
-
if (!current || !sameBinding(current, receipt.binding))
|
|
39168
|
-
throw new PlumeToolError(
|
|
39169
|
-
"LOCK_CONFLICT",
|
|
39170
|
-
"plume.lock changed during initialization. Inspect it before retrying."
|
|
39171
|
-
);
|
|
39172
|
-
} else {
|
|
39173
|
-
await createLock(lockPath, receipt.binding);
|
|
39174
|
-
}
|
|
39175
|
-
return {
|
|
39176
|
-
binding: receipt.binding,
|
|
39177
|
-
repository: receipt.repository,
|
|
39178
|
-
next: "Review and commit plume.schema.ts and plume.lock, then push the commit to your connected repository. Content stays in Plume; published content is public, so your website reads it with no token."
|
|
39179
|
-
};
|
|
39180
|
-
}
|
|
39181
|
-
|
|
39182
|
-
// packages/cli/src/index.ts
|
|
39183
38959
|
var DEFAULT_ENDPOINT = "https://app.plume.press";
|
|
39184
|
-
var
|
|
38960
|
+
var MAX_LOCK_BYTES = 16 * 1024;
|
|
39185
38961
|
var MAX_RESPONSE_BYTES2 = 16 * 1024;
|
|
39186
38962
|
var MAX_SCHEMA_BYTES2 = 256 * 1024;
|
|
39187
38963
|
var validationSchema = external_exports.object({
|
|
39188
38964
|
binding: contentBindingSchema,
|
|
39189
|
-
mode: external_exports.enum(["preview", "production"]),
|
|
39190
38965
|
revision: external_exports.number().int().nonnegative(),
|
|
39191
38966
|
sealed: external_exports.literal(true)
|
|
39192
38967
|
}).strict();
|
|
@@ -39200,10 +38975,10 @@ var PlumeBuildError = class extends Error {
|
|
|
39200
38975
|
};
|
|
39201
38976
|
async function readLock(cwd) {
|
|
39202
38977
|
try {
|
|
39203
|
-
const handle2 = await
|
|
38978
|
+
const handle2 = await open4(resolve6(cwd, "plume.lock"), "r");
|
|
39204
38979
|
try {
|
|
39205
38980
|
if (!(await handle2.stat()).isFile()) throw new Error();
|
|
39206
|
-
const bytes2 = Buffer.alloc(
|
|
38981
|
+
const bytes2 = Buffer.alloc(MAX_LOCK_BYTES + 1);
|
|
39207
38982
|
let length = 0;
|
|
39208
38983
|
while (length < bytes2.length) {
|
|
39209
38984
|
const result = await handle2.read(
|
|
@@ -39215,7 +38990,7 @@ async function readLock(cwd) {
|
|
|
39215
38990
|
if (!result.bytesRead) break;
|
|
39216
38991
|
length += result.bytesRead;
|
|
39217
38992
|
}
|
|
39218
|
-
if (length >
|
|
38993
|
+
if (length > MAX_LOCK_BYTES) throw new Error();
|
|
39219
38994
|
return contentBindingSchema.parse(
|
|
39220
38995
|
JSON.parse(
|
|
39221
38996
|
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
@@ -39236,14 +39011,14 @@ async function readLock(cwd) {
|
|
|
39236
39011
|
async function validateSchema(cwd, path, binding) {
|
|
39237
39012
|
let hash2;
|
|
39238
39013
|
try {
|
|
39239
|
-
const jiti = createJiti2(pathToFileURL2(
|
|
39014
|
+
const jiti = createJiti2(pathToFileURL2(resolve6(cwd, "package.json")).href, {
|
|
39240
39015
|
interopDefault: false,
|
|
39241
39016
|
moduleCache: false,
|
|
39242
39017
|
fsCache: false,
|
|
39243
39018
|
debug: false,
|
|
39244
39019
|
tryNative: false
|
|
39245
39020
|
});
|
|
39246
|
-
const module = await jiti.import(
|
|
39021
|
+
const module = await jiti.import(resolve6(cwd, path));
|
|
39247
39022
|
const schema3 = defineSchema(module.schema);
|
|
39248
39023
|
if (new TextEncoder().encode(canonicalJson(schema3)).byteLength > MAX_SCHEMA_BYTES2)
|
|
39249
39024
|
throw new Error();
|
|
@@ -39251,7 +39026,7 @@ async function validateSchema(cwd, path, binding) {
|
|
|
39251
39026
|
} catch (error62) {
|
|
39252
39027
|
throw new PlumeBuildError(
|
|
39253
39028
|
"INVALID_SCHEMA",
|
|
39254
|
-
await unresolvedSchemaImport(error62,
|
|
39029
|
+
await unresolvedSchemaImport(error62, resolve6(cwd, path)) ?? "Export a valid declarative schema named schema from plume.schema.ts (maximum 256 KiB)."
|
|
39255
39030
|
);
|
|
39256
39031
|
}
|
|
39257
39032
|
if (hash2 !== binding.schemaHash)
|
|
@@ -39274,16 +39049,13 @@ function validationUrl(endpoint) {
|
|
|
39274
39049
|
);
|
|
39275
39050
|
}
|
|
39276
39051
|
}
|
|
39277
|
-
async function validateRemote(url2,
|
|
39052
|
+
async function validateRemote(url2, binding) {
|
|
39278
39053
|
let response;
|
|
39279
39054
|
try {
|
|
39280
39055
|
response = await fetch(url2, {
|
|
39281
39056
|
method: "POST",
|
|
39282
|
-
headers: {
|
|
39283
|
-
|
|
39284
|
-
...token ? { authorization: `Bearer ${token}` } : {}
|
|
39285
|
-
},
|
|
39286
|
-
body: JSON.stringify({ binding, mode }),
|
|
39057
|
+
headers: { "content-type": "application/json" },
|
|
39058
|
+
body: JSON.stringify({ binding }),
|
|
39287
39059
|
redirect: "error",
|
|
39288
39060
|
cache: "no-store",
|
|
39289
39061
|
credentials: "omit",
|
|
@@ -39296,7 +39068,7 @@ async function validateRemote(url2, token, binding, mode) {
|
|
|
39296
39068
|
} catch {
|
|
39297
39069
|
throw new PlumeBuildError(
|
|
39298
39070
|
"VALIDATION_FAILED",
|
|
39299
|
-
|
|
39071
|
+
"Plume could not confirm this build. Build a commit whose plume.lock names prepared or published content (Plume commits it when you prepare or publish an Update), with the plume.schema.ts committed beside it."
|
|
39300
39072
|
);
|
|
39301
39073
|
}
|
|
39302
39074
|
try {
|
|
@@ -39323,7 +39095,7 @@ async function validateRemote(url2, token, binding, mode) {
|
|
|
39323
39095
|
new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(chunks))
|
|
39324
39096
|
)
|
|
39325
39097
|
);
|
|
39326
|
-
if (
|
|
39098
|
+
if (canonicalJson(result.binding) !== canonicalJson(binding))
|
|
39327
39099
|
throw new Error();
|
|
39328
39100
|
} catch {
|
|
39329
39101
|
throw new PlumeBuildError(
|
|
@@ -39363,15 +39135,14 @@ async function runCommand2(cwd, command) {
|
|
|
39363
39135
|
});
|
|
39364
39136
|
child.once("close", (code, signal) => {
|
|
39365
39137
|
cleanup();
|
|
39366
|
-
resolveExit(code ?? (signal ? 128 +
|
|
39138
|
+
resolveExit(code ?? (signal ? 128 + constants3.signals[signal] : 1));
|
|
39367
39139
|
});
|
|
39368
39140
|
});
|
|
39369
39141
|
}
|
|
39370
39142
|
async function runBuild(options2) {
|
|
39371
|
-
const cwd =
|
|
39372
|
-
const directory =
|
|
39373
|
-
const
|
|
39374
|
-
const bindingFile = resolve7(directory, "binding.json");
|
|
39143
|
+
const cwd = resolve6(options2.cwd);
|
|
39144
|
+
const directory = resolve6(cwd, ".plume");
|
|
39145
|
+
const bindingFile = resolve6(directory, "binding.json");
|
|
39375
39146
|
try {
|
|
39376
39147
|
await mkdir4(directory, { recursive: true });
|
|
39377
39148
|
if (!(await lstat4(directory)).isDirectory()) throw new Error();
|
|
@@ -39381,28 +39152,20 @@ async function runBuild(options2) {
|
|
|
39381
39152
|
"The .plume build directory is unavailable or is a symbolic link."
|
|
39382
39153
|
);
|
|
39383
39154
|
}
|
|
39384
|
-
|
|
39385
|
-
await mkdir4(lockDirectory);
|
|
39386
|
-
} catch {
|
|
39387
|
-
throw new PlumeBuildError(
|
|
39388
|
-
"BUILD_BUSY",
|
|
39389
|
-
"Another Plume build owns this checkout. If it stopped unexpectedly, confirm no build is running before removing .plume/build.lock."
|
|
39390
|
-
);
|
|
39391
|
-
}
|
|
39392
|
-
const temporary = resolve7(directory, `.binding-${randomUUID3()}.json`);
|
|
39155
|
+
const temporary = resolve6(directory, `.binding-${randomUUID2()}.json`);
|
|
39393
39156
|
try {
|
|
39394
39157
|
await rm3(bindingFile, { force: true });
|
|
39395
|
-
if (
|
|
39158
|
+
if (!options2.command.length || options2.command.some(
|
|
39396
39159
|
(part) => typeof part !== "string" || part.includes("\0")
|
|
39397
39160
|
) || !options2.command[0]?.trim())
|
|
39398
39161
|
throw new PlumeBuildError(
|
|
39399
39162
|
"INVALID_CONFIGURATION",
|
|
39400
|
-
"Provide a build command
|
|
39163
|
+
"Provide a build command."
|
|
39401
39164
|
);
|
|
39402
39165
|
const url2 = validationUrl(options2.endpoint);
|
|
39403
39166
|
const binding = await readLock(cwd);
|
|
39404
39167
|
await validateSchema(cwd, options2.schemaPath ?? "plume.schema.ts", binding);
|
|
39405
|
-
await validateRemote(url2,
|
|
39168
|
+
await validateRemote(url2, binding);
|
|
39406
39169
|
await writeFile2(temporary, `${JSON.stringify(binding, null, 2)}
|
|
39407
39170
|
`, {
|
|
39408
39171
|
flag: "wx",
|
|
@@ -39421,37 +39184,15 @@ async function runBuild(options2) {
|
|
|
39421
39184
|
} finally {
|
|
39422
39185
|
await rm3(temporary, { force: true }).catch(() => {
|
|
39423
39186
|
});
|
|
39424
|
-
await rm3(lockDirectory, { recursive: true, force: true });
|
|
39425
39187
|
}
|
|
39426
39188
|
}
|
|
39427
39189
|
async function main(args, env2 = process.env) {
|
|
39428
39190
|
if (args[0] === "connect") return connectMain(args, env2);
|
|
39429
39191
|
if (args[0] === "init") {
|
|
39430
39192
|
try {
|
|
39431
|
-
if (args.length
|
|
39432
|
-
|
|
39433
|
-
|
|
39434
|
-
process.stdout.write(`${JSON.stringify({ ok: true, result: result2 })}
|
|
39435
|
-
`);
|
|
39436
|
-
return 0;
|
|
39437
|
-
}
|
|
39438
|
-
if (args.length !== 3 || args[1] !== "--site")
|
|
39439
|
-
throw new Error("Usage: plume init [--site <uuidv7>]");
|
|
39440
|
-
try {
|
|
39441
|
-
await lstat4(resolve7(process.cwd(), ".plume", "local.sqlite"));
|
|
39442
|
-
throw new Error(
|
|
39443
|
-
"A local Plume database exists. Run plume connect to transfer it once; nothing was uploaded."
|
|
39444
|
-
);
|
|
39445
|
-
} catch (error62) {
|
|
39446
|
-
if (!(error62 && typeof error62 === "object" && "code" in error62 && error62.code === "ENOENT"))
|
|
39447
|
-
throw error62;
|
|
39448
|
-
}
|
|
39449
|
-
const result = await runLocalInit({
|
|
39450
|
-
cwd: process.cwd(),
|
|
39451
|
-
siteId: args[2],
|
|
39452
|
-
endpoint: env2.PLUME_ENDPOINT ?? "",
|
|
39453
|
-
token: env2.PLUME_SETUP_TOKEN ?? ""
|
|
39454
|
-
});
|
|
39193
|
+
if (args.length !== 1) throw new Error("Usage: plume init");
|
|
39194
|
+
const { runLocalInit: runLocalInit2 } = await Promise.resolve().then(() => (init_local(), local_exports));
|
|
39195
|
+
const result = await runLocalInit2(process.cwd());
|
|
39455
39196
|
process.stdout.write(`${JSON.stringify({ ok: true, result })}
|
|
39456
39197
|
`);
|
|
39457
39198
|
return 0;
|
|
@@ -39459,7 +39200,7 @@ async function main(args, env2 = process.env) {
|
|
|
39459
39200
|
const code = error62 && typeof error62 === "object" && "code" in error62 ? String(error62.code) : "INVALID_INPUT";
|
|
39460
39201
|
const message = error62 instanceof Error ? error62.message : "Initialization failed.";
|
|
39461
39202
|
process.stdout.write(
|
|
39462
|
-
`${JSON.stringify({ ok: false, error: { code, message
|
|
39203
|
+
`${JSON.stringify({ ok: false, error: { code, message } })}
|
|
39463
39204
|
`
|
|
39464
39205
|
);
|
|
39465
39206
|
return 1;
|
|
@@ -39504,10 +39245,7 @@ ${localHelp2}
|
|
|
39504
39245
|
|
|
39505
39246
|
${connectHelp}
|
|
39506
39247
|
|
|
39507
|
-
Usage: plume
|
|
39508
|
-
Initialize a connected Site's empty content with PLUME_SETUP_TOKEN and write plume.lock.
|
|
39509
|
-
|
|
39510
|
-
Usage: plume build [--preview] -- <command ...>
|
|
39248
|
+
Usage: plume build -- <command ...>
|
|
39511
39249
|
Check plume.lock with Plume, then run your framework's build.
|
|
39512
39250
|
|
|
39513
39251
|
${developerHelp}
|
|
@@ -39517,17 +39255,15 @@ ${developerHelp}
|
|
|
39517
39255
|
}
|
|
39518
39256
|
const divider = args.indexOf("--");
|
|
39519
39257
|
const prefix = args.slice(0, divider);
|
|
39520
|
-
if (divider < 1 || prefix
|
|
39521
|
-
process.stderr.write("Usage: plume build
|
|
39258
|
+
if (divider < 1 || prefix.length !== 1 || prefix[0] !== "build" || divider === args.length - 1) {
|
|
39259
|
+
process.stderr.write("Usage: plume build -- <command ...>\n");
|
|
39522
39260
|
return 1;
|
|
39523
39261
|
}
|
|
39524
39262
|
try {
|
|
39525
39263
|
const result = await runBuild({
|
|
39526
39264
|
cwd: process.cwd(),
|
|
39527
39265
|
command: args.slice(divider + 1),
|
|
39528
|
-
|
|
39529
|
-
endpoint: env2.PLUME_ENDPOINT || DEFAULT_ENDPOINT,
|
|
39530
|
-
token: env2.PLUME_TOKEN ?? ""
|
|
39266
|
+
endpoint: env2.PLUME_ENDPOINT || DEFAULT_ENDPOINT
|
|
39531
39267
|
});
|
|
39532
39268
|
return result.exitCode;
|
|
39533
39269
|
} catch (error62) {
|