Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .changeset/next-root-detection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@workflow/next": patch
---

Derive the workflow builder project root from Next.js workspace root configuration.
25 changes: 25 additions & 0 deletions packages/next/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,31 @@ describe('withWorkflow builder config', () => {
});
});

it('derives projectRoot from the nearest pnpm workspace root', async () => {
const repoRoot = mkdtempSync(join(realTmpDir, 'workflow-next-root-'));
const appRoot = join(repoRoot, 'apps/web');
mkdirSync(appRoot, { recursive: true });
writeFile(join(repoRoot, 'pnpm-workspace.yaml'), 'packages: []\n');
process.chdir(appRoot);

try {
const config = withWorkflow({});

await config('phase-production-build', {
defaultConfig: {},
});

expect(builderConfigs[0]).toMatchObject({
projectRoot: repoRoot,
moduleSpecifierRoot: appRoot,
workingDir: appRoot,
});
} finally {
process.chdir(originalCwd);
rmSync(repoRoot, { recursive: true, force: true });
}
});

it.each([
'phase-production-build',
'phase-development-server',
Expand Down
38 changes: 32 additions & 6 deletions packages/next/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { copyFileSync, mkdirSync, statSync } from 'node:fs';
import { copyFile, mkdir, readFile } from 'node:fs/promises';
import { dirname, isAbsolute, join } from 'node:path';
import { dirname, isAbsolute, join, resolve } from 'node:path';
import type { NextConfig } from 'next';
import semver from 'semver';
import { getNextBuilder } from './builder.js';
Expand All @@ -16,7 +16,6 @@ const VERCEL_WORLD_SERVER_EXTERNAL_PACKAGES = [
VERCEL_WORLD_PACKAGE,
...VERCEL_WORLD_DEPENDENCY_PACKAGES,
];

const useWorkflowPattern = /^\s*(['"])use workflow\1;?\s*$/m;
const useStepPattern = /^\s*(['"])use step\1;?\s*$/m;
const workflowSerdeImportPattern = /from\s+(['"])@workflow\/serde\1/;
Expand Down Expand Up @@ -232,6 +231,31 @@ function fileExists(path: string): boolean {
}
}

function resolveNextProjectRoot(
nextConfig: NextConfig,
workingDir: string
): string {
if (nextConfig.outputFileTracingRoot) {
return isAbsolute(nextConfig.outputFileTracingRoot)
? nextConfig.outputFileTracingRoot
: resolve(workingDir, nextConfig.outputFileTracingRoot);
}

let current = resolve(workingDir);

while (true) {
if (fileExists(join(current, 'pnpm-workspace.yaml'))) {
return current;
}

const parent = dirname(current);
if (parent === current) {
return workingDir;
}
current = parent;
}
}

function getWorkflowManifestCopyPaths({
projectDir,
distDir,
Expand Down Expand Up @@ -442,7 +466,9 @@ export function withWorkflow(
nextConfig.turbopack.rules = {};
}
const existingRules = nextConfig.turbopack.rules as any;
const nextVersion = resolveNextVersion(process.cwd());
const workingDir = process.cwd();
const nextVersion = resolveNextVersion(workingDir);
const projectRoot = resolveNextProjectRoot(nextConfig, workingDir);
const supportsTurboCondition = semver.gte(nextVersion, 'v16.0.0');

const shouldWatch = process.env.NODE_ENV === 'development';
Expand Down Expand Up @@ -474,9 +500,9 @@ export function withWorkflow(
'jsx',
'js',
],
projectRoot: nextConfig.outputFileTracingRoot,
moduleSpecifierRoot: process.cwd(),
workingDir: process.cwd(),
projectRoot,
moduleSpecifierRoot: workingDir,
workingDir,
distDir,
diagnosticsDir: `${distDir}/diagnostics`,
buildTarget: 'next',
Expand Down
Loading