@sanity/sdk 0.0.0 → 0.0.2

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
@@ -36,6 +36,8 @@ import {SanityQueryResult} from 'groq'
36
36
  import {SanityUser as SanityUser_2} from './types'
37
37
  import {StackablePerspective} from '@sanity/client'
38
38
  import {StateSource as StateSource_2} from '../_exports'
39
+ import {StateSource as StateSource_3} from '../../_exports'
40
+ import {Status} from '@sanity/comlink'
39
41
  import {StudioResource} from '@sanity/message-protocol'
40
42
  import {Subject} from 'rxjs'
41
43
  import {ValuePending as ValuePending_2} from './previewStore'
@@ -429,6 +431,7 @@ export declare interface ComlinkControllerState {
429
431
  */
430
432
  export declare interface ComlinkNodeState {
431
433
  nodes: Map<string, NodeEntry>
434
+ subscriptions: Map<string, Set<symbol>>
432
435
  }
433
436
 
434
437
  declare interface Context {
@@ -1211,6 +1214,20 @@ export declare const getFavoritesState: BoundStoreAction<
1211
1214
  */
1212
1215
  export declare const getLoginUrlState: BoundStoreAction<AuthStoreState, [], StateSource_2<string>>
1213
1216
 
1217
+ /**
1218
+ * Provides a subscribable state source for a node by name
1219
+ * @param instance - The Sanity instance to get the node state for
1220
+ * @param nodeInput - The configuration for the node to get the state for
1221
+
1222
+ * @returns A subscribable state source for the node
1223
+ * @public
1224
+ */
1225
+ export declare const getNodeState: BoundStoreAction_2<
1226
+ ComlinkNodeState,
1227
+ [NodeInput],
1228
+ StateSource_3<NodeState | undefined>
1229
+ >
1230
+
1214
1231
  /**
1215
1232
  * Retrieve or create a channel to be used for communication between
1216
1233
  * an application and the controller.
@@ -1233,18 +1250,6 @@ export declare const getOrCreateController: BoundStoreAction_2<
1233
1250
  Controller
1234
1251
  >
1235
1252
 
1236
- /**
1237
- * Retrieve or create a node to be used for communication between
1238
- * an application and the controller -- specifically, a node should
1239
- * be created within a frame / window to communicate with the controller.
1240
- * @public
1241
- */
1242
- export declare const getOrCreateNode: BoundStoreAction_2<
1243
- ComlinkNodeState,
1244
- [options: NodeInput],
1245
- Node_2<Message, Message>
1246
- >
1247
-
1248
1253
  /** @beta */
1249
1254
  export declare const getPermissionsState: BoundStoreAction<
1250
1255
  DocumentStoreState,
@@ -1634,7 +1639,16 @@ declare interface NegNode extends BaseNode {
1634
1639
  declare interface NodeEntry {
1635
1640
  node: Node_2<WindowMessage, FrameMessage>
1636
1641
  options: NodeInput
1637
- refCount: number
1642
+ status: Status
1643
+ statusUnsub?: () => void
1644
+ }
1645
+
1646
+ /**
1647
+ * @public
1648
+ */
1649
+ export declare interface NodeState {
1650
+ node: Node_2<WindowMessage, FrameMessage>
1651
+ status: Status | undefined
1638
1652
  }
1639
1653
 
1640
1654
  declare interface NotNode extends BaseNode {
@@ -1995,12 +2009,6 @@ export declare type ReleaseDocument = SanityDocument & {
1995
2009
  }
1996
2010
  }
1997
2011
 
1998
- /**
1999
- * Signals to the store that the consumer has stopped using the node
2000
- * @public
2001
- */
2002
- export declare const releaseNode: BoundStoreAction_2<ComlinkNodeState, [name: string], void>
2003
-
2004
2012
  /**
2005
2013
  * @public
2006
2014
  */
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { createClient } from "@sanity/client";
2
- import { Observable, share, map, distinctUntilChanged, skip, filter, exhaustMap, timer, from, takeWhile, switchMap, firstValueFrom, fromEvent, EMPTY, defer, asapScheduler, combineLatest, of, concatMap, withLatestFrom, concat, throwError, first as first$1, Subject, takeUntil, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, timeout, retry, NEVER, debounceTime as debounceTime$1, Subscription } from "rxjs";
2
+ import { Observable, share, map, distinctUntilChanged, skip, filter, exhaustMap, timer, from, takeWhile, switchMap, firstValueFrom, fromEvent, EMPTY, defer, asapScheduler, combineLatest, of, concatMap, withLatestFrom, concat, throwError, first as first$1, Subject, takeUntil, partition, merge, shareReplay, tap as tap$1, catchError as catchError$1, startWith as startWith$1, pairwise as pairwise$1, groupBy as groupBy$1, mergeMap as mergeMap$1, throttle, race, retry, NEVER, debounceTime as debounceTime$1, Subscription } from "rxjs";
3
3
  import { devtools } from "zustand/middleware";
4
4
  import { createStore } from "zustand/vanilla";
5
5
  import { pick, omit, isEqual, isObject } from "lodash-es";
6
6
  import { first, switchMap as switchMap$1, groupBy, mergeMap, startWith, pairwise, filter as filter$1, map as map$1, delay, tap, catchError, scan, share as share$1, take, debounceTime } from "rxjs/operators";
7
7
  import { createController, createNode } from "@sanity/comlink";
8
+ import { createSelector } from "reselect";
8
9
  import { SanityEncoder } from "@sanity/mutate";
9
10
  import { getPublishedId as getPublishedId$1 } from "@sanity/client/csm";
10
- import { createSelector } from "reselect";
11
11
  import { applyPatches, parsePatch, makePatches, stringifyPatches } from "@sanity/diff-match-patch";
12
12
  import { isKeySegment, isKeyedObject } from "@sanity/types";
13
13
  import { createDocumentLoaderFromClient } from "@sanity/mutate/_unstable_store";
@@ -894,35 +894,38 @@ const handleAuthCallback = bindActionGlobally(
894
894
  if (existing) {
895
895
  if (!isEqual(existing.options, options))
896
896
  throw new Error(`Node "${options.name}" already exists with different options`);
897
- return state.set("incrementNodeRefCount", {
898
- nodes: new Map(nodes).set(options.name, {
899
- ...existing,
900
- refCount: existing.refCount + 1
901
- })
902
- }), existing.node.start(), existing.node;
897
+ return existing.node.start(), existing.node;
903
898
  }
904
899
  const node = createNode(options);
905
- return node.start(), nodes.set(options.name, { node, options, refCount: 1 }), state.set("createNode", { nodes }), node;
900
+ node.start();
901
+ const statusUnsub = node.onStatus((status) => {
902
+ const currentNodes = state.get().nodes, currentEntry = currentNodes.get(options.name);
903
+ if (!currentEntry) return;
904
+ const updatedEntry = {
905
+ ...currentEntry,
906
+ status
907
+ };
908
+ state.set("updateNodeStatus", {
909
+ nodes: new Map(currentNodes).set(options.name, updatedEntry)
910
+ });
911
+ }), entry = {
912
+ node,
913
+ options,
914
+ status: "idle",
915
+ statusUnsub
916
+ };
917
+ return nodes.set(options.name, entry), state.set("createNode", { nodes }), node;
906
918
  }, releaseNode$1 = ({ state }, name) => {
907
919
  const nodes = state.get().nodes, existing = nodes.get(name);
908
920
  if (existing) {
909
- const newRefCount = existing.refCount - 1;
910
- if (newRefCount <= 0) {
911
- existing.node.stop(), nodes.delete(name), state.set("removeNode", { nodes });
912
- return;
913
- }
914
- state.set("decrementNodeRefCount", {
915
- nodes: new Map(nodes).set(name, {
916
- ...existing,
917
- refCount: newRefCount
918
- })
919
- });
921
+ existing.statusUnsub && existing.statusUnsub(), existing.node.stop(), nodes.delete(name), state.set("removeNode", { nodes });
920
922
  return;
921
923
  }
922
924
  }, comlinkNodeStore = {
923
925
  name: "nodeStore",
924
926
  getInitialState: () => ({
925
- nodes: /* @__PURE__ */ new Map()
927
+ nodes: /* @__PURE__ */ new Map(),
928
+ subscriptions: /* @__PURE__ */ new Map()
926
929
  }),
927
930
  initialize({ state }) {
928
931
  return () => {
@@ -931,7 +934,26 @@ const handleAuthCallback = bindActionGlobally(
931
934
  });
932
935
  };
933
936
  }
934
- }, releaseNode = bindActionGlobally(comlinkNodeStore, releaseNode$1), getOrCreateNode = bindActionGlobally(comlinkNodeStore, getOrCreateNode$1);
937
+ }, releaseNode = bindActionGlobally(comlinkNodeStore, releaseNode$1), getOrCreateNode = bindActionGlobally(comlinkNodeStore, getOrCreateNode$1), NODE_RELEASE_TIME = 5e3, selectNode = (context, nodeInput) => context.state.nodes.get(nodeInput.name), getNodeState = bindActionGlobally(
938
+ comlinkNodeStore,
939
+ createStateSourceAction({
940
+ selector: createSelector([selectNode], (nodeEntry) => nodeEntry?.status === "connected" ? {
941
+ node: nodeEntry.node,
942
+ status: nodeEntry.status
943
+ } : void 0),
944
+ onSubscribe: ({ state, instance }, nodeInput) => {
945
+ const nodeName = nodeInput.name, subscriberId = Symbol("comlink-node-subscriber");
946
+ getOrCreateNode(instance, nodeInput);
947
+ let subs = state.get().subscriptions.get(nodeName);
948
+ return subs || (subs = /* @__PURE__ */ new Set(), state.get().subscriptions.set(nodeName, subs)), subs.add(subscriberId), () => {
949
+ setTimeout(() => {
950
+ const activeSubs = state.get().subscriptions.get(nodeName);
951
+ activeSubs && (activeSubs.delete(subscriberId), activeSubs.size === 0 && (state.get().subscriptions.delete(nodeName), releaseNode(instance, nodeName)));
952
+ }, NODE_RELEASE_TIME);
953
+ };
954
+ }
955
+ })
956
+ );
935
957
  function createDocumentHandle(handle) {
936
958
  return handle;
937
959
  }
@@ -1017,7 +1039,7 @@ function discardDocument(doc) {
1017
1039
  documentId: getPublishedId(doc.documentId)
1018
1040
  };
1019
1041
  }
