@sanity/sdk 0.0.0-alpha.16 → 0.0.0-alpha.17

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
@@ -20,7 +20,6 @@ import {SanityClient} from '@sanity/client'
20
20
  import {SanityDocument} from '@sanity/types'
21
21
  import {SanityDocumentLike} from '@sanity/types'
22
22
  import {SanityProject as SanityProject_2} from '@sanity/client'
23
- import {SchemaTypeDefinition} from '@sanity/types'
24
23
  import {Subject} from 'rxjs'
25
24
 
26
25
  declare interface AccessAttributeNode extends BaseNode {
@@ -303,6 +302,7 @@ export declare interface AuthStoreState {
303
302
  callbackUrl: string | undefined
304
303
  providedToken: string | undefined
305
304
  }
305
+ dashboardContext?: DashboardContext
306
306
  }
307
307
 
308
308
  /** The base interface for SyntaxNode. */
@@ -481,6 +481,17 @@ export declare const createUsersStore: (instance: SanityInstance | ActionContext
481
481
 
482
482
  export {CurrentUser}
483
483
 
484
+ /**
485
+ * Represents the various states the authentication can be in.
486
+ *
487
+ * @public
488
+ */
489
+ declare interface DashboardContext {
490
+ mode?: string
491
+ env?: string
492
+ orgId?: string | object
493
+ }
494
+
484
495
  declare class DateTime {
485
496
  date: Date
486
497
  constructor(date: Date)
@@ -1524,6 +1535,17 @@ declare interface PosNode extends BaseNode {
1524
1535
  base: ExprNode
1525
1536
  }
1526
1537
 
1538
+ /**
1539
+ * Represents a media asset in a preview.
1540
+ *
1541
+ * @public
1542
+ */
1543
+ declare interface PreviewMedia {
1544
+ type: 'image-asset'
1545
+ _ref: string
1546
+ url: string
1547
+ }
1548
+
1527
1549
  /**
1528
1550
  * @public
1529
1551
  */
@@ -1561,10 +1583,7 @@ export declare interface PreviewValue {
1561
1583
  * An optional piece of media representing the document within its preview.
1562
1584
  * Currently, only image assets are available.
1563
1585
  */
1564
- media?: {
1565
- type: 'image-asset'
1566
- url: string
1567
- } | null
1586
+ media?: PreviewMedia | null
1568
1587
  /**
1569
1588
  * The status of the document.
1570
1589
  */
@@ -1818,7 +1837,6 @@ export declare interface SanityConfig {
1818
1837
  projectId: string
1819
1838
  dataset: string
1820
1839
  auth?: AuthConfig
1821
- schema?: SchemaConfig
1822
1840
  }
1823
1841
 
1824
1842
  export {SanityDocument}
@@ -1859,13 +1877,6 @@ declare interface SanityUserResponse {
1859
1877
  nextCursor: string | null
1860
1878
  }
1861
1879
 
1862
- /**
1863
- * @public
1864
- */
1865
- export declare interface SchemaConfig {
1866
- types: SchemaTypeDefinition[]
1867
- }
1868
-
1869
1880
  declare class Scope {
1870
1881
  params: Record<string, unknown>
1871
1882
  source: Value
package/dist/index.js CHANGED
@@ -3,8 +3,7 @@ import { devtools } from "zustand/middleware";
3
3
  import { createStore as createStore$1 } from "zustand/vanilla";
4
4
  import { createClient } from "@sanity/client";
5
5
  import { createSelector } from "reselect";
6
- import { noop, omit, isEqual } from "lodash-es";
7
- import { Schema } from "@sanity/schema";
6
+ import { noop, omit, isObject, isEqual } from "lodash-es";
8
7
  import { createController, createNode } from "@sanity/comlink";
9
8
  import { SanityEncoder } from "@sanity/mutate";
10
9
  import { getPublishedId as getPublishedId$1 } from "@sanity/client/csm";
@@ -583,13 +582,13 @@ function generateArrayKey(length = 12) {
583
582
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("").slice(0, length);
584
583
  }
585
584
  function memoize(fn) {
586
- const cache2 = /* @__PURE__ */ new WeakMap();
585
+ const cache = /* @__PURE__ */ new WeakMap();
587
586
  return (input) => {
588
587
  if (!input || typeof input != "object") return fn(input);
589
- const cached = cache2.get(input);
588
+ const cached = cache.get(input);
590
589
  if (cached) return cached;
591
590
  const result = fn(input);
592
- return cache2.set(input, result), result;
591
+ return cache.set(input, result), result;
593
592
  };
594
593
  }
595
594
  const ensureArrayKeysDeep = memoize((input) => {
@@ -890,8 +889,18 @@ const DEFAULT_API_VERSION = "2024-11-12", DEFAULT_REQUEST_TAG_PREFIX = "sanity.s
890
889
  if (authState.type === AuthStateType.LOGGING_IN && authState.isExchangingToken) return !1;
891
890
  const authCode = getAuthCode(callbackUrl, locationHref);
892
891
  if (!authCode) return !1;
892
+ const parsedUrl = new URL(locationHref);
893
+ let dashboardContext = {};
894
+ try {
895
+ const contextParam = parsedUrl.searchParams.get("_context") ?? "{}";
896
+ dashboardContext = JSON.parse(contextParam);
897
+ } catch (err) {
898
+ console.error("Failed to parse dashboard context:", err);
899
+ }
900
+ const { mode, env, orgId } = dashboardContext;
893
901
  state.set("exchangeSessionForToken", {
894
- authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !0 }
902
+ authState: { type: AuthStateType.LOGGING_IN, isExchangingToken: !0 },
903
+ dashboardContext: { mode, env, orgId }
895
904
  });
896
905
  try {
897
906
  const client = clientFactory({
@@ -935,16 +944,7 @@ const DEFAULT_API_VERSION = "2024-11-12", DEFAULT_REQUEST_TAG_PREFIX = "sanity.s
935
944
  }), storageArea?.removeItem(storageKey);
936
945
  }
937
946
  };
938
- }), schemaManager = {
939
- name: "schemaManager",
940
- getInitialState(instance) {
941
- const { config } = instance;
942
- return { schema: Schema.compile({
943
- name: "default",
944
- types: config.schema?.types ?? []
945
- }) };
946
- }
947
- };
947
+ });
948
948
  function createLiveEventSubscriber(tag) {
949
949
  return createInternalAction(({ instance, state }) => {
950
950
  const client$ = getClientState(instance, { apiVersion: "vX" }).observable, syncTags$ = state.observable.pipe(
@@ -972,73 +972,37 @@ function createLiveEventSubscriber(tag) {
972
972
  };
973
973
  });
974
974
  }
975
- const getSchemaState = createStateSourceAction(schemaManager, (state) => state.schema);
976
975
  function hashString(str) {
977
976
  let hash = 0;
978
977
  for (let i2 = 0; i2 < str.length; i2++)
979
978
  hash = (hash * 31 + str.charCodeAt(i2)) % 2147483647;
980
979
  return Math.abs(hash).toString(16).padStart(8, "0");
981
980
  }
982
- function getProjectionForSchemaType(schema, schemaTypeName) {
983
- const schemaType = schema.get(schemaTypeName);
984
- if (!schemaType)
985
- throw new Error(`Could not find type \`${schemaTypeName}\` in the provided schema.`);
986
- return `{${Object.entries(schemaType.preview?.select ?? {}).map(([key, path]) => `${JSON.stringify(key)}:${getGroqFromPath(schema, schemaType, path)}`).join(",")}}`;
987
- }
988
- function isReferenceType(type, visited = /* @__PURE__ */ new Set()) {
989
- return !type || visited.has(type) ? !1 : (visited.add(type), type.name === "reference" ? !0 : isReferenceType(type.type, visited));
990
- }
991
- function printPath(segments) {
992
- return segments.reduce((acc, segment) => segment.type === "deref" ? `${acc}->` : segment.type === "element" ? `${acc}[${segment.index}]` : acc.endsWith("->") ? `${acc}${segment.name}` : [acc, segment.name].filter(Boolean).join("."), "");
993
- }
994
- const cache = /* @__PURE__ */ new WeakMap();
995
- function getGroqFromPath(schema, node, path) {
996
- const cached = cache.get(node)?.get(path);
997
- if (cached) return cached;
998
- const possiblePaths = Array.from(
999
- new Set(resolveAllPaths(schema, node, path.split(".")).map(printPath))
1000
- );
1001
- if (!possiblePaths.length)
1002
- return console.warn(`Could not resolve path \`${path}\` from schema type \`${node.name}\`.`), "null";
1003
- const result = possiblePaths.length === 1 ? possiblePaths[0] : `coalesce(${possiblePaths.join(",")})`;
1004
- return cache.has(node) || cache.set(node, /* @__PURE__ */ new Map()), cache.get(node).set(path, result), result;
1005
- }
1006
- function resolveAllPaths(schema, schemaType, path) {
1007
- const [name, ...rest] = path;
1008
- if (name?.startsWith("_"))
1009
- return [
1010
- [
1011
- { type: "attribute", name },
1012
- ...rest.map(
1013
- (next) => /\d+/.test(next) ? { type: "element", index: parseInt(next, 10) } : { type: "attribute", name: next }
1014
- )
1015
- ]
1016
- ];
1017
- if (name) {
1018
- if (isReferenceType(schemaType))
1019
- return schemaType.to.flatMap(
1020
- (referenceType) => resolveAllPaths(schema, referenceType, path).map((nextPath) => [
1021
- { type: "deref" },
1022
- ...nextPath
1023
- ])
1024
- );
1025
- if (schemaType.jsonType === "object") {
1026
- const fieldType = schemaType.fields.find((field) => field.name === name)?.type;
1027
- return fieldType ? resolveAllPaths(schema, fieldType, rest).map((nextPath) => [
1028
- { type: "attribute", name },
1029
- ...nextPath
1030
- ]) : [];
1031
- } else if (schemaType.jsonType === "array") {
1032
- const index = parseInt(name, 10);
1033
- return schemaType.of.flatMap(
1034
- (itemType) => resolveAllPaths(schema, itemType, rest).map((nextPath) => [
1035
- { type: "element", index },
1036
- ...nextPath
1037
- ])
1038
- );
1039
- } else
1040
- return [];
1041
- } else return [[]];
981
+ const TITLE_CANDIDATES = ["title", "name", "label", "heading", "header", "caption"], SUBTITLE_CANDIDATES = ["description", "subtitle", ...TITLE_CANDIDATES];
982
+ function getPreviewProjection() {
983
+ return `{
984
+ // Get all potential title fields
985
+ "titleCandidates": {
986
+ ${TITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
987
+ `)}
988
+ },
989
+ // Get all potential subtitle fields
990
+ "subtitleCandidates": {
991
+ ${SUBTITLE_CANDIDATES.map((field) => `"${field}": ${field}`).join(`,
992
+ `)}
993
+ },
994
+ "media": coalesce(
995
+ select(
996
+ defined(asset) => {"type": "image-asset", "_ref": asset._ref},
997
+ defined(image.asset) => {"type": "image-asset", "_ref": image.asset._ref},
998
+ defined(mainImage.asset) => {"type": "image-asset", "_ref": mainImage.asset._ref},
999
+ null
1000
+ )
1001
+ ),
1002
+ _type,
1003
+ _id,
1004
+ _updatedAt
1005
+ }`;
1042
1006
  }
1043
1007
  const PREVIEW_TAG = "preview", STABLE_EMPTY_PREVIEW = { results: null, isPending: !1 }, STABLE_ERROR_PREVIEW = {
1044
1008
  results: {
@@ -1047,13 +1011,6 @@ const PREVIEW_TAG = "preview", STABLE_EMPTY_PREVIEW = { results: null, isPending
1047
1011
  },
1048
1012
  isPending: !1
1049
1013
  };
1050
- function defaultPrepare(value) {
1051
- let title, subtitle;
1052
- return "title" in value && typeof value.title == "string" && (title = value.title), "subtitle" in value && typeof value.subtitle == "string" && (subtitle = value.subtitle), { title: title ?? "Untitled", subtitle };
1053
- }
1054
- function hasImageAsset(value) {
1055
- return typeof value == "object" && value !== null && "asset" in value && typeof value.asset == "object" && typeof value.asset?._ref == "string";
1056
- }
1057
1014
  function assetIdToUrl(assetId, projectId, dataset) {
1058
1015
  const pattern = /^image-(?<assetName>[A-Za-z0-9]+)-(?<dimensions>\d+x\d+)-(?<format>[a-z]+)$/, match = assetId.match(pattern);
1059
1016
  if (!match?.groups)
@@ -1063,53 +1020,43 @@ function assetIdToUrl(assetId, projectId, dataset) {
1063
1020
  const { assetName, dimensions, format } = match.groups;
1064
1021
  return `https://cdn.sanity.io/images/${projectId}/${dataset}/${assetName}-${dimensions}.${format}`;
