@isograph/react 0.0.0-main-a840a70e → 0.0.0-main-c09c9dbf
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/.turbo/turbo-compile-libs.log +8 -5
- package/.turbo/turbo-tsc.log +2 -2
- package/dist/_virtual/{rolldown_runtime.js → rolldown_runtime.cjs} +10 -6
- package/dist/core/{FragmentReference.js → FragmentReference.cjs} +1 -1
- package/dist/core/{FragmentReference.d.ts → FragmentReference.d.cts} +5 -5
- package/dist/core/FragmentReference.d.cts.map +1 -0
- package/dist/core/FragmentReference.d.mts.map +1 -1
- package/dist/core/{IsographEnvironment.js → IsographEnvironment.cjs} +5 -5
- package/dist/core/{IsographEnvironment.d.ts → IsographEnvironment.d.cts} +15 -16
- package/dist/core/IsographEnvironment.d.cts.map +1 -0
- package/dist/core/IsographEnvironment.d.mts +5 -6
- package/dist/core/IsographEnvironment.d.mts.map +1 -1
- package/dist/core/IsographEnvironment.mjs +3 -3
- package/dist/core/IsographEnvironment.mjs.map +1 -1
- package/dist/core/{PromiseWrapper.d.ts → PromiseWrapper.d.cts} +1 -1
- package/dist/core/PromiseWrapper.d.cts.map +1 -0
- package/dist/core/PromiseWrapper.d.mts.map +1 -1
- package/dist/core/PromiseWrapper.mjs.map +1 -1
- package/dist/core/{areEqualWithDeepComparison.js → areEqualWithDeepComparison.cjs} +7 -7
- package/dist/core/areEqualWithDeepComparison.mjs +7 -7
- package/dist/core/areEqualWithDeepComparison.mjs.map +1 -1
- package/dist/core/{brand.d.ts → brand.d.cts} +2 -2
- package/dist/core/brand.d.cts.map +1 -0
- package/dist/core/brand.d.mts +1 -1
- package/dist/core/brand.d.mts.map +1 -1
- package/dist/core/{cache.js → cache.cjs} +11 -12
- package/dist/core/cache.d.cts +44 -0
- package/dist/core/cache.d.cts.map +1 -0
- package/dist/core/cache.d.mts +27 -19
- package/dist/core/cache.d.mts.map +1 -1
- package/dist/core/cache.mjs +4 -4
- package/dist/core/cache.mjs.map +1 -1
- package/dist/core/{check.js → check.cjs} +4 -4
- package/dist/core/{check.d.ts → check.d.cts} +4 -4
- package/dist/core/check.d.cts.map +1 -0
- package/dist/core/check.d.mts.map +1 -1
- package/dist/core/check.mjs.map +1 -1
- package/dist/core/{componentCache.js → componentCache.cjs} +2 -2
- package/dist/core/{entrypoint.d.ts → entrypoint.d.cts} +7 -7
- package/dist/core/entrypoint.d.cts.map +1 -0
- package/dist/core/entrypoint.d.mts.map +1 -1
- package/dist/core/{garbageCollection.js → garbageCollection.cjs} +3 -3
- package/dist/core/{garbageCollection.d.ts → garbageCollection.d.cts} +4 -4
- package/dist/core/garbageCollection.d.cts.map +1 -0
- package/dist/core/garbageCollection.d.mts.map +1 -1
- package/dist/core/garbageCollection.mjs.map +1 -1
- package/dist/core/{getOrCreateCacheForArtifact.js → getOrCreateCacheForArtifact.cjs} +4 -4
- package/dist/core/getOrCreateCacheForArtifact.mjs.map +1 -1
- package/dist/core/{logging.d.ts → logging.d.cts} +9 -10
- package/dist/core/logging.d.cts.map +1 -0
- package/dist/core/logging.d.mts +0 -1
- package/dist/core/logging.d.mts.map +1 -1
- package/dist/core/{makeNetworkRequest.js → makeNetworkRequest.cjs} +15 -15
- package/dist/core/{makeNetworkRequest.d.ts → makeNetworkRequest.d.cts} +7 -7
- package/dist/core/makeNetworkRequest.d.cts.map +1 -0
- package/dist/core/makeNetworkRequest.d.mts.map +1 -1
- package/dist/core/makeNetworkRequest.mjs +4 -4
- package/dist/core/makeNetworkRequest.mjs.map +1 -1
- package/dist/core/{optimisticProxy.js → optimisticProxy.cjs} +2 -2
- package/dist/core/{optimisticProxy.d.ts → optimisticProxy.d.cts} +2 -3
- package/dist/core/optimisticProxy.d.cts.map +1 -0
- package/dist/core/optimisticProxy.d.mts +0 -1
- package/dist/core/optimisticProxy.d.mts.map +1 -1
- package/dist/core/optimisticProxy.mjs.map +1 -1
- package/dist/core/{read.js → read.cjs} +47 -47
- package/dist/core/{read.d.ts → read.d.cts} +4 -5
- package/dist/core/read.d.cts.map +1 -0
- package/dist/core/read.d.mts.map +1 -1
- package/dist/core/read.mjs +39 -39
- package/dist/core/read.mjs.map +1 -1
- package/dist/core/{reader.d.ts → reader.d.cts} +6 -6
- package/dist/core/reader.d.cts.map +1 -0
- package/dist/core/reader.d.mts.map +1 -1
- package/dist/core/{startUpdate.js → startUpdate.cjs} +14 -14
- package/dist/core/startUpdate.mjs +6 -6
- package/dist/core/startUpdate.mjs.map +1 -1
- package/dist/core/{subscribe.js → subscribe.cjs} +3 -3
- package/dist/core/{subscribe.d.ts → subscribe.d.cts} +6 -6
- package/dist/core/subscribe.d.cts.map +1 -0
- package/dist/core/subscribe.d.mts.map +1 -1
- package/dist/core/subscribe.mjs.map +1 -1
- package/dist/core/{util.d.ts → util.d.cts} +1 -1
- package/dist/core/util.d.cts.map +1 -0
- package/dist/core/util.d.mts.map +1 -1
- package/dist/core/util.mjs.map +1 -1
- package/dist/core/{writeData.js → writeData.cjs} +6 -6
- package/dist/core/{writeData.d.ts → writeData.d.cts} +6 -6
- package/dist/core/writeData.d.cts.map +1 -0
- package/dist/core/writeData.d.mts +1 -1
- package/dist/core/writeData.d.mts.map +1 -1
- package/dist/core/writeData.mjs.map +1 -1
- package/dist/{index.js → index.cjs} +29 -29
- package/dist/{index.d.ts → index.d.cts} +31 -31
- package/dist/loadable-hooks/useClientSideDefer.cjs +14 -0
- package/dist/loadable-hooks/{useClientSideDefer.d.ts → useClientSideDefer.d.cts} +4 -4
- package/dist/loadable-hooks/useClientSideDefer.d.cts.map +1 -0
- package/dist/loadable-hooks/useClientSideDefer.d.mts.map +1 -1
- package/dist/loadable-hooks/{useConnectionSpecPagination.js → useConnectionSpecPagination.cjs} +13 -16
- package/dist/loadable-hooks/{useConnectionSpecPagination.d.ts → useConnectionSpecPagination.d.cts} +4 -4
- package/dist/loadable-hooks/useConnectionSpecPagination.d.cts.map +1 -0
- package/dist/loadable-hooks/useConnectionSpecPagination.d.mts.map +1 -1
- package/dist/loadable-hooks/useConnectionSpecPagination.mjs.map +1 -1
- package/dist/loadable-hooks/{useImperativeExposedMutationField.d.ts → useImperativeExposedMutationField.d.cts} +1 -1
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.cts.map +1 -0
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.mts.map +1 -1
- package/dist/loadable-hooks/{useImperativeLoadableField.js → useImperativeLoadableField.cjs} +4 -5
- package/dist/loadable-hooks/{useImperativeLoadableField.d.ts → useImperativeLoadableField.d.cts} +4 -4
- package/dist/loadable-hooks/useImperativeLoadableField.d.cts.map +1 -0
- package/dist/loadable-hooks/useImperativeLoadableField.d.mts.map +1 -1
- package/dist/loadable-hooks/{useSkipLimitPagination.js → useSkipLimitPagination.cjs} +13 -16
- package/dist/loadable-hooks/{useSkipLimitPagination.d.ts → useSkipLimitPagination.d.cts} +4 -4
- package/dist/loadable-hooks/useSkipLimitPagination.d.cts.map +1 -0
- package/dist/loadable-hooks/useSkipLimitPagination.d.mts.map +1 -1
- package/dist/loadable-hooks/useSkipLimitPagination.mjs.map +1 -1
- package/dist/react/{FragmentReader.js → FragmentReader.cjs} +1 -1
- package/dist/react/{FragmentReader.d.ts → FragmentReader.d.cts} +5 -5
- package/dist/react/FragmentReader.d.cts.map +1 -0
- package/dist/react/FragmentReader.d.mts.map +1 -1
- package/dist/react/{FragmentRenderer.js → FragmentRenderer.cjs} +2 -2
- package/dist/react/{FragmentRenderer.d.ts → FragmentRenderer.d.cts} +5 -5
- package/dist/react/FragmentRenderer.d.cts.map +1 -0
- package/dist/react/FragmentRenderer.d.mts.map +1 -1
- package/dist/react/{IsographEnvironmentProvider.js → IsographEnvironmentProvider.cjs} +1 -1
- package/dist/react/{IsographEnvironmentProvider.d.ts → IsographEnvironmentProvider.d.cts} +2 -2
- package/dist/react/IsographEnvironmentProvider.d.cts.map +1 -0
- package/dist/react/IsographEnvironmentProvider.d.mts.map +1 -1
- package/dist/react/{LoadableFieldReader.js → LoadableFieldReader.cjs} +3 -3
- package/dist/react/{LoadableFieldReader.d.ts → LoadableFieldReader.d.cts} +5 -5
- package/dist/react/LoadableFieldReader.d.cts.map +1 -0
- package/dist/react/LoadableFieldReader.d.mts.map +1 -1
- package/dist/react/{LoadableFieldRenderer.js → LoadableFieldRenderer.cjs} +3 -3
- package/dist/react/{LoadableFieldRenderer.d.ts → LoadableFieldRenderer.d.cts} +5 -5
- package/dist/react/LoadableFieldRenderer.d.cts.map +1 -0
- package/dist/react/LoadableFieldRenderer.d.mts.map +1 -1
- package/dist/react/{RenderAfterCommit__DO_NOT_USE.js → RenderAfterCommit__DO_NOT_USE.cjs} +1 -2
- package/dist/react/{RenderAfterCommit__DO_NOT_USE.d.ts → RenderAfterCommit__DO_NOT_USE.d.cts} +1 -2
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.cts.map +1 -0
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.mts +0 -1
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.mts.map +1 -1
- package/dist/react/{createIsographEnvironment.js → createIsographEnvironment.cjs} +2 -2
- package/dist/react/{createIsographEnvironment.d.ts → createIsographEnvironment.d.cts} +3 -3
- package/dist/react/createIsographEnvironment.d.cts.map +1 -0
- package/dist/react/createIsographEnvironment.d.mts +0 -1
- package/dist/react/createIsographEnvironment.d.mts.map +1 -1
- package/dist/react/{maybeUnwrapNetworkRequest.js → maybeUnwrapNetworkRequest.cjs} +1 -1
- package/dist/react/{useImperativeReference.js → useImperativeReference.cjs} +7 -8
- package/dist/react/{useImperativeReference.d.ts → useImperativeReference.d.cts} +5 -6
- package/dist/react/useImperativeReference.d.cts.map +1 -0
- package/dist/react/useImperativeReference.d.mts +0 -1
- package/dist/react/useImperativeReference.d.mts.map +1 -1
- package/dist/react/useLazyReference.cjs +18 -0
- package/dist/react/{useLazyReference.d.ts → useLazyReference.d.cts} +5 -6
- package/dist/react/useLazyReference.d.cts.map +1 -0
- package/dist/react/useLazyReference.d.mts +0 -1
- package/dist/react/useLazyReference.d.mts.map +1 -1
- package/dist/react/{useReadAndSubscribe.js → useReadAndSubscribe.cjs} +9 -10
- package/dist/react/{useReadAndSubscribe.d.ts → useReadAndSubscribe.d.cts} +4 -5
- package/dist/react/useReadAndSubscribe.d.cts.map +1 -0
- package/dist/react/useReadAndSubscribe.d.mts +0 -1
- package/dist/react/useReadAndSubscribe.d.mts.map +1 -1
- package/dist/react/useReadAndSubscribe.mjs.map +1 -1
- package/dist/react/{useRerenderOnChange.js → useRerenderOnChange.cjs} +3 -4
- package/dist/react/{useRerenderOnChange.d.ts → useRerenderOnChange.d.cts} +4 -4
- package/dist/react/useRerenderOnChange.d.cts.map +1 -0
- package/dist/react/useRerenderOnChange.d.mts.map +1 -1
- package/dist/react/{useResult.js → useResult.cjs} +7 -7
- package/dist/react/{useResult.d.ts → useResult.d.cts} +3 -3
- package/dist/react/useResult.d.cts.map +1 -0
- package/dist/react/useResult.d.mts.map +1 -1
- package/package.json +9 -9
- package/src/core/IsographEnvironment.ts +8 -4
- package/src/core/cache.ts +38 -25
- package/src/core/getOrCreateCacheForArtifact.ts +2 -2
- package/src/core/writeData.ts +4 -4
- package/src/tests/garbageCollection.test.ts +11 -11
- package/src/tests/normalizeData.test.ts +11 -3
- package/src/tests/optimisticProxy.test.ts +23 -23
- package/src/tests/startUpdate.test.ts +2 -2
- package/tsconfig.json +5 -4
- package/tsconfig.package.json +8 -0
- package/tsconfig.package.tsbuildinfo +1 -0
- package/tsconfig.test.json +12 -0
- package/tsconfig.test.tsbuildinfo +1 -0
- package/tsdown.config.ts +8 -0
- package/vitest.config.ts +1 -1
- package/dist/core/FragmentReference.d.ts.map +0 -1
- package/dist/core/IsographEnvironment.d.ts.map +0 -1
- package/dist/core/PromiseWrapper.d.ts.map +0 -1
- package/dist/core/brand.d.ts.map +0 -1
- package/dist/core/cache.d.ts +0 -37
- package/dist/core/cache.d.ts.map +0 -1
- package/dist/core/check.d.ts.map +0 -1
- package/dist/core/entrypoint.d.ts.map +0 -1
- package/dist/core/garbageCollection.d.ts.map +0 -1
- package/dist/core/logging.d.ts.map +0 -1
- package/dist/core/makeNetworkRequest.d.ts.map +0 -1
- package/dist/core/optimisticProxy.d.ts.map +0 -1
- package/dist/core/read.d.ts.map +0 -1
- package/dist/core/reader.d.ts.map +0 -1
- package/dist/core/subscribe.d.ts.map +0 -1
- package/dist/core/util.d.ts.map +0 -1
- package/dist/core/writeData.d.ts.map +0 -1
- package/dist/loadable-hooks/useClientSideDefer.d.ts.map +0 -1
- package/dist/loadable-hooks/useClientSideDefer.js +0 -15
- package/dist/loadable-hooks/useConnectionSpecPagination.d.ts.map +0 -1
- package/dist/loadable-hooks/useImperativeExposedMutationField.d.ts.map +0 -1
- package/dist/loadable-hooks/useImperativeLoadableField.d.ts.map +0 -1
- package/dist/loadable-hooks/useSkipLimitPagination.d.ts.map +0 -1
- package/dist/react/FragmentReader.d.ts.map +0 -1
- package/dist/react/FragmentRenderer.d.ts.map +0 -1
- package/dist/react/IsographEnvironmentProvider.d.ts.map +0 -1
- package/dist/react/LoadableFieldReader.d.ts.map +0 -1
- package/dist/react/LoadableFieldRenderer.d.ts.map +0 -1
- package/dist/react/RenderAfterCommit__DO_NOT_USE.d.ts.map +0 -1
- package/dist/react/createIsographEnvironment.d.ts.map +0 -1
- package/dist/react/useImperativeReference.d.ts.map +0 -1
- package/dist/react/useLazyReference.d.ts.map +0 -1
- package/dist/react/useLazyReference.js +0 -19
- package/dist/react/useReadAndSubscribe.d.ts.map +0 -1
- package/dist/react/useRerenderOnChange.d.ts.map +0 -1
- package/dist/react/useResult.d.ts.map +0 -1
- package/src/tests/tsconfig.json +0 -21
- package/tsconfig.pkg.json +0 -16
- /package/dist/core/{PromiseWrapper.js → PromiseWrapper.cjs} +0 -0
- /package/dist/core/{entrypoint.js → entrypoint.cjs} +0 -0
- /package/dist/core/{logging.js → logging.cjs} +0 -0
- /package/dist/core/{util.js → util.cjs} +0 -0
- /package/dist/loadable-hooks/{useImperativeExposedMutationField.js → useImperativeExposedMutationField.cjs} +0 -0
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
const require_PromiseWrapper = require('./PromiseWrapper.
|
|
2
|
-
const require_IsographEnvironment = require('./IsographEnvironment.
|
|
3
|
-
const require_logging = require('./logging.
|
|
4
|
-
const require_startUpdate = require('./startUpdate.
|
|
5
|
-
const require_componentCache = require('./componentCache.
|
|
6
|
-
const require_check = require('./check.
|
|
7
|
-
const require_read = require('./read.
|
|
8
|
-
const require_subscribe = require('./subscribe.
|
|
9
|
-
const require_optimisticProxy = require('./optimisticProxy.
|
|
10
|
-
const require_cache = require('./cache.
|
|
11
|
-
const require_garbageCollection = require('./garbageCollection.
|
|
1
|
+
const require_PromiseWrapper = require('./PromiseWrapper.cjs');
|
|
2
|
+
const require_IsographEnvironment = require('./IsographEnvironment.cjs');
|
|
3
|
+
const require_logging = require('./logging.cjs');
|
|
4
|
+
const require_startUpdate = require('./startUpdate.cjs');
|
|
5
|
+
const require_componentCache = require('./componentCache.cjs');
|
|
6
|
+
const require_check = require('./check.cjs');
|
|
7
|
+
const require_read = require('./read.cjs');
|
|
8
|
+
const require_subscribe = require('./subscribe.cjs');
|
|
9
|
+
const require_optimisticProxy = require('./optimisticProxy.cjs');
|
|
10
|
+
const require_cache = require('./cache.cjs');
|
|
11
|
+
const require_garbageCollection = require('./garbageCollection.cjs');
|
|
12
12
|
|
|
13
13
|
//#region src/core/makeNetworkRequest.ts
|
|
14
14
|
let networkRequestId = 0;
|
|
@@ -52,7 +52,7 @@ function makeNetworkRequest(environment, artifact, variables, readerWithRefetchQ
|
|
|
52
52
|
environment.networkFunction(artifact.networkRequestInfo.operation, variables),
|
|
53
53
|
status.retainedQuery.normalizationAst.promise,
|
|
54
54
|
readerWithRefetchQueries?.promise
|
|
55
|
-
]).then(([networkResponse, normalizationAst, readerWithRefetchQueries
|
|
55
|
+
]).then(([networkResponse, normalizationAst, readerWithRefetchQueries]) => {
|
|
56
56
|
require_logging.logMessage(environment, () => ({
|
|
57
57
|
kind: "ReceivedNetworkResponse",
|
|
58
58
|
networkResponse,
|
|
@@ -86,7 +86,7 @@ function makeNetworkRequest(environment, artifact, variables, readerWithRefetchQ
|
|
|
86
86
|
}
|
|
87
87
|
const onComplete = fetchOptions?.onComplete;
|
|
88
88
|
if (onComplete != null) {
|
|
89
|
-
let data = readDataForOnComplete(artifact, environment, root, variables, readerWithRefetchQueries
|
|
89
|
+
let data = readDataForOnComplete(artifact, environment, root, variables, readerWithRefetchQueries);
|
|
90
90
|
try {
|
|
91
91
|
onComplete(data);
|
|
92
92
|
} catch {}
|
|
@@ -178,8 +178,8 @@ function makeOptimisticUpdate(environment, artifact, variables, optimisticNetwor
|
|
|
178
178
|
require_subscribe.callSubscriptions(environment, encounteredIds);
|
|
179
179
|
return optimistic;
|
|
180
180
|
}
|
|
181
|
-
function revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(environment, status, normalizeData
|
|
182
|
-
if (status.optimistic != null) require_optimisticProxy.revertOptimisticStoreLayerAndMaybeReplace(environment, status.optimistic, normalizeData
|
|
181
|
+
function revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(environment, status, normalizeData) {
|
|
182
|
+
if (status.optimistic != null) require_optimisticProxy.revertOptimisticStoreLayerAndMaybeReplace(environment, status.optimistic, normalizeData);
|
|
183
183
|
return {
|
|
184
184
|
kind: "UndisposedComplete",
|
|
185
185
|
retainedQuery: status.retainedQuery
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { FetchOptions } from "./check.
|
|
2
|
-
import { AnyError, PromiseWrapper } from "./PromiseWrapper.
|
|
3
|
-
import { IsographEnvironment } from "./IsographEnvironment.
|
|
4
|
-
import { ExtractParameters, UnknownTReadFromStore } from "./FragmentReference.
|
|
5
|
-
import { NetworkResponseObject } from "./cache.
|
|
6
|
-
import { IsographEntrypoint, NormalizationAst, NormalizationAstLoader, ReaderWithRefetchQueries, RefetchQueryNormalizationArtifact } from "./entrypoint.
|
|
1
|
+
import { FetchOptions } from "./check.cjs";
|
|
2
|
+
import { AnyError, PromiseWrapper } from "./PromiseWrapper.cjs";
|
|
3
|
+
import { IsographEnvironment } from "./IsographEnvironment.cjs";
|
|
4
|
+
import { ExtractParameters, UnknownTReadFromStore } from "./FragmentReference.cjs";
|
|
5
|
+
import { NetworkResponseObject } from "./cache.cjs";
|
|
6
|
+
import { IsographEntrypoint, NormalizationAst, NormalizationAstLoader, ReaderWithRefetchQueries, RefetchQueryNormalizationArtifact } from "./entrypoint.cjs";
|
|
7
7
|
import { ItemCleanupPair } from "@isograph/disposable-types";
|
|
8
8
|
|
|
9
9
|
//#region src/core/makeNetworkRequest.d.ts
|
|
10
10
|
declare function makeNetworkRequest<TReadFromStore extends UnknownTReadFromStore, TClientFieldValue, TNormalizationAst extends NormalizationAst | NormalizationAstLoader, TRawResponseType extends NetworkResponseObject>(environment: IsographEnvironment, artifact: RefetchQueryNormalizationArtifact | IsographEntrypoint<TReadFromStore, TClientFieldValue, TNormalizationAst, TRawResponseType>, variables: ExtractParameters<TReadFromStore>, readerWithRefetchQueries: PromiseWrapper<ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>> | null, fetchOptions: FetchOptions<TClientFieldValue, TRawResponseType> | null): ItemCleanupPair<PromiseWrapper<void, AnyError>>;
|
|
11
11
|
//#endregion
|
|
12
12
|
export { makeNetworkRequest };
|
|
13
|
-
//# sourceMappingURL=makeNetworkRequest.d.
|
|
13
|
+
//# sourceMappingURL=makeNetworkRequest.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"makeNetworkRequest.d.cts","names":[],"sources":["../../src/core/makeNetworkRequest.ts"],"mappings":";;;;;;;;;iBA8JgB,kBAAA,wBACS,qBAAA,+CAEG,gBAAA,GAAmB,sBAAA,2BACpB,qBAAA,CAAA,CAEzB,WAAA,EAAa,mBAAA,EACb,QAAA,EACI,iCAAA,GACA,kBAAA,CACE,cAAA,EACA,iBAAA,EACA,iBAAA,EACA,gBAAA,GAEN,SAAA,EAAW,iBAAA,CAAkB,cAAA,GAC7B,wBAAA,EAA0B,cAAA,CACxB,wBAAA,CAAyB,cAAA,EAAgB,iBAAA,WAE3C,YAAA,EAAc,YAAA,CAAa,iBAAA,EAAmB,gBAAA,WAC7C,eAAA,CAAgB,cAAA,OAAqB,QAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeNetworkRequest.d.mts","names":[],"sources":["../../src/core/makeNetworkRequest.ts"],"
|
|
1
|
+
{"version":3,"file":"makeNetworkRequest.d.mts","names":[],"sources":["../../src/core/makeNetworkRequest.ts"],"mappings":";;;;;;;;;iBA8JgB,kBAAA,wBACS,qBAAA,+CAEG,gBAAA,GAAmB,sBAAA,2BACpB,qBAAA,CAAA,CAEzB,WAAA,EAAa,mBAAA,EACb,QAAA,EACI,iCAAA,GACA,kBAAA,CACE,cAAA,EACA,iBAAA,EACA,iBAAA,EACA,gBAAA,GAEN,SAAA,EAAW,iBAAA,CAAkB,cAAA,GAC7B,wBAAA,EAA0B,cAAA,CACxB,wBAAA,CAAyB,cAAA,EAAgB,iBAAA,WAE3C,YAAA,EAAc,YAAA,CAAa,iBAAA,EAAmB,gBAAA,WAC7C,eAAA,CAAgB,cAAA,OAAqB,QAAA"}
|
|
@@ -52,7 +52,7 @@ function makeNetworkRequest(environment, artifact, variables, readerWithRefetchQ
|
|
|
52
52
|
environment.networkFunction(artifact.networkRequestInfo.operation, variables),
|
|
53
53
|
status.retainedQuery.normalizationAst.promise,
|
|
54
54
|
readerWithRefetchQueries?.promise
|
|
55
|
-
]).then(([networkResponse, normalizationAst, readerWithRefetchQueries
|
|
55
|
+
]).then(([networkResponse, normalizationAst, readerWithRefetchQueries]) => {
|
|
56
56
|
logMessage(environment, () => ({
|
|
57
57
|
kind: "ReceivedNetworkResponse",
|
|
58
58
|
networkResponse,
|
|
@@ -86,7 +86,7 @@ function makeNetworkRequest(environment, artifact, variables, readerWithRefetchQ
|
|
|
86
86
|
}
|
|
87
87
|
const onComplete = fetchOptions?.onComplete;
|
|
88
88
|
if (onComplete != null) {
|
|
89
|
-
let data = readDataForOnComplete(artifact, environment, root, variables, readerWithRefetchQueries
|
|
89
|
+
let data = readDataForOnComplete(artifact, environment, root, variables, readerWithRefetchQueries);
|
|
90
90
|
try {
|
|
91
91
|
onComplete(data);
|
|
92
92
|
} catch {}
|
|
@@ -178,8 +178,8 @@ function makeOptimisticUpdate(environment, artifact, variables, optimisticNetwor
|
|
|
178
178
|
callSubscriptions(environment, encounteredIds);
|
|
179
179
|
return optimistic;
|
|
180
180
|
}
|
|
181
|
-
function revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(environment, status, normalizeData
|
|
182
|
-
if (status.optimistic != null) revertOptimisticStoreLayerAndMaybeReplace(environment, status.optimistic, normalizeData
|
|
181
|
+
function revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(environment, status, normalizeData) {
|
|
182
|
+
if (status.optimistic != null) revertOptimisticStoreLayerAndMaybeReplace(environment, status.optimistic, normalizeData);
|
|
183
183
|
return {
|
|
184
184
|
kind: "UndisposedComplete",
|
|
185
185
|
retainedQuery: status.retainedQuery
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"makeNetworkRequest.mjs","names":["status:\n | NetworkRequestStatusUndisposedComplete\n | NetworkRequestStatusDisposed","status: NetworkRequestStatus","readerWithRefetchQueries","encounteredIds: EncounteredIds","fragment: FragmentReference<TReadFromStore, TClientFieldValue>","retainedQuery: RetainedQuery","normalizeData"],"sources":["../../src/core/makeNetworkRequest.ts"],"sourcesContent":["import type { ItemCleanupPair } from '@isograph/disposable-types';\nimport {\n normalizeData,\n type EncounteredIds,\n type NetworkResponseObject,\n} from './cache';\nimport type { FetchOptions } from './check';\nimport { check, DEFAULT_SHOULD_FETCH_VALUE } from './check';\nimport { getOrCreateCachedComponent } from './componentCache';\nimport type {\n IsographEntrypoint,\n NormalizationAst,\n NormalizationAstLoader,\n ReaderWithRefetchQueries,\n RefetchQueryNormalizationArtifact,\n} from './entrypoint';\nimport type {\n ExtractParameters,\n FragmentReference,\n UnknownTReadFromStore,\n} from './FragmentReference';\nimport type { RetainedQuery } from './garbageCollection';\nimport {\n garbageCollectEnvironment,\n retainQuery,\n unretainQuery,\n} from './garbageCollection';\nimport type { IsographEnvironment, StoreLink } from './IsographEnvironment';\nimport { ROOT_ID } from './IsographEnvironment';\nimport { logMessage } from './logging';\nimport {\n addNetworkResponseStoreLayer,\n addOptimisticNetworkResponseStoreLayer,\n revertOptimisticStoreLayerAndMaybeReplace,\n type OptimisticStoreLayer,\n type StoreLayerWithData,\n} from './optimisticProxy';\nimport type { AnyError, PromiseWrapper } from './PromiseWrapper';\nimport { wrapPromise, wrapResolvedValue } from './PromiseWrapper';\nimport { readButDoNotEvaluate } from './read';\nimport { getOrCreateCachedStartUpdate } from './startUpdate';\nimport { callSubscriptions } from './subscribe';\n\nlet networkRequestId = 0;\n\nexport function maybeMakeNetworkRequest<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n readerWithRefetchQueries: PromiseWrapper<\n ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>\n > | null,\n fetchOptions: FetchOptions<TClientFieldValue, TRawResponseType> | null,\n): ItemCleanupPair<PromiseWrapper<void, AnyError>> {\n switch (fetchOptions?.shouldFetch ?? DEFAULT_SHOULD_FETCH_VALUE) {\n case 'Yes': {\n return makeNetworkRequest(\n environment,\n artifact,\n variables,\n readerWithRefetchQueries,\n fetchOptions,\n );\n }\n case 'No': {\n return retainQueryWithoutMakingNetworkRequest(\n environment,\n artifact,\n variables,\n );\n }\n case 'IfNecessary': {\n if (\n artifact.networkRequestInfo.normalizationAst.kind ===\n 'NormalizationAstLoader'\n ) {\n throw new Error(\n 'Using lazy loaded normalizationAst with shouldFetch: \"IfNecessary\" is ' +\n 'not supported as it will lead to a network waterfall.',\n );\n }\n const result = check(\n environment,\n artifact.networkRequestInfo.normalizationAst.selections,\n variables,\n {\n __link: ROOT_ID,\n __typename: artifact.concreteType,\n },\n );\n\n if (result.kind === 'EnoughData') {\n return retainQueryWithoutMakingNetworkRequest(\n environment,\n artifact,\n variables,\n );\n } else {\n return makeNetworkRequest(\n environment,\n artifact,\n variables,\n readerWithRefetchQueries,\n fetchOptions,\n );\n }\n }\n }\n}\n\nexport function retainQueryWithoutMakingNetworkRequest<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n NormalizationAst | NormalizationAstLoader,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n): ItemCleanupPair<PromiseWrapper<void, AnyError>> {\n let status:\n | NetworkRequestStatusUndisposedComplete\n | NetworkRequestStatusDisposed = {\n kind: 'UndisposedComplete',\n retainedQuery: fetchNormalizationAstAndRetainArtifact(\n environment,\n artifact,\n variables,\n ),\n };\n return [\n wrapResolvedValue(undefined),\n () => {\n if (status.kind !== 'Disposed') {\n status = unretainAndGarbageCollect(environment, status);\n }\n },\n ];\n}\n\nexport function makeNetworkRequest<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n readerWithRefetchQueries: PromiseWrapper<\n ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>\n > | null,\n fetchOptions: FetchOptions<TClientFieldValue, TRawResponseType> | null,\n): ItemCleanupPair<PromiseWrapper<void, AnyError>> {\n // TODO this should be a DataId and stored in the store\n const myNetworkRequestId = networkRequestId + '';\n networkRequestId++;\n let status: NetworkRequestStatus = {\n kind: 'UndisposedIncomplete',\n retainedQuery: fetchNormalizationAstAndRetainArtifact(\n environment,\n artifact,\n variables,\n ),\n optimistic:\n fetchOptions?.optimisticNetworkResponse != null\n ? makeOptimisticUpdate(\n environment,\n artifact,\n variables,\n fetchOptions?.optimisticNetworkResponse,\n )\n : null,\n };\n\n logMessage(environment, () => ({\n kind: 'MakeNetworkRequest',\n artifact,\n variables,\n networkRequestId: myNetworkRequestId,\n }));\n\n // This should be an observable, not a promise\n const promise = Promise.all([\n environment.networkFunction(\n artifact.networkRequestInfo.operation,\n variables,\n ),\n status.retainedQuery.normalizationAst.promise,\n readerWithRefetchQueries?.promise,\n ])\n .then(([networkResponse, normalizationAst, readerWithRefetchQueries]) => {\n logMessage(environment, () => ({\n kind: 'ReceivedNetworkResponse',\n networkResponse,\n networkRequestId: myNetworkRequestId,\n }));\n\n if (networkResponse.errors != null) {\n try {\n fetchOptions?.onError?.();\n } catch {}\n throw new Error('Network response had errors', {\n cause: networkResponse,\n });\n }\n\n const root = { __link: ROOT_ID, __typename: artifact.concreteType };\n\n if (status.kind === 'UndisposedIncomplete') {\n if (status.optimistic != null) {\n status =\n revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment,\n status,\n (storeLayer) =>\n normalizeData(\n environment,\n storeLayer,\n normalizationAst.selections,\n networkResponse.data ?? {},\n variables,\n root,\n new Map(),\n ),\n );\n } else {\n const encounteredIds: EncounteredIds = new Map();\n environment.store = addNetworkResponseStoreLayer(environment.store);\n normalizeData(\n environment,\n environment.store,\n normalizationAst.selections,\n networkResponse.data ?? {},\n variables,\n root,\n encounteredIds,\n );\n\n logMessage(environment, () => ({\n kind: 'AfterNormalization',\n store: environment.store,\n encounteredIds: encounteredIds,\n }));\n\n callSubscriptions(environment, encounteredIds);\n\n status = {\n kind: 'UndisposedComplete',\n retainedQuery: status.retainedQuery,\n };\n }\n }\n\n const onComplete = fetchOptions?.onComplete;\n if (onComplete != null) {\n let data = readDataForOnComplete(\n artifact,\n environment,\n root,\n variables,\n readerWithRefetchQueries,\n );\n\n try {\n // @ts-expect-error this problem will be fixed when we remove RefetchQueryNormalizationArtifact\n // (or we can fix this by having a single param of type { kind: 'Entrypoint', entrypoint,\n // fetchOptions: FetchOptions<TReadFromStore> } | { kind: 'RefetchQuery', refetchQuery,\n // fetchOptions: FetchOptions<void> }).\n onComplete(data);\n } catch {}\n }\n })\n .catch((e) => {\n logMessage(environment, () => ({\n kind: 'ReceivedNetworkError',\n networkRequestId: myNetworkRequestId,\n error: e,\n }));\n try {\n fetchOptions?.onError?.();\n } catch {}\n\n if (status.kind === 'UndisposedIncomplete') {\n status =\n revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment,\n status,\n null,\n );\n }\n\n throw e;\n });\n\n const wrapper = wrapPromise(promise);\n\n const response: ItemCleanupPair<PromiseWrapper<void, AnyError>> = [\n wrapper,\n () => {\n if (status.kind === 'UndisposedIncomplete') {\n status =\n revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment,\n status,\n null,\n );\n }\n if (status.kind !== 'Disposed') {\n status = unretainAndGarbageCollect(environment, status);\n }\n },\n ];\n return response;\n}\n\ntype NetworkRequestStatusUndisposedIncomplete = {\n readonly kind: 'UndisposedIncomplete';\n readonly retainedQuery: RetainedQuery;\n readonly optimistic: OptimisticStoreLayer | null;\n};\n\ntype NetworkRequestStatusUndisposedComplete = {\n readonly kind: 'UndisposedComplete';\n readonly retainedQuery: RetainedQuery;\n};\n\ntype NetworkRequestStatusDisposed = {\n readonly kind: 'Disposed';\n};\n\ntype NetworkRequestStatus =\n | NetworkRequestStatusUndisposedIncomplete\n | NetworkRequestStatusUndisposedComplete\n | NetworkRequestStatusDisposed;\n\nfunction readDataForOnComplete<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n environment: IsographEnvironment,\n root: StoreLink,\n variables: ExtractParameters<TReadFromStore>,\n readerWithRefetchQueries:\n | ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>\n | undefined,\n): TClientFieldValue | null {\n // An entrypoint, but not a RefetchQueryNormalizationArtifact, has a reader ASTs.\n // So, we can only pass data to onComplete if makeNetworkRequest was passed an entrypoint.\n // This is awkward, since we don't express that in the types of the parameters\n // (i.e. FetchOptions could be passed, along with a RefetchQueryNormalizationArtifact).\n //\n // However, this isn't a big deal: RefetchQueryNormalizationArtifact is going away.\n if (artifact.kind === 'Entrypoint') {\n // TODO this is a smell!\n const fakeNetworkRequest = wrapResolvedValue(undefined);\n // TODO this is a smell — we know the network response is not in flight,\n // so we don't really care!\n const fakeNetworkRequestOptions = {\n suspendIfInFlight: false,\n throwOnNetworkError: false,\n };\n if (readerWithRefetchQueries == null) {\n throw new Error(\n 'Expected readerWithRefetchQueries to be not null. This is indicative of a bug in Isograph.',\n );\n }\n\n const fragment: FragmentReference<TReadFromStore, TClientFieldValue> = {\n kind: 'FragmentReference',\n // TODO this smells.\n readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),\n fieldName: readerWithRefetchQueries.readerArtifact.fieldName,\n readerArtifactKind: readerWithRefetchQueries.readerArtifact.kind,\n root,\n variables,\n networkRequest: fakeNetworkRequest,\n };\n const fragmentResult = readButDoNotEvaluate(\n environment,\n fragment,\n fakeNetworkRequestOptions,\n ).item;\n const readerArtifact = readerWithRefetchQueries.readerArtifact;\n switch (readerArtifact.kind) {\n case 'ComponentReaderArtifact': {\n // @ts-expect-error We should find a way to encode this in the type system:\n // if we have a ComponentReaderArtifact, we will necessarily have a\n // TClientFieldValue which is a React.FC<...>\n return getOrCreateCachedComponent(\n environment,\n {\n kind: 'FragmentReference',\n readerWithRefetchQueries: wrapResolvedValue({\n kind: 'ReaderWithRefetchQueries',\n readerArtifact: readerArtifact,\n nestedRefetchQueries:\n readerWithRefetchQueries.nestedRefetchQueries,\n }),\n fieldName: readerArtifact.fieldName,\n readerArtifactKind: readerArtifact.kind,\n root,\n variables,\n networkRequest: fakeNetworkRequest,\n } as const,\n fakeNetworkRequestOptions,\n );\n }\n case 'EagerReaderArtifact': {\n return readerArtifact.resolver({\n data: fragmentResult,\n parameters: variables,\n ...(readerArtifact.hasUpdatable\n ? {\n startUpdate: getOrCreateCachedStartUpdate(\n environment,\n fragment,\n fakeNetworkRequestOptions,\n ),\n }\n : undefined),\n });\n }\n }\n }\n return null;\n}\n\nfunction fetchNormalizationAstAndRetainArtifact<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n NormalizationAst | NormalizationAstLoader,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n): RetainedQuery {\n const normalizationAst =\n artifact.networkRequestInfo.normalizationAst.kind === 'NormalizationAst'\n ? wrapResolvedValue(artifact.networkRequestInfo.normalizationAst)\n : wrapPromise(artifact.networkRequestInfo.normalizationAst.loader());\n\n const root = { __link: ROOT_ID, __typename: artifact.concreteType };\n const retainedQuery: RetainedQuery = {\n normalizationAst: normalizationAst,\n variables,\n root,\n };\n retainQuery(environment, retainedQuery);\n return retainedQuery;\n}\n\nfunction makeOptimisticUpdate<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n optimisticNetworkResponse: TRawResponseType,\n): OptimisticStoreLayer {\n const root = { __link: ROOT_ID, __typename: artifact.concreteType };\n\n if (\n artifact.networkRequestInfo.normalizationAst.kind ===\n 'NormalizationAstLoader'\n ) {\n throw new Error(\n 'Using lazy loaded normalizationAst with optimisticNetworkResponse is not supported.',\n );\n }\n const encounteredIds: EncounteredIds = new Map();\n const optimistic = (environment.store =\n addOptimisticNetworkResponseStoreLayer(environment.store));\n normalizeData(\n environment,\n environment.store,\n artifact.networkRequestInfo.normalizationAst.selections,\n optimisticNetworkResponse,\n variables,\n root,\n encounteredIds,\n );\n\n logMessage(environment, () => ({\n kind: 'AfterNormalization',\n store: environment.store,\n encounteredIds: encounteredIds,\n }));\n\n callSubscriptions(environment, encounteredIds);\n return optimistic;\n}\n\nfunction revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment: IsographEnvironment,\n status: NetworkRequestStatusUndisposedIncomplete,\n normalizeData: null | ((storeLayer: StoreLayerWithData) => void),\n): NetworkRequestStatusUndisposedComplete {\n if (status.optimistic != null) {\n revertOptimisticStoreLayerAndMaybeReplace(\n environment,\n status.optimistic,\n normalizeData,\n );\n }\n\n return {\n kind: 'UndisposedComplete',\n retainedQuery: status.retainedQuery,\n };\n}\n\nfunction unretainAndGarbageCollect(\n environment: IsographEnvironment,\n status: NetworkRequestStatusUndisposedComplete,\n): NetworkRequestStatusDisposed {\n const didUnretainSomeQuery = unretainQuery(environment, status.retainedQuery);\n if (didUnretainSomeQuery) {\n garbageCollectEnvironment(environment);\n }\n\n return {\n kind: 'Disposed',\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"makeNetworkRequest.mjs","names":[],"sources":["../../src/core/makeNetworkRequest.ts"],"sourcesContent":["import type { ItemCleanupPair } from '@isograph/disposable-types';\nimport {\n normalizeData,\n type EncounteredIds,\n type NetworkResponseObject,\n} from './cache';\nimport type { FetchOptions } from './check';\nimport { check, DEFAULT_SHOULD_FETCH_VALUE } from './check';\nimport { getOrCreateCachedComponent } from './componentCache';\nimport type {\n IsographEntrypoint,\n NormalizationAst,\n NormalizationAstLoader,\n ReaderWithRefetchQueries,\n RefetchQueryNormalizationArtifact,\n} from './entrypoint';\nimport type {\n ExtractParameters,\n FragmentReference,\n UnknownTReadFromStore,\n} from './FragmentReference';\nimport type { RetainedQuery } from './garbageCollection';\nimport {\n garbageCollectEnvironment,\n retainQuery,\n unretainQuery,\n} from './garbageCollection';\nimport type { IsographEnvironment, StoreLink } from './IsographEnvironment';\nimport { ROOT_ID } from './IsographEnvironment';\nimport { logMessage } from './logging';\nimport {\n addNetworkResponseStoreLayer,\n addOptimisticNetworkResponseStoreLayer,\n revertOptimisticStoreLayerAndMaybeReplace,\n type OptimisticStoreLayer,\n type StoreLayerWithData,\n} from './optimisticProxy';\nimport type { AnyError, PromiseWrapper } from './PromiseWrapper';\nimport { wrapPromise, wrapResolvedValue } from './PromiseWrapper';\nimport { readButDoNotEvaluate } from './read';\nimport { getOrCreateCachedStartUpdate } from './startUpdate';\nimport { callSubscriptions } from './subscribe';\n\nlet networkRequestId = 0;\n\nexport function maybeMakeNetworkRequest<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n readerWithRefetchQueries: PromiseWrapper<\n ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>\n > | null,\n fetchOptions: FetchOptions<TClientFieldValue, TRawResponseType> | null,\n): ItemCleanupPair<PromiseWrapper<void, AnyError>> {\n switch (fetchOptions?.shouldFetch ?? DEFAULT_SHOULD_FETCH_VALUE) {\n case 'Yes': {\n return makeNetworkRequest(\n environment,\n artifact,\n variables,\n readerWithRefetchQueries,\n fetchOptions,\n );\n }\n case 'No': {\n return retainQueryWithoutMakingNetworkRequest(\n environment,\n artifact,\n variables,\n );\n }\n case 'IfNecessary': {\n if (\n artifact.networkRequestInfo.normalizationAst.kind ===\n 'NormalizationAstLoader'\n ) {\n throw new Error(\n 'Using lazy loaded normalizationAst with shouldFetch: \"IfNecessary\" is ' +\n 'not supported as it will lead to a network waterfall.',\n );\n }\n const result = check(\n environment,\n artifact.networkRequestInfo.normalizationAst.selections,\n variables,\n {\n __link: ROOT_ID,\n __typename: artifact.concreteType,\n },\n );\n\n if (result.kind === 'EnoughData') {\n return retainQueryWithoutMakingNetworkRequest(\n environment,\n artifact,\n variables,\n );\n } else {\n return makeNetworkRequest(\n environment,\n artifact,\n variables,\n readerWithRefetchQueries,\n fetchOptions,\n );\n }\n }\n }\n}\n\nexport function retainQueryWithoutMakingNetworkRequest<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n NormalizationAst | NormalizationAstLoader,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n): ItemCleanupPair<PromiseWrapper<void, AnyError>> {\n let status:\n | NetworkRequestStatusUndisposedComplete\n | NetworkRequestStatusDisposed = {\n kind: 'UndisposedComplete',\n retainedQuery: fetchNormalizationAstAndRetainArtifact(\n environment,\n artifact,\n variables,\n ),\n };\n return [\n wrapResolvedValue(undefined),\n () => {\n if (status.kind !== 'Disposed') {\n status = unretainAndGarbageCollect(environment, status);\n }\n },\n ];\n}\n\nexport function makeNetworkRequest<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n readerWithRefetchQueries: PromiseWrapper<\n ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>\n > | null,\n fetchOptions: FetchOptions<TClientFieldValue, TRawResponseType> | null,\n): ItemCleanupPair<PromiseWrapper<void, AnyError>> {\n // TODO this should be a DataId and stored in the store\n const myNetworkRequestId = networkRequestId + '';\n networkRequestId++;\n let status: NetworkRequestStatus = {\n kind: 'UndisposedIncomplete',\n retainedQuery: fetchNormalizationAstAndRetainArtifact(\n environment,\n artifact,\n variables,\n ),\n optimistic:\n fetchOptions?.optimisticNetworkResponse != null\n ? makeOptimisticUpdate(\n environment,\n artifact,\n variables,\n fetchOptions?.optimisticNetworkResponse,\n )\n : null,\n };\n\n logMessage(environment, () => ({\n kind: 'MakeNetworkRequest',\n artifact,\n variables,\n networkRequestId: myNetworkRequestId,\n }));\n\n // This should be an observable, not a promise\n const promise = Promise.all([\n environment.networkFunction(\n artifact.networkRequestInfo.operation,\n variables,\n ),\n status.retainedQuery.normalizationAst.promise,\n readerWithRefetchQueries?.promise,\n ])\n .then(([networkResponse, normalizationAst, readerWithRefetchQueries]) => {\n logMessage(environment, () => ({\n kind: 'ReceivedNetworkResponse',\n networkResponse,\n networkRequestId: myNetworkRequestId,\n }));\n\n if (networkResponse.errors != null) {\n try {\n fetchOptions?.onError?.();\n } catch {}\n throw new Error('Network response had errors', {\n cause: networkResponse,\n });\n }\n\n const root = { __link: ROOT_ID, __typename: artifact.concreteType };\n\n if (status.kind === 'UndisposedIncomplete') {\n if (status.optimistic != null) {\n status =\n revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment,\n status,\n (storeLayer) =>\n normalizeData(\n environment,\n storeLayer,\n normalizationAst.selections,\n networkResponse.data ?? {},\n variables,\n root,\n new Map(),\n ),\n );\n } else {\n const encounteredIds: EncounteredIds = new Map();\n environment.store = addNetworkResponseStoreLayer(environment.store);\n normalizeData(\n environment,\n environment.store,\n normalizationAst.selections,\n networkResponse.data ?? {},\n variables,\n root,\n encounteredIds,\n );\n\n logMessage(environment, () => ({\n kind: 'AfterNormalization',\n store: environment.store,\n encounteredIds: encounteredIds,\n }));\n\n callSubscriptions(environment, encounteredIds);\n\n status = {\n kind: 'UndisposedComplete',\n retainedQuery: status.retainedQuery,\n };\n }\n }\n\n const onComplete = fetchOptions?.onComplete;\n if (onComplete != null) {\n let data = readDataForOnComplete(\n artifact,\n environment,\n root,\n variables,\n readerWithRefetchQueries,\n );\n\n try {\n // @ts-expect-error this problem will be fixed when we remove RefetchQueryNormalizationArtifact\n // (or we can fix this by having a single param of type { kind: 'Entrypoint', entrypoint,\n // fetchOptions: FetchOptions<TReadFromStore> } | { kind: 'RefetchQuery', refetchQuery,\n // fetchOptions: FetchOptions<void> }).\n onComplete(data);\n } catch {}\n }\n })\n .catch((e) => {\n logMessage(environment, () => ({\n kind: 'ReceivedNetworkError',\n networkRequestId: myNetworkRequestId,\n error: e,\n }));\n try {\n fetchOptions?.onError?.();\n } catch {}\n\n if (status.kind === 'UndisposedIncomplete') {\n status =\n revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment,\n status,\n null,\n );\n }\n\n throw e;\n });\n\n const wrapper = wrapPromise(promise);\n\n const response: ItemCleanupPair<PromiseWrapper<void, AnyError>> = [\n wrapper,\n () => {\n if (status.kind === 'UndisposedIncomplete') {\n status =\n revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment,\n status,\n null,\n );\n }\n if (status.kind !== 'Disposed') {\n status = unretainAndGarbageCollect(environment, status);\n }\n },\n ];\n return response;\n}\n\ntype NetworkRequestStatusUndisposedIncomplete = {\n readonly kind: 'UndisposedIncomplete';\n readonly retainedQuery: RetainedQuery;\n readonly optimistic: OptimisticStoreLayer | null;\n};\n\ntype NetworkRequestStatusUndisposedComplete = {\n readonly kind: 'UndisposedComplete';\n readonly retainedQuery: RetainedQuery;\n};\n\ntype NetworkRequestStatusDisposed = {\n readonly kind: 'Disposed';\n};\n\ntype NetworkRequestStatus =\n | NetworkRequestStatusUndisposedIncomplete\n | NetworkRequestStatusUndisposedComplete\n | NetworkRequestStatusDisposed;\n\nfunction readDataForOnComplete<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n environment: IsographEnvironment,\n root: StoreLink,\n variables: ExtractParameters<TReadFromStore>,\n readerWithRefetchQueries:\n | ReaderWithRefetchQueries<TReadFromStore, TClientFieldValue>\n | undefined,\n): TClientFieldValue | null {\n // An entrypoint, but not a RefetchQueryNormalizationArtifact, has a reader ASTs.\n // So, we can only pass data to onComplete if makeNetworkRequest was passed an entrypoint.\n // This is awkward, since we don't express that in the types of the parameters\n // (i.e. FetchOptions could be passed, along with a RefetchQueryNormalizationArtifact).\n //\n // However, this isn't a big deal: RefetchQueryNormalizationArtifact is going away.\n if (artifact.kind === 'Entrypoint') {\n // TODO this is a smell!\n const fakeNetworkRequest = wrapResolvedValue(undefined);\n // TODO this is a smell — we know the network response is not in flight,\n // so we don't really care!\n const fakeNetworkRequestOptions = {\n suspendIfInFlight: false,\n throwOnNetworkError: false,\n };\n if (readerWithRefetchQueries == null) {\n throw new Error(\n 'Expected readerWithRefetchQueries to be not null. This is indicative of a bug in Isograph.',\n );\n }\n\n const fragment: FragmentReference<TReadFromStore, TClientFieldValue> = {\n kind: 'FragmentReference',\n // TODO this smells.\n readerWithRefetchQueries: wrapResolvedValue(readerWithRefetchQueries),\n fieldName: readerWithRefetchQueries.readerArtifact.fieldName,\n readerArtifactKind: readerWithRefetchQueries.readerArtifact.kind,\n root,\n variables,\n networkRequest: fakeNetworkRequest,\n };\n const fragmentResult = readButDoNotEvaluate(\n environment,\n fragment,\n fakeNetworkRequestOptions,\n ).item;\n const readerArtifact = readerWithRefetchQueries.readerArtifact;\n switch (readerArtifact.kind) {\n case 'ComponentReaderArtifact': {\n // @ts-expect-error We should find a way to encode this in the type system:\n // if we have a ComponentReaderArtifact, we will necessarily have a\n // TClientFieldValue which is a React.FC<...>\n return getOrCreateCachedComponent(\n environment,\n {\n kind: 'FragmentReference',\n readerWithRefetchQueries: wrapResolvedValue({\n kind: 'ReaderWithRefetchQueries',\n readerArtifact: readerArtifact,\n nestedRefetchQueries:\n readerWithRefetchQueries.nestedRefetchQueries,\n }),\n fieldName: readerArtifact.fieldName,\n readerArtifactKind: readerArtifact.kind,\n root,\n variables,\n networkRequest: fakeNetworkRequest,\n } as const,\n fakeNetworkRequestOptions,\n );\n }\n case 'EagerReaderArtifact': {\n return readerArtifact.resolver({\n data: fragmentResult,\n parameters: variables,\n ...(readerArtifact.hasUpdatable\n ? {\n startUpdate: getOrCreateCachedStartUpdate(\n environment,\n fragment,\n fakeNetworkRequestOptions,\n ),\n }\n : undefined),\n });\n }\n }\n }\n return null;\n}\n\nfunction fetchNormalizationAstAndRetainArtifact<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n NormalizationAst | NormalizationAstLoader,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n): RetainedQuery {\n const normalizationAst =\n artifact.networkRequestInfo.normalizationAst.kind === 'NormalizationAst'\n ? wrapResolvedValue(artifact.networkRequestInfo.normalizationAst)\n : wrapPromise(artifact.networkRequestInfo.normalizationAst.loader());\n\n const root = { __link: ROOT_ID, __typename: artifact.concreteType };\n const retainedQuery: RetainedQuery = {\n normalizationAst: normalizationAst,\n variables,\n root,\n };\n retainQuery(environment, retainedQuery);\n return retainedQuery;\n}\n\nfunction makeOptimisticUpdate<\n TReadFromStore extends UnknownTReadFromStore,\n TClientFieldValue,\n TNormalizationAst extends NormalizationAst | NormalizationAstLoader,\n TRawResponseType extends NetworkResponseObject,\n>(\n environment: IsographEnvironment,\n artifact:\n | RefetchQueryNormalizationArtifact\n | IsographEntrypoint<\n TReadFromStore,\n TClientFieldValue,\n TNormalizationAst,\n TRawResponseType\n >,\n variables: ExtractParameters<TReadFromStore>,\n optimisticNetworkResponse: TRawResponseType,\n): OptimisticStoreLayer {\n const root = { __link: ROOT_ID, __typename: artifact.concreteType };\n\n if (\n artifact.networkRequestInfo.normalizationAst.kind ===\n 'NormalizationAstLoader'\n ) {\n throw new Error(\n 'Using lazy loaded normalizationAst with optimisticNetworkResponse is not supported.',\n );\n }\n const encounteredIds: EncounteredIds = new Map();\n const optimistic = (environment.store =\n addOptimisticNetworkResponseStoreLayer(environment.store));\n normalizeData(\n environment,\n environment.store,\n artifact.networkRequestInfo.normalizationAst.selections,\n optimisticNetworkResponse,\n variables,\n root,\n encounteredIds,\n );\n\n logMessage(environment, () => ({\n kind: 'AfterNormalization',\n store: environment.store,\n encounteredIds: encounteredIds,\n }));\n\n callSubscriptions(environment, encounteredIds);\n return optimistic;\n}\n\nfunction revertOptimisticStoreLayerAndMaybeReplaceIfUndisposedIncomplete(\n environment: IsographEnvironment,\n status: NetworkRequestStatusUndisposedIncomplete,\n normalizeData: null | ((storeLayer: StoreLayerWithData) => void),\n): NetworkRequestStatusUndisposedComplete {\n if (status.optimistic != null) {\n revertOptimisticStoreLayerAndMaybeReplace(\n environment,\n status.optimistic,\n normalizeData,\n );\n }\n\n return {\n kind: 'UndisposedComplete',\n retainedQuery: status.retainedQuery,\n };\n}\n\nfunction unretainAndGarbageCollect(\n environment: IsographEnvironment,\n status: NetworkRequestStatusUndisposedComplete,\n): NetworkRequestStatusDisposed {\n const didUnretainSomeQuery = unretainQuery(environment, status.retainedQuery);\n if (didUnretainSomeQuery) {\n garbageCollectEnvironment(environment);\n }\n\n return {\n kind: 'Disposed',\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_subscribe = require('./subscribe.
|
|
2
|
-
const require_cache = require('./cache.
|
|
1
|
+
const require_subscribe = require('./subscribe.cjs');
|
|
2
|
+
const require_cache = require('./cache.cjs');
|
|
3
3
|
|
|
4
4
|
//#region src/core/optimisticProxy.ts
|
|
5
5
|
function getOrInsertRecord(dataLayer, link) {
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { BaseStoreLayerData, StoreLayerData } from "./IsographEnvironment.
|
|
1
|
+
import { BaseStoreLayerData, StoreLayerData } from "./IsographEnvironment.cjs";
|
|
2
2
|
|
|
3
3
|
//#region src/core/optimisticProxy.d.ts
|
|
4
|
-
|
|
5
4
|
type BaseStoreLayer = {
|
|
6
5
|
readonly kind: 'BaseStoreLayer';
|
|
7
6
|
childStoreLayer: OptimisticStoreLayer | null;
|
|
@@ -40,4 +39,4 @@ type StoreLayer = OptimisticStoreLayer | NetworkResponseStoreLayer | StartUpdate
|
|
|
40
39
|
type StoreLayerWithData = BaseStoreLayer | NetworkResponseStoreLayer | OptimisticNetworkResponseStoreLayer;
|
|
41
40
|
//#endregion
|
|
42
41
|
export { StoreLayer, StoreLayerWithData };
|
|
43
|
-
//# sourceMappingURL=optimisticProxy.d.
|
|
42
|
+
//# sourceMappingURL=optimisticProxy.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"optimisticProxy.d.cts","names":[],"sources":["../../src/core/optimisticProxy.ts"],"mappings":";;;KAmGY,cAAA;EAAA,SACD,IAAA;EACT,eAAA,EAAiB,oBAAA;EAAA,SACR,gBAAA;EAAA,SACA,IAAA,EAAM,kBAAA;AAAA;AAAA,KAGL,yBAAA;EAAA,SACD,IAAA;EACT,eAAA,EAAiB,oBAAA,GAAuB,qBAAA;EACxC,gBAAA,EAAkB,oBAAA,GAAuB,qBAAA;EAAA,SAChC,IAAA,EAAM,cAAA;AAAA;AAAA,KAGL,UAAA,qBAA+B,UAAA,KACzC,UAAA,EAAY,WAAA;AAAA,KAGF,qBAAA;EAAA,SACD,IAAA;EACT,eAAA,EAAiB,oBAAA,GAAuB,yBAAA;EACxC,gBAAA,EAAkB,oBAAA,GAAuB,yBAAA;EACzC,IAAA,EAAM,cAAA;EACN,WAAA,EAAa,UAAA,CAAW,qBAAA,GAAwB,cAAA;AAAA;AAAA,KAGtC,oBAAA,GACR,2BAAA,GACA,mCAAA;AAAA,KAEQ,2BAAA;EAAA,SACD,IAAA;EACT,eAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA;EAEJ,gBAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA,GACA,cAAA;EACJ,IAAA,EAAM,cAAA;EAAA,SACG,WAAA,EAAa,UAAA,CAAW,2BAAA;AAAA;AAAA,KAGvB,mCAAA;EAAA,SACD,IAAA;EACT,eAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA;EAEJ,gBAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA,GACA,cAAA;EACJ,IAAA,EAAM,cAAA;AAAA;AAAA,KAiVI,UAAA,GACR,oBAAA,GACA,yBAAA,GACA,qBAAA,GACA,cAAA;AAAA,KAEQ,kBAAA,GACR,cAAA,GACA,yBAAA,GACA,mCAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimisticProxy.d.mts","names":[],"sources":["../../src/core/optimisticProxy.ts"],"
|
|
1
|
+
{"version":3,"file":"optimisticProxy.d.mts","names":[],"sources":["../../src/core/optimisticProxy.ts"],"mappings":";;;KAmGY,cAAA;EAAA,SACD,IAAA;EACT,eAAA,EAAiB,oBAAA;EAAA,SACR,gBAAA;EAAA,SACA,IAAA,EAAM,kBAAA;AAAA;AAAA,KAGL,yBAAA;EAAA,SACD,IAAA;EACT,eAAA,EAAiB,oBAAA,GAAuB,qBAAA;EACxC,gBAAA,EAAkB,oBAAA,GAAuB,qBAAA;EAAA,SAChC,IAAA,EAAM,cAAA;AAAA;AAAA,KAGL,UAAA,qBAA+B,UAAA,KACzC,UAAA,EAAY,WAAA;AAAA,KAGF,qBAAA;EAAA,SACD,IAAA;EACT,eAAA,EAAiB,oBAAA,GAAuB,yBAAA;EACxC,gBAAA,EAAkB,oBAAA,GAAuB,yBAAA;EACzC,IAAA,EAAM,cAAA;EACN,WAAA,EAAa,UAAA,CAAW,qBAAA,GAAwB,cAAA;AAAA;AAAA,KAGtC,oBAAA,GACR,2BAAA,GACA,mCAAA;AAAA,KAEQ,2BAAA;EAAA,SACD,IAAA;EACT,eAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA;EAEJ,gBAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA,GACA,cAAA;EACJ,IAAA,EAAM,cAAA;EAAA,SACG,WAAA,EAAa,UAAA,CAAW,2BAAA;AAAA;AAAA,KAGvB,mCAAA;EAAA,SACD,IAAA;EACT,eAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA;EAEJ,gBAAA,EACI,oBAAA,GACA,qBAAA,GACA,yBAAA,GACA,cAAA;EACJ,IAAA,EAAM,cAAA;AAAA;AAAA,KAiVI,UAAA,GACR,oBAAA,GACA,yBAAA,GACA,qBAAA,GACA,cAAA;AAAA,KAEQ,kBAAA,GACR,cAAA,GACA,yBAAA,GACA,mCAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"optimisticProxy.mjs","names":["startNode: StoreLayer | null","currentStoreLayer: StoreLayer | null","node: NetworkResponseStoreLayer","node: StartUpdateStoreLayer","node: OptimisticNetworkResponseStoreLayer","networkResponseStoreLayer: NetworkResponseStoreLayer","encounteredIds: EncounteredIds"],"sources":["../../src/core/optimisticProxy.ts"],"sourcesContent":["import { insertEmptySetIfMissing, type EncounteredIds } from './cache';\nimport { callSubscriptions } from './subscribe';\nimport type {\n BaseStoreLayerData,\n IsographEnvironment,\n StoreLayerData,\n StoreLink,\n StoreRecord,\n} from './IsographEnvironment';\n\nexport function getOrInsertRecord(\n dataLayer: StoreLayerData,\n link: StoreLink,\n): StoreRecord {\n const recordsById = (dataLayer[link.__typename] ??= {});\n return (recordsById[link.__link] ??= {});\n}\n\n/**\n * Given the child-most store layer (i.e. environment.store) and a link (identifying a\n * store record), create a proxy object that attempts to read through each successive\n * store layer until a value (i.e. field name) is found. If found, return that value.\n */\nexport function getStoreRecordProxy(\n storeLayer: StoreLayer,\n link: StoreLink,\n): Readonly<StoreRecord> | null | undefined {\n let startNode: StoreLayer | null = storeLayer;\n while (startNode != null) {\n const storeRecord = startNode.data[link.__typename]?.[link.__link];\n if (storeRecord === undefined) {\n startNode = startNode.parentStoreLayer;\n continue;\n }\n\n if (storeRecord == null) {\n return null;\n }\n\n return getMutableStoreRecordProxy(startNode, link);\n }\n\n return undefined;\n}\n\nexport function getMutableStoreRecordProxy(\n childMostStoreLayer: StoreLayer,\n link: StoreLink,\n): StoreRecord {\n return new Proxy<StoreRecord>(\n {},\n {\n get(_, propertyName) {\n let currentStoreLayer: StoreLayer | null = childMostStoreLayer;\n while (currentStoreLayer != null) {\n const storeRecord =\n currentStoreLayer.data[link.__typename]?.[link.__link];\n if (storeRecord !== undefined) {\n if (storeRecord == null) {\n return undefined;\n }\n const value = Reflect.get(storeRecord, propertyName);\n if (value !== undefined) {\n return value;\n }\n }\n currentStoreLayer = currentStoreLayer.parentStoreLayer;\n }\n },\n has(_, propertyName) {\n let currentStoreLayer: StoreLayer | null = childMostStoreLayer;\n while (currentStoreLayer != null) {\n const storeRecord =\n currentStoreLayer.data[link.__typename]?.[link.__link];\n if (storeRecord !== undefined) {\n if (storeRecord == null) {\n return false;\n }\n\n const value = Reflect.has(storeRecord, propertyName);\n if (value) {\n return true;\n }\n }\n currentStoreLayer = currentStoreLayer.parentStoreLayer;\n }\n return false;\n },\n set(_, p, newValue) {\n return Reflect.set(\n getOrInsertRecord(childMostStoreLayer.data, link),\n p,\n newValue,\n );\n },\n },\n );\n}\n\nexport type BaseStoreLayer = {\n readonly kind: 'BaseStoreLayer';\n childStoreLayer: OptimisticStoreLayer | null;\n readonly parentStoreLayer: null;\n readonly data: BaseStoreLayerData;\n};\n\nexport type NetworkResponseStoreLayer = {\n readonly kind: 'NetworkResponseStoreLayer';\n childStoreLayer: OptimisticStoreLayer | StartUpdateStoreLayer | null;\n parentStoreLayer: OptimisticStoreLayer | StartUpdateStoreLayer;\n readonly data: StoreLayerData;\n};\n\nexport type DataUpdate<TStoreLayer extends StoreLayer> = (\n storeLayer: TStoreLayer,\n) => void;\n\nexport type StartUpdateStoreLayer = {\n readonly kind: 'StartUpdateStoreLayer';\n childStoreLayer: OptimisticStoreLayer | NetworkResponseStoreLayer | null;\n parentStoreLayer: OptimisticStoreLayer | NetworkResponseStoreLayer;\n data: StoreLayerData;\n startUpdate: DataUpdate<StartUpdateStoreLayer | BaseStoreLayer>;\n};\n\nexport type OptimisticStoreLayer =\n | OptimisticUpdaterStoreLayer\n | OptimisticNetworkResponseStoreLayer;\n\nexport type OptimisticUpdaterStoreLayer = {\n readonly kind: 'OptimisticUpdaterStoreLayer';\n childStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | null;\n parentStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | BaseStoreLayer;\n data: StoreLayerData;\n readonly startUpdate: DataUpdate<OptimisticUpdaterStoreLayer>;\n};\n\nexport type OptimisticNetworkResponseStoreLayer = {\n readonly kind: 'OptimisticNetworkResponseStoreLayer';\n childStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | null;\n parentStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | BaseStoreLayer;\n data: StoreLayerData;\n};\n\nexport function addNetworkResponseStoreLayer(\n parent: StoreLayer,\n): StoreLayerWithData {\n switch (parent.kind) {\n case 'NetworkResponseStoreLayer':\n case 'BaseStoreLayer': {\n return parent;\n }\n case 'StartUpdateStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: NetworkResponseStoreLayer = {\n kind: 'NetworkResponseStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n };\n parent.childStoreLayer = node;\n\n return node;\n }\n }\n}\n\nfunction mergeDataLayer(target: StoreLayerData, source: StoreLayerData): void {\n for (const [typeName, sourceById] of Object.entries(source)) {\n if (sourceById == null) {\n target[typeName] = sourceById;\n continue;\n }\n const targetRecordById = (target[typeName] ??= {});\n for (const [id, sourceRecord] of Object.entries(sourceById)) {\n if (sourceRecord == null) {\n targetRecordById[id] = null;\n continue;\n }\n const targetRecord = (targetRecordById[id] ??= {});\n Object.assign(targetRecord, sourceRecord);\n }\n }\n}\n\nexport function addStartUpdateStoreLayer(\n parent: StoreLayer,\n startUpdate: StartUpdateStoreLayer['startUpdate'],\n): StoreLayer {\n switch (parent.kind) {\n case 'BaseStoreLayer': {\n startUpdate(parent);\n return parent;\n }\n case 'StartUpdateStoreLayer': {\n const node = parent;\n\n const prevStartUpdate = node.startUpdate;\n node.startUpdate = () => {\n prevStartUpdate(node);\n startUpdate(node);\n };\n\n startUpdate(node);\n return node;\n }\n case 'NetworkResponseStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: StartUpdateStoreLayer = {\n kind: 'StartUpdateStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n startUpdate: startUpdate,\n };\n parent.childStoreLayer = node;\n\n startUpdate(node);\n return node;\n }\n }\n}\n\nexport function addOptimisticUpdaterStoreLayer(\n parent: StoreLayer,\n startUpdate: OptimisticUpdaterStoreLayer['startUpdate'],\n): OptimisticUpdaterStoreLayer {\n switch (parent.kind) {\n case 'BaseStoreLayer':\n case 'StartUpdateStoreLayer':\n case 'NetworkResponseStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: OptimisticUpdaterStoreLayer = {\n kind: 'OptimisticUpdaterStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n startUpdate: startUpdate,\n };\n\n startUpdate(node);\n parent.childStoreLayer = node;\n\n return node;\n }\n }\n}\n\nexport function addOptimisticNetworkResponseStoreLayer(\n parent: StoreLayer,\n): OptimisticNetworkResponseStoreLayer {\n switch (parent.kind) {\n case 'BaseStoreLayer':\n case 'StartUpdateStoreLayer':\n case 'NetworkResponseStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: OptimisticNetworkResponseStoreLayer = {\n kind: 'OptimisticNetworkResponseStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n };\n\n parent.childStoreLayer = node;\n\n return node;\n }\n }\n}\n\n/**\n * Merge storeLayerToMerge, and its children, into baseStoreLayer.\n * We can merge until we reach a revertible layer (i.e. an optimistic layer).\n * All other layers cannot be reverted, so for housekeeping + perf, we merge\n * them into a single layer.\n *\n * Note that BaseStoreLayer.childStoreLayer has type OptimisticStoreLayer | null.\n * So, the state of the stack is never e.g. base <- network response. Instead,\n * we have a base + a child that we would like to attach to the base. So, we merge\n * (flatten) until we reach an optimistic layer or null, at which point, we can\n * set baseStoreLayer.childStoreLayer = storeLayerToMerge (via setChildOfNode).\n */\nfunction mergeLayersWithDataIntoBaseLayer(\n environment: IsographEnvironment,\n storeLayerToMerge: StoreLayer | null,\n baseStoreLayer: BaseStoreLayer,\n) {\n while (\n storeLayerToMerge != null &&\n storeLayerToMerge.kind !== 'OptimisticUpdaterStoreLayer'\n ) {\n mergeDataLayer(baseStoreLayer.data, storeLayerToMerge.data);\n storeLayerToMerge = storeLayerToMerge.childStoreLayer;\n }\n setChildOfNode(environment, baseStoreLayer, storeLayerToMerge);\n}\n\n/**\n * Now that we have replaced the optimistic layer with a network response layer, we need\n * to\n * - re-execute startUpdate and optimistic nodes, in light of the replaced data, and\n * - create two objects containing the old merged data (from the optimistic update layer\n * onward) and the new merged data (from the network response layer onward).\n * - we will compare the new and old merged data in order to determine the changed records\n * and trigger subscriptions.\n *\n * Here, \"merged data\" means all of the records + fields that were modified, starting at\n * storeLayer, e.g. in BaseLayer <- OptimisticLayer <- StartUpdateLayer, if we\n * are replacing Optimistic, then oldData will contain the records + fields modified by\n * OptimisticLayer + StartUpdateLayer.\n */\nfunction reexecuteUpdatesAndMergeData(\n storeLayer:\n | OptimisticStoreLayer\n | NetworkResponseStoreLayer\n | StartUpdateStoreLayer\n | null,\n // reflects the (now reverted) optimistic layer\n oldMergedData: StoreLayerData,\n // reflects whatever replaced the optimistic layer\n newMergedData: StoreLayerData,\n): void {\n while (storeLayer != null) {\n mergeDataLayer(oldMergedData, storeLayer.data);\n switch (storeLayer.kind) {\n case 'OptimisticNetworkResponseStoreLayer':\n case 'NetworkResponseStoreLayer':\n break;\n case 'StartUpdateStoreLayer': {\n storeLayer.data = {};\n storeLayer.startUpdate(storeLayer);\n break;\n }\n case 'OptimisticUpdaterStoreLayer': {\n storeLayer.data = {};\n storeLayer.startUpdate(storeLayer);\n break;\n }\n }\n mergeDataLayer(newMergedData, storeLayer.data);\n\n storeLayer = storeLayer.childStoreLayer;\n }\n}\n\n/**\n * Set storeLayerToModify's child to a given layer. This may be null!\n * If it is null, set the environment.store to storeLayerToModify.\n * If it is not null, then the existing environment.store value remains\n * valid.\n */\nfunction setChildOfNode<TStoreLayer extends StoreLayer>(\n environment: IsographEnvironment,\n storeLayerToModify: TStoreLayer,\n newChildStoreLayer: TStoreLayer['childStoreLayer'],\n) {\n storeLayerToModify.childStoreLayer = newChildStoreLayer;\n if (newChildStoreLayer != null) {\n newChildStoreLayer.parentStoreLayer = storeLayerToModify;\n } else {\n environment.store = storeLayerToModify;\n }\n}\n\n/**\n * Remove an optimistic store layer from the stack, potentially replacing it\n * with a network response.\n *\n * After we do this, we must re-execute all child startUpdate and optimistic\n * layers (since their data may have changed.) We also keep track of changed\n * records, in order to call affected subscriptions.\n */\nexport function revertOptimisticStoreLayerAndMaybeReplace(\n environment: IsographEnvironment,\n optimisticNode: OptimisticStoreLayer,\n normalizeData: null | ((storeLayer: StoreLayerWithData) => void),\n): void {\n // We cannot just replace the optimistic node with the network response node,\n // because (e.g.) the types allow Base <- Opt, but not Base <- NetworkResponse.\n // We also may be removing the optimistic layer without replacing it with\n // anything, which would also be disallowed if the original stack was\n // Base <- Opt <- NetworkResponse.\n //\n // Thus, instead, we will (1) replace the optimistic node's data with an empty object\n // and attach the network response as a child.\n const oldMergedData = optimisticNode.data;\n optimisticNode.data = {};\n\n let newMergedData = {};\n let childNode = optimisticNode.childStoreLayer;\n if (normalizeData != null) {\n const networkResponseStoreLayer: NetworkResponseStoreLayer = {\n kind: 'NetworkResponseStoreLayer',\n data: {},\n parentStoreLayer: optimisticNode,\n childStoreLayer: null,\n };\n normalizeData(networkResponseStoreLayer);\n\n if (childNode?.kind === 'NetworkResponseStoreLayer') {\n // (2) if the optimistic layer's child was a network response, and we are\n // replacing it with a network response, we must merge the replacement\n // and the child.\n mergeDataLayer(networkResponseStoreLayer.data, childNode.data);\n mergeDataLayer(oldMergedData, childNode.data);\n childNode = childNode.childStoreLayer;\n }\n newMergedData = structuredClone(networkResponseStoreLayer.data);\n setChildOfNode(environment, networkResponseStoreLayer, childNode);\n optimisticNode.childStoreLayer = networkResponseStoreLayer;\n }\n\n // (3) Re-execute all updates, accumulating all changed values into newMergedData.\n // Since we have already written the network response into newMergedData, we\n // can proceed from the child of the (potentially merged) network response layer.\n //\n // Note that it is important that reexecuteUpdatesAndMergeData is called here!\n // That is because we created newMergedData from the network response layer's data,\n // and later, we may merge that network response into the parent layer (if it is\n // a base layer). That merged layer will contain many extraneous records (unless the\n // base layer is empty).\n //\n // This would cause us to re-execute subscriptions unnecessarily, as these records\n // do not represent changes between the optimistic and network response layers.\n reexecuteUpdatesAndMergeData(childNode, oldMergedData, newMergedData);\n\n // (4) Now, we can finally remove the optimistic layer, i.e. do\n // optimistic.parent.child = optimistic.child.\n // But the types don't line up, so we handle the cases differently, based on the\n // parent layer type.\n if (optimisticNode.parentStoreLayer.kind === 'BaseStoreLayer') {\n // (4a) If the optimistic parent is the base layer, then we have a problem: base.child\n // must be an optimistic layer or null. So, we merge the optimistic children into the\n // base layer until we reach an optimistic layer.\n mergeLayersWithDataIntoBaseLayer(\n environment,\n optimisticNode.childStoreLayer,\n optimisticNode.parentStoreLayer,\n );\n } else if (\n optimisticNode.parentStoreLayer.kind === 'NetworkResponseStoreLayer' &&\n optimisticNode.childStoreLayer?.kind === 'NetworkResponseStoreLayer'\n ) {\n // (4b) if the parent is a network response layer, simply merge those. (We do not\n // attempt to merge other layers, e.g. startUpdate layers, because there is some\n // optimistic layer between this layer and the base, and the startUpdate will need\n // to be recalculated if the optimistic layer is reverted.)\n mergeDataLayer(\n optimisticNode.parentStoreLayer.data,\n optimisticNode.childStoreLayer.data,\n );\n\n setChildOfNode(\n environment,\n optimisticNode.parentStoreLayer,\n optimisticNode.childStoreLayer.childStoreLayer,\n );\n } else {\n // (4c) Otherwise, the parent is an optimistic or start update layer, and we can\n // set optimistic.parent.child = optimistic.child.\n setChildOfNode(\n environment,\n optimisticNode.parentStoreLayer,\n optimisticNode.childStoreLayer,\n );\n }\n\n // (5) finally, compare the oldMergedData and newMergedData objects, in order to extract\n // the modified IDs, and re-execute subscriptions.\n let encounteredIds: EncounteredIds = new Map();\n compareData(oldMergedData, newMergedData, encounteredIds);\n callSubscriptions(environment, encounteredIds);\n}\n\nexport type StoreLayer =\n | OptimisticStoreLayer\n | NetworkResponseStoreLayer\n | StartUpdateStoreLayer\n | BaseStoreLayer;\n\nexport type StoreLayerWithData =\n | BaseStoreLayer\n | NetworkResponseStoreLayer\n | OptimisticNetworkResponseStoreLayer;\n\nfunction compareData(\n oldData: StoreLayerData,\n newData: StoreLayerData,\n encounteredIds: EncounteredIds,\n): void {\n const oldDataTypeNames = new Set(Object.keys(oldData));\n const newDataTypeNames = new Set(Object.keys(newData));\n\n for (const oldTypeName of oldDataTypeNames.difference(newDataTypeNames)) {\n const set = insertEmptySetIfMissing(encounteredIds, oldTypeName);\n for (const id in oldData[oldTypeName]) {\n set.add(id);\n }\n }\n\n for (const [typeName, newRecords] of Object.entries(newData)) {\n if (newRecords == null) {\n continue;\n }\n const oldRecords = oldData[typeName];\n outer: for (const [id, newRecord] of Object.entries(newRecords)) {\n if (newRecord == null) {\n continue;\n }\n const oldRecord = oldRecords?.[id];\n\n for (const [recordKey, newRecordValue] of Object.entries(newRecord)) {\n // TODO: compare links, compare arrays\n if (newRecordValue !== oldRecord?.[recordKey]) {\n const set = insertEmptySetIfMissing(encounteredIds, typeName);\n set.add(id);\n continue outer;\n }\n }\n\n encounteredIds.get(typeName)?.delete(id);\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"optimisticProxy.mjs","names":[],"sources":["../../src/core/optimisticProxy.ts"],"sourcesContent":["import { insertEmptySetIfMissing, type EncounteredIds } from './cache';\nimport { callSubscriptions } from './subscribe';\nimport type {\n BaseStoreLayerData,\n IsographEnvironment,\n StoreLayerData,\n StoreLink,\n StoreRecord,\n} from './IsographEnvironment';\n\nexport function getOrInsertRecord(\n dataLayer: StoreLayerData,\n link: StoreLink,\n): StoreRecord {\n const recordsById = (dataLayer[link.__typename] ??= {});\n return (recordsById[link.__link] ??= {});\n}\n\n/**\n * Given the child-most store layer (i.e. environment.store) and a link (identifying a\n * store record), create a proxy object that attempts to read through each successive\n * store layer until a value (i.e. field name) is found. If found, return that value.\n */\nexport function getStoreRecordProxy(\n storeLayer: StoreLayer,\n link: StoreLink,\n): Readonly<StoreRecord> | null | undefined {\n let startNode: StoreLayer | null = storeLayer;\n while (startNode != null) {\n const storeRecord = startNode.data[link.__typename]?.[link.__link];\n if (storeRecord === undefined) {\n startNode = startNode.parentStoreLayer;\n continue;\n }\n\n if (storeRecord == null) {\n return null;\n }\n\n return getMutableStoreRecordProxy(startNode, link);\n }\n\n return undefined;\n}\n\nexport function getMutableStoreRecordProxy(\n childMostStoreLayer: StoreLayer,\n link: StoreLink,\n): StoreRecord {\n return new Proxy<StoreRecord>(\n {},\n {\n get(_, propertyName) {\n let currentStoreLayer: StoreLayer | null = childMostStoreLayer;\n while (currentStoreLayer != null) {\n const storeRecord =\n currentStoreLayer.data[link.__typename]?.[link.__link];\n if (storeRecord !== undefined) {\n if (storeRecord == null) {\n return undefined;\n }\n const value = Reflect.get(storeRecord, propertyName);\n if (value !== undefined) {\n return value;\n }\n }\n currentStoreLayer = currentStoreLayer.parentStoreLayer;\n }\n },\n has(_, propertyName) {\n let currentStoreLayer: StoreLayer | null = childMostStoreLayer;\n while (currentStoreLayer != null) {\n const storeRecord =\n currentStoreLayer.data[link.__typename]?.[link.__link];\n if (storeRecord !== undefined) {\n if (storeRecord == null) {\n return false;\n }\n\n const value = Reflect.has(storeRecord, propertyName);\n if (value) {\n return true;\n }\n }\n currentStoreLayer = currentStoreLayer.parentStoreLayer;\n }\n return false;\n },\n set(_, p, newValue) {\n return Reflect.set(\n getOrInsertRecord(childMostStoreLayer.data, link),\n p,\n newValue,\n );\n },\n },\n );\n}\n\nexport type BaseStoreLayer = {\n readonly kind: 'BaseStoreLayer';\n childStoreLayer: OptimisticStoreLayer | null;\n readonly parentStoreLayer: null;\n readonly data: BaseStoreLayerData;\n};\n\nexport type NetworkResponseStoreLayer = {\n readonly kind: 'NetworkResponseStoreLayer';\n childStoreLayer: OptimisticStoreLayer | StartUpdateStoreLayer | null;\n parentStoreLayer: OptimisticStoreLayer | StartUpdateStoreLayer;\n readonly data: StoreLayerData;\n};\n\nexport type DataUpdate<TStoreLayer extends StoreLayer> = (\n storeLayer: TStoreLayer,\n) => void;\n\nexport type StartUpdateStoreLayer = {\n readonly kind: 'StartUpdateStoreLayer';\n childStoreLayer: OptimisticStoreLayer | NetworkResponseStoreLayer | null;\n parentStoreLayer: OptimisticStoreLayer | NetworkResponseStoreLayer;\n data: StoreLayerData;\n startUpdate: DataUpdate<StartUpdateStoreLayer | BaseStoreLayer>;\n};\n\nexport type OptimisticStoreLayer =\n | OptimisticUpdaterStoreLayer\n | OptimisticNetworkResponseStoreLayer;\n\nexport type OptimisticUpdaterStoreLayer = {\n readonly kind: 'OptimisticUpdaterStoreLayer';\n childStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | null;\n parentStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | BaseStoreLayer;\n data: StoreLayerData;\n readonly startUpdate: DataUpdate<OptimisticUpdaterStoreLayer>;\n};\n\nexport type OptimisticNetworkResponseStoreLayer = {\n readonly kind: 'OptimisticNetworkResponseStoreLayer';\n childStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | null;\n parentStoreLayer:\n | OptimisticStoreLayer\n | StartUpdateStoreLayer\n | NetworkResponseStoreLayer\n | BaseStoreLayer;\n data: StoreLayerData;\n};\n\nexport function addNetworkResponseStoreLayer(\n parent: StoreLayer,\n): StoreLayerWithData {\n switch (parent.kind) {\n case 'NetworkResponseStoreLayer':\n case 'BaseStoreLayer': {\n return parent;\n }\n case 'StartUpdateStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: NetworkResponseStoreLayer = {\n kind: 'NetworkResponseStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n };\n parent.childStoreLayer = node;\n\n return node;\n }\n }\n}\n\nfunction mergeDataLayer(target: StoreLayerData, source: StoreLayerData): void {\n for (const [typeName, sourceById] of Object.entries(source)) {\n if (sourceById == null) {\n target[typeName] = sourceById;\n continue;\n }\n const targetRecordById = (target[typeName] ??= {});\n for (const [id, sourceRecord] of Object.entries(sourceById)) {\n if (sourceRecord == null) {\n targetRecordById[id] = null;\n continue;\n }\n const targetRecord = (targetRecordById[id] ??= {});\n Object.assign(targetRecord, sourceRecord);\n }\n }\n}\n\nexport function addStartUpdateStoreLayer(\n parent: StoreLayer,\n startUpdate: StartUpdateStoreLayer['startUpdate'],\n): StoreLayer {\n switch (parent.kind) {\n case 'BaseStoreLayer': {\n startUpdate(parent);\n return parent;\n }\n case 'StartUpdateStoreLayer': {\n const node = parent;\n\n const prevStartUpdate = node.startUpdate;\n node.startUpdate = () => {\n prevStartUpdate(node);\n startUpdate(node);\n };\n\n startUpdate(node);\n return node;\n }\n case 'NetworkResponseStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: StartUpdateStoreLayer = {\n kind: 'StartUpdateStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n startUpdate: startUpdate,\n };\n parent.childStoreLayer = node;\n\n startUpdate(node);\n return node;\n }\n }\n}\n\nexport function addOptimisticUpdaterStoreLayer(\n parent: StoreLayer,\n startUpdate: OptimisticUpdaterStoreLayer['startUpdate'],\n): OptimisticUpdaterStoreLayer {\n switch (parent.kind) {\n case 'BaseStoreLayer':\n case 'StartUpdateStoreLayer':\n case 'NetworkResponseStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: OptimisticUpdaterStoreLayer = {\n kind: 'OptimisticUpdaterStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n startUpdate: startUpdate,\n };\n\n startUpdate(node);\n parent.childStoreLayer = node;\n\n return node;\n }\n }\n}\n\nexport function addOptimisticNetworkResponseStoreLayer(\n parent: StoreLayer,\n): OptimisticNetworkResponseStoreLayer {\n switch (parent.kind) {\n case 'BaseStoreLayer':\n case 'StartUpdateStoreLayer':\n case 'NetworkResponseStoreLayer':\n case 'OptimisticNetworkResponseStoreLayer':\n case 'OptimisticUpdaterStoreLayer': {\n const node: OptimisticNetworkResponseStoreLayer = {\n kind: 'OptimisticNetworkResponseStoreLayer',\n parentStoreLayer: parent,\n childStoreLayer: null,\n data: {},\n };\n\n parent.childStoreLayer = node;\n\n return node;\n }\n }\n}\n\n/**\n * Merge storeLayerToMerge, and its children, into baseStoreLayer.\n * We can merge until we reach a revertible layer (i.e. an optimistic layer).\n * All other layers cannot be reverted, so for housekeeping + perf, we merge\n * them into a single layer.\n *\n * Note that BaseStoreLayer.childStoreLayer has type OptimisticStoreLayer | null.\n * So, the state of the stack is never e.g. base <- network response. Instead,\n * we have a base + a child that we would like to attach to the base. So, we merge\n * (flatten) until we reach an optimistic layer or null, at which point, we can\n * set baseStoreLayer.childStoreLayer = storeLayerToMerge (via setChildOfNode).\n */\nfunction mergeLayersWithDataIntoBaseLayer(\n environment: IsographEnvironment,\n storeLayerToMerge: StoreLayer | null,\n baseStoreLayer: BaseStoreLayer,\n) {\n while (\n storeLayerToMerge != null &&\n storeLayerToMerge.kind !== 'OptimisticUpdaterStoreLayer'\n ) {\n mergeDataLayer(baseStoreLayer.data, storeLayerToMerge.data);\n storeLayerToMerge = storeLayerToMerge.childStoreLayer;\n }\n setChildOfNode(environment, baseStoreLayer, storeLayerToMerge);\n}\n\n/**\n * Now that we have replaced the optimistic layer with a network response layer, we need\n * to\n * - re-execute startUpdate and optimistic nodes, in light of the replaced data, and\n * - create two objects containing the old merged data (from the optimistic update layer\n * onward) and the new merged data (from the network response layer onward).\n * - we will compare the new and old merged data in order to determine the changed records\n * and trigger subscriptions.\n *\n * Here, \"merged data\" means all of the records + fields that were modified, starting at\n * storeLayer, e.g. in BaseLayer <- OptimisticLayer <- StartUpdateLayer, if we\n * are replacing Optimistic, then oldData will contain the records + fields modified by\n * OptimisticLayer + StartUpdateLayer.\n */\nfunction reexecuteUpdatesAndMergeData(\n storeLayer:\n | OptimisticStoreLayer\n | NetworkResponseStoreLayer\n | StartUpdateStoreLayer\n | null,\n // reflects the (now reverted) optimistic layer\n oldMergedData: StoreLayerData,\n // reflects whatever replaced the optimistic layer\n newMergedData: StoreLayerData,\n): void {\n while (storeLayer != null) {\n mergeDataLayer(oldMergedData, storeLayer.data);\n switch (storeLayer.kind) {\n case 'OptimisticNetworkResponseStoreLayer':\n case 'NetworkResponseStoreLayer':\n break;\n case 'StartUpdateStoreLayer': {\n storeLayer.data = {};\n storeLayer.startUpdate(storeLayer);\n break;\n }\n case 'OptimisticUpdaterStoreLayer': {\n storeLayer.data = {};\n storeLayer.startUpdate(storeLayer);\n break;\n }\n }\n mergeDataLayer(newMergedData, storeLayer.data);\n\n storeLayer = storeLayer.childStoreLayer;\n }\n}\n\n/**\n * Set storeLayerToModify's child to a given layer. This may be null!\n * If it is null, set the environment.store to storeLayerToModify.\n * If it is not null, then the existing environment.store value remains\n * valid.\n */\nfunction setChildOfNode<TStoreLayer extends StoreLayer>(\n environment: IsographEnvironment,\n storeLayerToModify: TStoreLayer,\n newChildStoreLayer: TStoreLayer['childStoreLayer'],\n) {\n storeLayerToModify.childStoreLayer = newChildStoreLayer;\n if (newChildStoreLayer != null) {\n newChildStoreLayer.parentStoreLayer = storeLayerToModify;\n } else {\n environment.store = storeLayerToModify;\n }\n}\n\n/**\n * Remove an optimistic store layer from the stack, potentially replacing it\n * with a network response.\n *\n * After we do this, we must re-execute all child startUpdate and optimistic\n * layers (since their data may have changed.) We also keep track of changed\n * records, in order to call affected subscriptions.\n */\nexport function revertOptimisticStoreLayerAndMaybeReplace(\n environment: IsographEnvironment,\n optimisticNode: OptimisticStoreLayer,\n normalizeData: null | ((storeLayer: StoreLayerWithData) => void),\n): void {\n // We cannot just replace the optimistic node with the network response node,\n // because (e.g.) the types allow Base <- Opt, but not Base <- NetworkResponse.\n // We also may be removing the optimistic layer without replacing it with\n // anything, which would also be disallowed if the original stack was\n // Base <- Opt <- NetworkResponse.\n //\n // Thus, instead, we will (1) replace the optimistic node's data with an empty object\n // and attach the network response as a child.\n const oldMergedData = optimisticNode.data;\n optimisticNode.data = {};\n\n let newMergedData = {};\n let childNode = optimisticNode.childStoreLayer;\n if (normalizeData != null) {\n const networkResponseStoreLayer: NetworkResponseStoreLayer = {\n kind: 'NetworkResponseStoreLayer',\n data: {},\n parentStoreLayer: optimisticNode,\n childStoreLayer: null,\n };\n normalizeData(networkResponseStoreLayer);\n\n if (childNode?.kind === 'NetworkResponseStoreLayer') {\n // (2) if the optimistic layer's child was a network response, and we are\n // replacing it with a network response, we must merge the replacement\n // and the child.\n mergeDataLayer(networkResponseStoreLayer.data, childNode.data);\n mergeDataLayer(oldMergedData, childNode.data);\n childNode = childNode.childStoreLayer;\n }\n newMergedData = structuredClone(networkResponseStoreLayer.data);\n setChildOfNode(environment, networkResponseStoreLayer, childNode);\n optimisticNode.childStoreLayer = networkResponseStoreLayer;\n }\n\n // (3) Re-execute all updates, accumulating all changed values into newMergedData.\n // Since we have already written the network response into newMergedData, we\n // can proceed from the child of the (potentially merged) network response layer.\n //\n // Note that it is important that reexecuteUpdatesAndMergeData is called here!\n // That is because we created newMergedData from the network response layer's data,\n // and later, we may merge that network response into the parent layer (if it is\n // a base layer). That merged layer will contain many extraneous records (unless the\n // base layer is empty).\n //\n // This would cause us to re-execute subscriptions unnecessarily, as these records\n // do not represent changes between the optimistic and network response layers.\n reexecuteUpdatesAndMergeData(childNode, oldMergedData, newMergedData);\n\n // (4) Now, we can finally remove the optimistic layer, i.e. do\n // optimistic.parent.child = optimistic.child.\n // But the types don't line up, so we handle the cases differently, based on the\n // parent layer type.\n if (optimisticNode.parentStoreLayer.kind === 'BaseStoreLayer') {\n // (4a) If the optimistic parent is the base layer, then we have a problem: base.child\n // must be an optimistic layer or null. So, we merge the optimistic children into the\n // base layer until we reach an optimistic layer.\n mergeLayersWithDataIntoBaseLayer(\n environment,\n optimisticNode.childStoreLayer,\n optimisticNode.parentStoreLayer,\n );\n } else if (\n optimisticNode.parentStoreLayer.kind === 'NetworkResponseStoreLayer' &&\n optimisticNode.childStoreLayer?.kind === 'NetworkResponseStoreLayer'\n ) {\n // (4b) if the parent is a network response layer, simply merge those. (We do not\n // attempt to merge other layers, e.g. startUpdate layers, because there is some\n // optimistic layer between this layer and the base, and the startUpdate will need\n // to be recalculated if the optimistic layer is reverted.)\n mergeDataLayer(\n optimisticNode.parentStoreLayer.data,\n optimisticNode.childStoreLayer.data,\n );\n\n setChildOfNode(\n environment,\n optimisticNode.parentStoreLayer,\n optimisticNode.childStoreLayer.childStoreLayer,\n );\n } else {\n // (4c) Otherwise, the parent is an optimistic or start update layer, and we can\n // set optimistic.parent.child = optimistic.child.\n setChildOfNode(\n environment,\n optimisticNode.parentStoreLayer,\n optimisticNode.childStoreLayer,\n );\n }\n\n // (5) finally, compare the oldMergedData and newMergedData objects, in order to extract\n // the modified IDs, and re-execute subscriptions.\n let encounteredIds: EncounteredIds = new Map();\n compareData(oldMergedData, newMergedData, encounteredIds);\n callSubscriptions(environment, encounteredIds);\n}\n\nexport type StoreLayer =\n | OptimisticStoreLayer\n | NetworkResponseStoreLayer\n | StartUpdateStoreLayer\n | BaseStoreLayer;\n\nexport type StoreLayerWithData =\n | BaseStoreLayer\n | NetworkResponseStoreLayer\n | OptimisticNetworkResponseStoreLayer;\n\nfunction compareData(\n oldData: StoreLayerData,\n newData: StoreLayerData,\n encounteredIds: EncounteredIds,\n): void {\n const oldDataTypeNames = new Set(Object.keys(oldData));\n const newDataTypeNames = new Set(Object.keys(newData));\n\n for (const oldTypeName of oldDataTypeNames.difference(newDataTypeNames)) {\n const set = insertEmptySetIfMissing(encounteredIds, oldTypeName);\n for (const id in oldData[oldTypeName]) {\n set.add(id);\n }\n }\n\n for (const [typeName, newRecords] of Object.entries(newData)) {\n if (newRecords == null) {\n continue;\n }\n const oldRecords = oldData[typeName];\n outer: for (const [id, newRecord] of Object.entries(newRecords)) {\n if (newRecord == null) {\n continue;\n }\n const oldRecord = oldRecords?.[id];\n\n for (const [recordKey, newRecordValue] of Object.entries(newRecord)) {\n // TODO: compare links, compare arrays\n if (newRecordValue !== oldRecord?.[recordKey]) {\n const set = insertEmptySetIfMissing(encounteredIds, typeName);\n set.add(id);\n continue outer;\n }\n }\n\n encounteredIds.get(typeName)?.delete(id);\n }\n }\n}\n"],"mappings":"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"}
|