Skip to content

Commit c102de2

Browse files
os-zhuangclaude
andauthored
feat(cli): auto-wire marketplace from @objectstack/cloud-connection when a cloud URL resolves (#2009)
ADR-0006 Phase 4 removed the framework CLI's duplicate marketplace plugins (they lived in @objectstack/runtime, duplicating the cloud distribution's copies). ADR-0008 then open-sourced the canonical client into the Apache-2.0 @objectstack/cloud-connection package, so the CLI can wire it again without crossing the open-core boundary — there is no longer a cloud-only copy to duplicate. objectstack serve/dev/start now mount MarketplaceProxyPlugin + MarketplaceInstallLocalPlugin + the same-origin cloud-connection surface + RuntimeConfigPlugin (single-env, installLocal: true) whenever resolveCloudUrl() is truthy. OS_CLOUD_URL=off (or unset) mounts nothing, preserving the vanilla marketplace-less objectstack dev. Skipped in runtime/host-kernel mode (the cloud objectos-stack wires its own proxy on the host kernel — detected via ObjectOSEnvironmentPlugin, mirroring the existing AuthPlugin guard). Fixes objectstack start empty-boot, which advertised "boot an empty kernel against your marketplace" but — having no config or artifact to carry the wiring — actually mounted no marketplace at all. The plugins self-register their Setup nav bundles, so Browse Marketplace + Installed Apps reappear automatically. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c854f92 commit c102de2

4 files changed

Lines changed: 72 additions & 11 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"@objectstack/cli": minor
3+
---
4+
5+
feat(cli): auto-wire marketplace from `@objectstack/cloud-connection` when a cloud URL resolves
6+
7+
ADR-0006 Phase 4 removed the framework CLI's duplicate marketplace plugins (they lived in `@objectstack/runtime`, duplicating the cloud distribution's copies). ADR-0008 then open-sourced the canonical client into the Apache-2.0 `@objectstack/cloud-connection` package, so the CLI can wire it again without crossing the open-core boundary — there is no longer a cloud-only copy to duplicate.
8+
9+
`objectstack serve`/`dev`/`start` now mount `MarketplaceProxyPlugin` + `MarketplaceInstallLocalPlugin` + the same-origin cloud-connection surface + `RuntimeConfigPlugin` (single-env, `installLocal: true`) whenever `resolveCloudUrl()` is truthy. `OS_CLOUD_URL=off` (or unset) mounts nothing, preserving the vanilla marketplace-less `objectstack dev`. Skipped in runtime/host-kernel mode (the cloud `objectos-stack` wires its own proxy on the host kernel — detected via `ObjectOSEnvironmentPlugin`, mirroring the existing AuthPlugin guard).
10+
11+
Fixes `objectstack start` empty-boot, which advertised "boot an empty kernel against your marketplace" but — having no config or artifact to carry the wiring — actually mounted no marketplace at all. The plugins self-register their Setup nav bundles, so Browse Marketplace + Installed Apps reappear automatically.

packages/cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@ai-sdk/openai": "^3.0.71",
4646
"@objectstack/account": "workspace:*",
4747
"@objectstack/client": "workspace:*",
48+
"@objectstack/cloud-connection": "workspace:*",
4849
"@objectstack/console": "workspace:*",
4950
"@objectstack/core": "workspace:^",
5051
"@objectstack/driver-memory": "workspace:^",

packages/cli/src/commands/serve.ts

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,18 +1007,64 @@ export default class Serve extends Command {
10071007
}
10081008
}
10091009

