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
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,5 @@ Not applicable (proxied to Go binary).
- 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.
11 changes: 11 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 Down Expand Up @@ -28,6 +29,14 @@ const config = {
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 @@ -42,6 +51,8 @@ export const legacyFunctionsDeployCommand = Command.make("deploy", config).pipe(
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 @@ -9,6 +9,8 @@ interface LegacyFunctionsDeployFlags {
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 @@ -23,5 +25,7 @@ export const legacyFunctionsDeploy = Effect.fn("legacy.functions.deploy")(functi
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);
});
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ import { LegacyGoProxy } from "../../../../shared/legacy/go-proxy.service.ts";
import type { LegacyBucketsFlags } from "./buckets.command.ts";

export const legacyBuckets = Effect.fn("legacy.seed.buckets")(function* (
_flags: LegacyBucketsFlags,
flags: LegacyBucketsFlags,
) {
const proxy = yield* LegacyGoProxy;
yield* proxy.exec(["seed", "buckets"]);
const args: string[] = ["seed", "buckets"];
if (flags.linked) args.push("--linked");
if (flags.local) args.push("--local");
yield* proxy.exec(args);
});
4 changes: 4 additions & 0 deletions apps/cli/src/legacy/commands/start/start.command.ts
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 { legacyStart } from "./start.handler.ts";

const config = {
Expand All @@ -14,6 +15,9 @@ const config = {
ignoreHealthCheck: Flag.boolean("ignore-health-check").pipe(
Flag.withDescription("Ignore unhealthy services and exit 0"),
),
preview: withHidden(
Flag.boolean("preview").pipe(Flag.withDescription("Connect to feature preview branch")),
),
} as const;

export type LegacyStartFlags = CliCommand.Command.Config.Infer<typeof config>;
Expand Down
1 change: 1 addition & 0 deletions apps/cli/src/legacy/commands/start/start.handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ export const legacyStart = Effect.fn("legacy.start")(function* (flags: LegacySta
const args: string[] = ["start"];
for (const name of flags.exclude) args.push("--exclude", name);
if (flags.ignoreHealthCheck) args.push("--ignore-health-check");
if (flags.preview) args.push("--preview");
yield* proxy.exec(args);
});
44 changes: 44 additions & 0 deletions apps/cli/src/shared/cli/hidden-flag.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { Flag, HelpDoc } from "effect/unstable/cli";
import type * as Param from "effect/unstable/cli/Param";

const hiddenFlagNames = new Set<string>();

const collectSingleNames = (param: Param.Param<Param.ParamKind, unknown>): Array<string> => {
const node = param as
| Param.Single<Param.ParamKind, unknown>
| Param.Map<Param.ParamKind, unknown, unknown>
| Param.Transform<Param.ParamKind, unknown, unknown>
| Param.Optional<Param.ParamKind, unknown>
| Param.Variadic<Param.ParamKind, unknown>;
switch (node._tag) {
case "Single":
return [node.name];
case "Map":
case "Transform":
case "Optional":
case "Variadic":
return collectSingleNames(node.param);
}
};

/**
* Marks a flag as hidden so that it is parsed normally but omitted from
* `--help` output. This mirrors Cobra's `MarkHidden` from the Go CLI, which
* the upstream Effect CLI does not yet expose natively.
*/
export const withHidden = <A>(flag: Flag.Flag<A>): Flag.Flag<A> => {
for (const name of collectSingleNames(flag)) {
hiddenFlagNames.add(name);
}
return flag;
};

export const stripHiddenFlagsFromHelpDoc = (doc: HelpDoc.HelpDoc): HelpDoc.HelpDoc => {
const filteredFlags = doc.flags.filter((flag) => !hiddenFlagNames.has(flag.name));
const filteredGlobalFlags = doc.globalFlags?.filter((flag) => !hiddenFlagNames.has(flag.name));
return {
...doc,
flags: filteredFlags,
...(filteredGlobalFlags !== undefined && { globalFlags: filteredGlobalFlags }),
};
};
52 changes: 52 additions & 0 deletions apps/cli/src/shared/cli/hidden-flag.unit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Context, Option } from "effect";
import { Flag, type HelpDoc } from "effect/unstable/cli";
import { describe, expect, it } from "vitest";
import { stripHiddenFlagsFromHelpDoc, withHidden } from "./hidden-flag.ts";

const flagDoc = (name: string): HelpDoc.FlagDoc => ({
name,
aliases: [`--${name}`],
type: "boolean",
description: Option.none(),
required: false,
});

const helpDoc = (overrides: Partial<HelpDoc.HelpDoc>): HelpDoc.HelpDoc => ({
description: "",
usage: "",
flags: [],
annotations: Context.empty(),
...overrides,
});

describe("withHidden", () => {
it("returns the same flag instance", () => {
const flag = Flag.boolean("legacy-bundle");
expect(withHidden(flag)).toBe(flag);
});

it("registers the underlying single name even when wrapped with combinators", () => {
const flag = Flag.string("plan").pipe(Flag.optional);
withHidden(flag);

const stripped = stripHiddenFlagsFromHelpDoc(
helpDoc({ flags: [flagDoc("plan"), flagDoc("visible")] }),
);
expect(stripped.flags.map((f) => f.name)).toEqual(["visible"]);
});

it("filters hidden flags from globalFlags as well", () => {
withHidden(Flag.boolean("preview"));

const stripped = stripHiddenFlagsFromHelpDoc(
helpDoc({ globalFlags: [flagDoc("preview"), flagDoc("verbose")] }),
);
expect(stripped.globalFlags?.map((f) => f.name)).toEqual(["verbose"]);
});

it("leaves docs without globalFlags untouched", () => {
const stripped = stripHiddenFlagsFromHelpDoc(helpDoc({ flags: [flagDoc("foo")] }));
expect(stripped.globalFlags).toBeUndefined();
expect(stripped.flags.map((f) => f.name)).toEqual(["foo"]);
});
});
4 changes: 3 additions & 1 deletion apps/cli/src/shared/output/json-formatter.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { CliOutput, HelpDoc } from "effect/unstable/cli";
import { stripHiddenFlagsFromHelpDoc } from "../cli/hidden-flag.ts";

export function jsonCliOutputFormatter(): CliOutput.Formatter {
return {
formatHelpDoc: (doc: HelpDoc.HelpDoc) => JSON.stringify({ _tag: "Help", doc }),
formatHelpDoc: (doc: HelpDoc.HelpDoc) =>
JSON.stringify({ _tag: "Help", doc: stripHiddenFlagsFromHelpDoc(doc) }),
formatCliError: (error) =>
JSON.stringify({ _tag: "Error", error: { code: error._tag, message: error.message } }),
formatError: (error) =>
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/src/shared/output/text-formatter.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { CliOutput } from "effect/unstable/cli";
import { stripHiddenFlagsFromHelpDoc } from "../cli/hidden-flag.ts";

export function textCliOutputFormatter(): CliOutput.Formatter {
const base = CliOutput.defaultFormatter({ colors: false });
return {
...base,
formatHelpDoc: (doc) => base.formatHelpDoc(stripHiddenFlagsFromHelpDoc(doc)),
formatVersion: (_name, version) => version,
};
}
Loading