From c1861d2a9f14b2612e889a15431c104bdcbdee4d Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Wed, 18 Sep 2024 13:13:32 -0400 Subject: [PATCH] fix: generated code use given name (#1103) --- .../$/generated-clients/atlas/modules/Data.ts | 3 + .../generated-clients/atlas/modules/Global.ts | 4 +- .../atlas/modules/SchemaBuildtime.ts | 60 ++--- .../atlas/modules/SchemaIndex.ts | 5 +- .../atlas/modules/SchemaRuntime.ts | 60 +++-- .../generated-clients/atlas/modules/Select.ts | 3 +- .../generated-clients/pokemon/modules/Data.ts | 3 + .../pokemon/modules/Global.ts | 4 +- .../pokemon/modules/SchemaBuildtime.ts | 22 +- .../pokemon/modules/SchemaIndex.ts | 5 +- .../pokemon/modules/SchemaRuntime.ts | 21 +- .../pokemon/modules/Select.ts | 3 +- ...tension_headers__dynamicHeaders.output.txt | 2 +- .../20_output/output_envelope.output.txt | 10 +- ...on_opentelemetry__opentelemetry.output.txt | 58 ++-- package.json | 2 +- src/layers/1_Schema/Args.ts | 20 +- src/layers/1_Schema/Field.ts | 17 +- src/layers/1_Schema/Hybrid/types/Enum.ts | 2 +- src/layers/1_Schema/Input/Input.ts | 2 +- .../1_Schema/Input/types/InputObject.ts | 12 +- src/layers/1_Schema/Output/types/Interface.ts | 9 +- src/layers/1_Schema/Output/types/Object.ts | 15 ++ src/layers/1_Schema/core/Index.ts | 7 +- .../__snapshots__/files.test.ts.snap | 253 ++++++++++-------- src/layers/2_generator/code/Client.ts | 2 +- src/layers/2_generator/code/Data.ts | 15 ++ .../2_generator/code/SchemaBuildtime.ts | 64 +++-- src/layers/2_generator/code/SchemaIndex.ts | 35 ++- src/layers/2_generator/code/SchemaRuntime.ts | 31 ++- src/layers/2_generator/code/Select.ts | 8 +- src/layers/2_generator/code/__.ts | 2 +- src/layers/2_generator/code/global.ts | 8 +- src/layers/2_generator/generateCode.ts | 6 +- src/layers/3_SelectionSet/encode.test.ts | 4 +- src/layers/3_SelectionSet/encode.ts | 12 +- src/layers/3_SelectionSet/types.ts | 78 +++--- src/layers/4_ResultSet/types.test-d.ts | 5 +- src/layers/4_ResultSet/types.ts | 9 +- src/layers/6_client/RootTypeMethods.ts | 69 +++-- src/layers/6_client/Settings/Config.ts | 6 +- src/layers/6_client/client.error.test-d.ts | 4 +- src/layers/6_client/document.ts | 19 +- src/layers/6_client/rootTypeMethods.test-d.ts | 3 +- src/lib/Code.ts | 1 + src/lib/graphql.ts | 17 +- tests/_/schema/generated/modules/Data.ts | 3 + tests/_/schema/generated/modules/Global.ts | 4 +- .../generated/modules/SchemaBuildtime.ts | 122 ++++----- .../_/schema/generated/modules/SchemaIndex.ts | 5 +- .../schema/generated/modules/SchemaRuntime.ts | 123 ++++++--- tests/_/schema/generated/modules/Select.ts | 3 +- .../generated/modules/Data.ts | 3 + .../generated/modules/Global.ts | 4 +- .../generated/modules/SchemaBuildtime.ts | 2 +- .../generated/modules/SchemaIndex.ts | 5 +- .../generated/modules/SchemaRuntime.ts | 7 +- .../generated/modules/Select.ts | 3 +- .../schemaQueryOnly/generated/modules/Data.ts | 3 + .../generated/modules/Global.ts | 4 +- .../generated/modules/SchemaBuildtime.ts | 2 +- .../generated/modules/SchemaIndex.ts | 5 +- .../generated/modules/SchemaRuntime.ts | 7 +- .../generated/modules/Select.ts | 3 +- tsconfig.diagnostic.json | 35 +++ .../extension/opentelemetry.detail.md | 58 ++-- .../examples/extension/opentelemetry.md | 58 ++-- .../examples/output/envelope.detail.md | 10 +- .../_snippets/examples/output/envelope.md | 10 +- .../transport-http/dynamic-headers.detail.md | 2 +- .../transport-http/dynamic-headers.md | 2 +- .../transport-http/method-get.detail.md | 70 +++-- .../examples/transport-http/method-get.md | 70 +++-- .../10_transport-http/dynamic-headers.md | 2 +- .../examples/10_transport-http/method-get.md | 70 +++-- .../content/examples/20_output/envelope.md | 10 +- .../examples/60_extension/opentelemetry.md | 58 ++-- website/graffle/modules/Data.ts | 3 + website/graffle/modules/Global.ts | 4 +- website/graffle/modules/SchemaBuildtime.ts | 60 ++--- website/graffle/modules/SchemaIndex.ts | 5 +- website/graffle/modules/SchemaRuntime.ts | 60 +++-- website/graffle/modules/Select.ts | 3 +- website/pokemon/modules/Data.ts | 3 + website/pokemon/modules/Global.ts | 4 +- website/pokemon/modules/SchemaBuildtime.ts | 22 +- website/pokemon/modules/SchemaIndex.ts | 5 +- website/pokemon/modules/SchemaRuntime.ts | 21 +- website/pokemon/modules/Select.ts | 3 +- 89 files changed, 1195 insertions(+), 761 deletions(-) create mode 100644 examples/$/generated-clients/atlas/modules/Data.ts create mode 100644 examples/$/generated-clients/pokemon/modules/Data.ts create mode 100644 src/layers/2_generator/code/Data.ts create mode 100644 tests/_/schema/generated/modules/Data.ts create mode 100644 tests/_/schemaMutationOnly/generated/modules/Data.ts create mode 100644 tests/_/schemaQueryOnly/generated/modules/Data.ts create mode 100644 tsconfig.diagnostic.json create mode 100644 website/graffle/modules/Data.ts create mode 100644 website/pokemon/modules/Data.ts diff --git a/examples/$/generated-clients/atlas/modules/Data.ts b/examples/$/generated-clients/atlas/modules/Data.ts new file mode 100644 index 000000000..12232cc20 --- /dev/null +++ b/examples/$/generated-clients/atlas/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `Atlas` + +export type Name = 'Atlas' diff --git a/examples/$/generated-clients/atlas/modules/Global.ts b/examples/$/generated-clients/atlas/modules/Global.ts index a16b70a02..eb7c587f5 100644 --- a/examples/$/generated-clients/atlas/modules/Global.ts +++ b/examples/$/generated-clients/atlas/modules/Global.ts @@ -1,10 +1,12 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' declare global { export namespace GraffleGlobalTypes { export interface Schemas { Atlas: { - name: 'Atlas' + name: Data.Name index: Index customScalars: {} featureOptions: { diff --git a/examples/$/generated-clients/atlas/modules/SchemaBuildtime.ts b/examples/$/generated-clients/atlas/modules/SchemaBuildtime.ts index ebd894346..b0edadca2 100644 --- a/examples/$/generated-clients/atlas/modules/SchemaBuildtime.ts +++ b/examples/$/generated-clients/atlas/modules/SchemaBuildtime.ts @@ -6,42 +6,42 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ continent: $.Field< $.Output.Nullable, $.Args<{ - code: $Scalar.ID - }> + code: $.Input.Field<$Scalar.ID> + }, false> > continents: $.Field< $.Output.List, $.Args<{ - filter: $.Input.Nullable - }> + filter: $.Input.Field<$.Input.Nullable> + }, true> > countries: $.Field< $.Output.List, $.Args<{ - filter: $.Input.Nullable - }> + filter: $.Input.Field<$.Input.Nullable> + }, true> > country: $.Field< $.Output.Nullable, $.Args<{ - code: $Scalar.ID - }> + code: $.Input.Field<$Scalar.ID> + }, false> > language: $.Field< $.Output.Nullable, $.Args<{ - code: $Scalar.ID - }> + code: $.Input.Field<$Scalar.ID> + }, false> > languages: $.Field< $.Output.List, $.Args<{ - filter: $.Input.Nullable - }> + filter: $.Input.Field<$.Input.Nullable> + }, true> > }> } @@ -60,27 +60,27 @@ export namespace Enum { export namespace InputObject { export type ContinentFilterInput = $.InputObject<'ContinentFilterInput', { - code: $.Input.Nullable - }> + code: $.Input.Field<$.Input.Nullable> + }, true> export type CountryFilterInput = $.InputObject<'CountryFilterInput', { - code: $.Input.Nullable - continent: $.Input.Nullable - currency: $.Input.Nullable - name: $.Input.Nullable - }> + code: $.Input.Field<$.Input.Nullable> + continent: $.Input.Field<$.Input.Nullable> + currency: $.Input.Field<$.Input.Nullable> + name: $.Input.Field<$.Input.Nullable> + }, true> export type LanguageFilterInput = $.InputObject<'LanguageFilterInput', { - code: $.Input.Nullable - }> + code: $.Input.Field<$.Input.Nullable> + }, true> export type StringQueryOperatorInput = $.InputObject<'StringQueryOperatorInput', { - eq: $.Input.Nullable<$Scalar.String> - in: $.Input.Nullable<$.Input.List<$Scalar.String>> - ne: $.Input.Nullable<$Scalar.String> - nin: $.Input.Nullable<$.Input.List<$Scalar.String>> - regex: $.Input.Nullable<$Scalar.String> - }> + eq: $.Input.Field<$.Input.Nullable<$Scalar.String>> + in: $.Input.Field<$.Input.Nullable<$.Input.List<$Scalar.String>>> + ne: $.Input.Field<$.Input.Nullable<$Scalar.String>> + nin: $.Input.Field<$.Input.Nullable<$.Input.List<$Scalar.String>>> + regex: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> } // ------------------------------------------------------------ // @@ -115,8 +115,8 @@ export namespace Object { name: $.Field< $Scalar.String, $.Args<{ - lang: $.Input.Nullable<$Scalar.String> - }> + lang: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > native: $.Field<$Scalar.String, null> phone: $.Field<$Scalar.String, null> diff --git a/examples/$/generated-clients/atlas/modules/SchemaIndex.ts b/examples/$/generated-clients/atlas/modules/SchemaIndex.ts index 42a6539ce..730507977 100644 --- a/examples/$/generated-clients/atlas/modules/SchemaIndex.ts +++ b/examples/$/generated-clients/atlas/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'Atlas' + name: Data.Name RootTypesPresent: ['Query'] + RootUnion: Schema.Root.Query Root: { Query: Schema.Root.Query Mutation: null diff --git a/examples/$/generated-clients/atlas/modules/SchemaRuntime.ts b/examples/$/generated-clients/atlas/modules/SchemaRuntime.ts index 4f4d2dffe..48b57e75c 100644 --- a/examples/$/generated-clients/atlas/modules/SchemaRuntime.ts +++ b/examples/$/generated-clients/atlas/modules/SchemaRuntime.ts @@ -1,32 +1,34 @@ /* eslint-disable */ import * as $ from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = new URL('https://countries.trevorblades.com/graphql') export const ContinentFilterInput = $.InputObject(`ContinentFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) + code: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), +}, true) export const CountryFilterInput = $.InputObject(`CountryFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), - continent: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), - currency: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), - name: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) + code: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), + continent: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), + currency: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), + name: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), +}, true) export const LanguageFilterInput = $.InputObject(`LanguageFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) + code: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), +}, true) export const StringQueryOperatorInput = $.InputObject(`StringQueryOperatorInput`, { - eq: $.Input.field($.Input.Nullable($Scalar.String)), - in: $.Input.field($.Input.Nullable($.Input.List($Scalar.String))), - ne: $.Input.field($.Input.Nullable($Scalar.String)), - nin: $.Input.field($.Input.Nullable($.Input.List($Scalar.String))), - regex: $.Input.field($.Input.Nullable($Scalar.String)), -}) + eq: $.Input.Field($.Input.Nullable($Scalar.String)), + in: $.Input.Field($.Input.Nullable($.Input.List($Scalar.String))), + ne: $.Input.Field($.Input.Nullable($Scalar.String)), + nin: $.Input.Field($.Input.Nullable($.Input.List($Scalar.String))), + regex: $.Input.Field($.Input.Nullable($Scalar.String)), +}, true) // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Continent = $.Object$(`Continent`, { @@ -49,7 +51,7 @@ export const Country = $.Object$(`Country`, { emojiU: $.field($Scalar.String), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. languages: $.field($.Output.List(() => Language)), - name: $.field($Scalar.String, $.Args({ lang: $.Input.Nullable($Scalar.String) })), + name: $.field($Scalar.String, $.Args({ lang: $.Input.Field($.Input.Nullable($Scalar.String)) }, true)), native: $.field($Scalar.String), phone: $.field($Scalar.String), phones: $.field($.Output.List($Scalar.String)), @@ -85,22 +87,32 @@ export const Subdivision = $.Object$(`Subdivision`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Query = $.Object$(`Query`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - continent: $.field($.Output.Nullable(() => Continent), $.Args({ code: $Scalar.ID })), + continent: $.field($.Output.Nullable(() => Continent), $.Args({ code: $.Input.Field($Scalar.ID) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - continents: $.field($.Output.List(() => Continent), $.Args({ filter: $.Input.Nullable(ContinentFilterInput) })), + continents: $.field( + $.Output.List(() => Continent), + $.Args({ filter: $.Input.Field($.Input.Nullable(ContinentFilterInput)) }, true), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - countries: $.field($.Output.List(() => Country), $.Args({ filter: $.Input.Nullable(CountryFilterInput) })), + countries: $.field( + $.Output.List(() => Country), + $.Args({ filter: $.Input.Field($.Input.Nullable(CountryFilterInput)) }, true), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - country: $.field($.Output.Nullable(() => Country), $.Args({ code: $Scalar.ID })), + country: $.field($.Output.Nullable(() => Country), $.Args({ code: $.Input.Field($Scalar.ID) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - language: $.field($.Output.Nullable(() => Language), $.Args({ code: $Scalar.ID })), + language: $.field($.Output.Nullable(() => Language), $.Args({ code: $.Input.Field($Scalar.ID) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - languages: $.field($.Output.List(() => Language), $.Args({ filter: $.Input.Nullable(LanguageFilterInput) })), + languages: $.field( + $.Output.List(() => Language), + $.Args({ filter: $.Input.Field($.Input.Nullable(LanguageFilterInput)) }, true), + ), }) -export const $Index = { - name: 'Atlas' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation: null, diff --git a/examples/$/generated-clients/atlas/modules/Select.ts b/examples/$/generated-clients/atlas/modules/Select.ts index f44a0acb7..fc968a335 100644 --- a/examples/$/generated-clients/atlas/modules/Select.ts +++ b/examples/$/generated-clients/atlas/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from '../../../../../src/entrypoints/client.js' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // --------- diff --git a/examples/$/generated-clients/pokemon/modules/Data.ts b/examples/$/generated-clients/pokemon/modules/Data.ts new file mode 100644 index 000000000..e48a3cf54 --- /dev/null +++ b/examples/$/generated-clients/pokemon/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `Pokemon` + +export type Name = 'Pokemon' diff --git a/examples/$/generated-clients/pokemon/modules/Global.ts b/examples/$/generated-clients/pokemon/modules/Global.ts index 68fa19cd1..890dd8515 100644 --- a/examples/$/generated-clients/pokemon/modules/Global.ts +++ b/examples/$/generated-clients/pokemon/modules/Global.ts @@ -1,10 +1,12 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' declare global { export namespace GraffleGlobalTypes { export interface Schemas { Pokemon: { - name: 'Pokemon' + name: Data.Name index: Index customScalars: {} featureOptions: { diff --git a/examples/$/generated-clients/pokemon/modules/SchemaBuildtime.ts b/examples/$/generated-clients/pokemon/modules/SchemaBuildtime.ts index d5a1d41dd..0c473d5d9 100644 --- a/examples/$/generated-clients/pokemon/modules/SchemaBuildtime.ts +++ b/examples/$/generated-clients/pokemon/modules/SchemaBuildtime.ts @@ -6,31 +6,31 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Mutation = $.Object$2<'Mutation', { + export type Mutation = $.Output.ObjectMutation<{ addPokemon: $.Field< $.Output.Nullable, $.Args<{ - attack: $Scalar.Int - defense: $Scalar.Int - hp: $Scalar.Int - name: $Scalar.String - }> + attack: $.Input.Field<$Scalar.Int> + defense: $.Input.Field<$Scalar.Int> + hp: $.Input.Field<$Scalar.Int> + name: $.Input.Field<$Scalar.String> + }, false> > }> - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ pokemon: $.Field<$.Output.Nullable<$.Output.List>, null> pokemonByName: $.Field< $.Output.Nullable<$.Output.List>, $.Args<{ - name: $Scalar.String - }> + name: $.Input.Field<$Scalar.String> + }, false> > trainerByName: $.Field< $.Output.Nullable, $.Args<{ - name: $Scalar.String - }> + name: $.Input.Field<$Scalar.String> + }, false> > trainers: $.Field<$.Output.Nullable<$.Output.List>, null> }> diff --git a/examples/$/generated-clients/pokemon/modules/SchemaIndex.ts b/examples/$/generated-clients/pokemon/modules/SchemaIndex.ts index 5956c1ef5..1830dee07 100644 --- a/examples/$/generated-clients/pokemon/modules/SchemaIndex.ts +++ b/examples/$/generated-clients/pokemon/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'Pokemon' + name: Data.Name RootTypesPresent: ['Query', 'Mutation'] + RootUnion: Schema.Root.Query | Schema.Root.Mutation Root: { Query: Schema.Root.Query Mutation: Schema.Root.Mutation diff --git a/examples/$/generated-clients/pokemon/modules/SchemaRuntime.ts b/examples/$/generated-clients/pokemon/modules/SchemaRuntime.ts index f2f99b53f..6ac3fd11c 100644 --- a/examples/$/generated-clients/pokemon/modules/SchemaRuntime.ts +++ b/examples/$/generated-clients/pokemon/modules/SchemaRuntime.ts @@ -1,7 +1,9 @@ /* eslint-disable */ import * as $ from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = undefined @@ -29,7 +31,12 @@ export const Mutation = $.Object$(`Mutation`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. addPokemon: $.field( $.Output.Nullable(() => Pokemon), - $.Args({ attack: $Scalar.Int, defense: $Scalar.Int, hp: $Scalar.Int, name: $Scalar.String }), + $.Args({ + attack: $.Input.Field($Scalar.Int), + defense: $.Input.Field($Scalar.Int), + hp: $.Input.Field($Scalar.Int), + name: $.Input.Field($Scalar.String), + }, false), ), }) @@ -38,16 +45,20 @@ export const Query = $.Object$(`Query`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. pokemon: $.field($.Output.Nullable($.Output.List(() => Pokemon))), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - pokemonByName: $.field($.Output.Nullable($.Output.List(() => Pokemon)), $.Args({ name: $Scalar.String })), + pokemonByName: $.field( + $.Output.Nullable($.Output.List(() => Pokemon)), + $.Args({ name: $.Input.Field($Scalar.String) }, false), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - trainerByName: $.field($.Output.Nullable(() => Trainer), $.Args({ name: $Scalar.String })), + trainerByName: $.field($.Output.Nullable(() => Trainer), $.Args({ name: $.Input.Field($Scalar.String) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. trainers: $.field($.Output.Nullable($.Output.List(() => Trainer))), }) -export const $Index = { - name: 'Pokemon' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query', 'Mutation'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation, diff --git a/examples/$/generated-clients/pokemon/modules/Select.ts b/examples/$/generated-clients/pokemon/modules/Select.ts index 5b68c17af..67ef30da1 100644 --- a/examples/$/generated-clients/pokemon/modules/Select.ts +++ b/examples/$/generated-clients/pokemon/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from '../../../../../src/entrypoints/client.js' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // --------- diff --git a/examples/__outputs__/10_transport-http/transport-http_extension_headers__dynamicHeaders.output.txt b/examples/__outputs__/10_transport-http/transport-http_extension_headers__dynamicHeaders.output.txt index fbcd5f675..084ff576f 100644 --- a/examples/__outputs__/10_transport-http/transport-http_extension_headers__dynamicHeaders.output.txt +++ b/examples/__outputs__/10_transport-http/transport-http_extension_headers__dynamicHeaders.output.txt @@ -4,7 +4,7 @@ headers: Headers { accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', 'content-type': 'application/json', - 'x-sent-at-time': '1726596325884' + 'x-sent-at-time': '1726679254856' }, signal: undefined, method: 'post', diff --git a/examples/__outputs__/20_output/output_envelope.output.txt b/examples/__outputs__/20_output/output_envelope.output.txt index 49daf7048..9e0be5767 100644 --- a/examples/__outputs__/20_output/output_envelope.output.txt +++ b/examples/__outputs__/20_output/output_envelope.output.txt @@ -19,7 +19,7 @@ headers: Headers { connection: 'keep-alive', 'content-length': '119', - 'x-served-by': 'cache-yul1970046-YUL', + 'x-served-by': 'cache-yul1970040-YUL', 'accept-ranges': 'bytes', date: 'Sun, 08 Sep 2024 18:13:26 GMT', 'content-type': 'application/graphql-response+json; charset=utf-8', @@ -32,13 +32,13 @@ 'alt-svc': 'h3=":443"; ma=86400', 'access-control-allow-origin': '*', 'x-powered-by': 'Stellate', - age: '777121', + age: '860051', 'cache-control': 'public, s-maxage=2628000, stale-while-revalidate=2628000', 'x-cache': 'HIT', - 'x-cache-hits': '87', + 'x-cache-hits': '109', 'gcdn-cache': 'HIT', - 'stellate-rate-limit-budget-remaining': '48', - 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=48;refill=60', + 'stellate-rate-limit-budget-remaining': '38', + 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=38;refill=51', 'stellate-rate-limit-decision': 'pass', 'stellate-rate-limit-budget-required': '5', 'content-encoding': 'br' diff --git a/examples/__outputs__/60_extension/extension_opentelemetry__opentelemetry.output.txt b/examples/__outputs__/60_extension/extension_opentelemetry__opentelemetry.output.txt index 0ba02bdb0..23cc21cd3 100644 --- a/examples/__outputs__/60_extension/extension_opentelemetry__opentelemetry.output.txt +++ b/examples/__outputs__/60_extension/extension_opentelemetry__opentelemetry.output.txt @@ -9,14 +9,14 @@ } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'encode', - id: '045b80da91d65b9d', + id: '7c13553177946289', kind: 0, - timestamp: 1726596326575000, - duration: 1290.958, + timestamp: 1726679255958000, + duration: 522.417, attributes: {}, status: { code: 0 }, events: [], @@ -33,14 +33,14 @@ } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'pack', - id: '0854613b629f13f6', + id: '8133f915673ed123', kind: 0, - timestamp: 1726596326600000, - duration: 1107.5, + timestamp: 1726679255960000, + duration: 956.25, attributes: {}, status: { code: 0 }, events: [], @@ -57,14 +57,14 @@ } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'exchange', - id: '1a8a5ce00ea500ed', + id: '1812f1fcab09c9a8', kind: 0, - timestamp: 1726596326602000, - duration: 416840.875, + timestamp: 1726679255962000, + duration: 155840.833, attributes: {}, status: { code: 0 }, events: [], @@ -81,14 +81,14 @@ } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'unpack', - id: '79fc98db2f26ecb0', + id: 'a9f7183565f62ece', kind: 0, - timestamp: 1726596327019000, - duration: 2409.542, + timestamp: 1726679256118000, + duration: 2281.208, attributes: {}, status: { code: 0 }, events: [], @@ -105,14 +105,14 @@ } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'decode', - id: '5785c002db424547', + id: 'f2546a7c36cb5142', kind: 0, - timestamp: 1726596327022000, - duration: 126.584, + timestamp: 1726679256120000, + duration: 123.042, attributes: {}, status: { code: 0 }, events: [], @@ -129,14 +129,14 @@ } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', + traceId: '9052b021c626370eabb7d7fb4f575045', parentId: undefined, traceState: undefined, name: 'request', - id: 'ddcee8d1f8d74086', + id: '51abe3edd132250a', kind: 0, - timestamp: 1726596326573000, - duration: 448707.334, + timestamp: 1726679255958000, + duration: 163055.167, attributes: {}, status: { code: 0 }, events: [], diff --git a/package.json b/package.json index 7a9d819c5..6deb2599b 100644 --- a/package.json +++ b/package.json @@ -83,7 +83,7 @@ "test:unit": "vitest --exclude tests/examples", "test": "vitest", "test:web": "vitest --environment jsdom", - "test:types": "vitest --typecheck", + "test:types": "vitest --typecheck src/**/**/*.test-d.ts", "test:coverage": "pnpm test -- --coverage", "release:stable": "dripip stable", "release:preview": "dripip preview", diff --git a/src/layers/1_Schema/Args.ts b/src/layers/1_Schema/Args.ts index 37ff38842..2f6496294 100644 --- a/src/layers/1_Schema/Args.ts +++ b/src/layers/1_Schema/Args.ts @@ -1,26 +1,26 @@ import type { Input } from './_.js' -import type { Nullable } from './Input/types/Nullable.js' type InputFields = Record -// dprint-ignore -export type InputFieldsAllNullable<$Fields extends InputFields> = - Exclude<$Fields[keyof $Fields], Nullable> extends never ? true : false - -export interface Args<$Fields extends InputFields> { - fields: $Fields +export interface Args<$InputFields extends InputFields, $IsFieldsAllNullable extends boolean = boolean> { + fields: $InputFields + isFieldsAllNullable: $IsFieldsAllNullable } -export const Args = (fields: F): Args => { +export const Args = <$InputFields extends InputFields, const $IsInputFieldsAllNullable extends boolean>( + fields: $InputFields, + isFieldsAllNullable: $IsInputFieldsAllNullable, +): Args<$InputFields, $IsInputFieldsAllNullable> => { return { fields, + isFieldsAllNullable, } } export type OmitNullableFields<$Fields extends InputFields> = { - [Key in keyof $Fields as $Fields[Key] extends Input.Nullable ? never : Key]: $Fields[Key] + [Key in keyof $Fields as $Fields[Key]['type'] extends Input.Nullable ? never : Key]: $Fields[Key] } export type PickNullableFields<$Fields extends InputFields> = { - [Key in keyof $Fields as $Fields[Key] extends Input.Nullable ? Key : never]: $Fields[Key] + [Key in keyof $Fields as $Fields[Key]['type'] extends Input.Nullable ? Key : never]: $Fields[Key] } diff --git a/src/layers/1_Schema/Field.ts b/src/layers/1_Schema/Field.ts index 957f5b3a9..d643ffec0 100644 --- a/src/layers/1_Schema/Field.ts +++ b/src/layers/1_Schema/Field.ts @@ -19,19 +19,18 @@ export const field = <$Type extends Output.Any, $Args extends null | Args = } } -// todo test non null interface fields -export type SomeField = Field< +type FieldType = | Hybrid.Enum | Hybrid.Scalar.Any | Output.List | Output.Nullable | Output.Object$2 | Output.Union - | Output.Interface | null>>, [any, ...any[]]>, - Args | null -> + | Output.Interface | null>>, [any, ...any[]]> -export type SomeFields<$Keys extends string | number | symbol = string | number | symbol> = Record< - $Keys, - SomeField -> +// todo test non null interface fields +export type SomeField = Field | null> + +export type SomeFields<$Keys extends SomeKey = SomeKey> = Record<$Keys, SomeField> + +type SomeKey = string | number | symbol diff --git a/src/layers/1_Schema/Hybrid/types/Enum.ts b/src/layers/1_Schema/Hybrid/types/Enum.ts index 81a096297..725375e64 100644 --- a/src/layers/1_Schema/Hybrid/types/Enum.ts +++ b/src/layers/1_Schema/Hybrid/types/Enum.ts @@ -7,7 +7,7 @@ export interface Enum< members: $Members } -export const Enum = <$Name extends string, $Members extends [string, ...string[]]>( +export const Enum = <$Name extends string, const $Members extends [string, ...string[]]>( name: $Name, members: $Members, ): Enum<$Name, $Members> => ({ diff --git a/src/layers/1_Schema/Input/Input.ts b/src/layers/1_Schema/Input/Input.ts index 3d230bd26..5a5bb91a2 100644 --- a/src/layers/1_Schema/Input/Input.ts +++ b/src/layers/1_Schema/Input/Input.ts @@ -6,7 +6,7 @@ export * from './types/InputObject.js' export * from './types/List.js' export * from './types/Nullable.js' -export const field = <$Type extends Any>(type: MaybeThunk<$Type>): Field<$Type> => { +export const Field = <$Type extends Any>(type: MaybeThunk<$Type>): Field<$Type> => { return { // Thunks do not exist at the type level type: type as any, diff --git a/src/layers/1_Schema/Input/types/InputObject.ts b/src/layers/1_Schema/Input/types/InputObject.ts index c7db110ff..d63a8c110 100644 --- a/src/layers/1_Schema/Input/types/InputObject.ts +++ b/src/layers/1_Schema/Input/types/InputObject.ts @@ -3,19 +3,27 @@ export type InputFields = Record export interface InputObject< $Name extends string = string, $Fields extends InputFields = InputFields, + $IsFieldsAllNullable extends boolean = boolean, > { kind: 'InputObject' name: $Name fields: $Fields + isAllFieldsNullable: $IsFieldsAllNullable } -export const InputObject = <$Name extends string, $Fields extends Record>( +export const InputObject = < + $Name extends string, + $Fields extends Record, + const $IsFieldsAllNullable extends boolean, +>( name: $Name, fields: $Fields, -): InputObject<$Name, $Fields> => ({ + isAllFieldsNullable: $IsFieldsAllNullable, +): InputObject<$Name, $Fields, $IsFieldsAllNullable> => ({ kind: `InputObject`, name: name, fields: { ...fields, }, + isAllFieldsNullable, }) diff --git a/src/layers/1_Schema/Output/types/Interface.ts b/src/layers/1_Schema/Output/types/Interface.ts index 47c5c875c..719eccf5e 100644 --- a/src/layers/1_Schema/Output/types/Interface.ts +++ b/src/layers/1_Schema/Output/types/Interface.ts @@ -1,9 +1,10 @@ -import type { SomeFields } from '../../Field.js' +// import type { SomeFields } from '../../Field.js' import type { Object$2 } from './Object.js' export type Interface< $Name extends string = string, - $Fields extends SomeFields = SomeFields, + // $Fields extends SomeFields = SomeFields, + $Fields extends any = any, $Implementors extends [Object$2, ...Object$2[]] = [Object$2, ...Object$2[]], > = { kind: 'Interface' @@ -14,7 +15,9 @@ export type Interface< export const Interface = < $Name extends string, - $Fields extends SomeFields, + $Fields extends any, + // todo more accurate constraint but leads to incorrectly inferred types. + // $Fields extends SomeFields, $Implementors extends [Object$2, ...Object$2[]], >( name: $Name, diff --git a/src/layers/1_Schema/Output/types/Object.ts b/src/layers/1_Schema/Output/types/Object.ts index 3b21d8a9c..b37895b24 100644 --- a/src/layers/1_Schema/Output/types/Object.ts +++ b/src/layers/1_Schema/Output/types/Object.ts @@ -1,9 +1,24 @@ +import type { RootTypeNameMutation, RootTypeNameQuery, RootTypeNameSubscription } from '../../../../lib/graphql.js' import type { Field, SomeFields } from '../../Field.js' import { field } from '../../Field.js' import type { Hybrid } from '../../Hybrid/__.js' import type { UnwrapToNamed } from '../typeGroups.js' import { __typename } from './__typename.js' +export interface ObjectQuery< + $Fields extends SomeFields = SomeFields, +> extends Object$2 {} + +export interface ObjectMutation< + $Fields extends SomeFields = SomeFields, +> extends Object$2 {} + +export interface ObjectSubscription< + $Fields extends SomeFields = SomeFields, +> extends Object$2 {} + +export type RootType = ObjectQuery | ObjectMutation | ObjectSubscription + export interface Object$2< $Name extends string = string, $Fields extends SomeFields = SomeFields, diff --git a/src/layers/1_Schema/core/Index.ts b/src/layers/1_Schema/core/Index.ts index 4ddd4aff7..c17dea582 100644 --- a/src/layers/1_Schema/core/Index.ts +++ b/src/layers/1_Schema/core/Index.ts @@ -10,10 +10,11 @@ import type { Output } from '../Output/__.js' export interface Index { name: GlobalRegistry.SchemaNames RootTypesPresent: readonly RootTypeName[] + RootUnion: Output.RootType Root: { - Query: null | Output.Object$2 - Mutation: null | Output.Object$2 - Subscription: null | Output.Object$2 + Query: null | Output.ObjectQuery + Mutation: null | Output.ObjectMutation + Subscription: null | Output.ObjectSubscription } objects: Record unions: Record diff --git a/src/layers/2_generator/__snapshots__/files.test.ts.snap b/src/layers/2_generator/__snapshots__/files.test.ts.snap index 7bf67d736..f39b76c56 100644 --- a/src/layers/2_generator/__snapshots__/files.test.ts.snap +++ b/src/layers/2_generator/__snapshots__/files.test.ts.snap @@ -50,13 +50,14 @@ export const isError = <$Value>(value: $Value): value is Include<$Value, ErrorOb exports[`schema2 5`] = ` "import type { ResultSet, SelectionSet } from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from '../../../../../src/entrypoints/client.js' -export const Select = createSelect(\`default\`) +export const Select = createSelect(Data.Name) // Buildtime // --------- @@ -164,11 +165,14 @@ export namespace Select { exports[`schema2 6`] = ` "/* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'default' + name: Data.Name RootTypesPresent: ['Query', 'Mutation'] + RootUnion: Schema.Root.Query | Schema.Root.Mutation Root: { Query: Schema.Root.Query Mutation: Schema.Root.Mutation @@ -231,23 +235,23 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Mutation = $.Object$2<'Mutation', { + export type Mutation = $.Output.ObjectMutation<{ id: $.Field<$.Output.Nullable<$Scalar.ID>, null> idNonNull: $.Field<$Scalar.ID, null> }> - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ InputObjectNested: $.Field< $.Output.Nullable<$Scalar.ID>, $.Args<{ - input: $.Input.Nullable - }> + input: $.Input.Field<$.Input.Nullable> + }, true> > InputObjectNestedNonNull: $.Field< $.Output.Nullable<$Scalar.ID>, $.Args<{ - input: InputObject.InputObjectNestedNonNull - }> + input: $.Input.Field + }, false> > /** * Query enum field documentation. @@ -257,38 +261,38 @@ export namespace Root { dateArg: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.Nullable<$Scalar.Date> - }> + date: $.Input.Field<$.Input.Nullable<$Scalar.Date>> + }, true> > dateArgInputObject: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - input: $.Input.Nullable - }> + input: $.Input.Field<$.Input.Nullable> + }, true> > dateArgList: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.Nullable<$.Input.List<$Scalar.Date>> - }> + date: $.Input.Field<$.Input.Nullable<$.Input.List<$Scalar.Date>>> + }, true> > dateArgNonNull: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $Scalar.Date - }> + date: $.Input.Field<$Scalar.Date> + }, false> > dateArgNonNullList: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.List<$.Input.Nullable<$Scalar.Date>> - }> + date: $.Input.Field<$.Input.List<$.Input.Nullable<$Scalar.Date>>> + }, false> > dateArgNonNullListNonNull: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.List<$Scalar.Date> - }> + date: $.Input.Field<$.Input.List<$Scalar.Date>> + }, false> > dateInterface1: $.Field<$.Output.Nullable, null> dateList: $.Field<$.Output.Nullable<$.Output.List<$Scalar.Date>>, null> @@ -299,8 +303,8 @@ export namespace Root { error: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - case: $.Input.Nullable<$Scalar.String> - }> + case: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > id: $.Field<$.Output.Nullable<$Scalar.ID>, null> idNonNull: $.Field<$Scalar.ID, null> @@ -309,8 +313,8 @@ export namespace Root { interfaceWithArgs: $.Field< $.Output.Nullable, $.Args<{ - id: $Scalar.ID - }> + id: $.Input.Field<$Scalar.ID> + }, false> > listInt: $.Field<$.Output.Nullable<$.Output.List<$.Output.Nullable<$Scalar.Int>>>, null> listIntNonNull: $.Field<$.Output.List<$Scalar.Int>, null> @@ -328,79 +332,79 @@ export namespace Root { objectWithArgs: $.Field< $.Output.Nullable, $.Args<{ - boolean: $.Input.Nullable<$Scalar.Boolean> - float: $.Input.Nullable<$Scalar.Float> - id: $.Input.Nullable<$Scalar.ID> - int: $.Input.Nullable<$Scalar.Int> - string: $.Input.Nullable<$Scalar.String> - }> + boolean: $.Input.Field<$.Input.Nullable<$Scalar.Boolean>> + float: $.Input.Field<$.Input.Nullable<$Scalar.Float>> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + int: $.Input.Field<$.Input.Nullable<$Scalar.Int>> + string: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > result: $.Field< $.Output.Nullable, $.Args<{ - case: Enum.Case - }> + case: $.Input.Field + }, false> > resultNonNull: $.Field< Union.Result, $.Args<{ - case: $.Input.Nullable - }> + case: $.Input.Field<$.Input.Nullable> + }, true> > string: $.Field<$.Output.Nullable<$Scalar.String>, null> stringWithArgEnum: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - ABCEnum: $.Input.Nullable - }> + ABCEnum: $.Input.Field<$.Input.Nullable> + }, true> > stringWithArgInputObject: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - input: $.Input.Nullable - }> + input: $.Input.Field<$.Input.Nullable> + }, true> > stringWithArgInputObjectRequired: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - input: InputObject.InputObject - }> + input: $.Input.Field + }, false> > stringWithArgs: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - boolean: $.Input.Nullable<$Scalar.Boolean> - float: $.Input.Nullable<$Scalar.Float> - id: $.Input.Nullable<$Scalar.ID> - int: $.Input.Nullable<$Scalar.Int> - string: $.Input.Nullable<$Scalar.String> - }> + boolean: $.Input.Field<$.Input.Nullable<$Scalar.Boolean>> + float: $.Input.Field<$.Input.Nullable<$Scalar.Float>> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + int: $.Input.Field<$.Input.Nullable<$Scalar.Int>> + string: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > stringWithListArg: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - ints: $.Input.Nullable<$.Input.List<$.Input.Nullable<$Scalar.Int>>> - }> + ints: $.Input.Field<$.Input.Nullable<$.Input.List<$.Input.Nullable<$Scalar.Int>>>> + }, true> > stringWithListArgRequired: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - ints: $.Input.List<$Scalar.Int> - }> + ints: $.Input.Field<$.Input.List<$Scalar.Int>> + }, false> > stringWithRequiredArg: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - string: $Scalar.String - }> + string: $.Input.Field<$Scalar.String> + }, false> > unionFooBar: $.Field<$.Output.Nullable, null> unionFooBarNonNull: $.Field unionFooBarWithArgs: $.Field< $.Output.Nullable, $.Args<{ - id: $.Input.Nullable<$Scalar.ID> - }> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + }, true> > unionObject: $.Field<$.Output.Nullable, null> unionObjectNonNull: $.Field @@ -431,19 +435,19 @@ export namespace Enum { export namespace InputObject { export type InputObject = $.InputObject<'InputObject', { - date: $.Input.Nullable<$Scalar.Date> - dateRequired: $Scalar.Date - id: $.Input.Nullable<$Scalar.ID> - idRequired: $Scalar.ID - }> + date: $.Input.Field<$.Input.Nullable<$Scalar.Date>> + dateRequired: $.Input.Field<$Scalar.Date> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + idRequired: $.Input.Field<$Scalar.ID> + }, true> export type InputObjectNested = $.InputObject<'InputObjectNested', { - InputObject: $.Input.Nullable - }> + InputObject: $.Input.Field<$.Input.Nullable> + }, true> export type InputObjectNestedNonNull = $.InputObject<'InputObjectNestedNonNull', { - InputObject: InputObject.InputObject - }> + InputObject: $.Input.Field + }, false> } // ------------------------------------------------------------ // @@ -568,26 +572,28 @@ exports[`schema2 9`] = ` "/* eslint-disable */ import * as $ from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = undefined export const ABCEnum = $.Enum(\`ABCEnum\`, [\`A\`, \`B\`, \`C\`]) export const Case = $.Enum(\`Case\`, [\`ErrorOne\`, \`ErrorTwo\`, \`Object1\`]) export const InputObject = $.InputObject(\`InputObject\`, { - date: $.Input.field($.Input.Nullable($Scalar.Date)), - dateRequired: $.Input.field($Scalar.Date), - id: $.Input.field($.Input.Nullable($Scalar.ID)), - idRequired: $.Input.field($Scalar.ID), -}) + date: $.Input.Field($.Input.Nullable($Scalar.Date)), + dateRequired: $.Input.Field($Scalar.Date), + id: $.Input.Field($.Input.Nullable($Scalar.ID)), + idRequired: $.Input.Field($Scalar.ID), +}, true) export const InputObjectNested = $.InputObject(\`InputObjectNested\`, { - InputObject: $.Input.field(() => $.Input.Nullable(InputObject)), -}) + InputObject: $.Input.Field(() => $.Input.Nullable(InputObject)), +}, true) export const InputObjectNestedNonNull = $.InputObject(\`InputObjectNestedNonNull\`, { - InputObject: $.Input.field(() => InputObject), -}) + InputObject: $.Input.Field(() => InputObject), +}, false) // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Bar = $.Object$(\`Bar\`, { @@ -694,20 +700,38 @@ export const Mutation = $.Object$(\`Mutation\`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Query = $.Object$(\`Query\`, { - InputObjectNested: $.field($.Output.Nullable($Scalar.ID), $.Args({ input: $.Input.Nullable(InputObjectNested) })), - InputObjectNestedNonNull: $.field($.Output.Nullable($Scalar.ID), $.Args({ input: InputObjectNestedNonNull })), + InputObjectNested: $.field( + $.Output.Nullable($Scalar.ID), + $.Args({ input: $.Input.Field($.Input.Nullable(InputObjectNested)) }, true), + ), + InputObjectNestedNonNull: $.field( + $.Output.Nullable($Scalar.ID), + $.Args({ input: $.Input.Field(InputObjectNestedNonNull) }, false), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. abcEnum: $.field($.Output.Nullable(ABCEnum)), date: $.field($.Output.Nullable($Scalar.Date)), - dateArg: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.Nullable($Scalar.Date) })), - dateArgInputObject: $.field($.Output.Nullable($Scalar.Date), $.Args({ input: $.Input.Nullable(InputObject) })), - dateArgList: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.Nullable($.Input.List($Scalar.Date)) })), - dateArgNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $Scalar.Date })), + dateArg: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ date: $.Input.Field($.Input.Nullable($Scalar.Date)) }, true), + ), + dateArgInputObject: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ input: $.Input.Field($.Input.Nullable(InputObject)) }, true), + ), + dateArgList: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ date: $.Input.Field($.Input.Nullable($.Input.List($Scalar.Date))) }, true), + ), + dateArgNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.Field($Scalar.Date) }, false)), dateArgNonNullList: $.field( $.Output.Nullable($Scalar.Date), - $.Args({ date: $.Input.List($.Input.Nullable($Scalar.Date)) }), + $.Args({ date: $.Input.Field($.Input.List($.Input.Nullable($Scalar.Date))) }, false), + ), + dateArgNonNullListNonNull: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ date: $.Input.Field($.Input.List($Scalar.Date)) }, false), ), - dateArgNonNullListNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.List($Scalar.Date) })), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. dateInterface1: $.field($.Output.Nullable(() => DateInterface1)), dateList: $.field($.Output.Nullable($.Output.List($Scalar.Date))), @@ -717,7 +741,10 @@ export const Query = $.Object$(\`Query\`, { dateObject1: $.field($.Output.Nullable(() => DateObject1)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. dateUnion: $.field($.Output.Nullable(() => DateUnion)), - error: $.field($.Output.Nullable($Scalar.String), $.Args({ case: $.Input.Nullable($Scalar.String) })), + error: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ case: $.Input.Field($.Input.Nullable($Scalar.String)) }, true), + ), id: $.field($.Output.Nullable($Scalar.ID)), idNonNull: $.field($Scalar.ID), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. @@ -725,7 +752,7 @@ export const Query = $.Object$(\`Query\`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. interfaceNonNull: $.field(() => Interface), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - interfaceWithArgs: $.field($.Output.Nullable(() => Interface), $.Args({ id: $Scalar.ID })), + interfaceWithArgs: $.field($.Output.Nullable(() => Interface), $.Args({ id: $.Input.Field($Scalar.ID) }, false)), listInt: $.field($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int)))), listIntNonNull: $.field($.Output.List($Scalar.Int)), listListInt: $.field( @@ -748,55 +775,71 @@ export const Query = $.Object$(\`Query\`, { objectWithArgs: $.field( $.Output.Nullable(() => Object1), $.Args({ - boolean: $.Input.Nullable($Scalar.Boolean), - float: $.Input.Nullable($Scalar.Float), - id: $.Input.Nullable($Scalar.ID), - int: $.Input.Nullable($Scalar.Int), - string: $.Input.Nullable($Scalar.String), - }), + boolean: $.Input.Field($.Input.Nullable($Scalar.Boolean)), + float: $.Input.Field($.Input.Nullable($Scalar.Float)), + id: $.Input.Field($.Input.Nullable($Scalar.ID)), + int: $.Input.Field($.Input.Nullable($Scalar.Int)), + string: $.Input.Field($.Input.Nullable($Scalar.String)), + }, true), ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - result: $.field($.Output.Nullable(() => Result), $.Args({ case: Case })), + result: $.field($.Output.Nullable(() => Result), $.Args({ case: $.Input.Field(Case) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - resultNonNull: $.field(() => Result, $.Args({ case: $.Input.Nullable(Case) })), + resultNonNull: $.field(() => Result, $.Args({ case: $.Input.Field($.Input.Nullable(Case)) }, true)), string: $.field($.Output.Nullable($Scalar.String)), - stringWithArgEnum: $.field($.Output.Nullable($Scalar.String), $.Args({ ABCEnum: $.Input.Nullable(ABCEnum) })), + stringWithArgEnum: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ ABCEnum: $.Input.Field($.Input.Nullable(ABCEnum)) }, true), + ), stringWithArgInputObject: $.field( $.Output.Nullable($Scalar.String), - $.Args({ input: $.Input.Nullable(InputObject) }), + $.Args({ input: $.Input.Field($.Input.Nullable(InputObject)) }, true), + ), + stringWithArgInputObjectRequired: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ input: $.Input.Field(InputObject) }, false), ), - stringWithArgInputObjectRequired: $.field($.Output.Nullable($Scalar.String), $.Args({ input: InputObject })), stringWithArgs: $.field( $.Output.Nullable($Scalar.String), $.Args({ - boolean: $.Input.Nullable($Scalar.Boolean), - float: $.Input.Nullable($Scalar.Float), - id: $.Input.Nullable($Scalar.ID), - int: $.Input.Nullable($Scalar.Int), - string: $.Input.Nullable($Scalar.String), - }), + boolean: $.Input.Field($.Input.Nullable($Scalar.Boolean)), + float: $.Input.Field($.Input.Nullable($Scalar.Float)), + id: $.Input.Field($.Input.Nullable($Scalar.ID)), + int: $.Input.Field($.Input.Nullable($Scalar.Int)), + string: $.Input.Field($.Input.Nullable($Scalar.String)), + }, true), ), stringWithListArg: $.field( $.Output.Nullable($Scalar.String), - $.Args({ ints: $.Input.Nullable($.Input.List($.Input.Nullable($Scalar.Int))) }), + $.Args({ ints: $.Input.Field($.Input.Nullable($.Input.List($.Input.Nullable($Scalar.Int)))) }, true), + ), + stringWithListArgRequired: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ ints: $.Input.Field($.Input.List($Scalar.Int)) }, false), + ), + stringWithRequiredArg: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ string: $.Input.Field($Scalar.String) }, false), ), - stringWithListArgRequired: $.field($.Output.Nullable($Scalar.String), $.Args({ ints: $.Input.List($Scalar.Int) })), - stringWithRequiredArg: $.field($.Output.Nullable($Scalar.String), $.Args({ string: $Scalar.String })), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionFooBar: $.field($.Output.Nullable(() => FooBarUnion)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionFooBarNonNull: $.field(() => FooBarUnion), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - unionFooBarWithArgs: $.field($.Output.Nullable(() => FooBarUnion), $.Args({ id: $.Input.Nullable($Scalar.ID) })), + unionFooBarWithArgs: $.field( + $.Output.Nullable(() => FooBarUnion), + $.Args({ id: $.Input.Field($.Input.Nullable($Scalar.ID)) }, true), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionObject: $.field($.Output.Nullable(() => ObjectUnion)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionObjectNonNull: $.field(() => ObjectUnion), }) -export const $Index = { - name: 'default' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query', 'Mutation'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation, diff --git a/src/layers/2_generator/code/Client.ts b/src/layers/2_generator/code/Client.ts index 40bfb6e7d..ebb4c306b 100644 --- a/src/layers/2_generator/code/Client.ts +++ b/src/layers/2_generator/code/Client.ts @@ -8,7 +8,7 @@ export const { generate: generateClient, moduleName: moduleNameClient } = create code.push( `import { createPrefilled } from '${config.libraryPaths.client}'`, - `import { $defaultSchemaUrl, $Index } from '../${moduleNameSchemaRuntime}.js'`, + `import { $defaultSchemaUrl, $Index } from './${moduleNameSchemaRuntime}.js'`, ``, `export const create = createPrefilled(\`${config.name}\`, $Index, $defaultSchemaUrl)`, ) diff --git a/src/layers/2_generator/code/Data.ts b/src/layers/2_generator/code/Data.ts new file mode 100644 index 000000000..b1f2f43e8 --- /dev/null +++ b/src/layers/2_generator/code/Data.ts @@ -0,0 +1,15 @@ +import { createCodeGenerator } from '../createCodeGenerator.js' + +export const { generate: generateData, moduleName: moduleNameData } = createCodeGenerator( + `Data`, + (config) => { + const code: string[] = [] + + code.push( + `export const Name = \`${config.name}\``, + `export type Name = '${config.name}'`, + ) + + return code.join(`\n\n`) + }, +) diff --git a/src/layers/2_generator/code/SchemaBuildtime.ts b/src/layers/2_generator/code/SchemaBuildtime.ts index 7116531a6..172c83abe 100644 --- a/src/layers/2_generator/code/SchemaBuildtime.ts +++ b/src/layers/2_generator/code/SchemaBuildtime.ts @@ -20,9 +20,12 @@ import type { } from '../../../lib/graphql.js' import { getNodeDisplayName, + isAllArgsNullable, + isAllInputObjectFieldsNullable, isDeprecatableNode, isGraphQLOutputField, type NameToClass, + RootTypeName, unwrapToNonNull, } from '../../../lib/graphql.js' import { entries, values } from '../../../lib/prelude.js' @@ -102,7 +105,9 @@ const referenceRenderers = defineReferenceRenderers({ GraphQLEnumType: (_, node) => Code.propertyAccess(namespaceNames.GraphQLEnumType, node.name), GraphQLInputObjectType: (_, node) => Code.propertyAccess(namespaceNames.GraphQLInputObjectType, node.name), GraphQLInterfaceType: (_, node) => Code.propertyAccess(namespaceNames.GraphQLInterfaceType, node.name), - GraphQLObjectType: (_, node) => Code.propertyAccess(namespaceNames.GraphQLObjectType, node.name), + GraphQLObjectType: (_, node) => { + return Code.propertyAccess(namespaceNames.GraphQLObjectType, node.name) + }, GraphQLUnionType: (_, node) => Code.propertyAccess(namespaceNames.GraphQLUnionType, node.name), GraphQLScalarType: (_, node) => `$Scalar.${node.name}`, }) @@ -130,11 +135,19 @@ const concreteRenderers = defineConcreteRenderers({ ), ), ), - GraphQLInputObjectType: (config, node) => - Code.TSDoc( - getDocumentation(config, node), - Code.export$(Code.type(node.name, `$.InputObject<${Code.quote(node.name)}, ${renderInputFields(config, node)}>`)), - ), + GraphQLInputObjectType: (config, node) => { + const doc = getDocumentation(config, node) + const isAllFieldsNullable = isAllInputObjectFieldsNullable(node) + const source = Code.export$( + Code.type( + node.name, + `$.InputObject<${Code.quote(node.name)}, ${renderInputFields(config, node)}, ${ + Code.boolean(isAllFieldsNullable) + }>`, + ), + ) + return Code.TSDoc(doc, source) + }, GraphQLInterfaceType: (config, node) => { const implementors = config.typeMapByKind.GraphQLObjectType.filter(_ => _.getInterfaces().filter(_ => _.name === node.name).length > 0 @@ -149,11 +162,15 @@ const concreteRenderers = defineConcreteRenderers({ )), ) }, - GraphQLObjectType: (config, node) => - Code.TSDoc( - getDocumentation(config, node), - Code.export$(Code.type(node.name, `$.Object$2<${Code.quote(node.name)}, ${renderOutputFields(config, node)}>`)), - ), + GraphQLObjectType: (config, node) => { + const maybeRootTypeName = (RootTypeName as Record)[node.name] + const type = maybeRootTypeName + ? `$.Output.Object${maybeRootTypeName}<${renderOutputFields(config, node)}>` + : `$.Object$2<${Code.quote(node.name)}, ${renderOutputFields(config, node)}>` + const doc = getDocumentation(config, node) + const source = Code.export$(Code.type(node.name, type)) + return Code.TSDoc(doc, source) + }, GraphQLScalarType: () => ``, GraphQLUnionType: (config, node) => Code.TSDoc( @@ -258,7 +275,7 @@ const renderOutputField = (config: Config, field: AnyField): string => { } const renderInputField = (config: Config, field: AnyField): string => { - return buildType(`input`, config, field.type) + return `$.Input.Field<${buildType(`input`, config, field.type)}>` } const buildType = (direction: 'input' | 'output', config: Config, node: AnyClass) => { @@ -285,22 +302,21 @@ const buildType = (direction: 'input' | 'output', config: Config, node: AnyClass } const renderArgs = (config: Config, args: readonly GraphQLArgument[]) => { - let hasRequiredArgs = false - const argsRendered = `$.Args<${ + const code = `$.Args<${ Code.object( Code.fields( - args.map((arg) => { - const { nullable } = unwrapToNonNull(arg.type) - hasRequiredArgs = hasRequiredArgs || !nullable - return Code.field( - arg.name, - buildType(`input`, config, arg.type), - ) - }), + args.map((arg) => renderArg(config, arg)), ), ) - }>` - return argsRendered + }, ${Code.boolean(isAllArgsNullable(args))}>` + return code +} + +const renderArg = (config: Config, arg: GraphQLArgument) => { + // const { nullable } = unwrapToNonNull(arg.type) + // hasRequiredArgs = hasRequiredArgs || !nullable + const type = buildType(`input`, config, arg.type) + return Code.field(arg.name, `$.Input.Field<${type}>`) } // high level diff --git a/src/layers/2_generator/code/SchemaIndex.ts b/src/layers/2_generator/code/SchemaIndex.ts index a4cb9bc9f..90822b873 100644 --- a/src/layers/2_generator/code/SchemaIndex.ts +++ b/src/layers/2_generator/code/SchemaIndex.ts @@ -2,15 +2,17 @@ import { isUnionType } from 'graphql' import { Code } from '../../../lib/Code.js' import { hasMutation, hasQuery, hasSubscription, unwrapToNamed } from '../../../lib/graphql.js' import { createCodeGenerator } from '../createCodeGenerator.js' +import { moduleNameData } from './Data.js' import { moduleNameSchemaBuildtime } from './SchemaBuildtime.js' -export const { generate: generateIndex, moduleName: moduleNameIndex } = createCodeGenerator( +export const { generate: generateSchemaIndex, moduleName: moduleNameSchemaIndex } = createCodeGenerator( `SchemaIndex`, (config) => { - const SchemaNamespace = `Schema` + const SchemaBuildtimeNamespace = `Schema` const code = [] code.push(`/* eslint-disable */\n`) - code.push(`import type * as ${SchemaNamespace} from '../${moduleNameSchemaBuildtime}.js'\n`) + code.push(`import type * as Data from './${moduleNameData}.js'\n`) + code.push(`import type * as ${SchemaBuildtimeNamespace} from './${moduleNameSchemaBuildtime}.js'\n`) const rootTypesPresence = { Query: hasQuery(config.typeMapByKind), @@ -18,35 +20,40 @@ export const { generate: generateIndex, moduleName: moduleNameIndex } = createCo Subscription: hasSubscription(config.typeMapByKind), } + const rootTypesPresent = Object.entries(rootTypesPresence).filter(([_, present]) => present !== undefined).map(( + [_], + ) => _) + code.push(Code.export$( Code.interface$( `Index`, Code.objectFrom({ - name: Code.quote(config.name), - RootTypesPresent: `[${ - Object.entries(rootTypesPresence).filter(([_, present]) => present).map(([_]) => Code.quote(_)).join(`, `) - }]`, + name: `Data.Name`, + RootTypesPresent: `[${rootTypesPresent.map((_) => Code.quote(_)).join(`, `)}]`, + RootUnion: rootTypesPresent.map(_ => `${SchemaBuildtimeNamespace}.Root.${_}`).join(`|`), Root: { type: Code.objectFrom({ - Query: rootTypesPresence.Query ? `${SchemaNamespace}.Root.Query` : null, - Mutation: rootTypesPresence.Mutation ? `${SchemaNamespace}.Root.Mutation` : null, - Subscription: rootTypesPresence.Subscription ? `${SchemaNamespace}.Root.Subscription` : null, + Query: rootTypesPresence.Query ? `${SchemaBuildtimeNamespace}.Root.Query` : null, + Mutation: rootTypesPresence.Mutation ? `${SchemaBuildtimeNamespace}.Root.Mutation` : null, + Subscription: rootTypesPresence.Subscription ? `${SchemaBuildtimeNamespace}.Root.Subscription` : null, }), }, objects: Code.objectFromEntries( - config.typeMapByKind.GraphQLObjectType.map(_ => [_.name, `${SchemaNamespace}.Object.${_.name}`]), + config.typeMapByKind.GraphQLObjectType.map(_ => [_.name, `${SchemaBuildtimeNamespace}.Object.${_.name}`]), ), unions: Code.objectFromEntries( - config.typeMapByKind.GraphQLUnionType.map(_ => [_.name, `${SchemaNamespace}.Union.${_.name}`]), + config.typeMapByKind.GraphQLUnionType.map(_ => [_.name, `${SchemaBuildtimeNamespace}.Union.${_.name}`]), ), interfaces: Code.objectFromEntries( - config.typeMapByKind.GraphQLInterfaceType.map(_ => [_.name, `${SchemaNamespace}.Interface.${_.name}`]), + config.typeMapByKind.GraphQLInterfaceType.map( + _ => [_.name, `${SchemaBuildtimeNamespace}.Interface.${_.name}`], + ), ), // todo jsdoc comment saying: // Objects that match this pattern name: /.../ error: Code.objectFrom({ objects: Code.objectFromEntries( - config.error.objects.map(_ => [_.name, `${SchemaNamespace}.Object.${_.name}`]), + config.error.objects.map(_ => [_.name, `${SchemaBuildtimeNamespace}.Object.${_.name}`]), ), objectsTypename: Code.objectFromEntries( config.error.objects.map(_ => [_.name, `{ __typename: "${_.name}" }`]), diff --git a/src/layers/2_generator/code/SchemaRuntime.ts b/src/layers/2_generator/code/SchemaRuntime.ts index f09bdc1fd..020ada04d 100644 --- a/src/layers/2_generator/code/SchemaRuntime.ts +++ b/src/layers/2_generator/code/SchemaRuntime.ts @@ -23,10 +23,20 @@ import { } from 'graphql' import { Code } from '../../../lib/Code.js' import type { AnyClass, AnyGraphQLOutputField } from '../../../lib/graphql.js' -import { hasMutation, hasQuery, hasSubscription, unwrapToNamed, unwrapToNonNull } from '../../../lib/graphql.js' +import { + hasMutation, + hasQuery, + hasSubscription, + isAllArgsNullable, + isAllInputObjectFieldsNullable, + unwrapToNamed, + unwrapToNonNull, +} from '../../../lib/graphql.js' import { createCodeGenerator } from '../createCodeGenerator.js' import type { Config } from '../generateCode.js' +import { moduleNameData } from './Data.js' import { moduleNameScalar } from './Scalar.js' +import { moduleNameSchemaIndex } from './SchemaIndex.js' export const { generate: generateRuntimeSchema, moduleName: moduleNameSchemaRuntime } = createCodeGenerator( `SchemaRuntime`, @@ -39,7 +49,9 @@ export const { generate: generateRuntimeSchema, moduleName: moduleNameSchemaRunt code.push( ` import * as $ from '${config.libraryPaths.schema}' - import * as $Scalar from '../${moduleNameScalar}.js' + import * as Data from './${moduleNameData}.js' + import * as $Scalar from './${moduleNameScalar}.js' + import type { Index } from './${moduleNameSchemaIndex}.js' `, ) @@ -74,11 +86,12 @@ const index = (config: Config) => { } // todo input objects for decode/encode input object fields return ` - export const $Index = { - name: "${config.name}" as const, + export const $Index: Index = { + name: Data.Name, RootTypesPresent: [${ Object.entries(rootTypesPresence).filter(([_, present]) => present).map(([_]) => Code.quote(_)).join(`, `) }] as const, + RootUnion: undefined as any, // Type level only. Root: { Query ${rootTypesPresence.Query ? `` : `:null`} , Mutation ${rootTypesPresence.Mutation ? `` : `:null`}, @@ -166,13 +179,14 @@ const object = (config: Config, type: GraphQLObjectType) => { } const inputObject = (config: Config, type: GraphQLInputObjectType) => { + const isFieldsAllNullable = isAllInputObjectFieldsNullable(type) const fields = Object.values(type.getFields()).map((field) => `${field.name}: ${inputField(config, field)}`).join( `,\n`, ) return ` export const ${type.name} = $.InputObject(\`${type.name}\`, { ${fields} - }) + }, ${Code.boolean(isFieldsAllNullable)}) ` } unwrapToNamed @@ -180,7 +194,7 @@ unwrapToNamed const inputField = (config: Config, field: GraphQLInputField): string => { const type = buildType(`input`, config, field.type) const isNeedThunk = isInputObjectType(unwrapToNamed(field.type)) - return `$.Input.field(${isNeedThunk ? `() => ${type}` : type})` + return `$.Input.Field(${isNeedThunk ? `() => ${type}` : type})` } const outputField = (config: Config, field: AnyGraphQLOutputField): string => { @@ -191,12 +205,13 @@ const outputField = (config: Config, field: AnyGraphQLOutputField): string => { } const renderArgs = (config: Config, args: readonly GraphQLArgument[]) => { - return `$.Args({${args.map(arg => renderArg(config, arg)).join(`, `)}})` + const isFieldsAllNullable = isAllArgsNullable(args) + return `$.Args({${args.map(arg => renderArg(config, arg)).join(`, `)}}, ${Code.boolean(isFieldsAllNullable)})` } const renderArg = (config: Config, arg: GraphQLArgument) => { const type = buildType(`input`, config, arg.type) - return `${arg.name}: ${type}` + return `${arg.name}: $.Input.Field(${type})` } const scalar = (_config: Config, type: GraphQLScalarType) => { diff --git a/src/layers/2_generator/code/Select.ts b/src/layers/2_generator/code/Select.ts index 05c597aaf..2403b9db3 100644 --- a/src/layers/2_generator/code/Select.ts +++ b/src/layers/2_generator/code/Select.ts @@ -1,20 +1,22 @@ import { createCodeGenerator } from '../createCodeGenerator.js' import { title, typeTitle } from '../helpers.js' -import { moduleNameIndex } from './SchemaIndex.js' +import { moduleNameData } from './Data.js' +import { moduleNameSchemaIndex } from './SchemaIndex.js' export const { generate: generateSelect, moduleName: moduleNameSelect } = createCodeGenerator( `Select`, (config) => { const code: string[] = [] - code.push(`import type { Index } from '../${moduleNameIndex}.js'`) + code.push(`import * as Data from './${moduleNameData}.js'`) + code.push(`import type { Index } from './${moduleNameSchemaIndex}.js'`) code.push(`import type { SelectionSet, ResultSet } from '${config.libraryPaths.schema}'`) code.push(``) code.push( title(`Runtime`), `import { createSelect } from '${config.libraryPaths.client}'`, - `export const Select = createSelect(\`default\`)`, + `export const Select = createSelect(Data.Name)`, ``, title(`Buildtime`), ``, diff --git a/src/layers/2_generator/code/__.ts b/src/layers/2_generator/code/__.ts index 2074c77f4..b3515eddd 100644 --- a/src/layers/2_generator/code/__.ts +++ b/src/layers/2_generator/code/__.ts @@ -11,7 +11,7 @@ export const { generate: generate__, moduleName: moduleName__ } = createCodeGene const code: string[] = [] const namespace = config.name === defaultName ? defaultNamespace : capitalizeFirstLetter(config.name) code.push( - `export * as ${namespace} from '../${moduleName_}.js'`, + `export * as ${namespace} from './${moduleName_}.js'`, ) return code.join(`\n\n`) }, diff --git a/src/layers/2_generator/code/global.ts b/src/layers/2_generator/code/global.ts index f492d824c..730e0b256 100644 --- a/src/layers/2_generator/code/global.ts +++ b/src/layers/2_generator/code/global.ts @@ -1,5 +1,6 @@ import { createCodeGenerator } from '../createCodeGenerator.js' -import { moduleNameIndex } from './SchemaIndex.js' +import { moduleNameData } from './Data.js' +import { moduleNameSchemaIndex } from './SchemaIndex.js' export const { moduleName: moduleNameGlobal, generate: generateGlobal } = createCodeGenerator( `Global`, @@ -11,7 +12,8 @@ export const { moduleName: moduleNameGlobal, generate: generateGlobal } = create const code: string[] = [] code.push( - `import type { Index } from '../${moduleNameIndex}.js'`, + `import type * as Data from './${moduleNameData}.js'`, + `import type { Index } from './${moduleNameSchemaIndex}.js'`, ) if (config.typeMapByKind.GraphQLScalarTypeCustom.length > 0) { @@ -31,7 +33,7 @@ export const { moduleName: moduleNameGlobal, generate: generateGlobal } = create export namespace GraffleGlobalTypes { export interface Schemas { ${config.name}: { - name: '${config.name}' + name: Data.Name index: Index customScalars: { ${ diff --git a/src/layers/2_generator/generateCode.ts b/src/layers/2_generator/generateCode.ts index c8784b913..5197fcbfe 100644 --- a/src/layers/2_generator/generateCode.ts +++ b/src/layers/2_generator/generateCode.ts @@ -7,11 +7,12 @@ import { getTypeMapByKind } from '../../lib/graphql.js' import { generate_ } from './code/_.js' import { generate__ } from './code/__.js' import { generateClient } from './code/Client.js' +import { generateData } from './code/Data.js' import { generateError } from './code/Error.js' import { generateGlobal } from './code/global.js' import { generateScalar } from './code/Scalar.js' import { generateSchemaBuildtime } from './code/SchemaBuildtime.js' -import { generateIndex } from './code/SchemaIndex.js' +import { generateSchemaIndex } from './code/SchemaIndex.js' import { generateRuntimeSchema } from './code/SchemaRuntime.js' import { generateSelect } from './code/Select.js' @@ -132,10 +133,11 @@ export const generateCode = (input: Input) => { return [ generate__, generate_, + generateData, generateClient, generateGlobal, generateError, - generateIndex, + generateSchemaIndex, generateScalar, generateSchemaBuildtime, generateRuntimeSchema, diff --git a/src/layers/3_SelectionSet/encode.test.ts b/src/layers/3_SelectionSet/encode.test.ts index 682984634..98bff8cdd 100644 --- a/src/layers/3_SelectionSet/encode.test.ts +++ b/src/layers/3_SelectionSet/encode.test.ts @@ -16,9 +16,9 @@ const s = (selectionSet: Q) => selectionSet const testEachArgs = [ `Query`, ( - ...args: [SelectionSet.Object] | [ + ...args: [SelectionSet.Root] | [ description: string, - ss: SelectionSet.Object, + ss: SelectionSet.Root, ] ) => { const [description, ss] = args.length === 1 ? [undefined, args[0]] : args diff --git a/src/layers/3_SelectionSet/encode.ts b/src/layers/3_SelectionSet/encode.ts index de166ae5a..1365d814c 100644 --- a/src/layers/3_SelectionSet/encode.ts +++ b/src/layers/3_SelectionSet/encode.ts @@ -49,12 +49,14 @@ export interface Context { export const rootTypeSelectionSet = ( context: Context, - objectDef: Schema.Object$2, + rootObjectDef: Schema.Output.RootType, selectionSet: GraphQLObjectSelection, operationName: string = ``, ) => { - const operationTypeName = lowerCaseFirstLetter(objectDef.fields.__typename.type.type) - return `${operationTypeName} ${operationName} { ${resolveObjectLikeFieldValue(context, objectDef, selectionSet)} }` + const operationTypeName = lowerCaseFirstLetter(rootObjectDef.fields.__typename.type.type) + return `${operationTypeName} ${operationName} { ${ + resolveObjectLikeFieldValue(context, rootObjectDef, selectionSet) + } }` } const resolveDirectives = (fieldValue: FieldValue) => { @@ -135,9 +137,9 @@ const resolveArgs = (context: Context, schemaField: Schema.SomeField, ss: Indica return `(${ argEntries.map(([argFieldName, v]) => { - const schemaArgField = schemaArgs.fields[argFieldName] as Schema.Input.Any | undefined + const schemaArgField = schemaArgs.fields[argFieldName] as Schema.Input.Field | undefined if (!schemaArgField) throw new Error(`Arg field ${argFieldName} not found in schema.`) - const valueEncoded = resolveArgValue(context, schemaArgField, v) + const valueEncoded = resolveArgValue(context, schemaArgField.type, v) return `${argFieldName}: ${valueEncoded}` }).join(`, `) })` diff --git a/src/layers/3_SelectionSet/types.ts b/src/layers/3_SelectionSet/types.ts index 4129669e6..c73e07b51 100644 --- a/src/layers/3_SelectionSet/types.ts +++ b/src/layers/3_SelectionSet/types.ts @@ -1,24 +1,21 @@ -import type { MaybeList, StringNonEmpty, Values } from '../../lib/prelude.js' +import type { ExcludeNull, MaybeList, StringNonEmpty, Values } from '../../lib/prelude.js' import type { TSError } from '../../lib/TSError.js' -import type { - InputFieldsAllNullable, - OmitNullableFields, - PickNullableFields, - Schema, - SomeField, - SomeFields, -} from '../1_Schema/__.js' +import type { OmitNullableFields, PickNullableFields, Schema, SomeField, SomeFields } from '../1_Schema/__.js' -export type Query<$Index extends Schema.Index> = Root<$Index, 'Query'> +export type Query<$Index extends Schema.Index> = RootViaObject<$Index, $Index['Root']['Query']> -export type Mutation<$Index extends Schema.Index> = Root<$Index, 'Mutation'> +export type Mutation<$Index extends Schema.Index> = RootViaObject<$Index, $Index['Root']['Mutation']> -export type Subscription<$Index extends Schema.Index> = Root<$Index, 'Subscription'> +export type Subscription<$Index extends Schema.Index> = RootViaObject<$Index, $Index['Root']['Subscription']> -// dprint-ignore -export type Root<$Index extends Schema.Index, Type extends keyof Schema.Index['Root']> = - $Index['Root'][Type] extends Schema.Object$2 ? Object<$Index['Root'][Type], $Index> : - never +export type RootViaObject<$Index extends Schema.Index, $RootType extends null | Schema.Output.RootType> = + $RootType extends null ? never + : Object, $Index> + +export type Root<$Index extends Schema.Index, $RootTypeName extends Schema.RootTypeName> = RootViaObject< + $Index, + $Index['Root'][$RootTypeName] +> // dprint-ignore export type Object<$Object extends Schema.Object$2, $Index extends Schema.Index> = @@ -34,6 +31,7 @@ type Fields<$Fields extends SomeFields, $Index extends Schema.Index> = Field<$Fields[Key], $Index> } & + // todo optimize? /** * Alias support. * Allow every field to also be given as a key with this pattern `_as_: ...` @@ -94,7 +92,7 @@ export type Field_< TSError<'Field', '$Field case not handled', { $Field: $Field }> // dprint-ignore type Arguments<$Field extends SomeField> = - $Field['args'] extends Schema.Args ? InputFieldsAllNullable<$Field['args']['fields']> extends true ? { $?: Args<$Field['args']> } : + $Field['args'] extends Schema.Args ? $Field['args']['isFieldsAllNullable'] extends true ? { $?: Args<$Field['args']> } : { $: Args<$Field['args']> } : {} @@ -182,26 +180,27 @@ export type ResolveAliasTargets = { * Directives */ +// dprint-ignore export namespace Directive { - export type Include = { $include: boolean | { if?: boolean } } + export interface Include { $include: boolean | { if?: boolean } } export namespace Include { - export type Positive = { $include: true | { if: true } } - export type Negative = { $include: false | { if: false } } + export interface Positive { $include: true | { if: true } } + export interface Negative { $include: false | { if: false } } } - export type Skip = { $skip: boolean | { if?: boolean } } + export interface Skip { $skip: boolean | { if?: boolean } } export namespace Skip { - export type Positive = { $skip: true | { if: true } } - export type Negative = { $skip: false | { if: false } } + export interface Positive { $skip: true | { if: true } } + export interface Negative { $skip: false | { if: false } } } - export type Defer = { $defer: boolean | { if?: boolean; label?: string } } + export interface Defer { $defer: boolean | { if?: boolean; label?: string } } export namespace Defer { - export type Positive = { $defer: true | { if: true } } - export type Negative = { $defer: false | { if: false } } + export interface Positive { $defer: true | { if: true } } + export interface Negative { $defer: false | { if: false } } } - export type Stream = { $stream: boolean | { if?: boolean; label?: string; initialCount?: number } } + export interface Stream { $stream: boolean | { if?: boolean; label?: string; initialCount?: number } } export namespace Stream { - export type Positive = { $stream: true | { if: true } } - export type Negative = { $stream: false | { if: false } } + export interface Positive { $stream: true | { if: true } } + export interface Negative { $stream: false | { if: false } } } } @@ -220,6 +219,10 @@ export type OmitNegativeIndicators<$SelectionSet> = { [K in keyof $SelectionSet as $SelectionSet[K] extends ClientIndicatorNegative ? never : K]: $SelectionSet[K] } +// dprint-ignore +export type Indicator<$Field extends SomeField> = + $Field['args'] extends null ? NoArgsIndicator : ArgsIndicator> + /** * Field selection in general, with directives support too. * If a field directive is given as an indicator then it implies "select this" e.g. `true`/`1`. @@ -227,12 +230,9 @@ export type OmitNegativeIndicators<$SelectionSet> = { */ export type NoArgsIndicator = ClientIndicator | FieldDirectives -// dprint-ignore -export type Indicator<$Field extends SomeField> = - $Field['args'] extends Schema.Args ? InputFieldsAllNullable<$Field['args']['fields']> extends true - ? ({ $?: Args<$Field['args']> } & FieldDirectives) | ClientIndicator : - { $: Args<$Field['args']> } & FieldDirectives : - NoArgsIndicator +type ArgsIndicator<$Args extends Schema.Args> = $Args['isFieldsAllNullable'] extends true + ? ({ $?: Args<$Args> } & FieldDirectives) | ClientIndicator + : { $: Args<$Args> } & FieldDirectives // dprint-ignore export type Args<$Args extends Schema.Args> = ArgFields<$Args['fields']> @@ -246,10 +246,12 @@ export type ArgFields<$ArgFields extends Schema.InputObject['fields']> = [Key in keyof PickNullableFields<$ArgFields>]?: InputField<$ArgFields[Key]> | null } +type InputField<$InputField extends Schema.Input.Field> = InputFieldType<$InputField['type']> + // dprint-ignore -type InputField<$InputType extends Schema.Input.Any> = - $InputType extends Schema.Input.Nullable ? InputField<$InnerType> | null : - $InputType extends Schema.Input.List ? InputField<$InnerType>[] : +type InputFieldType<$InputType extends Schema.Input.Any> = + $InputType extends Schema.Input.Nullable ? InputFieldType<$InnerType> | null : + $InputType extends Schema.Input.List ? InputFieldType<$InnerType>[] : $InputType extends Schema.InputObject ? ArgFields<$Fields> : $InputType extends Schema.Enum ? $Members[number] : $InputType extends Schema.Scalar.Any ? ReturnType<$InputType['codec']['decode']> : diff --git a/src/layers/4_ResultSet/types.test-d.ts b/src/layers/4_ResultSet/types.test-d.ts index 7278038c2..5cffcac1e 100644 --- a/src/layers/4_ResultSet/types.test-d.ts +++ b/src/layers/4_ResultSet/types.test-d.ts @@ -5,7 +5,7 @@ import type { SelectionSet } from '../3_SelectionSet/__.js' import type { ResultSet } from './__.js' type I = Index -type RS<$selectionSet extends SelectionSet.Query> = ResultSet.Query<$selectionSet, I> +type RS<$SelectionSet extends SelectionSet.Query> = ResultSet.Query<$SelectionSet, I> // dprint-ignore test(`general`, () => { @@ -124,5 +124,6 @@ test(`general`, () => { // Errors // unknown field - expectTypeOf>().toEqualTypeOf<{ id2: ResultSet.Errors.UnknownFieldName<'id2', Schema.Root.Query> }>() + type Result = RS<{ id2: true }> + expectTypeOf().toEqualTypeOf<{ id2: ResultSet.Errors.UnknownFieldName<'id2', Schema.Root.Query> }>() }) diff --git a/src/layers/4_ResultSet/types.ts b/src/layers/4_ResultSet/types.ts index 97b048801..b1bdb1c45 100644 --- a/src/layers/4_ResultSet/types.ts +++ b/src/layers/4_ResultSet/types.ts @@ -13,6 +13,12 @@ export type Mutation<$SelectionSet extends object, $Index extends Schema.Index> // dprint-ignore export type Subscription<$SelectionSet extends object, $Index extends Schema.Index> = Root<$SelectionSet, $Index, 'Subscription'> +export type RootViaObject< + $SelectionSet extends object, + $Index extends Schema.Index, + $RootType extends Schema.Output.RootType, +> = Root<$SelectionSet, $Index, $RootType['fields']['__typename']['type']['type']> + export type Root< $SelectionSet extends object, $Index extends Schema.Index, @@ -101,5 +107,6 @@ type FieldDirectiveSkip<$SelectionSet> = // dprint-ignore export namespace Errors { - export type UnknownFieldName<$FieldName extends string, $Object extends Schema.Object$2> = TSError<'Object', `field "${$FieldName}" does not exist on object "${$Object['fields']['__typename']['type']['type']}"`> + export type UnknownFieldName<$FieldName extends string, $Object extends Schema.Object$2 | Schema.Output.RootType> = + TSError<'Object', `field "${$FieldName}" does not exist on object "${$Object['fields']['__typename']['type']['type']}"`> } diff --git a/src/layers/6_client/RootTypeMethods.ts b/src/layers/6_client/RootTypeMethods.ts index b6dcb0594..015cf8220 100644 --- a/src/layers/6_client/RootTypeMethods.ts +++ b/src/layers/6_client/RootTypeMethods.ts @@ -1,56 +1,53 @@ -import type { CamelCase } from 'type-fest' +import type { RootTypeNameToOperationName } from '../../lib/graphql.js' import type { Exact } from '../../lib/prelude.js' -import type { TSError } from '../../lib/TSError.js' -import type { InputFieldsAllNullable, Schema } from '../1_Schema/__.js' +import type { Schema } from '../1_Schema/__.js' import type { SelectionSet } from '../3_SelectionSet/__.js' import type { ResultSet } from '../4_ResultSet/__.js' import type { ResolveOutputReturnRootField, ResolveOutputReturnRootType, SimplifyOutput } from './handleOutput.js' import type { AugmentRootTypeSelectionWithTypename, Config, CreateSelectionTypename } from './Settings/Config.js' -type RootTypeFieldContext = { - Config: Config - Index: Schema.Index - RootTypeName: Schema.RootTypeName - RootTypeFieldName: string - Field: Schema.SomeField -} - // dprint-ignore export type BuilderRequestMethodsGeneratedRootTypes<$Config extends Config, $Index extends Schema.Index> = { - // todo - // [$OperationName in $Index['OperationsPresent'][number]]: - // RootTypeMethods<$Config, $Index, OperationNameToRootType> - [$RootTypeName in $Index['RootTypesPresent'][number] as CamelCase<$RootTypeName>]: - RootTypeMethods<$Config, $Index, $RootTypeName> + [$RootType in $Index['RootUnion'] as RootTypeNameToOperationName[$RootType['fields']['__typename']['type']['type']]]: + RootTypeMethods<$Config, $Index, $RootType> } // dprint-ignore -export type RootTypeMethods<$Config extends Config, $Index extends Schema.Index, $RootTypeName extends Schema.RootTypeName> = - $Index['Root'][$RootTypeName] extends Schema.Object$2 ? - ( - & { - $batch: RootMethod<$Config, $Index, $RootTypeName> - } +type RootTypeMethods<$Config extends Config, $Index extends Schema.Index, $RootType extends Schema.Output.RootType> = +( & { - [$RootTypeFieldName in keyof $Index['Root'][$RootTypeName]['fields'] & string]: - RootTypeFieldMethod<{ - Config: $Config, - Index: $Index, - RootTypeName: $RootTypeName, - RootTypeFieldName: $RootTypeFieldName - Field: $Index['Root'][$RootTypeName]['fields'][$RootTypeFieldName] - }> + $batch: RootTypeMethod<$Config, $Index, $RootType> } - ) - : TSError<'RootTypeMethods', `Your schema does not have the root type "${$RootTypeName}".`> + & RootTypeFieldMethods<$Config, $Index, $RootType> +) // dprint-ignore -export type RootMethod<$Config extends Config, $Index extends Schema.Index, $RootTypeName extends Schema.RootTypeName> = - <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Root<$Index, $RootTypeName>>) => +export type RootTypeMethod<$Config extends Config, $Index extends Schema.Index, $RootType extends Schema.Output.RootType> = + <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.RootViaObject<$Index, $RootType>>) => Promise< - ResolveOutputReturnRootType<$Config, $Index, ResultSet.Root, $Index, $RootTypeName>> + ResolveOutputReturnRootType<$Config, $Index, ResultSet.RootViaObject, $Index, $RootType>> > +type RootTypeFieldMethods< + $Config extends Config, + $Index extends Schema.Index, + $RootType extends Schema.Output.RootType, +> = { + [$RootTypeFieldName in keyof $RootType['fields'] & string]: RootTypeFieldMethod<{ + Config: $Config + Index: $Index + RootTypeFieldName: $RootTypeFieldName + Field: $RootType['fields'][$RootTypeFieldName] + }> +} + +type RootTypeFieldContext = { + Config: Config + Index: Schema.Index + RootTypeFieldName: string + Field: Schema.SomeField +} + // dprint-ignore type RootTypeFieldMethod<$Context extends RootTypeFieldContext> = RootTypeFieldMethod_<$Context, $Context['Field']['type']> @@ -75,7 +72,7 @@ type ObjectLikeFieldMethod<$Context extends RootTypeFieldContext> = // dprint-ignore type ScalarFieldMethod<$Context extends RootTypeFieldContext> = - $Context['Field']['args'] extends Schema.Args ? InputFieldsAllNullable<$Fields> extends true ? <$SelectionSet>(args?: Exact<$SelectionSet, SelectionSet.Args<$Context['Field']['args']>>) => Promise>> : + $Context['Field']['args'] extends Schema.Args ? $Context['Field']['args']['isFieldsAllNullable'] extends true ? <$SelectionSet>(args?: Exact<$SelectionSet, SelectionSet.Args<$Context['Field']['args']>>) => Promise>> : <$SelectionSet>(args: Exact<$SelectionSet, SelectionSet.Args<$Context['Field']['args']>>) => Promise>> : (() => Promise>>) // dprint-ignore diff --git a/src/layers/6_client/Settings/Config.ts b/src/layers/6_client/Settings/Config.ts index 8fbc1a935..c16892371 100644 --- a/src/layers/6_client/Settings/Config.ts +++ b/src/layers/6_client/Settings/Config.ts @@ -138,12 +138,14 @@ export type IsNeedSelectionTypename<$Config extends Config, $Index extends Schem export type AugmentRootTypeSelectionWithTypename< $Config extends Config, $Index extends Schema.Index, - $RootTypeName extends Schema.RootTypeName, + $RootType extends Schema.Output.RootType, $Selection extends object, > = IsNeedSelectionTypename<$Config, $Index> extends true ? { [$Key in StringKeyof<$Selection>]: & $Selection[$Key] - & (IsRootFieldNameAResultField<$Index, $RootTypeName, $Key> extends true ? TypenameSelection : {}) + & (IsRootFieldNameAResultField<$Index, $RootType['fields']['__typename']['type']['type'], $Key> extends true + ? TypenameSelection + : {}) } : $Selection diff --git a/src/layers/6_client/client.error.test-d.ts b/src/layers/6_client/client.error.test-d.ts index 7c8f5652c..1ebe415a8 100644 --- a/src/layers/6_client/client.error.test-d.ts +++ b/src/layers/6_client/client.error.test-d.ts @@ -4,10 +4,10 @@ import { Graffle } from '../../../tests/_/schema/generated/__.js' import { isError } from '../../../tests/_/schema/generated/modules/Error.js' import * as Schema from '../../../tests/_/schema/schema.js' -const client = Graffle.create({ schema: Schema.schema }) +const graffle = Graffle.create({ schema: Schema.schema }) test('isError utility function narrows for error objects', async () => { - const result = await client.query.result({ $: { case: 'Object1' }, __typename: true }) + const result = await graffle.query.result({ $: { case: 'Object1' }, __typename: true }) if (isError(result)) { expectTypeOf(result).toEqualTypeOf<{ __typename: 'ErrorOne' } | { __typename: 'ErrorTwo' }>() diff --git a/src/layers/6_client/document.ts b/src/layers/6_client/document.ts index 3fff08a6f..34bd04bad 100644 --- a/src/layers/6_client/document.ts +++ b/src/layers/6_client/document.ts @@ -1,6 +1,6 @@ import type { MergeExclusive, NonEmptyObject } from 'type-fest' import { operationTypeNameToRootTypeName } from '../../lib/graphql.js' -import type { IsMultipleKeys } from '../../lib/prelude.js' +import type { ExcludeNull, IsMultipleKeys } from '../../lib/prelude.js' import type { TSError } from '../../lib/TSError.js' import type { Schema } from '../1_Schema/__.js' import { SelectionSet } from '../3_SelectionSet/__.js' @@ -20,7 +20,6 @@ export type DocumentRunner<$Config extends Config, $Index extends Schema.Index, $Name extends keyof $Document & string, $Params extends (IsMultipleKeys<$Document> extends true ? [name: $Name] : ([] | [name: $Name | undefined])), >(...params: $Params) => Promise< - // $Config ResolveOutputReturnRootType<$Config, $Index, ResultSet.Root, $Index, GetRootType<$Document[$Name]>>> > } @@ -80,14 +79,22 @@ export type ValidateDocumentOperationNames<$Document> = type GetRootTypeSelection< $Config extends Config, $Index extends Schema.Index, - $Selection extends object + $Selection extends SomeSelection > = - $Selection extends { query: infer U extends object } ? AugmentRootTypeSelectionWithTypename<$Config, $Index, 'Query', U> : - $Selection extends { mutation: infer U extends object } ? AugmentRootTypeSelectionWithTypename<$Config, $Index, 'Mutation', U> : - never + $Selection extends { query: infer $SS extends object } + ? $Index['Root']['Query'] extends null + ? TSError<'GetRootTypeSelection', `Query root type is not allowed to be null in document`> + : AugmentRootTypeSelectionWithTypename<$Config, $Index, ExcludeNull<$Index['Root']['Query']>, $SS> + : $Selection extends { mutation: infer $SS extends object } + ? $Index['Root']['Mutation'] extends null + ? TSError<'GetRootTypeSelection', `Mutation root type is not allowed to be null in document`> + : AugmentRootTypeSelectionWithTypename<$Config, $Index, ExcludeNull<$Index['Root']['Mutation']>, $SS> + : never // dprint-ignore type GetRootType<$Selection extends object> = $Selection extends {query:any} ? 'Query' : $Selection extends {mutation:any} ? 'Mutation' : never + +type SomeSelection = object diff --git a/src/layers/6_client/rootTypeMethods.test-d.ts b/src/layers/6_client/rootTypeMethods.test-d.ts index a782f766c..ffea53fc5 100644 --- a/src/layers/6_client/rootTypeMethods.test-d.ts +++ b/src/layers/6_client/rootTypeMethods.test-d.ts @@ -14,9 +14,8 @@ test(`query`, () => { // custom scalar expectTypeOf(graffle.query.date).toEqualTypeOf<() => Promise>() expectTypeOf(graffle.query.dateNonNull).toEqualTypeOf<() => Promise>() - expectTypeOf(graffle.query.dateArg).toMatchTypeOf<(args?: { date?: Date | null }) => Promise>() + expectTypeOf(graffle.query.dateArg).toMatchTypeOf<(args?: { date?: Date | null | undefined }) => Promise>() expectTypeOf(graffle.query.dateArgNonNull).toMatchTypeOf<(args: { date: Date }) => Promise>() - const x2 = graffle.query.dateObject1({ date1: true }) // object expectTypeOf(graffle.query.dateObject1({ date1: true })).resolves.toEqualTypeOf<{ date1: Date | null } | null>() expectTypeOf(graffle.query.dateObject1({ $scalars: true })).resolves.toEqualTypeOf<{ __typename: "DateObject1"; date1: Date | null } | null>() diff --git a/src/lib/Code.ts b/src/lib/Code.ts index 0ecb00a7c..638d08527 100644 --- a/src/lib/Code.ts +++ b/src/lib/Code.ts @@ -33,6 +33,7 @@ export namespace Code { ), ) } + export const boolean = (value: boolean) => value ? `true` : `false` export const type = (name: string, type: string) => `type ${name} = ${type}` export const interface$ = (name: string, object: string) => `interface ${name} ${object}` export const export$ = (thing: string) => `export ${thing}` diff --git a/src/lib/graphql.ts b/src/lib/graphql.ts index 3f3e868ed..35eb8ca86 100644 --- a/src/lib/graphql.ts +++ b/src/lib/graphql.ts @@ -1,5 +1,6 @@ import type { DocumentNode, + GraphQLArgument, GraphQLEnumValue, GraphQLError, GraphQLField, @@ -42,18 +43,24 @@ export const RootTypeName = { Subscription: `Subscription`, } as const +export type RootTypeNameQuery = typeof RootTypeName['Query'] +export type RootTypeNameMutation = typeof RootTypeName['Mutation'] +export type RootTypeNameSubscription = typeof RootTypeName['Subscription'] + export const operationTypeNameToRootTypeName = { query: `Query`, mutation: `Mutation`, subscription: `Subscription`, } as const -export const rootTypeNameToOperationName = { +export const RootTypeNameToOperationName = { Query: `query`, Mutation: `mutation`, Subscription: `subscription`, } as const +export type RootTypeNameToOperationName = typeof RootTypeNameToOperationName + export type RootTypeName = keyof typeof RootTypeName export const isStandardScalarType = (type: GraphQLScalarType) => { @@ -333,3 +340,11 @@ export const parseGraphQLOperationType = (request: GraphQLRequestEncoded): Opera return definedOperationToAnalyze.operationType } + +export const isAllArgsNullable = (args: readonly GraphQLArgument[]) => { + return !args.some(_ => isNonNullType(_.type)) +} + +export const isAllInputObjectFieldsNullable = (node: GraphQLInputObjectType) => { + return Object.values(node.getFields()).some(_ => !isNonNullType(_.type)) +} diff --git a/tests/_/schema/generated/modules/Data.ts b/tests/_/schema/generated/modules/Data.ts new file mode 100644 index 000000000..c4ad27afc --- /dev/null +++ b/tests/_/schema/generated/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `default` + +export type Name = 'default' diff --git a/tests/_/schema/generated/modules/Global.ts b/tests/_/schema/generated/modules/Global.ts index b040cc02a..888db58c8 100644 --- a/tests/_/schema/generated/modules/Global.ts +++ b/tests/_/schema/generated/modules/Global.ts @@ -1,3 +1,5 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' import type * as CustomScalar from '../../../customScalarCodecs.js' @@ -6,7 +8,7 @@ declare global { export namespace GraffleGlobalTypes { export interface Schemas { default: { - name: 'default' + name: Data.Name index: Index customScalars: { Date: CustomScalar.Date diff --git a/tests/_/schema/generated/modules/SchemaBuildtime.ts b/tests/_/schema/generated/modules/SchemaBuildtime.ts index 00ef8d110..085b1d89e 100644 --- a/tests/_/schema/generated/modules/SchemaBuildtime.ts +++ b/tests/_/schema/generated/modules/SchemaBuildtime.ts @@ -6,23 +6,23 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Mutation = $.Object$2<'Mutation', { + export type Mutation = $.Output.ObjectMutation<{ id: $.Field<$.Output.Nullable<$Scalar.ID>, null> idNonNull: $.Field<$Scalar.ID, null> }> - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ InputObjectNested: $.Field< $.Output.Nullable<$Scalar.ID>, $.Args<{ - input: $.Input.Nullable - }> + input: $.Input.Field<$.Input.Nullable> + }, true> > InputObjectNestedNonNull: $.Field< $.Output.Nullable<$Scalar.ID>, $.Args<{ - input: InputObject.InputObjectNestedNonNull - }> + input: $.Input.Field + }, false> > /** * Query enum field documentation. @@ -32,38 +32,38 @@ export namespace Root { dateArg: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.Nullable<$Scalar.Date> - }> + date: $.Input.Field<$.Input.Nullable<$Scalar.Date>> + }, true> > dateArgInputObject: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - input: $.Input.Nullable - }> + input: $.Input.Field<$.Input.Nullable> + }, true> > dateArgList: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.Nullable<$.Input.List<$Scalar.Date>> - }> + date: $.Input.Field<$.Input.Nullable<$.Input.List<$Scalar.Date>>> + }, true> > dateArgNonNull: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $Scalar.Date - }> + date: $.Input.Field<$Scalar.Date> + }, false> > dateArgNonNullList: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.List<$.Input.Nullable<$Scalar.Date>> - }> + date: $.Input.Field<$.Input.List<$.Input.Nullable<$Scalar.Date>>> + }, false> > dateArgNonNullListNonNull: $.Field< $.Output.Nullable<$Scalar.Date>, $.Args<{ - date: $.Input.List<$Scalar.Date> - }> + date: $.Input.Field<$.Input.List<$Scalar.Date>> + }, false> > dateInterface1: $.Field<$.Output.Nullable, null> dateList: $.Field<$.Output.Nullable<$.Output.List<$Scalar.Date>>, null> @@ -74,8 +74,8 @@ export namespace Root { error: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - case: $.Input.Nullable<$Scalar.String> - }> + case: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > id: $.Field<$.Output.Nullable<$Scalar.ID>, null> idNonNull: $.Field<$Scalar.ID, null> @@ -84,8 +84,8 @@ export namespace Root { interfaceWithArgs: $.Field< $.Output.Nullable, $.Args<{ - id: $Scalar.ID - }> + id: $.Input.Field<$Scalar.ID> + }, false> > listInt: $.Field<$.Output.Nullable<$.Output.List<$.Output.Nullable<$Scalar.Int>>>, null> listIntNonNull: $.Field<$.Output.List<$Scalar.Int>, null> @@ -103,79 +103,79 @@ export namespace Root { objectWithArgs: $.Field< $.Output.Nullable, $.Args<{ - boolean: $.Input.Nullable<$Scalar.Boolean> - float: $.Input.Nullable<$Scalar.Float> - id: $.Input.Nullable<$Scalar.ID> - int: $.Input.Nullable<$Scalar.Int> - string: $.Input.Nullable<$Scalar.String> - }> + boolean: $.Input.Field<$.Input.Nullable<$Scalar.Boolean>> + float: $.Input.Field<$.Input.Nullable<$Scalar.Float>> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + int: $.Input.Field<$.Input.Nullable<$Scalar.Int>> + string: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > result: $.Field< $.Output.Nullable, $.Args<{ - case: Enum.Case - }> + case: $.Input.Field + }, false> > resultNonNull: $.Field< Union.Result, $.Args<{ - case: $.Input.Nullable - }> + case: $.Input.Field<$.Input.Nullable> + }, true> > string: $.Field<$.Output.Nullable<$Scalar.String>, null> stringWithArgEnum: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - ABCEnum: $.Input.Nullable - }> + ABCEnum: $.Input.Field<$.Input.Nullable> + }, true> > stringWithArgInputObject: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - input: $.Input.Nullable - }> + input: $.Input.Field<$.Input.Nullable> + }, true> > stringWithArgInputObjectRequired: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - input: InputObject.InputObject - }> + input: $.Input.Field + }, false> > stringWithArgs: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - boolean: $.Input.Nullable<$Scalar.Boolean> - float: $.Input.Nullable<$Scalar.Float> - id: $.Input.Nullable<$Scalar.ID> - int: $.Input.Nullable<$Scalar.Int> - string: $.Input.Nullable<$Scalar.String> - }> + boolean: $.Input.Field<$.Input.Nullable<$Scalar.Boolean>> + float: $.Input.Field<$.Input.Nullable<$Scalar.Float>> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + int: $.Input.Field<$.Input.Nullable<$Scalar.Int>> + string: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > stringWithListArg: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - ints: $.Input.Nullable<$.Input.List<$.Input.Nullable<$Scalar.Int>>> - }> + ints: $.Input.Field<$.Input.Nullable<$.Input.List<$.Input.Nullable<$Scalar.Int>>>> + }, true> > stringWithListArgRequired: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - ints: $.Input.List<$Scalar.Int> - }> + ints: $.Input.Field<$.Input.List<$Scalar.Int>> + }, false> > stringWithRequiredArg: $.Field< $.Output.Nullable<$Scalar.String>, $.Args<{ - string: $Scalar.String - }> + string: $.Input.Field<$Scalar.String> + }, false> > unionFooBar: $.Field<$.Output.Nullable, null> unionFooBarNonNull: $.Field unionFooBarWithArgs: $.Field< $.Output.Nullable, $.Args<{ - id: $.Input.Nullable<$Scalar.ID> - }> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + }, true> > unionObject: $.Field<$.Output.Nullable, null> unionObjectNonNull: $.Field @@ -206,19 +206,19 @@ export namespace Enum { export namespace InputObject { export type InputObject = $.InputObject<'InputObject', { - date: $.Input.Nullable<$Scalar.Date> - dateRequired: $Scalar.Date - id: $.Input.Nullable<$Scalar.ID> - idRequired: $Scalar.ID - }> + date: $.Input.Field<$.Input.Nullable<$Scalar.Date>> + dateRequired: $.Input.Field<$Scalar.Date> + id: $.Input.Field<$.Input.Nullable<$Scalar.ID>> + idRequired: $.Input.Field<$Scalar.ID> + }, true> export type InputObjectNested = $.InputObject<'InputObjectNested', { - InputObject: $.Input.Nullable - }> + InputObject: $.Input.Field<$.Input.Nullable> + }, true> export type InputObjectNestedNonNull = $.InputObject<'InputObjectNestedNonNull', { - InputObject: InputObject.InputObject - }> + InputObject: $.Input.Field + }, false> } // ------------------------------------------------------------ // diff --git a/tests/_/schema/generated/modules/SchemaIndex.ts b/tests/_/schema/generated/modules/SchemaIndex.ts index 2688ccfca..0be649614 100644 --- a/tests/_/schema/generated/modules/SchemaIndex.ts +++ b/tests/_/schema/generated/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'default' + name: Data.Name RootTypesPresent: ['Query', 'Mutation'] + RootUnion: Schema.Root.Query | Schema.Root.Mutation Root: { Query: Schema.Root.Query Mutation: Schema.Root.Mutation diff --git a/tests/_/schema/generated/modules/SchemaRuntime.ts b/tests/_/schema/generated/modules/SchemaRuntime.ts index 3b74a0477..15af3f7e5 100644 --- a/tests/_/schema/generated/modules/SchemaRuntime.ts +++ b/tests/_/schema/generated/modules/SchemaRuntime.ts @@ -1,26 +1,28 @@ /* eslint-disable */ import * as $ from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = undefined export const ABCEnum = $.Enum(`ABCEnum`, [`A`, `B`, `C`]) export const Case = $.Enum(`Case`, [`ErrorOne`, `ErrorTwo`, `Object1`]) export const InputObject = $.InputObject(`InputObject`, { - date: $.Input.field($.Input.Nullable($Scalar.Date)), - dateRequired: $.Input.field($Scalar.Date), - id: $.Input.field($.Input.Nullable($Scalar.ID)), - idRequired: $.Input.field($Scalar.ID), -}) + date: $.Input.Field($.Input.Nullable($Scalar.Date)), + dateRequired: $.Input.Field($Scalar.Date), + id: $.Input.Field($.Input.Nullable($Scalar.ID)), + idRequired: $.Input.Field($Scalar.ID), +}, true) export const InputObjectNested = $.InputObject(`InputObjectNested`, { - InputObject: $.Input.field(() => $.Input.Nullable(InputObject)), -}) + InputObject: $.Input.Field(() => $.Input.Nullable(InputObject)), +}, true) export const InputObjectNestedNonNull = $.InputObject(`InputObjectNestedNonNull`, { - InputObject: $.Input.field(() => InputObject), -}) + InputObject: $.Input.Field(() => InputObject), +}, false) // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Bar = $.Object$(`Bar`, { @@ -127,20 +129,38 @@ export const Mutation = $.Object$(`Mutation`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Query = $.Object$(`Query`, { - InputObjectNested: $.field($.Output.Nullable($Scalar.ID), $.Args({ input: $.Input.Nullable(InputObjectNested) })), - InputObjectNestedNonNull: $.field($.Output.Nullable($Scalar.ID), $.Args({ input: InputObjectNestedNonNull })), + InputObjectNested: $.field( + $.Output.Nullable($Scalar.ID), + $.Args({ input: $.Input.Field($.Input.Nullable(InputObjectNested)) }, true), + ), + InputObjectNestedNonNull: $.field( + $.Output.Nullable($Scalar.ID), + $.Args({ input: $.Input.Field(InputObjectNestedNonNull) }, false), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. abcEnum: $.field($.Output.Nullable(ABCEnum)), date: $.field($.Output.Nullable($Scalar.Date)), - dateArg: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.Nullable($Scalar.Date) })), - dateArgInputObject: $.field($.Output.Nullable($Scalar.Date), $.Args({ input: $.Input.Nullable(InputObject) })), - dateArgList: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.Nullable($.Input.List($Scalar.Date)) })), - dateArgNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $Scalar.Date })), + dateArg: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ date: $.Input.Field($.Input.Nullable($Scalar.Date)) }, true), + ), + dateArgInputObject: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ input: $.Input.Field($.Input.Nullable(InputObject)) }, true), + ), + dateArgList: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ date: $.Input.Field($.Input.Nullable($.Input.List($Scalar.Date))) }, true), + ), + dateArgNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.Field($Scalar.Date) }, false)), dateArgNonNullList: $.field( $.Output.Nullable($Scalar.Date), - $.Args({ date: $.Input.List($.Input.Nullable($Scalar.Date)) }), + $.Args({ date: $.Input.Field($.Input.List($.Input.Nullable($Scalar.Date))) }, false), + ), + dateArgNonNullListNonNull: $.field( + $.Output.Nullable($Scalar.Date), + $.Args({ date: $.Input.Field($.Input.List($Scalar.Date)) }, false), ), - dateArgNonNullListNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.List($Scalar.Date) })), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. dateInterface1: $.field($.Output.Nullable(() => DateInterface1)), dateList: $.field($.Output.Nullable($.Output.List($Scalar.Date))), @@ -150,7 +170,10 @@ export const Query = $.Object$(`Query`, { dateObject1: $.field($.Output.Nullable(() => DateObject1)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. dateUnion: $.field($.Output.Nullable(() => DateUnion)), - error: $.field($.Output.Nullable($Scalar.String), $.Args({ case: $.Input.Nullable($Scalar.String) })), + error: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ case: $.Input.Field($.Input.Nullable($Scalar.String)) }, true), + ), id: $.field($.Output.Nullable($Scalar.ID)), idNonNull: $.field($Scalar.ID), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. @@ -158,7 +181,7 @@ export const Query = $.Object$(`Query`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. interfaceNonNull: $.field(() => Interface), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - interfaceWithArgs: $.field($.Output.Nullable(() => Interface), $.Args({ id: $Scalar.ID })), + interfaceWithArgs: $.field($.Output.Nullable(() => Interface), $.Args({ id: $.Input.Field($Scalar.ID) }, false)), listInt: $.field($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int)))), listIntNonNull: $.field($.Output.List($Scalar.Int)), listListInt: $.field( @@ -181,55 +204,71 @@ export const Query = $.Object$(`Query`, { objectWithArgs: $.field( $.Output.Nullable(() => Object1), $.Args({ - boolean: $.Input.Nullable($Scalar.Boolean), - float: $.Input.Nullable($Scalar.Float), - id: $.Input.Nullable($Scalar.ID), - int: $.Input.Nullable($Scalar.Int), - string: $.Input.Nullable($Scalar.String), - }), + boolean: $.Input.Field($.Input.Nullable($Scalar.Boolean)), + float: $.Input.Field($.Input.Nullable($Scalar.Float)), + id: $.Input.Field($.Input.Nullable($Scalar.ID)), + int: $.Input.Field($.Input.Nullable($Scalar.Int)), + string: $.Input.Field($.Input.Nullable($Scalar.String)), + }, true), ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - result: $.field($.Output.Nullable(() => Result), $.Args({ case: Case })), + result: $.field($.Output.Nullable(() => Result), $.Args({ case: $.Input.Field(Case) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - resultNonNull: $.field(() => Result, $.Args({ case: $.Input.Nullable(Case) })), + resultNonNull: $.field(() => Result, $.Args({ case: $.Input.Field($.Input.Nullable(Case)) }, true)), string: $.field($.Output.Nullable($Scalar.String)), - stringWithArgEnum: $.field($.Output.Nullable($Scalar.String), $.Args({ ABCEnum: $.Input.Nullable(ABCEnum) })), + stringWithArgEnum: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ ABCEnum: $.Input.Field($.Input.Nullable(ABCEnum)) }, true), + ), stringWithArgInputObject: $.field( $.Output.Nullable($Scalar.String), - $.Args({ input: $.Input.Nullable(InputObject) }), + $.Args({ input: $.Input.Field($.Input.Nullable(InputObject)) }, true), + ), + stringWithArgInputObjectRequired: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ input: $.Input.Field(InputObject) }, false), ), - stringWithArgInputObjectRequired: $.field($.Output.Nullable($Scalar.String), $.Args({ input: InputObject })), stringWithArgs: $.field( $.Output.Nullable($Scalar.String), $.Args({ - boolean: $.Input.Nullable($Scalar.Boolean), - float: $.Input.Nullable($Scalar.Float), - id: $.Input.Nullable($Scalar.ID), - int: $.Input.Nullable($Scalar.Int), - string: $.Input.Nullable($Scalar.String), - }), + boolean: $.Input.Field($.Input.Nullable($Scalar.Boolean)), + float: $.Input.Field($.Input.Nullable($Scalar.Float)), + id: $.Input.Field($.Input.Nullable($Scalar.ID)), + int: $.Input.Field($.Input.Nullable($Scalar.Int)), + string: $.Input.Field($.Input.Nullable($Scalar.String)), + }, true), ), stringWithListArg: $.field( $.Output.Nullable($Scalar.String), - $.Args({ ints: $.Input.Nullable($.Input.List($.Input.Nullable($Scalar.Int))) }), + $.Args({ ints: $.Input.Field($.Input.Nullable($.Input.List($.Input.Nullable($Scalar.Int)))) }, true), + ), + stringWithListArgRequired: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ ints: $.Input.Field($.Input.List($Scalar.Int)) }, false), + ), + stringWithRequiredArg: $.field( + $.Output.Nullable($Scalar.String), + $.Args({ string: $.Input.Field($Scalar.String) }, false), ), - stringWithListArgRequired: $.field($.Output.Nullable($Scalar.String), $.Args({ ints: $.Input.List($Scalar.Int) })), - stringWithRequiredArg: $.field($.Output.Nullable($Scalar.String), $.Args({ string: $Scalar.String })), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionFooBar: $.field($.Output.Nullable(() => FooBarUnion)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionFooBarNonNull: $.field(() => FooBarUnion), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - unionFooBarWithArgs: $.field($.Output.Nullable(() => FooBarUnion), $.Args({ id: $.Input.Nullable($Scalar.ID) })), + unionFooBarWithArgs: $.field( + $.Output.Nullable(() => FooBarUnion), + $.Args({ id: $.Input.Field($.Input.Nullable($Scalar.ID)) }, true), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionObject: $.field($.Output.Nullable(() => ObjectUnion)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. unionObjectNonNull: $.field(() => ObjectUnion), }) -export const $Index = { - name: 'default' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query', 'Mutation'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation, diff --git a/tests/_/schema/generated/modules/Select.ts b/tests/_/schema/generated/modules/Select.ts index 8da158d3c..65d878179 100644 --- a/tests/_/schema/generated/modules/Select.ts +++ b/tests/_/schema/generated/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from '../../../../../src/entrypoints/client.js' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // --------- diff --git a/tests/_/schemaMutationOnly/generated/modules/Data.ts b/tests/_/schemaMutationOnly/generated/modules/Data.ts new file mode 100644 index 000000000..cc10a9037 --- /dev/null +++ b/tests/_/schemaMutationOnly/generated/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `MutationOnly` + +export type Name = 'MutationOnly' diff --git a/tests/_/schemaMutationOnly/generated/modules/Global.ts b/tests/_/schemaMutationOnly/generated/modules/Global.ts index 2faab311e..44c724f6a 100644 --- a/tests/_/schemaMutationOnly/generated/modules/Global.ts +++ b/tests/_/schemaMutationOnly/generated/modules/Global.ts @@ -1,10 +1,12 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' declare global { export namespace GraffleGlobalTypes { export interface Schemas { MutationOnly: { - name: 'MutationOnly' + name: Data.Name index: Index customScalars: {} featureOptions: { diff --git a/tests/_/schemaMutationOnly/generated/modules/SchemaBuildtime.ts b/tests/_/schemaMutationOnly/generated/modules/SchemaBuildtime.ts index f7b44aa8d..f3609f062 100644 --- a/tests/_/schemaMutationOnly/generated/modules/SchemaBuildtime.ts +++ b/tests/_/schemaMutationOnly/generated/modules/SchemaBuildtime.ts @@ -6,7 +6,7 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Mutation = $.Object$2<'Mutation', { + export type Mutation = $.Output.ObjectMutation<{ id: $.Field<$.Output.Nullable<$Scalar.ID>, null> idNonNull: $.Field<$Scalar.ID, null> }> diff --git a/tests/_/schemaMutationOnly/generated/modules/SchemaIndex.ts b/tests/_/schemaMutationOnly/generated/modules/SchemaIndex.ts index b2b9ec474..8c8378b80 100644 --- a/tests/_/schemaMutationOnly/generated/modules/SchemaIndex.ts +++ b/tests/_/schemaMutationOnly/generated/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'MutationOnly' + name: Data.Name RootTypesPresent: ['Mutation'] + RootUnion: Schema.Root.Mutation Root: { Query: null Mutation: Schema.Root.Mutation diff --git a/tests/_/schemaMutationOnly/generated/modules/SchemaRuntime.ts b/tests/_/schemaMutationOnly/generated/modules/SchemaRuntime.ts index ad90cffdb..6f7204560 100644 --- a/tests/_/schemaMutationOnly/generated/modules/SchemaRuntime.ts +++ b/tests/_/schemaMutationOnly/generated/modules/SchemaRuntime.ts @@ -1,7 +1,9 @@ /* eslint-disable */ import * as $ from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = undefined @@ -11,9 +13,10 @@ export const Mutation = $.Object$(`Mutation`, { idNonNull: $.field($Scalar.ID), }) -export const $Index = { - name: 'MutationOnly' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Mutation'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query: null, Mutation, diff --git a/tests/_/schemaMutationOnly/generated/modules/Select.ts b/tests/_/schemaMutationOnly/generated/modules/Select.ts index 79b20a5a8..a02e2ec2f 100644 --- a/tests/_/schemaMutationOnly/generated/modules/Select.ts +++ b/tests/_/schemaMutationOnly/generated/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from '../../../../../src/entrypoints/client.js' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // --------- diff --git a/tests/_/schemaQueryOnly/generated/modules/Data.ts b/tests/_/schemaQueryOnly/generated/modules/Data.ts new file mode 100644 index 000000000..ec4fc87b5 --- /dev/null +++ b/tests/_/schemaQueryOnly/generated/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `QueryOnly` + +export type Name = 'QueryOnly' diff --git a/tests/_/schemaQueryOnly/generated/modules/Global.ts b/tests/_/schemaQueryOnly/generated/modules/Global.ts index 37729ae59..d08faf49e 100644 --- a/tests/_/schemaQueryOnly/generated/modules/Global.ts +++ b/tests/_/schemaQueryOnly/generated/modules/Global.ts @@ -1,10 +1,12 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' declare global { export namespace GraffleGlobalTypes { export interface Schemas { QueryOnly: { - name: 'QueryOnly' + name: Data.Name index: Index customScalars: {} featureOptions: { diff --git a/tests/_/schemaQueryOnly/generated/modules/SchemaBuildtime.ts b/tests/_/schemaQueryOnly/generated/modules/SchemaBuildtime.ts index 1c593bf2a..001d3cbdf 100644 --- a/tests/_/schemaQueryOnly/generated/modules/SchemaBuildtime.ts +++ b/tests/_/schemaQueryOnly/generated/modules/SchemaBuildtime.ts @@ -6,7 +6,7 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ id: $.Field<$.Output.Nullable<$Scalar.ID>, null> idNonNull: $.Field<$Scalar.ID, null> }> diff --git a/tests/_/schemaQueryOnly/generated/modules/SchemaIndex.ts b/tests/_/schemaQueryOnly/generated/modules/SchemaIndex.ts index aafcffa23..d99ecd090 100644 --- a/tests/_/schemaQueryOnly/generated/modules/SchemaIndex.ts +++ b/tests/_/schemaQueryOnly/generated/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'QueryOnly' + name: Data.Name RootTypesPresent: ['Query'] + RootUnion: Schema.Root.Query Root: { Query: Schema.Root.Query Mutation: null diff --git a/tests/_/schemaQueryOnly/generated/modules/SchemaRuntime.ts b/tests/_/schemaQueryOnly/generated/modules/SchemaRuntime.ts index 876733676..d59103c7d 100644 --- a/tests/_/schemaQueryOnly/generated/modules/SchemaRuntime.ts +++ b/tests/_/schemaQueryOnly/generated/modules/SchemaRuntime.ts @@ -1,7 +1,9 @@ /* eslint-disable */ import * as $ from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = undefined @@ -11,9 +13,10 @@ export const Query = $.Object$(`Query`, { idNonNull: $.field($Scalar.ID), }) -export const $Index = { - name: 'QueryOnly' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation: null, diff --git a/tests/_/schemaQueryOnly/generated/modules/Select.ts b/tests/_/schemaQueryOnly/generated/modules/Select.ts index edc188220..9fa5b2d0e 100644 --- a/tests/_/schemaQueryOnly/generated/modules/Select.ts +++ b/tests/_/schemaQueryOnly/generated/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from '../../../../../src/entrypoints/schema.js' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from '../../../../../src/entrypoints/client.js' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // --------- diff --git a/tsconfig.diagnostic.json b/tsconfig.diagnostic.json new file mode 100644 index 000000000..e92ee3682 --- /dev/null +++ b/tsconfig.diagnostic.json @@ -0,0 +1,35 @@ +{ + "extends": [ + "@tsconfig/strictest/tsconfig.json", + "@tsconfig/node20/tsconfig.json" + ], + "compilerOptions": { + "noEmit": true, + "lib": ["DOM", "DOM.Iterable", "ES2023"], + // Use ESM + "module": "NodeNext", + "moduleResolution": "nodenext", + + // TODO enable, leads to lots of errors currently. + "exactOptionalPropertyTypes": false, + // We handle these with ESLint: + "noUnusedLocals": false, + "noUnusedParameters": false, + + // DX + "sourceMap": true, + "declaration": true, + "declarationMap": true, + "incremental": true, + "tsBuildInfoFile": "node_modules/.cache/.tsbuildinfo", + "noErrorTruncation": true, + + // Other + "skipLibCheck": true, + "esModuleInterop": true, + "isolatedModules": false, + "verbatimModuleSyntax": true + }, + "include": ["examples/55_generated/generated_arguments__arguments.ts"], + "exclude": ["build"] +} diff --git a/website/content/_snippets/examples/extension/opentelemetry.detail.md b/website/content/_snippets/examples/extension/opentelemetry.detail.md index b901b7686..754b9ac8b 100644 --- a/website/content/_snippets/examples/extension/opentelemetry.detail.md +++ b/website/content/_snippets/examples/extension/opentelemetry.detail.md @@ -37,14 +37,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'encode', - id: '045b80da91d65b9d', + id: '7c13553177946289', kind: 0, - timestamp: 1726596326575000, - duration: 1290.958, + timestamp: 1726679255958000, + duration: 522.417, attributes: {}, status: { code: 0 }, events: [], @@ -64,14 +64,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'pack', - id: '0854613b629f13f6', + id: '8133f915673ed123', kind: 0, - timestamp: 1726596326600000, - duration: 1107.5, + timestamp: 1726679255960000, + duration: 956.25, attributes: {}, status: { code: 0 }, events: [], @@ -91,14 +91,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'exchange', - id: '1a8a5ce00ea500ed', + id: '1812f1fcab09c9a8', kind: 0, - timestamp: 1726596326602000, - duration: 416840.875, + timestamp: 1726679255962000, + duration: 155840.833, attributes: {}, status: { code: 0 }, events: [], @@ -118,14 +118,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'unpack', - id: '79fc98db2f26ecb0', + id: 'a9f7183565f62ece', kind: 0, - timestamp: 1726596327019000, - duration: 2409.542, + timestamp: 1726679256118000, + duration: 2281.208, attributes: {}, status: { code: 0 }, events: [], @@ -145,14 +145,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'decode', - id: '5785c002db424547', + id: 'f2546a7c36cb5142', kind: 0, - timestamp: 1726596327022000, - duration: 126.584, + timestamp: 1726679256120000, + duration: 123.042, attributes: {}, status: { code: 0 }, events: [], @@ -172,14 +172,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', + traceId: '9052b021c626370eabb7d7fb4f575045', parentId: undefined, traceState: undefined, name: 'request', - id: 'ddcee8d1f8d74086', + id: '51abe3edd132250a', kind: 0, - timestamp: 1726596326573000, - duration: 448707.334, + timestamp: 1726679255958000, + duration: 163055.167, attributes: {}, status: { code: 0 }, events: [], diff --git a/website/content/_snippets/examples/extension/opentelemetry.md b/website/content/_snippets/examples/extension/opentelemetry.md index 9fd15fa81..d181ec523 100644 --- a/website/content/_snippets/examples/extension/opentelemetry.md +++ b/website/content/_snippets/examples/extension/opentelemetry.md @@ -35,14 +35,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'encode', - id: '045b80da91d65b9d', + id: '7c13553177946289', kind: 0, - timestamp: 1726596326575000, - duration: 1290.958, + timestamp: 1726679255958000, + duration: 522.417, attributes: {}, status: { code: 0 }, events: [], @@ -62,14 +62,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'pack', - id: '0854613b629f13f6', + id: '8133f915673ed123', kind: 0, - timestamp: 1726596326600000, - duration: 1107.5, + timestamp: 1726679255960000, + duration: 956.25, attributes: {}, status: { code: 0 }, events: [], @@ -89,14 +89,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'exchange', - id: '1a8a5ce00ea500ed', + id: '1812f1fcab09c9a8', kind: 0, - timestamp: 1726596326602000, - duration: 416840.875, + timestamp: 1726679255962000, + duration: 155840.833, attributes: {}, status: { code: 0 }, events: [], @@ -116,14 +116,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'unpack', - id: '79fc98db2f26ecb0', + id: 'a9f7183565f62ece', kind: 0, - timestamp: 1726596327019000, - duration: 2409.542, + timestamp: 1726679256118000, + duration: 2281.208, attributes: {}, status: { code: 0 }, events: [], @@ -143,14 +143,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'decode', - id: '5785c002db424547', + id: 'f2546a7c36cb5142', kind: 0, - timestamp: 1726596327022000, - duration: 126.584, + timestamp: 1726679256120000, + duration: 123.042, attributes: {}, status: { code: 0 }, events: [], @@ -170,14 +170,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', + traceId: '9052b021c626370eabb7d7fb4f575045', parentId: undefined, traceState: undefined, name: 'request', - id: 'ddcee8d1f8d74086', + id: '51abe3edd132250a', kind: 0, - timestamp: 1726596326573000, - duration: 448707.334, + timestamp: 1726679255958000, + duration: 163055.167, attributes: {}, status: { code: 0 }, events: [], diff --git a/website/content/_snippets/examples/output/envelope.detail.md b/website/content/_snippets/examples/output/envelope.detail.md index 08292d3e0..c9ed8a3e3 100644 --- a/website/content/_snippets/examples/output/envelope.detail.md +++ b/website/content/_snippets/examples/output/envelope.detail.md @@ -41,7 +41,7 @@ console.log(result) headers: Headers { connection: 'keep-alive', 'content-length': '119', - 'x-served-by': 'cache-yul1970046-YUL', + 'x-served-by': 'cache-yul1970040-YUL', 'accept-ranges': 'bytes', date: 'Sun, 08 Sep 2024 18:13:26 GMT', 'content-type': 'application/graphql-response+json; charset=utf-8', @@ -54,13 +54,13 @@ console.log(result) 'alt-svc': 'h3=":443"; ma=86400', 'access-control-allow-origin': '*', 'x-powered-by': 'Stellate', - age: '777121', + age: '860051', 'cache-control': 'public, s-maxage=2628000, stale-while-revalidate=2628000', 'x-cache': 'HIT', - 'x-cache-hits': '87', + 'x-cache-hits': '109', 'gcdn-cache': 'HIT', - 'stellate-rate-limit-budget-remaining': '48', - 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=48;refill=60', + 'stellate-rate-limit-budget-remaining': '38', + 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=38;refill=51', 'stellate-rate-limit-decision': 'pass', 'stellate-rate-limit-budget-required': '5', 'content-encoding': 'br' diff --git a/website/content/_snippets/examples/output/envelope.md b/website/content/_snippets/examples/output/envelope.md index cb05f751d..7fa81869c 100644 --- a/website/content/_snippets/examples/output/envelope.md +++ b/website/content/_snippets/examples/output/envelope.md @@ -39,7 +39,7 @@ console.log(result) headers: Headers { connection: 'keep-alive', 'content-length': '119', - 'x-served-by': 'cache-yul1970046-YUL', + 'x-served-by': 'cache-yul1970040-YUL', 'accept-ranges': 'bytes', date: 'Sun, 08 Sep 2024 18:13:26 GMT', 'content-type': 'application/graphql-response+json; charset=utf-8', @@ -52,13 +52,13 @@ console.log(result) 'alt-svc': 'h3=":443"; ma=86400', 'access-control-allow-origin': '*', 'x-powered-by': 'Stellate', - age: '777121', + age: '860051', 'cache-control': 'public, s-maxage=2628000, stale-while-revalidate=2628000', 'x-cache': 'HIT', - 'x-cache-hits': '87', + 'x-cache-hits': '109', 'gcdn-cache': 'HIT', - 'stellate-rate-limit-budget-remaining': '48', - 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=48;refill=60', + 'stellate-rate-limit-budget-remaining': '38', + 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=38;refill=51', 'stellate-rate-limit-decision': 'pass', 'stellate-rate-limit-budget-required': '5', 'content-encoding': 'br' diff --git a/website/content/_snippets/examples/transport-http/dynamic-headers.detail.md b/website/content/_snippets/examples/transport-http/dynamic-headers.detail.md index 62f107d91..f58bdc4f7 100644 --- a/website/content/_snippets/examples/transport-http/dynamic-headers.detail.md +++ b/website/content/_snippets/examples/transport-http/dynamic-headers.detail.md @@ -38,7 +38,7 @@ await graffle.rawString({ document: `{ languages { code } }` }) headers: Headers { accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', 'content-type': 'application/json', - 'x-sent-at-time': '1726596325884' + 'x-sent-at-time': '1726679254856' }, signal: undefined, method: 'post', diff --git a/website/content/_snippets/examples/transport-http/dynamic-headers.md b/website/content/_snippets/examples/transport-http/dynamic-headers.md index 58d61a628..c7925efe3 100644 --- a/website/content/_snippets/examples/transport-http/dynamic-headers.md +++ b/website/content/_snippets/examples/transport-http/dynamic-headers.md @@ -36,7 +36,7 @@ await graffle.rawString({ document: `{ languages { code } }` }) headers: Headers { accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', 'content-type': 'application/json', - 'x-sent-at-time': '1726596325884' + 'x-sent-at-time': '1726679254856' }, signal: undefined, method: 'post', diff --git a/website/content/_snippets/examples/transport-http/method-get.detail.md b/website/content/_snippets/examples/transport-http/method-get.detail.md index e344a1702..b0f02925f 100644 --- a/website/content/_snippets/examples/transport-http/method-get.detail.md +++ b/website/content/_snippets/examples/transport-http/method-get.detail.md @@ -30,28 +30,56 @@ await graffle.rawString({ document: `query { pokemonByName(name:"Nano") { hp } } ```txt -node:events:498 - throw er; // Unhandled 'error' event - ^ - -Error: listen EADDRINUSE: address already in use :::3000 - at Server.setupListenHandle [as _listen2] (node:net:XX:XX) - at listenInCluster (node:net:XX:XX) - at Server.listen (node:net:XX:XX) - at serveSchema (/some/path/to/helpers.ts:XX:XX) - at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX) - at async (/some/path/to/transport-http_method-get.ts:XX:XX) -Emitted 'error' event on Server instance at: - at emitErrorNT (node:net:XX:XX) - at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX) { - code: 'EADDRINUSE', - errno: -48, - syscall: 'listen', - address: '::', - port: 3000 +{ + methodMode: 'getReads', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', + 'content-type': 'application/json' + }, + signal: undefined, + method: 'post', + url: URL { + href: 'http://localhost:3000/graphql', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', + pathname: '/graphql', + search: '', + searchParams: URLSearchParams {}, + hash: '' + }, + body: '{"query":"mutation { addPokemon(attack:0, defense:0, hp:1, name:\\"Nano\\") { name } }"}' +} +``` + + +```txt +{ + methodMode: 'getReads', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8' + }, + signal: undefined, + method: 'get', + url: URL { + href: 'http://localhost:3000/graphql?query=query+%7B+pokemonByName%28name%3A%22Nano%22%29+%7B+hp+%7D+%7D', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', + pathname: '/graphql', + search: '?query=query+%7B+pokemonByName%28name%3A%22Nano%22%29+%7B+hp+%7D+%7D', + searchParams: URLSearchParams { 'query' => 'query { pokemonByName(name:"Nano") { hp } }' }, + hash: '' + } } - -Node.js vXX.XX.XX ``` diff --git a/website/content/_snippets/examples/transport-http/method-get.md b/website/content/_snippets/examples/transport-http/method-get.md index 9c29e9bae..10602311d 100644 --- a/website/content/_snippets/examples/transport-http/method-get.md +++ b/website/content/_snippets/examples/transport-http/method-get.md @@ -28,28 +28,56 @@ await graffle.rawString({ document: `query { pokemonByName(name:"Nano") { hp } } ```txt -node:events:498 - throw er; // Unhandled 'error' event - ^ - -Error: listen EADDRINUSE: address already in use :::3000 - at Server.setupListenHandle [as _listen2] (node:net:XX:XX) - at listenInCluster (node:net:XX:XX) - at Server.listen (node:net:XX:XX) - at serveSchema (/some/path/to/helpers.ts:XX:XX) - at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX) - at async (/some/path/to/transport-http_method-get.ts:XX:XX) -Emitted 'error' event on Server instance at: - at emitErrorNT (node:net:XX:XX) - at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX) { - code: 'EADDRINUSE', - errno: -48, - syscall: 'listen', - address: '::', - port: 3000 +{ + methodMode: 'getReads', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', + 'content-type': 'application/json' + }, + signal: undefined, + method: 'post', + url: URL { + href: 'http://localhost:3000/graphql', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', + pathname: '/graphql', + search: '', + searchParams: URLSearchParams {}, + hash: '' + }, + body: '{"query":"mutation { addPokemon(attack:0, defense:0, hp:1, name:\\"Nano\\") { name } }"}' +} +``` + + +```txt +{ + methodMode: 'getReads', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8' + }, + signal: undefined, + method: 'get', + url: URL { + href: 'http://localhost:3000/graphql?query=query+%7B+pokemonByName%28name%3A%22Nano%22%29+%7B+hp+%7D+%7D', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', + pathname: '/graphql', + search: '?query=query+%7B+pokemonByName%28name%3A%22Nano%22%29+%7B+hp+%7D+%7D', + searchParams: URLSearchParams { 'query' => 'query { pokemonByName(name:"Nano") { hp } }' }, + hash: '' + } } - -Node.js vXX.XX.XX ``` diff --git a/website/content/examples/10_transport-http/dynamic-headers.md b/website/content/examples/10_transport-http/dynamic-headers.md index e9120661c..9b30facb2 100644 --- a/website/content/examples/10_transport-http/dynamic-headers.md +++ b/website/content/examples/10_transport-http/dynamic-headers.md @@ -43,7 +43,7 @@ await graffle.rawString({ document: `{ languages { code } }` }) headers: Headers { accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', 'content-type': 'application/json', - 'x-sent-at-time': '1726596325884' + 'x-sent-at-time': '1726679254856' }, signal: undefined, method: 'post', diff --git a/website/content/examples/10_transport-http/method-get.md b/website/content/examples/10_transport-http/method-get.md index 9cec1eaac..e9f336016 100644 --- a/website/content/examples/10_transport-http/method-get.md +++ b/website/content/examples/10_transport-http/method-get.md @@ -36,27 +36,55 @@ await graffle.rawString({ document: `query { pokemonByName(name:"Nano") { hp } } ```txt -node:events:498 - throw er; // Unhandled 'error' event - ^ - -Error: listen EADDRINUSE: address already in use :::3000 - at Server.setupListenHandle [as _listen2] (node:net:XX:XX) - at listenInCluster (node:net:XX:XX) - at Server.listen (node:net:XX:XX) - at serveSchema (/some/path/to/helpers.ts:XX:XX) - at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX) - at async (/some/path/to/transport-http_method-get.ts:XX:XX) -Emitted 'error' event on Server instance at: - at emitErrorNT (node:net:XX:XX) - at process.processTicksAndRejections (node:internal/process/task_queues:XX:XX) { - code: 'EADDRINUSE', - errno: -48, - syscall: 'listen', - address: '::', - port: 3000 +{ + methodMode: 'getReads', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8', + 'content-type': 'application/json' + }, + signal: undefined, + method: 'post', + url: URL { + href: 'http://localhost:3000/graphql', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', + pathname: '/graphql', + search: '', + searchParams: URLSearchParams {}, + hash: '' + }, + body: '{"query":"mutation { addPokemon(attack:0, defense:0, hp:1, name:\\"Nano\\") { name } }"}' +} +``` + + +```txt +{ + methodMode: 'getReads', + headers: Headers { + accept: 'application/graphql-response+json; charset=utf-8, application/json; charset=utf-8' + }, + signal: undefined, + method: 'get', + url: URL { + href: 'http://localhost:3000/graphql?query=query+%7B+pokemonByName%28name%3A%22Nano%22%29+%7B+hp+%7D+%7D', + origin: 'http://localhost:3000', + protocol: 'http:', + username: '', + password: '', + host: 'localhost:3000', + hostname: 'localhost', + port: '3000', + pathname: '/graphql', + search: '?query=query+%7B+pokemonByName%28name%3A%22Nano%22%29+%7B+hp+%7D+%7D', + searchParams: URLSearchParams { 'query' => 'query { pokemonByName(name:"Nano") { hp } }' }, + hash: '' + } } - -Node.js vXX.XX.XX ``` diff --git a/website/content/examples/20_output/envelope.md b/website/content/examples/20_output/envelope.md index ff4d1f072..0302e4818 100644 --- a/website/content/examples/20_output/envelope.md +++ b/website/content/examples/20_output/envelope.md @@ -46,7 +46,7 @@ console.log(result) headers: Headers { connection: 'keep-alive', 'content-length': '119', - 'x-served-by': 'cache-yul1970046-YUL', + 'x-served-by': 'cache-yul1970040-YUL', 'accept-ranges': 'bytes', date: 'Sun, 08 Sep 2024 18:13:26 GMT', 'content-type': 'application/graphql-response+json; charset=utf-8', @@ -59,13 +59,13 @@ console.log(result) 'alt-svc': 'h3=":443"; ma=86400', 'access-control-allow-origin': '*', 'x-powered-by': 'Stellate', - age: '777121', + age: '860051', 'cache-control': 'public, s-maxage=2628000, stale-while-revalidate=2628000', 'x-cache': 'HIT', - 'x-cache-hits': '87', + 'x-cache-hits': '109', 'gcdn-cache': 'HIT', - 'stellate-rate-limit-budget-remaining': '48', - 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=48;refill=60', + 'stellate-rate-limit-budget-remaining': '38', + 'stellate-rate-limit-rules': '"IP limit";type="RequestCount";budget=50;limited=?0;remaining=38;refill=51', 'stellate-rate-limit-decision': 'pass', 'stellate-rate-limit-budget-required': '5', 'content-encoding': 'br' diff --git a/website/content/examples/60_extension/opentelemetry.md b/website/content/examples/60_extension/opentelemetry.md index a3fccd284..796987273 100644 --- a/website/content/examples/60_extension/opentelemetry.md +++ b/website/content/examples/60_extension/opentelemetry.md @@ -40,14 +40,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'encode', - id: '045b80da91d65b9d', + id: '7c13553177946289', kind: 0, - timestamp: 1726596326575000, - duration: 1290.958, + timestamp: 1726679255958000, + duration: 522.417, attributes: {}, status: { code: 0 }, events: [], @@ -67,14 +67,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'pack', - id: '0854613b629f13f6', + id: '8133f915673ed123', kind: 0, - timestamp: 1726596326600000, - duration: 1107.5, + timestamp: 1726679255960000, + duration: 956.25, attributes: {}, status: { code: 0 }, events: [], @@ -94,14 +94,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'exchange', - id: '1a8a5ce00ea500ed', + id: '1812f1fcab09c9a8', kind: 0, - timestamp: 1726596326602000, - duration: 416840.875, + timestamp: 1726679255962000, + duration: 155840.833, attributes: {}, status: { code: 0 }, events: [], @@ -121,14 +121,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'unpack', - id: '79fc98db2f26ecb0', + id: 'a9f7183565f62ece', kind: 0, - timestamp: 1726596327019000, - duration: 2409.542, + timestamp: 1726679256118000, + duration: 2281.208, attributes: {}, status: { code: 0 }, events: [], @@ -148,14 +148,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', - parentId: 'ddcee8d1f8d74086', + traceId: '9052b021c626370eabb7d7fb4f575045', + parentId: '51abe3edd132250a', traceState: undefined, name: 'decode', - id: '5785c002db424547', + id: 'f2546a7c36cb5142', kind: 0, - timestamp: 1726596327022000, - duration: 126.584, + timestamp: 1726679256120000, + duration: 123.042, attributes: {}, status: { code: 0 }, events: [], @@ -175,14 +175,14 @@ console.log(data) } }, instrumentationScope: { name: 'graffle', version: undefined, schemaUrl: undefined }, - traceId: '0c3328523947fd9b3201120e5b4cb4a0', + traceId: '9052b021c626370eabb7d7fb4f575045', parentId: undefined, traceState: undefined, name: 'request', - id: 'ddcee8d1f8d74086', + id: '51abe3edd132250a', kind: 0, - timestamp: 1726596326573000, - duration: 448707.334, + timestamp: 1726679255958000, + duration: 163055.167, attributes: {}, status: { code: 0 }, events: [], diff --git a/website/graffle/modules/Data.ts b/website/graffle/modules/Data.ts new file mode 100644 index 000000000..c4ad27afc --- /dev/null +++ b/website/graffle/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `default` + +export type Name = 'default' diff --git a/website/graffle/modules/Global.ts b/website/graffle/modules/Global.ts index ce1bb66ec..5b71de587 100644 --- a/website/graffle/modules/Global.ts +++ b/website/graffle/modules/Global.ts @@ -1,10 +1,12 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' declare global { export namespace GraffleGlobalTypes { export interface Schemas { default: { - name: 'default' + name: Data.Name index: Index customScalars: {} featureOptions: { diff --git a/website/graffle/modules/SchemaBuildtime.ts b/website/graffle/modules/SchemaBuildtime.ts index 433d266d5..58bf65468 100644 --- a/website/graffle/modules/SchemaBuildtime.ts +++ b/website/graffle/modules/SchemaBuildtime.ts @@ -6,42 +6,42 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ continent: $.Field< $.Output.Nullable, $.Args<{ - code: $Scalar.ID - }> + code: $.Input.Field<$Scalar.ID> + }, false> > continents: $.Field< $.Output.List, $.Args<{ - filter: $.Input.Nullable - }> + filter: $.Input.Field<$.Input.Nullable> + }, true> > countries: $.Field< $.Output.List, $.Args<{ - filter: $.Input.Nullable - }> + filter: $.Input.Field<$.Input.Nullable> + }, true> > country: $.Field< $.Output.Nullable, $.Args<{ - code: $Scalar.ID - }> + code: $.Input.Field<$Scalar.ID> + }, false> > language: $.Field< $.Output.Nullable, $.Args<{ - code: $Scalar.ID - }> + code: $.Input.Field<$Scalar.ID> + }, false> > languages: $.Field< $.Output.List, $.Args<{ - filter: $.Input.Nullable - }> + filter: $.Input.Field<$.Input.Nullable> + }, true> > }> } @@ -60,27 +60,27 @@ export namespace Enum { export namespace InputObject { export type ContinentFilterInput = $.InputObject<'ContinentFilterInput', { - code: $.Input.Nullable - }> + code: $.Input.Field<$.Input.Nullable> + }, true> export type CountryFilterInput = $.InputObject<'CountryFilterInput', { - code: $.Input.Nullable - continent: $.Input.Nullable - currency: $.Input.Nullable - name: $.Input.Nullable - }> + code: $.Input.Field<$.Input.Nullable> + continent: $.Input.Field<$.Input.Nullable> + currency: $.Input.Field<$.Input.Nullable> + name: $.Input.Field<$.Input.Nullable> + }, true> export type LanguageFilterInput = $.InputObject<'LanguageFilterInput', { - code: $.Input.Nullable - }> + code: $.Input.Field<$.Input.Nullable> + }, true> export type StringQueryOperatorInput = $.InputObject<'StringQueryOperatorInput', { - eq: $.Input.Nullable<$Scalar.String> - in: $.Input.Nullable<$.Input.List<$Scalar.String>> - ne: $.Input.Nullable<$Scalar.String> - nin: $.Input.Nullable<$.Input.List<$Scalar.String>> - regex: $.Input.Nullable<$Scalar.String> - }> + eq: $.Input.Field<$.Input.Nullable<$Scalar.String>> + in: $.Input.Field<$.Input.Nullable<$.Input.List<$Scalar.String>>> + ne: $.Input.Field<$.Input.Nullable<$Scalar.String>> + nin: $.Input.Field<$.Input.Nullable<$.Input.List<$Scalar.String>>> + regex: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> } // ------------------------------------------------------------ // @@ -115,8 +115,8 @@ export namespace Object { name: $.Field< $Scalar.String, $.Args<{ - lang: $.Input.Nullable<$Scalar.String> - }> + lang: $.Input.Field<$.Input.Nullable<$Scalar.String>> + }, true> > native: $.Field<$Scalar.String, null> phone: $.Field<$Scalar.String, null> diff --git a/website/graffle/modules/SchemaIndex.ts b/website/graffle/modules/SchemaIndex.ts index 4295ccc5c..730507977 100644 --- a/website/graffle/modules/SchemaIndex.ts +++ b/website/graffle/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'default' + name: Data.Name RootTypesPresent: ['Query'] + RootUnion: Schema.Root.Query Root: { Query: Schema.Root.Query Mutation: null diff --git a/website/graffle/modules/SchemaRuntime.ts b/website/graffle/modules/SchemaRuntime.ts index c7a82c114..c2209cf2c 100644 --- a/website/graffle/modules/SchemaRuntime.ts +++ b/website/graffle/modules/SchemaRuntime.ts @@ -1,32 +1,34 @@ /* eslint-disable */ import * as $ from 'graffle/schema' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = new URL('https://countries.trevorblades.com/graphql') export const ContinentFilterInput = $.InputObject(`ContinentFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) + code: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), +}, true) export const CountryFilterInput = $.InputObject(`CountryFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), - continent: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), - currency: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), - name: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) + code: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), + continent: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), + currency: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), + name: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), +}, true) export const LanguageFilterInput = $.InputObject(`LanguageFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) + code: $.Input.Field(() => $.Input.Nullable(StringQueryOperatorInput)), +}, true) export const StringQueryOperatorInput = $.InputObject(`StringQueryOperatorInput`, { - eq: $.Input.field($.Input.Nullable($Scalar.String)), - in: $.Input.field($.Input.Nullable($.Input.List($Scalar.String))), - ne: $.Input.field($.Input.Nullable($Scalar.String)), - nin: $.Input.field($.Input.Nullable($.Input.List($Scalar.String))), - regex: $.Input.field($.Input.Nullable($Scalar.String)), -}) + eq: $.Input.Field($.Input.Nullable($Scalar.String)), + in: $.Input.Field($.Input.Nullable($.Input.List($Scalar.String))), + ne: $.Input.Field($.Input.Nullable($Scalar.String)), + nin: $.Input.Field($.Input.Nullable($.Input.List($Scalar.String))), + regex: $.Input.Field($.Input.Nullable($Scalar.String)), +}, true) // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Continent = $.Object$(`Continent`, { @@ -49,7 +51,7 @@ export const Country = $.Object$(`Country`, { emojiU: $.field($Scalar.String), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. languages: $.field($.Output.List(() => Language)), - name: $.field($Scalar.String, $.Args({ lang: $.Input.Nullable($Scalar.String) })), + name: $.field($Scalar.String, $.Args({ lang: $.Input.Field($.Input.Nullable($Scalar.String)) }, true)), native: $.field($Scalar.String), phone: $.field($Scalar.String), phones: $.field($.Output.List($Scalar.String)), @@ -85,22 +87,32 @@ export const Subdivision = $.Object$(`Subdivision`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. export const Query = $.Object$(`Query`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - continent: $.field($.Output.Nullable(() => Continent), $.Args({ code: $Scalar.ID })), + continent: $.field($.Output.Nullable(() => Continent), $.Args({ code: $.Input.Field($Scalar.ID) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - continents: $.field($.Output.List(() => Continent), $.Args({ filter: $.Input.Nullable(ContinentFilterInput) })), + continents: $.field( + $.Output.List(() => Continent), + $.Args({ filter: $.Input.Field($.Input.Nullable(ContinentFilterInput)) }, true), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - countries: $.field($.Output.List(() => Country), $.Args({ filter: $.Input.Nullable(CountryFilterInput) })), + countries: $.field( + $.Output.List(() => Country), + $.Args({ filter: $.Input.Field($.Input.Nullable(CountryFilterInput)) }, true), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - country: $.field($.Output.Nullable(() => Country), $.Args({ code: $Scalar.ID })), + country: $.field($.Output.Nullable(() => Country), $.Args({ code: $.Input.Field($Scalar.ID) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - language: $.field($.Output.Nullable(() => Language), $.Args({ code: $Scalar.ID })), + language: $.field($.Output.Nullable(() => Language), $.Args({ code: $.Input.Field($Scalar.ID) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - languages: $.field($.Output.List(() => Language), $.Args({ filter: $.Input.Nullable(LanguageFilterInput) })), + languages: $.field( + $.Output.List(() => Language), + $.Args({ filter: $.Input.Field($.Input.Nullable(LanguageFilterInput)) }, true), + ), }) -export const $Index = { - name: 'default' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation: null, diff --git a/website/graffle/modules/Select.ts b/website/graffle/modules/Select.ts index 1c0fd0c95..38dd9a7b1 100644 --- a/website/graffle/modules/Select.ts +++ b/website/graffle/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from 'graffle/schema' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from 'graffle/client' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // --------- diff --git a/website/pokemon/modules/Data.ts b/website/pokemon/modules/Data.ts new file mode 100644 index 000000000..e48a3cf54 --- /dev/null +++ b/website/pokemon/modules/Data.ts @@ -0,0 +1,3 @@ +export const Name = `Pokemon` + +export type Name = 'Pokemon' diff --git a/website/pokemon/modules/Global.ts b/website/pokemon/modules/Global.ts index 68fa19cd1..890dd8515 100644 --- a/website/pokemon/modules/Global.ts +++ b/website/pokemon/modules/Global.ts @@ -1,10 +1,12 @@ +import type * as Data from './Data.js' + import type { Index } from './SchemaIndex.js' declare global { export namespace GraffleGlobalTypes { export interface Schemas { Pokemon: { - name: 'Pokemon' + name: Data.Name index: Index customScalars: {} featureOptions: { diff --git a/website/pokemon/modules/SchemaBuildtime.ts b/website/pokemon/modules/SchemaBuildtime.ts index c8e378ad7..c69b672ec 100644 --- a/website/pokemon/modules/SchemaBuildtime.ts +++ b/website/pokemon/modules/SchemaBuildtime.ts @@ -6,31 +6,31 @@ import type * as $Scalar from './Scalar.ts' // ------------------------------------------------------------ // export namespace Root { - export type Mutation = $.Object$2<'Mutation', { + export type Mutation = $.Output.ObjectMutation<{ addPokemon: $.Field< $.Output.Nullable, $.Args<{ - attack: $Scalar.Int - defense: $Scalar.Int - hp: $Scalar.Int - name: $Scalar.String - }> + attack: $.Input.Field<$Scalar.Int> + defense: $.Input.Field<$Scalar.Int> + hp: $.Input.Field<$Scalar.Int> + name: $.Input.Field<$Scalar.String> + }, false> > }> - export type Query = $.Object$2<'Query', { + export type Query = $.Output.ObjectQuery<{ pokemon: $.Field<$.Output.Nullable<$.Output.List>, null> pokemonByName: $.Field< $.Output.Nullable<$.Output.List>, $.Args<{ - name: $Scalar.String - }> + name: $.Input.Field<$Scalar.String> + }, false> > trainerByName: $.Field< $.Output.Nullable, $.Args<{ - name: $Scalar.String - }> + name: $.Input.Field<$Scalar.String> + }, false> > trainers: $.Field<$.Output.Nullable<$.Output.List>, null> }> diff --git a/website/pokemon/modules/SchemaIndex.ts b/website/pokemon/modules/SchemaIndex.ts index 5956c1ef5..1830dee07 100644 --- a/website/pokemon/modules/SchemaIndex.ts +++ b/website/pokemon/modules/SchemaIndex.ts @@ -1,10 +1,13 @@ /* eslint-disable */ +import type * as Data from './Data.js' + import type * as Schema from './SchemaBuildtime.js' export interface Index { - name: 'Pokemon' + name: Data.Name RootTypesPresent: ['Query', 'Mutation'] + RootUnion: Schema.Root.Query | Schema.Root.Mutation Root: { Query: Schema.Root.Query Mutation: Schema.Root.Mutation diff --git a/website/pokemon/modules/SchemaRuntime.ts b/website/pokemon/modules/SchemaRuntime.ts index 354bc0faa..0209a96da 100644 --- a/website/pokemon/modules/SchemaRuntime.ts +++ b/website/pokemon/modules/SchemaRuntime.ts @@ -1,7 +1,9 @@ /* eslint-disable */ import * as $ from 'graffle/schema' +import * as Data from './Data.js' import * as $Scalar from './Scalar.js' +import type { Index } from './SchemaIndex.js' export const $defaultSchemaUrl = undefined @@ -29,7 +31,12 @@ export const Mutation = $.Object$(`Mutation`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. addPokemon: $.field( $.Output.Nullable(() => Pokemon), - $.Args({ attack: $Scalar.Int, defense: $Scalar.Int, hp: $Scalar.Int, name: $Scalar.String }), + $.Args({ + attack: $.Input.Field($Scalar.Int), + defense: $.Input.Field($Scalar.Int), + hp: $.Input.Field($Scalar.Int), + name: $.Input.Field($Scalar.String), + }, false), ), }) @@ -38,16 +45,20 @@ export const Query = $.Object$(`Query`, { // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. pokemon: $.field($.Output.Nullable($.Output.List(() => Pokemon))), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - pokemonByName: $.field($.Output.Nullable($.Output.List(() => Pokemon)), $.Args({ name: $Scalar.String })), + pokemonByName: $.field( + $.Output.Nullable($.Output.List(() => Pokemon)), + $.Args({ name: $.Input.Field($Scalar.String) }, false), + ), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. - trainerByName: $.field($.Output.Nullable(() => Trainer), $.Args({ name: $Scalar.String })), + trainerByName: $.field($.Output.Nullable(() => Trainer), $.Args({ name: $.Input.Field($Scalar.String) }, false)), // @ts-ignore - circular types cannot infer. Ignore in case there are any. This comment is always added, it does not indicate if this particular type could infer or not. trainers: $.field($.Output.Nullable($.Output.List(() => Trainer))), }) -export const $Index = { - name: 'Pokemon' as const, +export const $Index: Index = { + name: Data.Name, RootTypesPresent: ['Query', 'Mutation'] as const, + RootUnion: undefined as any, // Type level only. Root: { Query, Mutation, diff --git a/website/pokemon/modules/Select.ts b/website/pokemon/modules/Select.ts index 100af8703..747ca4e53 100644 --- a/website/pokemon/modules/Select.ts +++ b/website/pokemon/modules/Select.ts @@ -1,11 +1,12 @@ import type { ResultSet, SelectionSet } from 'graffle/schema' +import * as Data from './Data.js' import type { Index } from './SchemaIndex.js' // Runtime // ------- import { createSelect } from 'graffle/client' -export const Select = createSelect(`default`) +export const Select = createSelect(Data.Name) // Buildtime // ---------