@sanity/client 6.27.2 → 6.27.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.
@@ -399,7 +399,7 @@ export declare type ClientPerspective =
399
399
  | 'published'
400
400
  | 'drafts'
401
401
  | 'raw'
402
- | ('published' | 'drafts' | ReleaseId)[]
402
+ | StackablePerspective[]
403
403
 
404
404
  /** @public */
405
405
  export declare type ClientReturn<
@@ -2402,7 +2402,10 @@ export declare type ReconnectEvent = {
2402
2402
  type: 'reconnect'
2403
2403
  }
2404
2404
 
2405
- /** @public */
2405
+ /**
2406
+ * @public
2407
+ * @deprecated – The `r`-prefix is not required, use `string` instead
2408
+ */
2406
2409
  export declare type ReleaseId = `r${string}`
2407
2410
 
2408
2411
  /**
@@ -3189,6 +3192,9 @@ export declare interface SingleMutationResult {
3189
3192
  }[]
3190
3193
  }
3191
3194
 
3195
+ /** @public */
3196
+ export declare type StackablePerspective = ('published' | 'drafts' | string) & {}
3197
+
3192
3198
  /**
3193
3199
  * Can take a `result` JSON from a `const {result} = client.fetch(query, params, {filterResponse: false})`
3194
3200
  * and remove all stega-encoded data from it.
@@ -399,7 +399,7 @@ export declare type ClientPerspective =
399
399
  | 'published'
400
400
  | 'drafts'
401
401
  | 'raw'
402
- | ('published' | 'drafts' | ReleaseId)[]
402
+ | StackablePerspective[]
403
403
 
404
404
  /** @public */
405
405
  export declare type ClientReturn<
@@ -2402,7 +2402,10 @@ export declare type ReconnectEvent = {
2402
2402
  type: 'reconnect'
2403
2403
  }
2404
2404
 
2405
- /** @public */
2405
+ /**
2406
+ * @public
2407
+ * @deprecated – The `r`-prefix is not required, use `string` instead
2408
+ */
2406
2409
  export declare type ReleaseId = `r${string}`
2407
2410
 
2408
2411
  /**
@@ -3189,6 +3192,9 @@ export declare interface SingleMutationResult {
3189
3192
  }[]
3190
3193
  }
3191
3194
 
3195
+ /** @public */
3196
+ export declare type StackablePerspective = ('published' | 'drafts' | string) & {}
3197
+
3192
3198
  /**
3193
3199
  * Can take a `result` JSON from a `const {result} = client.fetch(query, params, {filterResponse: false})`
3194
3200
  * and remove all stega-encoded data from it.
package/dist/stega.d.cts CHANGED
@@ -399,7 +399,7 @@ export declare type ClientPerspective =
399
399
  | 'published'
400
400
  | 'drafts'
401
401
  | 'raw'
402
- | ('published' | 'drafts' | ReleaseId)[]
402
+ | StackablePerspective[]
403
403
 
404
404
  /** @public */
405
405
  export declare type ClientReturn<
@@ -2402,7 +2402,10 @@ export declare type ReconnectEvent = {
2402
2402
  type: 'reconnect'
2403
2403
  }
2404
2404
 
2405
- /** @public */
2405
+ /**
2406
+ * @public
2407
+ * @deprecated – The `r`-prefix is not required, use `string` instead
2408
+ */
2406
2409
  export declare type ReleaseId = `r${string}`
2407
2410
 
2408
2411
  /**
@@ -3189,6 +3192,9 @@ export declare interface SingleMutationResult {
3189
3192
  }[]
3190
3193
  }
3191
3194
 
3195
+ /** @public */
3196
+ export declare type StackablePerspective = ('published' | 'drafts' | string) & {}
3197
+
3192
3198
  /**
3193
3199
  * Can take a `result` JSON from a `const {result} = client.fetch(query, params, {filterResponse: false})`
3194
3200
  * and remove all stega-encoded data from it.
package/dist/stega.d.ts CHANGED
@@ -399,7 +399,7 @@ export declare type ClientPerspective =
399
399
  | 'published'
400
400
  | 'drafts'
401
401
  | 'raw'
402
- | ('published' | 'drafts' | ReleaseId)[]
402
+ | StackablePerspective[]
403
403
 
404
404
  /** @public */
405
405
  export declare type ClientReturn<
@@ -2402,7 +2402,10 @@ export declare type ReconnectEvent = {
2402
2402
  type: 'reconnect'
2403
2403
  }
