From 031503f362c1423fcbeb3ec959e0f31642def20c Mon Sep 17 00:00:00 2001 From: Jason Kuhrt Date: Sun, 15 Sep 2024 12:15:02 -0400 Subject: [PATCH] feat(generator): allow using sdl and url at same time (#1092) --- .../10_transport-http/transport-http_abort.ts | 6 ++-- src/cli/generate.ts | 34 +++++++++++++------ src/layers/2_generator/files.ts | 16 +++++++-- src/layers/5_select/select.ts | 6 ++-- 4 files changed, 42 insertions(+), 20 deletions(-) diff --git a/examples/10_transport-http/transport-http_abort.ts b/examples/10_transport-http/transport-http_abort.ts index c2aca87f6..e44cf58c2 100644 --- a/examples/10_transport-http/transport-http_abort.ts +++ b/examples/10_transport-http/transport-http_abort.ts @@ -14,7 +14,7 @@ const graffle = Graffle.create({ const resultPromise = graffle .with({ transport: { signal: abortController.signal } }) - // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // ^^^^^^^^^^^^^^^ .rawString({ document: ` { @@ -26,10 +26,8 @@ const resultPromise = graffle }) abortController.abort() -// ^^^^^^^ +// ^^^^^ const result = await resultPromise.catch((error: unknown) => (error as Error).message) show(result) - -// todo .with(...) variant diff --git a/src/cli/generate.ts b/src/cli/generate.ts index b4ddb7aeb..4cc1c90d6 100755 --- a/src/cli/generate.ts +++ b/src/cli/generate.ts @@ -13,20 +13,12 @@ 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( `Path to where your GraphQL schema is. If a URL is given it will be introspected. Otherwise assumed to be a file path to your GraphQL SDL file.`, ), ) - .parameter( - `output`, - z.string().min(1).default(`./graffle`).describe( - `Directory path for where to output the generated TypeScript files.`, - ), - ) .parametersExclusive( `schemaErrorType`, $ => @@ -43,6 +35,23 @@ const args = Command.create().description(`Generate a type safe GraphQL client.` ), ).default(`schemaErrorTypes`, true), ) + .parameter( + `defaultSchemaUrl`, + z.union([ + z.boolean().describe( + `If a GraphQL endpoint is given for "--schema", should it be set as the default URL in the generated client. If true then the client will default to using this URL when sending requests.`, + ), + z.string().min(1).describe( + `A GraphQL endpoint to be used as the default URL in the generated client for requests.`, + ), + ]).default(true), + ) + .parameter( + `output`, + z.string().min(1).default(`./graffle`).describe( + `Directory path for where to output the generated TypeScript files.`, + ), + ) .parameter(`format`, z.boolean().describe(`Format the generated files using dprint.`).default(true)) .parameter( `libraryPathClient`, @@ -70,10 +79,15 @@ const args = Command.create().description(`Generate a type safe GraphQL client.` .parse() const url = urlParseSafe(args.schema) +const defaultSchemaUrl = typeof args.defaultSchemaUrl === `string` + ? new URL(args.defaultSchemaUrl) + : args.defaultSchemaUrl await generateFiles({ - sourceSchema: url ? { type: `url`, url } : { type: `sdl`, dirPath: Path.dirname(args.schema) }, - defaultSchemaUrl: url ?? undefined, + sourceSchema: url + ? { type: `url`, url } + : { type: `sdl`, dirPath: Path.dirname(args.schema) }, + defaultSchemaUrl, name: args.name, libraryPaths: { client: args.libraryPathClient, diff --git a/src/layers/2_generator/files.ts b/src/layers/2_generator/files.ts index e4dd8a68b..a7d0c830b 100644 --- a/src/layers/2_generator/files.ts +++ b/src/layers/2_generator/files.ts @@ -12,14 +12,17 @@ export interface Input { outputDirPath?: string name?: string code?: Omit - defaultSchemaUrl?: URL + defaultSchemaUrl?: boolean | URL sourceSchema: { type: 'sdl' /** * Defaults to the source directory if set, otherwise the current working directory. */ dirPath?: string - } | { type: 'url'; url: URL } + } | { + type: 'url' + url: URL + } /** * Defaults to the current working directory. */ @@ -73,9 +76,16 @@ export const generateFiles = async (input: Input) => { ) const customScalarCodecsPathExists = await fileExists(customScalarCodecsFilePath) const typeScriptFormatter = (input.format ?? true) ? await getTypeScriptFormatter() : undefined + // dprint-ignore + const defaultSchemaUrl = + typeof input.defaultSchemaUrl === `boolean` + ? input.sourceSchema.type === `url` + ? input.sourceSchema.url + : undefined + : input.defaultSchemaUrl const codes = generateCode({ - defaultSchemaUrl: input.defaultSchemaUrl, + defaultSchemaUrl, libraryPaths: { ...input.libraryPaths, }, diff --git a/src/layers/5_select/select.ts b/src/layers/5_select/select.ts index f5f16bc64..294173494 100644 --- a/src/layers/5_select/select.ts +++ b/src/layers/5_select/select.ts @@ -34,13 +34,13 @@ type Create = <$Name extends GlobalRegistry.SchemaNames>( ) => TypeSelectionSets> export const create: Create = (_name) => { - return idProxy as any + return identityProxy as any } -const idProxy = new Proxy({}, { +const identityProxy = new Proxy({}, { get: () => (value: unknown) => value, }) // eslint-disable-next-line // @ts-ignore generated types -export const select: TypeSelectionSets = idProxy +export const select: TypeSelectionSets = identityProxy