Skip to content

Commit

Permalink
upgrade to latest v17 alpha
Browse files Browse the repository at this point in the history
  • Loading branch information
yaacovCR committed Feb 9, 2025
1 parent 7910cfb commit 51efcda
Show file tree
Hide file tree
Showing 17 changed files with 392 additions and 697 deletions.
6 changes: 4 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@
"test": "npm run lint && npm run check && npm run testonly && npm run prettier:check && npm run check:spelling",
"lint": "eslint --cache --max-warnings 0 .",
"check": "tsc --pretty",
"testonly": "mocha --full-trace 'src/**/__tests__/**/*-test.ts'",
"testonly": "mocha --full-trace src/**/__tests__/**/*-test.ts",
"testonly:cover": "c8 npm run testonly",
"testonly:watch": "npm run testonly -- --watch",
"prettier": "prettier --cache --cache-strategy metadata --write --list-different .",
"prettier:check": "prettier --cache --cache-strategy metadata --check .",
"check:spelling": "cspell --cache --no-progress '**/*'",
"check:spelling": "cspell --cache --no-progress \"**/*\"",
"build:npm:dual": "node --loader ts-node/esm resources/build-npm-dual.ts",
"build:npm:esm-only": "node --loader ts-node/esm resources/build-npm-esm-only.ts",
"build:deno": "node --loader ts-node/esm resources/build-deno.ts",
Expand Down Expand Up @@ -77,6 +77,6 @@
},
"dependencies": {
"@repeaterjs/repeater": "^3.0.6",
"graphql": "^17.0.0-alpha.3"
"graphql": "^17.0.0-alpha.8"
}
}
20 changes: 4 additions & 16 deletions src/stitch/Planner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { invariant } from '../utilities/invariant.js';
import { memoize2 } from '../utilities/memoize2.js';
import { memoize3 } from '../utilities/memoize3.js';

import type { Subschema, SuperSchema } from './SuperSchema.js';
import type { Subschema, SuperSchema, VariableValues } from './SuperSchema.js';

