@sanity/sdk 3.0.0-rc.2 → 3.1.0
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/_exports/_internal.d.ts +25 -3
- package/dist/_exports/_internal.d.ts.map +1 -1
- package/dist/_exports/_internal.js +127 -9
- package/dist/_exports/_internal.js.map +1 -1
- package/dist/_exports/agent.d.ts +1 -1
- package/dist/_exports/agent.js +1 -1
- package/dist/_exports/comlink.d.ts +1 -1
- package/dist/_exports/comlink.js +2 -3
- package/dist/_exports/comlink.js.map +1 -1
- package/dist/{authStore-DKFX8fn7.d.ts → authStore-C-OEkGaM.d.ts} +30 -44
- package/dist/authStore-C-OEkGaM.d.ts.map +1 -0
- package/dist/{authStore-CtE9bLHW.js → clientStore-gUALQ0qW.js} +269 -11
- package/dist/{authStore-CtE9bLHW.js.map → clientStore-gUALQ0qW.js.map} +1 -1
- package/dist/{createSanityInstance-DUI1bGIg.d.ts → createSanityInstance-DCePpBYW.d.ts} +2 -2
- package/dist/{createSanityInstance-DUI1bGIg.d.ts.map → createSanityInstance-DCePpBYW.d.ts.map} +1 -1
- package/dist/{getNodeState-CR3__B2D.js → getNodeState-E0hjqFOo.js} +2 -3
- package/dist/{getNodeState-CR3__B2D.js.map → getNodeState-E0hjqFOo.js.map} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +168 -176
- package/dist/index.js.map +1 -1
- package/dist/{createStateSourceAction-BOKtqFNm.js → object-BwynGPRZ.js} +87 -3
- package/dist/object-BwynGPRZ.js.map +1 -0
- package/dist/{queryStore-DPf9sN3V.js → version-C90rNWaX.js} +48 -16
- package/dist/version-C90rNWaX.js.map +1 -0
- package/package.json +4 -4
- package/src/_exports/_internal.ts +1 -0
- package/src/_exports/index.ts +7 -4
- package/src/access/checkPermissions.test.ts +1 -1
- package/src/access/checkPermissions.ts +1 -1
- package/src/applications/applications.test.ts +4 -4
- package/src/applications/applications.ts +4 -4
- package/src/auth/handleAuthCallback.test.ts +2 -2
- package/src/auth/handleAuthCallback.ts +1 -1
- package/src/auth/logout.test.ts +1 -1
- package/src/auth/logout.ts +1 -1
- package/src/auth/refreshStampedToken.ts +1 -1
- package/src/auth/studioModeAuth.test.ts +1 -1
- package/src/auth/studioModeAuth.ts +1 -1
- package/src/auth/subscribeToStateAndFetchCurrentUser.test.ts +2 -2
- package/src/auth/subscribeToStateAndFetchCurrentUser.ts +1 -1
- package/src/comments/addonDatasetStore.test.ts +2 -2
- package/src/comments/addonDatasetStore.ts +2 -2
- package/src/comments/commentActions.ts +6 -5
- package/src/comments/commentsStore.ts +4 -4
- package/src/datasets/datasets.test.ts +44 -9
- package/src/datasets/datasets.ts +24 -23
- package/src/document/applyDocumentActions.ts +2 -6
- package/src/document/documentConstants.ts +9 -0
- package/src/document/documentStore.concurrency.test.ts +2 -1
- package/src/document/documentStore.test.ts +87 -17
- package/src/document/documentStore.ts +5 -5
- package/src/document/permissions.ts +2 -1
- package/src/document/processActions.test.ts +2 -1
- package/src/document/processMutations.ts +3 -2
- package/src/document/reducers.test.ts +224 -0
- package/src/document/reducers.ts +110 -27
- package/src/favorites/favorites.test.ts +64 -24
- package/src/favorites/favorites.ts +73 -22
- package/src/installations/installations.test.ts +2 -2
- package/src/installations/installations.ts +2 -2
- package/src/organization/organization.test.ts +2 -2
- package/src/organization/organization.ts +1 -1
- package/src/organizations/organizations.test.ts +2 -2
- package/src/organizations/organizations.ts +1 -1
- package/src/presence/presenceStore.test.ts +15 -22
- package/src/presence/presenceStore.ts +3 -2
- package/src/project/project.test.ts +3 -3
- package/src/project/project.ts +1 -1
- package/src/projection/getProjectionState.test.ts +6 -4
- package/src/projection/getProjectionState.ts +2 -2
- package/src/projects/projects.test.ts +2 -2
- package/src/projects/projects.ts +1 -1
- package/src/query/queryStore.ts +3 -3
- package/src/store/createSanityInstance.test.ts +1 -1
- package/src/store/createSanityInstance.ts +4 -4
- package/src/store/createStoreInstance.test.ts +0 -5
- package/src/store/fetcherStore.test.ts +23 -1
- package/src/store/fetcherStore.ts +3 -3
- package/src/telemetry/telemetryManager.test.ts +1 -1
- package/src/telemetry/telemetryManager.ts +2 -2
- package/src/users/usersStore.test.ts +1 -1
- package/src/users/usersStore.ts +5 -5
- package/src/utils/ids.test.ts +40 -15
- package/src/utils/ids.ts +47 -2
- package/dist/authStore-DKFX8fn7.d.ts.map +0 -1
- package/dist/clientStore-BtE2-q2i.js +0 -90
- package/dist/clientStore-BtE2-q2i.js.map +0 -1
- package/dist/createStateSourceAction-BOKtqFNm.js.map +0 -1
- package/dist/getEnv-D5RGkQLu.js +0 -8
- package/dist/getEnv-D5RGkQLu.js.map +0 -1
- package/dist/logger-DAtJb5RQ.js +0 -173
- package/dist/logger-DAtJb5RQ.js.map +0 -1
- package/dist/object-CxXlSVg7.js +0 -83
- package/dist/object-CxXlSVg7.js.map +0 -1
- package/dist/queryStore-DPf9sN3V.js.map +0 -1
- package/dist/rolldown-runtime-vyAXikos.js +0 -9
- package/dist/telemetryManager-Dq_qCkeI.js +0 -127
- package/dist/telemetryManager-Dq_qCkeI.js.map +0 -1
- package/dist/version-BChjsi4u.js +0 -9
- package/dist/version-BChjsi4u.js.map +0 -1
- package/src/utils/createFetcherStore.test.ts +0 -171
- package/src/utils/createFetcherStore.ts +0 -284
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { t as __exportAll } from "./rolldown-runtime-vyAXikos.js";
|
|
2
|
-
import { n as createLogger } from "./logger-DAtJb5RQ.js";
|
|
3
|
-
import { t as CORE_SDK_VERSION } from "./version-BChjsi4u.js";
|
|
4
|
-
import "@sanity/client";
|
|
5
|
-
import { createBatchedStore, defineEvent } from "@sanity/telemetry";
|
|
6
|
-
/** @internal */
|
|
7
|
-
const SDKSessionStarted = defineEvent({
|
|
8
|
-
name: "SDK Session Started",
|
|
9
|
-
version: 1,
|
|
10
|
-
description: "SDK instance created (environment is recorded in the event context)"
|
|
11
|
-
}), SDKHookMounted = defineEvent({
|
|
12
|
-
name: "SDK Hook Mounted",
|
|
13
|
-
version: 1,
|
|
14
|
-
description: "An SDK hook was mounted for the first time in this session"
|
|
15
|
-
}), SDKSessionEnded = defineEvent({
|
|
16
|
-
name: "SDK Session Ended",
|
|
17
|
-
version: 1,
|
|
18
|
-
description: "SDK instance disposed (environment is recorded in the event context)"
|
|
19
|
-
}), SDKError = defineEvent({
|
|
20
|
-
name: "SDK Error",
|
|
21
|
-
version: 1,
|
|
22
|
-
description: "Runtime error caught in the SDK"
|
|
23
|
-
});
|
|
24
|
-
var telemetryManager_exports = /* @__PURE__ */ __exportAll({ createTelemetryManager: () => createTelemetryManager });
|
|
25
|
-
const log = createLogger("telemetry");
|
|
26
|
-
/**
|
|
27
|
-
* Creates a telemetry manager for a single SDK instance session.
|
|
28
|
-
*
|
|
29
|
-
* The manager initializes a `createBatchedStore` from `@sanity/telemetry`,
|
|
30
|
-
* caches the consent check for the lifetime of the session, and provides
|
|
31
|
-
* typed methods for each SDK telemetry event.
|
|
32
|
-
*
|
|
33
|
-
* @internal
|
|
34
|
-
*/
|
|
35
|
-
function createTelemetryManager(options) {
|
|
36
|
-
let { sessionId, getClient, projectId, environment } = options, startedAt = Date.now(), emittedHooks = /* @__PURE__ */ new Set(), cachedConsent = null, resolveConsent = async () => {
|
|
37
|
-
if (cachedConsent) return cachedConsent;
|
|
38
|
-
try {
|
|
39
|
-
cachedConsent = await getClient().request({
|
|
40
|
-
uri: "/intake/telemetry-status",
|
|
41
|
-
tag: "telemetry-consent.sdk"
|
|
42
|
-
});
|
|
43
|
-
} catch {
|
|
44
|
-
cachedConsent = { status: "undetermined" };
|
|
45
|
-
}
|
|
46
|
-
return cachedConsent;
|
|
47
|
-
}, enrichBatch = (batch) => batch.map((event) => {
|
|
48
|
-
let existing = "context" in event ? event.context : void 0;
|
|
49
|
-
return {
|
|
50
|
-
...event,
|
|
51
|
-
context: {
|
|
52
|
-
...existing,
|
|
53
|
-
version: CORE_SDK_VERSION,
|
|
54
|
-
environment,
|
|
55
|
-
origin: typeof window < "u" ? window.location.origin : "node"
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}), sendEvents = async (batch) => {
|
|
59
|
-
let client = getClient();
|
|
60
|
-
return log.debug("sending event batch", {
|
|
61
|
-
batchSize: batch.length,
|
|
62
|
-
environment
|
|
63
|
-
}), client.request({
|
|
64
|
-
uri: "/intake/batch",
|
|
65
|
-
method: "POST",
|
|
66
|
-
body: {
|
|
67
|
-
projectId,
|
|
68
|
-
batch: enrichBatch(batch)
|
|
69
|
-
},
|
|
70
|
-
tag: "telemetry.batch"
|
|
71
|
-
});
|
|
72
|
-
}, store = createBatchedStore(sessionId, {
|
|
73
|
-
flushInterval: 3e4,
|
|
74
|
-
resolveConsent,
|
|
75
|
-
sendEvents
|
|
76
|
-
}), logger = store.logger;
|
|
77
|
-
return {
|
|
78
|
-
async checkConsent() {
|
|
79
|
-
let { status } = await resolveConsent();
|
|
80
|
-
return status === "granted";
|
|
81
|
-
},
|
|
82
|
-
logSessionStarted(data) {
|
|
83
|
-
log.debug("event: SDK Session Started", {
|
|
84
|
-
projectId: data.projectId,
|
|
85
|
-
perspective: data.perspective,
|
|
86
|
-
authMethod: data.authMethod,
|
|
87
|
-
version: CORE_SDK_VERSION,
|
|
88
|
-
environment
|
|
89
|
-
}), logger.log(SDKSessionStarted, {
|
|
90
|
-
version: CORE_SDK_VERSION,
|
|
91
|
-
...data
|
|
92
|
-
});
|
|
93
|
-
},
|
|
94
|
-
logHookFirstUsed(hookName) {
|
|
95
|
-
emittedHooks.has(hookName) || (emittedHooks.add(hookName), log.debug("event: SDK Hook Mounted", { hookName }), logger.log(SDKHookMounted, { hookName }));
|
|
96
|
-
},
|
|
97
|
-
logError(errorType, hookName) {
|
|
98
|
-
log.debug("event: SDK Error", {
|
|
99
|
-
errorType,
|
|
100
|
-
hookName
|
|
101
|
-
}), logger.log(SDKError, {
|
|
102
|
-
errorType,
|
|
103
|
-
hookName
|
|
104
|
-
});
|
|
105
|
-
},
|
|
106
|
-
endSession() {
|
|
107
|
-
let durationSeconds = Math.round((Date.now() - startedAt) / 1e3);
|
|
108
|
-
log.debug("event: SDK Session Ended", {
|
|
109
|
-
durationSeconds,
|
|
110
|
-
hooksUsed: [...emittedHooks],
|
|
111
|
-
environment
|
|
112
|
-
}), logger.log(SDKSessionEnded, {
|
|
113
|
-
durationSeconds,
|
|
114
|
-
hooksUsed: [...emittedHooks]
|
|
115
|
-
}), store.flush().catch(() => {}), store.end();
|
|
116
|
-
},
|
|
117
|
-
dispose() {
|
|
118
|
-
store.end();
|
|
119
|
-
},
|
|
120
|
-
get hooksUsed() {
|
|
121
|
-
return emittedHooks;
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
export { telemetryManager_exports as t };
|
|
126
|
-
|
|
127
|
-
//# sourceMappingURL=telemetryManager-Dq_qCkeI.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"telemetryManager-Dq_qCkeI.js","names":[],"sources":["../src/telemetry/events.ts","../src/telemetry/telemetryManager.ts"],"sourcesContent":["import {defineEvent} from '@sanity/telemetry'\n\n/** @internal */\nexport const SDKSessionStarted = defineEvent<{\n version: string\n projectId: string\n perspective: string\n authMethod: string\n}>({\n name: 'SDK Session Started',\n version: 1,\n description: 'SDK instance created (environment is recorded in the event context)',\n})\n\n/** @internal */\nexport const SDKHookMounted = defineEvent<{\n hookName: string\n}>({\n name: 'SDK Hook Mounted',\n version: 1,\n description: 'An SDK hook was mounted for the first time in this session',\n})\n\n/** @internal */\nexport const SDKSessionEnded = defineEvent<{\n durationSeconds: number\n hooksUsed: string[]\n}>({\n name: 'SDK Session Ended',\n version: 1,\n description: 'SDK instance disposed (environment is recorded in the event context)',\n})\n\n/** @internal */\nexport const SDKError = defineEvent<{\n errorType: string\n hookName: string\n}>({\n name: 'SDK Error',\n version: 1,\n description: 'Runtime error caught in the SDK',\n})\n","import {type SanityClient} from '@sanity/client'\nimport {\n type ConsentStatus,\n createBatchedStore,\n type SessionId,\n type TelemetryEvent,\n type TelemetryLogger,\n type TelemetryStore,\n} from '@sanity/telemetry'\n\nimport {createLogger} from '../utils/logger'\nimport {CORE_SDK_VERSION} from '../version'\nimport {type TelemetryEnvironment} from './environment'\nimport {SDKError, SDKHookMounted, SDKSessionEnded, SDKSessionStarted} from './events'\n\nconst FLUSH_INTERVAL_MS = 30_000\nconst CONSENT_TAG = 'telemetry-consent.sdk'\nconst BATCH_TAG = 'telemetry.batch'\n\nconst log = createLogger('telemetry')\n\n/**\n * Manages telemetry for a single SDK instance.\n *\n * Wraps `@sanity/telemetry`'s batched store with SDK-specific concerns:\n * consent caching, session lifecycle events, and hook usage tracking.\n * The `environment` is captured at construction time and recorded in\n * the event context so downstream pipelines can distinguish dev and\n * production sessions.\n *\n * @internal\n */\nexport interface TelemetryManager {\n /**\n * Eagerly resolve and cache the user's consent status.\n * Returns true only when the user has explicitly opted in (`granted`).\n * Call this before logging any events to avoid buffering events that\n * will be dropped on the first flush.\n */\n checkConsent(): Promise<boolean>\n\n /** Log a \"SDK Session Started\" event */\n logSessionStarted(data: {projectId: string; perspective: string; authMethod: string}): void\n\n /** Log a \"SDK Hook Mounted\" event (deduplicated per hook name) */\n logHookFirstUsed(hookName: string): void\n\n /** Log a \"SDK Error\" event */\n logError(errorType: string, hookName: string): void\n\n /** Log a \"SDK Session Ended\" event and tear down the store */\n endSession(): void\n\n /** Tear down the store without logging a session-end event */\n dispose(): void\n\n /** The set of hook names used during this session */\n readonly hooksUsed: ReadonlySet<string>\n}\n\ninterface TelemetryManagerOptions {\n sessionId: string\n getClient: () => SanityClient\n projectId: string\n environment: TelemetryEnvironment\n}\n\n/**\n * Creates a telemetry manager for a single SDK instance session.\n *\n * The manager initializes a `createBatchedStore` from `@sanity/telemetry`,\n * caches the consent check for the lifetime of the session, and provides\n * typed methods for each SDK telemetry event.\n *\n * @internal\n */\nexport function createTelemetryManager(options: TelemetryManagerOptions): TelemetryManager {\n const {sessionId, getClient, projectId, environment} = options\n const startedAt = Date.now()\n const emittedHooks = new Set<string>()\n\n let cachedConsent: {status: ConsentStatus} | null = null\n\n const resolveConsent = async (): Promise<{status: ConsentStatus}> => {\n if (cachedConsent) return cachedConsent\n try {\n const client = getClient()\n const result = await client.request<{status: ConsentStatus}>({\n uri: '/intake/telemetry-status',\n tag: CONSENT_TAG,\n })\n cachedConsent = result\n } catch {\n cachedConsent = {status: 'undetermined'}\n }\n return cachedConsent\n }\n\n const enrichBatch = (batch: TelemetryEvent[]) =>\n batch.map((event) => {\n // Trace events (`trace.start` / `trace.log` / `trace.error` /\n // `trace.complete`) arrive with their own caller-provided `context`.\n // Log / userProperties events don't. Narrow via `in` so `event`\n // stays typed as `TelemetryEvent`, then merge so we don't drop the\n // trace context. SDK-owned fields below win on conflict.\n const existing =\n 'context' in event ? (event.context as Record<string, unknown> | undefined) : undefined\n return {\n ...event,\n context: {\n ...existing,\n version: CORE_SDK_VERSION,\n environment,\n origin: typeof window !== 'undefined' ? window.location.origin : 'node',\n },\n }\n })\n\n const sendEvents = async (batch: TelemetryEvent[]): Promise<unknown> => {\n const client = getClient()\n log.debug('sending event batch', {batchSize: batch.length, environment})\n return client.request({\n uri: '/intake/batch',\n method: 'POST',\n body: {projectId, batch: enrichBatch(batch)},\n tag: BATCH_TAG,\n })\n }\n\n const store: TelemetryStore<Record<string, unknown>> = createBatchedStore(\n sessionId as SessionId,\n {\n flushInterval: FLUSH_INTERVAL_MS,\n resolveConsent,\n sendEvents,\n },\n )\n\n const logger: TelemetryLogger<Record<string, unknown>> = store.logger\n\n return {\n async checkConsent() {\n const {status} = await resolveConsent()\n return status === 'granted'\n },\n\n logSessionStarted(data) {\n log.debug('event: SDK Session Started', {\n projectId: data.projectId,\n perspective: data.perspective,\n authMethod: data.authMethod,\n version: CORE_SDK_VERSION,\n environment,\n })\n logger.log(SDKSessionStarted, {\n version: CORE_SDK_VERSION,\n ...data,\n })\n },\n\n logHookFirstUsed(hookName: string) {\n if (emittedHooks.has(hookName)) return\n emittedHooks.add(hookName)\n log.debug('event: SDK Hook Mounted', {hookName})\n logger.log(SDKHookMounted, {hookName})\n },\n\n logError(errorType: string, hookName: string) {\n log.debug('event: SDK Error', {errorType, hookName})\n logger.log(SDKError, {errorType, hookName})\n },\n\n endSession() {\n const durationSeconds = Math.round((Date.now() - startedAt) / 1000)\n log.debug('event: SDK Session Ended', {\n durationSeconds,\n hooksUsed: [...emittedHooks],\n environment,\n })\n logger.log(SDKSessionEnded, {\n durationSeconds,\n hooksUsed: [...emittedHooks],\n })\n\n store.flush().catch(() => {\n // Best-effort flush on dispose; swallow errors\n })\n store.end()\n },\n\n dispose() {\n store.end()\n },\n\n get hooksUsed(): ReadonlySet<string> {\n return emittedHooks\n },\n }\n}\n"],"mappings":";;;;;;AAGA,MAAa,oBAAoB,YAK9B;CACD,MAAM;CACN,SAAS;CACT,aAAa;AACf,CAAC,GAGY,iBAAiB,YAE3B;CACD,MAAM;CACN,SAAS;CACT,aAAa;AACf,CAAC,GAGY,kBAAkB,YAG5B;CACD,MAAM;CACN,SAAS;CACT,aAAa;AACf,CAAC,GAGY,WAAW,YAGrB;CACD,MAAM;CACN,SAAS;CACT,aAAa;AACf,CAAC;;AC1BD,MAIM,MAAM,aAAa,WAAW;;;;;;;;;;AAyDpC,SAAgB,uBAAuB,SAAoD;CACzF,IAAM,EAAC,WAAW,WAAW,WAAW,gBAAe,SACjD,YAAY,KAAK,IAAI,GACrB,+BAAe,IAAI,IAAY,GAEjC,gBAAgD,MAE9C,iBAAiB,YAA8C;EACnE,IAAI,eAAe,OAAO;EAC1B,IAAI;GAMF,gBAAgB,MALD,UACW,CAAC,CAAC,QAAiC;IAC3D,KAAK;IACL,KAAK;GACP,CAAC;EAEH,QAAQ;GACN,gBAAgB,EAAC,QAAQ,eAAc;EACzC;EACA,OAAO;CACT,GAEM,eAAe,UACnB,MAAM,KAAK,UAAU;EAMnB,IAAM,WACJ,aAAa,QAAS,MAAM,UAAkD,KAAA;EAChF,OAAO;GACL,GAAG;GACH,SAAS;IACP,GAAG;IACH,SAAS;IACT;IACA,QAAQ,OAAO,SAAW,MAAc,OAAO,SAAS,SAAS;GACnE;EACF;CACF,CAAC,GAEG,aAAa,OAAO,UAA8C;EACtE,IAAM,SAAS,UAAU;EAEzB,OADA,IAAI,MAAM,uBAAuB;GAAC,WAAW,MAAM;GAAQ;EAAW,CAAC,GAChE,OAAO,QAAQ;GACpB,KAAK;GACL,QAAQ;GACR,MAAM;IAAC;IAAW,OAAO,YAAY,KAAK;GAAC;GAC3C,KAAK;EACP,CAAC;CACH,GAEM,QAAiD,mBACrD,WACA;EACE,eAAe;EACf;EACA;CACF,CACF,GAEM,SAAmD,MAAM;CAE/D,OAAO;EACL,MAAM,eAAe;GACnB,IAAM,EAAC,WAAU,MAAM,eAAe;GACtC,OAAO,WAAW;EACpB;EAEA,kBAAkB,MAAM;GAQtB,AAPA,IAAI,MAAM,8BAA8B;IACtC,WAAW,KAAK;IAChB,aAAa,KAAK;IAClB,YAAY,KAAK;IACjB,SAAS;IACT;GACF,CAAC,GACD,OAAO,IAAI,mBAAmB;IAC5B,SAAS;IACT,GAAG;GACL,CAAC;EACH;EAEA,iBAAiB,UAAkB;GAC7B,aAAa,IAAI,QAAQ,MAC7B,aAAa,IAAI,QAAQ,GACzB,IAAI,MAAM,2BAA2B,EAAC,SAAQ,CAAC,GAC/C,OAAO,IAAI,gBAAgB,EAAC,SAAQ,CAAC;EACvC;EAEA,SAAS,WAAmB,UAAkB;GAE5C,AADA,IAAI,MAAM,oBAAoB;IAAC;IAAW;GAAQ,CAAC,GACnD,OAAO,IAAI,UAAU;IAAC;IAAW;GAAQ,CAAC;EAC5C;EAEA,aAAa;GACX,IAAM,kBAAkB,KAAK,OAAO,KAAK,IAAI,IAAI,aAAa,GAAI;GAclE,AAbA,IAAI,MAAM,4BAA4B;IACpC;IACA,WAAW,CAAC,GAAG,YAAY;IAC3B;GACF,CAAC,GACD,OAAO,IAAI,iBAAiB;IAC1B;IACA,WAAW,CAAC,GAAG,YAAY;GAC7B,CAAC,GAED,MAAM,MAAM,CAAC,CAAC,YAAY,CAE1B,CAAC,GACD,MAAM,IAAI;EACZ;EAEA,UAAU;GACR,MAAM,IAAI;EACZ;EAEA,IAAI,YAAiC;GACnC,OAAO;EACT;CACF;AACF"}
|
package/dist/version-BChjsi4u.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { t as getEnv } from "./getEnv-D5RGkQLu.js";
|
|
2
|
-
/**
|
|
3
|
-
* This version is provided by pkg-utils at build time
|
|
4
|
-
* @internal
|
|
5
|
-
*/
|
|
6
|
-
const CORE_SDK_VERSION = getEnv("PKG_VERSION") || "3.0.0-rc.2-development";
|
|
7
|
-
export { CORE_SDK_VERSION as t };
|
|
8
|
-
|
|
9
|
-
//# sourceMappingURL=version-BChjsi4u.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"version-BChjsi4u.js","names":[],"sources":["../package.json","../src/version.ts"],"sourcesContent":["","import {version} from '../package.json'\nimport {getEnv} from './utils/getEnv'\n\n/**\n * This version is provided by pkg-utils at build time\n * @internal\n */\nexport const CORE_SDK_VERSION = getEnv('PKG_VERSION') || `${version}-development`\n"],"mappings":";;;;;ACOA,MAAa,mBAAmB,OAAO,aAAa,KAAK"}
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import {delay, firstValueFrom, of, throwError} from 'rxjs'
|
|
2
|
-
import {filter, skip} from 'rxjs/operators'
|
|
3
|
-
import {beforeEach, describe, expect, it, vi} from 'vitest'
|
|
4
|
-
|
|
5
|
-
import {createSanityInstance, type SanityInstance} from '../store/createSanityInstance'
|
|
6
|
-
import {createFetcherStore} from './createFetcherStore'
|
|
7
|
-
|
|
8
|
-
describe('createFetcherStore', () => {
|
|
9
|
-
let instance: SanityInstance
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
instance = createSanityInstance({projectId: 'p', dataset: 'd'})
|
|
13
|
-
vi.useRealTimers()
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
afterEach(() => {
|
|
17
|
-
instance.dispose()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('should fetch data and update state when subscribed', async () => {
|
|
21
|
-
const store = createFetcherStore({
|
|
22
|
-
name: 'test',
|
|
23
|
-
fetcher: () => (param: number) => of(`data-${param}`).pipe(delay(100)),
|
|
24
|
-
getKey: (_instance, param: number) => `key-${param}`,
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
const stateSource = store.getState(instance, 1)
|
|
28
|
-
const dataPromise = firstValueFrom(
|
|
29
|
-
stateSource.observable.pipe(filter((data) => data !== undefined)),
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
vi.useFakeTimers()
|
|
33
|
-
await vi.advanceTimersByTimeAsync(100)
|
|
34
|
-
const data = await dataPromise
|
|
35
|
-
expect(data).toBe('data-1')
|
|
36
|
-
vi.useRealTimers()
|
|
37
|
-
|
|
38
|
-
expect(stateSource.getCurrent()).toBe('data-1')
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('should only fetch once for multiple subscriptions within throttle interval', async () => {
|
|
42
|
-
const fetchSpy = vi.fn().mockImplementation((param: number) => of(`data-${param}`))
|
|
43
|
-
const store = createFetcherStore({
|
|
44
|
-
name: 'test-throttle',
|
|
45
|
-
fetcher: () => fetchSpy,
|
|
46
|
-
getKey: (_instance, param: number) => `key-${param}`,
|
|
47
|
-
fetchThrottleInternal: 1000,
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
const stateSource = store.getState(instance, 1)
|
|
51
|
-
const sub1 = stateSource.subscribe()
|
|
52
|
-
const sub2 = stateSource.subscribe()
|
|
53
|
-
|
|
54
|
-
await firstValueFrom(stateSource.observable)
|
|
55
|
-
expect(fetchSpy).toHaveBeenCalledTimes(1)
|
|
56
|
-
|
|
57
|
-
sub1()
|
|
58
|
-
sub2()
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('should propagate errors correctly', async () => {
|
|
62
|
-
const store = createFetcherStore({
|
|
63
|
-
name: 'test-error',
|
|
64
|
-
fetcher: () => () => throwError(() => new Error('test error')),
|
|
65
|
-
getKey: () => 'key',
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
const stateSource = store.getState(instance)
|
|
69
|
-
const dataPromise = firstValueFrom(
|
|
70
|
-
stateSource.observable.pipe(
|
|
71
|
-
// the first value will be `undefined` since the store is not populated
|
|
72
|
-
skip(1),
|
|
73
|
-
),
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
await expect(dataPromise).rejects.toThrow()
|
|
77
|
-
expect(() => stateSource.getCurrent()).toThrow()
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('should clear state after expiration delay', async () => {
|
|
81
|
-
const fetchSpy = vi
|
|
82
|
-
.fn()
|
|
83
|
-
.mockImplementation((param: number) => of(`data-${param}`).pipe(delay(100)))
|
|
84
|
-
const store = createFetcherStore({
|
|
85
|
-
name: 'test-expiration',
|
|
86
|
-
fetcher: () => fetchSpy,
|
|
87
|
-
getKey: (_instance, param: number) => `key-${param}`,
|
|
88
|
-
stateExpirationDelay: 1000,
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
// First subscription
|
|
92
|
-
const stateSource1 = store.getState(instance, 1)
|
|
93
|
-
const sub1 = stateSource1.subscribe()
|
|
94
|
-
await firstValueFrom(stateSource1.observable.pipe(filter((data) => data !== undefined)))
|
|
95
|
-
expect(fetchSpy).toHaveBeenCalledTimes(1)
|
|
96
|
-
|
|
97
|
-
sub1()
|
|
98
|
-
|
|
99
|
-
// Wait for expiration delay
|
|
100
|
-
vi.useFakeTimers()
|
|
101
|
-
await vi.advanceTimersByTimeAsync(1000)
|
|
102
|
-
|
|
103
|
-
// Second subscription
|
|
104
|
-
const stateSource2 = store.getState(instance, 1)
|
|
105
|
-
const sub2 = stateSource2.subscribe()
|
|
106
|
-
await firstValueFrom(stateSource2.observable.pipe(filter((data) => data !== undefined)))
|
|
107
|
-
expect(fetchSpy).toHaveBeenCalledTimes(2)
|
|
108
|
-
|
|
109
|
-
sub2()
|
|
110
|
-
vi.useRealTimers()
|
|
111
|
-
})
|
|
112
|
-
|
|
113
|
-
it('should throttle fetches based on fetchThrottleInternal', async () => {
|
|
114
|
-
const fetchSpy = vi.fn().mockImplementation((param: number) => of(`data-${param}`))
|
|
115
|
-
const store = createFetcherStore({
|
|
116
|
-
name: 'test-throttle',
|
|
117
|
-
fetcher: () => fetchSpy,
|
|
118
|
-
getKey: (_instance, param: number) => `key-${param}`,
|
|
119
|
-
fetchThrottleInternal: 1000,
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
const stateSource = store.getState(instance, 1)
|
|
123
|
-
|
|
124
|
-
// First subscription
|
|
125
|
-
const sub1 = stateSource.subscribe()
|
|
126
|
-
await firstValueFrom(stateSource.observable)
|
|
127
|
-
expect(fetchSpy).toHaveBeenCalledTimes(1)
|
|
128
|
-
|
|
129
|
-
// Second subscription within throttle interval
|
|
130
|
-
const stateSource2 = store.getState(instance, 1)
|
|
131
|
-
const sub2 = stateSource2.subscribe()
|
|
132
|
-
await firstValueFrom(stateSource2.observable)
|
|
133
|
-
expect(fetchSpy).toHaveBeenCalledTimes(1)
|
|
134
|
-
|
|
135
|
-
// Advance past throttle interval
|
|
136
|
-
vi.useFakeTimers()
|
|
137
|
-
await vi.advanceTimersByTimeAsync(1000)
|
|
138
|
-
|
|
139
|
-
// Third subscription after throttle interval
|
|
140
|
-
const stateSource3 = store.getState(instance, 1)
|
|
141
|
-
const sub3 = stateSource3.subscribe()
|
|
142
|
-
await firstValueFrom(stateSource3.observable)
|
|
143
|
-
expect(fetchSpy).toHaveBeenCalledTimes(2)
|
|
144
|
-
|
|
145
|
-
sub1()
|
|
146
|
-
sub2()
|
|
147
|
-
sub3()
|
|
148
|
-
vi.useRealTimers()
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
it('should handle different parameters with different keys', async () => {
|
|
152
|
-
const store = createFetcherStore({
|
|
153
|
-
name: 'test-params',
|
|
154
|
-
fetcher: () => (param: number) => of(`data-${param}`),
|
|
155
|
-
getKey: (_instance, param: number) => `key-${param}`,
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
const stateSource1 = store.getState(instance, 1)
|
|
159
|
-
const stateSource2 = store.getState(instance, 2)
|
|
160
|
-
|
|
161
|
-
const data1 = await firstValueFrom(
|
|
162
|
-
stateSource1.observable.pipe(filter((data) => data !== undefined)),
|
|
163
|
-
)
|
|
164
|
-
const data2 = await firstValueFrom(
|
|
165
|
-
stateSource2.observable.pipe(filter((data) => data !== undefined)),
|
|
166
|
-
)
|
|
167
|
-
|
|
168
|
-
expect(data1).toBe('data-1')
|
|
169
|
-
expect(data2).toBe('data-2')
|
|
170
|
-
})
|
|
171
|
-
})
|
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import {asapScheduler, EMPTY, firstValueFrom, from, Observable} from 'rxjs'
|
|
2
|
-
import {
|
|
3
|
-
catchError,
|
|
4
|
-
delay,
|
|
5
|
-
filter,
|
|
6
|
-
first,
|
|
7
|
-
groupBy,
|
|
8
|
-
map,
|
|
9
|
-
mergeMap,
|
|
10
|
-
pairwise,
|
|
11
|
-
startWith,
|
|
12
|
-
switchMap,
|
|
13
|
-
tap,
|
|
14
|
-
} from 'rxjs/operators'
|
|
15
|
-
|
|
16
|
-
import {bindActionGlobally, type BoundStoreAction} from '../store/createActionBinder'
|
|
17
|
-
import {type SanityInstance} from '../store/createSanityInstance'
|
|
18
|
-
import {
|
|
19
|
-
createStateSourceAction,
|
|
20
|
-
type SelectorContext,
|
|
21
|
-
type StateSource,
|
|
22
|
-
} from '../store/createStateSourceAction'
|
|
23
|
-
import {defineStore, type StoreContext} from '../store/defineStore'
|
|
24
|
-
import {insecureRandomId} from '../utils/ids'
|
|
25
|
-
import {omitProperty} from '../utils/object'
|
|
26
|
-
import {setCleanupTimeout} from './setCleanupTimeout'
|
|
27
|
-
|
|
28
|
-
interface CreateFetcherStoreOptions<TParams extends unknown[], TData> {
|
|
29
|
-
/**
|
|
30
|
-
* A unique name for this store (for devtools)
|
|
31
|
-
*/
|
|
32
|
-
name: string
|
|
33
|
-
/**
|
|
34
|
-
* A function that creates the observable that will be used to fetch the data.
|
|
35
|
-
*/
|
|
36
|
-
fetcher: (instance: SanityInstance) => (...params: TParams) => Observable<TData>
|
|
37
|
-
/**
|
|
38
|
-
* The function used to convert the params into keys that state related to
|
|
39
|
-
* those params will be stored.
|
|
40
|
-
*/
|
|
41
|
-
getKey: (instance: SanityInstance, ...params: TParams) => string
|
|
42
|
-
/**
|
|
43
|
-
* Delay in ms before clearing state after the last subscription is removed.
|
|
44
|
-
* This results in react components suspending again due to no previous state
|
|
45
|
-
* to show.
|
|
46
|
-
*/
|
|
47
|
-
stateExpirationDelay?: number
|
|
48
|
-
/**
|
|
49
|
-
* The minimum time (ms) that must elapse since the last fetch for the same key
|
|
50
|
-
*/
|
|
51
|
-
fetchThrottleInternal?: number
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface StoreEntry<TParams extends unknown[], TData> {
|
|
55
|
-
params: TParams
|
|
56
|
-
instance: SanityInstance
|
|
57
|
-
key: string
|
|
58
|
-
data?: TData
|
|
59
|
-
error?: unknown
|
|
60
|
-
subscriptions: string[]
|
|
61
|
-
lastFetchInitiatedAt?: string
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Internal helper type
|
|
66
|
-
* @public
|
|
67
|
-
*/
|
|
68
|
-
export interface FetcherStoreState<TParams extends unknown[], TData> {
|
|
69
|
-
stateByParams: {[TSerializedKey in string]?: StoreEntry<TParams, TData>}
|
|
70
|
-
error?: unknown
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Internal helper type
|
|
75
|
-
* @public
|
|
76
|
-
*/
|
|
77
|
-
export interface FetcherStore<TParams extends unknown[], TData> {
|
|
78
|
-
getState: BoundStoreAction<
|
|
79
|
-
FetcherStoreState<TParams, TData>,
|
|
80
|
-
TParams,
|
|
81
|
-
StateSource<TData | undefined>
|
|
82
|
-
>
|
|
83
|
-
resolveState: BoundStoreAction<FetcherStoreState<TParams, TData>, TParams, Promise<TData>>
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Creates a store from a function that returns an observable that fetches data
|
|
88
|
-
* that supports parameterized state caching.
|
|
89
|
-
*
|
|
90
|
-
* This function creates a resource store keyed by parameter values (using the
|
|
91
|
-
* provided `getKey` function) and returns a state source (via `getState`)
|
|
92
|
-
* that components can subscribe to. When a new subscription is added, and if
|
|
93
|
-
* enough time has passed since the last fetch (controlled by
|
|
94
|
-
* `fetchThrottleInternal`), it invokes the observable factory (via
|
|
95
|
-
* `getObservable`) to fetch fresh data. The data is stored in state and can be
|
|
96
|
-
* accessed reactively.
|
|
97
|
-
*
|
|
98
|
-
* Additionally, the store provides a `resolveState` function that returns a
|
|
99
|
-
* Promise resolving with the next non-undefined value from the state source.
|
|
100
|
-
*
|
|
101
|
-
* State expiration is implemented: after the last subscription for a key is
|
|
102
|
-
* removed, its state is cleared after `stateExpirationDelay` ms, causing
|
|
103
|
-
* components to suspend until fresh data is fetched.
|
|
104
|
-
*/
|
|
105
|
-
export function createFetcherStore<TParams extends unknown[], TData>({
|
|
106
|
-
name,
|
|
107
|
-
fetcher: getObservable,
|
|
108
|
-
getKey,
|
|
109
|
-
fetchThrottleInternal = 1000,
|
|
110
|
-
stateExpirationDelay = 5000,
|
|
111
|
-
}: CreateFetcherStoreOptions<TParams, TData>): FetcherStore<TParams, TData> {
|
|
112
|
-
const store = defineStore<FetcherStoreState<TParams, TData>>({
|
|
113
|
-
name,
|
|
114
|
-
getInitialState: () => ({
|
|
115
|
-
stateByParams: {},
|
|
116
|
-
}),
|
|
117
|
-
initialize: (context) => {
|
|
118
|
-
const subscription = subscribeToSubscriptionsAndFetch(context)
|
|
119
|
-
return () => subscription.unsubscribe()
|
|
120
|
-
},
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* For each key in state.stateByParams we set up a grouped stream.
|
|
125
|
-
* When a subscription is added (i.e. the subscriptions array length increases)
|
|
126
|
-
* and if enough time has elapsed since the last fetch, we update the timestamp
|
|
127
|
-
* and call the factory function for that key.
|
|
128
|
-
*/
|
|
129
|
-
const subscribeToSubscriptionsAndFetch = ({
|
|
130
|
-
state,
|
|
131
|
-
}: StoreContext<FetcherStoreState<TParams, TData>>) => {
|
|
132
|
-
return state.observable
|
|
133
|
-
.pipe(
|
|
134
|
-
// Map the state to an array of [serialized, entry] pairs.
|
|
135
|
-
switchMap((s: FetcherStoreState<TParams, TData>) => {
|
|
136
|
-
const entries = Object.entries(s.stateByParams)
|
|
137
|
-
return entries.length > 0 ? from(entries) : EMPTY
|
|
138
|
-
}),
|
|
139
|
-
// Group by the serialized key.
|
|
140
|
-
groupBy(([key]) => key),
|
|
141
|
-
mergeMap((group$) =>
|
|
142
|
-
group$.pipe(
|
|
143
|
-
// Emit an initial value for pairwise comparisons.
|
|
144
|
-
startWith<[string, StoreEntry<TParams, TData> | undefined]>([group$.key, undefined]),
|
|
145
|
-
pairwise(),
|
|
146
|
-
// Trigger only when the subscriptions array grows.
|
|
147
|
-
filter(([[, prevEntry], [, currEntry]]) => {
|
|
148
|
-
const prevSubs = prevEntry?.subscriptions ?? []
|
|
149
|
-
const currSubs = currEntry?.subscriptions ?? []
|
|
150
|
-
return currSubs.length > prevSubs.length
|
|
151
|
-
}),
|
|
152
|
-
map(([, [, currEntry]]) => currEntry),
|
|
153
|
-
|
|
154
|
-
// Only trigger if we haven't fetched recently.
|
|
155
|
-
filter((entry) => {
|
|
156
|
-
const lastFetch = entry?.lastFetchInitiatedAt
|
|
157
|
-
if (!lastFetch) return true
|
|
158
|
-
return Date.now() - new Date(lastFetch).getTime() >= fetchThrottleInternal
|
|
159
|
-
}),
|
|
160
|
-
switchMap((entry) => {
|
|
161
|
-
// Retrieve params from the entry
|
|
162
|
-
if (!entry) return EMPTY
|
|
163
|
-
|
|
164
|
-
// Record that a fetch is being initiated.
|
|
165
|
-
state.set('setLastFetchInitiatedAt', (prev: FetcherStoreState<TParams, TData>) => ({
|
|
166
|
-
stateByParams: {
|
|
167
|
-
...prev.stateByParams,
|
|
168
|
-
[entry.key]: {
|
|
169
|
-
...entry,
|
|
170
|
-
...prev.stateByParams[entry.key],
|
|
171
|
-
lastFetchInitiatedAt: new Date().toISOString(),
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
}))
|
|
175
|
-
|
|
176
|
-
const factoryFn = getObservable(entry.instance)
|
|
177
|
-
return factoryFn(...entry.params).pipe(
|
|
178
|
-
// the `createStateSourceAction` util requires the update
|
|
179
|
-
// to
|
|
180
|
-
delay(0, asapScheduler),
|
|
181
|
-
tap((data: TData) =>
|
|
182
|
-
state.set('setData', (prev: FetcherStoreState<TParams, TData>) => ({
|
|
183
|
-
stateByParams: {
|
|
184
|
-
...prev.stateByParams,
|
|
185
|
-
[entry.key]: {
|
|
186
|
-
...omitProperty(entry, 'error'),
|
|
187
|
-
...(prev.stateByParams[entry.key]
|
|
188
|
-
? omitProperty(prev.stateByParams[entry.key], 'error')
|
|
189
|
-
: {}),
|
|
190
|
-
data,
|
|
191
|
-
},
|
|
192
|
-
},
|
|
193
|
-
})),
|
|
194
|
-
),
|
|
195
|
-
catchError((error) => {
|
|
196
|
-
state.set('setError', (prev) => ({
|
|
197
|
-
stateByParams: {
|
|
198
|
-
...prev.stateByParams,
|
|
199
|
-
[entry.key]: {
|
|
200
|
-
...entry,
|
|
201
|
-
...prev.stateByParams[entry.key],
|
|
202
|
-
error,
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
}))
|
|
206
|
-
|
|
207
|
-
return EMPTY
|
|
208
|
-
}),
|
|
209
|
-
)
|
|
210
|
-
}),
|
|
211
|
-
),
|
|
212
|
-
),
|
|
213
|
-
)
|
|
214
|
-
.subscribe({
|
|
215
|
-
error: (error) => state.set('setError', {error}),
|
|
216
|
-
})
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
const getState = bindActionGlobally(
|
|
220
|
-
store,
|
|
221
|
-
createStateSourceAction({
|
|
222
|
-
selector: (
|
|
223
|
-
{
|
|
224
|
-
instance,
|
|
225
|
-
state: {stateByParams, error},
|
|
226
|
-
}: SelectorContext<FetcherStoreState<TParams, TData>>,
|
|
227
|
-
...params: TParams
|
|
228
|
-
) => {
|
|
229
|
-
if (error) throw error
|
|
230
|
-
const key = getKey(instance, ...params)
|
|
231
|
-
const entry = stateByParams[key]
|
|
232
|
-
if (entry?.error) throw entry.error
|
|
233
|
-
return entry?.data
|
|
234
|
-
},
|
|
235
|
-
onSubscribe: ({instance, state}, ...params: TParams) => {
|
|
236
|
-
const subscriptionId = insecureRandomId()
|
|
237
|
-
const key = getKey(instance, ...params)
|
|
238
|
-
|
|
239
|
-
state.set('addSubscription', (prev: FetcherStoreState<TParams, TData>) => ({
|
|
240
|
-
stateByParams: {
|
|
241
|
-
...prev.stateByParams,
|
|
242
|
-
[key]: {
|
|
243
|
-
...prev.stateByParams[key],
|
|
244
|
-
instance,
|
|
245
|
-
key,
|
|
246
|
-
params: prev.stateByParams[key]?.params || params,
|
|
247
|
-
subscriptions: [...(prev.stateByParams[key]?.subscriptions || []), subscriptionId],
|
|
248
|
-
},
|
|
249
|
-
},
|
|
250
|
-
}))
|
|
251
|
-
|
|
252
|
-
return () => {
|
|
253
|
-
setCleanupTimeout(() => {
|
|
254
|
-
state.set('removeSubscription', (prev: FetcherStoreState<TParams, TData>) => {
|
|
255
|
-
const entry = prev.stateByParams[key]
|
|
256
|
-
if (!entry) return prev
|
|
257
|
-
|
|
258
|
-
const newSubs = (entry.subscriptions || []).filter((id) => id !== subscriptionId)
|
|
259
|
-
if (newSubs.length === 0) {
|
|
260
|
-
return {stateByParams: omitProperty(prev.stateByParams, key)}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
return {
|
|
264
|
-
stateByParams: {
|
|
265
|
-
...prev.stateByParams,
|
|
266
|
-
[key]: {
|
|
267
|
-
...entry,
|
|
268
|
-
subscriptions: newSubs,
|
|
269
|
-
},
|
|
270
|
-
},
|
|
271
|
-
}
|
|
272
|
-
})
|
|
273
|
-
}, stateExpirationDelay)
|
|
274
|
-
}
|
|
275
|
-
},
|
|
276
|
-
}),
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
const resolveState = bindActionGlobally(store, ({instance}, ...params: TParams) =>
|
|
280
|
-
firstValueFrom(getState(instance, ...params).observable.pipe(first((i) => i !== undefined))),
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
return {getState, resolveState}
|
|
284
|
-
}
|