Skip to content

feat(smithy): add canonical Smithy models for APIs#51

Draft
grdsdev wants to merge 6 commits into
mainfrom
feat/smithy-models
Draft

feat(smithy): add canonical Smithy models for APIs#51
grdsdev wants to merge 6 commits into
mainfrom
feat/smithy-models

Conversation

@grdsdev

@grdsdev grdsdev commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Smithy IDL definitions for Supabase Storage, Edge Functions, and PostgREST (Database) as a canonical source-of-truth for cross-SDK codegen spikes. The goal is for every SDK team to run their own generator toolchain against the same shared models.

These models were developed during the Swift codegen spike (supabase/supabase-swift#1047) and are now promoted here so other SDK teams can use them as a starting point.

What's included

smithy/
  model/
    common.smithy        — shared shapes (StringList, StringMap)
    storage.smithy       — buckets, objects, signed URLs, TUS resumable uploads
    functions.smithy     — invoke: GET/POST/PUT/PATCH/DELETE
    database.smithy      — PostgREST: row CRUD + RPC
  openapi/
    StorageService.openapi.json   — generated + patched OpenAPI 3.0 (ready to consume)
    FunctionsService.openapi.json — generated + patched OpenAPI 3.0 (ready to consume)
    DatabaseService.openapi.json  — generated + patched OpenAPI 3.0 (ready to consume)
  smithy-build.json      — Smithy CLI / Gradle build config
  patch-openapi.py       — post-generation patches (streaming blob format, multipart)
  README.md              — full documentation, known limitations, generator matrix

Key design decisions

  • Storage covers all bucket and object operations, signed URLs, direct multipart upload/update, and the full TUS 1.0.0 resumable upload protocol (3 operations).
  • Functions models five separate Smithy operations for the five HTTP methods Supabase Edge Functions accept (Smithy requires one fixed HTTP method per operation). The SDK client dispatches to the right operation at runtime based on FunctionInvokeOptions.method. FunctionInvokeOptions.query is now expressed via @httpQueryParams query: StringMap on all function inputs.
  • Database (PostgREST) covers all five row CRUD methods on /{table} plus CallRpcPost / CallRpcGet on /rpc/{functionName}. Key additions:
    • FilterOperator enum — all 24 PostgREST operators generated as typed constants in every SDK.
    • @httpQueryParams filters: StringMap on read/write row inputs — each map entry serialises to a ?column=op.value query param (e.g. {"id": "eq.5"}?id=eq.5). The query-builder API (.eq(), .like(), etc.) that populates the map stays hand-written; that's a UX layer, not a transport gap.
    • @httpQueryParams args: StringMap on CallRpcGet for function-specific GET params.
    • Bodies typed as Blob — row shapes are table-dependent and cannot be statically typed.
  • OpenAPI artifacts are committed — SDK consumers can feed them directly into their generator without installing Smithy.

Known limitations

# Gap Workaround
1 @streaming blob emits format: byte; generators need format: binary patch-openapi.py
2 No native multipart/form-data in Smithy patch-openapi.py injects upload operations
3 One Smithy operation per HTTP method 5 separate InvokeFunction* operations
4 GET + @httpPayload is illegal in Smithy Separate InvokeFunctionGetInput without a body
5 Realtime (WebSocket) is incompatible with REST codegen Out of scope
6 PostgREST write ops return 204 by default and 200 for return=representation — Smithy requires a single success code Model uses 200 throughout; clients must tolerate empty bodies

Not yet modelled

Auth is out of scope for this PR but is required scope for each SDK spike. OAuth redirects and cookie-based session management are difficult to express in Smithy; teams may find that layer unsuitable for codegen.

Related

DO NOT MERGE

This is a living draft. It will be updated as Auth models are added and as each SDK spike surfaces gaps that require model changes.

Adds Smithy IDL definitions for Supabase Storage and Edge Functions HTTP
APIs as a shared source-of-truth for cross-SDK codegen spikes. Each SDK
team runs their own generator toolchain against the same models.

Includes:
- model/common.smithy  — shared shapes (StringList)
- model/storage.smithy — buckets, objects, signed URLs, TUS resumable uploads
- model/functions.smithy — invoke operations for GET/POST/PUT/PATCH/DELETE
- smithy-build.json    — Smithy CLI / Gradle build config
- patch-openapi.py     — post-generation patches for streaming blob and multipart
- openapi/             — committed generated OpenAPI 3.0 artifacts (patched)

Known limitations documented in README (streaming blob format, multipart,
dynamic query params). Auth and PostgREST models are not yet included —
each SDK spike (SDK-1103 through SDK-1109) must assess those layers.

Related: RFC auto-generating parts of the Supabase SDKs
Swift spike: supabase/supabase-swift#1047
Adds model/database.smithy covering the full PostgREST HTTP surface:

- SelectRows / InsertRows / UpdateRows / UpsertRows / DeleteRows on /{table}
- CallRpcPost / CallRpcGet on /rpc/{functionName}
- Fixed query params: select, order, limit, offset, on_conflict, columns
- Well-known headers: Prefer, Range, Range-Unit, Accept, Accept-Profile,
  Content-Profile, Content-Range
- FilterOperator enum — all 24 PostgREST operators generated as typed constants
- @httpQueryParams filters: StringMap on read/write inputs so column=op.value
  filter params are model-declared and generated (not hand-wired middleware)
- @httpQueryParams args: StringMap on CallRpcGet for function-specific params

Also adds StringMap to common.smithy and uses it in functions.smithy to express
FunctionInvokeOptions.query (previously listed as a known limitation).

Adds database-openapi projection to smithy-build.json.
Runs smithy build + patch-openapi.py to produce the committed artifact
that SDK consumers can feed directly into their generator toolchain.

patch-openapi.py gains a database-specific branch (detected by info.title)
that injects the FilterOperator enum into components/schemas — the enum is
declared in database.smithy but absent from Smithy-generated OpenAPI because
it is not directly used as a member type (filter map values are raw strings).
@grdsdev grdsdev changed the title feat(smithy): add canonical Smithy models for Storage and Functions APIs feat(smithy): add canonical Smithy models for APIs Jul 1, 2026
spydon added a commit to supabase/supabase-flutter that referenced this pull request Jul 1, 2026
…ranch

The SDK branch (supabase/sdk#51) now includes a DatabaseService model.
Generate a DatabaseApi from it to verify the emitter works against every
model in the branch. Type query parameters by their schema instead of
always String?, and add PostgREST transport coverage.
grdsdev added 2 commits July 1, 2026 07:42
… uploads

The @httpMultipartForm custom trait is stripped as a DynamicTrait by the Smithy
OpenAPI converter before any OpenApiMapper.updateOperation hook runs, so the Java
plugin approach cannot work without significant additional infrastructure.

Restore the simpler approach: patch-openapi.py injects the multipart/form-data
requestBody for UploadObject (POST) and UpdateObject (PUT) in the StorageService
OpenAPI artifact. The @httpMultipartForm trait stays in the model as documentation.

The MultipartFormOpenApiMapper Java plugin is kept for reference but marked inactive.
@spydon

spydon commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

smithy build fails on a clean clone with:

The following artifacts could not be resolved: software.amazon.smithy:smithy-openapi:jar:1.52.1 (absent), software.amazon.smithy:smithy-aws-traits:jar:1.52.1 (absent), io.supabase:smithy-supabase-extensions:jar:1.0.0-SNAPSHOT (absent)

Two fixes needed:

  1. Document this required step in smithy/README.md (currently missing):

    cd smithy/extensions
    ./gradlew publishToMavenLocal
    
  2. Add Maven Central to smithy/smithy-build.json, it currently only has the local repo:

    "repositories": [
      {"url": "file://${HOME}/.m2/repository"},
      {"url": "https://repo1.maven.org/maven2"}
    ]

Also, smithy/extensions/.gradle/ and smithy/extensions/build/ were committed by mistake, add a .gitignore for them.

@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 81e1b5f8-01f8-4ef5-84a8-5e2172801cb4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

3 participants