@nudojs/service 1.0.1 → 3.0.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/dist/{chunk-2VHITMTM.js → chunk-ADFCZP72.js} +70 -2
- package/dist/config-Cqj8zeZH.d.ts +117 -0
- package/dist/evaluator/evaluator-api.d.ts +3 -12
- package/dist/evaluator/evaluator-api.js +3 -1
- package/dist/index.d.ts +436 -18
- package/dist/index.js +2046 -237
- package/package.json +5 -5
- package/dist/config-NqDRWWpn.d.ts +0 -68
|
@@ -306,7 +306,10 @@ async function importPathEnv(resolvedPath, mtimeMs) {
|
|
|
306
306
|
}
|
|
307
307
|
if (mod && typeof mod.defineEnv === "function") {
|
|
308
308
|
pathEnvCache.set(cacheKey, mod.defineEnv);
|
|
309
|
-
pathEnvByPath.set(resolvedPath,
|
|
309
|
+
pathEnvByPath.set(resolvedPath, {
|
|
310
|
+
factory: mod.defineEnv,
|
|
311
|
+
mtimeMs
|
|
312
|
+
});
|
|
310
313
|
}
|
|
311
314
|
}
|
|
312
315
|
function lookupPathEnv(name) {
|
|
@@ -314,10 +317,26 @@ function lookupPathEnv(name) {
|
|
|
314
317
|
const candidates = name.startsWith("/") ? [name] : [name, ...[...pathEnvBaseDirs].map((d) => resolvePath(d, name))];
|
|
315
318
|
for (const candidate of candidates) {
|
|
316
319
|
const hit = pathEnvByPath.get(candidate);
|
|
317
|
-
if (hit)
|
|
320
|
+
if (!hit) continue;
|
|
321
|
+
try {
|
|
322
|
+
const { mtimeMs } = statSync(candidate);
|
|
323
|
+
if (mtimeMs !== hit.mtimeMs) {
|
|
324
|
+
pathEnvByPath.delete(candidate);
|
|
325
|
+
return void 0;
|
|
326
|
+
}
|
|
327
|
+
} catch {
|
|
328
|
+
pathEnvByPath.delete(candidate);
|
|
329
|
+
return void 0;
|
|
330
|
+
}
|
|
331
|
+
return hit.factory;
|
|
318
332
|
}
|
|
319
333
|
return void 0;
|
|
320
334
|
}
|
|
335
|
+
function clearPathEnvCaches() {
|
|
336
|
+
pathEnvCache.clear();
|
|
337
|
+
pathEnvByPath.clear();
|
|
338
|
+
pathEnvBaseDirs.clear();
|
|
339
|
+
}
|
|
321
340
|
async function preloadPathEnvs(envNames, baseDir) {
|
|
322
341
|
pathEnvBaseDirs.add(baseDir);
|
|
323
342
|
for (const name of envNames) {
|
|
@@ -359,6 +378,51 @@ function loadEnvs(envNames, globalEnv) {
|
|
|
359
378
|
// src/evaluator/config.ts
|
|
360
379
|
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
361
380
|
import { resolve, dirname, relative, sep } from "path";
|
|
381
|
+
var DEFAULT_ANALYSIS_EXCLUDE = [
|
|
382
|
+
"**/node_modules/**",
|
|
383
|
+
"**/dist/**",
|
|
384
|
+
"**/coverage/**"
|
|
385
|
+
];
|
|
386
|
+
var DEFAULT_ANALYSIS_MODE = "exports";
|
|
387
|
+
function toStringArray(raw, fallback) {
|
|
388
|
+
if (raw === void 0) return fallback;
|
|
389
|
+
const arr = Array.isArray(raw) ? raw : [raw];
|
|
390
|
+
const out = arr.filter((s) => typeof s === "string" && s.length > 0);
|
|
391
|
+
return out.length > 0 ? out : fallback;
|
|
392
|
+
}
|
|
393
|
+
function analysisConfig(config) {
|
|
394
|
+
const raw = config?.analysis;
|
|
395
|
+
const modeRaw = raw?.mode;
|
|
396
|
+
const mode = modeRaw === "exports" || modeRaw === "all" || modeRaw === "directives" ? modeRaw : DEFAULT_ANALYSIS_MODE;
|
|
397
|
+
const diagRaw = raw?.diagnostics;
|
|
398
|
+
const diagnostics = diagRaw === "off" || diagRaw === "errors" || diagRaw === "default" || diagRaw === "verbose" ? diagRaw : mode === "directives" ? "errors" : "default";
|
|
399
|
+
const budgetRaw = raw?.callSiteBudget;
|
|
400
|
+
const callSiteBudget = typeof budgetRaw === "number" && Number.isFinite(budgetRaw) && budgetRaw >= 1 ? Math.min(Math.floor(budgetRaw), 64) : 3;
|
|
401
|
+
return {
|
|
402
|
+
// include 空数组 = 不过滤(与「省略」同义)
|
|
403
|
+
include: toStringArray(raw?.include, []),
|
|
404
|
+
// exclude 空数组回落默认安全列表,避免误关 node_modules 保护
|
|
405
|
+
exclude: toStringArray(raw?.exclude, DEFAULT_ANALYSIS_EXCLUDE),
|
|
406
|
+
mode,
|
|
407
|
+
diagnostics,
|
|
408
|
+
callSiteBudget,
|
|
409
|
+
evalMissingSlot: raw?.evalMissingSlot === "warning" ? "warning" : "off"
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
function diskCacheRoot(config, projectDir) {
|
|
413
|
+
const raw = config?.cache;
|
|
414
|
+
if (raw === false) return void 0;
|
|
415
|
+
if (typeof raw === "string" && raw.length > 0) {
|
|
416
|
+
return projectDir ? resolve(projectDir, raw) : raw;
|
|
417
|
+
}
|
|
418
|
+
if (raw === true) {
|
|
419
|
+
return projectDir ? resolve(projectDir, ".nudo/cache") : void 0;
|
|
420
|
+
}
|
|
421
|
+
const env = process.env.NUDO_CACHE_DIR;
|
|
422
|
+
if (env === "off" || env === "0") return void 0;
|
|
423
|
+
if (env && env.length > 0) return env;
|
|
424
|
+
return void 0;
|
|
425
|
+
}
|
|
362
426
|
function interfaceConfig(config) {
|
|
363
427
|
const raw = config?.interface?.emit;
|
|
364
428
|
const emit = raw === void 0 ? [] : Array.isArray(raw) ? raw.filter((s) => typeof s === "string" && s.length > 0) : typeof raw === "string" && raw.length > 0 ? [raw] : [];
|
|
@@ -474,9 +538,13 @@ function resolveNpmNudo(source, fromDir) {
|
|
|
474
538
|
}
|
|
475
539
|
|
|
476
540
|
export {
|
|
541
|
+
clearPathEnvCaches,
|
|
477
542
|
preloadPathEnvs,
|
|
478
543
|
loadEnvsAsync,
|
|
479
544
|
loadEnvs,
|
|
545
|
+
DEFAULT_ANALYSIS_MODE,
|
|
546
|
+
analysisConfig,
|
|
547
|
+
diskCacheRoot,
|
|
480
548
|
interfaceConfig,
|
|
481
549
|
matchesEmitAllowlist,
|
|
482
550
|
findProjectConfig,
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { Abs, Environment } from '@nudojs/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 调用点记录(CallRecord)。Abs 唯一真理源。
|
|
5
|
+
* argAbs/resultAbs/throwsAbs 必填;展示/外延在 CaseResult 边界再桥。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
type CallRecord = {
|
|
9
|
+
fnName: string;
|
|
10
|
+
/** 无损参数 Abs */
|
|
11
|
+
argAbs: Abs[];
|
|
12
|
+
/** 无损结果 Abs(threw 时为 never) */
|
|
13
|
+
resultAbs: Abs;
|
|
14
|
+
/** 无损抛出值 Abs(未抛为 never) */
|
|
15
|
+
throwsAbs: Abs;
|
|
16
|
+
/** Line-relative. Per-fn cache replay shifts this by lineDelta — if you
|
|
17
|
+
* add another position field (callee loc, arg loc), extend
|
|
18
|
+
* shiftCallRecordLines in analyzer.ts in the same change. */
|
|
19
|
+
callLoc?: {
|
|
20
|
+
line: number;
|
|
21
|
+
column: number;
|
|
22
|
+
};
|
|
23
|
+
targetModule?: string;
|
|
24
|
+
targetExport?: string;
|
|
25
|
+
/** export names the same function value was re-exported under after its
|
|
26
|
+
* defining module (barrel `index.js`, CJS forwarding shims); usage-site
|
|
27
|
+
* records stay name-matchable against them */
|
|
28
|
+
targetAliases?: string[];
|
|
29
|
+
/** module whose evaluation created the function value (definition site). */
|
|
30
|
+
fnModule?: string;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type LoadedEnv = {
|
|
34
|
+
/** Abs 原生模块导出(B 路径 / Abs 模块图) */
|
|
35
|
+
modules: Record<string, Record<string, Abs>>;
|
|
36
|
+
globals: Record<string, Abs>;
|
|
37
|
+
};
|
|
38
|
+
/** Host cache-clear hooks (CLI watch / vite / tests) must drop path-env modules too */
|
|
39
|
+
declare function clearPathEnvCaches(): void;
|
|
40
|
+
declare function preloadPathEnvs(envNames: string[], baseDir: string): Promise<void>;
|
|
41
|
+
declare function loadEnvsAsync(envNames: string[], globalEnv: Environment, baseDir?: string): Promise<LoadedEnv>;
|
|
42
|
+
declare function loadEnvs(envNames: string[], globalEnv: Environment): LoadedEnv;
|
|
43
|
+
|
|
44
|
+
type NudoConfig = {
|
|
45
|
+
env?: string[];
|
|
46
|
+
mocks?: Record<string, string>;
|
|
47
|
+
interface?: {
|
|
48
|
+
/** 侧车 ambient 绑定总开关(check/LSP 执法与 interface 打印共用) */
|
|
49
|
+
autoBind?: boolean;
|
|
50
|
+
/**
|
|
51
|
+
* emit 白名单(Phase 3,§7.3):glob 数组,相对 projectDir。
|
|
52
|
+
* 省略/空 = 不按路径过滤(仍受 --fn/--all 与「默认只刷已有生成段」约束)。
|
|
53
|
+
*/
|
|
54
|
+
emit?: string[] | string;
|
|
55
|
+
};
|
|
56
|
+
/** 分析范围与噪声档(design-analysis-scope.md / A2) */
|
|
57
|
+
analysis?: {
|
|
58
|
+
include?: string[] | string;
|
|
59
|
+
exclude?: string[] | string;
|
|
60
|
+
/** directives | exports(默认)| all */
|
|
61
|
+
mode?: string;
|
|
62
|
+
/** off | errors | default | verbose */
|
|
63
|
+
diagnostics?: string;
|
|
64
|
+
/** polyvariant:保留的精确调用点 case 上限(默认 3);超出进 symbolic #widened */
|
|
65
|
+
callSiteBudget?: number;
|
|
66
|
+
/** C0.5:求值命中闭对象缺字段 → nudo:missing-slot;默认 off */
|
|
67
|
+
evalMissingSlot?: "off" | "warning";
|
|
68
|
+
};
|
|
69
|
+
/** 磁盘缓存(B3):true → `.nudo/cache`;字符串 → 自定义根;false/省略 → 关 */
|
|
70
|
+
cache?: boolean | string;
|
|
71
|
+
};
|
|
72
|
+
type InterfaceConfig = {
|
|
73
|
+
autoBind: boolean;
|
|
74
|
+
/** emit 路径白名单(已归一化;空数组 = 不限制) */
|
|
75
|
+
emit: string[];
|
|
76
|
+
};
|
|
77
|
+
type AnalysisMode = "directives" | "exports" | "all";
|
|
78
|
+
type DiagnosticsLevel = "off" | "errors" | "default" | "verbose";
|
|
79
|
+
type AnalysisConfig = {
|
|
80
|
+
include: string[];
|
|
81
|
+
exclude: string[];
|
|
82
|
+
mode: AnalysisMode;
|
|
83
|
+
diagnostics: DiagnosticsLevel;
|
|
84
|
+
/** polyvariant 精确调用点上限(B4) */
|
|
85
|
+
callSiteBudget: number;
|
|
86
|
+
/** C0.5 evaluation-driven missing-slot;默认 off */
|
|
87
|
+
evalMissingSlot: "off" | "warning";
|
|
88
|
+
};
|
|
89
|
+
/** A1 产品默认:exports — 普通带导出的 .js 进 IDE;directives/all 需显式 */
|
|
90
|
+
declare const DEFAULT_ANALYSIS_MODE: AnalysisMode;
|
|
91
|
+
/**
|
|
92
|
+
* 归一化 `nudo.analysis`。默认 mode=exports(A1:无指令但有 export/侧车的文件
|
|
93
|
+
* 进 IDE 分析;`all` / `directives` 需显式配置)。
|
|
94
|
+
* diagnostics:directives→errors,exports/all→default。
|
|
95
|
+
* include 空 = 不按路径过滤(isNudoTargetPath 已管扩展名)。
|
|
96
|
+
*/
|
|
97
|
+
declare function analysisConfig(config: NudoConfig | null | undefined): AnalysisConfig;
|
|
98
|
+
/** 磁盘缓存根(B3):config.cache / NUDO_CACHE_DIR / 默认关 */
|
|
99
|
+
declare function diskCacheRoot(config: NudoConfig | null | undefined, projectDir: string | undefined): string | undefined;
|
|
100
|
+
/**
|
|
101
|
+
* 归一化 `nudo.interface` 配置段。
|
|
102
|
+
* - autoBind 默认 true
|
|
103
|
+
* - emit:string | string[] → string[](空 = 不限制路径)
|
|
104
|
+
*/
|
|
105
|
+
declare function interfaceConfig(config: NudoConfig | null | undefined): InterfaceConfig;
|
|
106
|
+
/**
|
|
107
|
+
* 极简 glob(`**` / `*` / `?`):相对 projectDir 匹配**源文件**绝对路径
|
|
108
|
+
* (不是侧车路径;侧车随源文件同目录写出)。无白名单 → true。
|
|
109
|
+
* 路径分隔符归一为 `/`。
|
|
110
|
+
*/
|
|
111
|
+
declare function matchesEmitAllowlist(absPath: string, projectDir: string | undefined, patterns: string[]): boolean;
|
|
112
|
+
declare function findProjectConfig(startDir: string): {
|
|
113
|
+
config: NudoConfig;
|
|
114
|
+
projectDir: string;
|
|
115
|
+
} | null;
|
|
116
|
+
|
|
117
|
+
export { type AnalysisConfig as A, type CallRecord as C, type DiagnosticsLevel as D, type InterfaceConfig as I, type LoadedEnv as L, type NudoConfig as N, type AnalysisMode as a, DEFAULT_ANALYSIS_MODE as b, analysisConfig as c, clearPathEnvCaches as d, diskCacheRoot as e, findProjectConfig as f, loadEnvsAsync as g, interfaceConfig as i, loadEnvs as l, matchesEmitAllowlist as m, preloadPathEnvs as p };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { C as CallRecord, I as InterfaceConfig, N as NudoConfig, f as findProjectConfig, i as interfaceConfig } from '../config-
|
|
2
|
-
import { Abs
|
|
1
|
+
export { A as AnalysisConfig, a as AnalysisMode, C as CallRecord, D as DiagnosticsLevel, I as InterfaceConfig, L as LoadedEnv, N as NudoConfig, c as analysisConfig, f as findProjectConfig, i as interfaceConfig, l as loadEnvs, g as loadEnvsAsync, p as preloadPathEnvs } from '../config-Cqj8zeZH.js';
|
|
2
|
+
import { Abs } from '@nudojs/core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 内置类原型成员近似表(Abs 声明)。
|
|
@@ -12,15 +12,6 @@ declare function describeAbsMember(a: Abs): string | null;
|
|
|
12
12
|
declare function builtinProtoMemberNames(className: string): string[];
|
|
13
13
|
declare function builtinProtoMember(className: string, member: string): Abs | null;
|
|
14
14
|
|
|
15
|
-
type LoadedEnv = {
|
|
16
|
-
/** Abs 原生模块导出(B 路径 / Abs 模块图) */
|
|
17
|
-
modules: Record<string, Record<string, Abs>>;
|
|
18
|
-
globals: Record<string, Abs>;
|
|
19
|
-
};
|
|
20
|
-
declare function preloadPathEnvs(envNames: string[], baseDir: string): Promise<void>;
|
|
21
|
-
declare function loadEnvsAsync(envNames: string[], globalEnv: Environment, baseDir?: string): Promise<LoadedEnv>;
|
|
22
|
-
declare function loadEnvs(envNames: string[], globalEnv: Environment): LoadedEnv;
|
|
23
|
-
|
|
24
15
|
declare function resolveNpmNudo(source: string, fromDir: string): string | null;
|
|
25
16
|
|
|
26
|
-
export { BUILTIN_PROTOTYPE_METHOD_APPROXIMATIONS,
|
|
17
|
+
export { BUILTIN_PROTOTYPE_METHOD_APPROXIMATIONS, builtinProtoMember, builtinProtoMemberNames, describeAbsMember, resolveNpmNudo };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BUILTIN_PROTOTYPE_METHOD_APPROXIMATIONS,
|
|
3
|
+
analysisConfig,
|
|
3
4
|
builtinProtoMember,
|
|
4
5
|
builtinProtoMemberNames,
|
|
5
6
|
describeAbsMember,
|
|
@@ -9,9 +10,10 @@ import {
|
|
|
9
10
|
loadEnvsAsync,
|
|
10
11
|
preloadPathEnvs,
|
|
11
12
|
resolveNpmNudo
|
|
12
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-ADFCZP72.js";
|
|
13
14
|
export {
|
|
14
15
|
BUILTIN_PROTOTYPE_METHOD_APPROXIMATIONS,
|
|
16
|
+
analysisConfig,
|
|
15
17
|
builtinProtoMember,
|
|
16
18
|
builtinProtoMemberNames,
|
|
17
19
|
describeAbsMember,
|