eslint-plugin-ts-fortress 1.1.0 → 1.2.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.
Files changed (37) hide show
  1. package/README.md +83 -4
  2. package/dist/index.mjs +2 -2
  3. package/dist/index.mjs.map +1 -1
  4. package/dist/plugin.d.mts +5 -0
  5. package/dist/plugin.d.mts.map +1 -1
  6. package/dist/plugin.mjs +32 -28
  7. package/dist/plugin.mjs.map +1 -1
  8. package/dist/rule-types.d.mts +43 -0
  9. package/dist/rule-types.d.mts.map +1 -1
  10. package/dist/rule-types.mjs +2 -1
  11. package/dist/rule-types.mjs.map +1 -1
  12. package/dist/rules/constants.mjs +17 -12
  13. package/dist/rules/constants.mjs.map +1 -1
  14. package/dist/rules/import-utils.mjs +96 -52
  15. package/dist/rules/import-utils.mjs.map +1 -1
  16. package/dist/rules/index.mjs +2 -2
  17. package/dist/rules/index.mjs.map +1 -1
  18. package/dist/rules/prefer-canonical-length-constrained-type.mjs +226 -157
  19. package/dist/rules/prefer-canonical-length-constrained-type.mjs.map +1 -1
  20. package/dist/rules/prefer-namespace-import.mjs +201 -149
  21. package/dist/rules/prefer-namespace-import.mjs.map +1 -1
  22. package/dist/rules/prefer-schema-over-guard-chain.d.mts +56 -0
  23. package/dist/rules/prefer-schema-over-guard-chain.d.mts.map +1 -0
  24. package/dist/rules/prefer-schema-over-guard-chain.mjs +212 -0
  25. package/dist/rules/prefer-schema-over-guard-chain.mjs.map +1 -0
  26. package/dist/rules/rules.d.mts +4 -0
  27. package/dist/rules/rules.d.mts.map +1 -1
  28. package/dist/rules/rules.mjs +6 -7
  29. package/dist/rules/rules.mjs.map +1 -1
  30. package/dist/types.mjs +2 -2
  31. package/dist/types.mjs.map +1 -1
  32. package/package.json +6 -7
  33. package/src/plugin.mts +1 -0
  34. package/src/rule-types.mts +50 -0
  35. package/src/rules/prefer-schema-over-guard-chain.mts +257 -0
  36. package/src/rules/prefer-schema-over-guard-chain.test.mts +143 -0
  37. package/src/rules/rules.mts +2 -0
