@sanity/sdk 2.4.0 → 2.5.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.
Files changed (47) hide show
  1. package/dist/index.d.ts +35 -90
  2. package/dist/index.js +237 -111
  3. package/dist/index.js.map +1 -1
  4. package/package.json +9 -8
  5. package/src/auth/authStore.test.ts +13 -13
  6. package/src/auth/refreshStampedToken.test.ts +16 -16
  7. package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +6 -6
  8. package/src/auth/subscribeToStorageEventsAndSetToken.test.ts +4 -4
  9. package/src/comlink/controller/actions/destroyController.test.ts +2 -2
  10. package/src/comlink/controller/actions/getOrCreateChannel.test.ts +6 -6
  11. package/src/comlink/controller/actions/getOrCreateController.test.ts +5 -5
  12. package/src/comlink/controller/actions/getOrCreateController.ts +1 -1
  13. package/src/comlink/controller/actions/releaseChannel.test.ts +3 -2
  14. package/src/comlink/controller/comlinkControllerStore.test.ts +4 -4
  15. package/src/comlink/node/actions/getOrCreateNode.test.ts +7 -7
  16. package/src/comlink/node/actions/releaseNode.test.ts +2 -2
  17. package/src/comlink/node/comlinkNodeStore.test.ts +4 -3
  18. package/src/config/sanityConfig.ts +8 -3
  19. package/src/document/actions.ts +11 -7
  20. package/src/document/applyDocumentActions.test.ts +9 -6
  21. package/src/document/applyDocumentActions.ts +9 -49
  22. package/src/document/documentStore.test.ts +128 -115
  23. package/src/document/documentStore.ts +40 -10
  24. package/src/document/permissions.test.ts +9 -9
  25. package/src/document/permissions.ts +17 -7
  26. package/src/document/processActions.test.ts +248 -0
  27. package/src/document/processActions.ts +173 -0
  28. package/src/document/reducers.ts +13 -6
  29. package/src/presence/presenceStore.ts +13 -7
  30. package/src/preview/previewStore.test.ts +10 -2
  31. package/src/preview/previewStore.ts +2 -1
  32. package/src/preview/subscribeToStateAndFetchBatches.test.ts +8 -5
  33. package/src/preview/subscribeToStateAndFetchBatches.ts +9 -3
  34. package/src/projection/projectionStore.test.ts +18 -2
  35. package/src/projection/projectionStore.ts +2 -1
  36. package/src/projection/subscribeToStateAndFetchBatches.test.ts +6 -5
  37. package/src/projection/subscribeToStateAndFetchBatches.ts +9 -3
  38. package/src/releases/getPerspectiveState.ts +2 -2
  39. package/src/releases/releasesStore.ts +10 -4
  40. package/src/store/createActionBinder.test.ts +8 -6
  41. package/src/store/createActionBinder.ts +44 -29
  42. package/src/store/createStateSourceAction.test.ts +12 -11
  43. package/src/store/createStateSourceAction.ts +6 -6
  44. package/src/store/createStoreInstance.test.ts +29 -16
  45. package/src/store/createStoreInstance.ts +6 -5
  46. package/src/store/defineStore.test.ts +1 -1
  47. package/src/store/defineStore.ts +12 -7
package/dist/index.js CHANGED
@@ -97,11 +97,11 @@ function createStoreState(initialState, devToolsOptions) {
97
97
  })
98
98
  };
99
99
  }
