@cardinali-studio/adminkit 2.2.17 → 2.2.19

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/api.d.ts CHANGED
@@ -288,6 +288,9 @@ export declare const api: {
288
288
  trashed: number;
289
289
  pagesUpdated: string[];
290
290
  refsToken?: string;
291
+ d1?: boolean;
292
+ deferred?: boolean;
293
+ operationId?: string;
291
294
  }>;
292
295
  requests: () => Promise<{
293
296
  ok: true;
@@ -1,6 +1,13 @@
1
- import { type AssetFile, type AssetFolder } from "../../api.js";
1
+ import { api, type AssetFile, type AssetFolder } from "../../api.js";
2
2
  import type { MediaOperationStatus } from "../../media.js";
3
3
  import { type MediaUploadJob } from "./media-upload-queue.js";
4
+ /** D1 registra l'intera cancellazione nel preflight: non esistono né il token Git né i
5
+ * successivi gruppi R2 della corsia legacy. Tenere qui la biforcazione evita che il client
6
+ * annunci un falso errore dopo che il server ha già accettato l'operazione. */
7
+ export declare function deleteMediaKeys(keys: string[], remove: typeof api.remove, onProgress?: (done: number) => void): Promise<{
8
+ done: number;
9
+ refsToken?: string;
10
+ }>;
4
11
  export type MediaOperationState = "idle" | "planning" | "awaiting_confirmation" | "moving" | "deleting" | "renaming" | "creating_folder" | "journal";
5
12
  export type SortKey = "uploaded" | "capturedAt" | "name" | "size";
6
13
  export declare const SORT_LABELS: Record<SortKey, string>;
@@ -21,6 +21,28 @@ import { executeMediaMovePlan, mediaMoveConfirmation, mediaMoveNeedsConfirmation
21
21
  * pensa che sia bloccato. Alzarlo fa tornare il difetto: richieste lunghe che muoiono a metà. */
22
22
  const CHUNK = 10;
23
23
  const MOVE_CONFIRM_FILE_THRESHOLD = 2;
24
+ /** D1 registra l'intera cancellazione nel preflight: non esistono né il token Git né i
25
+ * successivi gruppi R2 della corsia legacy. Tenere qui la biforcazione evita che il client
26
+ * annunci un falso errore dopo che il server ha già accettato l'operazione. */
27
+ export async function deleteMediaKeys(keys, remove, onProgress = () => { }) {
28
+ const preflight = await remove({ keys }, { refsOnly: true });
29
+ if (preflight.d1 === true) {
30
+ const done = preflight.trashed ?? keys.length;
31
+ onProgress(done);
32
+ return { done };
33
+ }
34
+ if (!preflight.refsToken) {
35
+ throw new Error("Il server non ha confermato la verifica dei riferimenti.");
36
+ }
37
+ let done = 0;
38
+ for (let i = 0; i < keys.length; i += CHUNK) {
39
+ const group = keys.slice(i, i + CHUNK);
40
+ const result = await remove({ keys: group }, { skipRefs: true, refsToken: preflight.refsToken });
41
+ done += result.trashed ?? group.length;
42
+ onProgress(done);
43
+ }
44
+ return { done, refsToken: preflight.refsToken };
45
+ }
24
46
  export const SORT_LABELS = {
25
47
  uploaded: "caricamento", capturedAt: "scatto", name: "nome", size: "peso",
26
48
  };
@@ -410,17 +432,9 @@ export function useMediaLibrary({ mode, multiple = true, active = true, remember
410
432
  let refsToken;
411
433
  if (keys.length) {
412
434
  setProgress({ done: 0, total: keys.length, verb: "Cestino" });
413
- const preflight = await api.remove({ keys }, { refsOnly: true });
414
- if (!preflight.refsToken)
415
- throw new Error("Il server non ha confermato la verifica dei riferimenti.");
416
- refsToken = preflight.refsToken;
417
- let done = 0;
418
- for (let i = 0; i < keys.length; i += CHUNK) {
419
- const group = keys.slice(i, i + CHUNK);
420
- const r = await api.remove({ keys: group }, { skipRefs: true, refsToken: preflight.refsToken });
421
- done += r.trashed ?? group.length;
422
- setProgress({ done, total: keys.length, verb: "Cestino" });
423
- }
435
+ const result = await deleteMediaKeys(keys, api.remove, (done) => setProgress({ done, total: keys.length, verb: "Cestino" }));
436
+ refsToken = result.refsToken;
437
+ const done = result.done;
424
438
  if (done < keys.length) {
425
439
  failure = `Cestinate ${done} foto su ${keys.length}: le altre sono ancora lì, riprova.`;
426
440
  }
@@ -123,6 +123,9 @@ async function rewriteDocuments({ db, data, replacements = {}, removals = [] })
123
123
  schemaVersion: row.schemaVersion, tombstone: false, payload: normalized.payload,
124
124
  });
125
125
  }
126
+ /* Nessun riferimento è un esito valido: l'operazione Media deve proseguire
127
+ * senza costruire una transazione editoriale vuota, che `saveMany` rifiuta. */
128
+ if (!commands.length) return { documents: [] };
126
129
  const who = editor(data);
127
130
  const repository = new D1ContentRepository(db);
128
131
  /* Every command was fully parsed and site-validated before the first write.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cardinali-studio/adminkit",
3
- "version": "2.2.17",
3
+ "version": "2.2.19",
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",