Skip to content
Merged
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
19 changes: 19 additions & 0 deletions .github/workflows/release-shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,17 @@ jobs:
git push origin "${note_ref}"
fi

# goreleaser used to publish both supabase_<version>_<os>_<arch>.tar.gz and
# supabase_<os>_<arch>.tar.gz; setup-cli, install scripts, docs and various
# third-party tools point at releases/latest/download/<unversioned>.tar.gz.
# Re-publish the alias so those callers keep working. See supabase/cli#5257.
- name: Create unversioned tarball aliases
run: |
set -euo pipefail
for triple in darwin_arm64 darwin_amd64 linux_arm64 linux_amd64 windows_arm64 windows_amd64; do
cp "dist/supabase_${{ inputs.version }}_${triple}.tar.gz" "dist/supabase_${triple}.tar.gz"
done

- name: Create draft GitHub Release
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2
with:
Expand All @@ -223,7 +234,15 @@ jobs:
dist/supabase_${{ inputs.version }}_linux_amd64.apk
dist/supabase_${{ inputs.version }}_windows_amd64.zip
dist/supabase_${{ inputs.version }}_windows_arm64.zip
dist/supabase_${{ inputs.version }}_windows_amd64.tar.gz
dist/supabase_${{ inputs.version }}_windows_arm64.tar.gz
dist/checksums.txt
dist/supabase_darwin_arm64.tar.gz
dist/supabase_darwin_amd64.tar.gz
dist/supabase_linux_arm64.tar.gz
dist/supabase_linux_amd64.tar.gz
dist/supabase_windows_arm64.tar.gz
dist/supabase_windows_amd64.tar.gz

- name: Publish GitHub Release (immutable)
env:
Expand Down
2 changes: 1 addition & 1 deletion .repos/effect
Submodule effect updated 749 files
2 changes: 1 addition & 1 deletion .repos/lalph
Submodule lalph updated 825 files
2 changes: 1 addition & 1 deletion .repos/opencode
Submodule opencode updated 811 files
2 changes: 1 addition & 1 deletion .repos/t3code
Submodule t3code updated 735 files
4 changes: 2 additions & 2 deletions apps/cli-e2e/src/server/pg-mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface PgFixture {
rows: (string | null)[][];
}