1010-
// 5 / 5b / 5b-ii — REMOVED (ADR-0006 Phase 4, cloud ADR-0007 ⑤).
1010+
// 5. Marketplace browse/install + runtime-config — auto-wired from the
1011+
// open `@objectstack/cloud-connection` package, gated on a resolved
1012+
// cloud URL.
10111013
//
1012-
// The CLI used to auto-inject MarketplaceProxyPlugin,
1013-
// MarketplaceInstallLocalPlugin and RuntimeConfigPlugin from
1014-
// `@objectstack/runtime` here. Those were duplicates of the canonical
1015-
// cloud implementations and are deleted from the framework in this
1016-
// phase: marketplace browse/install and the runtime-config endpoint
1017-
// are cloud-distribution features (`@objectstack/objectos-runtime`),
1018-
// wired explicitly by hosts that want them (see the cloud repo's
1019-
// apps/objectos-ee config for the single-env wiring). A vanilla
1020-
// `objectstack dev` no longer mounts a marketplace; the Console SPA
1021-
// falls back to its defaults when `/api/v1/runtime/config` is absent.
1014+
// History: ADR-0006 Phase 4 deleted the framework's DUPLICATE copies
1015+
// (which lived in `@objectstack/runtime`) because the canonical
1016+
// implementation then lived in the cloud distribution. ADR-0008 then
1017+
// open-sourced that client surface into `@objectstack/cloud-connection`
1018+
// (Apache-2.0, framework-side), so the CLI can wire it again WITHOUT
1019+
// crossing the open-core boundary — there is no longer a cloud-only
1020+
// copy to duplicate. This restores marketplace for `objectstack start`
1021+
// empty-boot, which advertises "boot an empty kernel against your
1022+
// marketplace" but, with no config/artifact, has no host to carry the
1023+
// wiring (the only place it can come from is the CLI itself).
1024+
//
1025+
// Mirrors the objectos-ee single-env host wiring: proxy + install-local
1026+
// + cloud-connection only when `resolveCloudUrl()` is truthy
1027+
// (OS_CLOUD_URL=off -> nothing mounts, preserving the vanilla
1028+
// marketplace-less `objectstack dev`). Each plugin self-registers its
1029+
// own Setup nav bundle in start(), so no manual bundle registration is
1030+
// needed here.
1031+
//
1032+
// SKIPPED in runtime/host-kernel mode: the cloud distribution
1033+
// (objectos-stack) wires its own MarketplaceProxyPlugin on the host
1034+
// kernel, so auto-wiring here would double-mount. Detect runtime mode by
1035+
// ObjectOSEnvironmentPlugin (same signal the AuthPlugin guard below
1036+
// uses); OS_CLOUD_URL alone is NOT a reliable signal -- a regular
1037+
// `objectstack dev` app sets it precisely to enable the marketplace.
1038+
const isRuntimeHostKernel = plugins.some(
1039+
(p: any) => p?.name === 'com.objectstack.runtime.objectos-environment'
1040+
|| p?.constructor?.name === 'ObjectOSEnvironmentPlugin'
1041+
);
1042+
if (!isRuntimeHostKernel) {
1043+
try {
1044+
const ccPkg = '@objectstack/cloud-connection';
1045+
const {
1046+
MarketplaceProxyPlugin,
1047+
MarketplaceInstallLocalPlugin,
1048+
RuntimeConfigPlugin,
1049+
createCloudConnectionPlugin,
1050+
resolveCloudUrl,
1051+
} = await import(/* webpackIgnore: true */ ccPkg);
1052+
const marketplaceUrl = resolveCloudUrl();
1053+
if (marketplaceUrl) {
1054+
await kernel.use(new MarketplaceProxyPlugin({ controlPlaneUrl: marketplaceUrl }));
1055+
await kernel.use(new MarketplaceInstallLocalPlugin({ controlPlaneUrl: marketplaceUrl }));
1056+
// Same-origin /cloud-connection/* surface (status + device-code
1057+
// bind + control-plane catalog views) in single-environment mode.
1058+
await kernel.use(createCloudConnectionPlugin({ singleEnvironment: true, controlPlaneUrl: marketplaceUrl }));
1059+
// Server-pushed runtime config so the Console knows marketplace +
1060+
// install-local are live (same-origin; install into THIS kernel).
1061+
await kernel.use(new RuntimeConfigPlugin({ controlPlaneUrl: '', singleEnvironment: true, installLocal: true }));
1062+
trackPlugin('Marketplace');
1063+
}
1064+
} catch (err: any) {
1065+
console.warn(chalk.yellow(` \u26a0 Marketplace/cloud-connection wiring failed: ${err?.message ?? err}`));
1066+
}
1067+
}
10221068

10231069
// 5c. Auto-register PlatformObjectsPlugin so platform-default
10241070
// translation bundles (Setup App + metadata-type configuration

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)