Skip to content

Commit

Permalink
inline graphql-js' printer
Browse files Browse the repository at this point in the history
  • Loading branch information
cometkim committed May 4, 2024
1 parent 76d6d77 commit 2ed355c
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 24 deletions.
5 changes: 3 additions & 2 deletions packages/babel-plugin-relay/compileGraphQLTag.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,15 @@ import type {
} from 'graphql';

const crypto = require('crypto');
const {print} = require('graphql');
const {
dirname,
join: joinPath,
relative: relativePath,
resolve: resolvePath,
} = require('path');

const printGraphQL = require('./printGraphQL.js');

const GENERATED = './__generated__/';

/**
Expand Down Expand Up @@ -125,7 +126,7 @@ function createNode(

const hash = crypto
.createHash('md5')
.update(print(graphqlDefinition), 'utf8')
.update(printGraphQL(graphqlDefinition), 'utf8')
.digest('hex');

let topScope = path.scope;
Expand Down
8 changes: 6 additions & 2 deletions packages/babel-plugin-relay/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@
"url": "https://github.com/facebook/relay.git",
"directory": "packages/babel-plugin-relay"
},
"peerDependencies": {
"@babel/core": "^7.0.0",
"graphql": "^15.0.0 || ^16.0.0"
},
"dependencies": {
"babel-plugin-macros": "^2.0.0",
"cosmiconfig": "^5.0.5",
"graphql": "15.3.0"
"cosmiconfig": "^5.0.5"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"graphql": "^16.8.1",
"prettier": "2.8.8",
"prettier-plugin-hermes-parser": "0.20.1"
}
Expand Down
184 changes: 184 additions & 0 deletions packages/babel-plugin-relay/printGraphQL.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/**
* Inlined GraphQL printer,
* forked from https://github.com/graphql/graphql-js/blob/v15.3.0/src/language/printer.js
*
* This ensure compatibility with document hash generated by the Relay compiler.
* graphql-js' printer is incompatible with Relay's one since v15.4
*
* TODO: Canonicalize printer spec for Relay projects
*
* @see https://github.com/facebook/relay/pull/3628
* @see https://github.com/facebook/relay/issues/4226
*/

const { visit } = require('graphql');

/**
* Converts an AST into a string, using one set of reasonable
* formatting rules.
*/
function print(ast: any): string {
return visit(ast, { leave: printDocASTReducer });
}

const printDocASTReducer: any = {
Name: (node) => node.value,
Variable: (node) => '$' + node.name,

// Document

Document: (node) => join(node.definitions, '\n\n') + '\n',

OperationDefinition(node) {
const op = node.operation;
const name = node.name;
const varDefs = wrap('(', join(node.variableDefinitions, ', '), ')');
const directives = join(node.directives, ' ');
const selectionSet = node.selectionSet;
// Anonymous queries with no directives or variable definitions can use
// the query short form.
return !name && !directives && !varDefs && op === 'query'
? selectionSet
: join([op, join([name, varDefs]), directives, selectionSet], ' ');
},

VariableDefinition: ({ variable, type, defaultValue, directives }) =>
variable +
': ' +
type +
wrap(' = ', defaultValue) +
wrap(' ', join(directives, ' ')),
SelectionSet: ({ selections }) => block(selections),

Field: ({ alias, name, arguments: args, directives, selectionSet }) =>
join(
[
wrap('', alias, ': ') + name + wrap('(', join(args, ', '), ')'),
join(directives, ' '),
selectionSet,
],
' ',
),

Argument: ({ name, value }) => name + ': ' + value,

// Fragments

FragmentSpread: ({ name, directives }) =>
'...' + name + wrap(' ', join(directives, ' ')),

InlineFragment: ({ typeCondition, directives, selectionSet }) =>
join(
['...', wrap('on ', typeCondition), join(directives, ' '), selectionSet],
' ',
),

FragmentDefinition: ({
name,
typeCondition,
variableDefinitions,
directives,
selectionSet,
}) =>
// Note: fragment variable definitions are experimental and may be changed
// or removed in the future.
`fragment ${name}${wrap('(', join(variableDefinitions, ', '), ')')} ` +
`on ${typeCondition} ${wrap('', join(directives, ' '), ' ')}` +
selectionSet,

// Value

IntValue: ({ value }) => value,
FloatValue: ({ value }) => value,
StringValue: ({ value, block: isBlockString }, key) =>
isBlockString
? printBlockString(value, key === 'description' ? '' : ' ')
: JSON.stringify(value),
BooleanValue: ({ value }) => (value ? 'true' : 'false'),
NullValue: () => 'null',
EnumValue: ({ value }) => value,
ListValue: ({ values }) => '[' + join(values, ', ') + ']',
ObjectValue: ({ fields }) => '{' + join(fields, ', ') + '}',
ObjectField: ({ name, value }) => name + ': ' + value,

// Directive

Directive: ({ name, arguments: args }) =>
'@' + name + wrap('(', join(args, ', '), ')'),

// Type

NamedType: ({ name }) => name,
ListType: ({ type }) => '[' + type + ']',
NonNullType: ({ type }) => type + '!',

// Type System Definitions
// Removed since that never included in the Relay documents
};

