sourceverity 1.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/LICENSE +21 -0
- package/README.md +188 -0
- package/bin/sourceverity.js +12 -0
- package/dist/analysis/controlFlow.d.ts +10 -0
- package/dist/analysis/controlFlow.d.ts.map +1 -0
- package/dist/analysis/controlFlow.js +278 -0
- package/dist/analysis/controlFlow.js.map +1 -0
- package/dist/analysis/frameworks.d.ts +11 -0
- package/dist/analysis/frameworks.d.ts.map +1 -0
- package/dist/analysis/frameworks.js +189 -0
- package/dist/analysis/frameworks.js.map +1 -0
- package/dist/analysis/functions.d.ts +27 -0
- package/dist/analysis/functions.d.ts.map +1 -0
- package/dist/analysis/functions.js +628 -0
- package/dist/analysis/functions.js.map +1 -0
- package/dist/analysis/promiseFlow.d.ts +44 -0
- package/dist/analysis/promiseFlow.d.ts.map +1 -0
- package/dist/analysis/promiseFlow.js +261 -0
- package/dist/analysis/promiseFlow.js.map +1 -0
- package/dist/analysis/values.d.ts +24 -0
- package/dist/analysis/values.d.ts.map +1 -0
- package/dist/analysis/values.js +189 -0
- package/dist/analysis/values.js.map +1 -0
- package/dist/baseline/manager.d.ts +20 -0
- package/dist/baseline/manager.d.ts.map +1 -0
- package/dist/baseline/manager.js +77 -0
- package/dist/baseline/manager.js.map +1 -0
- package/dist/baseline/types.d.ts +20 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +2 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/cli/args.d.ts +26 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +126 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/exitCodes.d.ts +8 -0
- package/dist/cli/exitCodes.d.ts.map +1 -0
- package/dist/cli/exitCodes.js +7 -0
- package/dist/cli/exitCodes.js.map +1 -0
- package/dist/cli/help.d.ts +5 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +46 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/main.d.ts +7 -0
- package/dist/cli/main.d.ts.map +1 -0
- package/dist/cli/main.js +156 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/core/fingerprint.d.ts +18 -0
- package/dist/core/fingerprint.d.ts.map +1 -0
- package/dist/core/fingerprint.js +26 -0
- package/dist/core/fingerprint.js.map +1 -0
- package/dist/core/paths.d.ts +10 -0
- package/dist/core/paths.d.ts.map +1 -0
- package/dist/core/paths.js +30 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/suppressions.d.ts +24 -0
- package/dist/core/suppressions.d.ts.map +1 -0
- package/dist/core/suppressions.js +100 -0
- package/dist/core/suppressions.js.map +1 -0
- package/dist/core/terminal.d.ts +18 -0
- package/dist/core/terminal.d.ts.map +1 -0
- package/dist/core/terminal.js +39 -0
- package/dist/core/terminal.js.map +1 -0
- package/dist/core/types.d.ts +119 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/engine/context.d.ts +16 -0
- package/dist/engine/context.d.ts.map +1 -0
- package/dist/engine/context.js +57 -0
- package/dist/engine/context.js.map +1 -0
- package/dist/engine/registry.d.ts +26 -0
- package/dist/engine/registry.d.ts.map +1 -0
- package/dist/engine/registry.js +38 -0
- package/dist/engine/registry.js.map +1 -0
- package/dist/engine/runner.d.ts +14 -0
- package/dist/engine/runner.d.ts.map +1 -0
- package/dist/engine/runner.js +166 -0
- package/dist/engine/runner.js.map +1 -0
- package/dist/engine/symbols.d.ts +46 -0
- package/dist/engine/symbols.d.ts.map +1 -0
- package/dist/engine/symbols.js +278 -0
- package/dist/engine/symbols.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +32 -0
- package/dist/index.js.map +1 -0
- package/dist/reporters/agent.d.ts +45 -0
- package/dist/reporters/agent.d.ts.map +1 -0
- package/dist/reporters/agent.js +40 -0
- package/dist/reporters/agent.js.map +1 -0
- package/dist/reporters/json.d.ts +6 -0
- package/dist/reporters/json.d.ts.map +1 -0
- package/dist/reporters/json.js +7 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/sarif.d.ts +6 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +60 -0
- package/dist/reporters/sarif.js.map +1 -0
- package/dist/reporters/terminal.d.ts +10 -0
- package/dist/reporters/terminal.d.ts.map +1 -0
- package/dist/reporters/terminal.js +105 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/repository/detector.d.ts +6 -0
- package/dist/repository/detector.d.ts.map +1 -0
- package/dist/repository/detector.js +231 -0
- package/dist/repository/detector.js.map +1 -0
- package/dist/repository/fileFilter.d.ts +10 -0
- package/dist/repository/fileFilter.d.ts.map +1 -0
- package/dist/repository/fileFilter.js +78 -0
- package/dist/repository/fileFilter.js.map +1 -0
- package/dist/repository/git.d.ts +7 -0
- package/dist/repository/git.d.ts.map +1 -0
- package/dist/repository/git.js +53 -0
- package/dist/repository/git.js.map +1 -0
- package/dist/repository/tsLoader.d.ts +15 -0
- package/dist/repository/tsLoader.d.ts.map +1 -0
- package/dist/repository/tsLoader.js +27 -0
- package/dist/repository/tsLoader.js.map +1 -0
- package/dist/repository/types.d.ts +38 -0
- package/dist/repository/types.d.ts.map +1 -0
- package/dist/repository/types.js +2 -0
- package/dist/repository/types.js.map +1 -0
- package/dist/rules/async/asyncForeach.d.ts +3 -0
- package/dist/rules/async/asyncForeach.d.ts.map +1 -0
- package/dist/rules/async/asyncForeach.js +76 -0
- package/dist/rules/async/asyncForeach.js.map +1 -0
- package/dist/rules/async/floatingPromise.d.ts +3 -0
- package/dist/rules/async/floatingPromise.d.ts.map +1 -0
- package/dist/rules/async/floatingPromise.js +359 -0
- package/dist/rules/async/floatingPromise.js.map +1 -0
- package/dist/rules/browser/eventListenerCleanup.d.ts +3 -0
- package/dist/rules/browser/eventListenerCleanup.d.ts.map +1 -0
- package/dist/rules/browser/eventListenerCleanup.js +378 -0
- package/dist/rules/browser/eventListenerCleanup.js.map +1 -0
- package/dist/rules/browser/observerCleanup.d.ts +3 -0
- package/dist/rules/browser/observerCleanup.d.ts.map +1 -0
- package/dist/rules/browser/observerCleanup.js +184 -0
- package/dist/rules/browser/observerCleanup.js.map +1 -0
- package/dist/rules/browser/timerCleanup.d.ts +3 -0
- package/dist/rules/browser/timerCleanup.d.ts.map +1 -0
- package/dist/rules/browser/timerCleanup.js +115 -0
- package/dist/rules/browser/timerCleanup.js.map +1 -0
- package/dist/rules/index.d.ts +19 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +41 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/network/fetchStatusUnchecked.d.ts +3 -0
- package/dist/rules/network/fetchStatusUnchecked.d.ts.map +1 -0
- package/dist/rules/network/fetchStatusUnchecked.js +96 -0
- package/dist/rules/network/fetchStatusUnchecked.js.map +1 -0
- package/dist/rules/react/asyncEffectCallback.d.ts +3 -0
- package/dist/rules/react/asyncEffectCallback.d.ts.map +1 -0
- package/dist/rules/react/asyncEffectCallback.js +62 -0
- package/dist/rules/react/asyncEffectCallback.js.map +1 -0
- package/dist/rules/react/derivedStateEffect.d.ts +3 -0
- package/dist/rules/react/derivedStateEffect.d.ts.map +1 -0
- package/dist/rules/react/derivedStateEffect.js +172 -0
- package/dist/rules/react/derivedStateEffect.js.map +1 -0
- package/dist/rules/react/missingEffectCleanup.d.ts +3 -0
- package/dist/rules/react/missingEffectCleanup.d.ts.map +1 -0
- package/dist/rules/react/missingEffectCleanup.js +86 -0
- package/dist/rules/react/missingEffectCleanup.js.map +1 -0
- package/dist/rules/typescript/nonNullAssertionRisk.d.ts +3 -0
- package/dist/rules/typescript/nonNullAssertionRisk.d.ts.map +1 -0
- package/dist/rules/typescript/nonNullAssertionRisk.js +65 -0
- package/dist/rules/typescript/nonNullAssertionRisk.js.map +1 -0
- package/dist/rules/typescript/uncheckedIndexAccess.d.ts +3 -0
- package/dist/rules/typescript/uncheckedIndexAccess.d.ts.map +1 -0
- package/dist/rules/typescript/uncheckedIndexAccess.js +79 -0
- package/dist/rules/typescript/uncheckedIndexAccess.js.map +1 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.d.ts +3 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.d.ts.map +1 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.js +94 -0
- package/dist/rules/typescript/unsafeUnvalidatedAssertion.js.map +1 -0
- package/dist/strictness/evaluator.d.ts +28 -0
- package/dist/strictness/evaluator.d.ts.map +1 -0
- package/dist/strictness/evaluator.js +141 -0
- package/dist/strictness/evaluator.js.map +1 -0
- package/dist/strictness/matrix.d.ts +8 -0
- package/dist/strictness/matrix.d.ts.map +1 -0
- package/dist/strictness/matrix.js +63 -0
- package/dist/strictness/matrix.js.map +1 -0
- package/dist/typescript/programManager.d.ts +18 -0
- package/dist/typescript/programManager.d.ts.map +1 -0
- package/dist/typescript/programManager.js +46 -0
- package/dist/typescript/programManager.js.map +1 -0
- package/dist/typescript/projectResolver.d.ts +17 -0
- package/dist/typescript/projectResolver.d.ts.map +1 -0
- package/dist/typescript/projectResolver.js +75 -0
- package/dist/typescript/projectResolver.js.map +1 -0
- package/package.json +56 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type * as tsType from "typescript";
|
|
2
|
+
import { type FunctionSummaryContext } from "./functions.js";
|
|
3
|
+
export interface PromiseClassification {
|
|
4
|
+
readonly isPromise: boolean;
|
|
5
|
+
readonly isDefinitePromise: boolean;
|
|
6
|
+
readonly isOptionalPromiseUnion: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Classifies a type into definite Promise vs optional void/undefined Promise union.
|
|
10
|
+
*/
|
|
11
|
+
export declare function classifyPromiseType(type: tsType.Type | undefined, checker: tsType.TypeChecker, ts: typeof tsType): PromiseClassification;
|
|
12
|
+
/**
|
|
13
|
+
* Inspects a Promise method chain to determine whether it terminates in an effective rejection handler.
|
|
14
|
+
* Supports:
|
|
15
|
+
* - `.catch(onRejected)`
|
|
16
|
+
* - `.then(onFulfilled, onRejected)` (with valid onRejected)
|
|
17
|
+
* - `.catch(onRejected).finally(cleanup)`
|
|
18
|
+
* - `.then(onFulfilled, onRejected).finally(cleanup)`
|
|
19
|
+
*
|
|
20
|
+
* Rejects as NOT terminal-handled:
|
|
21
|
+
* - `.finally(cleanup)` (without preceding catch on a rejecting base)
|
|
22
|
+
* - `.then(onFulfilled).finally(cleanup)`
|
|
23
|
+
* - `.catch(onRejected).then(onFulfilled)` (new unhandled then step)
|
|
24
|
+
*/
|
|
25
|
+
export declare function hasTerminalRejectionHandling(expr: tsType.Expression, ts: typeof tsType, checker?: tsType.TypeChecker | undefined): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Checks whether a variable or assignment target reaches a return statement without being overwritten.
|
|
28
|
+
* Handles:
|
|
29
|
+
* - Direct return of assigned variable: cached = load(); return cached;
|
|
30
|
+
* - Return of alias: const p = load(); const q = p; return q;
|
|
31
|
+
* - Detects and rejects overwrites: cached = load(); cached = null; return fallback;
|
|
32
|
+
*/
|
|
33
|
+
export declare function isVariableTargetReturnedInScope(node: tsType.Node, targetName: string, ts: typeof tsType): boolean;
|
|
34
|
+
export interface PromiseConsumptionResult {
|
|
35
|
+
readonly isConsumed: boolean;
|
|
36
|
+
readonly reason?: string | undefined;
|
|
37
|
+
readonly isRejectionHandled: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Evaluates whether an expression statement containing a Promise is safely consumed,
|
|
41
|
+
* handled, cached, or returned.
|
|
42
|
+
*/
|
|
43
|
+
export declare function evaluatePromiseConsumption(expr: tsType.Expression, ts: typeof tsType, checker?: tsType.TypeChecker | undefined, context?: FunctionSummaryContext | undefined): PromiseConsumptionResult;
|
|
44
|
+
//# sourceMappingURL=promiseFlow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promiseFlow.d.ts","sourceRoot":"","sources":["../../src/analysis/promiseFlow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AAG1C,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC;CAC1C;AAID;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,CAAC,IAAI,GAAG,SAAS,EAC7B,OAAO,EAAE,MAAM,CAAC,WAAW,EAC3B,EAAE,EAAE,OAAO,MAAM,GAChB,qBAAqB,CA6CvB;AAQD;;;;;;;;;;;;GAYG;AACH,wBAAgB,4BAA4B,CAC1C,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,EAAE,EAAE,OAAO,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,GACvC,OAAO,CAuCT;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,MAAM,CAAC,IAAI,EACjB,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,OAAO,MAAM,GAChB,OAAO,CAuHT;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,kBAAkB,EAAE,OAAO,CAAC;CACtC;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,EAAE,EAAE,OAAO,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,EACxC,OAAO,CAAC,EAAE,sBAAsB,GAAG,SAAS,GAC3C,wBAAwB,CA8C1B"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
import { isPromiseLike } from "../engine/symbols.js";
|
|
2
|
+
import { unwrapExpression } from "./values.js";
|
|
3
|
+
import { evaluateFrameworkPromiseCall } from "./frameworks.js";
|
|
4
|
+
const classifyPromiseCache = new WeakMap();
|
|
5
|
+
/**
|
|
6
|
+
* Classifies a type into definite Promise vs optional void/undefined Promise union.
|
|
7
|
+
*/
|
|
8
|
+
export function classifyPromiseType(type, checker, ts) {
|
|
9
|
+
if (!type) {
|
|
10
|
+
return { isPromise: false, isDefinitePromise: false, isOptionalPromiseUnion: false };
|
|
11
|
+
}
|
|
12
|
+
let checkerCache = classifyPromiseCache.get(checker);
|
|
13
|
+
if (!checkerCache) {
|
|
14
|
+
checkerCache = new WeakMap();
|
|
15
|
+
classifyPromiseCache.set(checker, checkerCache);
|
|
16
|
+
}
|
|
17
|
+
const cached = checkerCache.get(type);
|
|
18
|
+
if (cached !== undefined) {
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
if (!isPromiseLike(type, checker)) {
|
|
22
|
+
const res = { isPromise: false, isDefinitePromise: false, isOptionalPromiseUnion: false };
|
|
23
|
+
checkerCache.set(type, res);
|
|
24
|
+
return res;
|
|
25
|
+
}
|
|
26
|
+
if (type.isUnion()) {
|
|
27
|
+
const hasVoidOrUndefined = type.types.some((t) => (t.flags & (ts.TypeFlags.Void | ts.TypeFlags.Undefined | ts.TypeFlags.Null)) !== 0);
|
|
28
|
+
const hasPromise = type.types.some((t) => isPromiseLike(t, checker));
|
|
29
|
+
if (hasVoidOrUndefined && hasPromise) {
|
|
30
|
+
const res = {
|
|
31
|
+
isPromise: true,
|
|
32
|
+
isDefinitePromise: false,
|
|
33
|
+
isOptionalPromiseUnion: true,
|
|
34
|
+
};
|
|
35
|
+
checkerCache.set(type, res);
|
|
36
|
+
return res;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const res = {
|
|
40
|
+
isPromise: true,
|
|
41
|
+
isDefinitePromise: true,
|
|
42
|
+
isOptionalPromiseUnion: false,
|
|
43
|
+
};
|
|
44
|
+
checkerCache.set(type, res);
|
|
45
|
+
return res;
|
|
46
|
+
}
|
|
47
|
+
function isUndefinedOrNullNode(node, ts) {
|
|
48
|
+
if (ts.isIdentifier(node) && node.text === "undefined")
|
|
49
|
+
return true;
|
|
50
|
+
if (node.kind === ts.SyntaxKind.NullKeyword || node.kind === ts.SyntaxKind.UndefinedKeyword)
|
|
51
|
+
return true;
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Inspects a Promise method chain to determine whether it terminates in an effective rejection handler.
|
|
56
|
+
* Supports:
|
|
57
|
+
* - `.catch(onRejected)`
|
|
58
|
+
* - `.then(onFulfilled, onRejected)` (with valid onRejected)
|
|
59
|
+
* - `.catch(onRejected).finally(cleanup)`
|
|
60
|
+
* - `.then(onFulfilled, onRejected).finally(cleanup)`
|
|
61
|
+
*
|
|
62
|
+
* Rejects as NOT terminal-handled:
|
|
63
|
+
* - `.finally(cleanup)` (without preceding catch on a rejecting base)
|
|
64
|
+
* - `.then(onFulfilled).finally(cleanup)`
|
|
65
|
+
* - `.catch(onRejected).then(onFulfilled)` (new unhandled then step)
|
|
66
|
+
*/
|
|
67
|
+
export function hasTerminalRejectionHandling(expr, ts, checker) {
|
|
68
|
+
const current = unwrapExpression(expr, ts);
|
|
69
|
+
if (!ts.isCallExpression(current)) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const callee = current.expression;
|
|
73
|
+
if (!ts.isPropertyAccessExpression(callee)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const methodName = callee.name.text;
|
|
77
|
+
// 1. Direct terminal .catch(onRejected)
|
|
78
|
+
if (methodName === "catch") {
|
|
79
|
+
const args = current.arguments;
|
|
80
|
+
if (args.length >= 1 && args[0] && !isUndefinedOrNullNode(args[0], ts)) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// 2. Direct terminal .then(onFulfilled, onRejected)
|
|
85
|
+
if (methodName === "then") {
|
|
86
|
+
const args = current.arguments;
|
|
87
|
+
if (args.length >= 2 && args[1] && !isUndefinedOrNullNode(args[1], ts)) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// 3. Terminal .finally(cleanup) preceded by a rejection-handled chain
|
|
92
|
+
// e.g. verify().then(...).catch(handleError).finally(cleanup)
|
|
93
|
+
if (methodName === "finally") {
|
|
94
|
+
const receiver = callee.expression;
|
|
95
|
+
if (receiver && hasTerminalRejectionHandling(receiver, ts, checker)) {
|
|
96
|
+
return true;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Checks whether a variable or assignment target reaches a return statement without being overwritten.
|
|
103
|
+
* Handles:
|
|
104
|
+
* - Direct return of assigned variable: cached = load(); return cached;
|
|
105
|
+
* - Return of alias: const p = load(); const q = p; return q;
|
|
106
|
+
* - Detects and rejects overwrites: cached = load(); cached = null; return fallback;
|
|
107
|
+
*/
|
|
108
|
+
export function isVariableTargetReturnedInScope(node, targetName, ts) {
|
|
109
|
+
// Find enclosing statement
|
|
110
|
+
let stmt = node;
|
|
111
|
+
while (stmt.parent && !ts.isBlock(stmt.parent) && !ts.isSourceFile(stmt.parent)) {
|
|
112
|
+
stmt = stmt.parent;
|
|
113
|
+
}
|
|
114
|
+
if (!stmt.parent)
|
|
115
|
+
return false;
|
|
116
|
+
const parentBlock = stmt.parent;
|
|
117
|
+
const statements = ts.isBlock(parentBlock)
|
|
118
|
+
? parentBlock.statements
|
|
119
|
+
: ts.isSourceFile(parentBlock)
|
|
120
|
+
? parentBlock.statements
|
|
121
|
+
: [];
|
|
122
|
+
const startIndex = statements.indexOf(stmt);
|
|
123
|
+
if (startIndex === -1)
|
|
124
|
+
return false;
|
|
125
|
+
// Set of valid return target names (includes targetName and any alias variables)
|
|
126
|
+
const validReturnNames = new Set([targetName]);
|
|
127
|
+
for (let i = startIndex + 1; i < statements.length; i++) {
|
|
128
|
+
const currentStmt = statements[i];
|
|
129
|
+
if (!currentStmt)
|
|
130
|
+
continue;
|
|
131
|
+
// Check if targetName is overwritten before return
|
|
132
|
+
if (ts.isExpressionStatement(currentStmt)) {
|
|
133
|
+
const expr = unwrapExpression(currentStmt.expression, ts);
|
|
134
|
+
if (ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
135
|
+
const assignedLeft = unwrapExpression(expr.left, ts);
|
|
136
|
+
const assignedName = ts.isIdentifier(assignedLeft)
|
|
137
|
+
? assignedLeft.text
|
|
138
|
+
: ts.isPropertyAccessExpression(assignedLeft)
|
|
139
|
+
? assignedLeft.getText()
|
|
140
|
+
: undefined;
|
|
141
|
+
if (assignedName === targetName) {
|
|
142
|
+
// targetName was overwritten with another value before reaching return!
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Check for alias: const alias = targetName;
|
|
148
|
+
if (ts.isVariableStatement(currentStmt)) {
|
|
149
|
+
for (const decl of currentStmt.declarationList.declarations) {
|
|
150
|
+
if (ts.isIdentifier(decl.name) && decl.initializer) {
|
|
151
|
+
const init = unwrapExpression(decl.initializer, ts);
|
|
152
|
+
if (ts.isIdentifier(init) && validReturnNames.has(init.text)) {
|
|
153
|
+
validReturnNames.add(decl.name.text);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Check for return statement
|
|
159
|
+
if (ts.isReturnStatement(currentStmt) && currentStmt.expression) {
|
|
160
|
+
const unwrappedRet = unwrapExpression(currentStmt.expression, ts);
|
|
161
|
+
if (ts.isIdentifier(unwrappedRet) && validReturnNames.has(unwrappedRet.text)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (ts.isPropertyAccessExpression(unwrappedRet) && validReturnNames.has(unwrappedRet.getText())) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
// Reached an early return of something else -> does not reach return
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Also inspect enclosing function/block if the assignment was inside an if-statement:
|
|
172
|
+
// e.g. if (!cached) { cached = import(...); } return cached;
|
|
173
|
+
let outerStatement = parentBlock;
|
|
174
|
+
while (outerStatement.parent && !ts.isBlock(outerStatement.parent) && !ts.isSourceFile(outerStatement.parent)) {
|
|
175
|
+
outerStatement = outerStatement.parent;
|
|
176
|
+
}
|
|
177
|
+
if (outerStatement.parent && (ts.isBlock(outerStatement.parent) || ts.isSourceFile(outerStatement.parent))) {
|
|
178
|
+
const outerBlock = outerStatement.parent;
|
|
179
|
+
const outerStmts = ts.isBlock(outerBlock)
|
|
180
|
+
? outerBlock.statements
|
|
181
|
+
: outerBlock.statements;
|
|
182
|
+
const outerStartIndex = outerStmts.indexOf(outerStatement);
|
|
183
|
+
if (outerStartIndex !== -1) {
|
|
184
|
+
for (let j = outerStartIndex + 1; j < outerStmts.length; j++) {
|
|
185
|
+
const outerS = outerStmts[j];
|
|
186
|
+
if (!outerS)
|
|
187
|
+
continue;
|
|
188
|
+
if (ts.isExpressionStatement(outerS)) {
|
|
189
|
+
const expr = unwrapExpression(outerS.expression, ts);
|
|
190
|
+
if (ts.isBinaryExpression(expr) && expr.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
191
|
+
const assignedLeft = unwrapExpression(expr.left, ts);
|
|
192
|
+
const assignedName = ts.isIdentifier(assignedLeft)
|
|
193
|
+
? assignedLeft.text
|
|
194
|
+
: ts.isPropertyAccessExpression(assignedLeft)
|
|
195
|
+
? assignedLeft.getText()
|
|
196
|
+
: undefined;
|
|
197
|
+
if (assignedName === targetName) {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (ts.isReturnStatement(outerS) && outerS.expression) {
|
|
203
|
+
const unwrappedRet = unwrapExpression(outerS.expression, ts);
|
|
204
|
+
if (ts.isIdentifier(unwrappedRet) && validReturnNames.has(unwrappedRet.text)) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
if (ts.isPropertyAccessExpression(unwrappedRet) && validReturnNames.has(unwrappedRet.getText())) {
|
|
208
|
+
return true;
|
|
209
|
+
}
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Evaluates whether an expression statement containing a Promise is safely consumed,
|
|
219
|
+
* handled, cached, or returned.
|
|
220
|
+
*/
|
|
221
|
+
export function evaluatePromiseConsumption(expr, ts, checker, context) {
|
|
222
|
+
const unwrapped = unwrapExpression(expr, ts);
|
|
223
|
+
// 1. Explicit void operator
|
|
224
|
+
if (ts.isVoidExpression(unwrapped)) {
|
|
225
|
+
return { isConsumed: true, reason: "Explicit void operator indicates intentional discard.", isRejectionHandled: false };
|
|
226
|
+
}
|
|
227
|
+
// 2. Explicit await operator
|
|
228
|
+
if (ts.isAwaitExpression(unwrapped)) {
|
|
229
|
+
return { isConsumed: true, reason: "Awaited.", isRejectionHandled: true };
|
|
230
|
+
}
|
|
231
|
+
// 3. Terminal rejection handling (.catch(...) or .then(onF, onR) or .catch(...).finally(...))
|
|
232
|
+
if (hasTerminalRejectionHandling(unwrapped, ts, checker)) {
|
|
233
|
+
return { isConsumed: true, reason: "Terminal rejection handler chained.", isRejectionHandled: true };
|
|
234
|
+
}
|
|
235
|
+
// 4. Assignment to variable/cache that is subsequently returned without overwrite
|
|
236
|
+
// e.g. `cached = import(...); return cached;`
|
|
237
|
+
if (ts.isBinaryExpression(unwrapped) && unwrapped.operatorToken.kind === ts.SyntaxKind.EqualsToken) {
|
|
238
|
+
const left = unwrapExpression(unwrapped.left, ts);
|
|
239
|
+
const targetName = ts.isIdentifier(left)
|
|
240
|
+
? left.text
|
|
241
|
+
: ts.isPropertyAccessExpression(left)
|
|
242
|
+
? left.getText()
|
|
243
|
+
: undefined;
|
|
244
|
+
if (targetName && isVariableTargetReturnedInScope(unwrapped, targetName, ts)) {
|
|
245
|
+
return { isConsumed: true, reason: "Assigned Promise reaches return from enclosing function.", isRejectionHandled: true };
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
// 5. Verified framework API call based on symbol origin and argument inspection
|
|
249
|
+
if (ts.isCallExpression(unwrapped)) {
|
|
250
|
+
const frameworkCheck = evaluateFrameworkPromiseCall(unwrapped, ts, checker);
|
|
251
|
+
if (frameworkCheck.isHandled) {
|
|
252
|
+
return {
|
|
253
|
+
isConsumed: true,
|
|
254
|
+
reason: frameworkCheck.reason ?? "Verified framework API call.",
|
|
255
|
+
isRejectionHandled: true,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return { isConsumed: false, isRejectionHandled: false };
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=promiseFlow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promiseFlow.js","sourceRoot":"","sources":["../../src/analysis/promiseFlow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type * as tsType from "typescript";
|
|
2
|
+
export interface ResolvedConstantValue {
|
|
3
|
+
readonly kind: "string" | "number" | "boolean" | "null" | "undefined" | "other";
|
|
4
|
+
readonly value?: string | number | boolean | null | undefined;
|
|
5
|
+
readonly isStatic: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Strips parentheses, type assertions (as / <T>), and non-null assertions (!)
|
|
9
|
+
* to reach the underlying semantic expression.
|
|
10
|
+
*/
|
|
11
|
+
export declare function unwrapExpression(expr: tsType.Expression, ts: typeof tsType): tsType.Expression;
|
|
12
|
+
/**
|
|
13
|
+
* Resolves an expression to a static constant value if statically determinable.
|
|
14
|
+
*/
|
|
15
|
+
export declare function resolveConstantValue(expr: tsType.Expression, ts: typeof tsType, checker?: tsType.TypeChecker | undefined): ResolvedConstantValue;
|
|
16
|
+
/**
|
|
17
|
+
* Checks if an expression is a proven static reset value
|
|
18
|
+
* (e.g. 0, -1, "", null, undefined, false, static empty/populated literal object/array,
|
|
19
|
+
* or a const identifier resolving to a static constant value).
|
|
20
|
+
*
|
|
21
|
+
* NOTE: Does NOT rely on identifier naming heuristics.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isResetValue(expr: tsType.Expression, ts: typeof tsType, checker?: tsType.TypeChecker | undefined): boolean;
|
|
24
|
+
//# sourceMappingURL=values.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/analysis/values.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;IAChF,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC;IAC9D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,EAAE,EAAE,OAAO,MAAM,GAAG,MAAM,CAAC,UAAU,CAgB9F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,EAAE,EAAE,OAAO,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,GACvC,qBAAqB,CA6IvB;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,CAAC,UAAU,EACvB,EAAE,EAAE,OAAO,MAAM,EACjB,OAAO,CAAC,EAAE,MAAM,CAAC,WAAW,GAAG,SAAS,GACvC,OAAO,CAyBT"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Strips parentheses, type assertions (as / <T>), and non-null assertions (!)
|
|
3
|
+
* to reach the underlying semantic expression.
|
|
4
|
+
*/
|
|
5
|
+
export function unwrapExpression(expr, ts) {
|
|
6
|
+
let current = expr;
|
|
7
|
+
while (true) {
|
|
8
|
+
if (ts.isParenthesizedExpression(current)) {
|
|
9
|
+
current = current.expression;
|
|
10
|
+
}
|
|
11
|
+
else if (ts.isAsExpression(current)) {
|
|
12
|
+
current = current.expression;
|
|
13
|
+
}
|
|
14
|
+
else if (ts.isTypeAssertionExpression(current)) {
|
|
15
|
+
current = current.expression;
|
|
16
|
+
}
|
|
17
|
+
else if (ts.isNonNullExpression(current)) {
|
|
18
|
+
current = current.expression;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return current;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Resolves an expression to a static constant value if statically determinable.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveConstantValue(expr, ts, checker) {
|
|
30
|
+
const unwrapped = unwrapExpression(expr, ts);
|
|
31
|
+
// 1. String literal
|
|
32
|
+
if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) {
|
|
33
|
+
return { kind: "string", value: unwrapped.text, isStatic: true };
|
|
34
|
+
}
|
|
35
|
+
// 2. Numeric literal
|
|
36
|
+
if (ts.isNumericLiteral(unwrapped)) {
|
|
37
|
+
const num = Number(unwrapped.text);
|
|
38
|
+
return { kind: "number", value: Number.isNaN(num) ? undefined : num, isStatic: true };
|
|
39
|
+
}
|
|
40
|
+
// 3. Boolean literals
|
|
41
|
+
if (unwrapped.kind === ts.SyntaxKind.TrueKeyword) {
|
|
42
|
+
return { kind: "boolean", value: true, isStatic: true };
|
|
43
|
+
}
|
|
44
|
+
if (unwrapped.kind === ts.SyntaxKind.FalseKeyword) {
|
|
45
|
+
return { kind: "boolean", value: false, isStatic: true };
|
|
46
|
+
}
|
|
47
|
+
// 4. Null & undefined
|
|
48
|
+
if (unwrapped.kind === ts.SyntaxKind.NullKeyword) {
|
|
49
|
+
return { kind: "null", value: null, isStatic: true };
|
|
50
|
+
}
|
|
51
|
+
if (unwrapped.kind === ts.SyntaxKind.UndefinedKeyword ||
|
|
52
|
+
(ts.isIdentifier(unwrapped) && unwrapped.text === "undefined")) {
|
|
53
|
+
return { kind: "undefined", value: undefined, isStatic: true };
|
|
54
|
+
}
|
|
55
|
+
// 5. Unary expressions (e.g. -1, +0)
|
|
56
|
+
if (ts.isPrefixUnaryExpression(unwrapped)) {
|
|
57
|
+
if (unwrapped.operator === ts.SyntaxKind.MinusToken || unwrapped.operator === ts.SyntaxKind.PlusToken) {
|
|
58
|
+
const operand = resolveConstantValue(unwrapped.operand, ts, checker);
|
|
59
|
+
if (operand.kind === "number" && typeof operand.value === "number") {
|
|
60
|
+
const val = unwrapped.operator === ts.SyntaxKind.MinusToken ? -operand.value : operand.value;
|
|
61
|
+
return { kind: "number", value: val, isStatic: true };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// 6. Binary expressions with static operands (e.g. 1 + 1, "a" + "b")
|
|
66
|
+
if (ts.isBinaryExpression(unwrapped)) {
|
|
67
|
+
const left = resolveConstantValue(unwrapped.left, ts, checker);
|
|
68
|
+
const right = resolveConstantValue(unwrapped.right, ts, checker);
|
|
69
|
+
if (left.isStatic && right.isStatic) {
|
|
70
|
+
if (unwrapped.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
71
|
+
if (left.kind === "string" || right.kind === "string") {
|
|
72
|
+
return { kind: "string", value: `${left.value ?? ""}${right.value ?? ""}`, isStatic: true };
|
|
73
|
+
}
|
|
74
|
+
if (left.kind === "number" && right.kind === "number" && typeof left.value === "number" && typeof right.value === "number") {
|
|
75
|
+
return { kind: "number", value: left.value + right.value, isStatic: true };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (unwrapped.operatorToken.kind === ts.SyntaxKind.MinusToken) {
|
|
79
|
+
if (left.kind === "number" && right.kind === "number" && typeof left.value === "number" && typeof right.value === "number") {
|
|
80
|
+
return { kind: "number", value: left.value - right.value, isStatic: true };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// 7. Array literal
|
|
86
|
+
if (ts.isArrayLiteralExpression(unwrapped)) {
|
|
87
|
+
if (unwrapped.elements.length === 0) {
|
|
88
|
+
return { kind: "other", isStatic: true };
|
|
89
|
+
}
|
|
90
|
+
const allStatic = unwrapped.elements.every((elem) => {
|
|
91
|
+
return resolveConstantValue(elem, ts, checker).isStatic;
|
|
92
|
+
});
|
|
93
|
+
if (allStatic) {
|
|
94
|
+
return { kind: "other", isStatic: true };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// 8. Object literal
|
|
98
|
+
if (ts.isObjectLiteralExpression(unwrapped)) {
|
|
99
|
+
if (unwrapped.properties.length === 0) {
|
|
100
|
+
return { kind: "other", isStatic: true };
|
|
101
|
+
}
|
|
102
|
+
const allStatic = unwrapped.properties.every((prop) => {
|
|
103
|
+
if (ts.isPropertyAssignment(prop)) {
|
|
104
|
+
return resolveConstantValue(prop.initializer, ts, checker).isStatic;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
});
|
|
108
|
+
if (allStatic) {
|
|
109
|
+
return { kind: "other", isStatic: true };
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// 9. Identifiers -> trace symbol declaration if checker is present
|
|
113
|
+
if (ts.isIdentifier(unwrapped) && checker) {
|
|
114
|
+
const symbol = checker.getSymbolAtLocation(unwrapped);
|
|
115
|
+
if (symbol) {
|
|
116
|
+
let targetSym = symbol;
|
|
117
|
+
if (targetSym.flags & ts.SymbolFlags.Alias) {
|
|
118
|
+
try {
|
|
119
|
+
targetSym = checker.getAliasedSymbol(targetSym);
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// ignore
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
const visited = new Set();
|
|
126
|
+
while (targetSym && !visited.has(targetSym)) {
|
|
127
|
+
visited.add(targetSym);
|
|
128
|
+
const decl = targetSym.valueDeclaration ?? targetSym.declarations?.[0];
|
|
129
|
+
if (decl && ts.isVariableDeclaration(decl) && decl.initializer) {
|
|
130
|
+
// Only trace const / immutable declarations
|
|
131
|
+
const parentList = decl.parent;
|
|
132
|
+
const isConst = parentList && ts.isVariableDeclarationList(parentList) && (parentList.flags & ts.NodeFlags.Const) !== 0;
|
|
133
|
+
if (isConst) {
|
|
134
|
+
const resolved = resolveConstantValue(decl.initializer, ts, checker);
|
|
135
|
+
if (resolved.isStatic) {
|
|
136
|
+
return resolved;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
// Check literal type from checker
|
|
143
|
+
try {
|
|
144
|
+
const type = checker.getTypeAtLocation(unwrapped);
|
|
145
|
+
if (type.isStringLiteral()) {
|
|
146
|
+
return { kind: "string", value: type.value, isStatic: true };
|
|
147
|
+
}
|
|
148
|
+
if (type.isNumberLiteral()) {
|
|
149
|
+
return { kind: "number", value: type.value, isStatic: true };
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
catch {
|
|
153
|
+
// ignore
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return { kind: "other", isStatic: false };
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Checks if an expression is a proven static reset value
|
|
161
|
+
* (e.g. 0, -1, "", null, undefined, false, static empty/populated literal object/array,
|
|
162
|
+
* or a const identifier resolving to a static constant value).
|
|
163
|
+
*
|
|
164
|
+
* NOTE: Does NOT rely on identifier naming heuristics.
|
|
165
|
+
*/
|
|
166
|
+
export function isResetValue(expr, ts, checker) {
|
|
167
|
+
const unwrapped = unwrapExpression(expr, ts);
|
|
168
|
+
const resolved = resolveConstantValue(unwrapped, ts, checker);
|
|
169
|
+
if (!resolved.isStatic) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
if (resolved.kind === "number" && (resolved.value === 0 || resolved.value === -1)) {
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
if (resolved.kind === "string" && resolved.value === "") {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
if (resolved.kind === "null" || resolved.kind === "undefined") {
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
if (resolved.kind === "boolean" && resolved.value === false) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
if (resolved.kind === "other") {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=values.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"values.js","sourceRoot":"","sources":["../../src/analysis/values.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Finding } from "../core/types.js";
|
|
2
|
+
import type { BaselineFile, BaselineDelta } from "./types.js";
|
|
3
|
+
export declare const DEFAULT_BASELINE_FILENAME = ".sourceverity-baseline.json";
|
|
4
|
+
/**
|
|
5
|
+
* Creates a BaselineFile structure from a list of audit findings.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createBaseline(findings: readonly Finding[], repoRoot: string): BaselineFile;
|
|
8
|
+
/**
|
|
9
|
+
* Atomically writes a baseline file to disk.
|
|
10
|
+
*/
|
|
11
|
+
export declare function saveBaseline(baseline: BaselineFile, filePath: string): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Loads and validates a baseline file from disk. Returns null if missing or malformed.
|
|
14
|
+
*/
|
|
15
|
+
export declare function loadBaseline(filePath: string): Promise<BaselineFile | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Compares current audit findings against a baseline to determine new and resolved findings.
|
|
18
|
+
*/
|
|
19
|
+
export declare function compareWithBaseline(currentFindings: readonly Finding[], baseline: BaselineFile): BaselineDelta;
|
|
20
|
+
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/baseline/manager.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,EAAiB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE7E,eAAO,MAAM,yBAAyB,gCAAgC,CAAC;AAEvE;;GAEG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,CAsB3F;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU1F;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAYjF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,SAAS,OAAO,EAAE,EACnC,QAAQ,EAAE,YAAY,GACrB,aAAa,CAmBf"}
|