@ttsc/lint 0.11.0-dev.20260518-2 → 0.12.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 (57) hide show
  1. package/README.md +67 -141
  2. package/lib/{structures/defaultFormat.d.ts → defaultFormat.d.ts} +3 -3
  3. package/lib/{structures/defaultFormat.js → defaultFormat.js} +3 -3
  4. package/lib/defaultFormat.js.map +1 -0
  5. package/lib/index.d.ts +1 -38
  6. package/lib/index.js +7 -5
  7. package/lib/index.js.map +1 -1
  8. package/lib/structures/ITtscLintConfig.d.ts +27 -0
  9. package/lib/structures/{PluginRuleNames.js → ITtscLintConfig.js} +1 -1
  10. package/lib/structures/ITtscLintConfig.js.map +1 -0
  11. package/lib/structures/{TtscLintFormatConfig.d.ts → ITtscLintFormatConfig.d.ts} +17 -16
  12. package/lib/structures/{TtscLintConfig.js → ITtscLintFormatConfig.js} +1 -1
  13. package/lib/structures/ITtscLintFormatConfig.js.map +1 -0
  14. package/lib/structures/ITtscLintPluginConfig.d.ts +6 -6
  15. package/lib/structures/TtscLintRuleMap.d.ts +11 -9
  16. package/lib/structures/TtscLintRuleOptions.d.ts +118 -144
  17. package/lib/structures/index.d.ts +2 -7
  18. package/lib/structures/index.js +2 -7
  19. package/lib/structures/index.js.map +1 -1
  20. package/linthost/config.go +1 -6
  21. package/linthost/config_format.go +253 -298
  22. package/linthost/format.go +91 -1
  23. package/package.json +3 -3
  24. package/rule/rule.go +124 -124
  25. package/src/{structures/defaultFormat.ts → defaultFormat.ts} +5 -5
  26. package/src/index.ts +7 -5
  27. package/src/structures/ITtscLintConfig.ts +33 -0
  28. package/src/structures/{TtscLintFormatConfig.ts → ITtscLintFormatConfig.ts} +17 -16
  29. package/src/structures/ITtscLintPluginConfig.ts +6 -6
  30. package/src/structures/TtscLintRuleMap.ts +17 -13
  31. package/src/structures/TtscLintRuleOptions.ts +118 -144
  32. package/src/structures/index.ts +2 -7
  33. package/lib/defineConfig.d.ts +0 -55
  34. package/lib/defineConfig.js +0 -39
  35. package/lib/defineConfig.js.map +0 -1
  36. package/lib/structures/PluginRuleNames.d.ts +0 -14
  37. package/lib/structures/PluginRuleNames.js.map +0 -1
  38. package/lib/structures/TtscLintConfig.d.ts +0 -27
  39. package/lib/structures/TtscLintConfig.js.map +0 -1
  40. package/lib/structures/TtscLintConfigEntry.d.ts +0 -39
  41. package/lib/structures/TtscLintConfigEntry.js +0 -3
  42. package/lib/structures/TtscLintConfigEntry.js.map +0 -1
  43. package/lib/structures/TtscLintFormatConfig.js +0 -3
  44. package/lib/structures/TtscLintFormatConfig.js.map +0 -1
  45. package/lib/structures/TtscLintPlugins.d.ts +0 -9
  46. package/lib/structures/TtscLintPlugins.js +0 -3
  47. package/lib/structures/TtscLintPlugins.js.map +0 -1
  48. package/lib/structures/TtscLintRuleEntry.d.ts +0 -22
  49. package/lib/structures/TtscLintRuleEntry.js +0 -3
  50. package/lib/structures/TtscLintRuleEntry.js.map +0 -1
  51. package/lib/structures/defaultFormat.js.map +0 -1
  52. package/src/defineConfig.ts +0 -69
  53. package/src/structures/PluginRuleNames.ts +0 -19
  54. package/src/structures/TtscLintConfig.ts +0 -31
  55. package/src/structures/TtscLintConfigEntry.ts +0 -50
  56. package/src/structures/TtscLintPlugins.ts +0 -10
  57. package/src/structures/TtscLintRuleEntry.ts +0 -28
