From 2dc733b9e7ed0b6a919c5980b48aa8a6e72ce0d4 Mon Sep 17 00:00:00 2001 From: Kyle Corbitt Date: Sat, 3 Apr 2021 21:35:03 -0700 Subject: [PATCH 1/3] Static typing for cells This PR is the first step towards implementing https://github.com/redwoodjs/redwood/issues/2205. It allows users to declare the prop types their cells expect. It also renames `withCell` to `createCell`, for the reasons I outlined in https://github.com/redwoodjs/redwood/issues/2205#issuecomment-812964440. `createCell` feels like a more parsimonious name to me but I can back that change out if others disagree. It appears that the babel transform for wrapping cells already checks for a default export and bails out if one exists, so this shouldn't require any changes there. The major remaining task is updating the cell generator to add a `export default createCell` line at the end of each cell in Typescript. I'd appreciate more input on whether this is a change we're fine making on both the TS and JS sides, or whether we'll need two templates. Do we have multiple templates anywhere else? --- .../cell-with-commented-exports/output.js | 4 ++-- .../cell/cell-with-required-exports/output.js | 4 ++-- .../babelPlugins/babel-plugin-redwood-cell.ts | 18 +++++++------- .../{withCellHOC.tsx => createCell.tsx} | 24 +++++++++---------- packages/web/src/index.ts | 2 +- 5 files changed, 26 insertions(+), 26 deletions(-) rename packages/web/src/components/{withCellHOC.tsx => createCell.tsx} (85%) diff --git a/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-commented-exports/output.js b/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-commented-exports/output.js index 2b87ebb3411b..f7bb3a6af1e9 100644 --- a/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-commented-exports/output.js +++ b/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-commented-exports/output.js @@ -1,4 +1,4 @@ -import { withCell } from '@redwoodjs/web' +import { createCell } from '@redwoodjs/web' export const QUERY = gql` query { posts { @@ -22,7 +22,7 @@ export function Failure({ error }) { export const Success = ({ posts }) => { return JSON.stringify(posts, null, 2) } -export default withCell({ +export default createCell({ QUERY, afterQuery, Loading, diff --git a/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-required-exports/output.js b/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-required-exports/output.js index 59f1d8a6ecf0..419a792d8a3c 100644 --- a/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-required-exports/output.js +++ b/packages/core/src/babelPlugins/__tests__/__fixtures__/cell/cell-with-required-exports/output.js @@ -1,4 +1,4 @@ -import { withCell } from '@redwoodjs/web' +import { createCell } from '@redwoodjs/web' export const QUERY = gql` query { posts { @@ -22,7 +22,7 @@ export function Failure({ error }) { export const Success = ({ posts }) => { return JSON.stringify(posts, null, 2) } -export default withCell({ +export default createCell({ QUERY, beforeQuery, afterQuery, diff --git a/packages/core/src/babelPlugins/babel-plugin-redwood-cell.ts b/packages/core/src/babelPlugins/babel-plugin-redwood-cell.ts index e8667843e181..2f514666f0f5 100644 --- a/packages/core/src/babelPlugins/babel-plugin-redwood-cell.ts +++ b/packages/core/src/babelPlugins/babel-plugin-redwood-cell.ts @@ -1,12 +1,12 @@ import type { PluginObj, types } from '@babel/core' -// This wraps a file that has a suffix of `Cell` in Redwood's `withCell` higher +// This wraps a file that has a suffix of `Cell` in Redwood's `createCell` higher // order component. The HOC deals with the lifecycle methods during a GraphQL query. // // ```js -// import { withCell } from '@redwoodjs/web' +// import { createCell } from '@redwoodjs/web' // -// export default withCell({ QUERY, Loading, Succes, Failure, Empty, beforeQuery, afterQuery }) +// export default createCell({ QUERY, Loading, Success, Failure, Empty, beforeQuery, afterQuery }) // ``` // A cell can export the declarations below. @@ -23,7 +23,7 @@ const EXPECTED_EXPORTS_FROM_CELL = [ export default function ({ types: t }: { types: typeof types }): PluginObj { // This array will // - collect exports from the Cell file during ExportNamedDeclaration - // - collected exports will then be passed to `withCell` + // - collected exports will then be passed to `createCell` // - be cleared after Program exit to prepare for the next file let exportNames: string[] = [] let hasDefaultExport = false @@ -65,13 +65,13 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { } // Insert at the top of the file: - // + import { withCell } from '@redwoodjs/web' + // + import { createCell } from '@redwoodjs/web' path.node.body.unshift( t.importDeclaration( [ t.importSpecifier( - t.identifier('withCell'), - t.identifier('withCell') + t.identifier('createCell'), + t.identifier('createCell') ), ], t.stringLiteral('@redwoodjs/web') @@ -79,10 +79,10 @@ export default function ({ types: t }: { types: typeof types }): PluginObj { ) // Insert at the bottom of the file: - // + export default withCell({ QUERY?, Loading?, Succes?, Failure?, Empty?, beforeQuery?, afterQuery? }) + // + export default createCell({ QUERY?, Loading?, Succes?, Failure?, Empty?, beforeQuery?, afterQuery? }) path.node.body.push( t.exportDefaultDeclaration( - t.callExpression(t.identifier('withCell'), [ + t.callExpression(t.identifier('createCell'), [ t.objectExpression( exportNames.map((name) => t.objectProperty( diff --git a/packages/web/src/components/withCellHOC.tsx b/packages/web/src/components/createCell.tsx similarity index 85% rename from packages/web/src/components/withCellHOC.tsx rename to packages/web/src/components/createCell.tsx index ca8f3b155656..b206f67d2cea 100644 --- a/packages/web/src/components/withCellHOC.tsx +++ b/packages/web/src/components/createCell.tsx @@ -26,20 +26,20 @@ export type CellSuccessStateComponent = | Omit | DataObject -export interface WithCellProps { +export interface CreateCellProps { beforeQuery?: (props: TProps) => { variables: TProps } QUERY: DocumentNode | ((variables: Record) => DocumentNode) afterQuery?: (data: DataObject) => DataObject - Loading?: React.FC - Failure?: React.FC - Empty?: React.FC - Success: React.FC + Loading?: React.FC> + Failure?: React.FC> + Empty?: React.FC> + Success: React.FC> } /** * Is a higher-order-component that executes a GraphQL query and automatically * manages the lifecycle of that query. If you export named parameters that match - * the required params of `withCell` it will be automatically wrapped in this + * the required params of `createCell` it will be automatically wrapped in this * HOC via a babel-plugin. * * @param {string} QUERY - The graphQL syntax tree to execute @@ -56,10 +56,10 @@ export interface WithCellProps { * // `src/ExampleComponent/index.js`. This file is automatically dealt with * in webpack. * - * import { withCell } from '@redwoodjs/web' + * import { createCell } from '@redwoodjs/web' * import * as cell from './ExampleComponent' * - * export default withCell(cell) + * export default createCell(cell) * ``` * * // USAGE: @@ -89,7 +89,7 @@ const isEmpty = (data: DataObject) => { return isDataNull(data) || isDataEmptyArray(data) } -export const withCell = ({ +export function createCell({ beforeQuery = (props) => ({ variables: props, fetchPolicy: 'cache-and-network', @@ -101,13 +101,13 @@ export const withCell = ({ Failure, Empty, Success, -}: WithCellProps) => { +}: CreateCellProps): React.FC { // If its prerendering, render the Cell's Loading component if (global.__REDWOOD__PRERENDERING) { - return (props: Record) => + return (props) => } - return (props: Record) => { + return (props) => { const { children, // eslint-disable-line @typescript-eslint/no-unused-vars ...variables diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts index 73a16dd92d8a..0ac44800c8f4 100644 --- a/packages/web/src/index.ts +++ b/packages/web/src/index.ts @@ -12,7 +12,7 @@ export { useMutation, } from './components/GraphQLHooksProvider' -export { withCell } from './components/withCellHOC' +export { createCell } from './components/createCell' // TODO: Remove these in v.10, people can import from `@redwoodjs/web/toast` // deprecated From 466d7a53eda735e66d95997598e9ac80d363a837 Mon Sep 17 00:00:00 2001 From: Peter Pistorius Date: Fri, 16 Apr 2021 16:04:20 +0200 Subject: [PATCH 2/3] Add notice about 'withCell' deprecation for 'createCell.' --- packages/web/src/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts index 0ac44800c8f4..8ac3e99a23f3 100644 --- a/packages/web/src/index.ts +++ b/packages/web/src/index.ts @@ -12,7 +12,11 @@ export { useMutation, } from './components/GraphQLHooksProvider' -export { createCell } from './components/createCell' +import { createCell } from './components/createCell' +export { createCell } + +/** @deprecated `withCell` will be removed in v0.31.0, please use `createCell` instead. */ +export const withCell = createCell // TODO: Remove these in v.10, people can import from `@redwoodjs/web/toast` // deprecated From bc9f38903de44c7b4a54ec491a982bfa8598cd83 Mon Sep 17 00:00:00 2001 From: Peter Pistorius Date: Fri, 16 Apr 2021 16:37:13 +0200 Subject: [PATCH 3/3] Update packages/web/src/index.ts Co-authored-by: Daniel Choudhury --- packages/web/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/index.ts b/packages/web/src/index.ts index 8ac3e99a23f3..b882f568067b 100644 --- a/packages/web/src/index.ts +++ b/packages/web/src/index.ts @@ -15,7 +15,7 @@ export { import { createCell } from './components/createCell' export { createCell } -/** @deprecated `withCell` will be removed in v0.31.0, please use `createCell` instead. */ +/** @deprecated `withCell` will be removed in v0.32.0, please use `createCell` instead. */ export const withCell = createCell // TODO: Remove these in v.10, people can import from `@redwoodjs/web/toast`