@nudojs/service 4.0.0 → 5.0.0-beta.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.
- package/README.md +17 -7
- package/dist/analysis-_DlXLC-L.d.ts +281 -0
- package/dist/analysis.d.ts +8 -0
- package/dist/analysis.js +61 -0
- package/dist/analyzer-types-CfBrPK9L.d.ts +158 -0
- package/dist/call-record-CkyCFkT9.d.ts +33 -0
- package/dist/chunk-EG6FYQLI.js +89 -0
- package/dist/chunk-J2PUE4NV.js +235 -0
- package/dist/chunk-NQXAF4LJ.js +3739 -0
- package/dist/{chunk-ADFCZP72.js → chunk-ZXVAX7DE.js} +274 -15
- package/dist/{config-Cqj8zeZH.d.ts → config-DDB588oA.d.ts} +45 -48
- package/dist/emit/index.d.ts +607 -0
- package/dist/emit/index.js +3747 -0
- package/dist/env-loader-fj0TSCcA.d.ts +20 -0
- package/dist/evaluator/evaluator-api.d.ts +3 -1
- package/dist/evaluator/evaluator-api.js +7 -1
- package/dist/index.d.ts +291 -1197
- package/dist/index.js +232 -7554
- package/dist/what-if-mIo7I5Ii.d.ts +21 -0
- package/package.json +17 -9
|
@@ -235,6 +235,75 @@ import { tmpdir } from "os";
|
|
|
235
235
|
import { defineEnv as defineEsEnv } from "@nudojs/env/es";
|
|
236
236
|
import { defineEnv as defineWebEnv } from "@nudojs/env/web";
|
|
237
237
|
import { defineEnv as defineNodeEnv } from "@nudojs/env/node";
|
|
238
|
+
|
|
239
|
+
// src/lru-map.ts
|
|
240
|
+
var BoundedLruMap = class {
|
|
241
|
+
map = /* @__PURE__ */ new Map();
|
|
242
|
+
max;
|
|
243
|
+
constructor(max) {
|
|
244
|
+
this.max = max;
|
|
245
|
+
}
|
|
246
|
+
get size() {
|
|
247
|
+
return this.map.size;
|
|
248
|
+
}
|
|
249
|
+
/** 当前上限(可动态收紧;收紧时立刻按 LRU 压到新上限) */
|
|
250
|
+
getMax() {
|
|
251
|
+
return this.max;
|
|
252
|
+
}
|
|
253
|
+
setMax(max) {
|
|
254
|
+
this.max = max;
|
|
255
|
+
this.trim();
|
|
256
|
+
}
|
|
257
|
+
has(key) {
|
|
258
|
+
return this.map.has(key);
|
|
259
|
+
}
|
|
260
|
+
get(key) {
|
|
261
|
+
const hit = this.map.get(key);
|
|
262
|
+
if (hit === void 0) return void 0;
|
|
263
|
+
this.map.delete(key);
|
|
264
|
+
this.map.set(key, hit);
|
|
265
|
+
return hit;
|
|
266
|
+
}
|
|
267
|
+
/** 命中不改变 LRU 序(只读探测) */
|
|
268
|
+
peek(key) {
|
|
269
|
+
return this.map.get(key);
|
|
270
|
+
}
|
|
271
|
+
set(key, value) {
|
|
272
|
+
if (this.max <= 0) return;
|
|
273
|
+
while (this.map.size >= this.max && !this.map.has(key)) {
|
|
274
|
+
const oldest = this.map.keys().next().value;
|
|
275
|
+
if (oldest === void 0) break;
|
|
276
|
+
this.map.delete(oldest);
|
|
277
|
+
}
|
|
278
|
+
this.map.delete(key);
|
|
279
|
+
this.map.set(key, value);
|
|
280
|
+
}
|
|
281
|
+
delete(key) {
|
|
282
|
+
return this.map.delete(key);
|
|
283
|
+
}
|
|
284
|
+
clear() {
|
|
285
|
+
this.map.clear();
|
|
286
|
+
}
|
|
287
|
+
keys() {
|
|
288
|
+
return this.map.keys();
|
|
289
|
+
}
|
|
290
|
+
values() {
|
|
291
|
+
return this.map.values();
|
|
292
|
+
}
|
|
293
|
+
entries() {
|
|
294
|
+
return this.map.entries();
|
|
295
|
+
}
|
|
296
|
+
/** 压到当前 max(调低上限时收内存) */
|
|
297
|
+
trim() {
|
|
298
|
+
while (this.map.size > this.max) {
|
|
299
|
+
const oldest = this.map.keys().next().value;
|
|
300
|
+
if (oldest === void 0) break;
|
|
301
|
+
this.map.delete(oldest);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// src/evaluator/env-loader.ts
|
|
238
307
|
var envFactories = {
|
|
239
308
|
es: defineEsEnv,
|
|
240
309
|
web: defineWebEnv,
|
|
@@ -255,9 +324,28 @@ function resolveEnvNames(names) {
|
|
|
255
324
|
names.forEach(visit);
|
|
256
325
|
return [...resolved];
|
|
257
326
|
}
|
|
258
|
-
var
|
|
259
|
-
var
|
|
327
|
+
var PATH_ENV_CACHE_MAX = 64;
|
|
328
|
+
var PATH_ENV_BY_PATH_MAX = 64;
|
|
329
|
+
var PATH_ENV_BASE_DIRS_MAX = 64;
|
|
330
|
+
var pathEnvCache = new BoundedLruMap(PATH_ENV_CACHE_MAX);
|
|
331
|
+
var pathEnvByPath = new BoundedLruMap(PATH_ENV_BY_PATH_MAX);
|
|
260
332
|
var pathEnvBaseDirs = /* @__PURE__ */ new Set();
|
|
333
|
+
function addPathEnvBaseDir(baseDir) {
|
|
334
|
+
pathEnvBaseDirs.delete(baseDir);
|
|
335
|
+
pathEnvBaseDirs.add(baseDir);
|
|
336
|
+
while (pathEnvBaseDirs.size > PATH_ENV_BASE_DIRS_MAX) {
|
|
337
|
+
const oldest = pathEnvBaseDirs.values().next().value;
|
|
338
|
+
if (oldest === void 0) break;
|
|
339
|
+
pathEnvBaseDirs.delete(oldest);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
function getPathEnvCacheSizes() {
|
|
343
|
+
return {
|
|
344
|
+
byKey: pathEnvCache.size,
|
|
345
|
+
byPath: pathEnvByPath.size,
|
|
346
|
+
baseDirs: pathEnvBaseDirs.size
|
|
347
|
+
};
|
|
348
|
+
}
|
|
261
349
|
function isPathEnvName(name, baseDir) {
|
|
262
350
|
if (name in envFactories) return false;
|
|
263
351
|
if (name.includes("/") || name.startsWith("./") || name.startsWith("../")) return true;
|
|
@@ -281,7 +369,7 @@ function rewriteBareImports(text) {
|
|
|
281
369
|
}
|
|
282
370
|
async function importPathEnv(resolvedPath, mtimeMs) {
|
|
283
371
|
const cacheKey = `${resolvedPath}:${mtimeMs}`;
|
|
284
|
-
if (pathEnvCache.
|
|
372
|
+
if (pathEnvCache.get(cacheKey)) return;
|
|
285
373
|
let mod = null;
|
|
286
374
|
try {
|
|
287
375
|
const url = pathToFileURL(resolvedPath).href + `?mtime=${mtimeMs}`;
|
|
@@ -338,7 +426,7 @@ function clearPathEnvCaches() {
|
|
|
338
426
|
pathEnvBaseDirs.clear();
|
|
339
427
|
}
|
|
340
428
|
async function preloadPathEnvs(envNames, baseDir) {
|
|
341
|
-
|
|
429
|
+
addPathEnvBaseDir(baseDir);
|
|
342
430
|
for (const name of envNames) {
|
|
343
431
|
if (!isPathEnvName(name, baseDir)) continue;
|
|
344
432
|
const resolved = resolvePath(baseDir, name);
|
|
@@ -378,6 +466,81 @@ function loadEnvs(envNames, globalEnv) {
|
|
|
378
466
|
// src/evaluator/config.ts
|
|
379
467
|
import { readFileSync as readFileSync2, existsSync as existsSync2 } from "fs";
|
|
380
468
|
import { resolve, dirname, relative, sep } from "path";
|
|
469
|
+
|
|
470
|
+
// src/session-cache-limits.ts
|
|
471
|
+
var DEFAULT_SESSION_CACHE_LIMITS = {
|
|
472
|
+
maxFiles: 64,
|
|
473
|
+
maxFns: 1024,
|
|
474
|
+
maxBRuns: 32
|
|
475
|
+
};
|
|
476
|
+
var HARD_CAP = 65536;
|
|
477
|
+
function clampEntries(n, fallback) {
|
|
478
|
+
if (typeof n !== "number" || !Number.isFinite(n)) return fallback;
|
|
479
|
+
return Math.max(0, Math.min(HARD_CAP, Math.floor(n)));
|
|
480
|
+
}
|
|
481
|
+
function parseLimit(raw, fallback) {
|
|
482
|
+
if (raw === void 0 || raw === "") return fallback;
|
|
483
|
+
if (raw === "off" || raw === "0") return 0;
|
|
484
|
+
const n = Number(raw);
|
|
485
|
+
return clampEntries(n, fallback);
|
|
486
|
+
}
|
|
487
|
+
var explicit = {};
|
|
488
|
+
var fromProject = {};
|
|
489
|
+
var envCache = null;
|
|
490
|
+
function envLimits(env) {
|
|
491
|
+
return {
|
|
492
|
+
maxFiles: parseLimit(env.NUDO_CACHE_MAX_FILES, NaN),
|
|
493
|
+
maxFns: parseLimit(env.NUDO_CACHE_MAX_FNS, NaN),
|
|
494
|
+
maxBRuns: parseLimit(env.NUDO_CACHE_MAX_BRUNS, NaN)
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
function pick(key, env, fallback) {
|
|
498
|
+
const e = env[key];
|
|
499
|
+
if (typeof e === "number" && Number.isFinite(e)) return e;
|
|
500
|
+
const x = explicit[key];
|
|
501
|
+
if (typeof x === "number" && Number.isFinite(x)) return clampEntries(x, fallback);
|
|
502
|
+
const p = fromProject[key];
|
|
503
|
+
if (typeof p === "number" && Number.isFinite(p)) return clampEntries(p, fallback);
|
|
504
|
+
return fallback;
|
|
505
|
+
}
|
|
506
|
+
function getSessionCacheLimits(env = process.env) {
|
|
507
|
+
if (envCache === null) envCache = envLimits(env);
|
|
508
|
+
return {
|
|
509
|
+
maxFiles: pick("maxFiles", envCache, DEFAULT_SESSION_CACHE_LIMITS.maxFiles),
|
|
510
|
+
maxFns: pick("maxFns", envCache, DEFAULT_SESSION_CACHE_LIMITS.maxFns),
|
|
511
|
+
maxBRuns: pick("maxBRuns", envCache, DEFAULT_SESSION_CACHE_LIMITS.maxBRuns)
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
function setSessionCacheLimits(partial) {
|
|
515
|
+
explicit = partial ? { ...partial } : {};
|
|
516
|
+
return getSessionCacheLimits();
|
|
517
|
+
}
|
|
518
|
+
function setSessionCacheFromProject(partial) {
|
|
519
|
+
fromProject = partial ? { ...partial } : {};
|
|
520
|
+
}
|
|
521
|
+
function resetSessionCacheLimitState() {
|
|
522
|
+
explicit = {};
|
|
523
|
+
fromProject = {};
|
|
524
|
+
envCache = null;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// src/evaluator/config.ts
|
|
528
|
+
import { setBForkBudgetLimit, getBForkBudgetLimit, MAX_B_TOTAL_FORKS } from "@nudojs/core/internal";
|
|
529
|
+
function checkConfig(config) {
|
|
530
|
+
const raw = config?.check;
|
|
531
|
+
const rawEntry = raw?.entryThrows;
|
|
532
|
+
let entryThrows = "error";
|
|
533
|
+
if (rawEntry === "off" || rawEntry === "warning" || rawEntry === "error") {
|
|
534
|
+
entryThrows = rawEntry;
|
|
535
|
+
} else if (rawEntry !== void 0) {
|
|
536
|
+
process.stderr?.write?.(
|
|
537
|
+
`nudo.check.entryThrows: invalid value ${JSON.stringify(rawEntry)} (expected error|warning|off); using error
|
|
538
|
+
`
|
|
539
|
+
);
|
|
540
|
+
}
|
|
541
|
+
const ignore = Array.isArray(raw?.ignoreThrows) ? raw.ignoreThrows.filter((s) => typeof s === "string" && s.length > 0) : [];
|
|
542
|
+
return { entryThrows, ignoreThrows: ignore };
|
|
543
|
+
}
|
|
381
544
|
var DEFAULT_ANALYSIS_EXCLUDE = [
|
|
382
545
|
"**/node_modules/**",
|
|
383
546
|
"**/dist/**",
|
|
@@ -406,9 +569,24 @@ function analysisConfig(config) {
|
|
|
406
569
|
mode,
|
|
407
570
|
diagnostics,
|
|
408
571
|
callSiteBudget,
|
|
409
|
-
evalMissingSlot: raw?.evalMissingSlot === "warning" ? "warning" : "off"
|
|
572
|
+
evalMissingSlot: raw?.evalMissingSlot === "warning" ? "warning" : "off",
|
|
573
|
+
maxForks: parseMaxForks(raw?.maxForks) ?? MAX_B_TOTAL_FORKS
|
|
410
574
|
};
|
|
411
575
|
}
|
|
576
|
+
function parseMaxForks(raw) {
|
|
577
|
+
if (typeof raw !== "number" || !Number.isFinite(raw) || raw < 1) return void 0;
|
|
578
|
+
return Math.floor(raw);
|
|
579
|
+
}
|
|
580
|
+
function applyBForkBudgetFromConfig(config, env = process.env) {
|
|
581
|
+
const fromEnv = parseMaxForks(
|
|
582
|
+
env.NUDO_MAX_FORKS === void 0 ? void 0 : Number(env.NUDO_MAX_FORKS)
|
|
583
|
+
);
|
|
584
|
+
const fromCfg = parseMaxForks(config?.analysis?.maxForks);
|
|
585
|
+
return setBForkBudgetLimit(fromEnv ?? fromCfg ?? MAX_B_TOTAL_FORKS);
|
|
586
|
+
}
|
|
587
|
+
function currentBForkBudgetLimit() {
|
|
588
|
+
return getBForkBudgetLimit();
|
|
589
|
+
}
|
|
412
590
|
function diskCacheRoot(config, projectDir) {
|
|
413
591
|
const raw = config?.cache;
|
|
414
592
|
if (raw === false) return void 0;
|
|
@@ -424,10 +602,10 @@ function diskCacheRoot(config, projectDir) {
|
|
|
424
602
|
return void 0;
|
|
425
603
|
}
|
|
426
604
|
function interfaceConfig(config) {
|
|
427
|
-
const raw = config?.
|
|
605
|
+
const raw = config?.contract?.emit;
|
|
428
606
|
const emit = raw === void 0 ? [] : Array.isArray(raw) ? raw.filter((s) => typeof s === "string" && s.length > 0) : typeof raw === "string" && raw.length > 0 ? [raw] : [];
|
|
429
607
|
return {
|
|
430
|
-
autoBind: config?.
|
|
608
|
+
autoBind: config?.contract?.autoBind ?? true,
|
|
431
609
|
emit
|
|
432
610
|
};
|
|
433
611
|
}
|
|
@@ -478,7 +656,10 @@ function findProjectConfig(startDir) {
|
|
|
478
656
|
try {
|
|
479
657
|
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
480
658
|
if (pkg.nudo) {
|
|
481
|
-
|
|
659
|
+
const nudo = pkg.nudo;
|
|
660
|
+
setSessionCacheFromProject(nudo.sessionCache);
|
|
661
|
+
applyBForkBudgetFromConfig(nudo);
|
|
662
|
+
return { config: nudo, projectDir: dir };
|
|
482
663
|
}
|
|
483
664
|
} catch {
|
|
484
665
|
}
|
|
@@ -487,11 +668,12 @@ function findProjectConfig(startDir) {
|
|
|
487
668
|
if (parent === dir) break;
|
|
488
669
|
dir = parent;
|
|
489
670
|
}
|
|
671
|
+
applyBForkBudgetFromConfig(null);
|
|
490
672
|
return null;
|
|
491
673
|
}
|
|
492
674
|
|
|
493
675
|
// src/evaluator/resolve-npm.ts
|
|
494
|
-
import { readFileSync as readFileSync3, existsSync as existsSync3 } from "fs";
|
|
676
|
+
import { readFileSync as readFileSync3, existsSync as existsSync3, statSync as statSync2 } from "fs";
|
|
495
677
|
import { resolve as resolve2, join, dirname as dirname2 } from "path";
|
|
496
678
|
function findNodeModules(startDir) {
|
|
497
679
|
let dir = resolve2(startDir);
|
|
@@ -505,6 +687,72 @@ function findNodeModules(startDir) {
|
|
|
505
687
|
}
|
|
506
688
|
return null;
|
|
507
689
|
}
|
|
690
|
+
function resolveNpmJsEntry(source, fromDir) {
|
|
691
|
+
if (!source || source.startsWith(".") || source.startsWith("/") || source.startsWith("node:")) {
|
|
692
|
+
return null;
|
|
693
|
+
}
|
|
694
|
+
const parts = source.startsWith("@") ? source.split("/").slice(0, 2) : source.split("/").slice(0, 1);
|
|
695
|
+
const pkgName = parts.join("/");
|
|
696
|
+
const subpath = source.slice(pkgName.length).replace(/^\//, "") || ".";
|
|
697
|
+
const nodeModules = findNodeModules(fromDir);
|
|
698
|
+
if (!nodeModules) return null;
|
|
699
|
+
const pkgDir = join(nodeModules, pkgName);
|
|
700
|
+
const pkgJsonPath = join(pkgDir, "package.json");
|
|
701
|
+
if (!existsSync3(pkgJsonPath)) return null;
|
|
702
|
+
const tryFile = (p) => {
|
|
703
|
+
for (const c of [p, `${p}.js`, `${p}.cjs`, `${p}.mjs`, join(p, "index.js"), join(p, "index.cjs")]) {
|
|
704
|
+
try {
|
|
705
|
+
if (existsSync3(c) && statSync2(c).isFile()) return c;
|
|
706
|
+
} catch {
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return null;
|
|
710
|
+
};
|
|
711
|
+
let pkg = {};
|
|
712
|
+
try {
|
|
713
|
+
pkg = JSON.parse(readFileSync3(pkgJsonPath, "utf-8"));
|
|
714
|
+
} catch {
|
|
715
|
+
return null;
|
|
716
|
+
}
|
|
717
|
+
const exportsField = pkg.exports;
|
|
718
|
+
const pickExport = (entry) => {
|
|
719
|
+
if (typeof entry === "string") return entry;
|
|
720
|
+
if (entry && typeof entry === "object") {
|
|
721
|
+
const o = entry;
|
|
722
|
+
for (const k of ["nudo", "node", "require", "import", "default"]) {
|
|
723
|
+
const v = o[k];
|
|
724
|
+
const r = pickExport(v);
|
|
725
|
+
if (r) return r;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
return null;
|
|
729
|
+
};
|
|
730
|
+
if (exportsField) {
|
|
731
|
+
let rel = null;
|
|
732
|
+
if (typeof exportsField === "string" && subpath === ".") rel = exportsField;
|
|
733
|
+
else if (exportsField && typeof exportsField === "object") {
|
|
734
|
+
const map = exportsField;
|
|
735
|
+
const key = subpath === "." ? "." : `./${subpath}`;
|
|
736
|
+
rel = pickExport(map[key] ?? (subpath === "." ? map : void 0));
|
|
737
|
+
}
|
|
738
|
+
if (rel) {
|
|
739
|
+
const hit = tryFile(resolve2(pkgDir, rel));
|
|
740
|
+
if (hit) return hit;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
if (subpath === ".") {
|
|
744
|
+
const main = typeof pkg.main === "string" ? pkg.main : void 0;
|
|
745
|
+
const hit = tryFile(resolve2(pkgDir, main ?? "."));
|
|
746
|
+
if (hit) return hit;
|
|
747
|
+
const mod = typeof pkg.module === "string" ? pkg.module : void 0;
|
|
748
|
+
if (mod) {
|
|
749
|
+
const hitMod = tryFile(resolve2(pkgDir, mod));
|
|
750
|
+
if (hitMod) return hitMod;
|
|
751
|
+
}
|
|
752
|
+
return null;
|
|
753
|
+
}
|
|
754
|
+
return tryFile(resolve2(pkgDir, subpath));
|
|
755
|
+
}
|
|
508
756
|
function resolveExportsNudo(exports, subpath) {
|
|
509
757
|
if (!exports || typeof exports !== "object") return null;
|
|
510
758
|
const entry = exports[subpath];
|
|
@@ -538,19 +786,30 @@ function resolveNpmNudo(source, fromDir) {
|
|
|
538
786
|
}
|
|
539
787
|
|
|
540
788
|
export {
|
|
789
|
+
resolveNpmJsEntry,
|
|
790
|
+
resolveNpmNudo,
|
|
791
|
+
BUILTIN_PROTOTYPE_METHOD_APPROXIMATIONS,
|
|
792
|
+
describeAbsMember,
|
|
793
|
+
builtinProtoMemberNames,
|
|
794
|
+
builtinProtoMember,
|
|
795
|
+
BoundedLruMap,
|
|
796
|
+
getPathEnvCacheSizes,
|
|
541
797
|
clearPathEnvCaches,
|
|
542
798
|
preloadPathEnvs,
|
|
543
799
|
loadEnvsAsync,
|
|
544
800
|
loadEnvs,
|
|
801
|
+
DEFAULT_SESSION_CACHE_LIMITS,
|
|
802
|
+
getSessionCacheLimits,
|
|
803
|
+
setSessionCacheLimits,
|
|
804
|
+
setSessionCacheFromProject,
|
|
805
|
+
resetSessionCacheLimitState,
|
|
806
|
+
checkConfig,
|
|
545
807
|
DEFAULT_ANALYSIS_MODE,
|
|
546
808
|
analysisConfig,
|
|
809
|
+
applyBForkBudgetFromConfig,
|
|
810
|
+
currentBForkBudgetLimit,
|
|
547
811
|
diskCacheRoot,
|
|
548
812
|
interfaceConfig,
|
|
549
813
|
matchesEmitAllowlist,
|
|
550
|
-
findProjectConfig
|
|
551
|
-
resolveNpmNudo,
|
|
552
|
-
BUILTIN_PROTOTYPE_METHOD_APPROXIMATIONS,
|
|
553
|
-
describeAbsMember,
|
|
554
|
-
builtinProtoMemberNames,
|
|
555
|
-
builtinProtoMember
|
|
814
|
+
findProjectConfig
|
|
556
815
|
};
|
|
@@ -1,51 +1,8 @@
|
|
|
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
1
|
type NudoConfig = {
|
|
45
2
|
env?: string[];
|
|
46
3
|
mocks?: Record<string, string>;
|
|
47
|
-
|
|
48
|
-
/** 侧车 ambient 绑定总开关(check/LSP 执法与
|
|
4
|
+
contract?: {
|
|
5
|
+
/** 侧车 ambient 绑定总开关(check/LSP 执法与 contract 打印共用) */
|
|
49
6
|
autoBind?: boolean;
|
|
50
7
|
/**
|
|
51
8
|
* emit 白名单(Phase 3,§7.3):glob 数组,相对 projectDir。
|
|
@@ -53,7 +10,7 @@ type NudoConfig = {
|
|
|
53
10
|
*/
|
|
54
11
|
emit?: string[] | string;
|
|
55
12
|
};
|
|
56
|
-
/** 分析范围与噪声档(design-
|
|
13
|
+
/** 分析范围与噪声档(design-cli-semantics.md §7) */
|
|
57
14
|
analysis?: {
|
|
58
15
|
include?: string[] | string;
|
|
59
16
|
exclude?: string[] | string;
|
|
@@ -65,9 +22,30 @@ type NudoConfig = {
|
|
|
65
22
|
callSiteBudget?: number;
|
|
66
23
|
/** C0.5:求值命中闭对象缺字段 → nudo:missing-slot;默认 off */
|
|
67
24
|
evalMissingSlot?: "off" | "warning";
|
|
25
|
+
/**
|
|
26
|
+
* B $fork 总次数上限(默认 5000)。env `NUDO_MAX_FORKS` 优先。
|
|
27
|
+
* n≥1 有限整数;非法值回默认。启动时 set 进 core(setBForkBudgetLimit)。
|
|
28
|
+
*/
|
|
29
|
+
maxForks?: number;
|
|
68
30
|
};
|
|
69
31
|
/** 磁盘缓存(B3):true → `.nudo/cache`;字符串 → 自定义根;false/省略 → 关 */
|
|
70
32
|
cache?: boolean | string;
|
|
33
|
+
/**
|
|
34
|
+
* 进程内会话 LRU 上限(内存/速度权衡)。多项目开 IDE 时调低封顶;
|
|
35
|
+
* 单大仓 warm 命中可调高。0 = 关闭该层。env `NUDO_CACHE_MAX_*` 优先。
|
|
36
|
+
*/
|
|
37
|
+
sessionCache?: {
|
|
38
|
+
maxFiles?: number;
|
|
39
|
+
maxFns?: number;
|
|
40
|
+
maxBRuns?: number;
|
|
41
|
+
};
|
|
42
|
+
/** check 门禁(design-cli-semantics §3) */
|
|
43
|
+
check?: {
|
|
44
|
+
/** L2 入口 may-throw:error | warning | off(默认 error) */
|
|
45
|
+
entryThrows?: "error" | "warning" | "off";
|
|
46
|
+
/** L2 --ignore-throws 类型名列表 */
|
|
47
|
+
ignoreThrows?: string[];
|
|
48
|
+
};
|
|
71
49
|
};
|
|
72
50
|
type InterfaceConfig = {
|
|
73
51
|
autoBind: boolean;
|
|
@@ -85,7 +63,17 @@ type AnalysisConfig = {
|
|
|
85
63
|
callSiteBudget: number;
|
|
86
64
|
/** C0.5 evaluation-driven missing-slot;默认 off */
|
|
87
65
|
evalMissingSlot: "off" | "warning";
|
|
66
|
+
/** B $fork 总次数上限(已归一化;非法值回 core 默认) */
|
|
67
|
+
maxForks: number;
|
|
68
|
+
};
|
|
69
|
+
type CheckConfig = {
|
|
70
|
+
/** L2 入口 may-throw 执法档;默认 error */
|
|
71
|
+
entryThrows: "error" | "warning" | "off";
|
|
72
|
+
/** L2 ignoreThrows 类型名;默认空 */
|
|
73
|
+
ignoreThrows: string[];
|
|
88
74
|
};
|
|
75
|
+
/** package.json#nudo.check → 执法选项 */
|
|
76
|
+
declare function checkConfig(config: NudoConfig | null | undefined): CheckConfig;
|
|
89
77
|
/** A1 产品默认:exports — 普通带导出的 .js 进 IDE;directives/all 需显式 */
|
|
90
78
|
declare const DEFAULT_ANALYSIS_MODE: AnalysisMode;
|
|
91
79
|
/**
|
|
@@ -95,10 +83,19 @@ declare const DEFAULT_ANALYSIS_MODE: AnalysisMode;
|
|
|
95
83
|
* include 空 = 不按路径过滤(isNudoTargetPath 已管扩展名)。
|
|
96
84
|
*/
|
|
97
85
|
declare function analysisConfig(config: NudoConfig | null | undefined): AnalysisConfig;
|
|
86
|
+
/**
|
|
87
|
+
* 把 fork 预算写进 core(core 保持无 IO)。
|
|
88
|
+
* 优先级:env `NUDO_MAX_FORKS` > `package.json#nudo.analysis.maxForks` > 默认 5000。
|
|
89
|
+
* 约定:n≥1 有限整数;非法值回默认。返回实际生效值。
|
|
90
|
+
* 由 findProjectConfig / 宿主启动时调用(与 setSessionCacheFromProject 同时机)。
|
|
91
|
+
*/
|
|
92
|
+
declare function applyBForkBudgetFromConfig(config: NudoConfig | null | undefined, env?: NodeJS.ProcessEnv): number;
|
|
93
|
+
/** 当前生效 fork 上限(调试/测试;与 core getBForkBudgetLimit 同源) */
|
|
94
|
+
declare function currentBForkBudgetLimit(): number;
|
|
98
95
|
/** 磁盘缓存根(B3):config.cache / NUDO_CACHE_DIR / 默认关 */
|
|
99
96
|
declare function diskCacheRoot(config: NudoConfig | null | undefined, projectDir: string | undefined): string | undefined;
|
|
100
97
|
/**
|
|
101
|
-
* 归一化 `nudo.
|
|
98
|
+
* 归一化 `nudo.contract` 配置段。
|
|
102
99
|
* - autoBind 默认 true
|
|
103
100
|
* - emit:string | string[] → string[](空 = 不限制路径)
|
|
104
101
|
*/
|
|
@@ -114,4 +111,4 @@ declare function findProjectConfig(startDir: string): {
|
|
|
114
111
|
projectDir: string;
|
|
115
112
|
} | null;
|
|
116
113
|
|
|
117
|
-
export { type AnalysisConfig as A, type
|
|
114
|
+
export { type AnalysisConfig as A, type CheckConfig as C, type DiagnosticsLevel as D, type InterfaceConfig as I, type NudoConfig as N, type AnalysisMode as a, analysisConfig as b, checkConfig as c, diskCacheRoot as d, DEFAULT_ANALYSIS_MODE as e, findProjectConfig as f, applyBForkBudgetFromConfig as g, currentBForkBudgetLimit as h, interfaceConfig as i, matchesEmitAllowlist as m };
|