Skip to content

feat(config): trim the public surface and add a compiled build (CLI-2234, CLI-2232) - #6366

Draft
Coly010 wants to merge 7 commits into
developfrom
columferry/cli-2234-audit-and-trim-supabaseconfigs-public-export-surface-before
Draft

feat(config): trim the public surface and add a compiled build (CLI-2234, CLI-2232)#6366
Coly010 wants to merge 7 commits into
developfrom
columferry/cli-2234-audit-and-trim-supabaseconfigs-public-export-surface-before

Conversation

@Coly010

@Coly010 Coly010 commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Closes CLI-2234
Closes CLI-2232

What changed

Prepares @supabase/config for its first npm publish: the export surface is audited and trimmed (CLI-2234) and the package gains a real compiled build (CLI-2232). One PR because the audit decides what the entrypoints contain and the build compiles exactly that, and the audit's type-surface enforcement (API report) only works once the build emits .d.ts.

Export-surface audit (CLI-2234)

Every export got an explicit keep / move / trim decision:

Decision Symbols
Moved to apps/cli KONG_LOCAL_CA_CERT (+ its test) — a local-stack TLS asset, not config schema
Moved to new ./internal subpath (explicitly not semver-covered; enforced apps/cli-only) ENV_CAPTURE_REGEX, AUTH_HOOK_NAMES, unmappedSecretApiPaths, projectConfigMappingRows, ProjectConfigMappingRow, ProjectConfigApiAttributes, InternalLoadCliConfigOptions + goViperCompat-capable typings of loadCliConfig/resolveCliConfigValue/resolveCliConfigSubtree
Removed from public options goViperCompat (off LoadCliConfigOptions; resolvers lost their options param entirely — re-adding later is non-breaking)
Trimmed MissingCliConfigValueError deleted entirely (never constructed anywhere in the package; apps/cli only carried a telemetry mapping entry + a test that fabricated one — both removed), loadCliConfigFile/InternalResolveCliConfigOptions off the internal barrel (zero consumers)
Renamed (./io, zero consumers existed) findCliProjectRootFor→findCliProjectRoot, findCliProjectPathsFor→findCliProjectPaths, loadCliProjectEnvironmentFor→loadCliProjectEnvironment, loadFunctionsManifest→inferFunctionsManifest./io now mirrors ./effect 1:1; the subpath conveys Promise-vs-Effect
Added sync resolveCliConfigValue/resolveCliConfigSubtree on . (Effect-typed variants deliberately shadow them on ./effect); ProjectConfigSchema (runtime, Standard Schema v1 via Schema.toStandardSchemaV1 — one symbol serves Effect-native and ~standard consumers); toProjectConfigJsonSchema; PROJECT_CONFIG_SCHEMA_URL
Kept (documented contract in README) schema/types, encoders, defaults + sparse helpers, the ProjectConfig converters (toProjectConfig, fromConfigDocument, fromApiProjectConfig, attachApiResponse, comparableProjectConfigPaths, unmappedApiFields), errors, functions-manifest model

ProjectConfigSchema is derived from CliConfigSchema at the AST level (hosted sections → type-side → deep-optional → x-secret leaves dropped → cross-field checks stripped, leaf checks kept) with a two-way compile-time assignability pin against the ProjectConfig type, so the runtime schema and the type cannot drift.

./io's error channel is narrowed from unknown to the exact five-member union (verified exact by review: no wider member, none unused).

