From 5439516e824be5d76d3c1207014906de5abd7512 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 28 Sep 2020 21:51:59 -0700 Subject: [PATCH 1/8] add generateId option to graphql-mini-transforms --- packages/graphql-mini-transforms/README.md | 25 ++++++++++++- packages/graphql-mini-transforms/package.json | 4 ++- .../graphql-mini-transforms/src/document.ts | 24 ++++++++++--- .../graphql-mini-transforms/src/webpack.ts | 32 +++++++++++++++-- .../tests/webpack.test.ts | 8 +++++ yarn.lock | 36 +++++++++++++++++++ 6 files changed, 119 insertions(+), 10 deletions(-) diff --git a/packages/graphql-mini-transforms/README.md b/packages/graphql-mini-transforms/README.md index 38639d3..889685d 100644 --- a/packages/graphql-mini-transforms/README.md +++ b/packages/graphql-mini-transforms/README.md @@ -61,7 +61,9 @@ fragment ProductVariantId on ProductVariant { #### Options -This loader accepts a single option, `simple`. This option changes the shape of the value exported from `.graphql` files. By default, a `graphql-typed` `DocumentNode` is exported, but when `simple` is set to `true`, a `SimpleDocument` is exported instead. This representation of GraphQL documents is smaller than a full `DocumentNode`, but generally won’t work with normalized GraphQL caches. +##### simple + +This option changes the shape of the value exported from `.graphql` files. By default, a `graphql-typed` `DocumentNode` is exported, but when `simple` is set to `true`, a `SimpleDocument` is exported instead. This representation of GraphQL documents is smaller than a full `DocumentNode`, but generally won’t work with normalized GraphQL caches. ```js module.exports = { @@ -80,6 +82,27 @@ module.exports = { If this option is set to `true`, you should also use the `jest-simple` transformer for Jest, and the `--export-format simple` flag for `graphql-typescript-definitions`. +##### generateId + +This option changes the identifier value used. By default the hash of the minified GraphQL document is used as the identifier value, but when `generateId` is provided +the return value is used as the identifier value. `generateId` should be a function which takes a single parameter, the normalized GraphQL document source as a string, +and it should return a string value. + +```js +module.exports = { + module: { + rules: [ + { + test: /\.(graphql|gql)$/, + use: 'graphql-mini-transforms/webpack', + exclude: /node_modules/, + options: {generateId: normalizedSource => someHash(normalizedSource)}, + }, + ], + }, +}; +``` + ### Jest This package also provides a transformer for GraphQL files in Jest. To use the transformer, add a reference to it in your Jest configuration’s `transform` option: diff --git a/packages/graphql-mini-transforms/package.json b/packages/graphql-mini-transforms/package.json index 391d93e..3197761 100644 --- a/packages/graphql-mini-transforms/package.json +++ b/packages/graphql-mini-transforms/package.json @@ -34,6 +34,7 @@ "devDependencies": { "@types/common-tags": "^1.8.0", "@types/loader-utils": "^1.1.3", + "@types/schema-utils": "^2.4.0", "common-tags": "^1.8.0" }, "dependencies": { @@ -43,6 +44,7 @@ "fs-extra": "^9.0.0", "graphql": ">=14.5.0 <15.0.0", "graphql-typed": "^0.6.1", - "loader-utils": "^2.0.0" + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.1" } } diff --git a/packages/graphql-mini-transforms/src/document.ts b/packages/graphql-mini-transforms/src/document.ts index 3c15480..7fda0c2 100644 --- a/packages/graphql-mini-transforms/src/document.ts +++ b/packages/graphql-mini-transforms/src/document.ts @@ -16,9 +16,26 @@ import {DocumentNode, SimpleDocument} from 'graphql-typed'; const IMPORT_REGEX = /^#import\s+['"]([^'"]*)['"];?[\s\n]*/gm; const DEFAULT_NAME = 'Operation'; +function defaultGenerateId(normalizedSource: string) { + // This ID is a hash of the full file contents that are part of the document, + // including other documents that are injected in, but excluding any unused + // fragments. This is useful for things like persisted queries. + return createHash('sha256') + .update(minifySource(normalizedSource)) + .digest('hex'); +} + +export interface CleanDocumentOptions { + removeUnused?: boolean; + generateId?: (normalizedSource: string) => string; +} + export function cleanDocument( document: UntypedDocumentNode, - {removeUnused = true} = {}, + { + removeUnused = true, + generateId = defaultGenerateId, + }: CleanDocumentOptions = {}, ): DocumentNode { if (removeUnused) { removeUnusedDefinitions(document); @@ -35,10 +52,7 @@ export function cleanDocument( stripLoc(definition); } - // This ID is a hash of the full file contents that are part of the document, - // including other documents that are injected in, but excluding any unused - // fragments. This is useful for things like persisted queries. - const id = createHash('sha256').update(normalizedSource).digest('hex'); + const id = generateId(print(document)); Reflect.defineProperty(normalizedDocument, 'id', { value: id, diff --git a/packages/graphql-mini-transforms/src/webpack.ts b/packages/graphql-mini-transforms/src/webpack.ts index 2bdbc90..708a899 100644 --- a/packages/graphql-mini-transforms/src/webpack.ts +++ b/packages/graphql-mini-transforms/src/webpack.ts @@ -3,13 +3,32 @@ import {dirname} from 'path'; import {loader} from 'webpack'; import {parse, DocumentNode} from 'graphql'; import {getOptions} from 'loader-utils'; +import validateOptions from 'schema-utils'; -import {cleanDocument, extractImports, toSimpleDocument} from './document'; +import { + cleanDocument, + extractImports, + toSimpleDocument, + CleanDocumentOptions, +} from './document'; interface Options { + generateId?: (normalizedSource: string) => string; simple?: boolean; } +const schema = { + type: 'object' as const, + properties: { + simple: { + type: 'boolean' as const, + }, + generateId: { + instanceof: 'Function' as const, + }, + }, +}; + export default async function graphQLLoader( this: loader.LoaderContext, source: string | Buffer, @@ -17,7 +36,9 @@ export default async function graphQLLoader( this.cacheable(); const done = this.async(); - const {simple = false} = getOptions(this) as Options; + const options = {simple: false, ...getOptions(this)} as Options; + + validateOptions(schema, options, {name: '@shopify/graphql-mini-transforms'}); if (done == null) { throw new Error( @@ -25,11 +46,16 @@ export default async function graphQLLoader( ); } + const cleanDocumentOptions = { + generateId: options.generateId, + } as CleanDocumentOptions; + try { const document = cleanDocument( await loadDocument(source, this.context, this), + cleanDocumentOptions, ); - const exported = simple ? toSimpleDocument(document) : document; + const exported = options.simple ? toSimpleDocument(document) : document; done( null, diff --git a/packages/graphql-mini-transforms/tests/webpack.test.ts b/packages/graphql-mini-transforms/tests/webpack.test.ts index 16a9a10..a5bc08e 100644 --- a/packages/graphql-mini-transforms/tests/webpack.test.ts +++ b/packages/graphql-mini-transforms/tests/webpack.test.ts @@ -70,6 +70,14 @@ describe('graphql-mini-transforms/webpack', () => { ); }); + it('has option for custom ID generate function', async () => { + const result = await extractDocumentExport( + `query Shop { shop { id } }`, + createLoaderContext({query: {generateId: () => 'foo'}}), + ); + expect(result).toHaveProperty('id', 'foo'); + }); + describe('import', () => { it('adds the resolved import as a dependency', async () => { const context = '/app/'; diff --git a/yarn.lock b/yarn.lock index 8b5ae21..100c3a3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -720,6 +720,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/json-schema@^7.0.5": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + "@types/loader-utils@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-1.1.3.tgz#82b9163f2ead596c68a8c03e450fbd6e089df401" @@ -751,6 +756,13 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== +"@types/schema-utils@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/schema-utils/-/schema-utils-2.4.0.tgz#9983012045d541dcee053e685a27c9c87c840fcd" + integrity sha512-454hrj5gz/FXcUE20ygfEiN4DxZ1sprUo0V1gqIqkNZ/CzoEzAZEll2uxMsuyz6BYjiQan4Aa65xbTemfzW9hQ== + dependencies: + schema-utils "*" + "@types/source-list-map@*": version "0.1.2" resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" @@ -909,6 +921,11 @@ add-stream@^1.0.0: resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo= +ajv-keywords@^3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" + integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== + ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.12.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" @@ -919,6 +936,16 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ajv@^6.12.4: + version "6.12.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" + integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-escapes@^3.0.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -5884,6 +5911,15 @@ saxes@^3.1.9: dependencies: xmlchars "^2.1.1" +schema-utils@*, schema-utils@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" + integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== + dependencies: + "@types/json-schema" "^7.0.5" + ajv "^6.12.4" + ajv-keywords "^3.5.2" + "semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.4.1, semver@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" From 7f424078b55900e8e9b10314a6e2ce5549fa7f30 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 14 Dec 2020 14:49:08 -0800 Subject: [PATCH 2/8] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alexandre Côté --- packages/graphql-mini-transforms/src/webpack.ts | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/graphql-mini-transforms/src/webpack.ts b/packages/graphql-mini-transforms/src/webpack.ts index 708a899..6b4cec0 100644 --- a/packages/graphql-mini-transforms/src/webpack.ts +++ b/packages/graphql-mini-transforms/src/webpack.ts @@ -5,12 +5,7 @@ import {parse, DocumentNode} from 'graphql'; import {getOptions} from 'loader-utils'; import validateOptions from 'schema-utils'; -import { - cleanDocument, - extractImports, - toSimpleDocument, - CleanDocumentOptions, -} from './document'; +import {cleanDocument, extractImports, toSimpleDocument} from './document'; interface Options { generateId?: (normalizedSource: string) => string; @@ -36,7 +31,7 @@ export default async function graphQLLoader( this.cacheable(); const done = this.async(); - const options = {simple: false, ...getOptions(this)} as Options; + const options: Options = {simple: false, ...getOptions(this)}; validateOptions(schema, options, {name: '@shopify/graphql-mini-transforms'}); @@ -46,14 +41,10 @@ export default async function graphQLLoader( ); } - const cleanDocumentOptions = { - generateId: options.generateId, - } as CleanDocumentOptions; - try { const document = cleanDocument( await loadDocument(source, this.context, this), - cleanDocumentOptions, + {generateId: options.generateId}, ); const exported = options.simple ? toSimpleDocument(document) : document; From d50b4daaea300a2dcb88de7f2de35a183add4efc Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 14 Dec 2020 15:06:16 -0800 Subject: [PATCH 3/8] Apply code review suggestion --- packages/graphql-mini-transforms/src/document.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/graphql-mini-transforms/src/document.ts b/packages/graphql-mini-transforms/src/document.ts index 7fda0c2..c1bf2c8 100644 --- a/packages/graphql-mini-transforms/src/document.ts +++ b/packages/graphql-mini-transforms/src/document.ts @@ -45,14 +45,15 @@ export function cleanDocument( addTypename(definition); } - const normalizedSource = minifySource(print(document)); + const documentSource = print(document); + const normalizedSource = minifySource(documentSource); const normalizedDocument = parse(normalizedSource); for (const definition of normalizedDocument.definitions) { stripLoc(definition); } - const id = generateId(print(document)); + const id = generateId(documentSource); Reflect.defineProperty(normalizedDocument, 'id', { value: id, From fad6a450ae6ef2eed98a80389324517d032e718b Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 14 Dec 2020 15:13:17 -0800 Subject: [PATCH 4/8] Only minify source once when generating ID --- .../graphql-mini-transforms/src/document.ts | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/graphql-mini-transforms/src/document.ts b/packages/graphql-mini-transforms/src/document.ts index c1bf2c8..3d4ca1d 100644 --- a/packages/graphql-mini-transforms/src/document.ts +++ b/packages/graphql-mini-transforms/src/document.ts @@ -16,15 +16,6 @@ import {DocumentNode, SimpleDocument} from 'graphql-typed'; const IMPORT_REGEX = /^#import\s+['"]([^'"]*)['"];?[\s\n]*/gm; const DEFAULT_NAME = 'Operation'; -function defaultGenerateId(normalizedSource: string) { - // This ID is a hash of the full file contents that are part of the document, - // including other documents that are injected in, but excluding any unused - // fragments. This is useful for things like persisted queries. - return createHash('sha256') - .update(minifySource(normalizedSource)) - .digest('hex'); -} - export interface CleanDocumentOptions { removeUnused?: boolean; generateId?: (normalizedSource: string) => string; @@ -32,10 +23,7 @@ export interface CleanDocumentOptions { export function cleanDocument( document: UntypedDocumentNode, - { - removeUnused = true, - generateId = defaultGenerateId, - }: CleanDocumentOptions = {}, + {removeUnused = true, generateId}: CleanDocumentOptions = {}, ): DocumentNode { if (removeUnused) { removeUnusedDefinitions(document); @@ -53,7 +41,18 @@ export function cleanDocument( stripLoc(definition); } - const id = generateId(documentSource); + let id: string; + + if (generateId === undefined) { + // This ID is a hash of the full file contents that are part of the document, + // including other documents that are injected in, but excluding any unused + // fragments. This is useful for things like persisted queries. + id = createHash('sha256') + .update(minifySource(normalizedSource)) + .digest('hex'); + } else { + id = generateId(documentSource); + } Reflect.defineProperty(normalizedDocument, 'id', { value: id, From f6d9023055fdce490ed71c0e96448368ebebbde8 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 14 Dec 2020 15:34:23 -0800 Subject: [PATCH 5/8] Apply code review change --- .../graphql-mini-transforms/src/document.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/graphql-mini-transforms/src/document.ts b/packages/graphql-mini-transforms/src/document.ts index 3d4ca1d..76783cb 100644 --- a/packages/graphql-mini-transforms/src/document.ts +++ b/packages/graphql-mini-transforms/src/document.ts @@ -16,6 +16,13 @@ import {DocumentNode, SimpleDocument} from 'graphql-typed'; const IMPORT_REGEX = /^#import\s+['"]([^'"]*)['"];?[\s\n]*/gm; const DEFAULT_NAME = 'Operation'; +function defaultGenerateId(normalizedSource: string) { + // This ID is a hash of the full file contents that are part of the document, + // including other documents that are injected in, but excluding any unused + // fragments. This is useful for things like persisted queries. + return createHash('sha256').update(normalizedSource).digest('hex'); +} + export interface CleanDocumentOptions { removeUnused?: boolean; generateId?: (normalizedSource: string) => string; @@ -41,18 +48,10 @@ export function cleanDocument( stripLoc(definition); } - let id: string; - - if (generateId === undefined) { - // This ID is a hash of the full file contents that are part of the document, - // including other documents that are injected in, but excluding any unused - // fragments. This is useful for things like persisted queries. - id = createHash('sha256') - .update(minifySource(normalizedSource)) - .digest('hex'); - } else { - id = generateId(documentSource); - } + const id = + generateId === undefined + ? defaultGenerateId(normalizedSource) + : generateId(documentSource); Reflect.defineProperty(normalizedDocument, 'id', { value: id, From c8c54ff6bf00aed4425ac9267601f15dbaf6b6af Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 6 Jan 2021 01:20:46 -0800 Subject: [PATCH 6/8] address code review comments --- packages/graphql-mini-transforms/README.md | 8 +++----- .../tests/webpack.test.ts | 20 +++++++++++++++++-- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/packages/graphql-mini-transforms/README.md b/packages/graphql-mini-transforms/README.md index 889685d..6866b0e 100644 --- a/packages/graphql-mini-transforms/README.md +++ b/packages/graphql-mini-transforms/README.md @@ -61,7 +61,7 @@ fragment ProductVariantId on ProductVariant { #### Options -##### simple +##### `simple` This option changes the shape of the value exported from `.graphql` files. By default, a `graphql-typed` `DocumentNode` is exported, but when `simple` is set to `true`, a `SimpleDocument` is exported instead. This representation of GraphQL documents is smaller than a full `DocumentNode`, but generally won’t work with normalized GraphQL caches. @@ -82,11 +82,9 @@ module.exports = { If this option is set to `true`, you should also use the `jest-simple` transformer for Jest, and the `--export-format simple` flag for `graphql-typescript-definitions`. -##### generateId +##### `generateId` -This option changes the identifier value used. By default the hash of the minified GraphQL document is used as the identifier value, but when `generateId` is provided -the return value is used as the identifier value. `generateId` should be a function which takes a single parameter, the normalized GraphQL document source as a string, -and it should return a string value. +This option changes the identifier value used. By default the hash of the minified GraphQL document is used as the identifier value, but when `generateId` is provided the return value is used as the identifier value. `generateId` should be a function which takes a single parameter, the normalized GraphQL document source as a string, and it should return a string value. ```js module.exports = { diff --git a/packages/graphql-mini-transforms/tests/webpack.test.ts b/packages/graphql-mini-transforms/tests/webpack.test.ts index a5bc08e..11295a2 100644 --- a/packages/graphql-mini-transforms/tests/webpack.test.ts +++ b/packages/graphql-mini-transforms/tests/webpack.test.ts @@ -70,10 +70,26 @@ describe('graphql-mini-transforms/webpack', () => { ); }); - it('has option for custom ID generate function', async () => { + it('uses the generateId option for the document ID when provided', async () => { + // Mock function can't be called directly due to API schema validation, see + // https://github.com/facebook/jest/issues/6329 + const _generateId = jest.fn((_) => 'foo'); + const generateId = (src: string) => _generateId(src); const result = await extractDocumentExport( `query Shop { shop { id } }`, - createLoaderContext({query: {generateId: () => 'foo'}}), + createLoaderContext({query: {generateId}}), + ); + expect(_generateId).toHaveBeenCalledWith( + expect.toStartWith( + stripIndent` + query Shop { + shop { + id + __typename + } + } + `, + ), ); expect(result).toHaveProperty('id', 'foo'); }); From 13b8012b1b91f340be0491cf5c541dc275d3e349 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 6 Jan 2021 01:31:14 -0800 Subject: [PATCH 7/8] change generateId argument --- packages/graphql-mini-transforms/README.md | 4 ++-- .../graphql-mini-transforms/src/document.ts | 14 +++++++---- .../graphql-mini-transforms/src/webpack.ts | 9 ++++++-- .../tests/webpack.test.ts | 23 +++++++++++-------- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/packages/graphql-mini-transforms/README.md b/packages/graphql-mini-transforms/README.md index 6866b0e..84fa23c 100644 --- a/packages/graphql-mini-transforms/README.md +++ b/packages/graphql-mini-transforms/README.md @@ -84,7 +84,7 @@ If this option is set to `true`, you should also use the `jest-simple` transform ##### `generateId` -This option changes the identifier value used. By default the hash of the minified GraphQL document is used as the identifier value, but when `generateId` is provided the return value is used as the identifier value. `generateId` should be a function which takes a single parameter, the normalized GraphQL document source as a string, and it should return a string value. +This option changes the identifier value used. By default the hash of the minified GraphQL document is used as the identifier value, but when `generateId` is provided the return value is used as the identifier value. `generateId` should be a function which takes a single parameter, an object with the normalized GraphQL document source as a string under the `source` key, and it should return a string value. ```js module.exports = { @@ -94,7 +94,7 @@ module.exports = { test: /\.(graphql|gql)$/, use: 'graphql-mini-transforms/webpack', exclude: /node_modules/, - options: {generateId: normalizedSource => someHash(normalizedSource)}, + options: {generateId: ({source}) => someHash(source)}, }, ], }, diff --git a/packages/graphql-mini-transforms/src/document.ts b/packages/graphql-mini-transforms/src/document.ts index 76783cb..2d110ec 100644 --- a/packages/graphql-mini-transforms/src/document.ts +++ b/packages/graphql-mini-transforms/src/document.ts @@ -16,16 +16,20 @@ import {DocumentNode, SimpleDocument} from 'graphql-typed'; const IMPORT_REGEX = /^#import\s+['"]([^'"]*)['"];?[\s\n]*/gm; const DEFAULT_NAME = 'Operation'; -function defaultGenerateId(normalizedSource: string) { +export interface GenerateIdArguments { + source: string; +} + +function defaultGenerateId({source}: GenerateIdArguments) { // This ID is a hash of the full file contents that are part of the document, // including other documents that are injected in, but excluding any unused // fragments. This is useful for things like persisted queries. - return createHash('sha256').update(normalizedSource).digest('hex'); + return createHash('sha256').update(source).digest('hex'); } export interface CleanDocumentOptions { removeUnused?: boolean; - generateId?: (normalizedSource: string) => string; + generateId?: (args: GenerateIdArguments) => string; } export function cleanDocument( @@ -50,8 +54,8 @@ export function cleanDocument( const id = generateId === undefined - ? defaultGenerateId(normalizedSource) - : generateId(documentSource); + ? defaultGenerateId({source: normalizedSource}) + : generateId({source: documentSource}); Reflect.defineProperty(normalizedDocument, 'id', { value: id, diff --git a/packages/graphql-mini-transforms/src/webpack.ts b/packages/graphql-mini-transforms/src/webpack.ts index 6b4cec0..11e2cea 100644 --- a/packages/graphql-mini-transforms/src/webpack.ts +++ b/packages/graphql-mini-transforms/src/webpack.ts @@ -5,10 +5,15 @@ import {parse, DocumentNode} from 'graphql'; import {getOptions} from 'loader-utils'; import validateOptions from 'schema-utils'; -import {cleanDocument, extractImports, toSimpleDocument} from './document'; +import { + cleanDocument, + extractImports, + toSimpleDocument, + GenerateIdArguments, +} from './document'; interface Options { - generateId?: (normalizedSource: string) => string; + generateId?: (args: GenerateIdArguments) => string; simple?: boolean; } diff --git a/packages/graphql-mini-transforms/tests/webpack.test.ts b/packages/graphql-mini-transforms/tests/webpack.test.ts index 11295a2..e52959b 100644 --- a/packages/graphql-mini-transforms/tests/webpack.test.ts +++ b/packages/graphql-mini-transforms/tests/webpack.test.ts @@ -4,6 +4,7 @@ import {createHash} from 'crypto'; import {loader} from 'webpack'; import {stripIndent} from 'common-tags'; +import {GenerateIdArguments} from '../src/document'; import graphQLLoader from '../src/webpack'; describe('graphql-mini-transforms/webpack', () => { @@ -74,22 +75,24 @@ describe('graphql-mini-transforms/webpack', () => { // Mock function can't be called directly due to API schema validation, see // https://github.com/facebook/jest/issues/6329 const _generateId = jest.fn((_) => 'foo'); - const generateId = (src: string) => _generateId(src); + const generateId = (args: GenerateIdArguments) => _generateId(args); const result = await extractDocumentExport( `query Shop { shop { id } }`, createLoaderContext({query: {generateId}}), ); expect(_generateId).toHaveBeenCalledWith( - expect.toStartWith( - stripIndent` - query Shop { - shop { - id - __typename + expect.objectContaining({ + source: expect.toStartWith( + stripIndent` + query Shop { + shop { + id + __typename + } } - } - `, - ), + `, + ), + }) ); expect(result).toHaveProperty('id', 'foo'); }); From d09934617985f91e2bacb7be7f450c67d5a431e5 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Wed, 6 Jan 2021 01:35:49 -0800 Subject: [PATCH 8/8] fix linter error --- packages/graphql-mini-transforms/tests/webpack.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/graphql-mini-transforms/tests/webpack.test.ts b/packages/graphql-mini-transforms/tests/webpack.test.ts index e52959b..9062ed3 100644 --- a/packages/graphql-mini-transforms/tests/webpack.test.ts +++ b/packages/graphql-mini-transforms/tests/webpack.test.ts @@ -92,7 +92,7 @@ describe('graphql-mini-transforms/webpack', () => { } `, ), - }) + }), ); expect(result).toHaveProperty('id', 'foo'); });