@envelop/core
Advanced tools
Comparing version
import { GraphQLSchema } from 'graphql'; | ||
import { Envelop, Plugin } from '@envelop/types'; | ||
export declare function envelop(serverOptions: { | ||
export declare function envelop(options: { | ||
plugins: Plugin[]; | ||
extends?: Envelop[]; | ||
initialSchema?: GraphQLSchema; | ||
}): Envelop; |
129
index.cjs.js
@@ -10,9 +10,11 @@ 'use strict'; | ||
const resolversHooksSymbol = Symbol('RESOLVERS_HOOKS'); | ||
function envelop(serverOptions) { | ||
let schema = serverOptions.initialSchema; | ||
function envelop(options) { | ||
let schema = options.initialSchema; | ||
let initDone = false; | ||
const childPlugins = (options.extends || []).reduce((prev, child) => [...prev, ...child._plugins], []); | ||
const plugins = [...childPlugins, ...options.plugins]; | ||
const replaceSchema = (newSchema) => { | ||
schema = newSchema; | ||
if (initDone) { | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
plugin.onSchemaChange && plugin.onSchemaChange({ schema }); | ||
@@ -22,3 +24,3 @@ } | ||
}; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
plugin.onPluginInit && | ||
@@ -29,10 +31,10 @@ plugin.onPluginInit({ | ||
} | ||
const customParse = (source, options) => { | ||
const customParse = (source, parseOptions) => { | ||
let result = null; | ||
let parseFn = graphql.parse; | ||
const afterCalls = []; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
const afterFn = plugin.onParse && | ||
plugin.onParse({ | ||
params: { source, options }, | ||
params: { source, options: parseOptions }, | ||
parseFn, | ||
@@ -50,3 +52,3 @@ setParseFn: newFn => { | ||
try { | ||
result = parseFn(source, options); | ||
result = parseFn(source, parseOptions); | ||
} | ||
@@ -70,3 +72,3 @@ catch (e) { | ||
}; | ||
const customValidate = (schema, documentAST, rules, typeInfo, options) => { | ||
const customValidate = (schema, documentAST, rules, typeInfo, validationOptions) => { | ||
let actualRules = rules ? [...rules] : undefined; | ||
@@ -76,3 +78,3 @@ let validateFn = graphql.validate; | ||
const afterCalls = []; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
const afterFn = plugin.onValidate && | ||
@@ -85,3 +87,3 @@ plugin.onValidate({ | ||
typeInfo, | ||
options, | ||
options: validationOptions, | ||
}, | ||
@@ -105,3 +107,3 @@ validateFn, | ||
if (result === null) { | ||
result = validateFn(schema, documentAST, actualRules, typeInfo, options); | ||
result = validateFn(schema, documentAST, actualRules, typeInfo, validationOptions); | ||
} | ||
@@ -117,3 +119,3 @@ const valid = result.length === 0; | ||
const afterCalls = []; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
const afterFn = plugin.onContextBuilding && | ||
@@ -141,3 +143,66 @@ (await plugin.onContextBuilding({ | ||
}; | ||
const beforeExecuteCalls = serverOptions.plugins.filter(p => p.onExecute); | ||
const beforeExecuteCalls = plugins.filter(p => p.onExecute); | ||
const beforeSubscribeCalls = plugins.filter(p => p.onSubscribe); | ||
const customSubscribe = async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => { | ||
const args = argsOrSchema instanceof graphql.GraphQLSchema | ||
? { | ||
schema: argsOrSchema, | ||
document, | ||
rootValue, | ||
contextValue, | ||
variableValues, | ||
operationName, | ||
fieldResolver, | ||
subscribeFieldResolver, | ||
} | ||
: argsOrSchema; | ||
const onResolversHandlers = []; | ||
let subscribeFn = graphql.subscribe; | ||
const afterCalls = []; | ||
let context = args.contextValue; | ||
for (const plugin of beforeSubscribeCalls) { | ||
const after = plugin.onSubscribe({ | ||
subscribeFn, | ||
setSubscribeFn: newSubscribeFn => { | ||
subscribeFn = newSubscribeFn; | ||
}, | ||
extendContext: extension => { | ||
if (typeof extension === 'object') { | ||
context = { | ||
...(context || {}), | ||
...extension, | ||
}; | ||
} | ||
else { | ||
throw new Error(`Invalid context extension provided! Expected "object", got: "${JSON.stringify(extension)}" (${typeof extension})`); | ||
} | ||
}, | ||
args, | ||
}); | ||
if (after) { | ||
if (after.onSubscribeResult) { | ||
afterCalls.push(after.onSubscribeResult); | ||
} | ||
if (after.onResolverCalled) { | ||
onResolversHandlers.push(after.onResolverCalled); | ||
} | ||
} | ||
} | ||
if (onResolversHandlers.length) { | ||
context[resolversHooksSymbol] = onResolversHandlers; | ||
} | ||
let result = await subscribeFn({ | ||
...args, | ||
contextValue: context, | ||
}); | ||
for (const afterCb of afterCalls) { | ||
afterCb({ | ||
result, | ||
setResult: newResult => { | ||
result = newResult; | ||
}, | ||
}); | ||
} | ||
return result; | ||
}; | ||
const customExecute = async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => { | ||
@@ -247,3 +312,3 @@ const args = argsOrSchema instanceof graphql.GraphQLSchema | ||
initDone = true; | ||
return () => { | ||
const envelop = () => { | ||
prepareSchema(); | ||
@@ -255,5 +320,10 @@ return { | ||
execute: customExecute, | ||
schema, | ||
subscribe: customSubscribe, | ||
get schema() { | ||
return schema; | ||
}, | ||
}; | ||
}; | ||
envelop._plugins = plugins; | ||
return envelop; | ||
} | ||
@@ -278,2 +348,10 @@ | ||
}, | ||
onSubscribe({ args }) { | ||
options.logFn('subscribe-start', { args }); | ||
return { | ||
onSubscribeResult: ({ result }) => { | ||
options.logFn('subscribe-end', { args, result }); | ||
}, | ||
}; | ||
}, | ||
}; | ||
@@ -286,4 +364,5 @@ }; | ||
onExecutionMeasurement: (args, timing) => console.log(`Operation execution "${args.operationName}" done in ${timing.ms}ms`), | ||
onSubscriptionMeasurement: (args, timing) => console.log(`Operation subsctiption "${args.operationName}" done in ${timing.ms}ms`), | ||
onParsingMeasurement: (source, timing) => console.log(`Parsing "${source}" done in ${timing.ms}ms`), | ||
onValidationMeasurement: (document, timing) => { var _a; return console.log(`Validation "${(_a = graphql.getOperationAST(document).name) === null || _a === void 0 ? void 0 : _a.value}" done in ${timing.ms}ms`); }, | ||
onValidationMeasurement: (document, timing) => { var _a, _b; return console.log(`Validation "${((_b = (_a = graphql.getOperationAST(document)) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) || '-'}" done in ${timing.ms}ms`); }, | ||
onResolverMeasurement: (info, timing) => console.log(`\tResolver of "${info.parentType.toString()}.${info.fieldName}" done in ${timing.ms}ms`), | ||
@@ -323,3 +402,3 @@ onContextBuildingMeasurement: (timing) => console.log(`Context building done in ${timing.ms}ms`), | ||
return () => { | ||
options.onValidationMeasurement(params[1], deltaFrom(validateStartTime)); | ||
options.onValidationMeasurement(params.documentAST, deltaFrom(validateStartTime)); | ||
}; | ||
@@ -341,2 +420,16 @@ }, | ||
}, | ||
onSubscribe({ args }) { | ||
const subscribeStartTime = process.hrtime(); | ||
return { | ||
onSubscribeResult: () => { | ||
options.onSubscriptionMeasurement(args, deltaFrom(subscribeStartTime)); | ||
}, | ||
onResolverCalled: ({ info }) => { | ||
const resolverStartTime = process.hrtime(); | ||
return () => { | ||
options.onResolverMeasurement(info, deltaFrom(resolverStartTime)); | ||
}; | ||
}, | ||
}; | ||
}, | ||
}; | ||
@@ -343,0 +436,0 @@ }; |
131
index.esm.js
export * from '@envelop/types'; | ||
import { specifiedRules, isIntrospectionType, isObjectType, defaultFieldResolver, parse, validate, GraphQLSchema, execute, getOperationAST } from 'graphql'; | ||
import { specifiedRules, isIntrospectionType, isObjectType, defaultFieldResolver, parse, validate, GraphQLSchema, subscribe, execute, getOperationAST } from 'graphql'; | ||
const trackedSchemaSymbol = Symbol('TRACKED_SCHEMA'); | ||
const resolversHooksSymbol = Symbol('RESOLVERS_HOOKS'); | ||
function envelop(serverOptions) { | ||
let schema = serverOptions.initialSchema; | ||
function envelop(options) { | ||
let schema = options.initialSchema; | ||
let initDone = false; | ||
const childPlugins = (options.extends || []).reduce((prev, child) => [...prev, ...child._plugins], []); | ||
const plugins = [...childPlugins, ...options.plugins]; | ||
const replaceSchema = (newSchema) => { | ||
schema = newSchema; | ||
if (initDone) { | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
plugin.onSchemaChange && plugin.onSchemaChange({ schema }); | ||
@@ -17,3 +19,3 @@ } | ||
}; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
plugin.onPluginInit && | ||
@@ -24,10 +26,10 @@ plugin.onPluginInit({ | ||
} | ||
const customParse = (source, options) => { | ||
const customParse = (source, parseOptions) => { | ||
let result = null; | ||
let parseFn = parse; | ||
const afterCalls = []; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
const afterFn = plugin.onParse && | ||
plugin.onParse({ | ||
params: { source, options }, | ||
params: { source, options: parseOptions }, | ||
parseFn, | ||
@@ -45,3 +47,3 @@ setParseFn: newFn => { | ||
try { | ||
result = parseFn(source, options); | ||
result = parseFn(source, parseOptions); | ||
} | ||
@@ -65,3 +67,3 @@ catch (e) { | ||
}; | ||
const customValidate = (schema, documentAST, rules, typeInfo, options) => { | ||
const customValidate = (schema, documentAST, rules, typeInfo, validationOptions) => { | ||
let actualRules = rules ? [...rules] : undefined; | ||
@@ -71,3 +73,3 @@ let validateFn = validate; | ||
const afterCalls = []; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
const afterFn = plugin.onValidate && | ||
@@ -80,3 +82,3 @@ plugin.onValidate({ | ||
typeInfo, | ||
options, | ||
options: validationOptions, | ||
}, | ||
@@ -100,3 +102,3 @@ validateFn, | ||
if (result === null) { | ||
result = validateFn(schema, documentAST, actualRules, typeInfo, options); | ||
result = validateFn(schema, documentAST, actualRules, typeInfo, validationOptions); | ||
} | ||
@@ -112,3 +114,3 @@ const valid = result.length === 0; | ||
const afterCalls = []; | ||
for (const plugin of serverOptions.plugins) { | ||
for (const plugin of plugins) { | ||
const afterFn = plugin.onContextBuilding && | ||
@@ -136,3 +138,66 @@ (await plugin.onContextBuilding({ | ||
}; | ||
const beforeExecuteCalls = serverOptions.plugins.filter(p => p.onExecute); | ||
const beforeExecuteCalls = plugins.filter(p => p.onExecute); | ||
const beforeSubscribeCalls = plugins.filter(p => p.onSubscribe); | ||
const customSubscribe = async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, subscribeFieldResolver) => { | ||
const args = argsOrSchema instanceof GraphQLSchema | ||
? { | ||
schema: argsOrSchema, | ||
document, | ||
rootValue, | ||
contextValue, | ||
variableValues, | ||
operationName, | ||
fieldResolver, | ||
subscribeFieldResolver, | ||
} | ||
: argsOrSchema; | ||
const onResolversHandlers = []; | ||
let subscribeFn = subscribe; | ||
const afterCalls = []; | ||
let context = args.contextValue; | ||
for (const plugin of beforeSubscribeCalls) { | ||
const after = plugin.onSubscribe({ | ||
subscribeFn, | ||
setSubscribeFn: newSubscribeFn => { | ||
subscribeFn = newSubscribeFn; | ||
}, | ||
extendContext: extension => { | ||
if (typeof extension === 'object') { | ||
context = { | ||
...(context || {}), | ||
...extension, | ||
}; | ||
} | ||
else { | ||
throw new Error(`Invalid context extension provided! Expected "object", got: "${JSON.stringify(extension)}" (${typeof extension})`); | ||
} | ||
}, | ||
args, | ||
}); | ||
if (after) { | ||
if (after.onSubscribeResult) { | ||
afterCalls.push(after.onSubscribeResult); | ||
} | ||
if (after.onResolverCalled) { | ||
onResolversHandlers.push(after.onResolverCalled); | ||
} | ||
} | ||
} | ||
if (onResolversHandlers.length) { | ||
context[resolversHooksSymbol] = onResolversHandlers; | ||
} | ||
let result = await subscribeFn({ | ||
...args, | ||
contextValue: context, | ||
}); | ||
for (const afterCb of afterCalls) { | ||
afterCb({ | ||
result, | ||
setResult: newResult => { | ||
result = newResult; | ||
}, | ||
}); | ||
} | ||
return result; | ||
}; | ||
const customExecute = async (argsOrSchema, document, rootValue, contextValue, variableValues, operationName, fieldResolver, typeResolver) => { | ||
@@ -242,3 +307,3 @@ const args = argsOrSchema instanceof GraphQLSchema | ||
initDone = true; | ||
return () => { | ||
const envelop = () => { | ||
prepareSchema(); | ||
@@ -250,5 +315,10 @@ return { | ||
execute: customExecute, | ||
schema, | ||
subscribe: customSubscribe, | ||
get schema() { | ||
return schema; | ||
}, | ||
}; | ||
}; | ||
envelop._plugins = plugins; | ||
return envelop; | ||
} | ||
@@ -273,2 +343,10 @@ | ||
}, | ||
onSubscribe({ args }) { | ||
options.logFn('subscribe-start', { args }); | ||
return { | ||
onSubscribeResult: ({ result }) => { | ||
options.logFn('subscribe-end', { args, result }); | ||
}, | ||
}; | ||
}, | ||
}; | ||
@@ -281,4 +359,5 @@ }; | ||
onExecutionMeasurement: (args, timing) => console.log(`Operation execution "${args.operationName}" done in ${timing.ms}ms`), | ||
onSubscriptionMeasurement: (args, timing) => console.log(`Operation subsctiption "${args.operationName}" done in ${timing.ms}ms`), | ||
onParsingMeasurement: (source, timing) => console.log(`Parsing "${source}" done in ${timing.ms}ms`), | ||
onValidationMeasurement: (document, timing) => { var _a; return console.log(`Validation "${(_a = getOperationAST(document).name) === null || _a === void 0 ? void 0 : _a.value}" done in ${timing.ms}ms`); }, | ||
onValidationMeasurement: (document, timing) => { var _a, _b; return console.log(`Validation "${((_b = (_a = getOperationAST(document)) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.value) || '-'}" done in ${timing.ms}ms`); }, | ||
onResolverMeasurement: (info, timing) => console.log(`\tResolver of "${info.parentType.toString()}.${info.fieldName}" done in ${timing.ms}ms`), | ||
@@ -318,3 +397,3 @@ onContextBuildingMeasurement: (timing) => console.log(`Context building done in ${timing.ms}ms`), | ||
return () => { | ||
options.onValidationMeasurement(params[1], deltaFrom(validateStartTime)); | ||
options.onValidationMeasurement(params.documentAST, deltaFrom(validateStartTime)); | ||
}; | ||
@@ -336,2 +415,16 @@ }, | ||
}, | ||
onSubscribe({ args }) { | ||
const subscribeStartTime = process.hrtime(); | ||
return { | ||
onSubscribeResult: () => { | ||
options.onSubscriptionMeasurement(args, deltaFrom(subscribeStartTime)); | ||
}, | ||
onResolverCalled: ({ info }) => { | ||
const resolverStartTime = process.hrtime(); | ||
return () => { | ||
options.onResolverMeasurement(info, deltaFrom(resolverStartTime)); | ||
}; | ||
}, | ||
}; | ||
}, | ||
}; | ||
@@ -338,0 +431,0 @@ }; |
{ | ||
"name": "@envelop/core", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"sideEffects": false, | ||
"peerDependencies": { | ||
"graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0", | ||
"graphql-helix": "^1.2.0" | ||
"graphql": "^14.0.0 || ^15.0.0" | ||
}, | ||
"dependencies": { | ||
"@envelop/types": "0.0.1" | ||
"@envelop/types": "0.0.2" | ||
}, | ||
@@ -12,0 +11,0 @@ "author": "Dotan Simha <dotansimha@gmail.com>", |
import { Plugin } from '@envelop/types'; | ||
import { DocumentNode, ExecutionArgs, GraphQLResolveInfo, Source } from 'graphql'; | ||
import { DocumentNode, ExecutionArgs, GraphQLResolveInfo, Source, SubscriptionArgs } from 'graphql'; | ||
export declare type ResultTiming = { | ||
@@ -10,2 +10,3 @@ ms: number; | ||
onExecutionMeasurement?: (args: ExecutionArgs, timing: ResultTiming) => void; | ||
onSubscriptionMeasurement?: (args: SubscriptionArgs, timing: ResultTiming) => void; | ||
onParsingMeasurement?: (source: Source | string, timing: ResultTiming) => void; | ||
@@ -12,0 +13,0 @@ onValidationMeasurement?: (document: DocumentNode, timing: ResultTiming) => void; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
96098
28.78%2
-33.33%902
26.33%+ Added
- Removed
- Removed
Updated