diff --git a/package.json b/package.json index b0e983252..5f0eb4690 100644 --- a/package.json +++ b/package.json @@ -3,33 +3,10 @@ "version": "0.0.0-dripip", "packageManager": "pnpm@9.4.0", "type": "module", - "bin": { - "graffle": "./build/cli/generate.js" - }, + "main": "./build/entrypoints/main.js", "exports": { ".": { - "import": { - "types": "./build/entrypoints/main.d.ts", - "default": "./build/entrypoints/main.js" - } - }, - "./alpha/client": { - "import": { - "types": "./build/entrypoints/alpha/client.d.ts", - "default": "./build/entrypoints/alpha/client.js" - } - }, - "./alpha/schema": { - "import": { - "types": "./build/entrypoints/alpha/schema.d.ts", - "default": "./build/entrypoints/alpha/schema.js" - } - }, - "./alpha/schema/scalars": { - "import": { - "types": "./build/entrypoints/alpha/scalars.d.ts", - "default": "./build/entrypoints/alpha/scalars.js" - } + "default": "./build/entrypoints/main.js" } }, "files": [ @@ -69,7 +46,7 @@ "check:publint": "publint run --strict", "prepublishOnly": "pnpm build", "build:docs": "doctoc README.md --notitle && dprint fmt README.md", - "build": "pnpm clean && pnpm tsc --project tsconfig.build.json && chmod +x ./build/cli/generate.js", + "build": "pnpm clean && pnpm tsc --project tsconfig.build.json", "clean": "tsc --build --clean && rm -rf build", "test": "vitest", "test:web": "vitest --environment jsdom", @@ -80,27 +57,11 @@ "release:pr": "dripip pr" }, "dependencies": { - "@graphql-typed-document-node/core": "^3.2.0", - "@molt/command": "^0.9.0", - "zod": "^3.23.8" + "@graphql-typed-document-node/core": "^3.2.0" }, "peerDependencies": { - "@dprint/formatter": "^0.3.0", - "@dprint/typescript": "^0.91.1", - "dprint": "^0.46.2", "graphql": "14 - 16" }, - "peerDependenciesMeta": { - "dprint": { - "optional": true - }, - "@dprint/formatter": { - "optional": true - }, - "@dprint/typescript": { - "optional": true - } - }, "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", "@pothos/core": "^3.41.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c85c5c149..c1e1728de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,15 +17,9 @@ importers: '@graphql-typed-document-node/core': specifier: ^3.2.0 version: 3.2.0(graphql@16.9.0) - '@molt/command': - specifier: ^0.9.0 - version: 0.9.0 dprint: specifier: ^0.46.2 version: 0.46.2 - zod: - specifier: ^3.23.8 - version: 3.23.8 devDependencies: '@arethetypeswrong/cli': specifier: ^0.15.3 @@ -495,12 +489,6 @@ packages: '@microsoft/tsdoc@0.15.0': resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==} - '@molt/command@0.9.0': - resolution: {integrity: sha512-1JI8dAlpqlZoXyKWVQggX7geFNPxBpocHIXQCsnxDjKy+3WX4SGyZVJXuLlqRRrX7FmQCuuMAfx642ovXmPA9g==} - - '@molt/types@0.2.0': - resolution: {integrity: sha512-p6ChnEZDGjg9PYPec9BK6Yp5/DdSrYQvXTBAtgrnqX6N36cZy37ql1c8Tc5LclfIYBNG7EZp8NBcRTYJwyi84g==} - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -986,9 +974,6 @@ packages: ajv@8.12.0: resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} - alge@0.8.1: - resolution: {integrity: sha512-kiV9nTt+XIauAXsowVygDxMZLplZxDWt0W8plE/nB32/V2ziM/P/TxDbSVK7FYIUt2Xo16h3/htDh199LNPCKQ==} - anchor-markdown-header@0.6.0: resolution: {integrity: sha512-v7HJMtE1X7wTpNFseRhxsY/pivP4uAJbidVhPT+yhz4i/vV1+qx371IXuV9V7bN6KjFtheLJxqaSm0Y/8neJTA==} @@ -1000,10 +985,6 @@ packages: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -2243,18 +2224,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} - lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - - lodash.ismatch@4.4.0: - resolution: {integrity: sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==} - lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash.snakecase@4.1.1: - resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} - lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} @@ -2723,10 +2695,6 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - readline-sync@1.4.10: - resolution: {integrity: sha512-gNva8/6UAe8QYepIQH/jQ2qn91Qj0B9sYjMBBs3QOB8F2CXcKgLxQaJRP76sWVRQt+QU+8fAkCbCvjjMFu7Ycw==} - engines: {node: '>= 0.8.0'} - redeyed@2.1.1: resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} @@ -2754,9 +2722,6 @@ packages: remark-parse@9.0.0: resolution: {integrity: sha512-geKatMwSzEXKHuzBNU1z676sGcDcFoChMK38TgdHJNAYfFtsfHDQG7MoJAjs6sgYMqyLduCYWDIWZIxiPeafEw==} - remeda@1.61.0: - resolution: {integrity: sha512-caKfSz9rDeSKBQQnlJnVW3mbVdFgxgGWQKq1XlFokqjf+hQD5gxutLGTTY2A/x24UxVyJe9gH5fAkFI63ULw4A==} - repeat-string@1.6.1: resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} engines: {node: '>=0.10'} @@ -2936,10 +2901,6 @@ packages: std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - string-length@6.0.0: - resolution: {integrity: sha512-1U361pxZHEQ+FeSjzqRpV+cu2vTzYeWeafXFLykiFlv4Vc0n3njgU8HrMbyik5uwm77naWMuVG8fhEF+Ovb1Kg==} - engines: {node: '>=16'} - string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -2962,10 +2923,6 @@ packages: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} - strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} engines: {node: '>=4'} @@ -3049,9 +3006,6 @@ packages: ts-expose-internals-conditionally@1.0.0-empty.0: resolution: {integrity: sha512-F8m9NOF6ZhdOClDVdlM8gj3fDCav4ZIFSs/EI3ksQbAAXVSCN/Jh5OCJDDZWBuBy9psFc6jULGDlPwjMYMhJDw==} - ts-toolbelt@9.6.0: - resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} - tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -3395,9 +3349,6 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} - zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - zwitch@1.0.5: resolution: {integrity: sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==} @@ -3721,24 +3672,6 @@ snapshots: '@microsoft/tsdoc@0.15.0': {} - '@molt/command@0.9.0': - dependencies: - '@molt/types': 0.2.0 - alge: 0.8.1 - chalk: 5.3.0 - lodash.camelcase: 4.3.0 - lodash.snakecase: 4.1.1 - readline-sync: 1.4.10 - string-length: 6.0.0 - strip-ansi: 7.1.0 - ts-toolbelt: 9.6.0 - type-fest: 4.20.1 - zod: 3.23.8 - - '@molt/types@0.2.0': - dependencies: - ts-toolbelt: 9.6.0 - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -4366,13 +4299,6 @@ snapshots: require-from-string: 2.0.2 uri-js: 4.4.1 - alge@0.8.1: - dependencies: - lodash.ismatch: 4.4.0 - remeda: 1.61.0 - ts-toolbelt: 9.6.0 - zod: 3.23.8 - anchor-markdown-header@0.6.0: dependencies: emoji-regex: 10.1.0 @@ -4381,8 +4307,6 @@ snapshots: ansi-regex@5.0.1: {} - ansi-regex@6.0.1: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 @@ -5857,14 +5781,8 @@ snapshots: dependencies: p-locate: 5.0.0 - lodash.camelcase@4.3.0: {} - - lodash.ismatch@4.4.0: {} - lodash.merge@4.6.2: {} - lodash.snakecase@4.1.1: {} - lodash.sortby@4.7.0: {} lodash@4.17.21: {} @@ -6351,8 +6269,6 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 - readline-sync@1.4.10: {} - redeyed@2.1.1: dependencies: esprima: 4.0.1 @@ -6393,8 +6309,6 @@ snapshots: transitivePeerDependencies: - supports-color - remeda@1.61.0: {} - repeat-string@1.6.1: {} request@2.88.2: @@ -6626,10 +6540,6 @@ snapshots: std-env@3.7.0: {} - string-length@6.0.0: - dependencies: - strip-ansi: 7.1.0 - string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -6663,10 +6573,6 @@ snapshots: dependencies: ansi-regex: 5.0.1 - strip-ansi@7.1.0: - dependencies: - ansi-regex: 6.0.1 - strip-bom@3.0.0: {} strip-final-newline@3.0.0: {} @@ -6736,8 +6642,6 @@ snapshots: ts-expose-internals-conditionally@1.0.0-empty.0: {} - ts-toolbelt@9.6.0: {} - tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -7081,6 +6985,4 @@ snapshots: yocto-queue@1.0.0: {} - zod@3.23.8: {} - zwitch@1.0.5: {} diff --git a/src/cli/generate.ts b/src/cli/generate.ts deleted file mode 100755 index 7aa2dcb9c..000000000 --- a/src/cli/generate.ts +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env node - -import { Command } from '@molt/command' -import * as Path from 'node:path' -import { z } from 'zod' -import { generateFiles } from '../layers/2_generator/files.js' - -const args = Command.create().description(`Generate a type safe GraphQL client.`) - .parameter(`schema`, z.string().min(1).describe(`File path to where your GraphQL schema is.`)) - .parameter( - `output`, - z.string().min(1).describe( - `Directory path for where to output the generated TypeScript files.`, - ), - ) - .parametersExclusive( - `schemaErrorType`, - $ => - $.parameter( - `schemaErrorTypes`, - z.boolean().describe( - `Use the schema error types pattern. All object types whose name starts with "Error" will be considered to be error types. If you want to specify a custom name pattern then use the other parameter "schemaErrorTypePattern".`, - ), - ) - .parameter( - `schemaErrorTypePattern`, - z.string().min(1).describe( - `Designate objects whose name matches this JS regular expression as being error types in your schema.`, - ), - ).default(`schemaErrorTypes`, true), - ) - .parameter(`format`, z.boolean().describe(`Format the generated files using dprint.`).default(true)) - .settings({ - parameters: { - environment: false, - }, - }) - .parse() - -await generateFiles({ - 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, -}) diff --git a/src/entrypoints/alpha/client.ts b/src/entrypoints/alpha/client.ts deleted file mode 100644 index ef621dca3..000000000 --- a/src/entrypoints/alpha/client.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Client, create, createPrefilled, Input, InputPrefilled } from '../../layers/5_client/client.js' -export { create as createSelect, select } from '../../layers/5_select/select.js' diff --git a/src/entrypoints/alpha/main.ts b/src/entrypoints/alpha/main.ts deleted file mode 100644 index 4620dc77e..000000000 --- a/src/entrypoints/alpha/main.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { execute } from '../../layers/0_functions/execute.js' -export { request } from '../../layers/0_functions/request.js' -export * as Graffle from '../../layers/5_client/client.js' diff --git a/src/entrypoints/alpha/scalars.ts b/src/entrypoints/alpha/scalars.ts deleted file mode 100644 index ff0f7eb4e..000000000 --- a/src/entrypoints/alpha/scalars.ts +++ /dev/null @@ -1 +0,0 @@ -export * from '../../layers/1_Schema/Hybrid/types/Scalar/Scalar.js' diff --git a/src/entrypoints/alpha/schema.ts b/src/entrypoints/alpha/schema.ts deleted file mode 100644 index f7b20fd98..000000000 --- a/src/entrypoints/alpha/schema.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from '../../layers/1_Schema/__.js' -export { SelectionSet } from '../../layers/3_SelectionSet/__.js' -export { ResultSet } from '../../layers/4_ResultSet/__.js' diff --git a/src/layers/0_functions/execute.ts b/src/layers/0_functions/execute.ts deleted file mode 100644 index a97bc2479..000000000 --- a/src/layers/0_functions/execute.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { ExecutionResult, GraphQLSchema } from 'graphql' -import { execute as graphqlExecute, graphql } from 'graphql' -import type { BaseInput } from './types.js' - -interface Input extends BaseInput { - schema: GraphQLSchema -} - -export const execute = async (input: Input): Promise => { - switch (typeof input.document) { - case `string`: { - return await graphql({ - schema: input.schema, - source: input.document, - // contextValue: createContextValue(), // todo - variableValues: input.variables, - operationName: input.operationName, - }) - } - case `object`: { - return await graphqlExecute({ - schema: input.schema, - document: input.document, - // contextValue: createContextValue(), // todo - variableValues: input.variables, - operationName: input.operationName, - }) - } - default: - throw new Error(`Unsupported GraphQL document type: ${String(document)}`) - } -} diff --git a/src/layers/0_functions/request.ts b/src/layers/0_functions/request.ts deleted file mode 100644 index 2a6c5169f..000000000 --- a/src/layers/0_functions/request.ts +++ /dev/null @@ -1,49 +0,0 @@ -import type { ExecutionResult } from 'graphql' -import { print } from 'graphql' -import { parseExecutionResult } from '../../lib/graphqlHTTP.js' -import { CONTENT_TYPE_GQL } from '../../lib/http.js' -import type { BaseInput } from './types.js' - -export type URLInput = URL | string - -export interface NetworkRequestInput extends BaseInput { - url: URLInput - headers?: HeadersInit -} - -export type NetworkRequest = (input: NetworkRequestInput) => Promise - -/** - * @see https://graphql.github.io/graphql-over-http/draft/ - */ -export const request: NetworkRequest = async (input) => { - const documentEncoded = typeof input.document === `string` ? input.document : print(input.document) - - const body = { - query: documentEncoded, - variables: input.variables, - operationName: input.operationName, - } - - const bodyEncoded = JSON.stringify(body) - - const requestObject = new Request(input.url, { - method: `POST`, - headers: new Headers({ - 'accept': CONTENT_TYPE_GQL, - ...Object.fromEntries(new Headers(input.headers).entries()), - }), - body: bodyEncoded, - }) - - const response = await fetch(requestObject) - - if (!response.ok) { - throw new Error(`Request to GraphQL endpoint failed. (Status: ${String(response.status)})`) - } - - const json = await response.json() as object - const result = parseExecutionResult(json) - - return result -} diff --git a/src/layers/0_functions/requestOrExecute.ts b/src/layers/0_functions/requestOrExecute.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/layers/0_functions/types.ts b/src/layers/0_functions/types.ts deleted file mode 100644 index e18503eea..000000000 --- a/src/layers/0_functions/types.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { StandardScalarVariables } from '../../lib/graphql.js' -import type { DocumentInput, OperationNameInput } from '../5_client/types.js' - -export interface BaseInput { - document: DocumentInput - variables?: StandardScalarVariables - operationName?: OperationNameInput -} diff --git a/src/layers/1_Schema/Args.ts b/src/layers/1_Schema/Args.ts deleted file mode 100644 index 37ff38842..000000000 --- a/src/layers/1_Schema/Args.ts +++ /dev/null @@ -1,26 +0,0 @@ -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 const Args = (fields: F): Args => { - return { - fields, - } -} - -export type OmitNullableFields<$Fields extends InputFields> = { - [Key in keyof $Fields as $Fields[Key] 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] -} diff --git a/src/layers/1_Schema/Field.ts b/src/layers/1_Schema/Field.ts deleted file mode 100644 index 053a7c33c..000000000 --- a/src/layers/1_Schema/Field.ts +++ /dev/null @@ -1,37 +0,0 @@ -import type { Args } from './Args.js' -import type { MaybeThunk } from './core/helpers.js' -import type { Hybrid } from './Hybrid/__.js' -import type { Output } from './Output/__.js' - -export type Field<$Type extends Output.Any, $Args extends Args | null> = { - type: $Type - args: $Args -} - -export const field = <$Type extends Output.Any, $Args extends null | Args = null>( - type: MaybeThunk<$Type>, - args: $Args = null as $Args, -): Field<$Type, $Args> => { - return { - // At type level "type" is not a thunk - type: type as any, // eslint-disable-line - args, - } -} - -// todo test non null interface fields -export type SomeField = Field< - | Hybrid.Enum - | Hybrid.Scalar.Any - | Output.List - | Output.Nullable - | Output.Object$2 - | Output.Union - | Output.Interface | null>>, [any, ...any[]]>, - Args | null -> - -export type SomeFields<$Keys extends string | number | symbol = string | number | symbol> = Record< - $Keys, - SomeField -> diff --git a/src/layers/1_Schema/Hybrid/_.ts b/src/layers/1_Schema/Hybrid/_.ts deleted file mode 100644 index d2818dc2b..000000000 --- a/src/layers/1_Schema/Hybrid/_.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './types/Enum.js' -export * from './types/Scalar/__.js' diff --git a/src/layers/1_Schema/Hybrid/__.ts b/src/layers/1_Schema/Hybrid/__.ts deleted file mode 100644 index 780cae1e4..000000000 --- a/src/layers/1_Schema/Hybrid/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Hybrid from './_.js' diff --git a/src/layers/1_Schema/Hybrid/types/Enum.ts b/src/layers/1_Schema/Hybrid/types/Enum.ts deleted file mode 100644 index 81a096297..000000000 --- a/src/layers/1_Schema/Hybrid/types/Enum.ts +++ /dev/null @@ -1,17 +0,0 @@ -export interface Enum< - $Name extends string = string, - $Members extends [string, ...string[]] = [string, ...string[]], -> { - kind: 'Enum' - name: $Name - members: $Members -} - -export const Enum = <$Name extends string, $Members extends [string, ...string[]]>( - name: $Name, - members: $Members, -): Enum<$Name, $Members> => ({ - kind: `Enum`, - name, - members, -}) diff --git a/src/layers/1_Schema/Hybrid/types/Scalar/Scalar.ts b/src/layers/1_Schema/Hybrid/types/Scalar/Scalar.ts deleted file mode 100644 index d8043b63b..000000000 --- a/src/layers/1_Schema/Hybrid/types/Scalar/Scalar.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-types */ - -import type { GlobalRegistry } from '../../../../2_generator/globalRegistry.js' -import type { Codec } from './codec.js' -import { nativeScalarCodecs } from './nativeScalarCodecs.js' - -export { nativeScalarCodecs } from './nativeScalarCodecs.js' - -export const ScalarKind = `Scalar` - -export type ScalarKind = typeof ScalarKind - -export type StandardScalarRuntimeTypes = boolean | number | string - -export const scalar = <$Name extends string, $Codec extends Codec>( - name: $Name, - codec: $Codec, -): Scalar<$Name, $Codec> => ({ - kind: ScalarKind, - name: name, - codec: codec as any, // eslint-disable-line -}) - -export interface Scalar< - $Name extends string = string, - $Codec extends Codec = Codec, -> { - kind: ScalarKind - name: $Name - codec: $Codec -} - -export const String = scalar(`String`, nativeScalarCodecs.String) - -export const ID = scalar(`ID`, nativeScalarCodecs.String) - -export const Int = scalar(`Int`, nativeScalarCodecs.Number) - -export const Float = scalar(`Float`, nativeScalarCodecs.Number) - -export const Boolean = scalar(`Boolean`, nativeScalarCodecs.Boolean) - -export type ID = typeof ID - -export type String = typeof String - -export type Int = typeof Int - -export type Boolean = typeof Boolean - -export type Float = typeof Float - -export const Scalars = { - String, - ID, - Int, - Float, - Boolean, -} - -// todo this mixes scalars from different schemas -export type Any = - | String - | Int - | Boolean - | ID - | Float - | Values - -type Values = T extends any ? keyof T extends never ? never : T[keyof T] : never diff --git a/src/layers/1_Schema/Hybrid/types/Scalar/__.ts b/src/layers/1_Schema/Hybrid/types/Scalar/__.ts deleted file mode 100644 index e21bb3cfa..000000000 --- a/src/layers/1_Schema/Hybrid/types/Scalar/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Scalar from './Scalar.js' diff --git a/src/layers/1_Schema/Hybrid/types/Scalar/codec.ts b/src/layers/1_Schema/Hybrid/types/Scalar/codec.ts deleted file mode 100644 index 2072f6694..000000000 --- a/src/layers/1_Schema/Hybrid/types/Scalar/codec.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { StandardScalarRuntimeTypes } from './Scalar.js' - -export const codec = ( - codec: Codec, -) => codec - -export type Codec = { - encode: (value: Decoded) => Encoded - decode: (value: Encoded) => Decoded -} diff --git a/src/layers/1_Schema/Hybrid/types/Scalar/nativeScalarCodecs.ts b/src/layers/1_Schema/Hybrid/types/Scalar/nativeScalarCodecs.ts deleted file mode 100644 index b4441e6ef..000000000 --- a/src/layers/1_Schema/Hybrid/types/Scalar/nativeScalarCodecs.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { codec } from './codec.js' - -export const nativeScalarCodecs = { - String: codec({ - encode: (value) => value, - decode: (value) => value, - }), - Number: codec({ - encode: (value) => value, - decode: (value) => value, - }), - Boolean: codec({ - encode: (value) => value, - decode: (value) => value, - }), -} diff --git a/src/layers/1_Schema/Input/Input.ts b/src/layers/1_Schema/Input/Input.ts deleted file mode 100644 index 526979591..000000000 --- a/src/layers/1_Schema/Input/Input.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { MaybeThunk } from '../core/helpers.js' -import type { Any } from './typeGroups.js' - -export * from './typeGroups.js' -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> => { - return { - // Thunks do not exist at the type level - type: type as any, // eslint-disable-line - } -} - -export type Field<$Type extends any = any> = { - type: $Type -} diff --git a/src/layers/1_Schema/Input/__.ts b/src/layers/1_Schema/Input/__.ts deleted file mode 100644 index 31e74e92c..000000000 --- a/src/layers/1_Schema/Input/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Input from './Input.js' diff --git a/src/layers/1_Schema/Input/typeGroups.ts b/src/layers/1_Schema/Input/typeGroups.ts deleted file mode 100644 index ce8aa897e..000000000 --- a/src/layers/1_Schema/Input/typeGroups.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Hybrid } from '../Hybrid/__.js' -import type { InputObject } from './types/InputObject.js' -import type { List } from './types/List.js' -import type { Nullable } from './types/Nullable.js' - -export type Named = Hybrid.Enum | Hybrid.Scalar.Any | InputObject - -export type Any = List | Nullable | Named diff --git a/src/layers/1_Schema/Input/types/InputObject.ts b/src/layers/1_Schema/Input/types/InputObject.ts deleted file mode 100644 index c7db110ff..000000000 --- a/src/layers/1_Schema/Input/types/InputObject.ts +++ /dev/null @@ -1,21 +0,0 @@ -export type InputFields = Record - -export interface InputObject< - $Name extends string = string, - $Fields extends InputFields = InputFields, -> { - kind: 'InputObject' - name: $Name - fields: $Fields -} - -export const InputObject = <$Name extends string, $Fields extends Record>( - name: $Name, - fields: $Fields, -): InputObject<$Name, $Fields> => ({ - kind: `InputObject`, - name: name, - fields: { - ...fields, - }, -}) diff --git a/src/layers/1_Schema/Input/types/List.ts b/src/layers/1_Schema/Input/types/List.ts deleted file mode 100644 index 8d70d4e34..000000000 --- a/src/layers/1_Schema/Input/types/List.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Base } from '../../core/helpers.js' -import type { Any } from '../typeGroups.js' - -export type List<$InnerType extends Any> = Base.List<$InnerType> - -export const List = <$InnerType extends Any>(type: $InnerType): List<$InnerType> => ({ - kind: `list`, - type, -}) diff --git a/src/layers/1_Schema/Input/types/Nullable.ts b/src/layers/1_Schema/Input/types/Nullable.ts deleted file mode 100644 index 89b296582..000000000 --- a/src/layers/1_Schema/Input/types/Nullable.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Base, MaybeThunk } from '../../core/helpers.js' -import type { Any, Named } from '../typeGroups.js' -import type { List } from './List.js' - -type InnerType = Named | List - -export type Nullable<$InnerType extends InnerType> = Base.Nullable<$InnerType> - -export const Nullable = <$InnerType extends InnerType>(type: MaybeThunk<$InnerType>): Nullable<$InnerType> => ({ - kind: `nullable`, - // at type level "type" is not a thunk - type: type as any, // eslint-disable-line -}) - -// dprint-ignore -type UnwrapNullable<$Type> = - $Type extends Nullable ? UnwrapNullable<$innerType> - : $Type - -export const unwrapNullable = <$Type extends Any>(type: $Type): UnwrapNullable<$Type> => { - if (type.kind === `nullable`) return type.type - // @ts-expect-error fixme - return type -} diff --git a/src/layers/1_Schema/Output/Output.ts b/src/layers/1_Schema/Output/Output.ts deleted file mode 100644 index 4cf49c22e..000000000 --- a/src/layers/1_Schema/Output/Output.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { TSError } from '../../../lib/TSError.js' -import { readMaybeThunk } from '../core/helpers.js' -import type { Any, Named } from './typeGroups.js' -import type { __typename } from './types/__typename.js' -import type { List } from './types/List.js' -import type { Nullable } from './types/Nullable.js' - -export * from './typeGroups.js' -export * from './types/__typename.js' -export * from './types/Interface.js' -export * from './types/List.js' -export * from './types/Nullable.js' -export * from './types/Object.js' -export * from './types/Union.js' - -// todo extends any because of infinite depth issue in generated schema types -// dprint-ignore -export type Unwrap<$Type extends any> = - $Type extends List ? Unwrap<$innerType> : - $Type extends Nullable ? Unwrap<$innerType> : - $Type extends __typename ? $Type['type'] : - $Type extends Named ? $Type : - TSError<'Unwrap', 'Unknown $Type', { $Type: $Type }> - -// dprint-ignore -export type UnwrapNullable<$Type> = - $Type extends Nullable ? UnwrapNullable<$innerType> - : $Type - -export const unwrapNullable = <$Type extends Any>(type: $Type): UnwrapNullable<$Type> => { - if (type.kind === `nullable`) return type.type - return type as UnwrapNullable<$Type> -} - -export const unwrapToNamed = <$Type extends Any>(type: $Type): Unwrap<$Type> => { - // @ts-expect-error fixme - return type.kind === `list` || type.kind === `nullable` ? unwrapToNamed(readMaybeThunk(type).type) : type -} diff --git a/src/layers/1_Schema/Output/__.ts b/src/layers/1_Schema/Output/__.ts deleted file mode 100644 index 6df548327..000000000 --- a/src/layers/1_Schema/Output/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Output from './Output.js' diff --git a/src/layers/1_Schema/Output/typeGroups.ts b/src/layers/1_Schema/Output/typeGroups.ts deleted file mode 100644 index eb74a2627..000000000 --- a/src/layers/1_Schema/Output/typeGroups.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { Hybrid } from '../Hybrid/__.js' -import type { Enum } from '../Hybrid/types/Enum.js' -import type { __typename } from './types/__typename.js' -import type { Interface } from './types/Interface.js' -import type { List } from './types/List.js' -import type { Nullable } from './types/Nullable.js' -import type { Object$2 } from './types/Object.js' -import type { Union } from './types/Union.js' - -export type Named = Interface | Enum | Object$2 | Union | Hybrid.Scalar.Any - -export type Unnamed = List | Nullable - -export type Any = Unnamed | Named | __typename - -// dprint-ignore -export type UnwrapToNamed<$Type extends Any> = - $Type extends List ? UnwrapToNamed<$Inner> : - $Type extends Nullable ? UnwrapToNamed<$Inner> : - $Type diff --git a/src/layers/1_Schema/Output/types/Interface.ts b/src/layers/1_Schema/Output/types/Interface.ts deleted file mode 100644 index 47c5c875c..000000000 --- a/src/layers/1_Schema/Output/types/Interface.ts +++ /dev/null @@ -1,28 +0,0 @@ -import type { SomeFields } from '../../Field.js' -import type { Object$2 } from './Object.js' - -export type Interface< - $Name extends string = string, - $Fields extends SomeFields = SomeFields, - $Implementors extends [Object$2, ...Object$2[]] = [Object$2, ...Object$2[]], -> = { - kind: 'Interface' - name: $Name - fields: $Fields - implementors: $Implementors -} - -export const Interface = < - $Name extends string, - $Fields extends SomeFields, - $Implementors extends [Object$2, ...Object$2[]], ->( - name: $Name, - fields: $Fields, - implementors: $Implementors, -): Interface<$Name, $Fields, $Implementors> => ({ - kind: `Interface`, - name, - fields, - implementors, -}) diff --git a/src/layers/1_Schema/Output/types/List.ts b/src/layers/1_Schema/Output/types/List.ts deleted file mode 100644 index 9efc7d216..000000000 --- a/src/layers/1_Schema/Output/types/List.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Base, MaybeThunk } from '../../core/helpers.js' -import type { Named } from '../typeGroups.js' -import type { Nullable } from './Nullable.js' - -type InnerType = Named | Nullable | List - -export type List<$Type extends InnerType> = Base.List<$Type> - -export const List = <$Type extends InnerType>(type: MaybeThunk<$Type>): List<$Type> => ({ - kind: `list`, - // at type level "type" is not a thunk - type: type as any, // eslint-disable-line -}) diff --git a/src/layers/1_Schema/Output/types/Nullable.ts b/src/layers/1_Schema/Output/types/Nullable.ts deleted file mode 100644 index 86815f8df..000000000 --- a/src/layers/1_Schema/Output/types/Nullable.ts +++ /dev/null @@ -1,16 +0,0 @@ -import type { Base, MaybeThunk } from '../../core/helpers.js' -import type { Named } from '../typeGroups.js' -import type { __typename } from './__typename.js' -import type { List } from './List.js' - -type InnerType = Named | List - -export type Nullable<$Type extends InnerType> = Base.Nullable<$Type> - -export const Nullable = <$Type extends InnerType>( - type: MaybeThunk<$Type>, -): Nullable<$Type> => ({ - kind: `nullable`, - // at type level "type" is not a thunk - type: type as any, // eslint-disable-line -}) diff --git a/src/layers/1_Schema/Output/types/Object.ts b/src/layers/1_Schema/Output/types/Object.ts deleted file mode 100644 index 3b21d8a9c..000000000 --- a/src/layers/1_Schema/Output/types/Object.ts +++ /dev/null @@ -1,38 +0,0 @@ -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 Object$2< - $Name extends string = string, - $Fields extends SomeFields = SomeFields, -> { - kind: 'Object' - fields: { - __typename: Field<__typename<$Name>, null> - } & $Fields -} - -// Naming this "Object" breaks Vitest: https://github.com/vitest-dev/vitest/issues/5463 -export const Object$ = <$Name extends string, $Fields extends Record>>( - name: $Name, - fields: $Fields, - // eslint-disable-next-line - // @ts-ignore infinite depth issue -): Object$2<$Name, $Fields> => ({ - kind: `Object`, - fields: { - __typename: field(__typename(name)), - ...fields, - }, -}) - -export { Object$ as Object } - -// dprint-ignore -export type PickScalarFields<$Object extends Object$2> = { - [ - $Key in keyof $Object['fields'] as UnwrapToNamed<$Object['fields'][$Key]['type']> extends Hybrid.Scalar.Any | __typename ? $Key : never - ]: $Object['fields'][$Key] -} diff --git a/src/layers/1_Schema/Output/types/Union.ts b/src/layers/1_Schema/Output/types/Union.ts deleted file mode 100644 index 4e9e315ef..000000000 --- a/src/layers/1_Schema/Output/types/Union.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { Object$2 } from './Object.js' - -export type Union< - $Name extends string = string, - $Members extends [Object$2, ...Object$2[]] = [Object$2, ...Object$2[]], -> = { - kind: `Union` - name: $Name - members: $Members -} - -export const Union = < - $Name extends string, - $Members extends [Object$2, ...Object$2[]], ->( - name: $Name, - members: $Members, -): Union<$Name, $Members> => ({ - kind: `Union`, - name, - members, -}) diff --git a/src/layers/1_Schema/Output/types/__typename.ts b/src/layers/1_Schema/Output/types/__typename.ts deleted file mode 100644 index 3a7dc3428..000000000 --- a/src/layers/1_Schema/Output/types/__typename.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface __typename<$Type extends string = string> { - kind: 'typename' - type: $Type -} - -export const __typename = <$Type extends string>(type: $Type): __typename<$Type> => ({ kind: `typename`, type }) diff --git a/src/layers/1_Schema/_.ts b/src/layers/1_Schema/_.ts deleted file mode 100644 index 98b1cbbbd..000000000 --- a/src/layers/1_Schema/_.ts +++ /dev/null @@ -1,14 +0,0 @@ -export * from './Args.js' -export { type RootTypeName } from './core/helpers.js' -export * from './core/Index.js' -export * from './core/Named/__.js' -export * from './Field.js' -export * from './Hybrid/types/Enum.js' -export * from './Hybrid/types/Scalar/__.js' -export * from './Input/__.js' -export * from './Input/types/InputObject.js' -export * from './Output/__.js' -export * from './Output/types/__typename.js' -export * from './Output/types/Interface.js' -export { Object$, type Object$2 } from './Output/types/Object.js' -export * from './Output/types/Union.js' diff --git a/src/layers/1_Schema/__.ts b/src/layers/1_Schema/__.ts deleted file mode 100644 index ae38428c6..000000000 --- a/src/layers/1_Schema/__.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as Schema from './_.js' -export * from './_.js' diff --git a/src/layers/1_Schema/core/Index.ts b/src/layers/1_Schema/core/Index.ts deleted file mode 100644 index a6f7c78ac..000000000 --- a/src/layers/1_Schema/core/Index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { GlobalRegistry } from '../../2_generator/globalRegistry.js' -import type { Output } from '../Output/__.js' - -export interface Index { - name: GlobalRegistry.SchemaNames - Root: { - Query: null | Output.Object$2 - Mutation: null | Output.Object$2 - Subscription: null | Output.Object$2 - } - objects: Record - unions: Record - interfaces: Record - error: { - objects: Record - objectsTypename: Record - rootResultFields: { - Query: Record - Mutation: Record - Subscription: Record - } - } -} diff --git a/src/layers/1_Schema/core/Named/NamedType.test-d.ts b/src/layers/1_Schema/core/Named/NamedType.test-d.ts deleted file mode 100644 index e0c5b61cb..000000000 --- a/src/layers/1_Schema/core/Named/NamedType.test-d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { expectTypeOf, test } from 'vitest' -import type * as NamedType from './NamedType.js' - -test(`NameParse`, () => { - expectTypeOf>().toEqualTypeOf<'a'>() - expectTypeOf>().toEqualTypeOf<'a1'>() - expectTypeOf>().toEqualTypeOf<'A'>() - expectTypeOf>().toEqualTypeOf<'aa'>() - expectTypeOf>().toEqualTypeOf<'a_'>() - expectTypeOf>().toEqualTypeOf<'a__'>() - expectTypeOf>().toEqualTypeOf<'a__b'>() - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() - expectTypeOf>().toEqualTypeOf() -}) diff --git a/src/layers/1_Schema/core/Named/NamedType.ts b/src/layers/1_Schema/core/Named/NamedType.ts deleted file mode 100644 index 7c862a21d..000000000 --- a/src/layers/1_Schema/core/Named/NamedType.ts +++ /dev/null @@ -1,21 +0,0 @@ -import type { Digit, Letter } from '../../../../lib/prelude.js' - -/** - * @see http://spec.graphql.org/draft/#sec-Names - */ -// dprint-ignore -export type NameParse = - S extends NameHead ? S : - S extends `${NameHead}${infer Rest}` ? NameBodyParse extends never ? never : - S : - never - -// dprint-ignore -type NameBodyParse = - S extends NameBody ? S : - S extends `${NameBody}${infer Rest}` ? NameBodyParse extends never ? never : - S : - never - -export type NameHead = Letter | '_' -export type NameBody = Letter | '_' | Digit diff --git a/src/layers/1_Schema/core/Named/_.ts b/src/layers/1_Schema/core/Named/_.ts deleted file mode 100644 index a5943c577..000000000 --- a/src/layers/1_Schema/core/Named/_.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './NamedType.js' diff --git a/src/layers/1_Schema/core/Named/__.ts b/src/layers/1_Schema/core/Named/__.ts deleted file mode 100644 index 07fafba48..000000000 --- a/src/layers/1_Schema/core/Named/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Named from './_.js' diff --git a/src/layers/1_Schema/core/helpers.ts b/src/layers/1_Schema/core/helpers.ts deleted file mode 100644 index a97b25710..000000000 --- a/src/layers/1_Schema/core/helpers.ts +++ /dev/null @@ -1,22 +0,0 @@ -import type { Index } from './Index.js' - -export type MaybeThunk<$Type> = $Type | Thunk<$Type> - -export type Thunk<$Type> = () => $Type - -export const readMaybeThunk = (maybeThunk: MaybeThunk): T => - // @ts-expect-error fixme - typeof maybeThunk === `function` ? maybeThunk() : maybeThunk - -export namespace Base { - export interface Nullable<$Type> { - kind: 'nullable' - type: $Type - } - export interface List<$Type> { - kind: 'list' - type: $Type - } -} - -export type RootTypeName = keyof Index['Root'] diff --git a/src/layers/2_generator/__snapshots__/files.test.ts.snap b/src/layers/2_generator/__snapshots__/files.test.ts.snap deleted file mode 100644 index c0dea2380..000000000 --- a/src/layers/2_generator/__snapshots__/files.test.ts.snap +++ /dev/null @@ -1,819 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`schema2 1`] = ` -"import { createPrefilled } from '../../../../src/entrypoints/alpha/client.js' - -import { $Index } from './SchemaRuntime.js' - -export const create = createPrefilled(\`default\`, $Index) -" -`; - -exports[`schema2 2`] = ` -"export * as Graffle from './_.js' -" -`; - -exports[`schema2 3`] = ` -"export { create } from './Client.js' -export { isError } from './Error.js' -export { Select } from './Select.js' -" -`; - -exports[`schema2 4`] = ` -"type Include = Exclude> - -type ObjectWithTypeName = { __typename: string } - -const ErrorObjectsTypeNameSelectedEnum = { - ErrorOne: { __typename: 'ErrorOne' }, - ErrorTwo: { __typename: 'ErrorTwo' }, -} as const - -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) -} -" -`; - -exports[`schema2 5`] = ` -"import { ResultSet, SelectionSet } from '../../../../src/entrypoints/alpha/schema.js' -import { 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 Mutation<$SelectionSet extends SelectionSet.Root> = ResultSet.Root< - $SelectionSet, - Index, - 'Mutation' - > - - export type Query<$SelectionSet extends SelectionSet.Root> = ResultSet.Root< - $SelectionSet, - Index, - 'Query' - > - - // Object Types - // ------------ - - export type Bar<$SelectionSet extends SelectionSet.Object> = ResultSet.Object$< - $SelectionSet, - Index['objects']['Bar'], - Index - > - - export type DateObject1<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['DateObject1'], Index> - - export type DateObject2<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['DateObject2'], Index> - - export type ErrorOne<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ErrorOne'], Index> - - export type ErrorTwo<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ErrorTwo'], Index> - - export type Foo<$SelectionSet extends SelectionSet.Object> = ResultSet.Object$< - $SelectionSet, - Index['objects']['Foo'], - Index - > - - export type Object1<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['Object1'], Index> - - export type Object1ImplementingInterface< - $SelectionSet extends SelectionSet.Object, - > = ResultSet.Object$<$SelectionSet, Index['objects']['Object1ImplementingInterface'], Index> - - export type Object2ImplementingInterface< - $SelectionSet extends SelectionSet.Object, - > = ResultSet.Object$<$SelectionSet, Index['objects']['Object2ImplementingInterface'], Index> - - export type ObjectNested<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ObjectNested'], Index> - - export type ObjectUnion<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ObjectUnion'], Index> - - export type lowerCaseObject<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['lowerCaseObject'], Index> - - export type lowerCaseObject2<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['lowerCaseObject2'], Index> - - // Union Types - // ----------- - - export type DateUnion<$SelectionSet extends SelectionSet.Union> = - ResultSet.Union<$SelectionSet, Index['unions']['DateUnion'], Index> - - export type FooBarUnion<$SelectionSet extends SelectionSet.Union> = - ResultSet.Union<$SelectionSet, Index['unions']['FooBarUnion'], Index> - - export type Result<$SelectionSet extends SelectionSet.Union> = ResultSet.Union< - $SelectionSet, - Index['unions']['Result'], - Index - > - - export type lowerCaseUnion<$SelectionSet extends SelectionSet.Union> = - ResultSet.Union<$SelectionSet, Index['unions']['lowerCaseUnion'], Index> - - // Interface Types - // --------------- - - export type DateInterface1< - $SelectionSet extends SelectionSet.Interface, - > = ResultSet.Interface<$SelectionSet, Index['interfaces']['DateInterface1'], Index> - - export type Error<$SelectionSet extends SelectionSet.Interface> = - ResultSet.Interface<$SelectionSet, Index['interfaces']['Error'], Index> - - export type Interface<$SelectionSet extends SelectionSet.Interface> = - ResultSet.Interface<$SelectionSet, Index['interfaces']['Interface'], Index> -} -" -`; - -exports[`schema2 6`] = ` -"/* eslint-disable */ - -import type * as Schema from './SchemaBuildtime.js' - -export interface Index { - name: 'default' - Root: { - Query: Schema.Root.Query - Mutation: Schema.Root.Mutation - Subscription: null - } - objects: { - Bar: Schema.Object.Bar - DateObject1: Schema.Object.DateObject1 - DateObject2: Schema.Object.DateObject2 - ErrorOne: Schema.Object.ErrorOne - ErrorTwo: Schema.Object.ErrorTwo - Foo: Schema.Object.Foo - Object1: Schema.Object.Object1 - Object1ImplementingInterface: Schema.Object.Object1ImplementingInterface - Object2ImplementingInterface: Schema.Object.Object2ImplementingInterface - ObjectNested: Schema.Object.ObjectNested - ObjectUnion: Schema.Object.ObjectUnion - lowerCaseObject: Schema.Object.lowerCaseObject - lowerCaseObject2: Schema.Object.lowerCaseObject2 - } - unions: { - DateUnion: Schema.Union.DateUnion - FooBarUnion: Schema.Union.FooBarUnion - Result: Schema.Union.Result - lowerCaseUnion: Schema.Union.lowerCaseUnion - } - interfaces: { - DateInterface1: Schema.Interface.DateInterface1 - Error: Schema.Interface.Error - Interface: Schema.Interface.Interface - } - error: { - objects: { - ErrorOne: Schema.Object.ErrorOne - ErrorTwo: Schema.Object.ErrorTwo - } - objectsTypename: { - ErrorOne: { __typename: 'ErrorOne' } - ErrorTwo: { __typename: 'ErrorTwo' } - } - rootResultFields: { - Query: { - result: 'result' - resultNonNull: 'resultNonNull' - } - Mutation: {} - Subscription: {} - } - } -} -" -`; - -exports[`schema2 7`] = ` -"import type * as $ from '../../../../src/entrypoints/alpha/schema.js' -import type * as $Scalar from './Scalar.ts' - -// ------------------------------------------------------------ // -// Root // -// ------------------------------------------------------------ // - -export namespace Root { - export type Mutation = $.Object$2<'Mutation', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - idNonNull: $.Field<$Scalar.ID, null> - }> - - export type Query = $.Object$2<'Query', { - InputObjectNested: $.Field< - $.Output.Nullable<$Scalar.ID>, - $.Args<{ - input: $.Input.Nullable - }> - > - InputObjectNestedNonNull: $.Field< - $.Output.Nullable<$Scalar.ID>, - $.Args<{ - input: InputObject.InputObjectNestedNonNull - }> - > - /** - * Query enum field documentation. - */ - abcEnum: $.Field<$.Output.Nullable, null> - date: $.Field<$.Output.Nullable<$Scalar.Date>, null> - dateArg: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.Nullable<$Scalar.Date> - }> - > - dateArgInputObject: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - input: $.Input.Nullable - }> - > - dateArgList: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.Nullable<$.Input.List<$Scalar.Date>> - }> - > - dateArgNonNull: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $Scalar.Date - }> - > - dateArgNonNullList: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.List<$.Input.Nullable<$Scalar.Date>> - }> - > - dateArgNonNullListNonNull: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.List<$Scalar.Date> - }> - > - dateInterface1: $.Field<$.Output.Nullable, null> - dateList: $.Field<$.Output.Nullable<$.Output.List<$Scalar.Date>>, null> - dateListNonNull: $.Field<$.Output.List<$Scalar.Date>, null> - dateNonNull: $.Field<$Scalar.Date, null> - dateObject1: $.Field<$.Output.Nullable, null> - dateUnion: $.Field<$.Output.Nullable, null> - error: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - case: $.Input.Nullable<$Scalar.String> - }> - > - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - idNonNull: $.Field<$Scalar.ID, null> - interface: $.Field<$.Output.Nullable, null> - interfaceNonNull: $.Field - interfaceWithArgs: $.Field< - $.Output.Nullable, - $.Args<{ - id: $Scalar.ID - }> - > - listInt: $.Field<$.Output.Nullable<$.Output.List<$.Output.Nullable<$Scalar.Int>>>, null> - listIntNonNull: $.Field<$.Output.List<$Scalar.Int>, null> - listListInt: $.Field< - $.Output.Nullable<$.Output.List<$.Output.Nullable<$.Output.List<$.Output.Nullable<$Scalar.Int>>>>>, - null - > - listListIntNonNull: $.Field<$.Output.List<$.Output.List<$Scalar.Int>>, null> - lowerCaseUnion: $.Field<$.Output.Nullable, null> - object: $.Field<$.Output.Nullable, null> - objectList: $.Field<$.Output.Nullable<$.Output.List>, null> - objectListNonNull: $.Field<$.Output.List, null> - objectNested: $.Field<$.Output.Nullable, null> - objectNonNull: $.Field - 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> - }> - > - result: $.Field< - $.Output.Nullable, - $.Args<{ - case: Enum.Case - }> - > - resultNonNull: $.Field< - Union.Result, - $.Args<{ - case: $.Input.Nullable - }> - > - string: $.Field<$.Output.Nullable<$Scalar.String>, null> - stringWithArgEnum: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - ABCEnum: $.Input.Nullable - }> - > - stringWithArgInputObject: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - input: $.Input.Nullable - }> - > - stringWithArgInputObjectRequired: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - input: InputObject.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> - }> - > - stringWithListArg: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - ints: $.Input.Nullable<$.Input.List<$.Input.Nullable<$Scalar.Int>>> - }> - > - stringWithListArgRequired: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - ints: $.Input.List<$Scalar.Int> - }> - > - stringWithRequiredArg: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - string: $Scalar.String - }> - > - unionFooBar: $.Field<$.Output.Nullable, null> - unionFooBarNonNull: $.Field - unionFooBarWithArgs: $.Field< - $.Output.Nullable, - $.Args<{ - id: $.Input.Nullable<$Scalar.ID> - }> - > - unionObject: $.Field<$.Output.Nullable, null> - unionObjectNonNull: $.Field - }> -} - -// ------------------------------------------------------------ // -// Enum // -// ------------------------------------------------------------ // - -export namespace Enum { - /** - * Enum documentation. - * - * Members - * "A" - (DEPRECATED: Enum value A is deprecated.) - * "B" - Enum B member documentation. - * "C" - (DEPRECATED: Enum value C is deprecated.) - */ - export type ABCEnum = $.Enum<'ABCEnum', ['A', 'B', 'C']> - - export type Case = $.Enum<'Case', ['ErrorOne', 'ErrorTwo', 'Object1']> -} - -// ------------------------------------------------------------ // -// InputObject // -// ------------------------------------------------------------ // - -export namespace InputObject { - export type InputObject = $.InputObject<'InputObject', { - date: $.Input.Nullable<$Scalar.Date> - dateRequired: $Scalar.Date - id: $.Input.Nullable<$Scalar.ID> - idRequired: $Scalar.ID - }> - - export type InputObjectNested = $.InputObject<'InputObjectNested', { - InputObject: $.Input.Nullable - }> - - export type InputObjectNestedNonNull = $.InputObject<'InputObjectNestedNonNull', { - InputObject: InputObject.InputObject - }> -} - -// ------------------------------------------------------------ // -// Interface // -// ------------------------------------------------------------ // - -export namespace Interface { - export type DateInterface1 = $.Interface<'DateInterface1', { - date1: $.Field<$.Output.Nullable<$Scalar.Date>, null> - }, [Object.DateObject1]> - - export type Error = $.Interface<'Error', { - message: $.Field<$Scalar.String, null> - }, [Object.ErrorOne, Object.ErrorTwo]> - - export type Interface = $.Interface<'Interface', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }, [Object.Object1ImplementingInterface, Object.Object2ImplementingInterface]> -} - -// ------------------------------------------------------------ // -// Object // -// ------------------------------------------------------------ // - -export namespace Object { - export type Bar = $.Object$2<'Bar', { - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - }> - - export type DateObject1 = $.Object$2<'DateObject1', { - date1: $.Field<$.Output.Nullable<$Scalar.Date>, null> - }> - - export type DateObject2 = $.Object$2<'DateObject2', { - date2: $.Field<$.Output.Nullable<$Scalar.Date>, null> - }> - - export type ErrorOne = $.Object$2<'ErrorOne', { - infoId: $.Field<$.Output.Nullable<$Scalar.ID>, null> - message: $.Field<$Scalar.String, null> - }> - - export type ErrorTwo = $.Object$2<'ErrorTwo', { - infoInt: $.Field<$.Output.Nullable<$Scalar.Int>, null> - message: $.Field<$Scalar.String, null> - }> - - /** - * Object documentation. - */ - export type Foo = $.Object$2<'Foo', { - /** - * Field documentation. - * - * @deprecated Field a is deprecated. - */ - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }> - - export type Object1 = $.Object$2<'Object1', { - boolean: $.Field<$.Output.Nullable<$Scalar.Boolean>, null> - float: $.Field<$.Output.Nullable<$Scalar.Float>, null> - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - string: $.Field<$.Output.Nullable<$Scalar.String>, null> - }> - - export type Object1ImplementingInterface = $.Object$2<'Object1ImplementingInterface', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - }> - - export type Object2ImplementingInterface = $.Object$2<'Object2ImplementingInterface', { - boolean: $.Field<$.Output.Nullable<$Scalar.Boolean>, null> - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }> - - export type ObjectNested = $.Object$2<'ObjectNested', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - object: $.Field<$.Output.Nullable, null> - }> - - export type ObjectUnion = $.Object$2<'ObjectUnion', { - fooBarUnion: $.Field<$.Output.Nullable, null> - }> - - export type lowerCaseObject = $.Object$2<'lowerCaseObject', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }> - - export type lowerCaseObject2 = $.Object$2<'lowerCaseObject2', { - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - }> -} - -// ------------------------------------------------------------ // -// Union // -// ------------------------------------------------------------ // - -export namespace Union { - export type DateUnion = $.Union<'DateUnion', [Object.DateObject1, Object.DateObject2]> - - /** - * Union documentation. - */ - export type FooBarUnion = $.Union<'FooBarUnion', [Object.Bar, Object.Foo]> - - export type Result = $.Union<'Result', [Object.ErrorOne, Object.ErrorTwo, Object.Object1]> - - export type lowerCaseUnion = $.Union<'lowerCaseUnion', [Object.lowerCaseObject, Object.lowerCaseObject2]> -} -" -`; - -exports[`schema2 8`] = ` -"export * from '../../../../src/layers/1_Schema/Hybrid/types/Scalar/Scalar.js' -export * from '../../customScalarCodecs.js' -" -`; - -exports[`schema2 9`] = ` -"/* eslint-disable */ - -import * as $ from '../../../../src/entrypoints/alpha/schema.js' -import * as $Scalar from './Scalar.js' - -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), -}) - -export const InputObjectNested = $.InputObject(\`InputObjectNested\`, { - InputObject: $.Input.field(() => $.Input.Nullable(InputObject)), -}) - -export const InputObjectNestedNonNull = $.InputObject(\`InputObjectNestedNonNull\`, { - InputObject: $.Input.field(() => InputObject), -}) - -// @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\`, { - int: $.field($.Output.Nullable($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. -export const DateObject1 = $.Object$(\`DateObject1\`, { - date1: $.field($.Output.Nullable($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. -export const DateObject2 = $.Object$(\`DateObject2\`, { - date2: $.field($.Output.Nullable($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. -export const ErrorOne = $.Object$(\`ErrorOne\`, { - infoId: $.field($.Output.Nullable($Scalar.ID)), - message: $.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 ErrorTwo = $.Object$(\`ErrorTwo\`, { - infoInt: $.field($.Output.Nullable($Scalar.Int)), - message: $.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 Foo = $.Object$(\`Foo\`, { - 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. -export const Object1 = $.Object$(\`Object1\`, { - boolean: $.field($.Output.Nullable($Scalar.Boolean)), - float: $.field($.Output.Nullable($Scalar.Float)), - id: $.field($.Output.Nullable($Scalar.ID)), - int: $.field($.Output.Nullable($Scalar.Int)), - string: $.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. -export const Object1ImplementingInterface = $.Object$(\`Object1ImplementingInterface\`, { - id: $.field($.Output.Nullable($Scalar.ID)), - int: $.field($.Output.Nullable($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. -export const Object2ImplementingInterface = $.Object$(\`Object2ImplementingInterface\`, { - boolean: $.field($.Output.Nullable($Scalar.Boolean)), - 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. -export const ObjectNested = $.Object$(\`ObjectNested\`, { - id: $.field($.Output.Nullable($Scalar.ID)), - 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\`, { - fooBarUnion: $.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. -export const lowerCaseObject = $.Object$(\`lowerCaseObject\`, { - 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. -export const lowerCaseObject2 = $.Object$(\`lowerCaseObject2\`, { - int: $.field($.Output.Nullable($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. -export const DateUnion = $.Union(\`DateUnion\`, [DateObject1, DateObject2]) - -// @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 FooBarUnion = $.Union(\`FooBarUnion\`, [Bar, Foo]) - -// @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 Result = $.Union(\`Result\`, [ErrorOne, ErrorTwo, 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 lowerCaseUnion = $.Union(\`lowerCaseUnion\`, [lowerCaseObject, lowerCaseObject2]) - -export const DateInterface1 = $.Interface(\`DateInterface1\`, { date1: $.field($.Output.Nullable($Scalar.Date)) }, [ - DateObject1, -]) -export const Error = $.Interface(\`Error\`, { message: $.field($Scalar.String) }, [ErrorOne, ErrorTwo]) -export const Interface = $.Interface(\`Interface\`, { id: $.field($.Output.Nullable($Scalar.ID)) }, [ - Object1ImplementingInterface, - Object2ImplementingInterface, -]) - -// @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)), - 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. -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 })), - 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 })), - dateArgNonNullList: $.field( - $.Output.Nullable($Scalar.Date), - $.Args({ date: $.Input.List($.Input.Nullable($Scalar.Date)) }), - ), - dateArgNonNullListNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.List($Scalar.Date) })), - dateInterface1: $.field($.Output.Nullable(() => DateInterface1)), - dateList: $.field($.Output.Nullable($.Output.List($Scalar.Date))), - dateListNonNull: $.field($.Output.List($Scalar.Date)), - dateNonNull: $.field($Scalar.Date), - dateObject1: $.field($.Output.Nullable(() => DateObject1)), - 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), - interface: $.field($.Output.Nullable(() => Interface)), - interfaceNonNull: $.field(() => Interface), - 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)), - listListInt: $.field( - $.Output.Nullable($.Output.List($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int))))), - ), - listListIntNonNull: $.field($.Output.List($.Output.List($Scalar.Int))), - lowerCaseUnion: $.field($.Output.Nullable(() => lowerCaseUnion)), - object: $.field($.Output.Nullable(() => Object1)), - objectList: $.field($.Output.Nullable($.Output.List(() => Object1))), - objectListNonNull: $.field($.Output.List(() => Object1)), - objectNested: $.field($.Output.Nullable(() => ObjectNested)), - objectNonNull: $.field(() => Object1), - 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), - }), - ), - result: $.field($.Output.Nullable(() => Result), $.Args({ case: Case })), - 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) })), - stringWithArgInputObject: $.field( - $.Output.Nullable($Scalar.String), - $.Args({ input: $.Input.Nullable(InputObject) }), - ), - 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), - }), - ), - stringWithListArg: $.field( - $.Output.Nullable($Scalar.String), - $.Args({ ints: $.Input.Nullable($.Input.List($.Input.Nullable($Scalar.Int))) }), - ), - stringWithListArgRequired: $.field($.Output.Nullable($Scalar.String), $.Args({ ints: $.Input.List($Scalar.Int) })), - stringWithRequiredArg: $.field($.Output.Nullable($Scalar.String), $.Args({ string: $Scalar.String })), - unionFooBar: $.field($.Output.Nullable(() => FooBarUnion)), - unionFooBarNonNull: $.field(() => FooBarUnion), - unionFooBarWithArgs: $.field($.Output.Nullable(() => FooBarUnion), $.Args({ id: $.Input.Nullable($Scalar.ID) })), - unionObject: $.field($.Output.Nullable(() => ObjectUnion)), - unionObjectNonNull: $.field(() => ObjectUnion), -}) - -export const $Index = { - name: 'default' as const, - Root: { - Query, - Mutation, - Subscription: null, - }, - objects: { - Bar, - DateObject1, - DateObject2, - ErrorOne, - ErrorTwo, - Foo, - Object1, - Object1ImplementingInterface, - Object2ImplementingInterface, - ObjectNested, - ObjectUnion, - lowerCaseObject, - lowerCaseObject2, - }, - unions: { - DateUnion, - FooBarUnion, - Result, - lowerCaseUnion, - }, - interfaces: { - DateInterface1, - Error, - Interface, - }, - error: { - objects: { - ErrorOne, - ErrorTwo, - }, - objectsTypename: { - ErrorOne: { __typename: 'ErrorOne' }, - ErrorTwo: { __typename: 'ErrorTwo' }, - }, - rootResultFields: { - Query: { - result: 'result' as const, - resultNonNull: 'resultNonNull' as const, - }, - Mutation: {}, - Subscription: {}, - }, - }, -} -" -`; diff --git a/src/layers/2_generator/__snapshots__/generator.test.ts.snap b/src/layers/2_generator/__snapshots__/generator.test.ts.snap deleted file mode 100644 index 4f6123f04..000000000 --- a/src/layers/2_generator/__snapshots__/generator.test.ts.snap +++ /dev/null @@ -1,341 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`generates types from GraphQL SDL file 1`] = ` -"import type * as _ from '../../../../src/Schema/__.js' -import type * as $Scalar from './Scalar.ts' - -export namespace $ { - export interface Index { - Root: { - Query: Root.Query - Mutation: null - Subscription: null - } - objects: { - Foo: Object.Foo - Bar: Object.Bar - ObjectNested: Object.ObjectNested - lowerCaseObject: Object.lowerCaseObject - lowerCaseObject2: Object.lowerCaseObject2 - Object1: Object.Object1 - Object1ImplementingInterface: Object.Object1ImplementingInterface - Object2ImplementingInterface: Object.Object2ImplementingInterface - } - unions: { - FooBarUnion: Union.FooBarUnion - lowerCaseUnion: Union.lowerCaseUnion - } - } -} - -// ------------------------------------------------------------ // -// Root // -// ------------------------------------------------------------ // - -export namespace Root { - export type Query = _.Object<'Query', { - date: _.Field<_.Output.Nullable<$Scalar.Date>> - interface: _.Field<_.Output.Nullable> - id: _.Field<_.Output.Nullable<$Scalar.ID>> - idNonNull: _.Field<$Scalar.ID> - string: _.Field<_.Output.Nullable<$Scalar.String>> - stringWithRequiredArg: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - string: $Scalar.String - }> - > - stringWithArgs: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - string: _.Input.Nullable<$Scalar.String> - int: _.Input.Nullable<$Scalar.Int> - float: _.Input.Nullable<$Scalar.Float> - boolean: _.Input.Nullable<$Scalar.Boolean> - id: _.Input.Nullable<$Scalar.ID> - }> - > - stringWithArgEnum: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - ABCEnum: _.Input.Nullable - }> - > - stringWithListArg: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - ints: _.Input.Nullable<_.Input.List<_.Input.Nullable<$Scalar.Int>>> - }> - > - stringWithListArgRequired: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - ints: _.Input.List<_.Input.Nullable<$Scalar.Int>> - }> - > - stringWithArgInputObject: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - input: _.Input.Nullable - }> - > - stringWithArgInputObjectRequired: _.Field< - _.Output.Nullable<$Scalar.String>, - _.Args<{ - input: InputObject.InputObject - }> - > - listListIntNonNull: _.Field<_.Output.List<_.Output.List<$Scalar.Int>>> - listListInt: _.Field< - _.Output.Nullable<_.Output.List<_.Output.Nullable<_.Output.List<_.Output.Nullable<$Scalar.Int>>>>> - > - listInt: _.Field<_.Output.Nullable<_.Output.List<_.Output.Nullable<$Scalar.Int>>>> - listIntNonNull: _.Field<_.Output.List<$Scalar.Int>> - object: _.Field<_.Output.Nullable> - objectNonNull: _.Field - objectNested: _.Field<_.Output.Nullable> - objectWithArgs: _.Field< - _.Output.Nullable, - _.Args<{ - string: _.Input.Nullable<$Scalar.String> - int: _.Input.Nullable<$Scalar.Int> - float: _.Input.Nullable<$Scalar.Float> - boolean: _.Input.Nullable<$Scalar.Boolean> - id: _.Input.Nullable<$Scalar.ID> - }> - > - fooBarUnion: _.Field<_.Output.Nullable> - /** - * Query enum field documentation. - */ - abcEnum: _.Field<_.Output.Nullable> - lowerCaseUnion: _.Field<_.Output.Nullable> - }> -} - -// ------------------------------------------------------------ // -// Enum // -// ------------------------------------------------------------ // - -export namespace Enum { - /** - * Enum documentation. - * - * Members - * "A" - (DEPRECATED: Enum value A is deprecated.) - * "B" - Enum B member documentation. - * "C" - Enum C member documentation. (DEPRECATED: Enum value C is deprecated.) - */ - export type ABCEnum = _.Enum<'ABCEnum', ['A', 'B', 'C']> -} - -// ------------------------------------------------------------ // -// InputObject // -// ------------------------------------------------------------ // - -export namespace InputObject { - export type InputObject = _.InputObject<'InputObject', { - id: _.Input.Nullable<$Scalar.ID> - idRequired: $Scalar.ID - }> -} - -// ------------------------------------------------------------ // -// Interface // -// ------------------------------------------------------------ // - -export namespace Interface { - export type Interface = _.Interface<'Interface', { - id: _.Field<_.Output.Nullable<$Scalar.ID>> - }, [Object.Object1ImplementingInterface, Object.Object2ImplementingInterface]> -} - -// ------------------------------------------------------------ // -// Object // -// ------------------------------------------------------------ // - -export namespace Object { - /** - * Object documentation. - */ - export type Foo = _.Object<'Foo', { - /** - * Field documentation. - * - * @deprecated Field a is deprecated. - */ - id: _.Field<_.Output.Nullable<$Scalar.ID>> - }> - - export type Bar = _.Object<'Bar', { - int: _.Field<_.Output.Nullable<$Scalar.Int>> - }> - - export type ObjectNested = _.Object<'ObjectNested', { - id: _.Field<_.Output.Nullable<$Scalar.ID>> - object: _.Field<_.Output.Nullable> - }> - - export type lowerCaseObject = _.Object<'lowerCaseObject', { - id: _.Field<_.Output.Nullable<$Scalar.ID>> - }> - - export type lowerCaseObject2 = _.Object<'lowerCaseObject2', { - int: _.Field<_.Output.Nullable<$Scalar.Int>> - }> - - export type Object1 = _.Object<'Object1', { - string: _.Field<_.Output.Nullable<$Scalar.String>> - int: _.Field<_.Output.Nullable<$Scalar.Int>> - float: _.Field<_.Output.Nullable<$Scalar.Float>> - boolean: _.Field<_.Output.Nullable<$Scalar.Boolean>> - id: _.Field<_.Output.Nullable<$Scalar.ID>> - }> - - export type Object1ImplementingInterface = _.Object<'Object1ImplementingInterface', { - id: _.Field<_.Output.Nullable<$Scalar.ID>> - int: _.Field<_.Output.Nullable<$Scalar.Int>> - }> - - export type Object2ImplementingInterface = _.Object<'Object2ImplementingInterface', { - id: _.Field<_.Output.Nullable<$Scalar.ID>> - boolean: _.Field<_.Output.Nullable<$Scalar.Boolean>> - }> -} - -// ------------------------------------------------------------ // -// Union // -// ------------------------------------------------------------ // - -export namespace Union { - /** - * Union documentation. - */ - export type FooBarUnion = _.Union<'FooBarUnion', [Object.Foo, Object.Bar]> - - export type lowerCaseUnion = _.Union<'lowerCaseUnion', [Object.lowerCaseObject, Object.lowerCaseObject2]> -} -" -`; - -exports[`generates types from GraphQL SDL file 2`] = ` -"import * as Scalar from '../../../../src/Schema/NamedType/Scalar/Scalar.js' - -declare global { - interface SchemaCustomScalars { - Date: Date - } -} - -export const Date = Scalar.scalar(\`Date\`, Scalar.nativeScalarCodecs.String) -export type Date = typeof Date - -export * from '../../../../src/Schema/NamedType/Scalar/Scalar.js' -" -`; - -exports[`generates types from GraphQL SDL file 3`] = ` -"import * as _ from '../../../../src/Schema/__.js' -import * as $Scalar from './Scalar.js' - -export const ABCEnum = _.Enum(\`ABCEnum\`, [\`A\`, \`B\`, \`C\`]) - -export const Query = _.Object(\`Query\`, { - date: _.Output.field(_.Output.Nullable($Scalar.Date)), - interface: _.Output.field(_.Output.Nullable(() => Interface)), - id: _.Output.field(_.Output.Nullable($Scalar.ID)), - idNonNull: _.Output.field($Scalar.ID), - string: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithRequiredArg: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithArgs: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithArgEnum: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithListArg: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithListArgRequired: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithArgInputObject: _.Output.field(_.Output.Nullable($Scalar.String)), - stringWithArgInputObjectRequired: _.Output.field(_.Output.Nullable($Scalar.String)), - listListIntNonNull: _.Output.field(_.Output.List(_.Output.List($Scalar.Int))), - listListInt: _.Output.field( - _.Output.Nullable(_.Output.List(_.Output.Nullable(_.Output.List(_.Output.Nullable($Scalar.Int))))), - ), - listInt: _.Output.field(_.Output.Nullable(_.Output.List(_.Output.Nullable($Scalar.Int)))), - listIntNonNull: _.Output.field(_.Output.List($Scalar.Int)), - object: _.Output.field(_.Output.Nullable(() => Object1)), - objectNonNull: _.Output.field(() => Object1), - objectNested: _.Output.field(_.Output.Nullable(() => ObjectNested)), - objectWithArgs: _.Output.field(_.Output.Nullable(() => Object1)), - fooBarUnion: _.Output.field(_.Output.Nullable(() => FooBarUnion)), - abcEnum: _.Output.field(_.Output.Nullable(ABCEnum)), - lowerCaseUnion: _.Output.field(_.Output.Nullable(() => lowerCaseUnion)), -}) - -export const Foo = _.Object(\`Foo\`, { - id: _.Output.field(_.Output.Nullable($Scalar.ID)), -}) - -export const Bar = _.Object(\`Bar\`, { - int: _.Output.field(_.Output.Nullable($Scalar.Int)), -}) - -export const ObjectNested = _.Object(\`ObjectNested\`, { - id: _.Output.field(_.Output.Nullable($Scalar.ID)), - object: _.Output.field(_.Output.Nullable(() => Object1)), -}) - -export const lowerCaseObject = _.Object(\`lowerCaseObject\`, { - id: _.Output.field(_.Output.Nullable($Scalar.ID)), -}) - -export const lowerCaseObject2 = _.Object(\`lowerCaseObject2\`, { - int: _.Output.field(_.Output.Nullable($Scalar.Int)), -}) - -export const Object1 = _.Object(\`Object1\`, { - string: _.Output.field(_.Output.Nullable($Scalar.String)), - int: _.Output.field(_.Output.Nullable($Scalar.Int)), - float: _.Output.field(_.Output.Nullable($Scalar.Float)), - boolean: _.Output.field(_.Output.Nullable($Scalar.Boolean)), - id: _.Output.field(_.Output.Nullable($Scalar.ID)), -}) - -export const Object1ImplementingInterface = _.Object(\`Object1ImplementingInterface\`, { - id: _.Output.field(_.Output.Nullable($Scalar.ID)), - int: _.Output.field(_.Output.Nullable($Scalar.Int)), -}) - -export const Object2ImplementingInterface = _.Object(\`Object2ImplementingInterface\`, { - id: _.Output.field(_.Output.Nullable($Scalar.ID)), - boolean: _.Output.field(_.Output.Nullable($Scalar.Boolean)), -}) - -export const FooBarUnion = _.Union(\`FooBarUnion\`, [Foo, Bar]) - -export const lowerCaseUnion = _.Union(\`lowerCaseUnion\`, [lowerCaseObject, lowerCaseObject2]) - -export const Interface = _.Interface(\`Interface\`, { id: _.Output.field(_.Output.Nullable($Scalar.ID)) }, [ - Object1ImplementingInterface, - Object2ImplementingInterface, -]) - -export const $Index = { - Root: { - Query, - Mutation: null, - Subscription: null, - }, - objects: { - Foo, - Bar, - ObjectNested, - lowerCaseObject, - lowerCaseObject2, - Object1, - Object1ImplementingInterface, - Object2ImplementingInterface, - }, - unions: { - FooBarUnion, - lowerCaseUnion, - }, -} -" -`; diff --git a/src/layers/2_generator/code/Client.ts b/src/layers/2_generator/code/Client.ts deleted file mode 100644 index 395f0e186..000000000 --- a/src/layers/2_generator/code/Client.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createCodeGenerator } from '../createCodeGenerator.js' -import { moduleNameSchemaRuntime } from './SchemaRuntime.js' - -export const { generate: generateClient, moduleName: moduleNameClient } = createCodeGenerator( - `Client`, - (config) => { - const code: string[] = [] - - code.push( - `import { createPrefilled } from '${config.libraryPaths.client}'`, - `import { $Index } from './${moduleNameSchemaRuntime}.js'`, - ``, - `export const create = createPrefilled(\`${config.name}\`, $Index)`, - ) - - return code.join(`\n\n`) - }, -) diff --git a/src/layers/2_generator/code/Error.ts b/src/layers/2_generator/code/Error.ts deleted file mode 100644 index 6e4588046..000000000 --- a/src/layers/2_generator/code/Error.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { createCodeGenerator } from '../createCodeGenerator.js' - -export const { generate: generateError, moduleName: moduleNameError } = createCodeGenerator( - `Error`, - (config) => { - const code: string[] = [] - - code.push( - `type Include = Exclude>`, - `type ObjectWithTypeName = { __typename: string }`, - ) - - code.push(` - const ErrorObjectsTypeNameSelectedEnum = { - ${config.error.objects.map(_ => `${_.name}: { __typename: '${_.name}' }`).join(`,\n`)} - } as ${config.error.objects.length > 0 ? `const` : `Record`} - - const ErrorObjectsTypeNameSelected = Object.values(ErrorObjectsTypeNameSelectedEnum) - - type ErrorObjectsTypeNameSelected = (typeof ErrorObjectsTypeNameSelected)[number] - `) - - code.push( - `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) - }`, - ) - - return code.join(`\n\n`) - }, -) diff --git a/src/layers/2_generator/code/Index.ts b/src/layers/2_generator/code/Index.ts deleted file mode 100644 index eaf7834c5..000000000 --- a/src/layers/2_generator/code/Index.ts +++ /dev/null @@ -1,67 +0,0 @@ -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 { moduleNameSchemaBuildtime } from './SchemaBuildtime.js' - -export const { generate: generateIndex, moduleName: moduleNameIndex } = createCodeGenerator( - `Index`, - (config) => { - const namespace = `Schema` - const code = [] - code.push(`/* eslint-disable */\n`) - code.push(`import type * as ${namespace} from './${moduleNameSchemaBuildtime}.js'\n`) - - code.push(Code.export$( - Code.interface$( - `Index`, - Code.objectFrom({ - name: Code.quote(config.name), - Root: { - type: Code.objectFrom({ - Query: hasQuery(config.typeMapByKind) ? `${namespace}.Root.Query` : null, - Mutation: hasMutation(config.typeMapByKind) ? `${namespace}.Root.Mutation` : null, - Subscription: hasSubscription(config.typeMapByKind) ? `${namespace}.Root.Subscription` : null, - }), - }, - objects: Code.objectFromEntries( - config.typeMapByKind.GraphQLObjectType.map(_ => [_.name, `${namespace}.Object.${_.name}`]), - ), - unions: Code.objectFromEntries( - config.typeMapByKind.GraphQLUnionType.map(_ => [_.name, `${namespace}.Union.${_.name}`]), - ), - interfaces: Code.objectFromEntries( - config.typeMapByKind.GraphQLInterfaceType.map(_ => [_.name, `${namespace}.Interface.${_.name}`]), - ), - // todo jsdoc comment saying: - // Objects that match this pattern name: /.../ - error: Code.objectFrom({ - objects: Code.objectFromEntries( - config.error.objects.map(_ => [_.name, `${namespace}.Object.${_.name}`]), - ), - objectsTypename: Code.objectFromEntries( - config.error.objects.map(_ => [_.name, `{ __typename: "${_.name}" }`]), - ), - rootResultFields: `{ - ${ - Object.entries(config.rootTypes).map(([rootTypeName, rootType]) => { - if (!rootType) return `${rootTypeName}: {}` - - const resultFields = Object.values(rootType.getFields()).filter((field) => { - const type = unwrapToNamed(field.type) - return isUnionType(type) - && type.getTypes().some(_ => config.error.objects.some(__ => __.name === _.name)) - }).map((field) => field.name) - - return `${rootType.name}: {\n${resultFields.map(_ => `${_}: "${_}"`).join(`,\n`)} }` - }).join(`\n`) - } - }`, - }), - }), - ), - )) - - return code.join(`\n`) - }, -) diff --git a/src/layers/2_generator/code/Scalar.ts b/src/layers/2_generator/code/Scalar.ts deleted file mode 100644 index 5eea262f5..000000000 --- a/src/layers/2_generator/code/Scalar.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { createCodeGenerator } from '../createCodeGenerator.js' - -export const { generate: generateScalar, moduleName: moduleNameScalar } = createCodeGenerator( - `Scalar`, - (config) => { - let code = `` - - // todo test case for when this is true - const needsDefaultCustomScalarImplementation = config.typeMapByKind.GraphQLScalarTypeCustom.length > 0 - && !config.options.customScalars - - const StandardScalarNamespace = `StandardScalar` - code += ` - - ${ - needsDefaultCustomScalarImplementation - ? `import * as ${StandardScalarNamespace} from '${config.libraryPaths.scalars}'` - : `` - } - - export * from '${config.libraryPaths.scalars}' - ${config.options.customScalars ? `export * from '${config.importPaths.customScalarCodecs}'` : ``} - ` - - if (needsDefaultCustomScalarImplementation) { - console.log( - `WARNING: Custom scalars detected in the schema, but you have not created a custom scalars module to import implementations from.`, - ) - code += ` -${ - config.typeMapByKind.GraphQLScalarTypeCustom - .flatMap((_) => { - return [ - `export const ${_.name} = ${StandardScalarNamespace}.String`, - `export type ${_.name} = ${StandardScalarNamespace}.String`, - ] - }).join(`\n`) - } - ` - } - - return code - }, -) diff --git a/src/layers/2_generator/code/SchemaBuildtime.ts b/src/layers/2_generator/code/SchemaBuildtime.ts deleted file mode 100644 index 60dae6f1e..000000000 --- a/src/layers/2_generator/code/SchemaBuildtime.ts +++ /dev/null @@ -1,338 +0,0 @@ -import type { - GraphQLArgument, - GraphQLEnumValue, - GraphQLInputObjectType, - GraphQLInterfaceType, - GraphQLNamedType, - GraphQLObjectType, -} from 'graphql' -import { isEnumType, isListType, isNamedType } from 'graphql' -import _ from 'json-bigint' -import { Code } from '../../../lib/Code.js' -import type { - AnyClass, - AnyField, - AnyNamedClassName, - ClassToName, - Describable, - NamedNameToClass, - NameToClassNamedType, -} from '../../../lib/graphql.js' -import { - getNodeDisplayName, - isDeprecatableNode, - isGraphQLOutputField, - type NameToClass, - unwrapToNonNull, -} from '../../../lib/graphql.js' -import { entries, values } from '../../../lib/prelude.js' -import { createCodeGenerator } from '../createCodeGenerator.js' -import { type Config } from '../generateCode.js' - -const namespaceNames = { - GraphQLEnumType: `Enum`, - GraphQLInputObjectType: `InputObject`, - GraphQLInterfaceType: `Interface`, - GraphQLObjectType: `Object`, - GraphQLScalarType: `Scalar`, - GraphQLUnionType: `Union`, -} satisfies Record - -type AnyGraphQLFieldsType = - | GraphQLObjectType - | GraphQLInterfaceType - | GraphQLInputObjectType - -const defineReferenceRenderers = < - $Renderers extends { [ClassName in keyof NamedNameToClass]: any }, ->( - renderers: { - [ClassName in keyof $Renderers]: ( - config: Config, - node: ClassName extends keyof NamedNameToClass ? InstanceType - : never, - ) => string - }, -) => renderers - -const defineConcreteRenderers = < - $Renderers extends { [ClassName in keyof NameToClassNamedType]: any }, ->( - renderers: { - [ClassName in keyof $Renderers]: ( - config: Config, - node: ClassName extends keyof NameToClassNamedType ? InstanceType - : never, - ) => string - }, -): { - [ClassName in keyof $Renderers]: ( - node: ClassName extends keyof NameToClass ? InstanceType | null | undefined - : never, - ) => string -} => { - return Object.fromEntries( - Object.entries(renderers).map(([key, renderer]) => { - return [ - key, - (config: Config, node: any) => { - if (!node) return `` - return renderer(config, node) // eslint-disable-line - }, - ] - }), - ) as any -} - -const dispatchToReferenceRenderer = (config: Config, node: AnyClass): string => - // @ts-expect-error fixme - getReferenceRenderer(node)(config, node as any) - -// @ts-expect-error fixme -const getReferenceRenderer = (node: N): (typeof referenceRenderers)[ClassToName] => { - // @ts-expect-error lookup - const renderer = referenceRenderers[node.constructor.name] // eslint-disable-line - if (!renderer) { - throw new Error(`No renderer found for class: ${node.constructor.name}`) - } - return renderer -} - -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), - GraphQLUnionType: (_, node) => Code.propertyAccess(namespaceNames.GraphQLUnionType, node.name), - GraphQLScalarType: (_, node) => `$Scalar.${node.name}`, -}) - -const dispatchToConcreteRenderer = ( - config: Config, - node: GraphQLNamedType, -): string => { - // @ts-expect-error lookup - const renderer = concreteRenderers[node.constructor.name] // eslint-disable-line - if (!renderer) { - throw new Error(`No renderer found for class: ${node.constructor.name}`) - } - return renderer(config, node) // eslint-disable-line -} - -const concreteRenderers = defineConcreteRenderers({ - GraphQLEnumType: (config, node) => - Code.TSDoc( - getDocumentation(config, node), - Code.export$( - Code.type( - node.name, - `$.Enum<${Code.quote(node.name)}, ${Code.tuple(node.getValues().map((_) => Code.quote(_.name)))} >`, - ), - ), - ), - GraphQLInputObjectType: (config, node) => - Code.TSDoc( - getDocumentation(config, node), - Code.export$(Code.type(node.name, `$.InputObject<${Code.quote(node.name)}, ${renderInputFields(config, node)}>`)), - ), - GraphQLInterfaceType: (config, node) => { - const implementors = config.typeMapByKind.GraphQLObjectType.filter(_ => - _.getInterfaces().filter(_ => _.name === node.name).length > 0 - ) - return Code.TSDoc( - getDocumentation(config, node), - Code.export$(Code.type( - node.name, - `$.Interface<${Code.quote(node.name)}, ${renderOutputFields(config, node)}, ${ - Code.tuple(implementors.map(_ => `Object.${_.name}`)) - }>`, - )), - ) - }, - GraphQLObjectType: (config, node) => - Code.TSDoc( - getDocumentation(config, node), - Code.export$(Code.type(node.name, `$.Object$2<${Code.quote(node.name)}, ${renderOutputFields(config, node)}>`)), - ), - GraphQLScalarType: () => ``, - GraphQLUnionType: (config, node) => - Code.TSDoc( - getDocumentation(config, node), - Code.export$( - Code.type( - node.name, - `$.Union<${Code.quote(node.name)},${ - Code.tuple( - node - .getTypes() - .map( - (_) => dispatchToReferenceRenderer(config, _), - ), - ) - }>`, - ), - ), - ), -}) - -const getDocumentation = (config: Config, node: Describable) => { - const generalDescription = node.description - ?? (config.options.TSDoc.noDocPolicy === `message` ? defaultDescription(node) : null) - - const deprecationDescription = isDeprecatableNode(node) && node.deprecationReason - ? `@deprecated ${node.deprecationReason}` - : null - - const enumMemberDescriptions: string[] = isEnumType(node) - ? node - .getValues() - .map((_) => { - const deprecationDescription = _.deprecationReason - ? `(DEPRECATED: ${_.deprecationReason})` - : null - const generalDescription = _.description - ? _.description - : config.options.TSDoc.noDocPolicy === `message` - ? `Missing description.` - : null - if (!generalDescription && !deprecationDescription) return null - const content = [generalDescription, deprecationDescription] - .filter((_) => _ !== null) - .join(` `) - return [_, content] as const - }) - .filter((_): _ is [GraphQLEnumValue, string] => _ !== null) - .map(([node, description]) => { - const content = `"${node.name}" - ${description}` - return content - }) - : [] - const enumMemberDescription = enumMemberDescriptions.length > 0 - ? `Members\n${enumMemberDescriptions.join(`\n`)}` - : null - if (!enumMemberDescription && !generalDescription && !deprecationDescription) { - return null - } - const content = [ - generalDescription, - enumMemberDescription, - deprecationDescription, - ] - .filter((_) => _ !== null) - .join(`\n\n`) - return content -} - -const defaultDescription = (node: Describable) => `There is no documentation for this ${getNodeDisplayName(node)}.` - -const renderOutputFields = (config: Config, node: AnyGraphQLFieldsType): string => { - return Code.object(Code.fields([ - ...values(node.getFields()).map((field) => - Code.TSDoc( - getDocumentation(config, field), - Code.field(field.name, renderOutputField(config, field)), - ) - ), - ])) -} - -const renderInputFields = (config: Config, node: AnyGraphQLFieldsType): string => { - return Code.object(Code.fields([ - ...values(node.getFields()).map((field) => - Code.TSDoc( - getDocumentation(config, field), - Code.field(field.name, renderInputField(config, field)), - ) - ), - ])) -} - -const renderOutputField = (config: Config, field: AnyField): string => { - const type = buildType(`output`, config, field.type) - - const args = isGraphQLOutputField(field) && field.args.length > 0 - ? renderArgs(config, field.args) - : null - - return `$.Field<${type}${args ? `, ${args}` : `, null`}>` -} - -const renderInputField = (config: Config, field: AnyField): string => { - return buildType(`input`, config, field.type) -} - -const buildType = (direction: 'input' | 'output', config: Config, node: AnyClass) => { - const ns = direction === `input` ? `Input` : `Output` - const { ofType: nodeInner, nullable } = unwrapToNonNull(node) - - if (isNamedType(nodeInner)) { - const namedTypeReference = dispatchToReferenceRenderer(config, nodeInner) - // const namedTypeCode = `_.Named<${namedTypeReference}>` - const namedTypeCode = namedTypeReference - return nullable - ? `$.${ns}.Nullable<${namedTypeCode}>` - : namedTypeCode - } - - if (isListType(nodeInner)) { - const fieldType = `$.${ns}.List<${buildType(direction, config, nodeInner.ofType)}>` as any as string - return nullable - ? `$.${ns}.Nullable<${fieldType}>` - : fieldType - } - - throw new Error(`Unhandled type: ${String(node)}`) -} - -const renderArgs = (config: Config, args: readonly GraphQLArgument[]) => { - let hasRequiredArgs = false - const argsRendered = `$.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), - ) - }), - ), - ) - }>` - return argsRendered -} - -// high level - -export const { generate: generateSchemaBuildtime, moduleName: moduleNameSchemaBuildtime } = createCodeGenerator( - `SchemaBuildtime`, - (config: Config) => { - let code = `` - - code += `import type * as $ from '${config.libraryPaths.schema}'\n` - code += `import type * as $Scalar from './Scalar.ts'\n` - code += `\n\n` - - for (const [name, types] of entries(config.typeMapByKind)) { - if (name === `GraphQLScalarType`) continue - if (name === `GraphQLScalarTypeCustom`) continue - if (name === `GraphQLScalarTypeStandard`) continue - - const namespaceName = name === `GraphQLRootType` ? `Root` : namespaceNames[name] - code += Code.commentSectionTitle(namespaceName) - code += Code.export$( - Code.namespace( - namespaceName, - types.length === 0 - ? `// -- no types --\n` - : types - .map((_) => dispatchToConcreteRenderer(config, _)) - .join(`\n\n`), - ), - ) - } - - return code - }, -) diff --git a/src/layers/2_generator/code/SchemaRuntime.ts b/src/layers/2_generator/code/SchemaRuntime.ts deleted file mode 100644 index 89e8f628e..000000000 --- a/src/layers/2_generator/code/SchemaRuntime.ts +++ /dev/null @@ -1,214 +0,0 @@ -import type { - GraphQLArgument, - GraphQLEnumType, - GraphQLInputField, - GraphQLInputObjectType, - GraphQLInterfaceType, - GraphQLScalarType, - GraphQLUnionType, -} from 'graphql' -import { - type GraphQLObjectType, - isEnumType, - isInputObjectType, - isInterfaceType, - isListType, - isNamedType, - isObjectType, - isScalarType, - isUnionType, -} from 'graphql' -import type { AnyClass, AnyGraphQLOutputField } from '../../../lib/graphql.js' -import { hasMutation, hasQuery, hasSubscription, unwrapToNamed, unwrapToNonNull } from '../../../lib/graphql.js' -import { createCodeGenerator } from '../createCodeGenerator.js' -import type { Config } from '../generateCode.js' -import { moduleNameScalar } from './Scalar.js' - -export const { generate: generateRuntimeSchema, moduleName: moduleNameSchemaRuntime } = createCodeGenerator( - `SchemaRuntime`, - ( - config, - ) => { - const code: string[] = [] - - code.push(`/* eslint-disable */\n`) - code.push( - ` - import * as $ from '${config.libraryPaths.schema}' - import * as $Scalar from './${moduleNameScalar}.js' - `, - ) - - code.push( - config.typeMapByKind.GraphQLEnumType.map(type => enum$(config, type)).join(`\n`), - config.typeMapByKind.GraphQLInputObjectType.map(type => inputObject(config, type)).join(`\n`), - config.typeMapByKind.GraphQLObjectType.map(type => object(config, type)).join(`\n`), - config.typeMapByKind.GraphQLUnionType.map(type => union(config, type)).join(`\n`), - config.typeMapByKind.GraphQLInterfaceType.map(type => interface$(config, type)).join(`\n`), - config.typeMapByKind.GraphQLRootType.map(type => object(config, type)).join(`\n`), - ) - - code.push( - index(config), - ) - - return code.join(`\n`) - }, -) - -const index = (config: Config) => { - // todo input objects for decode/encode input object fields - return ` - export const $Index = { - name: "${config.name}" as const, - Root: { - Query ${hasQuery(config.typeMapByKind) ? `` : `:null`} , - Mutation ${hasMutation(config.typeMapByKind) ? `` : `:null`}, - Subscription ${hasSubscription(config.typeMapByKind) ? `` : `:null`} - }, - objects: { - ${config.typeMapByKind.GraphQLObjectType.map(type => type.name).join(`,\n`)} - }, - unions: { - ${config.typeMapByKind.GraphQLUnionType.map(type => type.name).join(`,\n`)} - }, - interfaces: { - ${config.typeMapByKind.GraphQLInterfaceType.map(type => type.name).join(`,\n`)} - }, - error: { - objects: { - ${config.error.objects.map(type => type.name).join(`,\n`)} - }, - objectsTypename: { - ${config.error.objects.map(_ => `${_.name}: { __typename: "${_.name}" }`).join(`,\n`)} - }, - rootResultFields: { - ${ - Object.entries(config.rootTypes).map(([rootTypeName, rootType]) => { - if (!rootType) return `${rootTypeName}: {}` - - const resultFields = Object.values(rootType.getFields()).filter((field) => { - const type = unwrapToNamed(field.type) - return isUnionType(type) - && type.getTypes().some(_ => config.error.objects.some(__ => __.name === _.name)) - }).map((field) => field.name) - - return `${rootType.name}: {\n${resultFields.map(_ => `${_}: "${_}" as const`).join(`,\n`)} }` - }).join(`,\n`) - } - } - } - } - ` -} - -const union = (_config: Config, type: GraphQLUnionType) => { - // todo probably need thunks here - const members = type.getTypes().map(t => t.name).join(`, `) - return ` - // @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 ${type.name} = $.Union(\`${type.name}\`, [${members}])\n` -} - -const interface$ = (config: Config, type: GraphQLInterfaceType) => { - // todo probably need thunks here - const implementors = config.typeMapByKind.GraphQLObjectType.filter(_ => - _.getInterfaces().filter(_ => _.name === type.name).length > 0 - ).map(_ => _.name).join(`,`) - const fields = Object.values(type.getFields()).map((field) => { - return `${field.name}: ${outputField(config, field)}` - }).join(`,\n`) - return `export const ${type.name} = $.Interface(\`${type.name}\`, {${fields}}, [${implementors}])` -} - -const enum$ = (_config: Config, type: GraphQLEnumType) => { - const members = type.getValues().map((value) => { - return `\`${value.name}\`` - }).join(`, `) - return `export const ${type.name} = $.Enum(\`${type.name}\`, [${members}])` -} - -const object = (config: Config, type: GraphQLObjectType) => { - const fields = Object.values(type.getFields()).map((field) => { - return `${field.name}: ${outputField(config, field)}` - }).join(`,\n`) - return ` - // @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 ${type.name} = $.Object$(\`${type.name}\`, { - ${fields} - }) - ` -} - -const inputObject = (config: Config, type: GraphQLInputObjectType) => { - const fields = Object.values(type.getFields()).map((field) => `${field.name}: ${inputField(config, field)}`).join( - `,\n`, - ) - return ` - export const ${type.name} = $.InputObject(\`${type.name}\`, { - ${fields} - }) - ` -} -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})` -} - -const outputField = (config: Config, field: AnyGraphQLOutputField): string => { - const type = buildType(`output`, config, field.type) - return field.args.length > 0 - ? `$.field(${type}, ${renderArgs(config, field.args)})` - : `$.field(${type})` -} - -const renderArgs = (config: Config, args: readonly GraphQLArgument[]) => { - return `$.Args({${args.map(arg => renderArg(config, arg)).join(`, `)}})` -} - -const renderArg = (config: Config, arg: GraphQLArgument) => { - const type = buildType(`input`, config, arg.type) - return `${arg.name}: ${type}` -} - -const scalar = (_config: Config, type: GraphQLScalarType) => { - return `$Scalar.${type.name}` -} - -const dispatchNamedType = (config: Config, type: AnyClass) => { - if (isScalarType(type)) return scalar(config, type) - if (isEnumType(type)) return type.name - if (isObjectType(type)) return thunk(type.name) - if (isInterfaceType(type)) return thunk(type.name) - if (isUnionType(type)) return thunk(type.name) - if (isInputObjectType(type)) return type.name - - throw new Error(`Unhandled type: ${String(type)}`) -} - -const thunk = (code: string) => `() => ${code}` - -const buildType = (direction: 'input' | 'output', config: Config, node: AnyClass) => { - const ns = direction === `input` ? `Input` : `Output` - const { ofType: nodeInner, nullable } = unwrapToNonNull(node) - - if (isNamedType(nodeInner)) { - const namedTypeReference = dispatchNamedType(config, nodeInner) - const namedTypeCode = namedTypeReference - return nullable - ? `$.${ns}.Nullable(${namedTypeCode})` - : namedTypeCode - } - - if (isListType(nodeInner)) { - const fieldType = `$.${ns}.List(${buildType(direction, config, nodeInner.ofType)})` as any as string - return nullable - ? `$.${ns}.Nullable(${fieldType})` - : fieldType - } - - throw new Error(`Unhandled type: ${String(node)}`) -} diff --git a/src/layers/2_generator/code/Select.ts b/src/layers/2_generator/code/Select.ts deleted file mode 100644 index 6164d5615..000000000 --- a/src/layers/2_generator/code/Select.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { createCodeGenerator } from '../createCodeGenerator.js' -import { title, typeTitle } from '../helpers.js' -import { moduleNameIndex } from './Index.js' - -export const { generate: generateSelect, moduleName: moduleNameSelect } = createCodeGenerator( - `Select`, - (config) => { - const code: string[] = [] - - code.push(`import { Index } from './${moduleNameIndex}.js'`) - code.push(`import { SelectionSet, ResultSet } from '${config.libraryPaths.schema}'`) - code.push(``) - - code.push( - title(`Runtime`), - `import { createSelect } from '${config.libraryPaths.client}'`, - `export const Select = createSelect('default')`, - ``, - title(`Buildtime`), - ``, - `export namespace Select {`, - typeTitle(config, `Root`), - ) - - code.push(...config.typeMapByKind.GraphQLRootType.map((type) => { - return `export type ${type.name}<$SelectionSet extends SelectionSet.Root> = ResultSet.Root<$SelectionSet, Index, '${type.name}'>\n` - })) - - code.push(typeTitle(config, `Object`)) - - // TODO propagate descriptions to JSDoc - code.push(...config.typeMapByKind.GraphQLObjectType.map((type) => { - return `export type ${type.name}<$SelectionSet extends SelectionSet.Object> = ResultSet.Object$<$SelectionSet, Index['objects']['${type.name}'], Index>\n` - })) - - code.push(typeTitle(config, `Union`)) - - code.push(...config.typeMapByKind.GraphQLUnionType.map((type) => { - return `export type ${type.name}<$SelectionSet extends SelectionSet.Union> = ResultSet.Union<$SelectionSet, Index['unions']['${type.name}'], Index>\n` - })) - - code.push(typeTitle(config, `Interface`)) - - code.push(...config.typeMapByKind.GraphQLInterfaceType.map((type) => { - return `export type ${type.name}<$SelectionSet extends SelectionSet.Interface> = ResultSet.Interface<$SelectionSet, Index['interfaces']['${type.name}'], Index>\n` - })) - - code.push(`}`) // namespace Select - - return code.join(`\n`) - }, -) diff --git a/src/layers/2_generator/code/_.ts b/src/layers/2_generator/code/_.ts deleted file mode 100644 index 559325f77..000000000 --- a/src/layers/2_generator/code/_.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { createCodeGenerator } from '../createCodeGenerator.js' -import { moduleNameClient } from './Client.js' -import { moduleNameError } from './Error.js' -import { moduleNameSelect } from './Select.js' - -export const { generate: generate_, moduleName: moduleName_ } = createCodeGenerator( - `_`, - (_config) => { - const code: string[] = [] - code.push( - `export { Select } from './${moduleNameSelect}.js'`, - `export { isError } from './${moduleNameError}.js'`, - `export { create } from './${moduleNameClient}.js'`, - ) - - return code.join(`\n`) - }, -) diff --git a/src/layers/2_generator/code/__.ts b/src/layers/2_generator/code/__.ts deleted file mode 100644 index b3515eddd..000000000 --- a/src/layers/2_generator/code/__.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { capitalizeFirstLetter } from '../../../lib/prelude.js' -import { createCodeGenerator } from '../createCodeGenerator.js' -import { defaultName } from '../generateCode.js' -import { moduleName_ } from './_.js' - -export const defaultNamespace = `Graffle` - -export const { generate: generate__, moduleName: moduleName__ } = createCodeGenerator( - `__`, - (config) => { - const code: string[] = [] - const namespace = config.name === defaultName ? defaultNamespace : capitalizeFirstLetter(config.name) - code.push( - `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 deleted file mode 100644 index 6f2c67f12..000000000 --- a/src/layers/2_generator/code/global.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { createCodeGenerator } from '../createCodeGenerator.js' -import { moduleNameIndex } from './Index.js' - -export const { moduleName: moduleNameGlobal, generate: generateGlobal } = createCodeGenerator( - `Global`, - (config) => { - const StandardScalarNamespace = `StandardScalar` - const needsDefaultCustomScalarImplementation = config.typeMapByKind.GraphQLScalarTypeCustom.length > 0 - && !config.options.customScalars - - const code: string[] = [] - - code.push( - `import { Index } from './${moduleNameIndex}.js'`, - ) - - if (config.typeMapByKind.GraphQLScalarTypeCustom.length > 0) { - code.push( - `import type * as CustomScalar from '${config.importPaths.customScalarCodecs}'`, - ) - } - - code.push(` - declare global { - export namespace GraphQLRequestTypes { - export interface Schemas { - ${config.name}: { - index: Index - customScalars: { - ${ - config.typeMapByKind.GraphQLScalarTypeCustom - .map((_) => { - return `${_.name}: ${ - needsDefaultCustomScalarImplementation ? `${StandardScalarNamespace}.String` : `CustomScalar.${_.name}` - }` - }).join(`\n`) - } - } - featureOptions: { - schemaErrors: ${config.options.errorTypeNamePattern ? `true` : `false`} - } - } - } - } - } - `) - - return code.join(`\n\n`) - }, -) diff --git a/src/layers/2_generator/createCodeGenerator.ts b/src/layers/2_generator/createCodeGenerator.ts deleted file mode 100644 index 140c09758..000000000 --- a/src/layers/2_generator/createCodeGenerator.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { Config } from './generateCode.js' - -export type CodeGeneratorImplementation = (config: Config) => CodeGeneratorImplementationResult -type CodeGeneratorImplementationResult = string - -interface CodeGeneratorResult { - moduleName: string - code: string -} - -export type CodeGenerator = (config: Config) => CodeGeneratorResult - -export type CodeGeneratorConstructor = ( - moduleName: string, - codeGenerator: CodeGeneratorImplementation, -) => { moduleName: string; generate: CodeGenerator } - -export const createCodeGenerator: CodeGeneratorConstructor = (moduleName: string, codeGeneratorImplementation) => { - const generate = (config: Config) => { - const code = codeGeneratorImplementation(config) - return { - code, - moduleName, - } - } - return { moduleName, generate } -} diff --git a/src/layers/2_generator/files.test.ts b/src/layers/2_generator/files.test.ts deleted file mode 100644 index d090ba86f..000000000 --- a/src/layers/2_generator/files.test.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { readFile } from 'fs/promises' -import { expect, test } from 'vitest' - -test(`schema2`, async () => { - expect( - await readFile(`./tests/_/schema/generated/Client.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/__.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/_.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/Error.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/Select.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/Index.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/SchemaBuildtime.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/Scalar.ts`, `utf8`), - ).toMatchSnapshot() - expect( - await readFile(`./tests/_/schema/generated/SchemaRuntime.ts`, `utf8`), - ).toMatchSnapshot() -}) diff --git a/src/layers/2_generator/files.ts b/src/layers/2_generator/files.ts deleted file mode 100644 index cf13b278c..000000000 --- a/src/layers/2_generator/files.ts +++ /dev/null @@ -1,65 +0,0 @@ -import type { Formatter } from '@dprint/formatter' -import _ from 'json-bigint' -import fs from 'node:fs/promises' -import * as Path from 'node:path' -import type { OptionsInput } from './generateCode.js' -import { generateCode, type Input as GenerateInput } from './generateCode.js' -import { fileExists } from './prelude.js' - -export interface Input { - name?: string - outputDirPath: string - code?: Omit - sourceDirPath?: string - sourceCustomScalarCodecsFilePath?: string - schemaPath?: string - format?: boolean - errorTypeNamePattern?: OptionsInput['errorTypeNamePattern'] -} - -const getTypeScriptFormatter = async (): Promise => { - try { - const { createFromBuffer } = await import(`@dprint/formatter`) - const { getPath } = await import(`@dprint/typescript`) - return createFromBuffer(await fs.readFile(getPath())) - } catch (error) { - return undefined - } -} - -export const generateFiles = async (input: Input) => { - const sourceDirPath = input.sourceDirPath ?? process.cwd() - const schemaPath = input.schemaPath ?? Path.join(sourceDirPath, `schema.graphql`) - const schemaSource = await fs.readFile(schemaPath, `utf8`) - - // todo support other extensions: .tsx,.js,.mjs,.cjs - const customScalarCodecsFilePath = input.sourceCustomScalarCodecsFilePath - ?? Path.join(sourceDirPath, `customScalarCodecs.ts`) - const customScalarCodecsImportPath = Path.relative( - input.outputDirPath, - customScalarCodecsFilePath.replace(/\.ts$/, `.js`), - ) - const customScalarCodecsPathExists = await fileExists(customScalarCodecsFilePath) - const typeScriptFormatter = (input.format ?? true) ? await getTypeScriptFormatter() : undefined - - const codes = generateCode({ - name: input.name, - schemaSource, - importPaths: { - customScalarCodecs: customScalarCodecsImportPath, - }, - ...input.code, - options: { - formatter: typeScriptFormatter, - customScalars: customScalarCodecsPathExists, - errorTypeNamePattern: input.errorTypeNamePattern, - }, - }) - - await fs.mkdir(input.outputDirPath, { recursive: true }) - await Promise.all( - codes.map((code) => { - return fs.writeFile(`${input.outputDirPath}/${code.moduleName}.ts`, code.code, { encoding: `utf8` }) - }), - ) -} diff --git a/src/layers/2_generator/generateCode.ts b/src/layers/2_generator/generateCode.ts deleted file mode 100644 index 8d931c25a..000000000 --- a/src/layers/2_generator/generateCode.ts +++ /dev/null @@ -1,143 +0,0 @@ -import type { Formatter } from '@dprint/formatter' -import type { GraphQLObjectType, GraphQLSchema } from 'graphql' -import { buildSchema } from 'graphql' -import * as Path from 'node:path' -import type { TypeMapByKind } from '../../lib/graphql.js' -import { getTypeMapByKind } from '../../lib/graphql.js' -import { generate_ } from './code/_.js' -import { generate__ } from './code/__.js' -import { generateClient } from './code/Client.js' -import { generateError } from './code/Error.js' -import { generateGlobal } from './code/global.js' -import { generateIndex } from './code/Index.js' -import { generateScalar } from './code/Scalar.js' -import { generateSchemaBuildtime } from './code/SchemaBuildtime.js' -import { generateRuntimeSchema } from './code/SchemaRuntime.js' -import { generateSelect } from './code/Select.js' - -export interface OptionsInput { - name?: string - errorTypeNamePattern?: RegExp - /** - * Should custom scalars definitions be imported into the generated output? - */ - customScalars?: boolean - formatter?: Formatter - TSDoc?: { - noDocPolicy?: 'message' | 'ignore' - } -} - -export interface Input { - name?: string - libraryPaths?: { - client?: string - schema?: string - scalars?: string - } - importPaths?: { - customScalarCodecs?: string - } - /** - * The GraphQL SDL source code. - */ - schemaSource: string - options?: OptionsInput -} - -export interface Config { - name: string - schema: GraphQLSchema - typeMapByKind: TypeMapByKind - rootTypes: { - Query: GraphQLObjectType | null - Mutation: GraphQLObjectType | null - Subscription: GraphQLObjectType | null - } - error: { - objects: GraphQLObjectType[] - enabled: boolean - } - libraryPaths: { - client: string - schema: string - scalars: string - } - importPaths: { - customScalarCodecs: string - } - options: { - errorTypeNamePattern: RegExp | null - customScalars: boolean - TSDoc: { - noDocPolicy: 'message' | 'ignore' - } - } -} - -export const defaultName = `default` - -export const resolveOptions = (input: Input): Config => { - const errorTypeNamePattern = input.options?.errorTypeNamePattern ?? null - const schema = buildSchema(input.schemaSource) - const typeMapByKind = getTypeMapByKind(schema) - const errorObjects = errorTypeNamePattern - ? Object.values(typeMapByKind.GraphQLObjectType).filter(_ => _.name.match(errorTypeNamePattern)) - : [] - return { - name: input.name ?? defaultName, - schema, - error: { - enabled: Boolean(errorTypeNamePattern), - objects: errorObjects, - }, - importPaths: { - customScalarCodecs: input.importPaths?.customScalarCodecs ?? Path.join(process.cwd(), `customScalarCodecs.js`), - }, - libraryPaths: { - client: input.libraryPaths?.client ?? `graphql-request/alpha/client`, - scalars: input.libraryPaths?.scalars ?? `graphql-request/alpha/schema/scalars`, - schema: input.libraryPaths?.schema ?? `graphql-request/alpha/schema`, - }, - typeMapByKind, - rootTypes: { - Query: typeMapByKind.GraphQLRootType.find(_ => _.name === `Query`) ?? null, - Mutation: typeMapByKind.GraphQLRootType.find(_ => _.name === `Mutation`) ?? null, - Subscription: typeMapByKind.GraphQLRootType.find(_ => _.name === `Subscription`) ?? null, - }, - options: { - errorTypeNamePattern, - customScalars: input.options?.customScalars ?? false, - TSDoc: { - noDocPolicy: input.options?.TSDoc?.noDocPolicy ?? `ignore`, - }, - }, - } -} - -export const generateCode = (input: Input) => { - const defaultDprintConfig = { - quoteStyle: `preferSingle`, - semiColons: `asi`, - } - const format = (source: string) => - input.options?.formatter?.formatText(`memory.ts`, source, defaultDprintConfig) ?? source - - const config = resolveOptions(input) - - return [ - generate__, - generate_, - generateClient, - generateGlobal, - generateError, - generateIndex, - generateScalar, - generateSchemaBuildtime, - generateRuntimeSchema, - generateSelect, - ].map(_ => _(config)).map(code => ({ - ...code, - code: format(code.code), - })) -} diff --git a/src/layers/2_generator/globalRegistry.ts b/src/layers/2_generator/globalRegistry.ts deleted file mode 100644 index 97036ff60..000000000 --- a/src/layers/2_generator/globalRegistry.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { Values } from '../../lib/prelude.js' -import type { TSError } from '../../lib/TSError.js' -import type { Schema } from '../1_Schema/__.js' - -declare global { - export namespace GraphQLRequestTypes { - interface Schemas {} - // Use this is for manual internal type testing. - // interface SchemasAlwaysEmpty {} - } -} - -type SomeSchema = { - index: Schema.Index - customScalars: Record - featureOptions: { - schemaErrors: boolean - } -} - -type ZeroSchema = { - index: { name: never } - featureOptions: { - schemaErrors: false - } -} - -export type GlobalRegistry = Record - -export namespace GlobalRegistry { - export type Schemas = GraphQLRequestTypes.Schemas - - export type IsEmpty = keyof Schemas extends never ? true : false - - export type SchemaList = IsEmpty extends true ? ZeroSchema : Values - - export type DefaultSchemaName = 'default' - - export type SchemaNames = keyof GraphQLRequestTypes.Schemas extends never - ? TSError<'SchemaNames', 'No schemas have been registered. Did you run graphql-request generate?'> - : keyof GraphQLRequestTypes.Schemas - - export type HasSchemaErrors<$Schema extends SchemaList> = $Schema['featureOptions']['schemaErrors'] - - export type HasSchemaErrorsViaName<$Name extends SchemaNames> = - // todo use conditional types? - // eslint-disable-next-line - // @ts-ignore passes after generation - GraphQLRequestTypes.Schemas[$Name]['featureOptions']['schemaErrors'] - - // eslint-disable-next-line - // @ts-ignore passes after generation - export type GetSchemaIndex<$Name extends SchemaNames> = GraphQLRequestTypes.Schemas[$Name]['index'] - - // eslint-disable-next-line - // @ts-ignore passes after generation - export type SchemaIndexDefault = GetSchemaIndex - - export type GetSchemaIndexOrDefault<$Name extends SchemaNames | undefined> = $Name extends SchemaNames - ? GetSchemaIndex<$Name> - : SchemaIndexDefault -} diff --git a/src/layers/2_generator/helpers.ts b/src/layers/2_generator/helpers.ts deleted file mode 100644 index c0a7cbe1c..000000000 --- a/src/layers/2_generator/helpers.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { Config } from './generateCode.js' - -export const title = (title: string) => { - const titleDecorated = `// ${title}\n// ${`-`.repeat(title.length)}\n` - return titleDecorated -} -export const typeTitle = (config: Config, typeName: string) => { - // @ts-expect-error ignoreme - // eslint-disable-next-line - const hasItems = config.typeMapByKind[`GraphQL${typeName}Type`]?.length > 0 - const title = `${typeName} Types` - const titleDecorated = `// ${title}\n// ${`-`.repeat(title.length)}\n` - if (hasItems) { - return titleDecorated - } else { - return `${titleDecorated}\n// -- None --\n` - } -} diff --git a/src/layers/2_generator/prelude.ts b/src/layers/2_generator/prelude.ts deleted file mode 100644 index 0f895429d..000000000 --- a/src/layers/2_generator/prelude.ts +++ /dev/null @@ -1,13 +0,0 @@ -import fs from 'node:fs/promises' -import { errorFromMaybeError } from '../../lib/prelude.js' - -export const fileExists = async (path: string) => { - return Boolean( - await fs.stat(path).catch((_: unknown) => { - const error = errorFromMaybeError(_) - return `code` in error && typeof error.code === `string` && error.code === `ENOENT` - ? null - : Promise.reject(error) - }), - ) -} diff --git a/src/layers/3_SelectionSet/_.ts b/src/layers/3_SelectionSet/_.ts deleted file mode 100644 index 4871ff9d0..000000000 --- a/src/layers/3_SelectionSet/_.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as Print from './encode.js' -export * from './types.js' diff --git a/src/layers/3_SelectionSet/__.ts b/src/layers/3_SelectionSet/__.ts deleted file mode 100644 index d927f56c3..000000000 --- a/src/layers/3_SelectionSet/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as SelectionSet from './_.js' diff --git a/src/layers/3_SelectionSet/__snapshots__/encode.test.ts.snap b/src/layers/3_SelectionSet/__snapshots__/encode.test.ts.snap deleted file mode 100644 index ef8270f9a..000000000 --- a/src/layers/3_SelectionSet/__snapshots__/encode.test.ts.snap +++ /dev/null @@ -1,1059 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`$defer > Query 1`] = ` -" -{ - "object": { - "$defer": true, - "id": true - } -} --------------- -{ - object @defer(if: true) { - id - } -} -" -`; - -exports[`$defer > Query 2`] = ` -" -{ - "object": { - "$defer": false, - "id": true - } -} --------------- -{ - object @defer(if: false) { - id - } -} -" -`; - -exports[`$defer > Query 3`] = ` -" -{ - "object": { - "id": true - } -} --------------- -{ - object { - id - } -} -" -`; - -exports[`$defer > Query 4`] = ` -" -{ - "object": { - "$defer": { - "if": true - }, - "id": true - } -} --------------- -{ - object @defer(if: true) { - id - } -} -" -`; - -exports[`$defer > Query 5`] = ` -" -{ - "object": { - "$defer": { - "if": false - }, - "id": true - } -} --------------- -{ - object @defer(if: false) { - id - } -} -" -`; - -exports[`$defer > Query 6`] = ` -" -{ - "object": { - "$defer": {}, - "id": true - } -} --------------- -{ - object @defer(if: true) { - id - } -} -" -`; - -exports[`$defer > Query 7`] = ` -" -{ - "object": { - "$defer": {}, - "id": true - } -} --------------- -{ - object @defer(if: true) { - id - } -} -" -`; - -exports[`$defer > Query 8`] = ` -" -{ - "object": { - "$defer": { - "label": "foobar" - }, - "id": true - } -} --------------- -{ - object @defer(if: true, label: "foobar") { - id - } -} -" -`; - -exports[`$include > Query 1`] = ` -" -{ - "object": { - "$include": true, - "id": true - } -} --------------- -{ - object @include(if: true) { - id - } -} -" -`; - -exports[`$include > Query 2`] = ` -" -{ - "object": { - "$include": false, - "id": true - } -} --------------- -{ - object @include(if: false) { - id - } -} -" -`; - -exports[`$include > Query 3`] = ` -" -{ - "object": { - "id": true - } -} --------------- -{ - object { - id - } -} -" -`; - -exports[`$include > Query 4`] = ` -" -{ - "object": { - "$include": { - "if": true - }, - "id": true - } -} --------------- -{ - object @include(if: true) { - id - } -} -" -`; - -exports[`$include > Query 5`] = ` -" -{ - "object": { - "$include": { - "if": false - }, - "id": true - } -} --------------- -{ - object @include(if: false) { - id - } -} -" -`; - -exports[`$include > Query 6`] = ` -" -{ - "object": { - "$include": {}, - "id": true - } -} --------------- -{ - object @include(if: true) { - id - } -} -" -`; - -exports[`$include > Query 7`] = ` -" -{ - "object": { - "$include": {}, - "id": true - } -} --------------- -{ - object @include(if: true) { - id - } -} -" -`; - -exports[`$skip > Query 1`] = ` -" -{ - "object": { - "$skip": true, - "id": true - } -} --------------- -{ - object @skip(if: true) { - id - } -} -" -`; - -exports[`$skip > Query 2`] = ` -" -{ - "object": { - "$skip": false, - "id": true - } -} --------------- -{ - object @skip(if: false) { - id - } -} -" -`; - -exports[`$skip > Query 3`] = ` -" -{ - "object": { - "id": true - } -} --------------- -{ - object { - id - } -} -" -`; - -exports[`$skip > Query 4`] = ` -" -{ - "object": { - "$skip": { - "if": true - }, - "id": true - } -} --------------- -{ - object @skip(if: true) { - id - } -} -" -`; - -exports[`$skip > Query 5`] = ` -" -{ - "object": { - "$skip": { - "if": false - }, - "id": true - } -} --------------- -{ - object @skip(if: false) { - id - } -} -" -`; - -exports[`$skip > Query 6`] = ` -" -{ - "object": { - "$skip": {}, - "id": true - } -} --------------- -{ - object @skip(if: true) { - id - } -} -" -`; - -exports[`$skip > Query 7`] = ` -" -{ - "object": { - "$skip": {}, - "id": true - } -} --------------- -{ - object @skip(if: true) { - id - } -} -" -`; - -exports[`$stream > Query 1`] = ` -" -{ - "object": { - "$stream": true, - "id": true - } -} --------------- -{ - object @stream(if: true) { - id - } -} -" -`; - -exports[`$stream > Query 2`] = ` -" -{ - "object": { - "$stream": false, - "id": true - } -} --------------- -{ - object @stream(if: false) { - id - } -} -" -`; - -exports[`$stream > Query 3`] = ` -" -{ - "object": { - "id": true - } -} --------------- -{ - object { - id - } -} -" -`; - -exports[`$stream > Query 4`] = ` -" -{ - "object": { - "$stream": { - "if": true - }, - "id": true - } -} --------------- -{ - object @stream(if: true) { - id - } -} -" -`; - -exports[`$stream > Query 5`] = ` -" -{ - "object": { - "$stream": { - "if": false - }, - "id": true - } -} --------------- -{ - object @stream(if: false) { - id - } -} -" -`; - -exports[`$stream > Query 6`] = ` -" -{ - "object": { - "$stream": {}, - "id": true - } -} --------------- -{ - object @stream(if: true) { - id - } -} -" -`; - -exports[`$stream > Query 7`] = ` -" -{ - "object": { - "$stream": {}, - "id": true - } -} --------------- -{ - object @stream(if: true) { - id - } -} -" -`; - -exports[`$stream > Query 8`] = ` -" -{ - "object": { - "$stream": { - "label": "foobar" - }, - "id": true - } -} --------------- -{ - object @stream(if: true, label: "foobar") { - id - } -} -" -`; - -exports[`$stream > Query 9`] = ` -" -{ - "object": { - "$stream": { - "initialCount": 5 - }, - "id": true - } -} --------------- -{ - object @stream(if: true, initialCount: 5) { - id - } -} -" -`; - -exports[`alias > Query 1`] = ` -" -{ - "id_as_x": true -} --------------- -{ - x: id -} -" -`; - -exports[`alias > Query 2`] = ` -" -{ - "id_as_x": true, - "id_as_id2": true -} --------------- -{ - x: id - id2: id -} -" -`; - -exports[`alias > Query 3`] = ` -" -{ - "id_as_x": { - "$skip": true - } -} --------------- -{ - x: id @skip(if: true) -} -" -`; - -exports[`alias > Query 4`] = ` -" -{ - "object_as_x": { - "$skip": true, - "id": true - } -} --------------- -{ - x: object @skip(if: true) { - id - } -} -" -`; - -exports[`args > Query 1`] = ` -" -{ - "stringWithArgs": { - "$": { - "boolean": true, - "float": 1 - } - } -} --------------- -{ - stringWithArgs(boolean: true, float: 1) -} -" -`; - -exports[`args > Query 2`] = ` -" -{ - "stringWithArgs": { - "$": {} - } -} --------------- -{ - stringWithArgs -} -" -`; - -exports[`args > Query 3`] = ` -" -{ - "objectWithArgs": { - "$": { - "id": "" - }, - "id": true - } -} --------------- -{ - objectWithArgs(id: "") { - id - } -} -" -`; - -exports[`args > Query 4`] = ` -" -{ - "objectWithArgs": { - "$": {}, - "id": true - } -} --------------- -{ - objectWithArgs { - id - } -} -" -`; - -exports[`args > custom scalars > Query > arg field 1`] = ` -" -{ - "dateArg": { - "$": { - "date": "1970-01-01T00:00:00.000Z" - } - } -} --------------- -{ - dateArg(date: "1970-01-01T00:00:00.000Z") -} -" -`; - -exports[`args > custom scalars > Query > arg field in list (null) 1`] = ` -" -{ - "dateArgList": { - "$": { - "date": null - } - } -} --------------- -{ - dateArgList(date: null) -} -" -`; - -exports[`args > custom scalars > Query > arg field in list 1`] = ` -" -{ - "dateArgList": { - "$": { - "date": [ - "1970-01-01T00:00:00.000Z", - "1970-01-01T00:00:00.001Z" - ] - } - } -} --------------- -{ - dateArgList(date: ["1970-01-01T00:00:00.000Z", "1970-01-01T00:00:00.001Z"]) -} -" -`; - -exports[`args > custom scalars > Query > arg field in non-null 1`] = ` -" -{ - "dateArgNonNull": { - "$": { - "date": "1970-01-01T00:00:00.000Z" - } - } -} --------------- -{ - dateArgNonNull(date: "1970-01-01T00:00:00.000Z") -} -" -`; - -exports[`args > custom scalars > Query > arg field in non-null list (with list) 1`] = ` -" -{ - "dateArgNonNullList": { - "$": { - "date": [ - "1970-01-01T00:00:00.000Z", - "1970-01-01T00:00:00.001Z" - ] - } - } -} --------------- -{ - dateArgNonNullList( - date: ["1970-01-01T00:00:00.000Z", "1970-01-01T00:00:00.001Z"] - ) -} -" -`; - -exports[`args > custom scalars > Query > arg field in non-null list (with null) 1`] = ` -" -{ - "dateArgNonNullList": { - "$": { - "date": [ - null, - "1970-01-01T00:00:00.000Z" - ] - } - } -} --------------- -{ - dateArgNonNullList(date: [null, "1970-01-01T00:00:00.000Z"]) -} -" -`; - -exports[`args > custom scalars > Query > arg field in non-null list non-null 1`] = ` -" -{ - "dateArgNonNullListNonNull": { - "$": { - "date": [ - "1970-01-01T00:00:00.000Z", - "1970-01-01T00:00:00.001Z" - ] - } - } -} --------------- -{ - dateArgNonNullListNonNull( - date: ["1970-01-01T00:00:00.000Z", "1970-01-01T00:00:00.001Z"] - ) -} -" -`; - -exports[`args > custom scalars > Query > input object field 1`] = ` -" -{ - "dateArgInputObject": { - "$": { - "input": { - "idRequired": "", - "dateRequired": "1970-01-01T00:00:00.000Z", - "date": "1970-01-01T00:00:00.001Z" - } - } - } -} --------------- -{ - dateArgInputObject( - input: {idRequired: "", dateRequired: "1970-01-01T00:00:00.000Z", date: "1970-01-01T00:00:00.001Z"} - ) -} -" -`; - -exports[`args > custom scalars > Query > nested input object field 1`] = ` -" -{ - "InputObjectNested": { - "$": { - "input": { - "InputObject": { - "idRequired": "", - "dateRequired": "1970-01-01T00:00:00.000Z", - "date": "1970-01-01T00:00:00.001Z" - } - } - } - } -} --------------- -{ - InputObjectNested( - input: {InputObject: {idRequired: "", dateRequired: "1970-01-01T00:00:00.000Z", date: "1970-01-01T00:00:00.001Z"}} - ) -} -" -`; - -exports[`enum > Query 1`] = ` -" -{ - "result": { - "$": { - "case": "Object1" - }, - "__typename": true - } -} --------------- -{ - result(case: Object1) { - __typename - } -} -" -`; - -exports[`other > Query 1`] = ` -" -{ - "__typename": true -} --------------- -{ - __typename -} -" -`; - -exports[`other > Query 2`] = ` -" -{ - "string": true -} --------------- -{ - string -} -" -`; - -exports[`other > Query 3`] = ` -" -{ - "string": 1 -} --------------- -{ - string -} -" -`; - -exports[`other > Query 4`] = ` -" -{ - "id": true, - "string": false -} --------------- -{ - id -} -" -`; - -exports[`other > Query 5`] = ` -" -{ - "id": true, - "string": 0 -} --------------- -{ - id -} -" -`; - -exports[`other > Query 6`] = ` -" -{ - "id": true -} --------------- -{ - id -} -" -`; - -exports[`other > Query 7`] = ` -" -{ - "object": { - "id": true - } -} --------------- -{ - object { - id - } -} -" -`; - -exports[`other > Query 8`] = ` -" -{ - "objectNested": { - "object": { - "string": true, - "id": true, - "int": false - } - } -} --------------- -{ - objectNested { - object { - string - id - } - } -} -" -`; - -exports[`other > Query 9`] = ` -" -{ - "objectNested": { - "object": { - "string": true, - "id": true, - "int": { - "$skip": true - } - } - } -} --------------- -{ - objectNested { - object { - string - id - int @skip(if: true) - } - } -} -" -`; - -exports[`union > Query 1`] = ` -" -{ - "unionFooBar": { - "__typename": true - } -} --------------- -{ - unionFooBar { - __typename - } -} -" -`; - -exports[`union > Query 2`] = ` -" -{ - "unionFooBar": { - "onBar": { - "int": true - } - } -} --------------- -{ - unionFooBar { - ... on Bar { - int - } - } -} -" -`; - -exports[`union > Query 3`] = ` -" -{ - "unionFooBar": { - "onBar": { - "$skip": true, - "int": true - } - } -} --------------- -{ - unionFooBar { - ... on Bar @skip(if: true) { - int - } - } -} -" -`; diff --git a/src/layers/3_SelectionSet/encode.test.ts b/src/layers/3_SelectionSet/encode.test.ts deleted file mode 100644 index 42630f435..000000000 --- a/src/layers/3_SelectionSet/encode.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -import { parse, print } from 'graphql' -import { describe, expect, test } from 'vitest' -import { db } from '../../../tests/_/db.js' -import type { Index } from '../../../tests/_/schema/generated/Index.js' -import { $Index as schemaIndex } from '../../../tests/_/schema/generated/SchemaRuntime.js' -import type { SelectionSet } from './__.js' -import type { Context } from './encode.js' -import { rootTypeSelectionSet } from './encode.js' - -// eslint-disable-next-line -// @ts-ignore -type Q = SelectionSet.Query -const s = (selectionSet: Q) => selectionSet - -const testEachArgs = [ - `Query`, - ( - ...args: [SelectionSet.Object] | [ - description: string, - ss: SelectionSet.Object, - ] - ) => { - const [description, ss] = args.length === 1 ? [undefined, args[0]] : args - const context: Context = { schemaIndex, config: { returnMode: `data` } } - const graphqlDocumentString = rootTypeSelectionSet(context, schemaIndex[`Root`][`Query`], ss as any) - // Should parse, ensures is syntactically valid graphql document. - const document = parse(graphqlDocumentString) - const graphqlDocumentStringFormatted = print(document) - const beforeAfter = `\n` - + JSON.stringify(ss, null, 2) - + `\n--------------\n` - + graphqlDocumentStringFormatted - + `\n` - expect(beforeAfter).toMatchSnapshot(description) - }, -] as const - -describe(`enum`, () => { - test.each([ - [s({ result: { $: { case: `Object1` }, __typename: true } })], - ])(...testEachArgs) -}) - -describe(`union`, () => { - test.each([ - [s({ unionFooBar: { __typename: true } })], - [s({ unionFooBar: { onBar: { int: true } } })], - [s({ unionFooBar: { onBar: { $skip: true, int: true } } })], - // s({ unionFooBar: { onBar: {} } }), // todo should be static type error - ])(...testEachArgs) -}) - -describe(`alias`, () => { - test.each([ - [s({ id_as_x: true })], - [s({ id_as_x: true, id_as_id2: true })], - [s({ id_as_x: { $skip: true } })], - [s({ object_as_x: { $skip: true, id: true } })], - ])(...testEachArgs) -}) - -describe(`args`, () => { - test.each([ - [s({ stringWithArgs: { $: { boolean: true, float: 1 } } })], - [s({ stringWithArgs: { $: {} } })], - // s({ objectWithArgs: { $: { id: `` } } }), // todo should be static error - // s({ objectWithArgs: { $: {} } }), // todo should be static error - [s({ objectWithArgs: { $: { id: `` }, id: true } })], - [s({ objectWithArgs: { $: {}, id: true } })], - ])(...testEachArgs) -}) - -describe(`$include`, () => { - test.each([ - [s({ object: { $include: true, id: true } })], - [s({ object: { $include: false, id: true } })], - [s({ object: { $include: undefined, id: true } })], - [s({ object: { $include: { if: true }, id: true } })], - [s({ object: { $include: { if: false }, id: true } })], - [s({ object: { $include: { if: undefined }, id: true } })], - [s({ object: { $include: {}, id: true } })], - ])(...testEachArgs) -}) - -describe(`$skip`, () => { - test.each([ - [s({ object: { $skip: true, id: true } })], - [s({ object: { $skip: false, id: true } })], - [s({ object: { $skip: undefined, id: true } })], - [s({ object: { $skip: { if: true }, id: true } })], - [s({ object: { $skip: { if: false }, id: true } })], - [s({ object: { $skip: { if: undefined }, id: true } })], - [s({ object: { $skip: {}, id: true } })], - ])(...testEachArgs) -}) - -describe(`$defer`, () => { - test.each([ - [s({ object: { $defer: true, id: true } })], - [s({ object: { $defer: false, id: true } })], - [s({ object: { $defer: undefined, id: true } })], - [s({ object: { $defer: { if: true }, id: true } })], - [s({ object: { $defer: { if: false }, id: true } })], - [s({ object: { $defer: { if: undefined }, id: true } })], - [s({ object: { $defer: {}, id: true } })], - [s({ object: { $defer: { label: `foobar` }, id: true } })], - ])(...testEachArgs) -}) - -describe(`$stream`, () => { - test.each([ - [s({ object: { $stream: true, id: true } })], - [s({ object: { $stream: false, id: true } })], - [s({ object: { $stream: undefined, id: true } })], - [s({ object: { $stream: { if: true }, id: true } })], - [s({ object: { $stream: { if: false }, id: true } })], - [s({ object: { $stream: { if: undefined }, id: true } })], - [s({ object: { $stream: {}, id: true } })], - [s({ object: { $stream: { label: `foobar` }, id: true } })], - [s({ object: { $stream: { initialCount: 5 }, id: true } })], - ])(...testEachArgs) -}) - -describe(`other`, () => { - test.each([ - [s({ __typename: true })], - [s({ string: true })], - [s({ string: 1 })], - // s({ string: false }), // todo should be static error - [s({ id: true, string: false })], - [s({ id: true, string: 0 })], - [s({ id: true, string: undefined })], - [s({ object: { id: true } })], - [s({ objectNested: { object: { string: true, id: true, int: false } } })], - [s({ objectNested: { object: { string: true, id: true, int: { $skip: true } } } })], - ])(...testEachArgs) -}) - -describe(`args`, () => { - // dprint-ignore - describe(`custom scalars`, () => { - test.each([ - [`arg field`, s({ dateArg: { $: { date: db.date0 } } })], - [`arg field in non-null`,s({ dateArgNonNull: { $: { date: db.date0 } } })], - [`arg field in list`,s({ dateArgList: { $: { date: [db.date0, new Date(1)] } } })], - [`arg field in list (null)`,s({ dateArgList: { $: { date: null } } })], - [`arg field in non-null list (with list)`,s({ dateArgNonNullList: { $: { date: [db.date0, new Date(1)] } } })], - [`arg field in non-null list (with null)`,s({ dateArgNonNullList: { $: { date: [null, db.date0] } } })], - [`arg field in non-null list non-null`,s({ dateArgNonNullListNonNull: { $: { date: [db.date0, new Date(1)] } } })], - [`input object field`,s({ dateArgInputObject: { $: { input: { idRequired: ``, dateRequired: db.date0, date: new Date(1) } } } })], - [`nested input object field`,s({ InputObjectNested: { $: { input: { InputObject: { idRequired: ``, dateRequired: db.date0, date: new Date(1) } } } } })] - ] as const)(...testEachArgs) - }) -}) diff --git a/src/layers/3_SelectionSet/encode.ts b/src/layers/3_SelectionSet/encode.ts deleted file mode 100644 index ae514573b..000000000 --- a/src/layers/3_SelectionSet/encode.ts +++ /dev/null @@ -1,269 +0,0 @@ -import { RootTypeName } from '../../lib/graphql.js' -import { assertArray, assertObject, lowerCaseFirstLetter } from '../../lib/prelude.js' -import { Schema } from '../1_Schema/__.js' -import { readMaybeThunk } from '../1_Schema/core/helpers.js' -import type { ReturnModeType } from '../5_client/Config.js' -import type { SelectionSet } from './__.js' -import { isSelectFieldName } from './helpers.js' -import { parseClientDirectiveDefer } from './runtime/directives/defer.js' -import { toGraphQLDirective } from './runtime/directives/directive.js' -import { parseClientDirectiveInclude } from './runtime/directives/include.js' -import { parseClientDirectiveSkip } from './runtime/directives/skip.js' -import { parseClientDirectiveStream } from './runtime/directives/stream.js' -import { parseClientFieldItem } from './runtime/FieldItem.js' -import { parseClientFieldName, toGraphQLFieldName } from './runtime/FieldName.js' -import type { Indicator } from './runtime/indicator.js' -import { isIndicator, isPositiveIndicator } from './runtime/indicator.js' -import { parseClientOn, toGraphQLOn } from './runtime/on.js' - -type SpecialFields = { - // todo - this requires having the schema at runtime to know which fields to select. - // $scalars?: SelectionSet.Indicator - $include?: SelectionSet.Directive.Include['$include'] - $skip?: SelectionSet.Directive.Skip['$skip'] - $defer?: SelectionSet.Directive.Defer['$defer'] - $stream?: SelectionSet.Directive.Stream['$stream'] - $?: Args -} - -type Args = { [k: string]: ArgValue } - -type ArgValue = string | boolean | null | number | Args - -export type DocumentObject = Record - -export type GraphQLRootSelection = { query: GraphQLObjectSelection } | { mutation: GraphQLObjectSelection } - -export type GraphQLObjectSelection = Record - -export type SS = { - [k: string]: Indicator | SS -} & SpecialFields - -type FieldValue = SS | Indicator - -export interface Context { - schemaIndex: Schema.Index - config: { - returnMode: ReturnModeType - } -} - -export const rootTypeSelectionSet = ( - context: Context, - objectDef: Schema.Object$2, - selectionSet: GraphQLObjectSelection, - operationName: string = ``, -) => { - const operationTypeName = lowerCaseFirstLetter(objectDef.fields.__typename.type.type) - return `${operationTypeName} ${operationName} { ${resolveObjectLikeFieldValue(context, objectDef, selectionSet)} }` -} - -const resolveDirectives = (fieldValue: FieldValue) => { - if (isIndicator(fieldValue)) return `` - - const { $include, $skip, $defer, $stream } = fieldValue - - let directives = `` - - if ($stream !== undefined) { - directives += toGraphQLDirective(parseClientDirectiveStream($stream)) - } - - if ($defer !== undefined) { - directives += toGraphQLDirective(parseClientDirectiveDefer($defer)) - } - - if ($include !== undefined) { - directives += toGraphQLDirective(parseClientDirectiveInclude($include)) - } - - if ($skip !== undefined) { - directives += toGraphQLDirective(parseClientDirectiveSkip($skip)) - } - - return directives -} - -const resolveArgValue = ( - context: Context, - schemaArgTypeMaybeThunk: Schema.Input.Any, - argValue: ArgValue, -): string => { - if (argValue === null) return String(null) // todo could check if index agrees is nullable. - - const schemaArgType = readMaybeThunk(schemaArgTypeMaybeThunk) - - switch (schemaArgType.kind) { - case `nullable`: - return resolveArgValue(context, schemaArgType.type, argValue) - case `list`: { - assertArray(argValue) - const value = argValue.map(_ => resolveArgValue(context, schemaArgType.type, _ as ArgValue)) - return `[${value.join(`, `)}]` - } - case `InputObject`: { - assertObject(argValue) - const entries = Object.entries(argValue).map(([argName, argValue]) => { - const schemaArgField = schemaArgType.fields[argName] as Schema.Input.Field | undefined - if (!schemaArgField) throw new Error(`Arg not found: ${argName}`) - return [argName, resolveArgValue(context, schemaArgField.type, argValue)] - }) - return `{ ${entries.map(([k, v]) => `${k!}: ${v!}`).join(`, `)} }` - } - case `Enum`: { - return String(argValue) - } - case `Scalar`: { - // @ts-expect-error fixme - return JSON.stringify(schemaArgType.codec.encode(argValue)) - } - default: - throw new Error(`Unsupported arg kind: ${JSON.stringify(schemaArgType)}`) - } -} - -const resolveArgs = (context: Context, schemaField: Schema.SomeField, ss: Indicator | SS) => { - if (isIndicator(ss)) return `` - - const { $ } = ss - if ($ === undefined) return `` - - const schemaArgs = schemaField.args - if (!schemaArgs) throw new Error(`Field has no args`) - - const argEntries = Object.entries($) - if (argEntries.length === 0) return `` - - return `(${ - argEntries.map(([argFieldName, v]) => { - const schemaArgField = schemaArgs.fields[argFieldName] as Schema.Input.Any | undefined // eslint-disable-line - if (!schemaArgField) throw new Error(`Arg field ${argFieldName} not found in schema.`) - const valueEncoded = resolveArgValue(context, schemaArgField, v) - return `${argFieldName}: ${valueEncoded}` - }).join(`, `) - })` -} -const pruneNonSelections = (ss: SS) => { - const entries = Object.entries(ss) - const selectEntries = entries.filter(_ => !_[0].startsWith(`$`)) - return Object.fromEntries(selectEntries) -} - -const resolveFieldValue = ( - context: Context, - schemaField: Schema.SomeField, - fieldValue: null | FieldValue, -): string => { - if (fieldValue === null) return `null` // todo test this case - - if (isIndicator(fieldValue)) return `` - - const entries = Object.entries(fieldValue) - const directives = resolveDirectives(fieldValue) - const args = resolveArgs(context, schemaField, fieldValue) - const selects = entries.filter(_ => isSelectFieldName(_[0])) - - if (selects.length === 0) { - return `${args} ${directives}` - } - - const selection = Object.fromEntries(selects) as GraphQLObjectSelection - - // eslint-disable-next-line - // @ts-ignore ID error - const schemaNamedOutputType = Schema.Output.unwrapToNamed(schemaField.type) as Schema.Object$2 - return `${args} ${directives} { - ${resolveObjectLikeFieldValue(context, readMaybeThunk(schemaNamedOutputType), selection)} - }` -} - -export const resolveObjectLikeFieldValue = ( - context: Context, - schemaItem: Schema.Object$2 | Schema.Union | Schema.Interface, - fieldValue: FieldValue, -): string => { - // todo optimize by doing single loop - const applicableSelections = Object.entries(fieldValue).filter(([_, ss]) => isPositiveIndicator(ss)) as [ - string, - FieldValue, - ][] - switch (schemaItem.kind) { - case `Object`: { - const rootTypeName = (RootTypeName as Record)[schemaItem.fields.__typename.type.type] - ?? null - return applicableSelections.map(([clientFieldName, ss]) => { - const fieldName = parseClientFieldName(clientFieldName) - const schemaField = schemaItem.fields[fieldName.actual] - if (!schemaField) throw new Error(`Field ${clientFieldName} not found in schema object`) - /** - * Inject __typename field for result fields that are missing it. - */ - // dprint-ignore - if (rootTypeName && context.config.returnMode === `successData` && context.schemaIndex.error.rootResultFields[rootTypeName][fieldName.actual]) { - (ss as Record)[`__typename`] = true - } - return `${toGraphQLFieldName(fieldName)} ${resolveFieldValue(context, schemaField, ss)}` - }).join(`\n`) + `\n` - } - case `Interface`: { - return applicableSelections.map(([ClientFieldName, ss]) => { - const fieldItem = parseClientFieldItem(ClientFieldName) - - switch (fieldItem._tag) { - case `FieldName`: { - if (fieldItem.actual === `__typename`) { - return `${toGraphQLFieldName(fieldItem)} ${resolveDirectives(ss)}` - } - const schemaField = schemaItem.fields[fieldItem.actual] - if (!schemaField) throw new Error(`Field ${ClientFieldName} not found in schema object`) - return `${toGraphQLFieldName(fieldItem)} ${resolveFieldValue(context, schemaField, ss)}` - } - case `On`: { - const schemaObject = context.schemaIndex[`objects`][fieldItem.typeOrFragmentName] - if (!schemaObject) throw new Error(`Fragment ${fieldItem.typeOrFragmentName} not found in schema`) - return `${toGraphQLOn(fieldItem)} ${resolveDirectives(ss)} { ${ - resolveObjectLikeFieldValue(context, schemaObject, ss) - } }` - } - default: { - throw new Error(`Unknown field item tag`) - } - } - }).join(`\n`) + `\n` - } - case `Union`: { - return applicableSelections.map(([fieldExpression, ss]) => { - const fieldItem = parseClientFieldItem(fieldExpression) - switch (fieldItem._tag) { - case `FieldName`: { - if (fieldItem.actual === `__typename`) { - return `${toGraphQLFieldName(fieldItem)} ${resolveDirectives(ss)}` - } - // todo - throw new Error(`todo resolve common interface fields from unions`) - } - case `On`: { - const schemaObject = context.schemaIndex[`objects`][fieldItem.typeOrFragmentName] - if (!schemaObject) throw new Error(`Fragment ${fieldItem.typeOrFragmentName} not found in schema`) - // if (isIndicator(ss)) throw new Error(`Union field must have selection set`) - return `${toGraphQLOn(fieldItem)} ${resolveDirectives(ss)} { ${ - // @ts-expect-error fixme - resolveObjectLikeFieldValue(context, schemaObject, pruneNonSelections(ss))} }` - } - default: { - throw new Error(`Unknown field item tag`) - } - } - }).join(`\n`) + `\n` - } - default: - throw new Error(`Unknown schema item kind`) - } -} - -export const resolveOn = (field: string) => { - const on = parseClientOn(field) - if (on) return toGraphQLOn(on) - return field -} diff --git a/src/layers/3_SelectionSet/helpers.ts b/src/layers/3_SelectionSet/helpers.ts deleted file mode 100644 index 5d8341da3..000000000 --- a/src/layers/3_SelectionSet/helpers.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isSpecialFieldName = (fieldName: string) => fieldName.startsWith(`$`) - -export const isSelectFieldName = (fieldName: string) => !isSpecialFieldName(fieldName) diff --git a/src/layers/3_SelectionSet/runtime/FieldItem.ts b/src/layers/3_SelectionSet/runtime/FieldItem.ts deleted file mode 100644 index af4bda18e..000000000 --- a/src/layers/3_SelectionSet/runtime/FieldItem.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { FieldName } from './FieldName.js' -import { parseClientFieldName } from './FieldName.js' -import type { On } from './on.js' -import { parseClientOn } from './on.js' - -export type FieldItem = On | FieldName - -export const parseClientFieldItem = (field: string): FieldItem => { - const on = parseClientOn(field) - if (on) return on - return parseClientFieldName(field) -} diff --git a/src/layers/3_SelectionSet/runtime/FieldName.ts b/src/layers/3_SelectionSet/runtime/FieldName.ts deleted file mode 100644 index eadb71e18..000000000 --- a/src/layers/3_SelectionSet/runtime/FieldName.ts +++ /dev/null @@ -1,37 +0,0 @@ -export interface FieldName { - _tag: 'FieldName' - actual: string - alias: string | null -} - -// todo use a given schema to ensure that field is actually a fragment and not just happened to be using pattern onX -export const parseClientFieldName = (field: string): FieldName => { - const match = field.match(aliasPattern) - if (match?.groups) { - return { - _tag: `FieldName`, - actual: match.groups[`actual`]!, - alias: match.groups[`alias`]!, - } - } - return { - _tag: `FieldName`, - actual: field, - alias: null, - } -} - -export const toGraphQLFieldName = (fieldName: FieldName) => { - if (fieldName.alias) { - // todo test coverage for this, discovered broken, not tested - return `${fieldName.alias}: ${fieldName.actual}` - } else { - return fieldName.actual - } -} - -/** - * @see https://regex101.com/r/XfOTMX/1 - * @see http://spec.graphql.org/draft/#sec-Names - */ -export const aliasPattern = /^(?[A-z][A-z_0-9]*)_as_(?[A-z][A-z_0-9]*)$/ diff --git a/src/layers/3_SelectionSet/runtime/directives/defer.ts b/src/layers/3_SelectionSet/runtime/directives/defer.ts deleted file mode 100644 index 5a5a4a55d..000000000 --- a/src/layers/3_SelectionSet/runtime/directives/defer.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { Directive } from '../../types.js' - -const name = `defer` - -export const parseClientDirectiveDefer = (input: Directive.Defer['$defer']) => { - const args = { - if: typeof input === `boolean` ? input : input.if === undefined ? true : input.if, - label: typeof input === `boolean` ? undefined : input.label, - } - return { - name, - args, - } -} diff --git a/src/layers/3_SelectionSet/runtime/directives/directive.ts b/src/layers/3_SelectionSet/runtime/directives/directive.ts deleted file mode 100644 index 3ff29830f..000000000 --- a/src/layers/3_SelectionSet/runtime/directives/directive.ts +++ /dev/null @@ -1,16 +0,0 @@ -export interface DirectiveLike { - name: string - args: Record -} - -export const toGraphQLDirective = (directive: DirectiveLike) => { - return `@${directive.name}(${toGraphQLDirectiveArgs(directive.args)})` -} - -export const toGraphQLDirectiveArgs = (args: object) => { - return Object.entries(args).filter(([_, v]) => v !== undefined).map(([k, clientValue]) => { - // todo can directives receive custom scalars? - const value = JSON.stringify(clientValue) - return `${k}: ${value}` - }).join(`, `) -} diff --git a/src/layers/3_SelectionSet/runtime/directives/include.ts b/src/layers/3_SelectionSet/runtime/directives/include.ts deleted file mode 100644 index fa7c33d24..000000000 --- a/src/layers/3_SelectionSet/runtime/directives/include.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Directive } from '../../types.js' - -const name = `include` - -export const parseClientDirectiveInclude = (input: Directive.Include['$include']) => { - const args = { - if: typeof input === `boolean` ? input : input.if === undefined ? true : input.if, - } - return { - name, - args, - } -} diff --git a/src/layers/3_SelectionSet/runtime/directives/skip.ts b/src/layers/3_SelectionSet/runtime/directives/skip.ts deleted file mode 100644 index a10102b61..000000000 --- a/src/layers/3_SelectionSet/runtime/directives/skip.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Directive } from '../../types.js' - -const name = `skip` - -export const parseClientDirectiveSkip = (input: Directive.Skip['$skip']) => { - const args = { - if: typeof input === `boolean` ? input : input.if === undefined ? true : input.if, - } - return { - name, - args, - } -} diff --git a/src/layers/3_SelectionSet/runtime/directives/stream.ts b/src/layers/3_SelectionSet/runtime/directives/stream.ts deleted file mode 100644 index 84c06c448..000000000 --- a/src/layers/3_SelectionSet/runtime/directives/stream.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Directive } from '../../types.js' - -const name = `stream` - -export const parseClientDirectiveStream = (input: Directive.Stream['$stream']) => { - const args = { - if: typeof input === `boolean` ? input : input.if === undefined ? true : input.if, - label: typeof input === `boolean` ? undefined : input.label, - initialCount: typeof input === `boolean` ? undefined : input.initialCount, - } - return { - name, - args, - } -} diff --git a/src/layers/3_SelectionSet/runtime/indicator.ts b/src/layers/3_SelectionSet/runtime/indicator.ts deleted file mode 100644 index fe1b5a611..000000000 --- a/src/layers/3_SelectionSet/runtime/indicator.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { ClientIndicatorPositive } from '../types.js' - -export type Indicator = 0 | 1 | boolean - -export const isIndicator = (v: any): v is Indicator => { - return String(v) in indicator -} - -export const isPositiveIndicator = (v: any): v is ClientIndicatorPositive => { - return !(String(v) in negativeIndicator) -} - -const negativeIndicator = { - '0': 0, - 'false': false, - 'undefined': undefined, -} - -const positiveIndicator = { - '1': 1, - 'true': true, -} - -const indicator = { - ...negativeIndicator, - ...positiveIndicator, -} diff --git a/src/layers/3_SelectionSet/runtime/on.ts b/src/layers/3_SelectionSet/runtime/on.ts deleted file mode 100644 index 6d1b58e39..000000000 --- a/src/layers/3_SelectionSet/runtime/on.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const onPattern = /^on(?[A-Z][A-z_0-9]*)$/ - -export interface On { - _tag: 'On' - typeOrFragmentName: string -} - -// todo use a given schema to ensure that field is actually a fragment and not just happened to be using pattern onX -export const parseClientOn = (field: string): null | On => { - const match = field.match(onPattern) - if (match?.groups) { - return { - _tag: `On`, - typeOrFragmentName: match.groups[`name`]!, - } - } - return null -} - -export const toGraphQLOn = (on: On) => { - return `...on ${on.typeOrFragmentName}` -} diff --git a/src/layers/3_SelectionSet/types.test-d.ts b/src/layers/3_SelectionSet/types.test-d.ts deleted file mode 100644 index dd670977d..000000000 --- a/src/layers/3_SelectionSet/types.test-d.ts +++ /dev/null @@ -1,238 +0,0 @@ -import { assertType, expectTypeOf, test } from 'vitest' -import type { Index } from '../../../tests/_/schema/generated/Index.js' -import type { SelectionSet } from './__.js' - -type Q = SelectionSet.Query - -test(`ParseAliasExpression`, () => { - expectTypeOf>().toEqualTypeOf>() - expectTypeOf>().toEqualTypeOf<'a'>() - expectTypeOf>().toEqualTypeOf<'$'>() - expectTypeOf>().toEqualTypeOf<'a_as_$'>() - expectTypeOf>().toEqualTypeOf<'$_as_b'>() - expectTypeOf>().toEqualTypeOf<'1_as_2'>() -}) - -// dprint-ignore -test(`Query`, () => { - assertType({ __typename: true }) - - // @ts-expect-error directive on root type Query - assertType({ $defer: true }) - - // Scalar - assertType({ id: true }) - assertType({ id: true }) - assertType({ id: false }) - assertType({ id: 1 }) - assertType({ id: 0 }) - assertType({ id: undefined }) - // non-null - assertType({ idNonNull: true }) - - // Custom Scalar - assertType({ date: true }) - assertType({ date: false }) - assertType({ date: 0 }) - assertType({ date: 1 }) - assertType({ date: undefined }) - - // Enum - assertType({ abcEnum: true }) - - // Object - assertType({ object: { id: true } }) - // typename - assertType({ __typename: true }) - // Non-Null - assertType({ objectNonNull: { id: true } }) - // @ts-expect-error excess property check - assertType({ id2: true }) - // @ts-expect-error excess property check - assertType({ object: { a2: true } }) - - // Union - assertType({ unionFooBar: { __typename: true } }) - assertType({ unionFooBar: { onFoo: { __typename: true } } }) - assertType({ unionFooBar: { onFoo: { id: true } } }) - // @ts-expect-error no b - assertType({ unionFooBar: { onFoo: { id2: true } } }) - assertType({ unionFooBar: { onBar: { __typename: true } } }) - assertType({ unionFooBar: { onBar: { int: true } } }) - // @ts-expect-error no a - assertType({ unionFooBar: { onBar: { int2: true } } }) - - // Union fragments Case - assertType({ lowerCaseUnion: { onLowerCaseObject: { id: true }, onLowerCaseObject2: { int: true } } }) - - // Interface - assertType({ interface: { id: true } }) - assertType({ interface: { id: { $defer: true } } }) - assertType({ interface: { id: { $include: true } } }) - assertType({ interface: { id: { $skip: true } } }) - assertType({ interface: { id: { $stream: true } } }) - assertType({ interface: { __typename: true } }) - assertType({ interface: { __typename: { $defer: true } } }) - assertType({ interface: { $scalars: true } }) - assertType({ interfaceWithArgs: { $: { id: `abc` }, id: true } }) - // @ts-expect-error needs fragment - assertType({ interface: { id: true, int: true } }) - // @ts-expect-error needs fragment - assertType({ interface: { id: true, boolean: true } }) - assertType({ interface: { id: true, onObject1ImplementingInterface: { int: true } } }) - assertType({ interface: { id: true, onObject2ImplementingInterface: { boolean: true } } }) - // @ts-expect-error incorrect implementor name - assertType({ interface: { id: true, onObject1ImplementingInterface2: { int: true } } }) - // directives work on fragments - assertType({ interface: { id: true, onObject1ImplementingInterface: { $include: true } } }) // todo should REQUIRE field selection - - // Alias - // alias: enum - assertType({ abcEnum_as_enum: true }) - // alias: object - assertType({ object_as_o: { id: true } }) - // @ts-expect-error invalid alias key format - assertType({ object_as_: { id: true } }) - // @ts-expect-error invalid alias key format - assertType({ object_as: { id: true } }) - // @ts-expect-error invalid alias key format - assertType({ object2_as_o: { id: true } }) - - // directives - // @skip - // on scalar - assertType({ string: { $skip: true } }) - assertType({ string: { $skip: false } }) - assertType({ string: { $skip: { if: true } } }) - assertType({ string: { $skip: { if: false } } }) - assertType({ string: { $skip: {} } }) - assertType({ string: { $skip: {} } }) - // assertType({ string: skip() }) - // on object - assertType({ object: { $skip: true, string: true } }) - // assertType({ scalars: skip().select({ a: true }) }) - // on fragment - assertType({ unionFooBar: { onBar: { $skip: true, int: true } } }) - // @include - assertType({ string: { $include: true } }) - assertType({ string: { $include: false } }) - assertType({ string: { $include: { if: true } } }) - assertType({ string: { $include: { if: false } } }) - assertType({ string: { $include: {} } }) - assertType({ string: { $include: {} } }) - // assertType({ string: include() }) - - // @defer - assertType({ string: { $defer: true } }) - assertType({ string: { $defer: { if: true, label: `foo` } } }) - assertType({ string: { $defer: { if: true } } }) - assertType({ string: { $defer: {} } }) - - // (todo limit to lists?) - // @stream - assertType({ string: { $stream: true } }) - assertType({ string: { $stream: { if: true, label: `foo`, initialCount: 0 } } }) - assertType({ string: { $stream: { if: true, label: `foo` } } }) - assertType({ string: { $stream: { if: true } } }) - assertType({ string: { $stream: {} } }) - - // Field Group - // On Object - assertType({ object: { ___: { int: true, id: true } } }) - assertType({ object: { ___: { $skip: true, int: true, id: true } } }) - assertType({ object: { ___: [{ $skip: true, int: true, id: true }] } }) - // On Root (Query) - assertType({ ___: { id: true } }) - assertType({ ___: { $skip: true, id: true } }) - - // Arguments - // all-optional on object - assertType({ objectWithArgs: { $: {}, id: true } }) - assertType({ objectWithArgs: { id: true } }) - assertType({ - objectWithArgs: { - $: { - boolean: true, - float: 1, - id: `id`, - int: 3, - string: `abc`, - }, - id: true, - }, - }) - // builder interface - // assertType({ foo: args({ ... }) }) - // all-optional on scalar - assertType({ stringWithArgs: true }) - assertType({ stringWithArgs: {} }) - assertType({ stringWithArgs: { $: { boolean: true, float: 1, id: `id`, int: 3, string: `abc` } } }) - assertType({ stringWithArgs: { $: { boolean: null, float: null, id: null, int: null, string: null } } }) - - // enum arg - assertType({ stringWithArgEnum: { $: { ABCEnum: `A` } } }) - assertType({ stringWithArgEnum: { $: { ABCEnum: `B` } } }) - assertType({ stringWithArgEnum: { $: { ABCEnum: `C` } } }) - assertType({ stringWithArgEnum: { $: { ABCEnum: null } } }) - assertType({ stringWithArgEnum: { $: {} } }) - // @ts-expect-error invalid enum value - assertType({ stringWithArgEnum: { $: { ABCEnum: `D` } } }) - // @ts-expect-error invalid enum value - assertType({ stringWithArgEnum: { $: { ABCEnum: `` } } }) - // @ts-expect-error invalid enum value - assertType({ stringWithArgEnum: { $: { ABCEnum: 1 } } }) - - // list arg - assertType({ stringWithListArg: { $: { ints: [1, 2, 3] } } }) - assertType({ stringWithListArg: { $: { ints: [] } } }) - assertType({ stringWithListArg: { $: { ints: [null] } } }) - assertType({ stringWithListArg: { $: { ints: null } } }) - assertType({ stringWithListArg: { $: {} } }) - // @ts-expect-error missing "ints" arg - assertType({ stringWithListArgRequired: { $: {} } }) - // @ts-expect-error missing non-null "ints" arg - assertType({ stringWithListArgRequired: { $: { ints: null } } }) - - // custom scalar arg - // @ts-expect-error wrong type - assertType({ dateArg: { $: { date: 0 } } }) - assertType({ dateArg: { $: { date: null } } }) - assertType({ dateArg: { $: { date: new Date(0) } } }) - - // input object arg - assertType({ stringWithArgInputObjectRequired: { $: { input: { id: ``, idRequired: ``, dateRequired: new Date(0) } } } }) - assertType({ stringWithArgInputObjectRequired: { $: { input: { id: null, idRequired: ``, dateRequired: new Date(0) } } } }) - assertType({ stringWithArgInputObjectRequired: { $: { input: { idRequired: ``, dateRequired: new Date(0) } } } }) - // @ts-expect-error missing "idRequired" field - assertType({ stringWithArgInputObjectRequired: { $: { input: {} } } }) - // type x = Exclude['$']['input'] - - // all-optional + scalar + directive - assertType({ stringWithArgs: { $: { boolean: true }, $skip: true } }) - // builder interface - // assertType({ foo: args({ boolean: true }).skip().select({ x: 1 }) }) - // 1+ required + scalar - assertType({ stringWithRequiredArg: { $: { string: `` } } }) - // @ts-expect-error missing "string" arg - assertType({ stringWithRequiredArg: { $: {} } }) - // @ts-expect-error missing args ("$") - assertType({ stringWithRequiredArg: {} }) - - // Scalars Wildcard ("client directive") - // object - assertType({ object: { $scalars: true } }) - // @ts-expect-error no directives on scalars field - assertType({ scalars: { $scalars: { $skip: true } } }) - // union fragment - assertType({ unionFooBar: { onBar: { $scalars: true } } }) - assertType({ unionFooBarWithArgs: { $: { id: `abc` }, onBar: { $scalars: true } } }) - - // assertType({ scalars: select() }) - - // todo empty selection set not allowed, with arguments given - // todo empty selection set not allowed, with directive given - // todo empty selection set not allowed - // // @ts-expect-error empty selection set not allowed - // assertType({ scalars: {} }) - // todo selection set of _only_ negative indicators should not be allowed -}) diff --git a/src/layers/3_SelectionSet/types.ts b/src/layers/3_SelectionSet/types.ts deleted file mode 100644 index 228e16f55..000000000 --- a/src/layers/3_SelectionSet/types.ts +++ /dev/null @@ -1,280 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-types */ - -import type { 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' - -export type Query<$Index extends Schema.Index> = Root<$Index, 'Query'> - -export type Mutation<$Index extends Schema.Index> = Root<$Index, 'Mutation'> - -export type Subscription<$Index extends Schema.Index> = Root<$Index, '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 - -// dprint-ignore -export type Object<$Object extends Schema.Object$2, $Index extends Schema.Index> = - Fields<$Object['fields'], $Index> - -// dprint-ignore -type Fields<$Fields extends SomeFields, $Index extends Schema.Index> = - & - { - [Key in keyof $Fields]?: - // eslint-disable-next-line - // @ts-ignore excessive deep error, fixme? - Field<$Fields[Key], $Index> - } - & - /** - * Alias support. - * Allow every field to also be given as a key with this pattern `_as_: ...` - */ - { - [ - Key in keyof $Fields as `${keyof $Fields & string}_as_${StringNonEmpty}` - ]?: - Field<$Fields[Key], $Index> - } - & - /** - * Inline fragments for field groups. - * @see https://spec.graphql.org/draft/#sec-Inline-Fragments - */ - { - ___?: MaybeList & FieldDirectives> - } - & - /** - * Special property to select all scalars. - */ - { - $scalars?: ClientIndicator - } - -export type IsSelectScalarsWildcard = SS extends { $scalars: ClientIndicatorPositive } ? true : false - -type FieldOptions = { - /** - * When using root type field methods there is no point in directives since there can be - * no no peer fields with those function that by design target sending one root type field. - */ - hideDirectives?: boolean -} - -type FieldOptionsDefault = { hideDirectives: false } - -// dprint-ignore -export type Field<$Field extends SomeField, $Index extends Schema.Index, $Options extends FieldOptions = FieldOptionsDefault> = - Field_<$Field['type'], $Field, $Index, $Options> - -// dprint-ignore -export type Field_< - $type extends Schema.Output.Any, - $Field extends SomeField, - $Index extends Schema.Index, - $Options extends FieldOptions -> = - $type extends Schema.Output.Nullable ? Field_<$typeInner, $Field, $Index, $Options> : - $type extends Schema.Output.List ? Field_<$typeInner, $Field, $Index, $Options> : - $type extends Schema.__typename ? NoArgsIndicator : - $type extends Schema.Scalar.Any ? Indicator<$Field> : - $type extends Schema.Enum ? Indicator<$Field> : - $type extends Schema.Object$2 ? Object<$type, $Index> & ($Options['hideDirectives'] extends true ? {} : FieldDirectives) & Arguments<$Field> : - $type extends Schema.Union ? Union<$type, $Index> & Arguments<$Field> : - $type extends Schema.Interface ? Interface<$type, $Index> & Arguments<$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']> } : - { $: Args<$Field['args']> } : - {} - -// dprint-ignore -export type Interface<$Node extends Schema.Interface, $Index extends Schema.Index> = - & InterfaceDistributed<$Node['implementors'][number], $Index> - & Fields< - & $Node['fields'] - & { - __typename: $Node['implementors'][number]['fields']['__typename'] - }, - $Index - > - -// dprint-ignore -type InterfaceDistributed<$Node extends Schema.Object$2, $Index extends Schema.Index> = - $Node extends any - ? { - [$typename in $Node['fields']['__typename']['type']['type'] as `on${Capitalize<$typename>}`]?: - Object<$Node, $Index> & FieldDirectives - } - : never - -// dprint-ignore -export type Union<$Node extends Schema.Union, $Index extends Schema.Index> = - & UnionDistributed<$Node['members'][number], $Index> - & { __typename?: NoArgsIndicator } - -// dprint-ignore -type UnionDistributed<$Object extends Schema.Object$2,$Index extends Schema.Index> = - $Object extends any - ? { - [$typename in $Object['fields']['__typename']['type']['type'] as `on${Capitalize<$typename>}`]?: - Object<$Object, $Index> & FieldDirectives - } - : never - -/** - * Helpers - * --------------------------------------------------------------------------------------------------- - */ - -/** - * Unions - */ - -export type UnionFragmentExtractName = T extends `on${infer $Name}` ? $Name : never -export type UnionExtractFragmentNames = Values< - { - [Key in keyof T]: UnionFragmentExtractName - } -> -export type OmitOnTypeFragments = { - [$K in keyof T as $K extends `on${StringNonEmpty}` ? never : $K]: T[$K] -} - -/** - * Aliases - */ - -export interface Alias { - origin: O - target: T -} - -// dprint-ignore -export type ParseAliasExpression = - E extends `${infer O}_as_${infer T}` ? Schema.Named.NameParse extends never ? E : - Schema.Named.NameParse extends never ? E : - Alias - : E - -export type AliasNameOrigin = ParseAliasExpression extends Alias ? O : N - -/** - * Resolve the target of an alias or if is not an alias just pass through the name. - */ -export type AliasNameTarget = ParseAliasExpression extends Alias ? T : N - -export type ResolveAliasTargets = { - [Field in keyof SelectionSet as AliasNameTarget]: SelectionSet[Field] -} - -/** - * Directives - */ - -export namespace Directive { - export type Include = { $include: boolean | { if?: boolean } } - export namespace Include { - export type Positive = { $include: true | { if: true } } - export type Negative = { $include: false | { if: false } } - } - export type Skip = { $skip: boolean | { if?: boolean } } - export namespace Skip { - export type Positive = { $skip: true | { if: true } } - export type Negative = { $skip: false | { if: false } } - } - export type 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 type 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 } } - } -} - -/** - * Indicators - */ - -/** - * Should this field be selected? - */ -export type ClientIndicator = ClientIndicatorPositive | ClientIndicatorNegative -export type ClientIndicatorPositive = true | 1 -export type ClientIndicatorNegative = false | 0 | undefined - -export type OmitNegativeIndicators<$SelectionSet> = { - [K in keyof $SelectionSet as $SelectionSet[K] extends ClientIndicatorNegative ? never : K]: $SelectionSet[K] -} - -/** - * 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`. - * Of course the semantics of the directive may change the derived type (e.g. `skip` means the field might not show up in the result set) - */ -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 - -// dprint-ignore -export type Args<$Args extends Schema.Args> = ArgFields<$Args['fields']> - -// dprint-ignore -export type ArgFields<$ArgFields extends Schema.InputObject['fields']> = - & { - [Key in keyof OmitNullableFields<$ArgFields>]: InputField<$ArgFields[Key]> - } - & { - [Key in keyof PickNullableFields<$ArgFields>]?: InputField<$ArgFields[Key]> | null - } - -// dprint-ignore -type InputField<$InputType extends Schema.Input.Any> = - $InputType extends Schema.Input.Nullable ? InputField<$InnerType> | null : - $InputType extends Schema.Input.List ? InputField<$InnerType>[] : - $InputType extends Schema.InputObject ? ArgFields<$Fields> : - $InputType extends Schema.Enum ? $Members[number] : - $InputType extends Schema.Scalar.Any ? ReturnType<$InputType['codec']['decode']> : - TSError<'InferTypeInput', 'Unknown $InputType', { $InputType: $InputType }> // never - -/** - * @see https://spec.graphql.org/draft/#sec-Type-System.Directives.Built-in-Directives - */ -export interface FieldDirectives { - /** - * https://spec.graphql.org/draft/#sec--skip - */ - $skip?: boolean | { if?: boolean } - /** - * https://spec.graphql.org/draft/#sec--include - */ - $include?: boolean | { if?: boolean } - /** - * @see https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md#defer - */ - $defer?: boolean | { if?: boolean; label?: string } - /** - * @see https://github.com/graphql/graphql-wg/blob/main/rfcs/DeferStream.md#stream - */ - $stream?: boolean | { if?: boolean; label?: string; initialCount?: number } -} diff --git a/src/layers/4_ResultSet/__.ts b/src/layers/4_ResultSet/__.ts deleted file mode 100644 index 6ad17db77..000000000 --- a/src/layers/4_ResultSet/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as ResultSet from './types.js' diff --git a/src/layers/4_ResultSet/customScalars.ts b/src/layers/4_ResultSet/customScalars.ts deleted file mode 100644 index e6149cf30..000000000 --- a/src/layers/4_ResultSet/customScalars.ts +++ /dev/null @@ -1,77 +0,0 @@ -import type { ExecutionResult } from 'graphql' -import { standardScalarTypeNames } from '../../lib/graphql.js' -import { assertArray, mapValues } from '../../lib/prelude.js' -import type { Object$2, Schema } from '../1_Schema/__.js' -import { Output } from '../1_Schema/__.js' -import { readMaybeThunk } from '../1_Schema/core/helpers.js' -import type { GraphQLObject } from '../4_ResultSet/runtime.js' -import { assertGraphQLObject } from '../4_ResultSet/runtime.js' - -export const decode = <$Data extends ExecutionResult['data']>(index: Schema.Object$2, data: $Data): $Data => { - if (!data) return data - return mapValues(data, (v, fieldName) => { - const indexField = index.fields[fieldName] - if (!indexField) throw new Error(`Field not found: ${String(fieldName)}`) - - const type = readMaybeThunk(indexField.type) - const typeWithoutNonNull = Output.unwrapNullable(type) as Output.Named | Output.List - const v2 = decodeCustomScalarValue(typeWithoutNonNull, v as any) - return v2 - }) as $Data -} - -const decodeCustomScalarValue = ( - indexType: Output.Any, - fieldValue: string | boolean | null | number | GraphQLObject | GraphQLObject[], -) => { - if (fieldValue === null) return null - - const indexTypeDethunked = readMaybeThunk(indexType) - const typeWithoutNonNull = Output.unwrapNullable(indexTypeDethunked) as Exclude> - - if (typeWithoutNonNull.kind === `list`) { - assertArray(fieldValue) - return fieldValue.map((v2: any): any => { - return decodeCustomScalarValue(typeWithoutNonNull.type, v2) - }) - } - - if (typeWithoutNonNull.kind === `Scalar`) { - if ((typeWithoutNonNull.name in standardScalarTypeNames)) { - // todo test this case - return fieldValue - } - if (typeof fieldValue === `object`) throw new Error(`Expected scalar. Got: ${String(fieldValue)}`) - // @ts-expect-error fixme - return typeWithoutNonNull.codec.decode(fieldValue) - } - - if (typeWithoutNonNull.kind === `typename`) { - return fieldValue - } - - assertGraphQLObject(fieldValue) - - if (typeWithoutNonNull.kind === `Object`) { - return decode(typeWithoutNonNull, fieldValue) - } - - if (typeWithoutNonNull.kind === `Interface` || typeWithoutNonNull.kind === `Union`) { - const possibleObjects = typeWithoutNonNull.kind === `Interface` - ? typeWithoutNonNull.implementors - : typeWithoutNonNull.members - // todo handle aliases -- will require having the selection set available for reference too :/ - // eslint-disable-next-line - // @ts-ignore infinite depth issue - // eslint-disable-next-line - const ObjectType = possibleObjects.find((ObjectType) => { - if (fieldValue.__typename === ObjectType.fields.__typename.type.type) return true - if (Object.keys(fieldValue).every(fieldName => ObjectType.fields[fieldName] !== undefined)) return true - return false - }) as undefined | Object$2 - if (!ObjectType) throw new Error(`Could not pick object for ${typeWithoutNonNull.kind} selection`) - return decode(ObjectType, fieldValue) - } - - return fieldValue -} diff --git a/src/layers/4_ResultSet/runtime.ts b/src/layers/4_ResultSet/runtime.ts deleted file mode 100644 index 045ff507a..000000000 --- a/src/layers/4_ResultSet/runtime.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { assertObject } from '../../lib/prelude.js' - -// eslint-disable-next-line -export function assertGraphQLObject(v: unknown): asserts v is GraphQLObject { - assertObject(v) - if (`__typename` in v && typeof v.__typename !== `string`) { - throw new Error(`Expected string __typename or undefined. Got: ${String(v.__typename)}`) - } -} - -export type GraphQLObject = { - __typename?: string -} diff --git a/src/layers/4_ResultSet/types.test-d.ts b/src/layers/4_ResultSet/types.test-d.ts deleted file mode 100644 index 24aa76a34..000000000 --- a/src/layers/4_ResultSet/types.test-d.ts +++ /dev/null @@ -1,130 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-types */ - -import { expectTypeOf, test } from 'vitest' -import type { Index } from '../../../tests/_/schema/generated/Index.js' -import type * as Schema from '../../../tests/_/schema/generated/SchemaBuildtime.js' -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> - -// dprint-ignore -test(`general`, () => { - // __typename - expectTypeOf>().toEqualTypeOf<{ __typename: 'Query' }>() - - // Scalar - expectTypeOf>().toEqualTypeOf<{ id: null | string }>() - expectTypeOf>().toEqualTypeOf<{ id: null | string }>() - // non-nullable - expectTypeOf>().toEqualTypeOf<{ idNonNull: string }>() - // indicator negative - expectTypeOf>().toEqualTypeOf<{ id: null | string }>() - expectTypeOf>().toEqualTypeOf<{ id: null | string }>() - expectTypeOf>().toEqualTypeOf<{ id: null | string }>() - - // Custom Scalar - expectTypeOf>().toEqualTypeOf<{ date: null | Date }>() - - // List - expectTypeOf>().toEqualTypeOf<{ listIntNonNull: number[] }>() - expectTypeOf>().toEqualTypeOf<{ listInt: null|(null|number)[] }>() - expectTypeOf>().toEqualTypeOf<{ listListIntNonNull: number[][] }>() - expectTypeOf>().toEqualTypeOf<{ listListInt: null|((null|(null|number)[])[]) }>() - - // Enum - expectTypeOf>().toEqualTypeOf<{ abcEnum: null|'A'|'B'|'C' }>() - - // Object - expectTypeOf>().toEqualTypeOf<{ object: null | { id: string | null } }>() - // non-nullable - expectTypeOf>().toEqualTypeOf<{ objectNonNull: { id: string | null } }>() - // with args - expectTypeOf>().toEqualTypeOf<{ objectWithArgs: null | { id: string | null } }>() - - // scalars-wildcard - expectTypeOf>().toEqualTypeOf<{ objectNonNull: { __typename: "Object1"; string: null|string; int: null|number; float: null|number; boolean: null|boolean; id: null|string } }>() - // scalars-wildcard with nested object - expectTypeOf>().toEqualTypeOf<{ objectNested: null | { __typename: "ObjectNested"; id: null|string } }>() - // __typename - expectTypeOf>().toEqualTypeOf<{ objectNonNull: { __typename: "Object1" } }>() - - // Union - expectTypeOf>().toEqualTypeOf<{ unionFooBar: null | { __typename: "Foo" } | { __typename: "Bar" } }>() - expectTypeOf>().toEqualTypeOf<{ unionFooBar: null | {} | { __typename: "Foo" } }>() - expectTypeOf>().toEqualTypeOf<{ unionFooBar: null | {} | { id: null|string } }>() - expectTypeOf>().toEqualTypeOf<{ unionFooBar: null | { __typename: "Bar" } | { __typename: "Foo"; id: null|string } }>() - // with Args - expectTypeOf>().toEqualTypeOf<{ unionFooBarWithArgs: null | {} | { id: null|string } }>() - - - // Union fragments Case - expectTypeOf>().toEqualTypeOf<{ lowerCaseUnion: null | { __typename: 'lowerCaseObject'; id: null|string } | { __typename: 'lowerCaseObject2'; int: null|number } }>() - - - // Interface - expectTypeOf>().toEqualTypeOf<{ interface: null | { id: null | string} | {} }>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { int: null | number} | {} }>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { id: null | string} }>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { id: null | string} }>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { id: null | string} | { id: null | string; int: null | number }}>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { __typename: 'Object1ImplementingInterface' } | { __typename: 'Object2ImplementingInterface' } }>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { __typename: 'Object1ImplementingInterface' } | {}}>() - expectTypeOf>().toEqualTypeOf<{ interface: null | { __typename: 'Object1ImplementingInterface', id: null | string, int: null|number} | { __typename: 'Object2ImplementingInterface', id: null | string; boolean:null|boolean} }>() - // with args - expectTypeOf>().toEqualTypeOf<{ interfaceWithArgs: null | { id: null | string } }>() - - // Alias - // scalar - expectTypeOf>().toEqualTypeOf<{ id2: null | string }>() - expectTypeOf>().toEqualTypeOf<{ id2: string }>() - expectTypeOf>().toEqualTypeOf<{ id_as: ResultSet.Errors.UnknownFieldName<'id_as', Schema.Root.Query> }>() - expectTypeOf>().toEqualTypeOf<{ id_as_$: ResultSet.Errors.UnknownFieldName<'id_as_$', Schema.Root.Query> }>() - // union fragment - expectTypeOf>().toEqualTypeOf<{ unionFooBar: null | {} | { id2: null|string } }>() - - // Directive @include - // On scalar non-nullable - expectTypeOf>().toEqualTypeOf<{ idNonNull: null|string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: null|string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: null }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: null }>() - // On scalar nullable - expectTypeOf>().toEqualTypeOf<{ id: null|string }>() - expectTypeOf>().toEqualTypeOf<{ id: null }>() - expectTypeOf>().toEqualTypeOf<{ id: null|string }>() - - // Directive @skip - // On scalar non-nullable - expectTypeOf>().toEqualTypeOf<{ idNonNull: null|string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: null|string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: null }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: null }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: string }>() - expectTypeOf>().toEqualTypeOf<{ idNonNull: string }>() - // On scalar nullable - expectTypeOf>().toEqualTypeOf<{ id: null|string }>() - expectTypeOf>().toEqualTypeOf<{ id: null|string }>() - expectTypeOf>().toEqualTypeOf<{ id: null }>() - - // Directive @defer - // todo - - // Directive @stream - // todo - - // Field Group - // todo - - // Arguments - // scalar - expectTypeOf>().toEqualTypeOf<{ stringWithArgs: null | string }>() - expectTypeOf>().toEqualTypeOf<{ stringWithArgs: null | string }>() - - // Errors - // unknown field - 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 deleted file mode 100644 index 96a29e7f2..000000000 --- a/src/layers/4_ResultSet/types.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-types */ - -import type { Simplify } from 'type-fest' -import type { ExcludeNull, GetKeyOr, SimplifyDeep } from '../../lib/prelude.js' -import type { TSError } from '../../lib/TSError.js' -import type { Schema, SomeField } from '../1_Schema/__.js' -import type { PickScalarFields } from '../1_Schema/Output/Output.js' -import type { SelectionSet } from '../3_SelectionSet/__.js' - -export type Query<$SelectionSet extends object, $Index extends Schema.Index> = Root<$SelectionSet, $Index, 'Query'> - -// dprint-ignore -export type Mutation<$SelectionSet extends object, $Index extends Schema.Index> = Root<$SelectionSet, $Index, 'Mutation'> - -// dprint-ignore -export type Subscription<$SelectionSet extends object, $Index extends Schema.Index> = Root<$SelectionSet, $Index, 'Subscription'> - -export type Root< - $SelectionSet extends object, - $Index extends Schema.Index, - $RootTypeName extends Schema.RootTypeName, -> = SimplifyDeep, $Index>> - -// dprint-ignore -export type Object$<$SelectionSet, $Node extends Schema.Output.Object$2, $Index extends Schema.Index> = - SelectionSet.IsSelectScalarsWildcard<$SelectionSet> extends true - /** - * Handle Scalars Wildcard - */ - ? - { - [$Key in keyof PickScalarFields<$Node>]: Field<$SelectionSet, $Node['fields'][$Key], $Index> - } - /** - * Handle fields in regular way. - */ - : - SelectionSet.ResolveAliasTargets<{ - [K in keyof SelectionSet.OmitNegativeIndicators<$SelectionSet> & string as K extends `${K}_as_${infer s}` ? s : K]: - SelectionSet.AliasNameOrigin extends keyof $Node['fields'] - ? Field<$SelectionSet[K], $Node['fields'][SelectionSet.AliasNameOrigin], $Index> - : Errors.UnknownFieldName, $Node> - }> - -// dprint-ignore -export type Union<$SelectionSet, $Node extends Schema.Output.Union, $Index extends Schema.Index> = - OnTypeFragment<$SelectionSet,$Node['members'][number], $Index> - -// dprint-ignore -export type Interface<$SelectionSet, $Node extends Schema.Output.Interface, $Index extends Schema.Index> = - OnTypeFragment<$SelectionSet, $Node['implementors'][number], $Index> - -// dprint-ignore -type OnTypeFragment<$SelectionSet, $Node extends Schema.Output.Object$2, $Index extends Schema.Index> = - $Node extends any // force distribution - ? Object$< - GetKeyOr<$SelectionSet, `on${Capitalize<$Node['fields']['__typename']['type']['type']>}`, {}> & SelectionSet.OmitOnTypeFragments<$SelectionSet>, - $Node, - $Index - > - : never - -// dprint-ignore -export type Field<$SelectionSet, $Field extends SomeField, $Index extends Schema.Index> = - $SelectionSet extends SelectionSet.Directive.Include.Negative | SelectionSet.Directive.Skip.Positive ? - null : - ( - | FieldDirectiveInclude<$SelectionSet> - | FieldDirectiveSkip<$SelectionSet> - | FieldType, $Field['type'], $Index> - ) - -// dprint-ignore -type FieldType< - $SelectionSet, - $Type extends Schema.Output.Any, - $Index extends Schema.Index -> = Simplify< - $Type extends Schema.__typename ? $Value : - $Type extends Schema.Output.Nullable ? null | FieldType<$SelectionSet, $InnerType, $Index> : - $Type extends Schema.Output.List ? Array> : - $Type extends Schema.Enum ? $Members[number] : - $Type extends Schema.Scalar.Any ? ReturnType<$Type['codec']['decode']> : - $Type extends Schema.Object$2 ? Object$<$SelectionSet,$Type,$Index> : - $Type extends Schema.Interface ? Interface<$SelectionSet,$Type,$Index> : - $Type extends Schema.Union ? Union<$SelectionSet,$Type,$Index> : - TSError<'FieldType', `Unknown type`, { $Type: $Type }> - > - -// dprint-ignore -type FieldDirectiveInclude<$SelectionSet> = - $SelectionSet extends SelectionSet.Directive.Include ? $SelectionSet extends SelectionSet.Directive.Include.Positive ? - never : - null - : never - -// dprint-ignore -type FieldDirectiveSkip<$SelectionSet> = - $SelectionSet extends SelectionSet.Directive.Skip ? $SelectionSet extends SelectionSet.Directive.Skip.Negative ? - never : - null - : never - -// 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']}"`> -} diff --git a/src/layers/5_client/Config.ts b/src/layers/5_client/Config.ts deleted file mode 100644 index bf0e00889..000000000 --- a/src/layers/5_client/Config.ts +++ /dev/null @@ -1,106 +0,0 @@ -import type { ExecutionResult } from 'graphql' -import type { GraphQLExecutionResultError } from '../../lib/graphql.js' -import type { SetProperty, StringKeyof } from '../../lib/prelude.js' -import type { Schema } from '../1_Schema/__.js' -import type { GlobalRegistry } from '../2_generator/globalRegistry.js' -import type { SelectionSet } from '../3_SelectionSet/__.js' - -export type ReturnModeType = - | ReturnModeTypeGraphQL - | ReturnModeTypeGraphQLSuccess - | ReturnModeTypeSuccessData - | ReturnModeTypeData - | ReturnModeTypeDataAndErrors - -export type ReturnModeTypeBase = - | ReturnModeTypeGraphQLSuccess - | ReturnModeTypeGraphQL - | ReturnModeTypeDataAndErrors - | ReturnModeTypeData - -export type ReturnModeTypeGraphQLSuccess = 'graphqlSuccess' - -export type ReturnModeTypeGraphQL = 'graphql' - -export type ReturnModeTypeData = 'data' - -export type ReturnModeTypeDataAndErrors = 'dataAndErrors' - -// todo rename to dataSuccess -export type ReturnModeTypeSuccessData = 'successData' - -export type OptionsInput = { - returnMode: ReturnModeType | undefined -} - -export type OptionsInputDefaults = { - returnMode: 'data' -} - -export type Config = { - returnMode: ReturnModeType -} - -export type ApplyInputDefaults = { - [Key in keyof OptionsInputDefaults]: undefined extends Input[Key] ? OptionsInputDefaults[Key] - : Exclude -} - -// dprint-ignore -export type ReturnModeRootType<$Config extends Config, $Index extends Schema.Index, $Data extends object> = - $Config['returnMode'] extends 'graphql' ? ExecutionResult<$Data> : - $Config['returnMode'] extends 'data' ? $Data : - $Config['returnMode'] extends 'successData' ? { [$Key in keyof $Data]: ExcludeSchemaErrors<$Index, $Data[$Key]> } : - $Data | GraphQLExecutionResultError - -// dprint-ignore -export type ReturnModeRootField<$Config extends Config, $Index extends Schema.Index, $Data, $DataRaw = undefined> = - $Config['returnMode'] extends 'graphql' ? ExecutionResult<$DataRaw extends undefined ? $Data : $DataRaw> : - $Config['returnMode'] extends 'data' ? $Data : - $Config['returnMode'] extends 'successData' ? ExcludeSchemaErrors<$Index, $Data> : - $Data | GraphQLExecutionResultError - -export type ExcludeSchemaErrors<$Index extends Schema.Index, $Data> = Exclude< - $Data, - $Index['error']['objectsTypename'][keyof $Index['error']['objectsTypename']] -> - -export type OrThrowifyConfig<$Config extends Config> = $Config['returnMode'] extends 'graphql' ? $Config - : SetProperty<$Config, 'returnMode', 'successData'> - -/** - * We inject __typename select when: - * 1. using schema errors - * 2. using return mode successData - */ - -type TypenameSelection = { __typename: true } - -// dprint-ignore -export type CreateSelectionTypename<$Config extends Config, $Index extends Schema.Index> = - IsNeedSelectionTypename<$Config, $Index> extends true ? TypenameSelection : {} // eslint-disable-line - -// dprint-ignore -export type IsNeedSelectionTypename<$Config extends Config, $Index extends Schema.Index> = - $Config['returnMode'] extends 'successData' ? GlobalRegistry.HasSchemaErrorsViaName<$Index['name']> extends true ? true : - false : - false - -export type AugmentRootTypeSelectionWithTypename< - $Config extends Config, - $Index extends Schema.Index, - $RootTypeName extends Schema.RootTypeName, - $Selection extends object, -> = IsNeedSelectionTypename<$Config, $Index> extends true ? { - [$Key in StringKeyof<$Selection>]: - & $Selection[$Key] - & (IsRootFieldNameAResultField<$Index, $RootTypeName, $Key> extends true ? TypenameSelection : {}) // eslint-disable-line - } - : $Selection - -type IsRootFieldNameAResultField< - $Index extends Schema.Index, - $RootTypeName extends Schema.RootTypeName, - $FieldName extends string, -> = SelectionSet.AliasNameOrigin<$FieldName> extends keyof $Index['error']['rootResultFields'][$RootTypeName] ? true - : false diff --git a/src/layers/5_client/RootTypeMethods.ts b/src/layers/5_client/RootTypeMethods.ts deleted file mode 100644 index 33f7a9c7a..000000000 --- a/src/layers/5_client/RootTypeMethods.ts +++ /dev/null @@ -1,91 +0,0 @@ -import type { OperationTypeName } 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 { SelectionSet } from '../3_SelectionSet/__.js' -import type { ResultSet } from '../4_ResultSet/__.js' -import type { - AugmentRootTypeSelectionWithTypename, - Config, - CreateSelectionTypename, - OrThrowifyConfig, - ReturnModeRootField, - ReturnModeRootType, -} from './Config.js' - -type RootTypeFieldContext = { - Config: Config - Index: Schema.Index - RootTypeName: Schema.RootTypeName - RootTypeFieldName: string - Field: Schema.SomeField -} - -// dprint-ignore -export type GetRootTypeMethods<$Config extends Config, $Index extends Schema.Index> = { - [$OperationName in OperationTypeName as $Index['Root'][Capitalize<$OperationName>] extends null ? never : $OperationName]: - RootTypeMethods<$Config, $Index, Capitalize<$OperationName>> -} - -// 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> - $batchOrThrow: RootMethod, $Index, $RootTypeName> - } - & { - [$RootTypeFieldName in keyof $Index['Root'][$RootTypeName]['fields'] & string]: - RootTypeFieldMethod<{ - Config: $Config, - Index: $Index, - RootTypeName: $RootTypeName, - RootTypeFieldName: $RootTypeFieldName - Field: $Index['Root'][$RootTypeName]['fields'][$RootTypeFieldName] - }> - } - & { - [$RootTypeFieldName in keyof $Index['Root'][$RootTypeName]['fields'] & string as `${$RootTypeFieldName}OrThrow`]: - RootTypeFieldMethod<{ - Config: OrThrowifyConfig<$Config>, - Index: $Index, - RootTypeName: $RootTypeName, - RootTypeFieldName: $RootTypeFieldName - Field: $Index['Root'][$RootTypeName]['fields'][$RootTypeFieldName] - }> - } - ) - : TSError<'RootTypeMethods', `Your schema does not have the root type "${$RootTypeName}".`> - -// dprint-ignore -type RootMethod<$Config extends Config, $Index extends Schema.Index, $RootTypeName extends Schema.RootTypeName> = - <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Root<$Index, $RootTypeName>>) => - Promise, $Index, $RootTypeName>>> - -// dprint-ignore -type RootTypeFieldMethod<$Context extends RootTypeFieldContext> = - RootTypeFieldMethod_<$Context, $Context['Field']['type']> - -// dprint-ignore -type RootTypeFieldMethod_<$Context extends RootTypeFieldContext, $Type extends Schema.Output.Any> = - $Type extends Schema.Output.Nullable ? RootTypeFieldMethod_<$Context, $InnerType> : - $Type extends Schema.Output.List ? RootTypeFieldMethod_<$Context, $InnerType> : - $Type extends Schema.Scalar.Any ? ScalarFieldMethod<$Context> : - // todo test this case - $Type extends Schema.__typename ? ScalarFieldMethod<$Context> : - ObjectLikeFieldMethod<$Context> - -// dprint-ignore -type ObjectLikeFieldMethod<$Context extends RootTypeFieldContext> = - <$SelectionSet>(selectionSet: Exact<$SelectionSet, SelectionSet.Field<$Context['Field'], $Context['Index'], { hideDirectives: true }>>) => - Promise, $Context['Field'], $Context['Index']>>> - -// 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>> : - <$SelectionSet>(args: Exact<$SelectionSet, SelectionSet.Args<$Context['Field']['args']>>) => Promise>> : - (() => Promise>>) -// dprint-ignore -type ReturnModeForFieldMethod<$Context extends RootTypeFieldContext, $Data> = - ReturnModeRootField<$Context['Config'], $Context['Index'], $Data, { [k in $Context['RootTypeFieldName']] : $Data }> diff --git a/src/layers/5_client/client.batch.test.ts b/src/layers/5_client/client.batch.test.ts deleted file mode 100644 index 31be0dd71..000000000 --- a/src/layers/5_client/client.batch.test.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { describe, expect, test } from 'vitest' -import { db } from '../../../tests/_/db.js' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import * as Schema from '../../../tests/_/schema/schema.js' - -const graffle = Graffle.create({ schema: Schema.schema }) - -// dprint-ignore -describe(`query`, () => { - test(`success`, async () => { - await expect(graffle.query.$batch({ id: true })).resolves.toMatchObject({ id:db.id }) - }) - test(`error`, async () => { - await expect(graffle.query.$batch({ error: true })).rejects.toMatchObject(db.errorAggregate) - }) - describe(`orThrow`, () => { - test(`success`, async () => { - await expect(graffle.query.$batchOrThrow({ id: true })).resolves.toMatchObject({ id:db.id }) - }) - test(`error`, async () => { - await expect(graffle.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) - }) - }) -}) diff --git a/src/layers/5_client/client.customScalar.test.ts b/src/layers/5_client/client.customScalar.test.ts deleted file mode 100644 index c5f6f22b0..000000000 --- a/src/layers/5_client/client.customScalar.test.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* eslint-disable */ -import { describe, expect } from 'vitest' -import { db } from '../../../tests/_/db.js' -import { createResponse, test } from '../../../tests/_/helpers.js' -import { Graffle } from '../../../tests/_/schema/generated/__.js' - -const date0Encoded = db.date0.toISOString() - -const client = Graffle.create({ schema: 'https://foo' }) - -test(`query field`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { date: date0Encoded } })) - expect(await client.query.$batch({ date: true })).toEqual({ date: db.date0 }) -}) -test(`query field in non-null`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateNonNull: date0Encoded } })) - expect(await client.query.$batch({ dateNonNull: true })).toEqual({ dateNonNull: db.date0 }) -}) -test(`query field in list`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateList: [0, 1] } })) - expect(await client.query.$batch({ dateList: true })).toEqual({ dateList: [db.date0, new Date(1)] }) -}) -test(`query field in list non-null`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateList: [0, 1] } })) - expect(await client.query.$batch({ dateList: true })).toEqual({ dateList: [db.date0, new Date(1)] }) -}) -test(`object field`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateObject1: { date1: 0 } } })) - expect(await client.query.$batch({ dateObject1: { date1: true } })).toEqual({ - dateObject1: { date1: db.date0 }, - }) -}) -test(`object field in interface`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateInterface1: { date1: 0 } } })) - expect(await client.query.$batch({ dateInterface1: { date1: true } })).toEqual({ - dateInterface1: { date1: db.date0 }, - }) -}) - -describe(`object field in union`, () => { - test(`case 1 with __typename`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateUnion: { __typename: `DateObject1`, date1: 0 } } })) - expect(await client.query.$batch({ dateUnion: { __typename: true, onDateObject1: { date1: true } } })) - .toEqual({ - dateUnion: { __typename: `DateObject1`, date1: db.date0 }, - }) - }) - test(`case 1 without __typename`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateUnion: { date1: date0Encoded } } })) - expect(await client.query.$batch({ dateUnion: { onDateObject1: { date1: true } } })).toEqual({ - dateUnion: { date1: db.date0 }, - }) - }) - test(`case 2`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateUnion: { date2: date0Encoded } } })) - expect( - await client.query.$batch({ - dateUnion: { onDateObject1: { date1: true }, onDateObject2: { date2: true } }, - }), - ) - .toEqual({ dateUnion: { date2: db.date0 } }) - }) - test(`case 2 miss`, async ({ fetch }) => { - fetch.mockResolvedValueOnce(createResponse({ data: { dateUnion: null } })) - expect(await client.query.$batch({ dateUnion: { onDateObject1: { date1: true } } })).toEqual({ - dateUnion: null, - }) // dprint-ignore - }) -}) diff --git a/src/layers/5_client/client.document.test-d.ts b/src/layers/5_client/client.document.test-d.ts deleted file mode 100644 index ea3978698..000000000 --- a/src/layers/5_client/client.document.test-d.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { describe, expectTypeOf, test } from 'vitest' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import * as Schema from '../../../tests/_/schema/schema.js' -import { MutationOnly } from '../../../tests/_/schemaMutationOnly/generated/__.js' -import * as SchemaMutationOnly from '../../../tests/_/schemaMutationOnly/schema.js' -import { QueryOnly } from '../../../tests/_/schemaQueryOnly/generated/__.js' -import * as SchemaQueryOnly from '../../../tests/_/schemaQueryOnly/schema.js' - -const graffle = Graffle.create({ schema: Schema.schema }) - -test(`requires input`, () => { - // @ts-expect-error missing input - graffle.document() - // @ts-expect-error empty object - graffle.document({}) -}) - -describe(`input`, () => { - test(`document with one query`, () => { - const run = graffle.document({ foo: { query: { id: true } } }).run - expectTypeOf(run).toMatchTypeOf<(...params: ['foo'] | [] | [undefined]) => Promise>() - }) - - test(`document with two queries`, () => { - const run = graffle.document({ - foo: { query: { id: true } }, - bar: { query: { id: true } }, - }).run - expectTypeOf(run).toMatchTypeOf<(name: 'foo' | 'bar') => Promise>() - }) - - test(`root operation not available if it is not in schema`, () => { - const queryOnly = QueryOnly.create({ - schema: SchemaQueryOnly.schema, - }) - queryOnly.document({ - foo: { query: { id: true } }, - // @ts-expect-error mutation not in schema - bar: { mutation: { id: true } }, - }) - const mutationOnly = MutationOnly.create({ - schema: SchemaMutationOnly.schema, - }) - mutationOnly.document({ - // @ts-expect-error query not in schema - foo: { query: { id: true } }, - bar: { mutation: { id: true } }, - }) - }) -}) - -describe(`document(...).run()`, () => { - test(`document with one query`, () => { - { - const result = graffle.document({ x: { query: { id: true } } }).run() - expectTypeOf(result).resolves.toEqualTypeOf<{ id: string | null }>() - } - { - const result = graffle.document({ x: { query: { id: true } } }).run(`x`) - expectTypeOf(result).resolves.toEqualTypeOf<{ id: string | null }>() - } - { - const result = graffle.document({ x: { query: { id: true } } }).run(undefined) - expectTypeOf(result).resolves.toEqualTypeOf<{ id: string | null }>() - } - }) - test(`document with two queries`, () => { - const result = graffle.document({ - foo: { query: { id: true } }, - bar: { query: { id: true } }, - }).run(`foo`) - expectTypeOf(result).resolves.toEqualTypeOf<{ id: string | null }>() - }) -}) - -describe(`document(...).runOrThrow()`, () => { - describe(`query result field`, () => { - test(`with __typename`, () => { - const result = graffle.document({ x: { query: { resultNonNull: { __typename: true } } } }).runOrThrow() - expectTypeOf(result).resolves.toEqualTypeOf<{ resultNonNull: { __typename: 'Object1' } }>() - }) - test(`without __typename`, () => { - const result = graffle.document({ x: { query: { resultNonNull: {} } } }).runOrThrow() - expectTypeOf(result).resolves.toEqualTypeOf<{ resultNonNull: { __typename: 'Object1' } }>() - }) - test(`multiple via alias`, () => { - const result = graffle.document({ x: { query: { resultNonNull: {}, resultNonNull_as_x: {} } } }).runOrThrow() - expectTypeOf(result).resolves.toEqualTypeOf< - { resultNonNull: { __typename: 'Object1' }; x: { __typename: 'Object1' } } - >() - }) - }) -}) diff --git a/src/layers/5_client/client.document.test.ts b/src/layers/5_client/client.document.test.ts deleted file mode 100644 index bed8bea6d..000000000 --- a/src/layers/5_client/client.document.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { describe, expect, test } from 'vitest' -import { db } from '../../../tests/_/db.js' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { schema } from '../../../tests/_/schema/schema.js' - -// todo test with custom scalars - -const graffle = Graffle.create({ schema }) - -describe(`document with two queries`, () => { - const withTwo = graffle.document({ - foo: { query: { id: true } }, - bar: { query: { idNonNull: true } }, - }) - - // todo allow sync extensions - // eslint-disable-next-line - graffle.extend(async ({ exchange }) => { - if (exchange.input.transport !== `http`) return exchange() - // @ts-expect-error Nextjs - exchange.input.request.next = { revalidate: 60, tags: [`menu`] } - return exchange({ - ...exchange.input, - request: { - ...exchange.input.request, - }, - }) - }).document({ - foo: { query: { id: true } }, - bar: { query: { idNonNull: true } }, - }) - - test(`works`, async () => { - const { run } = withTwo - await expect(run(`foo`)).resolves.toEqual({ id: db.id1 }) - await expect(run(`bar`)).resolves.toEqual({ idNonNull: db.id1 }) - }) - test(`error if no operation name is provided`, async () => { - const { run } = withTwo - // @ts-expect-error - await expect(run()).rejects.toMatchObject({ - errors: [{ message: `Must provide operation name if query contains multiple operations.` }], - }) - }) - test(`error if wrong operation name is provided`, async () => { - const { run } = withTwo - // @ts-expect-error - await expect(run(`boo`)).rejects.toMatchObject({ errors: [{ message: `Unknown operation named "boo".` }] }) - }) - test.skip(`error if invalid name in document`, async () => { - // @ts-expect-error - const { run } = graffle.document({ foo$: { query: { id: true } } }) - await expect(run(`foo$`)).rejects.toMatchObject({ - errors: [{ message: `Syntax Error: Expected "{", found "$".` }], - }) - }) -}) - -test(`document with one query`, async () => { - const { run } = graffle.document({ foo: { query: { id: true } } }) - await expect(run(`foo`)).resolves.toEqual({ id: db.id1 }) - await expect(run()).resolves.toEqual({ id: db.id1 }) - await expect(run(undefined)).resolves.toEqual({ id: db.id1 }) -}) - -test(`document with one mutation`, async () => { - const { run } = graffle.document({ foo: { mutation: { id: true } } }) - await expect(run(`foo`)).resolves.toEqual({ id: db.id1 }) - await expect(run()).resolves.toEqual({ id: db.id1 }) - await expect(run(undefined)).resolves.toEqual({ id: db.id1 }) -}) - -test(`error`, async () => { - const { run } = graffle.document({ foo: { query: { error: true } } }) - await expect(run()).rejects.toMatchObject({ errors: [{ message: `Something went wrong.` }] }) -}) - -test(`document with one mutation and one query`, async () => { - const { run } = graffle.document({ - foo: { - mutation: { id: true }, - }, - bar: { - query: { idNonNull: true }, - }, - }) - await expect(run(`foo`)).resolves.toEqual({ id: db.id1 }) - await expect(run(`bar`)).resolves.toEqual({ idNonNull: db.id1 }) -}) - -describe(`document(...).runOrThrow()`, () => { - describe(`query result field`, () => { - test(`with __typename`, async () => { - const result = graffle.document({ - x: { query: { resultNonNull: { $: { case: `ErrorOne` }, __typename: true } } }, - }) - .runOrThrow() - await expect(result).rejects.toMatchInlineSnapshot(`[Error: Failure on field resultNonNull: ErrorOne]`) - }) - test(`without __typename`, async () => { - const result = graffle.document({ x: { query: { resultNonNull: { $: { case: `ErrorOne` } } } } }).runOrThrow() - await expect(result).rejects.toMatchInlineSnapshot( - `[Error: Failure on field resultNonNull: ErrorOne]`, - ) - }) - test.todo(`multiple via alias`, async () => { - const result = graffle.document({ - x: { query: { resultNonNull: { $: { case: `ErrorOne` } }, resultNonNull_as_x: { $: { case: `ErrorOne` } } } }, - }).runOrThrow() - await expect(result).rejects.toMatchInlineSnapshot( - `[ContextualAggregateError: Two or more schema errors in the execution result.]`, - ) - }) - }) -}) diff --git a/src/layers/5_client/client.error.test-d.ts b/src/layers/5_client/client.error.test-d.ts deleted file mode 100644 index 5da670729..000000000 --- a/src/layers/5_client/client.error.test-d.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* eslint-disable */ -import { expectTypeOf, test } from 'vitest' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { isError } from '../../../tests/_/schema/generated/Error.js' -import * as Schema from '../../../tests/_/schema/schema.js' - -const client = Graffle.create({ schema: Schema.schema }) - -test('isError utility function narrows for error objects', async () => { - const result = await client.query.result({ $: { case: 'Object1' }, __typename: true }) - - if (isError(result)) { - expectTypeOf(result).toEqualTypeOf<{ __typename: 'ErrorOne' } | { __typename: 'ErrorTwo' }>() - } else { - expectTypeOf(result).toEqualTypeOf() - } -}) diff --git a/src/layers/5_client/client.extend.test.ts b/src/layers/5_client/client.extend.test.ts deleted file mode 100644 index 41dec82de..000000000 --- a/src/layers/5_client/client.extend.test.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* eslint-disable */ -import { describe, expect } from 'vitest' -import { db } from '../../../tests/_/db.js' -import { createResponse, test } from '../../../tests/_/helpers.js' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { oops } from '../../lib/anyware/specHelpers.js' - -const client = Graffle.create({ schema: 'https://foo', returnMode: 'dataAndErrors' }) -const headers = { 'x-foo': 'bar' } - -// todo each extension added should copy, not mutate the client - -describe(`entrypoint request`, () => { - test(`can add header to request`, async ({ fetch }) => { - fetch.mockImplementationOnce(async (input: Request) => { - expect(input.headers.get('x-foo')).toEqual(headers['x-foo']) - return createResponse({ data: { id: db.id } }) - }) - const client2 = client.extend(async ({ pack }) => { - // todo should be raw input types but rather resolved - // todo should be URL instance? - // todo these input type tests should be moved down to Anyware - // expectTypeOf(exchange).toEqualTypeOf() - // expect(exchange.input).toEqual({ url: 'https://foo', document: `query { id \n }` }) - return await pack({ ...pack.input, headers }) - }) - expect(await client2.query.id()).toEqual(db.id) - }) - test('can chain into exchange', async ({ fetch }) => { - fetch.mockImplementationOnce(async () => { - return createResponse({ data: { id: db.id } }) - }) - const client2 = client.extend(async ({ pack }) => { - const { exchange } = await pack({ ...pack.input, headers }) - return await exchange(exchange.input) - }) - expect(await client2.query.id()).toEqual(db.id) - }) -}) - -test('can retry failed request', async ({ fetch }) => { - fetch - .mockImplementationOnce(async () => { - throw oops - }) - .mockImplementationOnce(async () => { - throw oops - }) - .mockImplementationOnce(async () => { - return createResponse({ data: { id: db.id } }) - }) - const client2 = client.retry(async ({ exchange }) => { - let result = await exchange() - while (result instanceof Error) { - result = await exchange() - } - return result - }) - const result = await client2.query.id() - expect(result).toEqual(db.id) - expect(fetch.mock.calls.length).toEqual(3) -}) diff --git a/src/layers/5_client/client.input.test-d.ts b/src/layers/5_client/client.input.test-d.ts deleted file mode 100644 index eb3de2380..000000000 --- a/src/layers/5_client/client.input.test-d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { test } from 'vitest' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { schema } from '../../../tests/_/schema/schema.js' -import { QueryOnly } from '../../../tests/_/schemaQueryOnly/generated/__.js' - -test(`works`, () => { - Graffle.create({ schema, returnMode: `graphql` }) - Graffle.create({ schema, returnMode: `data` }) - Graffle.create({ schema, returnMode: `dataAndErrors` }) - Graffle.create({ schema, returnMode: `successData` }) - - QueryOnly.create({ schema, returnMode: `graphql` }) - QueryOnly.create({ schema, returnMode: `data` }) - QueryOnly.create({ schema, returnMode: `dataAndErrors` }) - // @ts-expect-error bad returnMode - QueryOnly.create({ schema, name: `QueryOnly`, returnMode: `successData` }) -}) diff --git a/src/layers/5_client/client.raw.test.ts b/src/layers/5_client/client.raw.test.ts deleted file mode 100644 index 8dbfc43df..000000000 --- a/src/layers/5_client/client.raw.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { expect, test } from 'vitest' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { schema } from '../../../tests/_/schema/schema.js' - -// todo test with custom scalars - -const graffle = Graffle.create({ schema }) - -test(`.rawOrThrow() throws if errors array non-empty`, async () => { - await expect(graffle.rawOrThrow({ document: `query {}` })).rejects.toMatchInlineSnapshot( - `[ContextualAggregateError: One or more errors in the execution result.]`, - ) -}) - -test(`.raw() returns errors in array`, async () => { - await expect(graffle.raw({ document: `query {}` })).resolves.toMatchInlineSnapshot(` - { - "errors": [ - [GraphQLError: Syntax Error: Expected Name, found "}".], - ], - } - `) -}) diff --git a/src/layers/5_client/client.returnMode.test-d.ts b/src/layers/5_client/client.returnMode.test-d.ts deleted file mode 100644 index 71d935b0a..000000000 --- a/src/layers/5_client/client.returnMode.test-d.ts +++ /dev/null @@ -1,155 +0,0 @@ -/* eslint-disable */ -import { ExecutionResult } from 'graphql' -import { type ObjMap } from 'graphql/jsutils/ObjMap.js' -import { describe } from 'node:test' -import { expectTypeOf, test } from 'vitest' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { schema } from '../../../tests/_/schema/schema.js' -import { GraphQLExecutionResultError } from '../../lib/graphql.js' - -// dprint-ignore -describe('default is data', () => { - const graffle = Graffle.create({ schema }) - test(`document.run`, async () => { - expectTypeOf(graffle.document({ main: { query: { id: true } } }).run()).resolves.toEqualTypeOf<{ id: string | null }>() - }) - test('query.', async () => { - await expectTypeOf(graffle.query.__typename()).resolves.toEqualTypeOf<'Query'>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqualTypeOf<{ __typename: 'Query', id: string|null }>() - }) - test('query.', async () => { - await expectTypeOf(graffle.query.result({$:{case:'Object1'},__typename:true})).resolves.toEqualTypeOf<{__typename: "Object1"} | {__typename: "ErrorOne"} | {__typename: "ErrorTwo"} | null>() - }) - test(`raw`, async () => { - expectTypeOf(graffle.raw({ document:'query main {\nid\n}', operationName: 'main' })).resolves.toEqualTypeOf() - }) -}) - -// dprint-ignore -describe('data', () => { - const graffle = Graffle.create({ schema, returnMode: 'data' }) - test(`document.run`, async () => { - expectTypeOf(graffle.document({ x: { query: { id: true } } }).run()).resolves.toEqualTypeOf<{ id: string | null }>() - }) - test('query.', async () => { - await expectTypeOf(graffle.query.__typename()).resolves.toEqualTypeOf<'Query'>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqualTypeOf<{ __typename: 'Query', id: string|null }>() - }) - test('query.',async () => { - await expectTypeOf(graffle.query.result({$:{case:'Object1'},__typename:true})).resolves.toEqualTypeOf<{__typename: "Object1"} | {__typename: "ErrorOne"} | {__typename: "ErrorTwo"} | null>() - }) - test('query. orThrow',async () => { - await expectTypeOf(graffle.query.resultOrThrow({$:{case:'Object1'},__typename:true})).resolves.toEqualTypeOf<{__typename: "Object1"} | null>() - }) - test(`raw`, async () => { - expectTypeOf(graffle.raw({ document:'query main {\nid\n}', operationName: 'main' })).resolves.toEqualTypeOf() - }) -}) - -// dprint-ignore -describe('successData', () => { - const graffle = Graffle.create({ schema, returnMode: 'successData' }) - test(`document.run`, async () => { - expectTypeOf(graffle.document({ x: { query: { id: true } } }).run()).resolves.toEqualTypeOf<{ id: string | null }>() - }) - test(`document.runOrThrow`, async () => { - expectTypeOf(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqualTypeOf<{ id: string | null }>() - }) - test('query.', async () => { - await expectTypeOf(graffle.query.__typename()).resolves.toEqualTypeOf<'Query'>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqualTypeOf<{ __typename: 'Query', id: string|null }>() - }) - describe('result field', () => { - test('document.run',async () => { - await expectTypeOf(graffle.document({x:{query:{result:{$:{case:'Object1'},__typename:true}}}}).run()).resolves.toEqualTypeOf<{result:{__typename: "Object1"} | null}>() - }) - test('query.',async () => { - await expectTypeOf(graffle.query.result({$:{case:'Object1'},__typename:true})).resolves.toEqualTypeOf<{__typename: "Object1"} | null>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ result:{$:{case:'Object1'},__typename:true} })).resolves.toEqualTypeOf<{result:{__typename: "Object1"} | null}>() - }) - describe('without explicit __typename', () => { - test('document',async () => { - const result = graffle.document({x:{query:{resultNonNull:{$:{case:'Object1'}}}}}).run() - await expectTypeOf(result).resolves.toEqualTypeOf<{resultNonNull:{__typename: "Object1"}}>() - }) - test('query.',async () => { - await expectTypeOf(graffle.query.result({$:{case:'Object1'}})).resolves.toEqualTypeOf<{__typename: "Object1"} | null>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ result:{$:{case:'Object1'}} })).resolves.toEqualTypeOf<{result:{__typename: "Object1"} | null}>() - }) - }) - }) - test(`raw`, async () => { - expectTypeOf(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqualTypeOf() - }) -}) - -// dprint-ignore -describe('dataAndErrors', () => { - const graffle = Graffle.create({ schema, returnMode: 'dataAndErrors' }) - test(`document`, async () => { - expectTypeOf(graffle.document({ main: { query: { id: true } } }).run()).resolves.toEqualTypeOf<{ id: string | null } | GraphQLExecutionResultError>() - }) - test(`document runOrThrow`, async () => { - expectTypeOf(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqualTypeOf<{ id: string | null }>() - }) - test('query.', async () => { - await expectTypeOf(graffle.query.__typename()).resolves.toEqualTypeOf<'Query' | GraphQLExecutionResultError>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqualTypeOf<{ __typename: 'Query', id: string|null } | GraphQLExecutionResultError>() - }) - test('query.',async () => { - await expectTypeOf(graffle.query.result({$:{case:'Object1'},__typename:true})).resolves.toEqualTypeOf<{__typename: "Object1"} | {__typename: "ErrorOne"} | {__typename: "ErrorTwo"} | null | GraphQLExecutionResultError>() - }) - test(`raw`, async () => { - expectTypeOf(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqualTypeOf() - }) -}) - -// dprint-ignore -describe('graphql', () => { - const graffle = Graffle.create({ schema, returnMode: 'graphql' }) - test(`document.run`, async () => { - expectTypeOf(graffle.document({ main: { query: { id: true } } }).run()).resolves.toEqualTypeOf>>() - }) - test(`document.runOrThrow`, async () => { - expectTypeOf(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqualTypeOf>>() - }) - test('query.', async () => { - await expectTypeOf(graffle.query.__typename()).resolves.toEqualTypeOf>() - }) - test('query.OrThrow', async () => { - await expectTypeOf(graffle.query.__typenameOrThrow()).resolves.toEqualTypeOf>() - }) - test('query.$batch', async () => { - await expectTypeOf(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqualTypeOf>() - }) - test('query.$batchOrThrow', async () => { - await expectTypeOf(graffle.query.$batchOrThrow({ __typename: true, id: true })).resolves.toEqualTypeOf>() - }) - test('query.',async () => { - await expectTypeOf(graffle.query.result({$:{case:'Object1'},__typename:true})).resolves.toEqualTypeOf>() - }) - test(`raw`, async () => { - expectTypeOf(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqualTypeOf() - }) -}) - -type z = { - __typename: 'ErrorOne' -} | { - __typename: 'ErrorTwo' -} - -type y = Exclude<{ id: string | null } | {} | {} | null, { id: 1 }> -type y2 = Exclude<{ id: string | null } | {} | {} | null, z> diff --git a/src/layers/5_client/client.returnMode.test.ts b/src/layers/5_client/client.returnMode.test.ts deleted file mode 100644 index 125afa739..000000000 --- a/src/layers/5_client/client.returnMode.test.ts +++ /dev/null @@ -1,174 +0,0 @@ -/* eslint-disable */ -import { describe, expect, test } from 'vitest' -import { db } from '../../../tests/_/db.js' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import { schema } from '../../../tests/_/schema/schema.js' -import { __typename } from '../1_Schema/_.js' - -// dprint-ignore -describe('default (data)', () => { - const graffle = Graffle.create({ schema }) - test(`document`, async () => { - await expect(graffle.document({ main: { query: { id: true } } }).run()).resolves.toEqual({ id: db.id }) - }) - test(`document.runOrThrow`, async () => { - await expect(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({ id: db.id }) - }) - test(`document.runOrThrow error`, async () => { - await expect(graffle.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.errorAggregate) - }) - test('raw', async () => { - await expect(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqual({ data: { id: db.id } }) - }) - test('query.', async () => { - await expect(graffle.query.__typename()).resolves.toEqual('Query') - }) - test('query. error', async () => { - await expect(graffle.query.error()).rejects.toMatchObject(db.errorAggregate) - }) - test('query. error orThrow', async () => { - await expect(graffle.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Query', id: db.id }) - }) - test('query.$batchOrThrow error', async () => { - await expect(graffle.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) - }) - test('mutation.', async () => { - await expect(graffle.mutation.__typename()).resolves.toEqual('Mutation') - }) - test('mutation.$batch', async () => { - await expect(graffle.mutation.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Mutation', id: db.id }) - }) -}) - -// dprint-ignore -describe('dataAndErrors', () => { - const graffle = Graffle.create({ schema, returnMode: 'dataAndErrors' }) - test(`document.run`, async () => { - await expect(graffle.document({ main: { query: { id: true } } }).run()).resolves.toEqual({ id: db.id }) - }) - test(`document.runOrThrow`, async () => { - await expect(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({ id: db.id }) - }) - test(`document.runOrThrow error`, async () => { - await expect(graffle.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.errorAggregate) - }) - test('raw', async () => { - await expect(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqual({ data: { id: db.id } }) - }) - test('query.', async () => { - await expect(graffle.query.__typename()).resolves.toEqual('Query') - }) - test('query. error', async () => { - await expect(graffle.query.error()).resolves.toMatchObject(db.errorAggregate) - }) - test('query. error orThrow', async () => { - await expect(graffle.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Query', id: db.id }) - }) - test('query.$batchOrThrow error', async () => { - await expect(graffle.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) - }) - test('mutation.', async () => { - await expect(graffle.mutation.__typename()).resolves.toEqual('Mutation') - }) - test('mutation.$batch', async () => { - await expect(graffle.mutation.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Mutation', id: db.id }) - }) -}) - -// dprint-ignore -describe('successData', () => { - const graffle = Graffle.create({ schema, returnMode: 'successData' }) - test(`document.run`, async () => { - expect(graffle.document({ x: { query: { id: true } } }).run()).resolves.toEqual({ id: db.id }) - }) - test(`document.runOrThrow`, async () => { - expect(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({ id: db.id }) - }) - test('query.', async () => { - await expect(graffle.query.__typename()).resolves.toEqual('Query') - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqual({ __typename: 'Query', id: db.id }) - }) - describe('result field', () => { - test('document.run',async () => { - await expect(graffle.document({x:{query:{result:{$:{case:'Object1'},__typename:true}}}}).run()).resolves.toEqual({result:{__typename: "Object1"}}) - }) - test('query.', async () => { - await expect(graffle.query.result({$:{case:'Object1'},__typename:true})).resolves.toEqual({ __typename: "Object1" }) - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ result:{$:{case:'Object1'},__typename:true} })).resolves.toEqual({result:{__typename: "Object1"}}) - }) - describe('without explicit __typename', () => { - test('document', async () => { - await expect(graffle.document({x:{query:{result:{$:{case:'Object1'}}}}}).run()).resolves.toEqual({result:{__typename: "Object1"}}) - }) - test('query.', async () => { - await expect(graffle.query.result({$:{case:'Object1'}})).resolves.toEqual({__typename: "Object1"}) - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ result:{$:{case:'Object1'}} })).resolves.toEqual({result:{__typename: "Object1"}}) - }) - }) - describe('throws', async () => { - test('document', async () => { - await expect(graffle.document({x:{query:{result:{$:{case:'ErrorOne'}}}}}).run()).rejects.toEqual(db.ErrorOneError) - }) - test('query.', async () => { - await expect(graffle.query.result({$:{case:'ErrorOne'}})).rejects.toEqual(db.ErrorOneError) - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ result:{$:{case:'ErrorOne'}} })).rejects.toEqual(db.ErrorOneError) - }) - // todo result twice, using aliases, check that aggregate error is thrown - }) - }) - test(`raw`, async () => { - expect(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqual({data:{id:db.id}}) - }) -}) - -// dprint-ignore -describe('graphql', () => { - const graffle = Graffle.create({ schema, returnMode: 'graphql' }) - test(`document.run`, async () => { - await expect(graffle.document({ main: { query: { id: true } } }).run()).resolves.toEqual({ data: { id: db.id } }) // dprint-ignore - }) - test(`document.runOrThrow`, async () => { - await expect(graffle.document({ main: { query: { id: true } } }).runOrThrow()).resolves.toEqual({data:{ id: db.id }}) - }) - test(`document.runOrThrow error`, async () => { - await expect(graffle.document({ main: { query: { error: true } } }).runOrThrow()).rejects.toEqual(db.errorAggregate) - }) - test('raw', async () => { - await expect(graffle.raw({ document: 'query main {\nid\n}', operationName: 'main' })).resolves.toEqual({ data: { id: db.id } }) - }) - test('query.', async () => { - await expect(graffle.query.__typename()).resolves.toEqual({ data: { __typename: 'Query' } }) - }) - test('query. error', async () => { - await expect(graffle.query.error()).resolves.toMatchObject({ errors:db.errorAggregate['errors'] }) - }) - test('query. orThrow error', async () => { - await expect(graffle.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) - }) - test('query.$batch', async () => { - await expect(graffle.query.$batch({ __typename: true, id: true })).resolves.toEqual({ data: { __typename: 'Query', id: db.id } }) - }) - test('query.$batchOrThrow error', async () => { - await expect(graffle.query.$batchOrThrow({ error: true })).rejects.toMatchObject(db.errorAggregate) - }) - test('mutation.', async () => { - await expect(graffle.mutation.__typename()).resolves.toEqual({ data: { __typename: 'Mutation' } }) - }) - test('mutation.$batch', async () => { - await expect(graffle.mutation.$batch({ __typename: true, id: true })).resolves.toEqual({ data: { __typename: 'Mutation', id: db.id } }) - }) -}) diff --git a/src/layers/5_client/client.rootTypeMethods.test-d.ts b/src/layers/5_client/client.rootTypeMethods.test-d.ts deleted file mode 100644 index 2896c727d..000000000 --- a/src/layers/5_client/client.rootTypeMethods.test-d.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* eslint-disable */ -import { expectTypeOf, test } from 'vitest' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import * as Schema from '../../../tests/_/schema/schema.js' -import { GraphQLExecutionResultError } from '../../lib/graphql.js' - -const graffle = Graffle.create({ schema: Schema.schema }) - -// dprint-ignore -test(`query`, () => { - // scalar - expectTypeOf(graffle.query.id).toEqualTypeOf<() => Promise>() - expectTypeOf(graffle.query.idNonNull).toEqualTypeOf<() => Promise>() - // 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.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>() - expectTypeOf(graffle.query.unionFooBar({ onFoo: { id: true }})).resolves.toEqualTypeOf<{} | { id: string | null } | null>() - expectTypeOf(graffle.query.interface({ id: true })).resolves.toEqualTypeOf() - expectTypeOf(graffle.query.interface({ onObject1ImplementingInterface: { int: true }})).resolves.toEqualTypeOf<{} | { int: number | null } | null>() - - // @ts-expect-error missing input selection set - graffle.query.dateObject1() - // @ts-expect-error excess properties - const x = graffle.query.dateObject1({ abc: true }) - // @ts-expect-error no directives on root type object fields - graffle.query.dateObject1({ $defer: true }) - // todo @ts-expect-error empty object - // client.query.dateObject1({}) -}) diff --git a/src/layers/5_client/client.rootTypeMethods.test.ts b/src/layers/5_client/client.rootTypeMethods.test.ts deleted file mode 100644 index f4c0e4011..000000000 --- a/src/layers/5_client/client.rootTypeMethods.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { describe, expect, test } from 'vitest' -import { db } from '../../../tests/_/db.js' -import { Graffle } from '../../../tests/_/schema/generated/__.js' -import * as Schema from '../../../tests/_/schema/schema.js' - -const graffle = Graffle.create({ schema: Schema.schema }) - -// dprint-ignore -describe(`query`, () => { - test(`scalar`, async () => { - await expect(graffle.query.id()).resolves.toEqual(db.id1) - }) - test(`scalar arg`, async () => { - await expect(graffle.query.dateArg()).resolves.toEqual(db.date0) - await expect(graffle.query.dateArg({ date: db.date1 })).resolves.toEqual(db.date1) - await expect(graffle.query.dateArgNonNull({ date: db.date1 })).resolves.toEqual(db.date1) - }) - test(`object`, async () => { - await expect(graffle.query.dateObject1({ date1: true })).resolves.toEqual({ date1: db.date0 }) - }) - test(`object with args`, async () => { - await expect(graffle.query.objectWithArgs({ $: { id: `x` }, id: true })).resolves.toEqual({ id: `x` }) - }) - test(`union found`, async () => { - await expect(graffle.query.unionFooBar({ onFoo: { id: true } })).resolves.toEqual({ id: db.id }) - }) - test(`union not found`, async () => { - await expect(graffle.query.unionFooBar({ onBar: { int: true } })).resolves.toEqual({}) - }) - test(`interface fields`, async () => { - await expect(graffle.query.interface({ id: true })).resolves.toEqual({ id: db.id }) - }) - test(`interface instance found`, async () => { - await expect(graffle.query.interface({ onObject1ImplementingInterface: { int: true } })).resolves.toEqual({ int: db.int }) - }) - test(`interface instance not found`, async () => { - await expect(graffle.query.interface({ onObject2ImplementingInterface: { boolean: true } })).resolves.toEqual({}) - }) - describe(`orThrow`, () => { - test(`without error`, async () => { - await expect(graffle.query.objectWithArgsOrThrow({ $: { id: `x` }, id: true })).resolves.toEqual({ id: `x`, __typename: `Object1` }) - }) - test(`with error`, async () => { - await expect(graffle.query.errorOrThrow()).rejects.toMatchObject(db.errorAggregate) - }) - }) -}) diff --git a/src/layers/5_client/client.test.ts b/src/layers/5_client/client.test.ts deleted file mode 100644 index c5754fc2a..000000000 --- a/src/layers/5_client/client.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { describe, expect, test } from 'vitest' -import { Graffle } from '../../entrypoints/alpha/main.js' - -describe(`without schemaIndex only raw is available`, () => { - const schema = new URL(`https://foo.io/api/graphql`) - const graffle = Graffle.create({ schema }) - - test(`unavailable methods`, () => { - // @ts-expect-error - expect(graffle.document).toBeUndefined() - // @ts-expect-error - expect(graffle.query).toBeUndefined() - // @ts-expect-error - expect(graffle.subscription).toBeUndefined() - // @ts-expect-error - expect(graffle.mutation).toBeUndefined() - }) - - test(`available methods`, () => { - expect(graffle.raw).toBeTypeOf(`function`) - expect(graffle.rawOrThrow).toBeTypeOf(`function`) - }) -}) diff --git a/src/layers/5_client/client.ts b/src/layers/5_client/client.ts deleted file mode 100644 index 6ba7ca985..000000000 --- a/src/layers/5_client/client.ts +++ /dev/null @@ -1,447 +0,0 @@ -import { type ExecutionResult, GraphQLSchema } from 'graphql' -import type { Anyware } from '../../lib/anyware/__.js' -import { Errors } from '../../lib/errors/__.js' -import type { SomeExecutionResultWithoutErrors } from '../../lib/graphql.js' -import { isOperationTypeName, operationTypeNameToRootTypeName, type RootTypeName } from '../../lib/graphql.js' -import { isPlainObject } from '../../lib/prelude.js' -import type { URLInput } from '../0_functions/request.js' -import type { BaseInput } from '../0_functions/types.js' -import { Schema } from '../1_Schema/__.js' -import { readMaybeThunk } from '../1_Schema/core/helpers.js' -import type { GlobalRegistry } from '../2_generator/globalRegistry.js' -import type { DocumentObject, GraphQLObjectSelection } from '../3_SelectionSet/encode.js' -import { Core } from '../5_core/__.js' -import { type HookInputEncode } from '../5_core/core.js' -import type { InterfaceRaw } from '../5_core/types.js' -import type { - ApplyInputDefaults, - Config, - ReturnModeType, - ReturnModeTypeBase, - ReturnModeTypeSuccessData, -} from './Config.js' -import type { DocumentFn } from './document.js' -import type { GetRootTypeMethods } from './RootTypeMethods.js' - -export type SchemaInput = URLInput | GraphQLSchema - -export interface RawInput extends BaseInput { - schema: SchemaInput -} - -// todo could list specific errors here -// Anyware entrypoint -// Extension -type GraffleExecutionResult = ExecutionResult | Errors.ContextualError - -export type SelectionSetOrIndicator = 0 | 1 | boolean | object - -export type SelectionSetOrArgs = object - -export interface Context { - retry: undefined | Anyware.Extension2 - extensions: Anyware.Extension2[] - config: Config -} - -export type TypedContext = Context & { - schemaIndex: Schema.Index -} - -const isTypedContext = (context: Context): context is TypedContext => `schemaIndex` in context - -// todo no config needed? -export type ClientRaw<_$Config extends Config> = { - raw: (input: Omit) => Promise - rawOrThrow: (input: Omit) => Promise -} - -// dprint-ignore -export type Client<$Index extends Schema.Index | null, $Config extends Config> = - & ClientRaw<$Config> - & ( - $Index extends Schema.Index - ? ClientTyped<$Index, $Config> - : {} // eslint-disable-line - ) - & { - extend: (extension: Anyware.Extension2) => Client<$Index, $Config> - retry: (extension: Anyware.Extension2) => Client<$Index, $Config> - } - -export type ClientTyped<$Index extends Schema.Index, $Config extends Config> = - & { - document: DocumentFn<$Config, $Index> - } - & GetRootTypeMethods<$Config, $Index> - -export type InputRaw = { - schema: SchemaInput - // todo condition on if schema is NOT GraphQLSchema - headers?: HeadersInit -} - -export type InputPrefilled<$Schema extends GlobalRegistry.SchemaList> = $Schema extends any ? { - returnMode?: - | ReturnModeTypeBase - | (GlobalRegistry.HasSchemaErrors<$Schema> extends true ? ReturnModeTypeSuccessData : never) - } & InputRaw - : never - -export type CreatePrefilled = <$Name extends GlobalRegistry.SchemaNames>(name: $Name, schemaIndex: Schema.Index) => < - // eslint-disable-next-line - // @ts-ignore passes after generation - $Input extends InputPrefilled, ->( - input: $Input, -) => Client< - // eslint-disable-next-line - // @ts-ignore passes after generation - GlobalRegistry.GetSchemaIndexOrDefault<$Name>, - ApplyInputDefaults<{ returnMode: $Input['returnMode'] }> -> - -export const createPrefilled: CreatePrefilled = (name, schemaIndex) => { - // eslint-disable-next-line - // @ts-ignore passes after generation - return (input) => create({ ...input, name, schemaIndex }) as any -} - -export type Input<$Schema extends GlobalRegistry.SchemaList> = { - /** - * Used internally. - * - * When custom scalars are being used, this runtime schema is used to - * encode/decode them before/after your application sends/receives them. - * - * When using root type field methods, this runtime schema is used to assist how arguments on scalars versus objects - * are constructed into the sent GraphQL document. - */ - readonly schemaIndex?: Schema.Index | null - /** - * The schema to use. - * - * TODO why don't we infer this from the runtime schemaIndex? - * - * @defaultValue 'default' - */ - name?: $Schema['index']['name'] - // todo way to hide Relay input pattern of nested input - // elideInputKey: true, -} & InputPrefilled<$Schema> - -// dprint-ignore -type Create = < - $Input extends Input, ->( - input: $Input, -) => - Client< - // eslint-disable-next-line - // @ts-ignore passes after generation - $Input['schemaIndex'] extends Schema.Index - // v-- TypeScript does not understand this type satisfies the Index constraint. - // v It does after generation. - ? GlobalRegistry.GetSchemaIndexOrDefault<$Input['name']> - : null, - ApplyInputDefaults<{ returnMode: $Input['returnMode'] }> - > - -export const create: Create = ( - input_, -) => createInternal(input_, { extensions: [], retry: undefined }) - -interface CreateState { - retry?: Anyware.Extension2 - extensions: Anyware.Extension2[] -} - -export const createInternal = ( - input_: Input, - state: CreateState, -) => { - // eslint-disable-next-line - // @ts-ignore passes after generation - const input = input_ as Readonly> - - /** - * @remarks Without generation the type of returnMode can be `ReturnModeTypeBase` which leads - * TS to think some errors below are invalid checks because of a non-present member. - * However our implementation here needs to be generic and support all return modes - * so we force cast it as such. - */ - const returnMode = input.returnMode ?? `data` as ReturnModeType - - const executeRootType = async ( - context: TypedContext, - rootTypeName: RootTypeName, - rootTypeSelectionSet: GraphQLObjectSelection, - ) => { - const transport = input.schema instanceof GraphQLSchema ? `memory` : `http` - const interface_ = `typed` - const initialInput = { - interface: interface_, - transport, - selection: rootTypeSelectionSet, - rootTypeName, - schema: input.schema, - context: { - config: context.config, - transport, - interface: interface_, - schemaIndex: context.schemaIndex, - }, - } as HookInputEncode - return await run(context, initialInput) - } - - const executeRootTypeField = async ( - context: TypedContext, - rootTypeName: RootTypeName, - rootTypeFieldName: string, - argsOrSelectionSet?: object, - ) => { - const selectedType = readMaybeThunk(context.schemaIndex.Root[rootTypeName]?.fields[rootTypeFieldName]?.type) - const selectedNamedType = readMaybeThunk( - // eslint-disable-next-line - // @ts-ignore excess depth error - Schema.Output.unwrapToNamed(selectedType), - ) as Schema.Output.Named - if (!selectedNamedType) throw new Error(`${rootTypeName} field not found: ${String(rootTypeFieldName)}`) // eslint-disable-line - // @ts-expect-error fixme - const isSelectedTypeScalarOrTypeName = selectedNamedType.kind === `Scalar` || selectedNamedType.kind === `typename` // todo fix type here, its valid - const isFieldHasArgs = Boolean(context.schemaIndex.Root[rootTypeName]?.fields[rootTypeFieldName]?.args) - // We should only need to add __typename for result type fields, but the return handler doesn't yet know how to look beyond a plain object type so we have to add all those cases here. - const needsTypenameAdded = context.config.returnMode === `successData` - && (selectedNamedType.kind === `Object` || selectedNamedType.kind === `Interface` - || selectedNamedType.kind === `Union`) - const rootTypeFieldSelectionSet = isSelectedTypeScalarOrTypeName - ? isFieldHasArgs && argsOrSelectionSet ? { $: argsOrSelectionSet } : true - : needsTypenameAdded - ? { ...argsOrSelectionSet, __typename: true } - : argsOrSelectionSet - - const result = await executeRootType(context, rootTypeName, { - [rootTypeFieldName]: rootTypeFieldSelectionSet, - } as GraphQLObjectSelection) - if (result instanceof Error) return result - return context.config.returnMode === `data` || context.config.returnMode === `dataAndErrors` - || context.config.returnMode === `successData` - // @ts-expect-error - ? result[rootTypeFieldName] - : result - } - - const createRootTypeMethods = (context: TypedContext, rootTypeName: RootTypeName) => { - return new Proxy({}, { - get: (_, key) => { - if (typeof key === `symbol`) throw new Error(`Symbols not supported.`) - - // todo We need to document that in order for this to 100% work none of the user's root type fields can end with "OrThrow". - const isOrThrow = key.endsWith(`OrThrow`) - const contextWithReturnModeSet = isOrThrow ? applyOrThrowToContext(context) : context - - if (key.startsWith(`$batch`)) { - return async (selectionSetOrIndicator: SelectionSetOrIndicator) => - executeRootType(contextWithReturnModeSet, rootTypeName, selectionSetOrIndicator as GraphQLObjectSelection) - } else { - const fieldName = isOrThrow ? key.slice(0, -7) : key - return (selectionSetOrArgs: SelectionSetOrArgs) => - executeRootTypeField(contextWithReturnModeSet, rootTypeName, fieldName, selectionSetOrArgs) - } - }, - }) - } - - const context: Context = { - retry: state.retry, - extensions: state.extensions, - config: { - returnMode, - }, - } - - const run = async (context: Context, initialInput: HookInputEncode) => { - const result = await Core.anyware.run({ - initialInput, - retryingExtension: context.retry, - extensions: context.extensions, - }) as GraffleExecutionResult - return handleReturn(context, result) - } - - const runRaw = async (context: Context, rawInput: RawInput) => { - const interface_: InterfaceRaw = `raw` - const transport = input.schema instanceof GraphQLSchema ? `memory` : `http` - const initialInput = { - interface: interface_, - transport, - document: rawInput.document, - schema: input.schema, - context: { - config: context.config, - }, - } as HookInputEncode - return await run(context, initialInput) - } - - // @ts-expect-error ignoreme - const client: Client = { - raw: async (rawInput: RawInput) => { - const contextWithReturnModeSet = updateContextConfig(context, { returnMode: `graphql` }) - return await runRaw(contextWithReturnModeSet, rawInput) - }, - rawOrThrow: async ( - rawInput: RawInput, - ) => { - const contextWithReturnModeSet = updateContextConfig(context, { returnMode: `graphqlSuccess` }) - return await runRaw(contextWithReturnModeSet, rawInput) - }, - extend: (extension: Anyware.Extension2) => { - // todo test that adding extensions returns a copy of client - return createInternal(input, { extensions: [...state.extensions, extension] }) - }, - retry: (extension: Anyware.Extension2) => { - return createInternal(input, { ...state, retry: extension }) - }, - } - - // todo extract this into constructor "create typed client" - if (input.schemaIndex) { - const typedContext: TypedContext = { - ...context, - schemaIndex: input.schemaIndex, - } - - Object.assign(client, { - document: (documentObject: DocumentObject) => { - const hasMultipleOperations = Object.keys(documentObject).length > 1 - - const processInput = (maybeOperationName: string) => { - if (!maybeOperationName && hasMultipleOperations) { - throw { - errors: [new Error(`Must provide operation name if query contains multiple operations.`)], - } - } - if (maybeOperationName && !(maybeOperationName in documentObject)) { - throw { - errors: [new Error(`Unknown operation named "${maybeOperationName}".`)], - } - } - const operationName = maybeOperationName ? maybeOperationName : Object.keys(documentObject)[0]! - const rootTypeSelection = documentObject[operationName] - if (!rootTypeSelection) throw new Error(`Operation with name ${operationName} not found.`) - const operationTypeName = Object.keys(rootTypeSelection)[0] - if (!isOperationTypeName(operationTypeName)) throw new Error(`Operation has no selection set.`) - // @ts-expect-error - const selection = rootTypeSelection[operationTypeName] as GraphQLObjectSelection - return { - rootTypeName: operationTypeNameToRootTypeName[operationTypeName], - selection, - } - } - - return { - run: async (maybeOperationName: string) => { - const { selection, rootTypeName } = processInput(maybeOperationName) - return await executeRootType(typedContext, rootTypeName, selection) - }, - runOrThrow: async (maybeOperationName: string) => { - const { selection, rootTypeName } = processInput(maybeOperationName) - return await executeRootType( - applyOrThrowToContext(typedContext), - rootTypeName, - selection, - ) - }, - } - }, - query: createRootTypeMethods(typedContext, `Query`), - mutation: createRootTypeMethods(typedContext, `Mutation`), - // todo - // subscription: async () => {}, - }) - } - - return client -} - -const handleReturn = ( - context: Context, - result: GraffleExecutionResult, -) => { - switch (context.config.returnMode) { - case `graphqlSuccess`: - case `dataAndErrors`: - case `successData`: - case `data`: { - if (result instanceof Error || (result.errors && result.errors.length > 0)) { - const error = result instanceof Error ? result : (new Errors.ContextualAggregateError( - `One or more errors in the execution result.`, - {}, - result.errors!, - )) - if ( - context.config.returnMode === `data` || context.config.returnMode === `successData` - || context.config.returnMode === `graphqlSuccess` - ) throw error - return error - } - - if (isTypedContext(context)) { - if (context.config.returnMode === `successData`) { - if (!isPlainObject(result.data)) throw new Error(`Expected data to be an object.`) - const schemaErrors = Object.entries(result.data).map(([rootFieldName, rootFieldValue]) => { - // todo this check would be nice but it doesn't account for aliases right now. To achieve this we would - // need to have the selection set available to use and then do a costly analysis for all fields that were aliases. - // So costly that we would probably instead want to create an index of them on the initial encoding step and - // then make available down stream. Also, note, here, the hardcoding of Query, needs to be any root type. - // const isResultField = Boolean(schemaIndex.error.rootResultFields.Query[rootFieldName]) - // if (!isResultField) return null - // if (!isPlainObject(rootFieldValue)) return new Error(`Expected result field to be an object.`) - if (!isPlainObject(rootFieldValue)) return null - const __typename = rootFieldValue[`__typename`] - if (typeof __typename !== `string`) throw new Error(`Expected __typename to be selected and a string.`) - const isErrorObject = Boolean( - context.schemaIndex.error.objectsTypename[__typename], - ) - if (!isErrorObject) return null - // todo extract message - return new Error(`Failure on field ${rootFieldName}: ${__typename}`) - }).filter((_): _ is Error => _ !== null) - - if (schemaErrors.length === 1) throw schemaErrors[0]! - if (schemaErrors.length > 0) { - const error = new Errors.ContextualAggregateError( - `Two or more schema errors in the execution result.`, - {}, - schemaErrors, - ) - throw error - } - } - } - - if (context.config.returnMode === `graphqlSuccess`) { - return result - } - - return result.data - } - default: { - return result - } - } -} - -const applyOrThrowToContext = <$Context extends Context>(context: $Context): $Context => { - if (context.config.returnMode === `successData` || context.config.returnMode === `graphqlSuccess`) { - return context - } - const newMode = context.config.returnMode === `graphql` ? `graphqlSuccess` : `successData` - return updateContextConfig(context, { returnMode: newMode }) -} - -const updateContextConfig = <$Context extends Context>(context: $Context, config: Config): $Context => { - return { ...context, config: { ...context.config, ...config } } -} diff --git a/src/layers/5_client/document.ts b/src/layers/5_client/document.ts deleted file mode 100644 index 33d278296..000000000 --- a/src/layers/5_client/document.ts +++ /dev/null @@ -1,94 +0,0 @@ -import type { MergeExclusive, NonEmptyObject } from 'type-fest' -import { operationTypeNameToRootTypeName } from '../../lib/graphql.js' -import type { 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' -import type { Context, DocumentObject } from '../3_SelectionSet/encode.js' -import type { ResultSet } from '../4_ResultSet/__.js' -import type { AugmentRootTypeSelectionWithTypename, Config, OrThrowifyConfig, ReturnModeRootType } from './Config.js' - -// dprint-ignore -export type DocumentFn<$Config extends Config, $Index extends Schema.Index> = -<$Document extends Document<$Index>>(document: ValidateDocumentOperationNames>) => - { - run: < - $Name extends keyof $Document & string, - $Params extends (IsMultipleKeys<$Document> extends true ? [name: $Name] : ([] | [name: $Name | undefined])), - >(...params: $Params) => Promise< - ReturnModeRootType<$Config, $Index, ResultSet.Root, $Index, GetRootType<$Document[$Name]>>> - > - runOrThrow: < - $Name extends keyof $Document & string, - $Params extends (IsMultipleKeys<$Document> extends true ? [name: $Name] : ([] | [name: $Name | undefined])), - >(...params: $Params) => Promise< - ReturnModeRootType, $Index, ResultSet.Root, $Index, $Document[$Name]>, $Index, GetRootType<$Document[$Name]>>> - > - } - -export const toDocumentString = ( - context: Context, - document: DocumentObject, -) => { - return Object.entries(document).map(([operationName, operationDocument]) => { - const operationType = `query` in operationDocument ? `query` : `mutation` - const rootType = operationTypeNameToRootTypeName[operationType] - const rootTypeDocument = (operationDocument as any)[operationType] as SelectionSet.Print.GraphQLObjectSelection // eslint-disable-line - - const schemaRootType = context.schemaIndex[`Root`][rootType] - if (!schemaRootType) throw new Error(`Schema has no ${rootType} root type`) - - const documentString = SelectionSet.Print.rootTypeSelectionSet( - context, - schemaRootType, - rootTypeDocument, - operationName, - ) - return documentString - }).join(`\n\n`) -} - -// dprint-ignore -export type Document<$Index extends Schema.Index> = - { - [name: string]: - $Index['Root']['Query'] extends null ? { mutation: SelectionSet.Root<$Index, 'Mutation'> } : - $Index['Root']['Mutation'] extends null ? { query: SelectionSet.Root<$Index, 'Query'> } : - MergeExclusive< - { - query: SelectionSet.Root<$Index, 'Query'> - }, - { - mutation: SelectionSet.Root<$Index, 'Mutation'> - } - > - } - -// dprint-ignore -export type ValidateDocumentOperationNames<$Document> = - // This initial condition checks that the document is not already in an error state. - // Namely from for example { x: { mutation: { ... }}} where the schema has no mutations. - // Which is statically caught by the `Document` type. In that case the document type variable - // no longer functions per normal with regards to keyof utility, not returning exact keys of the object - // but instead this more general union. Not totally clear _why_, but we have tests covering this... - string | number extends keyof $Document - ? $Document - : keyof { [K in keyof $Document & string as Schema.Named.NameParse extends never ? K : never]: K } extends never - ? $Document - : TSError<'ValidateDocumentOperationNames', `One or more Invalid operation name in document: ${keyof { [K in keyof $Document & string as Schema.Named.NameParse extends never ? K : never]: K }}`> - -// dprint-ignore -type GetRootTypeSelection< - $Config extends Config, - $Index extends Schema.Index, - $Selection extends object -> = - $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 - -// dprint-ignore -type GetRootType<$Selection extends object> = - $Selection extends {query:any} ? 'Query' : - $Selection extends {mutation:any} ? 'Mutation' : - never diff --git a/src/layers/5_client/types.ts b/src/layers/5_client/types.ts deleted file mode 100644 index b0ac627df..000000000 --- a/src/layers/5_client/types.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { DocumentNode } from 'graphql' - -export type DocumentInput = DocumentNode | string - -export type OperationNameInput = string diff --git a/src/layers/5_core/__.ts b/src/layers/5_core/__.ts deleted file mode 100644 index 994058c36..000000000 --- a/src/layers/5_core/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Core from './core.js' diff --git a/src/layers/5_core/core.ts b/src/layers/5_core/core.ts deleted file mode 100644 index ca5e6a870..000000000 --- a/src/layers/5_core/core.ts +++ /dev/null @@ -1,258 +0,0 @@ -import type { DocumentNode, ExecutionResult, GraphQLSchema } from 'graphql' -import { print } from 'graphql' -import { Anyware } from '../../lib/anyware/__.js' -import { type StandardScalarVariables } from '../../lib/graphql.js' -import { parseExecutionResult } from '../../lib/graphqlHTTP.js' -import { CONTENT_TYPE_GQL } from '../../lib/http.js' -import { casesExhausted } from '../../lib/prelude.js' -import { execute } from '../0_functions/execute.js' -import type { Schema } from '../1_Schema/__.js' -import { SelectionSet } from '../3_SelectionSet/__.js' -import type { GraphQLObjectSelection } from '../3_SelectionSet/encode.js' -import * as Result from '../4_ResultSet/customScalars.js' -import type { - ContextInterfaceRaw, - ContextInterfaceTyped, - InterfaceRaw, - InterfaceTyped, - TransportHttp, - TransportMemory, -} from './types.js' - -const getRootIndexOrThrow = (context: ContextInterfaceTyped, rootTypeName: string) => { - // @ts-expect-error - // eslint-disable-next-line - const rootIndex = context.schemaIndex.Root[rootTypeName] - if (!rootIndex) throw new Error(`Root type not found: ${rootTypeName}`) - return rootIndex -} - -// eslint-disable-next-line -type InterfaceInput = - | ({ - interface: InterfaceTyped - context: ContextInterfaceTyped - rootTypeName: Schema.RootTypeName - } & A) - | ({ - interface: InterfaceRaw - context: ContextInterfaceRaw - } & B) - -// eslint-disable-next-line -type TransportInput = - | ({ - transport: TransportHttp - } & A) - | ({ - transport: TransportMemory - } & B) - -export const hookNamesOrderedBySequence = [`encode`, `pack`, `exchange`, `unpack`, `decode`] as const - -export type HookSequence = typeof hookNamesOrderedBySequence - -export type HookInputEncode = - & InterfaceInput<{ selection: GraphQLObjectSelection }, { document: string | DocumentNode }> - & TransportInput<{ schema: string | URL }, { schema: GraphQLSchema }> - -export type HookInputPack = - & { - document: string | DocumentNode - variables: StandardScalarVariables - operationName?: string - } - & InterfaceInput - & TransportInput<{ url: string | URL; headers?: HeadersInit }, { schema: GraphQLSchema }> - -export type ExchangeInputHook = - & InterfaceInput - & TransportInput< - { request: Request }, - { - schema: GraphQLSchema - document: string | DocumentNode - variables: StandardScalarVariables - operationName?: string - } - > - -export type HookInputUnpack = - & InterfaceInput - & TransportInput< - { response: Response }, - { - result: ExecutionResult - } - > - -export type HookInputDecode = - & { result: ExecutionResult } - & InterfaceInput - -export type Hooks = { - encode: HookInputEncode - pack: HookInputPack - exchange: ExchangeInputHook - unpack: HookInputUnpack - decode: HookInputDecode -} - -export const anyware = Anyware.create({ - hookNamesOrderedBySequence, - hooks: { - encode: ( - input, - ) => { - // console.log(`encode:1`) - let document: string | DocumentNode - switch (input.interface) { - case `raw`: { - document = input.document - break - } - case `typed`: { - // todo turn inputs into variables - document = SelectionSet.Print.rootTypeSelectionSet( - input.context, - getRootIndexOrThrow(input.context, input.rootTypeName), - input.selection, - ) - break - } - default: - throw casesExhausted(input) - } - - // console.log(`encode:2`) - switch (input.transport) { - case `http`: { - return { - ...input, - transport: input.transport, - url: input.schema, - document, - variables: {}, - // operationName: '', - } - } - case `memory`: { - return { - ...input, - transport: input.transport, - schema: input.schema, - document, - variables: {}, - // operationName: '', - } - } - } - }, - pack: (input) => { - // console.log(`pack:1`) - const documentPrinted = typeof input.document === `string` - ? input.document - : print(input.document) - - switch (input.transport) { - case `http`: { - const body = { - query: documentPrinted, - variables: input.variables, - operationName: input.operationName, - } - - const bodyEncoded = JSON.stringify(body) - - const requestConfig = new Request(input.url, { - method: `POST`, - headers: new Headers({ - 'accept': CONTENT_TYPE_GQL, - ...Object.fromEntries(new Headers(input.headers).entries()), - }), - body: bodyEncoded, - }) - - return { - ...input, - request: requestConfig, - } - } - case `memory`: { - return { - ...input, - } - } - default: - throw casesExhausted(input) - } - }, - exchange: async (input) => { - switch (input.transport) { - case `http`: { - const response = await fetch(input.request) - return { - ...input, - response, - } - } - case `memory`: { - const result = await execute({ - schema: input.schema, - document: input.document, - variables: input.variables, - operationName: input.operationName, - }) - return { - ...input, - result, - } - } - default: - throw casesExhausted(input) - } - }, - unpack: async (input) => { - switch (input.transport) { - case `http`: { - const json = await input.response.json() as object - const result = parseExecutionResult(json) - return { - ...input, - result, - } - } - case `memory`: { - return { - ...input, - result: input.result, - } - } - default: - throw casesExhausted(input) - } - }, - decode: (input) => { - switch (input.interface) { - // todo this depends on the return mode - case `raw`: { - return input.result - } - case `typed`: { - // todo optimize - // 1. Generate a map of possible custom scalar paths (tree structure) - // 2. When traversing the result, skip keys that are not in the map - const dataDecoded = Result.decode(getRootIndexOrThrow(input.context, input.rootTypeName), input.result.data) - return { ...input.result, data: dataDecoded } - } - default: - throw casesExhausted(input) - } - }, - }, - // todo expose return handling as part of the pipeline? - // would be nice but alone would not yield type safe return handling - // still, while figuring the type story out, might be a useful escape hatch for some cases... -}) - -export type Core = (typeof anyware)['core'] diff --git a/src/layers/5_core/types.ts b/src/layers/5_core/types.ts deleted file mode 100644 index 611279959..000000000 --- a/src/layers/5_core/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type { Schema } from '../1_Schema/__.js' -import type { Config } from '../5_client/Config.js' - -export type Transport = TransportMemory | TransportHttp - -export type TransportMemory = 'memory' - -export type TransportHttp = 'http' - -export type Interface = InterfaceRaw | InterfaceTyped - -export type InterfaceRaw = 'raw' - -export type InterfaceTyped = 'typed' - -type BaseContext = { - config: Config -} - -export type ContextInterfaceTyped = - & BaseContext - & ({ schemaIndex: Schema.Index }) - -export type ContextInterfaceRaw = BaseContext diff --git a/src/layers/5_select/select.test-d.ts b/src/layers/5_select/select.test-d.ts deleted file mode 100644 index efa5bf5fa..000000000 --- a/src/layers/5_select/select.test-d.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { describe, expect, expectTypeOf, it, test } from 'vitest' -import type { Index } from '../../../tests/_/schema/schema.js' -import type { SelectionSet } from '../3_SelectionSet/__.js' -import { create } from './select.js' - -describe(`select`, () => { - const select = create(`default`) - - it(`returns the input for any method name`, () => { - const s = select as any // eslint-disable-line - expect(s.anything(1)).toEqual(1) // eslint-disable-line - }) - - it(`has type safe methods`, () => { - // @ts-expect-error ID issue - type $Parameters = Parameters - expectTypeOf<$Parameters>().toEqualTypeOf<[SelectionSet.Object]>() - expectTypeOf(select.Bar({ int: true })).toEqualTypeOf<{ int: true }>() - }) -}) - -describe(`create`, () => { - const select = create(`QueryOnly`) - test(`does not have root types if not in schema`, () => { - // fine - select.Query - // @ts-expect-error no mutation in schema - select.Mutation - // @ts-expect-error no mutation in schema - select.Subscription - }) -}) diff --git a/src/layers/5_select/select.test.ts b/src/layers/5_select/select.test.ts deleted file mode 100644 index 909cf330a..000000000 --- a/src/layers/5_select/select.test.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { expect, test } from 'vitest' -import { create } from './select.js' - -const select = create(`default`) - -test(`returns the input for any method name`, () => { - const s = select as any // eslint-disable-line - expect(s.anything(1)).toEqual(1) // eslint-disable-line -}) - -test(`has type safe methods`, () => { - expect(select.Bar({ ___: { $defer: true, int: true } })).toEqual({ ___: { $defer: true, int: true } }) -}) diff --git a/src/layers/5_select/select.ts b/src/layers/5_select/select.ts deleted file mode 100644 index f5f16bc64..000000000 --- a/src/layers/5_select/select.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { RootTypeName } from '../../lib/graphql.js' -import type { Exact } from '../../lib/prelude.js' -import type { Schema } from '../1_Schema/__.js' -import type { GlobalRegistry } from '../2_generator/globalRegistry.js' -import type { SelectionSet } from '../3_SelectionSet/__.js' - -// dprint-ignore -type TypeSelectionSets<$Index extends Schema.Index> = -& { - [$RootTypeName in RootTypeName as $RootTypeName extends keyof $Index['Root'] ? $Index['Root'][$RootTypeName] extends null ? never : $RootTypeName:never ]: - <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Root<$Index, $RootTypeName>>) => - $SelectionSet - } -& { - [$Name in keyof $Index['objects']]: - <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Object<$Index['objects'][$Name], $Index>>) => - $SelectionSet - } -& { - [$Name in keyof $Index['unions']]: - <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Union<$Index['unions'][$Name], $Index>>) => - $SelectionSet - } -& { - [$Name in keyof Schema.Index['interfaces']]: - <$SelectionSet extends object>(selectionSet: Exact<$SelectionSet, SelectionSet.Interface<$Index['interfaces'][$Name], $Index>>) => - $SelectionSet - } - -type Create = <$Name extends GlobalRegistry.SchemaNames>( - name: $Name, - // eslint-disable-next-line - // @ts-ignore passes after generation -) => TypeSelectionSets> - -export const create: Create = (_name) => { - return idProxy as any -} - -const idProxy = new Proxy({}, { - get: () => (value: unknown) => value, -}) - -// eslint-disable-next-line -// @ts-ignore generated types -export const select: TypeSelectionSets = idProxy diff --git a/tests/_/customScalarCodecs.ts b/tests/_/customScalarCodecs.ts deleted file mode 100644 index 114649350..000000000 --- a/tests/_/customScalarCodecs.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Scalar } from '../../src/layers/1_Schema/__.js' -import type { Codec } from '../../src/layers/1_Schema/Hybrid/types/Scalar/codec.js' - -export const Date = Scalar.scalar<'Date', Codec>(`Date`, { - encode: value => value.toISOString(), - decode: value => new globalThis.Date(value), -}) - -export type Date = typeof Date diff --git a/tests/_/db.ts b/tests/_/db.ts deleted file mode 100644 index 16de60b8d..000000000 --- a/tests/_/db.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { GraphQLError } from 'graphql' -import { Errors } from '../../src/lib/errors/__.js' - -const date0 = new Date(0) - -// const error = { errors: [{ message: `Something went wrong.` }] } -const errorAggregate = new Errors.ContextualAggregateError(`One or more errors in the execution result.`, {}, [ - new GraphQLError(`Something went wrong.`), -]) - -const ErrorOneError = new Error(`Failure on field result: ErrorOne`) -const ErrorTwoError = new Error(`Failure on field result: ErrorTwo`) - -const id = `abc` - -const int = 123 - -const string = `hi` - -const float = 123.456 - -const boolean = true - -const Object1 = { - string, - int, - float, - boolean, - id, -} - -const Foo = { - id, -} - -export const db = { - lowerCaseObject: { - id, - }, - lowerCaseObject2: { - int, - }, - Interface: { id }, - ABCEnum: `A`, - ErrorOne: { message: `errorOne`, infoId: id }, - ErrorTwo: { message: `errorOne`, infoInt: int }, - ErrorOneError, - ErrorTwoError, - int, - id, - id1: id, - string, - date0: new Date(0), - date1: new Date(1), - Foo, - Bar: { - int, - }, - Object1, - ObjectNested: { - id, - nested: Object1, - }, - ObjectUnion: { - fooBarUnion: Foo, - }, - DateInterface1: { - date1: date0, - }, - errorAggregate, -} as const diff --git a/tests/_/helpers.ts b/tests/_/helpers.ts deleted file mode 100644 index e4df0b67e..000000000 --- a/tests/_/helpers.ts +++ /dev/null @@ -1,23 +0,0 @@ -import type { Mock } from 'vitest' -import { test as testBase, vi } from 'vitest' -import { CONTENT_TYPE_JSON } from '../../src/lib/http.js' - -export const createResponse = (body: object) => - new Response(JSON.stringify(body), { status: 200, headers: { 'content-type': CONTENT_TYPE_JSON } }) - -interface Fixtures { - fetch: Mock -} - -export const test = testBase.extend({ - // @ts-expect-error https://github.com/vitest-dev/vitest/discussions/5710 - // eslint-disable-next-line - fetch: async ({}, use) => { - const fetch = globalThis.fetch - const fetchMock = vi.fn() - globalThis.fetch = fetchMock - // eslint-disable-next-line - await use(fetchMock) - globalThis.fetch = fetch - }, -}) diff --git a/tests/_/schema/generated/Client.ts b/tests/_/schema/generated/Client.ts deleted file mode 100644 index 44c2d2398..000000000 --- a/tests/_/schema/generated/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(`default`, $Index) diff --git a/tests/_/schema/generated/Error.ts b/tests/_/schema/generated/Error.ts deleted file mode 100644 index 116c46f0b..000000000 --- a/tests/_/schema/generated/Error.ts +++ /dev/null @@ -1,17 +0,0 @@ -type Include = Exclude> - -type ObjectWithTypeName = { __typename: string } - -const ErrorObjectsTypeNameSelectedEnum = { - ErrorOne: { __typename: 'ErrorOne' }, - ErrorTwo: { __typename: 'ErrorTwo' }, -} as const - -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/tests/_/schema/generated/Global.ts b/tests/_/schema/generated/Global.ts deleted file mode 100644 index 986787721..000000000 --- a/tests/_/schema/generated/Global.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Index } from './Index.js' - -import type * as CustomScalar from '../../customScalarCodecs.js' - -declare global { - export namespace GraphQLRequestTypes { - export interface Schemas { - default: { - index: Index - customScalars: { - Date: CustomScalar.Date - } - featureOptions: { - schemaErrors: true - } - } - } - } -} diff --git a/tests/_/schema/generated/Index.ts b/tests/_/schema/generated/Index.ts deleted file mode 100644 index 62afc2c45..000000000 --- a/tests/_/schema/generated/Index.ts +++ /dev/null @@ -1,56 +0,0 @@ -/* eslint-disable */ - -import type * as Schema from './SchemaBuildtime.js' - -export interface Index { - name: 'default' - Root: { - Query: Schema.Root.Query - Mutation: Schema.Root.Mutation - Subscription: null - } - objects: { - Bar: Schema.Object.Bar - DateObject1: Schema.Object.DateObject1 - DateObject2: Schema.Object.DateObject2 - ErrorOne: Schema.Object.ErrorOne - ErrorTwo: Schema.Object.ErrorTwo - Foo: Schema.Object.Foo - Object1: Schema.Object.Object1 - Object1ImplementingInterface: Schema.Object.Object1ImplementingInterface - Object2ImplementingInterface: Schema.Object.Object2ImplementingInterface - ObjectNested: Schema.Object.ObjectNested - ObjectUnion: Schema.Object.ObjectUnion - lowerCaseObject: Schema.Object.lowerCaseObject - lowerCaseObject2: Schema.Object.lowerCaseObject2 - } - unions: { - DateUnion: Schema.Union.DateUnion - FooBarUnion: Schema.Union.FooBarUnion - Result: Schema.Union.Result - lowerCaseUnion: Schema.Union.lowerCaseUnion - } - interfaces: { - DateInterface1: Schema.Interface.DateInterface1 - Error: Schema.Interface.Error - Interface: Schema.Interface.Interface - } - error: { - objects: { - ErrorOne: Schema.Object.ErrorOne - ErrorTwo: Schema.Object.ErrorTwo - } - objectsTypename: { - ErrorOne: { __typename: 'ErrorOne' } - ErrorTwo: { __typename: 'ErrorTwo' } - } - rootResultFields: { - Query: { - result: 'result' - resultNonNull: 'resultNonNull' - } - Mutation: {} - Subscription: {} - } - } -} diff --git a/tests/_/schema/generated/Scalar.ts b/tests/_/schema/generated/Scalar.ts deleted file mode 100644 index 2e11dcd1c..000000000 --- a/tests/_/schema/generated/Scalar.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from '../../../../src/layers/1_Schema/Hybrid/types/Scalar/Scalar.js' -export * from '../../customScalarCodecs.js' diff --git a/tests/_/schema/generated/SchemaBuildtime.ts b/tests/_/schema/generated/SchemaBuildtime.ts deleted file mode 100644 index f2666f3d6..000000000 --- a/tests/_/schema/generated/SchemaBuildtime.ts +++ /dev/null @@ -1,332 +0,0 @@ -import type * as $ from '../../../../src/entrypoints/alpha/schema.js' -import type * as $Scalar from './Scalar.ts' - -// ------------------------------------------------------------ // -// Root // -// ------------------------------------------------------------ // - -export namespace Root { - export type Mutation = $.Object$2<'Mutation', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - idNonNull: $.Field<$Scalar.ID, null> - }> - - export type Query = $.Object$2<'Query', { - InputObjectNested: $.Field< - $.Output.Nullable<$Scalar.ID>, - $.Args<{ - input: $.Input.Nullable - }> - > - InputObjectNestedNonNull: $.Field< - $.Output.Nullable<$Scalar.ID>, - $.Args<{ - input: InputObject.InputObjectNestedNonNull - }> - > - /** - * Query enum field documentation. - */ - abcEnum: $.Field<$.Output.Nullable, null> - date: $.Field<$.Output.Nullable<$Scalar.Date>, null> - dateArg: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.Nullable<$Scalar.Date> - }> - > - dateArgInputObject: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - input: $.Input.Nullable - }> - > - dateArgList: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.Nullable<$.Input.List<$Scalar.Date>> - }> - > - dateArgNonNull: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $Scalar.Date - }> - > - dateArgNonNullList: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.List<$.Input.Nullable<$Scalar.Date>> - }> - > - dateArgNonNullListNonNull: $.Field< - $.Output.Nullable<$Scalar.Date>, - $.Args<{ - date: $.Input.List<$Scalar.Date> - }> - > - dateInterface1: $.Field<$.Output.Nullable, null> - dateList: $.Field<$.Output.Nullable<$.Output.List<$Scalar.Date>>, null> - dateListNonNull: $.Field<$.Output.List<$Scalar.Date>, null> - dateNonNull: $.Field<$Scalar.Date, null> - dateObject1: $.Field<$.Output.Nullable, null> - dateUnion: $.Field<$.Output.Nullable, null> - error: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - case: $.Input.Nullable<$Scalar.String> - }> - > - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - idNonNull: $.Field<$Scalar.ID, null> - interface: $.Field<$.Output.Nullable, null> - interfaceNonNull: $.Field - interfaceWithArgs: $.Field< - $.Output.Nullable, - $.Args<{ - id: $Scalar.ID - }> - > - listInt: $.Field<$.Output.Nullable<$.Output.List<$.Output.Nullable<$Scalar.Int>>>, null> - listIntNonNull: $.Field<$.Output.List<$Scalar.Int>, null> - listListInt: $.Field< - $.Output.Nullable<$.Output.List<$.Output.Nullable<$.Output.List<$.Output.Nullable<$Scalar.Int>>>>>, - null - > - listListIntNonNull: $.Field<$.Output.List<$.Output.List<$Scalar.Int>>, null> - lowerCaseUnion: $.Field<$.Output.Nullable, null> - object: $.Field<$.Output.Nullable, null> - objectList: $.Field<$.Output.Nullable<$.Output.List>, null> - objectListNonNull: $.Field<$.Output.List, null> - objectNested: $.Field<$.Output.Nullable, null> - objectNonNull: $.Field - 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> - }> - > - result: $.Field< - $.Output.Nullable, - $.Args<{ - case: Enum.Case - }> - > - resultNonNull: $.Field< - Union.Result, - $.Args<{ - case: $.Input.Nullable - }> - > - string: $.Field<$.Output.Nullable<$Scalar.String>, null> - stringWithArgEnum: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - ABCEnum: $.Input.Nullable - }> - > - stringWithArgInputObject: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - input: $.Input.Nullable - }> - > - stringWithArgInputObjectRequired: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - input: InputObject.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> - }> - > - stringWithListArg: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - ints: $.Input.Nullable<$.Input.List<$.Input.Nullable<$Scalar.Int>>> - }> - > - stringWithListArgRequired: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - ints: $.Input.List<$Scalar.Int> - }> - > - stringWithRequiredArg: $.Field< - $.Output.Nullable<$Scalar.String>, - $.Args<{ - string: $Scalar.String - }> - > - unionFooBar: $.Field<$.Output.Nullable, null> - unionFooBarNonNull: $.Field - unionFooBarWithArgs: $.Field< - $.Output.Nullable, - $.Args<{ - id: $.Input.Nullable<$Scalar.ID> - }> - > - unionObject: $.Field<$.Output.Nullable, null> - unionObjectNonNull: $.Field - }> -} - -// ------------------------------------------------------------ // -// Enum // -// ------------------------------------------------------------ // - -export namespace Enum { - /** - * Enum documentation. - * - * Members - * "A" - (DEPRECATED: Enum value A is deprecated.) - * "B" - Enum B member documentation. - * "C" - (DEPRECATED: Enum value C is deprecated.) - */ - export type ABCEnum = $.Enum<'ABCEnum', ['A', 'B', 'C']> - - export type Case = $.Enum<'Case', ['ErrorOne', 'ErrorTwo', 'Object1']> -} - -// ------------------------------------------------------------ // -// InputObject // -// ------------------------------------------------------------ // - -export namespace InputObject { - export type InputObject = $.InputObject<'InputObject', { - date: $.Input.Nullable<$Scalar.Date> - dateRequired: $Scalar.Date - id: $.Input.Nullable<$Scalar.ID> - idRequired: $Scalar.ID - }> - - export type InputObjectNested = $.InputObject<'InputObjectNested', { - InputObject: $.Input.Nullable - }> - - export type InputObjectNestedNonNull = $.InputObject<'InputObjectNestedNonNull', { - InputObject: InputObject.InputObject - }> -} - -// ------------------------------------------------------------ // -// Interface // -// ------------------------------------------------------------ // - -export namespace Interface { - export type DateInterface1 = $.Interface<'DateInterface1', { - date1: $.Field<$.Output.Nullable<$Scalar.Date>, null> - }, [Object.DateObject1]> - - export type Error = $.Interface<'Error', { - message: $.Field<$Scalar.String, null> - }, [Object.ErrorOne, Object.ErrorTwo]> - - export type Interface = $.Interface<'Interface', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }, [Object.Object1ImplementingInterface, Object.Object2ImplementingInterface]> -} - -// ------------------------------------------------------------ // -// Object // -// ------------------------------------------------------------ // - -export namespace Object { - export type Bar = $.Object$2<'Bar', { - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - }> - - export type DateObject1 = $.Object$2<'DateObject1', { - date1: $.Field<$.Output.Nullable<$Scalar.Date>, null> - }> - - export type DateObject2 = $.Object$2<'DateObject2', { - date2: $.Field<$.Output.Nullable<$Scalar.Date>, null> - }> - - export type ErrorOne = $.Object$2<'ErrorOne', { - infoId: $.Field<$.Output.Nullable<$Scalar.ID>, null> - message: $.Field<$Scalar.String, null> - }> - - export type ErrorTwo = $.Object$2<'ErrorTwo', { - infoInt: $.Field<$.Output.Nullable<$Scalar.Int>, null> - message: $.Field<$Scalar.String, null> - }> - - /** - * Object documentation. - */ - export type Foo = $.Object$2<'Foo', { - /** - * Field documentation. - * - * @deprecated Field a is deprecated. - */ - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }> - - export type Object1 = $.Object$2<'Object1', { - boolean: $.Field<$.Output.Nullable<$Scalar.Boolean>, null> - float: $.Field<$.Output.Nullable<$Scalar.Float>, null> - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - string: $.Field<$.Output.Nullable<$Scalar.String>, null> - }> - - export type Object1ImplementingInterface = $.Object$2<'Object1ImplementingInterface', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - }> - - export type Object2ImplementingInterface = $.Object$2<'Object2ImplementingInterface', { - boolean: $.Field<$.Output.Nullable<$Scalar.Boolean>, null> - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }> - - export type ObjectNested = $.Object$2<'ObjectNested', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - object: $.Field<$.Output.Nullable, null> - }> - - export type ObjectUnion = $.Object$2<'ObjectUnion', { - fooBarUnion: $.Field<$.Output.Nullable, null> - }> - - export type lowerCaseObject = $.Object$2<'lowerCaseObject', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - }> - - export type lowerCaseObject2 = $.Object$2<'lowerCaseObject2', { - int: $.Field<$.Output.Nullable<$Scalar.Int>, null> - }> -} - -// ------------------------------------------------------------ // -// Union // -// ------------------------------------------------------------ // - -export namespace Union { - export type DateUnion = $.Union<'DateUnion', [Object.DateObject1, Object.DateObject2]> - - /** - * Union documentation. - */ - export type FooBarUnion = $.Union<'FooBarUnion', [Object.Bar, Object.Foo]> - - export type Result = $.Union<'Result', [Object.ErrorOne, Object.ErrorTwo, Object.Object1]> - - export type lowerCaseUnion = $.Union<'lowerCaseUnion', [Object.lowerCaseObject, Object.lowerCaseObject2]> -} diff --git a/tests/_/schema/generated/SchemaRuntime.ts b/tests/_/schema/generated/SchemaRuntime.ts deleted file mode 100644 index 876cb23f9..000000000 --- a/tests/_/schema/generated/SchemaRuntime.ts +++ /dev/null @@ -1,257 +0,0 @@ -/* eslint-disable */ - -import * as $ from '../../../../src/entrypoints/alpha/schema.js' -import * as $Scalar from './Scalar.js' - -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), -}) - -export const InputObjectNested = $.InputObject(`InputObjectNested`, { - InputObject: $.Input.field(() => $.Input.Nullable(InputObject)), -}) - -export const InputObjectNestedNonNull = $.InputObject(`InputObjectNestedNonNull`, { - InputObject: $.Input.field(() => InputObject), -}) - -// @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`, { - int: $.field($.Output.Nullable($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. -export const DateObject1 = $.Object$(`DateObject1`, { - date1: $.field($.Output.Nullable($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. -export const DateObject2 = $.Object$(`DateObject2`, { - date2: $.field($.Output.Nullable($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. -export const ErrorOne = $.Object$(`ErrorOne`, { - infoId: $.field($.Output.Nullable($Scalar.ID)), - message: $.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 ErrorTwo = $.Object$(`ErrorTwo`, { - infoInt: $.field($.Output.Nullable($Scalar.Int)), - message: $.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 Foo = $.Object$(`Foo`, { - 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. -export const Object1 = $.Object$(`Object1`, { - boolean: $.field($.Output.Nullable($Scalar.Boolean)), - float: $.field($.Output.Nullable($Scalar.Float)), - id: $.field($.Output.Nullable($Scalar.ID)), - int: $.field($.Output.Nullable($Scalar.Int)), - string: $.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. -export const Object1ImplementingInterface = $.Object$(`Object1ImplementingInterface`, { - id: $.field($.Output.Nullable($Scalar.ID)), - int: $.field($.Output.Nullable($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. -export const Object2ImplementingInterface = $.Object$(`Object2ImplementingInterface`, { - boolean: $.field($.Output.Nullable($Scalar.Boolean)), - 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. -export const ObjectNested = $.Object$(`ObjectNested`, { - id: $.field($.Output.Nullable($Scalar.ID)), - 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`, { - fooBarUnion: $.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. -export const lowerCaseObject = $.Object$(`lowerCaseObject`, { - 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. -export const lowerCaseObject2 = $.Object$(`lowerCaseObject2`, { - int: $.field($.Output.Nullable($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. -export const DateUnion = $.Union(`DateUnion`, [DateObject1, DateObject2]) - -// @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 FooBarUnion = $.Union(`FooBarUnion`, [Bar, Foo]) - -// @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 Result = $.Union(`Result`, [ErrorOne, ErrorTwo, 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 lowerCaseUnion = $.Union(`lowerCaseUnion`, [lowerCaseObject, lowerCaseObject2]) - -export const DateInterface1 = $.Interface(`DateInterface1`, { date1: $.field($.Output.Nullable($Scalar.Date)) }, [ - DateObject1, -]) -export const Error = $.Interface(`Error`, { message: $.field($Scalar.String) }, [ErrorOne, ErrorTwo]) -export const Interface = $.Interface(`Interface`, { id: $.field($.Output.Nullable($Scalar.ID)) }, [ - Object1ImplementingInterface, - Object2ImplementingInterface, -]) - -// @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)), - 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. -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 })), - 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 })), - dateArgNonNullList: $.field( - $.Output.Nullable($Scalar.Date), - $.Args({ date: $.Input.List($.Input.Nullable($Scalar.Date)) }), - ), - dateArgNonNullListNonNull: $.field($.Output.Nullable($Scalar.Date), $.Args({ date: $.Input.List($Scalar.Date) })), - dateInterface1: $.field($.Output.Nullable(() => DateInterface1)), - dateList: $.field($.Output.Nullable($.Output.List($Scalar.Date))), - dateListNonNull: $.field($.Output.List($Scalar.Date)), - dateNonNull: $.field($Scalar.Date), - dateObject1: $.field($.Output.Nullable(() => DateObject1)), - 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), - interface: $.field($.Output.Nullable(() => Interface)), - interfaceNonNull: $.field(() => Interface), - 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)), - listListInt: $.field( - $.Output.Nullable($.Output.List($.Output.Nullable($.Output.List($.Output.Nullable($Scalar.Int))))), - ), - listListIntNonNull: $.field($.Output.List($.Output.List($Scalar.Int))), - lowerCaseUnion: $.field($.Output.Nullable(() => lowerCaseUnion)), - object: $.field($.Output.Nullable(() => Object1)), - objectList: $.field($.Output.Nullable($.Output.List(() => Object1))), - objectListNonNull: $.field($.Output.List(() => Object1)), - objectNested: $.field($.Output.Nullable(() => ObjectNested)), - objectNonNull: $.field(() => Object1), - 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), - }), - ), - result: $.field($.Output.Nullable(() => Result), $.Args({ case: Case })), - 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) })), - stringWithArgInputObject: $.field( - $.Output.Nullable($Scalar.String), - $.Args({ input: $.Input.Nullable(InputObject) }), - ), - 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), - }), - ), - stringWithListArg: $.field( - $.Output.Nullable($Scalar.String), - $.Args({ ints: $.Input.Nullable($.Input.List($.Input.Nullable($Scalar.Int))) }), - ), - stringWithListArgRequired: $.field($.Output.Nullable($Scalar.String), $.Args({ ints: $.Input.List($Scalar.Int) })), - stringWithRequiredArg: $.field($.Output.Nullable($Scalar.String), $.Args({ string: $Scalar.String })), - unionFooBar: $.field($.Output.Nullable(() => FooBarUnion)), - unionFooBarNonNull: $.field(() => FooBarUnion), - unionFooBarWithArgs: $.field($.Output.Nullable(() => FooBarUnion), $.Args({ id: $.Input.Nullable($Scalar.ID) })), - unionObject: $.field($.Output.Nullable(() => ObjectUnion)), - unionObjectNonNull: $.field(() => ObjectUnion), -}) - -export const $Index = { - name: 'default' as const, - Root: { - Query, - Mutation, - Subscription: null, - }, - objects: { - Bar, - DateObject1, - DateObject2, - ErrorOne, - ErrorTwo, - Foo, - Object1, - Object1ImplementingInterface, - Object2ImplementingInterface, - ObjectNested, - ObjectUnion, - lowerCaseObject, - lowerCaseObject2, - }, - unions: { - DateUnion, - FooBarUnion, - Result, - lowerCaseUnion, - }, - interfaces: { - DateInterface1, - Error, - Interface, - }, - error: { - objects: { - ErrorOne, - ErrorTwo, - }, - objectsTypename: { - ErrorOne: { __typename: 'ErrorOne' }, - ErrorTwo: { __typename: 'ErrorTwo' }, - }, - rootResultFields: { - Query: { - result: 'result' as const, - resultNonNull: 'resultNonNull' as const, - }, - Mutation: {}, - Subscription: {}, - }, - }, -} diff --git a/tests/_/schema/generated/Select.ts b/tests/_/schema/generated/Select.ts deleted file mode 100644 index 6216e0471..000000000 --- a/tests/_/schema/generated/Select.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { ResultSet, SelectionSet } from '../../../../src/entrypoints/alpha/schema.js' -import { 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 Mutation<$SelectionSet extends SelectionSet.Root> = ResultSet.Root< - $SelectionSet, - Index, - 'Mutation' - > - - export type Query<$SelectionSet extends SelectionSet.Root> = ResultSet.Root< - $SelectionSet, - Index, - 'Query' - > - - // Object Types - // ------------ - - export type Bar<$SelectionSet extends SelectionSet.Object> = ResultSet.Object$< - $SelectionSet, - Index['objects']['Bar'], - Index - > - - export type DateObject1<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['DateObject1'], Index> - - export type DateObject2<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['DateObject2'], Index> - - export type ErrorOne<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ErrorOne'], Index> - - export type ErrorTwo<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ErrorTwo'], Index> - - export type Foo<$SelectionSet extends SelectionSet.Object> = ResultSet.Object$< - $SelectionSet, - Index['objects']['Foo'], - Index - > - - export type Object1<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['Object1'], Index> - - export type Object1ImplementingInterface< - $SelectionSet extends SelectionSet.Object, - > = ResultSet.Object$<$SelectionSet, Index['objects']['Object1ImplementingInterface'], Index> - - export type Object2ImplementingInterface< - $SelectionSet extends SelectionSet.Object, - > = ResultSet.Object$<$SelectionSet, Index['objects']['Object2ImplementingInterface'], Index> - - export type ObjectNested<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ObjectNested'], Index> - - export type ObjectUnion<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['ObjectUnion'], Index> - - export type lowerCaseObject<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['lowerCaseObject'], Index> - - export type lowerCaseObject2<$SelectionSet extends SelectionSet.Object> = - ResultSet.Object$<$SelectionSet, Index['objects']['lowerCaseObject2'], Index> - - // Union Types - // ----------- - - export type DateUnion<$SelectionSet extends SelectionSet.Union> = - ResultSet.Union<$SelectionSet, Index['unions']['DateUnion'], Index> - - export type FooBarUnion<$SelectionSet extends SelectionSet.Union> = - ResultSet.Union<$SelectionSet, Index['unions']['FooBarUnion'], Index> - - export type Result<$SelectionSet extends SelectionSet.Union> = ResultSet.Union< - $SelectionSet, - Index['unions']['Result'], - Index - > - - export type lowerCaseUnion<$SelectionSet extends SelectionSet.Union> = - ResultSet.Union<$SelectionSet, Index['unions']['lowerCaseUnion'], Index> - - // Interface Types - // --------------- - - export type DateInterface1< - $SelectionSet extends SelectionSet.Interface, - > = ResultSet.Interface<$SelectionSet, Index['interfaces']['DateInterface1'], Index> - - export type Error<$SelectionSet extends SelectionSet.Interface> = - ResultSet.Interface<$SelectionSet, Index['interfaces']['Error'], Index> - - export type Interface<$SelectionSet extends SelectionSet.Interface> = - ResultSet.Interface<$SelectionSet, Index['interfaces']['Interface'], Index> -} diff --git a/tests/_/schema/generated/_.ts b/tests/_/schema/generated/_.ts deleted file mode 100644 index 5e2498a39..000000000 --- a/tests/_/schema/generated/_.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/tests/_/schema/generated/__.ts b/tests/_/schema/generated/__.ts deleted file mode 100644 index 4fba9ada3..000000000 --- a/tests/_/schema/generated/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as Graffle from './_.js' diff --git a/tests/_/schema/schema.graphql b/tests/_/schema/schema.graphql deleted file mode 100644 index 8804a5d3b..000000000 --- a/tests/_/schema/schema.graphql +++ /dev/null @@ -1,176 +0,0 @@ -"""Enum documentation.""" -enum ABCEnum { - A @deprecated(reason: "Enum value A is deprecated.") - - """Enum B member documentation.""" - B - C @deprecated(reason: "Enum value C is deprecated.") -} - -type Bar { - int: Int -} - -enum Case { - ErrorOne - ErrorTwo - Object1 -} - -""" -A date-time string at UTC, such as 2007-12-03T10:15:30Z, compliant with the `date-time` format outlined in section 5.6 of the RFC 3339 profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.This scalar is serialized to a string in ISO 8601 format and parsed from a string in ISO 8601 format. -""" -scalar Date - -interface DateInterface1 { - date1: Date -} - -type DateObject1 implements DateInterface1 { - date1: Date -} - -type DateObject2 { - date2: Date -} - -union DateUnion = DateObject1 | DateObject2 - -interface Error { - message: String! -} - -type ErrorOne implements Error { - infoId: ID - message: String! -} - -type ErrorTwo implements Error { - infoInt: Int - message: String! -} - -"""Object documentation.""" -type Foo { - """Field documentation.""" - id: ID @deprecated(reason: "Field a is deprecated.") -} - -"""Union documentation.""" -union FooBarUnion = Bar | Foo - -input InputObject { - date: Date - dateRequired: Date! - id: ID - idRequired: ID! -} - -input InputObjectNested { - InputObject: InputObject -} - -input InputObjectNestedNonNull { - InputObject: InputObject! -} - -interface Interface { - id: ID -} - -type Mutation { - id: ID - idNonNull: ID! -} - -type Object1 { - boolean: Boolean - float: Float - id: ID - int: Int - string: String -} - -type Object1ImplementingInterface implements Interface { - id: ID - int: Int -} - -type Object2ImplementingInterface implements Interface { - boolean: Boolean - id: ID -} - -type ObjectNested { - id: ID - object: Object1 -} - -type ObjectUnion { - fooBarUnion: FooBarUnion -} - -type Query { - InputObjectNested(input: InputObjectNested): ID - InputObjectNestedNonNull(input: InputObjectNestedNonNull!): ID - - """Query enum field documentation.""" - abcEnum: ABCEnum - date: Date - dateArg(date: Date): Date - dateArgInputObject(input: InputObject): Date - dateArgList(date: [Date!]): Date - dateArgNonNull(date: Date!): Date - dateArgNonNullList(date: [Date]!): Date - dateArgNonNullListNonNull(date: [Date!]!): Date - dateInterface1: DateInterface1 - dateList: [Date!] - dateListNonNull: [Date!]! - dateNonNull: Date! - dateObject1: DateObject1 - dateUnion: DateUnion - error(case: String): String - id: ID - idNonNull: ID! - interface: Interface - interfaceNonNull: Interface! - interfaceWithArgs(id: ID!): Interface - listInt: [Int] - listIntNonNull: [Int!]! - listListInt: [[Int]] - listListIntNonNull: [[Int!]!]! - lowerCaseUnion: lowerCaseUnion - object: Object1 - objectList: [Object1!] - objectListNonNull: [Object1!]! - objectNested: ObjectNested - objectNonNull: Object1! - objectWithArgs(boolean: Boolean, float: Float, id: ID, int: Int, string: String): Object1 - result(case: Case!): Result - resultNonNull(case: Case): Result! - string: String - stringWithArgEnum(ABCEnum: ABCEnum): String - stringWithArgInputObject(input: InputObject): String - stringWithArgInputObjectRequired(input: InputObject!): String - stringWithArgs(boolean: Boolean, float: Float, id: ID, int: Int, string: String): String - stringWithListArg(ints: [Int]): String - stringWithListArgRequired(ints: [Int!]!): String - stringWithRequiredArg(string: String!): String - unionFooBar: FooBarUnion - unionFooBarNonNull: FooBarUnion! - unionFooBarWithArgs(id: ID): FooBarUnion - unionObject: ObjectUnion - unionObjectNonNull: ObjectUnion! -} - -union Result = ErrorOne | ErrorTwo | Object1 - -type lowerCaseObject { - id: ID -} - -type lowerCaseObject2 { - int: Int -} - -union lowerCaseUnion = lowerCaseObject | lowerCaseObject2 \ No newline at end of file diff --git a/tests/_/schema/schema.ts b/tests/_/schema/schema.ts deleted file mode 100644 index 36427987f..000000000 --- a/tests/_/schema/schema.ts +++ /dev/null @@ -1,438 +0,0 @@ -// TODO test case for recursive input objects -// -import SchemaBuilder from '@pothos/core' -import SimpleObjectsPlugin from '@pothos/plugin-simple-objects' -import { DateTimeISOResolver } from 'graphql-scalars' -import { db } from '../db.js' - -const builder = new SchemaBuilder<{ - DefaultFieldNullability: true - Scalars: { - Date: { - Input: Date - Output: Date - } - } -}>({ - defaultFieldNullability: true, - plugins: [SimpleObjectsPlugin], -}) - -builder.addScalarType(`Date`, DateTimeISOResolver, {}) - -const DateInterface1 = builder.simpleInterface(`DateInterface1`, { - fields: t => ({ - date1: t.field({ type: `Date` }), - }), - resolveType: value => { - if (`date1` in value) return `DateObject1` - throw new Error(`Cannot resolve type`) - }, -}) -const DateObject1 = builder.simpleObject(`DateObject1`, { - interfaces: [DateInterface1], - fields: t => ({ - date1: t.field({ type: `Date` }), - }), -}) - -const DateObject2 = builder.simpleObject(`DateObject2`, { - fields: t => ({ - date2: t.field({ type: `Date` }), - }), -}) - -const Object1 = builder.simpleObject(`Object1`, { - fields: t => ({ - string: t.string(), - int: t.int(), - float: t.float(), - boolean: t.boolean(), - id: t.id(), - }), -}) - -const Foo = builder.simpleObject(`Foo`, { - description: `Object documentation.`, - fields: t => ({ - id: t.id({ description: `Field documentation.`, deprecationReason: `Field a is deprecated.` }), - }), -}) - -const Bar = builder.simpleObject(`Bar`, { - fields: t => ({ - int: t.int(), - }), -}) - -const FooBarUnion = builder.unionType(`FooBarUnion`, { - types: [Foo, Bar], - description: `Union documentation.`, - resolveType: value => { - return `int` in value ? `Bar` : `Foo` - }, -}) - -builder.mutationType({ - fields: t => ({ - id: t.id({ resolve: () => db.id1 }), - idNonNull: t.id({ nullable: false, resolve: () => db.id1 }), - }), -}) - -const Interface = builder.simpleInterface(`Interface`, { - fields: t => ({ - id: t.id(), - }), - resolveType: value => { - return `boolean` in value ? `Object2ImplementingInterface` : `Object1ImplementingInterface` - }, -}) - -builder.simpleObject(`Object1ImplementingInterface`, { - interfaces: [Interface], - fields: t => ({ - int: t.int(), - }), -}) - -builder.simpleObject(`Object2ImplementingInterface`, { - interfaces: [Interface], - fields: t => ({ - boolean: t.boolean(), - }), -}) - -const ErrorInterface = builder.simpleInterface(`Error`, { - fields: t => ({ - message: t.string({ nullable: false }), - }), -}) - -const ErrorOne = builder.simpleObject(`ErrorOne`, { - interfaces: [ErrorInterface], - fields: t => ({ - infoId: t.id(), - }), -}) - -const ErrorTwo = builder.simpleObject(`ErrorTwo`, { - interfaces: [ErrorInterface], - fields: t => ({ - infoInt: t.int(), - }), -}) - -const Result = builder.unionType(`Result`, { - types: [Object1, ErrorOne, ErrorTwo], - resolveType: (data) => { - return `infoId` in data ? `ErrorOne` : `infoInt` in data ? `ErrorTwo` : `Object1` - }, -}) - -const ResultCase = builder.enumType(`Case`, { values: [`Object1`, `ErrorOne`, `ErrorTwo`] as const }) - -const DateUnion = builder.unionType(`DateUnion`, { - types: [DateObject1, DateObject2], - resolveType: value => { - return `date1` in value ? `DateObject1` : `DateObject2` - }, -}) - -const InputObject = builder.inputType(`InputObject`, { - fields: t => ({ - id: t.id(), - idRequired: t.id({ required: true }), - date: t.field({ type: `Date` }), - dateRequired: t.field({ type: `Date`, required: true }), - }), -}) - -const InputObjectNested = builder.inputType(`InputObjectNested`, { - fields: t => ({ - InputObject: t.field({ type: InputObject }), - }), -}) - -const InputObjectNestedNonNull = builder.inputType(`InputObjectNestedNonNull`, { - fields: t => ({ - InputObject: t.field({ type: InputObject, required: true }), - }), -}) - -const ABCEnum = builder.enumType(`ABCEnum`, { - description: `Enum documentation.`, - values: { - A: { - deprecationReason: `Enum value A is deprecated.`, - }, - B: { - description: `Enum B member documentation.`, - }, - C: { - deprecationReason: `Enum value C is deprecated.`, - }, - }, -}) - -const ObjectNested = builder.simpleObject(`ObjectNested`, { - fields: t => ({ - id: t.field({ type: `ID` }), - object: t.field({ type: Object1 }), - }), -}) - -const lowerCaseObject = builder.simpleObject(`lowerCaseObject`, { - fields: t => ({ - id: t.id(), - }), -}) -const lowerCaseObject2 = builder.simpleObject(`lowerCaseObject2`, { - fields: t => ({ - int: t.int(), - }), -}) -const lowerCaseUnion = builder.unionType(`lowerCaseUnion`, { - types: [lowerCaseObject, lowerCaseObject2], - resolveType: value => { - return `int` in value ? `lowerCaseObject2` : `lowerCaseObject` - }, -}) -const ObjectUnion = builder.simpleObject(`ObjectUnion`, { - fields: t => ({ - fooBarUnion: t.field({ type: FooBarUnion }), - }), -}) - -builder.queryType({ - fields: t => ({ - // error - error: t.string({ - args: { case: t.arg.string({ required: false }) }, - resolve: () => { - throw new Error(`Something went wrong.`) - }, - }), - // Custom Scalar - date: t.field({ type: `Date`, resolve: () => db.date0 }), - dateNonNull: t.field({ nullable: false, type: `Date`, resolve: () => db.date0 }), - dateList: t.field({ - type: t.listRef(`Date`), - resolve: () => [db.date0, db.date1], - }), - dateObject1: t.field({ type: DateObject1, resolve: () => ({ date1: db.date0 }) }), - dateUnion: t.field({ type: DateUnion, resolve: () => ({ date1: db.date0 }) }), - dateInterface1: t.field({ - type: DateInterface1, - resolve: () => ({ date1: db.date0 }), - }), - dateListNonNull: t.field({ - nullable: false, - type: t.listRef(`Date`, { nullable: false }), - resolve: () => [db.date0, db.date1], - }), - dateArg: t.field({ - type: `Date`, - args: { date: t.arg({ type: `Date` }) }, - resolve: (_, args) => args.date ?? db.date0, - }), - dateArgNonNull: t.field({ - type: `Date`, - args: { date: t.arg({ required: true, type: `Date` }) }, - resolve: (_, args) => args.date, - }), - dateArgList: t.field({ - type: `Date`, - args: { date: t.arg({ type: t.arg.listRef(`Date`) }) }, - resolve: (_, args) => args.date?.[0] ?? db.date0, - }), - dateArgNonNullList: t.field({ - type: `Date`, - args: { date: t.arg({ required: true, type: t.arg.listRef(`Date`, { required: false }) }) }, - resolve: (_, args) => args.date[0] ?? db.date0, - }), - dateArgNonNullListNonNull: t.field({ - type: `Date`, - args: { date: t.arg({ required: true, type: t.arg.listRef(`Date`, { required: true }) }) }, - resolve: (_, args) => args.date[0] ?? db.date0, - }), - dateArgInputObject: t.field({ - type: `Date`, - args: { input: t.arg({ type: InputObject }) }, - resolve: (_, args) => args.input?.date ?? db.date0, - }), - // Input Object - // Note: It is important that the type `InputObjectNested` is defined before `InputObject` in the generated runtime schema. - // This is to force the case of needing a thunk, to make sure our tests for it are actually testing the case. - InputObjectNested: t.field({ - type: `ID`, - args: { input: t.arg({ type: InputObjectNested }) }, - resolve: (_, args) => args.input?.InputObject?.id ?? db.id1, - }), - InputObjectNestedNonNull: t.field({ - type: `ID`, - args: { input: t.arg({ type: InputObjectNestedNonNull, required: true }) }, - resolve: (_, args) => args.input.InputObject.idRequired, - }), - // Scalar - id: t.id({ resolve: () => db.id1 }), - idNonNull: t.id({ nullable: false, resolve: () => db.id1 }), - string: t.string({ resolve: () => db.string }), - stringWithRequiredArg: t.field({ - type: `String`, - args: { string: t.arg.string({ required: true }) }, - resolve: (_, args) => args.string, - }), - stringWithArgs: t.field({ - type: `String`, - args: { - string: t.arg.string(), - int: t.arg.int(), - float: t.arg.float(), - boolean: t.arg.boolean(), - id: t.arg.id(), - }, - resolve: (_, args) => { - return JSON.stringify(args) - }, - }), - stringWithArgEnum: t.field({ - type: `String`, - args: { ABCEnum: t.arg({ type: ABCEnum }) }, - resolve: (_, args) => args.ABCEnum, - }), - stringWithListArg: t.field({ - type: `String`, - args: { ints: t.arg({ type: t.arg.listRef(`Int`, { required: false }) }) }, - resolve: (_, args) => JSON.stringify(args), - }), - stringWithListArgRequired: t.field({ - type: `String`, - args: { ints: t.arg({ type: t.arg.listRef(`Int`), required: true }) }, - resolve: (_, args) => JSON.stringify(args), - }), - stringWithArgInputObject: t.field({ - type: `String`, - args: { input: t.arg({ type: InputObject }) }, - resolve: (_, args) => JSON.stringify(args), - }), - stringWithArgInputObjectRequired: t.field({ - type: `String`, - args: { input: t.arg({ type: InputObject, required: true }) }, - resolve: (_, args) => JSON.stringify(args), - }), - // List Scalar - listListIntNonNull: t.field({ - nullable: false, - type: t.listRef(t.listRef(`Int`, { nullable: false }), { nullable: false }), - resolve: () => [[1], [2]], - }), - listListInt: t.field({ - type: t.listRef(t.listRef(`Int`, { nullable: true }), { nullable: true }), - resolve: () => [[1], [2]], - }), - listInt: t.field({ - type: t.listRef(`Int`, { nullable: true }), - resolve: () => [1, 2], - }), - listIntNonNull: t.field({ - nullable: false, - type: t.listRef(`Int`, { nullable: false }), - resolve: () => [1, 2], - }), - // Enum - abcEnum: t.field({ - type: ABCEnum, - description: `Query enum field documentation.`, - resolve: () => db.ABCEnum, - }), - // Object - object: t.field({ - type: Object1, - resolve: () => db.Object1, - }), - objectNonNull: t.field({ - type: Object1, - nullable: false, - resolve: () => db.Object1, - }), - objectNested: t.field({ - type: ObjectNested, - resolve: () => db.ObjectNested, - }), - objectWithArgs: t.field({ - args: { - string: t.arg.string(), - int: t.arg.int(), - float: t.arg.float(), - boolean: t.arg.boolean(), - id: t.arg.id(), - }, - type: Object1, - resolve: (_, args) => ({ ...db.Object1, ...args }), - }), - // Object List - objectList: t.field({ - type: t.listRef(Object1), - resolve: () => [db.Object1], - }), - objectListNonNull: t.field({ - nullable: false, - type: t.listRef(Object1, { nullable: false }), - resolve: () => [db.Object1], - }), - // Interface - interface: t.field({ - type: Interface, - resolve: () => ({ - ...db.Interface, - int: db.int, - }), - }), - interfaceNonNull: t.field({ - type: Interface, - nullable: false, - resolve: () => ({ - ...db.Interface, - int: db.int, - }), - }), - interfaceWithArgs: t.field({ - type: Interface, - args: { id: t.arg.id({ required: true }) }, - resolve: (_, args) => ({ id: args.id }), - }), - // Union - lowerCaseUnion: t.field({ type: lowerCaseUnion, resolve: () => db.lowerCaseObject }), - unionFooBar: t.field({ type: FooBarUnion, resolve: () => db.Foo }), - unionFooBarNonNull: t.field({ type: FooBarUnion, nullable: false, resolve: () => db.Foo }), - unionFooBarWithArgs: t.field({ - args: { id: t.arg.id() }, - type: FooBarUnion, - resolve: () => db.Foo, - }), - unionObject: t.field({ type: ObjectUnion, resolve: () => db.ObjectUnion }), - unionObjectNonNull: t.field({ type: ObjectUnion, nullable: false, resolve: () => db.ObjectUnion }), - // Result - result: t.field({ - args: { case: t.arg({ type: ResultCase, required: true }) }, - type: Result, - resolve: (_, args) => { - return db[args.case] - }, - }), - resultNonNull: t.field({ - args: { case: t.arg({ type: ResultCase, required: false }) }, - type: Result, - nullable: false, - resolve: (_, args) => { - return args.case ? db[args.case] : db.Object1 - }, - }), - }), -}) - -export const schema = builder.toSchema({ sortSchema: true }) - -export type { Index } from './generated/Index.js' -export { $Index } from './generated/SchemaRuntime.js' diff --git a/tests/_/schemaGenerate.ts b/tests/_/schemaGenerate.ts deleted file mode 100644 index b45c9d980..000000000 --- a/tests/_/schemaGenerate.ts +++ /dev/null @@ -1,51 +0,0 @@ -import type { GraphQLSchema } from 'graphql' -import { printSchema } from 'graphql' -import fs from 'node:fs/promises' -import { dirname, join } from 'node:path' -import { generateFiles } from '../../src/layers/2_generator/files.js' -import type { OptionsInput } from '../../src/layers/2_generator/generateCode.js' -import { schema as schema } from './schema/schema.js' -import { schema as schemaMutationOnly } from './schemaMutationOnly/schema.js' -import { schema as schemaQueryOnly } from './schemaQueryOnly/schema.js' - -const generate = async ( - input: { schema: GraphQLSchema; outputSchemaPath: string; name?: string; options?: OptionsInput }, -) => { - const sourceDirPath = dirname(input.outputSchemaPath) - await fs.writeFile( - input.outputSchemaPath, - printSchema(input.schema), - ) - await generateFiles({ - sourceDirPath, - sourceCustomScalarCodecsFilePath: join(`./tests/_/customScalarCodecs.ts`), - outputDirPath: join(sourceDirPath, `/generated`), - code: { - libraryPaths: { - client: `../../../../src/entrypoints/alpha/client.js`, - schema: `../../../../src/entrypoints/alpha/schema.js`, - scalars: `../../../../src/layers/1_Schema/Hybrid/types/Scalar/Scalar.js`, - }, - }, - name: input.name, - ...input.options, - }) -} - -await generate({ - name: `QueryOnly`, - schema: schemaQueryOnly, - outputSchemaPath: `./tests/_/schemaQueryOnly/schema.graphql`, -}) - -await generate({ - name: `MutationOnly`, - schema: schemaMutationOnly, - outputSchemaPath: `./tests/_/schemaMutationOnly/schema.graphql`, -}) - -await generate({ - schema, - outputSchemaPath: `./tests/_/schema/schema.graphql`, - options: { errorTypeNamePattern: /^Error.+/ }, -}) diff --git a/tests/_/schemaMutationOnly/generated/Client.ts b/tests/_/schemaMutationOnly/generated/Client.ts deleted file mode 100644 index 5fe4d6e40..000000000 --- a/tests/_/schemaMutationOnly/generated/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(`MutationOnly`, $Index) diff --git a/tests/_/schemaMutationOnly/generated/Error.ts b/tests/_/schemaMutationOnly/generated/Error.ts deleted file mode 100644 index 6a480e85c..000000000 --- a/tests/_/schemaMutationOnly/generated/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/tests/_/schemaMutationOnly/generated/Global.ts b/tests/_/schemaMutationOnly/generated/Global.ts deleted file mode 100644 index e3e3c6ad9..000000000 --- a/tests/_/schemaMutationOnly/generated/Global.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Index } from './Index.js' - -declare global { - export namespace GraphQLRequestTypes { - export interface Schemas { - MutationOnly: { - index: Index - customScalars: {} - featureOptions: { - schemaErrors: false - } - } - } - } -} diff --git a/tests/_/schemaMutationOnly/generated/Index.ts b/tests/_/schemaMutationOnly/generated/Index.ts deleted file mode 100644 index a3ca1101e..000000000 --- a/tests/_/schemaMutationOnly/generated/Index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable */ - -import type * as Schema from './SchemaBuildtime.js' - -export interface Index { - name: 'MutationOnly' - Root: { - Query: null - Mutation: Schema.Root.Mutation - Subscription: null - } - objects: {} - unions: {} - interfaces: {} - error: { - objects: {} - objectsTypename: {} - rootResultFields: { - Query: {} - Mutation: {} - Subscription: {} - } - } -} diff --git a/tests/_/schemaMutationOnly/generated/Scalar.ts b/tests/_/schemaMutationOnly/generated/Scalar.ts deleted file mode 100644 index 2e11dcd1c..000000000 --- a/tests/_/schemaMutationOnly/generated/Scalar.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from '../../../../src/layers/1_Schema/Hybrid/types/Scalar/Scalar.js' -export * from '../../customScalarCodecs.js' diff --git a/tests/_/schemaMutationOnly/generated/SchemaBuildtime.ts b/tests/_/schemaMutationOnly/generated/SchemaBuildtime.ts deleted file mode 100644 index 886b86780..000000000 --- a/tests/_/schemaMutationOnly/generated/SchemaBuildtime.ts +++ /dev/null @@ -1,53 +0,0 @@ -import type * as $ from '../../../../src/entrypoints/alpha/schema.js' -import type * as $Scalar from './Scalar.ts' - -// ------------------------------------------------------------ // -// Root // -// ------------------------------------------------------------ // - -export namespace Root { - export type Mutation = $.Object$2<'Mutation', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - idNonNull: $.Field<$Scalar.ID, null> - }> -} - -// ------------------------------------------------------------ // -// Enum // -// ------------------------------------------------------------ // - -export namespace Enum { - // -- no types -- -} - -// ------------------------------------------------------------ // -// InputObject // -// ------------------------------------------------------------ // - -export namespace InputObject { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Interface // -// ------------------------------------------------------------ // - -export namespace Interface { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Object // -// ------------------------------------------------------------ // - -export namespace Object { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Union // -// ------------------------------------------------------------ // - -export namespace Union { - // -- no types -- -} diff --git a/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts b/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts deleted file mode 100644 index 91f87dc75..000000000 --- a/tests/_/schemaMutationOnly/generated/SchemaRuntime.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable */ - -import * as $ from '../../../../src/entrypoints/alpha/schema.js' -import * as $Scalar from './Scalar.js' - -// @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)), - idNonNull: $.field($Scalar.ID), -}) - -export const $Index = { - name: 'MutationOnly' as const, - Root: { - Query: null, - Mutation, - Subscription: null, - }, - objects: {}, - unions: {}, - interfaces: {}, - error: { - objects: {}, - objectsTypename: {}, - rootResultFields: { - Query: {}, - Mutation: {}, - Subscription: {}, - }, - }, -} diff --git a/tests/_/schemaMutationOnly/generated/Select.ts b/tests/_/schemaMutationOnly/generated/Select.ts deleted file mode 100644 index c663e3d6c..000000000 --- a/tests/_/schemaMutationOnly/generated/Select.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ResultSet, SelectionSet } from '../../../../src/entrypoints/alpha/schema.js' -import { 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 Mutation<$SelectionSet extends SelectionSet.Root> = ResultSet.Root< - $SelectionSet, - Index, - 'Mutation' - > - - // Object Types - // ------------ - - // -- None -- - - // Union Types - // ----------- - - // -- None -- - - // Interface Types - // --------------- - - // -- None -- -} diff --git a/tests/_/schemaMutationOnly/generated/_.ts b/tests/_/schemaMutationOnly/generated/_.ts deleted file mode 100644 index 5e2498a39..000000000 --- a/tests/_/schemaMutationOnly/generated/_.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/tests/_/schemaMutationOnly/generated/__.ts b/tests/_/schemaMutationOnly/generated/__.ts deleted file mode 100644 index 0dde36ed9..000000000 --- a/tests/_/schemaMutationOnly/generated/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as MutationOnly from './_.js' diff --git a/tests/_/schemaMutationOnly/schema.graphql b/tests/_/schemaMutationOnly/schema.graphql deleted file mode 100644 index 5093ea4a0..000000000 --- a/tests/_/schemaMutationOnly/schema.graphql +++ /dev/null @@ -1,4 +0,0 @@ -type Mutation { - id: ID - idNonNull: ID! -} \ No newline at end of file diff --git a/tests/_/schemaMutationOnly/schema.ts b/tests/_/schemaMutationOnly/schema.ts deleted file mode 100644 index 125a0f65d..000000000 --- a/tests/_/schemaMutationOnly/schema.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SchemaBuilder from '@pothos/core' -import { db } from '../db.js' - -const builder = new SchemaBuilder<{ - DefaultFieldNullability: true -}>({ - defaultFieldNullability: true, -}) - -builder.mutationType({ - fields: t => ({ - id: t.id({ resolve: () => db.id1 }), - idNonNull: t.id({ nullable: false, resolve: () => db.id1 }), - }), -}) - -export const schema = builder.toSchema({ - sortSchema: true, -}) - -export type { Index } from './generated/Index.js' -export { $Index } from './generated/SchemaRuntime.js' diff --git a/tests/_/schemaQueryOnly/generated/Client.ts b/tests/_/schemaQueryOnly/generated/Client.ts deleted file mode 100644 index e534120b4..000000000 --- a/tests/_/schemaQueryOnly/generated/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(`QueryOnly`, $Index) diff --git a/tests/_/schemaQueryOnly/generated/Error.ts b/tests/_/schemaQueryOnly/generated/Error.ts deleted file mode 100644 index 6a480e85c..000000000 --- a/tests/_/schemaQueryOnly/generated/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/tests/_/schemaQueryOnly/generated/Global.ts b/tests/_/schemaQueryOnly/generated/Global.ts deleted file mode 100644 index 2dfd16886..000000000 --- a/tests/_/schemaQueryOnly/generated/Global.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Index } from './Index.js' - -declare global { - export namespace GraphQLRequestTypes { - export interface Schemas { - QueryOnly: { - index: Index - customScalars: {} - featureOptions: { - schemaErrors: false - } - } - } - } -} diff --git a/tests/_/schemaQueryOnly/generated/Index.ts b/tests/_/schemaQueryOnly/generated/Index.ts deleted file mode 100644 index 10019219e..000000000 --- a/tests/_/schemaQueryOnly/generated/Index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* eslint-disable */ - -import type * as Schema from './SchemaBuildtime.js' - -export interface Index { - name: 'QueryOnly' - Root: { - Query: Schema.Root.Query - Mutation: null - Subscription: null - } - objects: {} - unions: {} - interfaces: {} - error: { - objects: {} - objectsTypename: {} - rootResultFields: { - Query: {} - Mutation: {} - Subscription: {} - } - } -} diff --git a/tests/_/schemaQueryOnly/generated/Scalar.ts b/tests/_/schemaQueryOnly/generated/Scalar.ts deleted file mode 100644 index 2e11dcd1c..000000000 --- a/tests/_/schemaQueryOnly/generated/Scalar.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from '../../../../src/layers/1_Schema/Hybrid/types/Scalar/Scalar.js' -export * from '../../customScalarCodecs.js' diff --git a/tests/_/schemaQueryOnly/generated/SchemaBuildtime.ts b/tests/_/schemaQueryOnly/generated/SchemaBuildtime.ts deleted file mode 100644 index 1d170d7de..000000000 --- a/tests/_/schemaQueryOnly/generated/SchemaBuildtime.ts +++ /dev/null @@ -1,53 +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', { - id: $.Field<$.Output.Nullable<$Scalar.ID>, null> - idNonNull: $.Field<$Scalar.ID, null> - }> -} - -// ------------------------------------------------------------ // -// Enum // -// ------------------------------------------------------------ // - -export namespace Enum { - // -- no types -- -} - -// ------------------------------------------------------------ // -// InputObject // -// ------------------------------------------------------------ // - -export namespace InputObject { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Interface // -// ------------------------------------------------------------ // - -export namespace Interface { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Object // -// ------------------------------------------------------------ // - -export namespace Object { - // -- no types -- -} - -// ------------------------------------------------------------ // -// Union // -// ------------------------------------------------------------ // - -export namespace Union { - // -- no types -- -} diff --git a/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts b/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts deleted file mode 100644 index e9af4a0c0..000000000 --- a/tests/_/schemaQueryOnly/generated/SchemaRuntime.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable */ - -import * as $ from '../../../../src/entrypoints/alpha/schema.js' -import * as $Scalar from './Scalar.js' - -// @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)), - idNonNull: $.field($Scalar.ID), -}) - -export const $Index = { - name: 'QueryOnly' as const, - Root: { - Query, - Mutation: null, - Subscription: null, - }, - objects: {}, - unions: {}, - interfaces: {}, - error: { - objects: {}, - objectsTypename: {}, - rootResultFields: { - Query: {}, - Mutation: {}, - Subscription: {}, - }, - }, -} diff --git a/tests/_/schemaQueryOnly/generated/Select.ts b/tests/_/schemaQueryOnly/generated/Select.ts deleted file mode 100644 index e1218d233..000000000 --- a/tests/_/schemaQueryOnly/generated/Select.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ResultSet, SelectionSet } from '../../../../src/entrypoints/alpha/schema.js' -import { 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 - // ------------ - - // -- None -- - - // Union Types - // ----------- - - // -- None -- - - // Interface Types - // --------------- - - // -- None -- -} diff --git a/tests/_/schemaQueryOnly/generated/_.ts b/tests/_/schemaQueryOnly/generated/_.ts deleted file mode 100644 index 5e2498a39..000000000 --- a/tests/_/schemaQueryOnly/generated/_.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/tests/_/schemaQueryOnly/generated/__.ts b/tests/_/schemaQueryOnly/generated/__.ts deleted file mode 100644 index 80600b117..000000000 --- a/tests/_/schemaQueryOnly/generated/__.ts +++ /dev/null @@ -1 +0,0 @@ -export * as QueryOnly from './_.js' diff --git a/tests/_/schemaQueryOnly/schema.graphql b/tests/_/schemaQueryOnly/schema.graphql deleted file mode 100644 index a17a05bf7..000000000 --- a/tests/_/schemaQueryOnly/schema.graphql +++ /dev/null @@ -1,4 +0,0 @@ -type Query { - id: ID - idNonNull: ID! -} \ No newline at end of file diff --git a/tests/_/schemaQueryOnly/schema.ts b/tests/_/schemaQueryOnly/schema.ts deleted file mode 100644 index 699311de8..000000000 --- a/tests/_/schemaQueryOnly/schema.ts +++ /dev/null @@ -1,22 +0,0 @@ -import SchemaBuilder from '@pothos/core' -import { db } from '../db.js' - -const builder = new SchemaBuilder<{ - DefaultFieldNullability: true -}>({ - defaultFieldNullability: true, -}) - -builder.queryType({ - fields: t => ({ - id: t.id({ resolve: () => db.id1 }), - idNonNull: t.id({ nullable: false, resolve: () => db.id1 }), - }), -}) - -export const schema = builder.toSchema({ - sortSchema: true, -}) - -export type { Index } from './generated/Index.js' -export { $Index } from './generated/SchemaRuntime.js'