@stll/oxlint-plugin 0.2.2 → 0.4.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/index.cjs +26 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -1
- package/dist/index.d.mts +14 -1
- package/dist/index.mjs +20 -1
- package/dist/index.mjs.map +1 -1
- package/dist/no-any-casts.cjs.map +1 -1
- package/dist/no-checkout-writes-in-tests.cjs +115 -0
- package/dist/no-checkout-writes-in-tests.cjs.map +1 -0
- package/dist/no-checkout-writes-in-tests.d.cts +4 -0
- package/dist/no-checkout-writes-in-tests.d.mts +5 -0
- package/dist/no-checkout-writes-in-tests.mjs +111 -0
- package/dist/no-checkout-writes-in-tests.mjs.map +1 -0
- package/dist/no-dangerous-type-assertions.cjs.map +1 -1
- package/dist/no-partial-record-satisfies.cjs.map +1 -1
- package/dist/no-partial-record-satisfies.mjs +1 -1
- package/dist/no-raw-route-query-client.cjs.map +1 -1
- package/dist/no-raw-route-query-client.mjs +1 -1
- package/dist/no-real-network-in-tests.cjs +71 -0
- package/dist/no-real-network-in-tests.cjs.map +1 -0
- package/dist/no-real-network-in-tests.d.cts +4 -0
- package/dist/no-real-network-in-tests.d.mts +5 -0
- package/dist/no-real-network-in-tests.mjs +67 -0
- package/dist/no-real-network-in-tests.mjs.map +1 -0
- package/dist/no-real-timer-waits-in-tests.cjs +32 -0
- package/dist/no-real-timer-waits-in-tests.cjs.map +1 -0
- package/dist/no-real-timer-waits-in-tests.d.cts +4 -0
- package/dist/no-real-timer-waits-in-tests.d.mts +5 -0
- package/dist/no-real-timer-waits-in-tests.mjs +28 -0
- package/dist/no-real-timer-waits-in-tests.mjs.map +1 -0
- package/dist/no-unsafe-inner-html.cjs +458 -66
- package/dist/no-unsafe-inner-html.cjs.map +1 -1
- package/dist/no-unsafe-inner-html.d.cts +106 -1
- package/dist/no-unsafe-inner-html.d.mts +105 -1
- package/dist/no-unsafe-inner-html.mjs +458 -68
- package/dist/no-unsafe-inner-html.mjs.map +1 -1
- package/dist/no-unseeded-random-in-tests.cjs +25 -0
- package/dist/no-unseeded-random-in-tests.cjs.map +1 -0
- package/dist/no-unseeded-random-in-tests.d.cts +4 -0
- package/dist/no-unseeded-random-in-tests.d.mts +5 -0
- package/dist/no-unseeded-random-in-tests.mjs +21 -0
- package/dist/no-unseeded-random-in-tests.mjs.map +1 -0
- package/dist/no-wall-clock-in-tests.cjs +35 -0
- package/dist/no-wall-clock-in-tests.cjs.map +1 -0
- package/dist/no-wall-clock-in-tests.d.cts +4 -0
- package/dist/no-wall-clock-in-tests.d.mts +5 -0
- package/dist/no-wall-clock-in-tests.mjs +31 -0
- package/dist/no-wall-clock-in-tests.mjs.map +1 -0
- package/dist/require-loader-prefetch.cjs +8 -7
- package/dist/require-loader-prefetch.cjs.map +1 -1
- package/dist/require-loader-prefetch.mjs +8 -7
- package/dist/require-loader-prefetch.mjs.map +1 -1
- package/dist/test-rule-utils.cjs +143 -0
- package/dist/test-rule-utils.cjs.map +1 -0
- package/dist/test-rule-utils.mjs +114 -0
- package/dist/test-rule-utils.mjs.map +1 -0
- package/dist/utils.cjs +85 -10
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.mjs +54 -9
- package/dist/utils.mjs.map +1 -1
- package/package.json +57 -2
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
const require_test_rule_utils = require("./test-rule-utils.cjs");
|
|
6
|
+
//#region src/no-real-network-in-tests.ts
|
|
7
|
+
const ipv4Loopback = /^127(?:\.\d{1,3}){3}$/u;
|
|
8
|
+
const urlText = (value, resolveBinding) => {
|
|
9
|
+
if (!require_test_rule_utils.isNode(value)) return null;
|
|
10
|
+
if (value.type === "Literal" && typeof value.value === "string") return value.value;
|
|
11
|
+
if (value.type === "TemplateLiteral" && Array.isArray(value.quasis) && Array.isArray(value.expressions)) {
|
|
12
|
+
let text = "";
|
|
13
|
+
for (const [index, part] of value.quasis.entries()) {
|
|
14
|
+
const raw = require_test_rule_utils.isNode(part) ? Reflect.get(part.value ?? {}, "raw") : null;
|
|
15
|
+
if (typeof raw !== "string") return null;
|
|
16
|
+
text += raw;
|
|
17
|
+
const expression = value.expressions.at(index);
|
|
18
|
+
if (expression === void 0) continue;
|
|
19
|
+
const resolved = urlText(expression, resolveBinding);
|
|
20
|
+
if (resolved === null) return null;
|
|
21
|
+
text += resolved;
|
|
22
|
+
}
|
|
23
|
+
return text;
|
|
24
|
+
}
|
|
25
|
+
if (value.type === "Identifier") {
|
|
26
|
+
const binding = resolveBinding(value);
|
|
27
|
+
return binding.type === "const" ? urlText(binding.initializer, resolveBinding) : null;
|
|
28
|
+
}
|
|
29
|
+
if (value.type === "NewExpression" && require_test_rule_utils.isNode(value.callee) && resolveBinding(value.callee).type === "global" && require_test_rule_utils.identifierName(value.callee) === "URL" && Array.isArray(value.arguments)) return urlText(value.arguments.at(0), resolveBinding);
|
|
30
|
+
return null;
|
|
31
|
+
};
|
|
32
|
+
const external = (value, resolveBinding) => {
|
|
33
|
+
const text = urlText(value, resolveBinding);
|
|
34
|
+
if (text === null) return false;
|
|
35
|
+
try {
|
|
36
|
+
const { hostname: host, protocol } = new URL(text);
|
|
37
|
+
if (![
|
|
38
|
+
"http:",
|
|
39
|
+
"https:",
|
|
40
|
+
"ws:",
|
|
41
|
+
"wss:"
|
|
42
|
+
].includes(protocol) || host === "") return false;
|
|
43
|
+
return host !== "localhost" && !ipv4Loopback.test(host) && host !== "::1" && host !== "[::1]" && !host.endsWith(".localhost");
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var no_real_network_in_tests_default = require_test_rule_utils.testOnlyPlugin("no-real-network-in-tests", "noRealNetwork", "Use @stll/test-kit's withFakeServer instead of real network access in tests.", (report, getScope) => {
|
|
49
|
+
const resolveBinding = require_test_rule_utils.createBindingResolver(getScope);
|
|
50
|
+
const isGlobalCallee = (value, name) => {
|
|
51
|
+
if (!require_test_rule_utils.isNode(value)) return false;
|
|
52
|
+
if (value.type === "Identifier") {
|
|
53
|
+
const binding = resolveBinding(value);
|
|
54
|
+
return binding.type === "global" && binding.name === name;
|
|
55
|
+
}
|
|
56
|
+
if (value.type !== "MemberExpression" || require_test_rule_utils.propertyName(value.property) !== name) return false;
|
|
57
|
+
return require_test_rule_utils.isNode(value.object) && resolveBinding(value.object).type === "global" && require_test_rule_utils.identifierName(value.object) === "globalThis";
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
CallExpression(node) {
|
|
61
|
+
if (isGlobalCallee(node.callee, "fetch") && Array.isArray(node.arguments) && external(node.arguments.at(0), resolveBinding)) report(node);
|
|
62
|
+
},
|
|
63
|
+
NewExpression(node) {
|
|
64
|
+
if ((isGlobalCallee(node.callee, "WebSocket") || isGlobalCallee(node.callee, "EventSource")) && Array.isArray(node.arguments) && external(node.arguments.at(0), resolveBinding)) report(node);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
//#endregion
|
|
69
|
+
exports.default = no_real_network_in_tests_default;
|
|
70
|
+
|
|
71
|
+
//# sourceMappingURL=no-real-network-in-tests.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-real-network-in-tests.cjs","names":["isNode","identifierName","testOnlyPlugin","createBindingResolver","propertyName"],"sources":["../src/no-real-network-in-tests.ts"],"sourcesContent":["import {\n createBindingResolver,\n identifierName,\n isNode,\n propertyName,\n testOnlyPlugin,\n} from \"./test-rule-utils\";\n\nconst ipv4Loopback = /^127(?:\\.\\d{1,3}){3}$/u;\n\nconst urlText = (\n value: unknown,\n resolveBinding: ReturnType<typeof createBindingResolver>,\n): string | null => {\n if (!isNode(value)) return null;\n if (value.type === \"Literal\" && typeof value.value === \"string\")\n return value.value;\n if (\n value.type === \"TemplateLiteral\" &&\n Array.isArray(value.quasis) &&\n Array.isArray(value.expressions)\n ) {\n let text = \"\";\n for (const [index, part] of value.quasis.entries()) {\n const raw = isNode(part) ? Reflect.get(part.value ?? {}, \"raw\") : null;\n if (typeof raw !== \"string\") return null;\n text += raw;\n const expression = value.expressions.at(index);\n if (expression === undefined) continue;\n const resolved = urlText(expression, resolveBinding);\n if (resolved === null) return null;\n text += resolved;\n }\n return text;\n }\n if (value.type === \"Identifier\") {\n const binding = resolveBinding(value);\n return binding.type === \"const\"\n ? urlText(binding.initializer, resolveBinding)\n : null;\n }\n if (\n value.type === \"NewExpression\" &&\n isNode(value.callee) &&\n resolveBinding(value.callee).type === \"global\" &&\n identifierName(value.callee) === \"URL\" &&\n Array.isArray(value.arguments)\n )\n return urlText(value.arguments.at(0), resolveBinding);\n return null;\n};\nconst external = (\n value: unknown,\n resolveBinding: ReturnType<typeof createBindingResolver>,\n): boolean => {\n const text = urlText(value, resolveBinding);\n if (text === null) return false;\n try {\n const { hostname: host, protocol } = new URL(text);\n if (![\"http:\", \"https:\", \"ws:\", \"wss:\"].includes(protocol) || host === \"\")\n return false;\n return (\n host !== \"localhost\" &&\n !ipv4Loopback.test(host) &&\n host !== \"::1\" &&\n host !== \"[::1]\" &&\n !host.endsWith(\".localhost\")\n );\n } catch {\n return false;\n }\n};\n\nexport default testOnlyPlugin(\n \"no-real-network-in-tests\",\n \"noRealNetwork\",\n \"Use @stll/test-kit's withFakeServer instead of real network access in tests.\",\n (report, getScope) => {\n const resolveBinding = createBindingResolver(getScope);\n const isGlobalCallee = (value: unknown, name: string): boolean => {\n if (!isNode(value)) return false;\n if (value.type === \"Identifier\") {\n const binding = resolveBinding(value);\n return binding.type === \"global\" && binding.name === name;\n }\n if (\n value.type !== \"MemberExpression\" ||\n propertyName(value.property) !== name\n )\n return false;\n return (\n isNode(value.object) &&\n resolveBinding(value.object).type === \"global\" &&\n identifierName(value.object) === \"globalThis\"\n );\n };\n return {\n CallExpression(node) {\n if (\n isGlobalCallee(node.callee, \"fetch\") &&\n Array.isArray(node.arguments) &&\n external(node.arguments.at(0), resolveBinding)\n )\n report(node);\n },\n NewExpression(node) {\n if (\n (isGlobalCallee(node.callee, \"WebSocket\") ||\n isGlobalCallee(node.callee, \"EventSource\")) &&\n Array.isArray(node.arguments) &&\n external(node.arguments.at(0), resolveBinding)\n )\n report(node);\n },\n };\n },\n);\n"],"mappings":";;;;;;AAQA,MAAM,eAAe;AAErB,MAAM,WACJ,OACA,mBACkB;CAClB,IAAI,CAACA,wBAAAA,OAAO,KAAK,GAAG,OAAO;CAC3B,IAAI,MAAM,SAAS,aAAa,OAAO,MAAM,UAAU,UACrD,OAAO,MAAM;CACf,IACE,MAAM,SAAS,qBACf,MAAM,QAAQ,MAAM,MAAM,KAC1B,MAAM,QAAQ,MAAM,WAAW,GAC/B;EACA,IAAI,OAAO;EACX,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,OAAO,QAAQ,GAAG;GAClD,MAAM,MAAMA,wBAAAA,OAAO,IAAI,IAAI,QAAQ,IAAI,KAAK,SAAS,CAAC,GAAG,KAAK,IAAI;GAClE,IAAI,OAAO,QAAQ,UAAU,OAAO;GACpC,QAAQ;GACR,MAAM,aAAa,MAAM,YAAY,GAAG,KAAK;GAC7C,IAAI,eAAe,KAAA,GAAW;GAC9B,MAAM,WAAW,QAAQ,YAAY,cAAc;GACnD,IAAI,aAAa,MAAM,OAAO;GAC9B,QAAQ;EACV;EACA,OAAO;CACT;CACA,IAAI,MAAM,SAAS,cAAc;EAC/B,MAAM,UAAU,eAAe,KAAK;EACpC,OAAO,QAAQ,SAAS,UACpB,QAAQ,QAAQ,aAAa,cAAc,IAC3C;CACN;CACA,IACE,MAAM,SAAS,mBACfA,wBAAAA,OAAO,MAAM,MAAM,KACnB,eAAe,MAAM,MAAM,CAAC,CAAC,SAAS,YACtCC,wBAAAA,eAAe,MAAM,MAAM,MAAM,SACjC,MAAM,QAAQ,MAAM,SAAS,GAE7B,OAAO,QAAQ,MAAM,UAAU,GAAG,CAAC,GAAG,cAAc;CACtD,OAAO;AACT;AACA,MAAM,YACJ,OACA,mBACY;CACZ,MAAM,OAAO,QAAQ,OAAO,cAAc;CAC1C,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI;EACF,MAAM,EAAE,UAAU,MAAM,aAAa,IAAI,IAAI,IAAI;EACjD,IAAI,CAAC;GAAC;GAAS;GAAU;GAAO;EAAM,CAAC,CAAC,SAAS,QAAQ,KAAK,SAAS,IACrE,OAAO;EACT,OACE,SAAS,eACT,CAAC,aAAa,KAAK,IAAI,KACvB,SAAS,SACT,SAAS,WACT,CAAC,KAAK,SAAS,YAAY;CAE/B,QAAQ;EACN,OAAO;CACT;AACF;AAEA,IAAA,mCAAeC,wBAAAA,eACb,4BACA,iBACA,iFACC,QAAQ,aAAa;CACpB,MAAM,iBAAiBC,wBAAAA,sBAAsB,QAAQ;CACrD,MAAM,kBAAkB,OAAgB,SAA0B;EAChE,IAAI,CAACH,wBAAAA,OAAO,KAAK,GAAG,OAAO;EAC3B,IAAI,MAAM,SAAS,cAAc;GAC/B,MAAM,UAAU,eAAe,KAAK;GACpC,OAAO,QAAQ,SAAS,YAAY,QAAQ,SAAS;EACvD;EACA,IACE,MAAM,SAAS,sBACfI,wBAAAA,aAAa,MAAM,QAAQ,MAAM,MAEjC,OAAO;EACT,OACEJ,wBAAAA,OAAO,MAAM,MAAM,KACnB,eAAe,MAAM,MAAM,CAAC,CAAC,SAAS,YACtCC,wBAAAA,eAAe,MAAM,MAAM,MAAM;CAErC;CACA,OAAO;EACL,eAAe,MAAM;GACnB,IACE,eAAe,KAAK,QAAQ,OAAO,KACnC,MAAM,QAAQ,KAAK,SAAS,KAC5B,SAAS,KAAK,UAAU,GAAG,CAAC,GAAG,cAAc,GAE7C,OAAO,IAAI;EACf;EACA,cAAc,MAAM;GAClB,KACG,eAAe,KAAK,QAAQ,WAAW,KACtC,eAAe,KAAK,QAAQ,aAAa,MAC3C,MAAM,QAAQ,KAAK,SAAS,KAC5B,SAAS,KAAK,UAAU,GAAG,CAAC,GAAG,cAAc,GAE7C,OAAO,IAAI;EACf;CACF;AACF,CACF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { a as testOnlyPlugin, i as propertyName, n as identifierName, r as isNode, t as createBindingResolver } from "./test-rule-utils.mjs";
|
|
2
|
+
//#region src/no-real-network-in-tests.ts
|
|
3
|
+
const ipv4Loopback = /^127(?:\.\d{1,3}){3}$/u;
|
|
4
|
+
const urlText = (value, resolveBinding) => {
|
|
5
|
+
if (!isNode(value)) return null;
|
|
6
|
+
if (value.type === "Literal" && typeof value.value === "string") return value.value;
|
|
7
|
+
if (value.type === "TemplateLiteral" && Array.isArray(value.quasis) && Array.isArray(value.expressions)) {
|
|
8
|
+
let text = "";
|
|
9
|
+
for (const [index, part] of value.quasis.entries()) {
|
|
10
|
+
const raw = isNode(part) ? Reflect.get(part.value ?? {}, "raw") : null;
|
|
11
|
+
if (typeof raw !== "string") return null;
|
|
12
|
+
text += raw;
|
|
13
|
+
const expression = value.expressions.at(index);
|
|
14
|
+
if (expression === void 0) continue;
|
|
15
|
+
const resolved = urlText(expression, resolveBinding);
|
|
16
|
+
if (resolved === null) return null;
|
|
17
|
+
text += resolved;
|
|
18
|
+
}
|
|
19
|
+
return text;
|
|
20
|
+
}
|
|
21
|
+
if (value.type === "Identifier") {
|
|
22
|
+
const binding = resolveBinding(value);
|
|
23
|
+
return binding.type === "const" ? urlText(binding.initializer, resolveBinding) : null;
|
|
24
|
+
}
|
|
25
|
+
if (value.type === "NewExpression" && isNode(value.callee) && resolveBinding(value.callee).type === "global" && identifierName(value.callee) === "URL" && Array.isArray(value.arguments)) return urlText(value.arguments.at(0), resolveBinding);
|
|
26
|
+
return null;
|
|
27
|
+
};
|
|
28
|
+
const external = (value, resolveBinding) => {
|
|
29
|
+
const text = urlText(value, resolveBinding);
|
|
30
|
+
if (text === null) return false;
|
|
31
|
+
try {
|
|
32
|
+
const { hostname: host, protocol } = new URL(text);
|
|
33
|
+
if (![
|
|
34
|
+
"http:",
|
|
35
|
+
"https:",
|
|
36
|
+
"ws:",
|
|
37
|
+
"wss:"
|
|
38
|
+
].includes(protocol) || host === "") return false;
|
|
39
|
+
return host !== "localhost" && !ipv4Loopback.test(host) && host !== "::1" && host !== "[::1]" && !host.endsWith(".localhost");
|
|
40
|
+
} catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
var no_real_network_in_tests_default = testOnlyPlugin("no-real-network-in-tests", "noRealNetwork", "Use @stll/test-kit's withFakeServer instead of real network access in tests.", (report, getScope) => {
|
|
45
|
+
const resolveBinding = createBindingResolver(getScope);
|
|
46
|
+
const isGlobalCallee = (value, name) => {
|
|
47
|
+
if (!isNode(value)) return false;
|
|
48
|
+
if (value.type === "Identifier") {
|
|
49
|
+
const binding = resolveBinding(value);
|
|
50
|
+
return binding.type === "global" && binding.name === name;
|
|
51
|
+
}
|
|
52
|
+
if (value.type !== "MemberExpression" || propertyName(value.property) !== name) return false;
|
|
53
|
+
return isNode(value.object) && resolveBinding(value.object).type === "global" && identifierName(value.object) === "globalThis";
|
|
54
|
+
};
|
|
55
|
+
return {
|
|
56
|
+
CallExpression(node) {
|
|
57
|
+
if (isGlobalCallee(node.callee, "fetch") && Array.isArray(node.arguments) && external(node.arguments.at(0), resolveBinding)) report(node);
|
|
58
|
+
},
|
|
59
|
+
NewExpression(node) {
|
|
60
|
+
if ((isGlobalCallee(node.callee, "WebSocket") || isGlobalCallee(node.callee, "EventSource")) && Array.isArray(node.arguments) && external(node.arguments.at(0), resolveBinding)) report(node);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
//#endregion
|
|
65
|
+
export { no_real_network_in_tests_default as default };
|
|
66
|
+
|
|
67
|
+
//# sourceMappingURL=no-real-network-in-tests.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-real-network-in-tests.mjs","names":[],"sources":["../src/no-real-network-in-tests.ts"],"sourcesContent":["import {\n createBindingResolver,\n identifierName,\n isNode,\n propertyName,\n testOnlyPlugin,\n} from \"./test-rule-utils\";\n\nconst ipv4Loopback = /^127(?:\\.\\d{1,3}){3}$/u;\n\nconst urlText = (\n value: unknown,\n resolveBinding: ReturnType<typeof createBindingResolver>,\n): string | null => {\n if (!isNode(value)) return null;\n if (value.type === \"Literal\" && typeof value.value === \"string\")\n return value.value;\n if (\n value.type === \"TemplateLiteral\" &&\n Array.isArray(value.quasis) &&\n Array.isArray(value.expressions)\n ) {\n let text = \"\";\n for (const [index, part] of value.quasis.entries()) {\n const raw = isNode(part) ? Reflect.get(part.value ?? {}, \"raw\") : null;\n if (typeof raw !== \"string\") return null;\n text += raw;\n const expression = value.expressions.at(index);\n if (expression === undefined) continue;\n const resolved = urlText(expression, resolveBinding);\n if (resolved === null) return null;\n text += resolved;\n }\n return text;\n }\n if (value.type === \"Identifier\") {\n const binding = resolveBinding(value);\n return binding.type === \"const\"\n ? urlText(binding.initializer, resolveBinding)\n : null;\n }\n if (\n value.type === \"NewExpression\" &&\n isNode(value.callee) &&\n resolveBinding(value.callee).type === \"global\" &&\n identifierName(value.callee) === \"URL\" &&\n Array.isArray(value.arguments)\n )\n return urlText(value.arguments.at(0), resolveBinding);\n return null;\n};\nconst external = (\n value: unknown,\n resolveBinding: ReturnType<typeof createBindingResolver>,\n): boolean => {\n const text = urlText(value, resolveBinding);\n if (text === null) return false;\n try {\n const { hostname: host, protocol } = new URL(text);\n if (![\"http:\", \"https:\", \"ws:\", \"wss:\"].includes(protocol) || host === \"\")\n return false;\n return (\n host !== \"localhost\" &&\n !ipv4Loopback.test(host) &&\n host !== \"::1\" &&\n host !== \"[::1]\" &&\n !host.endsWith(\".localhost\")\n );\n } catch {\n return false;\n }\n};\n\nexport default testOnlyPlugin(\n \"no-real-network-in-tests\",\n \"noRealNetwork\",\n \"Use @stll/test-kit's withFakeServer instead of real network access in tests.\",\n (report, getScope) => {\n const resolveBinding = createBindingResolver(getScope);\n const isGlobalCallee = (value: unknown, name: string): boolean => {\n if (!isNode(value)) return false;\n if (value.type === \"Identifier\") {\n const binding = resolveBinding(value);\n return binding.type === \"global\" && binding.name === name;\n }\n if (\n value.type !== \"MemberExpression\" ||\n propertyName(value.property) !== name\n )\n return false;\n return (\n isNode(value.object) &&\n resolveBinding(value.object).type === \"global\" &&\n identifierName(value.object) === \"globalThis\"\n );\n };\n return {\n CallExpression(node) {\n if (\n isGlobalCallee(node.callee, \"fetch\") &&\n Array.isArray(node.arguments) &&\n external(node.arguments.at(0), resolveBinding)\n )\n report(node);\n },\n NewExpression(node) {\n if (\n (isGlobalCallee(node.callee, \"WebSocket\") ||\n isGlobalCallee(node.callee, \"EventSource\")) &&\n Array.isArray(node.arguments) &&\n external(node.arguments.at(0), resolveBinding)\n )\n report(node);\n },\n };\n },\n);\n"],"mappings":";;AAQA,MAAM,eAAe;AAErB,MAAM,WACJ,OACA,mBACkB;CAClB,IAAI,CAAC,OAAO,KAAK,GAAG,OAAO;CAC3B,IAAI,MAAM,SAAS,aAAa,OAAO,MAAM,UAAU,UACrD,OAAO,MAAM;CACf,IACE,MAAM,SAAS,qBACf,MAAM,QAAQ,MAAM,MAAM,KAC1B,MAAM,QAAQ,MAAM,WAAW,GAC/B;EACA,IAAI,OAAO;EACX,KAAK,MAAM,CAAC,OAAO,SAAS,MAAM,OAAO,QAAQ,GAAG;GAClD,MAAM,MAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,KAAK,SAAS,CAAC,GAAG,KAAK,IAAI;GAClE,IAAI,OAAO,QAAQ,UAAU,OAAO;GACpC,QAAQ;GACR,MAAM,aAAa,MAAM,YAAY,GAAG,KAAK;GAC7C,IAAI,eAAe,KAAA,GAAW;GAC9B,MAAM,WAAW,QAAQ,YAAY,cAAc;GACnD,IAAI,aAAa,MAAM,OAAO;GAC9B,QAAQ;EACV;EACA,OAAO;CACT;CACA,IAAI,MAAM,SAAS,cAAc;EAC/B,MAAM,UAAU,eAAe,KAAK;EACpC,OAAO,QAAQ,SAAS,UACpB,QAAQ,QAAQ,aAAa,cAAc,IAC3C;CACN;CACA,IACE,MAAM,SAAS,mBACf,OAAO,MAAM,MAAM,KACnB,eAAe,MAAM,MAAM,CAAC,CAAC,SAAS,YACtC,eAAe,MAAM,MAAM,MAAM,SACjC,MAAM,QAAQ,MAAM,SAAS,GAE7B,OAAO,QAAQ,MAAM,UAAU,GAAG,CAAC,GAAG,cAAc;CACtD,OAAO;AACT;AACA,MAAM,YACJ,OACA,mBACY;CACZ,MAAM,OAAO,QAAQ,OAAO,cAAc;CAC1C,IAAI,SAAS,MAAM,OAAO;CAC1B,IAAI;EACF,MAAM,EAAE,UAAU,MAAM,aAAa,IAAI,IAAI,IAAI;EACjD,IAAI,CAAC;GAAC;GAAS;GAAU;GAAO;EAAM,CAAC,CAAC,SAAS,QAAQ,KAAK,SAAS,IACrE,OAAO;EACT,OACE,SAAS,eACT,CAAC,aAAa,KAAK,IAAI,KACvB,SAAS,SACT,SAAS,WACT,CAAC,KAAK,SAAS,YAAY;CAE/B,QAAQ;EACN,OAAO;CACT;AACF;AAEA,IAAA,mCAAe,eACb,4BACA,iBACA,iFACC,QAAQ,aAAa;CACpB,MAAM,iBAAiB,sBAAsB,QAAQ;CACrD,MAAM,kBAAkB,OAAgB,SAA0B;EAChE,IAAI,CAAC,OAAO,KAAK,GAAG,OAAO;EAC3B,IAAI,MAAM,SAAS,cAAc;GAC/B,MAAM,UAAU,eAAe,KAAK;GACpC,OAAO,QAAQ,SAAS,YAAY,QAAQ,SAAS;EACvD;EACA,IACE,MAAM,SAAS,sBACf,aAAa,MAAM,QAAQ,MAAM,MAEjC,OAAO;EACT,OACE,OAAO,MAAM,MAAM,KACnB,eAAe,MAAM,MAAM,CAAC,CAAC,SAAS,YACtC,eAAe,MAAM,MAAM,MAAM;CAErC;CACA,OAAO;EACL,eAAe,MAAM;GACnB,IACE,eAAe,KAAK,QAAQ,OAAO,KACnC,MAAM,QAAQ,KAAK,SAAS,KAC5B,SAAS,KAAK,UAAU,GAAG,CAAC,GAAG,cAAc,GAE7C,OAAO,IAAI;EACf;EACA,cAAc,MAAM;GAClB,KACG,eAAe,KAAK,QAAQ,WAAW,KACtC,eAAe,KAAK,QAAQ,aAAa,MAC3C,MAAM,QAAQ,KAAK,SAAS,KAC5B,SAAS,KAAK,UAAU,GAAG,CAAC,GAAG,cAAc,GAE7C,OAAO,IAAI;EACf;CACF;AACF,CACF"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Object.defineProperties(exports, {
|
|
2
|
+
__esModule: { value: true },
|
|
3
|
+
[Symbol.toStringTag]: { value: "Module" }
|
|
4
|
+
});
|
|
5
|
+
const require_test_rule_utils = require("./test-rule-utils.cjs");
|
|
6
|
+
//#region src/no-real-timer-waits-in-tests.ts
|
|
7
|
+
const timerModules = /* @__PURE__ */ new Set(["timers/promises", "node:timers/promises"]);
|
|
8
|
+
var no_real_timer_waits_in_tests_default = require_test_rule_utils.testOnlyPlugin("no-real-timer-waits-in-tests", "noRealTimerWait", "Use @stll/test-kit's fake timers or bounded wait instead of real timer waits.", (report, getScope) => {
|
|
9
|
+
const resolveBinding = require_test_rule_utils.createBindingResolver(getScope);
|
|
10
|
+
const isTimer = (value) => {
|
|
11
|
+
if (!require_test_rule_utils.isNode(value)) return false;
|
|
12
|
+
if (value.type === "Identifier") {
|
|
13
|
+
const binding = resolveBinding(value);
|
|
14
|
+
if (binding.type === "global") return binding.name === "setTimeout" || binding.name === "setInterval";
|
|
15
|
+
if (binding.type === "import") return timerModules.has(binding.module) && binding.imported === "setTimeout";
|
|
16
|
+
return binding.type === "const" && isTimer(binding.initializer);
|
|
17
|
+
}
|
|
18
|
+
if (value.type !== "MemberExpression") return false;
|
|
19
|
+
const object = require_test_rule_utils.isNode(value.object) ? resolveBinding(value.object) : null;
|
|
20
|
+
const property = require_test_rule_utils.propertyName(value.property);
|
|
21
|
+
if (property === "setTimeout" && object?.type === "import" && object.imported === "*" && timerModules.has(object.module)) return true;
|
|
22
|
+
if ((property === "setTimeout" || property === "setInterval") && object?.type === "global" && (object.name === "globalThis" || object.name === "window" || object.name === "self")) return true;
|
|
23
|
+
return property === "sleep" && object?.type === "global" && object.name === "Bun";
|
|
24
|
+
};
|
|
25
|
+
return { CallExpression(node) {
|
|
26
|
+
if (isTimer(node.callee)) report(node);
|
|
27
|
+
} };
|
|
28
|
+
});
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.default = no_real_timer_waits_in_tests_default;
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=no-real-timer-waits-in-tests.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-real-timer-waits-in-tests.cjs","names":["testOnlyPlugin","createBindingResolver","isNode","propertyName"],"sources":["../src/no-real-timer-waits-in-tests.ts"],"sourcesContent":["import {\n createBindingResolver,\n isNode,\n propertyName,\n testOnlyPlugin,\n} from \"./test-rule-utils\";\n\nconst timerModules = new Set([\"timers/promises\", \"node:timers/promises\"]);\n\nexport default testOnlyPlugin(\n \"no-real-timer-waits-in-tests\",\n \"noRealTimerWait\",\n \"Use @stll/test-kit's fake timers or bounded wait instead of real timer waits.\",\n (report, getScope) => {\n const resolveBinding = createBindingResolver(getScope);\n const isTimer = (value: unknown): boolean => {\n if (!isNode(value)) return false;\n if (value.type === \"Identifier\") {\n const binding = resolveBinding(value);\n if (binding.type === \"global\")\n return (\n binding.name === \"setTimeout\" || binding.name === \"setInterval\"\n );\n if (binding.type === \"import\")\n return (\n timerModules.has(binding.module) &&\n binding.imported === \"setTimeout\"\n );\n return binding.type === \"const\" && isTimer(binding.initializer);\n }\n if (value.type !== \"MemberExpression\") return false;\n const object = isNode(value.object) ? resolveBinding(value.object) : null;\n const property = propertyName(value.property);\n if (\n property === \"setTimeout\" &&\n object?.type === \"import\" &&\n object.imported === \"*\" &&\n timerModules.has(object.module)\n )\n return true;\n if (\n (property === \"setTimeout\" || property === \"setInterval\") &&\n object?.type === \"global\" &&\n (object.name === \"globalThis\" ||\n object.name === \"window\" ||\n object.name === \"self\")\n )\n return true;\n return (\n property === \"sleep\" &&\n object?.type === \"global\" &&\n object.name === \"Bun\"\n );\n };\n return {\n CallExpression(node) {\n if (isTimer(node.callee)) report(node);\n },\n };\n },\n);\n"],"mappings":";;;;;;AAOA,MAAM,+BAAe,IAAI,IAAI,CAAC,mBAAmB,sBAAsB,CAAC;AAExE,IAAA,uCAAeA,wBAAAA,eACb,gCACA,mBACA,kFACC,QAAQ,aAAa;CACpB,MAAM,iBAAiBC,wBAAAA,sBAAsB,QAAQ;CACrD,MAAM,WAAW,UAA4B;EAC3C,IAAI,CAACC,wBAAAA,OAAO,KAAK,GAAG,OAAO;EAC3B,IAAI,MAAM,SAAS,cAAc;GAC/B,MAAM,UAAU,eAAe,KAAK;GACpC,IAAI,QAAQ,SAAS,UACnB,OACE,QAAQ,SAAS,gBAAgB,QAAQ,SAAS;GAEtD,IAAI,QAAQ,SAAS,UACnB,OACE,aAAa,IAAI,QAAQ,MAAM,KAC/B,QAAQ,aAAa;GAEzB,OAAO,QAAQ,SAAS,WAAW,QAAQ,QAAQ,WAAW;EAChE;EACA,IAAI,MAAM,SAAS,oBAAoB,OAAO;EAC9C,MAAM,SAASA,wBAAAA,OAAO,MAAM,MAAM,IAAI,eAAe,MAAM,MAAM,IAAI;EACrE,MAAM,WAAWC,wBAAAA,aAAa,MAAM,QAAQ;EAC5C,IACE,aAAa,gBACb,QAAQ,SAAS,YACjB,OAAO,aAAa,OACpB,aAAa,IAAI,OAAO,MAAM,GAE9B,OAAO;EACT,KACG,aAAa,gBAAgB,aAAa,kBAC3C,QAAQ,SAAS,aAChB,OAAO,SAAS,gBACf,OAAO,SAAS,YAChB,OAAO,SAAS,SAElB,OAAO;EACT,OACE,aAAa,WACb,QAAQ,SAAS,YACjB,OAAO,SAAS;CAEpB;CACA,OAAO,EACL,eAAe,MAAM;EACnB,IAAI,QAAQ,KAAK,MAAM,GAAG,OAAO,IAAI;CACvC,EACF;AACF,CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { a as testOnlyPlugin, i as propertyName, r as isNode, t as createBindingResolver } from "./test-rule-utils.mjs";
|
|
2
|
+
//#region src/no-real-timer-waits-in-tests.ts
|
|
3
|
+
const timerModules = /* @__PURE__ */ new Set(["timers/promises", "node:timers/promises"]);
|
|
4
|
+
var no_real_timer_waits_in_tests_default = testOnlyPlugin("no-real-timer-waits-in-tests", "noRealTimerWait", "Use @stll/test-kit's fake timers or bounded wait instead of real timer waits.", (report, getScope) => {
|
|
5
|
+
const resolveBinding = createBindingResolver(getScope);
|
|
6
|
+
const isTimer = (value) => {
|
|
7
|
+
if (!isNode(value)) return false;
|
|
8
|
+
if (value.type === "Identifier") {
|
|
9
|
+
const binding = resolveBinding(value);
|
|
10
|
+
if (binding.type === "global") return binding.name === "setTimeout" || binding.name === "setInterval";
|
|
11
|
+
if (binding.type === "import") return timerModules.has(binding.module) && binding.imported === "setTimeout";
|
|
12
|
+
return binding.type === "const" && isTimer(binding.initializer);
|
|
13
|
+
}
|
|
14
|
+
if (value.type !== "MemberExpression") return false;
|
|
15
|
+
const object = isNode(value.object) ? resolveBinding(value.object) : null;
|
|
16
|
+
const property = propertyName(value.property);
|
|
17
|
+
if (property === "setTimeout" && object?.type === "import" && object.imported === "*" && timerModules.has(object.module)) return true;
|
|
18
|
+
if ((property === "setTimeout" || property === "setInterval") && object?.type === "global" && (object.name === "globalThis" || object.name === "window" || object.name === "self")) return true;
|
|
19
|
+
return property === "sleep" && object?.type === "global" && object.name === "Bun";
|
|
20
|
+
};
|
|
21
|
+
return { CallExpression(node) {
|
|
22
|
+
if (isTimer(node.callee)) report(node);
|
|
23
|
+
} };
|
|
24
|
+
});
|
|
25
|
+
//#endregion
|
|
26
|
+
export { no_real_timer_waits_in_tests_default as default };
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=no-real-timer-waits-in-tests.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-real-timer-waits-in-tests.mjs","names":[],"sources":["../src/no-real-timer-waits-in-tests.ts"],"sourcesContent":["import {\n createBindingResolver,\n isNode,\n propertyName,\n testOnlyPlugin,\n} from \"./test-rule-utils\";\n\nconst timerModules = new Set([\"timers/promises\", \"node:timers/promises\"]);\n\nexport default testOnlyPlugin(\n \"no-real-timer-waits-in-tests\",\n \"noRealTimerWait\",\n \"Use @stll/test-kit's fake timers or bounded wait instead of real timer waits.\",\n (report, getScope) => {\n const resolveBinding = createBindingResolver(getScope);\n const isTimer = (value: unknown): boolean => {\n if (!isNode(value)) return false;\n if (value.type === \"Identifier\") {\n const binding = resolveBinding(value);\n if (binding.type === \"global\")\n return (\n binding.name === \"setTimeout\" || binding.name === \"setInterval\"\n );\n if (binding.type === \"import\")\n return (\n timerModules.has(binding.module) &&\n binding.imported === \"setTimeout\"\n );\n return binding.type === \"const\" && isTimer(binding.initializer);\n }\n if (value.type !== \"MemberExpression\") return false;\n const object = isNode(value.object) ? resolveBinding(value.object) : null;\n const property = propertyName(value.property);\n if (\n property === \"setTimeout\" &&\n object?.type === \"import\" &&\n object.imported === \"*\" &&\n timerModules.has(object.module)\n )\n return true;\n if (\n (property === \"setTimeout\" || property === \"setInterval\") &&\n object?.type === \"global\" &&\n (object.name === \"globalThis\" ||\n object.name === \"window\" ||\n object.name === \"self\")\n )\n return true;\n return (\n property === \"sleep\" &&\n object?.type === \"global\" &&\n object.name === \"Bun\"\n );\n };\n return {\n CallExpression(node) {\n if (isTimer(node.callee)) report(node);\n },\n };\n },\n);\n"],"mappings":";;AAOA,MAAM,+BAAe,IAAI,IAAI,CAAC,mBAAmB,sBAAsB,CAAC;AAExE,IAAA,uCAAe,eACb,gCACA,mBACA,kFACC,QAAQ,aAAa;CACpB,MAAM,iBAAiB,sBAAsB,QAAQ;CACrD,MAAM,WAAW,UAA4B;EAC3C,IAAI,CAAC,OAAO,KAAK,GAAG,OAAO;EAC3B,IAAI,MAAM,SAAS,cAAc;GAC/B,MAAM,UAAU,eAAe,KAAK;GACpC,IAAI,QAAQ,SAAS,UACnB,OACE,QAAQ,SAAS,gBAAgB,QAAQ,SAAS;GAEtD,IAAI,QAAQ,SAAS,UACnB,OACE,aAAa,IAAI,QAAQ,MAAM,KAC/B,QAAQ,aAAa;GAEzB,OAAO,QAAQ,SAAS,WAAW,QAAQ,QAAQ,WAAW;EAChE;EACA,IAAI,MAAM,SAAS,oBAAoB,OAAO;EAC9C,MAAM,SAAS,OAAO,MAAM,MAAM,IAAI,eAAe,MAAM,MAAM,IAAI;EACrE,MAAM,WAAW,aAAa,MAAM,QAAQ;EAC5C,IACE,aAAa,gBACb,QAAQ,SAAS,YACjB,OAAO,aAAa,OACpB,aAAa,IAAI,OAAO,MAAM,GAE9B,OAAO;EACT,KACG,aAAa,gBAAgB,aAAa,kBAC3C,QAAQ,SAAS,aAChB,OAAO,SAAS,gBACf,OAAO,SAAS,YAChB,OAAO,SAAS,SAElB,OAAO;EACT,OACE,aAAa,WACb,QAAQ,SAAS,YACjB,OAAO,SAAS;CAEpB;CACA,OAAO,EACL,eAAe,MAAM;EACnB,IAAI,QAAQ,KAAK,MAAM,GAAG,OAAO,IAAI;CACvC,EACF;AACF,CACF"}
|