Skip to content

feat(graphile-function-bindings): expose API-bound functions as GraphQL mutations#1365

Closed
pyramation wants to merge 2 commits into
mainfrom
feat/graphile-function-bindings
Closed

feat(graphile-function-bindings): expose API-bound functions as GraphQL mutations#1365
pyramation wants to merge 2 commits into
mainfrom
feat/graphile-function-bindings

Conversation

@pyramation

Copy link
Copy Markdown
Contributor

Summary

Track B2 of constructive-io/constructive-planning#1149.

New graphile/graphile-function-bindings package: a PostGraphile v5 plugin that, at gather time, loads function_api_bindings ⋈ function_definitions for the configured apiId and emits one mutation per graphql-enabled binding:

<alias>(input: <Alias>Input!): <Alias>Payload
# Payload: { clientMutationId, invocationId: UUID, status, invocation: FunctionInvocation }
  • Per-protocol control via binding config jsonb: absent graphql key ⇒ enabled; "graphql": false ⇒ not exposed.
  • Input derivation (src/derive.ts, shared source for future REST validation, no runtime validation):
    1. JSON Schema on config.schema/config.payloadSchema → typed input object (string/number/boolean/enum/array, required ⇒ non-null)
    2. else payload_args ([{name, type}]) → nullable scalar fields
    3. else fallback input { payload: JSON } passed through verbatim
  • Resolver = plain parameterized INSERT INTO <schema>.function_invocations (database_id, task_identifier, payload) via the Grafast context's withPgClient/pgSettings — RLS-enforced on the normal authenticated connection; the plugin never sets jwt.claims.* (server layer supplies jwt.claims.api_id provenance).
  • invocation field reuses the generated FunctionInvocation type via pgRegistry resource lookup (resource.get({ id })) when the table is exposed.
  • Server wiring: graphql/server/src/middleware/graphile.ts buildPreset(..., apiId) adds createFunctionBindingsPlugin({ apiId }) per API handler.
  • Schema invalidation: bindings load once per schema build; new/changed bindings appear on the next handler rebuild (existing graphile-cache invalidation or restart). TODO noted for a NOTIFY on binding changes.

Tests (graphile-test + seeded fn_test schema): mutation-per-binding schema snapshot, disabled/other-api bindings omitted, payload_args + JSON Schema input introspection, JSON fallback, and resolver insert returning the created invocation. pnpm test 22/22, package + server builds green.

Link to Devin session: https://app.devin.ai/sessions/0aa9b0eb80e24f57abbe55773acaa4f5
Requested by: @pyramation

…QL mutations

One mutation per graphql-enabled function_api_bindings row for the API,
with input types derived from JSON Schema / payload_args (JSON fallback)
and a plain RLS-enforced insert into function_invocations.

Track B2 of constructive-io/constructive-planning#1149
@pyramation pyramation self-assigned this Jul 12, 2026
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant