diff --git a/apps/cli/src/commands/gen/types/types.generator.integration.test.ts b/apps/cli/src/commands/gen/types/types.generator.integration.test.ts
index 3866e553e0..e4de6b0c2c 100644
--- a/apps/cli/src/commands/gen/types/types.generator.integration.test.ts
+++ b/apps/cli/src/commands/gen/types/types.generator.integration.test.ts
@@ -99,6 +99,106 @@ const withFakeDart = (
return yield* body({ cwd, bin });
}).pipe(Effect.provide(BunServices.layer));
+/** A stand-in `supabase-typegen` that echoes its arguments and its stdin. */
+const FAKE_SUPABASE_TYPEGEN = `#!/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 = (
+ body: (context: {
+ readonly cwd: string;
+ readonly install: (directory: string) => Effect.Effect;
+ }) => Effect.Effect,
+) =>
+ 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_SUPABASE_TYPEGEN);
+ 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("runs the binary SUPABASE_TYPEGEN names", () =>
+ withFakeSupabaseTypegen(({ cwd, install }) =>
+ Effect.gen(function* () {
+ const binary = yield* install(`${cwd}/tools`);
+ const output = yield* generate("swift").pipe(
+ Effect.provide(layerIn(cwd, { PATH: "/usr/bin:/bin", SUPABASE_TYPEGEN: binary })),
+ );
+ expectFakeSupabaseTypegenOutput(output);
+ }),
+ ),
+ );
+
+ 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",
() => {
diff --git a/apps/cli/src/commands/gen/types/types.generator.layer.ts b/apps/cli/src/commands/gen/types/types.generator.layer.ts
index 447a9a2f8f..33f0ecac81 100644
--- a/apps/cli/src/commands/gen/types/types.generator.layer.ts
+++ b/apps/cli/src/commands/gen/types/types.generator.layer.ts
@@ -72,6 +72,9 @@ export const genTypesGeneratorLayer = Layer.effect(
PATH: yield* optionalEnv("PATH"),
PATHEXT: yield* optionalEnv("PATHEXT"),
ComSpec: yield* optionalEnv("ComSpec"),
+ SUPABASE_TYPEGEN: yield* optionalEnv("SUPABASE_TYPEGEN"),
+ XDG_CACHE_HOME: yield* optionalEnv("XDG_CACHE_HOME"),
+ HOME: yield* optionalEnv("HOME"),
};
return GenTypesGenerator.of({
generate: Effect.fn("GenTypes.generate")(function* (input: GenTypesGenerateInput) {
diff --git a/apps/cli/src/commands/gen/types/types.typegen-host.ts b/apps/cli/src/commands/gen/types/types.typegen-host.ts
index 0776ea4c05..f1efb2a074 100644
--- a/apps/cli/src/commands/gen/types/types.typegen-host.ts
+++ b/apps/cli/src/commands/gen/types/types.typegen-host.ts
@@ -15,7 +15,10 @@ import { withProcessSpanScoped } from "../../../shared/telemetry/spans.ts";
export interface TypegenHostOptions {
/** Where out-of-process tools run: the directory the command was invoked from. */
readonly cwd: string;
- /** What the registry's Windows lookup reads; the child inherits the full environment. */
+ /**
+ * What the registry's drivers read: the Windows tool lookup and the Swift binary resolution.
+ * The child inherits the full environment.
+ */
readonly env: Readonly>;
readonly platform: NodeJS.Platform;
readonly spawner: ChildProcessSpawner.ChildProcessSpawner["Service"];
diff --git a/apps/cli/src/config/cli-config-key-annotations.ts b/apps/cli/src/config/cli-config-key-annotations.ts
index a8ac6fa9f0..a0cc2eee08 100644
--- a/apps/cli/src/config/cli-config-key-annotations.ts
+++ b/apps/cli/src/config/cli-config-key-annotations.ts
@@ -355,6 +355,7 @@ export const CLI_NON_CONFIG_ENV_NAMES: Readonly> = {
SUPABASE_TELEMETRY_POSTHOG_HOST: "telemetry",
SUPABASE_TELEMETRY_POSTHOG_KEY: "telemetry",
SUPABASE_TRACE_FILE: "telemetry",
+ SUPABASE_TYPEGEN: "gen types swift binary",
SUPABASE_URL: "functions runtime env",
SUPABASE_USE_SLIM_IMAGES: "image selection",
SUPABASE_WORKDIR: "global flag",