From 95414e5035ef194a1e665bacef47228b9813c9b8 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Tue, 21 May 2024 09:21:51 +0100 Subject: [PATCH] Overhaul legacy support and middleware creation; fix linting. --- grafast/grafast/src/args.ts | 88 +++++++++++---------- grafast/grafast/src/engine/executeBucket.ts | 1 - grafast/grafast/src/execute.ts | 34 ++++---- grafast/grafast/src/grafastGraphql.ts | 33 ++++---- grafast/grafast/src/index.ts | 1 - grafast/grafast/src/interfaces.ts | 2 +- grafast/grafast/src/middlewares.ts | 6 +- grafast/grafast/src/prepare.ts | 1 - grafast/grafast/src/subscribe.ts | 39 ++++----- grafast/grafserv/src/index.ts | 6 +- 10 files changed, 98 insertions(+), 113 deletions(-) diff --git a/grafast/grafast/src/args.ts b/grafast/grafast/src/args.ts index a797c524e1..4e81e9c49b 100644 --- a/grafast/grafast/src/args.ts +++ b/grafast/grafast/src/args.ts @@ -1,6 +1,10 @@ import type { ExecutionArgs } from "graphql"; -import type { GrafastExecutionArgs, PromiseOrDirect } from "./interfaces.js"; +import type { + GrafastExecutionArgs, + PrepareArgsEvent, + PromiseOrDirect, +} from "./interfaces.js"; import { $$hooked } from "./interfaces.js"; import { getMiddlewares } from "./middlewares.js"; import { isPromiseLike } from "./utils.js"; @@ -26,61 +30,63 @@ export function hookArgs( legacyResolvedPreset?: GraphileConfig.ResolvedPreset, legacyCtx?: Partial, ): PromiseOrDirect { - if ( - legacyResolvedPreset !== undefined || - legacyCtx !== undefined || - rawArgs.middlewares === undefined - ) { - rawArgs.resolvedPreset = rawArgs.resolvedPreset ?? legacyResolvedPreset; + if (legacyResolvedPreset !== undefined) { + rawArgs.resolvedPreset = legacyResolvedPreset; + } + if (legacyCtx !== undefined) { rawArgs.requestContext = rawArgs.requestContext ?? legacyCtx; - rawArgs.middlewares = - rawArgs.middlewares === undefined && rawArgs.resolvedPreset != null - ? getMiddlewares(rawArgs.resolvedPreset) - : rawArgs.middlewares; } - const args = rawArgs as Grafast.ExecutionArgs; const { + middlewares: rawMiddlewares, resolvedPreset, - requestContext: ctx = EMPTY_OBJECT, - middlewares, - } = args; + contextValue: rawContextValue, + } = rawArgs; + // Make context mutable + rawArgs.contextValue = Object.assign(Object.create(null), rawContextValue); + const middlewares = + rawMiddlewares === undefined && resolvedPreset != null + ? getMiddlewares(resolvedPreset) + : rawMiddlewares ?? null; + if (rawMiddlewares === undefined) { + rawArgs.middlewares = middlewares; + } + const args = rawArgs as Grafast.ExecutionArgs; // Assert that args haven't already been hooked if (args[$$hooked]) { throw new Error("Must not call hookArgs twice!"); } args[$$hooked] = true; - // Make context mutable - args.contextValue = Object.assign(Object.create(null), args.contextValue); + if (middlewares) { + return middlewares.run("prepareArgs", { args }, finalizeWithEvent); + } else { + return finalize(args); + } +} - // finalize(args): args is deliberately shadowed - const finalize = (args: Grafast.ExecutionArgs) => { - const userContext = resolvedPreset?.grafast?.context; - if (typeof userContext === "function") { - const result = userContext(ctx, args); - if (isPromiseLike(result)) { - // Deliberately shadowed 'result' - return result.then((result) => { - Object.assign(args.contextValue as Partial, result); - return args; - }); - } else { - Object.assign(args.contextValue as Partial, result); +function finalize(args: Grafast.ExecutionArgs) { + const userContext = args.resolvedPreset?.grafast?.context; + const contextValue = args.contextValue as Partial; + if (typeof userContext === "function") { + const result = userContext(args.requestContext ?? EMPTY_OBJECT, args); + if (isPromiseLike(result)) { + // Deliberately shadowed 'result' + return result.then((result) => { + Object.assign(contextValue, result); return args; - } - } else if (typeof userContext === "object" && userContext !== null) { - Object.assign(args.contextValue as Partial, userContext); - return args; + }); } else { + Object.assign(contextValue, result); return args; } - }; - - if (middlewares) { - return middlewares.run("prepareArgs", { args }, ({ args }) => - finalize(args), - ); + } else if (typeof userContext === "object" && userContext !== null) { + Object.assign(contextValue, userContext); + return args; } else { - return finalize(args); + return args; } } + +function finalizeWithEvent(event: PrepareArgsEvent) { + return finalize(event.args); +} diff --git a/grafast/grafast/src/engine/executeBucket.ts b/grafast/grafast/src/engine/executeBucket.ts index ba849b0881..8cd63c60c7 100644 --- a/grafast/grafast/src/engine/executeBucket.ts +++ b/grafast/grafast/src/engine/executeBucket.ts @@ -13,7 +13,6 @@ import type { ExecutionExtra, ExecutionValue, ForcedValues, - GrafastExecutionArgs, GrafastInternalResultsOrStream, GrafastResultsList, GrafastResultStreamList, diff --git a/grafast/grafast/src/execute.ts b/grafast/grafast/src/execute.ts index f9ea88abca..2640cc433f 100644 --- a/grafast/grafast/src/execute.ts +++ b/grafast/grafast/src/execute.ts @@ -120,24 +120,24 @@ export function execute( ): PromiseOrValue< ExecutionResult | AsyncGenerator > { - if ( - legacyResolvedPreset !== undefined || - legacyOutputDataAsString !== undefined || - args.middlewares === undefined - ) { - const resolvedPreset = args.resolvedPreset ?? legacyResolvedPreset; - const middlewares = - args.middlewares === undefined && resolvedPreset != null - ? getMiddlewares(resolvedPreset) - : args.middlewares; - return execute({ - ...args, - resolvedPreset, - middlewares, - }); + // TODO: remove legacy compatibility + if (legacyResolvedPreset !== undefined) { + args.resolvedPreset = legacyResolvedPreset; + } + if (legacyOutputDataAsString !== undefined) { + args.outputDataAsString = legacyOutputDataAsString; + } + + const { resolvedPreset } = args; + const middlewares = + args.middlewares === undefined && resolvedPreset != null + ? getMiddlewares(resolvedPreset) + : args.middlewares ?? null; + if (args.middlewares === undefined) { + args.middlewares = middlewares; } - if (args.middlewares != null) { - return args.middlewares.run("execute", { args }, executeMiddlewareCallback); + if (middlewares !== null) { + return middlewares.run("execute", { args }, executeMiddlewareCallback); } else { return withGrafastArgs(args); } diff --git a/grafast/grafast/src/grafastGraphql.ts b/grafast/grafast/src/grafastGraphql.ts index 1fc50f1574..51bddcbb6c 100644 --- a/grafast/grafast/src/grafastGraphql.ts +++ b/grafast/grafast/src/grafastGraphql.ts @@ -2,7 +2,6 @@ import LRU from "@graphile/lru"; import type { AsyncExecutionResult, DocumentNode, - ExecutionArgs, ExecutionResult, GraphQLSchema, } from "graphql"; @@ -140,24 +139,14 @@ export function grafast( ): PromiseOrValue< ExecutionResult | AsyncGenerator > { - if ( - legacyResolvedPreset !== undefined || - legacyCtx !== undefined || - args.middlewares === undefined - ) { - const resolvedPreset = args.resolvedPreset ?? legacyResolvedPreset; - const requestContext = args.requestContext ?? legacyCtx; - const middlewares = - args.middlewares === undefined && resolvedPreset != null - ? getMiddlewares(resolvedPreset) - : args.middlewares; - return grafast({ - ...args, - resolvedPreset, - requestContext, - middlewares, - }); + // Convert legacy args to properties on `args`: + if (legacyResolvedPreset !== undefined) { + args.resolvedPreset = args.resolvedPreset ?? legacyResolvedPreset; } + if (legacyCtx !== undefined) { + args.requestContext = args.requestContext ?? legacyCtx; + } + const { schema, source, @@ -169,8 +158,14 @@ export function grafast( typeResolver, resolvedPreset, requestContext, - middlewares, + middlewares: rawMiddlewares, } = args; + const middlewares = + rawMiddlewares !== undefined + ? rawMiddlewares + : resolvedPreset != null + ? getMiddlewares(resolvedPreset) + : null; // Validate Schema const schemaValidationErrors = middlewares diff --git a/grafast/grafast/src/index.ts b/grafast/grafast/src/index.ts index 612ccedb8d..3ece71f2f5 100644 --- a/grafast/grafast/src/index.ts +++ b/grafast/grafast/src/index.ts @@ -5,7 +5,6 @@ import debugFactory from "debug"; import type { CallbackOrDescriptor, MiddlewareNext } from "graphile-config"; import type { DocumentNode, - ExecutionArgs as GraphQLExecutionArgs, GraphQLError, OperationDefinitionNode, } from "graphql"; diff --git a/grafast/grafast/src/interfaces.ts b/grafast/grafast/src/interfaces.ts index 2dc8f9d3c5..a1a4d2ff04 100644 --- a/grafast/grafast/src/interfaces.ts +++ b/grafast/grafast/src/interfaces.ts @@ -933,7 +933,7 @@ export type StreamMoreableArray = Array & { export interface GrafastArgs extends GraphQLArgs { resolvedPreset?: GraphileConfig.ResolvedPreset; requestContext?: Partial; - middlewares?: Middlewares; + middlewares?: Middlewares | null; } export type Maybe = T | null | undefined; diff --git a/grafast/grafast/src/middlewares.ts b/grafast/grafast/src/middlewares.ts index f9a64d857b..c2e0c40a73 100644 --- a/grafast/grafast/src/middlewares.ts +++ b/grafast/grafast/src/middlewares.ts @@ -1,8 +1,4 @@ -import { - type MiddlewareNext, - Middlewares, - orderedApply, -} from "graphile-config"; +import { Middlewares, orderedApply } from "graphile-config"; const $$middleware = Symbol("middleware"); export function getMiddlewares( diff --git a/grafast/grafast/src/prepare.ts b/grafast/grafast/src/prepare.ts index c538cb8ee5..b02950c19f 100644 --- a/grafast/grafast/src/prepare.ts +++ b/grafast/grafast/src/prepare.ts @@ -1,4 +1,3 @@ -import type { ExecutionArgs } from "graphql"; import * as graphql from "graphql"; import type { AsyncExecutionResult, diff --git a/grafast/grafast/src/subscribe.ts b/grafast/grafast/src/subscribe.ts index ca1a044526..771e922013 100644 --- a/grafast/grafast/src/subscribe.ts +++ b/grafast/grafast/src/subscribe.ts @@ -5,7 +5,6 @@ import type { } from "graphql"; import type { PromiseOrValue } from "graphql/jsutils/PromiseOrValue"; -import { NULL_PRESET } from "./config.js"; import { withGrafastArgs } from "./execute.js"; import type { GrafastExecutionArgs } from "./index.js"; import type { SubscribeEvent } from "./interfaces.js"; @@ -41,28 +40,24 @@ export function subscribe( | AsyncGenerator | ExecutionResult > { - if ( - legacyResolvedPreset !== undefined || - legacyOutputDataAsString !== undefined || - args.middlewares === undefined - ) { - const resolvedPreset = args.resolvedPreset ?? legacyResolvedPreset; - const middlewares = - args.middlewares === undefined && resolvedPreset != null - ? getMiddlewares(resolvedPreset) - : args.middlewares; - return subscribe({ - ...args, - resolvedPreset, - middlewares, - }); + // TODO: remove legacy compatibility + if (legacyResolvedPreset !== undefined) { + args.resolvedPreset = legacyResolvedPreset; } - if (args.middlewares != null) { - return args.middlewares.run( - "subscribe", - { args }, - subscribeMiddlewareCallback, - ); + if (legacyOutputDataAsString !== undefined) { + args.outputDataAsString = legacyOutputDataAsString; + } + + const { resolvedPreset } = args; + const middlewares = + args.middlewares === undefined && resolvedPreset != null + ? getMiddlewares(resolvedPreset) + : args.middlewares ?? null; + if (args.middlewares === undefined) { + args.middlewares = middlewares; + } + if (middlewares !== null) { + return middlewares.run("subscribe", { args }, subscribeMiddlewareCallback); } else { return withGrafastArgs(args); } diff --git a/grafast/grafserv/src/index.ts b/grafast/grafserv/src/index.ts index 274abdb92b..9f30b93a0d 100644 --- a/grafast/grafserv/src/index.ts +++ b/grafast/grafserv/src/index.ts @@ -1,10 +1,6 @@ import type { PromiseOrDirect } from "grafast"; import type { ExecutionArgs, GraphQLError } from "grafast/graphql"; -import type { - CallbackOrDescriptor, - MiddlewareNext, - PluginHook, -} from "graphile-config"; +import type { CallbackOrDescriptor, MiddlewareNext } from "graphile-config"; import type { RuruHTMLParts } from "ruru/server"; import type {