Stop requiring dsh-client-store in the Plugins card bundle.

Shipped dsh web seed has no client-store entry; use a private snapshot store and only externalize platform seed modules.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
oliver 2026-09-04 22:38:52 +08:00
parent e45657b1ee
commit 69a4820369
6 changed files with 78 additions and 25 deletions

View file

@ -2,8 +2,12 @@
* Build lib/client.js as a DSH ModuleLoader factory artifact using Bun's bundler.
* Usage: bun run scripts/build-client.mjs
*
* Must emit production JSX (`react/jsx-runtime`). The web shell seeds only that
* specifier — `react/jsx-dev-runtime` is not in PLATFORM_MODULES and fails load.
* Externals must match the *installed* web shell seed table. Shipped
* `@deepseek-ai/dsh` 0.1.1-rc.2 seeds only:
* react, react/jsx-runtime, react-dom, react-dom/client,
* @deepseek-ai/cordis, dsh-client-ui-slots, dsh-client-ui-primitives
* Do not leave other @deepseek-ai packages as require() targets unless they
* are also listed in dsh.client.inject and arrive as graph factories.
*/
import { mkdirSync, writeFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
@ -14,28 +18,15 @@ const entry = join(root, 'src/client/index.ts')
const outFile = join(root, 'lib', 'client.js')
const id = 'dsh-netxops'
/** Align with @deepseek-ai/dsh-client-web PLATFORM_MODULES + dsh.client.inject. */
/** Exact PLATFORM_MODULES keys from shipped dsh-web-frontend seed. */
const external = [
'react',
'react/jsx-runtime',
'react-dom',
'react-dom/client',
'@deepseek-ai/cordis',
'@deepseek-ai/dsh-client-store',
'@deepseek-ai/dsh-client-locale',
'@deepseek-ai/dsh-client-locale/client',
'@deepseek-ai/dsh-client-ui-settings',
'@deepseek-ai/dsh-client-ui-settings/client',
'@deepseek-ai/dsh-client-ui-settings-plugins',
'@deepseek-ai/dsh-client-ui-settings-plugins/client',
'@deepseek-ai/dsh-client-ui-slots',
'@deepseek-ai/dsh-client-ui-renderer',
'@deepseek-ai/dsh-client-ui-renderer/client',
'@deepseek-ai/dsh-client-ui-primitives',
'@deepseek-ai/dsh-api-remotes',
'@deepseek-ai/dsh-api-remotes/client',
'@deepseek-ai/dsh-client-connection',
'@deepseek-ai/dsh-client-connection/client',
]
const result = await Bun.build({
@ -44,7 +35,6 @@ const result = await Bun.build({
format: 'cjs',
sourcemap: 'none',
minify: false,
// Force production JSX transform (jsx-runtime, not jsx-dev-runtime).
define: {
'process.env.NODE_ENV': JSON.stringify('production'),
},
@ -56,10 +46,21 @@ if (!result.success) {
throw new Error('Bun.build failed')
}
let raw = await result.outputs[0].text()
const raw = await result.outputs[0].text()
if (raw.includes('react/jsx-dev-runtime')) {
throw new Error('client bundle still references react/jsx-dev-runtime; refuse to ship')
}
if (raw.includes('@deepseek-ai/dsh-client-store')) {
throw new Error('client bundle still requires dsh-client-store; refuse to ship')
}
const requires = [...raw.matchAll(/require\("([^"]+)"\)/g)].map(m => m[1])
const allowed = new Set(external)
for (const spec of requires) {
if (!allowed.has(spec)) {
throw new Error(`client bundle requires undeclared external "${spec}"; refuse to ship`)
}
}
const body = raw
.replace(/^"use strict";\s*/m, '')
@ -79,4 +80,4 @@ ${body}
mkdirSync(dirname(outFile), { recursive: true })
writeFileSync(outFile, artifact, 'utf8')
console.log(`wrote ${outFile} (${artifact.length} bytes)`)
console.log(`wrote ${outFile} (${artifact.length} bytes); requires: ${[...new Set(requires)].join(', ') || '(none)'}`)