From c83e8a54f37802ec14e3242ad8f21a0aa42fb74e Mon Sep 17 00:00:00 2001 From: BenjAIe Date: Tue, 4 Aug 2026 12:29:57 +0100 Subject: [PATCH 1/6] Fix PgResourceUnique attribute tuple typing --- grafast/dataplan-pg/src/datasource.ts | 4 +++- grafast/dataplan-pg/src/interfaces.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/grafast/dataplan-pg/src/datasource.ts b/grafast/dataplan-pg/src/datasource.ts index 56709a5f7b..51fa125cc6 100644 --- a/grafast/dataplan-pg/src/datasource.ts +++ b/grafast/dataplan-pg/src/datasource.ts @@ -137,11 +137,13 @@ export interface PgResourceParameter< */ export interface PgResourceUnique< TAttributes extends PgCodecAttributes = PgCodecAttributes, + TUniqueAttributes extends ReadonlyArray = + ReadonlyArray, > { /** * The attributes that are unique */ - attributes: ReadonlyArray; + attributes: TUniqueAttributes; /** * If this is true, this represents the "primary key" of the resource. */ diff --git a/grafast/dataplan-pg/src/interfaces.ts b/grafast/dataplan-pg/src/interfaces.ts index b0281b5ac5..673c42a337 100644 --- a/grafast/dataplan-pg/src/interfaces.ts +++ b/grafast/dataplan-pg/src/interfaces.ts @@ -464,7 +464,7 @@ export type PlanByUniques< > = TAttributes extends PgCodecAttributes ? TuplePlanMap< TAttributes, - TUniqueAttributes[number]["attributes"] & string[] + TUniqueAttributes[number]["attributes"] >[number] : undefined; From 3f9a14e1412130858a278cad60d68a8c43eef814 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Wed, 5 Aug 2026 17:05:56 +0100 Subject: [PATCH 2/6] Start thinking about registry types --- grafast/dataplan-pg/src/codecs.ts | 3 +-- grafast/dataplan-pg/src/datasource.ts | 5 +++-- grafast/dataplan-pg/src/index.ts | 8 +++----- grafast/dataplan-pg/src/interfaces.ts | 20 ++----------------- graphile-build/graphile-build-pg/src/index.ts | 9 ++++++++- .../src/plugins/PgBasicsPlugin.ts | 2 +- 6 files changed, 18 insertions(+), 29 deletions(-) diff --git a/grafast/dataplan-pg/src/codecs.ts b/grafast/dataplan-pg/src/codecs.ts index 26eb80ebe8..8cd4e495b8 100644 --- a/grafast/dataplan-pg/src/codecs.ts +++ b/grafast/dataplan-pg/src/codecs.ts @@ -961,8 +961,7 @@ export function rangeOfCodec< : null), fromPg: needsCast ? function (value) { - const json = JSON.parse(value); - const [lowerInc, lower, upper, upperInc, empty] = json; + const [lowerInc, lower, upper, upperInc, empty] = JSON.parse(value); return empty ? { empty: true } : { diff --git a/grafast/dataplan-pg/src/datasource.ts b/grafast/dataplan-pg/src/datasource.ts index 51fa125cc6..89c0d713aa 100644 --- a/grafast/dataplan-pg/src/datasource.ts +++ b/grafast/dataplan-pg/src/datasource.ts @@ -137,8 +137,9 @@ export interface PgResourceParameter< */ export interface PgResourceUnique< TAttributes extends PgCodecAttributes = PgCodecAttributes, - TUniqueAttributes extends ReadonlyArray = - ReadonlyArray, + TUniqueAttributes extends ReadonlyArray< + keyof TAttributes & string + > = ReadonlyArray, > { /** * The attributes that are unique diff --git a/grafast/dataplan-pg/src/index.ts b/grafast/dataplan-pg/src/index.ts index 429aee6172..fbf77fc20a 100644 --- a/grafast/dataplan-pg/src/index.ts +++ b/grafast/dataplan-pg/src/index.ts @@ -236,6 +236,8 @@ export type { PgCodecAttributeVia, PgCodecAttributeViaExplicit, PgCodecExtensions, + PgCodecFromJavaScriptType, + PgCodecFromPostgresType, PgCodecList, PgCodecPolymorphism, PgCodecPolymorphismRelational, @@ -281,6 +283,7 @@ export type { PgPath, PgPoint, PgPolygon, + PgRangeValue, PgRecordTypeCodecSpec, PgRefDefinition, PgRefDefinitionExtensions, @@ -318,11 +321,6 @@ export type { TuplePlanMap, WithPgClient, }; -export type { - PgCodecFromJavaScriptType, - PgCodecFromPostgresType, - PgRangeValue, -}; export { assertPgClassSingleStep, domainOfCodec, diff --git a/grafast/dataplan-pg/src/interfaces.ts b/grafast/dataplan-pg/src/interfaces.ts index 673c42a337..0abe89938a 100644 --- a/grafast/dataplan-pg/src/interfaces.ts +++ b/grafast/dataplan-pg/src/interfaces.ts @@ -652,12 +652,7 @@ export interface PgRegistry< PgCodec >, TResourceOptions extends { - [name in string]: PgResourceOptions< - name, - PgCodec, // TCodecs[keyof TCodecs], - ReadonlyArray>, - readonly PgResourceParameter[] | undefined - >; + [name in string]: PgResourceOptions; } = Record< string, PgResourceOptions< @@ -670,18 +665,7 @@ export interface PgRegistry< >, TRelations extends { [codecName in keyof TCodecs]?: { - [relationName in string]: PgCodecRelationConfig< - // TCodecs[keyof TCodecs] & - PgCodec, - // TResourceOptions[keyof TResourceOptions] & - PgResourceOptions< - any, - // TCodecs[keyof TCodecs] & - PgCodecWithAttributes, - any, - any - > - >; + [relationName in string]: PgCodecRelationConfig; }; } = Record< string, diff --git a/graphile-build/graphile-build-pg/src/index.ts b/graphile-build/graphile-build-pg/src/index.ts index 4de5d97eb1..7877ecd759 100644 --- a/graphile-build/graphile-build-pg/src/index.ts +++ b/graphile-build/graphile-build-pg/src/index.ts @@ -108,8 +108,15 @@ declare global { [tagName: string]: null | true | string | (string | true)[]; } + /** Augment this interface to provide generated build-time types. */ + interface GeneratedTypes {} + interface BuildInput { - pgRegistry: PgRegistry; + pgRegistry: GeneratedTypes extends { + pgRegistry: infer TRegistry extends PgRegistry; + } + ? TRegistry + : PgRegistry; } interface SchemaOptions { diff --git a/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts b/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts index 78c318f759..ed6ca0f780 100644 --- a/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts +++ b/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts @@ -143,7 +143,7 @@ declare global { * Shortcut to primary executor; equivalent for most users to `build.input.pgRegistry.pgExecutors.main`. * (strictly it's `build.input.pgRegistry.pgExecutors[Object.keys(build.input.pgRegistry.pgExecutors)[0]]`) */ - pgExecutor: PgExecutor; + pgExecutor: GraphileBuild.Build["input"]["pgRegistry"]["pgExecutors"][keyof GraphileBuild.Build["input"]["pgRegistry"]["pgExecutors"]]; /** Shortcut to the resources in the registry */ pgResources: GraphileBuild.Build["input"]["pgRegistry"]["pgResources"]; /** Shortcut to the codecs in the registry */ From 2cb7a1c9ad6ad9892191c2e3bf4fd5d5d484c6a4 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 7 Aug 2026 10:01:05 +0100 Subject: [PATCH 3/6] Note on weakness of type --- .../graphile-build-pg/src/plugins/PgBasicsPlugin.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts b/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts index ed6ca0f780..380e9ddcfb 100644 --- a/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts +++ b/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts @@ -142,6 +142,11 @@ declare global { /** * Shortcut to primary executor; equivalent for most users to `build.input.pgRegistry.pgExecutors.main`. * (strictly it's `build.input.pgRegistry.pgExecutors[Object.keys(build.input.pgRegistry.pgExecutors)[0]]`) + * + * Note: the TypeScript type for this is an approximation, because + * TypeScript doesn't have a concept of "first key". For most people + * there will be just a single executor anyway, and the type of the + * executor doesn't tend to matter much. */ pgExecutor: GraphileBuild.Build["input"]["pgRegistry"]["pgExecutors"][keyof GraphileBuild.Build["input"]["pgRegistry"]["pgExecutors"]]; /** Shortcut to the resources in the registry */ From 7d1081585f94f901cf05586fe06fc259618210fc Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 7 Aug 2026 10:10:26 +0100 Subject: [PATCH 4/6] docs(changeset): Tweak some types to allow defining the PgRegistry types via declaration merging. --- .changeset/shaggy-mugs-agree.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .changeset/shaggy-mugs-agree.md diff --git a/.changeset/shaggy-mugs-agree.md b/.changeset/shaggy-mugs-agree.md new file mode 100644 index 0000000000..fba6ebfeb0 --- /dev/null +++ b/.changeset/shaggy-mugs-agree.md @@ -0,0 +1,8 @@ +--- +"graphile-build-pg": patch +"postgraphile": patch +"@dataplan/pg": patch +--- + +Tweak some types to allow defining the types of the final PgRegistry via +declaration merging (requires codegen). From 68d70a93f6c35abec3898dc1843abaa2dcfc0fb8 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 7 Aug 2026 10:23:09 +0100 Subject: [PATCH 5/6] Lint --- graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts b/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts index 380e9ddcfb..a758e1df84 100644 --- a/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts +++ b/graphile-build/graphile-build-pg/src/plugins/PgBasicsPlugin.ts @@ -5,7 +5,6 @@ import type { PgCodec, PgCodecRelation, PgCodecWithAttributes, - PgExecutor, PgRefDefinition, PgResource, PgResourceUnique, From ee72b0155f87c47fa6c5a20d16193b20f65a05ba Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Fri, 7 Aug 2026 14:40:00 +0100 Subject: [PATCH 6/6] Lint --- grafast/dataplan-pg/src/interfaces.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/grafast/dataplan-pg/src/interfaces.ts b/grafast/dataplan-pg/src/interfaces.ts index 0abe89938a..adc271affb 100644 --- a/grafast/dataplan-pg/src/interfaces.ts +++ b/grafast/dataplan-pg/src/interfaces.ts @@ -462,10 +462,7 @@ export type PlanByUniques< TAttributes extends PgCodecAttributes, TUniqueAttributes extends ReadonlyArray>, > = TAttributes extends PgCodecAttributes - ? TuplePlanMap< - TAttributes, - TUniqueAttributes[number]["attributes"] - >[number] + ? TuplePlanMap[number] : undefined; export type PgConditionLike = Modifier & {