@sanity/sdk 2.0.2 → 2.1.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.d.ts CHANGED
@@ -11,7 +11,10 @@ import {CurrentUser} from '@sanity/types'
11
11
  import {DatasetsResponse} from '@sanity/client'
12
12
  import {DocumentPermissionsResult as DocumentPermissionsResult_2} from './permissions'
13
13
  import {FetcherStoreState as FetcherStoreState_2} from '../_exports'
14
- import {IndexTuple} from '@sanity/types'
14
+ import {getIndexForKey} from '@sanity/json-match'
15
+ import {getPathDepth} from '@sanity/json-match'
16
+ import {joinPaths} from '@sanity/json-match'
17
+ import {jsonMatch} from '@sanity/json-match'
15
18
  import {ListenEvent} from '@sanity/client'
16
19
  import {MediaResource} from '@sanity/message-protocol'
17
20
  import {Message} from '@sanity/comlink'
@@ -21,7 +24,6 @@ import {NodeInput} from '@sanity/comlink'
21
24
  import {Observable} from 'rxjs'
22
25
  import {PatchMutation} from '@sanity/mutate/_unstable_store'
23
26
  import {PatchOperations} from '@sanity/types'
24
- import {PathSegment} from '@sanity/types'
25
27
  import {PreviewStoreState as PreviewStoreState_2} from './previewStore'
26
28
  import {ResponseQueryOptions} from '@sanity/client'
27
29
  import {Role} from '@sanity/types'
@@ -34,10 +36,12 @@ import {SanityProject as SanityProject_2} from '@sanity/client'
34
36
  import {SanityProjectionResult} from 'groq'
35
37
  import {SanityQueryResult} from 'groq'
36
38
  import {SanityUser as SanityUser_2} from './types'
39
+ import {slicePath} from '@sanity/json-match'
37
40
  import {StackablePerspective} from '@sanity/client'
38
41
  import {StateSource as StateSource_2} from '../_exports'
39
42
  import {StateSource as StateSource_3} from '../../_exports'
40
43
  import {Status} from '@sanity/comlink'
44
+ import {stringifyPath} from '@sanity/json-match'
41
45
  import {StudioResource} from '@sanity/message-protocol'
42
46
  import {Subject} from 'rxjs'
43
47
  import {ValuePending as ValuePending_2} from './previewStore'
@@ -1207,6 +1211,8 @@ export declare const getFavoritesState: BoundStoreAction<
1207
1211
  StateSource_2<FavoriteStatusResponse | undefined>
1208
1212
  >
1209
1213
 
1214
+ export {getIndexForKey}
1215
+
1210
1216
  /**
1211
1217
  * Returns a state source indicating if the SDK is running within a dashboard context.
1212
1218
  * @public
@@ -1270,6 +1276,8 @@ export declare const getOrCreateNode: BoundStoreAction_2<
1270
1276
  Node_2<Message, Message>
1271
1277
  >
1272
1278
 
1279
+ export {getPathDepth}
1280
+
1273
1281
  /** @beta */
1274
1282
  export declare const getPermissionsState: BoundStoreAction<
1275
1283
  DocumentStoreState,
@@ -1541,6 +1549,8 @@ declare interface InRangeNode extends BaseNode {
1541
1549
  isInclusive: boolean
1542
1550
  }
1543
1551
 
1552
+ export {joinPaths}
1553
+
1544
1554
  /**
1545
1555
  * Given a document type TDocument and a JSON Match path string TPath,
1546
1556
  * compute the type found at that path.
@@ -1551,26 +1561,7 @@ export declare type JsonMatch<TDocument, TPath extends string> = DeepGet<
1551
1561
  PathParts<TPath>
1552
1562
  >
1553
1563
 
1554
- /**
1555
- * A very simplified implementation of [JSONMatch][0] that only supports:
1556
- * - descent e.g. `friend.name`
1557
- * - array index e.g. `items[-1]`
1558
- * - array matching with `_key` e.g. `items[_key=="dd9efe09"]`
1559
- * - array matching with a range e.g. `items[4:]`
1560
- *
1561
- * E.g. `friends[_key=="dd9efe09"].address.zip`
1562
- *
1563
- * [0]: https://www.sanity.io/docs/json-match
1564
- *
1565
- * @beta
1566
- */
1567
- export declare function jsonMatch<TDocument, TPath extends string>(
1568
- input: TDocument,
1569
- path: TPath,
1570
- ): MatchEntry<JsonMatch<TDocument, TPath>>[]
1571
-
1572
- /** @beta */
1573
- export declare function jsonMatch<TValue>(input: unknown, path: string): MatchEntry<TValue>[]
1564
+ export {jsonMatch}
1574
1565
 
