@sanity/client 6.28.4-beta.1 → 6.28.4-resources.4

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.
@@ -2015,8 +2015,8 @@
2015
2015
  }
2016
2016
  function shouldRetry(err, attempt, options) {
2017
2017
  if (options.maxRetries === 0) return false;
2018
- const isSafe = options.method === "GET" || options.method === "HEAD", isQuery = (options.uri || options.url).startsWith("/data/query"), isRetriableResponse = err.response && (err.response.statusCode === 429 || err.response.statusCode === 502 || err.response.statusCode === 503);
2019
- return (isSafe || isQuery) && isRetriableResponse ? true : P.shouldRetry(err, attempt, options);
2018
+ const isSafe = options.method === "GET" || options.method === "HEAD", isQuery2 = (options.uri || options.url).startsWith("/data/query"), isRetriableResponse = err.response && (err.response.statusCode === 429 || err.response.statusCode === 502 || err.response.statusCode === 503);
2019
+ return (isSafe || isQuery2) && isRetriableResponse ? true : P.shouldRetry(err, attempt, options);
2020
2020
  }
2021
2021
  const BASE_URL = "https://www.sanity.io/help/";
2022
2022
  function generateHelpUrl(slug) {
@@ -2063,6 +2063,26 @@
2063
2063
  "Tag can only contain alphanumeric characters, underscores, dashes and dots, and be between one and 75 characters long."
2064
2064
  );
2065
2065
  return tag;
2066
+ }, resourceConfig = (config) => {
2067
+ if (!config["~experimental_resource"])
2068
+ throw new Error("`resource` must be provided to perform resource queries");
2069
+ const { type, id } = config["~experimental_resource"];
2070
+ switch (type) {
2071
+ case "dataset": {
2072
+ if (id.split(".").length !== 2)
2073
+ throw new Error('Dataset resource ID must be in the format "project.dataset"');
2074
+ return;
2075
+ }
2076
+ case "dashboard":
2077
+ case "media-library":
2078
+ case "canvas":
2079
+ return;
2080
+ default:
2081
+ throw new Error(`Unsupported resource type: ${type.toString()}`);
2082
+ }
2083
+ }, resourceGuard = (service, config) => {
2084
+ if (config["~experimental_resource"])
2085
+ throw new Error(`\`${service}\` does not support resource-based operations`);
2066
2086
  };
2067
2087
  function once(fn) {
2068
2088
  let didCall = false, returnValue;
@@ -2109,21 +2129,11 @@
2109
2129
  if (!(/^\d{4}-\d{2}-\d{2}$/.test(apiVersion) && apiDate instanceof Date && apiDate.getTime() > 0))
2110
2130
  throw new Error("Invalid API version string, expected `1` or date in format `YYYY-MM-DD`");
2111
2131
  }
2112
- const VALID_PERSPECTIVE = /^[a-z0-9_]+$/i;
2113
2132
  function validateApiPerspective(perspective) {
2114
- if (Array.isArray(perspective) && perspective.includes("raw"))
2133
+ if (Array.isArray(perspective) && perspective.length > 1 && perspective.includes("raw"))
2115
2134
  throw new TypeError(
2116
2135
  'Invalid API perspective value: "raw". The raw-perspective can not be combined with other perspectives'
2117
2136
  );
2118
- const invalid = (Array.isArray(perspective) ? perspective : [perspective]).filter(
2119
- (perspectiveName) => typeof perspectiveName != "string" || !VALID_PERSPECTIVE.test(perspectiveName)
2120
- );
2121
- if (invalid.length > 0) {
2122
- const formatted = invalid.map((v) => JSON.stringify(v));
2123
- throw new TypeError(
2124
- `Invalid API perspective value${invalid.length === 1 ? "" : "s"}: ${formatted.join(", ")}, expected \`published\`, \`drafts\`, \`raw\` or a release identifier string`
2125
- );
2126
- }
2127
2137
  }