2404
2404
 
2405
- /** @public */
2405
+ /**
2406
+ * @public
2407
+ * @deprecated – The `r`-prefix is not required, use `string` instead
2408
+ */
2406
2409
  export declare type ReleaseId = `r${string}`
2407
2410
 
2408
2411
  /**
@@ -3189,6 +3192,9 @@ export declare interface SingleMutationResult {
3189
3192
  }[]
3190
3193
  }
3191
3194
 
3195
+ /** @public */
3196
+ export declare type StackablePerspective = ('published' | 'drafts' | string) & {}
3197
+
3192
3198
  /**
3193
3199
  * Can take a `result` JSON from a `const {result} = client.fetch(query, params, {filterResponse: false})`
3194
3200
  * and remove all stega-encoded data from it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/client",
3
- "version": "6.27.2",
3
+ "version": "6.27.3-canary.1",
4
4
  "description": "Client for retrieving, creating and patching data from Sanity.io",
5
5
  "keywords": [
6
6
  "sanity",
@@ -130,7 +130,7 @@
130
130
  "@rollup/plugin-commonjs": "^28.0.2",
131
131
  "@rollup/plugin-node-resolve": "^16.0.0",
132
132
  "@sanity/client-latest": "npm:@sanity/client@latest",
133
- "@sanity/pkg-utils": "^7.0.3",
133
+ "@sanity/pkg-utils": "^7.0.4",
134
134
  "@types/json-diff": "^1.0.3",
135
135
  "@types/node": "^22.9.0",
136
136
  "@typescript-eslint/eslint-plugin": "^8.22.0",
@@ -153,7 +153,7 @@
153
153
  "prettier": "^3.4.2",
154
154
  "prettier-plugin-packagejson": "^2.5.8",
155
155
  "rimraf": "^5.0.7",
156
- "rollup": "^4.32.0",
156
+ "rollup": "^4.32.1",
157
157
  "sse-channel": "^4.0.0",
158
158
  "terser": "^5.37.0",
159
159
  "typescript": "5.7.3",
package/src/config.ts CHANGED
@@ -28,6 +28,8 @@ function validateApiVersion(apiVersion: string) {
28
28
  }
29
29
  }
30
30
 
31
+ const VALID_PERSPECTIVE = /^[a-z0-9_]+$/i
32
+
31
33
  /**
32
34
  * @internal - it may have breaking changes in any release
33
35
  */
