@drawnagency/primitives 0.1.107 → 0.1.108

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.
@@ -1 +1 @@
1
- {"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorShell.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAejD,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAyDtF,OAAO,KAAK,EAAE,eAAe,EAA2D,MAAM,oBAAoB,CAAC;AA+CnH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA2BxD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAIhB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC;IAIhE,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAKjC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,YAAY,EACZ,MAAM,EACN,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,WAAW,EACX,sBAA8B,EAC9B,eAAe,GAChB,EAAE,KAAK,2CAs8DP;AAwED;6EAC6E;AAC7E,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,EACvC,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,eAAe,EAAE,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK/B"}
1
+ {"version":3,"file":"EditorShell.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorShell.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAejD,OAAO,EAAoC,KAAK,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAuDtF,OAAO,KAAK,EAAE,eAAe,EAA2D,MAAM,oBAAoB,CAAC;AA+CnH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AA2BxD,UAAU,KAAK;IACb,OAAO,EAAE,MAAM,CAAC;IAIhB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAC5B,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,WAAW,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAA;KAAE,GAAG,IAAI,CAAC;IAIhE,sBAAsB,CAAC,EAAE,OAAO,CAAC;IAKjC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAClC,OAAO,EACP,YAAY,EACZ,MAAM,EACN,SAAS,EAAE,gBAAgB,EAC3B,YAAY,EACZ,WAAW,EACX,sBAA8B,EAC9B,eAAe,GAChB,EAAE,KAAK,2CA2+DP;AAwED;6EAC6E;AAC7E,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,WAAW,CAAC,YAAY,CAAC,EACvC,aAAa,EAAE,MAAM,GAAG,IAAI,EAC5B,eAAe,EAAE,MAAM,GAAG,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAK/B"}
@@ -52,6 +52,8 @@ interface PublishDeps {
52
52
  sections: LoadedSection[];
53
53
  index: SiteIndex;
54
54
  savedIds: string[];
55
+ mediaManifest: MediaManifest;
56
+ documentManifest: DocumentManifest;
55
57
  }) => Promise<void>;
56
58
  /** Injected by EditorShell. Receives non-fatal server warnings from a
57
59
  * successful save (e.g. the nav.json replacement was declined by the
@@ -1 +1 @@
1
- {"version":3,"file":"useEditorPublish.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorPublish.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useEditorPublish.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorPublish.ts"],"names":[],"mappings":"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"}
@@ -65,11 +65,24 @@ export declare function getBranchShas(): Promise<{
65
65
  mainSha: string | null;
66
66
  } | null>;
67
67
  export declare function getDeletedSections(): Promise<string[]>;
68
- export declare function cacheContent(sha: string, sections: LoadedSection[], index: SiteIndex, siteConfig: Record<string, unknown>, diff?: {
69
- savedBranchSha: string | null;
70
- changedSectionIds: string[];
71
- mainIndex: SiteIndex | null;
72
- documentManifest?: DocumentManifest;
68
+ /**
69
+ * Write the content snapshot for one commit.
70
+ *
71
+ * `manifests` is REQUIRED, and that is the whole point: both sidecars belong to
72
+ * this sha, so every writer that advances the row must restate them. They used to
73
+ * be optional (the media one lived in a separate store entirely), and every
74
+ * save/publish that re-primed this row left them behind at an older sha — a later
75
+ * cache hit then served pre-upload media ("No Image" on images the published site
76
+ * rendered fine) and an empty document manifest ("File missing" on committed
77
+ * documents). Passing them positionally makes forgetting a compile error.
78
+ */
79
+ export declare function cacheContent(sha: string, sections: LoadedSection[], index: SiteIndex, siteConfig: Record<string, unknown>, manifests: {
80
+ media: MediaManifest;
81
+ documents: DocumentManifest;
82
+ }, diff?: {
83
+ savedBranchSha?: string | null;
84
+ changedSectionIds?: string[];
85
+ mainIndex?: SiteIndex | null;
73
86
  }): Promise<void>;
