@plume-press/cli 0.4.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/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 = (id3, k) => `
3498
- let ${id3}_ab = false;
3499
- for (let i = 0; i < ${id3}.issues.length; i++) {
3500
- const iss = ${id3}.issues[i];
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) ${id3}_ab = true;
3503
+ if (iss.continue !== true) ${id2}_ab = true;
3504
3504
  }
3505
- if (${id3}_ab && ctx && ctx.abortEarly) {
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 id3 = ids2[key3];
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 ${id3} = ${parseStr(k)};`);
3526
+ doc.write(`const ${id2} = ${parseStr(k)};`);
3527
3527
  if (isOptionalIn && isOptionalOut) {
3528
- const assign = optin === "optional" ? `${id3}_present` : `${id3}.value !== undefined || ${id3}_present`;
3528
+ const assign = optin === "optional" ? `${id2}_present` : `${id2}.value !== undefined || ${id2}_present`;
3529
3529
  doc.write(`
3530
- const ${id3}_present = ${isPresent};
3531
- if (!${id3}.issues.length || ${id3}_present) {
3532
- if (${id3}.issues.length) {${prefixStr(id3, k)}
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}] = ${id3}.value;
3536
+ newResult[${k}] = ${id2}.value;
3537
3537
  }
3538
3538
  }
3539
3539
 
3540
3540
  `);
3541
3541
  } else if (!isOptionalIn) {
3542
3542
  doc.write(`
3543
- const ${id3}_present = ${isPresent};
3544
- if (${id3}.issues.length) {${prefixStr(id3, k)}
3543
+ const ${id2}_present = ${isPresent};
3544
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3545
3545
  }
3546
- if (!${id3}_present && !${id3}.issues.length) {
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 (${id3}_present) {
3560
- newResult[${k}] = ${id3}.value;
3559
+ if (${id2}_present) {
3560
+ newResult[${k}] = ${id2}.value;
3561
3561
  }
3562
3562
 
3563
3563
  `);
3564
3564
  } else {
3565
3565
  doc.write(`
3566
- if (${id3}.issues.length) {${prefixStr(id3, k)}
3566
+ if (${id2}.issues.length) {${prefixStr(id2, k)}
3567
3567
  }
3568
3568
  `);
3569
3569
  if (optin === "defaulted") {
3570
- doc.write(`newResult[${k}] = ${id3}.value;`);
3570
+ doc.write(`newResult[${k}] = ${id2}.value;`);
3571
3571
  } else {
3572
3572
  doc.write(`
3573
- if (${id3}.value !== undefined || ${isPresent}) {
3574
- newResult[${k}] = ${id3}.value;
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, resolve8) {
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, resolve8);
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, resolve8) : NONE;
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 ?? (resolve8 ? inst._zod.innerType : void 0);
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 id3 = ctx.metadataRegistry.get(entry[0])?.id;
15673
- if (id3) {
15674
- const existing = idToSchema.get(id3);
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 "${id3}" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);
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(id3, entry[0]);
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 ?? ((id4) => id4);
15685
+ const uriGenerator = ctx.external.uri ?? ((id3) => id3);
15686
15686
  if (externalId) {
15687
15687
  return { ref: uriGenerator(externalId) };
15688
15688
  }
15689
- const id3 = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;
15690
- entry[1].defId = id3;
15691
- return { defId: id3, ref: `${uriGenerator("__shared")}#/${defsSegment}/${encodeJSONPointerSegment(id3)}` };
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 id3 = ctx.metadataRegistry.get(entry[0])?.id;
15740
- if (id3) {
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 id3 = ctx.external.registry.get(schema3)?.id;
15972
- if (!id3)
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(id3);
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: id3, ...rest } = json2;
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, id3) {
29714
+ _isSpecialElement(element4, id2) {
29715
29715
  const ns = this.treeAdapter.getNamespaceURI(element4);
29716
- return SPECIAL_ELEMENTS[ns].has(id3);
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 id3 = String(value[key3]);
32327
- fn = own4.call(handlers, id3) ? handlers[id3] : one3.unknown;
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(resolve8, reject) {
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 (resolve8) {
34010
- resolve8(file3);
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(resolve8, reject) {
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 (resolve8) {
34127
- resolve8(resultingTree);
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 id3 = null;
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
- id3 = values[0] ?? null;
34373
+ id2 = values[0] ?? null;
34374
34374
  } else if (host === "youtu.be") {
34375
- id3 = /^\/([A-Za-z0-9_-]{11})$/.exec(url2.pathname)?.[1] ?? null;
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
- id3 = /^\/embed\/([A-Za-z0-9_-]{11})$/.exec(url2.pathname)?.[1] ?? null;
34377
+ id2 = /^\/embed\/([A-Za-z0-9_-]{11})$/.exec(url2.pathname)?.[1] ?? null;
34378
34378
  }
34379
- return id3 && YOUTUBE_ID.test(id3) ? `${EMBED_PREFIX}${id3}` : null;
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(id3, alt) {
34403
+ function imageNode(id2, alt) {
34404
34404
  return {
34405
34405
  type: "element",
34406
34406
  tagName: "img",
34407
- properties: { "data-plume-asset-id": id3.toLowerCase(), alt },
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 id3 = properties2["data-plume-asset-id"] ?? properties2.dataPlumeAssetId;
34413
+ const id2 = properties2["data-plume-asset-id"] ?? properties2.dataPlumeAssetId;
34414
34414
  const alt = properties2.alt;
34415
- return typeof id3 === "string" && ASSET_ID.test(id3) && typeof alt === "string" && alt.length <= 1024 ? { id: id3.toLowerCase(), alt } : null;
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
- try {
34800
- validatePreviewPath(
34801
- entityName,
34802
- entity2.previewPath,
34803
- isCollection ? entity2.fields : null
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
- readStoredSchema(schema3);
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 id3 = (item, itemPath) => {
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", id3);
34937
- else id3(v, path);
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((id3) => typeof id3 === "string") : [];
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((id3) => exists(field.collection, id3));
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, id3) => lookup.has(key2(collection, id3));
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 id3 of referenceIds(value)) {
35355
- const target = lookup.get(key2(field.collection, id3));
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
- (id3) => id3.trim().length > 0 && id3 !== "." && id3 !== ".." && Array.from(id3).every(
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, id3) => JSON.stringify([collection, id3]);
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
  });
@@ -35490,6 +35478,16 @@ var init_markers = __esm({
35490
35478
  }
35491
35479
  });
35492
35480
 
35481
+ // packages/core/src/media-object-key.ts
35482
+ var identifier;
35483
+ var init_media_object_key = __esm({
35484
+ "packages/core/src/media-object-key.ts"() {
35485
+ "use strict";
35486
+ init_zod();
35487
+ identifier = external_exports.uuidv7();
35488
+ }
35489
+ });
35490
+
35493
35491
  // packages/core/src/permissions.ts
35494
35492
  var init_permissions = __esm({
35495
35493
  "packages/core/src/permissions.ts"() {
@@ -35513,6 +35511,7 @@ var init_src = __esm({
35513
35511
  init_delivered();
35514
35512
  init_image_size();
35515
35513
  init_markers();
35514
+ init_media_object_key();
35516
35515
  init_permissions();
35517
35516
  init_reconcile();
35518
35517
  init_rich_text();
@@ -35522,7 +35521,7 @@ var init_src = __esm({
35522
35521
  });
35523
35522
 
35524
35523
  // packages/sdk/src/protocol.ts
35525
- var MAX_CONTENT_DATA_BYTES, MAX_CONTENT_RESPONSE_BYTES, MAX_MEDIA_BYTES, contentBindingSchema, name, depth, contentQuerySchema, mediaPath, mediaQuerySchema, mediaRequestSchema, contentRequestSchema, timestamp, contentRecordSchema, contentAssetSchema, contentResponseSchema;
35524
+ var MAX_CONTENT_DATA_BYTES, MAX_CONTENT_RESPONSE_BYTES, MAX_MEDIA_BYTES, contentBindingSchema, latestPublicationSchema, name, depth, contentQuerySchema, mediaPath, mediaQuerySchema, mediaRequestSchema, contentRequestSchema, timestamp, contentRecordSchema, contentAssetSchema, contentResponseSchema;
35526
35525
  var init_protocol = __esm({
35527
35526
  "packages/sdk/src/protocol.ts"() {
35528
35527
  "use strict";
@@ -35535,6 +35534,12 @@ var init_protocol = __esm({
35535
35534
  contentVersionId: external_exports.uuidv7(),
35536
35535
  schemaHash: external_exports.string().regex(/^sha256:[a-f0-9]{64}$/)
35537
35536
  }).strict();
35537
+ latestPublicationSchema = external_exports.object({
35538
+ binding: contentBindingSchema,
35539
+ commitSha: external_exports.string().min(1).max(64),
35540
+ branch: external_exports.string().min(1).max(256),
35541
+ acceptedAt: external_exports.iso.datetime({ offset: false, precision: 3 })
35542
+ });
35538
35543
  name = external_exports.string().regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/).max(100);
35539
35544
  depth = external_exports.union([external_exports.literal(0), external_exports.literal(1)]).optional();
35540
35545
  contentQuerySchema = external_exports.discriminatedUnion("kind", [
@@ -35573,6 +35578,11 @@ var init_protocol = __esm({
35573
35578
  updatedAt: timestamp
35574
35579
  });
35575
35580
  contentAssetSchema = external_exports.object({
35581
+ /** Direct immutable public object URL when the service has a media origin. */
35582
+ url: external_exports.url().refine((value) => {
35583
+ const url2 = new URL(value);
35584
+ return !url2.username && !url2.password && (url2.protocol === "https:" || url2.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url2.hostname));
35585
+ }, "Media URLs require HTTPS or a local development origin.").optional(),
35576
35586
  filename: external_exports.string().min(1).max(256),
35577
35587
  mediaType: external_exports.enum([
35578
35588
  "image/jpeg",
@@ -35602,7 +35612,7 @@ var init_protocol = __esm({
35602
35612
 
35603
35613
  // packages/cli/src/developer.ts
35604
35614
  import { execFile } from "node:child_process";
35605
- import { realpath } from "node:fs/promises";
35615
+ import { readFile, realpath, stat } from "node:fs/promises";
35606
35616
  import { resolve } from "node:path";
35607
35617
  import { pathToFileURL } from "node:url";
35608
35618
  import { promisify } from "node:util";
@@ -35862,7 +35872,9 @@ async function runLocalPrepare(options2) {
35862
35872
  "Finish starting this Update before preparing it."
35863
35873
  );
35864
35874
  await verifyCheckout(resolve(options2.cwd), inspect2, input2);
35865
- const localSchema = await loadCheckoutSchema(resolve(options2.cwd));
35875
+ const localSchema = await stat(
35876
+ resolve(options2.cwd, "plume.schema.ts")
35877
+ ).catch(() => null) ? await loadCheckoutSchema(resolve(options2.cwd)) : defineSchema({ collections: [] });
35866
35878
  if (await schemaHash(localSchema) !== inspect2.schemaHash)
35867
35879
  throw new PlumeToolError(
35868
35880
  "SCHEMA_MISMATCH",
@@ -35943,6 +35955,23 @@ async function readInput() {
35943
35955
  );
35944
35956
  }
35945
35957
  }
35958
+ async function unresolvedSchemaImport(error62, schemaPath) {
35959
+ if (!(error62 instanceof Error) || error62.code !== "MODULE_NOT_FOUND")
35960
+ return void 0;
35961
+ let source;
35962
+ try {
35963
+ const file2 = await stat(schemaPath);
35964
+ if (!file2.isFile() || file2.size > MAX_SCHEMA_SOURCE_BYTES) return void 0;
35965
+ source = await readFile(schemaPath, "utf8");
35966
+ } catch {
35967
+ return void 0;
35968
+ }
35969
+ if (/(?:\bfrom|\bimport|\brequire)\s*\(?\s*["']@plume\/cli\/schema["']/.test(
35970
+ source
35971
+ ))
35972
+ return "plume.schema.ts imports @plume/cli/schema, which is now @plume-press/cli/schema. Change the import, then install @plume-press/cli.";
35973
+ return "An import in plume.schema.ts can't be found. Install the package or fix the import path.";
35974
+ }
35946
35975
  async function loadCheckoutSchema(cwd) {
35947
35976
  try {
35948
35977
  const jiti = createJiti(pathToFileURL(resolve(cwd, "package.json")).href, {
@@ -35959,10 +35988,10 @@ async function loadCheckoutSchema(cwd) {
35959
35988
  if (Buffer.byteLength(canonicalJson(schema3), "utf8") > MAX_SCHEMA_BYTES)
35960
35989
  throw new Error();
35961
35990
  return schema3;
35962
- } catch {
35991
+ } catch (error62) {
35963
35992
  throw new PlumeToolError(
35964
35993
  "INVALID_SCHEMA",
35965
- "Export a valid declarative schema named schema from plume.schema.ts."
35994
+ await unresolvedSchemaImport(error62, resolve(cwd, "plume.schema.ts")) ?? "Export a valid declarative schema named schema from plume.schema.ts."
35966
35995
  );
35967
35996
  }
35968
35997
  }
@@ -36026,7 +36055,7 @@ async function developerMain(args, env2 = process.env) {
36026
36055
  return 1;
36027
36056
  }
36028
36057
  }
36029
- var execFileAsync, MAX_INPUT_BYTES, MAX_RESPONSE_BYTES, MAX_SCHEMA_BYTES, schemaIssues, remoteText, detailShapes, id, context, writer, revision, record2, sha, operation, prepareInput, inspectResult, preparedResult, schemas, developerActions, PlumeToolError, developerHelp;
36058
+ var execFileAsync, MAX_INPUT_BYTES, MAX_RESPONSE_BYTES, MAX_SCHEMA_BYTES, MAX_SCHEMA_SOURCE_BYTES, schemaIssues, remoteText, detailShapes, id, context, writer, revision, record2, sha, operation, prepareInput, inspectResult, preparedResult, schemas, developerActions, PlumeToolError, developerHelp;
36030
36059
  var init_developer = __esm({
36031
36060
  "packages/cli/src/developer.ts"() {
36032
36061
  "use strict";
@@ -36037,6 +36066,7 @@ var init_developer = __esm({
36037
36066
  MAX_INPUT_BYTES = 512 * 1024;
36038
36067
  MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
36039
36068
  MAX_SCHEMA_BYTES = 256 * 1024;
36069
+ MAX_SCHEMA_SOURCE_BYTES = 1024 * 1024;
36040
36070
  schemaIssues = external_exports.object({
36041
36071
  issues: external_exports.array(
36042
36072
  external_exports.object({
@@ -36241,23 +36271,6 @@ async function safePath(cwd, create2) {
36241
36271
  );
36242
36272
  return path;
36243
36273
  }
36244
- function addTimestamps(db) {
36245
- const missing = () => !db.prepare("PRAGMA table_info(local_records)").all().some((column) => column.name === "created_at");
36246
- if (!missing() && !db.prepare(
36247
- "SELECT 1 FROM local_records WHERE created_at IS NULL OR updated_at IS NULL LIMIT 1"
36248
- ).get())
36249
- return;
36250
- transaction(db, () => {
36251
- if (missing()) {
36252
- db.exec("ALTER TABLE local_records ADD COLUMN created_at INTEGER");
36253
- db.exec("ALTER TABLE local_records ADD COLUMN updated_at INTEGER");
36254
- }
36255
- const now = Date.now();
36256
- db.prepare(
36257
- "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"
36258
- ).run(now, now);
36259
- });
36260
- }
36261
36274
  function meta3(db) {
36262
36275
  return db.prepare("SELECT schema, revision FROM local_meta WHERE id = 1").get();
36263
36276
  }
@@ -36283,11 +36296,11 @@ function entity(schema3, name3) {
36283
36296
  if (singleton) return { fields: singleton.fields, singleton: true };
36284
36297
  throw new Error(`Unknown collection or singleton: ${name3}`);
36285
36298
  }
36286
- function identity(schema3, name3, id3) {
36299
+ function identity(schema3, name3, id2) {
36287
36300
  const found = entity(schema3, name3);
36288
- if (typeof id3 !== "string" || id3.trim() === "")
36301
+ if (typeof id2 !== "string" || id2.trim() === "")
36289
36302
  throw new Error("Record ID cannot be empty.");
36290
- if (found.singleton && id3 !== "singleton")
36303
+ if (found.singleton && id2 !== "singleton")
36291
36304
  throw new Error('Singleton records must use the ID "singleton".');
36292
36305
  return found.fields;
36293
36306
  }
@@ -36311,8 +36324,8 @@ function validateSnapshot2(schema3, all3, changed) {
36311
36324
  const value = record3[field.name];
36312
36325
  const fieldPath = path ? `${path}.${field.name}` : field.name;
36313
36326
  if (field.kind === "reference")
36314
- for (const id3 of referenceIds(value))
36315
- retainedReferences.add(`${fieldPath}\0${id3}`);
36327
+ for (const id2 of referenceIds(value))
36328
+ retainedReferences.add(`${fieldPath}\0${id2}`);
36316
36329
  else if (field.kind === "list" && Array.isArray(value))
36317
36330
  for (const item of value)
36318
36331
  collectReferences2(field.fields, item, fieldPath);
@@ -36323,9 +36336,9 @@ function validateSnapshot2(schema3, all3, changed) {
36323
36336
  if (value === void 0 || value === null) continue;
36324
36337
  const fieldPath = path ? `${path}.${field.name}` : field.name;
36325
36338
  if (field.kind === "reference") {
36326
- for (const id3 of referenceIds(value)) {
36327
- const target = lookup.get(`${field.collection}\0${id3}`);
36328
- const unchangedMissing = !field.required && (!changedRow || retainedReferences.has(`${fieldPath}\0${id3}`));
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}`));
36329
36342
  if (!target && !unchangedMissing)
36330
36343
  throw new Error(
36331
36344
  `Missing reference at ${row.collection}/${row.record_id}.${fieldPath}.`
@@ -36428,12 +36441,12 @@ function fromRow(row, schema3, lookup) {
36428
36441
  for (const field of fields) {
36429
36442
  const value = record3[field.name];
36430
36443
  if (field.kind === "reference" && !field.required) {
36431
- const exists = (id3) => lookup.has(`${field.collection}\0${id3}`);
36444
+ const exists = (id2) => lookup.has(`${field.collection}\0${id2}`);
36432
36445
  if (typeof value === "string" && !exists(value))
36433
36446
  record3[field.name] = null;
36434
36447
  else if (Array.isArray(value))
36435
36448
  record3[field.name] = value.map(
36436
- (id3) => typeof id3 === "string" && exists(id3) ? id3 : null
36449
+ (id2) => typeof id2 === "string" && exists(id2) ? id2 : null
36437
36450
  );
36438
36451
  } else if (field.kind === "list" && Array.isArray(value))
36439
36452
  for (const item of value)
@@ -36463,7 +36476,6 @@ async function open2(path, expected) {
36463
36476
  db.exec("PRAGMA busy_timeout = 5000");
36464
36477
  const stored = meta3(db);
36465
36478
  if (!stored) throw new Error("Local content database is not initialized.");
36466
- addTimestamps(db);
36467
36479
  let schema3 = defineSchema(JSON.parse(stored.schema));
36468
36480
  if (expected && canonicalJson(schema3) !== canonicalJson(expected))
36469
36481
  throw new Error(
@@ -36652,7 +36664,7 @@ async function openLocalStore(input2) {
36652
36664
  "CREATE TABLE local_meta (id INTEGER PRIMARY KEY CHECK(id = 1), schema TEXT NOT NULL, revision INTEGER NOT NULL)"
36653
36665
  );
36654
36666
  db.exec(
36655
- "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))"
36656
36668
  );
36657
36669
  db.prepare(
36658
36670
  "INSERT INTO local_meta (id, schema, revision) VALUES (1, ?, 0)"
@@ -36691,7 +36703,7 @@ var init_package = __esm({
36691
36703
  "packages/sdk/package.json"() {
36692
36704
  package_default = {
36693
36705
  name: "@plume-press/sdk",
36694
- version: "0.1.0",
36706
+ version: "0.3.0",
36695
36707
  private: true,
36696
36708
  license: "MIT",
36697
36709
  type: "module",
@@ -36718,7 +36730,7 @@ var init_package2 = __esm({
36718
36730
  "packages/cli/package.json"() {
36719
36731
  package_default2 = {
36720
36732
  name: "@plume-press/cli",
36721
- version: "0.4.0",
36733
+ version: "0.6.0",
36722
36734
  private: true,
36723
36735
  license: "MIT",
36724
36736
  type: "module",
@@ -36753,11 +36765,11 @@ __export(local_exports, {
36753
36765
  PlumeLocalError: () => PlumeLocalError,
36754
36766
  localHelp: () => localHelp,
36755
36767
  runLocalCommand: () => runLocalCommand,
36756
- runLocalInit: () => runLocalInit2
36768
+ runLocalInit: () => runLocalInit
36757
36769
  });
36758
- import { constants as constants3 } from "node:fs";
36759
- import { lstat as lstat3, mkdir as mkdir3, open as open4 } from "node:fs/promises";
36760
- import { resolve as resolve6 } from "node:path";
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";
36761
36773
  function assertRuntime() {
36762
36774
  const [major = 0, minor = 0] = process.versions.node.split(".").map(Number);
36763
36775
  if (major < 22 || major === 22 && minor < 13)
@@ -36768,9 +36780,9 @@ function assertRuntime() {
36768
36780
  }
36769
36781
  async function inspect(path) {
36770
36782
  try {
36771
- const stat = await lstat3(path);
36772
- if (stat.isFile()) return "file";
36773
- if (stat.isDirectory()) return "directory";
36783
+ const stat2 = await lstat3(path);
36784
+ if (stat2.isFile()) return "file";
36785
+ if (stat2.isDirectory()) return "directory";
36774
36786
  throw new PlumeLocalError(
36775
36787
  "UNSAFE_PATH",
36776
36788
  `${path} must be a regular file or directory, not a symbolic link or special file.`
@@ -36796,9 +36808,9 @@ async function writeAbsent(path, content2) {
36796
36808
  if (kind !== "missing")
36797
36809
  throw new PlumeLocalError("UNSAFE_PATH", `${path} must be a regular file.`);
36798
36810
  try {
36799
- const handle2 = await open4(
36811
+ const handle2 = await open3(
36800
36812
  path,
36801
- constants3.O_WRONLY | constants3.O_CREAT | constants3.O_EXCL | constants3.O_NOFOLLOW,
36813
+ constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | constants2.O_NOFOLLOW,
36802
36814
  420
36803
36815
  );
36804
36816
  try {
@@ -36815,7 +36827,7 @@ async function writeAbsent(path, content2) {
36815
36827
  }
36816
36828
  }
36817
36829
  async function ignoreLocalDatabase(cwd) {
36818
- const path = resolve6(cwd, ".gitignore");
36830
+ const path = resolve5(cwd, ".gitignore");
36819
36831
  const kind = await inspect(path);
36820
36832
  if (kind !== "missing" && kind !== "file")
36821
36833
  throw new PlumeLocalError(
@@ -36824,9 +36836,9 @@ async function ignoreLocalDatabase(cwd) {
36824
36836
  );
36825
36837
  let handle2;
36826
36838
  try {
36827
- handle2 = await open4(
36839
+ handle2 = await open3(
36828
36840
  path,
36829
- constants3.O_RDWR | constants3.O_CREAT | constants3.O_NOFOLLOW,
36841
+ constants2.O_RDWR | constants2.O_CREAT | constants2.O_NOFOLLOW,
36830
36842
  420
36831
36843
  );
36832
36844
  if (!(await handle2.stat()).isFile())
@@ -36845,11 +36857,11 @@ async function ignoreLocalDatabase(cwd) {
36845
36857
  }
36846
36858
  }
36847
36859
  async function pinPlumePackages(cwd) {
36848
- const path = resolve6(cwd, "package.json");
36860
+ const path = resolve5(cwd, "package.json");
36849
36861
  if (await inspect(path) === "missing") return null;
36850
36862
  let handle2;
36851
36863
  try {
36852
- handle2 = await open4(path, constants3.O_RDWR | constants3.O_NOFOLLOW);
36864
+ handle2 = await open3(path, constants2.O_RDWR | constants2.O_NOFOLLOW);
36853
36865
  if (!(await handle2.stat()).isFile()) throw new Error();
36854
36866
  const text3 = await handle2.readFile({ encoding: "utf8" });
36855
36867
  let manifest;
@@ -36900,20 +36912,20 @@ async function pinPlumePackages(cwd) {
36900
36912
  await handle2?.close();
36901
36913
  }
36902
36914
  }
36903
- async function runLocalInit2(cwd) {
36915
+ async function runLocalInit(cwd) {
36904
36916
  assertRuntime();
36905
- const root3 = resolve6(cwd);
36906
- const schemaPath = resolve6(root3, "plume.schema.ts");
36907
- const plumePath = resolve6(root3, ".plume");
36908
- const agentsPath = resolve6(root3, ".agents");
36909
- const skillsPath = resolve6(agentsPath, "skills");
36910
- const skillPath = resolve6(skillsPath, "plume-local");
36911
- if (await inspect(resolve6(root3, "plume.lock")) !== "missing")
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")
36912
36924
  throw new PlumeLocalError(
36913
36925
  "CONFLICTING_CONTENT_SOURCE",
36914
36926
  "plume.lock binds this checkout to a hosted Site. Local initialization requires a separate project folder."
36915
36927
  );
36916
- for (const path of [schemaPath, resolve6(root3, ".gitignore")]) {
36928
+ for (const path of [schemaPath, resolve5(root3, ".gitignore")]) {
36917
36929
  const kind = await inspect(path);
36918
36930
  if (kind === "directory")
36919
36931
  throw new PlumeLocalError(
@@ -36926,13 +36938,13 @@ async function runLocalInit2(cwd) {
36926
36938
  if (kind === "file")
36927
36939
  throw new PlumeLocalError("UNSAFE_PATH", `${path} must be a directory.`);
36928
36940
  }
36929
- const existingDatabase = await inspect(resolve6(plumePath, "local.sqlite"));
36941
+ const existingDatabase = await inspect(resolve5(plumePath, "local.sqlite"));
36930
36942
  if (existingDatabase === "directory")
36931
36943
  throw new PlumeLocalError(
36932
36944
  "UNSAFE_PATH",
36933
36945
  "local.sqlite must be a regular file."
36934
36946
  );
36935
- const existingSkill = await inspect(resolve6(skillPath, "SKILL.md"));
36947
+ const existingSkill = await inspect(resolve5(skillPath, "SKILL.md"));
36936
36948
  if (existingSkill === "directory")
36937
36949
  throw new PlumeLocalError(
36938
36950
  "UNSAFE_PATH",
@@ -36950,7 +36962,7 @@ async function runLocalInit2(cwd) {
36950
36962
  await ensureDirectory(agentsPath);
36951
36963
  await ensureDirectory(skillsPath);
36952
36964
  await ensureDirectory(skillPath);
36953
- const skillCreated = await writeAbsent(resolve6(skillPath, "SKILL.md"), SKILL);
36965
+ const skillCreated = await writeAbsent(resolve5(skillPath, "SKILL.md"), SKILL);
36954
36966
  const packages = await pinPlumePackages(root3);
36955
36967
  return {
36956
36968
  database: ".plume/local.sqlite",
@@ -37001,7 +37013,7 @@ async function runLocalCommand(args, cwd) {
37001
37013
  ].includes(args[1] ?? ""))
37002
37014
  throw new PlumeLocalError("INVALID_INPUT", localHelp);
37003
37015
  const action = args[1];
37004
- const schema3 = await loadCheckoutSchema(resolve6(cwd));
37016
+ const schema3 = await loadCheckoutSchema(resolve5(cwd));
37005
37017
  if (action === "schema") {
37006
37018
  return await applyLocalSchema({ cwd, schema: schema3 });
37007
37019
  }
@@ -37132,10 +37144,10 @@ init_src();
37132
37144
  init_protocol();
37133
37145
  init_zod();
37134
37146
  import { spawn } from "node:child_process";
37135
- import { randomUUID as randomUUID3 } from "node:crypto";
37136
- import { lstat as lstat4, mkdir as mkdir4, open as open5, rename as rename2, rm as rm3, writeFile as writeFile2 } from "node:fs/promises";
37137
- import { constants as constants4 } from "node:os";
37138
- import { resolve as resolve7 } from "node:path";
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";
37139
37151
  import { pathToFileURL as pathToFileURL2 } from "node:url";
37140
37152
  import { createJiti as createJiti2 } from "jiti";
37141
37153
 
@@ -37146,7 +37158,7 @@ import { createHash, randomBytes } from "node:crypto";
37146
37158
  import {
37147
37159
  lstat,
37148
37160
  mkdir,
37149
- readFile,
37161
+ readFile as readFile2,
37150
37162
  rename,
37151
37163
  rm,
37152
37164
  writeFile
@@ -37179,9 +37191,9 @@ var statusLabels = {
37179
37191
  merged: "Published",
37180
37192
  closed: "Closed"
37181
37193
  };
37182
- function updateLabel(id3) {
37183
- const timestamp2 = Number.parseInt(id3.replaceAll("-", "").slice(0, 12), 16);
37184
- return Number.isFinite(timestamp2) ? `Update \xB7 ${new Intl.DateTimeFormat("en", { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }).format(timestamp2)}` : "Update";
37194
+ function updateLabel(id2) {
37195
+ const timestamp2 = Number.parseInt(id2.replaceAll("-", "").slice(0, 12), 16);
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";
37185
37197
  }
37186
37198
  function clock(at) {
37187
37199
  const time3 = new Date(at);
@@ -37276,7 +37288,7 @@ var credentialHash = (token) => createHash("sha256").update(token).digest("hex")
37276
37288
  async function readSession(ctx) {
37277
37289
  try {
37278
37290
  const session = sessionShape.parse(
37279
- JSON.parse(await readFile(sessionFile(ctx), "utf8"))
37291
+ JSON.parse(await readFile2(sessionFile(ctx), "utf8"))
37280
37292
  );
37281
37293
  return session.credential === credentialHash(ctx.token) ? session : null;
37282
37294
  } catch {
@@ -37546,7 +37558,7 @@ function assignments(fields, pairs) {
37546
37558
  }
37547
37559
  async function readData(ctx, path) {
37548
37560
  try {
37549
- const value = JSON.parse(await readFile(resolve2(ctx.io.cwd, path), "utf8"));
37561
+ const value = JSON.parse(await readFile2(resolve2(ctx.io.cwd, path), "utf8"));
37550
37562
  if (!value || typeof value !== "object" || Array.isArray(value))
37551
37563
  throw new Error();
37552
37564
  return value;
@@ -37565,13 +37577,13 @@ async function getItem(ctx, session, collection, recordId) {
37565
37577
  true
37566
37578
  );
37567
37579
  }
37568
- var missingItem = (collection, id3) => new PlumeToolError(
37580
+ var missingItem = (collection, id2) => new PlumeToolError(
37569
37581
  "NOT_FOUND",
37570
- `There is no Item ${printable(id3)} in ${collection} in this Update. List them with plume items list ${collection}.`
37582
+ `There is no Item ${printable(id2)} in ${collection} in this Update. List them with plume items list ${collection}.`
37571
37583
  );
37572
- function savedLines(verb, collection, id3, session, issues) {
37584
+ function savedLines(verb, collection, id2, session, issues) {
37573
37585
  return [
37574
- `${verb} ${collection}/${printable(id3)} in ${updateLabel(session.updateId)}. The website has not been published.`,
37586
+ `${verb} ${collection}/${printable(id2)} in ${updateLabel(session.updateId)}. The website has not been published.`,
37575
37587
  ...issues.length ? [
37576
37588
  "Before publishing:",
37577
37589
  ...issues.map(
@@ -37606,7 +37618,7 @@ var count = (value, name3, fallback) => {
37606
37618
  return Number(value);
37607
37619
  };
37608
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"}}.
37609
- 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 Site`;
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`;
37610
37622
  async function status(ctx, args) {
37611
37623
  const options2 = parse6(args);
37612
37624
  if (options2.positional.length)
@@ -37809,26 +37821,26 @@ async function items(ctx, args) {
37809
37821
  return exitCodes.done;
37810
37822
  }
37811
37823
  const named2 = rest[0] !== void 0 && !/^[A-Za-z][A-Za-z0-9_]*:?=/.test(rest[0]) ? rest.shift() : void 0;
37812
- const id3 = named2 ?? (singleton ? "singleton" : sub === "create" ? uuidv72() : void 0);
37813
- if (!id3)
37824
+ const id2 = named2 ?? (singleton ? "singleton" : sub === "create" ? uuidv72() : void 0);
37825
+ if (!id2)
37814
37826
  throw new UsageError(`Name the Item: plume items ${sub} ${name3} <id>.`);
37815
37827
  if (sub === "get") {
37816
37828
  if (rest.length)
37817
37829
  throw new UsageError(
37818
37830
  "plume items get takes a Collection and an Item ID."
37819
37831
  );
37820
- const { record: record3 } = await getItem(ctx, session, name3, id3);
37821
- if (!record3) throw missingItem(name3, id3);
37832
+ const { record: record3 } = await getItem(ctx, session, name3, id2);
37833
+ if (!record3) throw missingItem(name3, id2);
37822
37834
  emit(
37823
37835
  ctx,
37824
37836
  {
37825
37837
  collection: name3,
37826
- id: id3,
37838
+ id: id2,
37827
37839
  visibility: record3.visibility,
37828
37840
  data: record3.data
37829
37841
  },
37830
37842
  () => [
37831
- `${name3}/${printable(id3)} \xB7 ${visibilityLabel(record3.visibility)}`,
37843
+ `${name3}/${printable(id2)} \xB7 ${visibilityLabel(record3.visibility)}`,
37832
37844
  ...entity2.fields.map(
37833
37845
  (field) => `${field.name}: ${showValue(record3.data[field.name])}`
37834
37846
  ),
@@ -37843,8 +37855,8 @@ async function items(ctx, args) {
37843
37855
  throw new UsageError(
37844
37856
  "plume items delete takes a Collection and an Item ID."
37845
37857
  );
37846
- const before2 = await getItem(ctx, session, name3, id3);
37847
- if (!before2.record) throw missingItem(name3, id3);
37858
+ const before2 = await getItem(ctx, session, name3, id2);
37859
+ if (!before2.record) throw missingItem(name3, id2);
37848
37860
  const lease2 = await control(ctx, session);
37849
37861
  await write(
37850
37862
  (operation2) => call(
@@ -37857,7 +37869,7 @@ async function items(ctx, args) {
37857
37869
  expectedVersionId: before2.versionId,
37858
37870
  expectedRevision: before2.revision,
37859
37871
  collection: name3,
37860
- recordId: id3,
37872
+ recordId: id2,
37861
37873
  ...operation2
37862
37874
  },
37863
37875
  external_exports.unknown()
@@ -37865,8 +37877,8 @@ async function items(ctx, args) {
37865
37877
  );
37866
37878
  emit(
37867
37879
  ctx,
37868
- { deleted: true, collection: name3, id: id3 },
37869
- () => `Deleted ${name3}/${printable(id3)} from ${updateLabel(session.updateId)}. The published version keeps it until this Update is published.`
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.`
37870
37882
  );
37871
37883
  return exitCodes.done;
37872
37884
  }
@@ -37876,14 +37888,14 @@ async function items(ctx, args) {
37876
37888
  const patch3 = file2 ? await readData(ctx, file2) : assignments(entity2.fields, rest);
37877
37889
  if (sub === "set" && !Object.keys(patch3).length && !visible && !hidden)
37878
37890
  throw new UsageError(
37879
- `Nothing to change. Example: plume items set ${name3} ${printable(id3)} title="New title".`
37891
+ `Nothing to change. Example: plume items set ${name3} ${printable(id2)} title="New title".`
37880
37892
  );
37881
- const before = await getItem(ctx, session, name3, id3);
37882
- if (sub === "set" && !before.record) throw missingItem(name3, id3);
37893
+ const before = await getItem(ctx, session, name3, id2);
37894
+ if (sub === "set" && !before.record) throw missingItem(name3, id2);
37883
37895
  if (sub === "create" && before.record)
37884
37896
  throw new PlumeToolError(
37885
37897
  "ALREADY_EXISTS",
37886
- `${name3}/${printable(id3)} already exists. Change it with plume items set ${name3} ${printable(id3)} field=value.`
37898
+ `${name3}/${printable(id2)} already exists. Change it with plume items set ${name3} ${printable(id2)} field=value.`
37887
37899
  );
37888
37900
  const defaults = Object.fromEntries(
37889
37901
  entity2.fields.filter((field) => field.default !== void 0).map((field) => [field.name, field.default])
@@ -37902,7 +37914,7 @@ async function items(ctx, args) {
37902
37914
  expectedVersionId: before.versionId,
37903
37915
  expectedRevision: before.revision,
37904
37916
  collection: name3,
37905
- recordId: id3,
37917
+ recordId: id2,
37906
37918
  data,
37907
37919
  visibility,
37908
37920
  fullReplacement: true,
@@ -37914,11 +37926,11 @@ async function items(ctx, args) {
37914
37926
  const issues = saved.issues;
37915
37927
  emit(
37916
37928
  ctx,
37917
- { saved: true, collection: name3, id: id3, visibility, issues },
37929
+ { saved: true, collection: name3, id: id2, visibility, issues },
37918
37930
  () => savedLines(
37919
37931
  sub === "create" ? `Created (${visibilityLabel(visibility)})` : "Saved",
37920
37932
  name3,
37921
- id3,
37933
+ id2,
37922
37934
  session,
37923
37935
  issues
37924
37936
  )
@@ -38165,7 +38177,7 @@ async function takeControl(ctx, args) {
38165
38177
  emit(
38166
38178
  ctx,
38167
38179
  { editing: true },
38168
- () => `You have editing control of this Site. Whoever held it can no longer save until they take it back. It lapses ${LEASE_SECONDS} seconds after your last command.`
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.`
38169
38181
  );
38170
38182
  return exitCodes.done;
38171
38183
  }
@@ -38193,7 +38205,7 @@ async function release(ctx, args) {
38193
38205
  emit(
38194
38206
  ctx,
38195
38207
  { released },
38196
- () => released ? "Editing control released. Someone else can edit this Site now." : "This checkout doesn\u2019t hold editing control."
38208
+ () => released ? "Editing control released. Someone else can edit this Update now." : "This checkout doesn\u2019t hold editing control."
38197
38209
  );
38198
38210
  return exitCodes.done;
38199
38211
  }
@@ -38278,11 +38290,11 @@ Example:
38278
38290
  },
38279
38291
  "take-control": {
38280
38292
  summary: "Take editing control from whoever holds it",
38281
- help: `plume take-control \u2014 take editing control of this Site.
38293
+ help: `plume take-control \u2014 take editing control of this Update.
38282
38294
 
38283
38295
  Usage: plume take-control [--json]
38284
38296
 
38285
- Only one person or agent edits a Site at a time. Taking control stops whoever holds it (in Plume or another checkout) from saving. Use it when plume says someone else is editing and you've checked they're done.
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.
38286
38298
 
38287
38299
  Example:
38288
38300
  plume take-control`,
@@ -38319,7 +38331,7 @@ function explain(error62, ctx) {
38319
38331
  const since = holder?.since ? `, since ${clock(holder.since)}` : "";
38320
38332
  return {
38321
38333
  ...base2,
38322
- message: holder?.you ? `You are editing this Site in another session (a browser tab or another checkout${since}). Finish there, or run plume take-control.` : `Someone else is editing this Site in Plume (${printable(holder?.name ?? "another person")}${since}). Try again when they\u2019re done, or run plume take-control.`,
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.`,
38323
38335
  exit: exitCodes.busy
38324
38336
  };
38325
38337
  }
@@ -38724,14 +38736,15 @@ var remoteHelp = (branch) => ({
38724
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.",
38725
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.`,
38726
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.`,
38727
- CMS_NOT_READY: `Branch ${branch} has no plume.lock for this Site and schema, or its CMS version is not ready. Finish Site setup in Plume and connect the schema the Site was set up with, then run plume connect again.`,
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.`,
38728
38740
  TRANSFER_PENDING: "Plume is holding a pending transfer for this Site. Run plume connect again to resume it.",
38729
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.",
38730
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.",
38731
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.`,
38732
38745
  TRANSFER_INTERRUPTED: "Plume could not finish the transfer and kept it pending. Run plume connect again to resume it.",
38733
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.`,
38734
- SITE_BUSY: "Someone currently holds editing control of this Site in Plume. Wait for their session to end, then run plume connect again."
38747
+ SITE_BUSY: "Someone is editing an Update on this Site in Plume. Wait for their session to end, then run plume connect again."
38735
38748
  });
38736
38749
  async function runConnect(options2) {
38737
38750
  const cwd = await realpath2(resolve4(options2.cwd));
@@ -38943,210 +38956,12 @@ Waiting for browser approval\u2026
38943
38956
 
38944
38957
  // packages/cli/src/index.ts
38945
38958
  init_developer();
38946
-
38947
- // packages/cli/src/init.ts
38948
- init_src();
38949
- init_protocol();
38950
- init_zod();
38951
- init_developer();
38952
- import { randomUUID as randomUUID2 } from "node:crypto";
38953
- import { constants as constants2 } from "node:fs";
38954
- import { link, open as open3, realpath as realpath3, unlink } from "node:fs/promises";
38955
- import { resolve as resolve5 } from "node:path";
38956
- var id2 = external_exports.uuidv7().refine((value) => value === value.toLowerCase());
38957
- var repositorySchema = external_exports.object({
38958
- owner: external_exports.string().min(1),
38959
- name: external_exports.string().min(1),
38960
- integrationBranch: external_exports.string().min(1)
38961
- }).strict();
38962
- var receiptSchema2 = external_exports.object({ binding: contentBindingSchema, repository: repositorySchema }).strict();
38963
- var MAX_LOCK_BYTES = 16 * 1024;
38964
- async function existingLock(path) {
38965
- try {
38966
- const handle2 = await open3(path, constants2.O_RDONLY | constants2.O_NOFOLLOW);
38967
- try {
38968
- const stat = await handle2.stat();
38969
- if (!stat.isFile() || stat.size > MAX_LOCK_BYTES) throw new Error();
38970
- const value = JSON.parse(
38971
- new TextDecoder("utf-8", { fatal: true }).decode(
38972
- await handle2.readFile()
38973
- )
38974
- );
38975
- return contentBindingSchema.parse(value);
38976
- } finally {
38977
- await handle2.close();
38978
- }
38979
- } catch (error62) {
38980
- if (error62.code === "ENOENT") return null;
38981
- throw new PlumeToolError(
38982
- "LOCK_CONFLICT",
38983
- "plume.lock exists but is invalid or unsafe. Inspect it before initializing."
38984
- );
38985
- }
38986
- }
38987
- function sameBinding(left, right) {
38988
- return left.siteId === right.siteId && left.contentVersionId === right.contentVersionId && left.schemaHash === right.schemaHash;
38989
- }
38990
- async function createLock(path, binding) {
38991
- const temp = `${path}.${randomUUID2()}.tmp`;
38992
- try {
38993
- const handle2 = await open3(temp, "wx", 384);
38994
- try {
38995
- await handle2.writeFile(`${JSON.stringify(binding, null, 2)}
38996
- `);
38997
- await handle2.sync();
38998
- } finally {
38999
- await handle2.close();
39000
- }
39001
- await link(temp, path);
39002
- } catch (error62) {
39003
- if (error62.code === "EEXIST") {
39004
- const current = await existingLock(path);
39005
- if (current && sameBinding(current, binding)) return;
39006
- throw new PlumeToolError(
39007
- "LOCK_CONFLICT",
39008
- "plume.lock changed during initialization. Inspect it before retrying."
39009
- );
39010
- }
39011
- throw new PlumeToolError(
39012
- "LOCK_WRITE_FAILED",
39013
- "Could not create plume.lock. Inspect the checkout and retry initialization."
39014
- );
39015
- } finally {
39016
- await unlink(temp).catch(() => void 0);
39017
- }
39018
- }
39019
- async function runLocalInit(options2) {
39020
- const parsedId = id2.safeParse(options2.siteId);
39021
- if (!parsedId.success)
39022
- throw new PlumeToolError(
39023
- "INVALID_INPUT",
39024
- "Pass a lowercase UUIDv7 Site ID with --site."
39025
- );
39026
- const cwd = resolve5(options2.cwd);
39027
- const root3 = await git(cwd, "rev-parse", "--show-toplevel");
39028
- if (await realpath3(root3) !== await realpath3(cwd))
39029
- throw new PlumeToolError(
39030
- "CHECKOUT_MISMATCH",
39031
- "Run plume init from the connected repository root."
39032
- );
39033
- const repository = githubRepository(
39034
- await git(cwd, "config", "--get", "remote.origin.url")
39035
- );
39036
- if (!repository)
39037
- throw new PlumeToolError(
39038
- "CHECKOUT_MISMATCH",
39039
- "The origin must be a GitHub HTTPS or SSH repository URL."
39040
- );
39041
- const schema3 = await loadCheckoutSchema(cwd);
39042
- const hash2 = await schemaHash(schema3);
39043
- const lockPath = resolve5(cwd, "plume.lock");
39044
- const prior = await existingLock(lockPath);
39045
- if (prior && (prior.siteId !== parsedId.data || prior.schemaHash !== hash2))
39046
- throw new PlumeToolError(
39047
- "LOCK_CONFLICT",
39048
- "plume.lock targets another Site or schema. Inspect it before initializing."
39049
- );
39050
- const url2 = developerUrl(options2.endpoint, "api/developer/initialize");
39051
- if (!/^plume_setup_[a-f0-9]{64}$/.test(options2.token))
39052
- throw new PlumeToolError(
39053
- "INVALID_CONFIGURATION",
39054
- "Set PLUME_SETUP_TOKEN to a valid setup credential."
39055
- );
39056
- const body3 = JSON.stringify({ siteId: parsedId.data, schema: schema3, repository });
39057
- if (Buffer.byteLength(body3, "utf8") > 512 * 1024)
39058
- throw new PlumeToolError(
39059
- "INVALID_SCHEMA",
39060
- "The schema exceeds the initialization request limit."
39061
- );
39062
- let response;
39063
- try {
39064
- response = await fetch(url2, {
39065
- method: "POST",
39066
- headers: {
39067
- "content-type": "application/json",
39068
- authorization: `Bearer ${options2.token}`
39069
- },
39070
- body: body3,
39071
- redirect: "error",
39072
- cache: "no-store",
39073
- credentials: "omit",
39074
- signal: AbortSignal.timeout(15e3)
39075
- });
39076
- } catch {
39077
- throw new PlumeToolError(
39078
- "REQUEST_FAILED",
39079
- "Initialization may have completed remotely. Rerun plume init with the same Site and schema to recover."
39080
- );
39081
- }
39082
- if (!response.ok) {
39083
- let code = "REMOTE_ERROR";
39084
- try {
39085
- const remote = await boundedJson(response, 16 * 1024);
39086
- if (remote && typeof remote === "object" && "error" in remote) {
39087
- const error62 = remote.error;
39088
- if (error62 && typeof error62 === "object" && "code" in error62 && typeof error62.code === "string" && /^[A-Z_]{1,40}$/.test(error62.code))
39089
- code = error62.code;
39090
- }
39091
- } catch {
39092
- }
39093
- throw new PlumeToolError(
39094
- code,
39095
- `Initialization was rejected (HTTP ${response.status}). Check Site access and connected repository.`
39096
- );
39097
- }
39098
- let receipt;
39099
- try {
39100
- receipt = receiptSchema2.parse(await boundedJson(response, 16 * 1024));
39101
- } catch {
39102
- throw new PlumeToolError(
39103
- "INVALID_RESPONSE",
39104
- "Initialization may have completed remotely, but its receipt was invalid. Rerun with the same Site and schema."
39105
- );
39106
- }
39107
- 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))
39108
- throw new PlumeToolError(
39109
- "INVALID_RESPONSE",
39110
- "The initialization receipt does not match this Site, schema, repository, or existing lock."
39111
- );
39112
- if (await schemaHash(await loadCheckoutSchema(cwd)) !== hash2)
39113
- throw new PlumeToolError(
39114
- "SCHEMA_MISMATCH",
39115
- "plume.schema.ts changed during initialization. Restore it or rerun with the new schema."
39116
- );
39117
- const currentRepository = githubRepository(
39118
- await git(cwd, "config", "--get", "remote.origin.url")
39119
- );
39120
- if (!currentRepository || currentRepository.owner.toLowerCase() !== repository.owner.toLowerCase() || currentRepository.name.toLowerCase() !== repository.name.toLowerCase())
39121
- throw new PlumeToolError(
39122
- "CHECKOUT_MISMATCH",
39123
- "The origin changed during initialization. Restore it or rerun."
39124
- );
39125
- if (prior) {
39126
- const current = await existingLock(lockPath);
39127
- if (!current || !sameBinding(current, receipt.binding))
39128
- throw new PlumeToolError(
39129
- "LOCK_CONFLICT",
39130
- "plume.lock changed during initialization. Inspect it before retrying."
39131
- );
39132
- } else {
39133
- await createLock(lockPath, receipt.binding);
39134
- }
39135
- return {
39136
- binding: receipt.binding,
39137
- repository: receipt.repository,
39138
- 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."
39139
- };
39140
- }
39141
-
39142
- // packages/cli/src/index.ts
39143
38959
  var DEFAULT_ENDPOINT = "https://app.plume.press";
39144
- var MAX_LOCK_BYTES2 = 16 * 1024;
38960
+ var MAX_LOCK_BYTES = 16 * 1024;
39145
38961
  var MAX_RESPONSE_BYTES2 = 16 * 1024;
39146
38962
  var MAX_SCHEMA_BYTES2 = 256 * 1024;
39147
38963
  var validationSchema = external_exports.object({
39148
38964
  binding: contentBindingSchema,
39149
- mode: external_exports.enum(["preview", "production"]),
39150
38965
  revision: external_exports.number().int().nonnegative(),
39151
38966
  sealed: external_exports.literal(true)
39152
38967
  }).strict();
@@ -39160,10 +38975,10 @@ var PlumeBuildError = class extends Error {
39160
38975
  };
39161
38976
  async function readLock(cwd) {
39162
38977
  try {
39163
- const handle2 = await open5(resolve7(cwd, "plume.lock"), "r");
38978
+ const handle2 = await open4(resolve6(cwd, "plume.lock"), "r");
39164
38979
  try {
39165
38980
  if (!(await handle2.stat()).isFile()) throw new Error();
39166
- const bytes2 = Buffer.alloc(MAX_LOCK_BYTES2 + 1);
38981
+ const bytes2 = Buffer.alloc(MAX_LOCK_BYTES + 1);
39167
38982
  let length = 0;
39168
38983
  while (length < bytes2.length) {
39169
38984
  const result = await handle2.read(
@@ -39175,7 +38990,7 @@ async function readLock(cwd) {
39175
38990
  if (!result.bytesRead) break;
39176
38991
  length += result.bytesRead;
39177
38992
  }
39178
- if (length > MAX_LOCK_BYTES2) throw new Error();
38993
+ if (length > MAX_LOCK_BYTES) throw new Error();
39179
38994
  return contentBindingSchema.parse(
39180
38995
  JSON.parse(
39181
38996
  new TextDecoder("utf-8", { fatal: true }).decode(
@@ -39196,22 +39011,22 @@ async function readLock(cwd) {
39196
39011
  async function validateSchema(cwd, path, binding) {
39197
39012
  let hash2;
39198
39013
  try {
39199
- const jiti = createJiti2(pathToFileURL2(resolve7(cwd, "package.json")).href, {
39014
+ const jiti = createJiti2(pathToFileURL2(resolve6(cwd, "package.json")).href, {
39200
39015
  interopDefault: false,
39201
39016
  moduleCache: false,
39202
39017
  fsCache: false,
39203
39018
  debug: false,
39204
39019
  tryNative: false
39205
39020
  });
39206
- const module = await jiti.import(resolve7(cwd, path));
39021
+ const module = await jiti.import(resolve6(cwd, path));
39207
39022
  const schema3 = defineSchema(module.schema);
39208
39023
  if (new TextEncoder().encode(canonicalJson(schema3)).byteLength > MAX_SCHEMA_BYTES2)
39209
39024
  throw new Error();
39210
39025
  hash2 = await schemaHash(schema3);
39211
- } catch {
39026
+ } catch (error62) {
39212
39027
  throw new PlumeBuildError(
39213
39028
  "INVALID_SCHEMA",
39214
- "Export a valid declarative schema named schema from plume.schema.ts (maximum 256 KiB)."
39029
+ await unresolvedSchemaImport(error62, resolve6(cwd, path)) ?? "Export a valid declarative schema named schema from plume.schema.ts (maximum 256 KiB)."
39215
39030
  );
39216
39031
  }
39217
39032
  if (hash2 !== binding.schemaHash)
@@ -39234,16 +39049,13 @@ function validationUrl(endpoint) {
39234
39049
  );
39235
39050
  }
39236
39051
  }
39237
- async function validateRemote(url2, token, binding, mode) {
39052
+ async function validateRemote(url2, binding) {
39238
39053
  let response;
39239
39054
  try {
39240
39055
  response = await fetch(url2, {
39241
39056
  method: "POST",
39242
- headers: {
39243
- "content-type": "application/json",
39244
- ...token ? { authorization: `Bearer ${token}` } : {}
39245
- },
39246
- body: JSON.stringify({ binding, mode }),
39057
+ headers: { "content-type": "application/json" },
39058
+ body: JSON.stringify({ binding }),
39247
39059
  redirect: "error",
39248
39060
  cache: "no-store",
39249
39061
  credentials: "omit",
@@ -39256,7 +39068,7 @@ async function validateRemote(url2, token, binding, mode) {
39256
39068
  } catch {
39257
39069
  throw new PlumeBuildError(
39258
39070
  "VALIDATION_FAILED",
39259
- mode === "production" ? "Plume could not confirm this build. Build a commit whose plume.lock names published content (Plume commits it when you publish), with the plume.schema.ts committed beside it." : "Plume could not authorize this build. Check the binding, build mode and access credential, then retry."
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."
39260
39072
  );
39261
39073
  }
39262
39074
  try {
@@ -39283,7 +39095,7 @@ async function validateRemote(url2, token, binding, mode) {
39283
39095
  new TextDecoder("utf-8", { fatal: true }).decode(Buffer.concat(chunks))
39284
39096
  )
39285
39097
  );
39286
- if (result.mode !== mode || canonicalJson(result.binding) !== canonicalJson(binding))
39098
+ if (canonicalJson(result.binding) !== canonicalJson(binding))
39287
39099
  throw new Error();
39288
39100
  } catch {
39289
39101
  throw new PlumeBuildError(
@@ -39323,15 +39135,14 @@ async function runCommand2(cwd, command) {
39323
39135
  });
39324
39136
  child.once("close", (code, signal) => {
39325
39137
  cleanup();
39326
- resolveExit(code ?? (signal ? 128 + constants4.signals[signal] : 1));
39138
+ resolveExit(code ?? (signal ? 128 + constants3.signals[signal] : 1));
39327
39139
  });
39328
39140
  });
39329
39141
  }
39330
39142
  async function runBuild(options2) {
39331
- const cwd = resolve7(options2.cwd);
39332
- const directory = resolve7(cwd, ".plume");
39333
- const lockDirectory = resolve7(directory, "build.lock");
39334
- 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");
39335
39146
  try {
39336
39147
  await mkdir4(directory, { recursive: true });
39337
39148
  if (!(await lstat4(directory)).isDirectory()) throw new Error();
@@ -39341,28 +39152,20 @@ async function runBuild(options2) {
39341
39152
  "The .plume build directory is unavailable or is a symbolic link."
39342
39153
  );
39343
39154
  }
39344
- try {
39345
- await mkdir4(lockDirectory);
39346
- } catch {
39347
- throw new PlumeBuildError(
39348
- "BUILD_BUSY",
39349
- "Another Plume build owns this checkout. If it stopped unexpectedly, confirm no build is running before removing .plume/build.lock."
39350
- );
39351
- }
39352
- const temporary = resolve7(directory, `.binding-${randomUUID3()}.json`);
39155
+ const temporary = resolve6(directory, `.binding-${randomUUID2()}.json`);
39353
39156
  try {
39354
39157
  await rm3(bindingFile, { force: true });
39355
- if (options2.mode === "preview" && !options2.token || options2.token.length > 8192 || /\s/.test(options2.token) || !["preview", "production"].includes(options2.mode) || !options2.command.length || options2.command.some(
39158
+ if (!options2.command.length || options2.command.some(
39356
39159
  (part) => typeof part !== "string" || part.includes("\0")
39357
39160
  ) || !options2.command[0]?.trim())
39358
39161
  throw new PlumeBuildError(
39359
39162
  "INVALID_CONFIGURATION",
39360
- "Provide a build command, and PLUME_TOKEN for a preview build."
39163
+ "Provide a build command."
39361
39164
  );
39362
39165
  const url2 = validationUrl(options2.endpoint);
39363
39166
  const binding = await readLock(cwd);
39364
39167
  await validateSchema(cwd, options2.schemaPath ?? "plume.schema.ts", binding);
39365
- await validateRemote(url2, options2.token, binding, options2.mode);
39168
+ await validateRemote(url2, binding);
39366
39169
  await writeFile2(temporary, `${JSON.stringify(binding, null, 2)}
39367
39170
  `, {
39368
39171
  flag: "wx",
@@ -39381,37 +39184,15 @@ async function runBuild(options2) {
39381
39184
  } finally {
39382
39185
  await rm3(temporary, { force: true }).catch(() => {
39383
39186
  });
39384
- await rm3(lockDirectory, { recursive: true, force: true });
39385
39187
  }
39386
39188
  }
39387
39189
  async function main(args, env2 = process.env) {
39388
39190
  if (args[0] === "connect") return connectMain(args, env2);
39389
39191
  if (args[0] === "init") {
39390
39192
  try {
39391
- if (args.length === 1) {
39392
- const { runLocalInit: runOfflineInit } = await Promise.resolve().then(() => (init_local(), local_exports));
39393
- const result2 = await runOfflineInit(process.cwd());
39394
- process.stdout.write(`${JSON.stringify({ ok: true, result: result2 })}
39395
- `);
39396
- return 0;
39397
- }
39398
- if (args.length !== 3 || args[1] !== "--site")
39399
- throw new Error("Usage: plume init [--site <uuidv7>]");
39400
- try {
39401
- await lstat4(resolve7(process.cwd(), ".plume", "local.sqlite"));
39402
- throw new Error(
39403
- "A local Plume database exists. Run plume connect to transfer it once; nothing was uploaded."
39404
- );
39405
- } catch (error62) {
39406
- if (!(error62 && typeof error62 === "object" && "code" in error62 && error62.code === "ENOENT"))
39407
- throw error62;
39408
- }
39409
- const result = await runLocalInit({
39410
- cwd: process.cwd(),
39411
- siteId: args[2],
39412
- endpoint: env2.PLUME_ENDPOINT ?? "",
39413
- token: env2.PLUME_SETUP_TOKEN ?? ""
39414
- });
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());
39415
39196
  process.stdout.write(`${JSON.stringify({ ok: true, result })}
39416
39197
  `);
39417
39198
  return 0;
@@ -39419,7 +39200,7 @@ async function main(args, env2 = process.env) {
39419
39200
  const code = error62 && typeof error62 === "object" && "code" in error62 ? String(error62.code) : "INVALID_INPUT";
39420
39201
  const message = error62 instanceof Error ? error62.message : "Initialization failed.";
39421
39202
  process.stdout.write(
39422
- `${JSON.stringify({ ok: false, error: { code, message: env2.PLUME_SETUP_TOKEN ? message.replaceAll(env2.PLUME_SETUP_TOKEN, "[REDACTED]") : message } })}
39203
+ `${JSON.stringify({ ok: false, error: { code, message } })}
39423
39204
  `
39424
39205
  );
39425
39206
  return 1;
@@ -39464,10 +39245,7 @@ ${localHelp2}
39464
39245
 
39465
39246
  ${connectHelp}
39466
39247
 
39467
- Usage: plume init --site <site-id>
39468
- Initialize a connected Site's empty content with PLUME_SETUP_TOKEN and write plume.lock.
39469
-
39470
- Usage: plume build [--preview] -- <command ...>
39248
+ Usage: plume build -- <command ...>
39471
39249
  Check plume.lock with Plume, then run your framework's build.
39472
39250
 
39473
39251
  ${developerHelp}
@@ -39477,17 +39255,15 @@ ${developerHelp}
39477
39255
  }
39478
39256
  const divider = args.indexOf("--");
39479
39257
  const prefix = args.slice(0, divider);
39480
- if (divider < 1 || prefix[0] !== "build" || prefix.length > 2 || prefix.length === 2 && prefix[1] !== "--preview" || divider === args.length - 1) {
39481
- process.stderr.write("Usage: plume build [--preview] -- <command ...>\n");
39258
+ if (divider < 1 || prefix.length !== 1 || prefix[0] !== "build" || divider === args.length - 1) {
39259
+ process.stderr.write("Usage: plume build -- <command ...>\n");
39482
39260
  return 1;
39483
39261
  }
39484
39262
  try {
39485
39263
  const result = await runBuild({
39486
39264
  cwd: process.cwd(),
39487
39265
  command: args.slice(divider + 1),
39488
- mode: prefix[1] === "--preview" ? "preview" : "production",
39489
- endpoint: env2.PLUME_ENDPOINT || DEFAULT_ENDPOINT,
39490
- token: env2.PLUME_TOKEN ?? ""
39266
+ endpoint: env2.PLUME_ENDPOINT || DEFAULT_ENDPOINT
39491
39267
  });
39492
39268
  return result.exitCode;
39493
39269
  } catch (error62) {