@@ -35,36 +37,22 @@ export function validateApiPerspective(
35
37
  perspective: unknown,
36
38
  ): asserts perspective is ClientPerspective {
37
39
  if (Array.isArray(perspective)) {
38
- for (const perspectiveValue of perspective) {
39
- if (perspectiveValue === 'published') {
40
- continue
41
- }
42
- if (perspectiveValue === 'drafts') {
43
- continue
44
- }
45
- if (
46
- typeof perspectiveValue === 'string' &&
47
- perspectiveValue.startsWith('r') &&
48
- perspectiveValue !== 'raw'
49
- ) {
50
- continue
51
- }
40
+ if (perspective.includes('raw')) {
52
41
  throw new TypeError(
53
- 'Invalid API perspective value, expected `published`, `drafts` or a valid release identifier string',
42
+ `Invalid API perspective value: "raw". The raw-perspective can not be combined with other perspectives`,
54
43
  )
55
44
  }
56
- return
57
45
  }
58
- switch (perspective as ClientPerspective) {
59
- case 'previewDrafts':
60
- case 'drafts':
61
- case 'published':
62
- case 'raw':
63
- return
64
- default:
65
- throw new TypeError(
66
- 'Invalid API perspective string, expected `published`, `previewDrafts` or `raw`',
67
- )
46
+
47
+ const invalid = (Array.isArray(perspective) ? perspective : [perspective]).filter(
48
+ (perspectiveName) =>
49
+ typeof perspectiveName !== 'string' || !VALID_PERSPECTIVE.test(perspectiveName),
50
+ )
51
+ if (invalid.length > 0) {
52
+ const formatted = invalid.map((v) => JSON.stringify(v))
53
+ throw new TypeError(
54
+ `Invalid API perspective value${invalid.length === 1 ? '' : 's'}: ${formatted.join(', ')}, expected \`published\`, \`drafts\`, \`raw\` or a release identifier string`,
55
+ )
68
56
  }
69
57
  }
70
58
 
@@ -1,5 +1,5 @@
1
1
  import {validateApiPerspective} from '../config'
2
- import type {ReleaseId} from '../types'
2
+ import type {StackablePerspective} from '../types'
3
3
  import type {ClientPerspective} from './types'
4
4
 
5
5
  /**
@@ -9,7 +9,7 @@ import type {ClientPerspective} from './types'
9
9
  */
10
10
  export function resolvePerspectives(
11
11
  perspective: Exclude<ClientPerspective, 'raw'>,
12
- ): ('published' | 'drafts' | ReleaseId)[] {
12
+ ): ('published' | 'drafts' | StackablePerspective)[] {
13
13
  validateApiPerspective(perspective)
14
14
 
15
15
  if (Array.isArray(perspective)) {
package/src/data/live.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import {catchError, concat, EMPTY, mergeMap, Observable, of} from 'rxjs'
2
- import {map} from 'rxjs/operators'
2
+ import {finalize, map} from 'rxjs/operators'
3
3
 
4
4
  import {CorsOriginError} from '../http/errors'
5
5
  import type {ObservableSanityClient, SanityClient} from '../SanityClient'
@@ -11,6 +11,7 @@ import type {
11
11
  LiveEventWelcome,
12
12
  SyncTag,
13
13
  } from '../types'
14
+ import {shareReplayLatest} from '../util/shareReplayLatest'
14
15
  import {_getDataUrl} from './dataMethods'
15
16
  import {connectEventSource} from './eventsource'
16
17
  import {eventSourcePolyfill} from './eventsourcePolyfill'
@@ -81,6 +82,13 @@ export class LiveClient {
81
82
  esOptions.withCredentials = true
82
83
  }
83
84
 
85
+ const key = `${url.href}::${JSON.stringify(esOptions)}`
86
+ const existing = eventsCache.get(key)
87
+
88
+ if (existing) {
89
+ return existing
90
+ }
91
+
84
92
  const initEventSource = () =>
85
93
  // use polyfill if there is no global EventSource or if we need to set headers
86
94
  (typeof EventSource === 'undefined' || esOptions.headers
@@ -118,7 +126,14 @@ export class LiveClient {
118
126
  throw new CorsOriginError({projectId: projectId!})
119
127
  }),
120
128
  )
121
- return concat(checkCors, events)
129
+ const observable = concat(checkCors, events).pipe(
130
+ finalize(() => eventsCache.delete(key)),
131
+ shareReplayLatest({
132
+ predicate: (event) => event.type === 'welcome',
133
+ }),
134
+ )
135
+ eventsCache.set(key, observable)
136
+ return observable
122
137
  }
123
138
  }
124
139
 
@@ -140,3 +155,5 @@ function fetchObservable(url: URL, init: RequestInit) {
140
155
  return () => controller.abort()
141
156
  })
142
157
  }
158
+
159
+ const eventsCache = new Map<string, Observable<LiveEvent>>()
package/src/types.ts CHANGED
@@ -31,16 +31,22 @@ export interface RequestOptions {
31
31
  signal?: AbortSignal
32
32
  }
33
33
 
34
- /** @public */
34
+ /**
35
+ * @public
36
+ * @deprecated – The `r`-prefix is not required, use `string` instead
37
+ */
35
38
  export type ReleaseId = `r${string}`
36
39
 
40
+ /** @public */
41
+ export type StackablePerspective = ('published' | 'drafts' | string) & {}
42
+
37
43
  /** @public */
38
44
  export type ClientPerspective =
39
45
  | 'previewDrafts'
40
46
  | 'published'
41
47
  | 'drafts'
42
48
  | 'raw'
43
- | ('published' | 'drafts' | ReleaseId)[]
49
+ | StackablePerspective[]
44
50
 
45
51
  /** @public */
