From d1007158f9b24090a8ded990fd1eb6ace35fbf54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=85=E5=91=A8=E6=B6=9B?= Date: Thu, 2 Jul 2026 12:47:14 -0700 Subject: [PATCH 1/2] fix(console): bundle THIS framework's client into the vendored console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The console SPA inlines @objectstack/client, and the version came from objectui's own lockfile — which necessarily lags the framework whenever a release adds new client APIs (the new client isn't on npm when objectui's lockfile is written). 11.5.0 shipped the new import UI bundled against client 11.2.0, so the console threw "The connected @objectstack/client does not support async import jobs." at runtime. build-console.sh now exports OBJECTSTACK_CLIENT_DIST=packages/client so vite aliases the bundled client to this repo's own build — the bundled client always matches the framework release, eliminating the framework → objectui pin-bump → framework re-release round-trip. Details: - Fail hard if the pinned objectui SHA lacks the vite.config.ts hook. - Build the client dist first if missing. - Split the build: deps via turbo, the console app via its own build script directly — turbo v2 strict env strips undeclared vars, which is exactly how the first injection attempt silently produced a stale bundle. - Post-build canary (CONSOLE_BUNDLE_CANARY, default 'import/jobs') asserts the fresh client actually landed in dist/assets. Verified: rebuilt at the currently pinned SHA 1432efe81 (whose lockfile still resolves client 11.2.0) — dist now contains the import/jobs routes; before this change it had zero occurrences. Fixes #2512 --- scripts/build-console.sh | 59 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/scripts/build-console.sh b/scripts/build-console.sh index 35ae388b1e..f185f616c7 100755 --- a/scripts/build-console.sh +++ b/scripts/build-console.sh @@ -19,9 +19,11 @@ # scripts/build-console.sh # # Env: -# OBJECTUI_ROOT override path to objectui checkout -# OBJECTUI_REPO_URL override clone URL (default: https://github.com/objectstack-ai/objectui.git) -# OBJECTUI_BUILD_CMD override build command (default: pnpm exec turbo run build --filter=@object-ui/console) +# OBJECTUI_ROOT override path to objectui checkout +# OBJECTUI_REPO_URL override clone URL (default: https://github.com/objectstack-ai/objectui.git) +# OBJECTUI_DEPS_BUILD_CMD override deps build (default: pnpm exec turbo run build --filter=@object-ui/console^...) +# OBJECTUI_BUILD_CMD override console build (default: pnpm --filter @object-ui/console run build) +# CONSOLE_BUNDLE_CANARY literal asserted in the built assets (default: import/jobs) set -euo pipefail @@ -40,7 +42,18 @@ if [[ -z "$PINNED_SHA" ]]; then fi REPO_URL="${OBJECTUI_REPO_URL:-https://github.com/objectstack-ai/objectui.git}" -BUILD_CMD="${OBJECTUI_BUILD_CMD:-pnpm exec turbo run build --filter=@object-ui/console}" +# The console app itself must NOT build through turbo: turbo v2 runs tasks in +# strict env mode and strips undeclared vars, so OBJECTSTACK_CLIENT_DIST +# (exported below) never reaches vite unless the pinned objectui SHA happens +# to declare it in turbo.json. Build the workspace deps through turbo +# (cacheable, env-independent), then invoke the console's own build script +# directly so the env survives. +DEPS_BUILD_CMD="${OBJECTUI_DEPS_BUILD_CMD:-pnpm exec turbo run build --filter=@object-ui/console^...}" +BUILD_CMD="${OBJECTUI_BUILD_CMD:-pnpm --filter @object-ui/console run build}" +# Post-build canary: a literal that only exists in an up-to-date bundled +# client. Guards against any future mechanism (turbo env stripping, a removed +# vite hook, chunking changes) silently shipping a stale client again. +BUNDLE_CANARY="${CONSOLE_BUNDLE_CANARY:-import/jobs}" # Resolve a source checkout of objectui. SOURCE_ROOT="" @@ -101,6 +114,32 @@ if [[ "$ACTUAL" != "$PINNED_SHA" ]]; then fi echo "→ Building @object-ui/console at ${PINNED_SHA:0:12}..." + +# ── Bundle THIS framework's client ─────────────────────────────────── +# The console SPA inlines @objectstack/client. Left to itself, the objectui +# build resolves the client from objectui's own lockfile — which lags the +# framework whenever a release adds new client APIs (the lockfile can't point +# at a client that isn't published yet). That shipped 11.5.0 with the new +# import UI bundled against client 11.2.0, so the console threw "does not +# support async import jobs" at runtime. Alias the build to the client in +# THIS tree instead: the bundled client then always matches the framework +# release being published, with no objectui pin-bump round-trip. +# objectui honors OBJECTSTACK_CLIENT_DIST in apps/console/vite.config.ts; +# fail hard if the pinned SHA predates that hook rather than silently drift. +CLIENT_PKG="${FRAMEWORK_ROOT}/packages/client" +if ! grep -q "OBJECTSTACK_CLIENT_DIST" "${BUILD_ROOT}/apps/console/vite.config.ts"; then + echo "✗ objectui@${PINNED_SHA:0:12} has no OBJECTSTACK_CLIENT_DIST hook in apps/console/vite.config.ts —" + echo " the bundled client would come from objectui's lockfile, not this framework." + echo " Bump .objectui-sha to a commit that includes the hook." + exit 1 +fi +if [[ ! -f "${CLIENT_PKG}/dist/index.mjs" ]]; then + echo "→ @objectstack/client dist missing — building it first..." + (cd "$CLIENT_PKG" && pnpm build) +fi +export OBJECTSTACK_CLIENT_DIST="$CLIENT_PKG" +echo "→ Console will bundle @objectstack/client from ${CLIENT_PKG}" + pushd "$BUILD_ROOT" > /dev/null # objectui's root package.json may pin packages that aren't available on @@ -109,7 +148,9 @@ NPM_CONFIG_REGISTRY_OVERRIDE="${OBJECTUI_NPM_REGISTRY:-https://registry.npmjs.or npm_config_registry="$NPM_CONFIG_REGISTRY_OVERRIDE" \ pnpm install --frozen-lockfile --prefer-offline --prod=false -# Build only the console SPA (turbo will pull in workspace deps). +# Build the console's workspace deps via turbo, then the SPA itself directly +# (see DEPS_BUILD_CMD/BUILD_CMD above for why these are split). +eval "$DEPS_BUILD_CMD" eval "$BUILD_CMD" popd > /dev/null @@ -133,6 +174,14 @@ cp -R "$CONSOLE_DIST" "$TARGET" # cloud/objectos Docker overlay that replaces dist/ restamps it too. echo "$PINNED_SHA" > "${TARGET}/.objectui-sha" +# Assert the injected client actually landed in the bundle (see BUNDLE_CANARY). +if ! grep -rq "$BUNDLE_CANARY" "${TARGET}/assets"; then + echo "✗ Built console dist does not contain '${BUNDLE_CANARY}' — the bundled" + echo " @objectstack/client is stale (OBJECTSTACK_CLIENT_DIST injection failed)." + exit 1 +fi +echo "✓ Bundle canary '${BUNDLE_CANARY}' present — framework client is in the bundle." + BYTES="$(du -sk "$TARGET" 2>/dev/null | awk '{print $1}')" echo "✓ @objectstack/console dist ready (${BYTES} KB) from objectui@${PINNED_SHA:0:12}" From dbb71f99e50556fdf7c247336431943a7ea699c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=85=E5=91=A8=E6=B6=9B?= Date: Thu, 2 Jul 2026 12:50:56 -0700 Subject: [PATCH 2/2] chore: changeset for console client-bundling fix --- .changeset/console-bundle-own-client.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/console-bundle-own-client.md diff --git a/.changeset/console-bundle-own-client.md b/.changeset/console-bundle-own-client.md new file mode 100644 index 0000000000..382947ff4a --- /dev/null +++ b/.changeset/console-bundle-own-client.md @@ -0,0 +1,5 @@ +--- +'@objectstack/console': patch +--- + +修复 console 产物打包旧版 @objectstack/client 的问题:`build-console.sh` 现在通过 `OBJECTSTACK_CLIENT_DIST` 把本仓库、本版本的 client 注入 console bundle(此前由 objectui lockfile 决定,11.5.0 因此发布了新导入 UI + client 11.2.0,运行时报 "does not support async import jobs")。构建拆为 deps(turbo)+ console 本体(直跑,避开 turbo strict env 剥离环境变量),并新增产物 canary 断言防止旧 client 再次静默发布。