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