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

Commit

Permalink
add generateId option to graphql-mini-transforms
Browse files Browse the repository at this point in the history
  • Loading branch information
dsanders11 committed Dec 10, 2020
1 parent 5cd97df commit 5439516
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 10 deletions.
25 changes: 24 additions & 1 deletion packages/graphql-mini-transforms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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:
Expand Down
4 changes: 3 additions & 1 deletion packages/graphql-mini-transforms/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -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"
}
}
24 changes: 19 additions & 5 deletions packages/graphql-mini-transforms/src/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<any, any, any> {
if (removeUnused) {
removeUnusedDefinitions(document);
Expand All @@ -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,
Expand Down
32 changes: 29 additions & 3 deletions packages/graphql-mini-transforms/src/webpack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,59 @@ 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,
) {
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(
'@shopify/graphql-loader does not support synchronous processing',
);
}

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,
Expand Down
8 changes: 8 additions & 0 deletions packages/graphql-mini-transforms/tests/webpack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/';
Expand Down
36 changes: 36 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 5439516

Please sign in to comment.