fix(build): align Client build metadata

This commit is contained in:
imccyu
2026-08-08 12:02:58 +08:00
parent 2a7c1175be
commit d85d0806cd
6 changed files with 13 additions and 11 deletions
@@ -2,5 +2,5 @@
# side as of the last confirmed-consistent state. Both languages carry equal authority;
# after editing either side, bring the other along and re-record with:
# pnpm run verify-translation-pairing --write .agents/notes/implemented/process/2026-08-08-api-remotes-generated-contract-build.md
2026-08-08-api-remotes-generated-contract-build.md: ac9bb445917e11a4b57280da513d36b0f434bbaf
2026-08-08-api-remotes-generated-contract-build.md: 83848290400441f0272b220ed0d396570e1ce2dc
2026-08-08-api-remotes-generated-contract-build.zh.md: 4f9760078c209a22b9e03837fd81769e156b5df9
@@ -53,7 +53,7 @@ This exception follows from the real generated-contract ordering and is not a te
Host tsdown enables `typertPlugin({ mode: 'workspace', faces: ['host'] })` in the normal root config. The generator uses only `tsconfig.host.json` as its program seed and produces both `typert.host.*` and the `typert.remote-client.*` projection of Host contracts; Client tsdown neither starts TypeRT nor analyzes the Client aggregate.
The TypeRT analyzer distinguishes compiler faces from runtime faces. Direct Project References in the aggregate determine which compiler face analyzes a project; only a split project explicitly referenced through `tsconfig.host.json` or `tsconfig.client.json` is restricted to that corresponding face. Runtime models follow package subpath contributions instead, so an ordinary single-project `dshClient` package may contribute both Host and Client runtime models.
The TypeRT analyzer distinguishes compiler faces from runtime faces. Direct Project References in the aggregate determine which compiler face analyzes a project; only a split project explicitly referenced through `tsconfig.host.json` or `tsconfig.client.json` is restricted to that corresponding face. Runtime models follow package subpath contributions instead, so an ordinary single-project `dshClient` package may contribute both Host and Client runtime models. Consequently, Host analysis of `api-remotes` does not also register its Client entry, while an ordinary dual-entry package does not lose its Host model.
Both the Host and Client tsdown passes receive the same complete workspace of `vendor/*`, `packages/*/*`, and `apps/cli`. The root config does not scan `lib/types/client/index.js`, maintain a package classification table, or use a tsdown filter; package-local configs return entries for the current phase according to `DSH_BUILD_FACE`.
+1 -1
View File
@@ -20,7 +20,7 @@ const PLUGINS: readonly (WebBootEntry & { bundlePath: string })[] = [
{ id: '@deepseek-ai/dsh-client-connection', bundlePath: 'packages/client/connection/lib/client.js', url: '/plugins/connection.js', rev: 'fx', inject: [], immediately: true },
{ id: '@deepseek-ai/dsh-api-gateway', bundlePath: 'packages/api/gateway/lib/client.js', url: '/plugins/api-gateway.js', rev: 'fx', inject: ['@deepseek-ai/dsh-typert-registry', '@deepseek-ai/dsh-client-connection'], immediately: true },
{ id: '@deepseek-ai/dsh-api-remotes', bundlePath: 'packages/api/remotes/lib/client.js', url: '/plugins/api-remotes.js', rev: 'fx', inject: ['@deepseek-ai/dsh-api-gateway'], immediately: true },
{ id: '@deepseek-ai/dsh-client-runtime', bundlePath: 'packages/client/runtime/lib/client.js', url: '/plugins/runtime.js', rev: 'fx', inject: ['@deepseek-ai/dsh-client-connection', '@deepseek-ai/dsh-api-remotes', '@deepseek-ai/dsh-typert-registry'], immediately: true },
{ id: '@deepseek-ai/dsh-client-runtime', bundlePath: 'packages/client/runtime/lib/client.js', url: '/plugins/runtime.js', rev: 'fx', inject: ['@deepseek-ai/dsh-client-connection', '@deepseek-ai/dsh-typert-registry'], immediately: true },
{ id: '@deepseek-ai/dsh-client-ui-theme', bundlePath: 'packages/client/ui-theme/lib/client.js', url: '/plugins/ui-theme.js', rev: 'fx', inject: [], immediately: true },
{ id: '@deepseek-ai/dsh-client-locale', bundlePath: 'packages/client/locale/lib/client.js', url: '/plugins/locale.js', rev: 'fx', inject: [], immediately: true },
{ id: '@deepseek-ai/dsh-client-ui-layout', bundlePath: 'packages/client/ui-layout/lib/client.js', url: '/plugins/ui-layout.js', rev: 'fx', inject: ['@deepseek-ai/dsh-client-runtime'] },
+7 -5
View File
@@ -93,10 +93,10 @@ export function clientBundle(
const client = clientConfig(id, face === undefined
? 'src/client/index.ts'
: 'lib/types/client/index.js')
const host = [lib, ...(options.host ?? [])]
if (face === 'host') return options.hostPhase === true ? host : [SKIP_WORKSPACE_BUILD]
if (face === 'client') return options.hostPhase === true ? [client] : [...host, client]
return [...host, client]
const node = [lib, ...(options.companions ?? [])]
if (face === 'host') return options.hostPhase === true ? node : [SKIP_WORKSPACE_BUILD]
if (face === 'client') return options.hostPhase === true ? [client] : [...node, client]
return [...node, client]
}
}
@@ -125,7 +125,9 @@ export function clientOnly(configs: readonly UserConfig[]): BuildFaceConfig {
interface ClientBundleOptions {
/** Emit the Node-side artifacts during the Host pass instead of the Client pass. */
readonly hostPhase?: boolean
readonly host?: readonly UserConfig[]
/** Additional Node-side configs emitted alongside the package library. */
readonly companions?: readonly UserConfig[]
/** Overrides for the package's primary Node-side library config. */
readonly lib?: UserConfig
}
@@ -7,7 +7,7 @@ export default clientBundle(
'@deepseek-ai/dsh-host-directory-picker-native',
['lib/types/index.js', 'lib/types/invariant.js'],
{
host: [{
companions: [{
// The artifact is lib/worker.cjs (the ./worker export the workspace
// constraint keys on), bundled from the descriptive source entry.
entry: { worker: 'lib/types/win32-dialog-worker.js' },
+2 -2
View File
@@ -263,8 +263,8 @@ function ciPrimaryGates(): Gate[] {
...docSyncLeafGates(),
pnpmScript('module-graph', 'verify-module-graph', { label: 'module graph' }),
pnpmScript('knip', 'knip'),
// typecheck and build now drive the same root solution graph; without the
// dependency two concurrent `tsc -b` runs race the same tsbuildinfo files.
// typecheck and build both drive the Host and Client tsc graphs; without
// the dependency concurrent runs race the same tsbuildinfo files.
// The tsc step is an incremental no-op after typecheck.
pnpmScript('build', 'build', { needs: ['typecheck'] }),
pnpmScript('publint', 'publint', { needs: ['build'] }),