@cardinali-studio/adminkit 2.2.23 → 2.2.24

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.
@@ -2,10 +2,10 @@
2
2
  * validator remains the authority for every draft revision generated by an
3
3
  * explicit Media operation. Git is never consulted from this module. */
4
4
  import {
5
- canonicalChecksum, canonicalJson, contentSaveRequestChecksum, D1ContentRepository,
5
+ canonicalChecksum, contentSaveRequestChecksum, D1ContentRepository,
6
6
  } from "../../persistence.js";
7
7
  import {
8
- D1MediaOperationRepository, mediaPublicUrl, prepareMediaCopy, rewriteMediaValue,
8
+ canonicalR2Metadata, D1MediaOperationRepository, mediaPublicUrl, prepareMediaCopy, rewriteMediaValue,
9
9
  } from "../../media.js";
10
10
  import { validateContentDocument } from "../site.js";
11
11
  import { isKey, moveToTrash, sanitizeName } from "./assets.js";
@@ -137,7 +137,7 @@ async function inspectSource(bucket, entry) {
137
137
  ...entry,
138
138
  objectChecksum,
139
139
  etag: object.etag ?? null,
140
- metadataJson: canonicalJson({ httpMetadata: object.httpMetadata ?? {}, customMetadata: object.customMetadata ?? {} }),
140
+ metadataJson: canonicalR2Metadata(object.httpMetadata ?? {}, object.customMetadata ?? {}),
141
141
  };
142
142
  }
143
143
 
package/dist/media.d.ts CHANGED
@@ -177,6 +177,9 @@ export type MediaR2Bucket = {
177
177
  };
178
178
  export type MediaPreparationJournal = Pick<D1MediaOperationRepository, "recordPreparedEntry">;
179
179
  export type MediaFinalizationJournal = Pick<D1MediaOperationRepository, "beginFinalization" | "recordFinalizedEntry">;
180
+ /** Cloudflare may expose unset R2 metadata fields as enumerable `undefined`
181
+ * values. Persist the JSON-visible representation, not the runtime wrapper. */
182
+ export declare function canonicalR2Metadata(httpMetadata?: MediaR2Object["httpMetadata"], customMetadata?: MediaR2Object["customMetadata"]): string;
180
183
  /** Copy-first R2 effect. No existing destination is overwritten: an identical
181
184
  * prior copy is an idempotent retry, while any opaque collision stops safely. */
182
185
  export declare function prepareMediaCopy(input: {
package/dist/media.js CHANGED
@@ -449,6 +449,11 @@ export class D1MediaOperationRepository {
449
449
  }
450
450
  }
451
451
  const MEDIA_CHECKSUM_METADATA = "adminkit-sha256";
452
+ /** Cloudflare may expose unset R2 metadata fields as enumerable `undefined`
453
+ * values. Persist the JSON-visible representation, not the runtime wrapper. */
454
+ export function canonicalR2Metadata(httpMetadata = {}, customMetadata = {}) {
455
+ return canonicalJson(JSON.parse(JSON.stringify({ httpMetadata, customMetadata })));
456
+ }
452
457
  async function bytesChecksum(bytes) {
453
458
  const digest = await crypto.subtle.digest("SHA-256", bytes);
454
459
  return Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("");
@@ -477,7 +482,7 @@ export async function prepareMediaCopy(input) {
477
482
  return input.journal.recordPreparedEntry({
478
483
  operationId: input.operationId, entryId: input.entryId, now: input.now, objectChecksum: checksum,
479
484
  etag: verified.etag ?? null,
480
- metadataJson: canonicalJson({ httpMetadata: source.httpMetadata ?? {}, customMetadata: source.customMetadata ?? {} }),
485
+ metadataJson: canonicalR2Metadata(source.httpMetadata ?? {}, source.customMetadata ?? {}),
481
486
  });
482
487
  }
483
488
  /** Cleanup starts only after the release is published. Failures are recorded as
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardinali-studio/adminkit",
3
- "version": "2.2.23",
3
+ "version": "2.2.24",
4
4
  "type": "module",
5
5
  "description": "Motore riusabile di un pannello di amministrazione per siti Hugo su Cloudflare Pages: codec del front matter guidato dallo schema, form React, libreria media su R2. NIENTE di specifico di un sito qui dentro.",
6
6
  "license": "UNLICENSED",