Skip to content
Open
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
12 changes: 12 additions & 0 deletions .changeset/next-base-path.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"@workflow/builders": patch
"@workflow/astro": patch
"@workflow/core": patch
"@workflow/next": patch
"@workflow/sveltekit": patch
"@workflow/utils": patch
"@workflow/world-local": patch
"@workflow/world-postgres": patch
---

Respect framework base paths when routing workflow traffic and expose health checks on generated Next.js workflow routes.
7 changes: 2 additions & 5 deletions packages/astro/src/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,16 +176,13 @@ export const prerender = false;`,
// Normalize request, needed for preserving request through astro
workflowsRouteContent = replaceGeneratedRouteExport(
workflowsRouteContent,
/const handler = workflowEntrypoint\(workflowCode(?<options>[^)]*)\);\s*export const HEAD = handler;\s*export const POST = handler;?\s*$/m,
/export const POST = workflowEntrypoint\(workflowCode(?<options>[^)]*)\);?$/m,
(_match, options = '') => `${NORMALIZE_REQUEST_CODE}
const handleWorkflowRequest = async ({request}) => {
export const POST = async ({request}) => {
const normalRequest = await normalizeRequest(request);
return workflowEntrypoint(workflowCode${options})(normalRequest);
};

export const HEAD = handleWorkflowRequest;
export const POST = handleWorkflowRequest;

export const prerender = false;`,
'Failed to wrap generated Astro workflow route'
);
Expand Down
17 changes: 10 additions & 7 deletions packages/builders/src/base-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ import {
applySwcTransform,
type WorkflowManifest,
} from './apply-swc-transform.js';
import { createWorkflowEntrypointOptionsCode } from './constants.js';
import {
createWorkflowEntrypointOptionsCode,
createWorkflowRouteHandlersCode,
} from './constants.js';
import { getEsbuildTsconfigOptions } from './esbuild-tsconfig.js';
import {
fastDiscoverEntries,
Expand Down Expand Up @@ -1342,8 +1345,11 @@ export const __steps_registered = true;
}
}

const workflowEntrypointOptionsCode =
createWorkflowEntrypointOptionsCode();
const workflowEntrypointOptionsCode = createWorkflowEntrypointOptionsCode(
{
basePath: this.config.basePath,
}
);

const bundleFinal = async (interimBundle: string) => {
const workflowBundleCode = interimBundle;
Expand All @@ -1354,10 +1360,7 @@ import { workflowEntrypoint } from 'workflow/runtime';

const workflowCode = \`${workflowBundleCode.replace(/[\\`$]/g, '\\$&')}\`;

const handler = workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode});

export const HEAD = handler;
export const POST = handler;`;
${createWorkflowRouteHandlersCode(`workflowEntrypoint(workflowCode${workflowEntrypointOptionsCode})`)}`;

// we skip the final bundling step for Next.js so it can bundle itself
if (!bundleFinalOutput) {
Expand Down
9 changes: 9 additions & 0 deletions packages/builders/src/constants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,13 @@ describe('createWorkflowEntrypointOptionsCode', () => {
', { namespace: "custom" }'
);
});

it('inlines basePath alongside namespace options', () => {
expect(
createWorkflowEntrypointOptionsCode({
namespace: 'custom',
basePath: '/v2',
})
).toBe(', { namespace: "custom", basePath: "/v2" }');
});
});
26 changes: 22 additions & 4 deletions packages/builders/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,35 @@ export function createWorkflowQueueTrigger(options?: { namespace?: string }) {
*/
export function createWorkflowEntrypointOptionsCode(options?: {
namespace?: string;
basePath?: string;
}) {
const namespace = resolveQueueNamespace(options?.namespace);
const fields: string[] = [];

if (!namespace) {
if (namespace) {
// Reuse prefix construction for namespace validation.
getQueueTopicPrefix('workflow', namespace);
fields.push(`namespace: ${JSON.stringify(namespace)}`);
}

if (options?.basePath !== undefined) {
fields.push(`basePath: ${JSON.stringify(options.basePath)}`);
}

if (fields.length === 0) {
return '';
}

// Reuse prefix construction for namespace validation.
getQueueTopicPrefix('workflow', namespace);
return `, { ${fields.join(', ')} }`;
}

return `, { namespace: ${JSON.stringify(namespace)} }`;
export function createWorkflowRouteHandlersCode(
workflowEntrypointCall: string
) {
return `export const POST = ${workflowEntrypointCall};
export const GET = POST;
export const HEAD = POST;
export const OPTIONS = POST;`;
}

/**
Expand Down
3 changes: 3 additions & 0 deletions packages/builders/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ interface BaseWorkflowConfig {
// Optional prefix for debug files (e.g., "_" for Astro to ignore them)
debugFilePrefix?: string;

// Optional route prefix for apps deployed below the origin root.
basePath?: string;

// Suppress informational logs emitted by createWorkflowsBundle()
// (e.g. intermediate/final workflow bundle timing logs).
suppressCreateWorkflowsBundleLogs?: boolean;
Expand Down
Loading
Loading