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 +

+ +
+ NPM Version +   + TypeScript +   + License +   + npm +   +
+ +
+ + Static Badge +   + Static Badge +   + Static Badge +   +
+ +
+ Demo (StackBlitz) +   โ€ข   + TypeScript Playground +   โ€ข   + npm +
+
+
+
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. +

+ +
+ NPM Version +   + TypeScript +   + License +   + npm +   +
+ +
+ + Static Badge +   + Static Badge +   + Static Badge +   +
+ +
+ Demo (StackBlitz) +   โ€ข   + TypeScript Playground +   โ€ข   + npm +
+
+
+
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 +

+ +
+ NPM Version +   + TypeScript +   + License +   + npm +   +
+ +
+ + Static Badge +   + Static Badge +   + Static Badge +   +
+ +
+ Demo (StackBlitz) +   โ€ข   + TypeScript Playground +   โ€ข   + npm +
+
+
+
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" },