@sanity-labs/client-fake-for-test 0.7.0 → 0.8.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/index.cjs +227 -164
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -11
- package/dist/index.d.ts +43 -11
- package/dist/index.js +227 -164
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -73,57 +73,6 @@ function makeRequestImpl(getAccess, projectId, dataset) {
|
|
|
73
73
|
);
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
|
-
function createTestStore(initial) {
|
|
77
|
-
const docs = /* @__PURE__ */ new Map(), promote2 = (doc) => {
|
|
78
|
-
if (typeof doc._id != "string" || doc._id.length === 0)
|
|
79
|
-
throw fakeError(
|
|
80
|
-
`Cannot seed/store a document without a non-empty string \`_id\` (got ${JSON.stringify(doc._id)}). This fake never auto-generates ids \u2014 give every document an explicit _id. Document: ${JSON.stringify(doc)}`
|
|
81
|
-
);
|
|
82
|
-
if (typeof doc._type != "string" || doc._type.length === 0)
|
|
83
|
-
throw fakeError(
|
|
84
|
-
`Document "${doc._id}" is missing a non-empty string \`_type\` (got ${JSON.stringify(doc._type)}). Every Sanity document needs a _type.`
|
|
85
|
-
);
|
|
86
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
87
|
-
return {
|
|
88
|
-
...doc,
|
|
89
|
-
_id: doc._id,
|
|
90
|
-
_type: doc._type,
|
|
91
|
-
_rev: doc._rev ?? cryptoRandomKey(),
|
|
92
|
-
_createdAt: doc._createdAt ?? now,
|
|
93
|
-
_updatedAt: doc._updatedAt ?? now
|
|
94
|
-
};
|
|
95
|
-
}, seed = (documents) => {
|
|
96
|
-
docs.clear();
|
|
97
|
-
for (const d of documents) {
|
|
98
|
-
const promoted = promote2(d);
|
|
99
|
-
docs.set(promoted._id, promoted);
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
return initial && seed(initial), {
|
|
103
|
-
seed,
|
|
104
|
-
add: (documents) => {
|
|
105
|
-
for (const d of documents) {
|
|
106
|
-
const promoted = promote2(d);
|
|
107
|
-
docs.set(promoted._id, promoted);
|
|
108
|
-
}
|
|
109
|
-
},
|
|
110
|
-
reset: () => docs.clear(),
|
|
111
|
-
all: () => [...docs.values()],
|
|
112
|
-
get: (id) => docs.get(id),
|
|
113
|
-
put: (doc) => {
|
|
114
|
-
docs.set(doc._id, doc);
|
|
115
|
-
},
|
|
116
|
-
remove: (id) => {
|
|
117
|
-
const doc = docs.get(id);
|
|
118
|
-
return doc && docs.delete(id), doc;
|
|
119
|
-
},
|
|
120
|
-
snapshot: () => [...docs.values()]
|
|
121
|
-
};
|
|
122
|
-
}
|
|
123
|
-
function cryptoRandomKey(length = 12) {
|
|
124
|
-
const bytes = new Uint8Array(length);
|
|
125
|
-
return globalThis.crypto.getRandomValues(bytes), [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, length);
|
|
126
|
-
}
|
|
127
76
|
function describeType(value) {
|
|
128
77
|
return value === null ? "null" : Array.isArray(value) ? "an array" : `a ${typeof value}`;
|
|
129
78
|
}
|
|
@@ -326,13 +275,140 @@ function insertIntoArray(doc, position, anchor, items) {
|
|
|
326
275
|
const idx = resolveSelector(arr, last.selector);
|
|
327
276
|
position === "replace" ? arr.splice(idx, 1, ...items) : position === "before" ? arr.splice(idx, 0, ...items) : arr.splice(idx + 1, 0, ...items);
|
|
328
277
|
}
|
|
329
|
-
const
|
|
278
|
+
const DRAFTS_PREFIX = "drafts.", VERSIONS_PREFIX$1 = "versions.", RELEASE_DOC_PREFIX$1 = "_.releases.";
|
|
279
|
+
function publishedIdOf(id) {
|
|
280
|
+
if (id.startsWith(DRAFTS_PREFIX)) return id.slice(DRAFTS_PREFIX.length);
|
|
281
|
+
if (id.startsWith(VERSIONS_PREFIX$1)) {
|
|
282
|
+
const rest = id.slice(VERSIONS_PREFIX$1.length), dot = rest.indexOf(".");
|
|
283
|
+
return dot === -1 ? rest : rest.slice(dot + 1);
|
|
284
|
+
}
|
|
285
|
+
return id;
|
|
286
|
+
}
|
|
287
|
+
function releaseNameOf(id) {
|
|
288
|
+
if (!id.startsWith(VERSIONS_PREFIX$1)) return;
|
|
289
|
+
const rest = id.slice(VERSIONS_PREFIX$1.length), dot = rest.indexOf(".");
|
|
290
|
+
if (dot !== -1)
|
|
291
|
+
return rest.slice(0, dot);
|
|
292
|
+
}
|
|
293
|
+
const isDraftId = (id) => id.startsWith(DRAFTS_PREFIX), isVersionId = (id) => id.startsWith(VERSIONS_PREFIX$1), isSystemId = (id) => id.startsWith("_."), isReleaseDocId = (id) => id.startsWith(RELEASE_DOC_PREFIX$1);
|
|
294
|
+
function applyPerspective(docs, perspective) {
|
|
295
|
+
if (perspective === "raw") return [...docs];
|
|
296
|
+
if (perspective === "published")
|
|
297
|
+
return docs.filter((d) => !isDraftId(d._id) && !isVersionId(d._id) && !isSystemId(d._id));
|
|
298
|
+
if (perspective === "drafts")
|
|
299
|
+
return mergeStack(docs, [], { includeDrafts: !0, includeReleaseDocs: !1 });
|
|
300
|
+
const stack = [];
|
|
301
|
+
let includeDrafts = !1;
|
|
302
|
+
for (const entry of perspective)
|
|
303
|
+
entry === "drafts" ? includeDrafts = !0 : stack.push(entry);
|
|
304
|
+
return mergeStack(docs, stack, { includeDrafts, includeReleaseDocs: !0 });
|
|
305
|
+
}
|
|
306
|
+
function mergeStack(docs, releaseStack, options) {
|
|
307
|
+
const groups = /* @__PURE__ */ new Map(), systemReleases = [];
|
|
308
|
+
for (const doc of docs) {
|
|
309
|
+
if (isReleaseDocId(doc._id)) {
|
|
310
|
+
options.includeReleaseDocs && systemReleases.push(doc);
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
if (isSystemId(doc._id)) continue;
|
|
314
|
+
const pubId = publishedIdOf(doc._id);
|
|
315
|
+
let group = groups.get(pubId);
|
|
316
|
+
if (group === void 0 && (group = { versions: /* @__PURE__ */ new Map() }, groups.set(pubId, group)), isDraftId(doc._id))
|
|
317
|
+
group.draft = doc;
|
|
318
|
+
else if (isVersionId(doc._id)) {
|
|
319
|
+
const releaseName = releaseNameOf(doc._id);
|
|
320
|
+
releaseName !== void 0 && group.versions.set(releaseName, doc);
|
|
321
|
+
} else
|
|
322
|
+
group.published = doc;
|
|
323
|
+
}
|
|
324
|
+
const out = [];
|
|
325
|
+
for (const [pubId, group] of groups) {
|
|
326
|
+
let chosen;
|
|
327
|
+
for (const releaseName of releaseStack) {
|
|
328
|
+
const v = group.versions.get(releaseName);
|
|
329
|
+
if (v !== void 0) {
|
|
330
|
+
if (isUnpublishStub(v)) {
|
|
331
|
+
chosen = void 0;
|
|
332
|
+
break;
|
|
333
|
+
}
|
|
334
|
+
chosen = v;
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
chosen === void 0 && options.includeDrafts && group.draft !== void 0 && (chosen = group.draft), chosen === void 0 && group.published !== void 0 && (releaseStack.some((name) => {
|
|
339
|
+
const v = group.versions.get(name);
|
|
340
|
+
return v !== void 0 && isUnpublishStub(v);
|
|
341
|
+
}) || (chosen = group.published)), chosen !== void 0 && out.push(projectToPublishedId(chosen, pubId));
|
|
342
|
+
}
|
|
343
|
+
return [...out, ...systemReleases];
|
|
344
|
+
}
|
|
345
|
+
function isUnpublishStub(doc) {
|
|
346
|
+
return doc._system?.delete === !0;
|
|
347
|
+
}
|
|
348
|
+
function projectToPublishedId(doc, pubId) {
|
|
349
|
+
return doc._id === pubId ? doc : { ...doc, _id: pubId, _originalId: doc._id };
|
|
350
|
+
}
|
|
351
|
+
function resolveDocument(docs, id, perspective) {
|
|
352
|
+
return perspective === "raw" ? docs.find((d) => d._id === id) : applyPerspective(docs, perspective).find((d) => d._id === id);
|
|
353
|
+
}
|
|
354
|
+
function createTestStore(initial) {
|
|
355
|
+
const docs = /* @__PURE__ */ new Map(), promote2 = (doc) => {
|
|
356
|
+
if (typeof doc._id != "string" || doc._id.length === 0)
|
|
357
|
+
throw fakeError(
|
|
358
|
+
`Cannot seed/store a document without a non-empty string \`_id\` (got ${JSON.stringify(doc._id)}). This fake never auto-generates ids \u2014 give every document an explicit _id. Document: ${JSON.stringify(doc)}`
|
|
359
|
+
);
|
|
360
|
+
if (typeof doc._type != "string" || doc._type.length === 0)
|
|
361
|
+
throw fakeError(
|
|
362
|
+
`Document "${doc._id}" is missing a non-empty string \`_type\` (got ${JSON.stringify(doc._type)}). Every Sanity document needs a _type.`
|
|
363
|
+
);
|
|
364
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
365
|
+
return {
|
|
366
|
+
...doc,
|
|
367
|
+
_id: doc._id,
|
|
368
|
+
_type: doc._type,
|
|
369
|
+
_rev: doc._rev ?? cryptoRandomKey(),
|
|
370
|
+
_createdAt: doc._createdAt ?? now,
|
|
371
|
+
_updatedAt: doc._updatedAt ?? now
|
|
372
|
+
};
|
|
373
|
+
}, seed = (documents) => {
|
|
374
|
+
docs.clear();
|
|
375
|
+
for (const d of documents) {
|
|
376
|
+
const promoted = promote2(d);
|
|
377
|
+
docs.set(promoted._id, promoted);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
return initial && seed(initial), {
|
|
381
|
+
seed,
|
|
382
|
+
add: (documents) => {
|
|
383
|
+
for (const d of documents) {
|
|
384
|
+
const promoted = promote2(d);
|
|
385
|
+
docs.set(promoted._id, promoted);
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
reset: () => docs.clear(),
|
|
389
|
+
all: () => [...docs.values()],
|
|
390
|
+
get: (id) => docs.get(id),
|
|
391
|
+
put: (doc) => {
|
|
392
|
+
docs.set(doc._id, doc);
|
|
393
|
+
},
|
|
394
|
+
remove: (id) => {
|
|
395
|
+
const doc = docs.get(id);
|
|
396
|
+
return doc && docs.delete(id), doc;
|
|
397
|
+
},
|
|
398
|
+
snapshot: () => [...docs.values()]
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
function cryptoRandomKey(length = 12) {
|
|
402
|
+
const bytes = new Uint8Array(length);
|
|
403
|
+
return globalThis.crypto.getRandomValues(bytes), [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("").slice(0, length);
|
|
404
|
+
}
|
|
405
|
+
const RELEASE_DOC_PREFIX = "_.releases.", VERSIONS_PREFIX = "versions.", releaseDocId = (releaseId) => `${RELEASE_DOC_PREFIX}${releaseId}`, versionDocId = (releaseId, publishedId) => `${VERSIONS_PREFIX}${releaseId}.${publishedId}`;
|
|
330
406
|
function parseVersionId(versionId) {
|
|
331
|
-
if (!versionId.startsWith(VERSIONS_PREFIX
|
|
407
|
+
if (!versionId.startsWith(VERSIONS_PREFIX))
|
|
332
408
|
throw fakeError(
|
|
333
409
|
`"${versionId}" is not a version document id. Version ids look like "versions.<releaseId>.<publishedId>" (e.g. "versions.summer-drop.product-1").`
|
|
334
410
|
);
|
|
335
|
-
const rest = versionId.slice(VERSIONS_PREFIX
|
|
411
|
+
const rest = versionId.slice(VERSIONS_PREFIX.length), dot = rest.indexOf(".");
|
|
336
412
|
if (dot === -1)
|
|
337
413
|
throw fakeError(
|
|
338
414
|
`"${versionId}" is not a version document id. Version ids look like "versions.<releaseId>.<publishedId>" (e.g. "versions.summer-drop.product-1").`
|
|
@@ -378,7 +454,7 @@ function requireActive(release) {
|
|
|
378
454
|
`Release "${release.name}" is "${release.state}", but only "active" releases accept version writes (create / replace / discard / unpublish). Unschedule or unarchive it back to "active" first, or target a different release.`
|
|
379
455
|
);
|
|
380
456
|
}
|
|
381
|
-
function applyAction(store, action) {
|
|
457
|
+
async function applyAction(store, action, hooks) {
|
|
382
458
|
switch (action.actionType) {
|
|
383
459
|
case "sanity.action.release.create": {
|
|
384
460
|
if (maybeRelease(store, action.releaseId) !== void 0)
|
|
@@ -436,7 +512,7 @@ function applyAction(store, action) {
|
|
|
436
512
|
throw fakeError(
|
|
437
513
|
`Cannot publish release "${action.releaseId}": it is "${release.state}", and only "active" or "scheduled" releases can be published.`
|
|
438
514
|
);
|
|
439
|
-
const prefix = `${VERSIONS_PREFIX
|
|
515
|
+
const prefix = `${VERSIONS_PREFIX}${action.releaseId}.`, sources = store.all().filter((d) => d._id.startsWith(prefix));
|
|
440
516
|
for (const v of sources) {
|
|
441
517
|
const pubId = v._id.slice(prefix.length);
|
|
442
518
|
if (v._system?.delete === !0)
|
|
@@ -476,7 +552,7 @@ function applyAction(store, action) {
|
|
|
476
552
|
throw fakeError(
|
|
477
553
|
`Cannot delete release "${action.releaseId}": it is "${release.state}", and only "archived" or "published" releases can be deleted. Archive it first (sanity.action.release.archive) or publish it.`
|
|
478
554
|
);
|
|
479
|
-
const prefix = `${VERSIONS_PREFIX
|
|
555
|
+
const prefix = `${VERSIONS_PREFIX}${action.releaseId}.`;
|
|
480
556
|
for (const v of store.all())
|
|
481
557
|
v._id.startsWith(prefix) && store.remove(v._id);
|
|
482
558
|
return store.remove(release._id), { transactionId: cryptoRandomKey() };
|
|
@@ -520,9 +596,46 @@ function applyAction(store, action) {
|
|
|
520
596
|
};
|
|
521
597
|
return store.put(promote(doc)), { transactionId: cryptoRandomKey() };
|
|
522
598
|
}
|
|
599
|
+
case "sanity.action.document.publish": {
|
|
600
|
+
requireDraftOf(action);
|
|
601
|
+
const draft = store.get(action.draftId);
|
|
602
|
+
if (draft === void 0)
|
|
603
|
+
throw fakeError(
|
|
604
|
+
`Cannot publish "${action.publishedId}": draft "${action.draftId}" not found. document.publish promotes an existing draft onto the published id \u2014 create the draft first (e.g. client.createOrReplace({ _id: "${action.draftId}", ... })).`
|
|
605
|
+
);
|
|
606
|
+
const published = store.get(action.publishedId);
|
|
607
|
+
requireRevisionMatch(action.draftId, draft._rev, action.ifDraftRevisionId), requireRevisionMatch(action.publishedId, published?._rev, action.ifPublishedRevisionId);
|
|
608
|
+
const promoted = promote({ ...draft, _id: action.publishedId });
|
|
609
|
+
return published !== void 0 && (promoted._createdAt = published._createdAt), await hooks?.gate?.(promoted, published === void 0 ? "create" : "update"), await hooks?.guard?.("publish", published ?? null, promoted), store.put(promoted), store.remove(action.draftId), { transactionId: cryptoRandomKey() };
|
|
610
|
+
}
|
|
611
|
+
case "sanity.action.document.unpublish": {
|
|
612
|
+
requireDraftOf(action);
|
|
613
|
+
const published = store.get(action.publishedId);
|
|
614
|
+
if (published === void 0)
|
|
615
|
+
throw fakeError(
|
|
616
|
+
`Cannot unpublish "${action.publishedId}": no published document with that _id exists. document.unpublish retracts a live published document into "${action.draftId}".`
|
|
617
|
+
);
|
|
618
|
+
if (await hooks?.gate?.(published, "update"), await hooks?.guard?.("unpublish", published, null), store.get(action.draftId) === void 0) {
|
|
619
|
+
const draft = promote({ ...published, _id: action.draftId });
|
|
620
|
+
draft._createdAt = published._createdAt, store.put(draft);
|
|
621
|
+
}
|
|
622
|
+
return store.remove(action.publishedId), { transactionId: cryptoRandomKey() };
|
|
623
|
+
}
|
|
523
624
|
}
|
|
524
625
|
}
|
|
525
|
-
function
|
|
626
|
+
function requireDraftOf(action) {
|
|
627
|
+
if (!(publishedIdOf(action.draftId) === action.publishedId && action.draftId !== action.publishedId))
|
|
628
|
+
throw fakeError(
|
|
629
|
+
`${action.actionType}: draftId "${action.draftId}" is not the draft of publishedId "${action.publishedId}" \u2014 expected draftId "drafts.${action.publishedId}".`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
function requireRevisionMatch(documentId, actualRev, expectedRev) {
|
|
633
|
+
if (!(expectedRev === void 0 || actualRev === expectedRev))
|
|
634
|
+
throw fakeError(
|
|
635
|
+
`Revision precondition failed for "${documentId}": expected _rev "${expectedRev}" but the document is at ${actualRev === void 0 ? "no revision (missing)" : `"${actualRev}"`}.`
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
async function applyActions(store, actions, hooks) {
|
|
526
639
|
const list = Array.isArray(actions) ? actions : [actions], snapshot = /* @__PURE__ */ new Map(), remember = (id) => {
|
|
527
640
|
snapshot.has(id) || snapshot.set(id, store.get(id));
|
|
528
641
|
};
|
|
@@ -537,11 +650,11 @@ function applyActions(store, actions) {
|
|
|
537
650
|
case "sanity.action.release.archive":
|
|
538
651
|
case "sanity.action.release.unarchive":
|
|
539
652
|
case "sanity.action.release.delete":
|
|
540
|
-
remember(`${RELEASE_DOC_PREFIX
|
|
653
|
+
remember(`${RELEASE_DOC_PREFIX}${a.releaseId}`);
|
|
541
654
|
break;
|
|
542
655
|
case "sanity.action.release.publish": {
|
|
543
|
-
remember(`${RELEASE_DOC_PREFIX
|
|
544
|
-
const prefix = `${VERSIONS_PREFIX
|
|
656
|
+
remember(`${RELEASE_DOC_PREFIX}${a.releaseId}`);
|
|
657
|
+
const prefix = `${VERSIONS_PREFIX}${a.releaseId}.`;
|
|
545
658
|
for (const d of store.all())
|
|
546
659
|
d._id.startsWith(prefix) && (remember(d._id), remember(d._id.slice(prefix.length)));
|
|
547
660
|
break;
|
|
@@ -558,8 +671,12 @@ function applyActions(store, actions) {
|
|
|
558
671
|
case "sanity.action.document.version.unpublish":
|
|
559
672
|
remember(a.versionId);
|
|
560
673
|
break;
|
|
674
|
+
case "sanity.action.document.publish":
|
|
675
|
+
case "sanity.action.document.unpublish":
|
|
676
|
+
remember(a.draftId), remember(a.publishedId);
|
|
677
|
+
break;
|
|
561
678
|
}
|
|
562
|
-
last = applyAction(store, a);
|
|
679
|
+
last = await applyAction(store, a, hooks);
|
|
563
680
|
}
|
|
564
681
|
return last;
|
|
565
682
|
} catch (err) {
|
|
@@ -568,82 +685,6 @@ function applyActions(store, actions) {
|
|
|
568
685
|
throw err;
|
|
569
686
|
}
|
|
570
687
|
}
|
|
571
|
-
const DRAFTS_PREFIX = "drafts.", VERSIONS_PREFIX = "versions.", RELEASE_DOC_PREFIX = "_.releases.";
|
|
572
|
-
function publishedIdOf(id) {
|
|
573
|
-
if (id.startsWith(DRAFTS_PREFIX)) return id.slice(DRAFTS_PREFIX.length);
|
|
574
|
-
if (id.startsWith(VERSIONS_PREFIX)) {
|
|
575
|
-
const rest = id.slice(VERSIONS_PREFIX.length), dot = rest.indexOf(".");
|
|
576
|
-
return dot === -1 ? rest : rest.slice(dot + 1);
|
|
577
|
-
}
|
|
578
|
-
return id;
|
|
579
|
-
}
|
|
580
|
-
function releaseNameOf(id) {
|
|
581
|
-
if (!id.startsWith(VERSIONS_PREFIX)) return;
|
|
582
|
-
const rest = id.slice(VERSIONS_PREFIX.length), dot = rest.indexOf(".");
|
|
583
|
-
if (dot !== -1)
|
|
584
|
-
return rest.slice(0, dot);
|
|
585
|
-
}
|
|
586
|
-
const isDraftId = (id) => id.startsWith(DRAFTS_PREFIX), isVersionId = (id) => id.startsWith(VERSIONS_PREFIX), isSystemId = (id) => id.startsWith("_."), isReleaseDocId = (id) => id.startsWith(RELEASE_DOC_PREFIX);
|
|
587
|
-
function applyPerspective(docs, perspective) {
|
|
588
|
-
if (perspective === "raw") return [...docs];
|
|
589
|
-
if (perspective === "published")
|
|
590
|
-
return docs.filter((d) => !isDraftId(d._id) && !isVersionId(d._id) && !isSystemId(d._id));
|
|
591
|
-
if (perspective === "drafts")
|
|
592
|
-
return mergeStack(docs, [], { includeDrafts: !0, includeReleaseDocs: !1 });
|
|
593
|
-
const stack = [];
|
|
594
|
-
let includeDrafts = !1;
|
|
595
|
-
for (const entry of perspective)
|
|
596
|
-
entry === "drafts" ? includeDrafts = !0 : stack.push(entry);
|
|
597
|
-
return mergeStack(docs, stack, { includeDrafts, includeReleaseDocs: !0 });
|
|
598
|
-
}
|
|
599
|
-
function mergeStack(docs, releaseStack, options) {
|
|
600
|
-
const groups = /* @__PURE__ */ new Map(), systemReleases = [];
|
|
601
|
-
for (const doc of docs) {
|
|
602
|
-
if (isReleaseDocId(doc._id)) {
|
|
603
|
-
options.includeReleaseDocs && systemReleases.push(doc);
|
|
604
|
-
continue;
|
|
605
|
-
}
|
|
606
|
-
if (isSystemId(doc._id)) continue;
|
|
607
|
-
const pubId = publishedIdOf(doc._id);
|
|
608
|
-
let group = groups.get(pubId);
|
|
609
|
-
if (group === void 0 && (group = { versions: /* @__PURE__ */ new Map() }, groups.set(pubId, group)), isDraftId(doc._id))
|
|
610
|
-
group.draft = doc;
|
|
611
|
-
else if (isVersionId(doc._id)) {
|
|
612
|
-
const releaseName = releaseNameOf(doc._id);
|
|
613
|
-
releaseName !== void 0 && group.versions.set(releaseName, doc);
|
|
614
|
-
} else
|
|
615
|
-
group.published = doc;
|
|
616
|
-
}
|
|
617
|
-
const out = [];
|
|
618
|
-
for (const [pubId, group] of groups) {
|
|
619
|
-
let chosen;
|
|
620
|
-
for (const releaseName of releaseStack) {
|
|
621
|
-
const v = group.versions.get(releaseName);
|
|
622
|
-
if (v !== void 0) {
|
|
623
|
-
if (isUnpublishStub(v)) {
|
|
624
|
-
chosen = void 0;
|
|
625
|
-
break;
|
|
626
|
-
}
|
|
627
|
-
chosen = v;
|
|
628
|
-
break;
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
chosen === void 0 && options.includeDrafts && group.draft !== void 0 && (chosen = group.draft), chosen === void 0 && group.published !== void 0 && (releaseStack.some((name) => {
|
|
632
|
-
const v = group.versions.get(name);
|
|
633
|
-
return v !== void 0 && isUnpublishStub(v);
|
|
634
|
-
}) || (chosen = group.published)), chosen !== void 0 && out.push(projectToPublishedId(chosen, pubId));
|
|
635
|
-
}
|
|
636
|
-
return [...out, ...systemReleases];
|
|
637
|
-
}
|
|
638
|
-
function isUnpublishStub(doc) {
|
|
639
|
-
return doc._system?.delete === !0;
|
|
640
|
-
}
|
|
641
|
-
function projectToPublishedId(doc, pubId) {
|
|
642
|
-
return doc._id === pubId ? doc : { ...doc, _id: pubId, _originalId: doc._id };
|
|
643
|
-
}
|
|
644
|
-
function resolveDocument(docs, id, perspective) {
|
|
645
|
-
return perspective === "raw" ? docs.find((d) => d._id === id) : applyPerspective(docs, perspective).find((d) => d._id === id);
|
|
646
|
-
}
|
|
647
688
|
function createTransaction(executor) {
|
|
648
689
|
const mutations = [], handle = {
|
|
649
690
|
create: (doc) => (mutations.push({ kind: "create", doc }), handle),
|
|
@@ -875,6 +916,15 @@ const RECORDED_METHODS = /* @__PURE__ */ new Set([
|
|
|
875
916
|
"unpublishVersion",
|
|
876
917
|
"request"
|
|
877
918
|
]), DEFAULT_PROJECT_ID = "test", DEFAULT_DATASET = "test";
|
|
919
|
+
function serializeWrite(backend, run) {
|
|
920
|
+
const result = backend.writeChain.then(run);
|
|
921
|
+
return backend.writeChain = result.then(
|
|
922
|
+
() => {
|
|
923
|
+
},
|
|
924
|
+
() => {
|
|
925
|
+
}
|
|
926
|
+
), result;
|
|
927
|
+
}
|
|
878
928
|
function requireIdentity(backend, token, site) {
|
|
879
929
|
if (backend.identities.has(token)) return;
|
|
880
930
|
const known = [...backend.identities.keys()];
|
|
@@ -899,7 +949,8 @@ function createTestClient(options = {}) {
|
|
|
899
949
|
stubs: /* @__PURE__ */ new Map(),
|
|
900
950
|
calls: [],
|
|
901
951
|
concurrentEdits: /* @__PURE__ */ new Map(),
|
|
902
|
-
identities: new Map(Object.entries(options.identities ?? {}))
|
|
952
|
+
identities: new Map(Object.entries(options.identities ?? {})),
|
|
953
|
+
writeChain: Promise.resolve()
|
|
903
954
|
}, registry = backend.registry;
|
|
904
955
|
rejectAmbiguousIdentity("createTestClient()", options), options.token !== void 0 && requireIdentity(backend, options.token, "createTestClient()");
|
|
905
956
|
const ensureStore = (projectId, dataset) => {
|
|
@@ -1128,7 +1179,7 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1128
1179
|
txnOptions?.returnDocuments ?? !1,
|
|
1129
1180
|
txnOptions?.returnFirst ?? !1
|
|
1130
1181
|
);
|
|
1131
|
-
}, accessVisibleDocs = async () => {
|
|
1182
|
+
}, runAction = (actions) => serializeWrite(backend, async () => applyActions(store, actions, { gate, guard: guardGate })), accessVisibleDocs = async () => {
|
|
1132
1183
|
const all = store.all();
|
|
1133
1184
|
if (activeAccess() === void 0) return all;
|
|
1134
1185
|
const out = [];
|
|
@@ -1172,7 +1223,7 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1172
1223
|
const view = await visibleDocs(effective);
|
|
1173
1224
|
return ids.map((id) => resolveDocument(view, id, effective) ?? null);
|
|
1174
1225
|
},
|
|
1175
|
-
create:
|
|
1226
|
+
create: (doc, opts) => serializeWrite(backend, async () => {
|
|
1176
1227
|
if (checkRevision(doc._id, opts?.ifRevisionId), store.get(doc._id) !== void 0)
|
|
1177
1228
|
throw fakeError(
|
|
1178
1229
|
`create() failed: a document with _id "${doc._id}" already exists in dataset "${projectId}:${dataset}". Use createOrReplace() to overwrite it, or createIfNotExists() to leave the existing one untouched.`
|
|
@@ -1186,8 +1237,8 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1186
1237
|
transactionId,
|
|
1187
1238
|
opts
|
|
1188
1239
|
);
|
|
1189
|
-
},
|
|
1190
|
-
createOrReplace:
|
|
1240
|
+
}),
|
|
1241
|
+
createOrReplace: (doc, opts) => serializeWrite(backend, async () => {
|
|
1191
1242
|
checkRevision(doc._id, opts?.ifRevisionId);
|
|
1192
1243
|
const promoted = promote2(doc), existing = store.get(doc._id);
|
|
1193
1244
|
await gate(existing ?? promoted, existing !== void 0 ? "update" : "create"), await guardGate(existing !== void 0 ? "update" : "create", existing ?? null, promoted);
|
|
@@ -1200,8 +1251,8 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1200
1251
|
transactionId,
|
|
1201
1252
|
opts
|
|
1202
1253
|
);
|
|
1203
|
-
},
|
|
1204
|
-
createIfNotExists:
|
|
1254
|
+
}),
|
|
1255
|
+
createIfNotExists: (doc, opts) => serializeWrite(backend, async () => {
|
|
1205
1256
|
checkRevision(doc._id, opts?.ifRevisionId);
|
|
1206
1257
|
const existing = store.get(doc._id), transactionId = opts?.transactionId ?? cryptoRandomKey();
|
|
1207
1258
|
if (existing !== void 0)
|
|
@@ -1218,8 +1269,8 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1218
1269
|
transactionId,
|
|
1219
1270
|
opts
|
|
1220
1271
|
);
|
|
1221
|
-
},
|
|
1222
|
-
delete:
|
|
1272
|
+
}),
|
|
1273
|
+
delete: (id, opts) => serializeWrite(backend, async () => {
|
|
1223
1274
|
checkRevision(id, opts?.ifRevisionId);
|
|
1224
1275
|
const existing = store.get(id);
|
|
1225
1276
|
existing !== void 0 && await gate(existing, "update"), existing !== void 0 && await guardGate("delete", existing, null);
|
|
@@ -1232,23 +1283,35 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1232
1283
|
opts.returnDocuments ?? !0,
|
|
1233
1284
|
opts.returnFirst ?? !0
|
|
1234
1285
|
);
|
|
1235
|
-
},
|
|
1286
|
+
}),
|
|
1236
1287
|
patch: (documentId) => createPatch(documentId, {
|
|
1237
|
-
apply:
|
|
1288
|
+
apply: (docId, ops, ifRev, options) => serializeWrite(backend, async () => {
|
|
1238
1289
|
const doc = await applyPatch(docId, ops, ifRev);
|
|
1239
1290
|
return record(
|
|
1240
1291
|
cryptoRandomKey(),
|
|
1241
|
-
[
|
|
1292
|
+
[
|
|
1293
|
+
{
|
|
1294
|
+
kind: "patch",
|
|
1295
|
+
documentId: docId,
|
|
1296
|
+
ops,
|
|
1297
|
+
...ifRev !== void 0 ? { ifRev } : {}
|
|
1298
|
+
}
|
|
1299
|
+
],
|
|
1242
1300
|
options?.tag
|
|
1243
1301
|
), doc;
|
|
1244
|
-
}
|
|
1302
|
+
})
|
|
1303
|
+
}),
|
|
1304
|
+
transaction: () => createTransaction({
|
|
1305
|
+
apply: (mutations, txnOptions) => serializeWrite(backend, () => applyTransaction(mutations, txnOptions))
|
|
1245
1306
|
}),
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1307
|
+
mutate: (operations, options) => serializeWrite(backend, () => applyTransaction(toTxnMutations(operations), options)),
|
|
1308
|
+
// Synchronous writes still take the lock: an action landing while a
|
|
1309
|
+
// guarded patch is parked in its gate would otherwise be clobbered
|
|
1310
|
+
// when that patch resumes over its pre-action snapshot.
|
|
1311
|
+
action: (action) => runAction(action),
|
|
1249
1312
|
releases: {
|
|
1250
1313
|
create: async ({ releaseId, metadata }) => {
|
|
1251
|
-
const result =
|
|
1314
|
+
const result = await runAction({
|
|
1252
1315
|
actionType: "sanity.action.release.create",
|
|
1253
1316
|
releaseId,
|
|
1254
1317
|
...metadata !== void 0 ? { metadata } : {}
|
|
@@ -1259,30 +1322,30 @@ function makeHandle(backend, projectId, dataset, accessControl, perspective, mut
|
|
|
1259
1322
|
metadata: doc?.metadata ?? { releaseType: "undecided" }
|
|
1260
1323
|
};
|
|
1261
1324
|
},
|
|
1262
|
-
edit:
|
|
1325
|
+
edit: ({ releaseId, patch }) => runAction({ actionType: "sanity.action.release.edit", releaseId, patch }),
|
|
1263
1326
|
get: async ({ releaseId }) => store.get(`_.releases.${releaseId}`),
|
|
1264
1327
|
fetchDocuments: async ({ releaseId }) => {
|
|
1265
1328
|
const prefix = `versions.${releaseId}.`;
|
|
1266
1329
|
return store.all().filter((d) => d._id.startsWith(prefix));
|
|
1267
1330
|
},
|
|
1268
|
-
schedule:
|
|
1331
|
+
schedule: ({ releaseId, publishAt }) => runAction({
|
|
1269
1332
|
actionType: "sanity.action.release.schedule",
|
|
1270
1333
|
releaseId,
|
|
1271
1334
|
publishAt
|
|
1272
1335
|
}),
|
|
1273
|
-
unschedule:
|
|
1274
|
-
publish:
|
|
1275
|
-
archive:
|
|
1276
|
-
unarchive:
|
|
1277
|
-
delete:
|
|
1336
|
+
unschedule: ({ releaseId }) => runAction({ actionType: "sanity.action.release.unschedule", releaseId }),
|
|
1337
|
+
publish: ({ releaseId }) => runAction({ actionType: "sanity.action.release.publish", releaseId }),
|
|
1338
|
+
archive: ({ releaseId }) => runAction({ actionType: "sanity.action.release.archive", releaseId }),
|
|
1339
|
+
unarchive: ({ releaseId }) => runAction({ actionType: "sanity.action.release.unarchive", releaseId }),
|
|
1340
|
+
delete: ({ releaseId }) => runAction({ actionType: "sanity.action.release.delete", releaseId })
|
|
1278
1341
|
},
|
|
1279
|
-
createVersion:
|
|
1342
|
+
createVersion: ({ releaseId, publishedId, document }) => runAction({
|
|
1280
1343
|
actionType: "sanity.action.document.version.create",
|
|
1281
1344
|
releaseId,
|
|
1282
1345
|
publishedId,
|
|
1283
1346
|
document
|
|
1284
1347
|
}),
|
|
1285
|
-
unpublishVersion:
|
|
1348
|
+
unpublishVersion: ({ releaseId, publishedId }) => runAction({
|
|
1286
1349
|
actionType: "sanity.action.document.version.unpublish",
|
|
1287
1350
|
versionId: `versions.${releaseId}.${publishedId}`,
|
|
1288
1351
|
publishedId
|