Skip to content

Commit

Permalink
refactor: inline custom scalars logic (#1238)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonkuhrt authored Oct 29, 2024
1 parent 4dc1a78 commit ed696db
Show file tree
Hide file tree
Showing 28 changed files with 108 additions and 123 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@ ContextualError: There was an error in the core implementation of hook "exchange
at runPipeline (/some/path/to/runPipeline.ts:XX:XX:18)
at async runPipeline (/some/path/to/runPipeline.ts:XX:XX:14)
at async runPipeline (/some/path/to/runPipeline.ts:XX:XX:14)
at async Object.run (/some/path/to/main.ts:XX:XX:22)
at async Object.send (/some/path/to/gql.ts:XX:XX:26)
... 2 lines matching cause stack trace ...
at async <anonymous> (/some/path/to/output_preset__standard-graphql.ts:XX:XX:16) {
context: { hookName: 'exchange', source: 'implementation' },
[cause]: TypeError: Failed to parse URL from ...
at new Request (node:internal/deps/undici/undici:XX:XX)
at Object.run (/some/path/to/core.ts:XX:XX:29)
at runHook (/some/path/to/runHook.ts:XX:XX:37)
at runHook (/some/path/to/runHook.ts:XX:XX:16) {
... 6 lines matching cause stack trace ...
at async <anonymous> (/some/path/to/output_preset__standard-graphql.ts:XX:XX:16) {
[cause]: TypeError: Invalid URL
at new URL (node:internal/url:XX:XX)
at new Request (node:internal/deps/undici/undici:XX:XX)
at Object.run (/some/path/to/core.ts:XX:XX:29)
at runHook (/some/path/to/runHook.ts:XX:XX:37)
at runHook (/some/path/to/runHook.ts:XX:XX:16) {
at runPipeline (/some/path/to/runPipeline.ts:XX:XX:8)
at runPipeline (/some/path/to/runPipeline.ts:XX:XX:20)
at async runPipeline (/some/path/to/runPipeline.ts:XX:XX:14)
at async Object.run (/some/path/to/main.ts:XX:XX:22)
at async Object.send (/some/path/to/gql.ts:XX:XX:26)
at async <anonymous> (/some/path/to/output_preset__standard-graphql.ts:XX:XX:16) {
code: 'ERR_INVALID_URL',
input: '...'
}
Expand Down
43 changes: 0 additions & 43 deletions src/extensions/CustomScalars/CustomScalars.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect, test } from 'vitest'
import { normalizeOrThrow } from '../../documentBuilder/Select/document.js'
import { SelectionSetGraphqlMapper } from '../../documentBuilder/SelectGraphQLMapper/__.js'
import { graffleMappedResultToRequest } from '../../layers/5_request/core.js'
import { graffleMappedResultToRequest } from '../../layers/6_client/requestMethods/requestMethods.js'
import { injectTypenameOnRootResultFields } from './injectTypenameOnRootResultFields.js'
import { GraffleSchemaErrors } from './tests/fixture/graffle/__.js'

Expand Down
1 change: 0 additions & 1 deletion src/layers/5_request/__.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/layers/6_client/Settings/Config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { GraphQLSchema } from 'graphql'
import type { RequireProperties } from '../../../lib/prelude.js'
import type { TransportHttp, TransportMemory } from '../../../requestPipeline/Transport.js'
import type { GlobalRegistry } from '../../../types/GlobalRegistry/GlobalRegistry.js'
import type { SchemaDrivenDataMap } from '../../../types/SchemaDrivenDataMap/__.js'
import type { TransportHttp, TransportMemory } from '../../5_request/Transport.js'
import type { Extension } from '../extension/extension.js'
import type { TransportHttpInput } from '../transportHttp/request.js'
import type { InputStatic } from './Input.js'
Expand Down
2 changes: 1 addition & 1 deletion src/layers/6_client/Settings/InputToConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { IsUnknown } from 'type-fest'
import type { ConfigManager } from '../../../lib/config-manager/__.js'
import { Transport } from '../../../requestPipeline/Transport.js'
import type { GlobalRegistry } from '../../../types/GlobalRegistry/GlobalRegistry.js'
import { Transport } from '../../5_request/Transport.js'
import { defaultMethodMode } from '../transportHttp/request.js'
import { outputConfigDefault, type TransportConfigHttp, type TransportConfigMemory } from './Config.js'
import type { InputOutputEnvelopeLonghand, InputStatic, URLInput } from './Input.js'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Transport, TransportMemory } from '../../../../requestPipeline/Transport.js'
import type { GlobalRegistry } from '../../../../types/GlobalRegistry/GlobalRegistry.js'
import type { Transport, TransportMemory } from '../../../5_request/Transport.js'
import type { TransportHttpInput } from '../../transportHttp/request.js'
import type { Config } from '../Config.js'
import type { NormalizeInput } from '../InputToConfig.js'
Expand Down
4 changes: 2 additions & 2 deletions src/layers/6_client/client.transport-http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { serveSchema } from '../../../tests/_/lib/serveSchema.js'
import { Graffle as Pokemon } from '../../../tests/_/schemas/pokemon/graffle/__.js'
import { Graffle } from '../../entrypoints/main.js'
import { ACCEPT_REC, CONTENT_TYPE_REC } from '../../lib/grafaid/http/http.js'
import { Transport } from '../5_request/Transport.js'
import { Transport } from '../../requestPipeline/Transport.js'

const schema = new URL(`https://foo.io/api/graphql`)

Expand Down Expand Up @@ -32,7 +32,7 @@ test(`anyware hooks are typed to http transport`, () => {
})

import { schema as schemaPokemon } from '../../../tests/_/schemas/pokemon/schema.js'
import type { CoreExchangeGetRequest, CoreExchangePostRequest } from '../5_request/hooks.js'
import type { CoreExchangeGetRequest, CoreExchangePostRequest } from '../../requestPipeline/hooks.js'

test(`when envelope is used then response property is present even if relying on schema url default`, async () => {
const service = await serveSchema({ schema: schemaPokemon })
Expand Down
2 changes: 1 addition & 1 deletion src/layers/6_client/client.transport-memory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expectTypeOf } from 'vitest'
import { test } from '../../../tests/_/helpers.js'
import { schema } from '../../../tests/_/schemas/kitchen-sink/schema.js'
import { Graffle } from '../../entrypoints/main.js'
import { Transport } from '../5_request/Transport.js'
import { Transport } from '../../requestPipeline/Transport.js'

test(`anyware hooks are typed to memory transport`, () => {
Graffle.create({ schema }).anyware(async ({ encode }) => {
Expand Down
3 changes: 1 addition & 2 deletions src/layers/6_client/client.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { CustomScalars } from '../../extensions/CustomScalars/CustomScalars.js' // todo
import type { ConfigManager } from '../../lib/config-manager/__.js'
import type { Fluent } from '../../lib/fluent/__.js'
import { proxyGet } from '../../lib/prelude.js'
Expand Down Expand Up @@ -56,7 +55,7 @@ type Create = <$Input extends InputStatic>(input: $Input) =>
export const create: Create = (input) => {
const initialState = createState({
name: input.name ?? `default`, // todo import from shared constants
extensions: [CustomScalars()],
extensions: [],
scalars: Schema.Scalar.Registry.empty,
retry: null,
input,
Expand Down
3 changes: 1 addition & 2 deletions src/layers/6_client/clientPrefilled.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { HasRequiredKeys } from 'type-fest'
import { CustomScalars } from '../../extensions/CustomScalars/CustomScalars.js'
import { type Exact } from '../../lib/prelude.js'
import type { GlobalRegistry } from '../../types/GlobalRegistry/GlobalRegistry.js'
import { type Schema } from '../../types/Schema/__.js'
Expand All @@ -16,7 +15,7 @@ export const createPrefilled: CreatePrefilled = (name, schemaMap, scalars, schem
const constructor = (input: any) => { // todo generic input type
const initialState = createState({
name,
extensions: [CustomScalars()],
extensions: [],
scalars,
retry: null,
input: {
Expand Down
4 changes: 2 additions & 2 deletions src/layers/6_client/extension/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import type { FnProperty } from '../../../lib/fluent/Fluent.js'
import type { AssertConstraint } from '../../../lib/prelude.js'
import type { TypeFunction } from '../../../lib/type-function/__.js'
import type { Fn } from '../../../lib/type-function/TypeFunction.js'
import type { RequestPipeline } from '../../../requestPipeline/__.js'
import type { GlobalRegistry } from '../../../types/GlobalRegistry/GlobalRegistry.js'
import type { RequestCore } from '../../5_request/__.js'
import type { Client } from '../client.js'
import type { ClientContext } from '../fluent.js'
import type { GraffleExecutionResultEnvelope } from '../handleOutput.js'
Expand Down Expand Up @@ -77,7 +77,7 @@ interface Base {
/**
* Anyware executed on every request.
*/
onRequest?: Anyware.Extension2<RequestCore.Core>
onRequest?: Anyware.Extension2<RequestPipeline.Core>
/**
* Hook into "get" events on the builder proxy. Useful for adding new methods or manipulating existing ones.
*
Expand Down
4 changes: 2 additions & 2 deletions src/layers/6_client/fluent.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Anyware } from '../../lib/anyware/__.js'
import type { Fluent } from '../../lib/fluent/__.js'
import type { RequestPipeline } from '../../requestPipeline/__.js'
import type { Schema } from '../../types/Schema/__.js'
import type { RequestCore } from '../5_request/__.js'
import type { Extension } from './extension/extension.js'
import type { Config } from './Settings/Config.js'
import type { InputStatic } from './Settings/Input.js'
Expand Down Expand Up @@ -50,7 +50,7 @@ export interface ClientContext {
name: string
input: InputStatic
config: Config
retry: Anyware.Extension2<RequestCore.Core, { retrying: true }> | null
retry: Anyware.Extension2<RequestPipeline.Core, { retrying: true }> | null
extensions: Extension[]
scalars: Schema.Scalar.Registry
}
Expand Down
6 changes: 3 additions & 3 deletions src/layers/6_client/gql/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
joinTemplateStringArrayAndArgs,
type TemplateStringsArguments,
} from '../../../lib/template-string.js'
import { RequestCore } from '../../5_request/__.js' // todo
import { RequestPipeline } from '../../../requestPipeline/__.js' // todo
import { type ClientContext, defineTerminus } from '../fluent.js'
import { handleOutput } from '../handleOutput.js'
import type { Config } from '../Settings/Config.js'
Expand Down Expand Up @@ -65,9 +65,9 @@ export const gqlProperties = defineTerminus((state) => {
schema,
// request,
request: analyzedRequest,
} as RequestCore.Hooks.HookDefEncode<Config>['input']
} as RequestPipeline.Hooks.HookDefEncode<Config>['input']

const result = await RequestCore.anyware.run({
const result = await RequestPipeline.anyware.run({
initialInput,
retryingExtension: state.retry as any,
extensions: state.extensions.filter(_ => _.onRequest !== undefined).map(_ => _.onRequest!) as any,
Expand Down
2 changes: 1 addition & 1 deletion src/layers/6_client/handleOutput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
type GetOrNever,
type Values,
} from '../../lib/prelude.js'
import type { TransportHttp } from '../../requestPipeline/Transport.js'
import type { GlobalRegistry } from '../../types/GlobalRegistry/GlobalRegistry.js'
import type { TransportHttp } from '../5_request/Transport.js'
import type { RunTypeHookOnRequestResult } from './extension/extension.js'
import type { ClientContext } from './fluent.js'
import {
Expand Down
6 changes: 3 additions & 3 deletions src/layers/6_client/properties/anyware.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Anyware, Anyware as AnywareLib } from '../../../lib/anyware/__.js'
import type { Fluent } from '../../../lib/fluent/__.js'
import type { RequestCore } from '../../5_request/__.js'
import type { RequestPipeline } from '../../../requestPipeline/__.js'
import { createExtension } from '../extension/extension.js'
import { defineProperties, type FnParametersProperty } from '../fluent.js'

Expand All @@ -14,13 +14,13 @@ export interface Anyware<$Args extends FnParametersProperty> {
* TODO Anyware Docs.
*/
(
anyware: AnywareLib.Extension2<RequestCore.Core<$Args['state']['context']['config']>>,
anyware: AnywareLib.Extension2<RequestPipeline.Core<$Args['state']['context']['config']>>,
): Fluent.IncrementNothing<$Args>
}

export const anywareProperties = defineProperties((builder, state) => {
return {
anyware: (anyware: Anyware.Extension2<RequestCore.Core>) => {
anyware: (anyware: Anyware.Extension2<RequestPipeline.Core>) => {
return builder({
...state,
extensions: [...state.extensions, createExtension({ name: `InlineAnyware`, onRequest: anyware })],
Expand Down
6 changes: 3 additions & 3 deletions src/layers/6_client/properties/retry.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Anyware } from '../../../lib/anyware/__.js'
import type { Fluent } from '../../../lib/fluent/__.js'
import type { RequestCore } from '../../5_request/__.js'
import type { RequestPipeline } from '../../../requestPipeline/__.js'
import { defineProperties, type FnParametersProperty } from '../fluent.js'

export interface FnRetry extends Fluent.FnProperty<`retry`> {
Expand All @@ -12,12 +12,12 @@ export interface Retry<$Args extends FnParametersProperty> {
/**
* TODO Retry Docs.
*/
(extension: Anyware.Extension2<RequestCore.Core, { retrying: true }>): Fluent.IncrementNothing<$Args>
(extension: Anyware.Extension2<RequestPipeline.Core, { retrying: true }>): Fluent.IncrementNothing<$Args>
}

export const retryProperties = defineProperties((builder, state) => {
return {
retry: (anyware: Anyware.Extension2<RequestCore.Core, { retrying: true }>) => {
retry: (anyware: Anyware.Extension2<RequestPipeline.Core, { retrying: true }>) => {
return builder({ ...state, retry: anyware })
},
}
Expand Down
34 changes: 30 additions & 4 deletions src/layers/6_client/requestMethods/requestMethods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { Select } from '../../../documentBuilder/Select/__.js'
import { SelectionSetGraphqlMapper } from '../../../documentBuilder/SelectGraphQLMapper/__.js'
import type { TypeFunction } from '../../../entrypoints/utilities-for-generated.js'
import type { Fluent } from '../../../lib/fluent/__.js'
import type { Grafaid } from '../../../lib/grafaid/__.js'
import { getOperationDefinition } from '../../../lib/grafaid/document.js'
import { isSymbol } from '../../../lib/prelude.js'
import { RequestPipeline } from '../../../requestPipeline/__.js'
import type { GlobalRegistry } from '../../../types/GlobalRegistry/GlobalRegistry.js'
import { RequestCore } from '../../5_request/__.js'
import { graffleMappedResultToRequest } from '../../5_request/core.js'
import { type ClientContext, defineTerminus } from '../fluent.js'
import { handleOutput } from '../handleOutput.js'
import type { Config } from '../Settings/Config.js'
Expand Down Expand Up @@ -130,13 +131,38 @@ const executeDocument = async (
url,
schema,
request,
} as RequestCore.Hooks.HookDefEncode<Config>['input']
} as RequestPipeline.Hooks.HookDefEncode<Config>['input']

const result = await RequestCore.anyware.run({
const result = await RequestPipeline.anyware.run({
initialInput,
retryingExtension: state.retry as any,
extensions: state.extensions.filter(_ => _.onRequest !== undefined).map(_ => _.onRequest!) as any,
})

return handleOutput(state, result)
}

export const graffleMappedResultToRequest = (
{ document, operationsVariables }: SelectionSetGraphqlMapper.Encoded,
operationName?: string,
): Grafaid.RequestAnalyzedDocumentNodeInput => {
// We get back variables for every operation in the Graffle document.
// However, we only need the variables for the operation that was selected to be executed.
// If there was NO operation name provided then we assume that the first operation in the document is the one that should be executed.
// If there are MULTIPLE operations in the Graffle document AND the user has supplied an invalid operation name (either none or given matches none)
// then what happens here is the variables from one operation can be mixed into another operation.
// This shouldn't matter because such a state would be rejected by the server since it wouldn't know what operation to execute.
const variables_ = operationName
? operationsVariables[operationName]
: Object.values(operationsVariables)[0]

const operation_ = getOperationDefinition({ query: document, operationName })
if (!operation_) throw new Error(`Unknown operation named "${String(operationName)}".`)

return {
operationName,
operation: operation_,
query: document,
variables: variables_,
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
1 change: 1 addition & 0 deletions src/requestPipeline/__.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as RequestPipeline from './_.js'
Loading

0 comments on commit ed696db

Please sign in to comment.