/**
* Given maybeArray, print an empty string if it is null or empty, otherwise
* print all items together separated by separator if provided
*/
function join(maybeArray: ?Array<string>, separator = '') {
return maybeArray?.filter((x) => x).join(separator) ?? '';
}

/**
* Given array, print each item on its own line, wrapped in an
* indented "{ }" block.
*/
function block(array) {
return array && array.length !== 0
? '{\n' + indent(join(array, '\n')) + '\n}'
: '';
}

/**
* If maybeString is not null or empty, then wrap with start and end, otherwise
* print an empty string.
*/
function wrap(start, maybeString, end = '') {
return maybeString ? start + maybeString + end : '';
}

function indent(maybeString) {
return maybeString && ' ' + maybeString.replace(/\n/g, '\n ');
}

/**
* Print a block string in the indented block form by adding a leading and
* trailing blank line. However, if a block string starts with whitespace and is
* a single-line, adding a leading blank line would strip that whitespace.
*
* @internal
*/
function printBlockString(
value: string,
indentation?: string = '',
preferMultipleLines?: boolean = false,
): string {
const isSingleLine = value.indexOf('\n') === -1;
const hasLeadingSpace = value[0] === ' ' || value[0] === '\t';
const hasTrailingQuote = value[value.length - 1] === '"';
const hasTrailingSlash = value[value.length - 1] === '\\';
const printAsMultipleLines =
!isSingleLine ||
hasTrailingQuote ||
hasTrailingSlash ||
preferMultipleLines;

let result = '';
// Format a multi-line block quote to account for leading space.
if (printAsMultipleLines && !(isSingleLine && hasLeadingSpace)) {
result += '\n' + indentation;
}
result += indentation ? value.replace(/\n/g, '\n' + indentation) : value;
if (printAsMultipleLines) {
result += '\n';
}

return '"""' + result.replace(/"""/g, '\\"""') + '"""';
}

module.exports = print;
40 changes: 20 additions & 20 deletions packages/babel-plugin-relay/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -348,27 +348,27 @@ globals@^11.1.0:
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==

graphql@15.3.0:
version "15.3.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.3.0.tgz#3ad2b0caab0d110e3be4a5a9b2aa281e362b5278"
integrity sha512-GTCJtzJmkFLWRfFJuoo9RWWa/FfamUHgiFosxi/X1Ani4AVWbeyBenZTNX6dM+7WSbbFfTo/25eh0LLkwHMw2w==
graphql@^16.8.1:
version "16.8.1"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==

has-flag@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=

hermes-estree@0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.16.0.tgz#e2c76a1e9d5a4d620790b9fe05fb01f2d53da07d"
integrity sha512-XCoTuBU8S+Jg8nFzaqgy6pNEYo0WYkbMmuJldb3svzpJ2SNUYJDg28b1ltoDMo7k3YlJwPRg7ZS3JTWV3DkDZA==
hermes-estree@0.20.1:
version "0.20.1"
resolved "https://registry.yarnpkg.com/hermes-estree/-/hermes-estree-0.20.1.tgz#0b9a544cf883a779a8e1444b915fa365bef7f72d"
integrity sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==

hermes-parser@0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.16.0.tgz#92d0a34ff4f9b7ffcb04511dfed0cc19df5038e0"
integrity sha512-tdJJntb45DUpv8j7ybHfq8NfIQgz8AgaD+PVFyfjK+O+v2N5zbsSDtlvQN2uxCghoTkQL86BEs9oi8IPrUE9Pg==
hermes-parser@0.20.1:
version "0.20.1"
resolved "https://registry.yarnpkg.com/hermes-parser/-/hermes-parser-0.20.1.tgz#ad10597b99f718b91e283f81cbe636c50c3cff92"
integrity sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==
dependencies:
hermes-estree "0.16.0"
hermes-estree "0.20.1"

is-arrayish@^0.2.1:
version "0.2.1"
Expand Down Expand Up @@ -443,14 +443,14 @@ picocolors@^1.0.0:
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==

prettier-plugin-hermes-parser@0.16.0:
version "0.16.0"
resolved "https://registry.yarnpkg.com/prettier-plugin-hermes-parser/-/prettier-plugin-hermes-parser-0.16.0.tgz#4393d43a4a6f4ed976493dccbbb93f62c44215c3"
integrity sha512-J4HdSmlxf3a0nVHVi0G6JJJ7sDVtSb5a+QR52LpiQonpQzMkqgIqyCg+Gt1sGMTJqn19Z0yTHxwCmUicVYXUVg==
prettier-plugin-hermes-parser@0.20.1:
version "0.20.1"
resolved "https://registry.yarnpkg.com/prettier-plugin-hermes-parser/-/prettier-plugin-hermes-parser-0.20.1.tgz#a5f395ae77170813e631f4538c9ef29311b4db1d"
integrity sha512-T6dfa1++ckTxd3MbLxS6sTv1T3yvTu1drahNt3g34hyCzSwYTKTByocLyhd1A9j9uCUlIPD+ogum7+i1h3+CEw==
dependencies:
hermes-estree "0.16.0"
hermes-parser "0.16.0"
prettier-plugin-hermes-parser "0.16.0"
hermes-estree "0.20.1"
hermes-parser "0.20.1"
prettier-plugin-hermes-parser "0.20.1"

prettier@2.8.8:
version "2.8.8"
Expand Down

0 comments on commit 2ed355c

Please sign in to comment.