From 5c734b21baa2a1ef605e650276eea24ee724e031 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:19:46 +0200 Subject: [PATCH 1/8] Add docs --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index ca10e84..2108bc7 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,20 @@ That's it! Now you're free to use all values and type supported by SuperJSON in +### Options + +You can use the `exclude` option to exclude specific properties from serialisation. + +```json5 +{ + presets: ['next/babel'], + plugins: [ + ... + ['superjson-next', { exclude: ["someProp"] }] + ] +} +``` + ## Contributing 1. Clone the repo From 4414622e69915db2199827c80e187156b088df1b Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:22:33 +0200 Subject: [PATCH 2/8] Pass exclude option to withSuperJSONProps --- src/index.ts | 9 +++++++++ src/tools.tsx | 3 ++- test/pages/class component/output.js | 2 +- .../output.js | 13 ++++++++----- test/pages/gSP arrow function/output.js | 2 +- test/pages/gSP function declaration/output.js | 3 ++- test/pages/gSSP function declaration/output.js | 3 ++- test/pages/separate export declaration/output.js | 2 +- test/pages/transforms a valid example/output.js | 2 +- test/plugin.test.ts | 3 +++ 10 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/index.ts b/src/index.ts index 12befa0..ce0fdb3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,6 +17,8 @@ import { isVariableDeclaration, variableDeclaration, variableDeclarator, + arrayExpression, + stringLiteral, } from '@babel/types'; import * as nodePath from 'path'; @@ -170,6 +172,10 @@ function superJsonWithNext(): PluginObj { name: 'add superjson to pages with prop getters', visitor: { Program(path, state) { + const propsToBeExcluded = (state.opts as any).exclude as + | string[] + | undefined; + const filePath = getFileName(state) ?? nodePath.join('pages', 'Default.js'); @@ -187,6 +193,9 @@ function superJsonWithNext(): PluginObj { (decl) => { return callExpression(addWithSuperJSONPropsImport(path), [ decl, + arrayExpression( + propsToBeExcluded?.map((prop) => stringLiteral(prop)) + ), ]); } ); diff --git a/src/tools.tsx b/src/tools.tsx index d7ad85f..e798c6a 100644 --- a/src/tools.tsx +++ b/src/tools.tsx @@ -8,7 +8,8 @@ type SuperJSONProps

= P & { }; export function withSuperJSONProps

