Skip to content

Commit 1f62662

Browse files
committed
Enhance development mode support by adding devPlugins loading and updating CLI commands for improved configuration handling
1 parent b332ad4 commit 1f62662

3 files changed

Lines changed: 84 additions & 3 deletions

File tree

PROTOCOL-QUICK-REFERENCE.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,43 @@
1111

1212
---
1313

14+
## 🏗️ Project & Plugin Definition
15+
16+
Use `objectstack.config.ts` to define your stack.
17+
18+
```typescript
19+
import { defineStack } from '@objectstack/spec';
20+
21+
export default defineStack({
22+
manifest: {
23+
id: 'com.example.app',
24+
version: '1.0.0',
25+
type: 'app',
26+
},
27+
28+
// 1. Objects & Logic
29+
objects: [ ... ],
30+
flows: [ ... ],
31+
32+
// 2. Production Dependencies
33+
plugins: [
34+
'@objectstack/driver-postgres',
35+
],
36+
37+
// 3. Development Dependencies (like package.json devDependencies)
38+
// These are ONLY loaded when running `objectstack dev`
39+
devPlugins: [
40+
'@objectstack/plugin-bi', // Debug integration with BI
41+
{
42+
manifest: { id: 'dev-db' },
43+
datasources: [{ type: 'sqlite', url: 'file:dev.db' }]
44+
}
45+
]
46+
});
47+
```
48+
49+
---
50+
1451
## 🔌 Client SDK
1552

1653
Access ObjectStack from your applications using the official client libraries:

packages/cli/src/commands/dev.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Command } from 'commander';
22
import chalk from 'chalk';
3-
import { execSync } from 'child_process';
3+
import { execSync, spawn } from 'child_process';
44
import os from 'os';
55
import fs from 'fs';
66
import path from 'path';
@@ -14,6 +14,28 @@ export const devCommand = new Command('dev')
1414
console.log(chalk.bold(`\n🚀 ObjectStack Development Mode`));
1515
console.log(chalk.dim(`-------------------------------`));
1616

17+
// Check if we are running inside a package (Single Package Mode)
18+
// If "package" argument is 'all' (default) AND objectstack.config.ts exists in CWD
19+
const configPath = path.resolve(process.cwd(), 'objectstack.config.ts');
20+
if (packageName === 'all' && fs.existsSync(configPath)) {
21+
console.log(chalk.blue(`📂 Detected package config: ${configPath}`));
22+
console.log(chalk.green(`⚡ Starting Dev Server...`));
23+
console.log('');
24+
25+
// Delegate to 'serve --dev'
26+
// We spawn a new process to ensure clean environment and watch capabilities (plugin-loader etc)
27+
// usage: objectstack serve --dev
28+
const binPath = process.argv[1]; // path to objectstack bin
29+
30+
const child = spawn(process.execPath, [binPath, 'serve', '--dev', ...(options.verbose ? ['--verbose'] : [])], {
31+
stdio: 'inherit',
32+
env: { ...process.env, NODE_ENV: 'development' }
33+
});
34+
35+
return;
36+
}
37+
38+
// Monorepo Orchestration Mode
1739
try {
1840
const cwd = process.cwd();
1941
const filter = packageName === 'all' ? '' : `--filter @objectstack/${packageName}`;

packages/cli/src/commands/serve.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export const serveCommand = new Command('serve')
3434
.description('Start ObjectStack server with plugins from configuration')
3535
.argument('[config]', 'Configuration file path', 'objectstack.config.ts')
3636
.option('-p, --port <port>', 'Server port', '3000')
37+
.option('--dev', 'Run in development mode (load devPlugins)')
3738
.option('--no-server', 'Skip starting HTTP server plugin')
3839
.action(async (configPath, options) => {
3940
let port = parseInt(options.port);
@@ -90,14 +91,35 @@ export const serveCommand = new Command('serve')
9091
});
9192

9293
// Load plugins from configuration
93-
const plugins = config.plugins || [];
94+
let plugins = config.plugins || [];
95+
96+
// Merge devPlugins if in dev mode
97+
if (options.dev && config.devPlugins) {
98+
console.log(chalk.blue(`📦 Loading development plugins...`));
99+
plugins = [...plugins, ...config.devPlugins];
100+
}
94101

95102
if (plugins.length > 0) {
96103
console.log(chalk.yellow(`📦 Loading ${plugins.length} plugin(s)...`));
97104

98105
for (const plugin of plugins) {
99106
try {
100-
kernel.use(plugin);
107+
let pluginToLoad = plugin;
108+
109+
// Resolve string references (package names)
110+
if (typeof plugin === 'string') {
111+
console.log(chalk.dim(` Trying to resolve plugin: ${plugin}`));
112+
try {
113+
// Try dynamic import for packages
114+
const imported = await import(plugin);
115+
pluginToLoad = imported.default || imported;
116+
} catch (importError: any) {
117+
// Fallback: try bundleRequire for local paths if needed, otherwise throw
118+
throw new Error(`Failed to import plugin '${plugin}': ${importError.message}`);
119+
}
120+
}
121+
122+
kernel.use(pluginToLoad);
101123
const pluginName = plugin.name || plugin.constructor?.name || 'unnamed';
102124
console.log(chalk.green(` ✓ Registered plugin: ${pluginName}`));
103125
} catch (e: any) {

0 commit comments

Comments
 (0)