@nodesecure/js-x-ray 9.0.0 → 9.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/LICENSE +21 -21
- package/README.md +9 -209
- package/package.json +62 -77
- package/src/{AstAnalyser.js → AstAnalyser.ts} +283 -222
- package/src/{Deobfuscator.js → Deobfuscator.ts} +228 -195
- package/src/{EntryFilesAnalyser.js → EntryFilesAnalyser.ts} +206 -167
- package/src/JsSourceParser.ts +77 -0
- package/src/NodeCounter.ts +90 -0
- package/src/{ProbeRunner.js → ProbeRunner.ts} +167 -144
- package/src/SourceFile.ts +226 -0
- package/src/index.ts +5 -0
- package/src/obfuscators/freejsobfuscator.ts +17 -0
- package/src/obfuscators/{jjencode.js → jjencode.ts} +39 -27
- package/src/obfuscators/jsfuck.ts +19 -0
- package/src/obfuscators/{obfuscator-io.js → obfuscator-io.ts} +25 -13
- package/src/obfuscators/{trojan-source.js → trojan-source.ts} +3 -1
- package/src/probes/{isArrayExpression.js → isArrayExpression.ts} +12 -3
- package/src/probes/{isBinaryExpression.js → isBinaryExpression.ts} +74 -55
- package/src/probes/isESMExport.ts +50 -0
- package/src/probes/{isFetch.js → isFetch.ts} +28 -19
- package/src/probes/isImportDeclaration.ts +58 -0
- package/src/probes/{isLiteral.js → isLiteral.ts} +91 -70
- package/src/probes/isLiteralRegex.ts +42 -0
- package/src/probes/{isRegexObject.js → isRegexObject.ts} +71 -49
- package/src/probes/isRequire/RequireCallExpressionWalker.ts +142 -0
- package/src/probes/isRequire/{isRequire.js → isRequire.ts} +195 -148
- package/src/probes/isSerializeEnv.ts +65 -0
- package/src/probes/isSyncIO.ts +96 -0
- package/src/probes/isUnsafeCallee.ts +89 -0
- package/src/probes/isUnsafeCommand.ts +133 -0
- package/src/probes/isWeakCrypto.ts +69 -0
- package/src/types/estree.ts +35 -0
- package/src/utils/extractNode.ts +22 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/{exportAssignmentHasRequireLeave.js → isOneLineExpressionExport.ts} +70 -40
- package/src/utils/notNullOrUndefined.ts +5 -0
- package/src/utils/toArrayLocation.ts +22 -0
- package/src/warnings.ts +146 -0
- package/index.d.ts +0 -46
- package/index.js +0 -4
- package/src/JsSourceParser.js +0 -57
- package/src/NodeCounter.js +0 -76
- package/src/SourceFile.js +0 -147
- package/src/obfuscators/freejsobfuscator.js +0 -9
- package/src/obfuscators/jsfuck.js +0 -11
- package/src/probes/isESMExport.js +0 -31
- package/src/probes/isImportDeclaration.js +0 -33
- package/src/probes/isLiteralRegex.js +0 -31
- package/src/probes/isRequire/RequireCallExpressionWalker.js +0 -93
- package/src/probes/isUnsafeCallee.js +0 -35
- package/src/probes/isWeakCrypto.js +0 -37
- package/src/utils/extractNode.js +0 -14
- package/src/utils/index.js +0 -8
- package/src/utils/isNode.js +0 -5
- package/src/utils/isOneLineExpressionExport.js +0 -24
- package/src/utils/isUnsafeCallee.js +0 -28
- package/src/utils/notNullOrUndefined.js +0 -3
- package/src/utils/rootLocation.js +0 -3
- package/src/utils/toArrayLocation.js +0 -11
- package/src/warnings.js +0 -77
- package/types/api.d.ts +0 -177
- package/types/warnings.d.ts +0 -36
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// Import Internal Dependencies
|
|
2
|
-
import { isUnsafeCallee } from "../utils/index.js";
|
|
3
|
-
import { ProbeSignals } from "../ProbeRunner.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @description Detect unsafe statement
|
|
7
|
-
* @example
|
|
8
|
-
* eval("this");
|
|
9
|
-
* Function("return this")();
|
|
10
|
-
*/
|
|
11
|
-
function validateNode(node) {
|
|
12
|
-
return isUnsafeCallee(node);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function main(node, options) {
|
|
16
|
-
const { sourceFile, data: calleeName } = options;
|
|
17
|
-
|
|
18
|
-
if (
|
|
19
|
-
calleeName === "Function" &&
|
|
20
|
-
node.callee.arguments.length > 0 &&
|
|
21
|
-
node.callee.arguments[0].value === "return this"
|
|
22
|
-
) {
|
|
23
|
-
return ProbeSignals.Skip;
|
|
24
|
-
}
|
|
25
|
-
sourceFile.addWarning("unsafe-stmt", calleeName, node.loc);
|
|
26
|
-
|
|
27
|
-
return ProbeSignals.Skip;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export default {
|
|
31
|
-
name: "isUnsafeCallee",
|
|
32
|
-
validateNode,
|
|
33
|
-
main,
|
|
34
|
-
breakOnMatch: false
|
|
35
|
-
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// Import Third-party Dependencies
|
|
2
|
-
import { getCallExpressionIdentifier } from "@nodesecure/estree-ast-utils";
|
|
3
|
-
|
|
4
|
-
// CONSTANTS
|
|
5
|
-
const kWeakAlgorithms = new Set([
|
|
6
|
-
"md5",
|
|
7
|
-
"sha1",
|
|
8
|
-
"ripemd160",
|
|
9
|
-
"md4",
|
|
10
|
-
"md2"
|
|
11
|
-
]);
|
|
12
|
-
|
|
13
|
-
function validateNode(node, { tracer }) {
|
|
14
|
-
const id = getCallExpressionIdentifier(node);
|
|
15
|
-
if (id === null || !tracer.importedModules.has("crypto")) {
|
|
16
|
-
return [false];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const data = tracer.getDataFromIdentifier(id);
|
|
20
|
-
|
|
21
|
-
return [data !== null && data.identifierOrMemberExpr === "crypto.createHash"];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function main(node, { sourceFile }) {
|
|
25
|
-
const arg = node.arguments.at(0);
|
|
26
|
-
|
|
27
|
-
if (kWeakAlgorithms.has(arg.value)) {
|
|
28
|
-
sourceFile.addWarning("weak-crypto", arg.value, node.loc);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export default {
|
|
33
|
-
name: "isWeakCrypto",
|
|
34
|
-
validateNode,
|
|
35
|
-
main,
|
|
36
|
-
breakOnMatch: false
|
|
37
|
-
};
|
package/src/utils/extractNode.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
// Import Internal Dependencies
|
|
2
|
-
import { notNullOrUndefined } from "./notNullOrUndefined.js";
|
|
3
|
-
|
|
4
|
-
export function extractNode(expectedType) {
|
|
5
|
-
return (callback, nodes) => {
|
|
6
|
-
const finalNodes = Array.isArray(nodes) ? nodes : [nodes];
|
|
7
|
-
|
|
8
|
-
for (const node of finalNodes) {
|
|
9
|
-
if (notNullOrUndefined(node) && node.type === expectedType) {
|
|
10
|
-
callback(node);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
}
|
package/src/utils/index.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export * from "./exportAssignmentHasRequireLeave.js";
|
|
2
|
-
export * from "./extractNode.js";
|
|
3
|
-
export * from "./isOneLineExpressionExport.js";
|
|
4
|
-
export * from "./isUnsafeCallee.js";
|
|
5
|
-
export * from "./notNullOrUndefined.js";
|
|
6
|
-
export * from "./rootLocation.js";
|
|
7
|
-
export * from "./toArrayLocation.js";
|
|
8
|
-
export * from "./isNode.js";
|
package/src/utils/isNode.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
// Import Internal Dependencies
|
|
2
|
-
import { exportAssignmentHasRequireLeave } from "./exportAssignmentHasRequireLeave.js";
|
|
3
|
-
|
|
4
|
-
export function isOneLineExpressionExport(body) {
|
|
5
|
-
if (body.length === 0 || body.length > 1) {
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const [firstNode] = body;
|
|
10
|
-
if (firstNode.type !== "ExpressionStatement") {
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
switch (firstNode.expression.type) {
|
|
15
|
-
// module.exports = require('...');
|
|
16
|
-
case "AssignmentExpression":
|
|
17
|
-
return exportAssignmentHasRequireLeave(firstNode.expression.right);
|
|
18
|
-
// require('...');
|
|
19
|
-
case "CallExpression":
|
|
20
|
-
return exportAssignmentHasRequireLeave(firstNode.expression);
|
|
21
|
-
default:
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// Import Third-party Dependencies
|
|
2
|
-
import { getCallExpressionIdentifier } from "@nodesecure/estree-ast-utils";
|
|
3
|
-
|
|
4
|
-
function isEvalCallee(node) {
|
|
5
|
-
const identifier = getCallExpressionIdentifier(node, {
|
|
6
|
-
resolveCallExpression: false
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
return identifier === "eval";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function isFunctionCallee(node) {
|
|
13
|
-
const identifier = getCallExpressionIdentifier(node);
|
|
14
|
-
|
|
15
|
-
return identifier === "Function" && node.callee.type === "CallExpression";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function isUnsafeCallee(node) {
|
|
19
|
-
if (isEvalCallee(node)) {
|
|
20
|
-
return [true, "eval"];
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
if (isFunctionCallee(node)) {
|
|
24
|
-
return [true, "Function"];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return [false, null];
|
|
28
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Import Internal Dependencies
|
|
2
|
-
import { rootLocation } from "./rootLocation.js";
|
|
3
|
-
|
|
4
|
-
export function toArrayLocation(location = rootLocation()) {
|
|
5
|
-
const { start, end = start } = location;
|
|
6
|
-
|
|
7
|
-
return [
|
|
8
|
-
[start.line || 0, start.column || 0],
|
|
9
|
-
[end.line || 0, end.column || 0]
|
|
10
|
-
];
|
|
11
|
-
}
|
package/src/warnings.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
// Import Internal Dependencies
|
|
2
|
-
import { toArrayLocation } from "./utils/toArrayLocation.js";
|
|
3
|
-
import { notNullOrUndefined } from "./utils/notNullOrUndefined.js";
|
|
4
|
-
|
|
5
|
-
export const warnings = Object.freeze({
|
|
6
|
-
"parsing-error": {
|
|
7
|
-
i18n: "sast_warnings.parsing_error",
|
|
8
|
-
severity: "Information"
|
|
9
|
-
},
|
|
10
|
-
"unsafe-import": {
|
|
11
|
-
i18n: "sast_warnings.unsafe_import",
|
|
12
|
-
severity: "Warning"
|
|
13
|
-
},
|
|
14
|
-
"unsafe-regex": {
|
|
15
|
-
i18n: "sast_warnings.unsafe_regex",
|
|
16
|
-
severity: "Warning"
|
|
17
|
-
},
|
|
18
|
-
"unsafe-stmt": {
|
|
19
|
-
code: "unsafe-stmt",
|
|
20
|
-
i18n: "sast_warnings.unsafe_stmt",
|
|
21
|
-
severity: "Warning"
|
|
22
|
-
},
|
|
23
|
-
"encoded-literal": {
|
|
24
|
-
i18n: "sast_warnings.encoded_literal",
|
|
25
|
-
severity: "Information"
|
|
26
|
-
},
|
|
27
|
-
"short-identifiers": {
|
|
28
|
-
i18n: "sast_warnings.short_identifiers",
|
|
29
|
-
severity: "Warning"
|
|
30
|
-
},
|
|
31
|
-
"suspicious-literal": {
|
|
32
|
-
i18n: "sast_warnings.suspicious_literal",
|
|
33
|
-
severity: "Warning"
|
|
34
|
-
},
|
|
35
|
-
"suspicious-file": {
|
|
36
|
-
i18n: "sast_warnings.suspicious_file",
|
|
37
|
-
severity: "Critical",
|
|
38
|
-
experimental: false
|
|
39
|
-
},
|
|
40
|
-
"obfuscated-code": {
|
|
41
|
-
i18n: "sast_warnings.obfuscated_code",
|
|
42
|
-
severity: "Critical",
|
|
43
|
-
experimental: true
|
|
44
|
-
},
|
|
45
|
-
"weak-crypto": {
|
|
46
|
-
i18n: "sast_warnings.weak_crypto",
|
|
47
|
-
severity: "Information",
|
|
48
|
-
experimental: false
|
|
49
|
-
},
|
|
50
|
-
"shady-link": {
|
|
51
|
-
i18n: "sast_warnings.shady_link",
|
|
52
|
-
severity: "Warning",
|
|
53
|
-
experimental: false
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
export function generateWarning(kind, options) {
|
|
58
|
-
const { location, file = null, value = null, source = "JS-X-Ray" } = options;
|
|
59
|
-
|
|
60
|
-
if (kind === "encoded-literal") {
|
|
61
|
-
return Object.assign(
|
|
62
|
-
{ kind, value, location: [toArrayLocation(location)], source },
|
|
63
|
-
warnings[kind]
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const result = { kind, location: toArrayLocation(location), source };
|
|
68
|
-
if (notNullOrUndefined(file)) {
|
|
69
|
-
result.file = file;
|
|
70
|
-
}
|
|
71
|
-
if (notNullOrUndefined(value)) {
|
|
72
|
-
result.value = value;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return Object.assign(result, warnings[kind]);
|
|
76
|
-
}
|
|
77
|
-
|
package/types/api.d.ts
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
// Third-party
|
|
2
|
-
import type { DiGraph, VertexDefinition, VertexBody } from "digraph-js";
|
|
3
|
-
import { Statement } from "meriyah";
|
|
4
|
-
|
|
5
|
-
// Internal
|
|
6
|
-
import {
|
|
7
|
-
Warning,
|
|
8
|
-
WarningName
|
|
9
|
-
} from "./warnings.js";
|
|
10
|
-
|
|
11
|
-
export {
|
|
12
|
-
AstAnalyser,
|
|
13
|
-
AstAnalyserOptions,
|
|
14
|
-
|
|
15
|
-
EntryFilesAnalyser,
|
|
16
|
-
EntryFilesAnalyserOptions,
|
|
17
|
-
|
|
18
|
-
JsSourceParser,
|
|
19
|
-
SourceParser,
|
|
20
|
-
|
|
21
|
-
RuntimeOptions,
|
|
22
|
-
RuntimeFileOptions,
|
|
23
|
-
|
|
24
|
-
Report,
|
|
25
|
-
ReportOnFile,
|
|
26
|
-
|
|
27
|
-
SourceFlags,
|
|
28
|
-
SourceLocation,
|
|
29
|
-
Dependency
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
type SourceFlags =
|
|
33
|
-
| "fetch"
|
|
34
|
-
| "oneline-require"
|
|
35
|
-
| "is-minified";
|
|
36
|
-
|
|
37
|
-
interface SourceLocation {
|
|
38
|
-
start: {
|
|
39
|
-
line: number;
|
|
40
|
-
column: number;
|
|
41
|
-
};
|
|
42
|
-
end: {
|
|
43
|
-
line: number;
|
|
44
|
-
column: number;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
interface Dependency {
|
|
49
|
-
unsafe: boolean;
|
|
50
|
-
inTry: boolean;
|
|
51
|
-
location?: null | SourceLocation;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
interface RuntimeOptions {
|
|
55
|
-
/**
|
|
56
|
-
* @default true
|
|
57
|
-
*/
|
|
58
|
-
module?: boolean;
|
|
59
|
-
/**
|
|
60
|
-
* @default false
|
|
61
|
-
*/
|
|
62
|
-
removeHTMLComments?: boolean;
|
|
63
|
-
/**
|
|
64
|
-
* @default false
|
|
65
|
-
*/
|
|
66
|
-
isMinified?: boolean;
|
|
67
|
-
initialize?: (sourceFile: SourceFile) => void;
|
|
68
|
-
finalize?: (sourceFile: SourceFile) => void;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
interface RuntimeFileOptions extends Omit<RuntimeOptions, "isMinified"> {
|
|
72
|
-
packageName?: string;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface AstAnalyserOptions {
|
|
76
|
-
/**
|
|
77
|
-
* @default JsSourceParser
|
|
78
|
-
*/
|
|
79
|
-
customParser?: SourceParser;
|
|
80
|
-
/**
|
|
81
|
-
* @default []
|
|
82
|
-
*/
|
|
83
|
-
customProbes?: Probe[];
|
|
84
|
-
/**
|
|
85
|
-
* @default false
|
|
86
|
-
*/
|
|
87
|
-
skipDefaultProbes?: boolean;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
interface Probe {
|
|
91
|
-
validateNode: Function | Function[];
|
|
92
|
-
main: Function;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
interface Report {
|
|
96
|
-
dependencies: Map<string, Dependency>;
|
|
97
|
-
warnings: Warning[];
|
|
98
|
-
flags: Set<SourceFlags>;
|
|
99
|
-
idsLengthAvg: number;
|
|
100
|
-
stringScore: number;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
type ReportOnFile = {
|
|
104
|
-
ok: true,
|
|
105
|
-
warnings: Warning[];
|
|
106
|
-
dependencies: Map<string, Dependency>;
|
|
107
|
-
flags: Set<SourceFlags>;
|
|
108
|
-
} | {
|
|
109
|
-
ok: false,
|
|
110
|
-
warnings: Warning[];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
interface SourceParser {
|
|
114
|
-
parse(source: string, options: unknown): Statement[];
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
declare class AstAnalyser {
|
|
118
|
-
constructor(options?: AstAnalyserOptions);
|
|
119
|
-
analyse: (
|
|
120
|
-
str: string,
|
|
121
|
-
options?: RuntimeOptions
|
|
122
|
-
) => Report;
|
|
123
|
-
analyseFile(
|
|
124
|
-
pathToFile: string,
|
|
125
|
-
options?: RuntimeFileOptions
|
|
126
|
-
): Promise<ReportOnFile>;
|
|
127
|
-
analyseFileSync(
|
|
128
|
-
pathToFile: string,
|
|
129
|
-
options?: RuntimeFileOptions
|
|
130
|
-
): ReportOnFile;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
declare class SourceFile {
|
|
134
|
-
flags: Set<SourceFlags>;
|
|
135
|
-
|
|
136
|
-
constructor(source: string, options: any);
|
|
137
|
-
addDependency(
|
|
138
|
-
name: string,
|
|
139
|
-
location?: string | null,
|
|
140
|
-
unsafe?: boolean
|
|
141
|
-
): void;
|
|
142
|
-
addWarning(
|
|
143
|
-
name: WarningName,
|
|
144
|
-
value: string,
|
|
145
|
-
location?: any
|
|
146
|
-
): void;
|
|
147
|
-
analyzeLiteral(node: any, inArrayExpr?: boolean): void;
|
|
148
|
-
getResult(isMinified: boolean): any;
|
|
149
|
-
walk(node: any): "skip" | null;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
interface EntryFilesAnalyserOptions {
|
|
153
|
-
astAnalyzer?: AstAnalyser;
|
|
154
|
-
loadExtensions?: (defaults: string[]) => string[];
|
|
155
|
-
rootPath?: string | URL;
|
|
156
|
-
ignoreENOENT?: boolean;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
declare class EntryFilesAnalyser {
|
|
160
|
-
public astAnalyzer: AstAnalyser;
|
|
161
|
-
public allowedExtensions: Set<string>;
|
|
162
|
-
public dependencies: DiGraph<VertexDefinition<VertexBody>>;
|
|
163
|
-
|
|
164
|
-
constructor(options?: EntryFilesAnalyserOptions);
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Asynchronously analyze a set of entry files yielding analysis reports.
|
|
168
|
-
*/
|
|
169
|
-
analyse(
|
|
170
|
-
entryFiles: Iterable<string | URL>,
|
|
171
|
-
options?: RuntimeFileOptions
|
|
172
|
-
): AsyncGenerator<ReportOnFile & { file: string }>;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
declare class JsSourceParser implements SourceParser {
|
|
176
|
-
parse(source: string, options: unknown): Statement[];
|
|
177
|
-
}
|
package/types/warnings.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export {
|
|
3
|
-
Warning,
|
|
4
|
-
WarningDefault,
|
|
5
|
-
WarningLocation,
|
|
6
|
-
WarningName,
|
|
7
|
-
WarningNameWithValue
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
type WarningNameWithValue = "parsing-error"
|
|
11
|
-
| "encoded-literal"
|
|
12
|
-
| "unsafe-regex"
|
|
13
|
-
| "unsafe-stmt"
|
|
14
|
-
| "short-identifiers"
|
|
15
|
-
| "suspicious-literal"
|
|
16
|
-
| "suspicious-file"
|
|
17
|
-
| "obfuscated-code"
|
|
18
|
-
| "weak-crypto"
|
|
19
|
-
| "shady-link";
|
|
20
|
-
type WarningName = WarningNameWithValue | "unsafe-import";
|
|
21
|
-
|
|
22
|
-
type WarningLocation = [[number, number], [number, number]];
|
|
23
|
-
|
|
24
|
-
interface WarningDefault<T = WarningName> {
|
|
25
|
-
kind: T;
|
|
26
|
-
file?: string;
|
|
27
|
-
value: string;
|
|
28
|
-
source: string;
|
|
29
|
-
location: null | WarningLocation | WarningLocation[];
|
|
30
|
-
i18n: string;
|
|
31
|
-
severity: "Information" | "Warning" | "Critical";
|
|
32
|
-
experimental?: boolean;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
type Warning<T extends WarningDefault = WarningDefault> =
|
|
36
|
-
T extends { kind: WarningNameWithValue } ? T : Omit<T, "value">;
|