export interface PgError {
interface PgError {
/** 5-char SQLSTATE code, e.g. "42501" (insufficient_privilege). */
code: string;
/** Human-readable error message. */
Expand All @@ -46,7 +46,7 @@ export interface PgError {
severity?: string;
}

export type PgMockState =
type PgMockState =
| { type: "empty" }
| { type: "fixture"; fixture: PgFixture }
| { type: "error"; error: PgError };
Expand Down
38 changes: 18 additions & 20 deletions apps/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,13 @@
"check:all": "nx run-many -t types:check lint:check fmt:check knip:check --projects=$npm_package_name",
"fix:all": "nx run-many -t lint:fix fmt:fix knip:fix --projects=$npm_package_name"
},
"dependencies": {
"@clack/prompts": "^1.2.0",
"devDependencies": {
"@clack/prompts": "^1.4.0",
"@effect/atom-react": "catalog:",
"@effect/platform-bun": "catalog:",
"@napi-rs/keyring": "^1.1.2",
"@parcel/watcher": "^2.5.6",
"@vercel/detect-agent": "^1.2.3",
"effect": "catalog:",
"ink": "^7.0.1",
"ink-spinner": "^5.0.0",
"posthog-node": "^5.29.4",
"react": "^19.2.5"
},
"devDependencies": {
"@effect/vitest": "catalog:",
"@napi-rs/keyring": "^1.3.0",
"@parcel/watcher": "^2.5.6",
"@supabase/api": "workspace:*",
"@supabase/config": "workspace:*",
"@supabase/process-compose": "workspace:*",
Expand All @@ -59,23 +51,21 @@
"@types/bun": "catalog:",
"@types/react": "^19.2.14",
"@typescript/native-preview": "catalog:",
"@vercel/detect-agent": "^1.2.3",
"@vitest/coverage-istanbul": "catalog:",
"effect": "catalog:",
"ink": "^7.0.3",
"ink-spinner": "^5.0.0",
"knip": "catalog:",
"oxfmt": "catalog:",
"oxlint": "catalog:",
"oxlint-tsgolint": "catalog:",
"posthog-node": "^5.34.3",
"react": "^19.2.6",
"react-devtools-core": "^7.0.1",
"vitest": "catalog:"
},
"optionalDependencies": {
"@parcel/watcher-darwin-arm64": "2.5.6",
"@parcel/watcher-darwin-x64": "2.5.6",
"@parcel/watcher-linux-arm64-glibc": "2.5.6",
"@parcel/watcher-linux-arm64-musl": "2.5.6",
"@parcel/watcher-linux-x64-glibc": "2.5.6",
"@parcel/watcher-linux-x64-musl": "2.5.6",
"@parcel/watcher-win32-arm64": "2.5.6",
"@parcel/watcher-win32-x64": "2.5.6",
"@supabase/cli-darwin-arm64": "workspace:*",
"@supabase/cli-darwin-x64": "workspace:*",
"@supabase/cli-linux-arm64": "workspace:*",
Expand Down Expand Up @@ -112,6 +102,14 @@
"nx"
],
"ignoreDependencies": [
"@parcel/watcher-darwin-arm64",
"@parcel/watcher-darwin-x64",
"@parcel/watcher-linux-arm64-glibc",
"@parcel/watcher-linux-arm64-musl",
"@parcel/watcher-linux-x64-glibc",
"@parcel/watcher-linux-x64-musl",
"@parcel/watcher-win32-arm64",
"@parcel/watcher-win32-x64",
"@typescript/native-preview",
"oxfmt",
"oxlint",
Expand Down
17 changes: 17 additions & 0 deletions apps/cli/scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,16 @@ async function archiveTarget(target: (typeof TARGETS)[number]) {
const files = [path.join(binDir, `supabase${target.ext}`)];
if (shell === "legacy") files.push(path.join(binDir, `supabase-go${target.ext}`));
await $`zip -j ${archivePath} ${files}`;

// setup-cli and other download clients always fetch a .tar.gz, including on
// Windows where tc.extractTar handles the archive. Publish a matching
// tar.gz alongside the .zip so those clients keep working. See #5257.
const tarArchive = target.archive.replace(/\.zip$/, ".tar.gz");
const tarArchivePath = path.join(distDir, tarArchive);
const tarFiles = [`supabase${target.ext}`];
if (shell === "legacy") tarFiles.push(`supabase-go${target.ext}`);
console.log(`[${target.pkg}] Creating archive ${tarArchive}...`);
await $`tar -czf ${tarArchivePath} -C ${binDir} ${tarFiles}`;
} else {
const files = [`supabase${target.ext}`];
if (shell === "legacy") files.push(`supabase-go${target.ext}`);
Expand Down Expand Up @@ -250,6 +260,13 @@ async function generateChecksums() {
const data = await readFile(archivePath);
const hash = createHash("sha256").update(data).digest("hex");
lines.push(`${hash} ${target.archive}`);

if (target.archive.endsWith(".zip")) {
const tarArchive = target.archive.replace(/\.zip$/, ".tar.gz");
const tarData = await readFile(path.join(distDir, tarArchive));
const tarHash = createHash("sha256").update(tarData).digest("hex");
lines.push(`${tarHash} ${tarArchive}`);
}
}

const linuxTargets = TARGETS.filter((target) => "nfpmArch" in target);
Expand Down
8 changes: 8 additions & 0 deletions apps/cli/scripts/publish.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { $ } from "bun";
import { copyFile } from "node:fs/promises";
import path from "node:path";
import process from "node:process";
import { parseArgs } from "node:util";
Expand Down Expand Up @@ -136,6 +137,13 @@ const platformResults = await Promise.all(
console.log("\nBuilding umbrella package shim...");
await $`pnpm build:shim`.cwd(cliDir);

// npm renders the README from the package directory on the package page.
// The workspace-internal apps/cli/README.md documents the source layout for
// contributors, which is not what we want users to see on npmjs.com. Copy
// the repo root README — the user-facing one — over it just before publish.
console.log("\nStaging root README for umbrella package...");
await copyFile(path.join(root, "README.md"), path.join(cliDir, "README.md"));

console.log(`Publishing umbrella package ${umbrellaName}...`);
const umbrellaResult = await publishPackage({
name: umbrellaName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ Not applicable (proxied to Go binary).
- Requires a linked project (`--project-ref` or linked project config).
- Uses Docker by default to bundle functions; `--use-api` switches to server-side bundling.
- `--prune` deletes functions that exist in the Supabase project but not locally.
- `--jobs` (`-j`) sets the maximum number of parallel deploys; must be combined with `--use-api`.
- `--use-docker` and `--legacy-bundle` are hidden flags forwarded to the Go binary for backward compatibility; they are mutually exclusive with `--use-api`.
- Phase 0 proxy: all invocations are forwarded to the bundled Go binary.
17 changes: 17 additions & 0 deletions apps/cli/src/legacy/commands/functions/deploy/deploy.command.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Argument, Command, Flag } from "effect/unstable/cli";
import { withHidden } from "../../../../shared/cli/hidden-flag.ts";
import { legacyFunctionsDeploy } from "./deploy.handler.ts";

const config = {
Expand All @@ -23,6 +24,19 @@ const config = {
prune: Flag.boolean("prune").pipe(
Flag.withDescription("Delete Functions that exist in Supabase project but not locally."),
),
jobs: Flag.integer("jobs").pipe(
Flag.withAlias("j"),
Flag.withDescription("Maximum number of parallel jobs."),
Flag.optional,
),
useDocker: withHidden(
Flag.boolean("use-docker").pipe(
Flag.withDescription("Use Docker to bundle functions locally."),
),
),
legacyBundle: withHidden(
Flag.boolean("legacy-bundle").pipe(Flag.withDescription("Use legacy bundling.")),
),
} as const;

export const legacyFunctionsDeployCommand = Command.make("deploy", config).pipe(
Expand All @@ -36,6 +50,9 @@ export const legacyFunctionsDeployCommand = Command.make("deploy", config).pipe(
useApi: flags.useApi,
importMap: flags.importMap,
prune: flags.prune,
jobs: flags.jobs,
useDocker: flags.useDocker,
legacyBundle: flags.legacyBundle,
}),
),
);
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ interface LegacyFunctionsDeployFlags {
readonly useApi: boolean;
readonly importMap: Option.Option<string>;
readonly prune: boolean;
readonly jobs: Option.Option<number>;
readonly useDocker: boolean;
readonly legacyBundle: boolean;
}

export const legacyFunctionsDeploy = Effect.fn("legacy.functions.deploy")(function* (
Expand All @@ -21,5 +24,8 @@ export const legacyFunctionsDeploy = Effect.fn("legacy.functions.deploy")(functi
if (flags.useApi) args.push("--use-api");
if (Option.isSome(flags.importMap)) args.push("--import-map", flags.importMap.value);
if (flags.prune) args.push("--prune");
if (Option.isSome(flags.jobs)) args.push("--jobs", String(flags.jobs.value));
if (flags.useDocker) args.push("--use-docker");
if (flags.legacyBundle) args.push("--legacy-bundle");
yield* proxy.exec(args);
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ Not applicable (proxied to Go binary).

- If no function name is provided, downloads all functions.
- Requires a linked project (`--project-ref` or linked project config).
- `--use-docker` and `--legacy-bundle` are hidden flags forwarded to the Go binary for backward compatibility; they are mutually exclusive with `--use-api`.
- Phase 0 proxy: all invocations are forwarded to the bundled Go binary.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Argument, Command, Flag } from "effect/unstable/cli";
import type * as CliCommand from "effect/unstable/cli/Command";
import { withHidden } from "../../../../shared/cli/hidden-flag.ts";
import { legacyFunctionsDownload } from "./download.handler.ts";

const config = {
Expand All @@ -14,6 +15,14 @@ const config = {
useApi: Flag.boolean("use-api").pipe(
Flag.withDescription("Unbundle functions server-side without using Docker."),
),
useDocker: withHidden(
Flag.boolean("use-docker").pipe(
Flag.withDescription("Use Docker to unbundle functions locally."),
),
),
legacyBundle: withHidden(
Flag.boolean("legacy-bundle").pipe(Flag.withDescription("Use legacy bundling.")),
),
} as const;

export type LegacyFunctionsDownloadFlags = CliCommand.Command.Config.Infer<typeof config>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,7 @@ export const legacyFunctionsDownload = Effect.fn("legacy.functions.download")(fu
if (Option.isSome(flags.functionName)) args.push(flags.functionName.value);
if (Option.isSome(flags.projectRef)) args.push("--project-ref", flags.projectRef.value);
if (flags.useApi) args.push("--use-api");
if (flags.useDocker) args.push("--use-docker");
if (flags.legacyBundle) args.push("--legacy-bundle");
yield* proxy.exec(args);
});
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,5 @@ Not applicable (proxied to Go binary).
- `--env-file` path to env file populated to Function environment.
- `--import-map` path to custom import map.
- `--inspect` / `--inspect-mode` activates Deno inspector for debugging.
- `--all` is a hidden flag (default true) retained for backward compatibility; it has no effect because the Go CLI always serves all functions.
- Phase 0 proxy: all invocations are forwarded to the bundled Go binary.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Command, Flag } from "effect/unstable/cli";
import type * as CliCommand from "effect/unstable/cli/Command";
import { withHidden } from "../../../../shared/cli/hidden-flag.ts";
import { legacyFunctionsServe } from "./serve.handler.ts";

const INSPECT_MODES = ["run", "brk", "wait"] as const;
Expand All @@ -24,6 +25,9 @@ const config = {
inspectMain: Flag.boolean("inspect-main").pipe(
Flag.withDescription("Allow inspecting the main worker."),
),
all: withHidden(
Flag.boolean("all").pipe(Flag.withDescription("Serve all Functions."), Flag.optional),
),
} as const;

export type LegacyFunctionsServeFlags = CliCommand.Command.Config.Infer<typeof config>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export const legacyFunctionsServe = Effect.fn("legacy.functions.serve")(function
if (flags.inspect) args.push("--inspect");
if (Option.isSome(flags.inspectMode)) args.push("--inspect-mode", flags.inspectMode.value);
if (flags.inspectMain) args.push("--inspect-main");
if (Option.isSome(flags.all)) args.push(`--all=${flags.all.value ? "true" : "false"}`);
yield* proxy.exec(args);
});
4 changes: 4 additions & 0 deletions apps/cli/src/legacy/commands/gen/types/types.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ const config = {
postgrestV9Compat: Flag.boolean("postgrest-v9-compat").pipe(
Flag.withDescription("Generate types compatible with PostgREST v9 and below."),
),
queryTimeout: Flag.string("query-timeout").pipe(
Flag.withDescription("Maximum timeout allowed for the database query."),
Flag.optional,
),
} as const;

export type LegacyGenTypesFlags = CliCommand.Command.Config.Infer<typeof config>;
Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/legacy/commands/gen/types/types.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ export const legacyGenTypes = Effect.fn("legacy.gen.types")(function* (flags: Le
if (Option.isSome(flags.swiftAccessControl))
args.push("--swift-access-control", flags.swiftAccessControl.value);
if (flags.postgrestV9Compat) args.push("--postgrest-v9-compat");
if (Option.isSome(flags.queryTimeout)) args.push("--query-timeout", flags.queryTimeout.value);
yield* proxy.exec(args);
});
14 changes: 14 additions & 0 deletions apps/cli/src/legacy/commands/projects/create/create.command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Argument, Command, Flag } from "effect/unstable/cli";
import type * as CliCommand from "effect/unstable/cli/Command";
import { withHidden } from "../../../../shared/cli/hidden-flag.ts";
import { legacyProjectsCreate } from "./create.handler.ts";

const AWS_REGIONS = [
Expand Down Expand Up @@ -66,6 +67,19 @@ const config = {
Flag.withDescription("Select a desired instance size for your project."),
Flag.optional,
),
interactive: withHidden(
Flag.boolean("interactive").pipe(
Flag.withDescription("Enables interactive mode."),
Flag.withAlias("i"),
Flag.optional,
),
),
plan: withHidden(
Flag.string("plan").pipe(
Flag.withDescription("Select a plan that suits your needs."),
Flag.optional,
),
),
};
export type LegacyProjectsCreateFlags = CliCommand.Command.Config.Infer<typeof config>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ export const legacyProjectsCreate = Effect.fn("legacy.projects.create")(function
if (Option.isSome(flags.dbPassword)) args.push("--db-password", flags.dbPassword.value);
if (Option.isSome(flags.region)) args.push("--region", flags.region.value);
if (Option.isSome(flags.size)) args.push("--size", flags.size.value);
if (Option.isSome(flags.interactive))
args.push(`--interactive=${flags.interactive.value ? "true" : "false"}`);
if (Option.isSome(flags.plan)) args.push("--plan", flags.plan.value);
yield* proxy.exec(args);
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Command } from "effect/unstable/cli";
import { Command, Flag } from "effect/unstable/cli";
import type * as CliCommand from "effect/unstable/cli/Command";
import { legacyBuckets } from "./buckets.handler.ts";

const config = {} as const;
const config = {
linked: Flag.boolean("linked").pipe(Flag.withDescription("Seeds the linked project.")),
local: Flag.boolean("local").pipe(Flag.withDescription("Seeds the local database.")),
} as const;

export type LegacyBucketsFlags = CliCommand.Command.Config.Infer<typeof config>;

Expand Down
Loading
Loading