Skip to content

Add 'isRequredArgument' & 'isRequredInputField' predicates (#1465) #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 8 additions & 10 deletions .babelrc.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
module.exports = {
"presets": [["@babel/preset-env", {
"modules": process.env.BABEL_MODULES ? false : 'commonjs',
"targets": {
"node": 6,
"browsers": [
"ie 9",
"ios 9",
"last 2 chrome versions",
"last 2 edge versions",
"last 2 firefox versions",
]
}
"targets": [
"node 6",
"ie 9",
"ios 9",
"last 2 chrome versions",
"last 2 edge versions",
"last 2 firefox versions",
],
}]],
"plugins": [
"./resources/inline-invariant",
Expand Down
2 changes: 1 addition & 1 deletion .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(<VERSION>\\)?)\\)
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(<VERSION>\\)?)\\)?:? #[0-9]+

[version]
^0.78.0
^0.79.0
33 changes: 15 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@
"type": "git",
"url": "http://github.com/graphql/graphql-js.git"
},
"options": {
"mocha": "--check-leaks --full-trace --timeout 15000 src/**/__tests__/**/*-test.js"
},
"engines": {
"node": "6.x || 8.x || >= 10.x"
},
Expand Down Expand Up @@ -48,30 +45,30 @@
"iterall": "^1.2.2"
},
"devDependencies": {
"@babel/cli": "7.0.0-beta.56",
"@babel/core": "7.0.0-beta.56",
"@babel/plugin-proposal-class-properties": "7.0.0-beta.56",
"@babel/plugin-proposal-object-rest-spread": "7.0.0-beta.56",
"@babel/plugin-syntax-async-generators": "7.0.0-beta.56",
"@babel/plugin-transform-classes": "7.0.0-beta.56",
"@babel/plugin-transform-destructuring": "7.0.0-beta.56",
"@babel/plugin-transform-flow-strip-types": "7.0.0-beta.56",
"@babel/plugin-transform-spread": "7.0.0-beta.56",
"@babel/polyfill": "7.0.0-beta.56",
"@babel/preset-env": "7.0.0-beta.56",
"@babel/register": "7.0.0-beta.56",
"@babel/cli": "7.0.0-rc.3",
"@babel/core": "7.0.0-rc.3",
"@babel/plugin-proposal-class-properties": "7.0.0-rc.3",
"@babel/plugin-proposal-object-rest-spread": "7.0.0-rc.3",
"@babel/plugin-syntax-async-generators": "7.0.0-rc.3",
"@babel/plugin-transform-classes": "7.0.0-rc.3",
"@babel/plugin-transform-destructuring": "7.0.0-rc.3",
"@babel/plugin-transform-flow-strip-types": "7.0.0-rc.3",
"@babel/plugin-transform-spread": "7.0.0-rc.3",
"@babel/polyfill": "7.0.0-rc.3",
"@babel/preset-env": "7.0.0-rc.3",
"@babel/register": "7.0.0-rc.3",
"babel-eslint": "8.2.6",
"beautify-benchmark": "0.2.4",
"benchmark": "2.1.4",
"chai": "4.1.2",
"coveralls": "3.0.2",
"eslint": "5.3.0",
"eslint": "5.4.0",
"eslint-plugin-flowtype": "2.50.0",
"eslint-plugin-prettier": "2.6.2",
"flow-bin": "0.78.0",
"flow-bin": "0.79.1",
"mocha": "5.2.0",
"nyc": "12.0.2",
"prettier": "1.14.0",
"prettier": "1.14.2",
"sane": "3.0.0"
}
}
108 changes: 56 additions & 52 deletions resources/benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ const { Suite } = require('benchmark');
const beautifyBenchmark = require('beautify-benchmark');
const { execSync } = require('child_process');
const os = require('os');
const fs = require('fs');
const path = require('path');

// Like build:cjs, but includes __tests__ and copies other files.
const BUILD_CMD = 'babel src --optional runtime --copy-files --out-dir dist/';
const LOCAL = 'local';
const LOCAL_DIR = path.join(__dirname, '../');
const TEMP_DIR = os.tmpdir();
function LOCAL_DIR(...paths) {
return path.join(__dirname, '..', ...paths);
}
function TEMP_DIR(...paths) {
return path.join(os.tmpdir(), 'graphql-js-benchmark', ...paths);
}