46
52
  export interface ClientConfig {
@@ -1291,7 +1297,6 @@ export interface LiveEventMessage {
1291
1297
  export interface LiveEventWelcome {
1292
1298
  type: 'welcome'
1293
1299
  }
1294
-
1295
1300
  /** @public */
1296
1301
  export type LiveEvent = LiveEventRestart | LiveEventReconnect | LiveEventMessage | LiveEventWelcome
1297
1302
 
@@ -0,0 +1,71 @@
1
+ import {
2
+ finalize,
3
+ merge,
4
+ type MonoTypeOperatorFunction,
5
+ Observable,
6
+ share,
7
+ type ShareConfig,
8
+ tap,
9
+ } from 'rxjs'
10
+
11
+ export type ShareReplayLatestConfig<T> = ShareConfig<T> & {predicate: (value: T) => boolean}
12
+
13
+ /**
14
+ * A variant of share that takes a predicate function to determine which value to replay to new subscribers
15
+ * @param predicate - Predicate function to determine which value to replay
16
+ */
17
+ export function shareReplayLatest<T>(predicate: (value: T) => boolean): MonoTypeOperatorFunction<T>
18
+
19
+ /**
20
+ * A variant of share that takes a predicate function to determine which value to replay to new subscribers
21
+ * @param config - ShareConfig with additional predicate function
22
+ */
23
+ export function shareReplayLatest<T>(
24
+ config: ShareReplayLatestConfig<T>,
25
+ ): MonoTypeOperatorFunction<T>
26
+
27
+ /**
28
+ * A variant of share that takes a predicate function to determine which value to replay to new subscribers
29
+ * @param configOrPredicate - Predicate function to determine which value to replay
30
+ * @param config - Optional ShareConfig
31
+ */
32
+ export function shareReplayLatest<T>(
33
+ configOrPredicate: ShareReplayLatestConfig<T> | ShareReplayLatestConfig<T>['predicate'],
34
+ config?: ShareConfig<T>,
35
+ ) {
36
+ return _shareReplayLatest(
37
+ typeof configOrPredicate === 'function'
38
+ ? {predicate: configOrPredicate, ...config}
39
+ : configOrPredicate,
40
+ )
41
+ }
42
+ function _shareReplayLatest<T>(config: ShareReplayLatestConfig<T>): MonoTypeOperatorFunction<T> {
43
+ return (source: Observable<T>) => {
44
+ let latest: T | undefined
45
+ let emitted = false
46
+
47
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
48
+ const {predicate, ...shareConfig} = config
49
+
50
+ const wrapped = source.pipe(
51
+ tap((value) => {
52
+ if (config.predicate(value)) {
53
+ emitted = true
54
+ latest = value
55
+ }
56
+ }),
57
+ finalize(() => {
58
+ emitted = false
59
+ latest = undefined
60
+ }),
61
+ share(shareConfig),
62
+ )
63
+ const emitLatest = new Observable<T>((subscriber) => {
64
+ if (emitted) {
65
+ subscriber.next(latest)
66
+ }
67
+ subscriber.complete()
68
+ })
69
+ return merge(wrapped, emitLatest)
70
+ }
71
+ }
@@ -1113,6 +1113,9 @@
1113
1113
  function popScheduler(args) {
1114
1114
  return isScheduler(last(args)) ? args.pop() : undefined;
1115
1115
  }
1116
+ function popNumber(args, defaultValue) {
1117
+ return typeof last(args) === 'number' ? args.pop() : defaultValue;
1118
+ }
1116
1119
 
1117
1120
  var isArrayLike = (function (x) { return x && typeof x.length === 'number' && typeof x !== 'function'; });
1118
1121
 
@@ -1619,6 +1622,7 @@
1619
1622
  }
1620
1623
 
1621
1624
  function mergeAll(concurrent) {
1625
+ if (concurrent === undefined) { concurrent = Infinity; }
1622
1626
  return mergeMap(identity, concurrent);
1623
1627
  }
1624
1628
 
@@ -1659,6 +1663,24 @@
1659
1663
  });
1660
1664
  }
1661
1665
 
1666
+ function merge() {
1667
+ var args = [];
1668
+ for (var _i = 0; _i < arguments.length; _i++) {
1669
+ args[_i] = arguments[_i];
1670
+ }
1671
+ var scheduler = popScheduler(args);
1672
+ var concurrent = popNumber(args, Infinity);
1673
+ var sources = args;
1674
+ return !sources.length
1675
+ ?
1676
+ EMPTY
1677
+ : sources.length === 1
1678
+ ?
1679
+ innerFrom(sources[0])
1680
+ :
1681
+ mergeAll(concurrent)(from(sources, scheduler));
1682
+ }
1683
+
1662
1684
  var isArray$1 = Array.isArray;
1663
1685
  function argsOrArgArray(args) {
1664
1686
  return args.length === 1 && isArray$1(args[0]) ? args[0] : args;
@@ -1716,6 +1738,17 @@
1716
1738
  return combineLatest.apply(undefined, __spreadArray([], __read(otherSources)));
1717
1739
  }
1718
1740
 
