@khanacademy/wonder-blocks-data 4.0.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/es/index.js +793 -375
- package/dist/index.js +1203 -523
- package/legacy-docs.md +3 -0
- package/package.json +2 -2
- package/src/__docs__/_overview_.stories.mdx +18 -0
- package/src/__docs__/_overview_graphql.stories.mdx +35 -0
- package/src/__docs__/_overview_ssr_.stories.mdx +185 -0
- package/src/__docs__/_overview_testing_.stories.mdx +123 -0
- package/src/__docs__/exports.clear-shared-cache.stories.mdx +20 -0
- package/src/__docs__/exports.data-error.stories.mdx +23 -0
- package/src/__docs__/exports.data-errors.stories.mdx +23 -0
- package/src/{components/data.md → __docs__/exports.data.stories.mdx} +15 -18
- package/src/__docs__/exports.fulfill-all-data-requests.stories.mdx +24 -0
- package/src/__docs__/exports.gql-error.stories.mdx +23 -0
- package/src/__docs__/exports.gql-errors.stories.mdx +20 -0
- package/src/__docs__/exports.gql-router.stories.mdx +29 -0
- package/src/__docs__/exports.has-unfulfilled-requests.stories.mdx +20 -0
- package/src/__docs__/exports.intercept-requests.stories.mdx +69 -0
- package/src/__docs__/exports.intialize-cache.stories.mdx +29 -0
- package/src/__docs__/exports.remove-all-from-cache.stories.mdx +24 -0
- package/src/__docs__/exports.remove-from-cache.stories.mdx +25 -0
- package/src/__docs__/exports.request-fulfillment.stories.mdx +36 -0
- package/src/__docs__/exports.scoped-in-memory-cache.stories.mdx +92 -0
- package/src/__docs__/exports.serializable-in-memory-cache.stories.mdx +112 -0
- package/src/__docs__/exports.status.stories.mdx +31 -0
- package/src/{components/track-data.md → __docs__/exports.track-data.stories.mdx} +15 -0
- package/src/__docs__/exports.use-cached-effect.stories.mdx +41 -0
- package/src/__docs__/exports.use-gql.stories.mdx +73 -0
- package/src/__docs__/exports.use-hydratable-effect.stories.mdx +43 -0
- package/src/__docs__/exports.use-server-effect.stories.mdx +38 -0
- package/src/__docs__/exports.use-shared-cache.stories.mdx +30 -0
- package/src/__docs__/exports.when-client-side.stories.mdx +33 -0
- package/src/__docs__/types.cached-response.stories.mdx +29 -0
- package/src/__docs__/types.error-options.stories.mdx +21 -0
- package/src/__docs__/types.gql-context.stories.mdx +20 -0
- package/src/__docs__/types.gql-fetch-fn.stories.mdx +24 -0
- package/src/__docs__/types.gql-fetch-options.stories.mdx +24 -0
- package/src/__docs__/types.gql-operation-type.stories.mdx +24 -0
- package/src/__docs__/types.gql-operation.stories.mdx +67 -0
- package/src/__docs__/types.response-cache.stories.mdx +33 -0
- package/src/__docs__/types.result.stories.mdx +39 -0
- package/src/__docs__/types.scoped-cache.stories.mdx +27 -0
- package/src/__docs__/types.valid-cache-data.stories.mdx +23 -0
- package/src/__tests__/__snapshots__/generated-snapshot.test.js.snap +0 -80
- package/src/__tests__/generated-snapshot.test.js +7 -31
- package/src/components/__tests__/data.test.js +160 -154
- package/src/components/__tests__/intercept-requests.test.js +58 -0
- package/src/components/data.js +22 -126
- package/src/components/intercept-context.js +4 -5
- package/src/components/intercept-requests.js +69 -0
- package/src/hooks/__tests__/__snapshots__/use-shared-cache.test.js.snap +8 -8
- package/src/hooks/__tests__/use-cached-effect.test.js +507 -0
- package/src/hooks/__tests__/use-gql-router-context.test.js +133 -0
- package/src/hooks/__tests__/use-gql.test.js +1 -30
- package/src/hooks/__tests__/use-hydratable-effect.test.js +708 -0
- package/src/hooks/__tests__/use-request-interception.test.js +255 -0
- package/src/hooks/__tests__/use-server-effect.test.js +39 -11
- package/src/hooks/use-cached-effect.js +225 -0
- package/src/hooks/use-gql-router-context.js +50 -0
- package/src/hooks/use-gql.js +22 -52
- package/src/hooks/use-hydratable-effect.js +206 -0
- package/src/hooks/use-request-interception.js +51 -0
- package/src/hooks/use-server-effect.js +14 -7
- package/src/hooks/use-shared-cache.js +13 -11
- package/src/index.js +54 -2
- package/src/util/__tests__/__snapshots__/serializable-in-memory-cache.test.js.snap +19 -0
- package/src/util/__tests__/merge-gql-context.test.js +74 -0
- package/src/util/__tests__/request-fulfillment.test.js +23 -42
- package/src/util/__tests__/request-tracking.test.js +26 -7
- package/src/util/__tests__/result-from-cache-response.test.js +19 -5
- package/src/util/__tests__/scoped-in-memory-cache.test.js +6 -85
- package/src/util/__tests__/serializable-in-memory-cache.test.js +398 -0
- package/src/util/__tests__/ssr-cache.test.js +52 -52
- package/src/util/abort-error.js +15 -0
- package/src/util/data-error.js +58 -0
- package/src/util/get-gql-data-from-response.js +3 -2
- package/src/util/gql-error.js +19 -11
- package/src/util/merge-gql-context.js +34 -0
- package/src/util/request-fulfillment.js +49 -46
- package/src/util/request-tracking.js +69 -15
- package/src/util/result-from-cache-response.js +12 -16
- package/src/util/scoped-in-memory-cache.js +24 -47
- package/src/util/serializable-in-memory-cache.js +49 -0
- package/src/util/ssr-cache.js +9 -8
- package/src/util/status.js +30 -0
- package/src/util/types.js +18 -1
- package/docs.md +0 -122
- package/src/components/__tests__/intercept-data.test.js +0 -63
- package/src/components/intercept-data.js +0 -66
- package/src/components/intercept-data.md +0 -51
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Exports / WhenClientSide"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# WhenClientSide
|
|
13
|
+
|
|
14
|
+
This enumeration is used with [`useHydratableEffect`](/docs/data-exports-usehydratableeffect--page). It defines how the hook should behave when rendering on the client.
|
|
15
|
+
|
|
16
|
+
## WhenClientSide.DoNotHydrate
|
|
17
|
+
|
|
18
|
+
The effect will not be hydrated and as such the effect will always be executed on initial render in the client. This is an advanced use-case that you should avoid unless you are certain of what you are doing.
|
|
19
|
+
|
|
20
|
+
Without hydration support to ensure the data is available for hydration on the client, your server and client rendered pages may differ and the hydration will fail. This option is useful if something else is responsible for data capture and hydration of the action that gets executed. For example, if the action uses Apollo Client to perform the asynchronous action executed by this effect, then that may be also performing hydration responsibilities. However, be cautious; the code that calls `useHydratableEffect` will have to have access to that data on hydration as `useHydratableEffect` will return a "loading" state on initial render, which is not what you will want.
|
|
21
|
+
|
|
22
|
+
## WhenClientSide.ExecuteWhenNoResult
|
|
23
|
+
|
|
24
|
+
On initial render in the client, the effect is hydrated from the server-side rendered result. However, it is only executed if there was no server-side render result to hydrate (this can happen if the server-side rendered request was aborted, or if the component is rendering for the first time on the client and was never part of the server-side rendered content).
|
|
25
|
+
|
|
26
|
+
## WhenClientSide.ExecuteWhenNoSuccessResult
|
|
27
|
+
|
|
28
|
+
This behavior will hydrate the server-side result, but it will only execute the effect on the client if the hydrated result is not a success result.
|
|
29
|
+
|
|
30
|
+
## WhenClientSide.AlwaysExecute
|
|
31
|
+
|
|
32
|
+
When the effect is executed with this behavior, the server-side result will be hydrated and the effect will be executed on the initial client-side render, regardless of the hydrated result status.
|
|
33
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / CachedResponse<>"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# CachedResponse<>
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type CachedResponse<TData: ValidCacheData> =
|
|
16
|
+
| {|
|
|
17
|
+
+error: string,
|
|
18
|
+
+data?: void,
|
|
19
|
+
|}
|
|
20
|
+
| {|
|
|
21
|
+
+data: TData,
|
|
22
|
+
+error?: void,
|
|
23
|
+
|};
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`CachedResponse<>` is a special union type that is used to represent the serialized result of a request, which can be used by Wonder Blocks Data to
|
|
27
|
+
hydrate the response.
|
|
28
|
+
|
|
29
|
+
See the section on [server-side rendering](/docs/data-server-side-rendering-and-hydration--page) for more information.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / ErrorOptions"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# ErrorOptions
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type ErrorOptions = {|
|
|
16
|
+
metadata?: ?Metadata,
|
|
17
|
+
cause?: ?Error,
|
|
18
|
+
|};
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
These options allow for the provision of a causal error instance as well as additional metadata that may be useful to the specific error being constructed (such as [`DataError`](/docs/data-exports-dataerror--page) or [`GqlError`](/docs/data-exports-gqlerror--page)).
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / GqlContext"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# GqlContext
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type GqlContext = {|
|
|
16
|
+
[key: string]: string,
|
|
17
|
+
|};
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`GqlContext` represents the valid range of values for the `context` of a GraphQL query or mutation.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / GqlFetchFn<>"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# GqlFetchFn<>
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type GqlFetchFn<TData, TVariables: {...}, TContext: GqlContext> = (
|
|
16
|
+
operation: GqlOperation<TData, TVariables>,
|
|
17
|
+
variables: ?TVariables,
|
|
18
|
+
context: TContext,
|
|
19
|
+
) => Promise<Response>;
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The `GqlFetchFn<>` type describes the function that will perform a GraphQL request. A function that fits this signature is configured in Wonder Blocks Data using the [`GqlRouter`](/docs/data-exports-gqlrouter--page) component. The [`useGql`](/docs/data-exports-usegql--page) hook and derivatives are then built on top of this to abstract away complexities, such as converting the `Response` to a valid [`Result<>`](/docs/data-types-result--page) instance, as various use cases see fit.
|
|
23
|
+
|
|
24
|
+
See the section on [GraphQL](/docs/data-graphql--page) for more information.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / GqlFetchOptions<>"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# GqlFetchOptions<>
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type GqlFetchOptions<TVariables: {...}, TContext: GqlContext> = {|
|
|
16
|
+
variables?: TVariables,
|
|
17
|
+
context?: Partial<TContext>,
|
|
18
|
+
|};
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This type describes optional configuration to apply when fulfilling a GraphQL request.
|
|
22
|
+
|
|
23
|
+
See the section on [GraphQL](/docs/data-graphql--page) for more information.
|
|
24
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / GqlOperationType"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# GqlOperationType
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type GqlOperationType = "mutation" | "query";
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Unlike some GraphQL clients, the Wonder Blocks Data GraphQL support avoids requiring the full GraphQL document node at runtime. This allows the client to be lighter weight and introduces the option for calling code to perform some GraphQL request optimizations at build time, such as formatting the document node as a string and therefore not requiring additional dependencies at runtime.
|
|
19
|
+
|
|
20
|
+
In order to allow consumers of our GraphQL support to include some validation of the GraphQL document node at runtime (such as ensuring that mutations are not performed in unsupported scenarios), we the type of the operation is included in the operation definition.
|
|
21
|
+
|
|
22
|
+
This type represents the valid values for that field.
|
|
23
|
+
|
|
24
|
+
See the section on [GraphQL](/docs/data-graphql--page) for more information.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / GqlOperation<>"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# GqlOperation<>
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type GqlOperation<
|
|
16
|
+
TData,
|
|
17
|
+
TVariables: {...} = Empty,
|
|
18
|
+
> = {
|
|
19
|
+
type: GqlOperationType,
|
|
20
|
+
id: string,
|
|
21
|
+
[key: string]: mixed,
|
|
22
|
+
...
|
|
23
|
+
};
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The `GqlOperation<>` type provides the Wonder Blocks Data definition of a GraphQL query or mutation. It has two required fields:
|
|
27
|
+
|
|
28
|
+
* `type`: The type of operation. It can be either `"query"` or `"mutation"`.
|
|
29
|
+
* `id`: The unique identifier of the operation.
|
|
30
|
+
|
|
31
|
+
Unlike some GraphQL clients, the definition of the operation (the document node, for example) is not required by the Wonder Blocks Data implementation. If a specific use requires that information, the calling code is able to provide it.
|
|
32
|
+
|
|
33
|
+
Consider the following GraphQL query (using `graphql-tag`):
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
const MyQuery = gql`
|
|
37
|
+
query myQuery {
|
|
38
|
+
user {
|
|
39
|
+
id
|
|
40
|
+
name
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Rather than using the full `DocumentNode` at runtime, one could envisage a build step that converts it to a `GqlOperation<>` at compile time by parsing the `DocumentNode` to determine the operation type and extract the name of the operation. If the actual definition is needed for sending to the server in the request, this can be obtained from `graphql/language/printer`. This would then reduce the dependencies needed to perform GraphQL operations at runtime.
|
|
47
|
+
|
|
48
|
+
The resulting `GqlOperation<>` would look like this:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
{
|
|
52
|
+
type: "query",
|
|
53
|
+
id: "myQuery",
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Or, if say, the query definition were needed (for example, Apollo will send requests with the `query` field):
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
{
|
|
61
|
+
type: "query",
|
|
62
|
+
id: "myQuery",
|
|
63
|
+
query: "query myQuery { user { id name } }",
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
See the section on [GraphQL](/docs/data-graphql--page) for more information.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / ResponseCache"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# ResponseCache
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type ResponseCache = {
|
|
16
|
+
[key: string]: CachedResponse<any>,
|
|
17
|
+
...
|
|
18
|
+
};
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`ResponseCache` describes the serialized cache that is used to hydrate responses. An example of a valid `ResponseCache` instance is shown below. Generally, you would not generate this object directly, but rather use the returned data from [`fulfillAllDataRequests`](/docs/data-exports-fulfillalldatarequests--page).
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
const responseCache: ResponseCache = {
|
|
25
|
+
DATA_ID_1: {error: "It go 💥boom 😢"},
|
|
26
|
+
DATA_ID_2: {data: ["array", "of", "data"]},
|
|
27
|
+
DATA_ID_3: {data: {some: "data"}},
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
In this example, the cache contains data retrieved for three different requests.
|
|
32
|
+
|
|
33
|
+
Each entry in the cache is of type [`CachedResponse`](/docs/data-types-cachedresponse--page). See the section on [server-side rendering](/docs/data-server-side-rendering-and-hydration--page) for more information.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / Result<>"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# Result<>
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type Result<TData: ValidCacheData> =
|
|
16
|
+
| {|
|
|
17
|
+
status: "loading",
|
|
18
|
+
|}
|
|
19
|
+
| {|
|
|
20
|
+
status: "success",
|
|
21
|
+
data: TData,
|
|
22
|
+
|}
|
|
23
|
+
| {|
|
|
24
|
+
status: "error",
|
|
25
|
+
error: Error,
|
|
26
|
+
|}
|
|
27
|
+
| {|
|
|
28
|
+
status: "aborted",
|
|
29
|
+
|};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The `Result<>` type is used to describe the result of an asynchronous operation. It is the primary type used by hooks and components in Wonder Blocks Data to convey the status of asynchronous tasks.
|
|
33
|
+
|
|
34
|
+
There are four states represented by the `Result<>` type:
|
|
35
|
+
|
|
36
|
+
* `loading`: The operation is in pending.
|
|
37
|
+
* `success`: The operation completed successfully.
|
|
38
|
+
* `error`: The operation failed.
|
|
39
|
+
* `aborted`: The operation was aborted.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / ScopedCache"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# ScopedCache
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type ScopedCache = {
|
|
16
|
+
[scope: string]: {
|
|
17
|
+
[id: string]: ValidCacheData,
|
|
18
|
+
...
|
|
19
|
+
},
|
|
20
|
+
...
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`ScopedCache` describes a cache that has distinct scoped sections. This is the representation of the caches used internally by Wonder Blocks Data to support the scoping of requests when using hooks such as [`useSharedCache`](/docs/data-exports-use-shared-cache--page), [`useCachedEffect`](/docs/data-exports-use-cached-effect--page), and [`useHydratableEffect`](/docs/data-exports-use-hydratable-effect--page).
|
|
26
|
+
|
|
27
|
+
See the section on [server-side rendering](/docs/data-server-side-rendering-and-hydration--page) for more information.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import {Meta} from "@storybook/addon-docs";
|
|
2
|
+
|
|
3
|
+
<Meta
|
|
4
|
+
title="Data / Types / ValidCacheData"
|
|
5
|
+
parameters={{
|
|
6
|
+
chromatic: {
|
|
7
|
+
disableSnapshot: true,
|
|
8
|
+
},
|
|
9
|
+
}}
|
|
10
|
+
/>
|
|
11
|
+
|
|
12
|
+
# ValidCacheData
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
type ValidCacheData =
|
|
16
|
+
| string
|
|
17
|
+
| boolean
|
|
18
|
+
| number
|
|
19
|
+
| {...}
|
|
20
|
+
| Array<?ValidCacheData>;
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This type represents the data that is allowed into the various caches provided and used by Wonder Blocks Data.
|
|
@@ -195,86 +195,6 @@ exports[`wonder-blocks-data example 2 1`] = `
|
|
|
195
195
|
I'm DATA from the hydration cache
|
|
196
196
|
</span>
|
|
197
197
|
</div>
|
|
198
|
-
<div
|
|
199
|
-
aria-hidden="true"
|
|
200
|
-
className=""
|
|
201
|
-
style={
|
|
202
|
-
Object {
|
|
203
|
-
"MsFlexBasis": 12,
|
|
204
|
-
"MsFlexPreferredSize": 12,
|
|
205
|
-
"WebkitFlexBasis": 12,
|
|
206
|
-
"alignItems": "stretch",
|
|
207
|
-
"borderStyle": "solid",
|
|
208
|
-
"borderWidth": 0,
|
|
209
|
-
"boxSizing": "border-box",
|
|
210
|
-
"display": "flex",
|
|
211
|
-
"flexBasis": 12,
|
|
212
|
-
"flexDirection": "column",
|
|
213
|
-
"flexShrink": 0,
|
|
214
|
-
"margin": 0,
|
|
215
|
-
"minHeight": 0,
|
|
216
|
-
"minWidth": 0,
|
|
217
|
-
"padding": 0,
|
|
218
|
-
"position": "relative",
|
|
219
|
-
"width": 12,
|
|
220
|
-
"zIndex": 0,
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
/>
|
|
224
|
-
<div
|
|
225
|
-
className=""
|
|
226
|
-
style={
|
|
227
|
-
Object {
|
|
228
|
-
"alignItems": "stretch",
|
|
229
|
-
"borderStyle": "solid",
|
|
230
|
-
"borderWidth": 0,
|
|
231
|
-
"boxSizing": "border-box",
|
|
232
|
-
"display": "flex",
|
|
233
|
-
"flexDirection": "column",
|
|
234
|
-
"margin": 0,
|
|
235
|
-
"minHeight": 0,
|
|
236
|
-
"minWidth": 0,
|
|
237
|
-
"padding": 0,
|
|
238
|
-
"position": "relative",
|
|
239
|
-
"zIndex": 0,
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
>
|
|
243
|
-
<span
|
|
244
|
-
className=""
|
|
245
|
-
style={
|
|
246
|
-
Object {
|
|
247
|
-
"MozOsxFontSmoothing": "grayscale",
|
|
248
|
-
"WebkitFontSmoothing": "antialiased",
|
|
249
|
-
"display": "block",
|
|
250
|
-
"fontFamily": "Lato, \\"Noto Sans\\", sans-serif",
|
|
251
|
-
"fontSize": 16,
|
|
252
|
-
"fontWeight": 400,
|
|
253
|
-
"lineHeight": "22px",
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
>
|
|
257
|
-
This cache has error!
|
|
258
|
-
</span>
|
|
259
|
-
<span
|
|
260
|
-
className=""
|
|
261
|
-
style={
|
|
262
|
-
Object {
|
|
263
|
-
"MozOsxFontSmoothing": "grayscale",
|
|
264
|
-
"WebkitFontSmoothing": "antialiased",
|
|
265
|
-
"color": "#d92916",
|
|
266
|
-
"display": "block",
|
|
267
|
-
"fontFamily": "Inconsolata, monospace",
|
|
268
|
-
"fontSize": 17,
|
|
269
|
-
"fontWeight": 400,
|
|
270
|
-
"lineHeight": "22px",
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
>
|
|
274
|
-
ERROR:
|
|
275
|
-
I'm an ERROR from hydration cache
|
|
276
|
-
</span>
|
|
277
|
-
</div>
|
|
278
198
|
</div>
|
|
279
199
|
`;
|
|
280
200
|
|
|
@@ -13,7 +13,7 @@ import {View, Server} from "@khanacademy/wonder-blocks-core";
|
|
|
13
13
|
import {
|
|
14
14
|
Data,
|
|
15
15
|
initializeCache,
|
|
16
|
-
|
|
16
|
+
InterceptRequests,
|
|
17
17
|
TrackData,
|
|
18
18
|
fulfillAllDataRequests,
|
|
19
19
|
} from "@khanacademy/wonder-blocks-data";
|
|
@@ -86,9 +86,6 @@ describe("wonder-blocks-data", () => {
|
|
|
86
86
|
DATA: {
|
|
87
87
|
data: "I'm DATA from the hydration cache",
|
|
88
88
|
},
|
|
89
|
-
ERROR: {
|
|
90
|
-
error: "I'm an ERROR from hydration cache",
|
|
91
|
-
},
|
|
92
89
|
});
|
|
93
90
|
const example = (
|
|
94
91
|
<View>
|
|
@@ -104,27 +101,6 @@ describe("wonder-blocks-data", () => {
|
|
|
104
101
|
}}
|
|
105
102
|
</Data>
|
|
106
103
|
</View>
|
|
107
|
-
<Strut size={Spacing.small_12} />
|
|
108
|
-
<View>
|
|
109
|
-
<Body>This cache has error!</Body>
|
|
110
|
-
<Data handler={myHandler} requestId="ERROR">
|
|
111
|
-
{(result) => {
|
|
112
|
-
if (result.status !== "error") {
|
|
113
|
-
return "If you see this, the example is broken!";
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return (
|
|
117
|
-
<BodyMonospace
|
|
118
|
-
style={{
|
|
119
|
-
color: Color.red,
|
|
120
|
-
}}
|
|
121
|
-
>
|
|
122
|
-
ERROR: {result.error}
|
|
123
|
-
</BodyMonospace>
|
|
124
|
-
);
|
|
125
|
-
}}
|
|
126
|
-
</Data>
|
|
127
|
-
</View>
|
|
128
104
|
</View>
|
|
129
105
|
);
|
|
130
106
|
const tree = renderer.create(example).toJSON();
|
|
@@ -135,13 +111,13 @@ describe("wonder-blocks-data", () => {
|
|
|
135
111
|
const myHandler = () =>
|
|
136
112
|
Promise.reject(new Error("You should not see this!"));
|
|
137
113
|
|
|
138
|
-
const
|
|
114
|
+
const interceptor = (requestId) =>
|
|
115
|
+
requestId === "INTERCEPT_EXAMPLE"
|
|
116
|
+
? Promise.resolve("INTERCEPTED DATA!")
|
|
117
|
+
: null;
|
|
139
118
|
|
|
140
119
|
const example = (
|
|
141
|
-
<
|
|
142
|
-
handler={interceptHandler}
|
|
143
|
-
requestId="INTERCEPT_EXAMPLE"
|
|
144
|
-
>
|
|
120
|
+
<InterceptRequests interceptor={interceptor}>
|
|
145
121
|
<View>
|
|
146
122
|
<Body>This received intercepted data!</Body>
|
|
147
123
|
<Data handler={myHandler} requestId="INTERCEPT_EXAMPLE">
|
|
@@ -154,7 +130,7 @@ describe("wonder-blocks-data", () => {
|
|
|
154
130
|
}}
|
|
155
131
|
</Data>
|
|
156
132
|
</View>
|
|
157
|
-
</
|
|
133
|
+
</InterceptRequests>
|
|
158
134
|
);
|
|
159
135
|
const tree = renderer.create(example).toJSON();
|
|
160
136
|
expect(tree).toMatchSnapshot();
|