Răsfoiți Sursa

refactor: projection-key home moves to src/types.ts with /types + /client/types dual outlets

imccyu 1 lună în urmă
părinte
comite
38ffb78e1c

+ 6 - 2
packages/session-title/session-title/package.json

@@ -15,9 +15,13 @@
       "types": "./lib/types/invariant.d.ts",
       "default": "./lib/invariant.js"
     },
+    "./types": {
+      "types": "./lib/types/types.d.ts",
+      "default": "./lib/types/types.js"
+    },
     "./client/types": {
-      "types": "./lib/types/client/types.d.ts",
-      "default": "./lib/types/client/types.js"
+      "types": "./lib/types/client/index.d.ts",
+      "default": "./lib/types/client/index.js"
     },
     "./src/*": "./src/*",
     "./package.json": "./package.json"

+ 10 - 0
packages/session-title/session-title/src/client/index.ts

@@ -0,0 +1,10 @@
+/**
+ * Browser half-entry of the title domain: a pure re-export of the package's
+ * types outlet. Client code imports ONLY the client namespace (repo
+ * discipline), so `./client/types` projects the same single-source content
+ * `./types` serves to host consumers — zero duplication.
+ *
+ * @module @deepseek-ai/dsh-session-title/client/types
+ */
+
+export type * from '../types.ts'

+ 5 - 6
packages/session-title/session-title/src/index.ts

@@ -17,12 +17,11 @@ import type {
 } from '@deepseek-ai/dsh-session'
 // Type-only: resolves ctx.sessionProjections for the optional unit child.
 import type {} from '@deepseek-ai/dsh-session-projection'
-// The `title` projection-key declaration lives in the client outlet (its one
-// home). A PLAIN side-effect import, not `import type`: declaration emit
-// elides type-only imports, and the aggregate programs resolve this package
-// through its emitted declarations — the merge must survive in index.d.ts.
-// The imported module is types-only, so the runtime edge is an empty module.
-import './client/types.ts'
+// The `title` projection-key declaration lives in src/types.ts (its one home);
+// this re-export projects the type face onto the package root AND keeps the
+// module edge in the emitted index.d.ts, so aggregate programs consuming the
+// declarations still receive the SessionProjectionMap merge.
+export type * from './types.ts'
 import { fallbackSessionTitle, normalizeSessionTitle } from './normalize.ts'
 
 export { fallbackSessionTitle, normalizeSessionTitle, truncateTitleUtf8 } from './normalize.ts'

+ 6 - 7
packages/session-title/session-title/src/client/types.ts → packages/session-title/session-title/src/types.ts

@@ -1,12 +1,11 @@
 /**
- * Pure-type client outlet of the title domain: the ONE home of the `title`
- * projection-key declaration, importable from client aggregates without
- * dragging this package's host-side value imports (cordis service,
- * schemastery, the llm seam). The host entry (`index.ts`) imports this module
- * type-only to reuse the same merge — one declaration serves both program
- * sides.
+ * Pure types of the title domain: the ONE home of the `title` projection-key
+ * declaration, free of this package's host-side value imports (cordis
+ * service, schemastery, the llm seam). Two namespace projections serve it —
+ * `./types` for host consumers, `./client/types` (the browser half-entry's
+ * re-export) for client aggregates — with zero content duplication.
  *
- * @module @deepseek-ai/dsh-session-title/client/types
+ * @module @deepseek-ai/dsh-session-title/types
  */
 
 // Marks this file a module so the declaration below AUGMENTS the projection

+ 6 - 2
packages/todo/tool-todo/package.json

@@ -15,9 +15,13 @@
       "types": "./lib/types/invariant.d.ts",
       "default": "./lib/invariant.js"
     },
+    "./types": {
+      "types": "./lib/types/types.d.ts",
+      "default": "./lib/types/types.js"
+    },
     "./client/types": {
-      "types": "./lib/types/client/types.d.ts",
-      "default": "./lib/types/client/types.js"
+      "types": "./lib/types/client/index.d.ts",
+      "default": "./lib/types/client/index.js"
     },
     "./src/*": "./src/*",
     "./package.json": "./package.json"

