@longzai-intelligence-cuts/ledger 0.0.0-stage → 0.0.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.
@@ -0,0 +1,253 @@
1
+ import "./rolldown-runtime-BqT_7tdF.js";
2
+ import { LziCutsConfig } from "@longzai-intelligence-cuts/config";
3
+ /**
4
+ * 注册表 lint 核心
5
+ *
6
+ * 六条核心规则守护衍生品标准形态:文件夹命名、正本在场、标题形态、登
7
+ * 记日期行、三节结构、聚合页一致。读侧判定与写侧渲染共用 `format.utils`
8
+ * 单一口径。
9
+ */
10
+ /**
11
+ * lint 发现
12
+ */
13
+ type LintFinding = {
14
+ /**
15
+ * 规则标识
16
+ */
17
+ rule: string;
18
+ /**
19
+ * 违规位置即相对注册表的文件或文件夹路径
20
+ */
21
+ file: string;
22
+ /**
23
+ * 违规描述
24
+ */
25
+ message: string;
26
+ };
27
+ /**
28
+ * lint 结果
29
+ */
30
+ type LintResult = {
31
+ /**
32
+ * 注册表目录路径
33
+ */
34
+ registryDir: string;
35
+ /**
36
+ * 衍生品总数
37
+ */
38
+ cutCount: number;
39
+ /**
40
+ * 发现清单
41
+ */
42
+ findings: LintFinding[];
43
+ };
44
+ /**
45
+ * 核心规则标识清单
46
+ */
47
+ declare const CORE_LINT_RULES: readonly ['folder-kebab-case', 'readme-present', 'entry-title-format', 'entry-date-line', 'entry-three-sections', 'registry-readme-consistent'];
48
+ /**
49
+ * 运行注册表 lint
50
+ *
51
+ * @param registryDir - 注册表目录路径
52
+ * @returns lint 结果即含全部发现不快速失败
53
+ */
54
+ declare function runLint(registryDir: string): LintResult;
55
+ /**
56
+ * 衍生品标题行解析结果类型
57
+ */
58
+ type CutTitleParts = {
59
+ /**
60
+ * 衍生品标题文本
61
+ */
62
+ title: string;
63
+ };
64
+ /**
65
+ * 解析衍生品标题行
66
+ *
67
+ * @param line - 标题行文本
68
+ * @returns 解析结果,未命中为 null
69
+ */
70
+ declare function parseCutTitleLine(line: string): CutTitleParts | null;
71
+ /**
72
+ * 衍生品文件夹解析器
73
+ *
74
+ * 读入单个衍生品文件夹,产出结构化登记记录:标题、登记日期、三节在场
75
+ * 态与解析问题清单。
76
+ */
77
+ /**
78
+ * 衍生品登记记录
79
+ */
80
+ type CutRecord = {
81
+ /**
82
+ * 衍生品文件夹名
83
+ */
84
+ folderName: string;
85
+ /**
86
+ * 衍生品文件夹绝对或相对路径
87
+ */
88
+ dirPath: string;
89
+ /**
90
+ * 衍生品标题,标题未命中为空串
91
+ */
92
+ title: string;
93
+ /**
94
+ * 登记日期,日期行未命中为 null
95
+ */
96
+ registeredDate: string | null;
97
+ /**
98
+ * 正文在场节标题清单
99
+ */
100
+ presentSections: string[];
101
+ /**
102
+ * 正文缺席节标题清单
103
+ */
104
+ missingSections: string[];
105
+ /**
106
+ * 解析问题清单即无法归入结构字段的形态异常
107
+ */
108
+ parseIssues: string[];
109
+ };
110
+ /**
111
+ * 解析衍生品文件夹
112
+ *
113
+ * @param dirPath - 衍生品文件夹路径
114
+ * @returns 登记记录,正本缺席时记录问题并返回骨架
115
+ */
116
+ declare function parseCut(dirPath: string): CutRecord;
117
+ /**
118
+ * 注册表扫描结果
119
+ */
120
+ type RegistryScan = {
121
+ /**
122
+ * 注册表目录路径
123
+ */
124
+ registryDir: string;
125
+ /**
126
+ * 衍生品登记记录清单即按文件夹名排序
127
+ */
128
+ cuts: CutRecord[];
129
+ /**
130
+ * 非法文件夹名清单即不匹配 kebab-case 的目录
131
+ */
132
+ invalidFolderNames: string[];
133
+ /**
134
+ * 注册表 README 是否在场
135
+ */
136
+ hasReadme: boolean;
137
+ };
138
+ /**
139
+ * 扫描注册表目录
140
+ *
141
+ * @param registryDir - 注册表目录路径
142
+ * @returns 扫描结果,目录缺席时返回空集
143
+ */
144
+ declare function scanRegistryDir(registryDir: string): RegistryScan;
145
+ /**
146
+ * 衍生品登记模板渲染器
147
+ *
148
+ * 渲染建档所需的全部文件文本:登记正本 `README.md`。形态与 format.utils
149
+ * 单一口径对齐。
150
+ */
151
+ /**
152
+ * 登记正本渲染选项
153
+ */
154
+ type RenderCutTemplateOptions = {
155
+ /**
156
+ * 衍生品标题
157
+ */
158
+ title: string;
159
+ /**
160
+ * 登记日期即 `YYYY-MM-DD` 形态
161
+ */
162
+ registeredDate: string;
163
+ };
164
+ /**
165
+ * 渲染登记正本全文
166
+ *
167
+ * @param options - 渲染选项
168
+ * @returns 登记正本全文文本
169
+ */
170
+ declare function renderCutTemplate(options: RenderCutTemplateOptions): string;
171
+ /**
172
+ * 建档模板字段清单即 create 命令必填项
173
+ */
174
+ declare const TEMPLATE_FIELDS: readonly ['title', 'slug'];
175
+ /**
176
+ * 衍生品建档核心
177
+ *
178
+ * 建档即新建 kebab-case 文件夹并落登记正本 `README.md`,标题即名称无编
179
+ * 号。落盘后回读校验解析结果。
180
+ */
181
+ /**
182
+ * 建档选项
183
+ */
184
+ type CreateCutOptions = {
185
+ /**
186
+ * 注册表目录路径
187
+ */
188
+ registryDir: string;
189
+ /**
190
+ * 衍生品标题
191
+ */
192
+ title: string;
193
+ /**
194
+ * 衍生品文件夹 kebab-case 名
195
+ */
196
+ slug: string;
197
+ /**
198
+ * 登记日期即 `YYYY-MM-DD` 形态
199
+ *
200
+ * @default 当日
201
+ */
202
+ registeredDate?: string;
203
+ };
204
+ /**
205
+ * 建档结果
206
+ */
207
+ type CreateCutResult = {
208
+ /**
209
+ * 衍生品文件夹路径
210
+ */
211
+ folderPath: string;
212
+ };
213
+ /**
214
+ * 创建衍生品登记
215
+ *
216
+ * @param options - 建档选项
217
+ * @returns 建档结果
218
+ * @throws {@link Error} slug 形态非法或文件夹已存在时抛错
219
+ */
220
+ declare function createCut(options: CreateCutOptions): CreateCutResult;
221
+ /**
222
+ * 聚合门禁结果
223
+ */
224
+ type CutsCheckResult = {
225
+ /**
226
+ * 全部门禁通过标记
227
+ */
228
+ ok: boolean;
229
+ /**
230
+ * 汇总退出码即 0 过 1 违规
231
+ */
232
+ exitCode: number;
233
+ /**
234
+ * 注册表级 lint 结果清单
235
+ */
236
+ lintResults: ReturnType<typeof runLint>[];
237
+ };
238
+ /**
239
+ * 运行聚合门禁
240
+ *
241
+ * @param root - 仓库根路径
242
+ * @param config - 解析后配置
243
+ * @returns 聚合门禁结果
244
+ */
245
+ declare function runCutsCheck(root: string, config: LziCutsConfig): CutsCheckResult;
246
+ /**
247
+ * lint 发现格式化为单行文本
248
+ *
249
+ * @param finding - lint 发现
250
+ * @returns `文件 [规则] 消息` 形态单行
251
+ */
252
+ declare function formatLintFinding(finding: LintFinding): string;
253
+ export { CORE_LINT_RULES, type CreateCutOptions, type CreateCutResult, type CutRecord, type CutTitleParts, type CutsCheckResult, type LintFinding, type LintResult, type RegistryScan, type RenderCutTemplateOptions, TEMPLATE_FIELDS, createCut, formatLintFinding, parseCut, parseCutTitleLine, renderCutTemplate, runCutsCheck, runLint, scanRegistryDir };
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import"./rolldown-runtime-BqT_7tdF.js";import{existsSync as e,mkdirSync as t,readFileSync as n,readdirSync as r,writeFileSync as i}from"node:fs";import{join as a}from"node:path";const o=`README.md`,s=`README.md`,c=/^[a-z][a-z0-9]*(?:-[a-z0-9]+)+$/,l=/^#\s+衍生品:(.+)$/,u=/^>\s*登记日期:(\d{4}-\d{2}-\d{2})$/,d=[`一、来源与背景`,`二、产物清单`,`三、说明与定位`];function f(e){let t=l.exec(e);return t===null?null:{title:t[1]??``}}function p(t){let r=t.split(/[\\/]/).pop()??t,i=a(t,o),s={folderName:r,dirPath:t,title:``,registeredDate:null,presentSections:[],missingSections:[],parseIssues:[]};if(!e(i))return s.parseIssues.push(`登记正本 ${o} 缺席`),s;let c=n(i,`utf8`).split(`
2
+ `),l=c.find(e=>e.startsWith(`# `))??``,u=f(l);u===null?s.parseIssues.push(`标题行不符合衍生品形态:${l||`未找到一级标题`}`):s.title=u.title,s.registeredDate=m(c);let p=c.filter(e=>/^##\s+/.test(e));return s.presentSections=d.filter(e=>p.some(t=>t.includes(e))),s.missingSections=d.filter(e=>!s.presentSections.includes(e)),s}function m(e){for(let t of e.slice(0,10)){let e=u.exec(t);if(e!==null)return e[1]??null}return null}function h(e){let t=r(e,{withFileTypes:!0}),n=t.filter(e=>e.isDirectory()).map(e=>e.name),i=n.filter(e=>c.test(e)),o=n.filter(e=>!c.test(e));return{registryDir:e,cuts:i.map(t=>p(a(e,t))).sort((e,t)=>e.folderName.localeCompare(t.folderName)),invalidFolderNames:o,hasReadme:t.some(e=>e.isFile()&&e.name===`README.md`)}}const g=[`folder-kebab-case`,`readme-present`,`entry-title-format`,`entry-date-line`,`entry-three-sections`,`registry-readme-consistent`];function _(e){let t=h(e),n=[];for(let e of t.invalidFolderNames)n.push({rule:`folder-kebab-case`,file:e,message:`衍生品文件夹名必须为 kebab-case 语义命名`});for(let e of t.cuts)v(e,n);return y(t,n),{registryDir:e,cutCount:t.cuts.length,findings:n}}function v(e,t){for(let n of e.parseIssues)n.includes(`缺席`)?t.push({rule:`readme-present`,file:e.folderName,message:`登记正本 ${o} 缺席`}):t.push({rule:`entry-title-format`,file:a(e.folderName,o),message:n});e.title===``&&t.push({rule:`entry-title-format`,file:a(e.folderName,o),message:"标题行必须为 `# 衍生品:名称` 形态"}),e.registeredDate===null&&t.push({rule:`entry-date-line`,file:a(e.folderName,o),message:"头部 10 行内必须含 `> 登记日期:YYYY-MM-DD` 行"}),e.missingSections.length>0&&t.push({rule:`entry-three-sections`,file:a(e.folderName,o),message:`缺席节:${e.missingSections.join(`、`)}`})}function y(e,t){if(!e.hasReadme){t.push({rule:`registry-readme-consistent`,file:s,message:`注册表聚合页 README.md 缺席`});return}let r=n(a(e.registryDir,s),`utf8`),i=/* @__PURE__ */ new Set;for(let e of r.split(`
3
+ `)){let t=/\]\(([^)/]+)\/?\)/.exec(e)?.[1];t!==void 0&&i.add(t)}let o=[...i].filter(t=>!e.cuts.some(e=>e.folderName===t));o.length>0&&t.push({rule:`registry-readme-consistent`,file:s,message:`聚合页引用缺席衍生品文件夹:${o.join(`、`)}`})}function b(e){return[`# 衍生品:${e.title}`,``,`> 登记日期:${e.registeredDate}`,``,`## 一、来源与背景`,``,`## 二、产物清单`,``,`## 三、说明与定位`,``].join(`
4
+ `)}const x=[`title`,`slug`];function S(n){if(!c.test(n.slug))throw Error(`slug 必须为多词 kebab-case 形态:${n.slug}`);let r=a(n.registryDir,n.slug);if(e(r))throw Error(`衍生品文件夹已存在:${r}`);let s=n.registeredDate??(/* @__PURE__ */ new Date()).toISOString().slice(0,10);t(r,{recursive:!0}),i(a(r,o),b({title:n.title,registeredDate:s}));let l=p(r);if(l.title!==n.title)throw Error(`建档后回读标题不一致:期望 ${n.title} 实得 ${l.title}`);return{folderPath:r}}function C(e,t){let n=[];for(let r of t.scopes){let t=a(e,r.registryDir);n.push(_(t))}let r=n.reduce((e,t)=>e+t.findings.length,0);return{ok:r===0,exitCode:r===0?0:1,lintResults:n}}function w(e){return`${e.file} [${e.rule}] ${e.message}`}export{g as CORE_LINT_RULES,x as TEMPLATE_FIELDS,S as createCut,w as formatLintFinding,p as parseCut,f as parseCutTitleLine,b as renderCutTemplate,C as runCutsCheck,_ as runLint,h as scanRegistryDir};
@@ -0,0 +1 @@
1
+ import"node:module";export{};
package/package.json CHANGED
@@ -1,6 +1,43 @@
1
1
  {
2
2
  "name": "@longzai-intelligence-cuts/ledger",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.0.1",
4
+ "description": "Longzai Intelligence Cuts 注册表引擎",
5
+ "keywords": [
6
+ "cuts",
7
+ "engine",
8
+ "ledger",
9
+ "longzai-intelligence",
10
+ "registry"
11
+ ],
12
+ "license": "UNLICENSED",
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "type": "module",
17
+ "main": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js"
23
+ }
24
+ },
25
+ "scripts": {
26
+ "build": "lzi-builder",
27
+ "build:prod": "NODE_ENV=production bun run build",
28
+ "prepublishOnly": "bun run build:prod",
29
+ "typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
30
+ "typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
31
+ "typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
32
+ "typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
33
+ "lint": "oxlint && oxfmt --check",
34
+ "lint:fix": "oxlint --fix && oxfmt",
35
+ "test": "lzi-bun test",
36
+ "test:watch": "lzi-bun test --watch",
37
+ "test:coverage": "lzi-bun test --coverage",
38
+ "clean": "lzi-dev-tools clean"
39
+ },
40
+ "dependencies": {
41
+ "@longzai-intelligence-cuts/config": "0.0.1"
42
+ }
43
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.