@nudojs/core 1.0.0 → 1.1.0
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.md +9 -5
- package/dist/check-report-AtnAfY9U.d.ts +661 -0
- package/dist/chunk-MA2QEIYC.js +15030 -0
- package/dist/chunk-US532PZA.js +0 -0
- package/dist/chunk-ZUQXJRJL.js +4923 -0
- package/dist/exec.d.ts +2 -1
- package/dist/exec.js +170 -15
- package/dist/hof-types-tAeoYvzY.d.ts +368 -0
- package/dist/index-B7Lb8FU6.d.ts +726 -0
- package/dist/index.d.ts +685 -1103
- package/dist/index.js +1751 -5753
- package/dist/internal.d.ts +541 -0
- package/dist/internal.js +583 -0
- package/package.json +13 -8
- package/dist/chunk-RZOQL6PT.js +0 -7369
- package/dist/index-OfNo5qlN.d.ts +0 -761
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
import { File } from '@babel/types';
|
|
2
|
+
import { T as Term, A as Abs, P as PrimName, a as Pred, b as Phi, C as Confidence } from './hof-types-tAeoYvzY.js';
|
|
3
|
+
|
|
4
|
+
declare function resetParseSourceCache(): void;
|
|
5
|
+
declare function getParseSourceCacheSize(): number;
|
|
6
|
+
declare function parseSource(source: string, opts?: {
|
|
7
|
+
errorRecovery?: boolean;
|
|
8
|
+
keepTs?: boolean;
|
|
9
|
+
}): File;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 项(Term)防爆炸:深度/宽度阈值 → leak 为新鲜 var + 等式约束。
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
type LeakBudget = {
|
|
16
|
+
maxDepth: number;
|
|
17
|
+
maxNodes: number;
|
|
18
|
+
};
|
|
19
|
+
declare const defaultLeakBudget: LeakBudget;
|
|
20
|
+
declare function termDepth(t: Term): number;
|
|
21
|
+
declare function termNodes(t: Term): number;
|
|
22
|
+
declare function exceedsBudget(t: Term, budget?: LeakBudget): boolean;
|
|
23
|
+
declare function resetLeakCounter(): void;
|
|
24
|
+
/**
|
|
25
|
+
* 若项超预算,替换为新鲜变量,并返回附加等式 pred:fresh = originalTerm。
|
|
26
|
+
* 未超预算则原样返回。
|
|
27
|
+
*/
|
|
28
|
+
declare function maybeLeak(a: Abs, budget?: LeakBudget, label?: string): Abs;
|
|
29
|
+
/**
|
|
30
|
+
* 批量:在算术结果上应用 leak。
|
|
31
|
+
*/
|
|
32
|
+
declare function leakIfNeeded(a: Abs, budget?: LeakBudget, label?: string): Abs;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 侧车/依赖路径纯函数(leaf 模块:零依赖,供 load-deps-fp / interface /
|
|
36
|
+
* refine / LSP 共享单一定义——历史上三份内联拷贝已各自漂移过)。
|
|
37
|
+
*/
|
|
38
|
+
declare function normPath(p: string): string;
|
|
39
|
+
/** core 不引 path:相对 spec 纯字符串拼接(与 LSP resolve 对齐时双方 norm) */
|
|
40
|
+
declare function resolveDepPath(fromFile: string, spec: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* 是否落在 node_modules 下(相对/绝对/盘符形态统一)。
|
|
43
|
+
* autoBind 永不 ambient 加载 node_modules 侧车(§2.2)——必须在 normPath
|
|
44
|
+
* 之后判定,否则 `node_modules/pkg/x.js`(无前导 `/`)会绕过守卫。
|
|
45
|
+
*/
|
|
46
|
+
declare function isNodeModulesPath(p: string): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* 源文件的旁路侧车路径:.js/.mjs → 同名 .nudo.js;.ts/.mts → 同名 .nudo.ts。
|
|
49
|
+
* 其他扩展名(.cjs/.jsx/无扩展名…)不做替换,直接追加 .nudo.js——侧车约定
|
|
50
|
+
* 只覆盖四类入口;host loadModule 对不存在的路径返回 miss,自然无侧车来源。
|
|
51
|
+
*/
|
|
52
|
+
declare function sidecarPathOf(file: string): string;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 约束模板构建器(参数无关)。
|
|
56
|
+
*
|
|
57
|
+
* number().gt(0) → 占位项 self 上的 Pred
|
|
58
|
+
* number().int().ge(0) → 整数 + 下界
|
|
59
|
+
* string().min(1) → 非空串(长度)
|
|
60
|
+
* array(number().gt(0)) → 元素约束
|
|
61
|
+
* shape({ id: number().gt(0) }) → object 形状约束
|
|
62
|
+
* lit(42) → 字面量(prim + eq(self, 42))
|
|
63
|
+
* union(number().gt(0), lit(0)) → 成员析取(or / joinAbs)
|
|
64
|
+
* fn({ x: number().gt(0) }, number()) → 一等函数约束
|
|
65
|
+
* number().gt(0).shift(1) → 界平移(x>0 ⇒ x+n>1)
|
|
66
|
+
* instantiate("ms") → Pred ms > 0 / u.id > 0 ∧ …
|
|
67
|
+
*
|
|
68
|
+
* 在 *.nudo.js 里执行;不是 zod 绑定,是我们自己的运行时 API。
|
|
69
|
+
* 不需要 interface/type 语法——契约用 JS 表达式声明。
|
|
70
|
+
* 命名:litC/andC 与 term.ts 的 lit、pred.ts 的 and 消歧(桶导出不再冲突)。
|
|
71
|
+
* 侧车注入表仍以 `lit`/`and` 为键名(*.nudo.js 用户写法不变)。
|
|
72
|
+
*/
|
|
73
|
+
|
|
74
|
+
/** 模板占位项;instantiate 时换成真实参数名 */
|
|
75
|
+
declare const SELF = "__nudo_self__";
|
|
76
|
+
/** 字段访问项:u.id */
|
|
77
|
+
declare function getTerm(obj: Term, key: string): Term;
|
|
78
|
+
/** 长度项:length(u) */
|
|
79
|
+
declare function lenTerm(t: Term): Term;
|
|
80
|
+
type NudoField = {
|
|
81
|
+
constraint: NudoConstraint;
|
|
82
|
+
optional?: boolean;
|
|
83
|
+
};
|
|
84
|
+
type NudoConstraint = {
|
|
85
|
+
readonly __nudoConstraint: true;
|
|
86
|
+
readonly prim?: PrimName;
|
|
87
|
+
readonly preds: Pred[];
|
|
88
|
+
/** object 形状:字段名 → 嵌套约束 */
|
|
89
|
+
readonly fields?: Record<string, NudoField>;
|
|
90
|
+
/** array 元素约束 */
|
|
91
|
+
readonly element?: NudoConstraint;
|
|
92
|
+
/** 整数(number 链式 .int()) */
|
|
93
|
+
readonly int?: boolean;
|
|
94
|
+
/** 该约束整体可选(shape 字段用;不用 optional 以免与链式方法撞名) */
|
|
95
|
+
readonly isOptional?: boolean;
|
|
96
|
+
/** union 成员(析取):instantiate 为 or(...),entry Abs 为成员 join */
|
|
97
|
+
readonly members?: NudoConstraint[];
|
|
98
|
+
/** 一等函数约束(fn() 构建器产出) */
|
|
99
|
+
readonly fn?: NudoFnConstraint;
|
|
100
|
+
};
|
|
101
|
+
/** fn(params, returns?, { throws? }) 的一等函数约束形态 */
|
|
102
|
+
type NudoFnConstraint = {
|
|
103
|
+
params: Record<string, NudoConstraint>;
|
|
104
|
+
returns?: NudoConstraint;
|
|
105
|
+
throws?: NudoConstraint;
|
|
106
|
+
};
|
|
107
|
+
declare function isNudoConstraint(x: unknown): x is NudoConstraint;
|
|
108
|
+
/** 链式约束:不可变,每次 .gt() 返回新对象 */
|
|
109
|
+
type ConstraintBuilder = NudoConstraint & {
|
|
110
|
+
gt(n: number): ConstraintBuilder;
|
|
111
|
+
ge(n: number): ConstraintBuilder;
|
|
112
|
+
lt(n: number): ConstraintBuilder;
|
|
113
|
+
le(n: number): ConstraintBuilder;
|
|
114
|
+
/** number:要求整数 */
|
|
115
|
+
int(): ConstraintBuilder;
|
|
116
|
+
/** string:长度下界 */
|
|
117
|
+
min(n: number): ConstraintBuilder;
|
|
118
|
+
/** string:长度上界 */
|
|
119
|
+
max(n: number): ConstraintBuilder;
|
|
120
|
+
/** string:精确长度 */
|
|
121
|
+
length(n: number): ConstraintBuilder;
|
|
122
|
+
/**
|
|
123
|
+
* 界平移:term 平移 n 后重写常数界(x>0 ⇒ x+n>n)。
|
|
124
|
+
* 仅数值标量界链合法;length 界 / shape / array / union / fn → throw。
|
|
125
|
+
*/
|
|
126
|
+
shift(n: number): ConstraintBuilder;
|
|
127
|
+
/** 字段可选(仅在 shape 内有意义) */
|
|
128
|
+
optional(): ConstraintBuilder;
|
|
129
|
+
};
|
|
130
|
+
/**
|
|
131
|
+
* builder 与纯数据形态统一的 int 标志读取:纯数据看 `int === true`,
|
|
132
|
+
* builder(int 是链式方法)查 WeakSet。toPlainConstraint 归一化后只剩前者。
|
|
133
|
+
*/
|
|
134
|
+
declare function isIntFlag(c: NudoConstraint): boolean;
|
|
135
|
+
/** number() —— 约束 number 原语 + 后续链式界 */
|
|
136
|
+
declare function number(): ConstraintBuilder;
|
|
137
|
+
declare function string(): ConstraintBuilder;
|
|
138
|
+
declare function boolean(): ConstraintBuilder;
|
|
139
|
+
/** any() —— 无约束;formatConstraint / draft import 与显示同源 */
|
|
140
|
+
declare function any(): ConstraintBuilder;
|
|
141
|
+
/** array(item) —— 数组,元素满足 item;item 亦可为具体字面量(指令文法) */
|
|
142
|
+
declare function array(item: NudoConstraint | ConstraintBuilder | number | string | boolean | null | undefined): ConstraintBuilder;
|
|
143
|
+
/**
|
|
144
|
+
* object 形状约束(契约规范形状,无需 interface):
|
|
145
|
+
*
|
|
146
|
+
* shape({ id: number().gt(0), name: string() })
|
|
147
|
+
*
|
|
148
|
+
* 字段值亦可为具体字面量(指令文法)。
|
|
149
|
+
*/
|
|
150
|
+
declare function shape(fields: Record<string, NudoConstraint | ConstraintBuilder | number | string | boolean | null | undefined>): ConstraintBuilder;
|
|
151
|
+
/** litC(v):字面量契约——prim 按 v 类型、eq(self, v) pred 编码(不开新字段) */
|
|
152
|
+
declare function litC(v: number | string | boolean | null | undefined): ConstraintBuilder;
|
|
153
|
+
/** union(...cs):成员析取;instantiate 为 or(...),entry Abs 为成员 joinAbs。空参 throw */
|
|
154
|
+
declare function union(...cs: (NudoConstraint | ConstraintBuilder | number | string | boolean | null | undefined)[]): ConstraintBuilder;
|
|
155
|
+
/**
|
|
156
|
+
* fn(params, returns?, { throws? }):一等函数约束。
|
|
157
|
+
* Phase 1 只展示不执法:参数位 instantiate 恒真(pTrue),
|
|
158
|
+
* 逐参约束经 fnConstraintToEntryReqs 消费。
|
|
159
|
+
*/
|
|
160
|
+
declare function fn(params: Record<string, NudoConstraint | ConstraintBuilder | number | string | boolean | null | undefined>, returns?: NudoConstraint | ConstraintBuilder | number | string | boolean | null | undefined, opts?: {
|
|
161
|
+
throws?: NudoConstraint | ConstraintBuilder | number | string | boolean | null | undefined;
|
|
162
|
+
}): ConstraintBuilder;
|
|
163
|
+
/**
|
|
164
|
+
* andC(...cs):标量合取(Phase 1 最小实现)。
|
|
165
|
+
* prim 一致(缺省 prim 视为无 prim 约束、可与任意 prim 合并)→ preds 拼接;
|
|
166
|
+
* prim 不一致或任一含 fields/element/members/fn → throw。
|
|
167
|
+
*/
|
|
168
|
+
declare function andC(...cs: (NudoConstraint | ConstraintBuilder)[]): ConstraintBuilder;
|
|
169
|
+
/** partial(c):shape 全字段变可选;非 shape throw */
|
|
170
|
+
declare function partial(c: NudoConstraint | ConstraintBuilder): ConstraintBuilder;
|
|
171
|
+
/** pick(c, keys):shape 子形状(不存在的 key 忽略);非 shape throw */
|
|
172
|
+
declare function pick(c: NudoConstraint | ConstraintBuilder, keys: string[]): ConstraintBuilder;
|
|
173
|
+
/** omit(c, keys):shape 去字段;非 shape throw */
|
|
174
|
+
declare function omit(c: NudoConstraint | ConstraintBuilder, keys: string[]): ConstraintBuilder;
|
|
175
|
+
/** 把模板绑定到参数名:self → paramName;shape 展开为字段访问 Pred */
|
|
176
|
+
declare function instantiateConstraint(c: NudoConstraint, paramName: string): Pred;
|
|
177
|
+
/**
|
|
178
|
+
* 契约 → 函数入口 param Abs(infer/hover 用)。
|
|
179
|
+
* 标量:prim + pred;shape:obj slots 递归;union:成员 joinAbs;
|
|
180
|
+
* fn 形态:一等 fn shape(paramTypes/returnType),供 refine→error / 展示。
|
|
181
|
+
*/
|
|
182
|
+
declare function constraintToEntryAbs(c: NudoConstraint, paramName: string): Abs;
|
|
183
|
+
/**
|
|
184
|
+
* fn 约束 → 逐参约束表(interface 推导 / 入口签名消费)。
|
|
185
|
+
* 非 fn() 形态 throw——调用方应先判 c.fn。
|
|
186
|
+
*/
|
|
187
|
+
declare function fnConstraintToEntryReqs(c: NudoConstraint): Array<{
|
|
188
|
+
param: string;
|
|
189
|
+
constraint: NudoConstraint;
|
|
190
|
+
}>;
|
|
191
|
+
/**
|
|
192
|
+
* fn(..., { throws }) / throws 约束 → 申报的 throws 类型名。
|
|
193
|
+
* `"Error"` / `lit("Error")` / brand / union 成员 / `*` 全收。
|
|
194
|
+
*/
|
|
195
|
+
declare function throwConstraintToKinds(c: NudoConstraint | undefined): string[] | "*" | undefined;
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* 源内契约解析:唯一形态
|
|
199
|
+
*
|
|
200
|
+
* @nudo:contract <param> <constraint> 参数契约(挂入口 Abs,参与运算)
|
|
201
|
+
* @nudo:contract return <constraint> 返回契约(推断返回值 ⊭ 时红)
|
|
202
|
+
*
|
|
203
|
+
* 不叫 requires:那只是「校验挡板」。
|
|
204
|
+
* contract 表示约束是类型的一部分——Abs = shape × term × **pred** × conf,
|
|
205
|
+
* pred 会流入代数(x>0 ⇒ x+1>1),不只是调用点挡一下。
|
|
206
|
+
*
|
|
207
|
+
* constraint 来自 *.nudo.js 导出的模板(number().gt(0) 等),
|
|
208
|
+
* 由 /// @nudo:import { delay } from "./delay.nudo.js" 引入。
|
|
209
|
+
* 不支持写 `x > 0`(绑死参数名)。
|
|
210
|
+
* 不用 JSDoc @param/@return:那是类型注解语法。
|
|
211
|
+
*
|
|
212
|
+
* 侧车加载:Babel 语句级改写(多行 import / 注释与字符串里的同形文本不误伤)、
|
|
213
|
+
* 相对 .nudo.js/.nudo.ts 经 loadModule 递归求值、环检测、执行失败改诊断
|
|
214
|
+
* (nudo:interface-load / nudo:interface-cycle,不再静默吞错)。
|
|
215
|
+
*/
|
|
216
|
+
|
|
217
|
+
/** `/// @nudo:import { delay, percent } from "./delay.nudo.js"` */
|
|
218
|
+
type NamedImport = {
|
|
219
|
+
names: string[];
|
|
220
|
+
spec: string;
|
|
221
|
+
};
|
|
222
|
+
declare function extractNudoImports(source: string): NamedImport[];
|
|
223
|
+
/** refine 侧车加载诊断(severity 由消费方按 code 定档,形状对齐 Issue 子集) */
|
|
224
|
+
type RefineDiag = {
|
|
225
|
+
code: string;
|
|
226
|
+
message: string;
|
|
227
|
+
file?: string;
|
|
228
|
+
};
|
|
229
|
+
/** 设置诊断观察者(null 清除);缓冲照常累积,takeRefineDiags 取走 */
|
|
230
|
+
declare function setRefineDiagCollector(fn: ((d: RefineDiag) => void) | null): void;
|
|
231
|
+
/** 当前诊断累计序号(since 锚) */
|
|
232
|
+
declare function refineDiagCount(): number;
|
|
233
|
+
/** 取走已收集的诊断(收集即清空) */
|
|
234
|
+
declare function takeRefineDiags(): RefineDiag[];
|
|
235
|
+
/** 只取走 seq > since 的增量(工具面防窃取在途诊断;全量 take 的 since 版) */
|
|
236
|
+
declare function takeRefineDiagsSince(since: number): RefineDiag[];
|
|
237
|
+
/** 侧车模块错误:code ∈ nudo:interface-cycle | nudo:interface-load */
|
|
238
|
+
declare class NudoSidecarError extends Error {
|
|
239
|
+
readonly code: string;
|
|
240
|
+
constructor(code: string, message: string);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* 执行 *.nudo.js(真实 JS + 我们的构建器)。import/export 由 Babel 语句级
|
|
244
|
+
* 改写:多行 named import、注释/字符串里的同形文本不误伤;相对 .nudo 递归
|
|
245
|
+
* 求值;环 → throw NudoSidecarError。结果进 exec 缓存(依赖闭包内容指纹键)。
|
|
246
|
+
*/
|
|
247
|
+
declare function execNudoModule(src: string, opts?: RefineResolveOpts): Record<string, unknown>;
|
|
248
|
+
type RefineResolveOpts = {
|
|
249
|
+
loadModule?: (spec: string, fromFile: string) => string | undefined;
|
|
250
|
+
/** 侧车自身的路径(相对 spec 解析基准 + 环检测链起点) */
|
|
251
|
+
fromFile?: string;
|
|
252
|
+
};
|
|
253
|
+
declare function resetNudoModuleExecCache(): void;
|
|
254
|
+
/**
|
|
255
|
+
* 解析 `ms delay` / `n percent` → [param, Pred]
|
|
256
|
+
* 多条用 && 或换行连接。
|
|
257
|
+
* 同时保留原始 NudoConstraint(shape 字段检查用)。
|
|
258
|
+
*/
|
|
259
|
+
type RefineEntry = {
|
|
260
|
+
param: string;
|
|
261
|
+
pred: Pred;
|
|
262
|
+
constraint: NudoConstraint;
|
|
263
|
+
};
|
|
264
|
+
declare function extractRefinesFromSource(source: string, fnName: string, opts?: RefineResolveOpts): RefineEntry[];
|
|
265
|
+
/** refine 参数 → 带约束模板的下标表(shape 检查用) */
|
|
266
|
+
declare function refineToIndexedFull(source: string, fnName: string, paramNames: string[], opts?: RefineResolveOpts): Array<[number, RefineEntry]>;
|
|
267
|
+
/**
|
|
268
|
+
* 解析 `@nudo:contract return positive` → 返回契约。
|
|
269
|
+
* 返回 undefined = 无声明(不猜后置)。
|
|
270
|
+
*/
|
|
271
|
+
declare function extractRefineReturnFromSource(source: string, fnName: string, opts?: RefineResolveOpts): {
|
|
272
|
+
name: string;
|
|
273
|
+
constraint: NudoConstraint;
|
|
274
|
+
} | undefined;
|
|
275
|
+
/**
|
|
276
|
+
* 申报式抛错(declare throws — L2 豁免):
|
|
277
|
+
* @nudo:throws Error
|
|
278
|
+
* @nudo:throws Error, TypeError
|
|
279
|
+
* @nudo:throws *
|
|
280
|
+
* @nudo:case "neg" (0) !! throws → 申报任意 throw
|
|
281
|
+
* @nudo:case "neg" (0) !! throws Error → 申报 Error
|
|
282
|
+
*
|
|
283
|
+
* 与 refine 同扫函数前注释块。返回 `*` = 申报任意;数组 = 按名申报;
|
|
284
|
+
* undefined = 无申报(L2 照常执法)。
|
|
285
|
+
*/
|
|
286
|
+
declare function extractDeclaredThrows(source: string, fnName: string): string[] | "*" | undefined;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Interface 分层推导(design-refine-derivation §2.1/§2.2/§11 第 0 步):
|
|
290
|
+
*
|
|
291
|
+
* effectiveInterface(source, fnName) —— 手写 ∪ 侧车同名绑定 ∪ 生成段的
|
|
292
|
+
* 唯一读取口,来源标注(handwritten / generated / implicit)随值返回。
|
|
293
|
+
*
|
|
294
|
+
* 来源三层(合并序 handwritten > generated > implicit,§4/§11):
|
|
295
|
+
* - handwritten:源码 `@nudo:contract`/`@nudo:contract` 行(复用 refine.ts 的
|
|
296
|
+
* extractRefinesFromSource / extractRefineReturnFromSource)∪ 侧车同名**手写**
|
|
297
|
+
* fn() 绑定。同名同参取合取 and()(§2.1:侧车 x>0 + 源码 x>1 → 有效契约
|
|
298
|
+
* 取合取);常数界交叉矛盾(x>0 ∧ x<0)→ conflict 标记,由调用方报
|
|
299
|
+
* nudo:interface-conflict——本函数不 throw。
|
|
300
|
+
* - generated:侧车同名导出且声明上方注释块含 @generated 标记(emit 产物)。
|
|
301
|
+
* 与手写并存时整体降级忽略(手写为准;混排由 nudo:interface-name-clash /
|
|
302
|
+
* drift 在 emit/check 侧处理)。
|
|
303
|
+
* - implicit:无任何契约 → 返回 undefined(隐式推断是调用方的事)。
|
|
304
|
+
*
|
|
305
|
+
* 自动绑定边界(§2.2):只绑源文件**本地 named export**(re-export /
|
|
306
|
+
* export default / 私有名不绑);opts.autoBind === false 或侧车路径含
|
|
307
|
+
* /node_modules/ → 不 ambient 加载(只看源码 refine)。opts.projectDir
|
|
308
|
+
* 提供时,树外侧车不 ambient 绑定(host 从 findProjectConfig 下传)。
|
|
309
|
+
*
|
|
310
|
+
* 侧车绑定 Phase 1 只承诺 fn() 形态:非 fn 的标量/shape 绑定不消费,收集
|
|
311
|
+
* nudo:interface-load 诊断(后续 Phase 再放开单参形态)。
|
|
312
|
+
*
|
|
313
|
+
* 诊断走本文件独立 side-channel(先例 refine.ts 的 setRefineDiagCollector):
|
|
314
|
+
* 侧车加载/执行失败 → nudo:interface-cycle / nudo:interface-load。
|
|
315
|
+
*/
|
|
316
|
+
|
|
317
|
+
/** interface 推导诊断(severity 由消费方按 code 定档,形状对齐 Issue 子集) */
|
|
318
|
+
type InterfaceDiag = {
|
|
319
|
+
code: string;
|
|
320
|
+
message: string;
|
|
321
|
+
file?: string;
|
|
322
|
+
};
|
|
323
|
+
/** 设置诊断观察者(null 清除);缓冲照常累积,takeInterfaceDiags 取走 */
|
|
324
|
+
declare function setInterfaceDiagCollector(fn: ((d: InterfaceDiag) => void) | null): void;
|
|
325
|
+
/** 当前诊断累计序号(since 锚:工具面只排干自身探测产生的增量) */
|
|
326
|
+
declare function interfaceDiagCount(): number;
|
|
327
|
+
/** 取走已收集的诊断(收集即清空) */
|
|
328
|
+
declare function takeInterfaceDiags(): InterfaceDiag[];
|
|
329
|
+
/**
|
|
330
|
+
* 只取走 seq > since 的诊断(清空仅限增量)——LSP 长驻进程里 lens/打印/
|
|
331
|
+
* emit 工具用它排干**自身探测**产生的诊断,不窃取在途 validateText 待消费
|
|
332
|
+
* 的接口诊断(全量 take 曾在 await 窗口偷走 checkSource 的待收诊断)。
|
|
333
|
+
*/
|
|
334
|
+
declare function takeInterfaceDiagsSince(since: number): InterfaceDiag[];
|
|
335
|
+
/** 有效契约来源:手写(源码 refine ∪ 侧车手写绑定)> 生成段 > 隐式 */
|
|
336
|
+
type InterfaceSource = "handwritten" | "generated" | "implicit";
|
|
337
|
+
/**
|
|
338
|
+
* 源文件本地导出名表(侧车自动绑定边界):
|
|
339
|
+
* - ESM:`export function/const/let/var/class` 与本地 `export { x }` /
|
|
340
|
+
* `export { local as exported }`(按**导出名**绑定);
|
|
341
|
+
* - `export default function add` / `const add = …; export default add`:
|
|
342
|
+
* 按**本地名** `add` 绑定(侧车可 `export const add = fn(…)`);
|
|
343
|
+
* 同时登记 `"default"`,供侧车 `export default fn(…)` 对齐;
|
|
344
|
+
* - CJS(C4.3):`module.exports = { a, b }`、`module.exports.a = …`、
|
|
345
|
+
* `exports.a = …`、`module.exports = localFn`(登记 localFn 名)。
|
|
346
|
+
* 排除 re-export(`export {x} from` / `export *`)。
|
|
347
|
+
*/
|
|
348
|
+
declare function localNamedExports(source: string): Set<string>;
|
|
349
|
+
/**
|
|
350
|
+
* 侧车源码的生成段导出名:export 之前(跳过紧邻的 import/const 链)的注释
|
|
351
|
+
* 行含 `@generated` → 该名为 generated。组合式下行段(§5.3)形态为
|
|
352
|
+
* `import` + `@generated 头` + prelude + export;callsite 段则是头紧贴
|
|
353
|
+
* export。隔了其他代码行 / 无标记 / re-export 列表均不算。
|
|
354
|
+
*/
|
|
355
|
+
declare function generatedExportNames(sidecarSrc: string): Set<string>;
|
|
356
|
+
type EffectiveInterfaceOpts = RefineResolveOpts & {
|
|
357
|
+
/** false(或谓词返回 false)→ 不 ambient 加载侧车;默认 true */
|
|
358
|
+
autoBind?: boolean | ((sidecarPath: string) => boolean);
|
|
359
|
+
/**
|
|
360
|
+
* 项目根(host 从 findProjectConfig 下传)。提供时 ambient 绑定仅接受
|
|
361
|
+
* 树内侧车;树外 → 不加载。undefined = 不限(测试/脚本;node_modules 仍拦)。
|
|
362
|
+
*/
|
|
363
|
+
projectDir?: string;
|
|
364
|
+
};
|
|
365
|
+
type EffectiveInterface = {
|
|
366
|
+
fnName: string;
|
|
367
|
+
params: Array<{
|
|
368
|
+
param: string;
|
|
369
|
+
constraint: NudoConstraint;
|
|
370
|
+
}>;
|
|
371
|
+
returns?: {
|
|
372
|
+
constraint: NudoConstraint;
|
|
373
|
+
};
|
|
374
|
+
/** 申报式抛错(@nudo:throws / case !! throws / sidecar fn.throws) */
|
|
375
|
+
throws?: {
|
|
376
|
+
kinds: string[] | "*";
|
|
377
|
+
};
|
|
378
|
+
source: InterfaceSource;
|
|
379
|
+
/**
|
|
380
|
+
* 合取不可满足标记:params = 常数界交叉矛盾(或 prim 矛盾等 and() 不可
|
|
381
|
+
* 合取形态)的参数名;returns = 返回位同样不可满足。调用方报
|
|
382
|
+
* nudo:interface-conflict 并跳过对应位执法。
|
|
383
|
+
*/
|
|
384
|
+
conflict?: {
|
|
385
|
+
params: string[];
|
|
386
|
+
returns?: boolean;
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
/**
|
|
390
|
+
* 单点读取口:手写 ∪ 侧车同名 ∪ 生成段 → 有效契约(含来源标注)。
|
|
391
|
+
* 无任何契约 → undefined(implicit 由调用方处理)。
|
|
392
|
+
*/
|
|
393
|
+
declare function effectiveInterface(source: string, fnName: string, opts?: EffectiveInterfaceOpts): EffectiveInterface | undefined;
|
|
394
|
+
/**
|
|
395
|
+
* 侧车及递归 .nudo 依赖闭包的内容指纹:`${hashSource(侧车)}|路径=hash,…`。
|
|
396
|
+
* 无 loadModule / autoBind 关闭 / node_modules / loadModule miss → undefined
|
|
397
|
+
* (无侧车影响即无需指纹)。闭包截断 → `trunc:` 前缀,键不可信,调用方
|
|
398
|
+
* fail-open(参照 loadModuleDepsFingerprint 的 truncated 契约)。
|
|
399
|
+
*/
|
|
400
|
+
declare function sidecarClosureFingerprint(fromFile: string, opts: EffectiveInterfaceOpts): string | undefined;
|
|
401
|
+
/** 组合式显示:重建构建器调用形态(number().gt(0) / union(…) / fn(…)) */
|
|
402
|
+
declare function formatConstraint(c: NudoConstraint): string;
|
|
403
|
+
/** EffectiveInterface → 契约展示串(与 CLI interface 打印同口径,不含函数名) */
|
|
404
|
+
declare function formatEffectiveInterfaceDisplay(eff: EffectiveInterface): string;
|
|
405
|
+
/** CodeLens / hover 首行标题(design-refine-derivation §8):`● interface / <source>` */
|
|
406
|
+
declare function formatInterfaceTierLine(source: InterfaceSource): string;
|
|
407
|
+
type InterfaceTierInfo = {
|
|
408
|
+
source: InterfaceSource;
|
|
409
|
+
/** handwritten/generated 时的契约展示;implicit 为 undefined */
|
|
410
|
+
display?: string;
|
|
411
|
+
};
|
|
412
|
+
type InterfaceTierOpts = EffectiveInterfaceOpts;
|
|
413
|
+
/**
|
|
414
|
+
* interface 档单一读取口(A7):CodeLens `● interface`、hover、inlay、
|
|
415
|
+
* semantic tokens 共用本函数,保证「同源」。
|
|
416
|
+
*
|
|
417
|
+
* 与 computeInterfaceLenses 同口径:仅源文件 **本地 named export** 进档;
|
|
418
|
+
* 私有名 / 非导出 → undefined(不进 interface 档,不假装 implicit 契约)。
|
|
419
|
+
*/
|
|
420
|
+
declare function interfaceTierOf(source: string, fnName: string, fromFile: string, opts?: InterfaceTierOpts): InterfaceTierInfo | undefined;
|
|
421
|
+
/** interfaceTierOf 的来源投影;非导出 → undefined */
|
|
422
|
+
declare function interfaceSourceOf(source: string, fnName: string, fromFile: string, opts?: InterfaceTierOpts): InterfaceSource | undefined;
|
|
423
|
+
|
|
424
|
+
type LoadDepsFingerprint = {
|
|
425
|
+
fp: string;
|
|
426
|
+
paths: string[];
|
|
427
|
+
/**
|
|
428
|
+
* path + loadModule-resolved content(miss → null)。调用方(磁盘缓存键)
|
|
429
|
+
* 必须优先用这里的 content,不得回读磁盘——否则 buffer-aware loadModule
|
|
430
|
+
* 与磁盘不一致时键会分叉。
|
|
431
|
+
*/
|
|
432
|
+
contents: Array<{
|
|
433
|
+
path: string;
|
|
434
|
+
content: string | null;
|
|
435
|
+
}>;
|
|
436
|
+
/** BFS 撞到节点上限:剩余 dep 未进指纹,键不可信 */
|
|
437
|
+
truncated: boolean;
|
|
438
|
+
};
|
|
439
|
+
/**
|
|
440
|
+
* All string module specs that analysis may resolve through loadModule.
|
|
441
|
+
* Regex over-approximates (may hit comments) — extra dep fingerprint is safe
|
|
442
|
+
* (more misses, never a stale hit).
|
|
443
|
+
*/
|
|
444
|
+
declare function extractAllLoadSpecs(source: string): string[];
|
|
445
|
+
/**
|
|
446
|
+
* 源里指向其他侧车的相对 spec(`.nudo.js`/`.nudo.ts`)。regex 过近似安全:
|
|
447
|
+
* 多算的 dep 只带来额外 miss,绝不产生陈旧命中。LSP 隐式依赖登记共用。
|
|
448
|
+
*/
|
|
449
|
+
declare function sidecarSpecsOf(source: string): string[];
|
|
450
|
+
/**
|
|
451
|
+
* Fingerprint every loadModule-reachable dep (not only `*.nudo.js`), including
|
|
452
|
+
* one hop of transitive specs from each dep source — plus the autoBind 侧车
|
|
453
|
+
* 闭包(`sidecar:` 前缀条目)。
|
|
454
|
+
*
|
|
455
|
+
* 侧车吸收范围 = fromFile 自身 **与每一个成功加载的依赖文件**的旁路侧车及其
|
|
456
|
+
* 递归 .nudo 依赖:跨文件被调(scan.ts checkExternalCall)会按定义文件路径
|
|
457
|
+
* ambient 绑定其侧车,依赖侧车内容影响调用方报告——不进指纹则编辑后 memo
|
|
458
|
+
* 陈旧命中(错诊断)。侧车 loadModule miss(无侧车文件)→ 不加任何条目。
|
|
459
|
+
*
|
|
460
|
+
* 注意:本扩展对 autoBind=false 与 /node_modules/ 均**不** gate(刻意过近似,
|
|
461
|
+
* 只过度失效、绝不陈旧命中——安全方向);ambient 生效边界由
|
|
462
|
+
* interface.ts 的 sidecarClosureFingerprint 负责,两者职责不同。
|
|
463
|
+
*/
|
|
464
|
+
declare function loadModuleDepsFingerprint(source: string, loadModule: (spec: string, fromFile: string) => string | undefined, fromFile: string): LoadDepsFingerprint;
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* 约束诊断:检查调用点实参是否满足函数的前置约束 / 参数 shape。
|
|
468
|
+
* 输出可行动的建议,而不是 TS 式「类型不匹配」。
|
|
469
|
+
*/
|
|
470
|
+
|
|
471
|
+
type Diagnostic = {
|
|
472
|
+
severity: "error" | "warning" | "info";
|
|
473
|
+
code: string;
|
|
474
|
+
message: string;
|
|
475
|
+
suggestion?: string;
|
|
476
|
+
fn?: string;
|
|
477
|
+
argIndex?: number;
|
|
478
|
+
};
|
|
479
|
+
/**
|
|
480
|
+
* 检查实参是否满足「期望约束」。
|
|
481
|
+
* expect: 相对参数 term 的 pred,例如 term > 0
|
|
482
|
+
* arg: 实际实参 Abs
|
|
483
|
+
*/
|
|
484
|
+
declare function checkArg(arg: Abs, expect: Pred | undefined, phi?: Phi): Diagnostic | undefined;
|
|
485
|
+
/**
|
|
486
|
+
* 对一次函数调用做诊断:实参 shape + 约束。
|
|
487
|
+
*/
|
|
488
|
+
declare function checkCall(source: string, fnName: string, args: Abs[], phi?: Phi): Diagnostic[];
|
|
489
|
+
declare function formatDiagnostics(diags: Diagnostic[]): string;
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* check 报告面:数据模型 + 渲染/序列化。
|
|
493
|
+
*
|
|
494
|
+
* 分析在 check.ts(Abs 优先的 Nudo 原生诊断),这里只投影:
|
|
495
|
+
* - formatCheckReport → 人类可读文本
|
|
496
|
+
* - serializeCheckJson → `nudo check --json` 稳定契约(CI / Agent,v1)
|
|
497
|
+
* - formatGithubAnnotations → PR 行内 `::error` / `::warning`(GHA)
|
|
498
|
+
* - formatGitlabCodeQuality → GitLab Code Quality JSON 数组
|
|
499
|
+
*/
|
|
500
|
+
|
|
501
|
+
/** 无损函数签名(类型即计算) */
|
|
502
|
+
type NudoSig = {
|
|
503
|
+
name: string;
|
|
504
|
+
params: string[];
|
|
505
|
+
/** 形参类型展示(入口无约束 = any) */
|
|
506
|
+
paramTypes?: string[];
|
|
507
|
+
/** 符号 Abs 本体 */
|
|
508
|
+
abs: Abs;
|
|
509
|
+
/** formatAbs 单行 */
|
|
510
|
+
display: string;
|
|
511
|
+
/** formatAbsMultiline */
|
|
512
|
+
detail: string;
|
|
513
|
+
conf: Confidence;
|
|
514
|
+
/** throws 域展示(如 TypeError);省略 = 无 may-throw */
|
|
515
|
+
throws?: string;
|
|
516
|
+
/** 模块边界入口(export / default / CJS exports) */
|
|
517
|
+
entry?: boolean;
|
|
518
|
+
};
|
|
519
|
+
type CheckIssue = Diagnostic & {
|
|
520
|
+
fn?: string;
|
|
521
|
+
line?: number;
|
|
522
|
+
column?: number;
|
|
523
|
+
/** 实参 / 实际值的 Abs 展示 */
|
|
524
|
+
actual?: string;
|
|
525
|
+
/** 期望约束(Pred 或 Abs 展示) */
|
|
526
|
+
expected?: string;
|
|
527
|
+
/**
|
|
528
|
+
* AI1:结构化下一步(additive)。agent 优先消费 `actions`,
|
|
529
|
+
* 不必解析 `suggestion` 散文;`command` 可直接执行。
|
|
530
|
+
*/
|
|
531
|
+
actions?: CheckAction[];
|
|
532
|
+
};
|
|
533
|
+
/** 结构化修复动作(AI1;稳定枚举,只增不改语义) */
|
|
534
|
+
type CheckAction = {
|
|
535
|
+
/** draft=生成侧车草稿 · relax=放宽契约 · callsite=改实参 · assume/mock/emit/ignore=辅助 */
|
|
536
|
+
kind: "draft" | "relax" | "callsite" | "assume" | "mock" | "emit" | "ignore-throws" | "info";
|
|
537
|
+
/** agent 可执行命令(无则只读 label/hint) */
|
|
538
|
+
command?: string;
|
|
539
|
+
/** 一行说明(与 suggestion 同源或更短) */
|
|
540
|
+
label: string;
|
|
541
|
+
/** 可选:目标 Pred / 字段名等,供程序化改写 */
|
|
542
|
+
hint?: string;
|
|
543
|
+
};
|
|
544
|
+
type CheckReport = {
|
|
545
|
+
file: string;
|
|
546
|
+
issues: CheckIssue[];
|
|
547
|
+
/** 有 error 则 CI 应失败 */
|
|
548
|
+
ok: boolean;
|
|
549
|
+
/** Abs 优先的签名表(替代 TS 式 display-only) */
|
|
550
|
+
signatures: NudoSig[];
|
|
551
|
+
summary: {
|
|
552
|
+
errors: number;
|
|
553
|
+
warnings: number;
|
|
554
|
+
infos: number;
|
|
555
|
+
functions: number;
|
|
556
|
+
};
|
|
557
|
+
/**
|
|
558
|
+
* A2 预算/截断可观测(additive)。`truncated=true` 时部分结果可能已
|
|
559
|
+
* widen 成 unknown——不是契约失败,是引擎预算。
|
|
560
|
+
*/
|
|
561
|
+
budget?: {
|
|
562
|
+
truncated: boolean;
|
|
563
|
+
callTruncated: boolean;
|
|
564
|
+
forkTruncated: boolean;
|
|
565
|
+
calls: number;
|
|
566
|
+
maxCalls: number;
|
|
567
|
+
forks: number;
|
|
568
|
+
maxForks: number;
|
|
569
|
+
};
|
|
570
|
+
};
|
|
571
|
+
/**
|
|
572
|
+
* `nudo check --json` 稳定契约(供 CI / Agent)。
|
|
573
|
+
* 字段只增不改语义;Abs 以 formatAbs 字符串给出,不序列化内部 shape 图。
|
|
574
|
+
*/
|
|
575
|
+
type CheckJson = {
|
|
576
|
+
version: 1;
|
|
577
|
+
file: string;
|
|
578
|
+
ok: boolean;
|
|
579
|
+
summary: CheckReport["summary"];
|
|
580
|
+
signatures: Array<{
|
|
581
|
+
name: string;
|
|
582
|
+
params: string[];
|
|
583
|
+
paramTypes?: string[];
|
|
584
|
+
display: string;
|
|
585
|
+
detail: string;
|
|
586
|
+
conf: string;
|
|
587
|
+
abs: string;
|
|
588
|
+
throws?: string;
|
|
589
|
+
entry?: boolean;
|
|
590
|
+
}>;
|
|
591
|
+
issues: Array<{
|
|
592
|
+
severity: string;
|
|
593
|
+
code: string;
|
|
594
|
+
message: string;
|
|
595
|
+
fn?: string;
|
|
596
|
+
line?: number;
|
|
597
|
+
column?: number;
|
|
598
|
+
actual?: string;
|
|
599
|
+
expected?: string;
|
|
600
|
+
suggestion?: string;
|
|
601
|
+
/** AI1:结构化 next-action(只增字段) */
|
|
602
|
+
actions?: CheckAction[];
|
|
603
|
+
}>;
|
|
604
|
+
/** A2:预算用量 / 是否截断(additive) */
|
|
605
|
+
budget?: CheckReport["budget"];
|
|
606
|
+
};
|
|
607
|
+
/** 诊断码 → 结构化动作(AI1);未知码给 info 提示 */
|
|
608
|
+
declare function actionsForIssue(i: {
|
|
609
|
+
code: string;
|
|
610
|
+
expected?: string;
|
|
611
|
+
suggestion?: string;
|
|
612
|
+
fn?: string;
|
|
613
|
+
}): CheckAction[];
|
|
614
|
+
/** 多文件 `check --json` 信封(CI / monorepo)。单文件仍输出裸 CheckJson。 */
|
|
615
|
+
type CheckJsonMulti = {
|
|
616
|
+
version: 1;
|
|
617
|
+
kind: "multi";
|
|
618
|
+
ok: boolean;
|
|
619
|
+
summary: CheckReport["summary"] & {
|
|
620
|
+
files: number;
|
|
621
|
+
budgetTruncated?: boolean;
|
|
622
|
+
};
|
|
623
|
+
budget?: CheckReport["budget"];
|
|
624
|
+
reports: CheckJson[];
|
|
625
|
+
};
|
|
626
|
+
declare function serializeCheckJson(r: CheckReport): CheckJson;
|
|
627
|
+
/** 多文件信封:汇总 summary,`ok` = 全部文件 ok。 */
|
|
628
|
+
declare function serializeCheckJsonMulti(reports: CheckJson[]): CheckJsonMulti;
|
|
629
|
+
/**
|
|
630
|
+
* Nudo 原生报告:Abs 签名表 + actual ⊭ expected。
|
|
631
|
+
* 不是 tsc 输出的换皮。
|
|
632
|
+
*/
|
|
633
|
+
declare function formatCheckReport(r: CheckReport, opts?: {
|
|
634
|
+
verbose?: boolean;
|
|
635
|
+
}): string;
|
|
636
|
+
/**
|
|
637
|
+
* GitHub Actions 行内注解(PR Files changed 红/黄标)。
|
|
638
|
+
* 协议:`::error file=…,line=…,col=…,title=…::message`
|
|
639
|
+
* 详见 https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
|
|
640
|
+
*/
|
|
641
|
+
declare function formatGithubAnnotations(r: CheckReport, opts?: {
|
|
642
|
+
workspaceRoot?: string;
|
|
643
|
+
}): string;
|
|
644
|
+
type GitlabCodeQualityIssue = {
|
|
645
|
+
description: string;
|
|
646
|
+
check_name: string;
|
|
647
|
+
fingerprint: string;
|
|
648
|
+
severity: "major" | "minor" | "info" | "blocker" | "critical";
|
|
649
|
+
location: {
|
|
650
|
+
path: string;
|
|
651
|
+
lines: {
|
|
652
|
+
begin: number;
|
|
653
|
+
};
|
|
654
|
+
};
|
|
655
|
+
};
|
|
656
|
+
/** GitLab Code Quality 报告数组(`--gitlab`;可写 gl-code-quality-report.json) */
|
|
657
|
+
declare function formatGitlabCodeQuality(r: CheckReport, opts?: {
|
|
658
|
+
workspaceRoot?: string;
|
|
659
|
+
}): GitlabCodeQualityIssue[];
|
|
660
|
+
|
|
661
|
+
export { fn as $, NudoSidecarError as A, type NudoSig as B, type CheckIssue as C, type Diagnostic as D, type EffectiveInterfaceOpts as E, type RefineEntry as F, type GitlabCodeQualityIssue as G, type RefineResolveOpts as H, type InterfaceSource as I, actionsForIssue as J, andC as K, type LeakBudget as L, any as M, type NudoConstraint as N, array as O, boolean as P, checkArg as Q, type RefineDiag as R, SELF as S, checkCall as T, constraintToEntryAbs as U, effectiveInterface as V, execNudoModule as W, extractDeclaredThrows as X, extractNudoImports as Y, extractRefineReturnFromSource as Z, extractRefinesFromSource as _, type InterfaceTierOpts as a, fnConstraintToEntryReqs as a0, formatCheckReport as a1, formatConstraint as a2, formatDiagnostics as a3, formatEffectiveInterfaceDisplay as a4, formatGithubAnnotations as a5, formatGitlabCodeQuality as a6, formatInterfaceTierLine as a7, generatedExportNames as a8, getParseSourceCacheSize as a9, string as aA, takeInterfaceDiags as aB, takeInterfaceDiagsSince as aC, takeRefineDiags as aD, takeRefineDiagsSince as aE, throwConstraintToKinds as aF, union as aG, getTerm as aa, instantiateConstraint as ab, interfaceDiagCount as ac, interfaceSourceOf as ad, interfaceTierOf as ae, isIntFlag as af, isNodeModulesPath as ag, isNudoConstraint as ah, lenTerm as ai, litC as aj, localNamedExports as ak, number as al, omit as am, partial as an, pick as ao, refineDiagCount as ap, refineToIndexedFull as aq, resetNudoModuleExecCache as ar, resetParseSourceCache as as, serializeCheckJson as at, serializeCheckJsonMulti as au, setInterfaceDiagCollector as av, setRefineDiagCollector as aw, shape as ax, sidecarClosureFingerprint as ay, sidecarPathOf as az, type LoadDepsFingerprint as b, extractAllLoadSpecs as c, defaultLeakBudget as d, exceedsBudget as e, loadModuleDepsFingerprint as f, resolveDepPath as g, termNodes as h, type CheckReport as i, type CheckAction as j, type CheckJson as k, leakIfNeeded as l, maybeLeak as m, normPath as n, type CheckJsonMulti as o, parseSource as p, type ConstraintBuilder as q, resetLeakCounter as r, sidecarSpecsOf as s, termDepth as t, type EffectiveInterface as u, type InterfaceDiag as v, type InterfaceTierInfo as w, type NamedImport as x, type NudoField as y, type NudoFnConstraint as z };
|