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
6 changes: 5 additions & 1 deletion .github/workflows/release-shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,10 @@ jobs:
run: chmod +x packages/cli-*/bin/supabase || true

- name: Run smoke tests
# Force bash so ${VERSION}/${NPM_TAG} expand identically across the
# ubuntu/macos/windows matrix — windows-latest defaults to pwsh, which
# treats those as empty PowerShell variables (env vars are `$env:VAR`).
shell: bash
run: pnpm run test:smoke -- --version "${VERSION}" --tag "${NPM_TAG}"
working-directory: apps/cli

Expand Down Expand Up @@ -164,7 +168,7 @@ jobs:
run: pnpm exec bun apps/cli/scripts/sync-versions.ts --version "${VERSION}"

- name: Publish to npm
run: pnpm exec bun apps/cli/scripts/publish.ts --tag ""${NPM_TAG}""
run: pnpm exec bun apps/cli/scripts/publish.ts --tag "${NPM_TAG}"

# Push the version tag to origin as soon as npm has the bytes, before any
# downstream step that can fail. Without this, a failure in the GH-release
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/src/legacy/commands/branches/branches.command.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Command } from "effect/unstable/cli";
import { withHiddenSubcommands } from "../../../shared/cli/hidden-flag.ts";
import { legacyBranchesListCommand } from "./list/list.command.ts";
import { legacyBranchesCreateCommand } from "./create/create.command.ts";
import { legacyBranchesGetCommand } from "./get/get.command.ts";
Expand All @@ -11,6 +12,7 @@ import { legacyBranchesDisableCommand } from "./disable/disable.command.ts";
export const legacyBranchesCommand = Command.make("branches").pipe(
Command.withDescription("Manage Supabase preview branches."),
Command.withShortDescription("Manage preview branches"),
withHiddenSubcommands(["disable"]),
Command.withSubcommands([
legacyBranchesListCommand,
legacyBranchesCreateCommand,
Expand Down
2 changes: 2 additions & 0 deletions apps/cli/src/legacy/commands/db/db.command.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Command } from "effect/unstable/cli";
import { withHiddenSubcommands } from "../../../shared/cli/hidden-flag.ts";
import { legacyDbDiffCommand } from "./diff/diff.command.ts";
import { legacyDbDumpCommand } from "./dump/dump.command.ts";
import { legacyDbPushCommand } from "./push/push.command.ts";
Expand All @@ -16,6 +17,7 @@ import { legacyDbSchemaCommand } from "./schema/schema.command.ts";
export const legacyDbCommand = Command.make("db").pipe(
Command.withDescription("Manage Postgres databases."),
Command.withShortDescription("Manage databases"),
withHiddenSubcommands(["branch", "remote", "test"]),
Command.withSubcommands([
legacyDbDiffCommand,
legacyDbDumpCommand,
Expand Down
36 changes: 32 additions & 4 deletions apps/cli/src/shared/cli/hidden-flag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ export const LegacyHiddenFlags: Context.Reference<ReadonlySet<string>> = Context
defaultValue: () => new Set<string>(),
});

export const LegacyHiddenSubcommands: Context.Reference<ReadonlySet<string>> = Context.Reference<
ReadonlySet<string>
>("supabase/legacy/LegacyHiddenSubcommands", {
defaultValue: () => new Set<string>(),
});

const hiddenFlagNames = new WeakMap<object, ReadonlyArray<string>>();

const collectSingleNames = (param: Param.Param<Param.ParamKind, unknown>): Array<string> => {
Expand Down Expand Up @@ -70,14 +76,36 @@ export const withHiddenFromConfig =
return Command.annotate(cmd, LegacyHiddenFlags, hidden);
};

export const withHiddenSubcommands =
(names: ReadonlyArray<string>) =>
<Name extends string, Input, ContextInput, E, R>(
cmd: Command.Command<Name, Input, ContextInput, E, R>,
): Command.Command<Name, Input, ContextInput, E, R> =>
Command.annotate(cmd, LegacyHiddenSubcommands, new Set(names));

export const stripHiddenFlagsFromHelpDoc = (doc: HelpDoc.HelpDoc): HelpDoc.HelpDoc => {
const hidden = Context.get(doc.annotations, LegacyHiddenFlags);
if (hidden.size === 0) return doc;
const filteredFlags = doc.flags.filter((flag) => !hidden.has(flag.name));
const filteredGlobalFlags = doc.globalFlags?.filter((flag) => !hidden.has(flag.name));
const hiddenFlags = Context.get(doc.annotations, LegacyHiddenFlags);
const hiddenSubcommands = Context.get(doc.annotations, LegacyHiddenSubcommands);
if (hiddenFlags.size === 0 && hiddenSubcommands.size === 0) return doc;
const filteredFlags = doc.flags.filter((flag) => !hiddenFlags.has(flag.name));
const filteredGlobalFlags = doc.globalFlags?.filter((flag) => !hiddenFlags.has(flag.name));
const filteredSubcommands = doc.subcommands?.flatMap((group) => {
const commands = group.commands.filter((command) => !hiddenSubcommands.has(command.name));
if (commands.length === 0) return [];
return [
{
...group,
commands: commands as unknown as readonly [
HelpDoc.SubcommandDoc,
...Array<HelpDoc.SubcommandDoc>,
],
},
];
});
return {
...doc,
flags: filteredFlags,
...(filteredSubcommands !== undefined && { subcommands: filteredSubcommands }),
...(filteredGlobalFlags !== undefined && { globalFlags: filteredGlobalFlags }),
};
};
42 changes: 42 additions & 0 deletions apps/cli/src/shared/cli/hidden-flag.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { Command, Flag, type HelpDoc } from "effect/unstable/cli";
import { describe, expect, it } from "vitest";
import {
LegacyHiddenFlags,
LegacyHiddenSubcommands,
stripHiddenFlagsFromHelpDoc,
withHidden,
withHiddenFromConfig,
withHiddenSubcommands,
} from "./hidden-flag.ts";

const flagDoc = (name: string): HelpDoc.FlagDoc => ({
Expand Down Expand Up @@ -33,6 +35,15 @@ const helpDocWithHidden = (
annotations: Context.make(LegacyHiddenFlags, new Set(hidden)),
});

const helpDocWithHiddenSubcommands = (
hidden: ReadonlyArray<string>,
overrides: Partial<HelpDoc.HelpDoc>,
): HelpDoc.HelpDoc =>
helpDoc({
...overrides,
annotations: Context.make(LegacyHiddenSubcommands, new Set(hidden)),
});

// Reach into the internal command shape to obtain the help doc the formatter
// would render. Effect builds this from `Command.annotations`, which is the
// contract `withHiddenFromConfig` relies on.
Expand Down Expand Up @@ -110,6 +121,15 @@ describe("withHiddenFromConfig", () => {
});
});

describe("withHiddenSubcommands", () => {
it("adds hidden subcommand annotations to the command help doc", () => {
const cmd = Command.make("demo").pipe(withHiddenSubcommands(["legacy"]));
const annotated = Context.get(buildHelpDoc(cmd).annotations, LegacyHiddenSubcommands);

expect([...annotated]).toEqual(["legacy"]);
});
});

describe("stripHiddenFlagsFromHelpDoc", () => {
it("returns the doc unchanged when annotations are empty", () => {
const doc = helpDoc({ flags: [flagDoc("foo")] });
Expand All @@ -134,4 +154,26 @@ describe("stripHiddenFlagsFromHelpDoc", () => {
expect(stripped.globalFlags).toBeUndefined();
expect(stripped.flags.map((f) => f.name)).toEqual(["bar"]);
});

it("filters hidden subcommands by the doc's annotation", () => {
const doc = helpDocWithHiddenSubcommands(["legacy"], {
subcommands: [
{
group: undefined,
commands: [
{
name: "visible",
alias: undefined,
shortDescription: "visible",
description: "visible",
},
{ name: "legacy", alias: undefined, shortDescription: "legacy", description: "legacy" },
],
},
],
});

const stripped = stripHiddenFlagsFromHelpDoc(doc);
expect(stripped.subcommands?.[0]?.commands.map((command) => command.name)).toEqual(["visible"]);
});
});
Loading