From cb8d5f89b9f5c85746ed86e75ba1e3e4c9fca360 Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 12 Nov 2026 19:59:58 -0300 Subject: [PATCH 1/2] fix(cli): pass SUPABASE_TYPEGEN, HOME and XDG_CACHE_HOME to the Swift typegen driver The Swift driver reads these variables from the host environment to find the supabase-typegen binary and its release cache. The generator layer passed only PATH, PATHEXT and ComSpec, so SUPABASE_TYPEGEN had no effect and the cache path resolved relative to the working directory, which put the downloaded binary inside the user's project. Closes CLI-3134 --- .../types/types.generator.integration.test.ts | 100 ++++++++++++++++++ .../gen/types/types.generator.layer.ts | 3 + .../commands/gen/types/types.typegen-host.ts | 5 +- 3 files changed, 107 insertions(+), 1 deletion(-) 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"]; From 0f4b16957e0ea651eddd66f2f82256e836efecfb Mon Sep 17 00:00:00 2001 From: Guilherme Souza Date: Thu, 12 Nov 2026 20:54:03 -0300 Subject: [PATCH 2/2] fix(cli): list SUPABASE_TYPEGEN among the non-config env names --- apps/cli/src/config/cli-config-key-annotations.ts | 1 + 1 file changed, 1 insertion(+) 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",