@xneog/dsh-typert-loader 0.1.0 → 0.1.2-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/typert/loader/README.md
5
- README.md: ab9293de1630fdbe8c560bb9e6d00c272cc34161
6
- README.zh.md: 4e962c05b73982f03accab938cf3282dfe333dbc
5
+ README.md: c46280f12ad5b912cac706326f23fcd6ceb3d066
6
+ README.zh.md: 96cf5ae9c62ff2f61fe31774353cee55498896a4
package/README.md CHANGED
@@ -1,24 +1,126 @@
1
+ ---
2
+ description: "Loader integration for generated Typert artifacts: how mounted packages automatically contribute their host-face reflection and schemas to the runtime registry."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @xneog/dsh-typert-loader
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- Node-only Loader integration for generated Typert artifacts. The plugin requires `ctx.loader` and `ctx.typert`; it does not provide the registry itself.
10
+ ## Summary
11
+
12
+ With `dsh-typert-loader` mounted, every package that mounts in a Loader composition automatically contributes its generated Typert reflection and schemas to the runtime registry — and withdraws them when the package or the plugin unmounts. Packages without the generated export are skipped, so adding the plugin to any composition is safe. An explicit `packages` list covers plugins nested behind another Loader entry, whose fibers carry no resolvable package specifier. It is a Node-only plugin and needs the config-tree resolution anchor to resolve packages.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Mount this plugin in a Host Loader composition that loads packages publishing generated Typert artifacts. The registry itself comes from `dsh-typert-registry`; this plugin only discovers and registers.
29
+
30
+ ### Minimal configuration
31
+
32
+ Load the registry and the loader; the loader defaults to discovering every Loader entry:
33
+
34
+ ```yaml
35
+ - name: '@xneog/dsh-typert-registry'
36
+ - name: '@xneog/dsh-typert-loader'
37
+ ```
38
+
39
+ | Field | Default | Meaning |
40
+ |---|---|---|
41
+ | `packages` | `[]` | Additional package artifacts to register for plugins nested behind another Loader entry; each must resolve from the config tree and export `./typert` |
42
+
43
+ The generated [configuration catalog](../../../docs/config-catalog.md#xneogdsh-typert-loader) is the exhaustive source for every accepted field.
44
+
45
+ ### What gets registered
46
+
47
+ Each qualifying Loader entry contributes its generated host-face reflection and schemas to the runtime registry. Registration follows the entry lifecycle: it is withdrawn when the entry or the plugin unmounts, and a registration whose import settles after both are gone is discarded.
48
+
49
+ ### Observable behavior and failures
50
+
51
+ Packages without the export are skipped silently. Resolution verdicts and imported manifests are cached for the process lifetime, so adding a `./typert` export requires a restart. A malformed artifact among already-mounted entries fails activation loudly; a later failure is logged per package without preventing unrelated packages from registering. An explicit `packages` entry that cannot be resolved from the config tree, or that lacks the export, fails loudly and names the package.
52
+
53
+ -----
54
+
55
+ <a id="understand-the-implementation"></a>
56
+ ## Understand the implementation
57
+
58
+ <details>
59
+ <summary>Implementation internals — click to expand</summary>
6
60
 
7
- During activation it scans existing Loader entries. It then follows Cordis `internal/plugin` lifecycle notifications, resolves each entry package's `package.json`, imports `./typert` when exported, validates its `TYPERT` manifest, and registers the contribution until the entry or this plugin unmounts. An import that settles after either owner is gone is discarded.
61
+ This section explains how the loader scans, validates, and registers; the observable behavior is covered in [Use this package](#use-this-package).
8
62
 
9
- `packages` lists additional package artifacts to register for plugins nested behind another Loader entry. Cordis fibers do not retain those nested plugins' npm specifiers, so this boundary is explicit; every configured package must resolve from the config tree and export `./typert`.
63
+ ### Design concept
10
64
 
11
- Packages without the export are skipped. Package resolution and imported manifests are cached for the process lifetime, so adding an export requires a restart. A malformed artifact fails activation when already mounted; a later failure is logged without preventing unrelated packages from registering.
65
+ The plugin is an incremental scanner mirroring the client-modules node half: every Cordis `internal/plugin` emission marks the fiber's entry name dirty, and a microtask flush reconciles each dirty name against the live Loader entries; the activation pass seeds the same dirty set with all current entries.
12
66
 
67
+ ### Manifest validation
68
+
69
+ `validateTypertManifest()` is the module/file boundary: the manifest crosses from a build artifact into the typed registry, so every field is checked. The manifest must name the package that exports it, carry face `host`, hold zod v4 schema instances, and keep well-formed service, event, object, member, type, and documentation records; invocation descriptors must use strict codecs. Every failure names the package and the defect.
70
+
71
+ ### Caching and ownership
72
+
73
+ Verdicts (resolvable specifier, export presence) and imported manifests are cached per package name and never expire. Registrations are keyed by entry name and withdrawn through the exact `ctx.typert.register()` disposer; in-flight tasks are tracked per entry so a late import cannot register a contribution after its owner is gone.
74
+
75
+ ### Source map
76
+
77
+ | File | Role |
78
+ |---|---|
79
+ | [`src/index.ts`](src/index.ts) | Plugin entry: `Config`, scanner, manifest validation, registration wiring |
80
+ | — | No runtime invariant companion is published; the Loader entry lifecycle directly owns each exact registry disposer, and integration tests observe registration and removal. |
81
+
82
+ </details>
83
+
84
+ -----
85
+
86
+ <a id="further-exploration"></a>
87
+ ## Further Exploration
88
+
89
+ Read these pages when the package-level contract is not enough; they move from the loader to what it registers and what produces it.
90
+
91
+ - [Typert registry](../registry/README.md) — the service this plugin feeds.
92
+ - [Typert generator](../generator/README.md) — what produces the artifacts the loader imports.
93
+ - [Generated configuration catalog](../../../docs/config-catalog.md#xneogdsh-typert-loader) — the `packages` field declaration and JSDoc.
94
+ - [Typert group map](../README.md) — the full type-reflection pipeline.
95
+
96
+ -----
97
+
98
+ <a id="model-experience"></a>
13
99
  ## Model Experience
14
100
 
15
- None, as the loader only feeds [`ctx.typert`](../registry/README.md); consumers own any model-visible projection.
101
+ None, as loader integration only registers generated artifacts; consumers own any model-visible projection.
16
102
 
17
103
  #### KV Cache effect
18
104
 
19
- No direct effect.
105
+ No direct effect; registration changes reach a request only through a consumer that reads the registry.
20
106
 
21
107
  ## Known Limitations and Deferred Work
22
108
 
23
- - Discovery imports only the host face; client runtimes need a separate composition owner before equivalent discovery is added.
24
- - Loader entries are discovered automatically. Nested or non-Loader plugins require an explicit `packages` entry or direct `ctx.typert.register()` ownership.
109
+ <a id="known-limitations-and-deferred-work"></a>
110
+
111
+
112
+ These limits define what the loader does not discover or register; they are current package constraints, not a task backlog.
113
+
114
+ - **Host face only** — discovery imports only the host `./typert` artifact; client runtimes need a separate composition owner before equivalent discovery is added.
115
+ - **Explicit entries for nested plugins** — Loader entries are discovered automatically, but plugins nested behind another entry, or not loaded by the Loader at all, need an explicit `packages` entry or direct `ctx.typert.register()` ownership.
116
+ - **Cached verdicts never expire** — a package that gains a `./typert` export mid-process needs a restart before the loader registers it.
117
+
118
+ <a id="dev-note"></a>
119
+ ### Dev Note
120
+
121
+ <details>
122
+ <summary>Working context for maintainers — click to expand</summary>
123
+
124
+ None.
125
+
126
+ </details>
package/README.zh.md CHANGED
@@ -1,24 +1,126 @@
1
+ ---
2
+ description: "生成的 Typert 产物所用的 Loader 集成:已挂载的包如何自动把宿主侧反射与 schema 贡献给运行时注册表。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @xneog/dsh-typert-loader
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 生成的 Typert 产物所用的 Loader 集成,仅支持 Node。该插件需要 `ctx.loader` 和 `ctx.typert`;它本身不提供注册表。
10
+ ## 概述
11
+
12
+ 挂载 `dsh-typert-loader` 后,Loader 组合中每个挂载的包都会自动把其生成的 Typert 反射与 schema 贡献给运行时注册表——并在包或本插件卸载时自动撤销。没有该导出的包会被跳过,因此在任何 Loader 组合中挂载它都是安全的。显式 `packages` 用于覆盖嵌套在另一 Loader 配置项之下的插件,这些插件的 fiber 不携带可解析的包说明符。它是仅支持 Node 的插件,需要配置树解析锚点才能解析包。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 在加载发布生成 Typert 产物的包的 Host Loader 组合中挂载本插件。注册表本身来自 `dsh-typert-registry`;本插件只负责发现与注册。
29
+
30
+ ### 最小配置
31
+
32
+ 加载注册表与 loader;loader 默认发现每一个 Loader 配置项:
33
+
34
+ ```yaml
35
+ - name: '@xneog/dsh-typert-registry'
36
+ - name: '@xneog/dsh-typert-loader'
37
+ ```
38
+
39
+ | 字段 | 默认值 | 含义 |
40
+ |---|---|---|
41
+ | `packages` | `[]` | 为嵌套在另一 Loader 配置项下的插件额外注册的包产物;每个包都必须能从配置树解析,并导出 `./typert` |
42
+
43
+ 生成的[配置目录](../../../docs/config-catalog.zh.md#xneogdsh-typert-loader)是每个受支持字段的穷尽式真源。
44
+
45
+ ### 注册什么
46
+
47
+ 每个符合条件的 Loader 配置项都会把其生成的宿主侧反射与 schema 贡献给运行时注册表。注册跟随配置项生命周期:配置项或本插件卸载时撤销;在两者都已消失后才结束的注册会被丢弃。
48
+
49
+ ### 可观察行为与失败
50
+
51
+ 没有该导出的包会被静默跳过。解析结论与已导入的 manifest 会在整个进程生命周期内缓存,因此新增 `./typert` 导出后必须重启。已挂载配置项对应的产物格式错误时,激活会大声失败;之后才发生的失败按包记录日志,不会阻止无关包完成注册。无法从配置树解析、或缺少该导出的显式 `packages` 条目会大声失败并指名该包。
52
+
53
+ -----
54
+
55
+ <a id="understand-the-implementation"></a>
56
+ ## 理解实现
57
+
58
+ <details>
59
+ <summary>实现细节——点击展开</summary>
6
60
 
7
- 激活时,该插件会扫描现有的 Loader 配置项。随后它会监听 Cordis `internal/plugin` 生命周期通知,解析每个配置项所属包的 `package.json`,在其导出 `./typert` 时导入该子路径,校验其 `TYPERT` manifest(元数据清单),并注册该贡献项,直到配置项或本插件卸载。如果导入操作在配置项或本插件卸载后才结束,系统会丢弃其结果。
61
+ 本节解释 loader 如何扫描、校验与注册;可观察行为已在[使用本包](#use-this-package)中说明。
8
62
 
9
- `packages` 用于列出需要为嵌套在另一 Loader 配置项下的插件额外注册的包产物。Cordis fiber 不会保留这些嵌套插件的 npm 包说明符,因此这里通过显式配置划定边界;配置中列出的每个包都必须能从配置树解析,并导出 `./typert`。
63
+ ### 设计理念
10
64
 
11
- 未导出该子路径的包会被跳过。包解析结果和已导入的 manifest 会在整个进程生命周期内缓存,因此新增该导出后必须重启进程。插件激活时,如果已挂载 Loader 配置项对应的产物格式错误,激活会失败;之后才发生的失败只会记录到日志,不会阻止无关包完成注册。
65
+ 本插件是一个增量扫描器,与 client-modules Node 半实现对称:每次 Cordis `internal/plugin` 事件都会把该 fiber 的配置项名称标记为脏,微任务 flush 会针对实时 Loader 配置项逐一调和每个脏名称;激活阶段用所有当前配置项填充同一脏集合。
12
66
 
67
+ ### Manifest 校验
68
+
69
+ `validateTypertManifest()` 是模块/文件边界:manifest 从构建产物进入类型化注册表,因此每个字段都会被检查。manifest 必须指名导出它的包、携带 `host` face、持有 zod v4 schema 实例,并保持服务、事件、对象、成员、类型与文档记录格式正确;调用描述符必须使用严格编解码器。每次失败都会指名包与缺陷。
70
+
71
+ ### 缓存与归属
72
+
73
+ 结论(可解析说明符、是否导出)与已导入的 manifest 按包名缓存且永不过期。注册按配置项名称键控,并通过 `ctx.typert.register()` 返回的同一资源释放函数撤销;进行中的任务按配置项跟踪,因此迟到的导入不可能在其所有者消失后注册贡献。
74
+
75
+ ### 源码地图
76
+
77
+ | 文件 | 职责 |
78
+ |---|---|
79
+ | [`src/index.ts`](src/index.ts) | 插件入口:`Config`、扫描器、manifest 校验、注册接线 |
80
+ | — | 不发布运行时不变式伴生入口;Loader entry 生命周期直接持有每个准确的 registry disposer,integration test 会观察注册与移除。 |
81
+
82
+ </details>
83
+
84
+ -----
85
+
86
+ <a id="further-exploration"></a>
87
+ ## 进一步探索
88
+
89
+ 当包级约定不够用时阅读以下页面;它们从 loader 逐步进入它注册什么以及什么产生这些内容。
90
+
91
+ - [Typert 注册表](../registry/README.zh.md)——本插件所供给的服务。
92
+ - [Typert 生成器](../generator/README.zh.md)——产生 loader 所导入产物的包。
93
+ - [生成配置目录](../../../docs/config-catalog.zh.md#xneogdsh-typert-loader)——`packages` 字段声明及其 JSDoc。
94
+ - [Typert 组地图](../README.zh.md)——完整的类型反射流水线。
95
+
96
+ -----
97
+
98
+ <a id="model-experience"></a>
13
99
  ## 模型体验
14
100
 
15
- 无。loader 只向 [`ctx.typert`](../registry/README.md) 提供注册项;任何模型可见投影均由消费方负责。
101
+ 无,因为 loader 集成只注册生成的产物;任何模型可见投影均由消费方负责。
16
102
 
17
103
  #### KV Cache 影响
18
104
 
19
- 无直接影响。
105
+ 无直接影响;注册变化只有在消费方读取注册表时才会触及请求。
106
+
107
+ ## 已知限制与延期工作
108
+
109
+ <a id="known-limitations-and-deferred-work"></a>
110
+
111
+
112
+ 这些限制说明 loader 不会发现或注册什么;它们是当前包约束,不是任务积压。
113
+
114
+ - **仅宿主侧**——发现机制只会导入宿主侧 `./typert` 产物;在为客户端运行时添加等价的发现机制之前,需要先有独立的组合所有者。
115
+ - **嵌套插件需要显式条目**——Loader 配置项会被自动发现,但嵌套在另一配置项之下、或完全不经 Loader 加载的插件,需要显式加入 `packages`,或由其所有者直接调用 `ctx.typert.register()`。
116
+ - **缓存结论永不过期**——进程中途新增 `./typert` 导出的包需要重启后 loader 才会注册它。
117
+
118
+ <a id="dev-note"></a>
119
+ ### 开发备注
120
+
121
+ <details>
122
+ <summary>维护者的工作上下文——点击展开</summary>
20
123
 
21
- ## 已知限制与暂缓事项
124
+ 无。
22
125
 
23
- - 发现机制只会导入宿主侧产物;若要为客户端运行时添加等价的发现机制,需要先有独立的组合所有者。
24
- - Loader 配置项会自动发现。嵌套插件或非 Loader 插件需要显式加入 `packages`,或由其所有者直接负责调用 `ctx.typert.register()`。
126
+ </details>
package/lib/index.js CHANGED
@@ -17,9 +17,9 @@ import z from "@xneog/schemastery";
17
17
  * fails loud — aggregated into this plugin's activation throw for existing
18
18
  * entries, contained to a logged error per package in steady state.
19
19
  *
20
- * Scanning is incremental per entry name, mirroring the client-modules node
21
- * half: every cordis `internal/plugin` emission marks the fiber's entry name
22
- * dirty and a microtask flush reconciles each dirty name against the live
20
+ * Scanning is incremental per entry name. Every cordis `internal/plugin`
21
+ * emission marks the fiber's entry name dirty, and a microtask flush
22
+ * reconciles each dirty name against the live
23
23
  * loader entries; the activation pass seeds the same dirty set with all
24
24
  * current entries. Package verdicts and imported manifests are cached per
25
25
  * package name and never expire — plugin-set changes take effect on restart.
@@ -11,9 +11,9 @@
11
11
  * fails loud — aggregated into this plugin's activation throw for existing
12
12
  * entries, contained to a logged error per package in steady state.
13
13
  *
14
- * Scanning is incremental per entry name, mirroring the client-modules node
15
- * half: every cordis `internal/plugin` emission marks the fiber's entry name
16
- * dirty and a microtask flush reconciles each dirty name against the live
14
+ * Scanning is incremental per entry name. Every cordis `internal/plugin`
15
+ * emission marks the fiber's entry name dirty, and a microtask flush
16
+ * reconciles each dirty name against the live
17
17
  * loader entries; the activation pass seeds the same dirty set with all
18
18
  * current entries. Package verdicts and imported manifests are cached per
19
19
  * package name and never expire — plugin-set changes take effect on restart.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xneog/dsh-typert-loader",
3
3
  "description": "Loader integration for generated Typert package contributions",
4
- "version": "0.1.0",
4
+ "version": "0.1.2-rc.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -18,33 +18,26 @@
18
18
  "types": "./lib/types/index.d.ts",
19
19
  "default": "./lib/index.js"
20
20
  },
21
- "./invariant": {
22
- "types": "./lib/types/invariant.d.ts",
23
- "default": "./lib/invariant.js"
24
- },
25
21
  "./src/*": "./src/*",
26
22
  "./package.json": "./package.json"
27
23
  },
28
24
  "files": [
29
25
  "lib/index.js",
30
- "lib/invariant.js",
31
26
  "lib/types/**/*.d.ts"
32
27
  ],
33
28
  "license": "MIT",
34
29
  "peerDependencies": {
35
- "@xneog/cordis-plugin-loader": "0.1.0",
36
- "@xneog/dsh-invariants": "0.1.0",
37
- "@xneog/dsh-typert-registry": "0.1.0",
38
- "@xneog/cordis": "0.1.0"
30
+ "@xneog/cordis-plugin-loader": "^1.0.3",
31
+ "@xneog/dsh-typert-registry": "^0.1.2-rc.1",
32
+ "@xneog/cordis": "^4.0.2"
39
33
  },
40
34
  "dependencies": {
41
- "@xneog/schemastery": "0.1.0"
35
+ "@xneog/schemastery": "^3.18.2"
42
36
  },
43
37
  "devDependencies": {
44
- "@xneog/cordis-plugin-loader": "0.1.0",
45
- "@xneog/dsh-invariants": "0.1.0",
46
- "@xneog/dsh-typert-registry": "0.1.0",
47
- "@xneog/cordis": "0.1.0",
48
- "zod": "^4.4.3"
38
+ "zod": "^4.4.3",
39
+ "@xneog/dsh-typert-registry": "^0.1.2-rc.1",
40
+ "@xneog/cordis-plugin-loader": "^1.0.3",
41
+ "@xneog/cordis": "^4.0.2"
49
42
  }
50
43
  }
package/lib/invariant.js DELETED
@@ -1,23 +0,0 @@
1
- //#region lib/types/invariant.js
2
- /**
3
- * Package-owned invariant companion for `@xneog/dsh-typert-loader`.
4
- * @module @xneog/dsh-typert-loader/invariant
5
- */
6
- const PACKAGE_NAME = "@xneog/dsh-typert-loader";
7
- /** Cordis companion plugin name. */
8
- const name = "typert-loader-invariant";
9
- /** Service required before the companion can reserve package ownership. */
10
- const inject = ["invariants"];
11
- /**
12
- * No runtime invariant: the Loader entry lifecycle directly owns each exact
13
- * registry disposer, and integration tests observe registration and removal.
14
- */
15
- const install = () => {};
16
- /**
17
- * Register this package's invariant companion.
18
- * @param ctx - Cordis context carrying the invariant service.
19
- * @returns the installed registration's disposer after setup succeeds.
20
- */
21
- const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
22
- //#endregion
23
- export { apply, inject, name };
@@ -1,16 +0,0 @@
1
- /**
2
- * Package-owned invariant companion for `@xneog/dsh-typert-loader`.
3
- * @module @xneog/dsh-typert-loader/invariant
4
- */
5
- import type { Context } from '@xneog/cordis';
6
- /** Cordis companion plugin name. */
7
- export declare const name = "typert-loader-invariant";
8
- /** Service required before the companion can reserve package ownership. */
9
- export declare const inject: string[];
10
- /**
11
- * Register this package's invariant companion.
12
- * @param ctx - Cordis context carrying the invariant service.
13
- * @returns the installed registration's disposer after setup succeeds.
14
- */
15
- export declare const apply: (ctx: Context) => Promise<() => void>;
16
- //# sourceMappingURL=invariant.d.ts.map