Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions apps/cli/src/commands/gen/types/SIDE_EFFECTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ instead of inspecting `supabase_db_*`.
| `<workdir>/supabase/config.json` or `config.toml` (`[db]` values only) | JSON/TOML | every `--remote=<db-url>` resolution, regardless of `--schema` — `DbConfigResolver` reads it through `readDbConfig` (`config.json` preferred when both exist) to fill a passwordless local DSN's `[db].password` and to classify the target host as local vs. remote. A present-but-unparseable config file fails the command (`DbConfigLoadError`) even on this path, independent of the schema-selecting load above. Resolving a remote project's connection reads the whole config the same strict way (auth hooks, SMTP, email templates, the `signing_keys_path` file, `[db.vault]` secrets), now for `--lang=typescript` too; a failure there fails other languages and falls back to the Management API for TypeScript. |
| `<workdir>{/supabase}/.env*` | dotenv | the local target; resolves the same nested environment overrides as the CLI. Every `--remote=<db-url>` resolution also reads it (same `.env.<SUPABASE_ENV>.local`/`.env.local`/`.env.<SUPABASE_ENV>`/`.env` search) to populate the `PG*` fallbacks used while parsing the DSN. |
| `~/.pg_service.conf` (or a `PGSERVICEFILE`/DSN `servicefile=` override) | libpq service file | `--remote=<db-url>`, only when the DSN or `PGSERVICE` names a `service` — its settings fill in for connection fields the DSN itself omits |
| `Package.resolved` (nearest) | JSON | `--lang swift` without `SUPABASE_TYPEGEN`, on macOS or Linux x86_64: the first one found walking up from the working directory, including the copies inside an `.xcodeproj` or `.xcworkspace`; the supabase-swift version it pins picks the `supabase-typegen` release |
| `Package.resolved` (nearest) | JSON | `--lang swift` on macOS or Linux x86_64: the first one found walking up from the working directory, including the copies inside an `.xcodeproj` or `.xcworkspace`; the supabase-swift version it pins picks the `supabase-typegen` release |
| `<workdir>/supabase/.temp/rest-version` | plain text | the local target, when `db.major_version > 14` — forces v9 compat if the tag contains `v9`; and `--lang=typescript` on the linked project, where it is required for direct generation and, without its leading `v`, becomes `__InternalSupabase.PostgrestVersion` |
| `$PGSSLROOTCERT`, `$PGSSLCERT` / `$PGSSLKEY`, `pg_service.conf` | PEM, libpq | a remote project (any `--lang`), when `PGSSLCERT`/`PGSSLKEY` or `PGSERVICE` are set; `$PGSSLROOTCERT` also replaces the pinned Supabase CA; the PEM files are skipped under `PGSSLMODE=disable` |

Expand Down Expand Up @@ -87,8 +87,7 @@ Any other `--lang` whose registry entry is out-of-process runs its own tool
the same way: stdout is the output, stderr is folded into the error on
failure. The tool inherits the CLI's entire environment, so a `PUB_CACHE` or
proxy setting reaches it unchanged. For `--lang swift` the binary is
`SUPABASE_TYPEGEN` when set, else the cached release binary of the
supabase-swift version `Package.resolved` pins, downloaded once from
the cached release binary of the supabase-swift version `Package.resolved` pins, downloaded once from
`https://github.com/supabase/supabase-swift/releases/download/v<version>/`,
else `supabase-typegen` from `PATH`. Introspection and the in-process
languages never shell out. On a native or Docker-based managed stack
Expand All @@ -111,7 +110,6 @@ way `--remote=<db-url>` does.
| `SUPABASE_DB_PASSWORD` | database password for a remote project (shell env > project `.env*` > config); withheld, with a stderr `Not sending SUPABASE_DB_PASSWORD to <target>: this directory is linked to <linked>. Using a temporary login role instead (needs supabase login or SUPABASE_ACCESS_TOKEN).` line, when the target differs from `.temp/project-ref`, which mints a temporary login role instead. **Not read by the local target**, which uses `[db].password` (default `postgres`) | no |
| `SUPABASE_SERVICES_HOSTNAME` | host used to reach the local database on the legacy Docker Compose stack; read from the shell env first, then project `.env*` | no (defaults to the shell `DOCKER_HOST`'s tcp host, else `127.0.0.1`) |
| `SUPABASE_WORKDIR` | working directory `supabase/config.toml`/`config.json` is read from (`--workdir` takes priority) | no — when unset, the CLI walks up from cwd looking for `supabase/config.toml` or `supabase/config.json`; when SET (flag or env) the directory is used exactly as given and **no ancestor is searched** |
| `SUPABASE_TYPEGEN` | path of the `supabase-typegen` binary `--lang swift` runs, skipping the version lookup and download | no |
| `XDG_CACHE_HOME`, `HOME` | locate the cache directory of the `--lang swift` release binary | no |
| `PATH`, `PATHEXT`, `ComSpec` | find the tool of an out-of-process `--lang`; `PATHEXT` and `ComSpec` matter on Windows only | no (`PATHEXT` defaults to `.COM;.EXE;.BAT;.CMD`, `ComSpec` to `cmd.exe`; without `PATH` the tool is reported as not installed) |
| `PGSSLMODE`, `PGSSLROOTCERT`, `PGSSLCERT`, `PGSSLKEY`, `PGSSLPASSWORD`, `PGSERVICE`, `PGSERVICEFILE` | a remote project (any `--lang`): client-cert pair outside `sslmode=disable`; invalid values fail (TypeScript falls back to the Management API instead); an explicit `sslmode`/`sslrootcert` replaces the Supabase CA pin (see Notes) | no |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,94 @@ const withFakeDart = <A, E, R>(
return yield* body({ cwd, bin });
}).pipe(Effect.provide(BunServices.layer));

