Skip to content

SDK codegen foundation: contract, Storage pipeline, and SupabaseRuntime#30

Draft
grdsdev wants to merge 50 commits into
mainfrom
claude/flamboyant-mendeleev-69a72f
Draft

SDK codegen foundation: contract, Storage pipeline, and SupabaseRuntime#30
grdsdev wants to merge 50 commits into
mainfrom
claude/flamboyant-mendeleev-69a72f

Conversation

@grdsdev

@grdsdev grdsdev commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

Foundation for cross-SDK code generation, piloted on Swift. The strategy: generate the mechanical layer (transport/types/errors) from upstream OpenAPI via a shared engine + per-language templates, and hand-write only what makes each stack unique. This PR lands the contract, the in-repo Storage pipeline, and a modern Swift 6 runtime. Draft — foundation for review; follow-on work outlined below.

What's included

  • Codegen contract (TS validator, scripts/capability-matrix) — optional binding: { spec, operationId } on capability features, codegen.yaml (engine pin + spec sources + per-language config) with its JSON schema, a conformance-vector format, and validation wired into npm run validate (binding ↔ spec/operation checks + drift guard).
  • In-repo Storage pipeline — a deterministic spec normalizer (src/normalize.ts) that makes the upstream Storage OpenAPI generation-ready (injects operationIds, fixes Fastify {*} wildcards, renames def-N schemas, OAS-3.1→3.0 fixups, injects octet-stream upload bodies), plus normalize/generate/generate:check scripts. The committed normalized spec is the deterministic, drift-guarded input.
  • SupabaseRuntime (codegen/runtime/swift/SupabaseRuntime) — a generic, dependency-free Swift 6 runtime: a narrow Transport seam over an actor URLSessionTransport (native async URLSession, streaming upload/download with progress, event-stream stream(), background-session guard + relaunch hook, typed errors), injected ClientConfiguration/AuthProvider, and a body-aware MockTransport. 30 swift-testing tests, parallel-stable, swift build clean.
  • Upstream trackingcodegen/upstream-spec-issues.md records 10 Storage spec problems the normalizer works around, each mapped to its upstream fix (so workarounds can be deleted once fixed upstream).

Intentionally NOT included

  • The generated Swift client. The earlier committed openapi-generator output was a pilot artifact that proved the pipeline builds; an audit found its stock transport non-idiomatic. The follow-up will regenerate a thin client onto SupabaseRuntime via lean templates, so the stock output is removed. Generated code is now treated as a build product (gitignored, regenerated from the committed normalized spec).

Roadmap (follow-on)

  • Lean templates/swift + codegen.yaml that regenerate Storage's thin client onto SupabaseRuntime (opens with a template-override spike).
  • The normalizer naming/dedup batch from the audit (operationIds, response-type names, shared $refs, Dates, ints).
  • The hand-written ergonomic surface, and integration tests for byte-accurate progress + full background delivery (device-level; out of unit-test scope).

Verification

  • scripts/capability-matrix: vitest suite + npm run validate pass.
  • SupabaseRuntime: 30 tests pass across repeated parallel runs; swift build clean, zero dependencies, Swift 6 language mode.

Notes for reviewers

  • Design docs: docs/design/2026-06-16-sdk-code-generation-design.md, docs/design/2026-06-16-swift-codegen-runtime-design.md. Plans under docs/plans/.
  • The branch history carries large blobs (the removed stock-generated package + early .build/ artifacts); please squash-merge to collapse them away.

Test plan

  • cd scripts/capability-matrix && npm ci && npm test && npm run validate
  • cd codegen/runtime/swift/SupabaseRuntime && swift test
  • cd scripts/capability-matrix && npm run generate:check (regenerates from the normalized spec; drift-clean)

