Ver Fonte

fix(build): align Client build metadata

imccyu há 1 mês atrás
pai
commit
d85d0806cd

+ 1 - 1
.agents/notes/implemented/process/2026-08-08-api-remotes-generated-contract-build.i18n.yaml

@@ -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

+ 1 - 1
.agents/notes/implemented/process/2026-08-08-api-remotes-generated-contract-build.md

@@ -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
apps/web/tests/assembled-boot.ts

@@ -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
packages/client/tsdown.client.ts

@@ -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
 }
 

+ 1 - 1
packages/host/directory-picker-native/tsdown.config.ts

@@ -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
scripts/run-gates.ts

@@ -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'] }),