diff --git a/examples/config-fetch.ts b/examples/config-fetch.ts index 464fefa2c..8a4a7f3ab 100644 --- a/examples/config-fetch.ts +++ b/examples/config-fetch.ts @@ -1,9 +1,7 @@ /* eslint-disable */ import { SocialStudies } from './generated-clients/SocialStudies/__.js' -// todo: if used introspection query to get schema, then default schema to that URL. -// todo: https://github.com/jasonkuhrt/graphql-request/issues/1015 -const socialStudies = SocialStudies.create({ schema: `https://countries.trevorblades.com/graphql` }) +const socialStudies = SocialStudies.create() .use({ name: `CustomFetch`, anyware: async ({ exchange }) => { diff --git a/examples/config-http-headers.ts b/examples/config-http-headers.ts index d6e6ca391..7c7fd4a67 100644 --- a/examples/config-http-headers.ts +++ b/examples/config-http-headers.ts @@ -1,7 +1,6 @@ import { SocialStudies } from './generated-clients/SocialStudies/__.js' const socialStudies = SocialStudies.create({ - schema: `https://countries.trevorblades.com/graphql`, headers: { authorization: `Bearer MY_TOKEN`, }, diff --git a/examples/generated-clients/SocialStudies/Client.ts b/examples/generated-clients/SocialStudies/Client.ts index 3fe693762..9407d6d71 100644 --- a/examples/generated-clients/SocialStudies/Client.ts +++ b/examples/generated-clients/SocialStudies/Client.ts @@ -1,5 +1,5 @@ import { createPrefilled } from '../../../src/entrypoints/alpha/client.js' -import { $Index } from './SchemaRuntime.js' +import { $defaultSchemaUrl, $Index } from './SchemaRuntime.js' -export const create = createPrefilled(`SocialStudies`, $Index) +export const create = createPrefilled(`SocialStudies`, $Index, $defaultSchemaUrl) diff --git a/examples/generated-clients/SocialStudies/Global.ts b/examples/generated-clients/SocialStudies/Global.ts index 0fe557ac1..22e18f71c 100644 --- a/examples/generated-clients/SocialStudies/Global.ts +++ b/examples/generated-clients/SocialStudies/Global.ts @@ -9,6 +9,10 @@ declare global { featureOptions: { schemaErrors: true } + /** + * https://countries.trevorblades.com/graphql + */ + defaultSchemaUrl: string } } } diff --git a/examples/generated-clients/SocialStudies/SchemaRuntime.ts b/examples/generated-clients/SocialStudies/SchemaRuntime.ts index 3a5e88a24..148c07f11 100644 --- a/examples/generated-clients/SocialStudies/SchemaRuntime.ts +++ b/examples/generated-clients/SocialStudies/SchemaRuntime.ts @@ -3,6 +3,8 @@ import * as $ from '../../../src/entrypoints/alpha/schema.js' import * as $Scalar from './Scalar.js' +export const $defaultSchemaUrl = new URL('https://countries.trevorblades.com/graphql') + export const ContinentFilterInput = $.InputObject(`ContinentFilterInput`, { code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), }) diff --git a/examples/generated-clients/countries/Client.ts b/examples/generated-clients/countries/Client.ts deleted file mode 100644 index 3fe693762..000000000 --- a/examples/generated-clients/countries/Client.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createPrefilled } from '../../../src/entrypoints/alpha/client.js' - -import { $Index } from './SchemaRuntime.js' - -export const create = createPrefilled(`SocialStudies`, $Index) diff --git a/examples/generated-clients/countries/Error.ts b/examples/generated-clients/countries/Error.ts deleted file mode 100644 index 6a480e85c..000000000 --- a/examples/generated-clients/countries/Error.ts +++ /dev/null @@ -1,14 +0,0 @@ -type Include = Exclude> - -type ObjectWithTypeName = { __typename: string } - -const ErrorObjectsTypeNameSelectedEnum = {} as Record - -const ErrorObjectsTypeNameSelected = Object.values(ErrorObjectsTypeNameSelectedEnum) - -type ErrorObjectsTypeNameSelected = (typeof ErrorObjectsTypeNameSelected)[number] - -export const isError = <$Value>(value: $Value): value is Include<$Value, ErrorObjectsTypeNameSelected> => { - return typeof value === 'object' && value !== null && '__typename' in value - && ErrorObjectsTypeNameSelected.some(_ => _.__typename === value.__typename) -} diff --git a/examples/generated-clients/countries/Global.ts b/examples/generated-clients/countries/Global.ts deleted file mode 100644 index 0fe557ac1..000000000 --- a/examples/generated-clients/countries/Global.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Index } from './Index.js' - -declare global { - export namespace GraphQLRequestTypes { - export interface Schemas { - SocialStudies: { - index: Index - customScalars: {} - featureOptions: { - schemaErrors: true - } - } - } - } -} diff --git a/examples/generated-clients/countries/Index.ts b/examples/generated-clients/countries/Index.ts deleted file mode 100644 index c84de63b8..000000000 --- a/examples/generated-clients/countries/Index.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* eslint-disable */ - -import type * as Schema from './SchemaBuildtime.js' - -export interface Index { - name: 'SocialStudies' - Root: { - Query: Schema.Root.Query - Mutation: null - Subscription: null - } - objects: { - Continent: Schema.Object.Continent - Country: Schema.Object.Country - Language: Schema.Object.Language - State: Schema.Object.State - Subdivision: Schema.Object.Subdivision - } - unions: {} - interfaces: {} - error: { - objects: {} - objectsTypename: {} - rootResultFields: { - Query: {} - Mutation: {} - Subscription: {} - } - } -} diff --git a/examples/generated-clients/countries/Scalar.ts b/examples/generated-clients/countries/Scalar.ts deleted file mode 100644 index 835a913c1..000000000 --- a/examples/generated-clients/countries/Scalar.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '../../../src/entrypoints/alpha/scalars.js' diff --git a/examples/generated-clients/countries/SchemaBuildtime.ts b/examples/generated-clients/countries/SchemaBuildtime.ts deleted file mode 100644 index 99347c396..000000000 --- a/examples/generated-clients/countries/SchemaBuildtime.ts +++ /dev/null @@ -1,154 +0,0 @@ -import type * as $ from '../../../src/entrypoints/alpha/schema.js' -import type * as $Scalar from './Scalar.ts' - -// ------------------------------------------------------------ // -// Root // -// ------------------------------------------------------------ // - -export namespace Root { - export type Query = $.Object$2<'Query', { - continent: $.Field< - $.Output.Nullable, - $.Args<{ - code: $Scalar.ID - }> - > - continents: $.Field< - $.Output.List, - $.Args<{ - filter: $.Input.Nullable - }> - > - countries: $.Field< - $.Output.List, - $.Args<{ - filter: $.Input.Nullable - }> - > - country: $.Field< - $.Output.Nullable, - $.Args<{ - code: $Scalar.ID - }> - > - language: $.Field< - $.Output.Nullable, - $.Args<{ - code: $Scalar.ID - }> - > - languages: $.Field< - $.Output.List, - $.Args<{ - filter: $.Input.Nullable - }> - > - }> -} - -// ------------------------------------------------------------ // -// Enum // -// ------------------------------------------------------------ // - -export namespace Enum { - // -- no types -- -} - -// ------------------------------------------------------------ // -// InputObject // -// ------------------------------------------------------------ // - -export namespace InputObject { - export type ContinentFilterInput = $.InputObject<'ContinentFilterInput', { - code: $.Input.Nullable - }> - - export type CountryFilterInput = $.InputObject<'CountryFilterInput', { - code: $.Input.Nullable - continent: $.Input.Nullable - currency: $.Input.Nullable - name: $.Input.Nullable - }> - - export type LanguageFilterInput = $.InputObject<'LanguageFilterInput', { - code: $.Input.Nullable - }> - - 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> - }> -} - -// ------------------------------------------------------------ // -// Interface // -// ------------------------------------------------------------ // - -export namespace Interface { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Object // -// ------------------------------------------------------------ // - -export namespace Object { - export type Continent = $.Object$2<'Continent', { - code: $.Field<$Scalar.ID, null> - countries: $.Field<$.Output.List, null> - name: $.Field<$Scalar.String, null> - }> - - export type Country = $.Object$2<'Country', { - awsRegion: $.Field<$Scalar.String, null> - capital: $.Field<$.Output.Nullable<$Scalar.String>, null> - code: $.Field<$Scalar.ID, null> - continent: $.Field - currencies: $.Field<$.Output.List<$Scalar.String>, null> - currency: $.Field<$.Output.Nullable<$Scalar.String>, null> - emoji: $.Field<$Scalar.String, null> - emojiU: $.Field<$Scalar.String, null> - languages: $.Field<$.Output.List, null> - name: $.Field< - $Scalar.String, - $.Args<{ - lang: $.Input.Nullable<$Scalar.String> - }> - > - native: $.Field<$Scalar.String, null> - phone: $.Field<$Scalar.String, null> - phones: $.Field<$.Output.List<$Scalar.String>, null> - states: $.Field<$.Output.List, null> - subdivisions: $.Field<$.Output.List, null> - }> - - export type Language = $.Object$2<'Language', { - code: $.Field<$Scalar.ID, null> - name: $.Field<$Scalar.String, null> - native: $.Field<$Scalar.String, null> - rtl: $.Field<$Scalar.Boolean, null> - }> - - export type State = $.Object$2<'State', { - code: $.Field<$.Output.Nullable<$Scalar.String>, null> - country: $.Field - name: $.Field<$Scalar.String, null> - }> - - export type Subdivision = $.Object$2<'Subdivision', { - code: $.Field<$Scalar.ID, null> - emoji: $.Field<$.Output.Nullable<$Scalar.String>, null> - name: $.Field<$Scalar.String, null> - }> -} - -// ------------------------------------------------------------ // -// Union // -// ------------------------------------------------------------ // - -export namespace Union { - // -- no types -- -} diff --git a/examples/generated-clients/countries/SchemaRuntime.ts b/examples/generated-clients/countries/SchemaRuntime.ts deleted file mode 100644 index 3a5e88a24..000000000 --- a/examples/generated-clients/countries/SchemaRuntime.ts +++ /dev/null @@ -1,124 +0,0 @@ -/* eslint-disable */ - -import * as $ from '../../../src/entrypoints/alpha/schema.js' -import * as $Scalar from './Scalar.js' - -export const ContinentFilterInput = $.InputObject(`ContinentFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) - -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)), -}) - -export const LanguageFilterInput = $.InputObject(`LanguageFilterInput`, { - code: $.Input.field(() => $.Input.Nullable(StringQueryOperatorInput)), -}) - -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)), -}) - -// @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`, { - code: $.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. - countries: $.field($.Output.List(() => Country)), - name: $.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. -export const Country = $.Object$(`Country`, { - awsRegion: $.field($Scalar.String), - capital: $.field($.Output.Nullable($Scalar.String)), - code: $.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. - continent: $.field(() => Continent), - currencies: $.field($.Output.List($Scalar.String)), - currency: $.field($.Output.Nullable($Scalar.String)), - emoji: $.field($Scalar.String), - 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) })), - native: $.field($Scalar.String), - phone: $.field($Scalar.String), - phones: $.field($.Output.List($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. - states: $.field($.Output.List(() => State)), - // @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. - subdivisions: $.field($.Output.List(() => 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 Language = $.Object$(`Language`, { - code: $.field($Scalar.ID), - name: $.field($Scalar.String), - native: $.field($Scalar.String), - rtl: $.field($Scalar.Boolean), -}) - -// @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 State = $.Object$(`State`, { - code: $.field($.Output.Nullable($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. - country: $.field(() => Country), - name: $.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. -export const Subdivision = $.Object$(`Subdivision`, { - code: $.field($Scalar.ID), - emoji: $.field($.Output.Nullable($Scalar.String)), - name: $.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. -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 })), - // @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) })), - // @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) })), - // @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 })), - // @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 })), - // @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) })), -}) - -export const $Index = { - name: 'SocialStudies' as const, - Root: { - Query, - Mutation: null, - Subscription: null, - }, - objects: { - Continent, - Country, - Language, - State, - Subdivision, - }, - unions: {}, - interfaces: {}, - error: { - objects: {}, - objectsTypename: {}, - rootResultFields: { - Query: {}, - Mutation: {}, - Subscription: {}, - }, - }, -} diff --git a/examples/generated-clients/countries/Select.ts b/examples/generated-clients/countries/Select.ts deleted file mode 100644 index 0d1a811f7..000000000 --- a/examples/generated-clients/countries/Select.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type { ResultSet, SelectionSet } from '../../../src/entrypoints/alpha/schema.js' -import type { Index } from './Index.js' - -// Runtime -// ------- - -import { createSelect } from '../../../src/entrypoints/alpha/client.js' -export const Select = createSelect('default') - -// Buildtime -// --------- - -export namespace Select { - // Root Types - // ---------- - - export type Query<$SelectionSet extends SelectionSet.Root> = ResultSet.Root< - $SelectionSet, - Index, - 'Query' - > - - // Object Types - // ------------ - - export type Continent<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['Continent'], Index> - - export type Country<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['Country'], Index> - - export type Language<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['Language'], Index> - - export type State<$SelectionSet extends SelectionSet.Object> = ResultSet.Object$< - $SelectionSet, - Index['objects']['State'], - Index - > - - export type Subdivision<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['Subdivision'], Index> - - // Union Types - // ----------- - - // -- None -- - - // Interface Types - // --------------- - - // -- None -- -} diff --git a/examples/generated-clients/countries/_.ts b/examples/generated-clients/countries/_.ts deleted file mode 100644 index 5e2498a39..000000000 --- a/examples/generated-clients/countries/_.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { create } from './Client.js' -export { isError } from './Error.js' -export { Select } from './Select.js' diff --git a/examples/generated-clients/countries/__.ts b/examples/generated-clients/countries/__.ts deleted file mode 100644 index 5984e15c3..000000000 --- a/examples/generated-clients/countries/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as SocialStudies from './_.js' diff --git a/src/cli/generate.ts b/src/cli/generate.ts index 840b001b5..658c065f5 100755 --- a/src/cli/generate.ts +++ b/src/cli/generate.ts @@ -1,12 +1,10 @@ #!/usr/bin/env node import { Command } from '@molt/command' -import { buildClientSchema } from 'graphql' import * as Path from 'node:path' import { z } from 'zod' import { generateFiles } from '../layers/2_generator/files.js' -import { safeParseUrl } from '../lib/prelude.js' -import { introspectionQuery } from './_helpers.js' +import { urlParseSafe } from '../lib/prelude.js' const args = Command.create().description(`Generate a type safe GraphQL client.`) .parameter( @@ -15,6 +13,8 @@ const args = Command.create().description(`Generate a type safe GraphQL client.` `The name of your client. If you are not generating multiple clients you probably do not need this. Otherwise you need to differentiate the clients so that their global type registrations do not conflict. It is possible to leave one client unnamed which will become the default client at the type level (e.g. in configuration etc.)`, ), ) + // TODO allow for URL to be read from an environment variable and henceforth referenced that way instead of being hardcoded in the generated client output. + // TODO allow explicitly providing URL for code generate even when reading from an SDL file. Allow faster generation times with URL still prefilled in generated client. .parameter( `schema`, z.string().min(1).describe( @@ -69,42 +69,22 @@ const args = Command.create().description(`Generate a type safe GraphQL client.` }) .parse() -const url = safeParseUrl(args.schema) +const url = urlParseSafe(args.schema) -if (url) { - const data = await introspectionQuery(url) - const schemaSource = buildClientSchema(data) - await generateFiles({ - name: args.name, - libraryPaths: { - client: args.libraryPathClient, - schema: args.libraryPathSchema, - scalars: args.libraryPathScalars, - }, - schemaSource: schemaSource, - outputDirPath: args.output, - format: args.format, - errorTypeNamePattern: args.schemaErrorType._tag === `schemaErrorTypePattern` - ? new RegExp(args.schemaErrorType.value) - : args.schemaErrorType.value - ? /^Error.+/ - : undefined, - }) -} else { - await generateFiles({ - name: args.name, - libraryPaths: { - client: args.libraryPathClient, - schema: args.libraryPathSchema, - scalars: args.libraryPathScalars, - }, - sourceDirPath: Path.dirname(args.schema), - outputDirPath: args.output, - format: args.format, - errorTypeNamePattern: args.schemaErrorType._tag === `schemaErrorTypePattern` - ? new RegExp(args.schemaErrorType.value) - : args.schemaErrorType.value - ? /^Error.+/ - : undefined, - }) -} +await generateFiles({ + sourceSchema: url ? { type: `url`, url } : { type: `sdl`, dirPath: Path.dirname(args.schema) }, + defaultSchemaUrl: url ?? undefined, + name: args.name, + libraryPaths: { + client: args.libraryPathClient, + schema: args.libraryPathSchema, + scalars: args.libraryPathScalars, + }, + outputDirPath: args.output, + format: args.format, + errorTypeNamePattern: args.schemaErrorType._tag === `schemaErrorTypePattern` + ? new RegExp(args.schemaErrorType.value) + : args.schemaErrorType.value + ? /^Error.+/ + : undefined, +}) diff --git a/src/layers/2_generator/__snapshots__/files.test.ts.snap b/src/layers/2_generator/__snapshots__/files.test.ts.snap index 0c39cdb7e..16a276ace 100644 --- a/src/layers/2_generator/__snapshots__/files.test.ts.snap +++ b/src/layers/2_generator/__snapshots__/files.test.ts.snap @@ -3,9 +3,9 @@ exports[`schema2 1`] = ` "import { createPrefilled } from '../../../../src/entrypoints/alpha/client.js' -import { $Index } from './SchemaRuntime.js' +import { $defaultSchemaUrl, $Index } from './SchemaRuntime.js' -export const create = createPrefilled(\`default\`, $Index) +export const create = createPrefilled(\`default\`, $Index, $defaultSchemaUrl) " `; @@ -563,6 +563,7 @@ exports[`schema2 9`] = ` import * as $ from '../../../../src/entrypoints/alpha/schema.js' import * as $Scalar from './Scalar.js' +export const $defaultSchemaUrl = undefined export const ABCEnum = $.Enum(\`ABCEnum\`, [\`A\`, \`B\`, \`C\`]) export const Case = $.Enum(\`Case\`, [\`ErrorOne\`, \`ErrorTwo\`, \`Object1\`]) @@ -637,11 +638,13 @@ export const Object2ImplementingInterface = $.Object$(\`Object2ImplementingInter // @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 ObjectNested = $.Object$(\`ObjectNested\`, { id: $.field($.Output.Nullable($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. object: $.field($.Output.Nullable(() => Object1)), }) // @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 ObjectUnion = $.Object$(\`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. fooBarUnion: $.field($.Output.Nullable(() => FooBarUnion)), }) @@ -686,6 +689,7 @@ export const Mutation = $.Object$(\`Mutation\`, { 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 })), + // @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) })), @@ -697,17 +701,23 @@ export const Query = $.Object$(\`Query\`, { $.Args({ date: $.Input.List($.Input.Nullable($Scalar.Date)) }), ), 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))), dateListNonNull: $.field($.Output.List($Scalar.Date)), dateNonNull: $.field($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. 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) })), 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. interface: $.field($.Output.Nullable(() => 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. 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 })), listInt: $.field($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int)))), listIntNonNull: $.field($.Output.List($Scalar.Int)), @@ -715,12 +725,19 @@ export const Query = $.Object$(\`Query\`, { $.Output.Nullable($.Output.List($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int))))), ), listListIntNonNull: $.field($.Output.List($.Output.List($Scalar.Int))), + // @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. lowerCaseUnion: $.field($.Output.Nullable(() => lowerCaseUnion)), + // @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. object: $.field($.Output.Nullable(() => Object1)), + // @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. objectList: $.field($.Output.Nullable($.Output.List(() => Object1))), + // @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. objectListNonNull: $.field($.Output.List(() => Object1)), + // @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. objectNested: $.field($.Output.Nullable(() => ObjectNested)), + // @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. objectNonNull: $.field(() => Object1), + // @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. objectWithArgs: $.field( $.Output.Nullable(() => Object1), $.Args({ @@ -731,7 +748,9 @@ export const Query = $.Object$(\`Query\`, { string: $.Input.Nullable($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. result: $.field($.Output.Nullable(() => Result), $.Args({ case: Case })), + // @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) })), string: $.field($.Output.Nullable($Scalar.String)), stringWithArgEnum: $.field($.Output.Nullable($Scalar.String), $.Args({ ABCEnum: $.Input.Nullable(ABCEnum) })), @@ -756,10 +775,15 @@ export const Query = $.Object$(\`Query\`, { ), 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) })), + // @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), }) diff --git a/src/layers/2_generator/code/Client.ts b/src/layers/2_generator/code/Client.ts index 395f0e186..ebb4c306b 100644 --- a/src/layers/2_generator/code/Client.ts +++ b/src/layers/2_generator/code/Client.ts @@ -8,9 +8,9 @@ export const { generate: generateClient, moduleName: moduleNameClient } = create code.push( `import { createPrefilled } from '${config.libraryPaths.client}'`, - `import { $Index } from './${moduleNameSchemaRuntime}.js'`, + `import { $defaultSchemaUrl, $Index } from './${moduleNameSchemaRuntime}.js'`, ``, - `export const create = createPrefilled(\`${config.name}\`, $Index)`, + `export const create = createPrefilled(\`${config.name}\`, $Index, $defaultSchemaUrl)`, ) return code.join(`\n\n`) diff --git a/src/layers/2_generator/code/SchemaRuntime.ts b/src/layers/2_generator/code/SchemaRuntime.ts index 3a9e15a4d..df1615666 100644 --- a/src/layers/2_generator/code/SchemaRuntime.ts +++ b/src/layers/2_generator/code/SchemaRuntime.ts @@ -42,6 +42,12 @@ export const { generate: generateRuntimeSchema, moduleName: moduleNameSchemaRunt `, ) + code.push( + `export const $defaultSchemaUrl = ${ + config.defaultSchemaUrl ? `new URL("${config.defaultSchemaUrl.href}")` : `undefined` + }`, + ) + code.push( config.typeMapByKind.GraphQLEnumType.map(type => enum$(config, type)).join(`\n`), config.typeMapByKind.GraphQLInputObjectType.map(type => inputObject(config, type)).join(`\n`), diff --git a/src/layers/2_generator/code/global.ts b/src/layers/2_generator/code/global.ts index 8048a59c6..0337903dc 100644 --- a/src/layers/2_generator/code/global.ts +++ b/src/layers/2_generator/code/global.ts @@ -20,6 +20,12 @@ export const { moduleName: moduleNameGlobal, generate: generateGlobal } = create ) } + const defaultSchemaUrlTsDoc = config.defaultSchemaUrl + ? `\n/** + * ${config.defaultSchemaUrl.href} + */` + : `` + code.push(` declare global { export namespace GraphQLRequestTypes { @@ -38,7 +44,8 @@ export const { moduleName: moduleNameGlobal, generate: generateGlobal } = create } featureOptions: { schemaErrors: ${config.options.errorTypeNamePattern ? `true` : `false`} - } + }${defaultSchemaUrlTsDoc} + defaultSchemaUrl: ${config.defaultSchemaUrl ? `string` : `null`} } } } diff --git a/src/layers/2_generator/files.ts b/src/layers/2_generator/files.ts index 218f0ad44..45fdf8cee 100644 --- a/src/layers/2_generator/files.ts +++ b/src/layers/2_generator/files.ts @@ -1,8 +1,9 @@ import type { Formatter } from '@dprint/formatter' -import { type GraphQLSchema, printSchema } from 'graphql' +import { buildClientSchema, printSchema } from 'graphql' import _ from 'json-bigint' import fs from 'node:fs/promises' import * as Path from 'node:path' +import { introspectionQuery } from '../../cli/_helpers.js' import type { OptionsInput } from './generateCode.js' import { generateCode, type Input as GenerateInput } from './generateCode.js' import { fileExists } from './prelude.js' @@ -11,9 +12,19 @@ export interface Input { outputDirPath: string name?: string code?: Omit + defaultSchemaUrl?: URL + sourceSchema: { + type: 'sdl' + /** + * Defaults to the source directory if set, otherwise the current working directory. + */ + dirPath?: string + } | { type: 'url'; url: URL } + /** + * Defaults to the current working directory. + */ sourceDirPath?: string sourceCustomScalarCodecsFilePath?: string - schemaSource?: GraphQLSchema schemaPath?: string format?: boolean errorTypeNamePattern?: OptionsInput['errorTypeNamePattern'] @@ -34,10 +45,23 @@ const getTypeScriptFormatter = async (): Promise => { } } +const resolveSourceSchema = async (input: Input) => { + if (input.sourceSchema.type === `sdl`) { + const sourceDirPath = input.sourceSchema.dirPath ?? input.sourceDirPath ?? process.cwd() + const schemaPath = input.schemaPath ?? Path.join(sourceDirPath, `schema.graphql`) + const sdl = await fs.readFile(schemaPath, `utf8`) + return sdl + } else { + const data = await introspectionQuery(input.sourceSchema.url) + const schema = buildClientSchema(data) + const sdl = printSchema(schema) + return sdl + } +} + export const generateFiles = async (input: Input) => { const sourceDirPath = input.sourceDirPath ?? process.cwd() - const schemaPath = input.schemaPath ?? Path.join(sourceDirPath, `schema.graphql`) - const schemaSource = input.schemaSource ? printSchema(input.schemaSource) : await fs.readFile(schemaPath, `utf8`) + const schemaSource = await resolveSourceSchema(input) // todo support other extensions: .tsx,.js,.mjs,.cjs const customScalarCodecsFilePath = input.sourceCustomScalarCodecsFilePath @@ -50,6 +74,7 @@ export const generateFiles = async (input: Input) => { const typeScriptFormatter = (input.format ?? true) ? await getTypeScriptFormatter() : undefined const codes = generateCode({ + defaultSchemaUrl: input.defaultSchemaUrl, libraryPaths: { ...input.libraryPaths, }, diff --git a/src/layers/2_generator/generateCode.ts b/src/layers/2_generator/generateCode.ts index 8d931c25a..b286d5d29 100644 --- a/src/layers/2_generator/generateCode.ts +++ b/src/layers/2_generator/generateCode.ts @@ -38,6 +38,7 @@ export interface Input { importPaths?: { customScalarCodecs?: string } + defaultSchemaUrl?: URL /** * The GraphQL SDL source code. */ @@ -49,6 +50,7 @@ export interface Config { name: string schema: GraphQLSchema typeMapByKind: TypeMapByKind + defaultSchemaUrl: URL | null rootTypes: { Query: GraphQLObjectType | null Mutation: GraphQLObjectType | null @@ -84,8 +86,10 @@ export const resolveOptions = (input: Input): Config => { const errorObjects = errorTypeNamePattern ? Object.values(typeMapByKind.GraphQLObjectType).filter(_ => _.name.match(errorTypeNamePattern)) : [] + const defaultSchemaUrl = input.defaultSchemaUrl ?? null return { name: input.name ?? defaultName, + defaultSchemaUrl, schema, error: { enabled: Boolean(errorTypeNamePattern), diff --git a/src/layers/2_generator/globalRegistry.ts b/src/layers/2_generator/globalRegistry.ts index 97036ff60..5c0cda8b8 100644 --- a/src/layers/2_generator/globalRegistry.ts +++ b/src/layers/2_generator/globalRegistry.ts @@ -16,6 +16,10 @@ type SomeSchema = { featureOptions: { schemaErrors: boolean } + /** + * If the code was generated with introspection, the URL used is taken as the default schema URL. + */ + defaultSchemaUrl: string | null } type ZeroSchema = { @@ -23,6 +27,7 @@ type ZeroSchema = { featureOptions: { schemaErrors: false } + defaultSchemaUrl: null } export type GlobalRegistry = Record diff --git a/src/layers/6_client/Settings/Input.ts b/src/layers/6_client/Settings/Input.ts index f7369b1a0..61ac375f8 100644 --- a/src/layers/6_client/Settings/Input.ts +++ b/src/layers/6_client/Settings/Input.ts @@ -42,24 +42,49 @@ export type Input<$Schema extends GlobalRegistry.SchemaList> = { // elideInputKey: true, } & InputPrefilled<$Schema> -export type InputRaw<$Schema extends GlobalRegistry.SchemaList> = { - schema: URLInput - /** - * Headers to send with each sent request. - */ - headers?: HeadersInit - /** - * Configure output behavior, such as if errors should be returned or thrown. - */ - output?: OutputInput<{ schemaErrors: GlobalRegistry.HasSchemaErrors<$Schema>; transport: 'http' }> -} | { - schema: GraphQLSchema - headers?: never - /** - * Configure output behavior, such as if errors should be returned or thrown. - */ - output?: OutputInput<{ schemaErrors: GlobalRegistry.HasSchemaErrors<$Schema>; transport: 'memory' }> -} +// TODO use code generation to display +// TODO test that schema is optional when introspection was used to generate client. +export type InputRaw<$Schema extends GlobalRegistry.SchemaList> = + | ( + & ($Schema['defaultSchemaUrl'] extends null ? { + schema: URLInput + } + : { + /** + * @defaultValue The introspection URL used to generate this Graffle client. + */ + schema?: URLInput + }) + & { + /** + * Headers to send with each sent request. + */ + headers?: HeadersInit + /** + * Configure output behavior, such as if errors should be returned or thrown. + */ + output?: OutputInput<{ schemaErrors: GlobalRegistry.HasSchemaErrors<$Schema>; transport: 'http' }> + } + ) + | ( + & ($Schema['defaultSchemaUrl'] extends null ? { + schema: GraphQLSchema + } + : { + /** + * TODO this TSDoc is never rendered in VSCode... + * @defaultValue The introspection URL used to generate this Graffle client. + */ + schema?: GraphQLSchema + }) + & { + headers?: never + /** + * Configure output behavior, such as if errors should be returned or thrown. + */ + output?: OutputInput<{ schemaErrors: GlobalRegistry.HasSchemaErrors<$Schema>; transport: 'memory' }> + } + ) export type OutputInput = & { diff --git a/src/layers/6_client/prefilled.ts b/src/layers/6_client/prefilled.ts new file mode 100644 index 000000000..e9197ea83 --- /dev/null +++ b/src/layers/6_client/prefilled.ts @@ -0,0 +1,44 @@ +import type { Exact, IsSomePropertiesRequired } from '../../lib/prelude.js' +import type { Schema } from '../1_Schema/__.js' +import type { GlobalRegistry } from '../2_generator/globalRegistry.js' +import { type Client, create } from './client.js' +import type { InputRaw, InputToConfig } from './Settings/Input.js' + +// dprint-ignore +export type CreatePrefilled = <$Name extends GlobalRegistry.SchemaNames>(name: $Name, schemaIndex: Schema.Index, schemaUrl?: URL) => < + // eslint-disable-next-line + // @ts-ignore passes after generation + $Input extends InputPrefilled, +>(...args: + // eslint-disable-next-line + // @ts-ignore passes after generation + IsSomePropertiesRequired> extends true + // eslint-disable-next-line + // @ts-ignore passes after generation + ? [input: Exact<$Input, InputPrefilled>] + // TODO test that input optional when no required properties + // eslint-disable-next-line + // @ts-ignore passes after generation + : ([input: Exact<$Input, InputPrefilled>] | []) +) => + // eslint-disable-next-line + // @ts-ignore passes after generation + Client, InputToConfig<$Input>> + +/** + * Create a constructor with some fields prefilled. Fields that can be prefilled are: + * - `name` + * - `schemaIndex` + * - `schema` (URL, if introspection was used for code generation) + */ +export const createPrefilled: CreatePrefilled = (name, schemaIndex, schemaUrl) => { + // eslint-disable-next-line + // @ts-ignore passes after generation + return ((input) => create({ schema: schemaUrl, ...input, name, schemaIndex })) as any +} + +// dprint-ignore +export type InputPrefilled<$Schema extends GlobalRegistry.SchemaList> = + $Schema extends any + ? InputRaw<$Schema> + : never diff --git a/src/lib/prelude.ts b/src/lib/prelude.ts index 6fb34ef69..6e511bf21 100644 --- a/src/lib/prelude.ts +++ b/src/lib/prelude.ts @@ -382,10 +382,16 @@ export namespace ConfigManager { // type AsBoolean = T extends boolean ? T : never -export const safeParseUrl = (url: string) => { +export const urlParseSafe = (url: string) => { try { return new URL(url) } catch { - return false + return null } } + +export type PickRequiredProperties = { + [K in keyof T as undefined extends T[K] ? never : K]: T[K] +} + +export type IsSomePropertiesRequired = keyof PickRequiredProperties extends never ? false : true diff --git a/tests/_/schema/generated/Client.ts b/tests/_/schema/generated/Client.ts index 44c2d2398..9a8f42c41 100644 --- a/tests/_/schema/generated/Client.ts +++ b/tests/_/schema/generated/Client.ts @@ -1,5 +1,5 @@ import { createPrefilled } from '../../../../src/entrypoints/alpha/client.js' -import { $Index } from './SchemaRuntime.js' +import { $defaultSchemaUrl, $Index } from './SchemaRuntime.js' -export const create = createPrefilled(`default`, $Index) +export const create = createPrefilled(`default`, $Index, $defaultSchemaUrl) diff --git a/tests/_/schema/generated/Global.ts b/tests/_/schema/generated/Global.ts index 9f89d200a..bb9a14ccd 100644 --- a/tests/_/schema/generated/Global.ts +++ b/tests/_/schema/generated/Global.ts @@ -13,6 +13,7 @@ declare global { featureOptions: { schemaErrors: true } + defaultSchemaUrl: null } } } diff --git a/tests/_/schema/generated/SchemaRuntime.ts b/tests/_/schema/generated/SchemaRuntime.ts index 876cb23f9..701c61682 100644 --- a/tests/_/schema/generated/SchemaRuntime.ts +++ b/tests/_/schema/generated/SchemaRuntime.ts @@ -3,6 +3,7 @@ import * as $ from '../../../../src/entrypoints/alpha/schema.js' import * as $Scalar from './Scalar.js' +export const $defaultSchemaUrl = undefined export const ABCEnum = $.Enum(`ABCEnum`, [`A`, `B`, `C`]) export const Case = $.Enum(`Case`, [`ErrorOne`, `ErrorTwo`, `Object1`]) @@ -77,11 +78,13 @@ export const Object2ImplementingInterface = $.Object$(`Object2ImplementingInterf // @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 ObjectNested = $.Object$(`ObjectNested`, { id: $.field($.Output.Nullable($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. object: $.field($.Output.Nullable(() => Object1)), }) // @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 ObjectUnion = $.Object$(`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. fooBarUnion: $.field($.Output.Nullable(() => FooBarUnion)), }) @@ -126,6 +129,7 @@ export const Mutation = $.Object$(`Mutation`, { 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 })), + // @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) })), @@ -137,17 +141,23 @@ export const Query = $.Object$(`Query`, { $.Args({ date: $.Input.List($.Input.Nullable($Scalar.Date)) }), ), 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))), dateListNonNull: $.field($.Output.List($Scalar.Date)), dateNonNull: $.field($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. 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) })), 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. interface: $.field($.Output.Nullable(() => 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. 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 })), listInt: $.field($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int)))), listIntNonNull: $.field($.Output.List($Scalar.Int)), @@ -155,12 +165,19 @@ export const Query = $.Object$(`Query`, { $.Output.Nullable($.Output.List($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int))))), ), listListIntNonNull: $.field($.Output.List($.Output.List($Scalar.Int))), + // @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. lowerCaseUnion: $.field($.Output.Nullable(() => lowerCaseUnion)), + // @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. object: $.field($.Output.Nullable(() => Object1)), + // @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. objectList: $.field($.Output.Nullable($.Output.List(() => Object1))), + // @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. objectListNonNull: $.field($.Output.List(() => Object1)), + // @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. objectNested: $.field($.Output.Nullable(() => ObjectNested)), + // @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. objectNonNull: $.field(() => Object1), + // @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. objectWithArgs: $.field( $.Output.Nullable(() => Object1), $.Args({ @@ -171,7 +188,9 @@ export const Query = $.Object$(`Query`, { string: $.Input.Nullable($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. result: $.field($.Output.Nullable(() => Result), $.Args({ case: Case })), + // @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) })), string: $.field($.Output.Nullable($Scalar.String)), stringWithArgEnum: $.field($.Output.Nullable($Scalar.String), $.Args({ ABCEnum: $.Input.Nullable(ABCEnum) })), @@ -196,10 +215,15 @@ export const Query = $.Object$(`Query`, { ), 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) })), + // @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), }) diff --git a/tests/_/schemaGenerate.ts b/tests/_/schemaGenerate.ts index b45c9d980..b54204d22 100644 --- a/tests/_/schemaGenerate.ts +++ b/tests/_/schemaGenerate.ts @@ -17,6 +17,7 @@ const generate = async ( printSchema(input.schema), ) await generateFiles({ + sourceSchema: { type: `sdl` }, sourceDirPath, sourceCustomScalarCodecsFilePath: join(`./tests/_/customScalarCodecs.ts`), outputDirPath: join(sourceDirPath, `/generated`), diff --git a/tests/_/schemaMutationOnly/generated/Client.ts b/tests/_/schemaMutationOnly/generated/Client.ts index 5fe4d6e40..0f3fdbcc2 100644 --- a/tests/_/schemaMutationOnly/generated/Client.ts +++ b/tests/_/schemaMutationOnly/generated/Client.ts @@ -1,5 +1,5 @@ import { createPrefilled } from '../../../../src/entrypoints/alpha/client.js' -import { $Index } from './SchemaRuntime.js' +import { $defaultSchemaUrl, $Index } from './SchemaRuntime.js' -export const create = createPrefilled(`MutationOnly`, $Index) +export const create = createPrefilled(`MutationOnly`, $Index, $defaultSchemaUrl) diff --git a/tests/_/schemaMutationOnly/generated/Global.ts b/tests/_/schemaMutationOnly/generated/Global.ts index e8c2d0a8c..0f07d32b9 100644 --- a/tests/_/schemaMutationOnly/generated/Global.ts +++ b/tests/_/schemaMutationOnly/generated/Global.ts @@ -9,6 +9,7 @@ declare global { featureOptions: { schemaErrors: false } + defaultSchemaUrl: null } } } diff --git a/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts b/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts index 91f87dc75..fbd8f2269 100644 --- a/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts +++ b/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts @@ -3,6 +3,8 @@ import * as $ from '../../../../src/entrypoints/alpha/schema.js' import * as $Scalar from './Scalar.js' +export const $defaultSchemaUrl = undefined + // @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 Mutation = $.Object$(`Mutation`, { id: $.field($.Output.Nullable($Scalar.ID)), diff --git a/tests/_/schemaQueryOnly/generated/Client.ts b/tests/_/schemaQueryOnly/generated/Client.ts index e534120b4..a902428ab 100644 --- a/tests/_/schemaQueryOnly/generated/Client.ts +++ b/tests/_/schemaQueryOnly/generated/Client.ts @@ -1,5 +1,5 @@ import { createPrefilled } from '../../../../src/entrypoints/alpha/client.js' -import { $Index } from './SchemaRuntime.js' +import { $defaultSchemaUrl, $Index } from './SchemaRuntime.js' -export const create = createPrefilled(`QueryOnly`, $Index) +export const create = createPrefilled(`QueryOnly`, $Index, $defaultSchemaUrl) diff --git a/tests/_/schemaQueryOnly/generated/Global.ts b/tests/_/schemaQueryOnly/generated/Global.ts index 3c915d1d5..dc3aa03ab 100644 --- a/tests/_/schemaQueryOnly/generated/Global.ts +++ b/tests/_/schemaQueryOnly/generated/Global.ts @@ -9,6 +9,7 @@ declare global { featureOptions: { schemaErrors: false } + defaultSchemaUrl: null } } } diff --git a/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts b/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts index e9af4a0c0..8521ebbeb 100644 --- a/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts +++ b/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts @@ -3,6 +3,8 @@ import * as $ from '../../../../src/entrypoints/alpha/schema.js' import * as $Scalar from './Scalar.js' +export const $defaultSchemaUrl = undefined + // @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`, { id: $.field($.Output.Nullable($Scalar.ID)),