@khanacademy/wonder-blocks-data 10.1.0 → 10.1.2
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/CHANGELOG.md +31 -0
- package/dist/components/data.d.ts +52 -0
- package/dist/components/data.js.flow +63 -0
- package/dist/components/gql-router.d.ts +24 -0
- package/dist/components/gql-router.js.flow +33 -0
- package/dist/components/intercept-context.d.ts +10 -0
- package/dist/components/intercept-context.js.flow +19 -0
- package/dist/components/intercept-requests.d.ts +42 -0
- package/dist/components/intercept-requests.js.flow +51 -0
- package/dist/components/track-data.d.ts +11 -0
- package/dist/components/track-data.js.flow +18 -0
- package/dist/es/index.js +184 -212
- package/dist/hooks/use-cached-effect.d.ts +70 -0
- package/dist/hooks/use-cached-effect.js.flow +85 -0
- package/dist/hooks/use-gql-router-context.d.ts +5 -0
- package/dist/hooks/use-gql-router-context.js.flow +15 -0
- package/dist/hooks/use-gql.d.ts +12 -0
- package/dist/hooks/use-gql.js.flow +29 -0
- package/dist/hooks/use-hydratable-effect.d.ts +102 -0
- package/dist/hooks/use-hydratable-effect.js.flow +125 -0
- package/dist/hooks/use-request-interception.d.ts +14 -0
- package/dist/hooks/use-request-interception.js.flow +25 -0
- package/dist/hooks/use-server-effect.d.ts +39 -0
- package/dist/hooks/use-server-effect.js.flow +51 -0
- package/dist/hooks/use-shared-cache.d.ts +32 -0
- package/dist/hooks/use-shared-cache.js.flow +43 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +186 -217
- package/dist/index.js.flow +48 -2
- package/dist/util/data-error.d.ts +45 -0
- package/dist/util/data-error.js.flow +64 -0
- package/dist/util/get-gql-data-from-response.d.ts +4 -0
- package/dist/util/get-gql-data-from-response.js.flow +13 -0
- package/dist/util/get-gql-request-id.d.ts +5 -0
- package/dist/util/get-gql-request-id.js.flow +20 -0
- package/dist/util/gql-error.d.ts +28 -0
- package/dist/util/gql-error.js.flow +43 -0
- package/dist/util/gql-router-context.d.ts +3 -0
- package/dist/util/gql-router-context.js.flow +10 -0
- package/dist/util/gql-types.d.ts +34 -0
- package/dist/util/gql-types.js.flow +53 -0
- package/dist/util/graphql-document-node-parser.d.ts +18 -0
- package/dist/util/graphql-document-node-parser.js.flow +31 -0
- package/dist/util/graphql-types.d.ts +19 -0
- package/dist/util/graphql-types.js.flow +30 -0
- package/dist/util/hydration-cache-api.d.ts +17 -0
- package/dist/util/hydration-cache-api.js.flow +30 -0
- package/dist/util/merge-gql-context.d.ts +8 -0
- package/dist/util/merge-gql-context.js.flow +19 -0
- package/dist/util/purge-caches.d.ts +8 -0
- package/dist/util/purge-caches.js.flow +15 -0
- package/dist/util/request-api.d.ts +28 -0
- package/dist/util/request-api.js.flow +34 -0
- package/dist/util/request-fulfillment.d.ts +37 -0
- package/dist/util/request-fulfillment.js.flow +50 -0
- package/dist/util/request-tracking.d.ts +62 -0
- package/dist/util/request-tracking.js.flow +81 -0
- package/dist/util/result-from-cache-response.d.ts +5 -0
- package/dist/util/result-from-cache-response.js.flow +15 -0
- package/dist/util/scoped-in-memory-cache.d.ts +38 -0
- package/dist/util/scoped-in-memory-cache.js.flow +57 -0
- package/dist/util/serializable-in-memory-cache.d.ts +16 -0
- package/dist/util/serializable-in-memory-cache.js.flow +26 -0
- package/dist/util/ssr-cache.d.ts +51 -0
- package/dist/util/ssr-cache.js.flow +87 -0
- package/dist/util/status.d.ts +10 -0
- package/dist/util/status.js.flow +19 -0
- package/dist/util/to-gql-operation.d.ts +32 -0
- package/dist/util/to-gql-operation.js.flow +45 -0
- package/dist/util/types.d.ts +111 -0
- package/dist/util/types.js.flow +151 -0
- package/package.json +5 -6
- package/src/components/__tests__/{data.test.js → data.test.tsx} +42 -2
- package/src/components/__tests__/{gql-router.test.js → gql-router.test.tsx} +4 -5
- package/src/components/__tests__/{intercept-requests.test.js → intercept-requests.test.tsx} +2 -3
- package/src/components/__tests__/{track-data.test.js → track-data.test.tsx} +2 -3
- package/src/components/{data.js → data.ts} +11 -15
- package/src/components/{gql-router.js → gql-router.tsx} +12 -14
- package/src/components/{intercept-context.js → intercept-context.ts} +4 -3
- package/src/components/{intercept-requests.js → intercept-requests.tsx} +7 -8
- package/src/components/{track-data.js → track-data.tsx} +4 -5
- package/src/hooks/__tests__/{use-cached-effect.test.js → use-cached-effect.test.tsx} +55 -50
- package/src/hooks/__tests__/{use-gql-router-context.test.js → use-gql-router-context.test.tsx} +7 -7
- package/src/hooks/__tests__/{use-gql.test.js → use-gql.test.tsx} +20 -21
- package/src/hooks/__tests__/{use-hydratable-effect.test.js → use-hydratable-effect.test.ts} +42 -37
- package/src/hooks/__tests__/{use-request-interception.test.js → use-request-interception.test.tsx} +5 -3
- package/src/hooks/__tests__/{use-server-effect.test.js → use-server-effect.test.ts} +8 -2
- package/src/hooks/__tests__/{use-shared-cache.test.js → use-shared-cache.test.ts} +12 -12
- package/src/hooks/{use-cached-effect.js → use-cached-effect.ts} +27 -20
- package/src/hooks/{use-gql-router-context.js → use-gql-router-context.ts} +2 -3
- package/src/hooks/{use-gql.js → use-gql.ts} +5 -5
- package/src/hooks/{use-hydratable-effect.js → use-hydratable-effect.ts} +53 -58
- package/src/hooks/{use-request-interception.js → use-request-interception.ts} +4 -4
- package/src/hooks/{use-server-effect.js → use-server-effect.ts} +7 -9
- package/src/hooks/{use-shared-cache.js → use-shared-cache.ts} +13 -8
- package/src/{index.js → index.ts} +0 -1
- package/src/util/__tests__/{get-gql-data-from-response.test.js → get-gql-data-from-response.test.ts} +0 -1
- package/src/util/__tests__/{get-gql-request-id.test.js → get-gql-request-id.test.ts} +9 -11
- package/src/util/__tests__/{graphql-document-node-parser.test.js → graphql-document-node-parser.test.ts} +11 -12
- package/src/util/__tests__/{hydration-cache-api.test.js → hydration-cache-api.test.ts} +1 -2
- package/src/util/__tests__/{merge-gql-context.test.js → merge-gql-context.test.ts} +4 -5
- package/src/util/__tests__/{purge-caches.test.js → purge-caches.test.ts} +0 -1
- package/src/util/__tests__/{request-api.test.js → request-api.test.ts} +2 -2
- package/src/util/__tests__/{request-fulfillment.test.js → request-fulfillment.test.ts} +0 -1
- package/src/util/__tests__/{request-tracking.test.js → request-tracking.test.tsx} +13 -6
- package/src/util/__tests__/{result-from-cache-response.test.js → result-from-cache-response.test.ts} +2 -4
- package/src/util/__tests__/{scoped-in-memory-cache.test.js → scoped-in-memory-cache.test.ts} +4 -5
- package/src/util/__tests__/{serializable-in-memory-cache.test.js → serializable-in-memory-cache.test.ts} +7 -7
- package/src/util/__tests__/{ssr-cache.test.js → ssr-cache.test.ts} +3 -2
- package/src/util/__tests__/{to-gql-operation.test.js → to-gql-operation.test.ts} +2 -1
- package/src/util/{data-error.js → data-error.ts} +2 -3
- package/src/util/{get-gql-data-from-response.js → get-gql-data-from-response.ts} +1 -6
- package/src/util/{get-gql-request-id.js → get-gql-request-id.ts} +12 -16
- package/src/util/{gql-error.js → gql-error.ts} +2 -3
- package/src/util/gql-router-context.ts +6 -0
- package/src/util/{gql-types.js → gql-types.ts} +27 -23
- package/src/util/{graphql-document-node-parser.js → graphql-document-node-parser.ts} +6 -7
- package/src/util/graphql-types.ts +27 -0
- package/src/util/{hydration-cache-api.js → hydration-cache-api.ts} +4 -2
- package/src/util/{merge-gql-context.js → merge-gql-context.ts} +2 -2
- package/src/util/{purge-caches.js → purge-caches.ts} +0 -1
- package/src/util/{request-api.js → request-api.ts} +0 -1
- package/src/util/{request-fulfillment.js → request-fulfillment.ts} +13 -12
- package/src/util/{request-tracking.js → request-tracking.ts} +12 -13
- package/src/util/{result-from-cache-response.js → result-from-cache-response.ts} +3 -4
- package/src/util/{scoped-in-memory-cache.js → scoped-in-memory-cache.ts} +1 -2
- package/src/util/{serializable-in-memory-cache.js → serializable-in-memory-cache.ts} +2 -3
- package/src/util/{ssr-cache.js → ssr-cache.ts} +19 -18
- package/src/util/{status.js → status.ts} +4 -5
- package/src/util/{to-gql-operation.js → to-gql-operation.ts} +1 -2
- package/src/util/{types.js → types.ts} +39 -48
- package/tsconfig.json +11 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/__docs__/_overview_.stories.mdx +0 -18
- package/src/__docs__/_overview_graphql.stories.mdx +0 -35
- package/src/__docs__/_overview_ssr_.stories.mdx +0 -185
- package/src/__docs__/_overview_testing_.stories.mdx +0 -123
- package/src/__docs__/exports.abort-inflight-requests.stories.mdx +0 -20
- package/src/__docs__/exports.data-error.stories.mdx +0 -23
- package/src/__docs__/exports.data-errors.stories.mdx +0 -23
- package/src/__docs__/exports.data.stories.mdx +0 -146
- package/src/__docs__/exports.fetch-tracked-requests.stories.mdx +0 -24
- package/src/__docs__/exports.get-gql-request-id.stories.mdx +0 -24
- package/src/__docs__/exports.gql-error.stories.mdx +0 -23
- package/src/__docs__/exports.gql-errors.stories.mdx +0 -20
- package/src/__docs__/exports.gql-router.stories.mdx +0 -29
- package/src/__docs__/exports.has-tracked-requests-to-be-fetched.stories.mdx +0 -20
- package/src/__docs__/exports.intercept-requests.stories.mdx +0 -69
- package/src/__docs__/exports.intialize-hydration-cache.stories.mdx +0 -29
- package/src/__docs__/exports.purge-caches.stories.mdx +0 -23
- package/src/__docs__/exports.purge-hydration-cache.stories.mdx +0 -24
- package/src/__docs__/exports.scoped-in-memory-cache.stories.mdx +0 -92
- package/src/__docs__/exports.serializable-in-memory-cache.stories.mdx +0 -112
- package/src/__docs__/exports.shared-cache.stories.mdx +0 -16
- package/src/__docs__/exports.status.stories.mdx +0 -31
- package/src/__docs__/exports.track-data.stories.mdx +0 -209
- package/src/__docs__/exports.use-cached-effect.stories.mdx +0 -44
- package/src/__docs__/exports.use-gql.stories.mdx +0 -41
- package/src/__docs__/exports.use-hydratable-effect.stories.mdx +0 -43
- package/src/__docs__/exports.use-server-effect.stories.mdx +0 -50
- package/src/__docs__/exports.use-shared-cache.stories.mdx +0 -30
- package/src/__docs__/exports.when-client-side.stories.mdx +0 -33
- package/src/__docs__/types.cached-response.stories.mdx +0 -29
- package/src/__docs__/types.error-options.stories.mdx +0 -21
- package/src/__docs__/types.fetch-policy.stories.mdx +0 -44
- package/src/__docs__/types.gql-context.stories.mdx +0 -20
- package/src/__docs__/types.gql-fetch-fn.stories.mdx +0 -24
- package/src/__docs__/types.gql-fetch-options.stories.mdx +0 -24
- package/src/__docs__/types.gql-operation-type.stories.mdx +0 -24
- package/src/__docs__/types.gql-operation.stories.mdx +0 -67
- package/src/__docs__/types.raw-scoped-cache.stories.mdx +0 -27
- package/src/__docs__/types.response-cache.stories.mdx +0 -33
- package/src/__docs__/types.result.stories.mdx +0 -39
- package/src/__docs__/types.scoped-cache.stories.mdx +0 -114
- package/src/__docs__/types.valid-cache-data.stories.mdx +0 -23
- package/src/util/gql-router-context.js +0 -6
- package/src/util/graphql-types.js +0 -30
- /package/src/hooks/__tests__/__snapshots__/{use-shared-cache.test.js.snap → use-shared-cache.test.ts.snap} +0 -0
- /package/src/util/__tests__/__snapshots__/{scoped-in-memory-cache.test.js.snap → scoped-in-memory-cache.test.ts.snap} +0 -0
- /package/src/util/__tests__/__snapshots__/{serializable-in-memory-cache.test.js.snap → serializable-in-memory-cache.test.ts.snap} +0 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {graphQLDocumentNodeParser} from "../graphql-document-node-parser";
|
|
3
2
|
|
|
4
3
|
describe("#graphQLDocumentNodeParser", () => {
|
|
@@ -61,7 +60,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
61
60
|
},
|
|
62
61
|
},
|
|
63
62
|
],
|
|
64
|
-
};
|
|
63
|
+
} as const;
|
|
65
64
|
|
|
66
65
|
// Act
|
|
67
66
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -87,7 +86,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
87
86
|
},
|
|
88
87
|
},
|
|
89
88
|
],
|
|
90
|
-
};
|
|
89
|
+
} as const;
|
|
91
90
|
|
|
92
91
|
// Act
|
|
93
92
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -122,7 +121,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
122
121
|
},
|
|
123
122
|
},
|
|
124
123
|
],
|
|
125
|
-
};
|
|
124
|
+
} as const;
|
|
126
125
|
|
|
127
126
|
// Act
|
|
128
127
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -157,7 +156,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
157
156
|
},
|
|
158
157
|
},
|
|
159
158
|
],
|
|
160
|
-
};
|
|
159
|
+
} as const;
|
|
161
160
|
|
|
162
161
|
// Act
|
|
163
162
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -192,7 +191,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
192
191
|
},
|
|
193
192
|
},
|
|
194
193
|
],
|
|
195
|
-
};
|
|
194
|
+
} as const;
|
|
196
195
|
|
|
197
196
|
// Act
|
|
198
197
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -207,7 +206,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
207
206
|
describe("not in production - more informative error messages", () => {
|
|
208
207
|
it("should throw if the document lacks the kind property", () => {
|
|
209
208
|
// Arrange
|
|
210
|
-
const documentNode =
|
|
209
|
+
const documentNode = {} as any;
|
|
211
210
|
|
|
212
211
|
// Act
|
|
213
212
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -250,7 +249,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
250
249
|
},
|
|
251
250
|
},
|
|
252
251
|
],
|
|
253
|
-
};
|
|
252
|
+
} as const;
|
|
254
253
|
|
|
255
254
|
// Act
|
|
256
255
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -276,7 +275,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
276
275
|
},
|
|
277
276
|
},
|
|
278
277
|
],
|
|
279
|
-
};
|
|
278
|
+
} as const;
|
|
280
279
|
|
|
281
280
|
// Act
|
|
282
281
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -311,7 +310,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
311
310
|
},
|
|
312
311
|
},
|
|
313
312
|
],
|
|
314
|
-
};
|
|
313
|
+
} as const;
|
|
315
314
|
|
|
316
315
|
// Act
|
|
317
316
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -346,7 +345,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
346
345
|
},
|
|
347
346
|
},
|
|
348
347
|
],
|
|
349
|
-
};
|
|
348
|
+
} as const;
|
|
350
349
|
|
|
351
350
|
// Act
|
|
352
351
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -381,7 +380,7 @@ describe("#graphQLDocumentNodeParser", () => {
|
|
|
381
380
|
},
|
|
382
381
|
},
|
|
383
382
|
],
|
|
384
|
-
};
|
|
383
|
+
} as const;
|
|
385
384
|
|
|
386
385
|
// Act
|
|
387
386
|
const underTest = () => graphQLDocumentNodeParser(documentNode);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {SsrCache} from "../ssr-cache";
|
|
3
2
|
|
|
4
3
|
import {
|
|
@@ -9,7 +8,7 @@ import {
|
|
|
9
8
|
describe("#initializeHydrationCache", () => {
|
|
10
9
|
it("should call SsrCache.Default.initialize", () => {
|
|
11
10
|
// Arrange
|
|
12
|
-
const sourceCache = {};
|
|
11
|
+
const sourceCache: Record<string, any> = {};
|
|
13
12
|
const initSpy = jest.spyOn(SsrCache.Default, "initialize");
|
|
14
13
|
|
|
15
14
|
// Act
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {mergeGqlContext} from "../merge-gql-context";
|
|
3
2
|
|
|
4
3
|
describe("#mergeGqlContext", () => {
|
|
@@ -6,7 +5,7 @@ describe("#mergeGqlContext", () => {
|
|
|
6
5
|
// Arrange
|
|
7
6
|
const baseContext = {
|
|
8
7
|
foo: "bar",
|
|
9
|
-
};
|
|
8
|
+
} as const;
|
|
10
9
|
|
|
11
10
|
// Act
|
|
12
11
|
const result = mergeGqlContext<any>(baseContext, {
|
|
@@ -24,7 +23,7 @@ describe("#mergeGqlContext", () => {
|
|
|
24
23
|
// Arrange
|
|
25
24
|
const baseContext = {
|
|
26
25
|
foo: "bar",
|
|
27
|
-
};
|
|
26
|
+
} as const;
|
|
28
27
|
|
|
29
28
|
// Act
|
|
30
29
|
const result = mergeGqlContext<any>(baseContext, {
|
|
@@ -41,7 +40,7 @@ describe("#mergeGqlContext", () => {
|
|
|
41
40
|
// Arrange
|
|
42
41
|
const baseContext = {
|
|
43
42
|
foo: "bar",
|
|
44
|
-
};
|
|
43
|
+
} as const;
|
|
45
44
|
|
|
46
45
|
// Act
|
|
47
46
|
const result = mergeGqlContext<any>(baseContext, {
|
|
@@ -59,7 +58,7 @@ describe("#mergeGqlContext", () => {
|
|
|
59
58
|
const baseContext = {
|
|
60
59
|
foo: "bar",
|
|
61
60
|
fiz: "baz",
|
|
62
|
-
};
|
|
61
|
+
} as const;
|
|
63
62
|
|
|
64
63
|
// Act
|
|
65
64
|
const result = mergeGqlContext<any>(baseContext, {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {Server} from "@khanacademy/wonder-blocks-core";
|
|
3
2
|
import {RequestFulfillment} from "../request-fulfillment";
|
|
4
3
|
import {RequestTracker} from "../request-tracking";
|
|
@@ -31,7 +30,7 @@ describe("#fetchTrackedRequests", () => {
|
|
|
31
30
|
|
|
32
31
|
it("should return the response cache", async () => {
|
|
33
32
|
// Arrange
|
|
34
|
-
const responseCache = {};
|
|
33
|
+
const responseCache: Record<string, any> = {};
|
|
35
34
|
jest.spyOn(
|
|
36
35
|
RequestTracker.Default,
|
|
37
36
|
"fulfillTrackedRequests",
|
|
@@ -124,6 +123,7 @@ describe("#hasTrackedRequestsToBeFetched", () => {
|
|
|
124
123
|
const result = hasTrackedRequestsToBeFetched();
|
|
125
124
|
|
|
126
125
|
// Assert
|
|
126
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'toBeTrue' does not exist on type 'JestMatchers<boolean>'.
|
|
127
127
|
expect(result).toBeTrue();
|
|
128
128
|
});
|
|
129
129
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as React from "react";
|
|
3
2
|
import {render} from "@testing-library/react";
|
|
4
3
|
|
|
@@ -12,10 +11,10 @@ describe("../request-tracking.js", () => {
|
|
|
12
11
|
// Arrange
|
|
13
12
|
|
|
14
13
|
// Act
|
|
15
|
-
const result = await new Promise((resolve, reject) => {
|
|
14
|
+
const result = await new Promise((resolve: any, reject: any) => {
|
|
16
15
|
render(
|
|
17
16
|
<TrackerContext.Consumer>
|
|
18
|
-
{(fn) => resolve(fn)}
|
|
17
|
+
{(fn: any) => resolve(fn)}
|
|
19
18
|
</TrackerContext.Consumer>,
|
|
20
19
|
);
|
|
21
20
|
});
|
|
@@ -164,9 +163,12 @@ describe("../request-tracking.js", () => {
|
|
|
164
163
|
// Arrange
|
|
165
164
|
const requestTracker = createRequestTracker();
|
|
166
165
|
const fakeBadRequestHandler = () =>
|
|
167
|
-
new Promise((resolve, reject) =>
|
|
166
|
+
new Promise((resolve: any, reject: any) =>
|
|
167
|
+
reject("OH NO!"),
|
|
168
|
+
);
|
|
168
169
|
requestTracker.trackDataRequest(
|
|
169
170
|
"ID",
|
|
171
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '() => Promise<unknown>' is not assignable to parameter of type '() => Promise<ValidCacheData>'.
|
|
170
172
|
fakeBadRequestHandler,
|
|
171
173
|
true,
|
|
172
174
|
);
|
|
@@ -191,19 +193,22 @@ describe("../request-tracking.js", () => {
|
|
|
191
193
|
* - Handlers that resolve
|
|
192
194
|
*/
|
|
193
195
|
const fakeBadRequestHandler = () =>
|
|
194
|
-
new Promise((resolve, reject) =>
|
|
196
|
+
new Promise((resolve: any, reject: any) =>
|
|
197
|
+
reject("OH NO!"),
|
|
198
|
+
);
|
|
195
199
|
const fakeBadHandler = () => {
|
|
196
200
|
throw new Error("OH NO!");
|
|
197
201
|
};
|
|
198
202
|
const fakeValidHandler = (() => {
|
|
199
203
|
let counter = 0;
|
|
200
|
-
return (o) => {
|
|
204
|
+
return (o: any) => {
|
|
201
205
|
counter++;
|
|
202
206
|
return Promise.resolve(`DATA:${counter}`);
|
|
203
207
|
};
|
|
204
208
|
})();
|
|
205
209
|
requestTracker.trackDataRequest(
|
|
206
210
|
"BAD_REQUEST",
|
|
211
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '() => Promise<unknown>' is not assignable to parameter of type '() => Promise<ValidCacheData>'.
|
|
207
212
|
fakeBadRequestHandler,
|
|
208
213
|
true,
|
|
209
214
|
);
|
|
@@ -214,11 +219,13 @@ describe("../request-tracking.js", () => {
|
|
|
214
219
|
);
|
|
215
220
|
requestTracker.trackDataRequest(
|
|
216
221
|
"VALID_HANDLER1",
|
|
222
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '(o: any) => Promise<string>' is not assignable to parameter of type '() => Promise<string>'.
|
|
217
223
|
fakeValidHandler,
|
|
218
224
|
true,
|
|
219
225
|
);
|
|
220
226
|
requestTracker.trackDataRequest(
|
|
221
227
|
"VALID_HANDLER2",
|
|
228
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '(o: any) => Promise<string>' is not assignable to parameter of type '() => Promise<string>'.
|
|
222
229
|
fakeValidHandler,
|
|
223
230
|
true,
|
|
224
231
|
);
|
package/src/util/__tests__/{result-from-cache-response.test.js → result-from-cache-response.test.ts}
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {resultFromCachedResponse} from "../result-from-cache-response";
|
|
3
2
|
|
|
4
3
|
describe("#resultFromCachedResponse", () => {
|
|
@@ -18,7 +17,7 @@ describe("#resultFromCachedResponse", () => {
|
|
|
18
17
|
const cacheEntry = {
|
|
19
18
|
data: "DATA",
|
|
20
19
|
error: undefined,
|
|
21
|
-
};
|
|
20
|
+
} as const;
|
|
22
21
|
|
|
23
22
|
// Act
|
|
24
23
|
const result = resultFromCachedResponse(cacheEntry);
|
|
@@ -71,8 +70,7 @@ describe("#resultFromCachedResponse", () => {
|
|
|
71
70
|
};
|
|
72
71
|
|
|
73
72
|
// Act
|
|
74
|
-
//
|
|
75
|
-
// $FlowIgnore[prop-missing]
|
|
73
|
+
// @ts-expect-error [FEI-5019] - TS2339 - Property 'error' does not exist on type 'Result<ValidCacheData> | null | undefined'.
|
|
76
74
|
const {error} = resultFromCachedResponse(cacheEntry);
|
|
77
75
|
|
|
78
76
|
// Assert
|
package/src/util/__tests__/{scoped-in-memory-cache.test.js → scoped-in-memory-cache.test.ts}
RENAMED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {ScopedInMemoryCache} from "../scoped-in-memory-cache";
|
|
3
2
|
|
|
4
3
|
describe("ScopedInMemoryCache", () => {
|
|
@@ -9,7 +8,7 @@ describe("ScopedInMemoryCache", () => {
|
|
|
9
8
|
${""}
|
|
10
9
|
${5}
|
|
11
10
|
${() => "BOO"}
|
|
12
|
-
`("should throw if the id is $id", ({id}) => {
|
|
11
|
+
`("should throw if the id is $id", ({id}: any) => {
|
|
13
12
|
// Arrange
|
|
14
13
|
const cache = new ScopedInMemoryCache();
|
|
15
14
|
|
|
@@ -26,7 +25,7 @@ describe("ScopedInMemoryCache", () => {
|
|
|
26
25
|
${""}
|
|
27
26
|
${5}
|
|
28
27
|
${() => "BOO"}
|
|
29
|
-
`("should throw if the scope is $scope", ({scope}) => {
|
|
28
|
+
`("should throw if the scope is $scope", ({scope}: any) => {
|
|
30
29
|
// Arrange
|
|
31
30
|
const cache = new ScopedInMemoryCache();
|
|
32
31
|
|
|
@@ -190,7 +189,7 @@ describe("ScopedInMemoryCache", () => {
|
|
|
190
189
|
});
|
|
191
190
|
|
|
192
191
|
// Act
|
|
193
|
-
cache.purgeScope("scope1", (id, value) => value === "a");
|
|
192
|
+
cache.purgeScope("scope1", (id: any, value: any) => value === "a");
|
|
194
193
|
const result = cache._cache;
|
|
195
194
|
|
|
196
195
|
// Assert
|
|
@@ -257,7 +256,7 @@ describe("ScopedInMemoryCache", () => {
|
|
|
257
256
|
});
|
|
258
257
|
|
|
259
258
|
// Act
|
|
260
|
-
cache.purgeAll((scope, id, value) => value === "2");
|
|
259
|
+
cache.purgeAll((scope: any, id: any, value: any) => value === "2");
|
|
261
260
|
const result = cache._cache;
|
|
262
261
|
|
|
263
262
|
// Assert
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import * as WSCore from "@khanacademy/wonder-stuff-core";
|
|
3
2
|
import {SerializableInMemoryCache} from "../serializable-in-memory-cache";
|
|
4
3
|
|
|
@@ -10,11 +9,12 @@ describe("SerializableInMemoryCache", () => {
|
|
|
10
9
|
scope: {
|
|
11
10
|
key: "value",
|
|
12
11
|
},
|
|
13
|
-
};
|
|
12
|
+
} as const;
|
|
14
13
|
|
|
15
14
|
// Act
|
|
16
15
|
const cache = new SerializableInMemoryCache(sourceData);
|
|
17
16
|
// Try to mutate the cache.
|
|
17
|
+
// @ts-expect-error [FEI-5019] - TS2540 - Cannot assign to 'scope' because it is a read-only property.
|
|
18
18
|
sourceData["scope"] = {key: "SOME_NEW_DATA"};
|
|
19
19
|
const result = cache.get("scope", "key");
|
|
20
20
|
|
|
@@ -50,7 +50,7 @@ describe("SerializableInMemoryCache", () => {
|
|
|
50
50
|
${""}
|
|
51
51
|
${5}
|
|
52
52
|
${() => "BOO"}
|
|
53
|
-
`("should throw if the id is $id", ({id}) => {
|
|
53
|
+
`("should throw if the id is $id", ({id}: any) => {
|
|
54
54
|
// Arrange
|
|
55
55
|
const cache = new SerializableInMemoryCache();
|
|
56
56
|
|
|
@@ -67,7 +67,7 @@ describe("SerializableInMemoryCache", () => {
|
|
|
67
67
|
${""}
|
|
68
68
|
${5}
|
|
69
69
|
${() => "BOO"}
|
|
70
|
-
`("should throw if the scope is $scope", ({scope}) => {
|
|
70
|
+
`("should throw if the scope is $scope", ({scope}: any) => {
|
|
71
71
|
// Arrange
|
|
72
72
|
const cache = new SerializableInMemoryCache();
|
|
73
73
|
|
|
@@ -231,7 +231,7 @@ describe("SerializableInMemoryCache", () => {
|
|
|
231
231
|
});
|
|
232
232
|
|
|
233
233
|
// Act
|
|
234
|
-
cache.purgeScope("scope1", (id, value) => value === "a");
|
|
234
|
+
cache.purgeScope("scope1", (id: any, value: any) => value === "a");
|
|
235
235
|
const result = cache.clone();
|
|
236
236
|
|
|
237
237
|
// Assert
|
|
@@ -298,7 +298,7 @@ describe("SerializableInMemoryCache", () => {
|
|
|
298
298
|
});
|
|
299
299
|
|
|
300
300
|
// Act
|
|
301
|
-
cache.purgeAll((scope, id, value) => value === "2");
|
|
301
|
+
cache.purgeAll((scope: any, id: any, value: any) => value === "2");
|
|
302
302
|
const result = cache.clone();
|
|
303
303
|
|
|
304
304
|
// Assert
|
|
@@ -330,7 +330,7 @@ describe("SerializableInMemoryCache", () => {
|
|
|
330
330
|
scope1: {key: "2"},
|
|
331
331
|
scope2: {key: "1"},
|
|
332
332
|
scope3: {key: "2"},
|
|
333
|
-
};
|
|
333
|
+
} as const;
|
|
334
334
|
const cache = new SerializableInMemoryCache(data);
|
|
335
335
|
|
|
336
336
|
// Act
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {Server} from "@khanacademy/wonder-blocks-core";
|
|
3
2
|
import {SsrCache} from "../ssr-cache";
|
|
4
3
|
import {SerializableInMemoryCache} from "../serializable-in-memory-cache";
|
|
@@ -126,11 +125,12 @@ describe("../ssr-cache.js", () => {
|
|
|
126
125
|
const cache = new SsrCache();
|
|
127
126
|
const sourceData = {
|
|
128
127
|
MY_KEY: {data: "THE_DATA"},
|
|
129
|
-
};
|
|
128
|
+
} as const;
|
|
130
129
|
|
|
131
130
|
// Act
|
|
132
131
|
cache.initialize(sourceData);
|
|
133
132
|
// Try to mutate the cache.
|
|
133
|
+
// @ts-expect-error [FEI-5019] - TS2540 - Cannot assign to 'MY_KEY' because it is a read-only property.
|
|
134
134
|
sourceData["MY_KEY"] = {data: "SOME_NEW_DATA"};
|
|
135
135
|
const result = cache.getEntry("MY_KEY");
|
|
136
136
|
|
|
@@ -448,6 +448,7 @@ describe("../ssr-cache.js", () => {
|
|
|
448
448
|
const cloneSpy = jest
|
|
449
449
|
.spyOn(hydrationCache, "clone")
|
|
450
450
|
.mockReturnValue({
|
|
451
|
+
// @ts-expect-error [FEI-5019] - TS2322 - Type 'string' is not assignable to type '{ [id: string]: ValidCacheData; }'.
|
|
451
452
|
default: "CLONE!",
|
|
452
453
|
});
|
|
453
454
|
const cache = new SsrCache(hydrationCache);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {toGqlOperation} from "../to-gql-operation";
|
|
3
2
|
import * as GDNP from "../graphql-document-node-parser";
|
|
4
3
|
|
|
@@ -10,6 +9,7 @@ describe("#toGqlOperation", () => {
|
|
|
10
9
|
const documentNode: any = {};
|
|
11
10
|
const parserSpy = jest
|
|
12
11
|
.spyOn(GDNP, "graphQLDocumentNodeParser")
|
|
12
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '{ name: string; type: string; }' is not assignable to parameter of type 'IDocumentDefinition'.
|
|
13
13
|
.mockReturnValue({
|
|
14
14
|
name: "operationName",
|
|
15
15
|
type: "query",
|
|
@@ -25,6 +25,7 @@ describe("#toGqlOperation", () => {
|
|
|
25
25
|
it("should return the Wonder Blocks Data representation of the given document node", () => {
|
|
26
26
|
// Arrange
|
|
27
27
|
const documentNode: any = {};
|
|
28
|
+
// @ts-expect-error [FEI-5019] - TS2345 - Argument of type '{ name: string; type: string; }' is not assignable to parameter of type 'IDocumentDefinition'.
|
|
28
29
|
jest.spyOn(GDNP, "graphQLDocumentNodeParser").mockReturnValue({
|
|
29
30
|
name: "operationName",
|
|
30
31
|
type: "mutation",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {KindError} from "@khanacademy/wonder-stuff-core";
|
|
3
2
|
import type {ErrorOptions} from "./types";
|
|
4
3
|
|
|
@@ -52,8 +51,8 @@ export const DataErrors = Object.freeze({
|
|
|
52
51
|
export class DataError extends KindError {
|
|
53
52
|
constructor(
|
|
54
53
|
message: string,
|
|
55
|
-
kind:
|
|
56
|
-
{metadata, cause}: ErrorOptions =
|
|
54
|
+
kind: typeof DataErrors[keyof typeof DataErrors],
|
|
55
|
+
{metadata, cause}: ErrorOptions = {} as Partial<ErrorOptions>,
|
|
57
56
|
) {
|
|
58
57
|
super(message, kind, {
|
|
59
58
|
metadata,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {DataError, DataErrors} from "./data-error";
|
|
3
2
|
import {GqlError, GqlErrors} from "./gql-error";
|
|
4
3
|
|
|
@@ -14,7 +13,7 @@ export const getGqlDataFromResponse = async <TData>(
|
|
|
14
13
|
let result;
|
|
15
14
|
try {
|
|
16
15
|
result = JSON.parse(bodyText);
|
|
17
|
-
} catch (e) {
|
|
16
|
+
} catch (e: any) {
|
|
18
17
|
throw new DataError("Failed to parse response", DataErrors.Parse, {
|
|
19
18
|
metadata: {
|
|
20
19
|
statusCode: response.status,
|
|
@@ -36,11 +35,7 @@ export const getGqlDataFromResponse = async <TData>(
|
|
|
36
35
|
|
|
37
36
|
// Check that we have a valid result payload.
|
|
38
37
|
if (
|
|
39
|
-
// Flow shouldn't be warning about this.
|
|
40
|
-
// $FlowIgnore[method-unbinding]
|
|
41
38
|
!Object.prototype.hasOwnProperty.call(result, "data") &&
|
|
42
|
-
// Flow shouldn't be warning about this.
|
|
43
|
-
// $FlowIgnore[method-unbinding]
|
|
44
39
|
!Object.prototype.hasOwnProperty.call(result, "errors")
|
|
45
40
|
) {
|
|
46
41
|
throw new GqlError("Server response missing", GqlErrors.BadResponse, {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {entries} from "@khanacademy/wonder-stuff-core";
|
|
3
2
|
import type {GqlOperation, GqlContext} from "./gql-types";
|
|
4
3
|
|
|
5
|
-
const toString = (value:
|
|
4
|
+
const toString = (value: unknown): string => {
|
|
6
5
|
if (typeof value === "string") {
|
|
7
6
|
return value;
|
|
8
7
|
}
|
|
@@ -17,7 +16,7 @@ const toString = (value: mixed): string => {
|
|
|
17
16
|
return JSON.stringify(value) ?? "";
|
|
18
17
|
};
|
|
19
18
|
|
|
20
|
-
const toStringifiedVariables = (acc: any, key: string, value:
|
|
19
|
+
const toStringifiedVariables = (acc: any, key: string, value: unknown): any => {
|
|
21
20
|
if (typeof value === "object" && value !== null) {
|
|
22
21
|
// If we have an object or array, we build sub-variables so that
|
|
23
22
|
// the ID is easily human-readable rather than having lots of
|
|
@@ -30,7 +29,7 @@ const toStringifiedVariables = (acc: any, key: string, value: mixed): any => {
|
|
|
30
29
|
// or some other non-standard value. While these generally should be
|
|
31
30
|
// avoided as variables, we should handle them gracefully.
|
|
32
31
|
if (subValues.length !== 0) {
|
|
33
|
-
return subValues.reduce((innerAcc, [i, v]) => {
|
|
32
|
+
return subValues.reduce((innerAcc, [i, v]: [any, any]) => {
|
|
34
33
|
const subKey = `${key}.${i}`;
|
|
35
34
|
return toStringifiedVariables(innerAcc, subKey, v);
|
|
36
35
|
}, acc);
|
|
@@ -44,18 +43,17 @@ const toStringifiedVariables = (acc: any, key: string, value: mixed): any => {
|
|
|
44
43
|
/**
|
|
45
44
|
* Get an identifier for a given request.
|
|
46
45
|
*/
|
|
47
|
-
export const getGqlRequestId = <TData, TVariables
|
|
46
|
+
export const getGqlRequestId = <TData, TVariables extends Record<any, any>>(
|
|
48
47
|
operation: GqlOperation<TData, TVariables>,
|
|
49
|
-
variables:
|
|
48
|
+
variables: TVariables | null | undefined,
|
|
50
49
|
context: GqlContext,
|
|
51
50
|
): string => {
|
|
52
51
|
// We add all the bits for this into an array and then join them with
|
|
53
52
|
// a chosen separator.
|
|
54
|
-
const parts = [];
|
|
53
|
+
const parts: Array<string> = [];
|
|
55
54
|
|
|
56
55
|
// First, we push the context values.
|
|
57
56
|
const sortableContext = new URLSearchParams(context);
|
|
58
|
-
// $FlowIgnore[prop-missing] Flow has incomplete support for URLSearchParams
|
|
59
57
|
sortableContext.sort();
|
|
60
58
|
parts.push(sortableContext.toString());
|
|
61
59
|
|
|
@@ -92,17 +90,15 @@ export const getGqlRequestId = <TData, TVariables: {...}>(
|
|
|
92
90
|
// Thus allowing our use of URLSearchParams to both sort and easily
|
|
93
91
|
// encode the variables into an idempotent identifier for those
|
|
94
92
|
// variable values that is also human-readable.
|
|
95
|
-
const stringifiedVariables = Object.keys(variables).reduce
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
);
|
|
93
|
+
const stringifiedVariables = Object.keys(variables).reduce<
|
|
94
|
+
Record<string, any>
|
|
95
|
+
>((acc, key) => {
|
|
96
|
+
const value = variables[key];
|
|
97
|
+
return toStringifiedVariables(acc, key, value);
|
|
98
|
+
}, {});
|
|
102
99
|
// We use the same mechanism as context to sort and arrange the
|
|
103
100
|
// variables.
|
|
104
101
|
const sortableVariables = new URLSearchParams(stringifiedVariables);
|
|
105
|
-
// $FlowIgnore[prop-missing] Flow has incomplete support for URLSearchParams
|
|
106
102
|
sortableVariables.sort();
|
|
107
103
|
parts.push(sortableVariables.toString());
|
|
108
104
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
import {KindError} from "@khanacademy/wonder-stuff-core";
|
|
3
2
|
|
|
4
3
|
import type {ErrorOptions} from "./types";
|
|
@@ -32,8 +31,8 @@ export const GqlErrors = Object.freeze({
|
|
|
32
31
|
export class GqlError extends KindError {
|
|
33
32
|
constructor(
|
|
34
33
|
message: string,
|
|
35
|
-
kind:
|
|
36
|
-
{metadata, cause}: ErrorOptions =
|
|
34
|
+
kind: typeof GqlErrors[keyof typeof GqlErrors],
|
|
35
|
+
{metadata, cause}: ErrorOptions = {} as Partial<ErrorOptions>,
|
|
37
36
|
) {
|
|
38
37
|
super(message, kind, {
|
|
39
38
|
metadata,
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type {GqlRouterConfiguration} from "./gql-types";
|
|
3
|
+
|
|
4
|
+
export const GqlRouterContext: React.Context<
|
|
5
|
+
GqlRouterConfiguration<any> | null | undefined
|
|
6
|
+
> = React.createContext<GqlRouterConfiguration<any> | null | undefined>(null);
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
// @flow
|
|
2
1
|
/**
|
|
3
2
|
* Operation types.
|
|
4
3
|
*/
|
|
@@ -11,50 +10,55 @@ export type GqlOperation<
|
|
|
11
10
|
// TData is not used to define a field on this type, but it is used
|
|
12
11
|
// to ensure that calls using this operation will properly return the
|
|
13
12
|
// correct data type.
|
|
14
|
-
// eslint-disable-next-line no-unused-vars
|
|
15
|
-
TData,
|
|
16
|
-
// TVariables is not used to define a field on this type, but it is used
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
14
|
+
TData, // TVariables is not used to define a field on this type, but it is used
|
|
17
15
|
// to ensure that calls using this operation will properly consume the
|
|
18
16
|
// correct variables type.
|
|
19
|
-
// eslint-disable-next-line no-unused-vars
|
|
20
|
-
TVariables
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
18
|
+
TVariables extends object = Empty,
|
|
21
19
|
> = {
|
|
22
|
-
type: GqlOperationType
|
|
23
|
-
id: string
|
|
20
|
+
type: GqlOperationType;
|
|
21
|
+
id: string;
|
|
24
22
|
// We allow other things here to be passed along to the fetch function.
|
|
25
23
|
// For example, we might want to pass the full query/mutation definition
|
|
26
24
|
// as a string here to allow that to be sent to an Apollo server that
|
|
27
25
|
// expects it. This is a courtesy to calling code; these additional
|
|
28
26
|
// values are ignored by WB Data, and passed through as-is.
|
|
29
|
-
[key: string]:
|
|
30
|
-
...
|
|
27
|
+
[key: string]: unknown;
|
|
31
28
|
};
|
|
32
29
|
|
|
33
|
-
export type GqlContext = {
|
|
34
|
-
[key: string]: string
|
|
35
|
-
|
|
30
|
+
export type GqlContext = {
|
|
31
|
+
[key: string]: string;
|
|
32
|
+
};
|
|
36
33
|
|
|
37
34
|
/**
|
|
38
35
|
* Functions that make fetches of GQL operations.
|
|
39
36
|
*/
|
|
40
|
-
export type GqlFetchFn<
|
|
37
|
+
export type GqlFetchFn<
|
|
38
|
+
TData,
|
|
39
|
+
TVariables extends Record<any, any>,
|
|
40
|
+
TContext extends GqlContext,
|
|
41
|
+
> = (
|
|
41
42
|
operation: GqlOperation<TData, TVariables>,
|
|
42
|
-
variables:
|
|
43
|
+
variables: TVariables | null | undefined,
|
|
43
44
|
context: TContext,
|
|
44
45
|
) => Promise<Response>;
|
|
45
46
|
|
|
46
47
|
/**
|
|
47
48
|
* The configuration stored in the GqlRouterContext context.
|
|
48
49
|
*/
|
|
49
|
-
export type GqlRouterConfiguration<TContext
|
|
50
|
-
fetch: GqlFetchFn<any, any, any
|
|
51
|
-
defaultContext: TContext
|
|
52
|
-
|
|
50
|
+
export type GqlRouterConfiguration<TContext extends GqlContext> = {
|
|
51
|
+
fetch: GqlFetchFn<any, any, any>;
|
|
52
|
+
defaultContext: TContext;
|
|
53
|
+
};
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
56
|
* Options for configuring a GQL fetch.
|
|
56
57
|
*/
|
|
57
|
-
export type GqlFetchOptions<
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
export type GqlFetchOptions<
|
|
59
|
+
TVariables extends Record<any, any>,
|
|
60
|
+
TContext extends GqlContext,
|
|
61
|
+
> = {
|
|
62
|
+
variables?: TVariables;
|
|
63
|
+
context?: Partial<TContext>;
|
|
64
|
+
};
|