1741
+ function finalize(callback) {
1742
+ return operate(function (source, subscriber) {
1743
+ try {
1744
+ source.subscribe(subscriber);
1745
+ }
1746
+ finally {
1747
+ subscriber.add(callback);
1748
+ }
1749
+ });
1750
+ }
1751
+
1719
1752
  function share(options) {
1720
1753
  if (options === undefined) { options = {}; }
1721
1754
  var _a = options.connector, connector = _a === undefined ? function () { return new Subject(); } : _a, _b = options.resetOnError, resetOnError = _b === undefined ? true : _b, _c = options.resetOnComplete, resetOnComplete = _c === undefined ? true : _c, _d = options.resetOnRefCountZero, resetOnRefCountZero = _d === undefined ? true : _d;
@@ -1810,6 +1843,42 @@
1810
1843
  });
1811
1844
  }
1812
1845
 
1846
+ function tap(observerOrNext, error, complete) {
1847
+ var tapObserver = isFunction(observerOrNext) || error || complete
1848
+ ?
1849
+ { next: observerOrNext, error: error, complete: complete }
1850
+ : observerOrNext;
1851
+ return tapObserver
1852
+ ? operate(function (source, subscriber) {
1853
+ var _a;
1854
+ (_a = tapObserver.subscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
1855
+ var isUnsub = true;
1856
+ source.subscribe(createOperatorSubscriber(subscriber, function (value) {
1857
+ var _a;
1858
+ (_a = tapObserver.next) === null || _a === void 0 ? void 0 : _a.call(tapObserver, value);
1859
+ subscriber.next(value);
1860
+ }, function () {
1861
+ var _a;
1862
+ isUnsub = false;
1863
+ (_a = tapObserver.complete) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
1864
+ subscriber.complete();
1865
+ }, function (err) {
1866
+ var _a;
1867
+ isUnsub = false;
1868
+ (_a = tapObserver.error) === null || _a === void 0 ? void 0 : _a.call(tapObserver, err);
1869
+ subscriber.error(err);
1870
+ }, function () {
1871
+ var _a, _b;
1872
+ if (isUnsub) {
1873
+ (_a = tapObserver.unsubscribe) === null || _a === void 0 ? void 0 : _a.call(tapObserver);
1874
+ }
1875
+ (_b = tapObserver.finalize) === null || _b === void 0 ? void 0 : _b.call(tapObserver);
1876
+ }));
1877
+ })
1878
+ :
1879
+ identity;
1880
+ }
1881
+
1813
1882
  var s = { 0: 8203, 1: 8204, 2: 8205, 3: 8290, 4: 8291, 5: 8288, 6: 65279, 7: 8289, 8: 119155, 9: 119156, a: 119157, b: 119158, c: 119159, d: 119160, e: 119161, f: 119162 }, c = { 0: 8203, 1: 8204, 2: 8205, 3: 65279 }, u = new Array(4).fill(String.fromCodePoint(c[0])).join("");
1814
1883
  function E(t) {
1815
1884
  let e = JSON.stringify(t);
@@ -2039,25 +2108,20 @@
2039
2108
  if (!(/^\d{4}-\d{2}-\d{2}$/.test(apiVersion) && apiDate instanceof Date && apiDate.getTime() > 0))
2040
2109
  throw new Error("Invalid API version string, expected `1` or date in format `YYYY-MM-DD`");
2041
2110
  }
2111
+ const VALID_PERSPECTIVE = /^[a-z0-9_]+$/i;
2042
2112
  function validateApiPerspective(perspective) {
2043
- if (Array.isArray(perspective)) {
2044
- for (const perspectiveValue of perspective)
2045
- if (perspectiveValue !== "published" && perspectiveValue !== "drafts" && !(typeof perspectiveValue == "string" && perspectiveValue.startsWith("r") && perspectiveValue !== "raw"))
2046
- throw new TypeError(
2047
- "Invalid API perspective value, expected `published`, `drafts` or a valid release identifier string"
2048
- );
2049
- return;
2050
- }
2051
- switch (perspective) {
2052
- case "previewDrafts":
2053
- case "drafts":
2054
- case "published":
2055
- case "raw":
2056
- return;
2057
- default:
2058
- throw new TypeError(
2059
- "Invalid API perspective string, expected `published`, `previewDrafts` or `raw`"
2060
- );
2113
+ if (Array.isArray(perspective) && perspective.includes("raw"))
2114
+ throw new TypeError(
2115
+ 'Invalid API perspective value: "raw". The raw-perspective can not be combined with other perspectives'
2116
+ );
2117
+ const invalid = (Array.isArray(perspective) ? perspective : [perspective]).filter(
2118
+ (perspectiveName) => typeof perspectiveName != "string" || !VALID_PERSPECTIVE.test(perspectiveName)
2119
+ );
2120
+ if (invalid.length > 0) {
2121
+ const formatted = invalid.map((v) => JSON.stringify(v));
2122
+ throw new TypeError(
2123
+ `Invalid API perspective value${invalid.length === 1 ? "" : "s"}: ${formatted.join(", ")}, expected \`published\`, \`drafts\`, \`raw\` or a release identifier string`
2124
+ );
2061
2125
  }
2062
2126
  }
2063
2127
  const initConfig = (config, prevConfig) => {
@@ -2350,9 +2414,9 @@ ${selectionOpts}`);
2350
2414
  reset() {
2351
2415
  return this.operations = {}, this;
2352
2416
  }
2353
- _assign(op, props, merge = true) {
2417
+ _assign(op, props, merge2 = true) {
2354
2418
  return validateObject(op, props), this.operations = Object.assign({}, this.operations, {
2355
- [op]: Object.assign({}, merge && this.operations[op] || {}, props)
2419
+ [op]: Object.assign({}, merge2 && this.operations[op] || {}, props)
2356
2420
  }), this;
2357
2421
  }
2358
2422
  _set(op, props) {
@@ -2869,6 +2933,28 @@ ${selectionOpts}`);
2869
2933
  )
2870
2934
  );