/** A stand-in `supabase-typegen` that echoes its arguments and its stdin. */
const FAKE_TYPEGEN_BINARY = `#!/bin/sh
printf 'supabase-typegen args: %s\\n' "$*"
cat
`;

const SWIFT_VERSION = "3.0.0-alpha.1";

/** Pins supabase-swift the way a SwiftPM `Package.resolved` does. */
const PACKAGE_RESOLVED = JSON.stringify({
pins: [
{
identity: "supabase-swift",
kind: "remoteSourceControl",
location: "https://github.com/supabase/supabase-swift",
state: { revision: "0000000", version: SWIFT_VERSION },
},
],
version: 3,
});

const hasSwiftReleaseAsset = ["darwin-arm64", "darwin-x64", "linux-x64"].includes(
`${process.platform}-${process.arch}`,
);

const withFakeSupabaseTypegen = <A, E, R>(
body: (context: {
readonly cwd: string;
readonly install: (directory: string) => Effect.Effect<string>;
}) => Effect.Effect<A, E, R>,
) =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const path = yield* Path.Path;
const cwd = yield* fs.realPath(
yield* fs.makeTempDirectoryScoped({ prefix: "gen-types-swift-" }),
);
const install = (directory: string) =>
Effect.gen(function* () {
const binary = path.join(directory, "supabase-typegen");
yield* fs.makeDirectory(directory, { recursive: true });
yield* fs.writeFileString(binary, FAKE_TYPEGEN_BINARY);
yield* fs.chmod(binary, 0o755);
return binary;
}).pipe(Effect.orDie);
return yield* body({ cwd, install });
}).pipe(Effect.provide(BunServices.layer));

const expectFakeSupabaseTypegenOutput = (output: string) => {
expect(output).toContain("supabase-typegen args: --access-control internal\n");
expect(output).toContain('"version":1');
};

describe.skipIf(process.platform === "win32")("genTypesGeneratorLayer for --lang swift", () => {
it.effect.skipIf(!hasSwiftReleaseAsset)(
"runs the cached release binary under XDG_CACHE_HOME for the pinned version",
() =>
withFakeSupabaseTypegen(({ cwd, install }) =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
yield* fs.writeFileString(`${cwd}/Package.resolved`, PACKAGE_RESOLVED);
yield* install(`${cwd}/cache/supabase/typegen/${SWIFT_VERSION}`);
const output = yield* generate("swift").pipe(
Effect.provide(layerIn(cwd, { PATH: "/usr/bin:/bin", XDG_CACHE_HOME: `${cwd}/cache` })),
);
expectFakeSupabaseTypegenOutput(output);
}),
),
);

it.effect.skipIf(!hasSwiftReleaseAsset)(
"runs the cached release binary under HOME when XDG_CACHE_HOME is unset",
() =>
withFakeSupabaseTypegen(({ cwd, install }) =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const caches = process.platform === "darwin" ? "Library/Caches" : ".cache";
yield* fs.writeFileString(`${cwd}/Package.resolved`, PACKAGE_RESOLVED);
yield* install(`${cwd}/home/${caches}/supabase/typegen/${SWIFT_VERSION}`);
const output = yield* generate("swift").pipe(
Effect.provide(layerIn(cwd, { PATH: "/usr/bin:/bin", HOME: `${cwd}/home` })),
);
expectFakeSupabaseTypegenOutput(output);
}),
),
);
});

describe.skipIf(process.platform === "win32")(
"genTypesGeneratorLayer with a real subprocess",
() => {
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/src/commands/gen/types/types.generator.layer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ export const genTypesGeneratorLayer = Layer.effect(
PATH: yield* optionalEnv("PATH"),
PATHEXT: yield* optionalEnv("PATHEXT"),
ComSpec: yield* optionalEnv("ComSpec"),
XDG_CACHE_HOME: yield* optionalEnv("XDG_CACHE_HOME"),
HOME: yield* optionalEnv("HOME"),
};
return GenTypesGenerator.of({
generate: Effect.fn("GenTypes.generate")(function* (input: GenTypesGenerateInput) {
Expand Down
Loading
Loading