diff --git a/.changeset/cruel-geese-buy.md b/.changeset/cruel-geese-buy.md
new file mode 100644
index 00000000..ba12aac2
--- /dev/null
+++ b/.changeset/cruel-geese-buy.md
@@ -0,0 +1,7 @@
+---
+"@traversable/graphql-types": patch
+"@traversable/graphql-test": patch
+"@traversable/graphql": patch
+---
+
+feat(graphql): adds `graphql` to `dependencies`
diff --git a/.changeset/fresh-years-lay.md b/.changeset/fresh-years-lay.md
new file mode 100644
index 00000000..98008b9a
--- /dev/null
+++ b/.changeset/fresh-years-lay.md
@@ -0,0 +1,7 @@
+---
+"@traversable/graphql-types": patch
+"@traversable/graphql-test": patch
+"@traversable/graphql": patch
+---
+
+initializes `@traversable/graphql`, `@traverable/graphql-test`, `@traversable/graphql-types` packages
diff --git a/bin/workspace.ts b/bin/workspace.ts
index c554938f..1a80850c 100755
--- a/bin/workspace.ts
+++ b/bin/workspace.ts
@@ -430,6 +430,7 @@ namespace write {
($) => pipe(
[
`export * from './exports.js'`,
+ null
].join('\n'),
$.dryRun ? tap(`\n\n[CREATE #10]: workspaceIndex\n`, globalThis.String)
: fs.writeString(path.join(PATH.packages, $.pkgName, 'src', 'index.ts')),
@@ -443,7 +444,8 @@ namespace write {
export const workspaceSrcExports = defineEffect(
($) => pipe(
[
- `export * from './version.js'`,
+ `export { VERSION } from './version.js'`,
+ null
].join('\n'),
$.dryRun ? tap(`\n\n[CREATE #11]: workspaceSrcExports\n`, globalThis.String)
: fs.writeString(path.join(PATH.packages, $.pkgName, 'src', 'exports.ts')),
diff --git a/config/__generated__/package-list.ts b/config/__generated__/package-list.ts
index 9aee010d..dee58135 100644
--- a/config/__generated__/package-list.ts
+++ b/config/__generated__/package-list.ts
@@ -2,6 +2,9 @@ export const PACKAGES = [
"packages/arktype",
"packages/arktype-test",
"packages/arktype-types",
+ "packages/graphql",
+ "packages/graphql-test",
+ "packages/graphql-types",
"packages/json",
"packages/json-schema",
"packages/json-schema-test",
diff --git a/packages/graphql-test/README.md b/packages/graphql-test/README.md
new file mode 100644
index 00000000..fcbae809
--- /dev/null
+++ b/packages/graphql-test/README.md
@@ -0,0 +1,40 @@
+
+
แฏ๐๐ฟ๐ฎ๐๐ฒ๐ฟ๐๐ฎ๐ฏ๐น๐ฒ/๐ด๐ฟ๐ฎ๐ฝ๐ต๐พ๐น-๐๐ฒ๐๐
+
+
+
+ TODO: write me
+
+
+
+
+
+
+
+
+
diff --git a/packages/graphql-test/package.json b/packages/graphql-test/package.json
new file mode 100644
index 00000000..f8b786fc
--- /dev/null
+++ b/packages/graphql-test/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "@traversable/graphql-test",
+ "type": "module",
+ "version": "0.0.0",
+ "private": false,
+ "description": "",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/traversable/schema.git",
+ "directory": "packages/graphql-test"
+ },
+ "bugs": {
+ "url": "https://github.com/traversable/schema/issues",
+ "email": "ahrjarrett@gmail.com"
+ },
+ "@traversable": {
+ "generateExports": { "include": ["**/*.ts"] },
+ "generateIndex": { "include": ["**/*.ts"] }
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist",
+ "registry": "https://registry.npmjs.org"
+ },
+ "scripts": {
+ "bench": "echo NOTHING TO BENCH",
+ "build": "pnpm build:esm && pnpm build:cjs && pnpm build:annotate",
+ "build:annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps",
+ "build:esm": "tsc -b tsconfig.build.json",
+ "build:cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps",
+ "check": "tsc -b tsconfig.json",
+ "clean": "pnpm run \"/^clean:.*/\"",
+ "clean:build": "rm -rf .tsbuildinfo dist build",
+ "clean:deps": "rm -rf node_modules",
+ "test": "vitest"
+ },
+ "peerDependencies": {
+ "@traversable/graphql-types": "workspace:^",
+ "@traversable/registry": "workspace:^"
+ },
+ "devDependencies": {
+ "@traversable/graphql-types": "workspace:^",
+ "@traversable/registry": "workspace:^"
+ }
+}
diff --git a/packages/graphql-test/src/__generated__/__manifest__.ts b/packages/graphql-test/src/__generated__/__manifest__.ts
new file mode 100644
index 00000000..c578a8d7
--- /dev/null
+++ b/packages/graphql-test/src/__generated__/__manifest__.ts
@@ -0,0 +1,46 @@
+export default {
+ "name": "@traversable/graphql-test",
+ "type": "module",
+ "version": "0.0.0",
+ "private": false,
+ "description": "",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/traversable/schema.git",
+ "directory": "packages/graphql-test"
+ },
+ "bugs": {
+ "url": "https://github.com/traversable/schema/issues",
+ "email": "ahrjarrett@gmail.com"
+ },
+ "@traversable": {
+ "generateExports": { "include": ["**/*.ts"] },
+ "generateIndex": { "include": ["**/*.ts"] }
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist",
+ "registry": "https://registry.npmjs.org"
+ },
+ "scripts": {
+ "bench": "echo NOTHING TO BENCH",
+ "build": "pnpm build:esm && pnpm build:cjs && pnpm build:annotate",
+ "build:annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps",
+ "build:esm": "tsc -b tsconfig.build.json",
+ "build:cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps",
+ "check": "tsc -b tsconfig.json",
+ "clean": "pnpm run \"/^clean:.*/\"",
+ "clean:build": "rm -rf .tsbuildinfo dist build",
+ "clean:deps": "rm -rf node_modules",
+ "test": "vitest"
+ },
+ "peerDependencies": {
+ "@traversable/graphql-types": "workspace:^",
+ "@traversable/registry": "workspace:^"
+ },
+ "devDependencies": {
+ "@traversable/graphql-types": "workspace:^",
+ "@traversable/registry": "workspace:^"
+ }
+} as const
\ No newline at end of file
diff --git a/packages/graphql-test/src/exports.ts b/packages/graphql-test/src/exports.ts
new file mode 100644
index 00000000..04783bce
--- /dev/null
+++ b/packages/graphql-test/src/exports.ts
@@ -0,0 +1 @@
+export * from './version.js'
\ No newline at end of file
diff --git a/packages/graphql-test/src/index.ts b/packages/graphql-test/src/index.ts
new file mode 100644
index 00000000..9fd152fb
--- /dev/null
+++ b/packages/graphql-test/src/index.ts
@@ -0,0 +1 @@
+export * from './exports.js'
\ No newline at end of file
diff --git a/packages/graphql-test/src/version.ts b/packages/graphql-test/src/version.ts
new file mode 100644
index 00000000..660ff1ca
--- /dev/null
+++ b/packages/graphql-test/src/version.ts
@@ -0,0 +1,3 @@
+import pkg from './__generated__/__manifest__.js'
+export const VERSION = `${pkg.name}@${pkg.version}` as const
+export type VERSION = typeof VERSION
diff --git a/packages/graphql-test/test/version.test.ts b/packages/graphql-test/test/version.test.ts
new file mode 100644
index 00000000..5494d934
--- /dev/null
+++ b/packages/graphql-test/test/version.test.ts
@@ -0,0 +1,10 @@
+import * as vi from 'vitest'
+import pkg from '../package.json' with { type: 'json' }
+import { VERSION } from '@traversable/graphql-test'
+
+vi.describe('ใโณ๏ธใโนโนโน โฒ@traversable/graphql-testโณ', () => {
+ vi.test('ใโณ๏ธใโบ โฒVERSIONโณ', () => {
+ const expected = `${pkg.name}@${pkg.version}`
+ vi.assert.equal(VERSION, expected)
+ })
+})
diff --git a/packages/graphql-test/tsconfig.build.json b/packages/graphql-test/tsconfig.build.json
new file mode 100644
index 00000000..16c1c0e4
--- /dev/null
+++ b/packages/graphql-test/tsconfig.build.json
@@ -0,0 +1,11 @@
+{
+ "extends": "./tsconfig.src.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo",
+ "types": ["node"],
+ "declarationDir": "build/dts",
+ "outDir": "build/esm",
+ "stripInternal": true
+ },
+ "references": [{ "path": "../graphql-types" }, { "path": "../registry" }]
+}
diff --git a/packages/graphql-test/tsconfig.json b/packages/graphql-test/tsconfig.json
new file mode 100644
index 00000000..2c291d21
--- /dev/null
+++ b/packages/graphql-test/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "include": [],
+ "references": [
+ { "path": "tsconfig.src.json" },
+ { "path": "tsconfig.test.json" }
+ ]
+}
diff --git a/packages/graphql-test/tsconfig.src.json b/packages/graphql-test/tsconfig.src.json
new file mode 100644
index 00000000..c110a318
--- /dev/null
+++ b/packages/graphql-test/tsconfig.src.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo",
+ "rootDir": "src",
+ "types": ["node"],
+ "outDir": "build/src"
+ },
+ "references": [{ "path": "../graphql-types" }, { "path": "../registry" }],
+ "include": ["src"]
+}
diff --git a/packages/graphql-test/tsconfig.test.json b/packages/graphql-test/tsconfig.test.json
new file mode 100644
index 00000000..e318a1ea
--- /dev/null
+++ b/packages/graphql-test/tsconfig.test.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo",
+ "rootDir": "test",
+ "types": ["node"],
+ "noEmit": true
+ },
+ "references": [
+ { "path": "tsconfig.src.json" },
+ { "path": "../graphql-types" },
+ { "path": "../registry" }
+ ],
+ "include": ["test"]
+}
diff --git a/packages/graphql-test/vite.config.ts b/packages/graphql-test/vite.config.ts
new file mode 100644
index 00000000..64dba4ad
--- /dev/null
+++ b/packages/graphql-test/vite.config.ts
@@ -0,0 +1,6 @@
+import { defineConfig, mergeConfig } from 'vitest/config'
+import sharedConfig from '../../vite.config.js'
+
+const localConfig = defineConfig({})
+
+export default mergeConfig(sharedConfig, localConfig)
\ No newline at end of file
diff --git a/packages/graphql-types/README.md b/packages/graphql-types/README.md
new file mode 100644
index 00000000..9f380e9b
--- /dev/null
+++ b/packages/graphql-types/README.md
@@ -0,0 +1,40 @@
+
+แฏ๐๐ฟ๐ฎ๐๐ฒ๐ฟ๐๐ฎ๐ฏ๐น๐ฒ/๐ด๐ฟ๐ฎ๐ฝ๐ต๐พ๐น-๐๐๐ฝ๐ฒ๐
+
+
+
+ "Low-level" primitives like types and predicates. Most of this package is re-exported by @traversable/graphql
, so you probably won't need to use it directly.
+
+
+
+
+
+
+
+
+
diff --git a/packages/graphql-types/package.json b/packages/graphql-types/package.json
new file mode 100644
index 00000000..cf97581a
--- /dev/null
+++ b/packages/graphql-types/package.json
@@ -0,0 +1,63 @@
+{
+ "name": "@traversable/graphql-types",
+ "type": "module",
+ "version": "0.0.0",
+ "private": false,
+ "description": "",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/traversable/schema.git",
+ "directory": "packages/graphql-types"
+ },
+ "bugs": {
+ "url": "https://github.com/traversable/schema/issues",
+ "email": "ahrjarrett@gmail.com"
+ },
+ "@traversable": {
+ "generateExports": {
+ "include": [
+ "**/*.ts"
+ ]
+ },
+ "generateIndex": {
+ "include": [
+ "**/*.ts"
+ ]
+ }
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist",
+ "registry": "https://registry.npmjs.org"
+ },
+ "scripts": {
+ "bench": "echo NOTHING TO BENCH",
+ "build": "pnpm build:esm && pnpm build:cjs && pnpm build:annotate",
+ "build:annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps",
+ "build:esm": "tsc -b tsconfig.build.json",
+ "build:cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps",
+ "check": "tsc -b tsconfig.json",
+ "clean": "pnpm run \"/^clean:.*/\"",
+ "clean:build": "rm -rf .tsbuildinfo dist build",
+ "clean:deps": "rm -rf node_modules",
+ "test": "vitest"
+ },
+ "peerDependencies": {
+ "@traversable/registry": "workspace:^",
+ "graphql": "^16.11.0"
+ },
+ "peerDependenciesMeta": {
+ "@traversable/registry": {
+ "optional": false
+ },
+ "graphql": {
+ "optional": false
+ }
+ },
+ "devDependencies": {
+ "@prettier/sync": "catalog:",
+ "@traversable/registry": "workspace:^",
+ "graphql": "^16.11.0"
+ }
+}
diff --git a/packages/graphql-types/src/__generated__/__manifest__.ts b/packages/graphql-types/src/__generated__/__manifest__.ts
new file mode 100644
index 00000000..90ca0075
--- /dev/null
+++ b/packages/graphql-types/src/__generated__/__manifest__.ts
@@ -0,0 +1,59 @@
+export default {
+ "name": "@traversable/graphql-types",
+ "type": "module",
+ "version": "0.0.0",
+ "private": false,
+ "description": "",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/traversable/schema.git",
+ "directory": "packages/graphql-types"
+ },
+ "bugs": {
+ "url": "https://github.com/traversable/schema/issues",
+ "email": "ahrjarrett@gmail.com"
+ },
+ "@traversable": {
+ "generateExports": {
+ "include": ["**/*.ts"]
+ },
+ "generateIndex": {
+ "include": ["**/*.ts"]
+ }
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist",
+ "registry": "https://registry.npmjs.org"
+ },
+ "scripts": {
+ "bench": "echo NOTHING TO BENCH",
+ "build": "pnpm build:esm && pnpm build:cjs && pnpm build:annotate",
+ "build:annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps",
+ "build:esm": "tsc -b tsconfig.build.json",
+ "build:cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps",
+ "check": "tsc -b tsconfig.json",
+ "clean": "pnpm run \"/^clean:.*/\"",
+ "clean:build": "rm -rf .tsbuildinfo dist build",
+ "clean:deps": "rm -rf node_modules",
+ "test": "vitest"
+ },
+ "peerDependencies": {
+ "@traversable/registry": "workspace:^",
+ "graphql": "^16.11.0"
+ },
+ "peerDependenciesMeta": {
+ "@traversable/registry": {
+ "optional": false
+ },
+ "graphql": {
+ "optional": false
+ }
+ },
+ "devDependencies": {
+ "@prettier/sync": "catalog:",
+ "@traversable/registry": "workspace:^",
+ "graphql": "^16.11.0"
+ }
+} as const
\ No newline at end of file
diff --git a/packages/graphql-types/src/exports.ts b/packages/graphql-types/src/exports.ts
new file mode 100644
index 00000000..e20f0bff
--- /dev/null
+++ b/packages/graphql-types/src/exports.ts
@@ -0,0 +1,54 @@
+export { VERSION } from './version.js'
+
+export type {
+ AST,
+ Algebra,
+ Fold,
+ Index,
+} from './functor.js'
+
+export {
+ Functor,
+ Kind,
+ NamedType,
+ defaultIndex,
+ fold,
+ isBooleanNode,
+ isBooleanValueNode,
+ isDirectiveNode,
+ isDocumentNode,
+ isEnumNode,
+ isEnumValueNode,
+ isFieldNode,
+ isFloatNode,
+ isFloatValueNode,
+ isFragmentDefinitionNode,
+ isFragmentSpreadNode,
+ isIDNode,
+ isInlineFragmentNode,
+ isInputObjectNode,
+ isInputValueNode,
+ isInterfaceNode,
+ isIntNode,
+ isIntValueNode,
+ isListNode,
+ isListValueNode,
+ isNamedTypeNode,
+ isNonNullTypeNode,
+ isNullaryNode,
+ isNullValueNode,
+ isNumberNode,
+ isObjectNode,
+ isObjectValueNode,
+ isRefNode,
+ isScalarTypeDefinition,
+ isSelectionSetNode,
+ isStringNode,
+ isStringValueNode,
+ isUnaryNode,
+ isUnionNode,
+ isValueNode,
+ isVariableNode,
+} from './functor.js'
+
+export { toType } from './to-type.js'
diff --git a/packages/graphql-types/src/functor.ts b/packages/graphql-types/src/functor.ts
new file mode 100644
index 00000000..4e828bf7
--- /dev/null
+++ b/packages/graphql-types/src/functor.ts
@@ -0,0 +1,882 @@
+import type * as T from '@traversable/registry'
+import { fn, has } from '@traversable/registry'
+import type * as gql from 'graphql'
+
+/**
+ * ## {@link Kind `Kind`}
+ *
+ * [Reference](https://github.com/graphql/graphql-js/blob/16.x.x/src/language/kinds.ts#L4)
+ */
+export const Kind = {
+ Document: 'Document',
+ EnumTypeDefinition: 'EnumTypeDefinition',
+ EnumValueDefinition: 'EnumValueDefinition',
+ FieldDefinition: 'FieldDefinition',
+ InputObjectTypeDefinition: 'InputObjectTypeDefinition',
+ InputValueDefinition: 'InputValueDefinition',
+ InterfaceTypeDefinition: 'InterfaceTypeDefinition',
+ ListType: 'ListType',
+ Name: 'Name',
+ NamedType: 'NamedType',
+ NonNullType: 'NonNullType',
+ ObjectTypeDefinition: 'ObjectTypeDefinition',
+ OperationDefinition: 'OperationDefinition',
+ ScalarTypeDefinition: 'ScalarTypeDefinition',
+ SelectionSet: 'SelectionSet',
+ UnionTypeDefinition: 'UnionTypeDefinition',
+ Variable: 'Variable',
+ VariableDefinition: 'VariableDefinition',
+ //
+ FragmentSpread: 'FragmentSpread',
+ InlineFragment: 'InlineFragment',
+ FragmentDefinition: 'FragmentDefinition',
+ //
+ Argument: 'Argument',
+ Directive: 'Directive',
+ DirectiveDefinition: 'DirectiveDefinition',
+ EnumValue: 'EnumValue',
+ Field: 'Field',
+ FloatValue: 'FloatValue',
+ StringValue: 'StringValue',
+ BooleanValue: 'BooleanValue',
+ IntValue: 'IntValue',
+ ListValue: 'ListValue',
+ NullValue: 'NullValue',
+ ObjectValue: 'ObjectValue',
+ ObjectField: 'ObjectField',
+ SchemaDefinition: 'SchemaDefinition',
+ SchemaExtension: 'SchemaExtension',
+ OperationTypeDefinition: 'OperationTypeDefinition',
+} as const
+
+export declare namespace Kind {
+ type Document = typeof Kind.Document
+ type EnumTypeDefinition = typeof Kind.EnumTypeDefinition
+ type EnumValueDefinition = typeof Kind.EnumValueDefinition
+ type FieldDefinition = typeof Kind.FieldDefinition
+ type InputObjectTypeDefinition = typeof Kind.InputObjectTypeDefinition
+ type InputValueDefinition = typeof Kind.InputValueDefinition
+ type InterfaceTypeDefinition = typeof Kind.InterfaceTypeDefinition
+ type ListType = typeof Kind.ListType
+ type Name = typeof Kind.Name
+ type NamedType = typeof Kind.NamedType
+ type NonNullType = typeof Kind.NonNullType
+ type ObjectTypeDefinition = typeof Kind.ObjectTypeDefinition
+ type OperationDefinition = typeof Kind.OperationDefinition
+ type ScalarTypeDefinition = typeof Kind.ScalarTypeDefinition
+ type SelectionSet = typeof Kind.SelectionSet
+ type UnionTypeDefinition = typeof Kind.UnionTypeDefinition
+ type Variable = typeof Kind.Variable
+ type VariableDefinition = typeof Kind.VariableDefinition
+ //
+ type FragmentSpread = typeof Kind.FragmentSpread
+ type InlineFragment = typeof Kind.InlineFragment
+ type FragmentDefinition = typeof Kind.FragmentDefinition
+ //
+ type Argument = typeof Kind.Argument
+ type Directive = typeof Kind.Directive
+ type DirectiveDefinition = typeof Kind.DirectiveDefinition
+ type EnumValue = typeof Kind.EnumValue
+ type Field = typeof Kind.Field
+ type FloatValue = typeof Kind.FloatValue
+ type StringValue = typeof Kind.StringValue
+ type BooleanValue = typeof Kind.BooleanValue
+ type IntValue = typeof Kind.IntValue
+ type ListValue = typeof Kind.ListValue
+ type NullValue = typeof Kind.NullValue
+ type ObjectValue = typeof Kind.ObjectValue
+ type ObjectField = typeof Kind.ObjectField
+ type SchemaDefinition = typeof Kind.SchemaDefinition
+ type SchemaExtension = typeof Kind.SchemaExtension
+ type OperationTypeDefinition = typeof Kind.OperationTypeDefinition
+}
+
+/**
+ * ## {@link NamedType `NamedType`}
+ */
+export const NamedType = {
+ Boolean: 'Boolean',
+ Float: 'Float',
+ ID: 'ID',
+ Int: 'Int',
+ Number: 'Number',
+ String: 'String',
+} as const
+
+export declare namespace NamedType {
+ type Boolean = typeof NamedType.Boolean
+ type Float = typeof NamedType.Float
+ type ID = typeof NamedType.ID
+ type Int = typeof NamedType.Int
+ type Number = typeof NamedType.Number
+ type String = typeof NamedType.String
+}
+
+export const OperationType = {
+ Query: 'query',
+ Mutation: 'mutation',
+ Subscription: 'subscription',
+} as const
+
+export declare namespace OperationType {
+ type Query = typeof OperationType.Query
+ type Mutation = typeof OperationType.Mutation
+ type Subscription = typeof OperationType.Subscription
+}
+
+/**
+ * ## {@link AST `AST`}
+ */
+export declare namespace AST {
+ type Catalog = { [Node in F as Node['kind']]: Node }
+
+ interface Location {
+ start: number
+ end: number
+ }
+
+ interface SelectionSetNode {
+ kind: Kind.SelectionSet
+ selections: readonly T[]
+ loc?: Location
+ }
+
+ interface NameNode {
+ kind: Kind.Name
+ value: Value
+ loc?: Location
+ }
+
+ interface NamedTypeNode {
+ name: NameNode
+ loc?: Location
+ }
+
+ /**
+ * ## {@link RefNode `RefNode`}
+ *
+ * A {@link RefNode `RefNode`} is a named type that is not one of the built-in types.
+ */
+ interface RefNode {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface DocumentNode {
+ kind: Kind.Document
+ definitions: readonly T[]
+ loc?: Location
+ }
+
+ interface InputValueNode {
+ kind: Kind.InputValueDefinition
+ name: NameNode
+ type: T
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface InputObjectNode {
+ kind: Kind.InputObjectTypeDefinition
+ name: NameNode
+ fields: readonly T[]
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface VariableNode {
+ kind: Kind.Variable
+ name: NameNode
+ loc?: Location
+ }
+
+ interface VariableDefinitionNode {
+ kind: Kind.VariableDefinition
+ variable: VariableNode
+ type: T
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface ScalarTypeDefinition {
+ kind: Kind.ScalarTypeDefinition
+ name: NameNode
+ loc?: Location
+ }
+
+ interface Boolean {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface Int {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface Number {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface Float {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface String {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface ID {
+ kind: Kind.NamedType
+ name: NameNode
+ loc?: Location
+ }
+
+ interface EnumValueNode {
+ kind: Kind.EnumValueDefinition
+ name: NameNode
+ loc?: Location
+ }
+
+ interface EnumNode {
+ kind: Kind.EnumTypeDefinition
+ name: NameNode
+ values: readonly EnumValueNode[]
+ loc?: Location
+ }
+
+ interface NonNullTypeNode {
+ kind: Kind.NonNullType
+ type: T
+ loc?: Location
+ }
+
+ interface ListNode {
+ kind: Kind.ListType
+ type: T
+ loc?: Location
+ }
+
+ interface FieldNode {
+ kind: Kind.FieldDefinition
+ name: NameNode
+ type: T
+ defaultValue?: unknown
+ arguments?: readonly T[]
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface ObjectNode {
+ kind: Kind.ObjectTypeDefinition
+ name: NameNode
+ fields: readonly T[]
+ interfaces: readonly T[]
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface InterfaceNode {
+ kind: Kind.InterfaceTypeDefinition
+ name: NameNode
+ fields: readonly T[]
+ interfaces: readonly T[]
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface UnionNode {
+ kind: Kind.UnionTypeDefinition
+ name: NameNode
+ types: readonly T[]
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface FragmentDefinitionNode {
+ kind: Kind.FragmentDefinition
+ name: NameNode
+ typeCondition: NamedTypeNode
+ directives?: readonly T[]
+ selectionSet: T
+ loc?: Location
+ }
+
+ interface FragmentSpreadNode {
+ kind: Kind.FragmentSpread
+ name: NameNode
+ directives?: readonly T[]
+ loc?: Location
+ }
+
+ interface InlineFragmentNode {
+ kind: Kind.InlineFragment
+ typeCondition?: NamedTypeNode
+ directives?: readonly T[]
+ selectionSet: T
+ loc?: Location
+ }
+
+ interface IntValueNode {
+ kind: Kind.IntValue
+ value: string
+ loc?: Location
+ }
+
+ interface FloatValueNode {
+ kind: Kind.FloatValue
+ value: string
+ loc?: Location
+ }
+
+ interface StringValueNode {
+ kind: Kind.StringValue
+ value: string
+ loc?: Location
+ }
+
+ interface BooleanValueNode {
+ kind: Kind.BooleanValue
+ value: boolean
+ loc?: Location
+ }
+
+ interface NullValueNode {
+ kind: Kind.NullValue
+ loc?: Location
+ }
+
+ interface ListValueNode {
+ kind: Kind.ListValue
+ values: readonly ValueNode[]
+ loc?: Location
+ }
+
+ interface ObjectValueNode {
+ kind: Kind.ObjectValue
+ fields: readonly ObjectFieldNode[]
+ loc?: Location
+ }
+
+ interface ObjectFieldNode {
+ kind: Kind.ObjectField
+ name: NameNode
+ value: ValueNode
+ loc?: Location
+ }
+
+ interface DirectiveNode {
+ kind: Kind.Directive
+ name: NameNode
+ arguments?: readonly T[]
+ loc?: Location
+ }
+
+ interface QueryOperation {
+ kind: Kind.OperationDefinition
+ operation: OperationType.Query
+ name?: NameNode
+ variableDefinitions?: readonly T[]
+ directives?: readonly T[]
+ selectionSet: T
+ loc?: Location
+ }
+
+ interface MutationOperation {
+ kind: Kind.OperationDefinition
+ operation: OperationType.Mutation
+ name?: NameNode
+ variableDefinitions?: readonly T[]
+ directives?: readonly T[]
+ selectionSet: T
+ loc?: Location
+ }
+
+ interface SubscriptionOperation {
+ kind: Kind.OperationDefinition
+ operation: OperationType.Subscription
+ name?: NameNode
+ variableDefinitions?: readonly T[]
+ directives?: readonly T[]
+ selectionSet: T
+ loc?: Location
+ }
+
+ type ValueNode =
+ | VariableNode
+ | IntValueNode
+ | FloatValueNode
+ | StringValueNode
+ | BooleanValueNode
+ | NullValueNode
+ | EnumValueNode
+ | ListValueNode
+ | ObjectValueNode
+
+ type Nullary =
+ | Boolean
+ | Int
+ | Number
+ | Float
+ | String
+ | ID
+ | ScalarTypeDefinition
+ | EnumNode
+ | ValueNode
+
+ type OperationDefinitionNode =
+ | QueryOperation
+ | MutationOperation
+ | SubscriptionOperation
+
+ type Unary =
+ | NonNullTypeNode
+ | ListNode
+ | FieldNode
+ | ObjectNode
+ | InterfaceNode
+ | UnionNode
+ | InputValueNode
+ | InputObjectNode
+ | SelectionSetNode
+ | FragmentDefinitionNode
+ | FragmentSpreadNode
+ | InlineFragmentNode
+ | DirectiveNode
+
+ type F =
+ | RefNode
+ | Nullary
+ | Unary
+ | OperationDefinitionNode
+ | DocumentNode
+}
+
+export function isScalarTypeDefinition(x: unknown): x is AST.ScalarTypeDefinition {
+ return has('kind', (kind) => kind === Kind.ScalarTypeDefinition)(x)
+}
+
+export function isBooleanNode(x: unknown): x is AST.Boolean {
+ return has('name', 'value', (value) => value === NamedType.Boolean)(x)
+}
+
+export function isIntNode(x: unknown): x is AST.Int {
+ return has('name', 'value', (value) => value === NamedType.Int)(x)
+}
+
+export function isNumberNode(x: unknown): x is AST.Number {
+ return has('name', 'value', (value) => value === NamedType.Number)(x)
+}
+
+export function isFloatNode(x: unknown): x is AST.Float {
+ return has('name', 'value', (value) => value === NamedType.Float)(x)
+}
+
+export function isStringNode(x: unknown): x is AST.String {
+ return has('name', 'value', (value) => value === NamedType.String)(x)
+}
+
+export function isIDNode(x: unknown): x is AST.ID {
+ return has('name', 'value', (value) => value === NamedType.ID)(x)
+}
+
+export function isEnumNode(x: unknown): x is AST.EnumNode {
+ return has('kind', (kind) => kind === Kind.EnumTypeDefinition)(x)
+}
+
+export function isVariableNode(x: unknown): x is AST.VariableNode {
+ return has('kind', (kind) => kind === Kind.Variable)(x)
+}
+
+export function isBooleanValueNode(x: unknown): x is AST.BooleanValueNode {
+ return has('kind', (kind) => kind === Kind.BooleanValue)(x)
+}
+
+export function isIntValueNode(x: unknown): x is AST.IntValueNode {
+ return has('kind', (kind) => kind === Kind.IntValue)(x)
+}
+
+export function isFloatValueNode(x: unknown): x is AST.FloatValueNode {
+ return has('kind', (kind) => kind === Kind.FloatValue)(x)
+}
+
+export function isStringValueNode(x: unknown): x is AST.StringValueNode {
+ return has('kind', (kind) => kind === Kind.StringValue)(x)
+}
+
+export function isNullValueNode(x: unknown): x is AST.NullValueNode {
+ return has('kind', (kind) => kind === Kind.NullValue)(x)
+}
+
+export function isEnumValueNode(x: unknown): x is AST.EnumValueNode {
+ return has('kind', (kind) => kind === Kind.EnumValue)(x)
+}
+
+export function isListValueNode(x: unknown): x is AST.ListValueNode {
+ return has('kind', (kind) => kind === Kind.ListValue)(x)
+}
+
+export function isObjectValueNode(x: unknown): x is AST.ObjectValueNode {
+ return has('kind', (kind) => kind === Kind.ObjectValue)(x)
+}
+
+export function isNonNullTypeNode(x: unknown): x is AST.NonNullTypeNode {
+ return has('kind', (kind) => kind === Kind.NonNullType)(x)
+}
+
+export function isListNode(x: unknown): x is AST.ListNode {
+ return has('kind', (kind) => kind === Kind.ListType)(x)
+}
+
+export function isFieldNode(x: unknown): x is AST.FieldNode {
+ return has('kind', (kind) => kind === Kind.FieldDefinition)(x)
+}
+
+export function isObjectNode(x: unknown): x is AST.ObjectNode {
+ return has('kind', (kind) => kind === Kind.ObjectTypeDefinition)(x)
+}
+
+export function isInterfaceNode(x: unknown): x is AST.InterfaceNode {
+ return has('kind', (kind) => kind === Kind.InterfaceTypeDefinition)(x)
+}
+
+export function isUnionNode(x: unknown): x is AST.UnionNode {
+ return has('kind', (kind) => kind === Kind.UnionTypeDefinition)(x)
+}
+
+export function isInputValueNode(x: unknown): x is AST.InputValueNode {
+ return has('kind', (kind) => kind === Kind.InputValueDefinition)(x)
+}
+
+export function isInputObjectNode(x: unknown): x is AST.InputObjectNode {
+ return has('kind', (kind) => kind === Kind.InputObjectTypeDefinition)(x)
+}
+
+export function isNamedTypeNode(x: unknown): x is AST.NamedTypeNode {
+ return has('name', 'value', (value) => typeof value === 'string')(x)
+}
+
+export function isSelectionSetNode(x: unknown): x is AST.SelectionSetNode {
+ return has('kind', (kind) => kind === Kind.SelectionSet)(x)
+}
+
+export function isFragmentDefinitionNode(x: unknown): x is AST.FragmentDefinitionNode {
+ return has('kind', (kind) => kind === Kind.FragmentDefinition)(x)
+}
+
+export function isFragmentSpreadNode(x: unknown): x is AST.FragmentSpreadNode {
+ return has('kind', (kind) => kind === Kind.FragmentSpread)(x)
+}
+
+export function isInlineFragmentNode(x: unknown): x is AST.InlineFragmentNode {
+ return has('kind', (kind) => kind === Kind.InlineFragment)(x)
+}
+
+export function isDirectiveNode(x: unknown): x is AST.DirectiveNode {
+ return has('kind', (kind) => kind === Kind.Directive)(x)
+}
+
+export function isQueryOperation(x: unknown): x is AST.QueryOperation {
+ return has('kind', (kind) => kind === OperationType.Query)(x)
+}
+
+export function isMutationOperation(x: unknown): x is AST.MutationOperation {
+ return has('kind', (kind) => kind === OperationType.Mutation)(x)
+}
+
+export function isSubscriptionOperation(x: unknown): x is AST.SubscriptionOperation {
+ return has('kind', (kind) => kind === OperationType.Subscription)(x)
+}
+
+export function isDocumentNode(x: unknown): x is AST.DocumentNode {
+ return has('kind', (kind) => kind === Kind.Document)(x)
+}
+
+export function isRefNode(x: unknown): x is AST.RefNode {
+ return has('kind', (kind) => kind === Kind.NamedType)(x)
+ && has('name', 'value', (value) => typeof value === 'string')(x)
+ && !isNullaryNode(x)
+}
+
+export function isValueNode(x: unknown): x is AST.ValueNode {
+ return isVariableNode(x)
+ || isIntValueNode(x)
+ || isFloatValueNode(x)
+ || isStringValueNode(x)
+ || isBooleanValueNode(x)
+ || isNullValueNode(x)
+ || isEnumValueNode(x)
+ || isListValueNode(x)
+ || isObjectValueNode(x)
+}
+
+export function isNullaryNode(x: unknown): x is AST.Nullary {
+ return isScalarTypeDefinition(x)
+ || isBooleanNode(x)
+ || isIntNode(x)
+ || isNumberNode(x)
+ || isFloatNode(x)
+ || isStringNode(x)
+ || isIDNode(x)
+ || isEnumNode(x)
+}
+
+export function isUnaryNode(x: unknown): x is AST.Unary {
+ return isNonNullTypeNode(x)
+ || isListNode(x)
+ || isObjectNode(x)
+ || isInterfaceNode(x)
+ || isUnionNode(x)
+ || isInputObjectNode(x)
+}
+
+export function isOperationDefinitionNode(x: unknown): x is AST.OperationDefinitionNode {
+ return isQueryOperation(x)
+ || isMutationOperation(x)
+ || isSubscriptionOperation(x)
+}
+
+export interface Index {
+ isNonNull: boolean
+}
+
+export const defaultIndex = {
+ isNonNull: false,
+} satisfies Index
+
+export type Algebra = {
+ (src: AST.F, ix?: Index): T
+ (src: gql.ASTNode, ix?: Index): T
+ (src: AST.F, ix?: Index): T
+}
+
+export type Fold = (g: (src: AST.F, ix: Index, x: gql.ASTNode) => T) => Algebra
+
+export interface Functor extends T.HKT { [-1]: AST.F }
+
+export declare namespace Functor {
+ export {
+ Index,
+ }
+}
+
+export const Functor: T.Functor.Ix = {
+ map(g) {
+ return (x) => {
+ switch (true) {
+ default: return fn.exhaustive(x)
+ case isRefNode(x): return x
+ case isNullaryNode(x): return x
+ case isListNode(x): return { ...x, type: g(x.type) }
+ case isNonNullTypeNode(x): return { ...x, type: g(x.type) }
+ case isSelectionSetNode(x): return { ...x, selections: x.selections.map(g) }
+ case isDocumentNode(x): return { ...x, definitions: x.definitions.map(g) }
+ case isUnionNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ types: x.types.map(g),
+ }
+ }
+ case isFieldNode(x): {
+ const { arguments: args, directives, ...xs } = x
+ return {
+ ...xs,
+ ...args && { arguments: args.map(g) },
+ ...directives && { directives: directives.map(g) },
+ type: g(x.type),
+ }
+ }
+ case isObjectNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ interfaces: x.interfaces.map(g),
+ fields: x.fields.map(g),
+ }
+ }
+ case isInterfaceNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ interfaces: x.interfaces.map(g),
+ fields: x.fields.map(g),
+ }
+ }
+ case isInputValueNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ type: g(x.type),
+ }
+ }
+ case isInputObjectNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ fields: x.fields.map(g),
+ }
+ }
+ case isFragmentDefinitionNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ selectionSet: g(x.selectionSet),
+ }
+ }
+ case isFragmentSpreadNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ }
+ }
+ case isInlineFragmentNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ selectionSet: g(x.selectionSet),
+ }
+ }
+ case isDirectiveNode(x): {
+ const { arguments: args, ...xs } = x
+ return {
+ ...xs,
+ ...args && { arguments: args.map(g) },
+ }
+ }
+ case isOperationDefinitionNode(x): {
+ const { directives, variableDefinitions: vars, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map(g) },
+ ...vars && { variableDefinitions: vars.map(g) },
+ selectionSet: g(x.selectionSet)
+ }
+ }
+ }
+ }
+ },
+ mapWithIndex(g) {
+ return (x, _ix) => {
+ const ix = isNonNullTypeNode(x) ? { isNonNull: true } satisfies Index : defaultIndex
+ switch (true) {
+ default: return fn.exhaustive(x)
+ case isRefNode(x): return x
+ case isNullaryNode(x): return x
+ case isListNode(x): return { ...x, type: g(x.type, ix, x) }
+ case isNonNullTypeNode(x): return { ...x, type: g(x.type, ix, x) }
+ case isSelectionSetNode(x): return { ...x, selections: x.selections.map((_) => g(_, ix, x)) }
+ case isDocumentNode(x): return { ...x, definitions: x.definitions.map((_) => g(_, ix, x)) }
+ case isUnionNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ types: x.types.map((_) => g(_, ix, x)),
+ }
+ }
+ case isFieldNode(x): {
+ const { arguments: args, directives, ...xs } = x
+ return {
+ ...xs,
+ ...args && { arguments: args.map((_) => g(_, ix, x)) },
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ type: g(x.type, isNonNullTypeNode(x.type) ? { isNonNull: true } : ix, x),
+ }
+ }
+ case isObjectNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ fields: x.fields.map((_) => g(_, ix, x)),
+ interfaces: x.interfaces.map((_) => g(_, ix, x)),
+ }
+ }
+ case isInterfaceNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ fields: x.fields.map((_) => g(_, ix, x)),
+ interfaces: x.interfaces.map((_) => g(_, ix, x)),
+ }
+ }
+ case isInputValueNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ type: g(x.type, ix, x),
+ }
+ }
+ case isInputObjectNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ fields: x.fields.map((_) => g(_, ix, x)),
+ }
+ }
+ case isFragmentDefinitionNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ selectionSet: g(x.selectionSet, ix, x),
+ }
+ }
+ case isFragmentSpreadNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ }
+ }
+ case isInlineFragmentNode(x): {
+ const { directives, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ selectionSet: g(x.selectionSet, ix, x),
+ }
+ }
+ case isDirectiveNode(x): {
+ const { arguments: args, ...xs } = x
+ return {
+ ...xs,
+ ...args && { arguments: args.map((_) => g(_, ix, x)) },
+ }
+ }
+ case isOperationDefinitionNode(x): {
+ const { directives, variableDefinitions: vars, ...xs } = x
+ return {
+ ...xs,
+ ...directives && { directives: directives.map((_) => g(_, ix, x)) },
+ ...vars && { variableDefinitions: vars.map((_) => g(_, ix, x)) },
+ selectionSet: g(x.selectionSet, ix, x)
+ }
+ }
+ }
+ }
+ }
+}
+
+export const fold: Fold = fn.catamorphism(Functor, defaultIndex) as never
diff --git a/packages/graphql-types/src/index.ts b/packages/graphql-types/src/index.ts
new file mode 100644
index 00000000..410a4bcb
--- /dev/null
+++ b/packages/graphql-types/src/index.ts
@@ -0,0 +1 @@
+export * from './exports.js'
diff --git a/packages/graphql-types/src/to-type.ts b/packages/graphql-types/src/to-type.ts
new file mode 100644
index 00000000..c9aa9c2e
--- /dev/null
+++ b/packages/graphql-types/src/to-type.ts
@@ -0,0 +1,103 @@
+import { fn, has, parseKey } from '@traversable/registry'
+import * as GQL from './functor.js'
+import type * as gql from 'graphql'
+import type { AST } from './functor.js'
+
+const unsupported = [
+ 'Directive',
+ 'FragmentDefinition',
+ 'FragmentSpread',
+ 'InlineFragment',
+ 'InputObjectTypeDefinition',
+ 'InputValueDefinition',
+ 'SelectionSet',
+ 'OperationDefinition'
+] as const satisfies Array
+
+type UnsupportedNodeMap = Pick
+type UnsupportedNode = UnsupportedNodeMap[keyof UnsupportedNodeMap]
+
+function isUnsupportedNode(x: unknown): x is UnsupportedNode {
+ return unsupported.some(
+ (nope) => has('kind', (kind): kind is never => kind === nope)(x)
+ )
+}
+
+function valueNodeToString(x: AST.ValueNode): string {
+ switch (x.kind) {
+ default: return fn.exhaustive(x)
+ case 'NullValue': return 'null'
+ case 'BooleanValue': return `${x.value}`
+ case 'IntValue': return `${x.value}`
+ case 'FloatValue': return `${x.value}`
+ case 'StringValue': return `"${x.value}"`
+ case 'EnumValueDefinition': return `"${x.name.value}"`
+ case 'ListValue': return `[${x.values.map(valueNodeToString).join(', ')}]`
+ case 'ObjectValue': return ''
+ + '{ '
+ + x.fields.map((node) => `${parseKey(node.name.value)}: ${valueNodeToString(node.value)}`).join(', ')
+ + ' }'
+ case 'Variable': return `${x.name.value}`
+ }
+}
+
+const fold = GQL.fold((x, _, original) => {
+ switch (true) {
+ default: return fn.exhaustive(x)
+ case GQL.isRefNode(x): return x.name.value
+ case GQL.isValueNode(x): return valueNodeToString(x)
+ case GQL.isScalarTypeDefinition(x): return x.name.value
+ case GQL.isBooleanNode(x): return 'boolean'
+ case GQL.isIntNode(x): return 'number'
+ case GQL.isNumberNode(x): return 'number'
+ case GQL.isFloatNode(x): return 'number'
+ case GQL.isStringNode(x): return 'string'
+ case GQL.isIDNode(x): return 'string'
+ case GQL.isEnumNode(x): return (
+ x.values.length === 0 ? 'never'
+ : x.values.length === 1 ? JSON.stringify(x.values[0])
+ : `(${x.values.map((v) => JSON.stringify(v)).join(' | ')})`
+ )
+ case GQL.isNonNullTypeNode(x): return `${x.type}!`
+ case GQL.isUnionNode(x): return (
+ x.types.length === 0 ? 'never'
+ : x.types.length === 1 ? JSON.stringify(x.types[0])
+ : `(${x.types.map((v) => JSON.stringify(v)).join(' | ')})`
+ )
+ case GQL.isListNode(x): {
+ if (!GQL.isListNode(original)) throw Error('Illegal state')
+ const isNonNull = x.type.endsWith('!')
+ const TYPE = isNonNull ? x.type.slice(0, -1) : `${x.type} | null`
+ return `Array<${TYPE}>`
+ }
+ case GQL.isFieldNode(x): {
+ const isNonNull = x.type.endsWith('!')
+ const VALUE = isNonNull ? x.type.slice(0, -1) : x.type
+ return `${parseKey(x.name.value)}${isNonNull ? '' : '?'}: ${VALUE}`
+ }
+ case GQL.isObjectNode(x): { return x.fields.length === 0 ? `{}` : `{ ${x.fields.join(', ')} }` }
+ case GQL.isInterfaceNode(x): { return x.fields.length === 0 ? `{}` : `{ ${x.fields.join(', ')} }` }
+ case GQL.isDocumentNode(x): throw Error('[@traversable/graphql-types/to-type.js]: Nesting documents is not allowed')
+ case isUnsupportedNode(x): throw Error(`[@traversable/graphql-types/to-type.js]: Unsupported node: ${x.kind}`)
+ }
+})
+
+export declare namespace toType {
+ export type {
+ UnsupportedNode
+ }
+}
+
+toType.unsupported = unsupported
+
+/**
+ * ## {@link toType `toType`}
+ *
+ * Convert a GraphQL AST into its corresponding TypeScript type.
+ */
+export function toType(doc: gql.DocumentNode) {
+ const types = doc.definitions.map(
+ (x, i) => `type ${GQL.isNamedTypeNode(x) ? x.name.value : `Type${i}`} = ${fold(x)}`
+ )
+ return types.join('\n')
+}
diff --git a/packages/graphql-types/src/version.ts b/packages/graphql-types/src/version.ts
new file mode 100644
index 00000000..660ff1ca
--- /dev/null
+++ b/packages/graphql-types/src/version.ts
@@ -0,0 +1,3 @@
+import pkg from './__generated__/__manifest__.js'
+export const VERSION = `${pkg.name}@${pkg.version}` as const
+export type VERSION = typeof VERSION
diff --git a/packages/graphql-types/test/to-type.test.ts b/packages/graphql-types/test/to-type.test.ts
new file mode 100644
index 00000000..5d06f81b
--- /dev/null
+++ b/packages/graphql-types/test/to-type.test.ts
@@ -0,0 +1,36 @@
+import * as vi from 'vitest'
+import { toType } from '@traversable/graphql-types'
+import * as graphql from 'graphql'
+import prettier from '@prettier/sync'
+
+const format = (src: string) => prettier.format(
+ src,
+ { parser: 'typescript', semi: false, printWidth: 35 }
+)
+
+vi.describe('ใโณ๏ธใโนโนโน โฒ@traversable/graphql-typesโณ', () => {
+ vi.test('ใโณ๏ธใโบ โฒtoTypeโณ', () => {
+ vi.expect.soft(format(
+ toType(graphql.parse(`
+ type Pet {
+ petName: [String!]
+ }
+ type Human {
+ humanName: String!
+ pet: Pet
+ }
+ `
+ ))
+ )).toMatchInlineSnapshot
+ (`
+ "type Pet = {
+ petName?: Array
+ }
+ type Human = {
+ humanName: string
+ pet?: Pet
+ }
+ "
+ `)
+ })
+})
diff --git a/packages/graphql-types/test/version.test.ts b/packages/graphql-types/test/version.test.ts
new file mode 100644
index 00000000..17cbd6e9
--- /dev/null
+++ b/packages/graphql-types/test/version.test.ts
@@ -0,0 +1,10 @@
+import * as vi from 'vitest'
+import pkg from '../package.json' with { type: 'json' }
+import { VERSION } from '@traversable/graphql-types'
+
+vi.describe('ใโณ๏ธใโนโนโน โฒ@traversable/graphql-typesโณ', () => {
+ vi.test('ใโณ๏ธใโบ โฒVERSIONโณ', () => {
+ const expected = `${pkg.name}@${pkg.version}`
+ vi.assert.equal(VERSION, expected)
+ })
+})
diff --git a/packages/graphql-types/tsconfig.build.json b/packages/graphql-types/tsconfig.build.json
new file mode 100644
index 00000000..aacae424
--- /dev/null
+++ b/packages/graphql-types/tsconfig.build.json
@@ -0,0 +1,11 @@
+{
+ "extends": "./tsconfig.src.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo",
+ "types": ["node"],
+ "declarationDir": "build/dts",
+ "outDir": "build/esm",
+ "stripInternal": true
+ },
+ "references": [{ "path": "../registry" }]
+}
diff --git a/packages/graphql-types/tsconfig.json b/packages/graphql-types/tsconfig.json
new file mode 100644
index 00000000..2c291d21
--- /dev/null
+++ b/packages/graphql-types/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "include": [],
+ "references": [
+ { "path": "tsconfig.src.json" },
+ { "path": "tsconfig.test.json" }
+ ]
+}
diff --git a/packages/graphql-types/tsconfig.src.json b/packages/graphql-types/tsconfig.src.json
new file mode 100644
index 00000000..f70f4837
--- /dev/null
+++ b/packages/graphql-types/tsconfig.src.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo",
+ "rootDir": "src",
+ "types": ["node"],
+ "outDir": "build/src"
+ },
+ "references": [{ "path": "../registry" }],
+ "include": ["src"]
+}
diff --git a/packages/graphql-types/tsconfig.test.json b/packages/graphql-types/tsconfig.test.json
new file mode 100644
index 00000000..1a25fb45
--- /dev/null
+++ b/packages/graphql-types/tsconfig.test.json
@@ -0,0 +1,14 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo",
+ "rootDir": "test",
+ "types": ["node"],
+ "noEmit": true
+ },
+ "references": [
+ { "path": "tsconfig.src.json" },
+ { "path": "../registry" }
+ ],
+ "include": ["test"]
+}
diff --git a/packages/graphql-types/vite.config.ts b/packages/graphql-types/vite.config.ts
new file mode 100644
index 00000000..64dba4ad
--- /dev/null
+++ b/packages/graphql-types/vite.config.ts
@@ -0,0 +1,6 @@
+import { defineConfig, mergeConfig } from 'vitest/config'
+import sharedConfig from '../../vite.config.js'
+
+const localConfig = defineConfig({})
+
+export default mergeConfig(sharedConfig, localConfig)
\ No newline at end of file
diff --git a/packages/graphql/README.md b/packages/graphql/README.md
new file mode 100644
index 00000000..756177b6
--- /dev/null
+++ b/packages/graphql/README.md
@@ -0,0 +1,40 @@
+
+แฏ๐๐ฟ๐ฎ๐๐ฒ๐ฟ๐๐ฎ๐ฏ๐น๐ฒ/๐ด๐ฟ๐ฎ๐ฝ๐ต๐พ๐น
+
+
+
+ TODO: write me
+
+
+
+
+
+
+
+
+
diff --git a/packages/graphql/package.json b/packages/graphql/package.json
new file mode 100644
index 00000000..80af8949
--- /dev/null
+++ b/packages/graphql/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "@traversable/graphql",
+ "type": "module",
+ "version": "0.0.0",
+ "private": false,
+ "description": "",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/traversable/schema.git",
+ "directory": "packages/graphql"
+ },
+ "bugs": {
+ "url": "https://github.com/traversable/schema/issues",
+ "email": "ahrjarrett@gmail.com"
+ },
+ "@traversable": {
+ "generateExports": { "include": ["**/*.ts"] },
+ "generateIndex": { "include": ["**/*.ts"] }
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist",
+ "registry": "https://registry.npmjs.org"
+ },
+ "scripts": {
+ "bench": "echo NOTHING TO BENCH",
+ "build": "pnpm build:esm && pnpm build:cjs && pnpm build:annotate",
+ "build:annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps",
+ "build:esm": "tsc -b tsconfig.build.json",
+ "build:cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps",
+ "check": "tsc -b tsconfig.json",
+ "clean": "pnpm run \"/^clean:.*/\"",
+ "clean:build": "rm -rf .tsbuildinfo dist build",
+ "clean:deps": "rm -rf node_modules",
+ "test": "vitest"
+ },
+ "dependencies": {
+ "@traversable/graphql-types": "workspace:^",
+ "@traversable/registry": "workspace:^"
+ }
+}
diff --git a/packages/graphql/src/__generated__/__manifest__.ts b/packages/graphql/src/__generated__/__manifest__.ts
new file mode 100644
index 00000000..92c562e7
--- /dev/null
+++ b/packages/graphql/src/__generated__/__manifest__.ts
@@ -0,0 +1,42 @@
+export default {
+ "name": "@traversable/graphql",
+ "type": "module",
+ "version": "0.0.0",
+ "private": false,
+ "description": "",
+ "license": "MIT",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/traversable/schema.git",
+ "directory": "packages/graphql"
+ },
+ "bugs": {
+ "url": "https://github.com/traversable/schema/issues",
+ "email": "ahrjarrett@gmail.com"
+ },
+ "@traversable": {
+ "generateExports": { "include": ["**/*.ts"] },
+ "generateIndex": { "include": ["**/*.ts"] }
+ },
+ "publishConfig": {
+ "access": "public",
+ "directory": "dist",
+ "registry": "https://registry.npmjs.org"
+ },
+ "scripts": {
+ "bench": "echo NOTHING TO BENCH",
+ "build": "pnpm build:esm && pnpm build:cjs && pnpm build:annotate",
+ "build:annotate": "babel build --plugins annotate-pure-calls --out-dir build --source-maps",
+ "build:esm": "tsc -b tsconfig.build.json",
+ "build:cjs": "babel build/esm --plugins @babel/transform-export-namespace-from --plugins @babel/transform-modules-commonjs --out-dir build/cjs --source-maps",
+ "check": "tsc -b tsconfig.json",
+ "clean": "pnpm run \"/^clean:.*/\"",
+ "clean:build": "rm -rf .tsbuildinfo dist build",
+ "clean:deps": "rm -rf node_modules",
+ "test": "vitest"
+ },
+ "dependencies": {
+ "@traversable/graphql-types": "workspace:^",
+ "@traversable/registry": "workspace:^"
+ }
+} as const
\ No newline at end of file
diff --git a/packages/graphql/src/exports.ts b/packages/graphql/src/exports.ts
new file mode 100644
index 00000000..c58b54ea
--- /dev/null
+++ b/packages/graphql/src/exports.ts
@@ -0,0 +1 @@
+export { VERSION } from './version.js'
diff --git a/packages/graphql/src/index.ts b/packages/graphql/src/index.ts
new file mode 100644
index 00000000..410a4bcb
--- /dev/null
+++ b/packages/graphql/src/index.ts
@@ -0,0 +1 @@
+export * from './exports.js'
diff --git a/packages/graphql/src/version.ts b/packages/graphql/src/version.ts
new file mode 100644
index 00000000..660ff1ca
--- /dev/null
+++ b/packages/graphql/src/version.ts
@@ -0,0 +1,3 @@
+import pkg from './__generated__/__manifest__.js'
+export const VERSION = `${pkg.name}@${pkg.version}` as const
+export type VERSION = typeof VERSION
diff --git a/packages/graphql/test/version.test.ts b/packages/graphql/test/version.test.ts
new file mode 100644
index 00000000..48330e1b
--- /dev/null
+++ b/packages/graphql/test/version.test.ts
@@ -0,0 +1,10 @@
+import * as vi from 'vitest'
+import pkg from '../package.json' with { type: 'json' }
+import { VERSION } from '@traversable/graphql'
+
+vi.describe('ใโณ๏ธใโนโนโน โฒ@traversable/graphqlโณ', () => {
+ vi.test('ใโณ๏ธใโบ โฒVERSIONโณ', () => {
+ const expected = `${pkg.name}@${pkg.version}`
+ vi.assert.equal(VERSION, expected)
+ })
+})
diff --git a/packages/graphql/tsconfig.build.json b/packages/graphql/tsconfig.build.json
new file mode 100644
index 00000000..16c1c0e4
--- /dev/null
+++ b/packages/graphql/tsconfig.build.json
@@ -0,0 +1,11 @@
+{
+ "extends": "./tsconfig.src.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/build.tsbuildinfo",
+ "types": ["node"],
+ "declarationDir": "build/dts",
+ "outDir": "build/esm",
+ "stripInternal": true
+ },
+ "references": [{ "path": "../graphql-types" }, { "path": "../registry" }]
+}
diff --git a/packages/graphql/tsconfig.json b/packages/graphql/tsconfig.json
new file mode 100644
index 00000000..2c291d21
--- /dev/null
+++ b/packages/graphql/tsconfig.json
@@ -0,0 +1,8 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "include": [],
+ "references": [
+ { "path": "tsconfig.src.json" },
+ { "path": "tsconfig.test.json" }
+ ]
+}
diff --git a/packages/graphql/tsconfig.src.json b/packages/graphql/tsconfig.src.json
new file mode 100644
index 00000000..c110a318
--- /dev/null
+++ b/packages/graphql/tsconfig.src.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/src.tsbuildinfo",
+ "rootDir": "src",
+ "types": ["node"],
+ "outDir": "build/src"
+ },
+ "references": [{ "path": "../graphql-types" }, { "path": "../registry" }],
+ "include": ["src"]
+}
diff --git a/packages/graphql/tsconfig.test.json b/packages/graphql/tsconfig.test.json
new file mode 100644
index 00000000..e318a1ea
--- /dev/null
+++ b/packages/graphql/tsconfig.test.json
@@ -0,0 +1,15 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "tsBuildInfoFile": ".tsbuildinfo/test.tsbuildinfo",
+ "rootDir": "test",
+ "types": ["node"],
+ "noEmit": true
+ },
+ "references": [
+ { "path": "tsconfig.src.json" },
+ { "path": "../graphql-types" },
+ { "path": "../registry" }
+ ],
+ "include": ["test"]
+}
diff --git a/packages/graphql/vite.config.ts b/packages/graphql/vite.config.ts
new file mode 100644
index 00000000..64dba4ad
--- /dev/null
+++ b/packages/graphql/vite.config.ts
@@ -0,0 +1,6 @@
+import { defineConfig, mergeConfig } from 'vitest/config'
+import sharedConfig from '../../vite.config.js'
+
+const localConfig = defineConfig({})
+
+export default mergeConfig(sharedConfig, localConfig)
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5737f9ce..493f8210 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -288,6 +288,39 @@ importers:
version: 2.1.20
publishDirectory: dist
+ packages/graphql:
+ dependencies:
+ '@traversable/graphql-types':
+ specifier: workspace:^
+ version: link:../graphql-types/dist
+ '@traversable/registry':
+ specifier: workspace:^
+ version: link:../registry/dist
+ publishDirectory: dist
+
+ packages/graphql-test:
+ devDependencies:
+ '@traversable/graphql-types':
+ specifier: workspace:^
+ version: link:../graphql-types/dist
+ '@traversable/registry':
+ specifier: workspace:^
+ version: link:../registry/dist
+ publishDirectory: dist
+
+ packages/graphql-types:
+ devDependencies:
+ '@prettier/sync':
+ specifier: 'catalog:'
+ version: 0.5.5(prettier@3.6.2)
+ '@traversable/registry':
+ specifier: workspace:^
+ version: link:../registry/dist
+ graphql:
+ specifier: ^16.11.0
+ version: 16.11.0
+ publishDirectory: dist
+
packages/json:
dependencies:
fast-check:
@@ -2371,6 +2404,10 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ graphql@16.11.0:
+ resolution: {integrity: sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==}
+ engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
+
has-bigints@1.1.0:
resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==}
engines: {node: '>= 0.4'}
@@ -5391,6 +5428,8 @@ snapshots:
graphemer@1.4.0: {}
+ graphql@16.11.0: {}
+
has-bigints@1.1.0: {}
has-flag@4.0.0: {}
diff --git a/tsconfig.base.json b/tsconfig.base.json
index b4c61481..8f24b6d6 100644
--- a/tsconfig.base.json
+++ b/tsconfig.base.json
@@ -34,6 +34,12 @@
"@traversable/arktype-types": ["packages/arktype-types/src/index.js"],
"@traversable/arktype-types/*": ["packages/arktype-types/*.js"],
"@traversable/arktype/*": ["packages/arktype/*.js"],
+ "@traversable/graphql": ["packages/graphql/src/index.js"],
+ "@traversable/graphql-test": ["packages/graphql-test/src/index.js"],
+ "@traversable/graphql-test/*": ["packages/graphql-test/*.js"],
+ "@traversable/graphql-types": ["packages/graphql-types/src/index.js"],
+ "@traversable/graphql-types/*": ["packages/graphql-types/*.js"],
+ "@traversable/graphql/*": ["packages/graphql/*.js"],
"@traversable/json": ["packages/json/src/index.js"],
"@traversable/json-schema": ["packages/json-schema/src/index.js"],
"@traversable/json-schema-test": [
diff --git a/tsconfig.build.json b/tsconfig.build.json
index f3db1e87..fa2f292f 100644
--- a/tsconfig.build.json
+++ b/tsconfig.build.json
@@ -5,6 +5,9 @@
{ "path": "packages/arktype-test/tsconfig.build.json" },
{ "path": "packages/arktype-types/tsconfig.build.json" },
{ "path": "packages/arktype/tsconfig.build.json" },
+ { "path": "packages/graphql-test/tsconfig.build.json" },
+ { "path": "packages/graphql-types/tsconfig.build.json" },
+ { "path": "packages/graphql/tsconfig.build.json" },
{ "path": "packages/json-schema-test/tsconfig.build.json" },
{ "path": "packages/json-schema-types/tsconfig.build.json" },
{ "path": "packages/json-schema/tsconfig.build.json" },
diff --git a/tsconfig.json b/tsconfig.json
index bb6039f0..fe1a435d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,6 +5,9 @@
{ "path": "packages/arktype" },
{ "path": "packages/arktype-test" },
{ "path": "packages/arktype-types" },
+ { "path": "packages/graphql" },
+ { "path": "packages/graphql-test" },
+ { "path": "packages/graphql-types" },
{ "path": "packages/json" },
{ "path": "packages/json-schema" },
{ "path": "packages/json-schema-test" },