@khanacademy/wonder-blocks-data 10.1.0 → 10.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -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,146 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
import {Data} from "../index.js";
|
|
3
|
-
|
|
4
|
-
<Meta
|
|
5
|
-
title="Data / Exports / Data"
|
|
6
|
-
component={Data}
|
|
7
|
-
parameters={{
|
|
8
|
-
chromatic: {
|
|
9
|
-
disableSnapshot: true,
|
|
10
|
-
},
|
|
11
|
-
}}
|
|
12
|
-
/>
|
|
13
|
-
|
|
14
|
-
# Data
|
|
15
|
-
|
|
16
|
-
The `Data` component is the frontend piece of our data architecture.
|
|
17
|
-
It describes a data requirement in terms of a handler and an identifier.
|
|
18
|
-
It also has props to govern hydrate behavior as well as loading and client-side
|
|
19
|
-
request behavior.
|
|
20
|
-
|
|
21
|
-
The handler is responsible for fulfilling the request when asked to do so.
|
|
22
|
-
|
|
23
|
-
#### Server-side Rendering and Hydration
|
|
24
|
-
|
|
25
|
-
The Wonder Blocks Data framework uses an in-memory cache for supporting
|
|
26
|
-
server-side rendering (SSR) and hydration.
|
|
27
|
-
|
|
28
|
-
##### Server-side behavior
|
|
29
|
-
|
|
30
|
-
###### Cache miss
|
|
31
|
-
|
|
32
|
-
When the `Data` component does not get data or an error from the cache and it
|
|
33
|
-
is rendering server-side, it tells our request tracking that it wants data, and
|
|
34
|
-
it renders in its `loading` state. It will always render in this state if there
|
|
35
|
-
is no cached response.
|
|
36
|
-
|
|
37
|
-
###### Cache hit
|
|
38
|
-
|
|
39
|
-
When the `Data` component gets data or an error from the cache and it is
|
|
40
|
-
rendering server-side, it will render as loaded, with that data or error,
|
|
41
|
-
as it would client-side. In this situation, it does not track the request it
|
|
42
|
-
would have made, as it already has the data and doesn't need to.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
##### Client-side behavior
|
|
46
|
-
|
|
47
|
-
###### Cache miss
|
|
48
|
-
|
|
49
|
-
When the hydration cache does not contain the data, the data will be requested.
|
|
50
|
-
While the request is pending, the data is rendered in the loading state.
|
|
51
|
-
In this example, we use a 3 second delayed promise to simulate the request.
|
|
52
|
-
We start out without any data and so the request is made. Upon receipt of that
|
|
53
|
-
data or an error, we re-render.
|
|
54
|
-
|
|
55
|
-
```jsx
|
|
56
|
-
import {Body, BodyMonospace} from "@khanacademy/wonder-blocks-typography";
|
|
57
|
-
import {View} from "@khanacademy/wonder-blocks-core";
|
|
58
|
-
import {Data} from "@khanacademy/wonder-blocks-data";
|
|
59
|
-
import {Strut} from "@khanacademy/wonder-blocks-layout";
|
|
60
|
-
import Color from "@khanacademy/wonder-blocks-color";
|
|
61
|
-
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
62
|
-
|
|
63
|
-
const myValidHandler = () => new Promise((resolve, reject) =>
|
|
64
|
-
setTimeout(() => resolve("I'm DATA from a request"), 3000),
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
-
const myInvalidHandler = () => new Promise((resolve, reject) =>
|
|
68
|
-
setTimeout(() => reject("I'm an ERROR from a request"), 3000),
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
<View>
|
|
72
|
-
<View>
|
|
73
|
-
<Body>This request will succeed and give us data!</Body>
|
|
74
|
-
<Data handler={myValidHandler} requestId="VALID">
|
|
75
|
-
{(result) => {
|
|
76
|
-
if (result.status === "loading") {
|
|
77
|
-
return "Loading...";
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return (
|
|
81
|
-
<BodyMonospace>{result.data}</BodyMonospace>
|
|
82
|
-
);
|
|
83
|
-
}}
|
|
84
|
-
</Data>
|
|
85
|
-
</View>
|
|
86
|
-
<Strut size={Spacing.small_12} />
|
|
87
|
-
<View>
|
|
88
|
-
<Body>This request will go boom and give us an error!</Body>
|
|
89
|
-
<Data handler={myInvalidHandler} requestId="INVALID">
|
|
90
|
-
{(result) => {
|
|
91
|
-
if (result.status === "loading") {
|
|
92
|
-
return "Loading...";
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<BodyMonospace style={{color: Color.red}}>ERROR: {result.error}</BodyMonospace>
|
|
97
|
-
);
|
|
98
|
-
}}
|
|
99
|
-
</Data>
|
|
100
|
-
</View>
|
|
101
|
-
</View>
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
###### Cache hit
|
|
105
|
-
|
|
106
|
-
If the hydration cache already contains data or an error for our request, then
|
|
107
|
-
the `Data` component will render it immediately. The hydration cache is
|
|
108
|
-
populated using the `initializeHydrationCache` method before rendering.
|
|
109
|
-
|
|
110
|
-
```jsx
|
|
111
|
-
import {Body, BodyMonospace} from "@khanacademy/wonder-blocks-typography";
|
|
112
|
-
import {View} from "@khanacademy/wonder-blocks-core";
|
|
113
|
-
import {Data, initializeHydrationCache} from "@khanacademy/wonder-blocks-data";
|
|
114
|
-
import {Strut} from "@khanacademy/wonder-blocks-layout";
|
|
115
|
-
import Color from "@khanacademy/wonder-blocks-color";
|
|
116
|
-
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
117
|
-
|
|
118
|
-
const myHandler = () => {
|
|
119
|
-
throw new Error(
|
|
120
|
-
"If you're seeing this error, the examples are broken and data isn't in the cache that should be.",
|
|
121
|
-
);
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
initializeHydrationCache({
|
|
125
|
-
DATA: {
|
|
126
|
-
data: "I'm DATA from the hydration cache"
|
|
127
|
-
},
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
<View>
|
|
131
|
-
<View>
|
|
132
|
-
<Body>This cache has data!</Body>
|
|
133
|
-
<Data handler={myHandler} requestId="DATA">
|
|
134
|
-
{(result) => {
|
|
135
|
-
if (result.status !== "success") {
|
|
136
|
-
return "If you see this, the example is broken!";
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return (
|
|
140
|
-
<BodyMonospace>{result.data}</BodyMonospace>
|
|
141
|
-
);
|
|
142
|
-
}}
|
|
143
|
-
</Data>
|
|
144
|
-
</View>
|
|
145
|
-
</View>
|
|
146
|
-
```
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / fetchTrackedRequests()"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# fetchTrackedRequests()
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
fetchTrackedRequests(): Promise<ResponseCache>;
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
When performing server-side rendering (SSR), the data requests that are being made via the [`Data`](/docs/data-exports-data--page) component can be tracked by rendering the React tree inside the [`TrackData`](/docs/data-exports-trackdata--page) component. After this has occurred, the tracked requests can be fulfilled using `fetchTrackedRequests`.
|
|
19
|
-
|
|
20
|
-
This method returns a promise that resolves to a copy of the data that was cached by fulfilling the tracked requests. In the process, it clears the record of tracked requests so that new requests can be tracked and fulfilled if so required.
|
|
21
|
-
|
|
22
|
-
The returned copy of the data cache can be used with the [`initializeHydrationCache`](/docs/data-exports-initializehydrationcache--page) method to prepare the data cache before a subsequent render. This is useful on the server to then SSR a more complete result, and again on the client, to rehydrate that result.
|
|
23
|
-
|
|
24
|
-
More details about server-side rendering with Wonder Blocks Data can be found in the [relevant overview section](/docs/data-server-side-rendering-and-hydration--page).
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / getGqlRequestId()"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# getGqlRequestId()
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
function getGqlRequestId<TData, TVariables: {...}>(
|
|
16
|
-
operation: GqlOperation<TData, TVariables>,
|
|
17
|
-
variables: ?TVariables,
|
|
18
|
-
context: GqlContext,
|
|
19
|
-
): string;
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
The `getGqlRequestId` function generates an identifier based on the operation, variables, and context of a specific GraphQL request. This identifier is guaranteed to be the same for all requests that share the same operation, variables, and context, even if variables and context values are in different orders.
|
|
23
|
-
|
|
24
|
-
The identifier returned by this function can then be used with our [`useCachedEffect`](/docs/data-exports-usecachedeffect--page), [`useServerEffect`](/docs/data-exports-useservereffect--page), and [`useHydratableEffect`](/docs/data-exports-usehydratableeffect--page) hooks as the `requestId` parameter, allowing them to be combined with the fetch operation from the [`useGql`](/docs/data-exports-usegql--page) hook.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / GqlError"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# GqlError
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
```ts
|
|
16
|
-
new GqlError(
|
|
17
|
-
message: string,
|
|
18
|
-
kind: $Values<typeof GqlErrors>,
|
|
19
|
-
options?: ErrorOptions,
|
|
20
|
-
);
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
The `GqlError` class is a derivation of the Wonder Blocks Core `KindError` (which is itself a derivation of `Error`). It is used by the Wonder Blocks Data GraphQL framework to encapsulate errors that can occur within the GraphQL API. The different kinds of errors supported are defined by the [`GqlErrors`](/docs/data-exports-gqlerrors--page) export.
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / GqlErrors"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# GqlErrors
|
|
13
|
-
|
|
14
|
-
This export defines the error taxonomy used by Wonder Blocks Data to describe the GraphQL-related errors that can occur with GraphQL requests. These are for use with [`GqlError`](/docs/data-exports-gqlerror--page).
|
|
15
|
-
|
|
16
|
-
| Kind | Description |
|
|
17
|
-
| ---- | ----------- |
|
|
18
|
-
| `GqlErrors.Unknown` | The type of error is unknown. |
|
|
19
|
-
| `GqlErrors.BadResponse` | Response does not have the correct structure for a GraphQL response. |
|
|
20
|
-
| `GqlErrors.ErrorResult` | A valid GraphQL result with errors field in the payload. |
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
import {GqlRouter} from "../index.js";
|
|
3
|
-
|
|
4
|
-
<Meta
|
|
5
|
-
title="Data / Exports / GqlRouter"
|
|
6
|
-
component={GqlRouter}
|
|
7
|
-
parameters={{
|
|
8
|
-
chromatic: {
|
|
9
|
-
disableSnapshot: true,
|
|
10
|
-
},
|
|
11
|
-
}}
|
|
12
|
-
/>
|
|
13
|
-
|
|
14
|
-
# GqlRouter
|
|
15
|
-
|
|
16
|
-
The `GqlRouter` component is used to define the default context and fetch function for performing GraphQL requests using the Wonder Blocks Data API.
|
|
17
|
-
|
|
18
|
-
The [`useGql`](/docs/data-exports-usegql--page) (and therefore any hooks or components that use it) requires at least one `GqlRouter` in the component hierarchy above it or it will throw an error.
|
|
19
|
-
|
|
20
|
-
The `defaultContext` is specific to the needs of your specific implementation, as is the `fetch` function. Currently, a default for the fetch function is not provided by Wonder Blocks Data and should be written to the specification of the server that will fulfill your GraphQL responses. The `fetch` function must conform to the [`GqlFetchFn<>`](/docs/data-types-gqlfetchfn--page) type.
|
|
21
|
-
|
|
22
|
-
```tsx
|
|
23
|
-
<GqlRouter defaultContext={{a: "1", b: "2"}} fetch={gqlFetchFn}>
|
|
24
|
-
<div>
|
|
25
|
-
The code that will ultimately use Wonder Blocks Data-based GraphQL
|
|
26
|
-
operations goes here.
|
|
27
|
-
</div>
|
|
28
|
-
</GqlRouter>
|
|
29
|
-
```
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / hasTrackedRequestsToBeFetched()"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# hasTrackedRequestsToBeFetched()
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
hasTrackedRequestsToBeFetched(): boolean;
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
When performing server-side rendering (SSR), any requests that have been tracked will cause this method to return `true`. Once [`fetchTrackedRequests`](/docs/data-exports-fetchtrackedrequests--page) has been called and the promise is settled, this method will return `false` to indicate that there are no more pending requests.
|
|
19
|
-
|
|
20
|
-
More details about server-side rendering with Wonder Blocks Data can be found in the [relevant overview section](/docs/data-server-side-rendering-and-hydration--page).
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
import {InterceptRequests} from "../index.js";
|
|
3
|
-
|
|
4
|
-
<Meta
|
|
5
|
-
title="Data / Exports / InterceptRequests"
|
|
6
|
-
component={InterceptRequests}
|
|
7
|
-
parameters={{
|
|
8
|
-
chromatic: {
|
|
9
|
-
disableSnapshot: true,
|
|
10
|
-
},
|
|
11
|
-
}}
|
|
12
|
-
/>
|
|
13
|
-
|
|
14
|
-
# InterceptRequests
|
|
15
|
-
|
|
16
|
-
When you want to generate tests that check the loading state and
|
|
17
|
-
subsequent loaded state are working correctly for your uses of `Data` you can
|
|
18
|
-
use the `InterceptRequests` component. You can also use this component to
|
|
19
|
-
register request interceptors for any code that uses the `useRequestInterception`
|
|
20
|
-
hook.
|
|
21
|
-
|
|
22
|
-
This component takes the children to be rendered, and an interceptor function.
|
|
23
|
-
|
|
24
|
-
Note that this component is expected to be used only within test cases or
|
|
25
|
-
stories. Be careful want request IDs are matched to avoid intercepting the
|
|
26
|
-
wrong requests and remember that in-flight requests for a given request ID
|
|
27
|
-
can be shared - which means a bad request ID match could share requests across
|
|
28
|
-
different request IDs..
|
|
29
|
-
|
|
30
|
-
The `interceptor` intercept function has the form:
|
|
31
|
-
|
|
32
|
-
```js static
|
|
33
|
-
(requestId: string) => ?Promise<TData>;
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
If this method returns `null`, then the next interceptor in the chain is
|
|
37
|
-
invoked, ultimately ending with the original handler. This
|
|
38
|
-
means that a request will be made for data via the handler assigned to the
|
|
39
|
-
`Data` component being intercepted if no interceptor handles the request first.
|
|
40
|
-
|
|
41
|
-
```jsx
|
|
42
|
-
import {Body, BodyMonospace} from "@khanacademy/wonder-blocks-typography";
|
|
43
|
-
import {View} from "@khanacademy/wonder-blocks-core";
|
|
44
|
-
import {InterceptRequests, Data} from "@khanacademy/wonder-blocks-data";
|
|
45
|
-
import {Strut} from "@khanacademy/wonder-blocks-layout";
|
|
46
|
-
import Color from "@khanacademy/wonder-blocks-color";
|
|
47
|
-
import Spacing from "@khanacademy/wonder-blocks-spacing";
|
|
48
|
-
|
|
49
|
-
const myHandler = () => Promise.reject(new Error("You should not see this!"));
|
|
50
|
-
|
|
51
|
-
const interceptor = (requestId) => requestId === "INTERCEPT_EXAMPLE" ? Promise.resolve("INTERCEPTED DATA!") : null;
|
|
52
|
-
|
|
53
|
-
<InterceptRequests interceptor={interceptor}>
|
|
54
|
-
<View>
|
|
55
|
-
<Body>This received intercepted data!</Body>
|
|
56
|
-
<Data handler={myHandler} requestId="INTERCEPT_EXAMPLE">
|
|
57
|
-
{(result) => {
|
|
58
|
-
if (result.status !== "success") {
|
|
59
|
-
return "If you see this, the example is broken!";
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<BodyMonospace>{result.data}</BodyMonospace>
|
|
64
|
-
);
|
|
65
|
-
}}
|
|
66
|
-
</Data>
|
|
67
|
-
</View>
|
|
68
|
-
</InterceptRequests>
|
|
69
|
-
```
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / initializeHydrationCache()"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# initializeHydrationCache()
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
initializeHydrationCache(sourceCache: ResponseCache): void;
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
| Argument | Flow Type | Default | Description |
|
|
19
|
-
| --- | --- | --- | --- |
|
|
20
|
-
| `sourceData` | `ResponseCache` | _Required_ | The source cache that will be used to initialize the response cache. |
|
|
21
|
-
|
|
22
|
-
Wonder Blocks Data caches data in its response cache for hydration. This cache can be initialized with data using the `initializeHydrationCache` method.
|
|
23
|
-
The `initializeHydrationCache` method can only be called when the hydration cache is empty.
|
|
24
|
-
|
|
25
|
-
Usually, the data to be passed to `v` will be obtained by calling [`fetchTrackedRequests`](/docs/data-exports-fetchtrackedrequests--page) after tracking data requests (see [`TrackData`](/docs/data-exports-trackdata--page)) during server-side rendering.
|
|
26
|
-
|
|
27
|
-
Combine with [`purgeHydrationCache`](/docs/data-exports-purgehydrationcache--page) to support your testing needs.
|
|
28
|
-
|
|
29
|
-
More details about server-side rendering with Wonder Blocks Data can be found in the [relevant overview section](/docs/data-server-side-rendering-and-hydration--page).
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / purgeCaches()"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# purgeCaches()
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
purgeCaches(scope?: string): void;
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
The `purgeCaches` method will purge the following caches managed by Wonder Blocks Data:
|
|
19
|
-
|
|
20
|
-
- Shared in-memory cache as used by [`useSharedCache`](/docs/data-exports-usesharedcache--page) and other hooks
|
|
21
|
-
- Hydration cache as used during server-side rendering
|
|
22
|
-
|
|
23
|
-
This is equivalent to calling both `SharedCache.purgeAll()` and `purgeHydrationCache()`, and is especially useful when writing tests or setting up a test environment.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / purgeHydrationCache()"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# purgeHydrationCache()
|
|
13
|
-
|
|
14
|
-
```ts
|
|
15
|
-
purgeHydrationCache(predicate?: (key: string, cacheEntry: $ReadOnly<CachedResponse<ValidCacheData>>) => boolean): void;
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
| Argument | Flow Type | Default | Description |
|
|
19
|
-
| --- | --- | --- | --- |
|
|
20
|
-
| `predicate` | `(key: string, entry: $ReadOnly<CachedResponse<TData>>) => boolean)` | _Optional_ | A predicate to identify which entries to remove. If absent, all data is removed; if present, any entries for which the predicate returns `true` will be returned. |
|
|
21
|
-
|
|
22
|
-
Removes all entries that match a given predicate from the cache. If no predicate is given, all cached entries.
|
|
23
|
-
|
|
24
|
-
This can be used after [`initializeHydrationCache`](/docs/data-exports-initializehydrationcache--page) to manipulate the cache prior to hydration wich can be useful during testing (especially to clear the cache so that it can be initialized again).
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / ScopedInMemoryCache"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# ScopedInMemoryCache
|
|
13
|
-
|
|
14
|
-
This class implements an in-memory cache that can contain different scopes of cached data. This allows for quick removal of entire classes of data as identified by their scopes without having to iterate each cached item to find them. It implements the [`ScopedCache`](/docs/data-types-scopedcache--page) interface.
|
|
15
|
-
|
|
16
|
-
## constructor()
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
new ScopedInMemoryCache(initialCache?: RawScopedCache)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Creates a new instance. An initial state for the cache can be provided.
|
|
23
|
-
|
|
24
|
-
## inUse
|
|
25
|
-
|
|
26
|
-
```ts
|
|
27
|
-
if (cache.inUse) {
|
|
28
|
-
// Cache is in use
|
|
29
|
-
}
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Is `true` if the cache contains any data; otherwise, `false`.
|
|
33
|
-
|
|
34
|
-
## set()
|
|
35
|
-
|
|
36
|
-
```ts
|
|
37
|
-
set(
|
|
38
|
-
scope: string,
|
|
39
|
-
id: string,
|
|
40
|
-
value: TValue,
|
|
41
|
-
): void;
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
Sets a value in the cache within a given scope.
|
|
45
|
-
|
|
46
|
-
### Throws
|
|
47
|
-
|
|
48
|
-
| Error Type | Error Name | Reason |
|
|
49
|
-
| ------ | ------ | ------ |
|
|
50
|
-
| [`DataError`](/docs/data-exports-dataerror--page) | `InvalidInputDataError` | `id` and `scope` must be non-empty strings |
|
|
51
|
-
| [`DataError`](/docs/data-exports-dataerror--page) | `InvalidInputDataError` | `value` must be a non-function value |
|
|
52
|
-
|
|
53
|
-
## get()
|
|
54
|
-
|
|
55
|
-
```ts
|
|
56
|
-
get(scope: string, id: string): ?ValidCacheData;
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Gets a value from the cache. If a value with the given identifier (`id`) is not found within the given scope (`scope`) of the cache, `null` is returned.
|
|
60
|
-
|
|
61
|
-
## purge()
|
|
62
|
-
|
|
63
|
-
```ts
|
|
64
|
-
purge(scope: string, id: string): void;
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
Purges the value from the cache. If a value with the given identifier (`id`) is not found within the given scope (`scope`) of the cache, nothing happens.
|
|
68
|
-
|
|
69
|
-
## purgeScope()
|
|
70
|
-
|
|
71
|
-
```ts
|
|
72
|
-
purgeScope(
|
|
73
|
-
scope: string,
|
|
74
|
-
predicate?: (id: string, value: ValidCacheData) => boolean,
|
|
75
|
-
): void;
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
Purges items within a given scope (`scope`) of the cache from that scope. If a predicate is provided, only items for which the predicate returns `true` will be purged; otherwise, the entire scope will be purged.
|
|
79
|
-
|
|
80
|
-
## purgeAll()
|
|
81
|
-
|
|
82
|
-
```ts
|
|
83
|
-
purgeAll(
|
|
84
|
-
predicate?: (
|
|
85
|
-
scope: string,
|
|
86
|
-
id: string,
|
|
87
|
-
value: ValidCacheData,
|
|
88
|
-
) => boolean,
|
|
89
|
-
): void;
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
Purges all items from the cache. If a predicate is provided, only items for which the predicate returns `true` will be purged; otherwise, the entire cache will be purged.
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / SerializableInMemoryCache"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# SerializableInMemoryCache
|
|
13
|
-
|
|
14
|
-
This class is a specialization of [`ScopedInMemoryCache`](/docs/data-exports-scopedinmemorycache--page). This specialization requires that values added can be serialized to and from strings.
|
|
15
|
-
|
|
16
|
-
## constructor()
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
new SerializableInMemoryCache(initialCache?: RawScopedCache)
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Creates a new instance. The `initialCache`, if provided, will be cloned and used as the initial state of the cache.
|
|
23
|
-
|
|
24
|
-
### Throws
|
|
25
|
-
|
|
26
|
-
| Error Type | Error Name | Reason |
|
|
27
|
-
| ------ | ------ | ------ |
|
|
28
|
-
| [`DataError`](/docs/data-exports-dataerror--page) | `InvalidInputDataError` | Could not clone the initial cache. |
|
|
29
|
-
|
|
30
|
-
## inUse
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
if (cache.inUse) {
|
|
34
|
-
// Cache is in use
|
|
35
|
-
}
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Is `true` if the cache contains any data; otherwise, `false`.
|
|
39
|
-
|
|
40
|
-
## set()
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
set<TValue: ValidCacheData>(
|
|
44
|
-
scope: string,
|
|
45
|
-
id: string,
|
|
46
|
-
value: TValue,
|
|
47
|
-
): void;
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
Sets a value in the cache within a given scope. The value is cloned and the clone is frozen before being added to the cache.
|
|
51
|
-
|
|
52
|
-
### Throws
|
|
53
|
-
|
|
54
|
-
| Error Type | Error Name | Reason |
|
|
55
|
-
| ------ | ------ | ------ |
|
|
56
|
-
| [`DataError`](/docs/data-exports-dataerror--page) | `InvalidInputDataError` | `id` and `scope` must be non-empty strings |
|
|
57
|
-
| [`DataError`](/docs/data-exports-dataerror--page) | `InvalidInputDataError` | `value` must be a non-function value |
|
|
58
|
-
|
|
59
|
-
## get()
|
|
60
|
-
|
|
61
|
-
```ts
|
|
62
|
-
get(scope: string, id: string): ?ValidCacheData;
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
Gets a value from the cache. If a value with the given identifier (`id`) is not found within the given scope (`scope`) of the cache, `null` is returned.
|
|
66
|
-
|
|
67
|
-
## clone()
|
|
68
|
-
|
|
69
|
-
```ts
|
|
70
|
-
clone(): RawScopedCache;
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
Returns a clone of the current cache.
|
|
74
|
-
|
|
75
|
-
### Throws
|
|
76
|
-
|
|
77
|
-
| Error Type | Error Name | Reason |
|
|
78
|
-
| ------ | ------ | ------ |
|
|
79
|
-
| [`DataError`](/docs/data-exports-dataerror--page) | `InternalDataError` | Could not clone the cache. |
|
|
80
|
-
|
|
81
|
-
## purge()
|
|
82
|
-
|
|
83
|
-
```ts
|
|
84
|
-
purge(scope: string, id: string): void;
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Purges the value from the cache. If a value with the given identifier (`id`) is not found within the given scope (`scope`) of the cache, nothing happens.
|
|
88
|
-
|
|
89
|
-
## purgeScope()
|
|
90
|
-
|
|
91
|
-
```ts
|
|
92
|
-
purgeScope(
|
|
93
|
-
scope: string,
|
|
94
|
-
predicate?: (id: string, value: ValidCacheData) => boolean,
|
|
95
|
-
): void;
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Purges items within a given scope (`scope`) of the cache from that scope. If a predicate is provided, only items for which the predicate returns `true` will be purged; otherwise, the entire scope will be purged.
|
|
99
|
-
|
|
100
|
-
## purgeAll()
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
purgeAll(
|
|
104
|
-
predicate?: (
|
|
105
|
-
scope: string,
|
|
106
|
-
id: string,
|
|
107
|
-
value: ValidCacheData,
|
|
108
|
-
) => boolean,
|
|
109
|
-
): void;
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Purges all items from the cache. If a predicate is provided, only items for which the predicate returns `true` will be purged; otherwise, the entire cache will be purged.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import {Meta} from "@storybook/addon-docs";
|
|
2
|
-
|
|
3
|
-
<Meta
|
|
4
|
-
title="Data / Exports / SharedCache"
|
|
5
|
-
parameters={{
|
|
6
|
-
chromatic: {
|
|
7
|
-
disableSnapshot: true,
|
|
8
|
-
},
|
|
9
|
-
}}
|
|
10
|
-
/>
|
|
11
|
-
|
|
12
|
-
# SharedCache
|
|
13
|
-
|
|
14
|
-
The `SharedCache` export can be used to view and modify the in-memory cache used by [`useSharedCache`](/docs/data-exports-usesharedcache--page) hook and the hooks and components that relate to it.
|
|
15
|
-
|
|
16
|
-
The `SharedCache` export implements the [`ScopedCache` interface type](/docs/data-types-scopedcache--page).
|