// Returns the complete git hash for a given git revision reference.
function hashForRevision(revision) {
if (revision === LOCAL) {
return revision;
}
const out = execSync(`git rev-parse "${revision}"`, { encoding: 'utf8' });
const match = /[0-9a-f]{8,40}/.exec(out);
if (!match) {
Expand All @@ -30,54 +32,48 @@ function hashForRevision(revision) {
return match[0];
}

// Returns the temporary directory which hosts the files for this git hash.
function dirForHash(hash) {
if (hash === LOCAL) {
return path.join(__dirname, '../');
}
return path.join(TEMP_DIR, 'graphql-js-benchmark', hash);
}

// Build a benchmarkable environment for the given revision.
// Build a benchmarkable environment for the given revision
// and returns path to its 'dist' directory.
function prepareRevision(revision) {
console.log(`🍳 Preparing ${revision}...`);
const hash = hashForRevision(revision);
const dir = dirForHash(hash);
if (hash === LOCAL) {
execSync(`(cd "${dir}" && yarn run ${BUILD_CMD})`);

if (revision === LOCAL) {
execSync(`yarn run ${BUILD_CMD}`);
return LOCAL_DIR('dist');
} else {
execSync(`
if [ ! -d "${dir}" ]; then
mkdir -p "${dir}" &&
git archive "${hash}" | tar -xC "${dir}" &&
(cd "${dir}" && yarn install);
fi &&
# Copy in local tests so the same logic applies to each revision.
for file in $(cd "${LOCAL_DIR}src"; find . -path '*/__tests__/*');
do cp "${LOCAL_DIR}src/$file" "${dir}/src/$file";
done &&
(cd "${dir}" && yarn run ${BUILD_CMD})
`);
if (!fs.existsSync(TEMP_DIR())) {
fs.mkdirSync(TEMP_DIR());
}

const hash = hashForRevision(revision);
const dir = TEMP_DIR(hash);

if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
execSync(`git archive "${hash}" | tar -xC "${dir}"`);
execSync('yarn install', { cwd: dir });
}
for (const file of findFiles(LOCAL_DIR('src'), '*/__tests__/*')) {
const from = LOCAL_DIR('src', file);
const to = path.join(dir, 'src', file);
fs.copyFileSync(from, to);
}
execSync(`cp -R "${LOCAL_DIR()}/src/__fixtures__/" "${dir}/src/__fixtures__/"`);
execSync(`yarn run ${BUILD_CMD}`, { cwd: dir });

return path.join(dir, 'dist');
}
}

// Find all benchmark tests to be run.
function findBenchmarks() {
const out = execSync(
`(cd ${LOCAL_DIR}src; find . -path '*/__tests__/*-benchmark.js')`,
{ encoding: 'utf8' },
);
function findFiles(cwd, pattern) {
const out = execSync(`find . -path '${pattern}'`, { cwd, encoding: 'utf8' });
return out.split('\n').filter(Boolean);
}

// Run a given benchmark test with the provided revisions.
function runBenchmark(benchmark, revisions) {
const modules = revisions.map(revision =>
require(path.join(
dirForHash(hashForRevision(revision)),
'dist',
benchmark,
)),
function runBenchmark(benchmark, enviroments) {
const modules = enviroments.map(({distPath}) =>
require(path.join(distPath, benchmark)),
);
const suite = new Suite(modules[0].name, {
onStart(event) {
Expand All @@ -94,28 +90,36 @@ function runBenchmark(benchmark, revisions) {
beautifyBenchmark.log();
},
});
for (let i = 0; i < revisions.length; i++) {
suite.add(revisions[i], modules[i].measure);
for (let i = 0; i < enviroments.length; i++) {
suite.add(enviroments[i].revision, modules[i].measure);
}
suite.run({ async: false });
}

// Prepare all revisions and run benchmarks matching a pattern against them.
function prepareAndRunBenchmarks(benchmarkPatterns, revisions) {
const benchmarks = findBenchmarks().filter(
benchmark =>
benchmarkPatterns.length === 0 ||
benchmarkPatterns.some(pattern => benchmark.indexOf(pattern) !== -1),
);
// Find all benchmark tests to be run.
let benchmarks = findFiles(LOCAL_DIR('src'), '*/__tests__/*-benchmark.js');
if (benchmarkPatterns.length !== 0) {
benchmarks = benchmarks.filter(
benchmark => benchmarkPatterns.some(
pattern => path.join('src', benchmark).includes(pattern)
),
);
}

if (benchmarks.length === 0) {
console.warn(
'No benchmarks matching: ' +
`\u001b[1m${benchmarkPatterns.join('\u001b[0m or \u001b[1m')}\u001b[0m`,
);
return;
}
revisions.forEach(revision => prepareRevision(revision));
benchmarks.forEach(benchmark => runBenchmark(benchmark, revisions));

const enviroments = revisions.map(
revision => ({ revision, distPath: prepareRevision(revision)})
);
benchmarks.forEach(benchmark => runBenchmark(benchmark, enviroments));
}

function getArguments(argv) {
Expand Down
11 changes: 11 additions & 0 deletions src/__fixtures__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { join } from 'path';
import { readFileSync } from 'fs';

function readLocalFile(filename) {
return readFileSync(join(__dirname, filename), 'utf8');
}

export const bigSchemaSDL = readLocalFile('github-schema.graphql');
export const bigSchemaIntrospectionResult = JSON.parse(
readLocalFile('github-schema.json'),
);
8 changes: 4 additions & 4 deletions src/__tests__/starWarsData.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,23 +100,23 @@ export type Character = {
appearsIn: Array<number>,
};

export type Human = {
export type Human = {|
type: 'Human',
id: string,
name: string,
friends: Array<string>,
appearsIn: Array<number>,
homePlanet: string,
};
|};

export type Droid = {
export type Droid = {|
type: 'Droid',
id: string,
name: string,
friends: Array<string>,
appearsIn: Array<number>,
primaryFunction: string,
};
|};

/**
* Helper function to get a character by ID.
Expand Down
4 changes: 2 additions & 2 deletions src/execution/execute.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ import type {
* Namely, schema of the type system that is currently executing,
* and the fragments defined in the query document
*/
export type ExecutionContext = {
export type ExecutionContext = {|
schema: GraphQLSchema,
fragments: ObjMap<FragmentDefinitionNode>,
rootValue: mixed,
Expand All @@ -103,7 +103,7 @@ export type ExecutionContext = {
variableValues: { [variable: string]: mixed },
fieldResolver: GraphQLFieldResolver<any, any>,
errors: Array<GraphQLError>,
};
|};

/**
* The result of GraphQL execution.
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ export {
isWrappingType,
isNullableType,
isNamedType,
isRequiredArgument,
isRequiredInputField,
isSpecifiedScalarType,
isIntrospectionType,
isSpecifiedDirective,
Expand Down
4 changes: 2 additions & 2 deletions src/language/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export type ASTNode =
/**
* Utility type listing all nodes indexed by their kind.
*/
export type ASTKindToNode = {
export type ASTKindToNode = {|
Name: NameNode,
Document: DocumentNode,
OperationDefinition: OperationDefinitionNode,
Expand Down Expand Up @@ -180,7 +180,7 @@ export type ASTKindToNode = {
UnionTypeExtension: UnionTypeExtensionNode,
EnumTypeExtension: EnumTypeExtensionNode,
InputObjectTypeExtension: InputObjectTypeExtensionNode,
};
|};

// Name

Expand Down
4 changes: 2 additions & 2 deletions src/language/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
import invariant from '../jsutils/invariant';
import defineToStringTag from '../jsutils/defineToStringTag';

type Location = {
type Location = {|
line: number,
column: number,
};
|};

/**
* A representation of source input to GraphQL.
Expand Down
10 changes: 10 additions & 0 deletions src/type/definition.js
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,10 @@ export type GraphQLArgument = {
astNode?: ?InputValueDefinitionNode,
};

export function isRequiredArgument(arg: GraphQLArgument): boolean %checks {
return isNonNullType(arg.type) && arg.defaultValue === undefined;
}

export type GraphQLFieldMap<TSource, TContext> = ObjMap<
GraphQLField<TSource, TContext>,
>;
Expand Down Expand Up @@ -1273,4 +1277,10 @@ export type GraphQLInputField = {
astNode?: ?InputValueDefinitionNode,
};

export function isRequiredInputField(
field: GraphQLInputField,
): boolean %checks {
return isNonNullType(field.type) && field.defaultValue === undefined;
}

export type GraphQLInputFieldMap = ObjMap<GraphQLInputField>;
2 changes: 2 additions & 0 deletions src/type/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ export {
isWrappingType,
isNullableType,
isNamedType,
isRequiredArgument,
isRequiredInputField,
// Assertions
assertType,
assertScalarType,
Expand Down
8 changes: 3 additions & 5 deletions src/utilities/__tests__/buildASTSchema-benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@
* LICENSE file in the root directory of this source tree.
*/

import { join } from 'path';
import { readFileSync } from 'fs';
import { bigSchemaSDL } from '../../__fixtures__';

import { parse } from '../../';
import { buildASTSchema } from '../buildASTSchema';

const schemaAST = parse(
readFileSync(join(__dirname, 'github-schema.graphql'), 'utf8'),
);
const schemaAST = parse(bigSchemaSDL);

export const name = 'Build Schema from AST';
export function measure() {
Expand Down
Loading