1575
1566
  /**
1576
1567
  * Loads more users for a specific resource.
@@ -1633,11 +1624,6 @@ declare interface MapNode extends BaseNode {
1633
1624
  expr: ExprNode
1634
1625
  }
1635
1626
 
1636
- declare type MatchEntry<T = unknown> = {
1637
- value: T
1638
- path: SingleValuePath
1639
- }
1640
-
1641
1627
  /**
1642
1628
  * @public
1643
1629
  */
@@ -2414,8 +2400,6 @@ declare interface SharedListener {
2414
2400
  dispose: () => void
2415
2401
  }
2416
2402
 
2417
- declare type SingleValuePath = Exclude<PathSegment, IndexTuple>[]
2418
-
2419
2403
  declare interface SliceNode extends BaseNode {
2420
2404
  type: 'Slice'
2421
2405
  base: ExprNode
@@ -2424,6 +2408,8 @@ declare interface SliceNode extends BaseNode {
2424
2408
  isInclusive: boolean
2425
2409
  }
2426
2410
 
2411
+ export {slicePath}
2412
+
2427
2413
  /**
2428
2414
  * Represents a reactive state source that provides synchronized access to store data
2429
2415
  *
@@ -2494,6 +2480,8 @@ declare class StreamValue {
2494
2480
  _nextTick(): Promise<void>
2495
2481
  }
2496
2482
 
2483
+ export {stringifyPath}
2484
+
2497
2485
  declare type StringValue = StaticValue<string, 'string'>
2498
2486
 
2499
2487
  /** @beta */
package/dist/index.js CHANGED
@@ -8,6 +8,8 @@ import { createController, createNode } from "@sanity/comlink";
8
8
  import { createSelector } from "reselect";
9
9
  import { SanityEncoder } from "@sanity/mutate";
10
10
  import { getPublishedId as getPublishedId$1 } from "@sanity/client/csm";
11
+ import { jsonMatch, stringifyPath, slicePath, getIndexForKey } from "@sanity/json-match";
12
+ import { getIndexForKey as getIndexForKey2, getPathDepth, joinPaths, jsonMatch as jsonMatch2, slicePath as slicePath2, stringifyPath as stringifyPath2 } from "@sanity/json-match";
11
13
  import { diffValue } from "@sanity/diff-patch";
12
14
  import { applyPatches, parsePatch } from "@sanity/diff-match-patch";
13
15
  import { isKeySegment, isKeyedObject } from "@sanity/types";
@@ -1062,101 +1064,6 @@ function discardDocument(doc) {
1062
1064
  };
1063
1065
  }
1064
1066
  const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$3 = "v2025-05-06";
