From 5c545870141219404981a7f18d2019db59a69896 Mon Sep 17 00:00:00 2001 From: lazarv Date: Thu, 19 Dec 2024 11:25:14 +0100 Subject: [PATCH] fix: handling deploy cli argument in build action adapter handler --- docs/src/pages/en/(pages)/deploy/api.mdx | 21 ++++++++++++- packages/react-server-adapter-core/index.d.ts | 23 ++++++++++++-- packages/react-server-adapter-core/index.mjs | 30 +++++++++++-------- packages/react-server/lib/build/adapter.mjs | 4 ++- 4 files changed, 61 insertions(+), 17 deletions(-) diff --git a/docs/src/pages/en/(pages)/deploy/api.mdx b/docs/src/pages/en/(pages)/deploy/api.mdx index e1f2b5a..38db61e 100644 --- a/docs/src/pages/en/(pages)/deploy/api.mdx +++ b/docs/src/pages/en/(pages)/deploy/api.mdx @@ -55,7 +55,26 @@ You need to pass adapter properties to the `createAdapter` function to configure `handler`: The adapter handler function. -`deploy`: The deployment command and arguments. This is optional. When provided, the adapter will show what command the developer needs to run to deploy the application after it has been built. If the `--deploy` flag is provided during the build, the adapter will run this command. +`deploy`: The deployment command and arguments. This is optional. When provided, the adapter will show what command the developer needs to run to deploy the application after it has been built. If the `--deploy` flag is provided during the build, the adapter will run this command. The `deploy` property can also be a function that will be called with the adapter options, CLI options and the handler result. This is useful if you need to customize the deployment command based on the adapter options or the handler result. If you don't provide a result with `command` and `args`, the default deployment handling spawning the command will be skipped. This is useful if you want to implement a custom deployment workflow in the adapter. + +```js +export const adapter = createAdapter({ + // ... + handler: async ({ adapterOptions, files, copy, config, reactServerDir, reactServerOutDir, root, options }) => { + // Your adapter handler implementation + return { + // Your handler result, this will be passed to the deploy function + }; + }, + async deploy({ adapterOptions, options, handlerResult }) { + // customize the deployment command based on the adapter options, CLI options or handler result + return { + command: "vercel", + args: ["deploy", "--prebuilt"], + }; + }, +}); +``` ## Adapter handler diff --git a/packages/react-server-adapter-core/index.d.ts b/packages/react-server-adapter-core/index.d.ts index 503fa34..0dfb72d 100644 --- a/packages/react-server-adapter-core/index.d.ts +++ b/packages/react-server-adapter-core/index.d.ts @@ -3,7 +3,13 @@ declare module "@lazarv/react-server-adapter-core" { (adapterOptions: T, root: string, options: any): Promise; } - export function createAdapter(options: { + export type DeployCommandDescriptor = { + command: string; + args: string[]; + message?: string; + }; + + export function createAdapter(options: { name: string; outDir: string; outStaticDir?: string; @@ -32,8 +38,19 @@ declare module "@lazarv/react-server-adapter-core" { reactServerDir: string; reactServerOutDir: string; root: string; - options: any; - }) => Promise; + options: Record; + }) => Promise; + deploy: + | DeployCommandDescriptor + | ((context: { + adapterOptions: T; + options: Record; + handlerResult: R; + }) => + | DeployCommandDescriptor + | Promise + | void + | Promise); }): Adapter; export function banner(message: string): void; diff --git a/packages/react-server-adapter-core/index.mjs b/packages/react-server-adapter-core/index.mjs index 2972b75..622f17e 100644 --- a/packages/react-server-adapter-core/index.mjs +++ b/packages/react-server-adapter-core/index.mjs @@ -446,7 +446,7 @@ export function createAdapter({ await copy.server(); } - await handler({ + const handlerResult = await handler({ files, copy, config, @@ -458,17 +458,23 @@ export function createAdapter({ }); success(`${name} deployment successfully created.`); - if (deploy && deploy.command && deploy.args) { - if (options.deploy) { - banner(`deploying to ${name}`); - clearProgress(); - await spawnCommand(deploy.command, deploy.args); - } else { - console.log( - `${colors.gray(`Deploy to ${name} using:`)} ${deploy.command} ${deploy.args.join(" ")}` - ); - if (deploy.message) { - console.log(deploy.message); + if (deploy) { + const { command, args, message } = + typeof deploy === "function" + ? await deploy({ adapterOptions, options, handlerResult }) + : deploy; + if (command && args) { + if (options.deploy) { + banner(`deploying to ${name}`); + clearProgress(); + await spawnCommand(command, args); + } else { + console.log( + `${colors.gray(`Deploy to ${name} using:`)} ${command} ${args.join(" ")}` + ); + if (message) { + console.log(message); + } } } } diff --git a/packages/react-server/lib/build/adapter.mjs b/packages/react-server/lib/build/adapter.mjs index fe0e222..6982062 100644 --- a/packages/react-server/lib/build/adapter.mjs +++ b/packages/react-server/lib/build/adapter.mjs @@ -15,7 +15,9 @@ export default async function adapter(root, options) { const adapter = options?.adapter?.[0] === "false" ? null - : options.adapter || config.adapter; + : typeof options.adapter?.[0] === "string" && options.adapter?.[0] + ? options.adapter?.[0] + : config.adapter; if (adapter) { if (typeof adapter === "function") { return await adapter({}, root, options);