diff --git a/.changeset/six-moons-shine.md b/.changeset/six-moons-shine.md new file mode 100644 index 00000000..4c327421 --- /dev/null +++ b/.changeset/six-moons-shine.md @@ -0,0 +1,5 @@ +--- +"@opennextjs/cloudflare": patch +--- + +feat: pass cli arguments not used by `opennextjs-cloudflare` to wrangler diff --git a/packages/cloudflare/src/cli/args.spec.ts b/packages/cloudflare/src/cli/args.spec.ts new file mode 100644 index 00000000..90877ea5 --- /dev/null +++ b/packages/cloudflare/src/cli/args.spec.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from "vitest"; + +import { getPassthroughArgs } from "./args.js"; + +describe("getPassthroughArgs", () => { + it("should return args not used by the cli", () => { + const args = [ + "pnpm", + "/opennextjs/cloudflare/examples/ssg-app/node_modules/@opennextjs/cloudflare/dist/cli/index.js", + "preview", + "--skipBuild", + "--preview", + "-t", + "-v=1", + "-pre", + "152", + "--pre2=1543", + "--", + "--port", + "1234", + "--inspector-port", + "1234", + ]; + + expect(getPassthroughArgs(args, { options: { skipBuild: { type: "boolean" } } })).toEqual([ + "--preview", + "-t", + "-v=1", + "-pre", + "152", + "--pre2=1543", + "--port", + "1234", + "--inspector-port", + "1234", + ]); + }); +}); diff --git a/packages/cloudflare/src/cli/args.ts b/packages/cloudflare/src/cli/args.ts index 292e3f7e..ef9c449b 100644 --- a/packages/cloudflare/src/cli/args.ts +++ b/packages/cloudflare/src/cli/args.ts @@ -1,5 +1,6 @@ import { mkdirSync, type Stats, statSync } from "node:fs"; import { resolve } from "node:path"; +import type { ParseArgsConfig } from "node:util"; import { parseArgs } from "node:util"; import type { WranglerTarget } from "./utils/run-wrangler.js"; @@ -25,32 +26,34 @@ export type Arguments = ( } ) & { outputDir?: string }; +// Config for parsing CLI arguments +const config = { + allowPositionals: true, + strict: false, + options: { + skipBuild: { type: "boolean", short: "s", default: false }, + output: { type: "string", short: "o" }, + noMinify: { type: "boolean", default: false }, + skipWranglerConfigCheck: { type: "boolean", default: false }, + cacheChunkSize: { type: "string" }, + }, +} as const satisfies ParseArgsConfig; + export function getArgs(): Arguments { - const { positionals, values } = parseArgs({ - options: { - skipBuild: { type: "boolean", short: "s", default: false }, - output: { type: "string", short: "o" }, - noMinify: { type: "boolean", default: false }, - skipWranglerConfigCheck: { type: "boolean", default: false }, - cacheChunkSize: { type: "string" }, - }, - allowPositionals: true, - }); + const { positionals, values } = parseArgs(config); - const outputDir = values.output ? resolve(values.output) : undefined; + const outputDir = typeof values.output === "string" ? resolve(values.output) : undefined; if (outputDir) assertDirArg(outputDir, "output", true); - const passthroughArgs = getPassthroughArgs(); - switch (positionals[0]) { case "build": return { command: "build", outputDir, skipNextBuild: - values.skipBuild || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)), + !!values.skipBuild || ["1", "true", "yes"].includes(String(process.env.SKIP_NEXT_APP_BUILD)), skipWranglerConfigCheck: - values.skipWranglerConfigCheck || + !!values.skipWranglerConfigCheck || ["1", "true", "yes"].includes(String(process.env.SKIP_WRANGLER_CONFIG_CHECK)), minify: !values.noMinify, }; @@ -60,7 +63,7 @@ export function getArgs(): Arguments { return { command: positionals[0], outputDir, - passthroughArgs, + passthroughArgs: getPassthroughArgs(process.argv, config), ...(values.cacheChunkSize && { cacheChunkSize: Number(values.cacheChunkSize) }), }; case "populateCache": @@ -71,7 +74,7 @@ export function getArgs(): Arguments { command: "populateCache", outputDir, target: positionals[1], - environment: getWranglerEnvironmentFlag(passthroughArgs), + environment: getWranglerEnvironmentFlag(process.argv), ...(values.cacheChunkSize && { cacheChunkSize: Number(values.cacheChunkSize) }), }; default: @@ -81,9 +84,26 @@ export function getArgs(): Arguments { } } -function getPassthroughArgs() { - const passthroughPos = process.argv.indexOf("--"); - return passthroughPos === -1 ? [] : process.argv.slice(passthroughPos + 1); +export function getPassthroughArgs(args: string[], { options = {} }: T) { + const passthroughArgs: string[] = []; + + for (let i = 0; i < args.length; i++) { + if (args[i] === "--") { + passthroughArgs.push(...args.slice(i + 1)); + return passthroughArgs; + } + + const [, name] = /^--?(\w[\w-_]*)(=.+)?$/.exec(args[i]!) ?? []; + if (name && !(name in options)) { + passthroughArgs.push(args[i]!); + + while (!args[i + 1]?.startsWith("-")) { + passthroughArgs.push(args[++i]!); + } + } + } + + return passthroughArgs; } function assertDirArg(path: string, argName?: string, make?: boolean) {