diff --git a/apps/cli/docs/go-cli-porting-status.md b/apps/cli/docs/go-cli-porting-status.md index ce27ec807d..84db7a7f55 100644 --- a/apps/cli/docs/go-cli-porting-status.md +++ b/apps/cli/docs/go-cli-porting-status.md @@ -308,7 +308,7 @@ Legend: | `functions download` | `ported` | [`../src/legacy/commands/functions/download/download.command.ts`](../src/legacy/commands/functions/download/download.command.ts) — native for `--use-api` (lists, downloads, and extracts via the Management API directly) and the default Docker-unbundle path (`--use-docker`, CLI-1963); hidden `--legacy-bundle` still delegates to the Go binary (pre-1.120.0 fallback requiring a host Deno-binary install with no precedent elsewhere in this codebase — tracked separately, see CLI-1963) | | `functions deploy` | `ported` | [`../src/legacy/commands/functions/deploy/deploy.command.ts`](../src/legacy/commands/functions/deploy/deploy.command.ts) — Intentional divergence (CLI-2179, ruled 2026-08-12; PR #6164): the functions import scanner (`walkImportPaths`/`substituteImportMapValue`, shared with `functions serve` and `start`'s Edge Runtime bring-up) matches import-map keys per the import-maps spec that Deno/edge-runtime implement — a key matches exactly, or as a prefix only when it ends with `/`, and a `/`-suffixed key normalizes away entirely when its value does not also end in `/` — diverging from Go's any-key `strings.HasPrefix` (`pkg/function/deno.go:150-155`). Because the runtime is itself spec-compliant, Go's lax matching only ever fabricated paths the runtime could never resolve, producing the ENOTDIR crash family and mounting/uploading files no import can reach. Deploy upload sets and serve/start bind mounts may shrink for maps that relied on bare-key prefix matching; no runtime-resolvable import is affected. | | `functions new` | `ported` | [`../src/legacy/commands/functions/new/new.command.ts`](../src/legacy/commands/functions/new/new.command.ts) | -| `functions serve` | `ported` | [`../src/legacy/commands/functions/serve/serve.command.ts`](../src/legacy/commands/functions/serve/serve.command.ts) — Intentional divergence (CLI-2179, ruled 2026-08-12; PR #6164): shares the spec-strict import-map key matching described in the `functions deploy` row (`walkImportPaths`/`substituteImportMapValue`); bind mounts may shrink for maps that relied on Go's bare-key `strings.HasPrefix` matching (`pkg/function/deno.go:150-155`), but no runtime-resolvable import is affected. | +| `functions serve` | `ported` | [`../src/legacy/commands/functions/serve/serve.command.ts`](../src/legacy/commands/functions/serve/serve.command.ts) — Accepts and ignores any legacy Function name positional arguments, preserving parser compatibility while serving all Functions like the current Go command. Intentional divergence (CLI-2179, ruled 2026-08-12; PR #6164): shares the spec-strict import-map key matching described in the `functions deploy` row (`walkImportPaths`/`substituteImportMapValue`); bind mounts may shrink for maps that relied on Go's bare-key `strings.HasPrefix` matching (`pkg/function/deno.go:150-155`), but no runtime-resolvable import is affected. | | `storage ls` | `ported` | [`../src/legacy/commands/storage/ls/ls.command.ts`](../src/legacy/commands/storage/ls/ls.command.ts) | | `storage cp` | `ported` | [`../src/legacy/commands/storage/cp/cp.command.ts`](../src/legacy/commands/storage/cp/cp.command.ts) | | `storage mv` | `ported` | [`../src/legacy/commands/storage/mv/mv.command.ts`](../src/legacy/commands/storage/mv/mv.command.ts) | diff --git a/apps/cli/src/legacy/commands/functions/serve/SIDE_EFFECTS.md b/apps/cli/src/legacy/commands/functions/serve/SIDE_EFFECTS.md index fd1aac8776..460aa1fdd6 100644 --- a/apps/cli/src/legacy/commands/functions/serve/SIDE_EFFECTS.md +++ b/apps/cli/src/legacy/commands/functions/serve/SIDE_EFFECTS.md @@ -94,6 +94,9 @@ Long-running raw log / error events only; there is no terminal `result` event on ## Notes +- Any legacy Function name positional arguments are accepted and ignored. The command always + serves every discovered Function, matching the current Go behavior while preserving invocations + such as `supabase functions serve `. - The hidden `--all` flag is still parsed but ignored; the native port always serves every discovered function, matching the Go command. - Each restart re-reads config, rebuilds per-function bind mounts, recreates the `supabase_edge_runtime_` container, and best-effort reloads Kong afterwards. - The command creates or reuses Docker resources derived from the resolved project id: diff --git a/apps/cli/src/legacy/commands/functions/serve/serve.command.integration.test.ts b/apps/cli/src/legacy/commands/functions/serve/serve.command.integration.test.ts new file mode 100644 index 0000000000..c2ef452ec3 --- /dev/null +++ b/apps/cli/src/legacy/commands/functions/serve/serve.command.integration.test.ts @@ -0,0 +1,33 @@ +import { describe, expect, it } from "@effect/vitest"; +import { BunServices } from "@effect/platform-bun"; +import { Effect, Exit, Layer } from "effect"; +import { CliOutput, Command } from "effect/unstable/cli"; +import { textCliOutputFormatter } from "../../../../shared/output/text-formatter.ts"; +import { legacyFunctionsServeCommand } from "./serve.command.ts"; + +describe("legacy functions serve command", () => { + it.live("accepts all legacy function name positional arguments", () => { + let handlerRan = false; + let parsedFunctionNames: ReadonlyArray = []; + const command = legacyFunctionsServeCommand.pipe( + Command.withHandler(({ legacyFunctionNames }) => + Effect.sync(() => { + handlerRan = true; + parsedFunctionNames = legacyFunctionNames; + }), + ), + ); + + return Effect.gen(function* () { + const exit = yield* Command.runWith(command, { + version: "0.0.0-test", + })(["hello-world", "send-email"]).pipe(Effect.exit); + + expect(Exit.isSuccess(exit)).toBe(true); + expect(handlerRan).toBe(true); + expect(parsedFunctionNames).toEqual(["hello-world", "send-email"]); + }).pipe( + Effect.provide(Layer.mergeAll(BunServices.layer, CliOutput.layer(textCliOutputFormatter()))), + ); + }); +}); diff --git a/apps/cli/src/legacy/commands/functions/serve/serve.command.ts b/apps/cli/src/legacy/commands/functions/serve/serve.command.ts index 83992053b6..bc269fc45a 100644 --- a/apps/cli/src/legacy/commands/functions/serve/serve.command.ts +++ b/apps/cli/src/legacy/commands/functions/serve/serve.command.ts @@ -1,5 +1,5 @@ import { Layer } from "effect"; -import { Command, Flag } from "effect/unstable/cli"; +import { Argument, Command, Flag } from "effect/unstable/cli"; import { withJsonErrorHandling } from "../../../../shared/output/json-error-handling.ts"; import { commandRuntimeLayer } from "../../../../shared/runtime/command-runtime.layer.ts"; import { @@ -49,7 +49,15 @@ const config = { ), } as const; -export const legacyFunctionsServeCommand = Command.make("serve", config).pipe( +const commandConfig = { + ...config, + legacyFunctionNames: Argument.string("Function name").pipe( + Argument.withDescription("Legacy Function names. All Functions are served."), + Argument.variadic(), + ), +} as const; + +export const legacyFunctionsServeCommand = Command.make("serve", commandConfig).pipe( Command.withDescription("Serve all Functions locally."), Command.withShortDescription("Serve all Functions locally"), Command.withHandler((flags) =>