diff --git a/examples/complex-app/CHANGELOG.md b/examples/complex-app/CHANGELOG.md index b0f57de68..9bb1f6bac 100644 --- a/examples/complex-app/CHANGELOG.md +++ b/examples/complex-app/CHANGELOG.md @@ -1,5 +1,15 @@ # @pothos-examples/complex-app +## 1.4.28 + +### Patch Changes + +- Updated dependencies [d60cb49e] + - @pothos/plugin-relay@3.36.0 + - @pothos/plugin-dataloader@3.14.0 + - @pothos/plugin-prisma@3.41.0 + - @pothos/plugin-scope-auth@3.18.0 + ## 1.4.27 ### Patch Changes diff --git a/examples/complex-app/package.json b/examples/complex-app/package.json index 27018adbc..1b3927231 100644 --- a/examples/complex-app/package.json +++ b/examples/complex-app/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "1.4.27", + "version": "1.4.28", "name": "@pothos-examples/complex-app", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/envelope-helix-fastify/CHANGELOG.md b/examples/envelope-helix-fastify/CHANGELOG.md index 70d4f9cd7..0aa2368c9 100644 --- a/examples/envelope-helix-fastify/CHANGELOG.md +++ b/examples/envelope-helix-fastify/CHANGELOG.md @@ -1,5 +1,12 @@ # @pothos-examples/envelope-helix-fastify +## 2.4.20 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + ## 2.4.19 ### Patch Changes diff --git a/examples/envelope-helix-fastify/package.json b/examples/envelope-helix-fastify/package.json index cc3c7ce7a..fc28876b0 100644 --- a/examples/envelope-helix-fastify/package.json +++ b/examples/envelope-helix-fastify/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.4.19", + "version": "2.4.20", "name": "@pothos-examples/envelope-helix-fastify", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/graphql-shield/CHANGELOG.md b/examples/graphql-shield/CHANGELOG.md index c037daf4d..c686aef98 100644 --- a/examples/graphql-shield/CHANGELOG.md +++ b/examples/graphql-shield/CHANGELOG.md @@ -1,5 +1,12 @@ # @pothos-examples/graphql-shield +## 2.2.20 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + ## 2.2.19 ### Patch Changes diff --git a/examples/graphql-shield/package.json b/examples/graphql-shield/package.json index b82da67b9..959265210 100644 --- a/examples/graphql-shield/package.json +++ b/examples/graphql-shield/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.2.19", + "version": "2.2.20", "name": "@pothos-examples/graphql-shield", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/helix/CHANGELOG.md b/examples/helix/CHANGELOG.md index 0445a4f8e..7f5ba47c7 100644 --- a/examples/helix/CHANGELOG.md +++ b/examples/helix/CHANGELOG.md @@ -1,5 +1,12 @@ # @pothos-examples/helix +## 2.4.20 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + ## 2.4.19 ### Patch Changes diff --git a/examples/helix/package.json b/examples/helix/package.json index 31fb5f77a..232aa459b 100644 --- a/examples/helix/package.json +++ b/examples/helix/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.4.19", + "version": "2.4.20", "name": "@pothos-examples/helix", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/nextjs/CHANGELOG.md b/examples/nextjs/CHANGELOG.md index 5ad10fd6d..3c86a9052 100644 --- a/examples/nextjs/CHANGELOG.md +++ b/examples/nextjs/CHANGELOG.md @@ -1,5 +1,12 @@ # @pothos-examples/nextjs +## 2.6.3 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + ## 2.6.2 ### Patch Changes diff --git a/examples/nextjs/package.json b/examples/nextjs/package.json index 33511e36a..ff9fdba42 100644 --- a/examples/nextjs/package.json +++ b/examples/nextjs/package.json @@ -1,6 +1,6 @@ { "name": "@pothos-examples/nextjs", - "version": "2.6.2", + "version": "2.6.3", "private": true, "scripts": { "generate": "graphql-codegen", diff --git a/examples/open-telemetry/CHANGELOG.md b/examples/open-telemetry/CHANGELOG.md index c99860f3d..5a58ac021 100644 --- a/examples/open-telemetry/CHANGELOG.md +++ b/examples/open-telemetry/CHANGELOG.md @@ -1,5 +1,14 @@ # @pothos-examples/open-telemetry +## 1.2.20 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + - @pothos/plugin-tracing@0.5.7 + - @pothos/tracing-opentelemetry@0.6.8 + ## 1.2.19 ### Patch Changes diff --git a/examples/open-telemetry/package.json b/examples/open-telemetry/package.json index fd0bed17b..cccf0bc76 100644 --- a/examples/open-telemetry/package.json +++ b/examples/open-telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@pothos-examples/open-telemetry", - "version": "1.2.19", + "version": "1.2.20", "main": "index.js", "license": "MIT", "dependencies": { diff --git a/examples/prisma-federation/CHANGELOG.md b/examples/prisma-federation/CHANGELOG.md index 08a6f1c32..875f055d2 100644 --- a/examples/prisma-federation/CHANGELOG.md +++ b/examples/prisma-federation/CHANGELOG.md @@ -1,5 +1,15 @@ # @pothos-examples/relay +## 2.7.4 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + - @pothos/plugin-directives@3.9.2 + - @pothos/plugin-federation@3.9.1 + - @pothos/plugin-prisma@3.41.0 + ## 2.7.3 ### Patch Changes diff --git a/examples/prisma-federation/package.json b/examples/prisma-federation/package.json index dea97a8eb..0454fe78c 100644 --- a/examples/prisma-federation/package.json +++ b/examples/prisma-federation/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.7.3", + "version": "2.7.4", "name": "@pothos-examples/prisma-federation", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/prisma-relay/CHANGELOG.md b/examples/prisma-relay/CHANGELOG.md index 55e67f0eb..c8e2f2e65 100644 --- a/examples/prisma-relay/CHANGELOG.md +++ b/examples/prisma-relay/CHANGELOG.md @@ -1,5 +1,13 @@ # @pothos-examples/prisma-relay +## 2.7.26 + +### Patch Changes + +- Updated dependencies [d60cb49e] + - @pothos/plugin-relay@3.36.0 + - @pothos/plugin-prisma@3.41.0 + ## 2.7.25 ### Patch Changes diff --git a/examples/prisma-relay/package.json b/examples/prisma-relay/package.json index 0f003c272..f09cc86d5 100644 --- a/examples/prisma-relay/package.json +++ b/examples/prisma-relay/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.7.25", + "version": "2.7.26", "name": "@pothos-examples/prisma-relay", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/prisma-smart-subscriptions-apollo/CHANGELOG.md b/examples/prisma-smart-subscriptions-apollo/CHANGELOG.md index 4299b1fcd..20cda5570 100644 --- a/examples/prisma-smart-subscriptions-apollo/CHANGELOG.md +++ b/examples/prisma-smart-subscriptions-apollo/CHANGELOG.md @@ -1,5 +1,14 @@ # @pothos-examples/prisma-smart-subscriptions-apollo +## 2.5.3 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + - @pothos/plugin-prisma@3.41.0 + - @pothos/plugin-smart-subscriptions@3.7.0 + ## 2.5.2 ### Patch Changes diff --git a/examples/prisma-smart-subscriptions-apollo/package.json b/examples/prisma-smart-subscriptions-apollo/package.json index 821c2acb6..119e18e7b 100644 --- a/examples/prisma-smart-subscriptions-apollo/package.json +++ b/examples/prisma-smart-subscriptions-apollo/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.5.2", + "version": "2.5.3", "name": "@pothos-examples/prisma-smart-subscriptions-apollo", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/prisma-subscriptions/CHANGELOG.md b/examples/prisma-subscriptions/CHANGELOG.md index 3b0209e07..977631aa1 100644 --- a/examples/prisma-subscriptions/CHANGELOG.md +++ b/examples/prisma-subscriptions/CHANGELOG.md @@ -1,5 +1,13 @@ # @pothos-examples/prisma-subscriptions +## 2.4.25 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + - @pothos/plugin-prisma@3.41.0 + ## 2.4.24 ### Patch Changes diff --git a/examples/prisma-subscriptions/package.json b/examples/prisma-subscriptions/package.json index be371ac75..248d38c7b 100644 --- a/examples/prisma-subscriptions/package.json +++ b/examples/prisma-subscriptions/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.4.24", + "version": "2.4.25", "name": "@pothos-examples/prisma-subscriptions", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/prisma/CHANGELOG.md b/examples/prisma/CHANGELOG.md index d0732aaae..29d3973d1 100644 --- a/examples/prisma/CHANGELOG.md +++ b/examples/prisma/CHANGELOG.md @@ -1,5 +1,13 @@ # @pothos-examples/relay +## 2.4.25 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + - @pothos/plugin-prisma@3.41.0 + ## 2.4.24 ### Patch Changes diff --git a/examples/prisma/package.json b/examples/prisma/package.json index 2ccd46d28..975a72743 100644 --- a/examples/prisma/package.json +++ b/examples/prisma/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.4.24", + "version": "2.4.25", "name": "@pothos-examples/prisma", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/relay-windowed-pagination/CHANGELOG.md b/examples/relay-windowed-pagination/CHANGELOG.md index 9a38659d2..68cdc6e27 100644 --- a/examples/relay-windowed-pagination/CHANGELOG.md +++ b/examples/relay-windowed-pagination/CHANGELOG.md @@ -1,5 +1,20 @@ # @pothos-examples/prisma-relay +## 2.7.26 + +### Patch Changes + +- Updated dependencies [d60cb49e] + - @pothos/plugin-relay@3.36.0 + +## 2.7.25 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + - @pothos/plugin-relay@3.35.0 + ## 2.7.24 ### Patch Changes diff --git a/examples/relay-windowed-pagination/package.json b/examples/relay-windowed-pagination/package.json index 2664722c6..f1bae9ffe 100644 --- a/examples/relay-windowed-pagination/package.json +++ b/examples/relay-windowed-pagination/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.7.24", + "version": "2.7.26", "name": "@pothos-examples/relay-windowed-pagination", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/simple-classes/CHANGELOG.md b/examples/simple-classes/CHANGELOG.md index 75302e8ca..195ae639a 100644 --- a/examples/simple-classes/CHANGELOG.md +++ b/examples/simple-classes/CHANGELOG.md @@ -1,5 +1,12 @@ # @pothos-examples/simple-classes +## 2.4.20 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + ## 2.4.19 ### Patch Changes diff --git a/examples/simple-classes/package.json b/examples/simple-classes/package.json index 7ac533ca6..2de2a0c6a 100644 --- a/examples/simple-classes/package.json +++ b/examples/simple-classes/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.4.19", + "version": "2.4.20", "name": "@pothos-examples/simple-classes", "main": "src/index.ts", "types": "src/index.ts", diff --git a/examples/simple-interfaces/CHANGELOG.md b/examples/simple-interfaces/CHANGELOG.md index d0a294170..3134677af 100644 --- a/examples/simple-interfaces/CHANGELOG.md +++ b/examples/simple-interfaces/CHANGELOG.md @@ -1,5 +1,12 @@ # @pothos-examples/simple-interfaces +## 2.4.20 + +### Patch Changes + +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + ## 2.4.19 ### Patch Changes diff --git a/examples/simple-interfaces/package.json b/examples/simple-interfaces/package.json index de09047b5..b1caca094 100644 --- a/examples/simple-interfaces/package.json +++ b/examples/simple-interfaces/package.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/package.json", - "version": "2.4.19", + "version": "2.4.20", "name": "@pothos-examples/simple-interfaces", "main": "src/index.ts", "types": "src/index.ts", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 3d74353f9..bef60fb9b 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 3.27.0 + +### Minor Changes + +- 42bf6190: Allow unionType to receive types as a thunk + ## 3.26.0 ### Minor Changes diff --git a/packages/core/package.json b/packages/core/package.json index b1fb6b2f9..c554fdb9a 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@pothos/core", - "version": "3.26.0", + "version": "3.27.0", "description": "Pothos (formerly GiraphQL) is a plugin based schema builder for creating code-first GraphQL schemas in typescript", "main": "./lib/index.js", "types": "./dts/index.d.ts", diff --git a/packages/core/src/builder.ts b/packages/core/src/builder.ts index 8ebe7bfae..46ea21d27 100644 --- a/packages/core/src/builder.ts +++ b/packages/core/src/builder.ts @@ -423,15 +423,17 @@ export default class SchemaBuilder { ParentShape >(name); - options.types.forEach((type) => { - verifyRef(type); - }); + if (Array.isArray(options.types)) { + options.types.forEach((type) => { + verifyRef(type); + }); + } const config: PothosUnionTypeConfig = { kind: 'Union', graphqlKind: 'Union', name, - types: (options.types || []) as ObjectParam[], + types: [], description: options.description, resolveType: options.resolveType as GraphQLTypeResolver, pothosOptions: options as unknown as PothosSchemaTypes.UnionTypeOptions, @@ -439,6 +441,7 @@ export default class SchemaBuilder { }; this.configStore.addTypeConfig(config, ref); + this.configStore.addUnionTypes(name, options.types); return ref; } diff --git a/packages/core/src/config-store.ts b/packages/core/src/config-store.ts index ef7bb0a66..6e2210812 100644 --- a/packages/core/src/config-store.ts +++ b/packages/core/src/config-store.ts @@ -26,6 +26,7 @@ import type { InputType, InputTypeParam, InterfaceParam, + ObjectParam, OutputRef, OutputType, PothosFieldConfig, @@ -62,6 +63,8 @@ export default class ConfigStore { private pendingInterfaces = new Map InterfaceParam[])[]>(); + private pendingUnionTypes = new Map ObjectParam[])[]>(); + private pendingRefResolutions = new Map< ConfigurableRef, ((config: PothosTypeConfig) => void)[] @@ -98,6 +101,31 @@ export default class ConfigStore { return this.refsToName.has(typeParam); } + addUnionTypes(typeName: string, unionTypes: ObjectParam[] | (() => ObjectParam[])) { + if (typeof unionTypes === 'function' && this.pending) { + if (this.pendingUnionTypes.has(typeName)) { + this.pendingUnionTypes.get(typeName)!.push(unionTypes); + } else { + this.pendingUnionTypes.set(typeName, [unionTypes]); + } + } else { + const typeConfig = this.getTypeConfig(typeName); + + if (typeConfig.graphqlKind !== 'Union') { + throw new PothosSchemaError( + `Can not add types to ${typeName} because it is a ${typeConfig.kind}`, + ); + } + + typeConfig.types = [ + ...typeConfig.types, + ...((typeof unionTypes === 'function' + ? unionTypes() + : unionTypes) as ObjectParam[]), + ]; + } + } + addInterfaces( typeName: string, interfaces: InterfaceParam[] | (() => InterfaceParam[]), @@ -428,6 +456,12 @@ export default class ConfigStore { ); } + for (const [typeName, unionFns] of this.pendingUnionTypes) { + for (const fn of unionFns) { + this.addUnionTypes(typeName, fn); + } + } + for (const [typeName, interfacesFns] of this.pendingInterfaces) { for (const fn of interfacesFns) { this.addInterfaces(typeName, fn); diff --git a/packages/core/src/types/global/type-options.ts b/packages/core/src/types/global/type-options.ts index bb6818ed9..4d3342caa 100644 --- a/packages/core/src/types/global/type-options.ts +++ b/packages/core/src/types/global/type-options.ts @@ -98,7 +98,7 @@ declare global { Member extends ObjectParam = ObjectParam, ResolveType = unknown, > extends BaseTypeOptions { - types: Member[]; + types: Member[] | (() => Member[]); resolveType?: ResolveType & (( parent: ParentShape, diff --git a/packages/core/tests/examples/giraffes/unions.ts b/packages/core/tests/examples/giraffes/unions.ts index e42b191f1..774acdfb9 100644 --- a/packages/core/tests/examples/giraffes/unions.ts +++ b/packages/core/tests/examples/giraffes/unions.ts @@ -14,7 +14,7 @@ const GiraffeNumericFact = builder.objectType('GiraffeNumericFact', { }); const GiraffeFact = builder.unionType('GiraffeFact', { - types: ['GiraffeStringFact', GiraffeNumericFact], + types: () => ['GiraffeStringFact', GiraffeNumericFact], resolveType: (fact) => { switch (fact.factKind) { case 'number': diff --git a/packages/deno/CHANGELOG.md b/packages/deno/CHANGELOG.md index 898f52621..7d8946ecd 100644 --- a/packages/deno/CHANGELOG.md +++ b/packages/deno/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 3.38.0 + +### Minor Changes + +- 42bf6190: Allow unionType to receive types as a thunk + ## 3.37.0 ### Minor Changes diff --git a/packages/deno/package.json b/packages/deno/package.json index 00d77495f..08ce2925f 100644 --- a/packages/deno/package.json +++ b/packages/deno/package.json @@ -1,6 +1,6 @@ { "name": "@pothos/deno", - "version": "3.37.0", + "version": "3.38.0", "description": "Deno compatible versions of Pothos packages", "repository": { "type": "git", diff --git a/packages/deno/packages/core/builder.ts b/packages/deno/packages/core/builder.ts index ead29f850..ad6dadef7 100644 --- a/packages/deno/packages/core/builder.ts +++ b/packages/deno/packages/core/builder.ts @@ -248,20 +248,23 @@ export default class SchemaBuilder { } unionType, ResolveType>(name: string, options: PothosSchemaTypes.UnionTypeOptions) { const ref = new UnionRef, ParentShape>(name); - options.types.forEach((type) => { - verifyRef(type); - }); + if (Array.isArray(options.types)) { + options.types.forEach((type) => { + verifyRef(type); + }); + } const config: PothosUnionTypeConfig = { kind: "Union", graphqlKind: "Union", name, - types: (options.types || []) as ObjectParam[], + types: [], description: options.description, resolveType: options.resolveType as GraphQLTypeResolver, pothosOptions: options as unknown as PothosSchemaTypes.UnionTypeOptions, extensions: options.extensions, }; this.configStore.addTypeConfig(config, ref); + this.configStore.addUnionTypes(name, options.types); return ref; } enumType>(param: Param, options: EnumTypeOptions) { diff --git a/packages/deno/packages/core/config-store.ts b/packages/deno/packages/core/config-store.ts index 29bb80f3a..452c6a3a4 100644 --- a/packages/deno/packages/core/config-store.ts +++ b/packages/deno/packages/core/config-store.ts @@ -11,7 +11,7 @@ import InputFieldRef from './refs/input-field.ts'; import InputListRef from './refs/input-list.ts'; import ListRef from './refs/list.ts'; import OutputTypeRef from './refs/output.ts'; -import type { ConfigurableRef, FieldMap, GraphQLFieldKind, InputFieldMap, InputRef, InputType, InputTypeParam, InterfaceParam, OutputRef, OutputType, PothosFieldConfig, PothosObjectTypeConfig, PothosTypeConfig, SchemaTypes, TypeParam, } from './types/index.ts'; +import type { ConfigurableRef, FieldMap, GraphQLFieldKind, InputFieldMap, InputRef, InputType, InputTypeParam, InterfaceParam, ObjectParam, OutputRef, OutputType, PothosFieldConfig, PothosObjectTypeConfig, PothosTypeConfig, SchemaTypes, TypeParam, } from './types/index.ts'; import { unwrapListParam } from './utils/index.ts'; export default class ConfigStore { typeConfigs = new Map(); @@ -23,6 +23,7 @@ export default class ConfigStore { private fieldRefsToConfigs = new Map[]>(); private pendingFields = new Map | OutputType>(); private pendingInterfaces = new Map InterfaceParam[])[]>(); + private pendingUnionTypes = new Map ObjectParam[])[]>(); private pendingRefResolutions = new Map, ((config: PothosTypeConfig) => void)[]>(); private fieldRefCallbacks = new Map) => void)[]>(); private pending = true; @@ -46,6 +47,28 @@ export default class ConfigStore { } return this.refsToName.has(typeParam); } + addUnionTypes(typeName: string, unionTypes: ObjectParam[] | (() => ObjectParam[])) { + if (typeof unionTypes === "function" && this.pending) { + if (this.pendingUnionTypes.has(typeName)) { + this.pendingUnionTypes.get(typeName)!.push(unionTypes); + } + else { + this.pendingUnionTypes.set(typeName, [unionTypes]); + } + } + else { + const typeConfig = this.getTypeConfig(typeName); + if (typeConfig.graphqlKind !== "Union") { + throw new PothosSchemaError(`Can not add types to ${typeName} because it is a ${typeConfig.kind}`); + } + typeConfig.types = [ + ...typeConfig.types, + ...((typeof unionTypes === "function" + ? unionTypes() + : unionTypes) as ObjectParam[]), + ]; + } + } addInterfaces(typeName: string, interfaces: InterfaceParam[] | (() => InterfaceParam[])) { if (typeof interfaces === "function" && this.pending) { if (this.pendingInterfaces.has(typeName)) { @@ -280,6 +303,11 @@ export default class ConfigStore { .map((ref) => this.describeRef(ref)) .join(", ")}).`); } + for (const [typeName, unionFns] of this.pendingUnionTypes) { + for (const fn of unionFns) { + this.addUnionTypes(typeName, fn); + } + } for (const [typeName, interfacesFns] of this.pendingInterfaces) { for (const fn of interfacesFns) { this.addInterfaces(typeName, fn); diff --git a/packages/deno/packages/core/types/global/type-options.ts b/packages/deno/packages/core/types/global/type-options.ts index c796aac2b..fc4f1c10f 100644 --- a/packages/deno/packages/core/types/global/type-options.ts +++ b/packages/deno/packages/core/types/global/type-options.ts @@ -42,7 +42,7 @@ declare global { resolveType?: ResolveType & ((parent: Shape, context: Types["Context"], info: GraphQLResolveInfo, type: GraphQLUnionType) => MaybePromise | string | null | undefined>); } export interface UnionTypeOptions = ObjectParam, ResolveType = unknown> extends BaseTypeOptions { - types: Member[]; + types: Member[] | (() => Member[]); resolveType?: ResolveType & ((parent: ParentShape, context: Types["Context"], info: GraphQLResolveInfo, type: GraphQLUnionType) => MaybePromise); } export interface ScalarTypeOptions extends BaseTypeOptions { diff --git a/packages/deno/packages/plugin-relay/utils/global-ids.ts b/packages/deno/packages/plugin-relay/utils/global-ids.ts index 43643d0fc..58c62755b 100644 --- a/packages/deno/packages/plugin-relay/utils/global-ids.ts +++ b/packages/deno/packages/plugin-relay/utils/global-ids.ts @@ -4,9 +4,10 @@ export function encodeGlobalID(typename: string, id: bigint | number | string) { return encodeBase64(`${typename}:${id}`); } export function decodeGlobalID(globalID: string) { - const [typename, id] = decodeBase64(globalID).split(":"); + const decoded = decodeBase64(globalID).split(":"); + const [typename, id] = decoded; if (!typename || !id) { throw new PothosValidationError(`Invalid global ID: ${globalID}`); } - return { typename, id }; + return { typename, id: decoded.length > 2 ? decoded.slice(1).join(":") : id }; } diff --git a/packages/plugin-relay/CHANGELOG.md b/packages/plugin-relay/CHANGELOG.md index deeb54d5c..08b2b6ca9 100644 --- a/packages/plugin-relay/CHANGELOG.md +++ b/packages/plugin-relay/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 3.36.0 + +### Minor Changes + +- d60cb49e: handle string contining ':' in global ID + ## 3.35.0 ### Minor Changes diff --git a/packages/plugin-relay/package.json b/packages/plugin-relay/package.json index 9ac934625..da763fee5 100644 --- a/packages/plugin-relay/package.json +++ b/packages/plugin-relay/package.json @@ -1,6 +1,6 @@ { "name": "@pothos/plugin-relay", - "version": "3.35.0", + "version": "3.36.0", "description": "A Pothos plugin for adding relay style connections, nodes, and cursor based pagination to your GraphQL schema", "main": "./lib/index.js", "types": "./dts/index.d.ts", diff --git a/packages/plugin-relay/src/utils/global-ids.ts b/packages/plugin-relay/src/utils/global-ids.ts index 666e3a209..2ec02d9c1 100644 --- a/packages/plugin-relay/src/utils/global-ids.ts +++ b/packages/plugin-relay/src/utils/global-ids.ts @@ -5,11 +5,12 @@ export function encodeGlobalID(typename: string, id: bigint | number | string) { } export function decodeGlobalID(globalID: string) { - const [typename, id] = decodeBase64(globalID).split(':'); + const decoded = decodeBase64(globalID).split(':'); + const [typename, id] = decoded; if (!typename || !id) { throw new PothosValidationError(`Invalid global ID: ${globalID}`); } - return { typename, id }; + return { typename, id: decoded.length > 2 ? decoded.slice(1).join(':') : id }; } diff --git a/packages/plugin-relay/tests/__snapshots__/index.test.ts.snap b/packages/plugin-relay/tests/__snapshots__/index.test.ts.snap index ea0bd4526..b49a781a9 100644 --- a/packages/plugin-relay/tests/__snapshots__/index.test.ts.snap +++ b/packages/plugin-relay/tests/__snapshots__/index.test.ts.snap @@ -53,6 +53,11 @@ type IDResult { typename: String! } +type IDWithColon implements Node { + id: ID! + idString: String! +} + type Mutation { answerPoll(answer: Int!, id: ID!): Poll! createPoll(answers: [String!]!, question: String!): Poll! @@ -137,6 +142,8 @@ type Query { cursorConnection(after: ID, before: ID, first: Int, last: Int): QueryCursorConnection! echoIDs(genericNumberThingID: ID!, globalID: ID!, numberThingID: ID!): [IDResult!]! extraNode: Node + idWithColon(id: ID!): IDWithColon! + idsWithColon(ids: [ID!]!): [IDWithColon!]! inputGlobalID(id: ID!, inputObj: GlobalIDInput!, normalId: ID!): String! moreNodes: [Node]! node(id: ID!): Node diff --git a/packages/plugin-relay/tests/examples/relay/schema/numbers.ts b/packages/plugin-relay/tests/examples/relay/schema/numbers.ts index cd151ecc5..348758ea5 100644 --- a/packages/plugin-relay/tests/examples/relay/schema/numbers.ts +++ b/packages/plugin-relay/tests/examples/relay/schema/numbers.ts @@ -1,6 +1,17 @@ import { resolveArrayConnection, resolveOffsetConnection } from '../../../../src'; import builder from '../builder'; +class IDWithColon { + id: string; + + constructor(id: string) { + if (!id.includes(':')) { + throw new TypeError(`Expected id to have a colon, saw ${id}`); + } + this.id = id; + } +} + class NumberThing { id: number; @@ -25,6 +36,16 @@ class BatchLoadableNumberThing { } } +const IDWithColonRef = builder.node(IDWithColon, { + name: 'IDWithColon', + id: { + resolve: (n) => n.id, + }, + fields: (t) => ({ + idString: t.exposeString('id'), + }), +}); + const NumberThingRef = builder.node(NumberThing, { id: { resolve: (n) => n.id, @@ -215,6 +236,26 @@ builder.queryField('sharedEdgeConnection', (t) => ), ); +builder.queryField('idWithColon', (t) => + t.field({ + type: IDWithColonRef, + args: { + id: t.arg.globalID({ required: true, for: [IDWithColonRef] }), + }, + resolve: (root, args) => new IDWithColon(args.id.id), + }), +); + +builder.queryField('idsWithColon', (t) => + t.field({ + type: [IDWithColonRef], + args: { + ids: t.arg.globalIDList({ required: true, for: [IDWithColonRef] }), + }, + resolve: (root, args) => args.ids.map((id) => new IDWithColon(id.id)), + }), +); + builder.queryField('numberThingByID', (t) => t.field({ type: NumberThing, diff --git a/packages/plugin-relay/tests/index.test.ts b/packages/plugin-relay/tests/index.test.ts index d362bd7e1..84015ed6c 100644 --- a/packages/plugin-relay/tests/index.test.ts +++ b/packages/plugin-relay/tests/index.test.ts @@ -513,6 +513,14 @@ describe('relay example schema', () => { it('parses ids', async () => { const query = gql` query { + idWithColon(id: "SURXaXRoQ29sb246MTp0ZXN0") { + id + idString + } + idsWithColon(ids: ["SURXaXRoQ29sb246MTp0ZXN0", "SURXaXRoQ29sb246Mjp0ZXN0OmV4YW1wbGU="]) { + id + idString + } numberThingByID(id: "TnVtYmVyOjE=") { id number @@ -571,6 +579,20 @@ describe('relay example schema', () => { "typename": "Number", }, ], + "idWithColon": { + "id": "SURXaXRoQ29sb246MTp0ZXN0", + "idString": "1:test", + }, + "idsWithColon": [ + { + "id": "SURXaXRoQ29sb246MTp0ZXN0", + "idString": "1:test", + }, + { + "id": "SURXaXRoQ29sb246Mjp0ZXN0OmV4YW1wbGU=", + "idString": "2:test:example", + }, + ], "invalid": null, "invalidList": null, "numberThingByID": { diff --git a/website/CHANGELOG.md b/website/CHANGELOG.md index 5262a125a..5e0aa683e 100644 --- a/website/CHANGELOG.md +++ b/website/CHANGELOG.md @@ -4,6 +4,13 @@ ### Patch Changes +- Updated dependencies [42bf6190] + - @pothos/core@3.27.0 + +## null + +### Patch Changes + - Updated dependencies [ec411ea1] - @pothos/core@3.26.0 diff --git a/website/pages/docs/api/schema-builder.mdx b/website/pages/docs/api/schema-builder.mdx index 07c3796cc..7724c1c5b 100644 --- a/website/pages/docs/api/schema-builder.mdx +++ b/website/pages/docs/api/schema-builder.mdx @@ -295,7 +295,7 @@ all types in SchemaTypes, or import the actual implementation of each interface ```typescript type UnionTypeOptions = { description?: string; - types: Member[]; + types: Member[] | (() => Member[]); resolveType: (parent: UnionShape, context) => MaybePromise; }; ``` diff --git a/website/pages/docs/guide/circular-references.mdx b/website/pages/docs/guide/circular-references.mdx index 933f9ff05..963d55676 100644 --- a/website/pages/docs/guide/circular-references.mdx +++ b/website/pages/docs/guide/circular-references.mdx @@ -45,7 +45,7 @@ loaded, these types of Circular imports should work without causing any issues. import { Post } from './post' export const User = builder.objectType('User', { - fields: t => ({ posts: t.t.expose('posts', { type: [Post]}) }), + fields: t => ({ posts: t.expose('posts', { type: [Post]}) }), }) // post.ts