2128
2138
  const initConfig = (config, prevConfig) => {
2129
2139
  const specifiedConfig = {
@@ -2138,14 +2148,14 @@
2138
2148
  const newConfig = {
2139
2149
  ...defaultConfig,
2140
2150
  ...specifiedConfig
2141
- }, projectBased = newConfig.useProjectHostname;
2151
+ }, projectBased = newConfig.useProjectHostname && !newConfig["~experimental_resource"];
2142
2152
  if (typeof Promise > "u") {
2143
2153
  const helpUrl = generateHelpUrl("js-client-promise-polyfill");
2144
2154
  throw new Error(`No native Promise-implementation found, polyfill needed - see ${helpUrl}`);
2145
2155
  }
2146
2156
  if (projectBased && !newConfig.projectId)
2147
2157
  throw new Error("Configuration must contain `projectId`");
2148
- if (typeof newConfig.perspective < "u" && validateApiPerspective(newConfig.perspective), "encodeSourceMap" in newConfig)
2158
+ if (newConfig["~experimental_resource"] && resourceConfig(newConfig), typeof newConfig.perspective < "u" && validateApiPerspective(newConfig.perspective), "encodeSourceMap" in newConfig)
2149
2159
  throw new Error(
2150
2160
  "It looks like you're using options meant for '@sanity/preview-kit/client'. 'encodeSourceMap' is not supported in '@sanity/client'. Did you mean 'stega.enabled'?"
2151
2161
  );
@@ -2164,7 +2174,7 @@
2164
2174
  const isBrowser = typeof window < "u" && window.location && window.location.hostname, isLocalhost = isBrowser && isLocal(window.location.hostname), hasToken = !!newConfig.token;
2165
2175
  newConfig.withCredentials && hasToken && (printCredentialedTokenWarning(), newConfig.withCredentials = false), isBrowser && isLocalhost && hasToken && newConfig.ignoreBrowserTokenWarning !== true ? printBrowserTokenWarning() : typeof newConfig.useCdn > "u" && printCdnWarning(), projectBased && projectId(newConfig.projectId), newConfig.dataset && dataset(newConfig.dataset), "requestTagPrefix" in newConfig && (newConfig.requestTagPrefix = newConfig.requestTagPrefix ? requestTag(newConfig.requestTagPrefix).replace(/\.+$/, "") : void 0), newConfig.apiVersion = `${newConfig.apiVersion}`.replace(/^v/, ""), newConfig.isDefaultApi = newConfig.apiHost === defaultConfig.apiHost, newConfig.useCdn === true && newConfig.withCredentials && printCdnAndWithCredentialsWarning(), newConfig.useCdn = newConfig.useCdn !== false && !newConfig.withCredentials, validateApiVersion(newConfig.apiVersion);
2166
2176
  const hostParts = newConfig.apiHost.split("://", 2), protocol = hostParts[0], host = hostParts[1], cdnHost = newConfig.isDefaultApi ? defaultCdnHost : host;
2167
- return newConfig.useProjectHostname ? (newConfig.url = `${protocol}://${newConfig.projectId}.${host}/v${newConfig.apiVersion}`, newConfig.cdnUrl = `${protocol}://${newConfig.projectId}.${cdnHost}/v${newConfig.apiVersion}`) : (newConfig.url = `${newConfig.apiHost}/v${newConfig.apiVersion}`, newConfig.cdnUrl = newConfig.url), newConfig;
2177
+ return projectBased ? (newConfig.url = `${protocol}://${newConfig.projectId}.${host}/v${newConfig.apiVersion}`, newConfig.cdnUrl = `${protocol}://${newConfig.projectId}.${cdnHost}/v${newConfig.apiVersion}`) : (newConfig.url = `${newConfig.apiHost}/v${newConfig.apiVersion}`, newConfig.cdnUrl = newConfig.url), newConfig;
2168
2178
  };
2169
2179
  class ConnectionFailedError extends Error {
2170
2180
  name = "ConnectionFailedError";
@@ -2732,7 +2742,7 @@ ${selectionOpts}`);
2732
2742
  );
2733
2743
  }
2734
2744
  function _dataRequest(client, httpRequest, endpoint, body, options = {}) {
2735
- 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, cacheMode } = options, uri = _getDataUrl(client, endpoint, stringQuery), reqOptions = {
2745
+ const isMutation = endpoint === "mutate", isAction = endpoint === "actions", isQuery2 = 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, cacheMode } = options, uri = _getDataUrl(client, endpoint, stringQuery), reqOptions = {
2736
2746
  method: useGet ? "GET" : "POST",
2737
2747
  uri,
2738
2748
  json: true,
@@ -2747,7 +2757,7 @@ ${selectionOpts}`);
2747
2757
  resultSourceMap: options.resultSourceMap,
