Skip to content
This repository was archived by the owner on Jun 29, 2021. It is now read-only.

Commit 4683827

Browse files
committed
add generateId option to graphql-mini-transforms
1 parent f5e2207 commit 4683827

File tree

6 files changed

+119
-10
lines changed

6 files changed

+119
-10
lines changed

packages/graphql-mini-transforms/README.md

+24-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,9 @@ fragment ProductVariantId on ProductVariant {
6161

6262
#### Options
6363

64-
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.
64+
##### simple
65+
66+
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.
6567

6668
```js
6769
module.exports = {
@@ -80,6 +82,27 @@ module.exports = {
8082

8183
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`.
8284

85+
##### generateId
86+
87+
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
88+
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,
89+
and it should return a string value.
90+
91+
```js
92+
module.exports = {
93+
module: {
94+
rules: [
95+
{
96+
test: /\.(graphql|gql)$/,
97+
use: 'graphql-mini-transforms/webpack',
98+
exclude: /node_modules/,
99+
options: {generateId: normalizedSource => someHash(normalizedSource)},
100+
},
101+
],
102+
},
103+
};
104+
```
105+
83106
### Jest
84107

85108
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:

packages/graphql-mini-transforms/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"devDependencies": {
3535
"@types/common-tags": "^1.8.0",
3636
"@types/loader-utils": "^1.1.3",
37+
"@types/schema-utils": "^2.4.0",
3738
"common-tags": "^1.8.0"
3839
},
3940
"dependencies": {
@@ -43,6 +44,7 @@
4344
"fs-extra": "^9.0.0",
4445
"graphql": ">=14.5.0 <15.0.0",
4546
"graphql-typed": "^0.6.0",
46-
"loader-utils": "^2.0.0"
47+
"loader-utils": "^2.0.0",
48+
"schema-utils": "^2.7.1"
4749
}
4850
}

packages/graphql-mini-transforms/src/document.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,26 @@ import {DocumentNode, SimpleDocument} from 'graphql-typed';
1616
const IMPORT_REGEX = /^#import\s+['"]([^'"]*)['"];?[\s\n]*/gm;
1717
const DEFAULT_NAME = 'Operation';
1818

