Skip to content

Commit d13a051

Browse files
committed
feat: update package.json to include @objectstack/service-cloud dependency and refactor serve command for project mode
1 parent 00cca64 commit d13a051

7 files changed

Lines changed: 41 additions & 67 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"dev": "pnpm --filter @objectstack/server dev",
99
"dev:cloud": "OBJECTSTACK_MODE=cloud pnpm --filter @objectstack/server dev",
1010
"start": "pnpm --filter @objectstack/server start",
11-
"dev:crm": "pnpm --filter @example/app-crm build && OBJECTSTACK_MODE=project OBJECTSTACK_PROJECT_ID=proj_crm pnpm --filter @example/app-crm dev",
11+
"dev:crm": "pnpm --filter @example/app-crm build && OBJECTSTACK_PROJECT_ID=proj_crm pnpm --filter @example/app-crm dev",
1212
"studio:start": "pnpm --filter @objectstack/studio start",
1313
"test": "turbo run test",
1414
"test:e2e": "turbo run test:e2e",

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"@objectstack/rest": "workspace:*",
5050
"@objectstack/runtime": "workspace:^",
5151
"@objectstack/service-ai": "workspace:*",
52+
"@objectstack/service-cloud": "workspace:*",
5253
"@objectstack/spec": "workspace:*",
5354
"@oclif/core": "^4.10.5",
5455
"bundle-require": "^5.1.0",

packages/cli/src/commands/serve.ts

Lines changed: 14 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -175,56 +175,21 @@ export default class Serve extends Command {
175175
throw new Error(`No default export found in ${args.config}`);
176176
}
177177

178-
// If the user's config is a bare defineStack() and OBJECTSTACK_MODE is
179-
// set (or config.bootMode is set), build the full project/cloud/
180-
// standalone stack via @objectstack/service-cloud. The package is
181-
// resolved by walking up node_modules from the user's cwd, so it
182-
// picks up the consumer's installation regardless of where the CLI
183-
// itself lives.
178+
// Project mode is the canonical OS dev workflow. Every bare
179+
// `defineStack()` is booted via `@objectstack/service-cloud`'s
180+
// `createBootStack()` (project / cloud / standalone are selected
181+
// by `OBJECTSTACK_MODE`, default `project`). Set
182+
// `OBJECTSTACK_MODE=off` to fall back to the legacy lightweight
183+
// assembler.
184184
if (shouldBootWithLibrary(config)) {
185-
try {
186-
const { pathToFileURL } = await import('node:url');
187-
let dir = process.cwd();
188-
let cloudPkgDir: string | null = null;
189-
// Walk upward from cwd looking for node_modules/@objectstack/service-cloud
190-
while (true) {
191-
const candidate = path.join(dir, 'node_modules', '@objectstack', 'service-cloud');
192-
if (fs.existsSync(path.join(candidate, 'package.json'))) {
193-
cloudPkgDir = candidate;
194-
break;
195-
}
196-
const parent = path.dirname(dir);
197-
if (parent === dir) break;
198-
dir = parent;
199-
}
200-
if (!cloudPkgDir) {
201-
throw new Error('@objectstack/service-cloud not found in any node_modules from cwd upward');
202-
}
203-
const pkg = JSON.parse(
204-
fs.readFileSync(path.join(cloudPkgDir, 'package.json'), 'utf8'),
205-
);
206-
const entry =
207-
pkg.exports?.['.']?.import ??
208-
pkg.exports?.['.']?.default ??
209-
pkg.module ??
210-
pkg.main ??
211-
'dist/index.js';
212-
const cloudEntry = path.join(cloudPkgDir, entry);
213-
const cloudMod: any = await import(pathToFileURL(cloudEntry).href);
214-
const bootResult = await cloudMod.createBootStack({
215-
mode: config.bootMode,
216-
project: config.project,
217-
cloud: config.cloud,
218-
standalone: config.standalone,
219-
});
220-
config = bootResult as any;
221-
} catch (err) {
222-
console.error(
223-
'OBJECTSTACK_MODE is set but @objectstack/service-cloud cannot be loaded.',
224-
'Install it with: pnpm add @objectstack/service-cloud',
225-
);
226-
throw err;
227-
}
185+
const { createBootStack } = await import('@objectstack/service-cloud');
186+
const bootResult = await createBootStack({
187+
mode: config.bootMode,
188+
project: config.project,
189+
cloud: config.cloud,
190+
standalone: config.standalone,
191+
});
192+
config = bootResult as any;
228193
}
229194