package/README.md CHANGED
@@ -67,10 +67,11 @@ export default [
67
67
 
68
68
  ## Rules
69
69
 
70
- | Rule | Description |
71
- | :----------------------------------------- | :-------------------------------------------------------------------------------------------- |
72
- | `prefer-canonical-length-constrained-type` | Normalize a length-constrained array combinator with degenerate bounds to its canonical form. |
73
- | `prefer-namespace-import` | Require `ts-fortress` to be imported as a namespace rather than by name. |
70
+ | Rule | Description |
71
+ | :----------------------------------------- | :--------------------------------------------------------------------------------------------- |
72
+ | `prefer-canonical-length-constrained-type` | Normalize a length-constrained array combinator with degenerate bounds to its canonical form. |
73
+ | `prefer-namespace-import` | Require `ts-fortress` to be imported as a namespace rather than by name. |
74
+ | `prefer-schema-over-guard-chain` | Report a hand-written chain of type guards on one value once it is long enough to be a schema. |
74
75
 
75
76
  ### `prefer-canonical-length-constrained-type`
76
77
 
@@ -216,6 +217,84 @@ completed safely:
216
217
  - the file has two namespace imports of `ts-fortress`, or one declaration that
217
218
  mixes a namespace specifier with a named or default one.
218
219
 
220
+ ### `prefer-schema-over-guard-chain`
221
+
222
+ A long chain of hand-written type guards is a shape declaration that cannot be
223
+ read as one:
224
+
225
+ ```ts
226
+ // ❌
227
+ const isProject = (value: unknown): value is Project =>
228
+ isRecord(value) &&
229
+ hasKey(value, 'name') &&
230
+ isString(value.name) &&
231
+ hasKey(value, 'path') &&
232
+ isString(value.path);
233
+
234
+ // ✅
235
+ const PROJECT = t.record({ name: t.string(), path: t.string() });
236
+ ```
237
+
238
+ The length is the least of it. What the chain cannot do is say what was wrong:
239
+ it returns `false`, so the caller filtering on it drops the value silently, with
240
+ nothing left of which field was missing or what type it turned out to be. The
241
+ shape is declared and checked in the same breath, so it cannot be named, reused,
242
+ or read on its own. `validate` returns structured `ValidationError`s, ready for
243
+ `validationErrorsToMessages`.
244
+
245
+ The rule reports; there is no fix. Writing the schema is the work, and it is not
246
+ mechanical — the chain says what the value must _have_, never what it _is_, so
247
+ an optional member, a union, and a member that is simply never checked are
248
+ indistinguishable from the guards alone.
249
+
250
+ #### What is counted
251
+
252
+ Guards within one `&&` chain, or one `||` chain of negated guards — the
253
+ early-return spelling of the same check — grouped by the identifier their first
254
+ argument is rooted at, so `hasKey(a, 'b')` and `isString(a.b)` count together
255
+ while guards on two different values do not add up.
256
+
257
+ A whole function body is deliberately not the unit. The same value checked once
258
+ per field across a `fill`-style function is a series of defaults rather than a
259
+ shape check, and measuring both units over one repository showed those to be
260
+ almost all of what a function-scoped count reports.
261
+
262
+ #### Options
263
+
264
+ ```ts
265
+ 'ts-fortress/prefer-schema-over-guard-chain': ['error', { threshold: 4 }],
266
+ ```
267
+
268
+ - `threshold` (default `5`) — how many guards on one value a single chain may
269
+ contain before it is reported.
270
+ - `guards` (default: the `ts-data-forge` narrowing helpers — `hasKey`,
271
+ `isRecord`, `isString`, `isNumber`, `isBoolean`, `isBigint`, `isSymbol`,
272
+ `isArray`, `isNonEmpty`, `isNonNullish`, `isNotNull`, `isNotUndefined`,
273
+ `isPrimitive`) — the names to count, replacing the default list. A member call
274
+ is matched on its property name, so `Arr.isArray` is named `isArray`.
275
+
276
+ The default threshold comes from a distribution rather than from taste. Counted
277
+ over the 3420 files of the repository this rule was written in, as they stood
278
+ before it was applied to them:
279
+
280
+ | guards | chains |
281
+ | -----: | -----: |
282
+ | 1 | 103 |
283
+ | 2 | 41 |
284
+ | 3 | 17 |
285
+ | 4 | 1 |
286
+ | 5 | 1 |
287
+ | 6+ | 0 |
288
+
289
+ One and two are ordinary narrowing and reporting them would be noise; three is
290
+ still common enough to be a style rather than a smell. Four and five have one
291
+ chain each, and they differ in exactly the way the threshold has to: the chain
292
+ of four narrows a value that is already typed, which is the case this rule is
293
+ least interested in, while the chain of five narrows the result of a
294
+ `JSON.parse` — the case it exists for. So the default sits between them, at the
295
+ length of the chain that prompted the rule. That chain of five is the one site
296
+ the rule reported when it was turned on, and it has since been rewritten.
297
+
219
298
  ## License
220
299
 
221
300
  [Apache-2.0](https://github.com/noshiro-pf/mono/blob/main/libs/eslint-plugin-ts-fortress/LICENSE)
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
  export { eslintPluginTsFortress } from './plugin.mjs';
2
- export { tsFortressRules } from './rules/rules.mjs';
3
- //# sourceMappingURL=index.mjs.map
2
+ export { tsFortressRules } from './rules/index.mjs';
3
+ //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.mts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAKtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/plugin.d.mts CHANGED
@@ -8,6 +8,10 @@ export declare const eslintPluginTsFortress: {
8
8
  readonly 'prefer-namespace-import': import("@typescript-eslint/utils/ts-eslint").RuleModule<"removeSideEffectImport" | "useNamespaceImport", readonly [(Readonly<{
9
9
  namespaceName?: string;
10
10
  }> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
+ readonly 'prefer-schema-over-guard-chain': import("@typescript-eslint/utils/ts-eslint").RuleModule<"preferSchema", readonly [(Readonly<{
12
+ threshold?: number;
13
+ guards?: readonly string[];
14
+ }> | undefined)?], unknown, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
11
15
  };
12
16
  readonly configs: {
13
17
  /** Enables every rule of this plugin at `error`. */
@@ -19,6 +23,7 @@ export declare const eslintPluginTsFortress: {
19
23
  readonly rules: {
20
24
  readonly 'ts-fortress/prefer-canonical-length-constrained-type': 'error';
21
25
  readonly 'ts-fortress/prefer-namespace-import': 'error';
26
+ readonly 'ts-fortress/prefer-schema-over-guard-chain': 'error';
22
27
  };
23
28
  };
24
29
  };
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.mts","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAgCvE,eAAO,MAAM,sBAAsB;;iBAE/B,IAAI,EAAE,2BAA2B;;;;;;;;;QAIjC,oDAAoD;iBACpD,WAAW;2BAtBP,yBAAyB;;yBAQzB,aAAa,EAAI,YAAY;;;iFAhBqB,OAAO;gEACxB,OAAO;;;;CA+Bf,CAAC"}
1
+ {"version":3,"file":"plugin.d.mts","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AAEA,OAAO,EAAyB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAiCvE,eAAO,MAAM,sBAAsB;;iBAE/B,IAAI,EAAE,2BAA2B;;;;;;;;;;;;;QAIjC,oDAAoD;iBACpD,WAAW;2BAtBP,yBAAyB;;yBAQzB,aAAa,EAAI,YAAY;;;iFAjBqB,OAAO;gEACxB,OAAO;uEACA,OAAO;;;;CA+BtB,CAAC"}
package/dist/plugin.mjs CHANGED
@@ -1,34 +1,38 @@
1
- import { tsFortressRules } from './rules/rules.mjs';
1
+ import { tsFortressRules } from './rules/index.mjs';
2
+
3
+
4
+
5
+
6
+
2
7
 
3
8
  const recommendedRules = {
4
- "ts-fortress/prefer-canonical-length-constrained-type": "error",
5
- "ts-fortress/prefer-namespace-import": "error"
9
+ 'ts-fortress/prefer-canonical-length-constrained-type': 'error',
10
+ 'ts-fortress/prefer-namespace-import': 'error',
11
+ 'ts-fortress/prefer-schema-over-guard-chain': 'error',
6
12
  };
7
13
  const recommendedConfig = {
8
- name: "ts-fortress/recommended",
9
- plugins: {
10
- // Resolved lazily so that this config registers the *same* object that
11
- // `eslintPluginTsFortress` refers to. ESLint rejects a plugin name that
12
- // maps to two different objects with `Cannot redefine plugin`, which is
13
- // what a user combining this preset with their own
14
- // `plugins: { 'ts-fortress': eslintPluginTsFortress }` entry would hit if
15
- // the preset embedded a separate copy of the plugin.
16
- get "ts-fortress"() {
17
- return eslintPluginTsFortress;
18
- }
19
- },
20
- rules: recommendedRules
21
- };
22
- const eslintPluginTsFortress = {
23
- meta: {
24
- name: "eslint-plugin-ts-fortress"
25
- },
26
- rules: tsFortressRules,
27
- configs: {
28
- /** Enables every rule of this plugin at `error`. */
29
- recommended: recommendedConfig
30
- }
14
+ name: 'ts-fortress/recommended',
15
+ plugins: {
16
+
17
+
18
+
19
+
20
+
21
+
22
+ get 'ts-fortress'() {
23
+ return eslintPluginTsFortress;
24
+ },
25
+ },
26
+ rules: recommendedRules,
31
27
  };
28
+ export const eslintPluginTsFortress = {
29
+ meta: {
30
+ name: 'eslint-plugin-ts-fortress',
31
+ },
32
+ rules: tsFortressRules,
33
+ configs: {
32
34
 
33
- export { eslintPluginTsFortress };
34
- //# sourceMappingURL=plugin.mjs.map
35
+ recommended: recommendedConfig,
36
+ },
37
+ };
38
+ //# sourceMappingURL=plugin.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","sources":["../src/plugin.mts"],"sourcesContent":["import { type ReadonlyRecord } from 'ts-type-forge';\nimport { tsFortressRules } from './rules/index.mjs';\nimport { type ESLintFlatConfig, type ESLintPlugin } from './types.mjs';\n\n/**\n * Every rule this plugin ships, at `error`.\n *\n * The `satisfies` clause below is keyed off {@link tsFortressRules}, so adding\n * a rule without listing it here fails to type-check.\n */\nconst recommendedRules = {\n 'ts-fortress/prefer-canonical-length-constrained-type': 'error',\n 'ts-fortress/prefer-namespace-import': 'error',\n} as const satisfies ReadonlyRecord<\n `ts-fortress/${keyof typeof tsFortressRules}`,\n 'error'\n>;\n\nconst recommendedConfig = {\n name: 'ts-fortress/recommended',\n plugins: {\n // Resolved lazily so that this config registers the *same* object that\n // `eslintPluginTsFortress` refers to. ESLint rejects a plugin name that\n // maps to two different objects with `Cannot redefine plugin`, which is\n // what a user combining this preset with their own\n // `plugins: { 'ts-fortress': eslintPluginTsFortress }` entry would hit if\n // the preset embedded a separate copy of the plugin.\n get 'ts-fortress'(): ESLintPlugin {\n return eslintPluginTsFortress;\n },\n },\n rules: recommendedRules,\n} as const satisfies ESLintFlatConfig;\n\nexport const eslintPluginTsFortress = {\n meta: {\n name: 'eslint-plugin-ts-fortress',\n },\n rules: tsFortressRules,\n configs: {\n /** Enables every rule of this plugin at `error`. */\n recommended: recommendedConfig,\n },\n} as const satisfies ESLintPlugin;\n"],"names":[],"mappings":";;AAUA,MAAM,gBAAA,GAAmB;AAAA,EACvB,sDAAA,EAAwD,OAAA;AAAA,EACxD,qCAAA,EAAuC;AACzC,CAAA;AAKA,MAAM,iBAAA,GAAoB;AAAA,EACxB,IAAA,EAAM,yBAAA;AAAA,EACN,OAAA,EAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOP,IAAI,aAAA,GAA8B;AAChC,MAAA,OAAO,sBAAA;AAAA,IACT;AAAA,GACF;AAAA,EACA,KAAA,EAAO;AACT,CAAA;AAEO,MAAM,sBAAA,GAAyB;AAAA,EACpC,IAAA,EAAM;AAAA,IACJ,IAAA,EAAM;AAAA,GACR;AAAA,EACA,KAAA,EAAO,eAAA;AAAA,EACP,OAAA,EAAS;AAAA;AAAA,IAEP,WAAA,EAAa;AAAA;AAEjB;;"}
1
+ {"version":3,"file":"plugin.mjs","sourceRoot":"","sources":["../src/plugin.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGpD;;;;;GAKG;AACH,MAAM,gBAAgB,GAAG;IACvB,sDAAsD,EAAE,OAAO;IAC/D,qCAAqC,EAAE,OAAO;IAC9C,4CAA4C,EAAE,OAAO;CAItD,CAAC;AAEF,MAAM,iBAAiB,GAAG;IACxB,IAAI,EAAE,yBAAyB;IAC/B,OAAO,EAAE;QACP,uEAAuE;QACvE,wEAAwE;QACxE,wEAAwE;QACxE,mDAAmD;QACnD,0EAA0E;QAC1E,qDAAqD;QACrD,IAAI,aAAa;YACf,OAAO,sBAAsB,CAAC;QAChC,CAAC;KACF;IACD,KAAK,EAAE,gBAAgB;CACY,CAAC;AAEtC,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,IAAI,EAAE;QACJ,IAAI,EAAE,2BAA2B;KAClC;IACD,KAAK,EAAE,eAAe;IACtB,OAAO,EAAE;QACP,oDAAoD;QACpD,WAAW,EAAE,iBAAiB;KAC/B;CAC8B,CAAC"}
@@ -57,12 +57,55 @@ declare namespace PreferNamespaceImport {
57
57
  type Options = NonNullable<RuleOptionsOf<'prefer-namespace-import'>[0]>;
58
58
  type RuleEntry = 'off' | Linter.Severity | SpreadOptionsIfIsArray<readonly [Linter.StringSeverity, Options]>;
59
59
  }
60
+ /**
61
+ * @description Report a chain of hand-written type guards narrowing one value, once it is long enough to be a schema, and point at `ts-fortress`
62
+ *
63
+ * ```md
64
+ * | key | value |
65
+ * | :--------- | :--------- |
66
+ * | type | suggestion |
67
+ * | deprecated | false |
68
+ * | fixable | false |
69
+ * ```
70
+ */
71
+ declare namespace PreferSchemaOverGuardChain {
72
+ /**
73
+ * ### schema
74
+ *
75
+ * ```json
76
+ * [
77
+ * {
78
+ * "type": "object",
79
+ * "properties": {
80
+ * "threshold": {
81
+ * "type": "integer",
82
+ * "minimum": 2,
83
+ * "description": "How many guards on one value a single chain may contain before it is reported. Defaults to 5."
84
+ * },
85
+ * "guards": {
86
+ * "type": "array",
87
+ * "items": {
88
+ * "type": "string"
89
+ * },
90
+ * "description": "Names of the guard functions to count, replacing the default list. A member call is matched on its property name, so `Arr.isArray` is named `isArray`."
91
+ * }
92
+ * },
93
+ * "additionalProperties": false
94
+ * }
95
+ * ]
96
+ * ```
97
+ */
98
+ type Options = NonNullable<RuleOptionsOf<'prefer-schema-over-guard-chain'>[0]>;
99
+ type RuleEntry = 'off' | Linter.Severity | SpreadOptionsIfIsArray<readonly [Linter.StringSeverity, Options]>;
100
+ }
60
101
  export type EslintTsFortressRules = Readonly<{
61
102
  'ts-fortress/prefer-canonical-length-constrained-type': PreferCanonicalLengthConstrainedType.RuleEntry;
62
103
  'ts-fortress/prefer-namespace-import': PreferNamespaceImport.RuleEntry;
104
+ 'ts-fortress/prefer-schema-over-guard-chain': PreferSchemaOverGuardChain.RuleEntry;
63
105
  }>;
64
106
  export type EslintTsFortressRulesOption = Readonly<{
65
107
  'ts-fortress/prefer-namespace-import': PreferNamespaceImport.Options;
108
+ 'ts-fortress/prefer-schema-over-guard-chain': PreferSchemaOverGuardChain.Options;
66
109
  }>;
67
110
  type AssertTrue<B extends true> = B;
68
111
  export type RuleNamesAreInSync = AssertTrue<TypeEq<keyof EslintTsFortressRules, `ts-fortress/${keyof typeof tsFortressRules}`>>;
@@ -1 +1 @@
1
- {"version":3,"file":"rule-types.d.mts","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,KAAK,sBAAsB,CACzB,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,IACjD,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,GAC/B,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GACzC,CAAC,CAAC;AAEN;;;;GAIG;AACH,KAAK,aAAa,CAAC,IAAI,SAAS,MAAM,OAAO,eAAe,IAC1D,CAAC,OAAO,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,UAAU,CACxD,MAAM,WAAW,SAAS,MAAM,EAChC,MAAM,OAAO,SAAS,SAAS,OAAO,EAAE,CACzC,GACG,OAAO,GACP,KAAK,CAAC;AAEZ;;;;;;;;;;GAUG;AACH,kBAAU,oCAAoC,CAAC;IAC7C,KAAY,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC;CAC/C;AAED;;;;;;;;;;GAUG;AACH,kBAAU,qBAAqB,CAAC;IAC9B;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAY,OAAO,GAAG,WAAW,CAC/B,aAAa,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAC5C,CAAC;IAEF,KAAY,SAAS,GACjB,KAAK,GACL,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;CACvE;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,sDAAsD,EAAE,oCAAoC,CAAC,SAAS,CAAC;IACvG,qCAAqC,EAAE,qBAAqB,CAAC,SAAS,CAAC;CACxE,CAAC,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,qCAAqC,EAAE,qBAAqB,CAAC,OAAO,CAAC;CACtE,CAAC,CAAC;AAIH,KAAK,UAAU,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;AAEpC,MAAM,MAAM,kBAAkB,GAAG,UAAU,CACzC,MAAM,CACJ,MAAM,qBAAqB,EAC3B,eAAe,MAAM,OAAO,eAAe,EAAE,CAC9C,CACF,CAAC"}
1
+ {"version":3,"file":"rule-types.d.mts","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AACrC,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,KAAK,sBAAsB,CACzB,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,IACjD,CAAC,CAAC,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,GAC/B,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GACzC,CAAC,CAAC;AAEN;;;;GAIG;AACH,KAAK,aAAa,CAAC,IAAI,SAAS,MAAM,OAAO,eAAe,IAC1D,CAAC,OAAO,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,QAAQ,CAAC,UAAU,CACxD,MAAM,WAAW,SAAS,MAAM,EAChC,MAAM,OAAO,SAAS,SAAS,OAAO,EAAE,CACzC,GACG,OAAO,GACP,KAAK,CAAC;AAEZ;;;;;;;;;;GAUG;AACH,kBAAU,oCAAoC,CAAC;IAC7C,KAAY,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC;CAC/C;AAED;;;;;;;;;;GAUG;AACH,kBAAU,qBAAqB,CAAC;IAC9B;;;;;;;;;;;;;;;;;;OAkBG;IACH,KAAY,OAAO,GAAG,WAAW,CAC/B,aAAa,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAC5C,CAAC;IAEF,KAAY,SAAS,GACjB,KAAK,GACL,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;CACvE;AAED;;;;;;;;;;GAUG;AACH,kBAAU,0BAA0B,CAAC;IACnC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,KAAY,OAAO,GAAG,WAAW,CAC/B,aAAa,CAAC,gCAAgC,CAAC,CAAC,CAAC,CAAC,CACnD,CAAC;IAEF,KAAY,SAAS,GACjB,KAAK,GACL,MAAM,CAAC,QAAQ,GACf,sBAAsB,CAAC,SAAS,CAAC,MAAM,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;CACvE;AAED,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,sDAAsD,EAAE,oCAAoC,CAAC,SAAS,CAAC;IACvG,qCAAqC,EAAE,qBAAqB,CAAC,SAAS,CAAC;IACvE,4CAA4C,EAAE,0BAA0B,CAAC,SAAS,CAAC;CACpF,CAAC,CAAC;AAEH,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,qCAAqC,EAAE,qBAAqB,CAAC,OAAO,CAAC;IACrE,4CAA4C,EAAE,0BAA0B,CAAC,OAAO,CAAC;CAClF,CAAC,CAAC;AAIH,KAAK,UAAU,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;AAEpC,MAAM,MAAM,kBAAkB,GAAG,UAAU,CACzC,MAAM,CACJ,MAAM,qBAAqB,EAC3B,eAAe,MAAM,OAAO,eAAe,EAAE,CAC9C,CACF,CAAC"}
@@ -1,2 +1,3 @@
1
1
 
2
- //# sourceMappingURL=rule-types.mjs.map
2
+ export {};
3
+ //# sourceMappingURL=rule-types.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"rule-types.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"rule-types.mjs","sourceRoot":"","sources":["../src/rule-types.mts"],"names":[],"mappings":"AAAA,oBAAoB"}
@@ -1,12 +1,17 @@
1
- const TS_FORTRESS_MODULE = "ts-fortress";
2
- const ARRAY_FN = "array";
3
- const BOUNDED_LENGTH_TUPLE_FN = "boundedLengthTuple";
4
- const FIXED_LENGTH_TUPLE_FN = "fixedLengthTuple";
5
- const MAX_LENGTH_TUPLE_FN = "maxLengthTuple";
6
- const MIN_LENGTH_ARRAY_FN = "minLengthArray";
7
- const MIN_LENGTH_TUPLE_FN = "minLengthTuple";
8
- const NON_EMPTY_ARRAY_FN = "nonEmptyArray";
9
- const STRUCTURAL_PREFIX_CAP = 10;
10
-
11
- export { ARRAY_FN, BOUNDED_LENGTH_TUPLE_FN, FIXED_LENGTH_TUPLE_FN, MAX_LENGTH_TUPLE_FN, MIN_LENGTH_ARRAY_FN, MIN_LENGTH_TUPLE_FN, NON_EMPTY_ARRAY_FN, STRUCTURAL_PREFIX_CAP, TS_FORTRESS_MODULE };
12
- //# sourceMappingURL=constants.mjs.map
1
+ export const TS_FORTRESS_MODULE = 'ts-fortress';
2
+ export const ARRAY_FN = 'array';
3
+ export const BOUNDED_LENGTH_TUPLE_FN = 'boundedLengthTuple';
4
+ export const FIXED_LENGTH_TUPLE_FN = 'fixedLengthTuple';
5
+ export const MAX_LENGTH_TUPLE_FN = 'maxLengthTuple';
6
+ export const MIN_LENGTH_ARRAY_FN = 'minLengthArray';
7
+ export const MIN_LENGTH_TUPLE_FN = 'minLengthTuple';
8
+ export const NON_EMPTY_ARRAY_FN = 'nonEmptyArray';
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+ export const STRUCTURAL_PREFIX_CAP = 10;
17
+ //# sourceMappingURL=constants.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","sources":["../../src/rules/constants.mts"],"sourcesContent":["export const TS_FORTRESS_MODULE = 'ts-fortress';\n\nexport const ARRAY_FN = 'array';\n\nexport const BOUNDED_LENGTH_TUPLE_FN = 'boundedLengthTuple';\n\nexport const FIXED_LENGTH_TUPLE_FN = 'fixedLengthTuple';\n\nexport const MAX_LENGTH_TUPLE_FN = 'maxLengthTuple';\n\nexport const MIN_LENGTH_ARRAY_FN = 'minLengthArray';\n\nexport const MIN_LENGTH_TUPLE_FN = 'minLengthTuple';\n\nexport const NON_EMPTY_ARRAY_FN = 'nonEmptyArray';\n\n/**\n * Inclusive upper bound of ts-type-forge's `StructuralPrefixLength` (`0..10`) —\n * the lengths the structural `*Tuple` combinators encode in their result type.\n * A bound outside this range selects a different overload (one that drops the\n * constraint), so a rewrite that carries a bound over to another combinator\n * only stays type-identical while the bound is within it.\n */\nexport const STRUCTURAL_PREFIX_CAP = 10;\n"],"names":[],"mappings":"AAAO,MAAM,kBAAA,GAAqB;AAE3B,MAAM,QAAA,GAAW;AAEjB,MAAM,uBAAA,GAA0B;AAEhC,MAAM,qBAAA,GAAwB;AAE9B,MAAM,mBAAA,GAAsB;AAE5B,MAAM,mBAAA,GAAsB;AAE5B,MAAM,mBAAA,GAAsB;AAE5B,MAAM,kBAAA,GAAqB;AAS3B,MAAM,qBAAA,GAAwB;;"}
1
+ {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../src/rules/constants.mts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEhD,MAAM,CAAC,MAAM,QAAQ,GAAG,OAAO,CAAC;AAEhC,MAAM,CAAC,MAAM,uBAAuB,GAAG,oBAAoB,CAAC;AAE5D,MAAM,CAAC,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAExD,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAEpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,gBAAgB,CAAC;AAEpD,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC"}
@@ -1,58 +1,102 @@
1
- import { AST_NODE_TYPES } from '@typescript-eslint/utils';
1
+ import { AST_NODE_TYPES, } from '@typescript-eslint/utils';
2
2
  import { Arr } from 'ts-data-forge';
3
3
  import { TS_FORTRESS_MODULE } from './constants.mjs';
4
4
 
5
- const getTsFortressImports = (program) => program.body.filter(
6
- (node) => node.type === AST_NODE_TYPES.ImportDeclaration && node.source.value === TS_FORTRESS_MODULE
7
- );
8
- const getImportedLocalName = (importDeclarations, importedName) => importDeclarations.flatMap((declaration) => declaration.specifiers).find(
9
- (specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier && (specifier.imported.type === AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value) === importedName
10
- )?.local.name;
11
- const buildCalleeResolver = (importDeclarations) => {
12
- const specifiers = importDeclarations.flatMap(
13
- (declaration) => declaration.specifiers
14
- );
15
- const namespaceNames = new Set(
16
- specifiers.filter(
17
- (specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier
18
- ).map((specifier) => specifier.local.name)
19
- );
20
- const localToCanonical = new Map(
21
- specifiers.flatMap((specifier) => {
22
- if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) return [];
23
- const importedName = specifier.imported.type === AST_NODE_TYPES.Identifier ? specifier.imported.name : specifier.imported.value;
24
- return typeof importedName === "string" ? [[specifier.local.name, importedName]] : [];
25
- })
26
- );
27
- return (callee) => {
28
- if (callee.type === AST_NODE_TYPES.Identifier) {
29
- const canonicalName = localToCanonical.get(callee.name);
30
- return canonicalName === void 0 ? void 0 : { canonicalName, propertyNode: callee, isNamespace: false };
31
- }
32
- return callee.type === AST_NODE_TYPES.MemberExpression && !callee.computed && callee.object.type === AST_NODE_TYPES.Identifier && namespaceNames.has(callee.object.name) && callee.property.type === AST_NODE_TYPES.Identifier ? {
33
- canonicalName: callee.property.name,
34
- propertyNode: callee.property,
35
- isNamespace: true
36
- } : void 0;
37
- };
5
+ export const getTsFortressImports = (program) => program.body.filter((node) => node.type === AST_NODE_TYPES.ImportDeclaration &&
6
+ node.source.value === TS_FORTRESS_MODULE);
7
+
8
+
9
+
10
+
11
+
12
+
13
+ export const getImportedLocalName = (importDeclarations, importedName) => importDeclarations
14
+ .flatMap((declaration) => declaration.specifiers)
15
+ .find((specifier) => specifier.type === AST_NODE_TYPES.ImportSpecifier &&
16
+ (specifier.imported.type === AST_NODE_TYPES.Identifier
17
+ ? specifier.imported.name
18
+ : specifier.imported.value) === importedName)?.local.name;
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+ export const buildCalleeResolver = (importDeclarations) => {
27
+ const specifiers = importDeclarations.flatMap((declaration) => declaration.specifiers);
28
+ const namespaceNames = new Set(specifiers
29
+ .filter((specifier) => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier)
30
+ .map((specifier) => specifier.local.name));
31
+ const localToCanonical = new Map(specifiers.flatMap((specifier) => {
32
+ if (specifier.type !== AST_NODE_TYPES.ImportSpecifier)
33
+ return [];
34
+ const importedName = specifier.imported.type === AST_NODE_TYPES.Identifier
35
+ ? specifier.imported.name
36
+ : specifier.imported.value;
37
+ return typeof importedName === 'string'
38
+ ? [[specifier.local.name, importedName]]
39
+ : [];
40
+ }));
41
+ return (callee) => {
42
+ if (callee.type === AST_NODE_TYPES.Identifier) {
43
+ const canonicalName = localToCanonical.get(callee.name);
44
+ return canonicalName === undefined
45
+ ? undefined
46
+ : { canonicalName, propertyNode: callee, isNamespace: false };
47
+ }
48
+ return callee.type === AST_NODE_TYPES.MemberExpression &&
49
+ !callee.computed &&
50
+ callee.object.type === AST_NODE_TYPES.Identifier &&
51
+ namespaceNames.has(callee.object.name) &&
52
+ callee.property.type === AST_NODE_TYPES.Identifier
53
+ ? {
54
+ canonicalName: callee.property.name,
55
+ propertyNode: callee.property,
56
+ isNamespace: true,
57
+ }
58
+ : undefined;
59
+ };
38
60
  };
39
- const hasForeignBinding = (sourceCode, node, name) => {
40
- for (let mut_scope = sourceCode.getScope(node); mut_scope !== null; mut_scope = mut_scope.upper) {
41
- const variable = mut_scope.set.get(name);
42
- if (variable !== void 0) {
43
- return variable.defs.some((def) => !isTsFortressImportDef(def.node));
61
+
62
+
63
+
64
+
65
+
66
+
67
+
68
+
69
+
70
+ export const hasForeignBinding = (sourceCode, node, name) => {
71
+ for (let mut_scope = sourceCode.getScope(node); mut_scope !== null; mut_scope = mut_scope.upper) {
72
+ const variable = mut_scope.set.get(name);
73
+
74
+
75
+ if (variable !== undefined) {
76
+ return variable.defs.some((def) => !isTsFortressImportDef(def.node));
77
+ }
44
78
  }
45
- }
46
- return false;
79
+ return false;
47
80
  };
48
- const buildImportsFix = (fixer, program, names) => Arr.isEmpty(names) ? [] : [
49
- fixer.insertTextBefore(
50
- program,
51
- names.map((name) => `import { ${name} } from '${TS_FORTRESS_MODULE}';
52
- `).join("")
53
- )
54
- ];
55
- const isTsFortressImportDef = (node) => (node.type === AST_NODE_TYPES.ImportSpecifier || node.type === AST_NODE_TYPES.ImportDefaultSpecifier || node.type === AST_NODE_TYPES.ImportNamespaceSpecifier) && node.parent.type === AST_NODE_TYPES.ImportDeclaration && node.parent.source.value === TS_FORTRESS_MODULE;
56
-
57
- export { buildCalleeResolver, buildImportsFix, getImportedLocalName, getTsFortressImports, hasForeignBinding };
58
- //# sourceMappingURL=import-utils.mjs.map
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+ export const buildImportsFix = (fixer, program, names) => Arr.isEmpty(names)
91
+ ? []
92
+ : [
93
+ fixer.insertTextBefore(program, names
94
+ .map((name) => `import { ${name} } from '${TS_FORTRESS_MODULE}';\n`)
95
+ .join('')),
96
+ ];
97
+ const isTsFortressImportDef = (node) => (node.type === AST_NODE_TYPES.ImportSpecifier ||
98
+ node.type === AST_NODE_TYPES.ImportDefaultSpecifier ||
99
+ node.type === AST_NODE_TYPES.ImportNamespaceSpecifier) &&
100
+ node.parent.type === AST_NODE_TYPES.ImportDeclaration &&
101
+ node.parent.source.value === TS_FORTRESS_MODULE;
102
+ //# sourceMappingURL=import-utils.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"import-utils.mjs","sources":["../../src/rules/import-utils.mts"],"sourcesContent":["import {\n AST_NODE_TYPES,\n type TSESLint,\n type TSESTree,\n} from '@typescript-eslint/utils';\nimport { Arr } from 'ts-data-forge';\nimport { TS_FORTRESS_MODULE } from './constants.mjs';\n\n/* eslint-disable @typescript-eslint/prefer-readonly-parameter-types */\n\nexport type ResolvedCallee = Readonly<{\n /** The canonical (imported) ts-fortress name, regardless of local alias. */\n canonicalName: string;\n /** The identifier node to rewrite when replacing the callee name. */\n propertyNode: TSESTree.Node;\n /** Whether the call was made through a namespace import (`t.foo(...)`). */\n isNamespace: boolean;\n}>;\n\n/** Every `import ... from 'ts-fortress'` declaration in the file. */\nexport const getTsFortressImports = (\n program: TSESTree.Program,\n): readonly TSESTree.ImportDeclaration[] =>\n program.body.filter(\n (node): node is TSESTree.ImportDeclaration =>\n node.type === AST_NODE_TYPES.ImportDeclaration &&\n node.source.value === TS_FORTRESS_MODULE,\n );\n\n/**\n * Returns the in-scope local name a given ts-fortress export is imported as\n * (handling aliases such as `import { nonEmptyArray as nea }` → `'nea'`), or\n * `undefined` when it is not imported. Used so autofixes reference the binding\n * that actually exists rather than the canonical name.\n */\nexport const getImportedLocalName = (\n importDeclarations: readonly TSESTree.ImportDeclaration[],\n importedName: string,\n): string | undefined =>\n importDeclarations\n .flatMap((declaration) => declaration.specifiers)\n .find(\n (specifier) =>\n specifier.type === AST_NODE_TYPES.ImportSpecifier &&\n (specifier.imported.type === AST_NODE_TYPES.Identifier\n ? specifier.imported.name\n : specifier.imported.value) === importedName,\n )?.local.name;\n\n/**\n * Builds a resolver that maps a call expression's callee to the canonical\n * ts-fortress function it refers to. Handles named imports (including aliases)\n * and namespace imports (`import * as t` → `t.foo(...)`) — the latter being the\n * idiomatic way to consume ts-fortress. Returns `undefined` for any callee that\n * does not reference the given ts-fortress imports.\n */\nexport const buildCalleeResolver = (\n importDeclarations: readonly TSESTree.ImportDeclaration[],\n): ((callee: TSESTree.Expression) => ResolvedCallee | undefined) => {\n const specifiers = importDeclarations.flatMap(\n (declaration) => declaration.specifiers,\n );\n\n const namespaceNames = new Set(\n specifiers\n .filter(\n (specifier) =>\n specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier,\n )\n .map((specifier) => specifier.local.name),\n );\n\n const localToCanonical = new Map<string, string>(\n specifiers.flatMap((specifier) => {\n if (specifier.type !== AST_NODE_TYPES.ImportSpecifier) return [];\n\n const importedName =\n specifier.imported.type === AST_NODE_TYPES.Identifier\n ? specifier.imported.name\n : specifier.imported.value;\n\n return typeof importedName === 'string'\n ? [[specifier.local.name, importedName] as const]\n : [];\n }),\n );\n\n return (callee) => {\n if (callee.type === AST_NODE_TYPES.Identifier) {\n const canonicalName = localToCanonical.get(callee.name);\n\n return canonicalName === undefined\n ? undefined\n : { canonicalName, propertyNode: callee, isNamespace: false };\n }\n\n return callee.type === AST_NODE_TYPES.MemberExpression &&\n !callee.computed &&\n callee.object.type === AST_NODE_TYPES.Identifier &&\n namespaceNames.has(callee.object.name) &&\n callee.property.type === AST_NODE_TYPES.Identifier\n ? {\n canonicalName: callee.property.name,\n propertyNode: callee.property,\n isNamespace: true,\n }\n : undefined;\n };\n};\n\n/**\n * Whether `name` resolves, at `node`, to a binding that is not a ts-fortress\n * import — a local declaration, a parameter, or an import from another module.\n * An autofix that makes a call reference `name` must bail out in that case,\n * because the rewritten call would resolve to the wrong binding.\n *\n * Scope-based rather than a scan of the top-level statements, so a binding that\n * merely shadows the ts-fortress one around the call site is caught too.\n */\nexport const hasForeignBinding = (\n sourceCode: TSESLint.SourceCode,\n node: TSESTree.Node,\n name: string,\n): boolean => {\n for (\n let mut_scope: TSESLint.Scope.Scope | null = sourceCode.getScope(node);\n mut_scope !== null;\n mut_scope = mut_scope.upper\n ) {\n const variable = mut_scope.set.get(name);\n\n // The innermost binding wins, so the first scope that declares `name`\n // decides — an outer ts-fortress import does not rescue a shadowed name.\n if (variable !== undefined) {\n return variable.defs.some((def) => !isTsFortressImportDef(def.node));\n }\n }\n\n return false;\n};\n\n/**\n * Inserts `import { <name> } from 'ts-fortress';` for each name at the top of\n * the file. Placement is deliberately naive: prettier-plugin-organize-imports\n * (or any equivalent) merges and sorts them afterwards.\n *\n * All names go into a single fix on purpose: ESLint merges the fixes of one\n * report into one edit span, so two reports each inserting at the start of the\n * file would conflict and one of them would be dropped.\n */\nexport const buildImportsFix = (\n fixer: TSESLint.RuleFixer,\n program: TSESTree.Program,\n names: readonly string[],\n): readonly TSESLint.RuleFix[] =>\n Arr.isEmpty(names)\n ? ([] as const)\n : ([\n fixer.insertTextBefore(\n program,\n names\n .map((name) => `import { ${name} } from '${TS_FORTRESS_MODULE}';\\n`)\n .join(''),\n ),\n ] as const);\n\nconst isTsFortressImportDef = (node: TSESTree.Node): boolean =>\n (node.type === AST_NODE_TYPES.ImportSpecifier ||\n node.type === AST_NODE_TYPES.ImportDefaultSpecifier ||\n node.type === AST_NODE_TYPES.ImportNamespaceSpecifier) &&\n node.parent.type === AST_NODE_TYPES.ImportDeclaration &&\n node.parent.source.value === TS_FORTRESS_MODULE;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"import-utils.mjs","sourceRoot":"","sources":["../../src/rules/import-utils.mts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export { tsFortressRules } from './rules.mjs';
2
- //# sourceMappingURL=index.mjs.map
1
+ export * from './rules.mjs';
2
+ //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../src/rules/index.mts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC"}