@@ -1 +0,0 @@
1
- {"version":3,"file":"TtscLintConfigEntry.js","sourceRoot":"","sources":["../../src/structures/TtscLintConfigEntry.ts"],"names":[],"mappings":""}
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=TtscLintFormatConfig.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TtscLintFormatConfig.js","sourceRoot":"","sources":["../../src/structures/TtscLintFormatConfig.ts"],"names":[],"mappings":""}
@@ -1,9 +0,0 @@
1
- import type { ITtscLintPlugin } from "./ITtscLintPlugin";
2
- /**
3
- * Map of contributor plugins, keyed by their namespace prefix.
4
- *
5
- * The key (e.g. `"import"`) is what `@ttsc/lint`'s rule-name union joins with
6
- * each plugin's exported `rules` tuple (`"no-cycle"`) to produce the namespaced
7
- * rule names a user writes in `rules` (`"import/no-cycle"`).
8
- */
9
- export type TtscLintPlugins = Record<string, ITtscLintPlugin>;
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=TtscLintPlugins.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TtscLintPlugins.js","sourceRoot":"","sources":["../../src/structures/TtscLintPlugins.ts"],"names":[],"mappings":""}
@@ -1,22 +0,0 @@
1
- import type { TtscLintRuleOptionsMap } from "./TtscLintRuleOptions";
2
- import type { TtscLintSeverity } from "./TtscLintSeverity";
3
- /**
4
- * One rule's configuration entry.
5
- *
6
- * Accepts either a bare severity literal or a `[severity, options]` tuple. The
7
- * options slot's type is _picked per rule name_ via `TtscLintRuleOptionsMap` —
8
- * so a user writing
9
- *
10
- * "format/sort-imports": ["error", { importOrder: [...] }]
11
- *
12
- * Inside `TtscLintRuleMap` gets exact autocomplete and typo detection on the
13
- * options object. The rule name is the object key; the `[severity, options]`
14
- * tuple is the value.
15
- *
16
- * Rules that do not appear in `TtscLintRuleOptionsMap` accept only the severity
17
- * literal (or the bare `[severity]` tuple): the conditional arm collapses to
18
- * `never`, removing the options-tuple branch from the union for those rules.
19
- * This keeps `no-var` and friends from silently accepting unrecognized option
20
- * blobs.
21
- */
22
- export type TtscLintRuleEntry<R extends string = string> = TtscLintSeverity | readonly [TtscLintSeverity] | (R extends keyof TtscLintRuleOptionsMap ? readonly [TtscLintSeverity, TtscLintRuleOptionsMap[R]] : never);
@@ -1,3 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- //# sourceMappingURL=TtscLintRuleEntry.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TtscLintRuleEntry.js","sourceRoot":"","sources":["../../src/structures/TtscLintRuleEntry.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"defaultFormat.js","sourceRoot":"","sources":["../../src/structures/defaultFormat.ts"],"names":[],"mappings":";;;AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACU,QAAA,aAAa,GAAG,MAAM,CAAC,MAAM,CAAC;IACzC,QAAQ,EAAE,SAAS;IACnB,IAAI,EAAE,IAAI;IACV,WAAW,EAAE,KAAK;IAClB,aAAa,EAAE,KAAK;IACpB,UAAU,EAAE,EAAE;IACd,QAAQ,EAAE,CAAC;IACX,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,IAAI;CACe,CAAC,CAAC"}
@@ -1,69 +0,0 @@
1
- import type { TtscLintConfig } from "./structures/TtscLintConfig";
2
- import type { TtscLintPlugins } from "./structures/TtscLintPlugins";
3
-
4
- /**
5
- * Authoring helper that preserves the literal type of a lint config.
6
- *
7
- * ESLint's flat-config experience relies on `defineConfig` to capture the
8
- * const-narrowed type of the configuration array, which is what makes plugin
9
- * rule names autocomplete across entries. `@ttsc/lint` follows the same
10
- * pattern: pass your config through this helper and the contributor plugin
11
- * objects in `plugins` propagate their `rules` tuples into the rule-name
12
- * union.
13
- *
14
- * ```ts
15
- * import { defineConfig } from "@ttsc/lint";
16
- * import importPlugin from "@ttsc/lint-plugin-import";
17
- *
18
- * export default defineConfig([
19
- * {
20
- * plugins: { import: importPlugin },
21
- * rules: {
22
- * "no-var": "error",
23
- * "import/no-cycle": ["error", { maxDepth: 1 }],
24
- * },
25
- * },
26
- * ]);
27
- * ```
28
- *
29
- * The function is a pure pass-through at runtime. The generic gymnastics below
30
- * gather every `plugins` map across the array of config entries into one
31
- * intersected `TtscLintPlugins` shape that gets threaded back into the
32
- * `TtscLintConfig<P>` constraint. Without this, `TtscLintConfig`'s default `P =
33
- * Record<string, never>` rules out every namespaced rule name and `{
34
- * "import/no-cycle": "error" }` would be flagged as a typo.
35
- */
36
- export function defineConfig<const T extends TtscLintConfig<GatherPlugins<T>>>(
37
- config: T,
38
- ): T {
39
- return config;
40
- }
41
-
42
- /**
43
- * Walks the input type to collect every plugin map declared across entries.
44
- * Single entries yield the entry's `plugins`; arrays intersect every entry's
45
- * `plugins` so each entry's rule-name union remains valid for the whole array.
46
- * The intersection (vs. union) is load-bearing — TypeScript's `keyof (A | B)`
47
- * collapses to `never`, which would reject every namespaced rule name.
48
- *
49
- * Plugins declared exclusively inside an `extends` chain are NOT collected:
50
- * recursing into `T extends { extends?: infer E } ? GatherPlugins<E> : {}`
51
- * blows TypeScript's instantiation budget (`extends` is itself a
52
- * `TtscLintConfigEntry` tree). Authors should declare each plugin's `plugins`
53
- * map on the outermost entry where its rules are configured. The runtime
54
- * resolver still picks up plugins from `extends` entries; only the autocomplete
55
- * domain is bounded.
56
- */
57
- type GatherPlugins<T> = T extends { plugins?: infer P }
58
- ? P extends TtscLintPlugins
59
- ? P
60
- : {}
61
- : T extends readonly (infer Item)[]
62
- ? UnionToIntersection<Item extends unknown ? GatherPlugins<Item> : never>
63
- : {};
64
-
65
- type UnionToIntersection<U> = (
66
- U extends unknown ? (x: U) => void : never
67
- ) extends (x: infer I) => void
68
- ? I
69
- : never;
@@ -1,19 +0,0 @@
1
- import type { TtscLintPlugins } from "./TtscLintPlugins";
2
-
3
- /**
4
- * Builds the union of `${namespace}/${rule}` strings from a plugins map.
5
- *
6
- * Each plugin's `rules` tuple is read literally: an `as const` tuple
7
- * (`["no-cycle", "order"] as const`) provides exact autocomplete, while a plain
8
- * `string[]` collapses to `${namespace}/${string}` and disables rule-level typo
9
- * detection for that namespace.
10
- */
11
- export type PluginRuleNames<P extends TtscLintPlugins> = {
12
- [Ns in keyof P]: P[Ns] extends { rules?: infer R }
13
- ? R extends readonly (infer N)[]
14
- ? N extends string
15
- ? `${Ns & string}/${N}`
16
- : never
17
- : never
18
- : never;
19
- }[keyof P];
@@ -1,31 +0,0 @@
1
- import type { TtscLintConfigEntry } from "./TtscLintConfigEntry";
2
- import type { TtscLintPlugins } from "./TtscLintPlugins";
3
- import type { TtscLintRuleMap } from "./TtscLintRuleMap";
4
-
5
- /**
6
- * Top-level config accepted by `@ttsc/lint`.
7
- *
8
- * Three accepted forms, listed in expected order of preference:
9
- *
10
- * 1. **Flat-config array** — mirrors ESLint flat config exactly. Each entry can
11
- * scope by `files` / `ignores`, declare a `plugins` map of contributors,
12
- * configure `rules`, and configure formatting through the Prettier-style
13
- * {@link TtscLintFormatConfig | `format`} block. Multiple entries layer in
14
- * order.
15
- * 2. **Single config object** — same shape as one flat-config entry. Useful when
16
- * the project has no per-file scoping. Pass `format: { … }` here for the
17
- * smallest "describe my style" config.
18
- * 3. **Rules-only map** — historical shape kept for backward compat with
19
- * single-file projects. `{"no-var":"error"}` is interpreted as `[{rules:
20
- * {"no-var":"error"}}]`. The shorthand intentionally has no slot for the
21
- * `format` block — use form (1) or (2) to enable formatting.
22
- *
23
- * The generic parameter `P` lets `defineConfig` capture the literal plugin
24
- * object types declared in `plugins`. When non-empty, rule-name keys
25
- * autocomplete as `BuiltInRule | "<ns>/<rule>"` where the namespace-rule
26
- * combinations come from each plugin's `rules` tuple.
27
- */
28
- export type TtscLintConfig<P extends TtscLintPlugins = Record<string, never>> =
29
- | TtscLintRuleMap<P>
30
- | TtscLintConfigEntry<P>
31
- | readonly TtscLintConfigEntry<P>[];
@@ -1,50 +0,0 @@
1
- import type { TtscLintFormatConfig } from "./TtscLintFormatConfig";
2
- import type { TtscLintPlugins } from "./TtscLintPlugins";
3
- import type { TtscLintRuleMap } from "./TtscLintRuleMap";
4
-
5
- /**
6
- * One flat-config entry. ESLint-style `files` / `ignores` glob scoping, a
7
- * `plugins` namespace map of contributor plugin objects, an `extends` list of
8
- * child entries to fold in first, and a severity-keyed `rules` map applied
9
- * after the extends chain.
10
- *
11
- * Prettier-style formatting opts in through a sibling `format` block — see
12
- * `TtscLintFormatConfig`. The block can scope per-entry (e.g. wider
13
- * `printWidth` for `legacy/**`) just like `rules` does.
14
- */
15
- export interface TtscLintConfigEntry<
16
- P extends TtscLintPlugins = Record<string, never>,
17
- > {
18
- /** Globs that select the files this entry applies to. */
19
- files?: string | readonly string[];
20
-
21
- /** Globs that exclude files this entry would otherwise match. */
22
- ignores?: string | readonly string[];
23
-
24
- /**
25
- * Nested entries (or arrays of entries) folded in before this entry's own
26
- * rules apply. Mirrors ESLint flat config's `extends`: each child's rules
27
- * layer first, with `this.rules` taking precedence on key collisions.
28
- */
29
- extends?:
30
- | TtscLintConfigEntry<P>
31
- | readonly TtscLintConfigEntry<P>[]
32
- | readonly (TtscLintConfigEntry<P> | readonly TtscLintConfigEntry<P>[])[];
33
-
34
- /**
35
- * Contributor plugin objects keyed by namespace. Each value is the default
36
- * export of a `@ttsc/lint` contributor package (an `ITtscLintPlugin`).
37
- */
38
- plugins?: P;
39
-
40
- /** Rule-name → severity map. Supports severity tuples with options. */
41
- rules?: TtscLintRuleMap<P>;
42
-
43
- /**
44
- * Prettier-style flat configuration for the `format/*` rules. Presence
45
- * (even an empty `format: {}`) enables format-class rules at Prettier
46
- * defaults; absence keeps them all off. Per-rule overrides go through
47
- * the `rules` map — the `rules` entry wins on conflict.
48
- */
49
- format?: TtscLintFormatConfig;
50
- }
@@ -1,10 +0,0 @@
1
- import type { ITtscLintPlugin } from "./ITtscLintPlugin";
2
-
3
- /**
4
- * Map of contributor plugins, keyed by their namespace prefix.
5
- *
6
- * The key (e.g. `"import"`) is what `@ttsc/lint`'s rule-name union joins with
7
- * each plugin's exported `rules` tuple (`"no-cycle"`) to produce the namespaced
8
- * rule names a user writes in `rules` (`"import/no-cycle"`).
9
- */
10
- export type TtscLintPlugins = Record<string, ITtscLintPlugin>;
@@ -1,28 +0,0 @@
1
- import type { TtscLintRuleOptionsMap } from "./TtscLintRuleOptions";
2
- import type { TtscLintSeverity } from "./TtscLintSeverity";
3
-
4
- /**
5
- * One rule's configuration entry.
6
- *
7
- * Accepts either a bare severity literal or a `[severity, options]` tuple. The
8
- * options slot's type is _picked per rule name_ via `TtscLintRuleOptionsMap` —
9
- * so a user writing
10
- *
11
- * "format/sort-imports": ["error", { importOrder: [...] }]
12
- *
13
- * Inside `TtscLintRuleMap` gets exact autocomplete and typo detection on the
14
- * options object. The rule name is the object key; the `[severity, options]`
15
- * tuple is the value.
16
- *
17
- * Rules that do not appear in `TtscLintRuleOptionsMap` accept only the severity
18
- * literal (or the bare `[severity]` tuple): the conditional arm collapses to
19
- * `never`, removing the options-tuple branch from the union for those rules.
20
- * This keeps `no-var` and friends from silently accepting unrecognized option
21
- * blobs.
22
- */
23
- export type TtscLintRuleEntry<R extends string = string> =
24
- | TtscLintSeverity
25
- | readonly [TtscLintSeverity]
26
- | (R extends keyof TtscLintRuleOptionsMap
27
- ? readonly [TtscLintSeverity, TtscLintRuleOptionsMap[R]]
28
- : never);