1065
- function parseBracketContent(content) {
1066
- const rangeMatch = content.match(/^(\d*):(\d*)$/);
1067
- if (rangeMatch) {
1068
- const startStr = rangeMatch[1], endStr = rangeMatch[2], start = startStr === "" ? "" : parseInt(startStr, 10), end = endStr === "" ? "" : parseInt(endStr, 10);
1069
- return [start, end];
1070
- }
1071
- const keyedMatch = content.match(/^_key==["'](.+)["']$/);
1072
- if (keyedMatch)
1073
- return { _key: keyedMatch[1] };
1074
- const index = parseInt(content, 10);
1075
- if (!isNaN(index))
1076
- return index;
1077
- throw new Error(`Invalid bracket content: "[${content}]"`);
1078
- }
1079
- function parseSegment(segment) {
1080
- const segments = [];
1081
- let idx = 0;
1082
- function pushIfNotEmpty(text) {
1083
- text && segments.push(text);
1084
- }
1085
- for (; idx < segment.length; ) {
1086
- const openIndex = segment.indexOf("[", idx);
1087
- if (openIndex === -1) {
1088
- const remaining = segment.slice(idx);
1089
- pushIfNotEmpty(remaining);
1090
- break;
1091
- }
1092
- const before = segment.slice(idx, openIndex);
1093
- pushIfNotEmpty(before);
1094
- const closeIndex = segment.indexOf("]", openIndex);
1095
- if (closeIndex === -1)
1096
- throw new Error(`Unmatched "[" in segment: "${segment}"`);
1097
- const bracketContent = segment.slice(openIndex + 1, closeIndex);
1098
- segments.push(parseBracketContent(bracketContent)), idx = closeIndex + 1;
1099
- }
1100
- return segments;
1101
- }
1102
- function parsePath(path) {
1103
- const result = [];
1104
- let buffer = "", bracketDepth = 0;
1105
- for (let i2 = 0; i2 < path.length; i2++) {
1106
- const ch = path[i2];
1107
- ch === "[" ? (bracketDepth++, buffer += ch) : ch === "]" ? (bracketDepth--, buffer += ch) : ch === "." && bracketDepth === 0 ? buffer && (result.push(...parseSegment(buffer)), buffer = "") : buffer += ch;
1108
- }
1109
- return buffer && result.push(...parseSegment(buffer)), result;
1110
- }
1111
- function stringifyPath(path) {
1112
- let result = "";
1113
- for (let i2 = 0; i2 < path.length; i2++) {
1114
- const segment = path[i2];
1115
- if (typeof segment == "string")
1116
- result && (result += "."), result += segment;
1117
- else if (typeof segment == "number")
1118
- result += `[${segment}]`;
1119
- else if (Array.isArray(segment)) {
1120
- const [start, end] = segment, startStr = start === "" ? "" : String(start), endStr = end === "" ? "" : String(end);
1121
- result += `[${startStr}:${endStr}]`;
1122
- } else
1123
- result += `[_key=="${segment._key}"]`;
1124
- }
1125
- return result;
1126
- }
1127
- function jsonMatch(input, pathExpression) {
1128
- return matchRecursive(input, parsePath(pathExpression), []);
1129
- }
1130
- function matchRecursive(value, path, currentPath) {
1131
- if (path.length === 0)
1132
- return [{ value, path: currentPath }];
1133
- const [head, ...rest] = path;
1134
- if (typeof head == "string") {
1135
- if (value && typeof value == "object" && !Array.isArray(value)) {
1136
- const nextValue = value[head];
1137
- return matchRecursive(nextValue, rest, [...currentPath, head]);
1138
- }
1139
- return [];
1140
- }
1141
- if (typeof head == "number") {
1142
- if (Array.isArray(value)) {
1143
- const nextValue = value.at(head);
1144
- return matchRecursive(nextValue, rest, [...currentPath, head]);
1145
- }
1146
- return [];
1147
- }
1148
- if (Array.isArray(head)) {
1149
- if (!Array.isArray(value))
1150
- return [];
1151
- const [start, end] = head, startIndex = start === "" ? 0 : start, endIndex = end === "" ? value.length : end;
1152
- return value.slice(startIndex, endIndex).flatMap((item, i2) => matchRecursive(item, rest, [...currentPath, i2 + startIndex]));
1153
- }
1154
- const keyed = head, arrIndex = getIndexForKey(value, keyed._key);
1155
- if (arrIndex === void 0 || !Array.isArray(value))
1156
- return [];
1157
- const nextVal = value[arrIndex];
1158
- return matchRecursive(nextVal, rest, [...currentPath, { _key: keyed._key }]);
1159
- }
1160
1067
  function generateArrayKey(length = 12) {
1161
1068
  const numBytes = Math.ceil(length / 2), bytes = crypto.getRandomValues(new Uint8Array(numBytes));
1162
1069
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, length);
@@ -1180,7 +1087,7 @@ const ensureArrayKeysDeep = memoize((input) => {
1180
1087
  });
1181
1088
  function set(input, pathExpressionValues) {
1182
1089
  const result = Object.entries(pathExpressionValues).flatMap(
1183
- ([pathExpression, replacementValue]) => jsonMatch(input, pathExpression).map((matchEntry) => ({
1090
+ ([pathExpression, replacementValue]) => Array.from(jsonMatch(input, pathExpression)).map((matchEntry) => ({
1184
1091
  ...matchEntry,
1185
1092
  replacementValue
1186
1093
  }))
@@ -1188,24 +1095,22 @@ function set(input, pathExpressionValues) {
1188
1095
  return ensureArrayKeysDeep(result);
1189
1096
  }
1190
1097
  function setIfMissing(input, pathExpressionValues) {
1191
- const result = Object.entries(pathExpressionValues).flatMap(([pathExpression, replacementValue]) => jsonMatch(input, pathExpression).map((matchEntry) => ({
1098
+ const result = Object.entries(pathExpressionValues).flatMap(([pathExpression, replacementValue]) => Array.from(jsonMatch(input, pathExpression)).map((matchEntry) => ({
1192
1099
  ...matchEntry,
1193
1100
  replacementValue
1194
1101
  }))).filter((matchEntry) => matchEntry.value === null || matchEntry.value === void 0).reduce((acc, { path, replacementValue }) => setDeep(acc, path, replacementValue), input);
1195
1102
  return ensureArrayKeysDeep(result);
1196
1103
  }
1197
1104
  function unset(input, pathExpressions) {
1198
- const result = pathExpressions.flatMap((pathExpression) => jsonMatch(input, pathExpression)).reverse().reduce((acc, { path }) => unsetDeep(acc, path), input);
1105
+ const result = pathExpressions.flatMap((pathExpression) => Array.from(jsonMatch(input, pathExpression))).reverse().reduce((acc, { path }) => unsetDeep(acc, path), input);
1199
1106
  return ensureArrayKeysDeep(result);
1200
1107
  }
1201
1108
  function insert(input, { items, ...insertPatch }) {
1202
1109
  let operation, pathExpression;
1203
- if ("before" in insertPatch ? (operation = "before", pathExpression = insertPatch.before) : "after" in insertPatch ? (operation = "after", pathExpression = insertPatch.after) : "replace" in insertPatch && (operation = "replace", pathExpression = insertPatch.replace), !operation || typeof pathExpression != "string") return input;
1204
- const parsedPath = parsePath(pathExpression);
1205
- if (!parsedPath.length) return input;
1206
- const arrayPath = stringifyPath(parsedPath.slice(0, -1)), positionPath = stringifyPath(parsedPath.slice(-1)), arrayMatches = jsonMatch(input, arrayPath);
1110
+ if ("before" in insertPatch ? (operation = "before", pathExpression = insertPatch.before) : "after" in insertPatch ? (operation = "after", pathExpression = insertPatch.after) : "replace" in insertPatch && (operation = "replace", pathExpression = insertPatch.replace), !operation || typeof pathExpression != "string" || !pathExpression.length) return input;
1111
+ const arrayPath = slicePath(pathExpression, 0, -1), positionPath = slicePath(pathExpression, -1);
1207
1112
  let result = input;
1208
- for (const { path, value } of arrayMatches) {
1113
+ for (const { path, value } of jsonMatch(input, arrayPath)) {
1209
1114
  if (!Array.isArray(value)) continue;
1210
1115
  let arr = value;
1211
1116
  switch (operation) {
@@ -1258,7 +1163,7 @@ function insert(input, { items, ...insertPatch }) {
1258
1163
  }
1259
1164
  function inc(input, pathExpressionValues) {
1260
1165
  const result = Object.entries(pathExpressionValues).flatMap(
1261
- ([pathExpression, valueToAdd]) => jsonMatch(input, pathExpression).map((matchEntry) => ({
1166
+ ([pathExpression, valueToAdd]) => Array.from(jsonMatch(input, pathExpression)).map((matchEntry) => ({
1262
1167
  ...matchEntry,
1263
1168
  valueToAdd
1264
1169
  }))
@@ -1277,7 +1182,9 @@ function dec(input, pathExpressionValues) {
1277
1182
  return ensureArrayKeysDeep(result);
1278
1183
  }
1279
1184
  function diffMatchPatch(input, pathExpressionValues) {
1280
- const result = Object.entries(pathExpressionValues).flatMap(([pathExpression, dmp]) => jsonMatch(input, pathExpression).map((m2) => ({ ...m2, dmp }))).filter((i2) => i2.value !== void 0).map(({ path, value, dmp }) => {
1185
+ const result = Object.entries(pathExpressionValues).flatMap(
1186
+ ([pathExpression, dmp]) => Array.from(jsonMatch(input, pathExpression)).map((m2) => ({ ...m2, dmp }))
1187
+ ).filter((i2) => i2.value !== void 0).map(({ path, value, dmp }) => {
1281
1188
  if (typeof value != "string")
1282
1189
  throw new Error(
1283
1190
  `Can't diff-match-patch \`${JSON.stringify(value)}\` at path \`${stringifyPath(path)}\`, because it is not a string`
@@ -1297,14 +1204,6 @@ function ifRevisionID(input, revisionId) {
1297
1204
  );
1298
1205
  return input;
1299
1206
  }
1300
- const indexCache = /* @__PURE__ */ new WeakMap();
1301
- function getIndexForKey(input, key) {
1302
- if (!Array.isArray(input)) return;
1303
- const cached = indexCache.get(input);
1304
- if (cached) return cached[key];
1305
- const lookup = input.reduce((acc, next, index) => (typeof next?._key == "string" && (acc[next._key] = index), acc), {});
1306
- return indexCache.set(input, lookup), lookup[key];
1307
- }
1308
1207
  function setDeep(input, path, value) {
1309
1208
  const [currentSegment, ...restOfPath] = path;
1310
1209
  if (currentSegment === void 0) return value;
@@ -1327,7 +1226,7 @@ function setDeep(input, path, value) {
1327
1226
  }
1328
1227
  if (Array.isArray(input)) {
1329
1228
  let index;
1330
- return isKeySegment(currentSegment) ? index = getIndexForKey(input, currentSegment._key) : typeof currentSegment == "number" && (index = currentSegment < 0 ? input.length + currentSegment : currentSegment), index === void 0 ? input : index in input ? input.map(
1229
+ return isKeySegment(currentSegment) ? index = getIndexForKey(input, currentSegment._key) ?? input.length : typeof currentSegment == "number" && (index = currentSegment < 0 ? input.length + currentSegment : currentSegment), index === void 0 ? input : index in input ? input.map(
1331
1230
  (nestedInput, i2) => i2 === index ? setDeep(nestedInput, restOfPath, value) : nestedInput
1332
1231
  ) : [
1333
1232
  ...input,
@@ -4107,7 +4006,11 @@ const _getDocumentState = bindActionByDataset(
4107
4006
  const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documentStates[draftId]?.local, published = documentStates[publishedId]?.local;
4108
4007
  if (draft === void 0 || published === void 0) return;
4109
4008
  const document = draft ?? published;
4110
- return path ? jsonMatch(document, path).at(0)?.value : document;
4009
+ if (!path) return document;
4010
+ const result = jsonMatch(document, path).next();
4011
+ if (result.done) return;
4012
+ const { value } = result.value;
4013
+ return value;
4111
4014
  },
4112
4015
  onSubscribe: (context, options) => manageSubscriberIds(context, options.documentId)
4113
4016
  })
@@ -5292,7 +5195,7 @@ function createGroqSearchFilter(query) {
5292
5195
  `${finalIncrementalToken}${WILDCARD_TOKEN}`
5293
5196
  ), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
5294
5197
  }
5295
- var version = "2.0.2";
5198
+ var version = "2.1.0";
5296
5199
  const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
5297
5200
  export {
5298
5201
  AuthStateType,
@@ -5319,12 +5222,14 @@ export {
5319
5222
  getDocumentState,
5320
5223
  getDocumentSyncStatus,
5321
5224
  getFavoritesState,
5225
+ getIndexForKey2 as getIndexForKey,
5322
5226
  getIsInDashboardState,
5323
5227
  getLoginUrlState,
5324
5228
  getNodeState,
5325
5229
  getOrCreateChannel,
5326
5230
  getOrCreateController,
5327
5231
  getOrCreateNode,
5232
+ getPathDepth,
5328
5233
  getPermissionsState,
5329
5234
  getPerspectiveState,
5330
5235
  getPreviewState,
@@ -5337,7 +5242,8 @@ export {
5337
5242
  getUsersKey,
5338
5243
  getUsersState,
5339
5244
  handleAuthCallback,
5340
- jsonMatch,
5245
+ joinPaths,
5246
+ jsonMatch2 as jsonMatch,
5341
5247
  loadMoreUsers,
5342
5248
  logout,
5343
5249
  observeOrganizationVerificationState,
@@ -5357,6 +5263,8 @@ export {
5357
5263
  resolveQuery,
5358
5264
  resolveUsers,
5359
5265
  setAuthToken,
5266
+ slicePath2 as slicePath,
5267
+ stringifyPath2 as stringifyPath,
5360
5268
  subscribeDocumentEvents,
5361
5269
  unpublishDocument
5362
5270
  };