nx-sk 0.3.2 → 0.3.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/CHANGELOG.md +23 -4
- package/package.json +1 -1
- package/src/core/fields.js +19 -0
- package/src/core/store.js +7 -2
- package/src/modules/sections/service.js +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,25 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.3.3] - 2026-09-26
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **自定义栏目在 Web 面板整页空白**:栏目的分组元数据有两条读取路径——CLI 从字段
|
|
12
|
+
**推导**(`groupFields(fields)`),面板按**声明数组**(`section.groups`)渲染。
|
|
13
|
+
用 `section add --fields '{…"group":"basic"…}'` 建栏目而没同时给 `--groups` 时,
|
|
14
|
+
`groups` 是空数组:CLI 显示正常、面板的字段表单整组消失,而页面本身不报错,
|
|
15
|
+
看起来就像「这个栏目不存在」。
|
|
16
|
+
- 修复:新增 `syncSectionGroups()` 把「分组声明 ⊇ 字段引用」钉成**栏目不变量**,
|
|
17
|
+
规则只写一份,在 `normalizeSection`(store 读写的唯一收口)与 `section add` 的
|
|
18
|
+
草稿两处调用——**存量数据读一次即自愈**,此后 `--add-field` / 面板加字段引用到
|
|
19
|
+
未声明的分组也会自动补齐声明。
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- CHANGELOG 中 0.3.1 那条安全说明不再复述被清除的原文(说明「清理了 PII」的句子
|
|
24
|
+
本身不该再带上那份 PII)。
|
|
25
|
+
|
|
7
26
|
## [0.3.2] - 2026-09-25
|
|
8
27
|
|
|
9
28
|
### Fixed
|
|
@@ -19,10 +38,10 @@
|
|
|
19
38
|
|
|
20
39
|
### Security
|
|
21
40
|
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
41
|
+
- **清除文档与帮助文本中的真实个人信息**:真实姓名与邮箱拼音样例统一替换为占位符
|
|
42
|
+
(姓名→`张三`、邮箱前缀→`zhangsan`),涉及 skill 文档示例(`assets/nx-sk/references/`)、
|
|
43
|
+
CLI 帮助文本(`help entry`)、面板 toast 提示与单测夹具;提交作者身份统一为
|
|
44
|
+
`nx-sk <nx-sk@local>`。已用 `git filter-repo` 重写全部历史并 force-push。
|
|
26
45
|
- 0.3.0 因包含上述信息已在 npm 标记 deprecated(unpublish 被 granular token
|
|
27
46
|
2FA 政策拦截,需官网手动删除)。
|
|
28
47
|
|
package/package.json
CHANGED
package/src/core/fields.js
CHANGED
|
@@ -294,6 +294,25 @@ export function groupFields(fields) {
|
|
|
294
294
|
return order.map((id) => ({ id, fields: map.get(id) }));
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
+
/**
|
|
298
|
+
* 分组声明的**唯一补全规则**:字段引用了未声明的分组 → 追加 `{ id, title: id }`。
|
|
299
|
+
*
|
|
300
|
+
* 背景(servers 栏目事故):CLI 的分组渲染从字段**推导**(groupFields),
|
|
301
|
+
* 面板却读**声明数组**(section.groups)——`--fields` 引用了 `--groups`
|
|
302
|
+
* 没声明的分组时,两端分叉,面板整个字段表单消失而 CLI 看起来一切正常。
|
|
303
|
+
* 所以「分组声明 ⊇ 字段引用」必须是不变量,在 normalize(读写唯一收口)
|
|
304
|
+
* 和 section add 的草稿上调用同一个函数,规则就不可能有第二份。
|
|
305
|
+
*/
|
|
306
|
+
export function syncSectionGroups(groups, fields) {
|
|
307
|
+
const out = [...(groups || [])];
|
|
308
|
+
const declared = new Set(out.map((g) => g.id));
|
|
309
|
+
for (const f of fields || []) {
|
|
310
|
+
const gid = f.group || 'other';
|
|
311
|
+
if (!declared.has(gid)) { declared.add(gid); out.push({ id: gid, title: gid }); }
|
|
312
|
+
}
|
|
313
|
+
return out;
|
|
314
|
+
}
|
|
315
|
+
|
|
297
316
|
export function fieldByKey(section, key) {
|
|
298
317
|
return (section?.fields || []).find((x) => x.key === key) || null;
|
|
299
318
|
}
|
package/src/core/store.js
CHANGED
|
@@ -4,7 +4,7 @@ import fsp from 'node:fs/promises';
|
|
|
4
4
|
import { join } from 'node:path';
|
|
5
5
|
import { displayPath, snapshotDir, storeFile } from './paths.js';
|
|
6
6
|
import { ensureDir, pathExists, writeAtomic, writeJsonAtomic } from './fsx.js';
|
|
7
|
-
import { instantiateTemplate, seedSections } from './fields.js';
|
|
7
|
+
import { instantiateTemplate, seedSections, syncSectionGroups } from './fields.js';
|
|
8
8
|
import { nowIso, stamp } from './ids.js';
|
|
9
9
|
|
|
10
10
|
/** v2:密钥栏目从 8 字段模板改成单字段 KV(名称 → 值)。
|
|
@@ -38,7 +38,7 @@ function emptyStore(seed) {
|
|
|
38
38
|
|
|
39
39
|
function normalizeSection(raw) {
|
|
40
40
|
if (!raw || typeof raw !== 'object' || !raw.id) return null;
|
|
41
|
-
|
|
41
|
+
const out = {
|
|
42
42
|
id: String(raw.id),
|
|
43
43
|
title: String(raw.title || raw.id),
|
|
44
44
|
description: String(raw.description || ''),
|
|
@@ -52,6 +52,11 @@ function normalizeSection(raw) {
|
|
|
52
52
|
createdAt: raw.createdAt || null,
|
|
53
53
|
updatedAt: raw.updatedAt || null,
|
|
54
54
|
};
|
|
55
|
+
// 「分组声明 ⊇ 字段引用」是栏目不变量:字段引用了没声明的分组,面板的分组表单
|
|
56
|
+
// 会整组消失(真实事故:servers 栏目 groups 为空,Web 端白屏而 CLI 正常)。
|
|
57
|
+
// 放在 normalize 收口——每条读写路径都会过这里,存量数据读一次就自愈。
|
|
58
|
+
out.groups = syncSectionGroups(out.groups, out.fields);
|
|
59
|
+
return out;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
function normalizeEntry(raw) {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { loadStore, mutateStore, snapshotStore } from '../../core/store.js';
|
|
4
4
|
import { assertFieldKey, assertSafeId } from '../../core/paths.js';
|
|
5
5
|
import { badInput, blocked, conflict, notFound } from '../../core/errors.js';
|
|
6
|
-
import { FILL_POLICIES, FIELD_TYPES, findSection, groupFields, instantiateTemplate, sectionNames, templateSummaries } from '../../core/fields.js';
|
|
6
|
+
import { FILL_POLICIES, FIELD_TYPES, findSection, groupFields, instantiateTemplate, sectionNames, syncSectionGroups, templateSummaries } from '../../core/fields.js';
|
|
7
7
|
import { dumpSection, formatValue } from '../../core/render.js';
|
|
8
8
|
import { sensitiveViewer } from '../../core/vault.js';
|
|
9
9
|
import { nowIso } from '../../core/ids.js';
|
|
@@ -116,6 +116,9 @@ export async function addSection({ id, title, template, description, order, fiel
|
|
|
116
116
|
const defaultGroup = draft.groups[0]?.id || 'other';
|
|
117
117
|
draft.fields = fields.map((x) => validateFieldDef(x, { allowGroup: defaultGroup }));
|
|
118
118
|
}
|
|
119
|
+
// 与 normalize 同一条规则:--fields 引用了 --groups 没声明的分组时自动补上,
|
|
120
|
+
// 否则面板按声明数组渲染会整组消失(CLI 从字段推导所以看不出来)。
|
|
121
|
+
draft.groups = syncSectionGroups(draft.groups, draft.fields);
|
|
119
122
|
draft.createdAt = nowIso();
|
|
120
123
|
draft.updatedAt = draft.createdAt;
|
|
121
124
|
|