@ttsc/lint 0.5.0 → 0.6.0-dev.20250501

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 CHANGED
@@ -27,8 +27,9 @@ Open your project's `tsconfig.json`, then add this entry under `compilerOptions.
27
27
  "plugins": [
28
28
  {
29
29
  "transform": "@ttsc/lint",
30
- "rules": {
30
+ "config": {
31
31
  "no-var": "error",
32
+ "prefer-const": "error",
32
33
  "no-explicit-any": "warning",
33
34
  "no-console": "off"
34
35
  }
@@ -47,6 +48,50 @@ npx ttsx src/index.ts
47
48
 
48
49
  Lint errors fail the command. With `ttsx`, lint errors stop the program before your entrypoint runs. Lint warnings are printed without changing the exit code.
49
50
 
51
+ You can also keep the lint rules in a standalone config file and leave only the file reference in `tsconfig.json`:
52
+
53
+ ```jsonc
54
+ {
55
+ "compilerOptions": {
56
+ "plugins": [
57
+ {
58
+ "transform": "@ttsc/lint",
59
+ "config": "./ttsc-lint.config.ts"
60
+ }
61
+ ]
62
+ }
63
+ }
64
+ ```
65
+
66
+ ```ts
67
+ // ttsc-lint.config.ts
68
+ export default {
69
+ "no-var": "error",
70
+ "prefer-const": "error",
71
+ "no-explicit-any": "warning",
72
+ "no-console": "off"
73
+ };
74
+ ```
75
+
76
+ `config` accepts either a config object or a path to `.json`, `.js`, `.cjs`, `.mjs`, `.ts`, `.cts`, or `.mts`. JavaScript and TypeScript config files may export the object directly, as `default`, as `config`, or as a function that returns the object. Relative paths are resolved from the owning tsconfig directory.
77
+
78
+ Inline `config` is also accepted:
79
+
80
+ ```jsonc
81
+ {
82
+ "compilerOptions": {
83
+ "plugins": [
84
+ {
85
+ "transform": "@ttsc/lint",
86
+ "config": {
87
+ "no-var": "error"
88
+ }
89
+ }
90
+ ]
91
+ }
92
+ }
93
+ ```
94
+
50
95
  ## Notes
51
96
 
52
97
  `@ttsc/lint` must be the first active plugin entry because it reports on the source code you wrote. Output plugins such as `@ttsc/banner`, `@ttsc/paths`, and `@ttsc/strip` can come after it.
@@ -56,7 +101,7 @@ Lint errors fail the command. With `ttsx`, lint errors stop the program before y
56
101
  "compilerOptions": {
57
102
  "plugins": [
58
103
  // Keep lint first.
59
- { "transform": "@ttsc/lint", "rules": { "no-var": "error" } },
104
+ { "transform": "@ttsc/lint", "config": { "no-var": "error", "prefer-const": "error" } },
60
105
 
61
106
  // Output plugins run after emit, in order.
62
107
  { "transform": "@ttsc/banner", "banner": "/*! @license MIT */" },
@@ -75,12 +120,10 @@ Rules are off until you enable them:
75
120
 
76
121
  ```jsonc
77
122
  {
78
- "rules": {
79
- "no-var": "error",
80
- "eqeqeq": "error",
81
- "prefer-template": "warning",
82
- "no-non-null-assertion": "off"
83
- }
123
+ "no-var": "error",
124
+ "eqeqeq": "error",
125
+ "prefer-template": "warning",
126
+ "no-non-null-assertion": "off"
84
127
  }
85
128
  ```
86
129
 
@@ -93,7 +136,10 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
93
136
  - [`ban-ts-comment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/ban-ts-comment.ts): rejects TypeScript suppression comments such as `@ts-ignore`.
94
137
  - [`ban-tslint-comment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/ban-tslint-comment.ts): rejects obsolete `tslint:` comments.
95
138
  - [`consistent-indexed-object-style`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-indexed-object-style.ts): prefers `Record` for single index-signature object types.
139
+ - [`consistent-type-assertions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-type-assertions.ts): prefers `as` type assertions over angle-bracket assertions.
140
+ - [`consistent-type-definitions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-type-definitions.ts): prefers interfaces for object-shaped type definitions.
96
141
  - [`consistent-type-imports`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/consistent-type-imports/violation.ts): uses `import type` when imported names are type-only.
142
+ - [`dot-notation`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/dot-notation.ts): prefers dot property access when a string-literal key is a valid identifier.
97
143
  - [`eqeqeq`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/eqeqeq.ts): requires strict equality operators.
98
144
  - [`for-direction`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/for-direction.ts): catches loop counters updated in the wrong direction.
99
145
  - [`no-alert`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-alert.ts): rejects `alert`, `confirm`, and `prompt`.
@@ -118,12 +164,14 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
118
164
  - [`no-dupe-keys`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dupe-keys.ts): rejects duplicate object keys.
119
165
  - [`no-duplicate-case`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-duplicate-case.ts): rejects duplicate `switch` case labels.
120
166
  - [`no-duplicate-enum-values`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-duplicate-enum-values.ts): rejects duplicate enum member values.
167
+ - [`no-dynamic-delete`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-dynamic-delete.ts): rejects `delete` on dynamically computed property keys.
121
168
  - [`no-empty`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty.ts): rejects empty blocks.
122
169
  - [`no-empty-character-class`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-character-class.ts): rejects empty regex character classes.
123
170
  - [`no-empty-function`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-function.ts): rejects empty functions.
124
171
  - [`no-empty-interface`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-interface.ts): rejects empty interfaces.
125
172
  - [`no-empty-object-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-object-type.ts): rejects empty object type literals.
126
173
  - [`no-empty-pattern`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-pattern.ts): rejects empty destructuring patterns.
174
+ - [`no-empty-static-block`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-empty-static-block.ts): rejects empty class static blocks.
127
175
  - [`no-eq-null`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-eq-null.ts): rejects loose null comparisons.
128
176
  - [`no-eval`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-eval.ts): rejects `eval`.
129
177
  - [`no-ex-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-ex-assign.ts): rejects reassignment of caught exceptions.
@@ -151,6 +199,7 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
151
199
  - [`no-new`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new.ts): rejects `new` expressions used only for side effects.
152
200
  - [`no-new-func`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new-func.ts): rejects `Function` constructors.
153
201
  - [`no-new-wrappers`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-new-wrappers.ts): rejects primitive wrapper constructors.
202
+ - [`no-non-null-asserted-nullish-coalescing`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-asserted-nullish-coalescing.ts): rejects non-null assertions next to `??`.
154
203
  - [`no-non-null-asserted-optional-chain`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-asserted-optional-chain.ts): rejects non-null assertions on optional chains.
155
204
  - [`no-non-null-assertion`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-non-null-assertion.ts): rejects postfix non-null assertions.
156
205
  - [`no-obj-calls`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-obj-calls.ts): rejects calling global objects as functions.
@@ -168,6 +217,7 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
168
217
  - [`no-self-assign`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-self-assign.ts): rejects assignments to the same value.
169
218
  - [`no-self-compare`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-self-compare.ts): rejects comparing a value to itself.
170
219
  - [`no-sequences`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-sequences.ts): rejects comma expressions.
220
+ - [`no-setter-return`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-setter-return.ts): rejects returned values from setters.
171
221
  - [`no-shadow-restricted-names`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-shadow-restricted-names.ts): rejects shadowing restricted globals.
172
222
  - [`no-sparse-arrays`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-sparse-arrays.ts): rejects sparse arrays.
173
223
  - [`no-template-curly-in-string`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-template-curly-in-string.ts): rejects `${...}` text inside normal strings.
@@ -175,24 +225,32 @@ The rule corpus is tested in `tests/lint/cases/*.ts`, which is the best place to
175
225
  - [`no-throw-literal`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-throw-literal.ts): rejects throwing literals.
176
226
  - [`no-undef-init`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-undef-init.ts): rejects initializing to `undefined`.
177
227
  - [`no-undefined`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-undefined.ts): rejects the global `undefined` identifier.
228
+ - [`no-unnecessary-type-constraint`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unnecessary-type-constraint.ts): rejects redundant `extends any` and `extends unknown` constraints.
178
229
  - [`no-unneeded-ternary`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unneeded-ternary.ts): rejects redundant ternary expressions.
230
+ - [`no-unsafe-declaration-merging`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-declaration-merging.ts): rejects unsafe class/interface declaration merging.
179
231
  - [`no-unsafe-finally`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-finally.ts): rejects control flow from `finally`.
232
+ - [`no-unsafe-function-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-function-type.ts): rejects the unsafe `Function` type.
180
233
  - [`no-unsafe-negation`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unsafe-negation.ts): rejects unsafe negation before relational checks.
181
234
  - [`no-unused-expressions`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unused-expressions.ts): rejects expression statements with no effect.
235
+ - [`no-unused-labels`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-unused-labels.ts): rejects labels that no `break` or `continue` targets.
182
236
  - [`no-useless-call`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-call.ts): rejects unnecessary `.call()` and `.apply()`.
183
237
  - [`no-useless-catch`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-catch.ts): rejects catch blocks that only rethrow.
184
238
  - [`no-useless-computed-key`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-computed-key.ts): rejects unnecessary computed property keys.
185
239
  - [`no-useless-concat`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-concat.ts): rejects unnecessary string concatenation.
240
+ - [`no-useless-constructor`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-constructor.ts): rejects empty constructors with no parameters.
186
241
  - [`no-useless-rename`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-useless-rename.ts): rejects import/export/destructure renames to the same name.
187
242
  - [`no-var`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-var.ts): rejects `var`.
188
243
  - [`no-with`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-with.ts): rejects `with` statements.
244
+ - [`no-wrapper-object-types`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/no-wrapper-object-types.ts): rejects boxed object type names such as `String` and `Boolean`.
189
245
  - [`object-shorthand`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/object-shorthand.ts): requires object property shorthand where possible.
190
246
  - [`operator-assignment`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/operator-assignment.ts): prefers compound assignment operators.
191
247
  - [`prefer-as-const`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-as-const.ts): prefers `as const` for literal assertions.
248
+ - [`prefer-const`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-const.ts): prefers `const` for `let` bindings that are never reassigned.
192
249
  - [`prefer-enum-initializers`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-enum-initializers.ts): requires explicit enum member initializers.
193
250
  - [`prefer-exponentiation-operator`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-exponentiation-operator.ts): prefers `**` over `Math.pow`.
194
251
  - [`prefer-for-of`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-for-of.ts): prefers `for...of` for simple array iteration.
195
252
  - [`prefer-function-type`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-function-type.ts): prefers function type aliases over single-call interfaces.
253
+ - [`prefer-literal-enum-member`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-literal-enum-member.ts): prefers literal enum member initializers over computed expressions.
196
254
  - [`prefer-namespace-keyword`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-namespace-keyword.ts): prefers `namespace` over TypeScript's legacy `module` keyword.
197
255
  - [`prefer-spread`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-spread.ts): prefers spread arguments over `.apply`.
198
256
  - [`prefer-template`](https://github.com/samchon/ttsc/blob/master/tests/lint/cases/prefer-template.ts): prefers template literals over string concatenation.
package/go.mod CHANGED
@@ -30,7 +30,7 @@ require (
30
30
  require (
31
31
  github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
32
32
  github.com/klauspost/cpuid/v2 v2.2.10 // indirect
33
- github.com/microsoft/typescript-go v0.0.0-20260428010401-3499951dbc49 // indirect
33
+ github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157 // indirect
34
34
  github.com/zeebo/xxh3 v1.1.0 // indirect
35
35
  golang.org/x/sync v0.20.0 // indirect
36
36
  golang.org/x/sys v0.42.0 // indirect
package/lib/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import type { ITtscProjectPluginConfig, ITtscPlugin, ITtscPluginFactoryContext } from "ttsc";
2
+ import type { ITtscLintConfig } from "./structures/ITtscLintConfig";
3
+ export * from "./structures/ITtscLintConfig";
4
+ export * from "./structures/ITtscLintRule";
5
+ export * from "./structures/ITtscLintSeverity";
6
+ export type ITtscLintPluginConfig = ITtscProjectPluginConfig & {
7
+ config?: string | ITtscLintConfig;
8
+ };
9
+ export declare function createTtscPlugin(_context: ITtscPluginFactoryContext<ITtscLintPluginConfig>): ITtscPlugin;
10
+ export default createTtscPlugin;
package/lib/index.js ADDED
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.createTtscPlugin = createTtscPlugin;
21
+ const node_path_1 = __importDefault(require("node:path"));
22
+ __exportStar(require("./structures/ITtscLintConfig"), exports);
23
+ __exportStar(require("./structures/ITtscLintRule"), exports);
24
+ __exportStar(require("./structures/ITtscLintSeverity"), exports);
25
+ function createTtscPlugin(_context) {
26
+ return {
27
+ name: "@ttsc/lint",
28
+ native: {
29
+ mode: "ttsc-lint",
30
+ source: {
31
+ dir: node_path_1.default.resolve(__dirname, ".."),
32
+ entry: "./plugin",
33
+ },
34
+ contractVersion: 1,
35
+ capabilities: ["check"],
36
+ },
37
+ };
38
+ }
39
+ exports.default = createTtscPlugin;
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,0DAA6B;AAS7B,+DAA6C;AAC7C,6DAA2C;AAC3C,iEAA+C;AAM/C,0BACE,QAA0D;IAE1D,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE;YACN,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE;gBACN,GAAG,EAAE,mBAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC;gBAClC,KAAK,EAAE,UAAU;aAClB;YACD,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,CAAC,OAAO,CAAC;SACxB;KACF,CAAC;AACJ,CAAC;kBAEc,gBAAgB"}
@@ -0,0 +1,5 @@
1
+ import type { ITtscLintRule } from "./ITtscLintRule";
2
+ import type { ITtscLintSeverity } from "./ITtscLintSeverity";
3
+ export type ITtscLintConfig = {
4
+ [P in ITtscLintRule]?: ITtscLintSeverity;
5
+ };
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ITtscLintConfig.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITtscLintConfig.js","sourceRoot":"","sources":["../../src/structures/ITtscLintConfig.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export type ITtscLintRule = "adjacent-overload-signatures" | "array-type" | "ban-ts-comment" | "ban-tslint-comment" | "consistent-indexed-object-style" | "consistent-type-assertions" | "consistent-type-definitions" | "consistent-type-imports" | "dot-notation" | "eqeqeq" | "for-direction" | "no-alert" | "no-array-constructor" | "no-array-delete" | "no-async-promise-executor" | "no-bitwise" | "no-caller" | "no-case-declarations" | "no-class-assign" | "no-compare-neg-zero" | "no-cond-assign" | "no-confusing-non-null-assertion" | "no-console" | "no-constant-condition" | "no-continue" | "no-control-regex" | "no-debugger" | "no-delete-var" | "no-dupe-args" | "no-dupe-else-if" | "no-dupe-keys" | "no-duplicate-case" | "no-duplicate-enum-values" | "no-dynamic-delete" | "no-empty" | "no-empty-character-class" | "no-empty-function" | "no-empty-interface" | "no-empty-object-type" | "no-empty-pattern" | "no-empty-static-block" | "no-eq-null" | "no-eval" | "no-ex-assign" | "no-explicit-any" | "no-extra-bind" | "no-extra-boolean-cast" | "no-extra-non-null-assertion" | "no-fallthrough" | "no-func-assign" | "no-inferrable-types" | "no-inner-declarations" | "no-irregular-whitespace" | "no-iterator" | "no-labels" | "no-lone-blocks" | "no-lonely-if" | "no-loss-of-precision" | "no-misleading-character-class" | "no-misused-new" | "no-multi-assign" | "no-multi-str" | "no-namespace" | "no-negated-condition" | "no-nested-ternary" | "no-new" | "no-new-func" | "no-new-wrappers" | "no-non-null-asserted-nullish-coalescing" | "no-non-null-asserted-optional-chain" | "no-non-null-assertion" | "no-obj-calls" | "no-object-constructor" | "no-octal" | "no-octal-escape" | "no-plusplus" | "no-promise-executor-return" | "no-proto" | "no-prototype-builtins" | "no-regex-spaces" | "no-require-imports" | "no-return-assign" | "no-script-url" | "no-self-assign" | "no-self-compare" | "no-sequences" | "no-setter-return" | "no-shadow-restricted-names" | "no-sparse-arrays" | "no-template-curly-in-string" | "no-this-alias" | "no-throw-literal" | "no-undef-init" | "no-undefined" | "no-unnecessary-type-constraint" | "no-unneeded-ternary" | "no-unsafe-declaration-merging" | "no-unsafe-finally" | "no-unsafe-function-type" | "no-unsafe-negation" | "no-unused-expressions" | "no-unused-labels" | "no-useless-call" | "no-useless-catch" | "no-useless-computed-key" | "no-useless-concat" | "no-useless-constructor" | "no-useless-rename" | "no-var" | "no-with" | "no-wrapper-object-types" | "object-shorthand" | "operator-assignment" | "prefer-as-const" | "prefer-const" | "prefer-enum-initializers" | "prefer-exponentiation-operator" | "prefer-for-of" | "prefer-function-type" | "prefer-literal-enum-member" | "prefer-namespace-keyword" | "prefer-spread" | "prefer-template" | "radix" | "require-yield" | "triple-slash-reference" | "use-isnan" | "valid-typeof" | "vars-on-top" | "yoda";
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ITtscLintRule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITtscLintRule.js","sourceRoot":"","sources":["../../src/structures/ITtscLintRule.ts"],"names":[],"mappings":""}
@@ -0,0 +1 @@
1
+ export type ITtscLintSeverity = "off" | "warning" | "warn" | "error" | 0 | 1 | 2;
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ITtscLintSeverity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ITtscLintSeverity.js","sourceRoot":"","sources":["../../src/structures/ITtscLintSeverity.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -1,10 +1,14 @@
1
1
  {
2
2
  "name": "@ttsc/lint",
3
- "version": "0.5.0",
3
+ "version": "0.6.0-dev.20250501",
4
4
  "description": "Reference ttsc plugin: ESLint-style lint rules hosted in the same Program/Checker as the type-check pass.",
5
- "main": "src/index.cjs",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
6
7
  "exports": {
7
- ".": "./src/index.cjs",
8
+ ".": {
9
+ "types": "./lib/index.d.ts",
10
+ "default": "./lib/index.js"
11
+ },
8
12
  "./package.json": "./package.json"
9
13
  },
10
14
  "keywords": [
@@ -16,10 +20,18 @@
16
20
  ],
17
21
  "files": [
18
22
  "README.md",
19
- "src/index.cjs",
23
+ "lib",
24
+ "src",
25
+ "tsconfig.json",
20
26
  "go.mod",
21
27
  "plugin"
22
28
  ],
29
+ "devDependencies": {
30
+ "@typescript/native-preview": "7.0.0-dev.20260429.1",
31
+ "@types/node": "^25.3.0",
32
+ "rimraf": "^6.1.2",
33
+ "ttsc": "0.6.0-dev.20250501"
34
+ },
23
35
  "repository": {
24
36
  "type": "git",
25
37
  "url": "https://github.com/samchon/ttsc"
@@ -30,11 +42,8 @@
30
42
  "url": "https://github.com/samchon/ttsc/issues"
31
43
  },
32
44
  "homepage": "https://github.com/samchon/ttsc/tree/master/packages/lint#readme",
33
- "deprecation": {
34
- "preferred": "@typescript-eslint/eslint-plugin",
35
- "rationale": "@ttsc/lint is a curated reference implementation. The strongly preferred outcome is for eslint / @typescript-eslint maintainers to take ownership of the host slot. If they do, this package will be deprecated and re-pointed at theirs."
36
- },
37
45
  "scripts": {
38
- "test": "pnpm --dir ../../tests/lint start"
46
+ "build": "rimraf lib && tsgo -p tsconfig.json",
47
+ "test": "pnpm run build && pnpm --dir ../../tests/lint start"
39
48
  }
40
49
  }
@@ -168,3 +168,59 @@ func stringLiteralText(node *shimast.Node) string {
168
168
  }
169
169
  return ""
170
170
  }
171
+
172
+ // walkDescendants visits node and every child below it, depth-first.
173
+ func walkDescendants(node *shimast.Node, visit func(*shimast.Node)) {
174
+ if node == nil {
175
+ return
176
+ }
177
+ visit(node)
178
+ node.ForEachChild(func(child *shimast.Node) bool {
179
+ walkDescendants(child, visit)
180
+ return false
181
+ })
182
+ }
183
+
184
+ func bindingIdentifierNames(node *shimast.Node) []string {
185
+ if node == nil {
186
+ return nil
187
+ }
188
+ if name := identifierText(node); name != "" {
189
+ return []string{name}
190
+ }
191
+ if node.Kind != shimast.KindObjectBindingPattern && node.Kind != shimast.KindArrayBindingPattern {
192
+ return nil
193
+ }
194
+ var names []string
195
+ walkDescendants(node, func(child *shimast.Node) {
196
+ if child == node {
197
+ return
198
+ }
199
+ if name := identifierText(child); name != "" {
200
+ names = append(names, name)
201
+ }
202
+ })
203
+ return names
204
+ }
205
+
206
+ func isLiteralLike(node *shimast.Node) bool {
207
+ node = stripParens(node)
208
+ if node == nil {
209
+ return false
210
+ }
211
+ if isLiteralExpression(node) {
212
+ return true
213
+ }
214
+ if node.Kind == shimast.KindPrefixUnaryExpression {
215
+ prefix := node.AsPrefixUnaryExpression()
216
+ if prefix == nil {
217
+ return false
218
+ }
219
+ switch prefix.Operator {
220
+ case shimast.KindPlusToken, shimast.KindMinusToken:
221
+ return prefix.Operand != nil &&
222
+ (prefix.Operand.Kind == shimast.KindNumericLiteral || prefix.Operand.Kind == shimast.KindBigIntLiteral)
223
+ }
224
+ }
225
+ return false
226
+ }
package/plugin/compile.go CHANGED
@@ -93,7 +93,7 @@ func RunTransform(args []string) int {
93
93
  }
94
94
  defer prog.close()
95
95
 
96
- rules, err := loadRules(*pluginsJSON)
96
+ rules, err := loadRules(*pluginsJSON, resolvedCwd, *tsconfig)
97
97
  if err != nil {
98
98
  fmt.Fprintln(os.Stderr, err)
99
99
  return 2
@@ -227,7 +227,7 @@ func runProject(opts *subcommandOpts) int {
227
227
  }
228
228
  defer prog.close()
229
229
 
230
- rules, err := loadRules(opts.pluginsJSON)
230
+ rules, err := loadRules(opts.pluginsJSON, opts.cwd, opts.tsconfig)
231
231
  if err != nil {
232
232
  fmt.Fprintln(os.Stderr, err)
233
233
  return 2
@@ -268,7 +268,7 @@ func runProject(opts *subcommandOpts) int {
268
268
  return 0
269
269
  }
270
270
 
271
- func loadRules(pluginsJSON string) (RuleConfig, error) {
271
+ func loadRules(pluginsJSON, cwd, tsconfigPath string) (RuleConfig, error) {
272
272
  entries, err := ParsePlugins(pluginsJSON)
273
273
  if err != nil {
274
274
  return nil, err
@@ -280,7 +280,7 @@ func loadRules(pluginsJSON string) (RuleConfig, error) {
280
280
  if entry == nil {
281
281
  return RuleConfig{}, nil
282
282
  }
283
- return ParseRules(entry.Config["rules"])
283
+ return LoadRuleConfig(entry, cwd, tsconfigPath)
284
284
  }
285
285
 
286
286
  func warnUnknownRules(w io.Writer, unknown []string) {