@dsh-workbench/module-tools 0.3.6 → 0.3.8
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/package.json +2 -2
- package/src/checks/contracts.mjs +5 -3
- package/src/design.mjs +27 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/module-tools",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"description": "模块包的构建与门禁工具:build(单文件 ESM 宿主侧 + 套 loader 壳的浏览器侧)、check(契约/产物边界/源码边界/卡片渲染)。模块包不再各带一份构建脚本。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"eslint-plugin-react": "^7.37.5",
|
|
30
30
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
31
31
|
"typescript-eslint": "^8.71.0",
|
|
32
|
-
"@dsh-workbench/shared": "0.3.
|
|
32
|
+
"@dsh-workbench/shared": "0.3.8"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
|
35
35
|
"selfcheck": "node scripts/selfcheck/index.mjs"
|
package/src/checks/contracts.mjs
CHANGED
|
@@ -252,12 +252,13 @@ function fakeLongTasks(created) {
|
|
|
252
252
|
create(options) {
|
|
253
253
|
created.push(options);
|
|
254
254
|
// 形状跟着真外壳那份注册表走(`createLongTaskRegistry`):假的那份少一个方法,
|
|
255
|
-
// 把注册表原样返回的模块就会被这条判据冤枉成"缺方法"——所以 `stop` 也在这里。
|
|
255
|
+
// 把注册表原样返回的模块就会被这条判据冤枉成"缺方法"——所以 `stop` / `live` 也在这里。
|
|
256
256
|
return {
|
|
257
257
|
start: () => ({}),
|
|
258
258
|
snapshot: () => null,
|
|
259
259
|
active: () => null,
|
|
260
260
|
current: () => [],
|
|
261
|
+
live: () => [],
|
|
261
262
|
stop: () => false,
|
|
262
263
|
onChange: () => () => {},
|
|
263
264
|
};
|
|
@@ -350,7 +351,7 @@ function mountOf(face, created, manifest, tools) {
|
|
|
350
351
|
}
|
|
351
352
|
}
|
|
352
353
|
|
|
353
|
-
const LONG_TASK_METHODS = ['start', 'snapshot', 'active', 'current', 'stop', 'onChange'];
|
|
354
|
+
const LONG_TASK_METHODS = ['start', 'snapshot', 'active', 'current', 'live', 'stop', 'onChange'];
|
|
354
355
|
|
|
355
356
|
const LONG_TASK_RENDERERS = ['useLongTask', 'LongTaskRow', 'longTaskDot'];
|
|
356
357
|
|
|
@@ -814,7 +815,8 @@ export async function run() {
|
|
|
814
815
|
if (missing.length > 0) {
|
|
815
816
|
problems.push(
|
|
816
817
|
`${name}: 长任务注册表缺方法 ${missing.join(' / ')} —— 外壳按它给这个单元投影出 /runs 路由(停止那颗钮也按它发),` +
|
|
817
|
-
`kit 的 useLongTask
|
|
818
|
+
`kit 的 useLongTask 与左栏会话行那颗 loading 点读的也是它(后者走 \`live()\`;注册表用 ` +
|
|
819
|
+
`@dsh-workbench/shared/host 的 createLongTaskRegistry 建)`,
|
|
818
820
|
);
|
|
819
821
|
}
|
|
820
822
|
}
|
package/src/design.mjs
CHANGED
|
@@ -51,6 +51,26 @@ const ROWS = {
|
|
|
51
51
|
const DATASOURCE_FIELDS = ['read', 'params', 'credentials', 'notLoggedIn', 'timeout'];
|
|
52
52
|
const WRITE_FIELDS = ['command', 'params', 'credentials', 'preview', 'readback', 'undo', 'failure'];
|
|
53
53
|
|
|
54
|
+
/** `params` 里写了"必填",就得说清凭什么是必填 —— 来源只能是这五个词之一
|
|
55
|
+
* (`已证` 那句话的来源是**录下来的图**上那个红 `*`,或者**契约**里 `--help -f json` 的 `required`)。**气味判据不是解析器**:
|
|
56
|
+
* 只看来源有没有写出来,不看句式、不数个数、不认字段名,也不校验来源是不是真的 ——
|
|
57
|
+
* 真话假话只有人和复核能判(照 `undo` 那条的原话:逼作者想过,不逼他造假)。 */
|
|
58
|
+
const SOURCE_TAGS = ['已证', '声明', '人证', '契约', '未定'];
|
|
59
|
+
|
|
60
|
+
/** `params` 里有没有一处「必填」**没被否掉** —— `非必填` / `不必填`(只看紧邻的那个字符)才算被否掉。
|
|
61
|
+
* 这是**字符级守卫**,只挡这一种写法:不认"必填项""必填字段"以外的语法、不做否定句理解。
|
|
62
|
+
* 为什么非要有它:`design check` 是模块作者天天跑的门禁,`非必填` 这种**明确说不要**的写法
|
|
63
|
+
* 被误咬一次,他下次就把这条判据当噪音 —— 误红的代价比漏一两次大得多。 */
|
|
64
|
+
function hasBareRequired(value) {
|
|
65
|
+
let at = value.indexOf('必填');
|
|
66
|
+
while (at !== -1) {
|
|
67
|
+
const before = value[at - 1];
|
|
68
|
+
if (before !== '非' && before !== '不') return true;
|
|
69
|
+
at = value.indexOf('必填', at + 2);
|
|
70
|
+
}
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
54
74
|
/** 一条卡背后可以有多条读(甚至跨站点):规范形状 `reads: [ … ]`,一条一行;
|
|
55
75
|
* `datasource: { … }` 是只有一条读时的写法(老模块都长这样,继续认)。 */
|
|
56
76
|
function readsOf(design) {
|
|
@@ -208,6 +228,13 @@ export function emptyCells(design) {
|
|
|
208
228
|
writes.forEach((write, index) => {
|
|
209
229
|
const label = writes.length === 1 ? 'write' : `writes[${index}]`;
|
|
210
230
|
for (const field of WRITE_FIELDS) need(cells, write?.[field], `${label}.${field}`);
|
|
231
|
+
// 写了"必填"却不带来源词 ⇒ 点名(`非必填` / `不必填` 那种**明确说不要**的不算,见 hasBareRequired)。
|
|
232
|
+
// 空着 / `(待填)` 是上一轮那条 `pending` 的事,两条不叠。
|
|
233
|
+
// 判的是**值**不是表头:渲染出来的行名「参数(必填 / 取值枚举 / 上限)」不在这条路上。
|
|
234
|
+
const params = text(write?.params);
|
|
235
|
+
if (!pending(params) && hasBareRequired(params) && !SOURCE_TAGS.some((tag) => params.includes(tag))) {
|
|
236
|
+
cells.push(`${label}.params.source`);
|
|
237
|
+
}
|
|
211
238
|
});
|
|
212
239
|
|
|
213
240
|
return cells;
|