Skip to content

Commit 9870f55

Browse files
authored
feat(extension-system): inject builders (#1298)
1 parent 0787747 commit 9870f55

File tree

6 files changed

+71
-75
lines changed

6 files changed

+71
-75
lines changed

src/extension/TypeHooks.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,12 @@ export namespace States {
4747
export type Empty = TypeHooksEmpty
4848
}
4949

50-
export interface TypeHooksBuilderCallback<$TypeHooks extends TypeHooks> {
51-
(builder: TypeHooksBuilder): TypeHooksBuilder<$TypeHooks>
50+
// todo: type-level only, so can be a proxy that allows anything.
51+
export const typeHooksBuilder: TypeHooksBuilder = {
52+
requestResultDataTypes: () => typeHooksBuilder as any,
53+
onRequestResult: () => typeHooksBuilder as any,
54+
onRequestDocumentRootType: () => typeHooksBuilder as any,
55+
type: null as any,
5256
}
5357

5458
export interface TypeHooksBuilder<$TypeHooks extends TypeHooks = TypeHooksEmpty> {

src/extension/builder.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,12 @@ export type BuilderExtension<
88
& { type: $BuilderExtension }
99

1010
export namespace BuilderExtension {
11-
export interface Creator {
11+
export interface Create {
1212
<$BuilderExtension extends ExtensionChainable>(
1313
interceptor: Interceptor,
1414
): BuilderExtension<$BuilderExtension>
1515
}
16-
export const create: Creator = identity as any
17-
18-
export interface CreatorCallback<$BuilderExtension extends BuilderExtension | undefined> {
19-
(creator: Creator): $BuilderExtension
20-
}
16+
export const create: Create = identity as any
2117

2218
export type Interceptor = (
2319
input: {

src/extension/extension.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import type { RequestPipelineBaseInterceptor } from '../requestPipeline/RequestP
88
import type { Transport } from '../types/Transport.js'
99
import type { Extension } from './__.js'
1010
import { BuilderExtension } from './builder.js'
11-
import type { TypeHooks, TypeHooksEmpty } from './TypeHooks.js'
12-
import type { TypeHooksBuilderCallback } from './TypeHooks.js'
11+
import { type TypeHooks, type TypeHooksBuilder, typeHooksBuilder, type TypeHooksEmpty } from './TypeHooks.js'
1312

1413
export * from './context.js'
1514
export * as TypeHooks from './TypeHooks.js'
@@ -50,10 +49,10 @@ export const create = <
5049
name: $Name
5150
normalizeConfig?: (...args: $ConfigInputParameters) => $Config
5251
custom?: $Custom
53-
create: (params: { config: $Config }) => {
54-
builder?: BuilderExtension.CreatorCallback<$BuilderExtension> // | $BuilderExtension // todo
52+
create: (parameters: { config: $Config; builder: BuilderExtension.Create; typeHooks: TypeHooksBuilder }) => {
53+
builder?: $BuilderExtension
54+
typeHooks?: TypeHooksBuilder<$TypeHooks>
5555
onRequest?: RequestPipelineBaseInterceptor
56-
typeHooks?: TypeHooksBuilderCallback<$TypeHooks> | $TypeHooks
5756
transport?: (
5857
OverloadBuilder: Transport.Builder.Create,
5958
) => $TransportCallbackResult
@@ -81,8 +80,12 @@ export const create = <
8180
> => {
8281
const extensionConstructor = (input?: object) => {
8382
const config: $Config = ((definitionInput.normalizeConfig as any)?.(input) ?? {}) as any // eslint-disable-line
84-
const extensionBuilder = definitionInput.create({ config })
85-
const builder = extensionBuilder.builder?.(BuilderExtension.create)
83+
const extensionBuilder = definitionInput.create({
84+
config,
85+
builder: BuilderExtension.create,
86+
typeHooks: typeHooksBuilder,
87+
})
88+
const builder = extensionBuilder.builder
8689
const overload = extensionBuilder.transport?.((name) =>
8790
Anyware.Overload.create({ discriminant: [`transportType`, name] })
8891
)?.type

src/extensions/Introspection/Introspection.ts

Lines changed: 33 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -27,49 +27,44 @@ export const Introspection = create({
2727
const config = createConfig(input)
2828
return config
2929
},
30-
// todo consider this API:
31-
// create: ({ config, typeHooks }) => {
32-
// return {
33-
// typeHooks: typeHooks<{ ... }>,
34-
create: ({ config }) => {
30+
create: ({ config, builder, typeHooks }) => {
3531
return {
36-
typeHooks: $ => $.requestResultDataTypes<IntrospectionQuery>(),
37-
builder: (builder) =>
38-
builder<BuilderExtension>(({ path, property, client }) => {
39-
if (!(path.length === 0 && property === `introspect`)) return
40-
const clientCatching = client.with({ output: { envelope: false, errors: { execution: `return` } } })
32+
typeHooks: typeHooks.requestResultDataTypes<IntrospectionQuery>(),
33+
builder: builder<BuilderExtension>(({ path, property, client }) => {
34+
if (!(path.length === 0 && property === `introspect`)) return
35+
const clientCatching = client.with({ output: { envelope: false, errors: { execution: `return` } } })
4136

42-
return async () => {
43-
let introspectionQueryDocument = getIntrospectionQuery(config.options)
44-
// @ts-expect-error fixme
45-
const result = await clientCatching.gql(introspectionQueryDocument).send()
46-
const featuresDropped: string[] = []
47-
const enabledKnownPotentiallyUnsupportedFeatures = knownPotentiallyUnsupportedFeatures.filter(_ =>
48-
config.options[_] !== false
49-
)
37+
return async () => {
38+
let introspectionQueryDocument = getIntrospectionQuery(config.options)
39+
// @ts-expect-error fixme
40+
const result = await clientCatching.gql(introspectionQueryDocument).send()
41+
const featuresDropped: string[] = []
42+
const enabledKnownPotentiallyUnsupportedFeatures = knownPotentiallyUnsupportedFeatures.filter(_ =>
43+
config.options[_] !== false
44+
)
5045

51-
// Try to find a working introspection query.
52-
if (result instanceof Error) {
53-
for (const feature of enabledKnownPotentiallyUnsupportedFeatures) {
54-
featuresDropped.push(feature)
55-
introspectionQueryDocument = getIntrospectionQuery({
56-
...config.options,
57-
[feature]: false,
58-
})
59-
// @ts-expect-error fixme
60-
const result = await clientCatching.gql(introspectionQueryDocument).send()
61-
if (!(result instanceof Error)) break
62-
}
46+
// Try to find a working introspection query.
47+
if (result instanceof Error) {
48+
for (const feature of enabledKnownPotentiallyUnsupportedFeatures) {
49+
featuresDropped.push(feature)
50+
introspectionQueryDocument = getIntrospectionQuery({
51+
...config.options,
52+
[feature]: false,
53+
})
54+
// @ts-expect-error fixme
55+
const result = await clientCatching.gql(introspectionQueryDocument).send()
56+
if (!(result instanceof Error)) break
6357
}
64-
65-
// Send the query again with the host configuration for output.
66-
// TODO rather than having to make this query again expose a way to send a value through the output handler here.
67-
// TODO expose the featuresDropped info on the envelope so that upstream can communicate to users what happened
68-
// finally at runtime.
69-
// @ts-expect-error fixme
70-
return await client.gql(introspectionQueryDocument).send()
7158
}
72-
}),
59+
60+
// Send the query again with the host configuration for output.
61+
// TODO rather than having to make this query again expose a way to send a value through the output handler here.
62+
// TODO expose the featuresDropped info on the envelope so that upstream can communicate to users what happened
63+
// finally at runtime.
64+
// @ts-expect-error fixme
65+
return await client.gql(introspectionQueryDocument).send()
66+
}
67+
}),
7368
}
7469
},
7570
})

src/extensions/SchemaErrors/runtime.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,11 @@ export interface SchemaErrors extends Extension {
2323

2424
export const SchemaErrors: () => SchemaErrors = Extension.create({
2525
name: `SchemaErrors`,
26-
create() {
26+
create({ typeHooks }) {
2727
return {
28+
typeHooks: typeHooks
29+
.onRequestDocumentRootType<OnRequestDocumentRootType_>()
30+
.onRequestResult<OnRequestResult_>(),
2831
async onRequest({ pack }) {
2932
const state = pack.input.state
3033
const sddm = state.schemaMap
@@ -82,10 +85,6 @@ export const SchemaErrors: () => SchemaErrors = Extension.create({
8285

8386
return result
8487
},
85-
typeHooks: ($) =>
86-
$
87-
.onRequestDocumentRootType<OnRequestDocumentRootType_>()
88-
.onRequestResult<OnRequestResult_>(),
8988
}
9089
},
9190
})

src/extensions/Throws/Throws.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,26 @@ import type { ConfigManager } from '../../lib/config-manager/__.js'
55

66
export const Throws = create({
77
name: `Throws`,
8-
create: () => {
8+
create: ({ builder }) => {
99
return {
10-
builder: (create) =>
11-
create<BuilderExtension>(({ client, property, path }) => {
12-
if (property !== `throws` || path.length !== 0) return undefined
10+
builder: builder<BuilderExtension>(({ client, property, path }) => {
11+
if (property !== `throws` || path.length !== 0) return undefined
1312

14-
// todo redesign input to allow to force throw always
15-
// todo pull pre-configured config from core
16-
const throwsifiedInput: ConfigInit = {
17-
output: {
18-
envelope: {
19-
enabled: client._.output.envelope.enabled,
20-
// @ts-expect-error
21-
errors: { execution: false, other: false, schema: false },
22-
},
13+
// todo redesign input to allow to force throw always
14+
// todo pull pre-configured config from core
15+
const throwsifiedInput: ConfigInit = {
16+
output: {
17+
envelope: {
18+
enabled: client._.output.envelope.enabled,
2319
// @ts-expect-error
24-
errors: { execution: `throw`, other: `throw`, schema: `throw` },
20+
errors: { execution: false, other: false, schema: false },
2521
},
26-
}
27-
return () => client.with(throwsifiedInput)
28-
}),
22+
// @ts-expect-error
23+
errors: { execution: `throw`, other: `throw`, schema: `throw` },
24+
},
25+
}
26+
return () => client.with(throwsifiedInput)
27+
}),
2928
}
3029
},
3130
})

0 commit comments

Comments
 (0)