100
- function createStoreInstance(instance, { name, getInitialState: getInitialState2, initialize }) {
101
- const state = createStoreState(getInitialState2(instance), {
100
+ function createStoreInstance(instance, key, { name, getInitialState: getInitialState2, initialize }) {
101
+ const state = createStoreState(getInitialState2(instance, key), {
102
102
  enabled: !!getEnv("DEV"),
103
- name: `${name}-${instance.config.projectId}.${instance.config.dataset}`
104
- }), dispose = initialize?.({ state, instance }), disposed = { current: !1 };
103
+ name: `${name}-${key.name}`
104
+ }), dispose = initialize?.({ state, instance, key }), disposed = { current: !1 };
105
105
  return {
106
106
  state,
107
107
  dispose: () => {
@@ -114,32 +114,32 @@ function createActionBinder(keyFn) {
114
114
  const instanceRegistry = /* @__PURE__ */ new Map(), storeRegistry = /* @__PURE__ */ new Map();
115
115
  return function(storeDefinition, action) {
116
116
  return function(instance, ...params) {
117
- const keySuffix = keyFn(instance.config, ...params), compositeKey = storeDefinition.name + (keySuffix ? `:${keySuffix}` : "");
117
+ const key = keyFn(instance, ...params), compositeKey = storeDefinition.name + (key.name ? `:${key.name}` : "");
118
118
  let instances = instanceRegistry.get(compositeKey);
119
119
  instances || (instances = /* @__PURE__ */ new Set(), instanceRegistry.set(compositeKey, instances)), instances.has(instance.instanceId) || (instances.add(instance.instanceId), instance.onDispose(() => {
120
120
  instances.delete(instance.instanceId), instances.size === 0 && (storeRegistry.get(compositeKey)?.dispose(), storeRegistry.delete(compositeKey), instanceRegistry.delete(compositeKey));
121
121
  }));
122
122
  let storeInstance = storeRegistry.get(compositeKey);
123
- return storeInstance || (storeInstance = createStoreInstance(instance, storeDefinition), storeRegistry.set(compositeKey, storeInstance)), action({ instance, state: storeInstance.state }, ...params);
123
+ return storeInstance || (storeInstance = createStoreInstance(instance, key, storeDefinition), storeRegistry.set(compositeKey, storeInstance)), action({ instance, state: storeInstance.state, key }, ...params);
124
124
  };
125
125
  };
126
126
  }
127
- const bindActionByDataset = createActionBinder(({ projectId, dataset }) => {
127
+ const bindActionByDataset = createActionBinder((instance, options) => {
128
+ const projectId = options?.projectId ?? instance.config.projectId, dataset = options?.dataset ?? instance.config.dataset;
128
129
  if (!projectId || !dataset)
129
130
  throw new Error("This API requires a project ID and dataset configured.");
130
- return `${projectId}.${dataset}`;
131
- }), bindActionBySource = createActionBinder(
132
- ({ projectId, dataset }, { source }) => {
133
- if (source) {
134
- const id = source[SOURCE_ID];
135
- if (!id) throw new Error("Invalid source (missing ID information)");
136
- return Array.isArray(id) ? id.join(":") : `${id.projectId}.${id.dataset}`;
137
- }
138
- if (!projectId || !dataset)
139
- throw new Error("This API requires a project ID and dataset configured.");
140
- return `${projectId}.${dataset}`;
131
+ return { name: `${projectId}.${dataset}`, projectId, dataset };
132
+ }), bindActionBySource = createActionBinder((instance, { source }) => {
133
+ if (source) {
134
+ const id = source[SOURCE_ID];
135
+ if (!id) throw new Error("Invalid source (missing ID information)");
136
+ return Array.isArray(id) ? { name: id.join(":") } : { name: `${id.projectId}.${id.dataset}` };
141
137
  }
142
- ), bindActionGlobally = createActionBinder(() => "global");
138
+ const { projectId, dataset } = instance.config;
139
+ if (!projectId || !dataset)
140
+ throw new Error("This API requires a project ID and dataset configured.");
141
+ return { name: `${projectId}.${dataset}` };
142
+ }), bindActionGlobally = createActionBinder((..._rest) => ({ name: "global" }));
143
143
  function createStateSourceAction(options) {
144
144
  const selector = typeof options == "function" ? options : options.selector, subscribeHandler = options && "onSubscribe" in options ? options.onSubscribe : void 0, isEqual2 = options && "isEqual" in options ? options.isEqual ?? Object.is : Object.is, selectorContextCache = /* @__PURE__ */ new WeakMap();
145
145
  function stateSourceAction(context, ...params) {
@@ -188,7 +188,7 @@ function createStateSourceAction(options) {
188
188
  return stateSourceAction;
189
189
  }
190
190
  var AuthStateType = /* @__PURE__ */ ((AuthStateType2) => (AuthStateType2.LOGGED_IN = "logged-in", AuthStateType2.LOGGING_IN = "logging-in", AuthStateType2.ERROR = "error", AuthStateType2.LOGGED_OUT = "logged-out", AuthStateType2))(AuthStateType || {});
191
- const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth", REFRESH_INTERVAL = 12 * 60 * 60 * 1e3, LOCK_NAME = "sanity-token-refresh-lock";
191
+ const DEFAULT_BASE = "http://localhost", AUTH_CODE_PARAM = "sid", DEFAULT_API_VERSION$1 = "2021-06-07", REQUEST_TAG_PREFIX = "sanity.sdk.auth", REFRESH_INTERVAL = 720 * 60 * 1e3, LOCK_NAME = "sanity-token-refresh-lock";
192
192
  function getLastRefreshTime(storageArea, storageKey) {
193
193
  try {
194
194
  const data = storageArea?.getItem(`${storageKey}_last_refresh`), parsed = data ? parseInt(data, 10) : 0;
@@ -1163,7 +1163,9 @@ function createDocument(doc, initialValue) {
1163
1163
  return {
1164
1164
  type: "document.create",
1165
1165
  ...doc,
1166
- ...doc.documentId && { documentId: getPublishedId(doc.documentId) },
1166
+ ...doc.documentId && {
1167
+ documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
1168
+ },
1167
1169
  ...initialValue && { initialValue }
1168
1170
  };
1169
1171
  }
@@ -1171,7 +1173,7 @@ function deleteDocument(doc) {
1171
1173
  return {
1172
1174
  type: "document.delete",
1173
1175
  ...doc,
1174
- documentId: getPublishedId(doc.documentId)
1176
+ documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
1175
1177
  };
1176
1178
  }
1177
1179
  function convertSanityMutatePatch(sanityPatchMutation) {
@@ -1181,19 +1183,20 @@ function convertSanityMutatePatch(sanityPatchMutation) {
1181
1183
  });
1182
1184
  }
1183
1185
  function editDocument(doc, patches) {
1186
+ const documentId = doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId);
1184
1187
  if (isSanityMutatePatch(patches)) {
1185
1188
  const converted = convertSanityMutatePatch(patches) ?? [];
1186
1189
  return {
1187
1190
  ...doc,
1188
1191
  type: "document.edit",
1189
- documentId: getPublishedId(doc.documentId),
1192
+ documentId,
1190
1193
  patches: converted
1191
1194
  };
1192
1195
  }
1193
1196
  return {
1194
1197
  ...doc,
1195
1198
  type: "document.edit",
1196
- documentId: getPublishedId(doc.documentId),
1199
+ documentId,
1197
1200
  ...patches && { patches: Array.isArray(patches) ? patches : [patches] }
1198
1201
  };
1199
1202
  }
@@ -1201,21 +1204,21 @@ function publishDocument(doc) {
1201
1204
  return {
1202
1205
  type: "document.publish",
1203
1206
  ...doc,
1204
- documentId: getPublishedId(doc.documentId)
1207
+ documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
1205
1208
  };
1206
1209
  }
1207
1210
  function unpublishDocument(doc) {
1208
1211
  return {
1209
1212
  type: "document.unpublish",
1210
1213
  ...doc,
1211
- documentId: getPublishedId(doc.documentId)
1214
+ documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
1212
1215
  };
1213
1216
  }
1214
1217
  function discardDocument(doc) {
1215
1218
  return {
1216
1219
  type: "document.discard",
1217
1220
  ...doc,
1218
- documentId: getPublishedId(doc.documentId)
1221
+ documentId: doc.liveEdit ? doc.documentId : getPublishedId(doc.documentId)
1219
1222
  };
1220
1223
  }
1221
1224
  const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$3 = "v2025-05-06";
@@ -1225,13 +1228,13 @@ function generateArrayKey(length = 12) {
1225
1228
  }
1226
1229
  function memoize(fn) {
1227
1230
  const cache = /* @__PURE__ */ new WeakMap();
1228
- return (input) => {
1231
+ return ((input) => {
1229
1232
  if (!input || typeof input != "object") return fn(input);
1230
1233
  const cached = cache.get(input);
1231
1234
  if (cached) return cached;
1232
1235
  const result = fn(input);
1233
1236
  return cache.set(input, result), result;
1234
- };
1237
+ });
1235
1238
  }
1236
1239
  const ensureArrayKeysDeep = memoize((input) => {
1237
1240
  if (!input || typeof input != "object") return input;
@@ -1744,11 +1747,11 @@ function createGrantsLookup(datasetAcl) {
1744
1747
  const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new WeakMap(), nullReplacer = {}, documentsSelector = createSelector(
1745
1748
  [
1746
1749
  ({ state: { documentStates } }) => documentStates,
1747
- (_context, actions) => actions
1750
+ (_context, { actions }) => actions
1748
1751
  ],
1749
1752
  (documentStates, actions) => {
1750
1753
  const documentIds = new Set(
1751
- (Array.isArray(actions) ? actions : [actions]).map((i) => i.documentId).filter((i) => typeof i == "string").flatMap((documentId) => [getPublishedId(documentId), getDraftId(documentId)])
1754
+ actions.map((action) => typeof action.documentId != "string" ? [] : action.liveEdit ? [action.documentId] : [getPublishedId(action.documentId), getDraftId(action.documentId)]).flat()
1752
1755
  ), documents = {};
1753
1756
  for (const documentId of documentIds) {
1754
1757
  const local = documentStates[documentId]?.local;
@@ -1765,7 +1768,7 @@ const documentsCache = new MultiKeyWeakMap(), actionsCache = /* @__PURE__ */ new
1765
1768
  ), memoizedActionsSelector = createSelector(
1766
1769
  [
1767
1770
  documentsSelector,
1768
- (_state, actions) => actions
1771
+ (_state, { actions }) => actions
1769
1772
  ],
1770
1773
  (documents, actions) => {
1771
1774
  if (!documents) return;
@@ -1819,7 +1822,7 @@ const _calculatePermissions = createSelector(
1819
1822
  }
1820
1823
  for (const action of actions)
1821
1824
  if (action.type === "document.edit" && !action.patches?.length) {
1822
- const docId = action.documentId, doc = documents[getDraftId(docId)] ?? documents[getPublishedId(docId)];
1825
+ const docId = action.documentId, doc = action.liveEdit ? documents[docId] : documents[getDraftId(docId)] ?? documents[getPublishedId(docId)];
1823
1826
  doc ? checkGrant$1(grants.update, doc) || reasons.push({
1824
1827
  type: "access",
1825
1828
  message: `You are not allowed to edit the document with ID "${docId}".`,
@@ -1866,7 +1869,39 @@ function processActions({
1866
1869
  for (const action of actions)
1867
1870
  switch (action.type) {
1868
1871
  case "document.create": {
1869
- const documentId = getId(action.documentId), draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
1872
+ const documentId = getId(action.documentId);
1873
+ if (action.liveEdit) {
1874
+ if (working[documentId])
1875
+ throw new ActionError({
1876
+ documentId,
1877
+ transactionId,
1878
+ message: "This document already exists."
1879
+ });
1880
+ const newDocBase2 = { _type: action.documentType, _id: documentId }, newDocWorking2 = { _type: action.documentType, _id: documentId }, mutations2 = [{ create: newDocWorking2 }];
1881
+ if (base = processMutations({
1882
+ documents: base,
1883
+ transactionId,
1884
+ mutations: [{ create: newDocBase2 }],
1885
+ timestamp
1886
+ }), working = processMutations({
1887
+ documents: working,
1888
+ transactionId,
1889
+ mutations: mutations2,
1890
+ timestamp
1891
+ }), !checkGrant(grants.create, working[documentId]))
1892
+ throw new PermissionActionError({
1893
+ documentId,
1894
+ transactionId,
1895
+ message: `You do not have permission to create document "${documentId}".`
1896
+ });
1897
+ outgoingMutations.push(...mutations2), outgoingActions.push({
1898
+ actionType: "sanity.action.document.create",
1899
+ publishedId: documentId,
1900
+ attributes: newDocWorking2
1901
+ });
1902
+ continue;
1903
+ }
1904
+ const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
1870
1905
  if (working[draftId])
1871
1906
  throw new ActionError({
1872
1907
  documentId,
@@ -1908,7 +1943,28 @@ function processActions({
1908
1943
  continue;
1909
1944
  }
1910
1945
  case "document.delete": {
1911
- const documentId = action.documentId, draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
1946
+ const documentId = action.documentId;
1947
+ if (action.liveEdit) {
1948
+ if (!working[documentId])
1949
+ throw new ActionError({
1950
+ documentId,
1951
+ transactionId,
1952
+ message: "The document you are trying to delete does not exist."
1953
+ });
1954
+ if (!checkGrant(grants.update, working[documentId]))
1955
+ throw new PermissionActionError({
1956
+ documentId,
1957
+ transactionId,
1958
+ message: "You do not have permission to delete this document."
1959
+ });
1960
+ const mutations2 = [{ delete: { id: documentId } }];
1961
+ base = processMutations({ documents: base, transactionId, mutations: mutations2, timestamp }), working = processMutations({ documents: working, transactionId, mutations: mutations2, timestamp }), outgoingMutations.push(...mutations2), outgoingActions.push({
1962
+ actionType: "sanity.action.document.delete",
1963
+ publishedId: documentId
1964
+ });
1965
+ continue;
1966
+ }
1967
+ const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
1912
1968
  if (!working[publishedId])
1913
1969
  throw new ActionError({
1914
1970
  documentId,
@@ -1931,7 +1987,14 @@ function processActions({
1931
1987
  continue;
1932
1988
  }
1933
1989
  case "document.discard": {
1934
- const documentId = getId(action.documentId), draftId = getDraftId(documentId), mutations = [{ delete: { id: draftId } }];
1990
+ const documentId = getId(action.documentId);
1991
+ if (action.liveEdit)
1992
+ throw new ActionError({
1993
+ documentId,
1994
+ transactionId,
1995
+ message: `Cannot discard changes for liveEdit document "${documentId}". LiveEdit documents do not support drafts.`
1996
+ });
1997
+ const draftId = getDraftId(documentId), mutations = [{ delete: { id: draftId } }];
1935
1998
  if (!working[draftId])
1936
1999
  throw new ActionError({
1937
2000
  documentId,
@@ -1951,7 +2014,50 @@ function processActions({
1951
2014
  continue;
1952
2015
  }
1953
2016
  case "document.edit": {
1954
- const documentId = getId(action.documentId), draftId = getDraftId(documentId), publishedId = getPublishedId(documentId), userPatches = action.patches?.map((patch) => ({ patch: { id: draftId, ...patch } }));
2017
+ const documentId = getId(action.documentId);
2018
+ if (action.liveEdit) {
2019
+ const userPatches2 = action.patches?.map((patch) => ({ patch: { id: documentId, ...patch } }));
2020
+ if (!userPatches2?.length) continue;
2021
+ if (!working[documentId] || !base[documentId])
2022
+ throw new ActionError({
2023
+ documentId,
2024
+ transactionId,
2025
+ message: "Cannot edit document because it does not exist."
2026
+ });
2027
+ const baseBefore2 = base[documentId];
2028
+ userPatches2 && (base = processMutations({
2029
+ documents: base,
2030
+ transactionId,
2031
+ mutations: userPatches2,
2032
+ timestamp
2033
+ }));
2034
+ const baseAfter2 = base[documentId], patches2 = diffValue(baseBefore2, baseAfter2), workingBefore2 = working[documentId];
2035
+ if (!checkGrant(grants.update, workingBefore2))
2036
+ throw new PermissionActionError({
2037
+ documentId,
2038
+ transactionId,
2039
+ message: `You do not have permission to edit document "${documentId}".`
2040
+ });
2041
+ const workingMutations2 = patches2.map((patch) => ({ patch: { id: documentId, ...patch } }));
2042
+ working = processMutations({
2043
+ documents: working,
2044
+ transactionId,
2045
+ mutations: workingMutations2,
2046
+ timestamp
2047
+ }), outgoingMutations.push(...workingMutations2), outgoingActions.push(
2048
+ ...patches2.map(
2049
+ (patch) => ({
2050
+ actionType: "sanity.action.document.edit",
2051
+ // Server requires draftId to have drafts. prefix for validation, even for liveEdit
2052
+ draftId: getDraftId(documentId),
2053
+ publishedId: documentId,
2054
+ patch
2055
+ })
2056
+ )
2057
+ );
2058
+ continue;
2059
+ }
2060
+ const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId), userPatches = action.patches?.map((patch) => ({ patch: { id: draftId, ...patch } }));
1955
2061
  if (!userPatches?.length) continue;
1956
2062
  if (!working[draftId] && !working[publishedId] || !base[draftId] && !base[publishedId])
1957
2063
  throw new ActionError({
@@ -2004,7 +2110,14 @@ function processActions({
2004
2110
  continue;
2005
2111
  }
2006
2112
  case "document.publish": {
2007
- const documentId = getId(action.documentId), draftId = getDraftId(documentId), publishedId = getPublishedId(documentId), workingDraft = working[draftId], baseDraft = base[draftId];
2113
+ const documentId = getId(action.documentId);
2114
+ if (action.liveEdit)
2115
+ throw new ActionError({
2116
+ documentId,
2117
+ transactionId,
2118
+ message: `Cannot publish liveEdit document "${documentId}". LiveEdit documents do not support drafts or publishing.`
2119
+ });
2120
+ const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId), workingDraft = working[draftId], baseDraft = base[draftId];
2008
2121
  if (!workingDraft || !baseDraft)
2009
2122
  throw new ActionError({
2010
2123
  documentId,
@@ -2047,7 +2160,14 @@ function processActions({
2047
2160
  continue;
2048
2161
  }
2049
2162
  case "document.unpublish": {
2050
- const documentId = getId(action.documentId), draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
2163
+ const documentId = getId(action.documentId);
2164
+ if (action.liveEdit)
2165
+ throw new ActionError({
2166
+ documentId,
2167
+ transactionId,
2168
+ message: `Cannot unpublish liveEdit document "${documentId}". LiveEdit documents do not support drafts or publishing.`
2169
+ });
2170
+ const draftId = getDraftId(documentId), publishedId = getPublishedId(documentId);
2051
2171
  if (!working[publishedId] && !base[publishedId])
2052
2172
  throw new ActionError({
2053
2173
  documentId,
@@ -2369,13 +2489,13 @@ function removeSubscriptionIdFromDocument(prev, documentId, subscriptionId) {
2369
2489
  }
2370
2490
  } : { ...prev, documentStates: omit(prev.documentStates, documentId) } : prev;
2371
2491
  }
2372
- function manageSubscriberIds({ state }, documentId) {
2373
- const documentIds = Array.from(
2492
+ function manageSubscriberIds({ state }, documentId, options) {
2493
+ const expandDraftPublished = options?.expandDraftPublished ?? !0, documentIds = Array.from(
2374
2494
  new Set(
2375
- (Array.isArray(documentId) ? documentId : [documentId]).flatMap((id) => [
2495
+ expandDraftPublished ? (Array.isArray(documentId) ? documentId : [documentId]).flatMap((id) => [
2376
2496
  getPublishedId$1(id),
2377
2497
  getDraftId(id)
2378
- ])
2498
+ ]) : Array.isArray(documentId) ? documentId : [documentId]
2379
2499
  )
2380
2500
  ), subscriptionId = insecureRandomId();
2381
2501
  return state.set(
@@ -2396,8 +2516,7 @@ function manageSubscriberIds({ state }, documentId) {
2396
2516
  }, DOCUMENT_STATE_CLEAR_DELAY);
2397
2517
  };
2398
2518
  }
2399
- function getDocumentIdsFromActions(action) {
2400
- const actions = Array.isArray(action) ? action : [action];
2519
+ function getDocumentIdsFromActions(actions) {
2401
2520
  return Array.from(
2402
2521
  new Set(
2403
2522
  actions.map((i) => i.documentId).filter((i) => typeof i == "string").flatMap((documentId) => [getPublishedId$1(documentId), getDraftId(documentId)])
@@ -2509,8 +2628,17 @@ const _getDocumentState = bindActionByDataset(
2509
2628
  documentStore,
2510
2629
  createStateSourceAction({
2511
2630
  selector: ({ state: { error, documentStates } }, options) => {
2512
- const { documentId, path } = options;
2631
+ const { documentId, path, liveEdit } = options;
2513
2632
  if (error) throw error;
2633
+ if (liveEdit) {
2634
+ const document22 = documentStates[documentId]?.local;
2635
+ if (document22 === void 0) return;
2636
+ if (!path) return document22;
2637
+ const result2 = jsonMatch(document22, path).next();
2638
+ if (result2.done) return;
2639
+ const { value: value2 } = result2.value;
2640
+ return value2;
2641
+ }
2514
2642
  const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documentStates[draftId]?.local, published = documentStates[publishedId]?.local;
2515
2643
  if (draft === void 0 || published === void 0) return;
2516
2644
  const document2 = draft ?? published;
@@ -2520,7 +2648,7 @@ const _getDocumentState = bindActionByDataset(
2520
2648
  const { value } = result.value;
2521
2649
  return value;
2522
2650
  },
2523
- onSubscribe: (context, options) => manageSubscriberIds(context, options.documentId)
2651
+ onSubscribe: (context, options) => manageSubscriberIds(context, options.documentId, { expandDraftPublished: !options.liveEdit })
2524
2652
  })
2525
2653
  );
2526
2654
  function resolveDocument(...args) {
@@ -2540,6 +2668,8 @@ const _resolveDocument = bindActionByDataset(
2540
2668
  selector: ({ state: { error, documentStates: documents, outgoing, applied, queued } }, doc) => {
2541
2669
  const documentId = typeof doc == "string" ? doc : doc.documentId;
2542
2670
  if (error) throw error;
2671
+ if (doc.liveEdit)
2672
+ return documents[documentId] === void 0 ? void 0 : !queued.length && !applied.length && !outgoing;
2543
2673
  const draftId = getDraftId(documentId), publishedId = getPublishedId$1(documentId), draft = documents[draftId], published = documents[publishedId];
2544
2674
  if (!(draft === void 0 || published === void 0))
2545
2675
  return !queued.length && !applied.length && !outgoing;
@@ -2550,12 +2680,12 @@ const _resolveDocument = bindActionByDataset(
2550
2680
  documentStore,
2551
2681
  createStateSourceAction({
2552
2682
  selector: calculatePermissions,
2553
- onSubscribe: (context, actions) => manageSubscriberIds(context, getDocumentIdsFromActions(actions))
2683
+ onSubscribe: (context, { actions }) => manageSubscriberIds(context, getDocumentIdsFromActions(actions))
2554
2684
  })
2555
2685
  ), resolvePermissions = bindActionByDataset(
2556
2686
  documentStore,
2557
- ({ instance }, actions) => firstValueFrom(
2558
- getPermissionsState(instance, actions).observable.pipe(filter((i) => i !== void 0))
2687
+ ({ instance }, options) => firstValueFrom(
2688
+ getPermissionsState(instance, options).observable.pipe(filter((i) => i !== void 0))
2559
2689
  )
2560
2690
  ), subscribeDocumentEvents = bindActionByDataset(
2561
2691
  documentStore,
@@ -2661,51 +2791,25 @@ const _resolveDocument = bindActionByDataset(
2661
2791
  ).subscribe({ error: (error) => state.set("setError", { error }) });
2662
2792
  }, subscribeToClientAndFetchDatasetAcl = ({
2663
2793
  instance,
2664
- state
2665
- }) => {
2666
- const { projectId, dataset } = instance.config;
2667
- return getClientState(instance, { apiVersion: API_VERSION$3 }).observable.pipe(
2668
- switchMap(
2669
- (client) => client.observable.request({
2670
- uri: `/projects/${projectId}/datasets/${dataset}/acl`,
2671
- tag: "acl.get",
2672
- withCredentials: !0
2673
- })
2674
- ),
2675
- tap$1((datasetAcl) => state.set("setGrants", { grants: createGrantsLookup(datasetAcl) }))
2676
- ).subscribe({
2677
- error: (error) => state.set("setError", { error })
2678
- });
2679
- };
2794
+ state,
2795
+ key: { projectId, dataset }
2796
+ }) => getClientState(instance, { apiVersion: API_VERSION$3 }).observable.pipe(
2797
+ switchMap(
2798
+ (client) => client.observable.request({
2799
+ uri: `/projects/${projectId}/datasets/${dataset}/acl`,
2800
+ tag: "acl.get",
2801
+ withCredentials: !0
2802
+ })
2803
+ ),
2804
+ tap$1((datasetAcl) => state.set("setGrants", { grants: createGrantsLookup(datasetAcl) }))
2805
+ ).subscribe({
2806
+ error: (error) => state.set("setError", { error })
2807
+ });
2680
2808
  function applyDocumentActions(...args) {
2681
2809
  return boundApplyDocumentActions(...args);
2682
2810
  }
2683
2811
  const boundApplyDocumentActions = bindActionByDataset(documentStore, _applyDocumentActions);
2684
- async function _applyDocumentActions({ instance, state }, actionOrActions, { transactionId = crypto.randomUUID(), disableBatching } = {}) {
2685
- const actions = Array.isArray(actionOrActions) ? actionOrActions : [actionOrActions];
2686
- let projectId, dataset;
2687
- for (const action of actions)
2688
- if (action.projectId) {
2689
- if (projectId || (projectId = action.projectId), action.projectId !== projectId)
2690
- throw new Error(
2691
- `Mismatched project IDs found in actions. All actions must belong to the same project. Found "${action.projectId}" but expected "${projectId}".`
2692
- );
2693
- if (action.dataset && (dataset || (dataset = action.dataset), action.dataset !== dataset))
2694
- throw new Error(
2695
- `Mismatched datasets found in actions. All actions must belong to the same dataset. Found "${action.dataset}" but expected "${dataset}".`
2696
- );
2697
- }
2698
- if (projectId && projectId !== instance.config.projectId || dataset && dataset !== instance.config.dataset) {
2699
- const matchedInstance = instance.match({ projectId, dataset });
2700
- if (!matchedInstance)
2701
- throw new Error(
2702
- `Could not find a matching instance for projectId: "${projectId}" and dataset: "${dataset}"`
2703
- );
2704
- return boundApplyDocumentActions(matchedInstance, actionOrActions, {
2705
- disableBatching,
2706
- transactionId
2707
- });
2708
- }
2812
+ async function _applyDocumentActions({ state }, { actions, transactionId = crypto.randomUUID(), disableBatching }) {
2709
2813
  const { events } = state.get(), transaction = {
2710
2814
  transactionId,
2711
2815
  actions,
@@ -3073,8 +3177,14 @@ const handleIncomingMessage = (event) => {
3073
3177
  name: "presence",
3074
3178
  getInitialState,
3075
3179
  initialize: (context) => {
3076
- const { instance, state } = context, sessionId = crypto.randomUUID(), client = getClient(instance, {
3077
- apiVersion: "2022-06-30"
3180
+ const {
3181
+ instance,
3182
+ state,
3183
+ key: { projectId, dataset }
3184
+ } = context, sessionId = crypto.randomUUID(), client = getClient(instance, {
3185
+ apiVersion: "2022-06-30",
3186
+ projectId,
3187
+ dataset
3078
3188
  }), token$ = getTokenState(instance).observable.pipe(distinctUntilChanged()), [incomingEvents$, dispatch] = createBifurTransport({
3079
3189
  client,
3080
3190
  token$,
@@ -3116,8 +3226,8 @@ const handleIncomingMessage = (event) => {
3116
3226
  ), getPresence = bindActionByDataset(
3117
3227
  presenceStore,
3118
3228
  createStateSourceAction({
3119
- selector: (context) => selectPresence(context.state),
3120
- onSubscribe: (context) => {
3229
+ selector: (context, _) => selectPresence(context.state),
3230
+ onSubscribe: (context, _) => {
3121
3231
  const subscription = context.state.observable.pipe(
3122
3232
  map(
3123
3233
  (state) => Array.from(state.locations.values()).map((l) => l.userId).filter((id) => !!id)
@@ -3131,7 +3241,7 @@ const handleIncomingMessage = (event) => {
3131
3241
  (userId) => getUserState(context.instance, {
3132
3242
  userId,
3133
3243
  resourceType: "project",
3134
- projectId: context.instance.config.projectId
3244
+ projectId: context.key.projectId
3135
3245
  }).pipe(filter((v) => !!v))
3136
3246
  );
3137
3247
  return combineLatest(userObservables);
@@ -3212,11 +3322,17 @@ const ARCHIVED_RELEASE_STATES = ["archived", "published"], releasesStore = {
3212
3322
  }, getActiveReleasesState = bindActionByDataset(
3213
3323
  releasesStore,
3214
3324
  createStateSourceAction({
3215
- selector: ({ state }) => state.activeReleases
3325
+ selector: ({ state }, _) => state.activeReleases
3216
3326
  })
3217
- ), RELEASES_QUERY = "releases::all()", QUERY_PARAMS = {}, subscribeToReleases = ({ instance, state }) => getClientState(instance, {
3327
+ ), RELEASES_QUERY = "releases::all()", QUERY_PARAMS = {}, subscribeToReleases = ({
3328
+ instance,
3329
+ state,
3330
+ key: { projectId, dataset }
3331
+ }) => getClientState(instance, {
3218
3332
  apiVersion: "2025-04-10",
3219
- perspective: "raw"
3333
+ perspective: "raw",
3334
+ projectId,
3335
+ dataset
3220
3336
  }).observable.pipe(
3221
3337
  switchMap(
3222
3338
  (client) => (
@@ -3244,7 +3360,7 @@ const ARCHIVED_RELEASE_STATES = ["archived", "published"], releasesStore = {
3244
3360
  function isReleasePerspective(perspective) {
3245
3361
  return typeof perspective == "object" && perspective !== null && "releaseName" in perspective;
3246
3362
  }
3247
- const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
3363
+ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(), selectInstancePerspective = (context, _) => context.instance.config.perspective, selectActiveReleases = (context) => context.state.activeReleases, selectOptions = (_context, options) => options, memoizedOptionsSelector = createSelector(
3248
3364
  [selectActiveReleases, selectOptions],
3249
3365
  (activeReleases, options) => {
3250
3366
  if (!options || !activeReleases) return options;
@@ -3564,7 +3680,8 @@ function createPreviewQuery(documentIds) {
3564
3680
  }
3565
3681
  const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a, b) => a.size === b.size && Array.from(a).every((i) => b.has(i)), subscribeToStateAndFetchBatches$1 = ({
3566
3682
  state,
3567
- instance
3683
+ instance,
3684
+ key: { projectId, dataset }
3568
3685
  }) => state.observable.pipe(
3569
3686
  map(({ subscriptions }) => new Set(Object.keys(subscriptions))),
3570
3687
  distinctUntilChanged(isSetEqual$1),
@@ -3592,14 +3709,18 @@ const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a, b) => a.size === b.size &&
3592
3709
  query,
3593
3710
  params,
3594
3711
  tag: PREVIEW_TAG,
3595
- perspective: PREVIEW_PERSPECTIVE
3712
+ perspective: PREVIEW_PERSPECTIVE,
3713
+ projectId,
3714
+ dataset
3596
3715
  }), subscription = defer(() => getCurrent() === void 0 ? from(
3597
3716
  resolveQuery(instance, {
3598
3717
  query,
3599
3718
  params,
3600
3719
  tag: PREVIEW_TAG,
3601
3720
  perspective: PREVIEW_PERSPECTIVE,
3602
- signal: controller.signal
3721
+ signal: controller.signal,
3722
+ projectId,
3723
+ dataset
3603
3724
  })
3604
3725
  ).pipe(switchMap(() => observable)) : observable).pipe(filter((result) => result !== void 0)).subscribe(observer);
3605
3726
  return () => {
@@ -3609,8 +3730,8 @@ const BATCH_DEBOUNCE_TIME$1 = 50, isSetEqual$1 = (a, b) => a.size === b.size &&
3609
3730
  }),
3610
3731
  map(({ ids, data }) => ({
3611
3732
  values: processPreviewQuery({
3612
- projectId: instance.config.projectId,
3613
- dataset: instance.config.dataset,
3733
+ projectId,
3734
+ dataset,
3614
3735
  ids,
3615
3736
  results: data
3616
3737
  })
@@ -3727,7 +3848,8 @@ function processProjectionQuery({ ids, results }) {
3727
3848
  }
3728
3849
  const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Array.from(a).every((i) => b.has(i)), subscribeToStateAndFetchBatches = ({
3729
3850
  state,
3730
- instance
3851
+ instance,
3852
+ key: { projectId, dataset }
3731
3853
  }) => {
3732
3854
  const documentProjections$ = state.observable.pipe(
3733
3855
  map((s) => s.documentProjections),
@@ -3770,12 +3892,16 @@ const BATCH_DEBOUNCE_TIME = 50, isSetEqual = (a, b) => a.size === b.size && Arra
3770
3892
  const { getCurrent, observable } = getQueryState(instance, {
3771
3893
  query,
3772
3894
  params,
3895
+ projectId,
3896
+ dataset,
3773
3897
  tag: PROJECTION_TAG,
3774
3898
  perspective: PROJECTION_PERSPECTIVE
3775
3899
  }), subscription = defer(() => getCurrent() === void 0 ? from(
3776
3900
  resolveQuery(instance, {
3777
3901
  query,
3778
3902
  params,
3903
+ projectId,
3904
+ dataset,
3779
3905
  tag: PROJECTION_TAG,
3780
3906
  perspective: PROJECTION_PERSPECTIVE,
3781
3907
  signal: controller.signal
@@ -3915,12 +4041,12 @@ const _resolveProjection = bindActionByDataset(
3915
4041
  });
3916
4042
  })
3917
4043
  )
3918
- }), getProjectsState = projects.getState, resolveProjects = projects.resolveState, WILDCARD_TOKEN = "*", NEGATION_TOKEN = "-", TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
4044
+ }), getProjectsState = projects.getState, resolveProjects = projects.resolveState, TOKEN_REGEX = /(?:[^\s"]+|"[^"]*")+/g;
3919
4045
  function isNegationToken(token) {
3920
- return typeof token < "u" && token.trim().startsWith(NEGATION_TOKEN);
4046
+ return typeof token < "u" && token.trim().startsWith("-");
3921
4047
  }
3922
4048
  function isPrefixToken(token) {
3923
- return typeof token < "u" && token.trim().endsWith(WILDCARD_TOKEN);
4049
+ return typeof token < "u" && token.trim().endsWith("*");
3924
4050
  }
3925
4051
  function isExactMatchToken(token) {
3926
4052
  return !!token && token.length >= 2 && token.startsWith('"') && token.endsWith('"');
@@ -3935,7 +4061,7 @@ function createGroqSearchFilter(query) {
3935
4061
  return finalIncrementalToken !== void 0 && !isPrefixToken(finalIncrementalToken) && processedTokens.splice(
3936
4062
  finalIncrementalTokenIndex,
3937
4063
  1,
3938
- `${finalIncrementalToken}${WILDCARD_TOKEN}`
4064
+ `${finalIncrementalToken}*`
3939
4065
  ), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
3940
4066
  }
3941
4067
  function defineIntent(intent) {
@@ -3996,7 +4122,7 @@ function getCorsErrorProjectId(error) {
3996
4122
  const projMatch = (error.message || "").match(/manage\/project\/([^/?#]+)/);
3997
4123
  return projMatch ? projMatch[1] : null;
3998
4124
  }
3999
- var version = "2.4.0";
4125
+ var version = "2.5.0";
4000
4126
  const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
4001
4127
  export {
4002
4128
  AuthStateType,