export interface RootPlan {
superSchema: SuperSchema;
Expand Down Expand Up @@ -59,8 +59,6 @@ interface SelectionSplit {
otherSelections: ReadonlyArray<SelectionNode>;
}

const emptyObject = {};

export const createPlanner = memoize2(
(superSchema: SuperSchema, operation: OperationDefinitionNode) =>
new Planner(superSchema, operation),
Expand All @@ -85,11 +83,7 @@ export class Planner {
this.variableDefinitions = operation.variableDefinitions ?? [];
}

createRootPlan(
variableValues: {
[key: string]: unknown;
} = emptyObject,
): RootPlan | GraphQLError {
createRootPlan(variableValues: VariableValues): RootPlan | GraphQLError {
const rootType = this.superSchema.getRootType(this.operation.operation);

if (rootType === undefined) {
Expand Down Expand Up @@ -432,14 +426,8 @@ export class Planner {
selectionSplit.ownSelections,
{
kind: Kind.FIELD,
name: {
kind: Kind.NAME,
value: TypeNameMetaFieldDef.name,
},
alias: {
kind: Kind.NAME,
value: '__stitching__typename',
},
name: { kind: Kind.NAME, value: TypeNameMetaFieldDef.name },
alias: { kind: Kind.NAME, value: '__stitching__typename' },
},
);
}
Expand Down
155 changes: 90 additions & 65 deletions src/stitch/SuperSchema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type {
ConstValueNode,
DirectiveLocation,
DocumentNode,
ExecutionResult,
Expand Down Expand Up @@ -26,6 +27,7 @@ import type {
VariableDefinitionNode,
} from 'graphql';
import {
coerceInputLiteral,
coerceInputValue,
execute,
GraphQLDirective,
Expand All @@ -48,21 +50,16 @@ import {
Kind,
OperationTypeNode,
print,
valueFromAST,
validateInputValue,
} from 'graphql';

import type { ObjMap } from '../types/ObjMap.js';
import type { ObjMap, ReadOnlyObjMap } from '../types/ObjMap.js';
import type { PromiseOrValue } from '../types/PromiseOrValue.js';
import type { SimpleAsyncGenerator } from '../types/SimpleAsyncGenerator.js';

import { AccumulatorMap } from '../utilities/AccumulatorMap.js';
import { inspect } from '../utilities/inspect.js';
import { printPathArray } from '../utilities/printPathArray.js';

type CoercedVariableValues =
| { errors: ReadonlyArray<GraphQLError>; coerced?: never }
| { coerced: { [variable: string]: unknown }; errors?: never };

const operations = [
OperationTypeNode.QUERY,
OperationTypeNode.MUTATION,
Expand All @@ -85,6 +82,27 @@ export interface Subschema {
subscriber?: Subscriber;
}

export interface VariableValues {
readonly sources: ReadOnlyObjMap<VariableValueSource>;
readonly coerced: ReadOnlyObjMap<unknown>;
}

interface VariableValueSource {
readonly signature: GraphQLVariableSignature;
readonly value?: unknown;
}

export interface GraphQLVariableSignature {
name: string;
type: GraphQLInputType;
defaultValue?: never;
default: { literal: ConstValueNode } | undefined;
}

type VariableValuesOrErrors =
| { variableValues: VariableValues; errors?: never }
| { errors: ReadonlyArray<GraphQLError>; variableValues?: never };

/**
* @internal
*/
Expand Down Expand Up @@ -122,11 +140,7 @@ export class SuperSchema {

const introspectionSubschema: Subschema = {
schema: this.mergedSchema,
executor: (args) =>
execute({
...args,
schema: this.mergedSchema,
}),
executor: (args) => execute({ ...args, schema: this.mergedSchema }),
};
for (const [name, type] of Object.entries(this.mergedSchema.getTypeMap())) {
if (!name.startsWith('__')) {
Expand Down Expand Up @@ -531,11 +545,11 @@ export class SuperSchema {
varDefNodes: ReadonlyArray<VariableDefinitionNode>,
inputs: { readonly [variable: string]: unknown },
options?: { maxErrors?: number },
): CoercedVariableValues {
): VariableValuesOrErrors {
const errors = [];
const maxErrors = options?.maxErrors;
try {
const coerced = this._coerceVariableValues(
const variableValues = this._coerceVariableValues(
varDefNodes,
inputs,
(error) => {
Expand All @@ -549,7 +563,7 @@ export class SuperSchema {
);

if (errors.length === 0) {
return { coerced };
return { variableValues };
}
} catch (error) {
errors.push(error);
Expand Down Expand Up @@ -588,74 +602,85 @@ export class SuperSchema {
varDefNodes: ReadonlyArray<VariableDefinitionNode>,
inputs: { readonly [variable: string]: unknown },
onError: (error: GraphQLError) => void,
): { [variable: string]: unknown } {
const coercedValues: { [variable: string]: unknown } = {};
hideSuggestions?: boolean,
): VariableValues {
const sources: ObjMap<VariableValueSource> = Object.create(null);
const coerced: ObjMap<unknown> = Object.create(null);
for (const varDefNode of varDefNodes) {
const varName = varDefNode.variable.name.value;
const varType = this._typeFromAST(varDefNode.type);
if (!isInputType(varType)) {
// Must use input types for variables. This should be caught during
// validation, however is checked again here for safety.
const varTypeStr = print(varDefNode.type);
onError(
new GraphQLError(
`Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`,
{ nodes: varDefNode.type },
),
);
const varSignature = this._getVariableSignature(varDefNode);

if (varSignature instanceof GraphQLError) {
onError(varSignature);
continue;
}

const { name: varName, type: varType } = varSignature;
let value: unknown;
if (!Object.hasOwn(inputs, varName)) {
sources[varName] = { signature: varSignature };
if (varDefNode.defaultValue) {
coercedValues[varName] = valueFromAST(
coerced[varName] = coerceInputLiteral(
varDefNode.defaultValue,
varType,
);
} else if (isNonNullType(varType)) {
const varTypeStr = inspect(varType);
onError(
new GraphQLError(
`Variable "$${varName}" of required type "${varTypeStr}" was not provided.`,
{ nodes: varDefNode },
),
);
continue;
} else if (!isNonNullType(varType)) {
// Non-provided values for nullable variables are omitted.
continue;
}
continue;
} else {
value = inputs[varName];
sources[varName] = { signature: varSignature, value };
}

const value = inputs[varName];
if (value === null && isNonNullType(varType)) {
const varTypeStr = inspect(varType);
onError(
new GraphQLError(
`Variable "$${varName}" of non-null type "${varTypeStr}" must not be null.`,
{ nodes: varDefNode },
),
const coercedValue = coerceInputValue(value, varType);
if (coercedValue !== undefined) {
coerced[varName] = coercedValue;
} else {
validateInputValue(
value,
varType,
(error, path) => {
onError(
new GraphQLError(
`Variable "$${varName}" has invalid value${printPathArray(path)}: ${
error.message
}`,
{ nodes: varDefNode, originalError: error },
),
);
},
hideSuggestions,
);
continue;
}
}

coercedValues[varName] = coerceInputValue(
value,
varType,
(path, invalidValue, error) => {
let prefix =
`Variable "$${varName}" got invalid value ` + inspect(invalidValue);
if (path.length > 0) {
prefix += ` at "${varName}${printPathArray(path)}"`;
}
onError(
new GraphQLError(prefix + '; ' + error.message, {
nodes: varDefNode,
originalError: error.originalError,
}),
);
},
return { sources, coerced };
}

_getVariableSignature(
varDefNode: VariableDefinitionNode,
): GraphQLVariableSignature | GraphQLError {
const varName = varDefNode.variable.name.value;
const varType = this._typeFromAST(varDefNode.type);

if (!isInputType(varType)) {
// Must use input types for variables. This should be caught during
// validation, however is checked again here for safety.
const varTypeStr = print(varDefNode.type);
return new GraphQLError(
`Variable "$${varName}" expected value of type "${varTypeStr}" which cannot be used as an input type.`,
{ nodes: varDefNode.type },
);
}

return coercedValues;
const defaultValue = varDefNode.defaultValue;

return {
name: varName,
type: varType,
default: defaultValue && { literal: defaultValue },
};
}

getSubschemaId(subschema: Subschema): string {
Expand Down
11 changes: 2 additions & 9 deletions src/stitch/__tests__/Planner-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@ import type { Subschema } from '../SuperSchema.js';
import { SuperSchema } from '../SuperSchema.js';

function getSubschema(schema: GraphQLSchema): Subschema {
return {
schema,
executor: (args) =>
execute({
...args,
schema,
}),
};
return { schema, executor: (args) => execute({ ...args, schema }) };
}

function createRootPlan(
Expand All @@ -40,7 +33,7 @@ function createRootPlan(

const planner = new Planner(superSchema, operation);

const rootPlan = planner.createRootPlan();
const rootPlan = planner.createRootPlan({ coerced: {}, sources: {} });

invariant(!(rootPlan instanceof GraphQLError));

Expand Down
Loading

0 comments on commit 51efcda

Please sign in to comment.