2871
2935
  }
2936
+ function shareReplayLatest(configOrPredicate, config) {
2937
+ return _shareReplayLatest(
2938
+ typeof configOrPredicate == "function" ? { predicate: configOrPredicate, ...config } : configOrPredicate
2939
+ );
2940
+ }
2941
+ function _shareReplayLatest(config) {
2942
+ return (source) => {
2943
+ let latest, emitted = false;
2944
+ const { predicate, ...shareConfig } = config, wrapped = source.pipe(
2945
+ tap((value) => {
2946
+ config.predicate(value) && (emitted = true, latest = value);
2947
+ }),
2948
+ finalize(() => {
2949
+ emitted = false, latest = undefined;
2950
+ }),
2951
+ share(shareConfig)
2952
+ ), emitLatest = new Observable((subscriber) => {
2953
+ emitted && subscriber.next(latest), subscriber.complete();
2954
+ });
2955
+ return merge(wrapped, emitLatest);
2956
+ };
2957
+ }
2872
2958
  const requiredApiVersion = "2021-03-25";
2873
2959
  class LiveClient {
2874
2960
  #client;
@@ -2903,6 +2989,9 @@ ${selectionOpts}`);
2903
2989
  includeDrafts && token && (esOptions.headers = {
2904
2990
  Authorization: `Bearer ${token}`
2905
2991
  }), includeDrafts && withCredentials && (esOptions.withCredentials = true);
2992
+ const key = `${url.href}::${JSON.stringify(esOptions)}`, existing = eventsCache.get(key);
2993
+ if (existing)
2994
+ return existing;
2906
2995
  const events = connectEventSource(() => (
2907
2996
  // use polyfill if there is no global EventSource or if we need to set headers
2908
2997
  (typeof EventSource > "u" || esOptions.headers ? eventSourcePolyfill : of(EventSource)).pipe(map((EventSource2) => new EventSource2(url.href, esOptions)))
@@ -2930,8 +3019,13 @@ ${selectionOpts}`);
2930
3019
  catchError(() => {
2931
3020
  throw new CorsOriginError({ projectId: projectId2 });
2932
3021
  })
3022
+ ), observable2 = concat(checkCors, events).pipe(
3023
+ finalize(() => eventsCache.delete(key)),
3024
+ shareReplayLatest({
3025
+ predicate: (event) => event.type === "welcome"
3026
+ })
2933
3027
  );
2934
- return concat(checkCors, events);
3028
+ return eventsCache.set(key, observable2), observable2;
2935
3029
  }
2936
3030
  }
2937
3031
  function fetchObservable(url, init) {
@@ -2947,6 +3041,7 @@ ${selectionOpts}`);
2947
3041
  ), () => controller.abort();
2948
3042
  });
2949
3043
  }
3044
+ const eventsCache = /* @__PURE__ */ new Map();
2950
3045
  class ObservableDatasetsClient {
2951
3046
  #client;
2952
3047
  #httpRequest;