@timmo001/oxlint-rules 0.3.6 → 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/README.md +11 -2
- package/dist/cli.js +42 -14
- package/dist/configs/recommended-effect.js +30 -2
- package/dist/configs/recommended.js +30 -2
- package/dist/generic/index.js +28 -1
- package/package.json +6 -6
- package/src/generic/index.ts +2 -0
- package/src/generic/rules/prefer-types-over-assertions.ts +38 -0
package/README.md
CHANGED
|
@@ -74,12 +74,20 @@ replace an existing destination unless `--force` is passed.
|
|
|
74
74
|
### `anti-slop` and `anti-slop-effect`
|
|
75
75
|
|
|
76
76
|
See the upstream [rule documentation](https://github.com/dmmulroy/anti-slop#rules).
|
|
77
|
+
The recommended configs disable
|
|
78
|
+
`anti-slop/require-safety-comment-for-type-assertion` in favour of
|
|
79
|
+
`timmo/prefer-types-over-assertions`. The upstream rule remains available for
|
|
80
|
+
explicit use.
|
|
77
81
|
|
|
78
82
|
### `timmo`
|
|
79
83
|
|
|
80
84
|
- `prefer-event-parameter-type`: reports assertions on a handler parameter's
|
|
81
85
|
`target` or `currentTarget`. Express the target type in the function signature
|
|
82
86
|
instead so every use sees the same contract.
|
|
87
|
+
- `prefer-types-over-assertions`: reports non-`const` TypeScript assertions,
|
|
88
|
+
even when preceded by a `SAFETY:` comment. Type values where they enter the
|
|
89
|
+
code, for example in function parameters or a checked DOM lookup helper that
|
|
90
|
+
returns `null` when the element is missing or has the wrong type.
|
|
83
91
|
|
|
84
92
|
### `timmo-effect`
|
|
85
93
|
|
|
@@ -104,8 +112,9 @@ bunx jsr@0.14.3 publish --dry-run --allow-dirty
|
|
|
104
112
|
|
|
105
113
|
`bun run lint` builds the local plugins before linting all maintained code,
|
|
106
114
|
including tests, tooling, the root config and packaged skill scripts. The root
|
|
107
|
-
config extends the local `recommended-effect` source config, enabling
|
|
108
|
-
|
|
115
|
+
config extends the local `recommended-effect` source config, enabling registered
|
|
116
|
+
rules in `anti-slop`, `timmo`, `anti-slop-effect` and `timmo-effect` except for
|
|
117
|
+
the upstream safety-comment requirement described above.
|
|
109
118
|
Plugin imports resolve through this package's exports to the fresh `dist` build.
|
|
110
119
|
|
|
111
120
|
Lint disables nested configs so the vendored submodule's config cannot override
|
package/dist/cli.js
CHANGED
|
@@ -2604,11 +2604,38 @@ var preferEventParameterTypeRule = defineRule18({
|
|
|
2604
2604
|
}
|
|
2605
2605
|
});
|
|
2606
2606
|
|
|
2607
|
+
// src/generic/rules/prefer-types-over-assertions.ts
|
|
2608
|
+
import { defineRule as defineRule19 } from "@oxlint/plugins";
|
|
2609
|
+
var preferTypesOverAssertionsRule = defineRule19({
|
|
2610
|
+
meta: {
|
|
2611
|
+
type: "problem",
|
|
2612
|
+
docs: {
|
|
2613
|
+
description: "Prefer typing a value at its source over a TypeScript type assertion."
|
|
2614
|
+
},
|
|
2615
|
+
messages: {
|
|
2616
|
+
avoidAssertion: "Type this value at its source, such as a function parameter or DOM lookup, instead of asserting it here. A SAFETY comment is not a fix."
|
|
2617
|
+
}
|
|
2618
|
+
},
|
|
2619
|
+
create(context) {
|
|
2620
|
+
const checkAssertion = (node) => {
|
|
2621
|
+
if (node.typeAnnotation.type === "TSTypeReference" && node.typeAnnotation.typeName.type === "Identifier" && node.typeAnnotation.typeName.name === "const") {
|
|
2622
|
+
return;
|
|
2623
|
+
}
|
|
2624
|
+
context.report({ node, messageId: "avoidAssertion" });
|
|
2625
|
+
};
|
|
2626
|
+
return {
|
|
2627
|
+
TSAsExpression: checkAssertion,
|
|
2628
|
+
TSTypeAssertion: checkAssertion
|
|
2629
|
+
};
|
|
2630
|
+
}
|
|
2631
|
+
});
|
|
2632
|
+
|
|
2607
2633
|
// src/generic/index.ts
|
|
2608
2634
|
var timmoPlugin = eslintCompatPlugin2({
|
|
2609
2635
|
meta: { name: "timmo" },
|
|
2610
2636
|
rules: {
|
|
2611
|
-
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
2637
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule,
|
|
2638
|
+
"prefer-types-over-assertions": preferTypesOverAssertionsRule
|
|
2612
2639
|
}
|
|
2613
2640
|
});
|
|
2614
2641
|
var generic_default = timmoPlugin;
|
|
@@ -2629,7 +2656,8 @@ var recommended = defineConfig({
|
|
|
2629
2656
|
],
|
|
2630
2657
|
rules: {
|
|
2631
2658
|
...enablePluginRules("anti-slop", src_default),
|
|
2632
|
-
...enablePluginRules("timmo", generic_default)
|
|
2659
|
+
...enablePluginRules("timmo", generic_default),
|
|
2660
|
+
"anti-slop/require-safety-comment-for-type-assertion": "off"
|
|
2633
2661
|
}
|
|
2634
2662
|
});
|
|
2635
2663
|
var recommended_default = recommended;
|
|
@@ -2638,7 +2666,7 @@ var recommended_default = recommended;
|
|
|
2638
2666
|
import { eslintCompatPlugin as eslintCompatPlugin3 } from "@oxlint/plugins";
|
|
2639
2667
|
|
|
2640
2668
|
// src/effect/rules/no-try-catch-in-effect-generators.ts
|
|
2641
|
-
import { defineRule as
|
|
2669
|
+
import { defineRule as defineRule20 } from "@oxlint/plugins";
|
|
2642
2670
|
function resolveVariable2(sourceCode, identifier) {
|
|
2643
2671
|
let scope = sourceCode.getScope(identifier);
|
|
2644
2672
|
while (scope) {
|
|
@@ -2704,7 +2732,7 @@ function isRecognisedEffectGenerator(sourceCode, owner) {
|
|
|
2704
2732
|
const factoryCall = parent.callee;
|
|
2705
2733
|
return factoryCall.type === "CallExpression" && isEffectMethod(sourceCode, factoryCall.callee, "fn");
|
|
2706
2734
|
}
|
|
2707
|
-
var noTryCatchInEffectGeneratorsRule =
|
|
2735
|
+
var noTryCatchInEffectGeneratorsRule = defineRule20({
|
|
2708
2736
|
meta: {
|
|
2709
2737
|
type: "problem",
|
|
2710
2738
|
docs: {
|
|
@@ -2742,7 +2770,7 @@ var effect_default = timmoEffectPlugin;
|
|
|
2742
2770
|
import { eslintCompatPlugin as eslintCompatPlugin4 } from "@oxlint/plugins";
|
|
2743
2771
|
|
|
2744
2772
|
// vendor/anti-slop/src/effect/rules/no-manual-effect-error-tag.ts
|
|
2745
|
-
import { defineRule as
|
|
2773
|
+
import { defineRule as defineRule21 } from "@oxlint/plugins";
|
|
2746
2774
|
|
|
2747
2775
|
// vendor/anti-slop/src/effect/shared/tagged-values.ts
|
|
2748
2776
|
var equalityOperators = new Set(["==", "===", "!=", "!=="]);
|
|
@@ -2789,7 +2817,7 @@ var isMatchPatternObject = (node) => {
|
|
|
2789
2817
|
};
|
|
2790
2818
|
|
|
2791
2819
|
// vendor/anti-slop/src/effect/rules/no-manual-effect-error-tag.ts
|
|
2792
|
-
var noManualEffectErrorTagRule =
|
|
2820
|
+
var noManualEffectErrorTagRule = defineRule21({
|
|
2793
2821
|
meta: {
|
|
2794
2822
|
type: "problem",
|
|
2795
2823
|
docs: {
|
|
@@ -2826,8 +2854,8 @@ var noManualEffectErrorTagRule = defineRule20({
|
|
|
2826
2854
|
});
|
|
2827
2855
|
|
|
2828
2856
|
// vendor/anti-slop/src/effect/rules/no-manual-tag-comparison.ts
|
|
2829
|
-
import { defineRule as
|
|
2830
|
-
var noManualTagComparisonRule =
|
|
2857
|
+
import { defineRule as defineRule22 } from "@oxlint/plugins";
|
|
2858
|
+
var noManualTagComparisonRule = defineRule22({
|
|
2831
2859
|
meta: {
|
|
2832
2860
|
type: "problem",
|
|
2833
2861
|
docs: {
|
|
@@ -2857,8 +2885,8 @@ var noManualTagComparisonRule = defineRule21({
|
|
|
2857
2885
|
});
|
|
2858
2886
|
|
|
2859
2887
|
// vendor/anti-slop/src/effect/rules/no-manual-tagged-construction.ts
|
|
2860
|
-
import { defineRule as
|
|
2861
|
-
var noManualTaggedConstructionRule =
|
|
2888
|
+
import { defineRule as defineRule23 } from "@oxlint/plugins";
|
|
2889
|
+
var noManualTaggedConstructionRule = defineRule23({
|
|
2862
2890
|
meta: {
|
|
2863
2891
|
type: "problem",
|
|
2864
2892
|
docs: {
|
|
@@ -2883,7 +2911,7 @@ var noManualTaggedConstructionRule = defineRule22({
|
|
|
2883
2911
|
});
|
|
2884
2912
|
|
|
2885
2913
|
// vendor/anti-slop/src/effect/rules/no-service-constructor-imports.ts
|
|
2886
|
-
import { defineRule as
|
|
2914
|
+
import { defineRule as defineRule24 } from "@oxlint/plugins";
|
|
2887
2915
|
var SERVICE_CONSTRUCTOR_NAME = /^make[A-Z]/u;
|
|
2888
2916
|
var TEST_FILE = /\.(?:test|spec)\.[cm]?[jt]sx?$/u;
|
|
2889
2917
|
function isProjectLocalImport(source) {
|
|
@@ -2894,7 +2922,7 @@ function getImportedName(specifier) {
|
|
|
2894
2922
|
return specifier.imported.name;
|
|
2895
2923
|
return specifier.imported.value;
|
|
2896
2924
|
}
|
|
2897
|
-
var noServiceConstructorImportsRule =
|
|
2925
|
+
var noServiceConstructorImportsRule = defineRule24({
|
|
2898
2926
|
meta: {
|
|
2899
2927
|
type: "problem",
|
|
2900
2928
|
docs: {
|
|
@@ -2928,9 +2956,9 @@ var noServiceConstructorImportsRule = defineRule23({
|
|
|
2928
2956
|
});
|
|
2929
2957
|
|
|
2930
2958
|
// vendor/anti-slop/src/effect/rules/prefer-effect-match.ts
|
|
2931
|
-
import { defineRule as
|
|
2959
|
+
import { defineRule as defineRule25 } from "@oxlint/plugins";
|
|
2932
2960
|
var equalityOperators2 = new Set(["==", "===", "!=", "!=="]);
|
|
2933
|
-
var preferEffectMatchRule =
|
|
2961
|
+
var preferEffectMatchRule = defineRule25({
|
|
2934
2962
|
meta: {
|
|
2935
2963
|
type: "problem",
|
|
2936
2964
|
docs: {
|
|
@@ -2957,11 +2957,38 @@ var preferEventParameterTypeRule = defineRule24({
|
|
|
2957
2957
|
}
|
|
2958
2958
|
});
|
|
2959
2959
|
|
|
2960
|
+
// src/generic/rules/prefer-types-over-assertions.ts
|
|
2961
|
+
import { defineRule as defineRule25 } from "@oxlint/plugins";
|
|
2962
|
+
var preferTypesOverAssertionsRule = defineRule25({
|
|
2963
|
+
meta: {
|
|
2964
|
+
type: "problem",
|
|
2965
|
+
docs: {
|
|
2966
|
+
description: "Prefer typing a value at its source over a TypeScript type assertion."
|
|
2967
|
+
},
|
|
2968
|
+
messages: {
|
|
2969
|
+
avoidAssertion: "Type this value at its source, such as a function parameter or DOM lookup, instead of asserting it here. A SAFETY comment is not a fix."
|
|
2970
|
+
}
|
|
2971
|
+
},
|
|
2972
|
+
create(context) {
|
|
2973
|
+
const checkAssertion = (node) => {
|
|
2974
|
+
if (node.typeAnnotation.type === "TSTypeReference" && node.typeAnnotation.typeName.type === "Identifier" && node.typeAnnotation.typeName.name === "const") {
|
|
2975
|
+
return;
|
|
2976
|
+
}
|
|
2977
|
+
context.report({ node, messageId: "avoidAssertion" });
|
|
2978
|
+
};
|
|
2979
|
+
return {
|
|
2980
|
+
TSAsExpression: checkAssertion,
|
|
2981
|
+
TSTypeAssertion: checkAssertion
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2984
|
+
});
|
|
2985
|
+
|
|
2960
2986
|
// src/generic/index.ts
|
|
2961
2987
|
var timmoPlugin = eslintCompatPlugin4({
|
|
2962
2988
|
meta: { name: "timmo" },
|
|
2963
2989
|
rules: {
|
|
2964
|
-
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
2990
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule,
|
|
2991
|
+
"prefer-types-over-assertions": preferTypesOverAssertionsRule
|
|
2965
2992
|
}
|
|
2966
2993
|
});
|
|
2967
2994
|
var generic_default = timmoPlugin;
|
|
@@ -2977,7 +3004,8 @@ var recommended = defineConfig({
|
|
|
2977
3004
|
],
|
|
2978
3005
|
rules: {
|
|
2979
3006
|
...enablePluginRules("anti-slop", src_default),
|
|
2980
|
-
...enablePluginRules("timmo", generic_default)
|
|
3007
|
+
...enablePluginRules("timmo", generic_default),
|
|
3008
|
+
"anti-slop/require-safety-comment-for-type-assertion": "off"
|
|
2981
3009
|
}
|
|
2982
3010
|
});
|
|
2983
3011
|
var recommended_default = recommended;
|
|
@@ -2599,11 +2599,38 @@ var preferEventParameterTypeRule = defineRule18({
|
|
|
2599
2599
|
}
|
|
2600
2600
|
});
|
|
2601
2601
|
|
|
2602
|
+
// src/generic/rules/prefer-types-over-assertions.ts
|
|
2603
|
+
import { defineRule as defineRule19 } from "@oxlint/plugins";
|
|
2604
|
+
var preferTypesOverAssertionsRule = defineRule19({
|
|
2605
|
+
meta: {
|
|
2606
|
+
type: "problem",
|
|
2607
|
+
docs: {
|
|
2608
|
+
description: "Prefer typing a value at its source over a TypeScript type assertion."
|
|
2609
|
+
},
|
|
2610
|
+
messages: {
|
|
2611
|
+
avoidAssertion: "Type this value at its source, such as a function parameter or DOM lookup, instead of asserting it here. A SAFETY comment is not a fix."
|
|
2612
|
+
}
|
|
2613
|
+
},
|
|
2614
|
+
create(context) {
|
|
2615
|
+
const checkAssertion = (node) => {
|
|
2616
|
+
if (node.typeAnnotation.type === "TSTypeReference" && node.typeAnnotation.typeName.type === "Identifier" && node.typeAnnotation.typeName.name === "const") {
|
|
2617
|
+
return;
|
|
2618
|
+
}
|
|
2619
|
+
context.report({ node, messageId: "avoidAssertion" });
|
|
2620
|
+
};
|
|
2621
|
+
return {
|
|
2622
|
+
TSAsExpression: checkAssertion,
|
|
2623
|
+
TSTypeAssertion: checkAssertion
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
});
|
|
2627
|
+
|
|
2602
2628
|
// src/generic/index.ts
|
|
2603
2629
|
var timmoPlugin = eslintCompatPlugin2({
|
|
2604
2630
|
meta: { name: "timmo" },
|
|
2605
2631
|
rules: {
|
|
2606
|
-
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
2632
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule,
|
|
2633
|
+
"prefer-types-over-assertions": preferTypesOverAssertionsRule
|
|
2607
2634
|
}
|
|
2608
2635
|
});
|
|
2609
2636
|
var generic_default = timmoPlugin;
|
|
@@ -2624,7 +2651,8 @@ var recommended = defineConfig({
|
|
|
2624
2651
|
],
|
|
2625
2652
|
rules: {
|
|
2626
2653
|
...enablePluginRules("anti-slop", src_default),
|
|
2627
|
-
...enablePluginRules("timmo", generic_default)
|
|
2654
|
+
...enablePluginRules("timmo", generic_default),
|
|
2655
|
+
"anti-slop/require-safety-comment-for-type-assertion": "off"
|
|
2628
2656
|
}
|
|
2629
2657
|
});
|
|
2630
2658
|
var recommended_default = recommended;
|
package/dist/generic/index.js
CHANGED
|
@@ -57,11 +57,38 @@ var preferEventParameterTypeRule = defineRule({
|
|
|
57
57
|
}
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
+
// src/generic/rules/prefer-types-over-assertions.ts
|
|
61
|
+
import { defineRule as defineRule2 } from "@oxlint/plugins";
|
|
62
|
+
var preferTypesOverAssertionsRule = defineRule2({
|
|
63
|
+
meta: {
|
|
64
|
+
type: "problem",
|
|
65
|
+
docs: {
|
|
66
|
+
description: "Prefer typing a value at its source over a TypeScript type assertion."
|
|
67
|
+
},
|
|
68
|
+
messages: {
|
|
69
|
+
avoidAssertion: "Type this value at its source, such as a function parameter or DOM lookup, instead of asserting it here. A SAFETY comment is not a fix."
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
create(context) {
|
|
73
|
+
const checkAssertion = (node) => {
|
|
74
|
+
if (node.typeAnnotation.type === "TSTypeReference" && node.typeAnnotation.typeName.type === "Identifier" && node.typeAnnotation.typeName.name === "const") {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
context.report({ node, messageId: "avoidAssertion" });
|
|
78
|
+
};
|
|
79
|
+
return {
|
|
80
|
+
TSAsExpression: checkAssertion,
|
|
81
|
+
TSTypeAssertion: checkAssertion
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
60
86
|
// src/generic/index.ts
|
|
61
87
|
var timmoPlugin = eslintCompatPlugin({
|
|
62
88
|
meta: { name: "timmo" },
|
|
63
89
|
rules: {
|
|
64
|
-
"prefer-event-parameter-type": preferEventParameterTypeRule
|
|
90
|
+
"prefer-event-parameter-type": preferEventParameterTypeRule,
|
|
91
|
+
"prefer-types-over-assertions": preferTypesOverAssertionsRule
|
|
65
92
|
}
|
|
66
93
|
});
|
|
67
94
|
var generic_default = timmoPlugin;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmo001/oxlint-rules",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Shared Oxlint plugins and configs with optional Effect rules.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -46,14 +46,14 @@
|
|
|
46
46
|
"typecheck": "tsc --noEmit"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
|
49
|
-
"@oxlint/plugins": "1.
|
|
50
|
-
"oxlint": "1.
|
|
49
|
+
"@oxlint/plugins": "1.86.0",
|
|
50
|
+
"oxlint": "1.86.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
|
-
"@oxlint/plugins": "1.
|
|
53
|
+
"@oxlint/plugins": "1.86.0",
|
|
54
54
|
"@types/bun": "^1.3.14",
|
|
55
|
-
"oxlint": "1.
|
|
56
|
-
"oxlint-tsgolint": "7.0.
|
|
55
|
+
"oxlint": "1.86.0",
|
|
56
|
+
"oxlint-tsgolint": "7.0.2003",
|
|
57
57
|
"prettier": "^3.9.5",
|
|
58
58
|
"skills-ref": "0.1.5",
|
|
59
59
|
"typescript": "^7.0.0"
|
package/src/generic/index.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { eslintCompatPlugin } from "@oxlint/plugins";
|
|
2
2
|
|
|
3
3
|
import { preferEventParameterTypeRule } from "./rules/prefer-event-parameter-type.ts";
|
|
4
|
+
import { preferTypesOverAssertionsRule } from "./rules/prefer-types-over-assertions.ts";
|
|
4
5
|
|
|
5
6
|
const timmoPlugin = eslintCompatPlugin({
|
|
6
7
|
meta: { name: "timmo" },
|
|
7
8
|
rules: {
|
|
8
9
|
"prefer-event-parameter-type": preferEventParameterTypeRule,
|
|
10
|
+
"prefer-types-over-assertions": preferTypesOverAssertionsRule,
|
|
9
11
|
},
|
|
10
12
|
});
|
|
11
13
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { defineRule } from "@oxlint/plugins";
|
|
2
|
+
|
|
3
|
+
import type { ESTree } from "@oxlint/plugins";
|
|
4
|
+
|
|
5
|
+
type TypeAssertion = ESTree.TSAsExpression | ESTree.TSTypeAssertion;
|
|
6
|
+
|
|
7
|
+
/** Prefer typing values at their source over asserting them at use sites. */
|
|
8
|
+
export const preferTypesOverAssertionsRule = defineRule({
|
|
9
|
+
meta: {
|
|
10
|
+
type: "problem",
|
|
11
|
+
docs: {
|
|
12
|
+
description:
|
|
13
|
+
"Prefer typing a value at its source over a TypeScript type assertion.",
|
|
14
|
+
},
|
|
15
|
+
messages: {
|
|
16
|
+
avoidAssertion:
|
|
17
|
+
"Type this value at its source, such as a function parameter or DOM lookup, instead of asserting it here. A SAFETY comment is not a fix.",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
create(context) {
|
|
21
|
+
const checkAssertion = (node: TypeAssertion) => {
|
|
22
|
+
if (
|
|
23
|
+
node.typeAnnotation.type === "TSTypeReference" &&
|
|
24
|
+
node.typeAnnotation.typeName.type === "Identifier" &&
|
|
25
|
+
node.typeAnnotation.typeName.name === "const"
|
|
26
|
+
) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
context.report({ node, messageId: "avoidAssertion" });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
TSAsExpression: checkAssertion,
|
|
35
|
+
TSTypeAssertion: checkAssertion,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
});
|