2748
2758
  lastLiveEventId: Array.isArray(lastLiveEventId) ? lastLiveEventId[0] : lastLiveEventId,
2749
2759
  cacheMode,
2750
- canUseCdn: isQuery,
2760
+ canUseCdn: isQuery2,
2751
2761
  signal: options.signal,
2752
2762
  fetch: options.fetch,
2753
2763
  useAbortSignal: options.useAbortSignal,
@@ -2775,11 +2785,12 @@ ${selectionOpts}`);
2775
2785
  const mutation = { [op]: doc }, opts = Object.assign({ returnFirst: true, returnDocuments: true }, options);
2776
2786
  return _dataRequest(client, httpRequest, "mutate", { mutations: [mutation] }, opts);
2777
2787
  }
2788
+ const hasDataConfig = (client) => client.config().dataset !== void 0 && client.config().projectId !== void 0 || client.config()["~experimental_resource"] !== void 0, isQuery = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "query")), isMutate = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "mutate")), isDoc = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "doc", "")), isListener = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "listen")), isHistory = (client, uri) => hasDataConfig(client) && uri.startsWith(_getDataUrl(client, "history", "")), isData = (client, uri) => uri.startsWith("/data/") || isQuery(client, uri) || isMutate(client, uri) || isDoc(client, uri) || isListener(client, uri) || isHistory(client, uri);
2778
2789
  function _requestObservable(client, httpRequest, options) {
2779
- const uri = options.url || options.uri, config = client.config(), canUseCdn = typeof options.canUseCdn > "u" ? ["GET", "HEAD"].indexOf(options.method || "GET") >= 0 && uri.indexOf("/data/") === 0 : options.canUseCdn;
2790
+ const uri = options.url || options.uri, config = client.config(), canUseCdn = typeof options.canUseCdn > "u" ? ["GET", "HEAD"].indexOf(options.method || "GET") >= 0 && isData(client, uri) : options.canUseCdn;
2780
2791
  let useCdn = (options.useCdn ?? config.useCdn) && canUseCdn;
2781
2792
  const tag = options.tag && config.requestTagPrefix ? [config.requestTagPrefix, options.tag].join(".") : options.tag || config.requestTagPrefix;
2782
- if (tag && options.tag !== null && (options.query = { tag: requestTag(tag), ...options.query }), ["GET", "HEAD", "POST"].indexOf(options.method || "GET") >= 0 && uri.indexOf("/data/query/") === 0) {
2793
+ if (tag && options.tag !== null && (options.query = { tag: requestTag(tag), ...options.query }), ["GET", "HEAD", "POST"].indexOf(options.method || "GET") >= 0 && isQuery(client, uri)) {
2783
2794
  const resultSourceMap = options.resultSourceMap ?? config.resultSourceMap;
2784
2795
  resultSourceMap !== void 0 && resultSourceMap !== false && (options.query = { resultSourceMap, ...options.query });
2785
2796
  const perspectiveOption = options.perspective || config.perspective;
@@ -2806,8 +2817,14 @@ ${selectionOpts}`);
2806
2817
  );
2807
2818
  }
2808
2819
  function _getDataUrl(client, operation, path) {
2809
- const config = client.config(), catalog = hasDataset(config), baseUri = `/${operation}/${catalog}`;
2810
- return `/data${path ? `${baseUri}/${path}` : baseUri}`.replace(/\/($|\?)/, "$1");
2820
+ const config = client.config();
2821
+ if (config["~experimental_resource"]) {
2822
+ resourceConfig(config);
2823
+ const resourceBase = resourceDataBase(config), uri2 = path !== void 0 ? `${operation}/${path}` : operation;
2824
+ return `${resourceBase}/${uri2}`.replace(/\/($|\?)/, "$1");
2825
+ }
2826
+ const catalog = hasDataset(config), baseUri = `/${operation}/${catalog}`;
2827
+ return `/data${path !== void 0 ? `${baseUri}/${path}` : baseUri}`.replace(/\/($|\?)/, "$1");
2811
2828
  }
