| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
chore(api): sync Management API OpenAPI spec (#7484) This PR was automatically created to sync the generated `@supabase/api` package with the latest Management API OpenAPI document. Changes were detected in the upstream OpenAPI documents exposed by `https://api.supabase.com/api/v1-json` and `https://api.supabase.com/api/v2-json`. Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com> | 1 天前 | |
chore(api): sync Management API OpenAPI spec (#7418) This PR was automatically created to sync the generated `@supabase/api` package with the latest Management API OpenAPI document. Changes were detected in the upstream OpenAPI documents exposed by `https://api.supabase.com/api/v1-json` and `https://api.supabase.com/api/v2-json`. --------- Co-authored-by: jgoux <1443499+jgoux@users.noreply.github.com> Co-authored-by: avallete <andrew.valleteau@supabase.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Andrew Valleteau <avallete@users.noreply.github.com> | 2 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
fix(cli): route every management api call through the typed client (#7123) ## Summary Every Management API call in `apps/cli` now goes through the typed `@supabase/api` client. Each call gets an `api.operation` span named after its OpenAPI operation ID, so telemetry can tell which operations a command really calls. It complements the permission mapping added in #7105, which declares the operations each module calls. Before this PR, a dozen call sites built URLs by hand. Those calls skipped the span, response decoding, and the client's retry and error handling. Some of them existed because the generated client couldn't express what they needed, so this PR fixes the generator and client first, then moves the call sites, then adds a lint rule so new raw URLs fail CI. ```mermaid flowchart LR subgraph before["Before"] direction TB H1["command handler"] -->|"typed call"| C1["@supabase/api"] H2["sso / snippets / advisors /<br/>postgres-config / db query / login …"] -->|"hand-built /v1/... URL"| X1["HttpClient"] C1 --> X1 X1 --> API1[("Management API")] end subgraph after["After"] direction TB H3["every command handler<br/>and shared module"] -->|"api.v1.op(input, options?)"| C2["@supabase/api<br/>span · decode · retry"] C2 --> X2["HttpClient"] X2 --> API2[("Management API")] L["lint rule<br/>supabase/no-raw-management-api-url"] -. "blocks new raw URLs" .-> H3 end ``` ## What changes ### 1. Generator and client (`packages/api`) Four gaps forced callers back to raw HTTP: | Gap | Fix | | --- | --- | | Response enums were closed, so a new server value broke decoding | Multi-value response enums are open: `"ACTIVE" \| "PAUSED" \| (string & {})`. Single-value enums stay closed. | | Unknown request keys were dropped without an error | Request input decodes with `onExcessProperty: "error"`, so a typo fails as `SupabaseApiInputError` before any request is sent | | `const` schemas weren't generated | `const` maps to a literal | | One client meant one host and one token | Every wrapper takes an optional second argument: `{ baseUrl?, accessToken?, headers? }` | The last row is what let login and SSO profile reconciliation drop raw HTTP: ```ts // before: login built its own request because the client had no token yet const response = yield* httpClient.execute( HttpClientRequest.get(`${apiHost}/v1/profile`).pipe( HttpClientRequest.setHeader("Authorization", `Bearer ${token}`), ), ); // after const api = yield* makeApiClient({ baseUrl: apiHost, accessToken: token, userAgent }); const profile = yield* api.v1.getProfile(); ``` ```ts // per-request override on an existing client (sso update against a reconciled profile) yield* api.v1.updateASsoProvider(input, { baseUrl: profile.apiUrl, accessToken: profile.token }); ``` **Retries now back off.** The client used to retry immediately. It now uses exponential backoff with full jitter: ```mermaid xychart-beta title "Maximum delay before each retry (ms, full jitter picks 0 to max)" x-axis ["retry 1", "retry 2", "retry 3", "retry 4", "retry 5"] y-axis "ms" 0 --> 4500 bar [250, 500, 1000, 2000, 4000] ``` | Response | Retried for | Delay | | --- | --- | --- | | `429` | every method | `Retry-After` if present, otherwise backoff | | `5xx` / transport error | `GET` `PUT` `DELETE` `HEAD` only | `Retry-After` if present, otherwise backoff | | other `4xx` | never | — | `POST` and `PATCH` aren't retried on 5xx because they aren't idempotent. A `Retry-After` longer than 10 s isn't waited out: the response goes straight back to the caller. Each retry records `http.request.resend_count` on the span. A single request can override the policy with `retry: { maxRetries, requestTimeoutMs }`: ```ts // functions deploy runs its own rate-limit loop, so the client stays out of it api.executeRaw(operationDefinitions.v1DeployAFunction, input, { retry: { maxRetries: 0 } }); ``` | Caller | Override | Why | | --- | --- | --- | | `functions deploy` upload and bulk update | `maxRetries: 0` | the command's own `429` loop is the only retry layer | | `postgres-config update/delete` PUT | `maxRetries: 0` | a resent write with `restart_database` restarts the database twice | | linked-project cache fill at exit | `maxRetries: 0` | exit isn't held up when the API is failing | | `db query --linked` | `requestTimeoutMs: Infinity` | long queries keep running with no client timeout, as before | | `sso add` / `sso update` | `requestTimeoutMs: Infinity` | the server may fetch `--metadata-url` during the request; no client timeout, as before | ### 2. Self-validating OpenAPI overrides `openapi-overrides.json` patches upstream spec bugs. Patches used to fail silently once upstream fixed the bug, so stale patches piled up. The loader now rejects: - a `replace` without a `test` on the same path directly before it, so the patch states what it expects upstream to say; - a `replace` whose value already matches upstream, because the fix has landed upstream; - a `remove` whose target doesn't exist; - any entry without a `$comment` explaining the upstream bug. ```jsonc { "$comment": "Hostnames stored before the upstream fix can lack `status`; the fix covers only new writes.", "op": "test", "path": "/components/schemas/.../required", "value": ["status", "..."] }, { "op": "replace", "path": "/components/schemas/.../required", "value": ["..."] } ``` With these checks, the overrides go from 37 entries to 25. The removed patches were ones upstream has since fixed, plus a lenient removal of the v2 webhook paths, which now generate normally. ### 3. Call sites moved to the typed client (`apps/cli`) | Area | Before | After | | --- | --- | --- | | `sso add` / `sso update` | string URLs, hand-written response views | `createASsoProvider`, `getASsoProvider`, `updateASsoProvider`, per-request host and token for reconciled profiles. Structured output still prints the server body unchanged. | | `db query` | raw `POST /database/query` | `v1RunAQuery` | | `postgres-config get/update/delete` | raw GET and PUT | GET keeps the raw record (stored keys may predate the schema). PUT validates the keys the user passed against the same strict schema the platform enforces. Stored overrides are resent unvalidated through `executeRaw`'s `extraBody`, so one this CLI version doesn't know is kept. The returned record prints unchanged. | | `snippets list/download` | raw | typed operation. `--output json/yaml/toml` still prints the server body unchanged. | | `db advisors` (linked) | raw | `getSecurityAdvisors`, `getPerformanceAdvisors` | | `config push` cost check | raw | `listProjectAddons` | | login profile, upgrade suggestion, linked-project cache | raw | typed calls. Each builds its own client for its host and token. | | `projects list` / `projects create` | typed client's `executeRaw` | unchanged: `executeRaw` keeps fields the schema doesn't model | The shared `raw-http.ts` helper is deleted. One raw call remains, the device-login poll under `/platform/cli/login`. That route isn't in the Management API spec, so no typed operation exists. It now URL-encodes its parameters and has a commented lint exception. ### 4. Lint rule: `supabase/no-raw-management-api-url` A local oxlint JS plugin (`tools/oxlint/supabase-plugin.js`) reports any string or template literal in `apps/cli/src` (tests excluded) that starts a `/v1/…`, `/v2/…` or `/platform/…` path, including path constants that are joined to a base URL later. Service-scoped paths such as `/auth/v1/` and `/storage/v1/` don't match. ```ts const url = `${apiHost}/v1/projects/${ref}/config/database/postgres`; // ^ supabase/no-raw-management-api-url: Build Management API requests with the // typed `@supabase/api` client (`api.v1.*`, `execute`/`executeRaw`) so the call // emits the `api.operation` span; do not assemble `/v1/`, `/v2/` or `/platform/` URLs by hand. ``` ### 5. cli-e2e placeholder ref Recorded fixtures used `__PROJECT_REF__` as the project ref, which the typed client rejects as a path parameter. That kept login, upgrade suggestion and the linked-project cache on raw HTTP. Fixtures now use `replayfixtureprojref`, a 20-character ref that passes the check, and the replay server no longer rewrites placeholders back and forth. This explains the large fixture rename in the diff. Injected `429`/`5xx` replay responses send `Retry-After: 0`, so the new backoff doesn't slow down the suite. ## User-visible behavior changes Most of these come from validating input locally and decoding responses strictly: - `postgres-config update` and `config push` reject keys and values the platform would refuse before sending a request. An unknown `--config` key reports `unknown Postgres config parameter(s): …` and suggests upgrading the CLI if the parameter is new. Stored overrides are never checked locally. An invalid value reports `invalid Postgres config value for <key>: …`, and a bare number for a size or duration suggests adding a unit (`work_mem=4096kB`). - The SSO attribute-mapping file is decoded strictly, so unknown keys are an error. The `sso` table shows only modelled fields. - `notebooks` rejects an unknown `view`. - `functions deploy` rejects an unknown function status. Unknown custom-domain statuses are shown as returned. - `snippets` output follows the spec's nullability (`description: null` instead of a missing field). - `db query` error output caps the response body and strips control characters. - Idempotent requests now retry on `5xx` and transport errors with backoff. `429` is retried for every method, except where a command opts out (see the overrides table above). | 21 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 | |
refactor(api): cover the client sources with effect lint (CLI-2841) (#7309) ## TL;DR brings `packages/api/src` and its tests under the effect lint ## whats introduced? - `packages/api/src/**` joins the allow list, and the generated `contracts.ts` stays out - `SupabaseApiConfigError` and `SupabaseApiInputError` move to `Data.TaggedError` with the same message, name, cause, json and printed output, pinned by a new test, so two `apps/cli` call sites whose failures include them now yield them directly - `createApiClient` in `bun.ts` and `node.ts` chains its promise instead of being `async`, still disposing the runtime before it rejects - the src tests move to effect: `FileSystem` and `Path`, schema json codecs, and `Effect.runPromise` bodies instead of `async` callbacks ## ref - closes: CLI-2841 | 9 天前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 9 天前 | ||
| 1 天前 | ||
| 2 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 21 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 9 天前 | ||
| 9 天前 |