74
87
  export declare function getCachedContent(): Promise<{
75
88
  sha: string;
@@ -79,14 +92,18 @@ export declare function getCachedContent(): Promise<{
79
92
  savedBranchSha: string | null;
80
93
  changedSectionIds: string[];
81
94
  mainIndex: SiteIndex | null;
82
- documentManifest: DocumentManifest;
95
+ /** Both are null ONLY for a row written before the sidecars moved onto it.
96
+ * Callers must treat null as an unusable cache and re-fetch — substituting an
97
+ * empty manifest would blank every image ("No Image") or every committed
98
+ * document ("File missing") on the page. An EMPTY manifest is a legitimate
99
+ * value and is not null. */
100
+ mediaManifest: MediaManifest | null;
101
+ documentManifest: DocumentManifest | null;
83
102
  } | null>;
84
103
  /** Invalidate only the cached content snapshot (e.g. after a publish removes the
85
104
  * draft), forcing the next editor load to refetch rather than serve stale diff
86
105
  * state. Narrower than discardSavedChanges, which also clears index/meta/config. */
87
106
  export declare function clearContentCache(): Promise<void>;
88
- export declare function persistMediaManifest(manifest: MediaManifest): Promise<void>;
89
- export declare function getMediaManifest(): Promise<MediaManifest | null>;
90
107
  export declare function addPendingMediaItem(item: MediaItem, localUrls?: Record<string, string>, blobs?: Record<string, Blob>): Promise<void>;
91
108
  export declare function getPendingMediaItems(): Promise<MediaItem[]>;
92
109
  export declare function getPendingMediaLocalUrls(id: string): Promise<Record<string, string> | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"dexie.d.ts","sourceRoot":"","sources":["../../src/lib/dexie.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dexie.d.ts","sourceRoot":"","sources":["../../src/lib/dexie.ts"],"names":[],"mappings":"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"}
package/dist/lib/dexie.js CHANGED
@@ -8,7 +8,6 @@ var EditorDatabase = class extends Dexie {
8
8
  meta;
9
9
  siteConfig;
10
10
  contentCache;
11
- mediaManifest;
12
11
  pendingMedia;
13
12
  pendingMediaDeletions;
14
13
  preservedEdits;
@@ -114,6 +113,20 @@ var EditorDatabase = class extends Dexie {
114
113
  preservedEdits: "id, sectionId",
115
114
  pendingDocuments: "id"
116
115
  });
116
+ this.version(11).stores({
117
+ sections: "sectionId",
118
+ siteIndex: "key",
119
+ meta: "key",
120
+ siteConfig: "key",
121
+ contentCache: "key",
122
+ mediaManifest: null,
123
+ pendingMedia: "id",
124
+ pendingMediaDeletions: "id",
125
+ preservedEdits: "id, sectionId",
126
+ pendingDocuments: "id"
127
+ }).upgrade(async (tx) => {
128
+ await tx.table("contentCache").clear();
129
+ });
117
130
  }
118
131
  };
119
132
  var db = null;
@@ -310,7 +323,7 @@ async function getDeletedSections() {
310
323
  const row = await getDb().siteIndex.get("current");
311
324
  return row?.deletedSections ?? [];
312
325
  }