grdsdev added 30 commits June 16, 2026 15:28
Introduces Binding type (spec + operationId) and optional binding field
on Feature; mirrors the change in the JSON schema with a sibling $defs
entry and ref from the feature definition. Covered by binding-schema tests.
Pure transform functions that normalize an upstream OpenAPI doc in-place:
renameWildcardParams (Fastify {*} paths), renameSchemas ($ref-aware),
deriveOperationId, injectOperationIds, and a top-level normalizeSpec
orchestrator. Covers the three Storage spec issues: missing operationIds,
wildcard path params, and opaque def-N schema names.
Add findUnmatchedOverrides guard that detects override keys with no matching
operation; call it in the CLI after normalization so bad keys throw instead of
silently producing wrong derived ids. Fix storage.json GET/POST /bucket keys
to include the trailing slash that the spec actually uses.
Extends the normalizer with five OAS 3.1→3.0 fix-ups required for
openapi-generator 7.x / Swift 6 to produce clean compilable output:
- fixArrayTypes: type:[null,T] → nullable+single type
- stripDollarComments: removes $comment (OAS 3.1 annotation)
- stripSchemaExamples: removes plural examples array (OAS 3.1)
- inlineExternalRefs: replaces unresolvable http:// $refs with {}
- dedupCaseInsensitiveProperties: drops PascalCase vs lowercase
  property name collisions (Id vs id in POST /object/copy response)

Re-runs normalize → generate → verified swift build with zero errors.
Adds codegen/generated/swift-storage (162 files, urlsession, no deps).
Excludes .build/ via .gitignore.
Adds checkBindingOperations (bindings.ts) which verifies each feature
binding's operationId actually exists in the referenced normalized spec.
Wires it into run() immediately after checkBindings. Adds operationId
overrides for deleteBucket and getBucket, regenerates the normalized spec
and Swift output, and binds five Storage features: createBucket,
listBuckets, uploadObject, deleteBucket, getBucket.
grdsdev added 20 commits June 17, 2026 07:28
Introduces AuthProvider (async closure-based, Sendable, with a .none static)
and ClientConfiguration (baseURL, defaultHeaders, auth, encoder, decoder,
sessionKind, errorMapper) as the central config struct for the SupabaseRuntime
Swift package.
Implements `URLSessionTransport` with buffered `send` variants (no-body,
with-body, fire-and-forget). Uses `URLComponents` path concatenation to
compose request URLs from the configured base, merges default + auth +
per-request headers, and maps non-2xx via `errorMapper` then falls back
to `TransportError.http`. Upload/download/stream stubs left as
`fatalError` for Tasks 6-7. Adds `StubURLProtocol` test helper and
`@Suite(.serialized)` to guard shared static state against parallel runs.
…egate

Implements Task 6: replaces fatalError stubs in URLSessionTransport with
real async upload(for:)/download(for:) calls. Progress is wired via
SessionDelegate when the transport owns its session; under an injected stub
session (no delegate) the progress stream is empty but terminates correctly.
Replace the session-level SessionDelegate (which registered but never
actually yielded to the per-call continuation) with a lightweight
TaskProgressDelegate that is passed directly to the per-call async
URLSession APIs (upload(for:from:delegate:), download(for:delegate:)).
The continuation is now held by the delegate, so progress DOES emit in
production. The stream terminates via defer { cont.finish() } in both
upload and download paths. Adds uploadProgressStreamTerminates test.
Implement URLSessionTransport.stream() using URLSession.bytes(for:) to
drive an AsyncThrowingStream that buffers bytes in 4 KiB chunks, maps
non-2xx responses to TransportError, and cancels the producer Task on
stream termination to avoid leaks.
Add file-only guard to `upload` that throws `TransportError.backgroundRequiresFile`
when a `.background` session attempts an in-memory `.data` upload. Add actor-isolated
`handleBackgroundEvents` / `consumeBackgroundCompletion` for the OS relaunch hook.
Unit-tested via injected stub session; full background delivery (session delegate +
OS relaunch wiring) is a documented integration gap.
…s a build product

The committed openapi-generator output was a Plan 2 pilot artifact proving the
pipeline builds. The lean templates (Plan B) will regenerate the Storage client
onto SupabaseRuntime, so the stock output is removed. Generated code is now
gitignored (regenerated from the committed normalized spec); the drift guard is
rescoped to the normalized spec.
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