1065
1022
  }
1023
+ function hasImageRef(value) {
1024
+ return isObject(value) && "_ref" in value && typeof value._ref == "string";
1025
+ }
1066
1026
  function normalizeMedia(media, projectId, dataset) {
1067
- return !media || !hasImageAsset(media) ? null : { type: "image-asset", url: assetIdToUrl(media.asset._ref, projectId, dataset) };
1027
+ return !media || !hasImageRef(media) ? null : {
1028
+ type: "image-asset",
1029
+ _ref: media._ref,
1030
+ url: assetIdToUrl(media._ref, projectId, dataset)
1031
+ };
1068
1032
  }
1069
- function preparePreviewForSchemaType({
1070
- projectId,
1071
- dataset,
1072
- schema,
1073
- schemaTypeName,
1074
- selectResult
1075
- }) {
1076
- const schemaType = schema.get(schemaTypeName);
1077
- if (!schemaType)
1078
- throw new Error(
1079
- `Could not find schema type \`${schemaTypeName}\` in schema \`${schema.name}\`.`
1080
- );
1081
- const prepare = schemaType.preview?.prepare ?? defaultPrepare;
1082
- try {
1083
- const result = prepare(selectResult);
1084
- return { ...result, media: normalizeMedia(result.media, projectId, dataset) };
1085
- } catch (e3) {
1086
- const message = typeof e3 == "object" && e3 && "message" in e3 && typeof e3.message == "string" ? e3.message : "Unknown error.";
1087
- throw new Error(`Failed to prepare preview: ${message}`, { cause: e3 });
1088
- }
1033
+ function findFirstDefined(fieldsToSearch, candidates, exclude) {
1034
+ if (candidates)
1035
+ for (const field of fieldsToSearch) {
1036
+ const value = candidates[field];
1037
+ if (typeof value == "string" && value.trim() !== "" && value !== exclude)
1038
+ return value;
1039
+ }
1089
1040
  }
1090
1041
  function processPreviewQuery({
1091
1042
  projectId,
1092
1043
  dataset,
1093
- schema,
1094
1044
  ids,
1095
- documentTypes,
1096
1045
  results
1097
1046
  }) {
1098
1047
  const resultMap = results.reduce((acc, next) => (acc[next._id] = next, acc), {});
1099
1048
  return Object.fromEntries(
1100
1049
  Array.from(ids).map((id) => {
1101
- const publishedId = getPublishedId(id), draftId = getDraftId(id), draftResult = resultMap[draftId], publishedResult = resultMap[publishedId], documentType = documentTypes[publishedId];
1102
- if (!documentType) return [id, STABLE_EMPTY_PREVIEW];
1103
- const selectResult = draftResult?.select ?? publishedResult?.select;
1104
- if (!selectResult) return [id, STABLE_EMPTY_PREVIEW];
1050
+ const publishedId = getPublishedId(id), draftId = getDraftId(id), draftResult = resultMap[draftId], publishedResult = resultMap[publishedId];
1051
+ if (!draftResult && !publishedResult) return [id, STABLE_EMPTY_PREVIEW];
1105
1052
  try {
1106
- const preview = preparePreviewForSchemaType({
1107
- projectId,
1108
- dataset,
1109
- schema,
1110
- schemaTypeName: documentType,
1111
- selectResult
1112
- }), status = {
1053
+ const result = draftResult || publishedResult;
1054
+ if (!result) return [id, STABLE_EMPTY_PREVIEW];
1055
+ const title = findFirstDefined(TITLE_CANDIDATES, result.titleCandidates), subtitle = findFirstDefined(SUBTITLE_CANDIDATES, result.subtitleCandidates, title), preview = {
1056
+ title: String(title || `${result._type}: ${result._id}`),
1057
+ subtitle: subtitle || void 0,
1058
+ media: normalizeMedia(result.media, projectId, dataset)
1059
+ }, status = {
1113
1060
  ...draftResult?._updatedAt && { lastEditedDraftAt: draftResult._updatedAt },
1114
1061
  ...publishedResult?._updatedAt && { lastEditedPublishedAt: publishedResult._updatedAt }
1115
1062
  };
@@ -1120,37 +1067,18 @@ function processPreviewQuery({
1120
1067
  })
1121
1068
  );
1122
1069
  }
1123
- function createPreviewQuery(documentIds, documentTypes, schema) {
1124
- const documentIdsByDocumentType = Array.from(documentIds).reduce(
1125
- (acc, id) => {
1126
- const documentType = documentTypes[id];
1127
- if (!documentType) return acc;
1128
- const ids = acc[documentType] ?? /* @__PURE__ */ new Set();
1129
- return ids.add(id), acc[documentType] = ids, acc;
1130
- },
1131
- {}
1132
- ), projections = Object.keys(documentIdsByDocumentType).map((documentType) => {
1133
- const projection = getProjectionForSchemaType(schema, documentType), projectionHash = hashString(projection);
1134
- return { documentType, projection, projectionHash };
1135
- }).reduce((acc, { documentType, projection, projectionHash }) => {
1136
- const obj = acc[projectionHash] ?? { documentTypes: /* @__PURE__ */ new Set(), projection };
1137
- return obj.documentTypes.add(documentType), acc[projectionHash] = obj, acc;
1138
- }, {}), query = `[${Object.entries(projections).map(([projectionHash, { projection }]) => `...*[_id in $__ids_${projectionHash}]{_id,_type,_updatedAt,"select":${projection}}`).join(",")}]`, params = Object.fromEntries(
1139
- Object.entries(projections).map(([projectionHash, value]) => {
1140
- const idsInProjection = Array.from(
1141
- Array.from(value.documentTypes).map((documentType) => documentIdsByDocumentType[documentType] ?? /* @__PURE__ */ new Set()).reduce((acc, next) => {
1142
- for (const i2 of next) acc.add(i2);
1143
- return acc;
1144
- }, /* @__PURE__ */ new Set())
1145
- ).flatMap((id) => [getPublishedId(id), getDraftId(id)]);
1146
- return [`__ids_${projectionHash}`, Array.from(idsInProjection)];
1147
- })
1148
- );
1149
- return { query, params };
1070
+ function createPreviewQuery(documentIds) {
1071
+ const allIds = Array.from(documentIds).flatMap((id) => [getPublishedId(id), getDraftId(id)]), projection = getPreviewProjection(), queryHash = hashString(projection);
1072
+ return {
1073
+ query: `*[_id in $__ids_${queryHash}]${projection}`,
1074
+ params: {
1075
+ [`__ids_${queryHash}`]: allIds
1076
+ }
1077
+ };
1150
1078
  }
1151
1079
  const BATCH_DEBOUNCE_TIME$1 = 50, subscribeToStateAndFetchBatches$1 = createInternalAction(
1152
1080
  ({ state, instance }) => function() {
1153
- const client$ = getClientState(instance, { apiVersion: "vX" }).observable, schema$ = getSchemaState(instance).observable, documentTypes$ = state.observable.pipe(
1081
+ const client$ = getClientState(instance, { apiVersion: "vX" }).observable, documentTypes$ = state.observable.pipe(
1154
1082
  map((i2) => i2.documentTypes),
1155
1083
  distinctUntilChanged()
1156
1084
  ), lastLiveEventId$ = state.observable.pipe(
@@ -1177,27 +1105,25 @@ const BATCH_DEBOUNCE_TIME$1 = 50, subscribeToStateAndFetchBatches$1 = createInte
1177
1105
  withLatestFrom(documentTypes$),
1178
1106
  map(([[, ids], documentTypes]) => ({ ids, documentTypes }))
1179
1107
  );
1180
- return combineLatest([newSubscriberIds$, lastLiveEventId$, client$, schema$]).pipe(
1181
- switchMap$1(([{ ids, documentTypes }, lastLiveEventId, client, schema]) => {
1108
+ return combineLatest([newSubscriberIds$, lastLiveEventId$, client$]).pipe(
1109
+ switchMap$1(([{ ids }, lastLiveEventId, client]) => {
1182
1110
  if (!ids.size) return EMPTY;
1183
- const { query, params } = createPreviewQuery(ids, documentTypes, schema);
1111
+ const { query, params } = createPreviewQuery(ids);
1184
1112
  return client.observable.fetch(query, params, {
1185
1113
  filterResponse: !1,
1186
1114
  returnQuery: !1,
1187
1115
  perspective: "drafts",
1188
1116
  tag: PREVIEW_TAG,
1189
1117
  lastLiveEventId
1190
- }).pipe(map((response) => ({ ...response, ids, schema, documentTypes })));
1118
+ }).pipe(map((response) => ({ ...response, ids })));
1191
1119
  }),
1192
- map(({ ids, result, syncTags, documentTypes, schema }) => ({
1120
+ map(({ ids, result, syncTags }) => ({
1193
1121
  syncTags,
1194
1122
  values: processPreviewQuery({
1195
1123
  projectId: instance.identity.projectId,
1196
1124
  dataset: instance.identity.dataset,
1197
1125
  ids,
1198
- documentTypes,
1199
- results: result,
1200
- schema
1126
+ results: result
1201
1127
  })
1202
1128
  }))
1203
1129
  ).subscribe({
@@ -4916,7 +4842,7 @@ const _resolveQuery = createAction(queryStore, ({ state }) => function(query, {
4916
4842
  );
4917
4843
  return firstValueFrom(race([resolved$, aborted$]));
4918
4844
  });
4919
- var version = "0.0.0-alpha.16";
4845
+ var version = "0.0.0-alpha.17";
4920
4846
  const CORE_SDK_VERSION = getEnv("PKG_VERSION") || `${version}-development`;
4921
4847
  export {
4922
4848
  AuthStateType,