@timmo001/oxlint-rules 0.1.4 → 0.2.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 +12 -5
- package/dist/cli.js +184 -77
- package/dist/configs/effect.js +144 -72
- package/dist/configs/recommended.js +74 -2
- package/dist/generic/index.js +70 -0
- package/package.json +5 -2
- package/skills/add-oxlint-rule/SKILL.md +6 -2
- package/skills/install-timmo-oxlint-rules/SKILL.md +8 -8
- package/skills/release-oxlint-rules/SKILL.md +38 -0
- package/src/generic/index.ts +12 -0
- package/src/generic/rules/prefer-event-parameter-type.ts +83 -0
package/dist/configs/effect.js
CHANGED
|
@@ -102,11 +102,67 @@ var timmoEffectPlugin = eslintCompatPlugin({
|
|
|
102
102
|
});
|
|
103
103
|
var effect_default = timmoEffectPlugin;
|
|
104
104
|
|
|
105
|
-
// vendor/anti-slop/src/index.ts
|
|
105
|
+
// vendor/anti-slop/src/effect/index.ts
|
|
106
106
|
import { eslintCompatPlugin as eslintCompatPlugin2 } from "@oxlint/plugins";
|
|
107
107
|
|
|
108
|
-
// vendor/anti-slop/src/rules/no-
|
|
108
|
+
// vendor/anti-slop/src/effect/rules/no-service-constructor-imports.ts
|
|
109
109
|
import { defineRule as defineRule2 } from "@oxlint/plugins";
|
|
110
|
+
var SERVICE_CONSTRUCTOR_NAME = /^make[A-Z]/u;
|
|
111
|
+
var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/u;
|
|
112
|
+
function isProjectLocalImport(source) {
|
|
113
|
+
return source.startsWith("./") || source.startsWith("../");
|
|
114
|
+
}
|
|
115
|
+
function getImportedName(specifier) {
|
|
116
|
+
if (specifier.imported.type === "Identifier")
|
|
117
|
+
return specifier.imported.name;
|
|
118
|
+
return specifier.imported.value;
|
|
119
|
+
}
|
|
120
|
+
var noServiceConstructorImportsRule = defineRule2({
|
|
121
|
+
meta: {
|
|
122
|
+
type: "problem",
|
|
123
|
+
docs: {
|
|
124
|
+
description: "Disallow project-local make<CapabilityName> imports outside test and spec files."
|
|
125
|
+
},
|
|
126
|
+
messages: {
|
|
127
|
+
serviceConstructorImport: 'Do not import Effect service constructor "{{name}}" into runtime code. Import the owning Layer, yield the contextual service, and allow its requirements to propagate to the composition root.'
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
create(context) {
|
|
131
|
+
const isTestFile = TEST_FILE.test(context.filename.replaceAll("\\", "/"));
|
|
132
|
+
return {
|
|
133
|
+
ImportDeclaration(node) {
|
|
134
|
+
if (isTestFile || !isProjectLocalImport(node.source.value))
|
|
135
|
+
return;
|
|
136
|
+
for (const specifier of node.specifiers) {
|
|
137
|
+
if (specifier.type !== "ImportSpecifier")
|
|
138
|
+
continue;
|
|
139
|
+
const importedName = getImportedName(specifier);
|
|
140
|
+
if (!SERVICE_CONSTRUCTOR_NAME.test(importedName))
|
|
141
|
+
continue;
|
|
142
|
+
context.report({
|
|
143
|
+
node: specifier,
|
|
144
|
+
messageId: "serviceConstructorImport",
|
|
145
|
+
data: { name: importedName }
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// vendor/anti-slop/src/effect/index.ts
|
|
154
|
+
var antiSlopEffectPlugin = eslintCompatPlugin2({
|
|
155
|
+
meta: { name: "anti-slop-effect" },
|
|
156
|
+
rules: {
|
|
157
|
+
"no-service-constructor-imports": noServiceConstructorImportsRule
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
var effect_default2 = antiSlopEffectPlugin;
|
|
161
|
+
// vendor/anti-slop/src/index.ts
|
|
162
|
+
import { eslintCompatPlugin as eslintCompatPlugin3 } from "@oxlint/plugins";
|
|
163
|
+
|
|
164
|
+
// vendor/anti-slop/src/rules/no-chained-type-assertions.ts
|
|
165
|
+
import { defineRule as defineRule3 } from "@oxlint/plugins";
|
|
110
166
|
function isTypeAssertionExpression(node) {
|
|
111
167
|
return node.type === "TSAsExpression" || node.type === "TSTypeAssertion";
|
|
112
168
|
}
|
|
@@ -141,7 +197,7 @@ function isForbiddenAssertionChain(node) {
|
|
|
141
197
|
}
|
|
142
198
|
return assertionCount > 1 && hasNonConstAssertion;
|
|
143
199
|
}
|
|
144
|
-
var noChainedTypeAssertionsRule =
|
|
200
|
+
var noChainedTypeAssertionsRule = defineRule3({
|
|
145
201
|
meta: {
|
|
146
202
|
type: "problem",
|
|
147
203
|
docs: {
|
|
@@ -165,7 +221,7 @@ var noChainedTypeAssertionsRule = defineRule2({
|
|
|
165
221
|
});
|
|
166
222
|
|
|
167
223
|
// vendor/anti-slop/src/rules/no-conditional-empty-object-spread.ts
|
|
168
|
-
import { defineRule as
|
|
224
|
+
import { defineRule as defineRule4 } from "@oxlint/plugins";
|
|
169
225
|
function unwrapParentheses(node) {
|
|
170
226
|
let current = node;
|
|
171
227
|
while (current.type === "ParenthesizedExpression") {
|
|
@@ -180,7 +236,7 @@ function isConditionalEmptyObjectSpread(node) {
|
|
|
180
236
|
const conditional = unwrapParentheses(node);
|
|
181
237
|
return conditional.type === "ConditionalExpression" && (isEmptyObjectExpression(conditional.consequent) || isEmptyObjectExpression(conditional.alternate));
|
|
182
238
|
}
|
|
183
|
-
var noConditionalEmptyObjectSpreadRule =
|
|
239
|
+
var noConditionalEmptyObjectSpreadRule = defineRule4({
|
|
184
240
|
meta: {
|
|
185
241
|
type: "suggestion",
|
|
186
242
|
docs: {
|
|
@@ -204,7 +260,7 @@ var noConditionalEmptyObjectSpreadRule = defineRule3({
|
|
|
204
260
|
});
|
|
205
261
|
|
|
206
262
|
// vendor/anti-slop/src/rules/no-known-value-widening.ts
|
|
207
|
-
import { defineRule as
|
|
263
|
+
import { defineRule as defineRule5 } from "@oxlint/plugins";
|
|
208
264
|
|
|
209
265
|
// vendor/anti-slop/src/shared/lexical-type-parameters.ts
|
|
210
266
|
function isNode(value) {
|
|
@@ -903,7 +959,7 @@ function isDictionaryAccumulatorTarget(destination) {
|
|
|
903
959
|
function hasParentAssertion(node) {
|
|
904
960
|
return node.parent?.type === "TSAsExpression" || node.parent?.type === "TSTypeAssertion";
|
|
905
961
|
}
|
|
906
|
-
var noKnownValueWideningRule =
|
|
962
|
+
var noKnownValueWideningRule = defineRule5({
|
|
907
963
|
meta: {
|
|
908
964
|
type: "problem",
|
|
909
965
|
docs: {
|
|
@@ -1016,7 +1072,7 @@ var noKnownValueWideningRule = defineRule4({
|
|
|
1016
1072
|
});
|
|
1017
1073
|
|
|
1018
1074
|
// vendor/anti-slop/src/rules/no-module-mocking.ts
|
|
1019
|
-
import { defineRule as
|
|
1075
|
+
import { defineRule as defineRule6 } from "@oxlint/plugins";
|
|
1020
1076
|
var moduleMockMethods = new Set(["doMock", "mock", "unstable_mockModule"]);
|
|
1021
1077
|
function resolveVariable3(sourceCode, identifier) {
|
|
1022
1078
|
let scope = sourceCode.getScope(identifier);
|
|
@@ -1061,7 +1117,7 @@ function moduleMockCall(sourceCode, callee) {
|
|
|
1061
1117
|
const method = callee.computed ? property.type === "Literal" && (property.value === "doMock" || property.value === "mock" || property.value === "unstable_mockModule") ? property.value : null : property.type === "Identifier" ? property.name : null;
|
|
1062
1118
|
return method !== null && moduleMockMethods.has(method);
|
|
1063
1119
|
}
|
|
1064
|
-
var noModuleMockingRule =
|
|
1120
|
+
var noModuleMockingRule = defineRule6({
|
|
1065
1121
|
meta: {
|
|
1066
1122
|
type: "problem",
|
|
1067
1123
|
docs: {
|
|
@@ -1085,8 +1141,8 @@ var noModuleMockingRule = defineRule5({
|
|
|
1085
1141
|
});
|
|
1086
1142
|
|
|
1087
1143
|
// vendor/anti-slop/src/rules/no-object-parameters.ts
|
|
1088
|
-
import { defineRule as
|
|
1089
|
-
var noObjectParametersRule =
|
|
1144
|
+
import { defineRule as defineRule7 } from "@oxlint/plugins";
|
|
1145
|
+
var noObjectParametersRule = defineRule7({
|
|
1090
1146
|
meta: {
|
|
1091
1147
|
type: "problem",
|
|
1092
1148
|
docs: {
|
|
@@ -1139,7 +1195,7 @@ var noObjectParametersRule = defineRule6({
|
|
|
1139
1195
|
});
|
|
1140
1196
|
|
|
1141
1197
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1142
|
-
import { defineRule as
|
|
1198
|
+
import { defineRule as defineRule8 } from "@oxlint/plugins";
|
|
1143
1199
|
|
|
1144
1200
|
// vendor/anti-slop/src/shared/reflect-method.ts
|
|
1145
1201
|
function resolveVariable4(sourceCode, identifier) {
|
|
@@ -1170,7 +1226,7 @@ function isGlobalReflectMethodCall(sourceCode, callee, methodName) {
|
|
|
1170
1226
|
}
|
|
1171
1227
|
|
|
1172
1228
|
// vendor/anti-slop/src/rules/no-reflect-apply.ts
|
|
1173
|
-
var noReflectApplyRule =
|
|
1229
|
+
var noReflectApplyRule = defineRule8({
|
|
1174
1230
|
meta: {
|
|
1175
1231
|
type: "problem",
|
|
1176
1232
|
docs: {
|
|
@@ -1194,8 +1250,8 @@ var noReflectApplyRule = defineRule7({
|
|
|
1194
1250
|
});
|
|
1195
1251
|
|
|
1196
1252
|
// vendor/anti-slop/src/rules/no-reflect-get.ts
|
|
1197
|
-
import { defineRule as
|
|
1198
|
-
var noReflectGetRule =
|
|
1253
|
+
import { defineRule as defineRule9 } from "@oxlint/plugins";
|
|
1254
|
+
var noReflectGetRule = defineRule9({
|
|
1199
1255
|
meta: {
|
|
1200
1256
|
type: "problem",
|
|
1201
1257
|
docs: {
|
|
@@ -1219,7 +1275,7 @@ var noReflectGetRule = defineRule8({
|
|
|
1219
1275
|
});
|
|
1220
1276
|
|
|
1221
1277
|
// vendor/anti-slop/src/rules/no-runtime-typeof.ts
|
|
1222
|
-
import { defineRule as
|
|
1278
|
+
import { defineRule as defineRule10 } from "@oxlint/plugins";
|
|
1223
1279
|
function isRuntimeFunction(node) {
|
|
1224
1280
|
return node.type === "ArrowFunctionExpression" || node.type === "FunctionDeclaration" || node.type === "FunctionExpression";
|
|
1225
1281
|
}
|
|
@@ -1242,7 +1298,7 @@ function isExistenceProbe(node) {
|
|
|
1242
1298
|
const other = parent.left === node ? parent.right : parent.left;
|
|
1243
1299
|
return other.type === "Literal" && other.value === "undefined";
|
|
1244
1300
|
}
|
|
1245
|
-
var noRuntimeTypeofRule =
|
|
1301
|
+
var noRuntimeTypeofRule = defineRule10({
|
|
1246
1302
|
meta: {
|
|
1247
1303
|
type: "problem",
|
|
1248
1304
|
docs: {
|
|
@@ -1276,7 +1332,7 @@ var noRuntimeTypeofRule = defineRule9({
|
|
|
1276
1332
|
});
|
|
1277
1333
|
|
|
1278
1334
|
// vendor/anti-slop/src/rules/no-shape-in-symbol-names.ts
|
|
1279
|
-
import { defineRule as
|
|
1335
|
+
import { defineRule as defineRule11 } from "@oxlint/plugins";
|
|
1280
1336
|
var FORBIDDEN_SYMBOL_NAME = "shape";
|
|
1281
1337
|
function containsForbiddenSymbolName(name) {
|
|
1282
1338
|
return name.toLowerCase().includes(FORBIDDEN_SYMBOL_NAME);
|
|
@@ -1287,7 +1343,7 @@ function isBorrowedMemberName(node) {
|
|
|
1287
1343
|
return false;
|
|
1288
1344
|
return parent.property === node && parent.computed === false;
|
|
1289
1345
|
}
|
|
1290
|
-
var noForbiddenTermInSymbolNamesRule =
|
|
1346
|
+
var noForbiddenTermInSymbolNamesRule = defineRule11({
|
|
1291
1347
|
meta: {
|
|
1292
1348
|
type: "problem",
|
|
1293
1349
|
docs: {
|
|
@@ -1316,12 +1372,12 @@ var noForbiddenTermInSymbolNamesRule = defineRule10({
|
|
|
1316
1372
|
});
|
|
1317
1373
|
|
|
1318
1374
|
// vendor/anti-slop/src/rules/no-unknown-parameters.ts
|
|
1319
|
-
import { defineRule as
|
|
1375
|
+
import { defineRule as defineRule12 } from "@oxlint/plugins";
|
|
1320
1376
|
function isTypePredicateSubject(owner, parameterName) {
|
|
1321
1377
|
const predicate = owner.returnType?.typeAnnotation;
|
|
1322
1378
|
return predicate?.type === "TSTypePredicate" && predicate.parameterName.type === "Identifier" && predicate.parameterName.name === parameterName;
|
|
1323
1379
|
}
|
|
1324
|
-
var noUnknownParametersRule =
|
|
1380
|
+
var noUnknownParametersRule = defineRule12({
|
|
1325
1381
|
meta: {
|
|
1326
1382
|
type: "problem",
|
|
1327
1383
|
docs: {
|
|
@@ -1365,8 +1421,8 @@ var noUnknownParametersRule = defineRule11({
|
|
|
1365
1421
|
});
|
|
1366
1422
|
|
|
1367
1423
|
// vendor/anti-slop/src/rules/no-unknown-returns.ts
|
|
1368
|
-
import { defineRule as
|
|
1369
|
-
var noUnknownReturnsRule =
|
|
1424
|
+
import { defineRule as defineRule13 } from "@oxlint/plugins";
|
|
1425
|
+
var noUnknownReturnsRule = defineRule13({
|
|
1370
1426
|
meta: {
|
|
1371
1427
|
type: "problem",
|
|
1372
1428
|
docs: {
|
|
@@ -1419,8 +1475,8 @@ var noUnknownReturnsRule = defineRule12({
|
|
|
1419
1475
|
});
|
|
1420
1476
|
|
|
1421
1477
|
// vendor/anti-slop/src/rules/no-unknown-type-aliases.ts
|
|
1422
|
-
import { defineRule as
|
|
1423
|
-
var noUnknownTypeAliasesRule =
|
|
1478
|
+
import { defineRule as defineRule14 } from "@oxlint/plugins";
|
|
1479
|
+
var noUnknownTypeAliasesRule = defineRule14({
|
|
1424
1480
|
meta: {
|
|
1425
1481
|
type: "problem",
|
|
1426
1482
|
docs: {
|
|
@@ -1458,7 +1514,7 @@ var noUnknownTypeAliasesRule = defineRule13({
|
|
|
1458
1514
|
});
|
|
1459
1515
|
|
|
1460
1516
|
// vendor/anti-slop/src/rules/no-unsafe-dictionary-type.ts
|
|
1461
|
-
import { defineRule as
|
|
1517
|
+
import { defineRule as defineRule15 } from "@oxlint/plugins";
|
|
1462
1518
|
var typeNodeKinds = new Set([
|
|
1463
1519
|
"JSDocNonNullableType",
|
|
1464
1520
|
"JSDocNullableType",
|
|
@@ -1545,7 +1601,7 @@ function shouldReportType(node, environment) {
|
|
|
1545
1601
|
}
|
|
1546
1602
|
return true;
|
|
1547
1603
|
}
|
|
1548
|
-
var noUnsafeDictionaryTypeRule =
|
|
1604
|
+
var noUnsafeDictionaryTypeRule = defineRule15({
|
|
1549
1605
|
meta: {
|
|
1550
1606
|
type: "problem",
|
|
1551
1607
|
docs: {
|
|
@@ -1587,7 +1643,7 @@ var noUnsafeDictionaryTypeRule = defineRule14({
|
|
|
1587
1643
|
});
|
|
1588
1644
|
|
|
1589
1645
|
// vendor/anti-slop/src/rules/no-widen-then-assert.ts
|
|
1590
|
-
import { defineRule as
|
|
1646
|
+
import { defineRule as defineRule16 } from "@oxlint/plugins";
|
|
1591
1647
|
var functionBoundaryTypes = new Set([
|
|
1592
1648
|
"ArrowFunctionExpression",
|
|
1593
1649
|
"FunctionDeclaration",
|
|
@@ -1783,7 +1839,7 @@ function assertionIsNarrower(sourceText, broadKind, evidence, assertedType) {
|
|
|
1783
1839
|
return isDefinitelyObjectType(assertedType);
|
|
1784
1840
|
return isDefinitelyNarrowerRecordType(assertedType);
|
|
1785
1841
|
}
|
|
1786
|
-
var noWidenThenAssertRule =
|
|
1842
|
+
var noWidenThenAssertRule = defineRule16({
|
|
1787
1843
|
meta: {
|
|
1788
1844
|
type: "problem",
|
|
1789
1845
|
docs: {
|
|
@@ -1823,7 +1879,7 @@ var noWidenThenAssertRule = defineRule15({
|
|
|
1823
1879
|
});
|
|
1824
1880
|
|
|
1825
1881
|
// vendor/anti-slop/src/rules/require-safety-comment-for-type-assertion.ts
|
|
1826
|
-
import { defineRule as
|
|
1882
|
+
import { defineRule as defineRule17 } from "@oxlint/plugins";
|
|
1827
1883
|
var DEFAULT_SAFETY_MARKERS = ["SAFETY"];
|
|
1828
1884
|
var commentOwnerKinds = new Set([
|
|
1829
1885
|
"ExpressionStatement",
|
|
@@ -1866,7 +1922,7 @@ function hasSafetyComment(sourceCode, node, pattern) {
|
|
|
1866
1922
|
current = current.parent;
|
|
1867
1923
|
}
|
|
1868
1924
|
}
|
|
1869
|
-
var requireSafetyCommentForTypeAssertionRule =
|
|
1925
|
+
var requireSafetyCommentForTypeAssertionRule = defineRule17({
|
|
1870
1926
|
meta: {
|
|
1871
1927
|
type: "problem",
|
|
1872
1928
|
docs: {
|
|
@@ -1916,7 +1972,7 @@ var requireSafetyCommentForTypeAssertionRule = defineRule16({
|
|
|
1916
1972
|
});
|
|
1917
1973
|
|
|
1918
1974
|
// vendor/anti-slop/src/index.ts
|
|
1919
|
-
var antiSlopPlugin =
|
|
1975
|
+
var antiSlopPlugin = eslintCompatPlugin3({
|
|
1920
1976
|
meta: { name: "anti-slop" },
|
|
1921
1977
|
rules: {
|
|
1922
1978
|
"no-chained-type-assertions": noChainedTypeAssertionsRule,
|
|
@@ -1937,62 +1993,74 @@ var antiSlopPlugin = eslintCompatPlugin2({
|
|
|
1937
1993
|
}
|
|
1938
1994
|
});
|
|
1939
1995
|
var src_default = antiSlopPlugin;
|
|
1940
|
-
//
|
|
1941
|
-
import { eslintCompatPlugin as
|
|
1996
|
+
// src/generic/index.ts
|
|
1997
|
+
import { eslintCompatPlugin as eslintCompatPlugin4 } from "@oxlint/plugins";
|
|
1942
1998
|
|
|
1943
|
-
//
|
|
1944
|
-
import { defineRule as
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1999
|
+
// src/generic/rules/prefer-event-parameter-type.ts
|
|
2000
|
+
import { defineRule as defineRule18 } from "@oxlint/plugins";
|
|
2001
|
+
function nearestEnclosingFunction2(node) {
|
|
2002
|
+
let current = node.parent;
|
|
2003
|
+
while (current) {
|
|
2004
|
+
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
2005
|
+
return current;
|
|
2006
|
+
}
|
|
2007
|
+
current = current.parent;
|
|
2008
|
+
}
|
|
2009
|
+
return null;
|
|
1949
2010
|
}
|
|
1950
|
-
function
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
2011
|
+
function assertedEventParameter(node) {
|
|
2012
|
+
const expression = node.expression;
|
|
2013
|
+
if (expression.type !== "MemberExpression" || expression.computed || expression.object.type !== "Identifier" || expression.property.type !== "Identifier" || expression.property.name !== "currentTarget" && expression.property.name !== "target") {
|
|
2014
|
+
return null;
|
|
2015
|
+
}
|
|
2016
|
+
const parameterName = expression.object.name;
|
|
2017
|
+
const property = expression.property.name;
|
|
2018
|
+
const owner = nearestEnclosingFunction2(node);
|
|
2019
|
+
if (!owner?.params.some((parameter) => parameter.type === "Identifier" && parameter.name === parameterName)) {
|
|
2020
|
+
return null;
|
|
2021
|
+
}
|
|
2022
|
+
return {
|
|
2023
|
+
parameter: parameterName,
|
|
2024
|
+
property
|
|
2025
|
+
};
|
|
1954
2026
|
}
|
|
1955
|
-
var
|
|
2027
|
+
var preferEventParameterTypeRule = defineRule18({
|
|
1956
2028
|
meta: {
|
|
1957
|
-
type: "
|
|
2029
|
+
type: "suggestion",
|
|
1958
2030
|
docs: {
|
|
1959
|
-
description: "
|
|
2031
|
+
description: "Prefer typing event target properties in the handler parameter instead of asserting them at use sites."
|
|
1960
2032
|
},
|
|
1961
2033
|
messages: {
|
|
1962
|
-
|
|
2034
|
+
typeEventParameter: "Type `{{parameter}}.{{property}}` in the function signature instead of asserting it at the use site."
|
|
1963
2035
|
}
|
|
1964
2036
|
},
|
|
1965
2037
|
create(context) {
|
|
1966
|
-
const
|
|
2038
|
+
const checkAssertion = (node) => {
|
|
2039
|
+
const eventParameter = assertedEventParameter(node);
|
|
2040
|
+
if (!eventParameter)
|
|
2041
|
+
return;
|
|
2042
|
+
context.report({
|
|
2043
|
+
node,
|
|
2044
|
+
messageId: "typeEventParameter",
|
|
2045
|
+
data: eventParameter
|
|
2046
|
+
});
|
|
2047
|
+
};
|
|
1967
2048
|
return {
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
return;
|
|
1971
|
-
for (const specifier of node.specifiers) {
|
|
1972
|
-
if (specifier.type !== "ImportSpecifier")
|
|
1973
|
-
continue;
|
|
1974
|
-
const importedName2 = getImportedName(specifier);
|
|
1975
|
-
if (!SERVICE_CONSTRUCTOR_NAME.test(importedName2))
|
|
1976
|
-
continue;
|
|
1977
|
-
context.report({
|
|
1978
|
-
node: specifier,
|
|
1979
|
-
messageId: "serviceConstructorImport",
|
|
1980
|
-
data: { name: importedName2 }
|
|
1981
|
-
});
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
2049
|
+
TSAsExpression: checkAssertion,
|
|
2050
|
+
TSTypeAssertion: checkAssertion
|
|
1984
2051
|
};
|
|
1985
2052
|
}
|
|
1986
2053
|
});
|
|
1987
2054
|
|
|
1988
|
-
//
|
|
1989
|
-
var
|
|
1990
|
-
meta: { name: "
|
|
2055
|
+
// src/generic/index.ts
|
|
2056
|
+
var timmoPlugin = eslintCompatPlugin4({
|
|
2057
|
+
meta: { name: "timmo" },
|
|
1991
2058
|
rules: {
|
|
1992
|
-
"
|
|
2059
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
1993
2060
|
}
|
|
1994
2061
|
});
|
|
1995
|
-
var
|
|
2062
|
+
var generic_default = timmoPlugin;
|
|
2063
|
+
|
|
1996
2064
|
// node_modules/oxlint/dist/index.js
|
|
1997
2065
|
function defineConfig(config) {
|
|
1998
2066
|
return config;
|
|
@@ -2009,9 +2077,13 @@ var recommended = defineConfig({
|
|
|
2009
2077
|
{
|
|
2010
2078
|
name: "anti-slop",
|
|
2011
2079
|
specifier: "@timmo001/oxlint-rules/upstream/anti-slop"
|
|
2012
|
-
}
|
|
2080
|
+
},
|
|
2081
|
+
{ name: "timmo", specifier: "@timmo001/oxlint-rules/generic" }
|
|
2013
2082
|
],
|
|
2014
|
-
rules:
|
|
2083
|
+
rules: {
|
|
2084
|
+
...enablePluginRules("anti-slop", src_default),
|
|
2085
|
+
...enablePluginRules("timmo", generic_default)
|
|
2086
|
+
}
|
|
2015
2087
|
});
|
|
2016
2088
|
var recommended_default = recommended;
|
|
2017
2089
|
|
|
@@ -1833,6 +1833,74 @@ var antiSlopPlugin = eslintCompatPlugin({
|
|
|
1833
1833
|
}
|
|
1834
1834
|
});
|
|
1835
1835
|
var src_default = antiSlopPlugin;
|
|
1836
|
+
// src/generic/index.ts
|
|
1837
|
+
import { eslintCompatPlugin as eslintCompatPlugin2 } from "@oxlint/plugins";
|
|
1838
|
+
|
|
1839
|
+
// src/generic/rules/prefer-event-parameter-type.ts
|
|
1840
|
+
import { defineRule as defineRule16 } from "@oxlint/plugins";
|
|
1841
|
+
function nearestEnclosingFunction(node) {
|
|
1842
|
+
let current = node.parent;
|
|
1843
|
+
while (current) {
|
|
1844
|
+
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
1845
|
+
return current;
|
|
1846
|
+
}
|
|
1847
|
+
current = current.parent;
|
|
1848
|
+
}
|
|
1849
|
+
return null;
|
|
1850
|
+
}
|
|
1851
|
+
function assertedEventParameter(node) {
|
|
1852
|
+
const expression = node.expression;
|
|
1853
|
+
if (expression.type !== "MemberExpression" || expression.computed || expression.object.type !== "Identifier" || expression.property.type !== "Identifier" || expression.property.name !== "currentTarget" && expression.property.name !== "target") {
|
|
1854
|
+
return null;
|
|
1855
|
+
}
|
|
1856
|
+
const parameterName = expression.object.name;
|
|
1857
|
+
const property = expression.property.name;
|
|
1858
|
+
const owner = nearestEnclosingFunction(node);
|
|
1859
|
+
if (!owner?.params.some((parameter) => parameter.type === "Identifier" && parameter.name === parameterName)) {
|
|
1860
|
+
return null;
|
|
1861
|
+
}
|
|
1862
|
+
return {
|
|
1863
|
+
parameter: parameterName,
|
|
1864
|
+
property
|
|
1865
|
+
};
|
|
1866
|
+
}
|
|
1867
|
+
var preferEventParameterTypeRule = defineRule16({
|
|
1868
|
+
meta: {
|
|
1869
|
+
type: "suggestion",
|
|
1870
|
+
docs: {
|
|
1871
|
+
description: "Prefer typing event target properties in the handler parameter instead of asserting them at use sites."
|
|
1872
|
+
},
|
|
1873
|
+
messages: {
|
|
1874
|
+
typeEventParameter: "Type `{{parameter}}.{{property}}` in the function signature instead of asserting it at the use site."
|
|
1875
|
+
}
|
|
1876
|
+
},
|
|
1877
|
+
create(context) {
|
|
1878
|
+
const checkAssertion = (node) => {
|
|
1879
|
+
const eventParameter = assertedEventParameter(node);
|
|
1880
|
+
if (!eventParameter)
|
|
1881
|
+
return;
|
|
1882
|
+
context.report({
|
|
1883
|
+
node,
|
|
1884
|
+
messageId: "typeEventParameter",
|
|
1885
|
+
data: eventParameter
|
|
1886
|
+
});
|
|
1887
|
+
};
|
|
1888
|
+
return {
|
|
1889
|
+
TSAsExpression: checkAssertion,
|
|
1890
|
+
TSTypeAssertion: checkAssertion
|
|
1891
|
+
};
|
|
1892
|
+
}
|
|
1893
|
+
});
|
|
1894
|
+
|
|
1895
|
+
// src/generic/index.ts
|
|
1896
|
+
var timmoPlugin = eslintCompatPlugin2({
|
|
1897
|
+
meta: { name: "timmo" },
|
|
1898
|
+
rules: {
|
|
1899
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
1900
|
+
}
|
|
1901
|
+
});
|
|
1902
|
+
var generic_default = timmoPlugin;
|
|
1903
|
+
|
|
1836
1904
|
// node_modules/oxlint/dist/index.js
|
|
1837
1905
|
function defineConfig(config) {
|
|
1838
1906
|
return config;
|
|
@@ -1849,9 +1917,13 @@ var recommended = defineConfig({
|
|
|
1849
1917
|
{
|
|
1850
1918
|
name: "anti-slop",
|
|
1851
1919
|
specifier: "@timmo001/oxlint-rules/upstream/anti-slop"
|
|
1852
|
-
}
|
|
1920
|
+
},
|
|
1921
|
+
{ name: "timmo", specifier: "@timmo001/oxlint-rules/generic" }
|
|
1853
1922
|
],
|
|
1854
|
-
rules:
|
|
1923
|
+
rules: {
|
|
1924
|
+
...enablePluginRules("anti-slop", src_default),
|
|
1925
|
+
...enablePluginRules("timmo", generic_default)
|
|
1926
|
+
}
|
|
1855
1927
|
});
|
|
1856
1928
|
var recommended_default = recommended;
|
|
1857
1929
|
export {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/generic/index.ts
|
|
2
|
+
import { eslintCompatPlugin } from "@oxlint/plugins";
|
|
3
|
+
|
|
4
|
+
// src/generic/rules/prefer-event-parameter-type.ts
|
|
5
|
+
import { defineRule } from "@oxlint/plugins";
|
|
6
|
+
function nearestEnclosingFunction(node) {
|
|
7
|
+
let current = node.parent;
|
|
8
|
+
while (current) {
|
|
9
|
+
if (current.type === "FunctionDeclaration" || current.type === "FunctionExpression" || current.type === "ArrowFunctionExpression") {
|
|
10
|
+
return current;
|
|
11
|
+
}
|
|
12
|
+
current = current.parent;
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
function assertedEventParameter(node) {
|
|
17
|
+
const expression = node.expression;
|
|
18
|
+
if (expression.type !== "MemberExpression" || expression.computed || expression.object.type !== "Identifier" || expression.property.type !== "Identifier" || expression.property.name !== "currentTarget" && expression.property.name !== "target") {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
const parameterName = expression.object.name;
|
|
22
|
+
const property = expression.property.name;
|
|
23
|
+
const owner = nearestEnclosingFunction(node);
|
|
24
|
+
if (!owner?.params.some((parameter) => parameter.type === "Identifier" && parameter.name === parameterName)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
parameter: parameterName,
|
|
29
|
+
property
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
var preferEventParameterTypeRule = defineRule({
|
|
33
|
+
meta: {
|
|
34
|
+
type: "suggestion",
|
|
35
|
+
docs: {
|
|
36
|
+
description: "Prefer typing event target properties in the handler parameter instead of asserting them at use sites."
|
|
37
|
+
},
|
|
38
|
+
messages: {
|
|
39
|
+
typeEventParameter: "Type `{{parameter}}.{{property}}` in the function signature instead of asserting it at the use site."
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
create(context) {
|
|
43
|
+
const checkAssertion = (node) => {
|
|
44
|
+
const eventParameter = assertedEventParameter(node);
|
|
45
|
+
if (!eventParameter)
|
|
46
|
+
return;
|
|
47
|
+
context.report({
|
|
48
|
+
node,
|
|
49
|
+
messageId: "typeEventParameter",
|
|
50
|
+
data: eventParameter
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
return {
|
|
54
|
+
TSAsExpression: checkAssertion,
|
|
55
|
+
TSTypeAssertion: checkAssertion
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// src/generic/index.ts
|
|
61
|
+
var timmoPlugin = eslintCompatPlugin({
|
|
62
|
+
meta: { name: "timmo" },
|
|
63
|
+
rules: {
|
|
64
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
var generic_default = timmoPlugin;
|
|
68
|
+
export {
|
|
69
|
+
generic_default as default
|
|
70
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmo001/oxlint-rules",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Shared Oxlint plugins and configs with optional Effect rules.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"exports": {
|
|
15
15
|
"./upstream/anti-slop": "./dist/upstream/anti-slop.js",
|
|
16
16
|
"./upstream/effect": "./dist/upstream/effect.js",
|
|
17
|
+
"./generic": "./dist/generic/index.js",
|
|
17
18
|
"./effect": "./dist/effect/index.js",
|
|
18
19
|
"./configs/recommended": "./dist/configs/recommended.js",
|
|
19
20
|
"./configs/effect": "./dist/configs/effect.js"
|
|
@@ -21,6 +22,8 @@
|
|
|
21
22
|
"files": [
|
|
22
23
|
"dist",
|
|
23
24
|
"src/effect",
|
|
25
|
+
"src/generic",
|
|
26
|
+
"!src/generic/**/*.test.ts",
|
|
24
27
|
"!src/effect/**/*.test.ts",
|
|
25
28
|
"vendor/anti-slop/src",
|
|
26
29
|
"vendor/anti-slop/LICENSE",
|
|
@@ -37,7 +40,7 @@
|
|
|
37
40
|
"format": "prettier --write \"{src,scripts}/**/*.ts\" \"skills/**/*.{md,mjs}\" \"*.md\" \"*.json\"",
|
|
38
41
|
"format:check": "prettier --check \"{src,scripts}/**/*.ts\" \"skills/**/*.{md,mjs}\" \"*.md\" \"*.json\"",
|
|
39
42
|
"lint": "oxlint src scripts",
|
|
40
|
-
"skills:validate": "bunx skills-ref validate skills/install-timmo-oxlint-rules && bunx skills-ref validate skills/add-oxlint-rule",
|
|
43
|
+
"skills:validate": "bunx skills-ref validate skills/install-timmo-oxlint-rules && bunx skills-ref validate skills/add-oxlint-rule && bunx skills-ref validate skills/release-oxlint-rules",
|
|
41
44
|
"test": "node --experimental-strip-types scripts/test.ts",
|
|
42
45
|
"typecheck": "tsc --noEmit"
|
|
43
46
|
},
|
|
@@ -23,9 +23,13 @@ description: >-
|
|
|
23
23
|
separately when Dylan Mulroy's plugin should own the behaviour.
|
|
24
24
|
6. Register the rule in its plugin. Verify the matching config and copy command
|
|
25
25
|
discover it from the plugin's `rules` map, then update the README rule list
|
|
26
|
-
and behaviour description.
|
|
26
|
+
and behaviour description. Keep skills workflow-only; do not duplicate rule
|
|
27
|
+
or plugin inventories or counts in them.
|
|
27
28
|
7. Run `mise run check`, `mise run build`, `npm pack --dry-run`, and
|
|
28
|
-
`bunx jsr@0.14.3 publish --dry-run` in the central checkout.
|
|
29
|
+
`bunx jsr@0.14.3 publish --dry-run --allow-dirty` in the central checkout.
|
|
30
|
+
8. If the user also asks to publish the change, load `release-oxlint-rules` and
|
|
31
|
+
hand off the release after the rule checks pass. Do not duplicate or bypass
|
|
32
|
+
its release workflow.
|
|
29
33
|
|
|
30
34
|
Report the fixture contract, registration and docs changed, checks, and any
|
|
31
35
|
consumer rollout left for a separate stage. Do not publish or assume a local
|
|
@@ -23,9 +23,9 @@ description: >-
|
|
|
23
23
|
2. Detect Bun, npm, pnpm, or Yarn from the target's package manager declaration
|
|
24
24
|
and lockfile. Add an exact development dependency through that package
|
|
25
25
|
manager.
|
|
26
|
-
3. Extend `@timmo001/oxlint-rules/configs/recommended`.
|
|
27
|
-
|
|
28
|
-
requests it.
|
|
26
|
+
3. Extend `@timmo001/oxlint-rules/configs/recommended`. The config owns plugin
|
|
27
|
+
registration and recommended severities. Use `/configs/effect` instead only
|
|
28
|
+
when `effect` is a direct dependency or the user explicitly requests it.
|
|
29
29
|
4. Keep dependency and config edits visible. Do not delegate them to a script.
|
|
30
30
|
|
|
31
31
|
## Copy rules
|
|
@@ -36,11 +36,11 @@ description: >-
|
|
|
36
36
|
meaningful differences before asking whether replacement is intended.
|
|
37
37
|
3. Run `node scripts/copy.mjs <bun|npm|pnpm|yarn> <destination>`. Add `--force`
|
|
38
38
|
only after explicit replacement approval.
|
|
39
|
-
4. Register
|
|
40
|
-
|
|
41
|
-
setting
|
|
42
|
-
|
|
43
|
-
this skill.
|
|
39
|
+
4. Register every plugin entry point printed by the command. Merge every printed
|
|
40
|
+
general rule setting into the target config. Merge every printed Effect rule
|
|
41
|
+
setting only for direct Effect use or an explicit request. Treat the command
|
|
42
|
+
output as authoritative rather than maintaining plugin or rule inventories
|
|
43
|
+
in this skill.
|
|
44
44
|
|
|
45
45
|
Run the target repository's normal lint, typecheck, tests, and build. Report
|
|
46
46
|
package-manager changes, preserved local configuration, enabled rule groups,
|