Skip to content

Commit c5efe15

Browse files
committed
chore: remove service-cloud coupling from open-core CLI
1 parent 9e5dba3 commit c5efe15

7 files changed

Lines changed: 50 additions & 91 deletions

File tree

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
---
2+
'@objectstack/cli': patch
3+
'@objectstack/runtime': patch
4+
---
5+
6+
Remove residual coupling to the (already-extracted) `@objectstack/service-cloud` package.
7+
8+
The cloud distribution was migrated to a separate repo a while back, but the open-core CLI still carried:
9+
10+
- A dynamic `import('@objectstack/service-cloud')` in the boot-mode dispatch for `cloud` / `runtime` modes.
11+
- A dev-mode auto-mount that tried to load `createSingleEnvironmentPlugin` from the cloud package (now fully covered by the built-in `RuntimeConfigPlugin`).
12+
- An ambient `.d.ts` stub for `@objectstack/service-cloud`.
13+
- A leftover empty `packages/services/service-cloud/` directory (only stale `dist/` + `node_modules/`).
14+
- Several doc-comment references.
15+
16+
All gone. The open-core CLI now supports `bootMode: 'standalone'` only — non-standalone modes throw a clear error pointing users to the cloud distribution. No runtime behavior change for standalone users.

packages/cli/src/commands/serve.ts

