@sanity/client 6.17.2 → 6.17.3-canary.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/client",
3
- "version": "6.17.2",
3
+ "version": "6.17.3-canary.1",
4
4
  "description": "Client for retrieving, creating and patching data from Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -4,6 +4,7 @@ import {AssetsClient, ObservableAssetsClient} from './assets/AssetsClient'
4
4
  import {defaultConfig, initConfig} from './config'
5
5
  import * as dataMethods from './data/dataMethods'
6
6
  import {_listen} from './data/listen'
7
+ import {_live} from './data/live'
7
8
  import {ObservablePatch, Patch} from './data/patch'
8
9
  import {ObservableTransaction, Transaction} from './data/transaction'
9
10
  import {DatasetsClient, ObservableDatasetsClient} from './datasets/DatasetsClient'
@@ -41,6 +42,7 @@ import {ObservableUsersClient, UsersClient} from './users/UsersClient'
41
42
 
42
43
  export type {
43
44
  _listen,
45
+ _live,
44
46
  AssetsClient,
45
47
  DatasetsClient,
46
48
  ObservableAssetsClient,
@@ -68,6 +70,7 @@ export class ObservableSanityClient {
68
70
  * Instance properties
69
71
  */
70
72
  listen = _listen
73
+ live = _live
71
74
 
72
75
  constructor(httpRequest: HttpRequest, config: ClientConfig = defaultConfig) {
73
76
  this.config(config)
@@ -713,6 +716,7 @@ export class SanityClient {
713
716
  * Instance properties
714
717
  */
715
718
  listen = _listen
719
+ live = _live
716
720
 
717
721
  constructor(httpRequest: HttpRequest, config: ClientConfig = defaultConfig) {
718
722
  this.config(config)
@@ -67,9 +67,11 @@ export function _fetch<R, Q>(
67
67
  httpRequest: HttpRequest,
68
68
  _stega: InitializedStegaConfig,
69
69
  query: string,
70
- _params: Q = {} as Q,
70
+ __params: Q = {} as Q,
71
71
  options: QueryOptions = {},
72
72
  ): Observable<RawQueryResponse<R> | R> {
73
+ const _params = options.refresh ? {...__params, _: options.refresh} : __params
74
+
73
75
  const stega =
74
76
  'stega' in options
75
77
  ? {
@@ -0,0 +1,83 @@
1
+ import {Observable} from 'rxjs'
2
+
3
+ import type {ObservableSanityClient, SanityClient} from '../SanityClient'
4
+ import type {LiveChangeEvent, LiveErrorEvent, LiveOptions, LiveRestartEvent} from '../types'
5
+ import {_getDataUrl} from './dataMethods'
6
+
7
+ /** @public */
8
+ export function _live(
9
+ this: SanityClient | ObservableSanityClient,
10
+ opts: LiveOptions = {},
11
+ ): Observable<LiveChangeEvent | LiveErrorEvent | LiveRestartEvent> {
12
+ const path = _getDataUrl(this, 'sync-tags')
13
+ const url = new URL(this.getUrl(path, false))
14
+ if (opts.start) {
15
+ url.searchParams.append('start', opts.start)
16
+ }
17
+
18
+ return new Observable((observer) => {
19
+ const controller = new AbortController()
20
+ const {signal} = controller
21
+ fetch(url, {signal})
22
+ .then(async (res) => {
23
+ if (!res.body) {
24
+ throw new TypeError('Response body is not readable')
25
+ }
26
+ const reader = res.body
27
+ .pipeThrough(new TextDecoderStream())
28
+ .pipeThrough(splitStream('\n'))
29
+ .pipeThrough(parseJSON())
30
+ .getReader()
31
+
32
+ const results = {
33
+ [Symbol.asyncIterator]() {
34
+ return {
35
+ next: () => reader.read(),
36
+ }
37
+ },
38
+ }
39
+
40
+ for await (const chunk of results) {
41
+ if (signal.aborted) break
42
+ if (chunk.type === 'error') {
43
+ observer.error(chunk)
44
+ break
45
+ }
46
+ observer.next(chunk)
47
+ }
48
+ })
49
+ .catch((err) => {
50
+ if (err?.name !== 'TimeoutError' && err?.name !== 'AbortError') {
51
+ observer.error(err)
52
+ }
53
+ })
54
+ return () => {
55
+ controller.abort()
56
+ }
57
+ })
58
+ }
59
+
60
+ function splitStream(splitOn: string) {
61
+ let buffer = ''
62
+
63
+ return new TransformStream({
64
+ transform(chunk, controller) {
65
+ buffer += chunk
66
+ const parts = buffer.split(splitOn)
67
+ parts.slice(0, -1).forEach((part) => controller.enqueue(part))
68
+ buffer = parts[parts.length - 1]
69
+ },
70
+ flush(controller) {
71
+ if (buffer) controller.enqueue(buffer)
72
+ },
73
+ })
74
+ }
75
+
76
+ function parseJSON() {
77
+ return new TransformStream({
78
+ transform(chunk, controller) {
79
+ if (!chunk) return
80
+ controller.enqueue(JSON.parse(chunk))
81
+ },
82
+ })
83
+ }
package/src/types.ts CHANGED
@@ -479,6 +479,8 @@ export interface QueryParams {
479
479
  token?: never
480
480
  /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
481
481
  useCdn?: never
482
+ /** @deprecated you're using a fetch option as a GROQ parameter, this is likely a mistake */
483
+ refresh?: never
482
484
  /* eslint-enable @typescript-eslint/no-explicit-any */
483
485
  }
484
486
 
@@ -743,6 +745,7 @@ export interface ResponseQueryOptions extends RequestOptions {
743
745
  // The `cache` and `next` options are specific to the Next.js App Router integration
744
746
  cache?: 'next' extends keyof RequestInit ? RequestInit['cache'] : never
745
747
  next?: ('next' extends keyof RequestInit ? RequestInit : never)['next']
748
+ refresh?: string
746
749
  }
747
750
 
748
751
  /** @public */
@@ -785,6 +788,7 @@ export interface RawQueryResponse<R> {
785
788
  ms: number
786
789
  result: R
787
790
  resultSourceMap?: ContentSourceMap
791
+ syncTags?: `s1:${string}`[]
788
792
  }
789
793
 
790
794
  /** @public */
@@ -999,6 +1003,26 @@ export interface ContentSourceMap {
999
1003
  paths: ContentSourceMapPaths
1000
1004
  }
1001
1005
 
1006
+ /** @public */
1007
+ export interface LiveOptions {
1008
+ start?: string
1009
+ }
1010
+ /** @public */
1011
+ export interface LiveErrorEvent {
1012
+ type: 'error'
1013
+ status: number
1014
+ message: string
1015
+ }
1016
+ /** @public */
1017
+ export interface LiveRestartEvent {
1018
+ type: 'restart'
1019
+ }
1020
+ /** @public */
1021
+ export interface LiveChangeEvent {
1022
+ tags: `s1:${string}`[]
1023
+ pos: string
1024
+ }
1025
+
1002
1026
  export type {
1003
1027
  ContentSourceMapParsedPath,
1004
1028
  ContentSourceMapParsedPathKeyedSegment,
@@ -2415,8 +2415,8 @@ ${selectionOpts}`);
2415
2415
  autoGenerateArrayKeys: options.autoGenerateArrayKeys,
2416
2416
  skipCrossDatasetReferenceValidation: options.skipCrossDatasetReferenceValidation
2417
2417
  }), isResponse = (event) => event.type === "response", getBody = (event) => event.body, indexBy = (docs, attr) => docs.reduce((indexed, doc) => (indexed[attr(doc)] = doc, indexed), /* @__PURE__ */ Object.create(null)), getQuerySizeLimit = 11264;
2418
- function _fetch(client, httpRequest, _stega, query, _params = {}, options = {}) {
2419
- const stega = "stega" in options ? {
2418
+ function _fetch(client, httpRequest, _stega, query, __params = {}, options = {}) {
2419
+ const _params = options.refresh ? { ...__params, _: options.refresh } : __params, stega = "stega" in options ? {
2420
2420
  ..._stega || {},
2421
2421
  ...typeof options.stega == "boolean" ? { enabled: options.stega } : options.stega || {}
2422
2422
  } : _stega, params = stega.enabled ? stegaClean(_params) : _params, mapResponse = options.filterResponse === !1 ? (res) => res : (res) => res.result, { cache, next, ...opts } = {
@@ -2726,6 +2726,57 @@ ${selectionOpts}`);
2726
2726
  function extractErrorMessage(err) {
2727
2727
  return err.error ? err.error.description ? err.error.description : typeof err.error == "string" ? err.error : JSON.stringify(err.error, null, 2) : err.message || "Unknown listener error";
2728
2728
  }
2729
+ function _live(opts = {}) {
2730
+ const path = _getDataUrl(this, "sync-tags"), url = new URL(this.getUrl(path, !1));
2731
+ return opts.start && url.searchParams.append("start", opts.start), new Observable((observer) => {
2732
+ const controller = new AbortController(), { signal } = controller;
2733
+ return fetch(url, { signal }).then(async (res) => {
2734
+ if (!res.body)
2735
+ throw new TypeError("Response body is not readable");
2736
+ const reader = res.body.pipeThrough(new TextDecoderStream()).pipeThrough(splitStream(`
2737
+ `)).pipeThrough(parseJSON()).getReader(), results = {
2738
+ [Symbol.asyncIterator]() {
2739
+ return {
2740
+ next: () => reader.read()
2741
+ };
2742
+ }
2743
+ };
2744
+ for await (const chunk of results) {
2745
+ if (signal.aborted)
2746
+ break;
2747
+ if (chunk.type === "error") {
2748
+ observer.error(chunk);
2749
+ break;
2750
+ }
2751
+ observer.next(chunk);
2752
+ }
2753
+ }).catch((err) => {
2754
+ (err == null ? void 0 : err.name) !== "TimeoutError" && (err == null ? void 0 : err.name) !== "AbortError" && observer.error(err);
2755
+ }), () => {
2756
+ controller.abort();
2757
+ };
2758
+ });
2759
+ }
2760
+ function splitStream(splitOn) {
2761
+ let buffer = "";
2762
+ return new TransformStream({
2763
+ transform(chunk, controller) {
2764
+ buffer += chunk;
2765
+ const parts = buffer.split(splitOn);
2766
+ parts.slice(0, -1).forEach((part) => controller.enqueue(part)), buffer = parts[parts.length - 1];
2767
+ },
2768
+ flush(controller) {
2769
+ buffer && controller.enqueue(buffer);
2770
+ }
2771
+ });
2772
+ }
2773
+ function parseJSON() {
2774
+ return new TransformStream({
2775
+ transform(chunk, controller) {
2776
+ chunk && controller.enqueue(JSON.parse(chunk));
2777
+ }
2778
+ });
2779
+ }
2729
2780
  var __accessCheck$3 = (obj, member, msg) => {
2730
2781
  if (!member.has(obj))
2731
2782
  throw TypeError("Cannot " + msg);
@@ -2930,7 +2981,7 @@ ${selectionOpts}`);
2930
2981
  }, __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value), _clientConfig, _httpRequest;
2931
2982
  const _ObservableSanityClient = class _ObservableSanityClient2 {
2932
2983
  constructor(httpRequest, config = defaultConfig) {
2933
- __publicField(this, "assets"), __publicField(this, "datasets"), __publicField(this, "projects"), __publicField(this, "users"), __privateAdd(this, _clientConfig, void 0), __privateAdd(this, _httpRequest, void 0), __publicField(this, "listen", _listen), this.config(config), __privateSet(this, _httpRequest, httpRequest), this.assets = new ObservableAssetsClient(this, __privateGet(this, _httpRequest)), this.datasets = new ObservableDatasetsClient(this, __privateGet(this, _httpRequest)), this.projects = new ObservableProjectsClient(this, __privateGet(this, _httpRequest)), this.users = new ObservableUsersClient(this, __privateGet(this, _httpRequest));
2984
+ __publicField(this, "assets"), __publicField(this, "datasets"), __publicField(this, "projects"), __publicField(this, "users"), __privateAdd(this, _clientConfig, void 0), __privateAdd(this, _httpRequest, void 0), __publicField(this, "listen", _listen), __publicField(this, "live", _live), this.config(config), __privateSet(this, _httpRequest, httpRequest), this.assets = new ObservableAssetsClient(this, __privateGet(this, _httpRequest)), this.datasets = new ObservableDatasetsClient(this, __privateGet(this, _httpRequest)), this.projects = new ObservableProjectsClient(this, __privateGet(this, _httpRequest)), this.users = new ObservableUsersClient(this, __privateGet(this, _httpRequest));
2934
2985
  }
2935
2986
  /**
2936
2987
  * Clone the client - returns a new instance
@@ -3059,7 +3110,7 @@ ${selectionOpts}`);
3059
3110
  var _clientConfig2, _httpRequest2;
3060
3111
  const _SanityClient = class _SanityClient2 {
3061
3112
  constructor(httpRequest, config = defaultConfig) {
3062
- __publicField(this, "assets"), __publicField(this, "datasets"), __publicField(this, "projects"), __publicField(this, "users"), __publicField(this, "observable"), __privateAdd(this, _clientConfig2, void 0), __privateAdd(this, _httpRequest2, void 0), __publicField(this, "listen", _listen), this.config(config), __privateSet(this, _httpRequest2, httpRequest), this.assets = new AssetsClient(this, __privateGet(this, _httpRequest2)), this.datasets = new DatasetsClient(this, __privateGet(this, _httpRequest2)), this.projects = new ProjectsClient(this, __privateGet(this, _httpRequest2)), this.users = new UsersClient(this, __privateGet(this, _httpRequest2)), this.observable = new ObservableSanityClient(httpRequest, config);
3113
+ __publicField(this, "assets"), __publicField(this, "datasets"), __publicField(this, "projects"), __publicField(this, "users"), __publicField(this, "observable"), __privateAdd(this, _clientConfig2, void 0), __privateAdd(this, _httpRequest2, void 0), __publicField(this, "listen", _listen), __publicField(this, "live", _live), this.config(config), __privateSet(this, _httpRequest2, httpRequest), this.assets = new AssetsClient(this, __privateGet(this, _httpRequest2)), this.datasets = new DatasetsClient(this, __privateGet(this, _httpRequest2)), this.projects = new ProjectsClient(this, __privateGet(this, _httpRequest2)), this.users = new UsersClient(this, __privateGet(this, _httpRequest2)), this.observable = new ObservableSanityClient(httpRequest, config);
3063
3114
  }
3064
3115
  /**
3065
3116
  * Clone the client - returns a new instance