@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.
Files changed (180) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/components/data.d.ts +52 -0
  3. package/dist/components/data.js.flow +63 -0
  4. package/dist/components/gql-router.d.ts +24 -0
  5. package/dist/components/gql-router.js.flow +33 -0
  6. package/dist/components/intercept-context.d.ts +10 -0
  7. package/dist/components/intercept-context.js.flow +19 -0
  8. package/dist/components/intercept-requests.d.ts +42 -0
  9. package/dist/components/intercept-requests.js.flow +51 -0
  10. package/dist/components/track-data.d.ts +11 -0
  11. package/dist/components/track-data.js.flow +18 -0
  12. package/dist/es/index.js +184 -212
  13. package/dist/hooks/use-cached-effect.d.ts +70 -0
  14. package/dist/hooks/use-cached-effect.js.flow +85 -0
  15. package/dist/hooks/use-gql-router-context.d.ts +5 -0
  16. package/dist/hooks/use-gql-router-context.js.flow +15 -0
  17. package/dist/hooks/use-gql.d.ts +12 -0
  18. package/dist/hooks/use-gql.js.flow +29 -0
  19. package/dist/hooks/use-hydratable-effect.d.ts +102 -0
  20. package/dist/hooks/use-hydratable-effect.js.flow +125 -0
  21. package/dist/hooks/use-request-interception.d.ts +14 -0
  22. package/dist/hooks/use-request-interception.js.flow +25 -0
  23. package/dist/hooks/use-server-effect.d.ts +39 -0
  24. package/dist/hooks/use-server-effect.js.flow +51 -0
  25. package/dist/hooks/use-shared-cache.d.ts +32 -0
  26. package/dist/hooks/use-shared-cache.js.flow +43 -0
  27. package/dist/index.d.ts +24 -0
  28. package/dist/index.js +186 -217
  29. package/dist/index.js.flow +48 -2
  30. package/dist/util/data-error.d.ts +45 -0
  31. package/dist/util/data-error.js.flow +64 -0
  32. package/dist/util/get-gql-data-from-response.d.ts +4 -0
  33. package/dist/util/get-gql-data-from-response.js.flow +13 -0
  34. package/dist/util/get-gql-request-id.d.ts +5 -0
  35. package/dist/util/get-gql-request-id.js.flow +20 -0
  36. package/dist/util/gql-error.d.ts +28 -0
  37. package/dist/util/gql-error.js.flow +43 -0
  38. package/dist/util/gql-router-context.d.ts +3 -0
  39. package/dist/util/gql-router-context.js.flow +10 -0
  40. package/dist/util/gql-types.d.ts +34 -0
  41. package/dist/util/gql-types.js.flow +53 -0
  42. package/dist/util/graphql-document-node-parser.d.ts +18 -0
  43. package/dist/util/graphql-document-node-parser.js.flow +31 -0
  44. package/dist/util/graphql-types.d.ts +19 -0
  45. package/dist/util/graphql-types.js.flow +30 -0
  46. package/dist/util/hydration-cache-api.d.ts +17 -0
  47. package/dist/util/hydration-cache-api.js.flow +30 -0
  48. package/dist/util/merge-gql-context.d.ts +8 -0
  49. package/dist/util/merge-gql-context.js.flow +19 -0
  50. package/dist/util/purge-caches.d.ts +8 -0
  51. package/dist/util/purge-caches.js.flow +15 -0
  52. package/dist/util/request-api.d.ts +28 -0
  53. package/dist/util/request-api.js.flow +34 -0
  54. package/dist/util/request-fulfillment.d.ts +37 -0
  55. package/dist/util/request-fulfillment.js.flow +50 -0
  56. package/dist/util/request-tracking.d.ts +62 -0
  57. package/dist/util/request-tracking.js.flow +81 -0
  58. package/dist/util/result-from-cache-response.d.ts +5 -0
  59. package/dist/util/result-from-cache-response.js.flow +15 -0
  60. package/dist/util/scoped-in-memory-cache.d.ts +38 -0
  61. package/dist/util/scoped-in-memory-cache.js.flow +57 -0
  62. package/dist/util/serializable-in-memory-cache.d.ts +16 -0
  63. package/dist/util/serializable-in-memory-cache.js.flow +26 -0
  64. package/dist/util/ssr-cache.d.ts +51 -0
  65. package/dist/util/ssr-cache.js.flow +87 -0
  66. package/dist/util/status.d.ts +10 -0
  67. package/dist/util/status.js.flow +19 -0
  68. package/dist/util/to-gql-operation.d.ts +32 -0
  69. package/dist/util/to-gql-operation.js.flow +45 -0
  70. package/dist/util/types.d.ts +111 -0
  71. package/dist/util/types.js.flow +151 -0
  72. package/package.json +5 -6
  73. package/src/components/__tests__/{data.test.js → data.test.tsx} +42 -2
  74. package/src/components/__tests__/{gql-router.test.js → gql-router.test.tsx} +4 -5
  75. package/src/components/__tests__/{intercept-requests.test.js → intercept-requests.test.tsx} +2 -3
  76. package/src/components/__tests__/{track-data.test.js → track-data.test.tsx} +2 -3
  77. package/src/components/{data.js → data.ts} +11 -15
  78. package/src/components/{gql-router.js → gql-router.tsx} +12 -14
  79. package/src/components/{intercept-context.js → intercept-context.ts} +4 -3
  80. package/src/components/{intercept-requests.js → intercept-requests.tsx} +7 -8
  81. package/src/components/{track-data.js → track-data.tsx} +4 -5
  82. package/src/hooks/__tests__/{use-cached-effect.test.js → use-cached-effect.test.tsx} +55 -50
  83. package/src/hooks/__tests__/{use-gql-router-context.test.js → use-gql-router-context.test.tsx} +7 -7
  84. package/src/hooks/__tests__/{use-gql.test.js → use-gql.test.tsx} +20 -21
  85. package/src/hooks/__tests__/{use-hydratable-effect.test.js → use-hydratable-effect.test.ts} +42 -37
  86. package/src/hooks/__tests__/{use-request-interception.test.js → use-request-interception.test.tsx} +5 -3
  87. package/src/hooks/__tests__/{use-server-effect.test.js → use-server-effect.test.ts} +8 -2
  88. package/src/hooks/__tests__/{use-shared-cache.test.js → use-shared-cache.test.ts} +12 -12
  89. package/src/hooks/{use-cached-effect.js → use-cached-effect.ts} +27 -20
  90. package/src/hooks/{use-gql-router-context.js → use-gql-router-context.ts} +2 -3
  91. package/src/hooks/{use-gql.js → use-gql.ts} +5 -5
  92. package/src/hooks/{use-hydratable-effect.js → use-hydratable-effect.ts} +53 -58
  93. package/src/hooks/{use-request-interception.js → use-request-interception.ts} +4 -4
  94. package/src/hooks/{use-server-effect.js → use-server-effect.ts} +7 -9
  95. package/src/hooks/{use-shared-cache.js → use-shared-cache.ts} +13 -8
  96. package/src/{index.js → index.ts} +0 -1
  97. package/src/util/__tests__/{get-gql-data-from-response.test.js → get-gql-data-from-response.test.ts} +0 -1
  98. package/src/util/__tests__/{get-gql-request-id.test.js → get-gql-request-id.test.ts} +9 -11
  99. package/src/util/__tests__/{graphql-document-node-parser.test.js → graphql-document-node-parser.test.ts} +11 -12
  100. package/src/util/__tests__/{hydration-cache-api.test.js → hydration-cache-api.test.ts} +1 -2
  101. package/src/util/__tests__/{merge-gql-context.test.js → merge-gql-context.test.ts} +4 -5
  102. package/src/util/__tests__/{purge-caches.test.js → purge-caches.test.ts} +0 -1
  103. package/src/util/__tests__/{request-api.test.js → request-api.test.ts} +2 -2
  104. package/src/util/__tests__/{request-fulfillment.test.js → request-fulfillment.test.ts} +0 -1
  105. package/src/util/__tests__/{request-tracking.test.js → request-tracking.test.tsx} +13 -6
  106. package/src/util/__tests__/{result-from-cache-response.test.js → result-from-cache-response.test.ts} +2 -4
  107. package/src/util/__tests__/{scoped-in-memory-cache.test.js → scoped-in-memory-cache.test.ts} +4 -5
  108. package/src/util/__tests__/{serializable-in-memory-cache.test.js → serializable-in-memory-cache.test.ts} +7 -7
  109. package/src/util/__tests__/{ssr-cache.test.js → ssr-cache.test.ts} +3 -2
  110. package/src/util/__tests__/{to-gql-operation.test.js → to-gql-operation.test.ts} +2 -1
  111. package/src/util/{data-error.js → data-error.ts} +2 -3
  112. package/src/util/{get-gql-data-from-response.js → get-gql-data-from-response.ts} +1 -6
  113. package/src/util/{get-gql-request-id.js → get-gql-request-id.ts} +12 -16
  114. package/src/util/{gql-error.js → gql-error.ts} +2 -3
  115. package/src/util/gql-router-context.ts +6 -0
  116. package/src/util/{gql-types.js → gql-types.ts} +27 -23
  117. package/src/util/{graphql-document-node-parser.js → graphql-document-node-parser.ts} +6 -7
  118. package/src/util/graphql-types.ts +27 -0
  119. package/src/util/{hydration-cache-api.js → hydration-cache-api.ts} +4 -2
  120. package/src/util/{merge-gql-context.js → merge-gql-context.ts} +2 -2
  121. package/src/util/{purge-caches.js → purge-caches.ts} +0 -1
  122. package/src/util/{request-api.js → request-api.ts} +0 -1
  123. package/src/util/{request-fulfillment.js → request-fulfillment.ts} +13 -12
  124. package/src/util/{request-tracking.js → request-tracking.ts} +12 -13
  125. package/src/util/{result-from-cache-response.js → result-from-cache-response.ts} +3 -4
  126. package/src/util/{scoped-in-memory-cache.js → scoped-in-memory-cache.ts} +1 -2
  127. package/src/util/{serializable-in-memory-cache.js → serializable-in-memory-cache.ts} +2 -3
  128. package/src/util/{ssr-cache.js → ssr-cache.ts} +19 -18
  129. package/src/util/{status.js → status.ts} +4 -5
  130. package/src/util/{to-gql-operation.js → to-gql-operation.ts} +1 -2
  131. package/src/util/{types.js → types.ts} +39 -48
  132. package/tsconfig.json +11 -0
  133. package/tsconfig.tsbuildinfo +1 -0
  134. package/src/__docs__/_overview_.stories.mdx +0 -18
  135. package/src/__docs__/_overview_graphql.stories.mdx +0 -35
  136. package/src/__docs__/_overview_ssr_.stories.mdx +0 -185
  137. package/src/__docs__/_overview_testing_.stories.mdx +0 -123
  138. package/src/__docs__/exports.abort-inflight-requests.stories.mdx +0 -20
  139. package/src/__docs__/exports.data-error.stories.mdx +0 -23
  140. package/src/__docs__/exports.data-errors.stories.mdx +0 -23
  141. package/src/__docs__/exports.data.stories.mdx +0 -146
  142. package/src/__docs__/exports.fetch-tracked-requests.stories.mdx +0 -24
  143. package/src/__docs__/exports.get-gql-request-id.stories.mdx +0 -24
  144. package/src/__docs__/exports.gql-error.stories.mdx +0 -23
  145. package/src/__docs__/exports.gql-errors.stories.mdx +0 -20
  146. package/src/__docs__/exports.gql-router.stories.mdx +0 -29
  147. package/src/__docs__/exports.has-tracked-requests-to-be-fetched.stories.mdx +0 -20
  148. package/src/__docs__/exports.intercept-requests.stories.mdx +0 -69
  149. package/src/__docs__/exports.intialize-hydration-cache.stories.mdx +0 -29
  150. package/src/__docs__/exports.purge-caches.stories.mdx +0 -23
  151. package/src/__docs__/exports.purge-hydration-cache.stories.mdx +0 -24
  152. package/src/__docs__/exports.scoped-in-memory-cache.stories.mdx +0 -92
  153. package/src/__docs__/exports.serializable-in-memory-cache.stories.mdx +0 -112
  154. package/src/__docs__/exports.shared-cache.stories.mdx +0 -16
  155. package/src/__docs__/exports.status.stories.mdx +0 -31
  156. package/src/__docs__/exports.track-data.stories.mdx +0 -209
  157. package/src/__docs__/exports.use-cached-effect.stories.mdx +0 -44
  158. package/src/__docs__/exports.use-gql.stories.mdx +0 -41
  159. package/src/__docs__/exports.use-hydratable-effect.stories.mdx +0 -43
  160. package/src/__docs__/exports.use-server-effect.stories.mdx +0 -50
  161. package/src/__docs__/exports.use-shared-cache.stories.mdx +0 -30
  162. package/src/__docs__/exports.when-client-side.stories.mdx +0 -33
  163. package/src/__docs__/types.cached-response.stories.mdx +0 -29
  164. package/src/__docs__/types.error-options.stories.mdx +0 -21
  165. package/src/__docs__/types.fetch-policy.stories.mdx +0 -44
  166. package/src/__docs__/types.gql-context.stories.mdx +0 -20
  167. package/src/__docs__/types.gql-fetch-fn.stories.mdx +0 -24
  168. package/src/__docs__/types.gql-fetch-options.stories.mdx +0 -24
  169. package/src/__docs__/types.gql-operation-type.stories.mdx +0 -24
  170. package/src/__docs__/types.gql-operation.stories.mdx +0 -67
  171. package/src/__docs__/types.raw-scoped-cache.stories.mdx +0 -27
  172. package/src/__docs__/types.response-cache.stories.mdx +0 -33
  173. package/src/__docs__/types.result.stories.mdx +0 -39
  174. package/src/__docs__/types.scoped-cache.stories.mdx +0 -114
  175. package/src/__docs__/types.valid-cache-data.stories.mdx +0 -23
  176. package/src/util/gql-router-context.js +0 -6
  177. package/src/util/graphql-types.js +0 -30
  178. /package/src/hooks/__tests__/__snapshots__/{use-shared-cache.test.js.snap → use-shared-cache.test.ts.snap} +0 -0
  179. /package/src/util/__tests__/__snapshots__/{scoped-in-memory-cache.test.js.snap → scoped-in-memory-cache.test.ts.snap} +0 -0
  180. /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 type {
3
2
  DocumentNode,
4
3
  DefinitionNode,
@@ -12,12 +11,12 @@ export const DocumentTypes = Object.freeze({
12
11
  mutation: "mutation",
13
12
  });
14
13
 
15
- export type DocumentType = $Values<typeof DocumentTypes>;
14
+ export type DocumentType = typeof DocumentTypes[keyof typeof DocumentTypes];
16
15
 
17
16
  export interface IDocumentDefinition {
18
17
  type: DocumentType;
19
18
  name: string;
20
- variables: $ReadOnlyArray<VariableDefinitionNode>;
19
+ variables: ReadonlyArray<VariableDefinitionNode>;
21
20
  }
22
21
 
23
22
  const cache = new Map<DocumentNode, IDocumentDefinition>();
@@ -60,19 +59,19 @@ export function graphQLDocumentNodeParser(
60
59
 
61
60
  const queries = document.definitions.filter(
62
61
  (x: DefinitionNode) =>
63
- // $FlowIgnore[prop-missing]
62
+ // @ts-expect-error [FEI-5019] - TS2339 - Property 'operation' does not exist on type 'DefinitionNode'.
64
63
  x.kind === "OperationDefinition" && x.operation === "query",
65
64
  );
66
65
 
67
66
  const mutations = document.definitions.filter(
68
67
  (x: DefinitionNode) =>
69
- // $FlowIgnore[prop-missing]
68
+ // @ts-expect-error [FEI-5019] - TS2339 - Property 'operation' does not exist on type 'DefinitionNode'.
70
69
  x.kind === "OperationDefinition" && x.operation === "mutation",
71
70
  );
72
71
 
73
72
  const subscriptions = document.definitions.filter(
74
73
  (x: DefinitionNode) =>
75
- // $FlowIgnore[prop-missing]
74
+ // @ts-expect-error [FEI-5019] - TS2339 - Property 'operation' does not exist on type 'DefinitionNode'.
76
75
  x.kind === "OperationDefinition" && x.operation === "subscription",
77
76
  );
78
77
 
@@ -120,7 +119,7 @@ export function graphQLDocumentNodeParser(
120
119
  const type = queries.length ? DocumentTypes.query : DocumentTypes.mutation;
121
120
  const definitions = queries.length ? queries : mutations;
122
121
 
123
- const definition: OperationDefinitionNode = (definitions[0]: any);
122
+ const definition: OperationDefinitionNode = definitions[0] as any;
124
123
  const variables = definition.variableDefinitions || [];
125
124
 
126
125
  // fallback to using data if no name
@@ -0,0 +1,27 @@
1
+ // NOTE(somewhatabstract):
2
+ // These types are bare minimum to support document parsing. They're derived
3
+ // from graphql@14.5.8, the last version that provided TypeScript types.
4
+ // Doing this avoids us having to take a dependency on that library just for
5
+ // these types.
6
+ export interface DefinitionNode {
7
+ readonly kind: string;
8
+ }
9
+
10
+ export type VariableDefinitionNode = {
11
+ readonly kind: "VariableDefinition";
12
+ };
13
+
14
+ export interface OperationDefinitionNode extends DefinitionNode {
15
+ readonly kind: "OperationDefinition";
16
+ readonly operation: string;
17
+ readonly variableDefinitions: ReadonlyArray<VariableDefinitionNode>;
18
+ readonly name?: {
19
+ readonly kind: unknown;
20
+ readonly value: string;
21
+ };
22
+ }
23
+
24
+ export type DocumentNode = {
25
+ readonly kind: "Document";
26
+ readonly definitions: ReadonlyArray<DefinitionNode>;
27
+ };
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {SsrCache} from "./ssr-cache";
3
2
 
4
3
  import type {ValidCacheData, CachedResponse, ResponseCache} from "./types";
@@ -23,6 +22,9 @@ export const initializeHydrationCache = (source: ResponseCache): void =>
23
22
  export const purgeHydrationCache = (
24
23
  predicate?: (
25
24
  key: string,
26
- cacheEntry: ?$ReadOnly<CachedResponse<ValidCacheData>>,
25
+ cacheEntry?:
26
+ | Readonly<CachedResponse<ValidCacheData>>
27
+ | null
28
+ | undefined,
27
29
  ) => boolean,
28
30
  ): void => SsrCache.Default.purgeData(predicate);
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import type {GqlContext} from "./gql-types";
3
2
 
4
3
  /**
@@ -7,7 +6,7 @@ import type {GqlContext} from "./gql-types";
7
6
  * Values in the partial context that are `undefined` will be ignored.
8
7
  * Values in the partial context that are `null` will be deleted.
9
8
  */
10
- export const mergeGqlContext = <TContext: GqlContext>(
9
+ export const mergeGqlContext = <TContext extends GqlContext>(
11
10
  defaultContext: TContext,
12
11
  overrides: Partial<TContext>,
13
12
  ): TContext => {
@@ -24,6 +23,7 @@ export const mergeGqlContext = <TContext: GqlContext>(
24
23
  delete acc[key];
25
24
  } else {
26
25
  // Otherwise, we set it.
26
+ // @ts-expect-error [FEI-5019] - TS2536 - Type 'string' cannot be used to index type 'TContext'.
27
27
  acc[key] = overrides[key];
28
28
  }
29
29
  }
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {SharedCache} from "../hooks/use-shared-cache";
3
2
  import {purgeHydrationCache} from "./hydration-cache-api";
4
3
 
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {Server} from "@khanacademy/wonder-blocks-core";
3
2
  import {RequestTracker} from "./request-tracking";
4
3
  import {RequestFulfillment} from "./request-fulfillment";
@@ -1,16 +1,15 @@
1
- // @flow
2
1
  import type {Result, ValidCacheData} from "./types";
3
2
 
4
3
  import {DataError, DataErrors} from "./data-error";
5
4
 
6
5
  type RequestCache = {
7
- [id: string]: Promise<Result<any>>,
6
+ [id: string]: Promise<Result<any>>;
8
7
  };
9
8
 
10
- type FulfillOptions<TData: ValidCacheData> = {|
11
- handler: () => Promise<TData>,
12
- hydrate?: boolean,
13
- |};
9
+ type FulfillOptions<TData extends ValidCacheData> = {
10
+ handler: () => Promise<TData>;
11
+ hydrate?: boolean;
12
+ };
14
13
 
15
14
  let _default: RequestFulfillment;
16
15
 
@@ -33,10 +32,10 @@ export class RequestFulfillment {
33
32
  * This will return an inflight request if one exists, otherwise it will
34
33
  * make a new request. Inflight requests are deleted once they resolve.
35
34
  */
36
- fulfill: <TData: ValidCacheData>(
35
+ fulfill: <TData extends ValidCacheData>(
37
36
  id: string,
38
37
  options: FulfillOptions<TData>,
39
- ) => Promise<Result<TData>> = <TData: ValidCacheData>(
38
+ ) => Promise<Result<TData>> = <TData extends ValidCacheData>(
40
39
  id: string,
41
40
  {handler, hydrate = true}: FulfillOptions<TData>,
42
41
  ): Promise<Result<TData>> => {
@@ -52,10 +51,12 @@ export class RequestFulfillment {
52
51
  * We don't have an inflight request, so let's set one up.
53
52
  */
54
53
  const request = handler()
55
- .then((data: TData): Result<TData> => ({
56
- status: "success",
57
- data,
58
- }))
54
+ .then(
55
+ (data: TData): Result<TData> => ({
56
+ status: "success",
57
+ data,
58
+ }),
59
+ )
59
60
  .catch((error: string | Error): Result<TData> => {
60
61
  const actualError =
61
62
  typeof error === "string"
@@ -1,22 +1,20 @@
1
- // @flow
2
1
  import * as React from "react";
3
2
  import {SsrCache} from "./ssr-cache";
4
3
  import {RequestFulfillment} from "./request-fulfillment";
5
4
 
6
5
  import type {ResponseCache, ValidCacheData} from "./types";
7
6
 
8
- type TrackerFn = <TData: ValidCacheData>(
7
+ type TrackerFn = <TData extends ValidCacheData>(
9
8
  id: string,
10
9
  handler: () => Promise<TData>,
11
10
  hydrate: boolean,
12
11
  ) => void;
13
12
 
14
13
  type RequestCache = {
15
- [id: string]: {|
16
- hydrate: boolean,
17
- handler: () => Promise<any>,
18
- |},
19
- ...
14
+ [id: string]: {
15
+ hydrate: boolean;
16
+ handler: () => Promise<any>;
17
+ };
20
18
  };
21
19
 
22
20
  /**
@@ -24,8 +22,8 @@ type RequestCache = {
24
22
  *
25
23
  * INTERNAL USE ONLY
26
24
  */
27
- export const TrackerContext: React.Context<?TrackerFn> =
28
- React.createContext<?TrackerFn>(null);
25
+ export const TrackerContext: React.Context<TrackerFn | null | undefined> =
26
+ React.createContext<TrackerFn | null | undefined>(null);
29
27
 
30
28
  /**
31
29
  * The default instance is stored here.
@@ -53,7 +51,8 @@ export class RequestTracker {
53
51
  _responseCache: SsrCache;
54
52
  _requestFulfillment: RequestFulfillment;
55
53
 
56
- constructor(responseCache: ?SsrCache = undefined) {
54
+ // @ts-expect-error [FEI-5019] - TS2322 - Type 'undefined' is not assignable to type 'SsrCache | null'.
55
+ constructor(responseCache: SsrCache | null = undefined) {
57
56
  this._responseCache = responseCache || SsrCache.Default;
58
57
  this._requestFulfillment = new RequestFulfillment();
59
58
  }
@@ -64,11 +63,11 @@ export class RequestTracker {
64
63
  * This method caches a request and its handler for use during server-side
65
64
  * rendering to allow us to fulfill requests before producing a final render.
66
65
  */
67
- trackDataRequest: <TData: ValidCacheData>(
66
+ trackDataRequest: <TData extends ValidCacheData>(
68
67
  id: string,
69
68
  handler: () => Promise<TData>,
70
69
  hydrate: boolean,
71
- ) => void = <TData: ValidCacheData>(
70
+ ) => void = <TData extends ValidCacheData>(
72
71
  id: string,
73
72
  handler: () => Promise<TData>,
74
73
  hydrate: boolean,
@@ -167,7 +166,7 @@ export class RequestTracker {
167
166
  return;
168
167
  }),
169
168
  );
170
- } catch (e) {
169
+ } catch (e: any) {
171
170
  // This captures if there are problems in the code that
172
171
  // begins the requests.
173
172
  promises.push(
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {Status} from "./status";
3
2
  import {DataError, DataErrors} from "./data-error";
4
3
  import type {ValidCacheData, CachedResponse, Result} from "./types";
@@ -6,9 +5,9 @@ import type {ValidCacheData, CachedResponse, Result} from "./types";
6
5
  /**
7
6
  * Turns a cache entry into a stateful result.
8
7
  */
9
- export const resultFromCachedResponse = <TData: ValidCacheData>(
10
- cacheEntry: ?CachedResponse<TData>,
11
- ): ?Result<TData> => {
8
+ export const resultFromCachedResponse = <TData extends ValidCacheData>(
9
+ cacheEntry?: CachedResponse<TData> | null,
10
+ ): Result<TData> | null | undefined => {
12
11
  // No cache entry means no result to be hydrated.
13
12
  if (cacheEntry == null) {
14
13
  return null;
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {DataError, DataErrors} from "./data-error";
3
2
  import type {ScopedCache, RawScopedCache, ValidCacheData} from "./types";
4
3
 
@@ -53,7 +52,7 @@ export class ScopedInMemoryCache implements ScopedCache {
53
52
  /**
54
53
  * Retrieve a value from the cache.
55
54
  */
56
- get(scope: string, id: string): ?ValidCacheData {
55
+ get(scope: string, id: string): ValidCacheData | null | undefined {
57
56
  return this._cache[scope]?.[id] ?? null;
58
57
  }
59
58
 
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {clone} from "@khanacademy/wonder-stuff-core";
3
2
  import {DataError, DataErrors} from "./data-error";
4
3
  import {ScopedInMemoryCache} from "./scoped-in-memory-cache";
@@ -11,7 +10,7 @@ export class SerializableInMemoryCache extends ScopedInMemoryCache {
11
10
  constructor(initialCache: RawScopedCache = {}) {
12
11
  try {
13
12
  super(clone(initialCache));
14
- } catch (e) {
13
+ } catch (e: any) {
15
14
  throw new DataError(
16
15
  `An error occurred trying to initialize from a response cache snapshot: ${e}`,
17
16
  DataErrors.InvalidInput,
@@ -32,7 +31,7 @@ export class SerializableInMemoryCache extends ScopedInMemoryCache {
32
31
  clone(): RawScopedCache {
33
32
  try {
34
33
  return clone(this._cache);
35
- } catch (e) {
34
+ } catch (e: any) {
36
35
  throw new DataError(
37
36
  "An error occurred while trying to clone the cache",
38
37
  DataErrors.Internal,
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {Server} from "@khanacademy/wonder-blocks-core";
3
2
  import {SerializableInMemoryCache} from "./serializable-in-memory-cache";
4
3
 
@@ -29,15 +28,15 @@ export class SsrCache {
29
28
  _ssrOnlyCache: SerializableInMemoryCache;
30
29
 
31
30
  constructor(
32
- hydrationCache: ?SerializableInMemoryCache = null,
33
- ssrOnlyCache: ?SerializableInMemoryCache = null,
31
+ hydrationCache: SerializableInMemoryCache | null = null,
32
+ ssrOnlyCache: SerializableInMemoryCache | null = null,
34
33
  ) {
35
34
  this._ssrOnlyCache = ssrOnlyCache || new SerializableInMemoryCache();
36
35
  this._hydrationCache =
37
36
  hydrationCache || new SerializableInMemoryCache();
38
37
  }
39
38
 
40
- _setCachedResponse<TData: ValidCacheData>(
39
+ _setCachedResponse<TData extends ValidCacheData>(
41
40
  id: string,
42
41
  entry: CachedResponse<TData>,
43
42
  hydrate: boolean,
@@ -70,7 +69,6 @@ export class SsrCache {
70
69
  );
71
70
  }
72
71
  this._hydrationCache = new SerializableInMemoryCache({
73
- // $FlowIgnore[incompatible-call]
74
72
  [DefaultScope]: source,
75
73
  });
76
74
  };
@@ -80,11 +78,11 @@ export class SsrCache {
80
78
  *
81
79
  * This is a noop when client-side.
82
80
  */
83
- cacheData: <TData: ValidCacheData>(
81
+ cacheData: <TData extends ValidCacheData>(
84
82
  id: string,
85
83
  data: TData,
86
84
  hydrate: boolean,
87
- ) => CachedResponse<TData> = <TData: ValidCacheData>(
85
+ ) => CachedResponse<TData> = <TData extends ValidCacheData>(
88
86
  id: string,
89
87
  data: TData,
90
88
  hydrate: boolean,
@@ -95,11 +93,11 @@ export class SsrCache {
95
93
  *
96
94
  * This is a noop when client-side.
97
95
  */
98
- cacheError: <TData: ValidCacheData>(
96
+ cacheError: <TData extends ValidCacheData>(
99
97
  id: string,
100
98
  error: Error | string,
101
99
  hydrate: boolean,
102
- ) => CachedResponse<TData> = <TData: ValidCacheData>(
100
+ ) => CachedResponse<TData> = <TData extends ValidCacheData>(
103
101
  id: string,
104
102
  error: Error | string,
105
103
  hydrate: boolean,
@@ -111,11 +109,13 @@ export class SsrCache {
111
109
  /**
112
110
  * Retrieve data from our cache.
113
111
  */
114
- getEntry: <TData: ValidCacheData>(
112
+ getEntry: <TData extends ValidCacheData>(
115
113
  id: string,
116
- ) => ?$ReadOnly<CachedResponse<TData>> = <TData: ValidCacheData>(
114
+ ) => Readonly<CachedResponse<TData>> | null | undefined = <
115
+ TData extends ValidCacheData,
116
+ >(
117
117
  id: string,
118
- ): ?$ReadOnly<CachedResponse<TData>> => {
118
+ ): Readonly<CachedResponse<TData>> | null | undefined => {
119
119
  // Get the cached entry for this value.
120
120
 
121
121
  // We first look in the ssr cache, if we need to.
@@ -139,8 +139,8 @@ export class SsrCache {
139
139
  this._hydrationCache.purge(DefaultScope, id);
140
140
  }
141
141
  // Getting the typing right between the in-memory cache and this
142
- // is hard. Just telling flow it's OK.
143
- // $FlowIgnore[incompatible-return]
142
+ // is hard. Just telling TypeScript it's OK.
143
+ // @ts-expect-error [FEI-5019] - TS2322 - Type 'string | number | boolean | Record<any, any> | null | undefined' is not assignable to type 'Readonly<CachedResponse<TData>> | null | undefined'.
144
144
  return internalEntry;
145
145
  };
146
146
 
@@ -155,14 +155,15 @@ export class SsrCache {
155
155
  purgeData: (
156
156
  predicate?: (
157
157
  key: string,
158
- cachedEntry: $ReadOnly<CachedResponse<ValidCacheData>>,
158
+ cachedEntry: Readonly<CachedResponse<ValidCacheData>>,
159
159
  ) => boolean,
160
160
  ) => void = (predicate) => {
161
161
  const realPredicate = predicate
162
162
  ? // We know what we're putting into the cache so let's assume it
163
163
  // conforms.
164
- // $FlowIgnore[incompatible-call]
165
- (_, key, cachedEntry) => predicate(key, cachedEntry)
164
+ // @ts-expect-error [FEI-5019] - TS7006 - Parameter 'cachedEntry' implicitly has an 'any' type.
165
+ (_: string, key: string, cachedEntry) =>
166
+ predicate(key, cachedEntry)
166
167
  : undefined;
167
168
 
168
169
  // Apply the predicate to what we have in our caches.
@@ -183,7 +184,7 @@ export class SsrCache {
183
184
  // to an empty object.
184
185
  // We only need the default scope out of our scoped in-memory cache.
185
186
  // We know that it conforms to our expectations.
186
- // $FlowIgnore[incompatible-return]
187
+ // @ts-expect-error [FEI-5019] - TS2322 - Type '{ [id: string]: ValidCacheData; }' is not assignable to type 'ResponseCache'.
187
188
  return cache[DefaultScope] ?? {};
188
189
  };
189
190
  }
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import type {Result, ValidCacheData} from "./types";
3
2
 
4
3
  const loadingStatus = Object.freeze({
@@ -13,15 +12,15 @@ const abortedStatus = Object.freeze({
13
12
  * Create Result<TData> instances with specific statuses.
14
13
  */
15
14
  export const Status = Object.freeze({
16
- loading: <TData: ValidCacheData = ValidCacheData>(): Result<TData> =>
15
+ loading: <TData extends ValidCacheData = ValidCacheData>(): Result<TData> =>
17
16
  loadingStatus,
18
- aborted: <TData: ValidCacheData = ValidCacheData>(): Result<TData> =>
17
+ aborted: <TData extends ValidCacheData = ValidCacheData>(): Result<TData> =>
19
18
  abortedStatus,
20
- success: <TData: ValidCacheData>(data: TData): Result<TData> => ({
19
+ success: <TData extends ValidCacheData>(data: TData): Result<TData> => ({
21
20
  status: "success",
22
21
  data,
23
22
  }),
24
- error: <TData: ValidCacheData = ValidCacheData>(
23
+ error: <TData extends ValidCacheData = ValidCacheData>(
25
24
  error: Error,
26
25
  ): Result<TData> => ({
27
26
  status: "error",
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import {graphQLDocumentNodeParser} from "./graphql-document-node-parser";
3
2
  import type {GqlOperation} from "./gql-types";
4
3
  import type {DocumentNode} from "./graphql-types";
@@ -32,7 +31,7 @@ import type {DocumentNode} from "./graphql-types";
32
31
  * };
33
32
  * ```
34
33
  */
35
- export const toGqlOperation = <TData, TVariables: {...}>(
34
+ export const toGqlOperation = <TData, TVariables extends Record<any, any>>(
36
35
  documentNode: DocumentNode,
37
36
  ): GqlOperation<TData, TVariables> => {
38
37
  const definition = graphQLDocumentNodeParser(documentNode);
@@ -1,4 +1,3 @@
1
- // @flow
2
1
  import type {Metadata} from "@khanacademy/wonder-stuff-core";
3
2
 
4
3
  /**
@@ -10,24 +9,24 @@ export const FetchPolicy = {
10
9
  * If the data is in the cache, return that; otherwise, fetch from the
11
10
  * server.
12
11
  */
13
- CacheBeforeNetwork: ("CacheBeforeNetwork": "CacheBeforeNetwork"),
12
+ CacheBeforeNetwork: "CacheBeforeNetwork" as const,
14
13
 
15
14
  /**
16
15
  * If the data is in the cache, return that; always fetch from the server
17
16
  * regardless of cache.
18
17
  */
19
- CacheAndNetwork: ("CacheAndNetwork": "CacheAndNetwork"),
18
+ CacheAndNetwork: "CacheAndNetwork" as const,
20
19
 
21
20
  /**
22
21
  * If the data is in the cache, return that; otherwise, do nothing.
23
22
  */
24
- CacheOnly: ("CacheOnly": "CacheOnly"),
23
+ CacheOnly: "CacheOnly" as const,
25
24
 
26
25
  /**
27
26
  * Ignore any existing cached result; always fetch from the server.
28
27
  */
29
- NetworkOnly: ("NetworkOnly": "NetworkOnly"),
30
- };
28
+ NetworkOnly: "NetworkOnly" as const,
29
+ } as const;
31
30
 
32
31
  /**
33
32
  * Define what can be cached.
@@ -39,47 +38,46 @@ export type ValidCacheData =
39
38
  | string
40
39
  | boolean
41
40
  | number
42
- | {...}
43
- | Array<?ValidCacheData>;
41
+ | Record<any, any>
42
+ | Array<ValidCacheData | null | undefined>;
44
43
 
45
44
  /**
46
45
  * The normalized result of a request.
47
46
  */
48
- export type Result<TData: ValidCacheData> =
49
- | {|
50
- status: "loading",
51
- |}
52
- | {|
53
- status: "success",
54
- data: TData,
55
- |}
56
- | {|
57
- status: "error",
58
- error: Error,
59
- |}
60
- | {|
61
- status: "aborted",
62
- |};
47
+ export type Result<TData extends ValidCacheData> =
48
+ | {
49
+ status: "loading";
50
+ }
51
+ | {
52
+ status: "success";
53
+ data: TData;
54
+ }
55
+ | {
56
+ status: "error";
57
+ error: Error;
58
+ }
59
+ | {
60
+ status: "aborted";
61
+ };
63
62
 
64
63
  /**
65
64
  * A cache entry for a fulfilled request response.
66
65
  */
67
- export type CachedResponse<TData: ValidCacheData> =
68
- | {|
69
- +error: string,
70
- +data?: void,
71
- |}
72
- | {|
73
- +data: TData,
74
- +error?: void,
75
- |};
66
+ export type CachedResponse<TData extends ValidCacheData> =
67
+ | {
68
+ readonly error: string;
69
+ readonly data?: undefined;
70
+ }
71
+ | {
72
+ readonly data: TData;
73
+ readonly error?: undefined;
74
+ };
76
75
 
77
76
  /**
78
77
  * A cache of fulfilled request responses.
79
78
  */
80
79
  export type ResponseCache = {
81
- [key: string]: CachedResponse<any>,
82
- ...
80
+ [key: string]: CachedResponse<any>;
83
81
  };
84
82
 
85
83
  /**
@@ -93,40 +91,34 @@ export type RawScopedCache = {
93
91
  /**
94
92
  * Each value in the cache is then identified within a given scope.
95
93
  */
96
- [id: string]: ValidCacheData,
97
- ...
98
- },
99
- ...
94
+ [id: string]: ValidCacheData;
95
+ };
100
96
  };
101
97
 
102
98
  /**
103
99
  * Options to pass to error construction.
104
100
  */
105
- export type ErrorOptions = {|
101
+ export type ErrorOptions = {
106
102
  /**
107
103
  * Metadata to attach to the error.
108
104
  */
109
- metadata?: ?Metadata,
110
-
105
+ metadata?: Metadata | null | undefined;
111
106
  /**
112
107
  * The error that caused the error being constructed.
113
108
  */
114
- cause?: ?Error,
115
- |};
109
+ cause?: Error | null | undefined;
110
+ };
116
111
 
117
112
  export interface ScopedCache {
118
113
  set(scope: string, id: string, value: ValidCacheData): void;
119
-
120
114
  /**
121
115
  * Retrieve a value from the cache.
122
116
  */
123
- get(scope: string, id: string): ?ValidCacheData;
124
-
117
+ get(scope: string, id: string): ValidCacheData | null | undefined;
125
118
  /**
126
119
  * Purge an item from the cache.
127
120
  */
128
121
  purge(scope: string, id: string): void;
129
-
130
122
  /**
131
123
  * Purge a scope of items that match the given predicate.
132
124
  *
@@ -136,7 +128,6 @@ export interface ScopedCache {
136
128
  scope: string,
137
129
  predicate?: (id: string, value: ValidCacheData) => boolean,
138
130
  ): void;
139
-
140
131
  /**
141
132
  * Purge all items from the cache that match the given predicate.
142
133
  *
package/tsconfig.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "exclude": ["dist"],
3
+ "extends": "../tsconfig-shared.json",
4
+ "compilerOptions": {
5
+ "outDir": "./dist",
6
+ "rootDir": "src",
7
+ },
8
+ "references": [
9
+ {"path": "../wonder-blocks-core"},
10
+ ]
11
+ }