19+
function defaultGenerateId(normalizedSource: string) {
20+
// This ID is a hash of the full file contents that are part of the document,
21+
// including other documents that are injected in, but excluding any unused
22+
// fragments. This is useful for things like persisted queries.
23+
return createHash('sha256')
24+
.update(minifySource(normalizedSource))
25+
.digest('hex');
26+
}
27+
28+
export interface CleanDocumentOptions {
29+
removeUnused?: boolean;
30+
generateId?: (normalizedSource: string) => string;
31+
}
32+
1933
export function cleanDocument(
2034
document: UntypedDocumentNode,
21-
{removeUnused = true} = {},
35+
{
36+
removeUnused = true,
37+
generateId = defaultGenerateId,
38+
}: CleanDocumentOptions = {},
2239
): DocumentNode<any, any, any> {
2340
if (removeUnused) {
2441
removeUnusedDefinitions(document);
@@ -35,10 +52,7 @@ export function cleanDocument(
3552
stripLoc(definition);
3653
}
3754

38-
// This ID is a hash of the full file contents that are part of the document,
39-
// including other documents that are injected in, but excluding any unused
40-
// fragments. This is useful for things like persisted queries.
41-
const id = createHash('sha256').update(normalizedSource).digest('hex');
55+
const id = generateId(print(document));
4256

4357
Reflect.defineProperty(normalizedDocument, 'id', {
4458
value: id,

packages/graphql-mini-transforms/src/webpack.ts

+29-3
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,59 @@ import {dirname} from 'path';
33
import {loader} from 'webpack';
44
import {parse, DocumentNode} from 'graphql';
55
import {getOptions} from 'loader-utils';
6+
import validateOptions from 'schema-utils';
67

7-
import {cleanDocument, extractImports, toSimpleDocument} from './document';
8+
import {
9+
cleanDocument,
10+
extractImports,
11+
toSimpleDocument,
12+
CleanDocumentOptions,
13+
} from './document';
814

915
interface Options {
16+
generateId?: (normalizedSource: string) => string;
1017
simple?: boolean;
1118
}
1219

20+
const schema = {
21+
type: 'object' as const,
22+
properties: {
23+
simple: {
24+
type: 'boolean' as const,
25+
},
26+
generateId: {
27+
instanceof: 'Function' as const,
28+
},
29+
},
30+
};
31+
1332
export default async function graphQLLoader(
1433
this: loader.LoaderContext,
1534
source: string | Buffer,
1635
) {
1736
this.cacheable();
1837

1938
const done = this.async();
20-
const {simple = false} = getOptions(this) as Options;
39+
const options = {simple: false, ...getOptions(this)} as Options;
40+
41+
validateOptions(schema, options, {name: '@shopify/graphql-mini-transforms'});
2142

2243
if (done == null) {
2344
throw new Error(
2445
'@shopify/graphql-loader does not support synchronous processing',
2546
);
2647
}
2748

49+
const cleanDocumentOptions = {
50+
generateId: options.generateId,
51+
} as CleanDocumentOptions;
52+
2853
try {
2954
const document = cleanDocument(
3055
await loadDocument(source, this.context, this),
56+
cleanDocumentOptions,
3157
);
32-
const exported = simple ? toSimpleDocument(document) : document;
58+
const exported = options.simple ? toSimpleDocument(document) : document;
3359

3460
done(
3561
null,

packages/graphql-mini-transforms/tests/webpack.test.ts

+8
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ describe('graphql-mini-transforms/webpack', () => {
7070
);
7171
});
7272

73+
it('has option for custom ID generate function', async () => {
74+
const result = await extractDocumentExport(
75+
`query Shop { shop { id } }`,
76+
createLoaderContext({query: {generateId: () => 'foo'}}),
77+
);
78+
expect(result).toHaveProperty('id', 'foo');
79+
});
80+
7381
describe('import', () => {
7482
it('adds the resolved import as a dependency', async () => {
7583
const context = '/app/';

yarn.lock

+36
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,11 @@
720720
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
721721
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
722722

723+
"@types/json-schema@^7.0.5":
724+
version "7.0.6"
725+
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0"
726+
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==
727+
723728
"@types/loader-utils@^1.1.3":
724729
version "1.1.3"
725730
resolved "https://registry.yarnpkg.com/@types/loader-utils/-/loader-utils-1.1.3.tgz#82b9163f2ead596c68a8c03e450fbd6e089df401"
@@ -751,6 +756,13 @@
751756
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f"
752757
integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ==
753758

759+
"@types/schema-utils@^2.4.0":
760+
version "2.4.0"
761+
resolved "https://registry.yarnpkg.com/@types/schema-utils/-/schema-utils-2.4.0.tgz#9983012045d541dcee053e685a27c9c87c840fcd"
762+
integrity sha512-454hrj5gz/FXcUE20ygfEiN4DxZ1sprUo0V1gqIqkNZ/CzoEzAZEll2uxMsuyz6BYjiQan4Aa65xbTemfzW9hQ==
763+
dependencies:
764+
schema-utils "*"
765+
754766
"@types/source-list-map@*":
755767
version "0.1.2"
756768
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:
909921
resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa"
910922
integrity sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=
911923

924+
ajv-keywords@^3.5.2:
925+
version "3.5.2"
926+
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
927+
integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
928+
912929
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
913930
version "6.12.0"
914931
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:
919936
json-schema-traverse "^0.4.1"
920937
uri-js "^4.2.2"
921938

939+
ajv@^6.12.4:
940+
version "6.12.5"
941+
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da"
942+
integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==
943+
dependencies:
944+
fast-deep-equal "^3.1.1"
945+
fast-json-stable-stringify "^2.0.0"
946+
json-schema-traverse "^0.4.1"
947+
uri-js "^4.2.2"
948+
922949
ansi-escapes@^3.0.0:
923950
version "3.2.0"
924951
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
@@ -5889,6 +5916,15 @@ saxes@^3.1.9:
58895916
dependencies:
58905917
xmlchars "^2.1.1"
58915918

5919+
schema-utils@*, schema-utils@^2.7.1:
5920+
version "2.7.1"
5921+
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
5922+
integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
5923+
dependencies:
5924+
"@types/json-schema" "^7.0.5"
5925+
ajv "^6.12.4"
5926+
ajv-keywords "^3.5.2"
5927+
58925928
"semver@2 || 3 || 4 || 5", semver@^5.1.0, semver@^5.4.1, semver@^5.5.0:
58935929
version "5.7.1"
58945930
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"

0 commit comments

Comments
 (0)