Compiled build (CLI-2232)

  • Plain tsc (tsgo 7.0.2, nodenext + rewriteRelativeImportExtensions) emits ESM .js + .d.ts + maps to dist/; no bundler.
  • Conditional exports: in-repo Bun resolves src/*.ts (with customConditions: ["bun"] so tsc typechecks against source, not stale dist); external consumers get dist js + types.
  • Tarball sealed via files + .npmignore (npm-packlist otherwise applies the root .gitignore and ships no distnpm pack and pnpm pack now agree); publish metadata (license, repository, publishConfig, engines) added; peers widened to >=4.0.0-rc.111 <5.
  • sideEffects: false, proven by a tree-shake probe with positive + negative controls against the built artifact.
  • dist/project-schema.json joins dist/schema.json (both draft-2020-12, now with $id/title, and with Effect's non-finite-number anyOf encoding collapsed so numeric fields keep description/default).
  • Build ends with a pack-and-install smoke test: real npm pack → temp install → real node imports every subpath.

Enforcement (surface changes stay deliberate)

  • Sealed exports map, pinned key set at runtime.
  • Per-entrypoint export-name snapshots (now incl. ./internal), purity walker over index.ts and io-browser.ts.
  • Type-surface changes: pnpm run check:config-api (root task; advisory continue-on-error CI step) emits declarations for the PR base and head — base source extracted via git archive into the package dir so the current install resolves deps, no second install — and reports the .d.ts diff in the job summary. Per-PR signal, zero committed artifacts. The hard gate moves to release time (CLI-2233): diff the new dist/*.d.ts against the previously published tarball's in the human-approval step.
  • @supabase/config/internal imports enforced apps/cli-only.

Review rounds

Three internal reviews (engineer, architect, DX-as-consumer incl. a clean-Node tarball install exercising 23 checks) ran before this PR; all accepted findings are in the final commit. Explicitly rejected, for the record:

  • @deprecated markers on ./internal exports (strikethrough noise across apps/cli's own legitimate call sites; the no-semver contract is documented at the barrel, README, and AGENTS.md).
  • message getters on the tagged error classes (would change CLI-visible error output pinned by normalize-error tests; README documents the structured-fields contract instead — candidate follow-up).
  • A checked-in api-report/ .d.ts mirror (53 files + freshness test) existed in earlier commits of this branch and was removed by owner decision — per-PR accept semantics weren't worth 580 KB of generated diff noise. Replaced by the advisory base-vs-head compare above; an api-extractor-style rollup was also considered and skipped (TS7/tsgo compatibility unproven).
  • saveCliConfig's atomic-write rename failure stays a defect (documented); re-channeling it as a typed failure is a behavioral follow-up.
  • Moving KONG_LOCAL_CA_CERT to packages/stack (single legacy consumer today; speculative second move).

Known collateral: @supabase/pg-topo under customConditions

customConditions: ["bun"] in apps/cli/tsconfig.json (needed so tsc typechecks @supabase/config against source instead of gitignored dist/) also changes resolution for @supabase/pg-topo, whose own bun exports condition points at unbuilt src/*.ts carrying 3 type errors at 1.0.0-alpha.5. Worked around with a commented paths pin to its shipped dist/index.d.ts. 1.0.0-alpha.6 is published but currently blocked by pnpm's minimumReleaseAge; once it ages in, bump it in apps/cli and drop the pin (and the bun-condition source errors deserve an upstream fix in supabase/pg-toolbelt either way).

Notes for CLI-2233 / CLI-2169 (publish)

  • The release pipeline must diff the new dist/*.d.ts against the previously published tarball's and surface that diff in the human-approval step — that is the hard semver gate (the PR-time compare above is advisory only; first publish trivially has no compare target).
  • Publish with pnpm publish (only pnpm rewrites any residual catalog:; peers are now literal ranges regardless).
  • effect@latest is still 3.x — README instructs effect@rc; revisit ranges when Effect 4 goes stable.
  • No top-level main/types (deliberate ESM + exports-only; node10 resolution unsupported).
  • Pre-existing @supabase/cli-go#lint:check gosec findings fail local check:all on clean develop too — untouched by this PR.

@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor
Superseded by a newer AI review

🤖 AI Review

This PR is too large for a full AI review (+10567/-520 lines across 118 files).

A maintainer can request a review anyway with a /ai-review comment.

1 similar comment
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor
Superseded by a newer AI review

🤖 AI Review

This PR is too large for a full AI review (+10567/-520 lines across 118 files).

A maintainer can request a review anyway with a /ai-review comment.

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