@cedarjs/web 0.0.4
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/LICENSE +21 -0
- package/README.md +33 -0
- package/apollo/index.js +2 -0
- package/apollo/package.json +4 -0
- package/dist/apollo/fragmentRegistry.d.ts +43 -0
- package/dist/apollo/fragmentRegistry.d.ts.map +1 -0
- package/dist/apollo/fragmentRegistry.js +39 -0
- package/dist/apollo/index.d.ts +77 -0
- package/dist/apollo/index.d.ts.map +1 -0
- package/dist/apollo/index.js +198 -0
- package/dist/apollo/links.d.ts +27 -0
- package/dist/apollo/links.d.ts.map +1 -0
- package/dist/apollo/links.js +94 -0
- package/dist/apollo/sseLink.d.ts +29 -0
- package/dist/apollo/sseLink.d.ts.map +1 -0
- package/dist/apollo/sseLink.js +94 -0
- package/dist/apollo/suspense.d.ts +59 -0
- package/dist/apollo/suspense.d.ts.map +1 -0
- package/dist/apollo/suspense.js +113 -0
- package/dist/apollo/typeOverride.d.ts +21 -0
- package/dist/apollo/typeOverride.d.ts.map +1 -0
- package/dist/apollo/typeOverride.js +0 -0
- package/dist/apollo/useCache.d.ts +22 -0
- package/dist/apollo/useCache.d.ts.map +1 -0
- package/dist/apollo/useCache.js +25 -0
- package/dist/bins/cross-env.d.ts +3 -0
- package/dist/bins/cross-env.d.ts.map +1 -0
- package/dist/bins/msw.d.ts +3 -0
- package/dist/bins/msw.d.ts.map +1 -0
- package/dist/bins/redwood.d.ts +9 -0
- package/dist/bins/redwood.d.ts.map +1 -0
- package/dist/bins/rwfw.d.ts +3 -0
- package/dist/bins/rwfw.d.ts.map +1 -0
- package/dist/bins/storybook.d.ts +3 -0
- package/dist/bins/storybook.d.ts.map +1 -0
- package/dist/bins/tsc.d.ts +3 -0
- package/dist/bins/tsc.d.ts.map +1 -0
- package/dist/bundled/apollo-upload-client.d.ts +3 -0
- package/dist/bundled/apollo-upload-client.d.ts.map +1 -0
- package/dist/bundled/apollo-upload-client.js +4 -0
- package/dist/cjs/apollo/fragmentRegistry.d.ts +43 -0
- package/dist/cjs/apollo/fragmentRegistry.d.ts.map +1 -0
- package/dist/cjs/apollo/fragmentRegistry.js +75 -0
- package/dist/cjs/apollo/index.d.ts +77 -0
- package/dist/cjs/apollo/index.d.ts.map +1 -0
- package/dist/cjs/apollo/index.js +216 -0
- package/dist/cjs/apollo/links.d.ts +27 -0
- package/dist/cjs/apollo/links.d.ts.map +1 -0
- package/dist/cjs/apollo/links.js +122 -0
- package/dist/cjs/apollo/sseLink.d.ts +29 -0
- package/dist/cjs/apollo/sseLink.d.ts.map +1 -0
- package/dist/cjs/apollo/sseLink.js +120 -0
- package/dist/cjs/apollo/suspense.d.ts +59 -0
- package/dist/cjs/apollo/suspense.d.ts.map +1 -0
- package/dist/cjs/apollo/suspense.js +127 -0
- package/dist/cjs/apollo/typeOverride.d.ts +21 -0
- package/dist/cjs/apollo/typeOverride.d.ts.map +1 -0
- package/dist/cjs/apollo/typeOverride.js +16 -0
- package/dist/cjs/apollo/useCache.d.ts +22 -0
- package/dist/cjs/apollo/useCache.d.ts.map +1 -0
- package/dist/cjs/apollo/useCache.js +49 -0
- package/dist/cjs/bins/cross-env.d.ts +3 -0
- package/dist/cjs/bins/cross-env.d.ts.map +1 -0
- package/dist/cjs/bins/cross-env.js +30 -0
- package/dist/cjs/bins/msw.d.ts +3 -0
- package/dist/cjs/bins/msw.d.ts.map +1 -0
- package/dist/cjs/bins/msw.js +28 -0
- package/dist/cjs/bins/redwood.d.ts +9 -0
- package/dist/cjs/bins/redwood.d.ts.map +1 -0
- package/dist/cjs/bins/redwood.js +36 -0
- package/dist/cjs/bins/rwfw.d.ts +3 -0
- package/dist/cjs/bins/rwfw.d.ts.map +1 -0
- package/dist/cjs/bins/rwfw.js +36 -0
- package/dist/cjs/bins/storybook.d.ts +3 -0
- package/dist/cjs/bins/storybook.d.ts.map +1 -0
- package/dist/cjs/bins/storybook.js +49 -0
- package/dist/cjs/bins/tsc.d.ts +3 -0
- package/dist/cjs/bins/tsc.d.ts.map +1 -0
- package/dist/cjs/bins/tsc.js +30 -0
- package/dist/cjs/bundled/apollo-upload-client.d.ts +3 -0
- package/dist/cjs/bundled/apollo-upload-client.d.ts.map +1 -0
- package/dist/cjs/bundled/apollo-upload-client.js +2474 -0
- package/dist/cjs/components/DevFatalErrorPage.d.ts +21 -0
- package/dist/cjs/components/DevFatalErrorPage.d.ts.map +1 -0
- package/dist/cjs/components/DevFatalErrorPage.js +436 -0
- package/dist/cjs/components/FatalErrorBoundary.d.ts +24 -0
- package/dist/cjs/components/FatalErrorBoundary.d.ts.map +1 -0
- package/dist/cjs/components/FatalErrorBoundary.js +63 -0
- package/dist/cjs/components/FetchConfigProvider.d.ts +25 -0
- package/dist/cjs/components/FetchConfigProvider.d.ts.map +1 -0
- package/dist/cjs/components/FetchConfigProvider.js +80 -0
- package/dist/cjs/components/GraphQLHooksProvider.d.ts +45 -0
- package/dist/cjs/components/GraphQLHooksProvider.d.ts.map +1 -0
- package/dist/cjs/components/GraphQLHooksProvider.js +135 -0
- package/dist/cjs/components/MetaTags.d.ts +52 -0
- package/dist/cjs/components/MetaTags.d.ts.map +1 -0
- package/dist/cjs/components/MetaTags.js +69 -0
- package/dist/cjs/components/Metadata.d.ts +9 -0
- package/dist/cjs/components/Metadata.d.ts.map +1 -0
- package/dist/cjs/components/Metadata.js +95 -0
- package/dist/cjs/components/PortalHead.d.ts +4 -0
- package/dist/cjs/components/PortalHead.d.ts.map +1 -0
- package/dist/cjs/components/PortalHead.js +59 -0
- package/dist/cjs/components/RedwoodProvider.d.ts +9 -0
- package/dist/cjs/components/RedwoodProvider.d.ts.map +1 -0
- package/dist/cjs/components/RedwoodProvider.js +58 -0
- package/dist/cjs/components/ServerInject.d.ts +26 -0
- package/dist/cjs/components/ServerInject.d.ts.map +1 -0
- package/dist/cjs/components/ServerInject.js +75 -0
- package/dist/cjs/components/cell/CellCacheContext.d.ts +20 -0
- package/dist/cjs/components/cell/CellCacheContext.d.ts.map +1 -0
- package/dist/cjs/components/cell/CellCacheContext.js +53 -0
- package/dist/cjs/components/cell/CellErrorBoundary.d.ts +25 -0
- package/dist/cjs/components/cell/CellErrorBoundary.d.ts.map +1 -0
- package/dist/cjs/components/cell/CellErrorBoundary.js +66 -0
- package/dist/cjs/components/cell/cellTypes.d.ts +152 -0
- package/dist/cjs/components/cell/cellTypes.d.ts.map +1 -0
- package/dist/cjs/components/cell/cellTypes.js +16 -0
- package/dist/cjs/components/cell/createCell.d.ts +10 -0
- package/dist/cjs/components/cell/createCell.d.ts.map +1 -0
- package/dist/cjs/components/cell/createCell.js +165 -0
- package/dist/cjs/components/cell/createCell.test.js +351 -0
- package/dist/cjs/components/cell/createServerCell.d.ts +15 -0
- package/dist/cjs/components/cell/createServerCell.d.ts.map +1 -0
- package/dist/cjs/components/cell/createServerCell.js +91 -0
- package/dist/cjs/components/cell/createSuspendingCell.d.ts +11 -0
- package/dist/cjs/components/cell/createSuspendingCell.d.ts.map +1 -0
- package/dist/cjs/components/cell/createSuspendingCell.js +152 -0
- package/dist/cjs/components/cell/createSuspendingCell.test.js +115 -0
- package/dist/cjs/components/cell/isCellEmpty.d.ts +41 -0
- package/dist/cjs/components/cell/isCellEmpty.d.ts.map +1 -0
- package/dist/cjs/components/cell/isCellEmpty.js +35 -0
- package/dist/cjs/components/htmlTags.d.ts +52 -0
- package/dist/cjs/components/htmlTags.d.ts.map +1 -0
- package/dist/cjs/components/htmlTags.js +88 -0
- package/dist/cjs/config.d.ts +2 -0
- package/dist/cjs/config.d.ts.map +1 -0
- package/dist/cjs/config.js +6 -0
- package/dist/cjs/entry/index.js +39 -0
- package/dist/cjs/global.web-auto-imports.d.ts +30 -0
- package/dist/cjs/global.web-auto-imports.d.ts.map +1 -0
- package/dist/cjs/global.web-auto-imports.js +16 -0
- package/dist/cjs/graphql.d.ts +24 -0
- package/dist/cjs/graphql.d.ts.map +1 -0
- package/dist/cjs/graphql.js +36 -0
- package/dist/cjs/index.d.ts +20 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +80 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/routeHooks.types.d.ts +12 -0
- package/dist/cjs/routeHooks.types.d.ts.map +1 -0
- package/dist/cjs/routeHooks.types.js +16 -0
- package/dist/cjs/server/MiddlewareRequest.d.ts +28 -0
- package/dist/cjs/server/MiddlewareRequest.d.ts.map +1 -0
- package/dist/cjs/server/MiddlewareRequest.js +71 -0
- package/dist/cjs/server/MiddlewareResponse.d.ts +44 -0
- package/dist/cjs/server/MiddlewareResponse.d.ts.map +1 -0
- package/dist/cjs/server/MiddlewareResponse.js +130 -0
- package/dist/cjs/server/middleware.d.ts +17 -0
- package/dist/cjs/server/middleware.d.ts.map +1 -0
- package/dist/cjs/server/middleware.js +24 -0
- package/dist/cjs/server/request.d.ts +2 -0
- package/dist/cjs/server/request.d.ts.map +1 -0
- package/dist/cjs/server/request.js +34 -0
- package/dist/cjs/streamUtils/useDocumentReady.d.ts +11 -0
- package/dist/cjs/streamUtils/useDocumentReady.d.ts.map +1 -0
- package/dist/cjs/streamUtils/useDocumentReady.js +41 -0
- package/dist/cjs/toast/index.d.ts +3 -0
- package/dist/cjs/toast/index.d.ts.map +1 -0
- package/dist/cjs/toast/index.js +41 -0
- package/dist/components/DevFatalErrorPage.d.ts +21 -0
- package/dist/components/DevFatalErrorPage.d.ts.map +1 -0
- package/dist/components/DevFatalErrorPage.js +402 -0
- package/dist/components/FatalErrorBoundary.d.ts +24 -0
- package/dist/components/FatalErrorBoundary.d.ts.map +1 -0
- package/dist/components/FatalErrorBoundary.js +29 -0
- package/dist/components/FetchConfigProvider.d.ts +25 -0
- package/dist/components/FetchConfigProvider.d.ts.map +1 -0
- package/dist/components/FetchConfigProvider.js +43 -0
- package/dist/components/GraphQLHooksProvider.d.ts +45 -0
- package/dist/components/GraphQLHooksProvider.d.ts.map +1 -0
- package/dist/components/GraphQLHooksProvider.js +94 -0
- package/dist/components/MetaTags.d.ts +52 -0
- package/dist/components/MetaTags.d.ts.map +1 -0
- package/dist/components/MetaTags.js +35 -0
- package/dist/components/Metadata.d.ts +9 -0
- package/dist/components/Metadata.d.ts.map +1 -0
- package/dist/components/Metadata.js +61 -0
- package/dist/components/PortalHead.d.ts +4 -0
- package/dist/components/PortalHead.d.ts.map +1 -0
- package/dist/components/PortalHead.js +29 -0
- package/dist/components/RedwoodProvider.d.ts +9 -0
- package/dist/components/RedwoodProvider.d.ts.map +1 -0
- package/dist/components/RedwoodProvider.js +24 -0
- package/dist/components/ServerInject.d.ts +26 -0
- package/dist/components/ServerInject.d.ts.map +1 -0
- package/dist/components/ServerInject.js +37 -0
- package/dist/components/cell/CellCacheContext.d.ts +20 -0
- package/dist/components/cell/CellCacheContext.d.ts.map +1 -0
- package/dist/components/cell/CellCacheContext.js +18 -0
- package/dist/components/cell/CellErrorBoundary.d.ts +25 -0
- package/dist/components/cell/CellErrorBoundary.d.ts.map +1 -0
- package/dist/components/cell/CellErrorBoundary.js +32 -0
- package/dist/components/cell/cellTypes.d.ts +152 -0
- package/dist/components/cell/cellTypes.d.ts.map +1 -0
- package/dist/components/cell/cellTypes.js +0 -0
- package/dist/components/cell/createCell.d.ts +10 -0
- package/dist/components/cell/createCell.d.ts.map +1 -0
- package/dist/components/cell/createCell.js +131 -0
- package/dist/components/cell/createCell.test.js +328 -0
- package/dist/components/cell/createServerCell.d.ts +15 -0
- package/dist/components/cell/createServerCell.d.ts.map +1 -0
- package/dist/components/cell/createServerCell.js +57 -0
- package/dist/components/cell/createSuspendingCell.d.ts +11 -0
- package/dist/components/cell/createSuspendingCell.d.ts.map +1 -0
- package/dist/components/cell/createSuspendingCell.js +118 -0
- package/dist/components/cell/createSuspendingCell.test.js +92 -0
- package/dist/components/cell/isCellEmpty.d.ts +41 -0
- package/dist/components/cell/isCellEmpty.d.ts.map +1 -0
- package/dist/components/cell/isCellEmpty.js +11 -0
- package/dist/components/htmlTags.d.ts +52 -0
- package/dist/components/htmlTags.d.ts.map +1 -0
- package/dist/components/htmlTags.js +53 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +5 -0
- package/dist/entry/index.d.ts +1 -0
- package/dist/entry/index.js +16 -0
- package/dist/global.web-auto-imports.d.ts +30 -0
- package/dist/global.web-auto-imports.d.ts.map +1 -0
- package/dist/global.web-auto-imports.js +0 -0
- package/dist/graphql.d.ts +24 -0
- package/dist/graphql.d.ts.map +1 -0
- package/dist/graphql.js +12 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/package.json +1 -0
- package/dist/routeHooks.types.d.ts +12 -0
- package/dist/routeHooks.types.d.ts.map +1 -0
- package/dist/routeHooks.types.js +0 -0
- package/dist/server/MiddlewareRequest.d.ts +28 -0
- package/dist/server/MiddlewareRequest.d.ts.map +1 -0
- package/dist/server/MiddlewareRequest.js +46 -0
- package/dist/server/MiddlewareResponse.d.ts +44 -0
- package/dist/server/MiddlewareResponse.d.ts.map +1 -0
- package/dist/server/MiddlewareResponse.js +95 -0
- package/dist/server/middleware.d.ts +17 -0
- package/dist/server/middleware.d.ts.map +1 -0
- package/dist/server/middleware.js +2 -0
- package/dist/server/request.d.ts +2 -0
- package/dist/server/request.d.ts.map +1 -0
- package/dist/server/request.js +12 -0
- package/dist/streamUtils/useDocumentReady.d.ts +11 -0
- package/dist/streamUtils/useDocumentReady.d.ts.map +1 -0
- package/dist/streamUtils/useDocumentReady.js +17 -0
- package/dist/toast/index.d.ts +3 -0
- package/dist/toast/index.d.ts.map +1 -0
- package/dist/toast/index.js +5 -0
- package/package.json +193 -0
- package/src/entry/index.jsx +29 -0
- package/toast/index.js +2 -0
- package/toast/package.json +4 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import type { ComponentProps, JSXElementConstructor } from 'react';
|
|
2
|
+
import type { ApolloClient, NetworkStatus, OperationVariables, QueryRef, UseBackgroundQueryResult } from '@apollo/client';
|
|
3
|
+
import type { DocumentNode } from 'graphql';
|
|
4
|
+
import type { A, L, O, U } from 'ts-toolbelt';
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* If the Cell has a `beforeQuery` function, then the variables are not required,
|
|
8
|
+
* but instead the arguments of the `beforeQuery` function are required.
|
|
9
|
+
*
|
|
10
|
+
* If the Cell does not have a `beforeQuery` function, then the variables are required.
|
|
11
|
+
*
|
|
12
|
+
* Note that a query that doesn't take any variables is defined as {[x: string]: never}
|
|
13
|
+
* The ternary at the end makes sure we don't include it, otherwise it won't allow merging any
|
|
14
|
+
* other custom props from the Success component.
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
type CellPropsVariables<Cell, GQLVariables> = Cell extends {
|
|
18
|
+
beforeQuery: (...args: any[]) => any;
|
|
19
|
+
} ? Parameters<Cell['beforeQuery']>[0] extends unknown ? Record<string, unknown> : Parameters<Cell['beforeQuery']>[0] : GQLVariables extends Record<string, never> ? unknown : GQLVariables;
|
|
20
|
+
/**
|
|
21
|
+
* Cell component props which is the combination of query variables and Success props.
|
|
22
|
+
*/
|
|
23
|
+
export type CellProps<CellSuccess extends keyof JSX.IntrinsicElements | JSXElementConstructor<any>, GQLResult, CellType, GQLVariables> = A.Compute<Omit<ComponentProps<CellSuccess>, keyof CellPropsVariables<CellType, GQLVariables> | keyof GQLResult | 'updating' | 'queryResult'> & CellPropsVariables<CellType, GQLVariables>>;
|
|
24
|
+
type InputVarProps<T> = T extends {
|
|
25
|
+
[key: string]: never;
|
|
26
|
+
} ? unknown : T;
|
|
27
|
+
export type CellLoadingProps<TVariables extends OperationVariables = any> = {
|
|
28
|
+
queryResult?: NonSuspenseCellQueryResult<TVariables, any> | SuspenseCellQueryResult;
|
|
29
|
+
} & InputVarProps<TVariables>;
|
|
30
|
+
export type CellFailureProps<TVariables extends OperationVariables = any> = {
|
|
31
|
+
queryResult?: NonSuspenseCellQueryResult<TVariables, any> | SuspenseCellQueryResult;
|
|
32
|
+
error?: QueryOperationResult['error'] | Error;
|
|
33
|
+
/**
|
|
34
|
+
* @see {@link https://www.apollographql.com/docs/apollo-server/data/errors/#error-codes}
|
|
35
|
+
*/
|
|
36
|
+
errorCode?: string;
|
|
37
|
+
updating?: boolean;
|
|
38
|
+
} & InputVarProps<TVariables>;
|
|
39
|
+
type Guaranteed<T> = {
|
|
40
|
+
[K in keyof T]-?: NonNullable<T[K]>;
|
|
41
|
+
};
|
|
42
|
+
type KeyCount<T extends object> = L.Length<U.ListOf<O.SelectKeys<T, any>>>;
|
|
43
|
+
type ConditionallyGuaranteed<T extends object> = KeyCount<T> extends 1 ? Guaranteed<T> : T;
|
|
44
|
+
/**
|
|
45
|
+
* @params TData = Type of data based on your graphql query. This can be imported from 'types/graphql'
|
|
46
|
+
* @example
|
|
47
|
+
* import type { FindPosts } from 'types/graphql'
|
|
48
|
+
*
|
|
49
|
+
* const { post }: CellSuccessData<FindPosts> = props
|
|
50
|
+
*/
|
|
51
|
+
export type CellSuccessData<TData = any> = ConditionallyGuaranteed<Omit<TData, '__typename'>>;
|
|
52
|
+
/**
|
|
53
|
+
* @MARK not sure about this partial, but we need to do this for tests and storybook.
|
|
54
|
+
*
|
|
55
|
+
* `updating` is just `loading` renamed; since Cells default to stale-while-refetch,
|
|
56
|
+
* this prop lets users render something like a spinner to show that a request is in-flight.
|
|
57
|
+
*/
|
|
58
|
+
export type CellSuccessProps<TData = any, TVariables extends OperationVariables = any> = {
|
|
59
|
+
queryResult?: NonSuspenseCellQueryResult<TVariables, TData> | SuspenseCellQueryResult;
|
|
60
|
+
updating?: boolean;
|
|
61
|
+
} & InputVarProps<TVariables> & A.Compute<CellSuccessData<TData>>;
|
|
62
|
+
/**
|
|
63
|
+
* A coarse type for the `data` prop returned by `useQuery`.
|
|
64
|
+
*
|
|
65
|
+
* ```js
|
|
66
|
+
* {
|
|
67
|
+
* data: {
|
|
68
|
+
* post: { ... }
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export type DataObject = {
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The main interface.
|
|
78
|
+
*/
|
|
79
|
+
export interface CreateCellProps<CellProps, CellVariables> {
|
|
80
|
+
/**
|
|
81
|
+
* The GraphQL syntax tree to execute or function to call that returns it.
|
|
82
|
+
* If `QUERY` is a function, it's called with the result of `beforeQuery`.
|
|
83
|
+
*/
|
|
84
|
+
QUERY: DocumentNode | ((variables: Record<string, unknown>) => DocumentNode);
|
|
85
|
+
/**
|
|
86
|
+
* Parse `props` into query variables. Most of the time `props` are appropriate variables as is.
|
|
87
|
+
*/
|
|
88
|
+
beforeQuery?: ((props: CellProps) => {
|
|
89
|
+
variables: CellVariables;
|
|
90
|
+
}) | (() => {
|
|
91
|
+
variables: CellVariables;
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Sanitize the data returned from the query.
|
|
95
|
+
*/
|
|
96
|
+
afterQuery?: (data: DataObject) => DataObject;
|
|
97
|
+
/**
|
|
98
|
+
* How to decide if the result of a query should render the `Empty` component.
|
|
99
|
+
* The default implementation checks that the first field isn't `null` or an empty array.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
*
|
|
103
|
+
* In the example below, only `users` is checked:
|
|
104
|
+
*
|
|
105
|
+
* ```js
|
|
106
|
+
* export const QUERY = gql`
|
|
107
|
+
* users {
|
|
108
|
+
* name
|
|
109
|
+
* }
|
|
110
|
+
* posts {
|
|
111
|
+
* title
|
|
112
|
+
* }
|
|
113
|
+
* `
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
isEmpty?: (response: DataObject, options: {
|
|
117
|
+
isDataEmpty: (data: DataObject) => boolean;
|
|
118
|
+
}) => boolean;
|
|
119
|
+
/**
|
|
120
|
+
* If the query's in flight and there's no stale data, render this.
|
|
121
|
+
*/
|
|
122
|
+
Loading?: React.FC<CellLoadingProps & Partial<CellProps>>;
|
|
123
|
+
/**
|
|
124
|
+
* If something went wrong, render this.
|
|
125
|
+
*/
|
|
126
|
+
Failure?: React.FC<CellFailureProps & Partial<CellProps>>;
|
|
127
|
+
/**
|
|
128
|
+
* If no data was returned, render this.
|
|
129
|
+
*/
|
|
130
|
+
Empty?: React.FC<CellSuccessProps & Partial<CellProps>>;
|
|
131
|
+
/**
|
|
132
|
+
* If data was returned, render this.
|
|
133
|
+
*/
|
|
134
|
+
Success: React.FC<CellSuccessProps & Partial<CellProps>>;
|
|
135
|
+
/**
|
|
136
|
+
* What to call the Cell. Defaults to the filename.
|
|
137
|
+
*/
|
|
138
|
+
displayName?: string;
|
|
139
|
+
}
|
|
140
|
+
export type SuspendingSuccessProps = React.PropsWithChildren<Record<string, unknown>> & {
|
|
141
|
+
queryRef: QueryRef<DataObject>;
|
|
142
|
+
suspenseQueryResult: SuspenseCellQueryResult<DataObject, any>;
|
|
143
|
+
userProps: Record<string, any>;
|
|
144
|
+
};
|
|
145
|
+
export type NonSuspenseCellQueryResult<TVariables extends OperationVariables = any, TData = any> = Partial<Omit<QueryOperationResult<TData, TVariables>, 'loading' | 'error' | 'data'>>;
|
|
146
|
+
export interface SuspenseCellQueryResult<_TData = any, _TVariables extends OperationVariables = any> extends UseBackgroundQueryResult {
|
|
147
|
+
client: ApolloClient<any>;
|
|
148
|
+
networkStatus?: NetworkStatus;
|
|
149
|
+
called: boolean;
|
|
150
|
+
}
|
|
151
|
+
export {};
|
|
152
|
+
//# sourceMappingURL=cellTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cellTypes.d.ts","sourceRoot":"","sources":["../../../src/components/cell/cellTypes.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { CreateCellProps } from './cellTypes.js';
|
|
3
|
+
import { createSuspendingCell } from './createSuspendingCell.js';
|
|
4
|
+
export declare const createCell: typeof createSuspendingCell | typeof createNonSuspendingCell;
|
|
5
|
+
/**
|
|
6
|
+
* Creates a Cell out of a GraphQL query and components that track to its lifecycle.
|
|
7
|
+
*/
|
|
8
|
+
declare function createNonSuspendingCell<CellProps extends Record<string, unknown>, CellVariables extends Record<string, unknown>>({ QUERY, beforeQuery, afterQuery, isEmpty, Loading, Failure, Empty, Success, displayName, }: CreateCellProps<CellProps, CellVariables>): React.FC<CellProps>;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=createCell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createCell.d.ts","sourceRoot":"","sources":["../../../src/components/cell/createCell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAUzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAIhE,eAAO,MAAM,UAAU,8DAEI,CAAA;AAE3B;;GAEG;AACH,iBAAS,uBAAuB,CAC9B,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACzC,aAAa,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7C,EACA,KAAK,EACL,WAWE,EACF,UAA2B,EAC3B,OAAqB,EACrB,OAA+B,EAC/B,OAAO,EACP,KAAK,EACL,OAAO,EACP,WAAoB,GACrB,EAAE,eAAe,CAAC,SAAS,EAAE,aAAa,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CAuIjE"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { fragmentRegistry } from "../../apollo/fragmentRegistry.js";
|
|
3
|
+
import { getOperationName } from "../../graphql.js";
|
|
4
|
+
import { useQuery } from "../GraphQLHooksProvider.js";
|
|
5
|
+
import { useCellCacheContext } from "./CellCacheContext.js";
|
|
6
|
+
import { createSuspendingCell } from "./createSuspendingCell.js";
|
|
7
|
+
import { isDataEmpty } from "./isCellEmpty.js";
|
|
8
|
+
const createCell = RWJS_ENV.RWJS_EXP_STREAMING_SSR ? createSuspendingCell : createNonSuspendingCell;
|
|
9
|
+
function createNonSuspendingCell({
|
|
10
|
+
QUERY,
|
|
11
|
+
beforeQuery = (props) => ({
|
|
12
|
+
// By default, we assume that the props are the gql-variables.
|
|
13
|
+
variables: props,
|
|
14
|
+
/**
|
|
15
|
+
* We're duplicating these props here due to a suspected bug in Apollo Client v3.5.4
|
|
16
|
+
* (it doesn't seem to be respecting `defaultOptions` in `RedwoodApolloProvider`.)
|
|
17
|
+
*
|
|
18
|
+
* @see {@link https://github.com/apollographql/apollo-client/issues/9105}
|
|
19
|
+
*/
|
|
20
|
+
fetchPolicy: "cache-and-network",
|
|
21
|
+
notifyOnNetworkStatusChange: true
|
|
22
|
+
}),
|
|
23
|
+
afterQuery = (data) => data,
|
|
24
|
+
isEmpty = isDataEmpty,
|
|
25
|
+
Loading = () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Loading..."),
|
|
26
|
+
Failure,
|
|
27
|
+
Empty,
|
|
28
|
+
Success,
|
|
29
|
+
displayName = "Cell"
|
|
30
|
+
}) {
|
|
31
|
+
function NamedCell(props) {
|
|
32
|
+
const { children: _, ...variables } = props;
|
|
33
|
+
const options = beforeQuery(variables);
|
|
34
|
+
const query = typeof QUERY === "function" ? QUERY(options) : QUERY;
|
|
35
|
+
let {
|
|
36
|
+
// eslint-disable-next-line prefer-const
|
|
37
|
+
error,
|
|
38
|
+
loading,
|
|
39
|
+
data,
|
|
40
|
+
...queryResult
|
|
41
|
+
} = useQuery(query, options);
|
|
42
|
+
if (globalThis.__REDWOOD__PRERENDERING) {
|
|
43
|
+
const { queryCache } = useCellCacheContext();
|
|
44
|
+
const operationName = getOperationName(query);
|
|
45
|
+
const transformedQuery = fragmentRegistry.transform(query);
|
|
46
|
+
let cacheKey;
|
|
47
|
+
if (operationName) {
|
|
48
|
+
cacheKey = operationName + "_" + JSON.stringify(variables);
|
|
49
|
+
} else {
|
|
50
|
+
const cellName = displayName === "Cell" ? "the cell" : displayName;
|
|
51
|
+
throw new Error(
|
|
52
|
+
`The gql query in ${cellName} is missing an operation name. Something like FindBlogPostQuery in \`query FindBlogPostQuery($id: Int!)\``
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
const queryInfo = queryCache[cacheKey];
|
|
56
|
+
if (queryInfo?.renderLoading) {
|
|
57
|
+
loading = true;
|
|
58
|
+
} else {
|
|
59
|
+
if (queryInfo?.hasProcessed) {
|
|
60
|
+
loading = false;
|
|
61
|
+
data = queryInfo.data;
|
|
62
|
+
queryResult = { variables };
|
|
63
|
+
} else {
|
|
64
|
+
queryCache[cacheKey] ||= {
|
|
65
|
+
query: transformedQuery,
|
|
66
|
+
variables: options.variables,
|
|
67
|
+
hasProcessed: false
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (error) {
|
|
73
|
+
if (Failure) {
|
|
74
|
+
return /* @__PURE__ */ React.createElement(
|
|
75
|
+
Failure,
|
|
76
|
+
{
|
|
77
|
+
error,
|
|
78
|
+
errorCode: (
|
|
79
|
+
// Use the ad-hoc QueryResultWithErrorCode type to access the errorCode
|
|
80
|
+
queryResult.errorCode ?? error.graphQLErrors?.[0]?.extensions?.["code"]
|
|
81
|
+
),
|
|
82
|
+
...props,
|
|
83
|
+
updating: loading,
|
|
84
|
+
queryResult
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
} else {
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
} else if (data) {
|
|
91
|
+
const afterQueryData = afterQuery(data);
|
|
92
|
+
if (isEmpty(data, { isDataEmpty }) && Empty) {
|
|
93
|
+
return /* @__PURE__ */ React.createElement(
|
|
94
|
+
Empty,
|
|
95
|
+
{
|
|
96
|
+
...props,
|
|
97
|
+
...afterQueryData,
|
|
98
|
+
updating: loading,
|
|
99
|
+
queryResult
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
return /* @__PURE__ */ React.createElement(
|
|
104
|
+
Success,
|
|
105
|
+
{
|
|
106
|
+
...props,
|
|
107
|
+
...afterQueryData,
|
|
108
|
+
updating: loading,
|
|
109
|
+
queryResult
|
|
110
|
+
}
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
} else if (loading) {
|
|
114
|
+
return /* @__PURE__ */ React.createElement(Loading, { ...props, queryResult });
|
|
115
|
+
} else {
|
|
116
|
+
console.warn(
|
|
117
|
+
`If you're using Apollo Client, check for its debug logs here in the console, which may help explain the error.`
|
|
118
|
+
);
|
|
119
|
+
throw new Error(
|
|
120
|
+
"Cannot render Cell: reached an unexpected state where the query succeeded but `data` is `null`. If this happened in Storybook, your query could be missing fields; otherwise this is most likely a GraphQL caching bug. Note that adding an `id` field to all the fields on your query may fix the issue."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
NamedCell.displayName = displayName;
|
|
125
|
+
return (props) => {
|
|
126
|
+
return /* @__PURE__ */ React.createElement(NamedCell, { ...props });
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
createCell
|
|
131
|
+
};
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { vi, describe, beforeAll, test, expect } from "vitest";
|
|
4
|
+
import { GraphQLHooksProvider } from "../GraphQLHooksProvider.js";
|
|
5
|
+
import { createCell } from "./createCell.js";
|
|
6
|
+
describe("createCell", () => {
|
|
7
|
+
beforeAll(() => {
|
|
8
|
+
globalThis.RWJS_ENV = {
|
|
9
|
+
RWJS_EXP_STREAMING_SSR: false
|
|
10
|
+
};
|
|
11
|
+
});
|
|
12
|
+
test("Renders a static Success component", () => {
|
|
13
|
+
const TestCell = createCell({
|
|
14
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
15
|
+
QUERY: "query TestQuery { answer }",
|
|
16
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!")
|
|
17
|
+
});
|
|
18
|
+
const myUseQueryHook = () => ({ data: {} });
|
|
19
|
+
render(
|
|
20
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
21
|
+
);
|
|
22
|
+
screen.getByText(/^Great success!$/);
|
|
23
|
+
});
|
|
24
|
+
test("Renders Success with data", () => {
|
|
25
|
+
const TestCell = createCell({
|
|
26
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
27
|
+
QUERY: "query TestQuery { answer }",
|
|
28
|
+
Success: ({ answer }) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("dl", null, /* @__PURE__ */ React.createElement("dt", null, "What's the meaning of life?"), /* @__PURE__ */ React.createElement("dd", null, answer)))
|
|
29
|
+
});
|
|
30
|
+
const myUseQueryHook = () => {
|
|
31
|
+
return { data: { answer: 42 } };
|
|
32
|
+
};
|
|
33
|
+
render(
|
|
34
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
35
|
+
);
|
|
36
|
+
screen.getByText(/^What's the meaning of life\?$/);
|
|
37
|
+
screen.getByText(/^42$/);
|
|
38
|
+
});
|
|
39
|
+
test("Renders Success if any of the fields have data (i.e. not just the first)", () => {
|
|
40
|
+
const TestCell = createCell({
|
|
41
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
42
|
+
QUERY: "query TestQuery { users { name } posts { title } }",
|
|
43
|
+
Empty: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "No users or posts"),
|
|
44
|
+
Success: ({ users, posts }) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", null, users.length > 0 ? /* @__PURE__ */ React.createElement("ul", null, users.map(({ name }) => /* @__PURE__ */ React.createElement("li", { key: name }, name))) : "no users"), /* @__PURE__ */ React.createElement("div", null, posts.length > 0 ? /* @__PURE__ */ React.createElement("ul", null, posts.map(({ title }) => /* @__PURE__ */ React.createElement("li", { key: title }, title))) : "no posts"))
|
|
45
|
+
});
|
|
46
|
+
const myUseQueryHook = () => {
|
|
47
|
+
return {
|
|
48
|
+
data: {
|
|
49
|
+
users: [],
|
|
50
|
+
posts: [{ title: "bazinga" }, { title: "kittens" }]
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
render(
|
|
55
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
56
|
+
);
|
|
57
|
+
screen.getByText(/bazinga/);
|
|
58
|
+
screen.getByText(/kittens/);
|
|
59
|
+
});
|
|
60
|
+
test("Renders default Loading when there is no data", () => {
|
|
61
|
+
const TestCell = createCell({
|
|
62
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
63
|
+
QUERY: "query TestQuery { answer }",
|
|
64
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!")
|
|
65
|
+
});
|
|
66
|
+
const myUseQueryHook = () => ({ loading: true });
|
|
67
|
+
render(
|
|
68
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
69
|
+
);
|
|
70
|
+
screen.getByText(/^Loading...$/);
|
|
71
|
+
});
|
|
72
|
+
test("Renders custom Loading when there is no data", () => {
|
|
73
|
+
const TestCell = createCell({
|
|
74
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
75
|
+
QUERY: "query TestQuery { answer }",
|
|
76
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
77
|
+
Loading: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Fetching answer...")
|
|
78
|
+
});
|
|
79
|
+
const myUseQueryHook = () => ({ loading: true });
|
|
80
|
+
render(
|
|
81
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
82
|
+
);
|
|
83
|
+
screen.getByText(/^Fetching answer...$/);
|
|
84
|
+
});
|
|
85
|
+
test("Renders Success even when `loading` is true if there is data", () => {
|
|
86
|
+
const TestCell = createCell({
|
|
87
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
88
|
+
QUERY: "query TestQuery { answer }",
|
|
89
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
90
|
+
Loading: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Fetching answer...")
|
|
91
|
+
});
|
|
92
|
+
const myUseQueryHook = () => ({ loading: true, data: {} });
|
|
93
|
+
render(
|
|
94
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
95
|
+
);
|
|
96
|
+
screen.getByText(/^Great success!$/);
|
|
97
|
+
});
|
|
98
|
+
test("Renders Empty if available, and data field is null", () => {
|
|
99
|
+
const TestCell = createCell({
|
|
100
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
101
|
+
QUERY: "query TestQuery { answer }",
|
|
102
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
103
|
+
Empty: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "No one knows")
|
|
104
|
+
});
|
|
105
|
+
const myUseQueryHook = () => ({ loading: true, data: { answer: null } });
|
|
106
|
+
render(
|
|
107
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
108
|
+
);
|
|
109
|
+
screen.getByText(/^No one knows$/);
|
|
110
|
+
});
|
|
111
|
+
test("Renders Empty if available, and data field is an empty array", () => {
|
|
112
|
+
const TestCell = createCell({
|
|
113
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
114
|
+
QUERY: "query TestQuery { answers }",
|
|
115
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
116
|
+
Empty: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "No one knows")
|
|
117
|
+
});
|
|
118
|
+
const myUseQueryHook = () => ({ loading: true, data: { answers: [] } });
|
|
119
|
+
render(
|
|
120
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
121
|
+
);
|
|
122
|
+
screen.getByText(/^No one knows$/);
|
|
123
|
+
});
|
|
124
|
+
test("Renders Success even if data is empty when no Empty is available", () => {
|
|
125
|
+
const TestCell = createCell({
|
|
126
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
127
|
+
QUERY: "query TestQuery { answer }",
|
|
128
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Empty success")
|
|
129
|
+
});
|
|
130
|
+
const myUseQueryHook = () => ({ loading: true, data: { answer: null } });
|
|
131
|
+
render(
|
|
132
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
133
|
+
);
|
|
134
|
+
screen.getByText(/^Empty success$/);
|
|
135
|
+
});
|
|
136
|
+
test("Allows passing children to Success", () => {
|
|
137
|
+
const TestCell = createCell({
|
|
138
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
139
|
+
QUERY: "query TestQuery { answer }",
|
|
140
|
+
Success: ({ children }) => /* @__PURE__ */ React.createElement(React.Fragment, null, "Look at my beautiful ", children)
|
|
141
|
+
});
|
|
142
|
+
const myUseQueryHook = () => ({ data: {} });
|
|
143
|
+
render(
|
|
144
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null, /* @__PURE__ */ React.createElement("div", null, "\u{1F986}")))
|
|
145
|
+
);
|
|
146
|
+
screen.getByText(/^Look at my beautiful$/);
|
|
147
|
+
screen.getByText(/^🦆$/);
|
|
148
|
+
});
|
|
149
|
+
test("Cell props are passed to the query as variables", () => {
|
|
150
|
+
const TestCell = createCell({
|
|
151
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
152
|
+
QUERY: `query Greet($name: String!) {
|
|
153
|
+
greet(name: $name) {
|
|
154
|
+
greeting
|
|
155
|
+
}
|
|
156
|
+
}`,
|
|
157
|
+
Success: ({ greeting }) => /* @__PURE__ */ React.createElement("p", null, greeting)
|
|
158
|
+
});
|
|
159
|
+
const myUseQueryHook = (_query, options) => {
|
|
160
|
+
return { data: { greeting: `Hello ${options.variables.name}!` } };
|
|
161
|
+
};
|
|
162
|
+
render(
|
|
163
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, { name: "Bob" }))
|
|
164
|
+
);
|
|
165
|
+
screen.getByText(/^Hello Bob!$/);
|
|
166
|
+
});
|
|
167
|
+
test("Allows QUERY to be a function", () => {
|
|
168
|
+
const TestCell = createCell({
|
|
169
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
170
|
+
QUERY: ({ variables }) => {
|
|
171
|
+
if (variables.character === "BEAST") {
|
|
172
|
+
return "query BeastQuery { name }";
|
|
173
|
+
}
|
|
174
|
+
return "query HeroQuery { name }";
|
|
175
|
+
},
|
|
176
|
+
Success: ({ name }) => /* @__PURE__ */ React.createElement("p", null, "Call me ", name)
|
|
177
|
+
});
|
|
178
|
+
const myUseQueryHook = (query) => {
|
|
179
|
+
if (query.includes("BeastQuery")) {
|
|
180
|
+
return { data: { name: "Boogeyman" } };
|
|
181
|
+
} else if (query.includes("HeroQuery")) {
|
|
182
|
+
return { data: { name: "Lara Croft" } };
|
|
183
|
+
}
|
|
184
|
+
return { data: { name: "John Doe" } };
|
|
185
|
+
};
|
|
186
|
+
render(
|
|
187
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, { character: "BEAST" }), /* @__PURE__ */ React.createElement(TestCell, { character: "HERO" }))
|
|
188
|
+
);
|
|
189
|
+
screen.getByText(/^Call me Boogeyman$/);
|
|
190
|
+
screen.getByText(/^Call me Lara Croft$/);
|
|
191
|
+
});
|
|
192
|
+
test("Renders Failure when there is an error", () => {
|
|
193
|
+
const TestCell = createCell({
|
|
194
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
195
|
+
QUERY: "query TestQuery { answer }",
|
|
196
|
+
Failure: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Sad face :("),
|
|
197
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
198
|
+
Loading: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Fetching answer...")
|
|
199
|
+
});
|
|
200
|
+
const myUseQueryHook = () => ({ error: true });
|
|
201
|
+
render(
|
|
202
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
203
|
+
);
|
|
204
|
+
screen.getByText(/^Sad face :\($/);
|
|
205
|
+
});
|
|
206
|
+
test("Passes error to Failure component", () => {
|
|
207
|
+
const TestCell = createCell({
|
|
208
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
209
|
+
QUERY: "query TestQuery { answer }",
|
|
210
|
+
Failure: ({ error }) => /* @__PURE__ */ React.createElement(React.Fragment, null, JSON.stringify(error)),
|
|
211
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
212
|
+
Loading: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Fetching answer...")
|
|
213
|
+
});
|
|
214
|
+
const myUseQueryHook = () => ({ error: { msg: "System malfunction" } });
|
|
215
|
+
render(
|
|
216
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
217
|
+
);
|
|
218
|
+
screen.getByText(/^{"msg":"System malfunction"}$/);
|
|
219
|
+
});
|
|
220
|
+
test("Passes error and errorCode to Failure component", () => {
|
|
221
|
+
const TestCell = createCell({
|
|
222
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
223
|
+
QUERY: "query TestQuery { answer }",
|
|
224
|
+
Failure: ({ error, errorCode }) => /* @__PURE__ */ React.createElement(React.Fragment, null, JSON.stringify(error), ",code:", errorCode),
|
|
225
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
226
|
+
Loading: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Fetching answer...")
|
|
227
|
+
});
|
|
228
|
+
const myUseQueryHook = () => ({
|
|
229
|
+
error: { msg: "System malfunction" },
|
|
230
|
+
errorCode: "SIMON_SAYS_NO"
|
|
231
|
+
});
|
|
232
|
+
render(
|
|
233
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
234
|
+
);
|
|
235
|
+
screen.getByText(/^{"msg":"System malfunction"},code:SIMON_SAYS_NO$/);
|
|
236
|
+
});
|
|
237
|
+
test("Passes children to Failure", () => {
|
|
238
|
+
const TestCell = createCell({
|
|
239
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
240
|
+
QUERY: "query TestQuery { answer }",
|
|
241
|
+
Failure: ({ children }) => /* @__PURE__ */ React.createElement(React.Fragment, null, "I'm a failure ", children)
|
|
242
|
+
});
|
|
243
|
+
const myUseQueryHook = () => ({ error: {} });
|
|
244
|
+
render(
|
|
245
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null, /* @__PURE__ */ React.createElement("div", null, "Child")))
|
|
246
|
+
);
|
|
247
|
+
screen.getByText(/^I'm a failure$/);
|
|
248
|
+
screen.getByText(/^Child$/);
|
|
249
|
+
});
|
|
250
|
+
test("Throws an error when there is an error if no Failure component exists", () => {
|
|
251
|
+
const TestCell = createCell({
|
|
252
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
253
|
+
QUERY: "query TestQuery { answer }",
|
|
254
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
255
|
+
Loading: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Fetching answer...")
|
|
256
|
+
});
|
|
257
|
+
const myUseQueryHook = () => ({ error: { message: "200 GraphQL" } });
|
|
258
|
+
const err = console.error;
|
|
259
|
+
console.error = vi.fn();
|
|
260
|
+
let error;
|
|
261
|
+
try {
|
|
262
|
+
render(
|
|
263
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
264
|
+
);
|
|
265
|
+
} catch (e) {
|
|
266
|
+
error = e;
|
|
267
|
+
}
|
|
268
|
+
expect(error.message).toEqual("200 GraphQL");
|
|
269
|
+
console.error = err;
|
|
270
|
+
});
|
|
271
|
+
test("Allows overriding of default isDataEmpty", () => {
|
|
272
|
+
const TestCell = createCell({
|
|
273
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
274
|
+
QUERY: "query TestQuery { answer }",
|
|
275
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
276
|
+
Empty: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Got nothing"),
|
|
277
|
+
isEmpty: () => true
|
|
278
|
+
});
|
|
279
|
+
const myUseQueryHook = () => ({
|
|
280
|
+
data: {},
|
|
281
|
+
loading: false
|
|
282
|
+
});
|
|
283
|
+
render(
|
|
284
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
285
|
+
);
|
|
286
|
+
screen.getByText(/^Got nothing$/);
|
|
287
|
+
});
|
|
288
|
+
test("Allows mixing isDataEmpty with custom logic", () => {
|
|
289
|
+
const TestCell = createCell({
|
|
290
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
291
|
+
QUERY: "query TestQuery { answer }",
|
|
292
|
+
Success: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Great success!"),
|
|
293
|
+
Empty: () => /* @__PURE__ */ React.createElement(React.Fragment, null, "Got nothing"),
|
|
294
|
+
isEmpty: (data, { isDataEmpty }) => isDataEmpty(data) || data.answer === "0"
|
|
295
|
+
});
|
|
296
|
+
const myUseQueryHook = () => ({
|
|
297
|
+
data: { answer: "0" },
|
|
298
|
+
loading: false
|
|
299
|
+
});
|
|
300
|
+
render(
|
|
301
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
302
|
+
);
|
|
303
|
+
screen.getByText(/^Got nothing$/);
|
|
304
|
+
});
|
|
305
|
+
test("Allows overriding variables in beforeQuery", () => {
|
|
306
|
+
const TestCell = createCell({
|
|
307
|
+
// @ts-expect-error - Purposefully using a plain string here.
|
|
308
|
+
QUERY: `query Greet($name: String!) {
|
|
309
|
+
greet(name: $name) {
|
|
310
|
+
greeting
|
|
311
|
+
}
|
|
312
|
+
}`,
|
|
313
|
+
Success: ({ greeting }) => /* @__PURE__ */ React.createElement("p", null, greeting),
|
|
314
|
+
beforeQuery: () => ({
|
|
315
|
+
variables: {
|
|
316
|
+
name: "Bob"
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
});
|
|
320
|
+
const myUseQueryHook = (_query, options) => {
|
|
321
|
+
return { data: { greeting: `Hello ${options.variables.name}!` } };
|
|
322
|
+
};
|
|
323
|
+
render(
|
|
324
|
+
/* @__PURE__ */ React.createElement(GraphQLHooksProvider, { useQuery: myUseQueryHook, useMutation: null }, /* @__PURE__ */ React.createElement(TestCell, null))
|
|
325
|
+
);
|
|
326
|
+
screen.getByText(/^Hello Bob!$/);
|
|
327
|
+
});
|
|
328
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { CreateCellProps } from './cellTypes.js';
|
|
3
|
+
type CreateServerCellProps<CellProps, CellVariables> = Omit<CreateCellProps<CellProps, CellVariables>, 'QUERY' | 'Failure'> & {
|
|
4
|
+
data: (variables?: AnyObj) => any;
|
|
5
|
+
Failure?: React.ComponentType<{
|
|
6
|
+
error: unknown;
|
|
7
|
+
queryResult: {
|
|
8
|
+
refetch: (variables: CellProps) => AnyObj;
|
|
9
|
+
};
|
|
10
|
+
}>;
|
|
11
|
+
};
|
|
12
|
+
type AnyObj = Record<string, unknown>;
|
|
13
|
+
export declare function createServerCell<CellProps extends AnyObj, CellVariables extends AnyObj>(createCellProps: CreateServerCellProps<CellProps, CellVariables>): React.FC<CellProps>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=createServerCell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createServerCell.d.ts","sourceRoot":"","sources":["../../../src/components/cell/createServerCell.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAmB,MAAM,OAAO,CAAA;AAMvC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAIrD,KAAK,qBAAqB,CAAC,SAAS,EAAE,aAAa,IAAI,IAAI,CACzD,eAAe,CAAC,SAAS,EAAE,aAAa,CAAC,EACzC,OAAO,GAAG,SAAS,CACpB,GAAG;IACF,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,GAAG,CAAA;IACjC,OAAO,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;QAC5B,KAAK,EAAE,OAAO,CAAA;QACd,WAAW,EAAE;YAAE,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,MAAM,CAAA;SAAE,CAAA;KAC3D,CAAC,CAAA;CACH,CAAA;AAED,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAErC,wBAAgB,gBAAgB,CAC9B,SAAS,SAAS,MAAM,EACxB,aAAa,SAAS,MAAM,EAE5B,eAAe,EAAE,qBAAqB,CAAC,SAAS,EAAE,aAAa,CAAC,GAC/D,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CA2ErB"}
|