313
- async function cacheContent(sha, sections, index, siteConfig, diff) {
326
+ async function cacheContent(sha, sections, index, siteConfig, manifests, diff) {
314
327
  const now = (/* @__PURE__ */ new Date()).toISOString();
315
328
  await getDb().contentCache.put({
316
329
  key: "current",
@@ -322,7 +335,8 @@ async function cacheContent(sha, sections, index, siteConfig, diff) {
322
335
  savedBranchSha: diff?.savedBranchSha ?? null,
323
336
  changedSectionIds: diff?.changedSectionIds ?? [],
324
337
  mainIndex: diff?.mainIndex ?? null,
325
- documentManifest: diff?.documentManifest ?? null
338
+ mediaManifest: manifests.media,
339
+ documentManifest: manifests.documents
326
340
  });
327
341
  }
328
342
  async function getCachedContent() {
@@ -338,23 +352,13 @@ async function getCachedContent() {
338
352
  // No stored mainIndex (e.g. legacy or post-publish cache) means "no draft",
339
353
  // so the published index equals the current index.
340
354
  mainIndex: row.mainIndex ?? row.index,
341
- // Legacy row (pre-documents package): {} matches the fetch path's posture.
342
- // The narrow stale edge — an old row at a sha that DOES hold a manifest —
343
- // heals on the next fresh load or save.
344
- documentManifest: row.documentManifest ?? {}
355
+ mediaManifest: row.mediaManifest ?? null,
356
+ documentManifest: row.documentManifest ?? null
345
357
  };
346
358
  }
347
359
  async function clearContentCache() {
348
360
  await getDb().contentCache.clear();
349
361
  }
350
- async function persistMediaManifest(manifest) {
351
- const now = (/* @__PURE__ */ new Date()).toISOString();
352
- await getDb().mediaManifest.put({ key: "current", manifest, updatedAt: now });
353
- }
354
- async function getMediaManifest() {
355
- const row = await getDb().mediaManifest.get("current");
356
- return row?.manifest ?? null;
357
- }
358
362
  async function addPendingMediaItem(item, localUrls = {}, blobs = {}) {
359
363
  const now = (/* @__PURE__ */ new Date()).toISOString();
360
364
  await getDb().pendingMedia.put({ id: item.id, item, localUrls, blobs, updatedAt: now });
@@ -444,7 +448,6 @@ export {
444
448
  getDeletedSections,
445
449
  getDirtySectionRows,
446
450
  getDirtySections,
447
- getMediaManifest,
448
451
  getPendingDocumentBlob,
449
452
  getPendingDocuments,
450
453
  getPendingMediaBlobs,
@@ -456,7 +459,6 @@ export {
456
459
  listPreservedEdits,
457
460
  markPendingMediaDeleted,
458
461
  persistAll,
459
- persistMediaManifest,
460
462
  persistSiteConfig,
461
463
  persistSiteIndex,
462
464
  preserveEdit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawnagency/primitives",
3
- "version": "0.1.107",
3
+ "version": "0.1.108",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
@@ -67,8 +67,6 @@ import {
67
67
  discardLocalChanges,
68
68
  getCachedContent,
69
69
  cacheContent,
70
- persistMediaManifest,
71
- getMediaManifest,
72
70
  getPendingMediaItems,
73
71
  getPendingMediaBlobs,
74
72
  getPendingMediaDeletions,
@@ -311,6 +309,13 @@ export default function EditorShell({
311
309
  // immediate 409 retry assembles the saved manifest against the rebased copy.
312
310
  const mediaManifestRef = useRef<MediaManifest>(mediaManifest);
313
311
  useEffect(() => { mediaManifestRef.current = mediaManifest; }, [mediaManifest]);
312
+ // Same reason, for the document sidecar: the collab handlers cache it against a
313
+ // remote sha, and reading the state directly there would either capture a stale
314
+ // closure copy (writing an outdated sidecar for that sha — "File missing" on the
315
+ // next cache hit) or force documentManifest into their dep arrays, churning the
316
+ // callback identity the collab wiring subscribes with.
317
+ const documentManifestRef = useRef<DocumentManifest | null>(documentManifest);
318
+ useEffect(() => { documentManifestRef.current = documentManifest; }, [documentManifest]);
314
319
  // Guards the debounced preview-image composition effect (below): skips
315
320
  // recomposing on the very first run when a preview already exists, and
316
321
  // dedupes concurrent runs against the same composition signature.
@@ -603,13 +608,22 @@ export default function EditorShell({
603
608
  // snapshot, never the rebased result. Caching the rebase (local dirty
604
609
  // overlays folded in) would poison the next recovery's diff: dirty
605
610
  // sections would read as remote-unchanged (silent local-wins) and a
606
- // locally-added section would read as "deleted remotely".
611
+ // locally-added section would read as "deleted remotely". The manifest
612
+ // follows the same rule: the remote one, not the rebased view.
607
613
  await cacheContent(
608
614
  remote.sha ?? remote.savedBranchSha ?? headSha,
609
615
  remote.sections,
610
616
  remote.index,
611
617
  remote.siteConfig,
612
- { savedBranchSha: remote.savedBranchSha, changedSectionIds: remote.changedSectionIds, mainIndex: remote.mainIndex },
618
+ {
619
+ media: remote.mediaManifest ?? mediaManifestRef.current,
620
+ documents: remote.documentManifest ?? documentManifestRef.current ?? {},
621
+ },
622
+ {
623
+ savedBranchSha: remote.savedBranchSha,
624
+ changedSectionIds: remote.changedSectionIds,
625
+ mainIndex: remote.mainIndex,
626
+ },
613
627
  );
614
628
  return true;
615
629
  } catch (err) {
@@ -698,13 +712,21 @@ export default function EditorShell({
698
712
  // ...but the CLEAN fetched remote snapshot is what gets cached as the
699
713
  // baseline (amendment 1: caching the rebased result would poison the next
700
714
  // 409 recovery — dirty sections would read as remote-unchanged and a ghost
701
- // race would never surface).
715
+ // race would never surface). Same for the manifest: remote, not rebased.
702
716
  await cacheContent(
703
717
  remote.sha ?? remote.savedBranchSha ?? headSha,
704
718
  remote.sections,
705
719
  remote.index,
706
720
  remote.siteConfig,
707
- { savedBranchSha: remote.savedBranchSha, changedSectionIds: remote.changedSectionIds, mainIndex: remote.mainIndex },
721
+ {
722
+ media: remote.mediaManifest ?? mediaManifestRef.current,
723
+ documents: remote.documentManifest ?? documentManifestRef.current ?? {},
724
+ },
725
+ {
726
+ savedBranchSha: remote.savedBranchSha,
727
+ changedSectionIds: remote.changedSectionIds,
728
+ mainIndex: remote.mainIndex,
729
+ },
708
730
  );
709
731
  } catch (err) {
710
732
  console.error("Remote saved-event sync failed:", err);
@@ -947,17 +969,24 @@ export default function EditorShell({
947
969
  // just-saved sections now differ from main, so fold them into
948
970
  // changedSectionIds (state + ref + cache stay consistent, and a reload that
949
971
  // hits this cache shows the same badges the server would report).
950
- onBaselineCommitted: async ({ sha, sections: baselineSections, index, savedIds }) => {
972
+ onBaselineCommitted: async ({ sha, sections: baselineSections, index, savedIds, mediaManifest: committedManifest, documentManifest: committedDocumentManifest }) => {
951
973
  const changed = new Set(
952
974
  [...changedSectionIdsRef.current, ...savedIds].filter((id) => id in index.sections),
953
975
  );
954
976
  changedSectionIdsRef.current = changed;
955
977
  setChangedSectionIds(changed);
956
- await cacheContent(sha, baselineSections, index, (siteConfig ?? {}) as Record<string, unknown>, {
957
- savedBranchSha: sha,
958
- changedSectionIds: [...changed],
959
- mainIndex: mainIndexRef.current,
960
- });
978
+ await cacheContent(
979
+ sha, baselineSections, index, (siteConfig ?? {}) as Record<string, unknown>,
980
+ // What the save actually committed — NOT the refs/state, which the
981
+ // onMediaPublished / onDocumentsPublished callbacks only refresh through a
982
+ // state effect and can still lag by a render at this point.
983
+ { media: committedManifest, documents: committedDocumentManifest },
984
+ {
985
+ savedBranchSha: sha,
986
+ changedSectionIds: [...changed],
987
+ mainIndex: mainIndexRef.current,
988
+ },
989
+ );
961
990
  },
962
991
  savingRef: inFlightSaveRef,
963
992
  getEditGeneration: persistence.currentGeneration,
@@ -1148,36 +1177,40 @@ export default function EditorShell({
1148
1177
  // deliberately don't block every load on a freshness fetch to validate this.
1149
1178
  const cacheKeySha = draftHeadSha ?? headSha;
1150
1179
 
1180
+ // A row missing either sidecar predates them moving onto it (v11); it is
1181
+ // not a usable snapshot — serving it would render every image as "No Image"
1182
+ // and every committed document as "File missing" — so treat it as a miss
1183
+ // and re-fetch. An EMPTY manifest is a legitimate value, not an absence.
1151
1184
  const cached = await getCachedContent();
1152
- if (cached && cached.sha === cacheKeySha) {
1185
+ if (cached && cached.sha === cacheKeySha && cached.mediaManifest && cached.documentManifest) {
1153
1186
  loadedSections = cached.sections;
1154
1187
  loadedIndex = cached.index;
1155
1188
  loadedConfig = SiteConfigSchema.parse(cached.siteConfig);
1156
- const savedManifest = await getMediaManifest();
1157
- if (savedManifest) loadedManifest = savedManifest;
1189
+ loadedManifest = cached.mediaManifest;
1158
1190
  setSavedSha(cached.savedBranchSha ?? null);
1159
1191
  setMainSha(headSha);
1160
1192
  setChangedSectionIds(new Set(cached.changedSectionIds ?? []));
1161
1193
  setMainIndex(cached.mainIndex ?? loadedIndex);
1162
1194
  // Without this, a cache-hit load left documentManifest null forever —
1163
1195
  // the siteDocuments memo's null-guard then never lifted and every
1164
- // document row (committed or staged) read "File missing".
1165
- setDocumentManifest(cached.documentManifest ?? {});
1196
+ // document row (committed or staged) read "File missing". The row's copy
1197
+ // is authoritative: the hit gate above rejected a row without one.
1198
+ setDocumentManifest(cached.documentManifest);
1166
1199
  } else {
1167
1200
  const data = await fetchSavedContent();
1168
1201
  loadedSections = data.sections;
1169
1202
  loadedIndex = data.index;
1170
1203
  loadedConfig = SiteConfigSchema.parse(data.siteConfig);
1171
- await cacheContent(data.sha, data.sections, data.index, data.siteConfig, {
1172
- savedBranchSha: data.savedBranchSha,
1173
- changedSectionIds: data.changedSectionIds,
1174
- mainIndex: data.mainIndex,
1175
- documentManifest: data.documentManifest ?? {},
1176
- });
1177
- if (data.mediaManifest) {
1178
- loadedManifest = data.mediaManifest;
1179
- await persistMediaManifest(loadedManifest);
1180
- }
1204
+ if (data.mediaManifest) loadedManifest = data.mediaManifest;
1205
+ await cacheContent(
1206
+ data.sha, data.sections, data.index, data.siteConfig,
1207
+ { media: loadedManifest, documents: data.documentManifest ?? {} },
1208
+ {
1209
+ savedBranchSha: data.savedBranchSha,
1210
+ changedSectionIds: data.changedSectionIds,
1211
+ mainIndex: data.mainIndex,
1212
+ },
1213
+ )
1181
1214
  setDocumentManifest(data.documentManifest ?? {});
1182
1215
  setSavedSha(data.savedBranchSha);
1183
1216
  setMainSha(headSha);
@@ -1343,9 +1376,11 @@ export default function EditorShell({
1343
1376
  setSiteConfig(parsed.data);
1344
1377
  applySiteConfigPreview(parsed.data);
1345
1378
  }
1379
+ // Discard restores the cached snapshot, so the sidecars must come from that
1380
+ // same row — anything else could disagree with the sections we just set.
1381
+ if (cached.mediaManifest) setMediaManifest(cached.mediaManifest);
1382
+ if (cached.documentManifest) setDocumentManifest(cached.documentManifest);
1346
1383
  }
1347
- const savedManifest = await getMediaManifest();
1348
- setMediaManifest(savedManifest ?? { images: {}, folders: {} });
1349
1384
  persistence.clearConfigDirty();
1350
1385
  // Discard wiped the Dexie siteIndex row — no unsaved structure remains.
1351
1386
  // Tokenless: discard is unconditional, unlike the save-success clear.
@@ -98,7 +98,7 @@ interface PublishDeps {
98
98
  * baseline that recoverConflict diffs against. Without this, the baseline
99
99
  * dies at the first save (discardSavedChanges clears it) and later 409
100
100
  * recoveries would silently merge local-wins. */
101
- onBaselineCommitted?: (args: { sha: string; sections: LoadedSection[]; index: SiteIndex; savedIds: string[] }) => Promise<void>;
101
+ onBaselineCommitted?: (args: { sha: string; sections: LoadedSection[]; index: SiteIndex; savedIds: string[]; mediaManifest: MediaManifest; documentManifest: DocumentManifest }) => Promise<void>;
102
102
  /** Injected by EditorShell. Receives non-fatal server warnings from a
103
103
  * successful save (e.g. the nav.json replacement was declined by the
104
104
  * degraded-nav guard) so the shell can surface them instead of the save
@@ -291,6 +291,15 @@ export function useEditorPublish({
291
291
  uploadedItems: MediaItem[];
292
292
  // The index actually sent (deletions applied) — the committed index state.
293
293
  sentIndex: SiteIndex;
294
+ // The media manifest as committed by this save: the assembled manifest when
295
+ // media changed, otherwise the (unchanged) manifest we saved against. The
296
+ // content-cache re-prime writes it alongside the new sha, so the two can
297
+ // never drift.
298
+ committedManifest: MediaManifest;
299
+ // The document sidecar as committed by this save — the view we saved against,
300
+ // plus the entries this save committed, minus the ids it deleted. Same
301
+ // contract as committedManifest: it rides the cache write for this sha.
302
+ committedDocumentManifest: DocumentManifest;
294
303
  committedDocumentIds: string[];
295
304
  // The deleted ids the final request actually carried — empty when nothing
296
305
  // was staged, and never populated on a failure (see the catch below).
@@ -499,6 +508,10 @@ export function useEditorPublish({
499
508
  savedSections: dirty.map(({ sectionId, updatedAt, content }) => ({ sectionId, updatedAt, content })),
500
509
  uploadedItems: [...uploadedItems, ...finalUploads.map((u) => u.item)],
501
510
  sentIndex: siteIndex,
511
+ committedManifest: gathered.updatedManifest ?? args.mediaManifest,
512
+ // Read AFTER the final request: committedDocuments is complete and the
513
+ // deletions (which ride only that request) have landed.
514
+ committedDocumentManifest: documentManifestToSend(),
502
515
  committedDocumentIds,
503
516
  committedDocumentDeletions: args.pendingDocumentDeletions,
504
517
  };
@@ -659,7 +672,7 @@ export function useEditorPublish({
659
672
  return;
660
673
  }
661
674
 
662
- const { sha, savedSections, uploadedItems, sentIndex, committedDocumentIds, committedDocumentDeletions } = await saveWithConflictRecovery();
675
+ const { sha, savedSections, uploadedItems, sentIndex, committedManifest, committedDocumentManifest, committedDocumentIds, committedDocumentDeletions } = await saveWithConflictRecovery();
663
676
  onShasUpdated(sha, null);
664
677
 
665
678
  try {
@@ -681,6 +694,8 @@ export function useEditorPublish({
681
694
  sections: baselineSections,
682
695
  index: sentIndex,
683
696
  savedIds: savedSections.map((s) => s.sectionId),
697
+ mediaManifest: committedManifest,
698
+ documentManifest: committedDocumentManifest,
684
699
  });
685
700
  }
686
701
  finishSave(uploadedItems, savedSections.map((s) => s.sectionId));
@@ -750,10 +765,12 @@ export function useEditorPublish({
750
765
  let savedSections: { sectionId: string; updatedAt: string; content: SectionContent }[] = [];
751
766
  let uploadedItems: MediaItem[] = [];
752
767
  let sentIndex: SiteIndex | null = null;
768
+ let committedManifest: MediaManifest | null = null;
769
+ let committedDocumentManifest: DocumentManifest | null = null;
753
770
  let committedDocumentIds: string[] = [];
754
771
  let committedDocumentDeletions: string[] = [];
755
772
  if (hasLocalEdits) {
756
- ({ savedSections, uploadedItems, sentIndex, committedDocumentIds, committedDocumentDeletions } = await saveWithConflictRecovery());
773
+ ({ savedSections, uploadedItems, sentIndex, committedManifest, committedDocumentManifest, committedDocumentIds, committedDocumentDeletions } = await saveWithConflictRecovery());
757
774
  }
758
775
 
759
776
  setPublishAction("publishing");
@@ -789,7 +806,15 @@ export function useEditorPublish({
789
806
  savedRows: savedSections,
790
807
  sentIndex: sentIndex!,
791
808
  });
792
- await cacheContent(sha, baselineSections, sentIndex!, siteConfig!);
809
+ // Both sidecars ride the same write as the sha they belong to: publish
810
+ // deleted the draft, so main's head IS this sha and the next load hits
811
+ // this row. Omitting them here is what blanked freshly uploaded images
812
+ // ("No Image", while the published site was correct) and freshly
813
+ // committed documents ("File missing").
814
+ await cacheContent(sha, baselineSections, sentIndex!, siteConfig!, {
815
+ media: committedManifest!,
816
+ documents: committedDocumentManifest!,
817
+ });
793
818
  finishSave(uploadedItems, savedSections.map((s) => s.sectionId));
794
819
  if (committedDocumentIds.length > 0) onDocumentsPublished?.(committedDocumentIds);
795
820
  if (committedDocumentDeletions.length > 0) onDocumentsDeleted?.(committedDocumentDeletions);
package/src/lib/dexie.ts CHANGED
@@ -50,19 +50,21 @@ interface ContentCacheRow {
50
50
  savedBranchSha?: string | null;
51
51
  changedSectionIds?: string[];
52
52
  mainIndex?: SiteIndex | null;
53
- // The document sidecar at this sha. Optional for rows written by older
54
- // packages; readers fall back to {} (same posture as the fetch path's
55
- // `data.documentManifest ?? {}`). Without this, a cache-hit editor load left
56
- // documentManifest null and the whole documents feature dead for the session.
53
+ // Both sidecars AT THIS SHA. They live HERE and nowhere else, and cacheContent
54
+ // takes them as a required argument, because every way of storing them apart
55
+ // from the sha drifted: the media manifest was a separate singleton row and the
56
+ // document manifest was an optional extra, and both were written only by the
57
+ // cache-miss load path — so every save/publish that re-primed this row advanced
58
+ // the sha and left them behind. A later cache hit then restored pre-upload
59
+ // media (freshly uploaded images rendered "No Image" in the editor while the
60
+ // published site was correct) and an empty document manifest (committed
61
+ // documents read "File missing"). Optional in the TYPE only because Dexie rows
62
+ // are not schema-enforced; readers treat absence as a MISS (getCachedContent),
63
+ // never as "nothing here".
64
+ mediaManifest?: MediaManifest | null;
57
65
  documentManifest?: DocumentManifest | null;
58
66
  }
59
67
 
60
- interface MediaManifestRow {
61
- key: string;
62
- manifest: MediaManifest;
63
- updatedAt: string;
64
- }
65
-
66
68
  interface PendingMediaRow {
67
69
  id: string;
68
70
  item: MediaItem;
@@ -101,7 +103,6 @@ class EditorDatabase extends Dexie {
101
103
  meta!: Dexie.Table<MetaRow, string>;
102
104
  siteConfig!: Dexie.Table<SiteConfigRow, string>;
103
105
  contentCache!: Dexie.Table<ContentCacheRow, string>;
104
- mediaManifest!: Dexie.Table<MediaManifestRow, string>;
105
106
  pendingMedia!: Dexie.Table<PendingMediaRow, string>;
106
107
  pendingMediaDeletions!: Dexie.Table<PendingMediaDeletionRow, string>;
107
108
  preservedEdits!: Dexie.Table<PreservedEditRow, string>;
@@ -223,6 +224,28 @@ class EditorDatabase extends Dexie {
223
224
  preservedEdits: "id, sectionId",
224
225
  pendingDocuments: "id",
225
226
  });
227
+ // v11: the media manifest moved onto the sha-keyed contentCache row and the
228
+ // standalone `mediaManifest` store is deleted. It was written by the
229
+ // cache-miss load path ONLY, so every save/publish that re-primed
230
+ // contentCache advanced the cached sha while leaving the manifest at its
231
+ // older value — and the next cache hit served that stale manifest, blanking
232
+ // every image uploaded since. Dropping the store makes the drift
233
+ // unrepresentable. contentCache is cleared because no pre-v11 row carries a
234
+ // manifest; the next load re-fetches and writes both together.
235
+ this.version(11).stores({
236
+ sections: "sectionId",
237
+ siteIndex: "key",
238
+ meta: "key",
239
+ siteConfig: "key",
240
+ contentCache: "key",
241
+ mediaManifest: null,
242
+ pendingMedia: "id",
243
+ pendingMediaDeletions: "id",
244
+ preservedEdits: "id, sectionId",
245
+ pendingDocuments: "id",
246
+ }).upgrade(async (tx) => {
247
+ await tx.table("contentCache").clear();
248
+ });
226
249
  }
227
250
  }
228
251
 
@@ -478,12 +501,28 @@ export async function getDeletedSections(): Promise<string[]> {
478
501
  return row?.deletedSections ?? [];
479
502
  }
480
503
 
504
+ /**
505
+ * Write the content snapshot for one commit.
506
+ *
507
+ * `manifests` is REQUIRED, and that is the whole point: both sidecars belong to
508
+ * this sha, so every writer that advances the row must restate them. They used to
509
+ * be optional (the media one lived in a separate store entirely), and every
510
+ * save/publish that re-primed this row left them behind at an older sha — a later
511
+ * cache hit then served pre-upload media ("No Image" on images the published site
512
+ * rendered fine) and an empty document manifest ("File missing" on committed
513
+ * documents). Passing them positionally makes forgetting a compile error.
514
+ */
481
515
  export async function cacheContent(
482
516
  sha: string,
483
517
  sections: LoadedSection[],
484
518
  index: SiteIndex,
485
519
  siteConfig: Record<string, unknown>,
486
- diff?: { savedBranchSha: string | null; changedSectionIds: string[]; mainIndex: SiteIndex | null; documentManifest?: DocumentManifest },
520
+ manifests: { media: MediaManifest; documents: DocumentManifest },
521
+ diff?: {
522
+ savedBranchSha?: string | null;
523
+ changedSectionIds?: string[];
524
+ mainIndex?: SiteIndex | null;
525
+ },
487
526
  ): Promise<void> {
488
527
  const now = new Date().toISOString();
489
528
  await getDb().contentCache.put({
@@ -496,7 +535,8 @@ export async function cacheContent(
496
535
  savedBranchSha: diff?.savedBranchSha ?? null,
497
536
  changedSectionIds: diff?.changedSectionIds ?? [],
498
537
  mainIndex: diff?.mainIndex ?? null,
499
- documentManifest: diff?.documentManifest ?? null,
538
+ mediaManifest: manifests.media,
539
+ documentManifest: manifests.documents,
500
540
  });
501
541
  }
502
542
 
@@ -508,7 +548,13 @@ export async function getCachedContent(): Promise<{
508
548
  savedBranchSha: string | null;
509
549
  changedSectionIds: string[];
510
550
  mainIndex: SiteIndex | null;
511
- documentManifest: DocumentManifest;
551
+ /** Both are null ONLY for a row written before the sidecars moved onto it.
552
+ * Callers must treat null as an unusable cache and re-fetch — substituting an
553
+ * empty manifest would blank every image ("No Image") or every committed
554
+ * document ("File missing") on the page. An EMPTY manifest is a legitimate
555
+ * value and is not null. */
556
+ mediaManifest: MediaManifest | null;
557
+ documentManifest: DocumentManifest | null;
512
558
  } | null> {
513
559
  const row = await getDb().contentCache.get("current");
514
560
  if (!row) return null;
@@ -522,10 +568,8 @@ export async function getCachedContent(): Promise<{
522
568
  // No stored mainIndex (e.g. legacy or post-publish cache) means "no draft",
523
569
  // so the published index equals the current index.
524
570
  mainIndex: row.mainIndex ?? row.index,
525
- // Legacy row (pre-documents package): {} matches the fetch path's posture.
526
- // The narrow stale edge — an old row at a sha that DOES hold a manifest —
527
- // heals on the next fresh load or save.
528
- documentManifest: row.documentManifest ?? {},
571
+ mediaManifest: row.mediaManifest ?? null,
572
+ documentManifest: row.documentManifest ?? null,
529
573
  };
530
574
  }
531
575
 
@@ -536,16 +580,6 @@ export async function clearContentCache(): Promise<void> {
536
580
  await getDb().contentCache.clear();
537
581
  }
538
582
 
539
- export async function persistMediaManifest(manifest: MediaManifest): Promise<void> {
540
- const now = new Date().toISOString();
541
- await getDb().mediaManifest.put({ key: "current", manifest, updatedAt: now });
542
- }
543
-
544
- export async function getMediaManifest(): Promise<MediaManifest | null> {
545
- const row = await getDb().mediaManifest.get("current");
546
- return row?.manifest ?? null;
547
- }
548
-
549
583
  export async function addPendingMediaItem(
550
584
  item: MediaItem,
551
585
  localUrls: Record<string, string> = {},