Skip to content

Add @pothos/plugin-semantic-nullability#1612

Draft
hayes wants to merge 2 commits intomainfrom
claude/pothos-work-7zqAa
Draft

Add @pothos/plugin-semantic-nullability#1612
hayes wants to merge 2 commits intomainfrom
claude/pothos-work-7zqAa

Conversation

@hayes
Copy link
Copy Markdown
Owner

@hayes hayes commented Apr 8, 2026

Summary

Adds a new @pothos/plugin-semantic-nullability plugin that converts non-null fields to nullable with @semanticNonNull directives, for use with clients that support semantic nullability (Relay 18+, Apollo Kotlin, etc.).

Plugin API

Per-field opt-in:

t.string({
  nullable: false,
  semanticNonNull: true,  // → emits String @semanticNonNull instead of String!
  resolve: () => 'hello',
})

Schema-wide default with per-field opt-out:

const builder = new SchemaBuilder({
  plugins: ['semanticNullability'],
  semanticNullability: {
    allNonNullFields: true,  // convert all non-null fields
  },
});

// Opt out for specific fields:
t.id({ nullable: false, semanticNonNull: false })  // stays ID!

List levels support: automatically computes the correct levels argument for nested list types (e.g., [String!]![String] @semanticNonNull(levels: [0, 1])).

How it works

The plugin uses onOutputFieldConfig to intercept non-null fields, flip them to nullable, and attach the @semanticNonNull directive to extensions. The directive definition is registered on the schema via afterBuild. TypeScript types are unchanged — the resolver contract remains non-null.

Test plan

  • Per-field opt-in converts non-null to nullable with directive
  • Fields without semanticNonNull stay as strict non-null
  • Already-nullable fields are unchanged (no directive added)
  • List fields get correct levels computed
  • Schema-wide allNonNullFields converts all non-null fields
  • Per-field semanticNonNull: false overrides schema-wide default
  • @semanticNonNull directive definition registered on schema
  • TypeScript type checking passes
  • Snapshot tests for generated schema

https://claude.ai/code/session_01MLrx31yBgXYrx1LEzfPs2e

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pothos Ready Ready Preview, Comment Apr 8, 2026 7:29am

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 8, 2026

⚠️ No Changeset found

Latest commit: 4b450b0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Apr 8, 2026

Open in StackBlitz

@pothos/core

npm i https://pkg.pr.new/hayes/pothos/@pothos/core@1612

@pothos/plugin-add-graphql

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-add-graphql@1612

@pothos/plugin-complexity

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-complexity@1612

@pothos/plugin-dataloader

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-dataloader@1612

@pothos/plugin-directives

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-directives@1612

@pothos/plugin-drizzle

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-drizzle@1612

@pothos/plugin-errors

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-errors@1612

@pothos/plugin-example

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-example@1612

@pothos/plugin-federation

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-federation@1612

@pothos/plugin-grafast

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-grafast@1612

@pothos/plugin-mocks

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-mocks@1612

@pothos/plugin-prisma

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-prisma@1612

@pothos/plugin-prisma-utils

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-prisma-utils@1612

@pothos/plugin-relay

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-relay@1612

@pothos/plugin-scope-auth

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-scope-auth@1612

@pothos/plugin-semantic-nullability

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-semantic-nullability@1612

@pothos/plugin-simple-objects

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-simple-objects@1612

@pothos/plugin-smart-subscriptions

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-smart-subscriptions@1612

@pothos/plugin-sub-graph

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-sub-graph@1612

@pothos/plugin-tracing

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-tracing@1612

@pothos/plugin-validation

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-validation@1612

@pothos/plugin-with-input

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-with-input@1612

@pothos/plugin-zod

npm i https://pkg.pr.new/hayes/pothos/@pothos/plugin-zod@1612

@pothos/tracing-newrelic

npm i https://pkg.pr.new/hayes/pothos/@pothos/tracing-newrelic@1612

@pothos/tracing-opentelemetry

npm i https://pkg.pr.new/hayes/pothos/@pothos/tracing-opentelemetry@1612

@pothos/tracing-sentry

npm i https://pkg.pr.new/hayes/pothos/@pothos/tracing-sentry@1612

@pothos/tracing-xray

npm i https://pkg.pr.new/hayes/pothos/@pothos/tracing-xray@1612

commit: 4b450b0

@hayes hayes force-pushed the claude/pothos-work-7zqAa branch from 5dad7f7 to cec32ea Compare April 8, 2026 07:21
Plugin that converts non-null fields to nullable with @semanticNonNull
directives. Supports per-field opt-in via `semanticNonNull: true` and
schema-wide conversion via `allNonNullFields: true` with per-field
opt-out. Correctly computes `levels` for nested list types.

https://claude.ai/code/session_01MLrx31yBgXYrx1LEzfPs2e
- `true` now only converts level 0 (the field itself), not all levels
- Accept `number[]` to specify explicit levels (e.g. `[0, 1]`)
- Only convert levels that are actually non-null (skip already-nullable)
- Nullable fields with `semanticNonNull: true` are correctly ignored

https://claude.ai/code/session_01MLrx31yBgXYrx1LEzfPs2e
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.

2 participants