@longzai-intelligence-tsconfig/core 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,108 @@
1
+ import "./rolldown-runtime-BqT_7tdF.js";
2
+ //#region src/types.d.ts
3
+ /**
4
+ * 违例严重级别
5
+ */
6
+ type Severity = 'error' | 'warn';
7
+ /**
8
+ * 单条违例
9
+ */
10
+ type Violation = {
11
+ /**
12
+ * 所属单元
13
+ *
14
+ * 单元相对仓根路径,模块根为 `.`,如 `packages/core`
15
+ */
16
+ unit: string;
17
+ /**
18
+ * 规则编号
19
+ *
20
+ * 取值 `R1` 到 `R6`,语义正本见仓 README 规则表
21
+ */
22
+ rule: string;
23
+ /**
24
+ * 严重级别
25
+ */
26
+ severity: Severity;
27
+ /**
28
+ * 相关文件
29
+ *
30
+ * 相对单元的路径,如 `tsconfig/node.json`;单元本身相关时与 `unit` 同值
31
+ */
32
+ file: string;
33
+ /**
34
+ * 违例描述与修复指引
35
+ */
36
+ message: string;
37
+ };
38
+ /**
39
+ * 检测汇总
40
+ */
41
+ type CheckSummary = {
42
+ /**
43
+ * 参与检测的单元数
44
+ *
45
+ * 含模块根
46
+ */
47
+ unitCount: number;
48
+ /**
49
+ * error 级违例数
50
+ */
51
+ errorCount: number;
52
+ /**
53
+ * warn 级违例数
54
+ */
55
+ warnCount: number;
56
+ };
57
+ /**
58
+ * 检测结果
59
+ */
60
+ type CheckOutcome = {
61
+ /**
62
+ * 全部违例,按检测顺序输出
63
+ */
64
+ violations: Violation[];
65
+ /**
66
+ * 汇总计数
67
+ */
68
+ summary: CheckSummary;
69
+ };
70
+ /**
71
+ * 引擎入参
72
+ */
73
+ type EngineInput = {
74
+ /**
75
+ * 目标仓根目录绝对路径
76
+ */
77
+ rootDir: string;
78
+ /**
79
+ * 解析后的就地配置,零配置时为空对象
80
+ */
81
+ config: import('@longzai-intelligence-tsconfig/config').LziTsconfigConfig;
82
+ };
83
+ //#endregion
84
+ //#region src/check-engine.service.d.ts
85
+ /**
86
+ * 执行形态检测
87
+ *
88
+ * 目标含 workspaces 声明时按模块根模式——模块根与全部子包单元逐一经 R1 到 R6 判定;无 workspaces 而实有 `tsconfig.json`
89
+ * 时按单包模式——目标整体作为一个子包单元判定,不套用模块根判据。`exclude` 声明的单元整体跳过
90
+ *
91
+ * @param input - 引擎入参
92
+ * @returns 检测结果与汇总
93
+ */
94
+ declare function runCheck(input: EngineInput): CheckOutcome;
95
+ //#endregion
96
+ //#region src/workspace-expansion.utils.d.ts
97
+ /**
98
+ * 按 workspaces 声明有界展开单元清单
99
+ *
100
+ * 逐模式按段行进——字面段直接下钻、`*` 段展开一层目录,走到模式末端时以实有 `package.json` 判定单元成立。排除 `!` 负向模式,结果去重升序
101
+ *
102
+ * @param rootDir - 仓根目录
103
+ * @param patterns - workspaces 声明的模式表
104
+ * @returns 单元相对路径表,如 `['apps/cli', 'packages/core']`
105
+ */
106
+ declare function expandWorkspaceUnits(rootDir: string, patterns: readonly string[]): string[];
107
+ //#endregion
108
+ export { type CheckOutcome, type CheckSummary, type EngineInput, type Severity, type Violation, expandWorkspaceUnits, runCheck };
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ import"./rolldown-runtime-BqT_7tdF.js";import{existsSync as e,readFileSync as t,readdirSync as n}from"node:fs";import{join as r}from"node:path";const i=/^(?:lzi-[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|oxlint|oxfmt)\.config\.ts$/,a=[`@longzai-intelligence-typescript/bun-config/`,`@longzai-intelligence-typescript/node-config/`],o=/\/presets\/[a-z0-9-]+-test\.json$/;function s(e){return i.test(e)}function c(e){try{return n(e,{withFileTypes:!0}).filter(e=>e.isFile()&&s(e.name)).map(e=>e.name).sort()}catch{return[]}}function l(e){try{return n(e,{withFileTypes:!0}).filter(e=>e.isFile()&&e.name.endsWith(`.json`)).map(e=>e.name).sort()}catch{return[]}}function u(e){return e===`app.json`?`app`:e===`node.json`?`node`:e===`test.json`?`test`:`other`}function d(e,t){let n=t.startsWith(`./`)?t.slice(2):t;return e.some(e=>{let t=e.startsWith(`./`)?e.slice(2):e;return t===n||new Bun.Glob(t).match(n)})}function f(e,t,n,r,i){e.push({unit:t,rule:n,severity:`error`,file:r,message:i})}function p(e,t,n,r,i){if(r!==`../`)return;let a=t.include;if(Array.isArray(a))for(let t of a)typeof t==`string`&&!t.startsWith(`../`)&&!t.startsWith(`/`)&&f(i,e,`R4`,n,`include 条目 ${t} 为 dot-style 相对基准,相对 tsconfig 目录解析悬空——改写为 ../ 起`)}function m(e,t,n,r,i,a){for(let o of c(n)){let n=i===`../`?`../${o}`:o;d(t,n)||f(a,e,`R4`,r,`include 未覆盖 ${r===`tsconfig.json`?o:`包根配置文件 ${o}`}——C6,补列 ${n} 或以通配一次列全`)}}function h(e,t,n,r,i,s){let c=t.extends,l=typeof c==`string`?[c]:Array.isArray(c)?c.filter(e=>typeof e==`string`):[];if(l.length===0){f(s,e,`R5`,n,`缺失 extends——须指向共享配置包预设`);return}for(let t of l)t.startsWith(`.`)?f(s,e,`R5`,n,`extends 指向仓内相对路径 ${t}——D4 禁任意本地 base,改指共享配置包预设`):a.some(e=>t.startsWith(e))||f(s,e,`R5`,n,`extends 指向共享配置包以外的 ${t}——D4,改指 bun-config 或 node-config 预设`);r===`node`&&!l.some(e=>e.endsWith(`/presets/node.json`))&&f(s,e,`R5`,n,`node 片须 extends node 预设`),r===`test`&&!l.some(e=>o.test(e))&&f(s,e,`R5`,n,`test 片须 extends 对应的 *-test 预设`),r===`app`&&i!==void 0&&!l.some(e=>e.endsWith(`/presets/${i}.json`))&&f(s,e,`R5`,n,`app 片须 extends 配置声明的 ${i} 预设`)}function g(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function _(e){return typeof e==`string`}function v(e){let t=[],n=!1;for(let r=0;r<e.length;r+=1){let i=e[r],a=e[r+1];if(n){t.push(i??``),i===`\\`?(a!==void 0&&t.push(a),r+=1):i===`"`&&(n=!1);continue}if(i===`"`){n=!0,t.push(i);continue}if(i===`/`&&a===`/`){for(;r<e.length&&e[r]!==`
2
+ `;)r+=1;t.push(`
3
+ `);continue}if(i===`/`&&a===`*`){for(r+=2;r<e.length&&(e[r]!==`*`||e[r+1]!==`/`);)r+=1;r+=1,t.push(` `);continue}t.push(i??``)}return t.join(``)}function y(e){try{let n=t(e,`utf8`),r=JSON.parse(v(n));return g(r)?r:null}catch{return null}}function b(e,t){if(e===null)return[];let n=e[t];return Array.isArray(n)?n.filter(_):[]}function x(e){if(!Array.isArray(e))return[];let t=[];for(let n of e)g(n)&&_(n.path)&&t.push(S(n.path));return t}function S(e){let t=e.startsWith(`./`)?e.slice(2):e;for(;t.endsWith(`/`)&&t.length>1;)t=t.slice(0,-1);return t}const C=/* @__PURE__ */ new Set([`node_modules`,`dist`,`.turbo`,`.git`,`.cache`,`out`,`build`,`coverage`,`.bun`,`.swc`]);function w(e,t){let n=/* @__PURE__ */ new Set;for(let r of t)r.startsWith(`!`)||T(e,r.split(`/`).filter(e=>e.length>0),0,``,n);return[...n].sort()}function T(t,i,a,o,s){if(a===i.length){e(r(t,`package.json`))&&s.add(o);return}let c=i[a];if(c===void 0)return;if(c===`*`){let e=[];try{e=n(t,{withFileTypes:!0}).filter(e=>e.isDirectory()&&!C.has(e.name)).map(e=>e.name)}catch{e=[]}for(let n of e)T(r(t,n),i,a+1,o===``?n:`${o}/${n}`,s);return}let l=r(t,c);e(l)&&T(l,i,a+1,o===``?c:`${o}/${c}`,s)}const E=[`app.json`,`node.json`,`test.json`];function D(e){let t=y(r(e,`package.json`));if(t===null)return[];let n=t.workspaces;return Array.isArray(n)?n.filter(_):g(n)&&Array.isArray(n.packages)?n.packages.filter(_):[]}function O(e){let t=y(r(e,`package.json`));if(t===null)return!1;let n=t.scripts;return g(n)&&_(n.typecheck)}function k(t,n,i,a){let o=r(t,`tsconfig.json`),s=e(o),c=O(t),u=i.packages?.[n];if(u?.singleTsconfig!==void 0){A(t,n,s,a);return}if(!c&&!s)return;if(c&&!s){f(a,n,`R1`,`package.json`,`声明 typecheck 脚本但缺失 tsconfig.json——C1,补建 solution 根与分片`);return}!c&&s&&f(a,n,`R1`,`package.json`,`实有 tsconfig.json 但缺失 typecheck 脚本——C3,补齐标准三件套脚本`);let d=l(r(t,`tsconfig`));for(let e of E)d.includes(e)||f(a,n,`R1`,`tsconfig/${e}`,`缺失分片 tsconfig/${e}——C2,照产品群标准模板补建`);let p=y(o);if(p===null){f(a,n,`R2`,`tsconfig.json`,`tsconfig.json 解析失败`);return}let m=Array.isArray(p.files)&&p.files.length===0,h=x(p.references);(!m||h.length===0||b(p,`include`).length>0)&&f(a,n,`R2`,`tsconfig.json`,`包根 tsconfig.json 须为 solution 形态——files 空数组、references 非空且不含 include,编译项归各分片`);let g=new Set(h);for(let e of d){let t=`tsconfig/${e}`;g.has(t)||f(a,n,`R3`,`tsconfig.json`,`分片 ${t} 未被根 tsconfig.json references 引用——C5,补引 { "path": "./${t}" }`)}for(let i of g)e(r(t,i))||f(a,n,`R3`,`tsconfig.json`,`references 指向不存在路径 ${i}——C5,移除悬空引用或补建目标`);j(t,n,d,u?.appPreset,a)}function A(e,t,n,i){if(!n){f(i,t,`R1`,`tsconfig.json`,`声明单一 tsconfig 豁免但缺失 tsconfig.json——ADR 0050 豁免以实有为前提`);return}let a=y(r(e,`tsconfig.json`));if(a===null){f(i,t,`R2`,`tsconfig.json`,`tsconfig.json 解析失败`);return}let o=b(a,`include`);p(t,a,`tsconfig.json`,``,i),m(t,o,e,`tsconfig.json`,``,i),h(t,a,`tsconfig.json`,`other`,void 0,i)}function j(e,t,n,i,a){for(let o of n){let n=y(r(e,`tsconfig`,o)),s=`tsconfig/${o}`;if(n===null){f(a,t,`R2`,s,`分片 ${s} 解析失败`);continue}p(t,n,s,`../`,a),o===`node.json`&&m(t,b(n,`include`),e,s,`../`,a),h(t,n,s,u(o),i,a)}}function M(t,n,i){let a=l(r(t,`tsconfig`));for(let e of a)e!==`node.json`&&f(i,`.`,`R3`,`tsconfig/${e}`,`模块根 tsconfig 目录仅允许 node.json——ADR 0011,发现 ${e}`);let o=r(t,`tsconfig.json`),s=r(t,`tsconfig`,`node.json`);if(e(o)?N(t,n,i):f(i,`.`,`R3`,`tsconfig.json`,`模块根缺失溶液根 tsconfig.json——ADR 0011,补建 files 空数组加 references 形态`),e(s)){let e=y(s);e===null?f(i,`.`,`R2`,`tsconfig/node.json`,`根 node 片解析失败`):(p(`.`,e,`tsconfig/node.json`,`../`,i),m(`.`,b(e,`include`),t,`tsconfig/node.json`,`../`,i),h(`.`,e,`tsconfig/node.json`,`node`,void 0,i))}else c(t).length>0&&f(i,`.`,`R4`,`tsconfig/node.json`,`模块根缺失 tsconfig/node.json,根配置文件零类型检查覆盖——C6,照标准模板补建`)}function N(t,n,i){let a=y(r(t,`tsconfig.json`));if(a===null){f(i,`.`,`R2`,`tsconfig.json`,`模块根 tsconfig.json 解析失败`);return}(!(Array.isArray(a.files)&&a.files.length===0)||b(a,`include`).length>0)&&f(i,`.`,`R2`,`tsconfig.json`,`模块根 tsconfig.json 须为 files 空数组且不含 include——编译项归子包分片`);let o=x(a.references),s=new Set(o);o.length===0&&f(i,`.`,`R2`,`tsconfig.json`,`模块根 tsconfig.json references 为空——须引用自身 node 片与子包`);for(let n of s)n!==`tsconfig/node.json`&&(n.startsWith(`tsconfig/`)?f(i,`.`,`R3`,`tsconfig.json`,`模块根 references 引用了 node 片以外的 ${n}——ADR 0011 只准引 node 片与子包`):e(r(t,n))||f(i,`.`,`R3`,`tsconfig.json`,`模块根 references 指向不存在路径 ${n}——C5`));e(r(t,`tsconfig`,`node.json`))&&!s.has(`tsconfig/node.json`)&&f(i,`.`,`R3`,`tsconfig.json`,`根 node 片未被模块根 references 引用——C5,补引 { "path": "./tsconfig/node.json" }`);for(let a of n)e(r(t,a,`tsconfig.json`))&&!s.has(a)&&!s.has(`${a}/tsconfig.json`)&&f(i,`.`,`R3`,`tsconfig.json`,`仓根溶液 references 缺引单元 ${a}——C5,补引 { "path": "./${a}" }`)}function P(e){let t=[],n=D(e.rootDir);if(n.length===0)return F(e,t);let i=w(e.rootDir,n),a=new Set(e.config.exclude??[]),o=i.filter(e=>!a.has(e));M(e.rootDir,o,t);for(let n of o)k(r(e.rootDir,n),n,e.config,t);return{violations:t,summary:{unitCount:o.length+1,errorCount:t.filter(e=>e.severity===`error`).length,warnCount:t.filter(e=>e.severity===`warn`).length}}}function F(t,n){return e(r(t.rootDir,`tsconfig.json`))?(k(t.rootDir,`.`,t.config,n),{violations:n,summary:{unitCount:1,errorCount:n.filter(e=>e.severity===`error`).length,warnCount:n.filter(e=>e.severity===`warn`).length}}):{violations:n,summary:{unitCount:0,errorCount:0,warnCount:0}}}export{w as expandWorkspaceUnits,P as runCheck};
@@ -0,0 +1 @@
1
+ import"node:module";export{};
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@longzai-intelligence-tsconfig/core",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "description": "Longzai Intelligence tsconfig 形态校验引擎",
6
+ "license": "UNLICENSED",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "type": "module",
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "build": "lzi-builder",
21
+ "build:prod": "NODE_ENV=production bun run build",
22
+ "prepublishOnly": "bun run build:prod",
23
+ "typecheck": "bun run typecheck:app && bun run typecheck:node && bun run typecheck:test",
24
+ "typecheck:app": "lzi-tsgo typecheck tsconfig/app.json",
25
+ "typecheck:node": "lzi-tsgo typecheck tsconfig/node.json",
26
+ "typecheck:test": "lzi-tsgo typecheck tsconfig/test.json",
27
+ "lint": "oxlint && oxfmt --check",
28
+ "lint:fix": "oxlint --fix && oxfmt",
29
+ "test": "bun test",
30
+ "test:watch": "bun test --watch",
31
+ "test:coverage": "bun test --coverage",
32
+ "clean": "lzi-dev-cli clean"
33
+ },
34
+ "dependencies": {
35
+ "@longzai-intelligence-tsconfig/config": "0.0.1"
36
+ }
37
+ }