@deepseek-ai/dsh-typert-loader 0.2.1-alpha.1 → 0.2.1-alpha.3
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 +6 -6
- package/README.md +5 -2
- package/README.zh.md +5 -2
- package/lib/index.js +26 -3
- package/lib/types/index.d.ts +3 -2
- package/locale/en.json +5 -0
- package/locale/zh.json +6 -0
- package/package.json +15 -11
package/README.i18n.yaml
CHANGED
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
en: 881670b2d7dfb04d
|
|
22
22
|
zh: fbf612e945aaf066
|
|
23
23
|
/deepseek-ai-dsh-typert-loader/use-this-package/what-gets-registered:
|
|
24
|
-
en:
|
|
25
|
-
zh:
|
|
24
|
+
en: 73660724a51afcea
|
|
25
|
+
zh: 448a32bb29614c7a
|
|
26
26
|
/deepseek-ai-dsh-typert-loader/use-this-package/observable-behavior-and-failures:
|
|
27
27
|
en: 01494e9fbd469ec8
|
|
28
28
|
zh: 3025d870c0f36e2b
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
en: 03fc077e58271e18
|
|
34
34
|
zh: 20f8fc02008cee5e
|
|
35
35
|
/deepseek-ai-dsh-typert-loader/understand-the-implementation/manifest-validation:
|
|
36
|
-
en:
|
|
37
|
-
zh:
|
|
36
|
+
en: c7d93c72a224e8fb
|
|
37
|
+
zh: 51f0e4b8a043c238
|
|
38
38
|
/deepseek-ai-dsh-typert-loader/understand-the-implementation/caching-and-ownership:
|
|
39
39
|
en: 38e781e052fdf44e
|
|
40
40
|
zh: d8f6b4d119bf9856
|
|
@@ -51,8 +51,8 @@
|
|
|
51
51
|
en: f8a0ad3d0fc0eb32
|
|
52
52
|
zh: 7649a694b279f5f3
|
|
53
53
|
/deepseek-ai-dsh-typert-loader/known-limitations-and-deferred-work:
|
|
54
|
-
en:
|
|
55
|
-
zh:
|
|
54
|
+
en: 9bc795b850f7ab8a
|
|
55
|
+
zh: f3aea571a70bf327
|
|
56
56
|
/deepseek-ai-dsh-typert-loader/known-limitations-and-deferred-work/dev-note:
|
|
57
57
|
en: e67f633dc6fe7773
|
|
58
58
|
zh: 3bb0c20c93f16f98
|
package/README.md
CHANGED
|
@@ -44,7 +44,9 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a
|
|
|
44
44
|
|
|
45
45
|
### What gets registered
|
|
46
46
|
|
|
47
|
-
Each qualifying Loader entry contributes its generated host-face reflection
|
|
47
|
+
Each qualifying Loader entry contributes its generated host-face reflection, schema factories, and `TYPERT.invocations` to the runtime registry. The ordinary artifact's getter exposes descriptors from a private Remote info instance; generated direct descriptors also provide named input and invocation helpers. Registration follows the entry lifecycle: it is withdrawn when the entry or the plugin unmounts, and an import that settles after either owner is gone is discarded.
|
|
48
|
+
|
|
49
|
+
Source compositions requiring strict Remote validation prebuild and load the ordinary `./typert` artifact. The loader registers its invocations in `ctx.typert.local`; it does not recover erased constraints, documentation, or schemas from live Services. Limited descriptor-free source fallback remains a Gateway concern, and `local.hasSeen()` prevents downgrading to it after a registered definition is withdrawn.
|
|
48
50
|
|
|
49
51
|
### Observable behavior and failures
|
|
50
52
|
|
|
@@ -66,7 +68,7 @@ The plugin is an incremental scanner mirroring the client-modules node half: eve
|
|
|
66
68
|
|
|
67
69
|
### Manifest validation
|
|
68
70
|
|
|
69
|
-
`validateTypertManifest()`
|
|
71
|
+
`validateTypertManifest()` checks artifacts before they enter the typed registry. A manifest must name its exporting package, carry face `host`, hold schema factories, and contain well-formed reflection records; invocation descriptors require strict codecs with factories. Validation checks parameter `codec` and any supplied `strictCodec` specs and requires generated direct-method `input` and `invoke` to be callable; `result` remains the sole output codec. Documentation and JSON Schema are optional. Registration never calls the input selector, parser factories, or projection getters; validation inspects only supplied static projection data. Every failure names the package and the defect.
|
|
70
72
|
|
|
71
73
|
### Caching and ownership
|
|
72
74
|
|
|
@@ -113,6 +115,7 @@ These limits define what the loader does not discover or register; they are curr
|
|
|
113
115
|
- **Host face only** — discovery imports only the host `./typert` artifact; client runtimes need a separate composition owner before equivalent discovery is added.
|
|
114
116
|
- **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.
|
|
115
117
|
- **Cached verdicts never expire** — a package that gains a `./typert` export mid-process needs a restart before the loader registers it.
|
|
118
|
+
- **Host readiness remains composition-owned** — consumers requiring strict metadata must wait for registration before serving calls. The lazy info factory does not make asynchronous Loader registration ready; `local.hasSeen()` only protects definitions already observed.
|
|
116
119
|
|
|
117
120
|
<a id="dev-note"></a>
|
|
118
121
|
### Dev Note
|
package/README.zh.md
CHANGED
|
@@ -44,7 +44,9 @@ kind: "package-reference"
|
|
|
44
44
|
|
|
45
45
|
### 注册什么
|
|
46
46
|
|
|
47
|
-
每个符合条件的 Loader
|
|
47
|
+
每个符合条件的 Loader 配置项都会把其生成的宿主侧反射、schema factory 和 `TYPERT.invocations` 贡献给运行时注册表。普通产物的 getter 暴露来自私有 Remote info 实例的描述符;生成的直接方法描述符还提供具名输入与调用辅助能力。注册跟随配置项生命周期:配置项或本插件卸载时撤销;在配置项或本插件任一方卸载后才结束的导入操作会被丢弃。
|
|
48
|
+
|
|
49
|
+
要求严格 Remote 校验的源码组合预先构建并加载普通 `./typert` 产物。loader 将其调用定义注册到 `ctx.typert.local`;它不会从运行中的 Service 恢复已擦除的约束、文档或 schema。受限的无描述符源码回退仍由 Gateway 负责,`local.hasSeen()` 会阻止已注册定义撤销后降级到该回退。
|
|
48
50
|
|
|
49
51
|
### 可观察行为与失败
|
|
50
52
|
|
|
@@ -66,7 +68,7 @@ kind: "package-reference"
|
|
|
66
68
|
|
|
67
69
|
### Manifest 校验
|
|
68
70
|
|
|
69
|
-
`validateTypertManifest()`
|
|
71
|
+
`validateTypertManifest()` 在产物进入类型化注册表前执行检查。manifest 必须指名导出它的包、携带 `host` face、持有 schema factory,并包含格式正确的反射记录;调用描述符要求带 factory 的严格 codec。校验检查参数 `codec` 及提供的 `strictCodec` spec,并要求生成直接方法的 `input` 和 `invoke` 可调用;`result` 仍是唯一输出 codec。文档和 JSON Schema 可选。注册绝不调用输入选择器、解析器 factory 或投影 getter;校验只检查已提供的静态投影数据。每次失败都会指名包与缺陷。
|
|
70
72
|
|
|
71
73
|
### 缓存与归属
|
|
72
74
|
|
|
@@ -113,6 +115,7 @@ kind: "package-reference"
|
|
|
113
115
|
- **仅宿主侧**——发现机制只会导入宿主侧 `./typert` 产物;在为客户端运行时添加等价的发现机制之前,需要先有独立的组合所有者。
|
|
114
116
|
- **嵌套插件需要显式条目**——Loader 配置项会被自动发现,但嵌套在另一配置项之下、或完全不经 Loader 加载的插件,需要显式加入 `packages`,或由其所有者直接调用 `ctx.typert.register()`。
|
|
115
117
|
- **缓存结论永不过期**——进程中途新增 `./typert` 导出的包需要重启后 loader 才会注册它。
|
|
118
|
+
- **Host 就绪仍由组合负责**——要求严格元数据的消费方必须等待注册完成后再接受调用。惰性 info factory 不会让异步 Loader 注册自动就绪;`local.hasSeen()` 只保护已经观察到的定义。
|
|
116
119
|
|
|
117
120
|
<a id="dev-note"></a>
|
|
118
121
|
### 开发备注
|
package/lib/index.js
CHANGED
|
@@ -68,8 +68,9 @@ function typertExportOf(pkgName, exportsField) {
|
|
|
68
68
|
/**
|
|
69
69
|
* Narrow a dynamically imported typert module's `TYPERT` export to a
|
|
70
70
|
* contribution owned by `pkgName`. This is the module/file boundary: the
|
|
71
|
-
* manifest crosses from a build artifact into the typed registry
|
|
72
|
-
*
|
|
71
|
+
* manifest crosses from a build artifact into the typed registry. Dispatch
|
|
72
|
+
* facts and eager projection fields are checked; computed tool projections
|
|
73
|
+
* remain lazy until a consumer requests them. Failures name the package and defect.
|
|
73
74
|
* @param pkgName - the package whose typert face was imported.
|
|
74
75
|
* @param exported - the module's `TYPERT` export.
|
|
75
76
|
* @returns the validated contribution.
|
|
@@ -127,6 +128,9 @@ function requireArray(pkgName, value, subject) {
|
|
|
127
128
|
function requireString(pkgName, value, key, subject) {
|
|
128
129
|
if (typeof value[key] !== "string" || value[key].length === 0) throw new Error(`typert-loader: ${pkgName} ${subject} has a missing or empty ${key}`);
|
|
129
130
|
}
|
|
131
|
+
function requireOptionalString(pkgName, value, key, subject) {
|
|
132
|
+
if (value[key] !== void 0 && typeof value[key] !== "string") throw new Error(`typert-loader: ${pkgName} ${subject}.${key} must be a string`);
|
|
133
|
+
}
|
|
130
134
|
function requireDocumentation(pkgName, value, subject) {
|
|
131
135
|
requireArray(pkgName, value.tags, `${subject}.tags`);
|
|
132
136
|
for (const key of [
|
|
@@ -159,6 +163,8 @@ function requireInvocation(pkgName, value) {
|
|
|
159
163
|
"method"
|
|
160
164
|
]) requireString(pkgName, invocation, key, "invocation");
|
|
161
165
|
const id = invocation.id;
|
|
166
|
+
requireOptionalString(pkgName, invocation, "description", `invocation "${id}"`);
|
|
167
|
+
if (invocation.mode !== void 0 && invocation.mode !== "stream") throw new Error(`typert-loader: ${pkgName} invocation "${id}" mode must be "stream" when present`);
|
|
162
168
|
const receiver = requireObject(pkgName, invocation.invocation, `invocation "${id}" receiver`);
|
|
163
169
|
if (receiver.kind === "context") {
|
|
164
170
|
requireString(pkgName, receiver, "context", `invocation "${id}" Context receiver`);
|
|
@@ -172,6 +178,7 @@ function requireInvocation(pkgName, value) {
|
|
|
172
178
|
const parameter = requireObject(pkgName, valueParameter, `invocation "${id}" parameter`);
|
|
173
179
|
requireString(pkgName, parameter, "name", `invocation "${id}" parameter`);
|
|
174
180
|
requireString(pkgName, parameter, "wire", `invocation "${id}" parameter`);
|
|
181
|
+
requireOptionalString(pkgName, parameter, "description", `invocation "${id}" parameter`);
|
|
175
182
|
const wire = parameter.wire;
|
|
176
183
|
if (wires.has(wire)) throw new Error(`typert-loader: ${pkgName} invocation "${id}" repeats wire field "${wire}"`);
|
|
177
184
|
wires.add(wire);
|
|
@@ -183,6 +190,7 @@ function requireInvocation(pkgName, value) {
|
|
|
183
190
|
} else throw new Error(`typert-loader: ${pkgName} invocation "${id}" parameter source must be "json" or "lookup"`);
|
|
184
191
|
parameters.set(wire, parameter);
|
|
185
192
|
requireStrictCodec(pkgName, parameter.codec, `invocation "${id}" parameter codec`);
|
|
193
|
+
if (parameter.strictCodec !== void 0) requireStrictCodec(pkgName, parameter.strictCodec, `invocation "${id}" strict input codec`);
|
|
186
194
|
}
|
|
187
195
|
if (invocation.cancellation !== void 0) {
|
|
188
196
|
if (requireObject(pkgName, invocation.cancellation, `invocation "${id}" cancellation`).parameter !== "signal") throw new Error(`typert-loader: ${pkgName} invocation "${id}" cancellation parameter must be "signal"`);
|
|
@@ -197,18 +205,33 @@ function requireInvocation(pkgName, value) {
|
|
|
197
205
|
}
|
|
198
206
|
if (receiver.kind === "context" && wires.has(receiver.wire)) throw new Error(`typert-loader: ${pkgName} invocation "${id}" repeats Context wire field "${receiver.wire}"`);
|
|
199
207
|
requireStrictCodec(pkgName, invocation.result, `invocation "${id}" result codec`);
|
|
208
|
+
if (invocation.input !== void 0 || invocation.invoke !== void 0) {
|
|
209
|
+
if (receiver.kind !== "direct") throw new Error(`typert-loader: ${pkgName} invocation "${id}" input/invoke require a direct receiver`);
|
|
210
|
+
if (typeof invocation.input !== "function") throw new Error(`typert-loader: ${pkgName} invocation "${id}" has no input() selector`);
|
|
211
|
+
if (typeof invocation.invoke !== "function") throw new Error(`typert-loader: ${pkgName} invocation "${id}" has no invoke() function`);
|
|
212
|
+
}
|
|
200
213
|
if (invocation.sourceLocation !== void 0) {
|
|
201
214
|
const location = requireObject(pkgName, invocation.sourceLocation, `invocation "${id}" sourceLocation`);
|
|
202
215
|
requireString(pkgName, location, "file", `invocation "${id}" sourceLocation`);
|
|
203
216
|
for (const key of ["line", "column"]) if (!Number.isInteger(location[key]) || location[key] < 1) throw new Error(`typert-loader: ${pkgName} invocation "${id}" sourceLocation.${key} must be a positive integer`);
|
|
204
217
|
}
|
|
205
218
|
}
|
|
219
|
+
function requireSchemaProjection(pkgName, value, subject) {
|
|
220
|
+
if (typeof value.create !== "function") throw new Error(`typert-loader: ${pkgName} ${subject} has no create() factory`);
|
|
221
|
+
const fields = Object.getOwnPropertyDescriptors(value);
|
|
222
|
+
for (const key of ["description", "jsonSchemaError"]) {
|
|
223
|
+
const field = fields[key]?.value;
|
|
224
|
+
if (field !== void 0 && typeof field !== "string") throw new Error(`typert-loader: ${pkgName} ${subject}.${key} must be a string`);
|
|
225
|
+
}
|
|
226
|
+
const schema = fields.jsonSchema?.value;
|
|
227
|
+
if (schema !== void 0) requireObject(pkgName, schema, `${subject}.jsonSchema`);
|
|
228
|
+
}
|
|
206
229
|
function requireStrictCodec(pkgName, value, subject) {
|
|
207
230
|
const codec = requireObject(pkgName, value, subject);
|
|
208
231
|
if (codec.mode !== "strict") throw new Error(`typert-loader: ${pkgName} ${subject} must use a strict codec`);
|
|
209
232
|
requireString(pkgName, codec, "typeSymbol", subject);
|
|
210
233
|
for (const method of ["decode", "encode"]) if (codec[method] !== void 0 && typeof codec[method] !== "function") throw new Error(`typert-loader: ${pkgName} ${subject} ${method} must be a function`);
|
|
211
|
-
|
|
234
|
+
requireSchemaProjection(pkgName, codec, subject);
|
|
212
235
|
}
|
|
213
236
|
/**
|
|
214
237
|
* Scan current Loader entries during activation, then follow entry mounts and
|
package/lib/types/index.d.ts
CHANGED
|
@@ -43,8 +43,9 @@ export declare const Config: z<Config>;
|
|
|
43
43
|
/**
|
|
44
44
|
* Narrow a dynamically imported typert module's `TYPERT` export to a
|
|
45
45
|
* contribution owned by `pkgName`. This is the module/file boundary: the
|
|
46
|
-
* manifest crosses from a build artifact into the typed registry
|
|
47
|
-
*
|
|
46
|
+
* manifest crosses from a build artifact into the typed registry. Dispatch
|
|
47
|
+
* facts and eager projection fields are checked; computed tool projections
|
|
48
|
+
* remain lazy until a consumer requests them. Failures name the package and defect.
|
|
48
49
|
* @param pkgName - the package whose typert face was imported.
|
|
49
50
|
* @param exported - the module's `TYPERT` export.
|
|
50
51
|
* @returns the validated contribution.
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-typert-loader",
|
|
3
3
|
"description": "Loader integration for generated Typert package contributions",
|
|
4
|
-
"version": "0.2.1-alpha.
|
|
4
|
+
"version": "0.2.1-alpha.3",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -19,26 +19,30 @@
|
|
|
19
19
|
"default": "./lib/index.js"
|
|
20
20
|
},
|
|
21
21
|
"./src/*": "./src/*",
|
|
22
|
-
"./package.json": "./package.json"
|
|
22
|
+
"./package.json": "./package.json",
|
|
23
|
+
"./locale/*.json": "./locale/*.json"
|
|
23
24
|
},
|
|
24
25
|
"files": [
|
|
26
|
+
"locale/*.json",
|
|
25
27
|
"lib/index.js",
|
|
26
28
|
"lib/types/**/*.d.ts"
|
|
27
29
|
],
|
|
28
30
|
"license": "MIT",
|
|
29
31
|
"peerDependencies": {
|
|
30
|
-
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.
|
|
31
|
-
"@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.
|
|
32
|
-
"@deepseek-ai/cordis": "~4.0.5-alpha.
|
|
32
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.2",
|
|
33
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.3",
|
|
34
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.2"
|
|
33
35
|
},
|
|
34
36
|
"dependencies": {
|
|
35
|
-
"@deepseek-ai/schemastery": "~3.18.5-alpha.
|
|
37
|
+
"@deepseek-ai/schemastery": "~3.18.5-alpha.2"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
38
|
-
"
|
|
39
|
-
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.
|
|
40
|
-
"@deepseek-ai/dsh-
|
|
41
|
-
"@deepseek-ai/dsh-typert-
|
|
42
|
-
"@deepseek-ai/cordis": "~4.0.5-alpha.
|
|
40
|
+
"@deepseek-ai/dsh-app-boot": "0.2.1-alpha.3",
|
|
41
|
+
"@deepseek-ai/cordis-plugin-loader": "~1.0.6-alpha.2",
|
|
42
|
+
"@deepseek-ai/dsh-typert-registry": "0.2.1-alpha.3",
|
|
43
|
+
"@deepseek-ai/dsh-typert-protocol": "0.2.1-alpha.3",
|
|
44
|
+
"@deepseek-ai/cordis": "~4.0.5-alpha.2",
|
|
45
|
+
"typescript": "^6.0.3",
|
|
46
|
+
"zod": "4.4.3"
|
|
43
47
|
}
|
|
44
48
|
}
|