1020
- const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$3 = "vX";
1042
+ const DOCUMENT_STATE_CLEAR_DELAY = 1e3, INITIAL_OUTGOING_THROTTLE_TIME = 1e3, API_VERSION$3 = "v2025-05-06";
1021
1043
  function parseBracketContent(content) {
1022
1044
  const rangeMatch = content.match(/^(\d*):(\d*)$/);
1023
1045
  if (rangeMatch) {
@@ -4114,7 +4136,7 @@ function getDocumentEvents(outgoing) {
4114
4136
  )
4115
4137
  );
4116
4138
  }
4117
- const API_VERSION$2 = "vX";
4139
+ const API_VERSION$2 = "v2025-05-06";
4118
4140
  function createSharedListener(instance) {
4119
4141
  const dispose$ = new Subject(), events$ = getClientState(instance, {
4120
4142
  apiVersion: API_VERSION$2
@@ -4441,7 +4463,6 @@ async function _applyDocumentActions({ instance, state }, actionOrActions, { tra
4441
4463
  submitted
4442
4464
  };
4443
4465
  }
4444
- const FAVORITES_FETCH_TIMEOUT = 3e3;
4445
4466
  function createFavoriteKey(context) {
4446
4467
  return `${context.documentId}:${context.documentType}:${context.resourceId}:${context.resourceType}${context.schemaName ? `:${context.schemaName}` : ""}`;
4447
4468
  }
@@ -4449,7 +4470,7 @@ const favorites = createFetcherStore({
4449
4470
  name: "Favorites",
4450
4471
  getKey: (_instance, context) => createFavoriteKey(context),
4451
4472
  fetcher: (instance) => (context) => {
4452
- const node = getOrCreateNode(instance, {
4473
+ const nodeStateSource = getNodeState(instance, {
4453
4474
  name: SDK_NODE_NAME,
4454
4475
  connectTo: SDK_CHANNEL_NAME
4455
4476
  }), payload = {
@@ -4462,28 +4483,25 @@ const favorites = createFetcherStore({
4462
4483
  schemaName: context.schemaName
4463
4484
  }
4464
4485
  }
4465
- }, dashboardFetch = from(
4466
- node.fetch(
4467
- // @ts-expect-error -- getOrCreateNode should be refactored to take type arguments
4468
- "dashboard/v1/events/favorite/query",
4469
- payload
4470
- )
4471
- ).pipe(
4472
- timeout({
4473
- first: FAVORITES_FETCH_TIMEOUT,
4474
- with: () => throwError(() => new Error("Favorites service connection timeout"))
4475
- }),
4476
- map((response) => ({ isFavorited: response.isFavorited })),
4477
- catchError$1((err) => (console.error("Favorites service connection error", err), of({ isFavorited: !1 }))),
4478
- // Share the same subscription between multiple subscribers
4479
- shareReplay(1)
4486
+ };
4487
+ return nodeStateSource.observable.pipe(
4488
+ filter((nodeState) => !!nodeState),
4489
+ // Only proceed when connected
4490
+ shareReplay(1),
4491
+ switchMap((nodeState) => {
4492
+ const node = nodeState.node;
4493
+ return from(
4494
+ node.fetch(
4495
+ // @ts-expect-error -- getOrCreateNode should be refactored to take type arguments
4496
+ "dashboard/v1/events/favorite/query",
4497
+ payload
4498
+ )
4499
+ ).pipe(
4500
+ map((response) => ({ isFavorited: response.isFavorited })),
4501
+ catchError$1((err) => (console.error("Favorites service connection error", err), of({ isFavorited: !1 })))
4502
+ );
4503
+ })
4480
4504
  );
4481
- return new Observable((subscriber) => {
4482
- const subscription = dashboardFetch.subscribe(subscriber);
4483
- return () => {
4484
- subscription.unsubscribe(), subscription.closed && releaseNode(instance, SDK_NODE_NAME);
4485
- };
4486
- });
4487
4505
  }
4488
4506
  }), getFavoritesState = favorites.getState, resolveFavoritesState = favorites.resolveState, fetch = (client, query, params, options) => defer(
4489
4507
  () => client.observable.fetch(query, params, {
@@ -4608,7 +4626,7 @@ const DEFAULT_PERSPECTIVE = "drafts", optionsCache = /* @__PURE__ */ new Map(),
4608
4626
  }
4609
4627
  )
4610
4628
  })
4611
- ), QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "vX", setQueryError = (key, error) => (prev) => {
4629
+ ), QUERY_STATE_CLEAR_DELAY = 1e3, QUERY_STORE_API_VERSION = "v2025-05-06", setQueryError = (key, error) => (prev) => {
4612
4630
  const prevQuery = prev.queries[key];
4613
4631
  return prevQuery ? { ...prev, queries: { ...prev.queries, [key]: { ...prevQuery, error } } } : prev;
4614
4632
  }, setQueryData = (key, result, syncTags) => (prev) => {
@@ -5387,7 +5405,7 @@ function createGroqSearchFilter(query) {
5387
5405
  `${finalIncrementalToken}${WILDCARD_TOKEN}`
5388
5406
  ), `[@] match text::query("${processedTokens.join(" ").replace(/"/g, '\\"')}")`;
5389
5407
  }
5390
- var version = "0.0.0";
5408
+ var version = "0.0.2";
5391
5409
  const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
5392
5410
  export {
5393
5411
  AuthStateType,
@@ -5415,9 +5433,9 @@ export {
5415
5433
  getDocumentSyncStatus,
5416
5434
  getFavoritesState,
5417
5435
  getLoginUrlState,
5436
+ getNodeState,
5418
5437
  getOrCreateChannel,
5419
5438
  getOrCreateController,
5420
- getOrCreateNode,
5421
5439
  getPermissionsState,
5422
5440
  getPerspectiveState,
5423
5441
  getPreviewState,
@@ -5438,7 +5456,6 @@ export {
5438
5456
  parseUsersKey,
5439
5457
  publishDocument,
5440
5458
  releaseChannel,
5441
- releaseNode,
5442
5459
  resolveDatasets,
5443
5460
  resolveDocument,
5444
5461
  resolveFavoritesState,