@plume-press/cli 0.6.0 → 0.7.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/local.mjs CHANGED
@@ -33491,9 +33491,10 @@ function validatePreviewPath(entity2, path, fields) {
33491
33491
  }
33492
33492
  async function schemaHash(schema2) {
33493
33493
  defineSchema(schema2);
33494
- const bytes2 = new TextEncoder().encode(
33495
- canonicalJson(schema2)
33496
- );
33494
+ return hashSchemaJson(canonicalJson(schema2));
33495
+ }
33496
+ async function hashSchemaJson(json2) {
33497
+ const bytes2 = new TextEncoder().encode(json2);
33497
33498
  const digest = await crypto.subtle.digest("SHA-256", bytes2);
33498
33499
  return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
33499
33500
  }
@@ -33633,7 +33634,10 @@ function validateRecord(schema2, name, data, options2) {
33633
33634
  const entity2 = [...schema2.collections, ...schema2.singletons ?? []].find(
33634
33635
  (candidate) => candidate.name === name
33635
33636
  );
33636
- if (!entity2)
33637
+ return validateRecordFields(entity2?.fields, name, data, options2);
33638
+ }
33639
+ function validateRecordFields(fields, name, data, options2) {
33640
+ if (!fields)
33637
33641
  return [
33638
33642
  {
33639
33643
  path: "",
@@ -33654,7 +33658,7 @@ function validateRecord(schema2, name, data, options2) {
33654
33658
  }
33655
33659
  const issues = [];
33656
33660
  validateFields(
33657
- entity2.fields,
33661
+ fields,
33658
33662
  data,
33659
33663
  "",
33660
33664
  options2.publication,
package/dist/schema.d.ts CHANGED
@@ -198,6 +198,15 @@ export declare function isLocalPath(path: unknown): path is string;
198
198
  export declare function resolvePreviewPath(entity: Collection | Singleton, recordId: string, data: JsonValue | undefined): string | null;
199
199
  /** Hashes a valid schema using its canonical JSON representation. */
200
200
  export declare function schemaHash(schema: SchemaDefinition): Promise<string>;
201
+ /** Owns an immutable schema snapshot for validating many records without rechecking
202
+ * the schema. Mutating the source cannot change the snapshot or its cached hash. */
203
+ export declare function createSchemaValidator<const S extends SchemaDefinition>(source: S): {
204
+ schema: S;
205
+ hash: () => Promise<string>;
206
+ validateRecord: (name: string, data: unknown, options: {
207
+ publication: boolean;
208
+ }) => FieldIssue[];
209
+ };
201
210
  /** Validates shape only; richText HTML requires sanitization at the write/render boundary.
202
211
  * Slug uniqueness, reference targets and media `accept` need the whole content and are
203
212
  * checked where it is available (save, preparation, local store). */
package/dist/schema.mjs CHANGED
@@ -285,12 +285,35 @@ function resolvePreviewPath(entity, recordId, data) {
285
285
  }
286
286
  async function schemaHash(schema) {
287
287
  defineSchema(schema);
288
- const bytes = new TextEncoder().encode(
289
- canonicalJson(schema)
290
- );
288
+ return hashSchemaJson(canonicalJson(schema));
289
+ }
290
+ async function hashSchemaJson(json) {
291
+ const bytes = new TextEncoder().encode(json);
291
292
  const digest = await crypto.subtle.digest("SHA-256", bytes);
292
293
  return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
293
294
  }
295
+ function createSchemaValidator(source) {
296
+ const json = canonicalJson(source);
297
+ const schema = defineSchema(JSON.parse(json));
298
+ const freeze = (value) => {
299
+ for (const child of Object.values(value))
300
+ if (child !== null && typeof child === "object") freeze(child);
301
+ Object.freeze(value);
302
+ };
303
+ freeze(schema);
304
+ const entities = [...schema.collections, ...schema.singletons ?? []];
305
+ let hash;
306
+ return {
307
+ schema,
308
+ hash: () => hash ??= hashSchemaJson(json),
309
+ validateRecord: (name, data, options2) => validateRecordFields(
310
+ entities.find((entity) => entity.name === name)?.fields,
311
+ name,
312
+ data,
313
+ options2
314
+ )
315
+ };
316
+ }
294
317
  var unset = (field, record) => !Object.hasOwn(record, field.name) || record[field.name] === null && !field.required;
295
318
  function validateFields(fields, value, prefix, publication, report) {
296
319
  if (!object(value)) {
@@ -427,7 +450,10 @@ function validateRecord(schema, name, data, options2) {
427
450
  const entity = [...schema.collections, ...schema.singletons ?? []].find(
428
451
  (candidate) => candidate.name === name
429
452
  );
430
- if (!entity)
453
+ return validateRecordFields(entity?.fields, name, data, options2);
454
+ }
455
+ function validateRecordFields(fields, name, data, options2) {
456
+ if (!fields)
431
457
  return [
432
458
  {
433
459
  path: "",
@@ -448,7 +474,7 @@ function validateRecord(schema, name, data, options2) {
448
474
  }
449
475
  const issues = [];
450
476
  validateFields(
451
- entity.fields,
477
+ fields,
452
478
  data,
453
479
  "",
454
480
  options2.publication,
@@ -558,6 +584,7 @@ function validDate(value) {
558
584
  }
559
585
  export {
560
586
  canonicalJson,
587
+ createSchemaValidator,
561
588
  defineSchema,
562
589
  dropMissingReferences,
563
590
  isLocalPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plume-press/cli",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "The plume command: set up a website's Plume CMS and check its builds.",
5
5
  "homepage": "https://app.plume.press",
6
6
  "license": "MIT",
@@ -32,7 +32,8 @@
32
32
  "THIRD_PARTY_NOTICES.md"
33
33
  ],
34
34
  "dependencies": {
35
- "jiti": "2.7.0"
35
+ "jiti": "2.7.0",
36
+ "yazl": "3.3.1"
36
37
  },
37
38
  "publishConfig": {
38
39
  "access": "public"