@@ -399,24 +399,42 @@ jobs:
399399 if (!expRes.ok) return;
400400 const text = await expRes.text();
401401 const devDocs = text.trim().split("\n").filter(Boolean).map((l) => JSON.parse(l));
402- const deleteMutations = [];
402+ const nonAssetDeletes = [];
403+ const assetDeletes = [];
403404
404405 for (const d of devDocs) {
405406 if (d._type.startsWith("system.")) continue;
406407 if (d._type === "sanity.imageAsset" || d._type === "sanity.fileAsset") {
407408 if (typeof d.path === "string" && d.path.includes("/production/")) {
408- deleteMutations .push({ delete: { id: d._id } } );
409+ assetDeletes .push(d );
409410 }
410411 continue;
411412 }
412413 if (!activeTypes.has(d._type) || (d._type === "transcript" && !allTargetIds.has(d._id))) {
413- deleteMutations .push({ delete: { id: d._id } } );
414+ nonAssetDeletes .push(d );
414415 }
415416 }
416417
417- if (deleteMutations.length > 0) {
418- console.log(`Cleaning up ${deleteMutations.length} legacy/orphaned documents in 'dev'...`);
419- await sendChunked(deleteMutations, "Cleanup Legacy & Orphaned Docs", "raw");
418+ const totalToDelete = nonAssetDeletes.length + assetDeletes.length;
419+ if (totalToDelete > 0) {
420+ console.log(`Cleaning up ${totalToDelete} legacy/orphaned documents in 'dev'...`);
421+ if (nonAssetDeletes.length > 0) {
422+ // First strip all references on legacy documents so inter-document references cannot block deletion
423+ const emptyStubs = nonAssetDeletes.map((d) => ({ _id: d._id, _type: d._type }));
424+ await sendChunked(emptyStubs, "Cleanup Pass 1: Strip References on Legacy Docs", "createOrReplace");
425+ await sendChunked(
426+ nonAssetDeletes.map((d) => ({ delete: { id: d._id } })),
427+ "Cleanup Pass 2: Delete Legacy Docs",
428+ "raw"
429+ );
430+ }
431+ if (assetDeletes.length > 0) {
432+ await sendChunked(
433+ assetDeletes.map((d) => ({ delete: { id: d._id } })),
434+ "Cleanup Pass 3: Delete Orphaned Production Asset Metadata",
435+ "raw"
436+ );
437+ }
420438 }
421439 }
422440
0 commit comments