Skip to content

Commit 8094da8

Browse files
committed
feat: add Build and Start commands for artifact compilation and serving
1 parent 7b175fb commit 8094da8

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

packages/cli/src/commands/build.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import Compile from './compile.js';
4+
5+
export default class Build extends Compile {
6+
static override description = 'Compile ObjectStack configuration to JSON artifact (alias for compile)';
7+
}

packages/cli/src/commands/start.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { Command, Flags } from '@oclif/core';
4+
import { spawn } from 'child_process';
5+
import fs from 'fs';
6+
import path from 'path';
7+
import { printHeader, printKV, printStep, printError } from '../utils/format.js';
8+
9+
export default class Start extends Command {
10+
static override description = 'Serve the pre-compiled artifact in production mode (requires objectstack build first)';
11+
12+
static override flags = {
13+
ui: Flags.boolean({ description: 'Enable Studio UI at /_studio/' }),
14+
verbose: Flags.boolean({ char: 'v', description: 'Verbose output' }),
15+
port: Flags.integer({ char: 'p', description: 'Port to listen on' }),
16+
};
17+
18+
async run(): Promise<void> {
19+
const { flags } = await this.parse(Start);
20+
21+
printHeader('Production Mode');
22+
23+
const artifactPath = process.env.OBJECTSTACK_ARTIFACT_PATH
24+
?? path.resolve(process.cwd(), 'dist/objectstack.json');
25+
26+
if (!fs.existsSync(artifactPath)) {
27+
printError(`Artifact not found: ${path.relative(process.cwd(), artifactPath)}`);
28+
console.error(' Run \x1b[33mobjectstack build\x1b[0m to compile your configuration first.');
29+
process.exit(1);
30+
}
31+
32+
printKV('Artifact', path.relative(process.cwd(), artifactPath), '📦');
33+
printStep('Starting server (production mode)...');
34+
35+
const localEnv: NodeJS.ProcessEnv = {
36+
...process.env,
37+
NODE_ENV: 'production',
38+
OBJECTSTACK_PROJECT_ID: process.env.OBJECTSTACK_PROJECT_ID ?? 'proj_local',
39+
OBJECTSTACK_ARTIFACT_PATH: process.env.OBJECTSTACK_ARTIFACT_PATH ?? artifactPath,
40+
...(flags.port ? { PORT: String(flags.port) } : {}),
41+
};
42+
43+
if (!process.env.OBJECTSTACK_CLOUD_URL) {
44+
delete localEnv.OBJECTSTACK_CLOUD_URL;
45+
}
46+
47+
printKV('Project ID', localEnv.OBJECTSTACK_PROJECT_ID!, '🎯');
48+
49+
const binPath = process.argv[1];
50+
spawn(
51+
process.execPath,
52+
[
53+
binPath,
54+
'serve',
55+
'--prebuilt',
56+
...(flags.ui ? ['--ui'] : []),
57+
...(flags.verbose ? ['--verbose'] : []),
58+
],
59+
{ stdio: 'inherit', env: localEnv },
60+
);
61+
}
62+
}

packages/cli/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ export { default as InfoCommand } from './commands/info.js';
1010
export { default as InitCommand } from './commands/init.js';
1111
export { default as GenerateCommand } from './commands/generate.js';
1212
export { default as CreateCommand } from './commands/create.js';
13+
export { default as BuildCommand } from './commands/build.js';
1314
export { default as DevCommand } from './commands/dev.js';
1415
export { default as ServeCommand } from './commands/serve.js';
16+
export { default as StartCommand } from './commands/start.js';
1517
export { default as TestCommand } from './commands/test.js';
1618
export { default as DoctorCommand } from './commands/doctor.js';
1719

0 commit comments

Comments
 (0)