Add sdk build (#17335)

## Summary

Adds `app:build` command as a one-shot version of `app:dev` - builds
manifest, functions, and front components once then exits (no watching).

**Changes:**
- Added `watch` option to `FunctionsWatcher` and
`FrontComponentsWatcher` to support both watch and one-shot modes
- Created `AppBuildCommand` reusing the same build logic as `app:dev`
with `watch: false`
- Added integration tests for `app:build` on both `rich-app` and
`root-app`
- Updated manifest types: `handlerPath` → `sourceHandlerPath` +
`builtHandlerPath`, `componentPath` → `sourceComponentPath` +
`builtComponentPath`
- Updated test app `package.json` scripts to match `create-twenty-app`
template
This commit is contained in:
Charles Bochet
2026-01-22 14:36:40 +01:00
committed by GitHub
parent d6f088f720
commit d537d941a7
25 changed files with 1050 additions and 86 deletions
@@ -0,0 +1,17 @@
import { runCliCommand, type RunCliCommandResult } from './run-cli-command.util';
export type RunAppBuildOptions = {
appPath: string;
timeout?: number;
};
export const runAppBuild = (options: RunAppBuildOptions): Promise<RunCliCommandResult> => {
const { appPath, timeout = 30000 } = options;
// app:build runs once and exits, so we don't wait for specific output
return runCliCommand({
command: 'app:build',
args: [appPath],
timeout,
});
};
@@ -54,15 +54,21 @@ export const runCliCommand = (
? [waitForOutput]
: [];
let isResolved = false;
child.stdout?.on('data', (data: Buffer) => {
output += data.toString();
if (
!isResolved &&
waitForOutputs.length > 0 &&
waitForOutputs.every((w) => output.includes(w))
) {
isResolved = true;
clearTimeout(timeoutId);
child.kill();
resolve({ success: true, output });
// Wait a bit before killing to allow any in-progress file writes to complete
setTimeout(() => {
child.kill();
resolve({ success: true, output });
}, 500);
}
});