2812
2829
  function _getUrl(client, uri, canUseCdn = false) {
2813
2830
  const { url, cdnUrl } = client.config();
@@ -2833,6 +2850,27 @@ ${selectionOpts}`);
2833
2850
  const error = new Error(signal?.reason ?? "The operation was aborted.");
2834
2851
  return error.name = "AbortError", error;
2835
2852
  }
2853
+ const resourceDataBase = (config) => {
2854
+ if (!config["~experimental_resource"])
2855
+ throw new Error("`resource` must be provided to perform resource queries");
2856
+ const { type, id } = config["~experimental_resource"];
2857
+ switch (type) {
2858
+ case "dataset": {
2859
+ const segments = id.split(".");
2860
+ if (segments.length !== 2)
2861
+ throw new Error('Dataset ID must be in the format "project.dataset"');
2862
+ return `/projects/${segments[0]}/datasets/${segments[1]}`;
2863
+ }
2864
+ case "canvas":
2865
+ return `/canvases/${id}`;
2866
+ case "media-library":
2867
+ return `/media-libraries/${id}`;
2868
+ case "dashboard":
2869
+ return `/dashboards/${id}`;
2870
+ default:
2871
+ throw new Error(`Unsupported resource type: ${type.toString()}`);
2872
+ }
2873
+ };
2836
2874
  class ObservableAssetsClient {
2837
2875
  #client;
2838
2876
  #httpRequest;
@@ -2865,7 +2903,7 @@ ${selectionOpts}`);
2865
2903
  validateAssetType(assetType);
2866
2904
  let meta = opts.extract || void 0;
2867
2905
  meta && !meta.length && (meta = ["none"]);