( - gssp: GetServerSideProps

+ gssp: GetServerSideProps

, + exclude: string[] = [] ): GetServerSideProps> { return async function withSuperJSON(...args) { const result = await gssp(...args); diff --git a/test/pages/class component/output.js b/test/pages/class component/output.js index e507fb3..5f2209d 100644 --- a/test/pages/class component/output.js +++ b/test/pages/class component/output.js @@ -12,7 +12,7 @@ export const getServerSideProps = _withSuperJSONProps(async () => { products, }, }; -}); +}, ['smth']); class Page { render({ products }) { diff --git a/test/pages/gSP arrow function with implicit return/output.js b/test/pages/gSP arrow function with implicit return/output.js index ea56167..e9658c4 100644 --- a/test/pages/gSP arrow function with implicit return/output.js +++ b/test/pages/gSP arrow function with implicit return/output.js @@ -1,10 +1,13 @@ import { withSuperJSONPage as _withSuperJSONPage } from 'babel-plugin-superjson-next/tools'; import { withSuperJSONProps as _withSuperJSONProps } from 'babel-plugin-superjson-next/tools'; -export const getStaticProps = _withSuperJSONProps(() => ({ - props: { - today: new Date(), - }, -})); +export const getStaticProps = _withSuperJSONProps( + () => ({ + props: { + today: new Date(), + }, + }), + ['smth'] +); function IndexPage({ today }) { return JSON.stringify({ diff --git a/test/pages/gSP arrow function/output.js b/test/pages/gSP arrow function/output.js index 9055457..84fb0d2 100644 --- a/test/pages/gSP arrow function/output.js +++ b/test/pages/gSP arrow function/output.js @@ -12,7 +12,7 @@ export const getStaticProps = _withSuperJSONProps(async () => { products, }, }; -}); +}, ['smth']); function Page({ products }) { return JSON.stringify(products); diff --git a/test/pages/gSP function declaration/output.js b/test/pages/gSP function declaration/output.js index 6ec565b..2f966c6 100644 --- a/test/pages/gSP function declaration/output.js +++ b/test/pages/gSP function declaration/output.js @@ -13,7 +13,8 @@ export const getStaticProps = _withSuperJSONProps( products, }, }; - } + }, + ['smth'] ); function Page({ products }) { diff --git a/test/pages/gSSP function declaration/output.js b/test/pages/gSSP function declaration/output.js index 7c908a2..13e2c0d 100644 --- a/test/pages/gSSP function declaration/output.js +++ b/test/pages/gSSP function declaration/output.js @@ -13,7 +13,8 @@ export const getServerSideProps = _withSuperJSONProps( products, }, }; - } + }, + ['smth'] ); function Page({ products }) { diff --git a/test/pages/separate export declaration/output.js b/test/pages/separate export declaration/output.js index 2527544..0960291 100644 --- a/test/pages/separate export declaration/output.js +++ b/test/pages/separate export declaration/output.js @@ -12,7 +12,7 @@ export const getServerSideProps = _withSuperJSONProps(async () => { products, }, }; -}); +}, ['smth']); function Page({ products }) { return JSON.stringify(products); diff --git a/test/pages/transforms a valid example/output.js b/test/pages/transforms a valid example/output.js index 2527544..0960291 100644 --- a/test/pages/transforms a valid example/output.js +++ b/test/pages/transforms a valid example/output.js @@ -12,7 +12,7 @@ export const getServerSideProps = _withSuperJSONProps(async () => { products, }, }; -}); +}, ['smth']); function Page({ products }) { return JSON.stringify(products); diff --git a/test/plugin.test.ts b/test/plugin.test.ts index eba20fb..cbcc123 100644 --- a/test/plugin.test.ts +++ b/test/plugin.test.ts @@ -4,5 +4,8 @@ import * as path from 'path'; pluginTester({ plugin: superJsonWithNext, + pluginOptions: { + exclude: ['smth'], + }, fixtures: path.join(__dirname, 'pages'), }); From ceb21e975fc8bb5f8660182639a072b1c4716c82 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:30:26 +0200 Subject: [PATCH 3/8] respect "exclude" --- src/tools.tsx | 10 +++++++ test/tools.test.tsx | 69 +++++++++++++++++++++++++++++++-------------- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/tools.tsx b/src/tools.tsx index e798c6a..d02e2ce 100644 --- a/src/tools.tsx +++ b/src/tools.tsx @@ -22,6 +22,12 @@ export function withSuperJSONProps

( return result; } + const excludedPropValues = exclude.map((propKey) => { + const value = (result.props as any)[propKey]; + delete (result.props as any)[propKey]; + return value; + }); + const { json, meta } = SuperJSON.serialize(result.props); const props = json as any; @@ -29,6 +35,10 @@ export function withSuperJSONProps

( props._superjson = meta; } + exclude.forEach((key, index) => { + props[key] = excludedPropValues[index]; + }); + return { ...result, props, diff --git a/test/tools.test.tsx b/test/tools.test.tsx index 5075df9..a7f0730 100644 --- a/test/tools.test.tsx +++ b/test/tools.test.tsx @@ -1,28 +1,55 @@ -import { withSuperJSONPage } from "../src/tools" -import { render } from "@testing-library/react-native" -import * as React from "react" +import { withSuperJSONPage, withSuperJSONProps } from '../src/tools'; +import { render } from '@testing-library/react-native'; +import * as React from 'react'; -describe("tools", () => { - describe("a component wrapped withSuperJSONPage", () => { - describe("when used from a test", () => { - it("works", () => { +describe('tools', () => { + describe('a component wrapped withSuperJSONPage', () => { + describe('when used from a test', () => { + it('works', () => { function Greeter(props: { name: string }) { - return ( -

- Greetings, {props.name}! -

- ) + return

Greetings, {props.name}!

; } - const WrappedGreeter = withSuperJSONPage(Greeter) + const WrappedGreeter = withSuperJSONPage(Greeter); - const GreeterFromTest = WrappedGreeter as any as typeof Greeter + const GreeterFromTest = (WrappedGreeter as any) as typeof Greeter; - const result = render() + const result = render(); expect(result.toJSON().children).toEqual([ - "Greetings, ", "Earthling", "!" - ]) - }) - }) - }) -}) \ No newline at end of file + 'Greetings, ', + 'Earthling', + '!', + ]); + }); + }); + }); + + describe('withSuperJSONProps', () => { + it('respects `exclude`', async () => { + const aDate = new Date(); + const bDate = new Date(); + async function gSSP() { + return { + props: { + a: aDate, + b: bDate, + }, + }; + } + const wrappedGssp = withSuperJSONProps(gSSP, ['a']); + + const result = await wrappedGssp(null); + expect(result).toEqual({ + props: { + a: aDate, + b: bDate.toISOString(), + _superjson: { + values: { + b: ['Date'], + }, + }, + }, + }); + }); + }); +}); From 16a5047c2b78b540060e2e5454ca14599b32b3fa Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:33:08 +0200 Subject: [PATCH 4/8] fix types --- test/tools.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/tools.test.tsx b/test/tools.test.tsx index a7f0730..2cf4fd9 100644 --- a/test/tools.test.tsx +++ b/test/tools.test.tsx @@ -38,7 +38,7 @@ describe('tools', () => { } const wrappedGssp = withSuperJSONProps(gSSP, ['a']); - const result = await wrappedGssp(null); + const result = await wrappedGssp(null as any); expect(result).toEqual({ props: { a: aDate, From 40634ebcfd932c845e91e33cbf0e64192258bb28 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:38:22 +0200 Subject: [PATCH 5/8] Add integration test --- example/.babelrc | 13 ++++++++++--- example/pages/excluded-props.tsx | 21 +++++++++++++++++++++ example/tests/excluded-props.ts | 10 ++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 example/pages/excluded-props.tsx create mode 100644 example/tests/excluded-props.ts diff --git a/example/.babelrc b/example/.babelrc index 28793a5..635aedc 100644 --- a/example/.babelrc +++ b/example/.babelrc @@ -1,4 +1,11 @@ { - "presets": ["next/babel"], - "plugins": ["superjson-next"] -} \ No newline at end of file + "presets": ["next/babel"], + "plugins": [ + [ + "superjson-next", + { + "exclude": ["superJsonSkipped"] + } + ] + ] +} diff --git a/example/pages/excluded-props.tsx b/example/pages/excluded-props.tsx new file mode 100644 index 0000000..7f70bfc --- /dev/null +++ b/example/pages/excluded-props.tsx @@ -0,0 +1,21 @@ +import type { InferGetStaticPropsType } from 'next'; + +export async function getStaticProps() { + return { + props: { + superJsonSkipped: new Date(0).toISOString(), + date: new Date(0) + }, + }; +} + +const Page = (props: InferGetStaticPropsType) => { + return ( + 'props.superJsonSkipped is string: ' + + (typeof props.superJsonSkipped === 'string') + ); +}; + +Page.getLayout = (page) => <>This is part of the static method {page}; + +export default Page; diff --git a/example/tests/excluded-props.ts b/example/tests/excluded-props.ts new file mode 100644 index 0000000..da46623 --- /dev/null +++ b/example/tests/excluded-props.ts @@ -0,0 +1,10 @@ +import { Selector } from 'testcafe'; + +fixture`With Static Methods`.page`http://localhost:3099/excluded-props`; + +test('Static methods are preserved', async (t) => { + const result = Selector('#__next'); + await t + .expect(result.innerText) + .eql('props.superJsonSkipped is string: true'); +}); From bed5fb18b8a3fa254821c22b9891cae3b3c04baf Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:43:26 +0200 Subject: [PATCH 6/8] don't assign undefined onto props --- src/tools.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools.tsx b/src/tools.tsx index d02e2ce..e3f3fa0 100644 --- a/src/tools.tsx +++ b/src/tools.tsx @@ -36,7 +36,10 @@ export function withSuperJSONProps

( } exclude.forEach((key, index) => { - props[key] = excludedPropValues[index]; + const excludedPropValue = excludedPropValues[index]; + if (typeof excludedPropValue !== 'undefined') { + props[key] = excludedPropValue; + } }); return { From 25d815624ff0b8cc0c6b8bcece03e5f1415d2521 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:50:04 +0200 Subject: [PATCH 7/8] fix fixture name --- example/tests/excluded-props.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/tests/excluded-props.ts b/example/tests/excluded-props.ts index da46623..d58e696 100644 --- a/example/tests/excluded-props.ts +++ b/example/tests/excluded-props.ts @@ -1,8 +1,8 @@ import { Selector } from 'testcafe'; -fixture`With Static Methods`.page`http://localhost:3099/excluded-props`; +fixture`Excluded Props`.page`http://localhost:3099/excluded-props`; -test('Static methods are preserved', async (t) => { +test('works', async (t) => { const result = Selector('#__next'); await t .expect(result.innerText) From cd91c28c16fa9e0be10ad5cb28890ada86e7b2c9 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Sat, 1 May 2021 14:55:15 +0200 Subject: [PATCH 8/8] remove layout --- example/pages/excluded-props.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/example/pages/excluded-props.tsx b/example/pages/excluded-props.tsx index 7f70bfc..a6fef90 100644 --- a/example/pages/excluded-props.tsx +++ b/example/pages/excluded-props.tsx @@ -16,6 +16,4 @@ const Page = (props: InferGetStaticPropsType) => { ); }; -Page.getLayout = (page) => <>This is part of the static method {page}; - export default Page;