Lines changed: 23 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ export default class Serve extends Command {
179179
*
180180
* Opt out: `objectstack serve --preset minimal`.
181181
*
182-
* Mirrored on hosted objectos per-project kernels by
183-
* `mountDefaultProjectPlugins()` in `@objectstack/service-cloud`.
182+
* Cloud / multi-environment hosts (which live in a separate distribution)
183+
* mirror this list on their per-project kernels.
184184
*/
185185
static readonly ALWAYS_ON_CAPABILITIES: readonly string[] = Object.freeze([
186186
'queue', 'job', 'cache', 'settings', 'email', 'storage',
@@ -359,9 +359,10 @@ export default class Serve extends Command {
359359
config = merged;
360360
}
361361

362-
// Boot-mode dispatch: standalone goes directly through
363-
// `@objectstack/runtime` (no cloud dependencies). runtime/cloud
364-
// modes go through `@objectstack/service-cloud`.
362+
// Boot-mode dispatch: this open-core CLI only supports `standalone`
363+
// (and the artifact-fallback shortcut). Cloud / multi-environment
364+
// boot modes live in a separate distribution and are no longer
365+
// resolved from this package.
365366
if (useArtifactFallback || shouldBootWithLibrary(config)) {
366367
// The boot stack returns only `{plugins, api}` — preserve the
367368
// original stack metadata (notably `requires`, `analyticsCubes`,
@@ -370,9 +371,6 @@ export default class Serve extends Command {
370371
const resolvedMode = config.bootMode ?? process.env.OS_MODE ?? 'standalone';
371372
if (useArtifactFallback) {
372373
// Artifact-only boot — no objectstack.config.ts authored.
373-
// Always use the default-host helper which is standalone-only
374-
// and never depends on @objectstack/service-cloud.
375-
//
376374
// When `useEmptyBoot` is set the user asked for a quick-start
377375
// ("objectstack start" with nothing to load); skip the
378376
// "missing artifact" error and assemble a bare kernel that
@@ -385,26 +383,12 @@ export default class Serve extends Command {
385383
const bootResult = await createStandaloneStack(config.standalone);
386384
config = { ...originalConfig, ...bootResult } as any;
387385
} else {
388-
// Cloud / multi-environment boot modes require @objectstack/service-cloud.
389-
// When the package is unavailable (e.g. someone vendored only the
390-
// public framework), fail with a clear, actionable error instead of
391-
// an opaque module-not-found stack trace.
392-
let createBootStack: any;
393-
try {
394-
({ createBootStack } = await import('@objectstack/service-cloud'));
395-
} catch (err) {
396-
throw new Error(
397-
`Boot mode '${resolvedMode}' requires @objectstack/service-cloud, which is not installed.\n`
398-
+ `Either install it (\`pnpm add @objectstack/service-cloud\`) or switch to bootMode='standalone'.\n`
399-
+ `Underlying error: ${(err as Error)?.message ?? String(err)}`,
400-
);
401-
}
402-
const bootResult = await createBootStack({
403-
mode: config.bootMode,
404-
runtime: config.runtime ?? config.project,
405-
cloud: config.cloud,
406-
});
407-
config = { ...originalConfig, ...bootResult } as any;
386+
throw new Error(
387+
`Boot mode '${resolvedMode}' is not available in the open-core CLI.\n`
388+
+ `Only 'standalone' is supported here. Cloud / multi-environment hosts ship\n`
389+
+ `from a separate distribution. Either switch to bootMode='standalone' or use\n`
390+
+ `the cloud-aware CLI.`,
391+
);
408392
}
409393
}
410394

@@ -889,41 +873,15 @@ export default class Serve extends Command {
889873
}
890874
}
891875

892-
// 5. Auto-register Studio single-environment signal in dev mode.
893-
//
894-
// `objectstack dev` runs a vanilla user stack (e.g. the HotCRM
895-
// reference app at https://github.com/objectstack-ai/hotcrm)
896-
// as a single project — there is no apps/cloud control plane and no
897-
// org/project picker is meaningful. Without this plugin Studio would
898-
// fall back to its multi-environment default and ask the user to "Create
899-
// organization" before showing any platform metadata.
876+
// 5. Studio single-environment signal.
900877
//
901-
// The plugin only registers `GET /api/v1/studio/runtime-config`
902-
// (returning `{ singleEnvironment: true, defaultOrgId, defaultProjectId }`)
903-
// — no identity seed, since CLI dev mode has no sys_organization /
904-
// sys_environment tables to write into. Skipped when the user config
905-
// already carries a single-environment / multi-environment plugin.
906-
const hasProjectModePlugin = plugins.some((p: any) => {
907-
const n = p?.name ?? p?.constructor?.name ?? '';
908-
return n === 'com.objectstack.studio.single-environment'
909-
|| n === 'com.objectstack.multi-environment'
910-
|| n === 'com.objectstack.studio.runtime-config';
911-
});
912-
if (isDev && !hasProjectModePlugin) {
913-
try {
914-
const cloudPkg = '@objectstack/service-cloud';
915-
const { createSingleEnvironmentPlugin } = await import(/* webpackIgnore: true */ cloudPkg);
916-
await kernel.use(createSingleEnvironmentPlugin({
917-
environmentId: process.env.OS_ENVIRONMENT_ID ?? 'proj_local',
918-
orgId: process.env.OS_ORG_ID ?? 'org_local',
919-
orgName: 'Local',
920-
}));
921-
trackPlugin('SingleEnvironment');
922-
} catch {
923-
// @objectstack/service-cloud not installed — Studio falls back
924-
// to multi-environment mode (org/project picker visible).
925-
}
926-
}
878+
// The built-in `RuntimeConfigPlugin` (auto-registered below at
879+
// step 5b-ii) already responds to `GET /api/v1/studio/runtime-config`
880+
// with `{ singleEnvironment, defaultOrgId, defaultEnvironmentId }`,
881+
// so no extra plugin is needed here. Cloud / multi-environment
882+
// hosts ship their own runtime-config plugin in a separate
883+
// distribution; if the user config carries one already we skip
884+
// injecting the default one further down.
927885

928886
// 5b. Auto-register MarketplaceProxyPlugin so the runtime console's
929887
// marketplace browse UI works in `objectstack dev` without manually
@@ -1037,7 +995,7 @@ export default class Serve extends Command {
1037995
if (isHostKernel) {
1038996
console.warn(chalk.yellow(
1039997
' ⚠ AuthPlugin skipped on host kernel — runtime mode (ObjectOSEnvironmentPlugin detected).\n' +
1040-
' Auth is owned per-project by ArtifactKernelFactory (see service-cloud).'
998+
' Auth is owned per-project by ArtifactKernelFactory in the cloud distribution.'
1041999
));
10421000
} else if (!secret) {
10431001
console.warn(chalk.yellow(' ⚠ AuthPlugin skipped — set AUTH_SECRET to enable authentication in production'));
@@ -1072,8 +1030,8 @@ export default class Serve extends Command {
10721030
if (!trustedOrigins.includes(baseOrigin)) trustedOrigins.push(baseOrigin);
10731031
} catch { /* ignore malformed baseUrl */ }
10741032
// Preview-mode subdomain wildcards (`<commit>--<pid>.<base>`).
1075-
// Honour `OS_PREVIEW_BASE_DOMAINS` (used by service-cloud's
1076-
// preview routing) and add `http://*.<base>:*` patterns.
1033+
// Honour `OS_PREVIEW_BASE_DOMAINS` (used by the cloud preview routing)
1034+
// and add `http://*.<base>:*` patterns.
10771035
const previewMode = (process.env.OS_PREVIEW_MODE ?? '').trim().toLowerCase();
10781036
const isPreviewMode = previewMode === '1' || previewMode === 'true' || previewMode === 'yes';
10791037
if (isPreviewMode) {

packages/cli/src/types/service-cloud.d.ts

Lines changed: 0 additions & 13 deletions
This file was deleted.

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ export function isHostConfig(config: any): boolean {
3030
* 2. `OS_MODE=off` is explicitly set (escape hatch for the
3131
* legacy lightweight assembler).
3232
*
33-
* Recognised mode aliases match `resolveMode()` in
34-
* `@objectstack/service-cloud/boot-env`.
33+
* Recognised mode aliases match the cloud distribution's
34+
* `resolveMode()` (kept in sync for back-compat).
3535
*/
3636
const RECOGNISED_MODES = new Set([
3737
'runtime',

packages/runtime/src/cloud/environment-registry.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
* - a local file artifact (see {@link FileArtifactApiClient} +
1111
* {@link ArtifactEnvironmentRegistry})
1212
*
13-
* The contract was extracted from `@objectstack/service-cloud` in Phase R
14-
* so the runtime can express "fetch artifact + boot per-project kernel"
15-
* without taking a dependency on the cloud control plane.
13+
* The contract lives in `@objectstack/runtime` so the runtime can
14+
* express "fetch artifact + boot per-project kernel" without taking a
15+
* dependency on the cloud control plane.
1616
*/
1717

1818
import type * as Contracts from '@objectstack/spec/contracts';

packages/runtime/src/cloud/marketplace-proxy-plugin.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
*
66
* Forwards `GET /api/v1/marketplace/*` from a tenant ObjectOS runtime to
77
* the configured ObjectStack Cloud control-plane URL. The cloud endpoint
8-
* (`packages/service-cloud/src/routes/marketplace.ts`) is unauthenticated
9-
* and only exposes packages whose owner has opted in to the public catalog
10-
* (`sys_package.marketplace_listed = true`) — so the proxy passes through
11-
* without any credentials.
8+
* is unauthenticated and only exposes packages whose owner has opted in
9+
* to the public catalog (`sys_package.marketplace_listed = true`) — so the
10+
* proxy passes through without any credentials.
1211
*
1312
* Why proxy instead of direct browser → cloud:
1413
* - The Console SPA stays on the tenant origin, so no CORS configuration

packages/runtime/src/default-host.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
* flows and a `requires: [...]` capability list. That should be enough
1111
* to boot a runtime, with zero hand-written host code.
1212
*
13-
* Boot mode: **standalone only**. This module intentionally does NOT
14-
* depend on `@objectstack/service-cloud`. Cloud / multi-environment hosts
15-
* still write their own `objectstack.config.ts` (see
16-
* `apps/objectos/objectstack.config.ts`).
13+
* Boot mode: **standalone only**. This module deliberately has zero
14+
* dependency on the cloud distribution — cloud / multi-environment hosts
15+
* ship their own bootstrap and write their own `objectstack.config.ts`.
1716
*
1817
* Resolution order for the artifact path:
1918
* 1. `options.artifactPath` (explicit caller override)

0 commit comments

Comments
 (0)