2868
- const dataset2 = hasDataset(client.config()), assetEndpoint = assetType === "image" ? "images" : "files", options = optionsFromFile(opts, body), { tag, label, title, description, creditLine, filename, source } = options, query = {
2906
+ const config = client.config(), options = optionsFromFile(opts, body), { tag, label, title, description, creditLine, filename, source } = options, query = {
2869
2907
  label,
2870
2908
  title,
2871
2909
  description,
@@ -2877,12 +2915,34 @@ ${selectionOpts}`);
2877
2915
  tag,
2878
2916
  method: "POST",
2879
2917
  timeout: options.timeout || 0,
2880
- uri: `/assets/${assetEndpoint}/${dataset2}`,
2918
+ uri: buildAssetUploadUrl(config, assetType),
2881
2919
  headers: options.contentType ? { "Content-Type": options.contentType } : {},
2882
2920
  query,
2883
2921
  body
2884
2922
  });
2885
2923
  }
2924
+ function buildAssetUploadUrl(config, assetType) {
2925
+ const assetTypeEndpoint = assetType === "image" ? "images" : "files";
2926
+ if (config["~experimental_resource"]) {
2927
+ const { type, id } = config["~experimental_resource"];
2928
+ switch (type) {
2929
+ case "dataset":
2930
+ throw new Error(
2931
+ "Assets are not supported for dataset resources, yet. Configure the client with `{projectId: <projectId>, dataset: <datasetId>}` instead."
2932
+ );
2933
+ case "canvas":
2934
+ return `/canvases/${id}/assets/${assetTypeEndpoint}`;
2935
+ case "media-library":
2936
+ return `/media-libraries/${id}/upload`;
2937
+ case "dashboard":
2938
+ return `/dashboards/${id}/assets/${assetTypeEndpoint}`;
2939
+ default:
2940
+ throw new Error(`Unsupported resource type: ${type.toString()}`);
2941
+ }
2942
+ }
2943
+ const dataset2 = hasDataset(config);
2944
+ return `assets/${assetTypeEndpoint}/${dataset2}`;
2945
+ }
2886
2946
  function optionsFromFile(opts, file) {
2887
2947
  return typeof File > "u" || !(file instanceof File) ? opts : Object.assign(
2888
2948
  {
@@ -2974,6 +3034,7 @@ ${selectionOpts}`);
2974
3034
  includeDrafts = false,
2975
3035
  tag: _tag
2976
3036
  } = {}) {
3037
+ resourceGuard("live", this.#client.config());
2977
3038
  const {
2978
3039
  projectId: projectId2,
2979
3040
  apiVersion: _apiVersion,
@@ -3103,7 +3164,7 @@ ${selectionOpts}`);
3103
3164
  * @param options - Options for the dataset
3104
3165
  */
3105
3166
  create(name, options) {
3106
- return lastValueFrom(
3167
+ return resourceGuard("dataset", this.#client.config()), lastValueFrom(
3107
3168
  _modify(this.#client, this.#httpRequest, "PUT", name, options)
3108
3169
  );
3109
3170
  }
@@ -3114,7 +3175,7 @@ ${selectionOpts}`);
3114
3175
  * @param options - New options for the dataset
3115
3176
  */
3116
3177
  edit(name, options) {
3117
- return lastValueFrom(
3178
+ return resourceGuard("dataset", this.#client.config()), lastValueFrom(
3118
3179
  _modify(this.#client, this.#httpRequest, "PATCH", name, options)
3119
3180
  );
3120
3181
  }
@@ -3124,19 +3185,19 @@ ${selectionOpts}`);
3124
3185
  * @param name - Name of the dataset to delete
3125
3186
  */
3126
3187
  delete(name) {
3127
- return lastValueFrom(_modify(this.#client, this.#httpRequest, "DELETE", name));
3188
+ return resourceGuard("dataset", this.#client.config()), lastValueFrom(_modify(this.#client, this.#httpRequest, "DELETE", name));
3128
3189
  }
3129
3190
  /**
3130
3191
  * Fetch a list of datasets for the configured project
3131
3192
  */
3132
3193
  list() {
3133
- return lastValueFrom(
3194
+ return resourceGuard("dataset", this.#client.config()), lastValueFrom(
3134
3195
  _request(this.#client, this.#httpRequest, { uri: "/datasets", tag: null })
3135
3196
  );
3136
3197
  }
3137
3198
  }
3138
3199
  function _modify(client, httpRequest, method, name, options) {
3139
- return dataset(name), _request(client, httpRequest, {
3200
+ return resourceGuard("dataset", client.config()), dataset(name), _request(client, httpRequest, {
3140
3201
  method,
3141
3202
  uri: `/datasets/${name}`,
3142
3203
  body: options,
@@ -3150,6 +3211,7 @@ ${selectionOpts}`);
3150
3211
  this.#client = client, this.#httpRequest = httpRequest;
3151
3212
  }
3152
3213
  list(options) {
3214
+ resourceGuard("projects", this.#client.config());
3153
3215
  const uri = options?.includeMembers === false ? "/projects?includeMembers=false" : "/projects";
3154
3216
  return _request(this.#client, this.#httpRequest, { uri });
3155
3217
  }
@@ -3159,7 +3221,7 @@ ${selectionOpts}`);
3159
3221
  * @param projectId - ID of the project to fetch
3160
3222
  */
3161
3223
  getById(projectId2) {
3162
- return _request(this.#client, this.#httpRequest, { uri: `/projects/${projectId2}` });
3224
+ return resourceGuard("projects", this.#client.config()), _request(this.#client, this.#httpRequest, { uri: `/projects/${projectId2}` });
3163
3225
  }
3164
3226
  }
3165
3227
  class ProjectsClient {
@@ -3169,6 +3231,7 @@ ${selectionOpts}`);
3169
3231
  this.#client = client, this.#httpRequest = httpRequest;
3170
3232
  }
3171
3233
  list(options) {
3234
+ resourceGuard("projects", this.#client.config());
3172
3235
  const uri = options?.includeMembers === false ? "/projects?includeMembers=false" : "/projects";
3173
3236
  return lastValueFrom(_request(this.#client, this.#httpRequest, { uri }));
3174
3237
  }
@@ -3178,7 +3241,7 @@ ${selectionOpts}`);
3178
3241
  * @param projectId - ID of the project to fetch
3179
3242
  */
3180
3243
  getById(projectId2) {
3181
- return lastValueFrom(
3244
+ return resourceGuard("projects", this.#client.config()), lastValueFrom(
3182
3245
  _request(this.#client, this.#httpRequest, { uri: `/projects/${projectId2}` })
3183
3246
  );
3184
3247
  }