Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: no schema required for document object mapping #1160

Merged
merged 2 commits into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const pokemon = Pokemon

type _result = typeof result
const result = await pokemon.mutation.addPokemon({
$: { name: ``, hp: 1, defense: 0, attack: 0, type: `water` },
$: { name: ``, hp: 1, defense: 0, attack: 0, $type: `water` },
// ^^
name: true,
})
Expand Down
4 changes: 2 additions & 2 deletions examples/55_generated/generated_document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ const pokemons = await pokemon.document({
makeSomeNewPokemons: {
addPokemon: [
[`addAngryPikachu`, {
$: { name: `AngryPikachu`, attack: 100, defense: 100, hp: 100, type: `electric` },
$: { name: `AngryPikachu`, attack: 100, defense: 100, hp: 100, $type: `electric` },
name: true,
}],
[`addAngryCharizard`, {
$: { name: `AngryCharizard`, attack: 100, defense: 100, hp: 100, type: `fire` },
$: { name: `AngryCharizard`, attack: 100, defense: 100, hp: 100, $type: `fire` },
name: true,
}],
],
Expand Down
1 change: 1 addition & 0 deletions src/entrypoints/utilities-for-generated.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { type Simplify } from 'type-fest'
export * from '../layers/2_Select/__.js'
export { type SchemaIndex as SchemaIndexBase } from '../layers/4_generator/generators/SchemaIndex.js'
export type {
ConfigGetOutputError,
ResolveOutputReturnRootField,
Expand Down
1 change: 0 additions & 1 deletion src/layers/1_Schema/_.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export { readMaybeThunk, type RootTypeName } from './core/helpers.js'
export * from './core/Index.js'
export * from './core/Named/__.js'
export * as Directives from './Directives.js'
export * from './Hybrid/__.js'
Expand Down
43 changes: 0 additions & 43 deletions src/layers/1_Schema/core/Index.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/layers/1_Schema/core/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { Index } from './Index.js'

export type MaybeThunk<$Type> = $Type | Thunk<$Type>

export type Thunk<$Type> = () => $Type
Expand All @@ -19,4 +17,5 @@ export namespace Base {
}
}

export type RootTypeName = keyof Index['Root']
// todo stop using this, just use the graphql one
export type RootTypeName = 'Query' | 'Mutation' | 'Subscription'
6 changes: 6 additions & 0 deletions src/layers/2_Select/arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ export type ArgValue = string | boolean | null | number | ArgsObject
export type ArgsObject = { [k: string]: ArgValue }

export const key = `$`

export const enumKeyPrefix = `$`

export const enumKeyPrefixPattern = /^\$/g

export const isEnumKey = (key: string) => key.startsWith(enumKeyPrefix)
5 changes: 3 additions & 2 deletions src/layers/3_ResultSet/infer/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import type { Simplify } from 'type-fest'
import type { TSError } from '../../../lib/TSError.js'
import type { Schema } from '../../1_Schema/__.js'
import type { Select } from '../../2_Select/__.js'
import type { SchemaIndex } from '../../4_generator/generators/SchemaIndex.js'
import type { InferInterface, InferObject, InferUnion } from './root.js'

// dprint-ignore
export type InferField<$SelectionSet, $Field extends Schema.SomeField, $Schema extends Schema.Index> =
export type InferField<$SelectionSet, $Field extends Schema.SomeField, $Schema extends SchemaIndex> =
Simplify<
$SelectionSet extends Select.Directive.Include.FieldStates.Negative | Select.Directive.Skip.FieldStates.Positive ?
null :
Expand All @@ -20,7 +21,7 @@ export type InferField<$SelectionSet, $Field extends Schema.SomeField, $Schema e
type InferFieldType<
$SelectionSet,
$Type extends Schema.Output.Any,
$Schema extends Schema.Index
$Schema extends SchemaIndex
> =
$Type extends Schema.__typename<infer $Value> ? $Value :
$Type extends Schema.Output.Nullable<infer $InnerType> ? null | InferFieldType<$SelectionSet, $InnerType, $Schema> :
Expand Down
9 changes: 5 additions & 4 deletions src/layers/3_ResultSet/infer/SelectAlias.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { mergeObjectArray, ValuesOrEmptyObject } from '../../../lib/prelude.js'
import type { Schema } from '../../1_Schema/__.js'
import type { Select } from '../../2_Select/__.js'
import type { SchemaIndex } from '../../4_generator/generators/SchemaIndex.js'
import type { InferField } from './Field.js'

// dprint-ignore
export type InferSelectionSelectAlias<
$SelectionSet,
$Schema extends Schema.Index,
$Schema extends SchemaIndex,
$Node extends Schema.Output.Object$2
> =
ValuesOrEmptyObject<
Expand All @@ -30,7 +31,7 @@ export type InferSelectionSelectAlias<
export type InferSelectAlias<
$SelectAlias extends Select.SelectAlias.SelectAlias,
$FieldName extends string,
$Schema extends Schema.Index,
$Schema extends SchemaIndex,
$Node extends Schema.Output.Object$2,
> =
$SelectAlias extends Select.SelectAlias.SelectAliasOne ? InferSelectAliasOne<$SelectAlias, $FieldName, $Schema, $Node> :
Expand All @@ -40,7 +41,7 @@ export type InferSelectAlias<
type InferSelectAliasMultiple<
$SelectAliasMultiple extends Select.SelectAlias.SelectAliasMultiple,
$FieldName extends string,
$Schema extends Schema.Index,
$Schema extends SchemaIndex,
$Node extends Schema.Output.Object$2,
> = mergeObjectArray<
{
Expand All @@ -51,7 +52,7 @@ type InferSelectAliasMultiple<
type InferSelectAliasOne<
$SelectAliasOne extends Select.SelectAlias.SelectAliasOne,
$FieldName extends string,
$Schema extends Schema.Index,
$Schema extends SchemaIndex,
$Node extends Schema.Output.Object$2,
> = {
[_ in $SelectAliasOne[0]]: InferField<$SelectAliasOne[1], $Node['fields'][$FieldName], $Schema>
Expand Down
25 changes: 13 additions & 12 deletions src/layers/3_ResultSet/infer/root.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ import { AssertIsEqual, type ExcludeNull, type GetKeyOr, type StringKeyof } from
import type { TSError } from '../../../lib/TSError.js'
import type { Schema } from '../../1_Schema/__.js'
import type { Select } from '../../2_Select/__.js'
import type { SchemaIndex } from '../../4_generator/generators/SchemaIndex.js'
import type { InferField } from './Field.js'
import type { InferSelectionSelectAlias } from './SelectAlias.js'

export type RootViaObject<
$SelectionSet,
$Schema extends Schema.Index,
$Schema extends SchemaIndex,
$RootType extends Schema.Output.RootType,
> = InferRoot<
$SelectionSet,
Expand All @@ -16,25 +17,25 @@ export type RootViaObject<
>

// dprint-ignore
export type Query<$SelectionSet, $Schema extends Schema.Index> =
export type Query<$SelectionSet, $Schema extends SchemaIndex> =
InferRoot<$SelectionSet, $Schema, 'Query'>

// dprint-ignore
export type Mutation<$SelectionSet, $Schema extends Schema.Index> =
export type Mutation<$SelectionSet, $Schema extends SchemaIndex> =
InferRoot<$SelectionSet, $Schema, 'Mutation'>

// dprint-ignore
export type Subscription<$SelectionSet, $Schema extends Schema.Index> =
export type Subscription<$SelectionSet, $Schema extends SchemaIndex> =
InferRoot<$SelectionSet, $Schema, 'Subscription'>

export type InferRoot<
$SelectionSet,
$Schema extends Schema.Index,
$Schema extends SchemaIndex,
$RootTypeName extends Schema.RootTypeName,
> = InferObject<$SelectionSet, $Schema, ExcludeNull<$Schema['Root'][$RootTypeName]>>

// dprint-ignore
export type InferObject<$SelectionSet, $Schema extends Schema.Index, $Node extends Schema.Output.Object$2> =
export type InferObject<$SelectionSet, $Schema extends SchemaIndex, $Node extends Schema.Output.Object$2> =
Select.SelectScalarsWildcard.IsSelectScalarsWildcard<$SelectionSet> extends true
// todo what about when scalars wildcard is combined with other fields like relations?
? InferSelectScalarsWildcard<$SelectionSet, $Schema,$Node>
Expand All @@ -45,7 +46,7 @@ export type InferObject<$SelectionSet, $Schema extends Schema.Index, $Node exten
)

// dprint-ignore
type InferSelectionNonSelectAlias<$SelectionSet , $Schema extends Schema.Index, $Node extends Schema.Output.Object$2> =
type InferSelectionNonSelectAlias<$SelectionSet , $Schema extends SchemaIndex, $Node extends Schema.Output.Object$2> =
{
[$Select in PickSelectsPositiveIndicatorAndNotSelectAlias<$SelectionSet>]:
$Select extends keyof $Node['fields']
Expand All @@ -69,14 +70,14 @@ AssertIsEqual<PickSelectsPositiveIndicatorAndNotSelectAlias<{ a: ['b', true]; b:

type InferSelectScalarsWildcard<
$SelectionSet,
$Index extends Schema.Index,
$Index extends SchemaIndex,
$Node extends Schema.Output.Object$2,
> = {
[$Key in keyof PickScalarFields<$Node>]: InferField<$SelectionSet, $Node['fields'][$Key], $Index>
}

// todo could we use this since the valuesoremptyobject could drop the nevers?
// type HandFieldExpressionAliases<$SelectionSet, $Index extends Schema.Index, $Node extends Schema.Output.Object$2> =
// type HandFieldExpressionAliases<$SelectionSet, $Index extends SchemaIndex, $Node extends Schema.Output.Object$2> =
// ValuesOrEmptyObject<
// {
// [$KeyExpression in keyof $SelectionSet & string]:
Expand All @@ -94,15 +95,15 @@ type InferSelectScalarsWildcard<
// >

// dprint-ignore
export type InferUnion<$SelectionSet, $Index extends Schema.Index, $Node extends Schema.Output.Union> =
export type InferUnion<$SelectionSet, $Index extends SchemaIndex, $Node extends Schema.Output.Union> =
InferInlineFragmentTypeConditional<$SelectionSet, $Node['members'][number], $Index>

// dprint-ignore
export type InferInterface<$SelectionSet, $Index extends Schema.Index, $Node extends Schema.Output.Interface> =
export type InferInterface<$SelectionSet, $Index extends SchemaIndex, $Node extends Schema.Output.Interface> =
InferInlineFragmentTypeConditional<$SelectionSet, $Node['implementors'][number], $Index>

// dprint-ignore
type InferInlineFragmentTypeConditional<$SelectionSet, $Node extends Schema.Output.Object$2, $Index extends Schema.Index> =
type InferInlineFragmentTypeConditional<$SelectionSet, $Node extends Schema.Output.Object$2, $Index extends SchemaIndex> =
$Node extends any // force distribution
? InferObject<
& GetKeyOr<
Expand Down
29 changes: 17 additions & 12 deletions src/layers/3_SelectionSetGraphqlMapper/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import type { Schema } from '../1_Schema/__.js'
import type { Select } from '../2_Select/__.js'
import type { CustomScalarsIndex, SchemaIndex } from '../4_generator/generators/SchemaIndex.js'
import { toGraphQLDocument } from './nodes/Document.js'

export const toGraphQL = (input: {
schema: Schema.Index
schema: SchemaIndex
document: Select.Document.DocumentNormalized
customScalarsIndex?: CustomScalarsIndex
// we can probably remove this. was an idea that was aborted. Do we need scalar hook?
// hooks?: Context['hooks']
}) => {
return toGraphQLDocument(
{
schema: input.schema,
captures: {
customScalarOutputs: [],
variables: [],
},
const context = {
schema: input.schema,
captures: {
customScalarOutputs: [],
variables: [],
},
[],
input.document,
)
// hooks: input.hooks,
}

// const location: Location = []
const customScalarsIndex: CustomScalarsIndex = input.customScalarsIndex ?? {}

return toGraphQLDocument(context, customScalarsIndex, input.document)
}
31 changes: 18 additions & 13 deletions src/layers/3_SelectionSetGraphqlMapper/nodes/Argument.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
import { Nodes } from '../../../lib/graphql-plus/_Nodes.js'
import type { Schema } from '../../1_Schema/__.js'
import type { Select } from '../../2_Select/__.js'
import type { GraphQLNodeMapper } from '../types.js'
import { Select } from '../../2_Select/__.js'
import { advanceIndex, type GraphQLNodeMapper } from '../types.js'
import { toGraphQLValue } from './Value.js'

export interface Argument {
name: string
value: Select.Arguments.ArgValue
}

export const toGraphQLArgument: GraphQLNodeMapper<
Nodes.ArgumentNode,
[arg: {
name: string
type: Schema.Input.Any
value: Select.Arguments.ArgValue
}]
[arg: Argument]
> = (
context,
location,
index,
arg,
) => {
return Nodes.Argument({
name: Nodes.Name({ value: arg.name }),
value: toGraphQLValue(context, location, arg.type, arg.value),
})
const value = toGraphQLValue(
{ ...context, value: { isEnum: Select.Arguments.isEnumKey(arg.name) } },
advanceIndex(index, arg.name),
arg.value,
)

const name = Nodes.Name({ value: arg.name.replace(Select.Arguments.enumKeyPrefixPattern, ``) })

return Nodes.Argument({ name, value })
}
2 changes: 1 addition & 1 deletion src/layers/3_SelectionSetGraphqlMapper/nodes/Directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const toGraphQLDirective: GraphQLNodeMapper<
}

// todo lift directive arguments to document variables
const value = toGraphQLValue(context, location, argumentType, argumentValue)
const value = toGraphQLValue({ ...context, value: { isEnum: false } }, location, argumentValue)
return Nodes.Argument({
name: Nodes.Name({
value: argumentName,
Expand Down
10 changes: 6 additions & 4 deletions src/layers/3_SelectionSetGraphqlMapper/nodes/Document.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { print } from 'graphql'
import { describe, expect, test } from 'vitest'
import { db } from '../../../../tests/_/schemas/db.js'
import { $Index as schemaIndex } from '../../../../tests/_/schemas/kitchen-sink/graffle/modules/SchemaRuntime.js'
import { $index as customScalarsIndex } from '../../../../tests/_/schemas/kitchen-sink/graffle/modules/RuntimeCustomScalars.js'
import { $Index as SchemaIndex } from '../../../../tests/_/schemas/kitchen-sink/graffle/modules/SchemaRuntime.js'
import type * as SelectionSets from '../../../../tests/_/schemas/kitchen-sink/graffle/modules/SelectionSets.js'
import { Select } from '../../2_Select/__.js'
import type { Context } from '../types.js'
Expand All @@ -17,7 +18,7 @@ const testEachArguments = [
const [description, selectionSet] = args.length === 1 ? [undefined, args[0]] : args

const context: Context = {
schema: schemaIndex,
schema: SchemaIndex,
captures: {
variables: [],
customScalarOutputs: [],
Expand All @@ -34,7 +35,8 @@ const testEachArguments = [
`Query`,
selectionSet as any,
)
const graphqlDocument = toGraphQLDocument(context, [], documentNormalized)

const graphqlDocument = toGraphQLDocument(context, customScalarsIndex as any, documentNormalized)
const graphqlDocumentStringFormatted = print(graphqlDocument)

const beforeAfter = `\n`
Expand Down Expand Up @@ -69,7 +71,7 @@ describe(`inline fragment`, () => {

describe(`enum`, () => {
test.each<CasesQuery>([
[{ result: { $: { case: `Object1` }, __typename: true } }],
[{ result: { $: { $case: `Object1` }, __typename: true } }],
])(...testEachArguments)
})

Expand Down
Loading