+ 10 - 0
packages/todo/tool-todo/src/client/index.ts

@@ -0,0 +1,10 @@
+/**
+ * Browser half-entry of the todo domain: a pure re-export of the package's
+ * types outlet. Client code imports ONLY the client namespace (repo
+ * discipline), so `./client/types` projects the same single-source content
+ * `./types` serves to host consumers — zero duplication.
+ *
+ * @module @deepseek-ai/dsh-tool-todo/client/types
+ */
+
+export type * from '../types.ts'

+ 5 - 6
packages/todo/tool-todo/src/index.ts

@@ -12,12 +12,11 @@ import { defineTool } from '@deepseek-ai/dsh-tools'
 import type { TodoItem } from '@deepseek-ai/dsh-session'
 // Type-only: resolves ctx.sessionProjections for the optional unit child.
 import type {} from '@deepseek-ai/dsh-session-projection'
-// The `todos` projection-key declaration lives in the client outlet (its one
-// home). A PLAIN side-effect import, not `import type`: declaration emit
-// elides type-only imports, and the aggregate programs resolve this package
-// through its emitted declarations — the merge must survive in index.d.ts.
-// The imported module is types-only, so the runtime edge is an empty module.
-import './client/types.ts'
+// The `todos` projection-key declaration lives in src/types.ts (its one home);
+// this re-export projects the type face onto the package root AND keeps the
+// module edge in the emitted index.d.ts, so aggregate programs consuming the
+// declarations still receive the SessionProjectionMap merge.
+export type * from './types.ts'
 
 export const name = 'tool-todo'
 export const inject = ['tools']

+ 6 - 6
packages/todo/tool-todo/src/client/types.ts → packages/todo/tool-todo/src/types.ts

@@ -1,11 +1,11 @@
 /**
- * Pure-type client outlet of the todo domain: the ONE home of the `todos`
- * projection-key declaration, importable from client aggregates without
- * dragging this package's host-side value imports (dsh-tools, zod). The host
- * entry (`index.ts`) imports this module type-only to reuse the same merge —
- * one declaration serves both program sides.
+ * Pure types of the todo domain: the ONE home of the `todos` projection-key
+ * declaration plus its payload types, free of this package's host-side value
+ * imports (dsh-tools, zod). Two namespace projections serve it — `./types`
+ * for host consumers, `./client/types` (the browser half-entry's re-export)
+ * for client aggregates — with zero content duplication.
  *
- * @module @deepseek-ai/dsh-tool-todo/client/types
+ * @module @deepseek-ai/dsh-tool-todo/types
  */
 
 import type { TodoItem } from '@deepseek-ai/dsh-session/types'

+ 4 - 2
tsconfig.base.json

@@ -42,8 +42,10 @@
       "@deepseek-ai/dsh-session/types": ["./packages/core/session/src/types.ts"],
       "@deepseek-ai/dsh-session/surface": ["./packages/core/session/src/surface.ts"],
       "@deepseek-ai/dsh-session-projection/types": ["./packages/session-projection/session-projection/src/types.ts"],
-      "@deepseek-ai/dsh-tool-todo/client/types": ["./packages/todo/tool-todo/src/client/types.ts"],
-      "@deepseek-ai/dsh-session-title/client/types": ["./packages/session-title/session-title/src/client/types.ts"],
+      "@deepseek-ai/dsh-tool-todo/types": ["./packages/todo/tool-todo/src/types.ts"],
+      "@deepseek-ai/dsh-tool-todo/client/types": ["./packages/todo/tool-todo/src/client/index.ts"],
+      "@deepseek-ai/dsh-session-title/types": ["./packages/session-title/session-title/src/types.ts"],
+      "@deepseek-ai/dsh-session-title/client/types": ["./packages/session-title/session-title/src/client/index.ts"],
       "@deepseek-ai/dsh-llm/types": ["./packages/llm/llm/src/types.ts"],
       "@deepseek-ai/dsh-llm/brand": ["./packages/llm/llm/src/brand.ts"],
       "@deepseek-ai/dsh-tools/presentation": ["./packages/core/tools/src/presentation.ts"],