Created
February 26, 2026 16:06
-
-
Save Tam/6657a4b9f7a246c7315c44a9352c75fc to your computer and use it in GitHub Desktop.
Adds the `@cast` smart tag to Postgraphile v5
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| declare global { | |
| namespace GraphileBuild { | |
| interface ScopeObjectFieldsField { | |
| castMap?: Map<string, string>; | |
| } | |
| interface ScopeObjectFieldsFieldArgsArg { | |
| castMap?: Map<string, string>; | |
| } | |
| } | |
| } | |
| const CAST_RE = /\s+as\s+/; | |
| /** | |
| * Allows generic casting from one GraphQL type to another in function arguments | |
| * | |
| * ```sql | |
| * create or replace public.my_function (arg_a varchar, arg_b varchar); | |
| * | |
| * comment on public.my_function is E' | |
| * @cast arg_a as IncludeArchivedOption | |
| * @cast arg_b as SomeOtherType | |
| * '; | |
| * ``` | |
| */ | |
| const CastType: GraphileConfig.Plugin = { | |
| name: 'CastType', | |
| version: '1.0.0', | |
| schema: { | |
| hooks: { | |
| GraphQLObjectType_fields_field (field, build, context) { | |
| const resource = context.scope?.pgFieldResource; | |
| const raw = resource?.extensions?.tags?.cast; | |
| if (!raw) return field; | |
| const castTags = Array.isArray(raw) ? raw : [raw]; | |
| const castMap = new Map<string, string>(); | |
| for (const tag of castTags) { | |
| const [k, v] = String(tag).split(CAST_RE); | |
| const i = resource.parameters!.findIndex((p: any) => p.name === k); | |
| if (i === -1) continue; | |
| const inflected = build.inflection.argument({ | |
| resource, | |
| param: resource.parameters![i], | |
| index: i, | |
| }); | |
| castMap.set(inflected, v); | |
| } | |
| if (castMap.size) context.scope.castMap = castMap; | |
| return field; | |
| }, | |
| GraphQLObjectType_fields_field_args_arg (arg, build, context) { | |
| const castMap: Map<string, string> | undefined = context.scope.castMap; | |
| if (!castMap) return arg; | |
| const targetType = castMap.get(context.scope.argName); | |
| if (targetType) arg.type = build.getInputTypeByName(targetType); | |
| return arg; | |
| }, | |
| }, | |
| }, | |
| }; | |
| export default CastType; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment