@sanity/client 6.18.3 → 6.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/client",
3
- "version": "6.18.3",
3
+ "version": "6.19.0",
4
4
  "description": "Client for retrieving, creating and patching data from Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -10,9 +10,11 @@ import {ObservableTransaction, Transaction} from './data/transaction'
10
10
  import {DatasetsClient, ObservableDatasetsClient} from './datasets/DatasetsClient'
11
11
  import {ObservableProjectsClient, ProjectsClient} from './projects/ProjectsClient'
12
12
  import type {
13
+ Action,
13
14
  AllDocumentIdsMutationOptions,
14
15
  AllDocumentsMutationOptions,
15
16
  Any,
17
+ BaseActionOptions,
16
18
  BaseMutationOptions,
17
19
  ClientConfig,
18
20
  FilteredResponseQueryOptions,
@@ -21,6 +23,7 @@ import type {
21
23
  HttpRequest,
22
24
  IdentifiedSanityDocumentStub,
23
25
  InitializedClientConfig,
26
+ MultipleActionResult,
24
27
  MultipleMutationResult,
25
28
  Mutation,
26
29
  MutationSelection,
@@ -34,6 +37,7 @@ import type {
34
37
  RawRequestOptions,
35
38
  SanityDocument,
36
39
  SanityDocumentStub,
40
+ SingleActionResult,
37
41
  SingleMutationResult,
38
42
  UnfilteredResponseQueryOptions,
39
43
  UnfilteredResponseWithoutQuery,
@@ -665,6 +669,19 @@ export class ObservableSanityClient {
665
669
  return new ObservableTransaction(operations, this)
666
670
  }
667
671
 
672
+ /**
673
+ * Perform action operations against the configured dataset
674
+ *
675
+ * @param operations - Action operation(s) to execute
676
+ * @param options - Action options
677
+ */
678
+ action(
679
+ operations: Action | Action[],
680
+ options?: BaseActionOptions,
681
+ ): Observable<SingleActionResult | MultipleActionResult> {
682
+ return dataMethods._action(this, this.#httpRequest, operations, options)
683
+ }
684
+
668
685
  /**
669
686
  * Perform an HTTP request against the Sanity API
670
687
  *
@@ -1322,6 +1339,20 @@ export class SanityClient {
1322
1339
  return new Transaction(operations, this)
1323
1340
  }
1324
1341
 
1342
+ /**
1343
+ * Perform action operations against the configured dataset
1344
+ * Returns a promise that resolves to the transaction result
1345
+ *
1346
+ * @param operations - Action operation(s) to execute
1347
+ * @param options - Action options
1348
+ */
1349
+ action(
1350
+ operations: Action | Action[],
1351
+ options?: BaseActionOptions,
1352
+ ): Promise<SingleActionResult | MultipleActionResult> {
1353
+ return lastValueFrom(dataMethods._action(this, this.#httpRequest, operations, options))
1354
+ }
1355
+
1325
1356
  /**
1326
1357
  * Perform a request against the Sanity API
1327
1358
  * NOTE: Only use this for Sanity API endpoints, not for your own APIs!
@@ -6,9 +6,11 @@ import {requestOptions} from '../http/requestOptions'
6
6
  import type {ObservableSanityClient, SanityClient} from '../SanityClient'
7
7
  import {stegaClean} from '../stega/stegaClean'
8
8
  import type {
9
+ Action,
9
10
  AllDocumentIdsMutationOptions,
10
11
  AllDocumentsMutationOptions,
11
12
  Any,
13
+ BaseActionOptions,
12
14
  BaseMutationOptions,
13
15
  FirstDocumentIdMutationOptions,
14
16
  FirstDocumentMutationOptions,
@@ -16,6 +18,7 @@ import type {
16
18
  HttpRequestEvent,
17
19
  IdentifiedSanityDocumentStub,
18
20
  InitializedStegaConfig,
21
+ MultipleActionResult,
19
22
  MultipleMutationResult,
20
23
  Mutation,
21
24
  MutationSelection,
@@ -24,6 +27,7 @@ import type {
24
27
  RequestObservableOptions,
25
28
  RequestOptions,
26
29
  SanityDocument,
30
+ SingleActionResult,
27
31
  SingleMutationResult,
28
32
  } from '../types'
29
33
  import {getSelection} from '../util/getSelection'
@@ -238,6 +242,30 @@ export function _mutate<R extends Record<string, Any>>(
238
242
  return _dataRequest(client, httpRequest, 'mutate', {mutations: muts, transactionId}, options)
239
243
  }
240
244
 
245
+ /**
246
+ * @internal
247
+ */
248
+ export function _action(
249
+ client: SanityClient | ObservableSanityClient,
250
+ httpRequest: HttpRequest,
251
+ actions: Action | Action[],
252
+ options?: BaseActionOptions,
253
+ ): Observable<SingleActionResult | MultipleActionResult> {
254
+ const acts = Array.isArray(actions) ? actions : [actions]
255
+ const transactionId = (options && options.transactionId) || undefined
256
+ const skipCrossDatasetReferenceValidation =
257
+ (options && options.skipCrossDatasetReferenceValidation) || undefined
258
+ const dryRun = (options && options.dryRun) || undefined
259
+
260
+ return _dataRequest(
261
+ client,
262
+ httpRequest,
263
+ 'actions',
264
+ {actions: acts, transactionId, skipCrossDatasetReferenceValidation, dryRun},
265
+ options,
266
+ )
267
+ }
268
+
241
269
  /**
242
270
  * @internal
243
271
  */
@@ -249,12 +277,13 @@ export function _dataRequest(
249
277
  options: Any = {},
250
278
  ): Any {
251
279
  const isMutation = endpoint === 'mutate'
280
+ const isAction = endpoint === 'actions'
252
281
  const isQuery = endpoint === 'query'
253
282
 
254
283
  // Check if the query string is within a configured threshold,
255
284
  // in which case we can use GET. Otherwise, use POST.
256
- const strQuery = isMutation ? '' : encodeQueryString(body)
257
- const useGet = !isMutation && strQuery.length < getQuerySizeLimit
285
+ const strQuery = isMutation || isAction ? '' : encodeQueryString(body)
286
+ const useGet = !isMutation && !isAction && strQuery.length < getQuerySizeLimit
258
287
  const stringQuery = useGet ? strQuery : ''
259
288
  const returnFirst = options.returnFirst
260
289
  const {timeout, token, tag, headers, returnQuery, lastLiveEventId} = options
@@ -1,4 +1,4 @@
1
- import type {Any, ErrorProps, MutationError} from '../types'
1
+ import type {ActionError, Any, ErrorProps, MutationError} from '../types'
2
2
 
3
3
  const MAX_ITEMS_IN_ERROR_MESSAGE = 5
4
4
 
@@ -47,7 +47,7 @@ function extractErrorProps(res: Any): ErrorProps {
47
47
  }
48
48
 
49
49
  // Mutation errors (specifically)
50
- if (isMutationError(body)) {
50
+ if (isMutationError(body) || isActionError(body)) {
51
51
  const allItems = body.error.items || []
52
52
  const items = allItems
53
53
  .slice(0, MAX_ITEMS_IN_ERROR_MESSAGE)
@@ -83,6 +83,15 @@ function isMutationError(body: Any): body is MutationError {
83
83
  )
84
84
  }
85
85
 
86
+ function isActionError(body: Any): body is ActionError {
87
+ return (
88
+ isPlainObject(body) &&
89
+ isPlainObject(body.error) &&
90
+ body.error.type === 'actionError' &&
91
+ typeof body.error.description === 'string'
92
+ )
93
+ }
94
+
86
95
  function isPlainObject(obj: Any): obj is Record<string, unknown> {
87
96
  return typeof obj === 'object' && obj !== null && !Array.isArray(obj)
88
97
  }
package/src/types.ts CHANGED
@@ -511,6 +511,193 @@ export type Mutation<R extends Record<string, Any> = Record<string, Any>> =
511
511
  | {delete: MutationSelection}
512
512
  | {patch: PatchMutationOperation}
513
513
 
514
+ /** @public */
515
+ export type Action =
516
+ | CreateAction
517
+ | ReplaceDraftAction
518
+ | EditAction
519
+ | DeleteAction
520
+ | DiscardAction
521
+ | PublishAction
522
+ | UnpublishAction
523
+
524
+ /**
525
+ * Creates a new draft document. The published version of the document must not already exist.
526
+ * If the draft version of the document already exists the action will fail by default, but
527
+ * this can be adjusted to instead leave the existing document in place.
528
+ *
529
+ * @public
530
+ */
531
+ export type CreateAction = {
532
+ actionType: 'sanity.action.document.create'
533
+
534
+ /**
535
+ * ID of the published document to create a draft for.
536
+ */
537
+ publishedId: string
538
+
539
+ /**
540
+ * Document to create. Requires a `_type` property.
541
+ */
542
+ attributes: IdentifiedSanityDocumentStub
543
+
544
+ /**
545
+ * ifExists controls what to do if the draft already exists
546
+ */
547
+ ifExists: 'fail' | 'ignore'
548
+ }
549
+
550
+ /**
551
+ * Replaces an existing draft document.
552
+ * At least one of the draft or published versions of the document must exist.
553
+ *
554
+ * @public
555
+ */
556
+ export type ReplaceDraftAction = {
557
+ actionType: 'sanity.action.document.replaceDraft'
558
+
559
+ /**
560
+ * Draft document ID to replace, if it exists.
561
+ */
562
+ draftId: string
563
+
564
+ /**
565
+ * Published document ID to create draft from, if draft does not exist
566
+ */
567
+ publishedId: string
568
+
569
+ /**
570
+ * Document to create if it does not already exist. Requires `_id` and `_type` properties.
571
+ */
572
+ attributes: IdentifiedSanityDocumentStub
573
+ }
574
+
575
+ /**
576
+ * Modifies an existing draft document.
577
+ * It applies the given patch to the document referenced by draftId.
578
+ * If there is no such document then one is created using the current state of the published version and then that is updated accordingly.
579
+ *
580
+ * @public
581
+ */
582
+ export type EditAction = {
583
+ actionType: 'sanity.action.document.edit'
584
+
585
+ /**
586
+ * Draft document ID to edit
587
+ */
588
+ draftId: string
589
+
590
+ /**
591
+ * Published document ID to create draft from, if draft does not exist
592
+ */
593
+ publishedId: string
594
+
595
+ /**
596
+ * Patch operations to apply
597
+ */
598
+ patch: PatchOperations
599
+ }
600
+
601
+ /**
602
+ * Deletes the published version of a document and optionally some (likely all known) draft versions.
603
+ * If any draft version exists that is not specified for deletion this is an error.
604
+ * If the purge flag is set then the document history is also deleted.
605
+ *
606
+ * @public
607
+ */
608
+ export type DeleteAction = {
609
+ actionType: 'sanity.action.document.delete'
610
+
611
+ /**
612
+ * Published document ID to delete
613
+ */
614
+ publishedId: string
615
+
616
+ /**
617
+ * Draft document ID to delete
618
+ */
619
+ includeDrafts: string[]
620
+
621
+ /**
622
+ * Delete document history
623
+ */
624
+ purge: boolean
625
+ }
626
+
627
+ /**
628
+ * Delete the draft version of a document.
629
+ * It is an error if it does not exist. If the purge flag is set, the document history is also deleted.
630
+ *
631
+ * @public
632
+ */
633
+ export type DiscardAction = {
634
+ actionType: 'sanity.action.document.discard'
635
+
636
+ /**
637
+ * Draft document ID to delete
638
+ */
639
+ draftId: string
640
+
641
+ /**
642
+ * Delete document history
643
+ */
644
+ purge: boolean
645
+ }
646
+
647
+ /**
648
+ * Publishes a draft document.
649
+ * If a published version of the document already exists this is replaced by the current draft document.
650
+ * In either case the draft document is deleted.
651
+ * The optional revision id parameters can be used for optimistic locking to ensure
652
+ * that the draft and/or published versions of the document have not been changed by another client.
653
+ *
654
+ * @public
655
+ */
656
+ export type PublishAction = {
657
+ actionType: 'sanity.action.document.publish'
658
+
659
+ /**
660
+ * Draft document ID to publish
661
+ */
662
+ draftId: string
663
+
664
+ /**
665
+ * Draft revision ID to match
666
+ */
667
+ ifDraftRevisionId: string
668
+
669
+ /**
670
+ * Published document ID to replace
671
+ */
672
+ publishedId: string
673
+
674
+ /**
675
+ * Published revision ID to match
676
+ */
677
+ ifPublishedRevisionId: string
678
+ }
679
+
680
+ /**
681
+ * Retract a published document.
682
+ * If there is no draft version then this is created from the published version.
683
+ * In either case the published version is deleted.
684
+ *
685
+ * @public
686
+ */
687
+ export type UnpublishAction = {
688
+ actionType: 'sanity.action.document.unpublish'
689
+
690
+ /**
691
+ * Draft document ID to replace the published document with
692
+ */
693
+ draftId: string
694
+
695
+ /**
696
+ * Published document ID to delete
697
+ */
698
+ publishedId: string
699
+ }
700
+
514
701
  /**
515
702
  * A mutation was performed. Note that when updating multiple documents in a transaction,
516
703
  * each document affected will get a separate mutation event.
@@ -884,6 +1071,23 @@ export type TransactionMutationOptions =
884
1071
  | TransactionAllDocumentsMutationOptions
885
1072
  | TransactionAllDocumentIdsMutationOptions
886
1073
 
1074
+ /** @internal */
1075
+ export type BaseActionOptions = RequestOptions & {
1076
+ transactionId?: string
1077
+ skipCrossDatasetReferenceValidation?: boolean
1078
+ dryRun?: boolean
1079
+ }
1080
+
1081
+ /** @internal */
1082
+ export interface SingleActionResult {
1083
+ transactionId: string
1084
+ }
1085
+
1086
+ /** @internal */
1087
+ export interface MultipleActionResult {
1088
+ transactionId: string
1089
+ }
1090
+
887
1091
  /** @internal */
888
1092
  export interface RawRequestOptions {
889
1093
  url?: string
@@ -927,6 +1131,25 @@ export interface MutationErrorItem {
927
1131
  }
928
1132
  }
929
1133
 
1134
+ /** @internal */
1135
+ export interface ActionError {
1136
+ error: {
1137
+ type: 'actionError'
1138
+ description: string
1139
+ items?: ActionErrorItem[]
1140
+ }
1141
+ }
1142
+
1143
+ /** @internal */
1144
+ export interface ActionErrorItem {
1145
+ error: {
1146
+ type: string
1147
+ description: string
1148
+ value?: unknown
1149
+ }
1150
+ index: number
1151
+ }
1152
+
930
1153
  /**
931
1154
  * DocumentValueSource is a path to a value within a document
932
1155
  * @public
@@ -1839,7 +1839,7 @@
1839
1839
  };
1840
1840
  if (body.error && body.message)
1841
1841
  return props.message = `${body.error} - ${body.message}`, props;
1842
- if (isMutationError(body)) {
1842
+ if (isMutationError(body) || isActionError(body)) {
1843
1843
  const allItems = body.error.items || [], items = allItems.slice(0, 5).map((item) => {
1844
1844
  var _a;
1845
1845
  return (_a = item.error) == null ? void 0 : _a.description;
@@ -1855,6 +1855,9 @@
1855
1855
  function isMutationError(body) {
1856
1856
  return isPlainObject(body) && isPlainObject(body.error) && body.error.type === "mutationError" && typeof body.error.description == "string";
1857
1857
  }
1858
+ function isActionError(body) {
1859
+ return isPlainObject(body) && isPlainObject(body.error) && body.error.type === "actionError" && typeof body.error.description == "string";
1860
+ }
1858
1861
  function isPlainObject(obj) {
1859
1862
  return typeof obj == "object" && obj !== null && !Array.isArray(obj);
1860
1863
  }
@@ -2486,8 +2489,18 @@ ${selectionOpts}`);
2486
2489
  const muts = Array.isArray(mut) ? mut : [mut], transactionId = options && options.transactionId || void 0;
2487
2490
  return _dataRequest(client, httpRequest, "mutate", { mutations: muts, transactionId }, options);
2488
2491
  }
2492
+ function _action(client, httpRequest, actions, options) {
2493
+ const acts = Array.isArray(actions) ? actions : [actions], transactionId = options && options.transactionId || void 0, skipCrossDatasetReferenceValidation = options && options.skipCrossDatasetReferenceValidation || void 0, dryRun = options && options.dryRun || void 0;
2494
+ return _dataRequest(
2495
+ client,
2496
+ httpRequest,
2497
+ "actions",
2498
+ { actions: acts, transactionId, skipCrossDatasetReferenceValidation, dryRun },
2499
+ options
2500
+ );
2501
+ }
2489
2502
  function _dataRequest(client, httpRequest, endpoint, body, options = {}) {
2490
- const isMutation = endpoint === "mutate", isQuery = endpoint === "query", strQuery = isMutation ? "" : encodeQueryString(body), useGet = !isMutation && strQuery.length < getQuerySizeLimit, stringQuery = useGet ? strQuery : "", returnFirst = options.returnFirst, { timeout, token, tag, headers, returnQuery, lastLiveEventId } = options, uri = _getDataUrl(client, endpoint, stringQuery), reqOptions = {
2503
+ const isMutation = endpoint === "mutate", isAction = endpoint === "actions", isQuery = endpoint === "query", strQuery = isMutation || isAction ? "" : encodeQueryString(body), useGet = !isMutation && !isAction && strQuery.length < getQuerySizeLimit, stringQuery = useGet ? strQuery : "", returnFirst = options.returnFirst, { timeout, token, tag, headers, returnQuery, lastLiveEventId } = options, uri = _getDataUrl(client, endpoint, stringQuery), reqOptions = {
2491
2504
  method: useGet ? "GET" : "POST",
2492
2505
  uri,
2493
2506
  json: !0,
@@ -3099,6 +3112,15 @@ ${selectionOpts}`);
3099
3112
  transaction(operations) {
3100
3113
  return new ObservableTransaction(operations, this);
3101
3114
  }
3115
+ /**
3116
+ * Perform action operations against the configured dataset
3117
+ *
3118
+ * @param operations - Action operation(s) to execute
3119
+ * @param options - Action options
3120
+ */
3121
+ action(operations, options) {
3122
+ return _action(this, __privateGet(this, _httpRequest), operations, options);
3123
+ }
3102
3124
  /**
3103
3125
  * Perform an HTTP request against the Sanity API
3104
3126
  *
@@ -3236,6 +3258,16 @@ ${selectionOpts}`);
3236
3258
  transaction(operations) {
3237
3259
  return new Transaction(operations, this);
3238
3260
  }
3261
+ /**
3262
+ * Perform action operations against the configured dataset
3263
+ * Returns a promise that resolves to the transaction result
3264
+ *
3265
+ * @param operations - Action operation(s) to execute
3266
+ * @param options - Action options
3267
+ */
3268
+ action(operations, options) {
3269
+ return lastValueFrom(_action(this, __privateGet(this, _httpRequest2), operations, options));
3270
+ }
3239
3271
  /**
3240
3272
  * Perform a request against the Sanity API
3241
3273
  * NOTE: Only use this for Sanity API endpoints, not for your own APIs!