230195
// ── Resolve plugin tiers ──────────────────────────────────────
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Stub ambient declaration for the @objectstack/service-cloud package.
2+
// The package's tsup build cannot emit .d.ts yet (pre-existing typecheck
3+
// errors in upstream dependencies). The CLI only consumes the runtime
4+
// `createBootStack()` factory, so a loose `any` type suffices.
5+
declare module '@objectstack/service-cloud' {
6+
export function createBootStack(config?: any): Promise<any>;
7+
}

packages/cli/src/utils/plugin-detection.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,15 @@ export function isHostConfig(config: any): boolean {
2020
* `createBootStack()` (full project / cloud / standalone stack) rather
2121
* than the CLI's lightweight in-memory plugin assembler.
2222
*
23-
* Triggers when:
24-
* 1. The config is NOT already a host config (no instantiated
25-
* plugins) — a host config takes precedence.
26-
* 2. `OBJECTSTACK_MODE` env var is set to a recognised value, OR the
27-
* config carries an explicit `bootMode` field.
23+
* **Default behaviour: enabled.** Project mode is the canonical OS dev
24+
* workflow — every bare `defineStack()` config gets the full stack
25+
* (ObjectQL + Auth + Studio + control plane) unless one of the
26+
* opt-out conditions below applies.
27+
*
28+
* Skips library boot when:
29+
* 1. The config is a host config (already has instantiated plugins).
30+
* 2. `OBJECTSTACK_MODE=off` is explicitly set (escape hatch for the
31+
* legacy lightweight assembler).
2832
*
2933
* Recognised mode aliases match `resolveMode()` in
3034
* `@objectstack/service-cloud/boot-env`.
@@ -41,9 +45,10 @@ const RECOGNISED_MODES = new Set([
4145
export function shouldBootWithLibrary(config: any): boolean {
4246
if (isHostConfig(config)) return false;
4347
const mode = process.env.OBJECTSTACK_MODE?.trim().toLowerCase();
44-
if (mode && RECOGNISED_MODES.has(mode)) return true;
45-
if (config?.bootMode && ['project', 'cloud', 'standalone'].includes(config.bootMode)) {
46-
return true;
48+
if (mode === 'off' || mode === 'none' || mode === 'legacy') return false;
49+
if (mode && !RECOGNISED_MODES.has(mode)) {
50+
console.warn(`[objectstack] Unknown OBJECTSTACK_MODE=${mode}; falling back to project mode.`);
4751
}
48-
return false;
52+
if (config?.bootMode === 'off') return false;
53+
return true;
4954
}

packages/plugins/plugin-auth/package.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,7 @@
1515
},
1616
"scripts": {
1717
"build": "tsup --config ../../../tsup.config.ts",
18-
"test": "vitest run",
19-
"validate": "objectstack validate",
20-
"compile": "objectstack compile",
21-
"info": "objectstack info"
18+
"test": "vitest run"
2219
},
2320
"dependencies": {
2421
"@better-auth/oauth-provider": "^1.6.9",
@@ -28,7 +25,6 @@
2825
"better-auth": "^1.6.9"
2926
},
3027
"devDependencies": {
31-
"@objectstack/cli": "workspace:*",
3228
"@types/node": "^25.6.0",
3329
"typescript": "^6.0.3",
3430
"vitest": "^4.1.4"

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)