@thethracian/oxlint-config 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +124 -18
  3. package/dist/codemod-fix/cli.d.ts +3 -0
  4. package/dist/codemod-fix/cli.d.ts.map +1 -0
  5. package/dist/codemod-fix/cli.js +22 -0
  6. package/dist/codemod-fix/cli.js.map +1 -0
  7. package/dist/codemod-fix/index.d.ts +44 -0
  8. package/dist/codemod-fix/index.d.ts.map +1 -0
  9. package/dist/codemod-fix/index.js +110 -0
  10. package/dist/codemod-fix/index.js.map +1 -0
  11. package/dist/codemods/arrow-body-style.d.ts +7 -0
  12. package/dist/codemods/arrow-body-style.d.ts.map +1 -0
  13. package/dist/codemods/arrow-body-style.js +106 -0
  14. package/dist/codemods/arrow-body-style.js.map +1 -0
  15. package/dist/codemods/comment-format.d.ts +24 -0
  16. package/dist/codemods/comment-format.d.ts.map +1 -0
  17. package/dist/codemods/comment-format.js +100 -0
  18. package/dist/codemods/comment-format.js.map +1 -0
  19. package/dist/codemods/explicit-return-types.d.ts +7 -0
  20. package/dist/codemods/explicit-return-types.d.ts.map +1 -0
  21. package/dist/codemods/explicit-return-types.js +350 -0
  22. package/dist/codemods/explicit-return-types.js.map +1 -0
  23. package/dist/codemods/format-file-header.d.ts +7 -0
  24. package/dist/codemods/format-file-header.d.ts.map +1 -0
  25. package/dist/codemods/format-file-header.js +163 -0
  26. package/dist/codemods/format-file-header.js.map +1 -0
  27. package/dist/codemods/format-jsdoc-comments.d.ts +7 -0
  28. package/dist/codemods/format-jsdoc-comments.d.ts.map +1 -0
  29. package/dist/codemods/format-jsdoc-comments.js +129 -0
  30. package/dist/codemods/format-jsdoc-comments.js.map +1 -0
  31. package/dist/codemods/function-declarations.d.ts +7 -0
  32. package/dist/codemods/function-declarations.d.ts.map +1 -0
  33. package/dist/codemods/function-declarations.js +202 -0
  34. package/dist/codemods/function-declarations.js.map +1 -0
  35. package/dist/codemods/inline-export-lists.d.ts +7 -0
  36. package/dist/codemods/inline-export-lists.d.ts.map +1 -0
  37. package/dist/codemods/inline-export-lists.js +168 -0
  38. package/dist/codemods/inline-export-lists.js.map +1 -0
  39. package/dist/codemods/internal-export-docs.d.ts +7 -0
  40. package/dist/codemods/internal-export-docs.d.ts.map +1 -0
  41. package/dist/codemods/internal-export-docs.js +93 -0
  42. package/dist/codemods/internal-export-docs.js.map +1 -0
  43. package/dist/codemods/no-ternary-branch-initializers.d.ts +14 -0
  44. package/dist/codemods/no-ternary-branch-initializers.d.ts.map +1 -0
  45. package/dist/codemods/no-ternary-branch-initializers.js +240 -0
  46. package/dist/codemods/no-ternary-branch-initializers.js.map +1 -0
  47. package/dist/codemods/no-ternary-variable-initializers.d.ts +14 -0
  48. package/dist/codemods/no-ternary-variable-initializers.d.ts.map +1 -0
  49. package/dist/codemods/no-ternary-variable-initializers.js +235 -0
  50. package/dist/codemods/no-ternary-variable-initializers.js.map +1 -0
  51. package/dist/codemods/no-ternary.d.ts +7 -0
  52. package/dist/codemods/no-ternary.d.ts.map +1 -0
  53. package/dist/codemods/no-ternary.js +215 -0
  54. package/dist/codemods/no-ternary.js.map +1 -0
  55. package/dist/codemods/rename-acronyms.d.ts +8 -0
  56. package/dist/codemods/rename-acronyms.d.ts.map +1 -0
  57. package/dist/codemods/rename-acronyms.js +193 -0
  58. package/dist/codemods/rename-acronyms.js.map +1 -0
  59. package/dist/codemods/run.d.ts +2 -0
  60. package/dist/codemods/run.d.ts.map +1 -0
  61. package/dist/codemods/run.js +14 -0
  62. package/dist/codemods/run.js.map +1 -0
  63. package/dist/codemods/sort-imports.d.ts +7 -0
  64. package/dist/codemods/sort-imports.d.ts.map +1 -0
  65. package/dist/codemods/sort-imports.js +235 -0
  66. package/dist/codemods/sort-imports.js.map +1 -0
  67. package/dist/index.d.ts +30 -96
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +156 -94
  70. package/dist/index.js.map +1 -1
  71. package/dist/rules/acronym-case.d.ts +7 -3
  72. package/dist/rules/acronym-case.d.ts.map +1 -1
  73. package/dist/rules/acronym-case.js +129 -118
  74. package/dist/rules/acronym-case.js.map +1 -1
  75. package/dist/rules/acronyms-1.d.ts +3 -0
  76. package/dist/rules/acronyms-1.d.ts.map +1 -0
  77. package/dist/rules/acronyms-1.js +407 -0
  78. package/dist/rules/acronyms-1.js.map +1 -0
  79. package/dist/rules/acronyms-2.d.ts +3 -0
  80. package/dist/rules/acronyms-2.d.ts.map +1 -0
  81. package/dist/rules/acronyms-2.js +407 -0
  82. package/dist/rules/acronyms-2.js.map +1 -0
  83. package/dist/rules/acronyms-3.d.ts +3 -0
  84. package/dist/rules/acronyms-3.d.ts.map +1 -0
  85. package/dist/rules/acronyms-3.js +407 -0
  86. package/dist/rules/acronyms-3.js.map +1 -0
  87. package/dist/rules/acronyms-4.d.ts +3 -0
  88. package/dist/rules/acronyms-4.d.ts.map +1 -0
  89. package/dist/rules/acronyms-4.js +377 -0
  90. package/dist/rules/acronyms-4.js.map +1 -0
  91. package/dist/rules/acronyms.d.ts +1 -8
  92. package/dist/rules/acronyms.d.ts.map +1 -1
  93. package/dist/rules/acronyms.js +14 -1578
  94. package/dist/rules/acronyms.js.map +1 -1
  95. package/dist/rules/boolean-prefix.d.ts +11 -2
  96. package/dist/rules/boolean-prefix.d.ts.map +1 -1
  97. package/dist/rules/boolean-prefix.js +95 -59
  98. package/dist/rules/boolean-prefix.js.map +1 -1
  99. package/dist/rules/camel-case-identifiers.d.ts +3 -4
  100. package/dist/rules/camel-case-identifiers.d.ts.map +1 -1
  101. package/dist/rules/camel-case-identifiers.js +59 -40
  102. package/dist/rules/camel-case-identifiers.js.map +1 -1
  103. package/dist/rules/char-class.d.ts +26 -13
  104. package/dist/rules/char-class.d.ts.map +1 -1
  105. package/dist/rules/char-class.js +56 -24
  106. package/dist/rules/char-class.js.map +1 -1
  107. package/dist/rules/diagnostic-guidance.d.ts +91 -0
  108. package/dist/rules/diagnostic-guidance.d.ts.map +1 -0
  109. package/dist/rules/diagnostic-guidance.js +243 -0
  110. package/dist/rules/diagnostic-guidance.js.map +1 -0
  111. package/dist/rules/effect-default-ast.d.ts +89 -0
  112. package/dist/rules/effect-default-ast.d.ts.map +1 -0
  113. package/dist/rules/effect-default-ast.js +208 -0
  114. package/dist/rules/effect-default-ast.js.map +1 -0
  115. package/dist/rules/effect-default-compat-rules.d.ts +76 -0
  116. package/dist/rules/effect-default-compat-rules.d.ts.map +1 -0
  117. package/dist/rules/effect-default-compat-rules.js +270 -0
  118. package/dist/rules/effect-default-compat-rules.js.map +1 -0
  119. package/dist/rules/effect-default-env-rules.d.ts +60 -0
  120. package/dist/rules/effect-default-env-rules.d.ts.map +1 -0
  121. package/dist/rules/effect-default-env-rules.js +259 -0
  122. package/dist/rules/effect-default-env-rules.js.map +1 -0
  123. package/dist/rules/effect-default-fiber-helpers.d.ts +13 -0
  124. package/dist/rules/effect-default-fiber-helpers.d.ts.map +1 -0
  125. package/dist/rules/effect-default-fiber-helpers.js +76 -0
  126. package/dist/rules/effect-default-fiber-helpers.js.map +1 -0
  127. package/dist/rules/effect-default-floating-helpers.d.ts +7 -0
  128. package/dist/rules/effect-default-floating-helpers.d.ts.map +1 -0
  129. package/dist/rules/effect-default-floating-helpers.js +113 -0
  130. package/dist/rules/effect-default-floating-helpers.js.map +1 -0
  131. package/dist/rules/effect-default-helpers.d.ts +8 -32
  132. package/dist/rules/effect-default-helpers.d.ts.map +1 -1
  133. package/dist/rules/effect-default-helpers.js +11 -535
  134. package/dist/rules/effect-default-helpers.js.map +1 -1
  135. package/dist/rules/effect-default-resource-helpers.d.ts +18 -4
  136. package/dist/rules/effect-default-resource-helpers.d.ts.map +1 -1
  137. package/dist/rules/effect-default-resource-helpers.js +30 -13
  138. package/dist/rules/effect-default-resource-helpers.js.map +1 -1
  139. package/dist/rules/effect-default-safety-helpers.d.ts +43 -0
  140. package/dist/rules/effect-default-safety-helpers.d.ts.map +1 -0
  141. package/dist/rules/effect-default-safety-helpers.js +126 -0
  142. package/dist/rules/effect-default-safety-helpers.js.map +1 -0
  143. package/dist/rules/effect-default-scan-helpers.d.ts +43 -0
  144. package/dist/rules/effect-default-scan-helpers.d.ts.map +1 -0
  145. package/dist/rules/effect-default-scan-helpers.js +141 -0
  146. package/dist/rules/effect-default-scan-helpers.js.map +1 -0
  147. package/dist/rules/effect-default-schema-helpers.d.ts +37 -0
  148. package/dist/rules/effect-default-schema-helpers.d.ts.map +1 -0
  149. package/dist/rules/effect-default-schema-helpers.js +104 -0
  150. package/dist/rules/effect-default-schema-helpers.js.map +1 -0
  151. package/dist/rules/effect-default-test-helpers.d.ts +18 -4
  152. package/dist/rules/effect-default-test-helpers.d.ts.map +1 -1
  153. package/dist/rules/effect-default-test-helpers.js +41 -20
  154. package/dist/rules/effect-default-test-helpers.js.map +1 -1
  155. package/dist/rules/effect-default-workflow-helpers.d.ts +91 -0
  156. package/dist/rules/effect-default-workflow-helpers.d.ts.map +1 -0
  157. package/dist/rules/effect-default-workflow-helpers.js +247 -0
  158. package/dist/rules/effect-default-workflow-helpers.js.map +1 -0
  159. package/dist/rules/effect-default.d.ts +1 -1
  160. package/dist/rules/effect-default.d.ts.map +1 -1
  161. package/dist/rules/effect-default.js +105 -680
  162. package/dist/rules/effect-default.js.map +1 -1
  163. package/dist/rules/effect-exported-declarations.d.ts +19 -0
  164. package/dist/rules/effect-exported-declarations.d.ts.map +1 -0
  165. package/dist/rules/effect-exported-declarations.js +237 -0
  166. package/dist/rules/effect-exported-declarations.js.map +1 -0
  167. package/dist/rules/effect-path-options.d.ts +49 -11
  168. package/dist/rules/effect-path-options.d.ts.map +1 -1
  169. package/dist/rules/effect-path-options.js +85 -52
  170. package/dist/rules/effect-path-options.js.map +1 -1
  171. package/dist/rules/effect-rule-aliases.d.ts +55 -0
  172. package/dist/rules/effect-rule-aliases.d.ts.map +1 -0
  173. package/dist/rules/effect-rule-aliases.js +278 -0
  174. package/dist/rules/effect-rule-aliases.js.map +1 -0
  175. package/dist/rules/effect-rule-core.d.ts +38 -24
  176. package/dist/rules/effect-rule-core.d.ts.map +1 -1
  177. package/dist/rules/effect-rule-core.js +157 -344
  178. package/dist/rules/effect-rule-core.js.map +1 -1
  179. package/dist/rules/effect-rule-names.d.ts +12 -3
  180. package/dist/rules/effect-rule-names.d.ts.map +1 -1
  181. package/dist/rules/effect-rule-names.js +15 -3
  182. package/dist/rules/effect-rule-names.js.map +1 -1
  183. package/dist/rules/effect-source-comments.d.ts +7 -0
  184. package/dist/rules/effect-source-comments.d.ts.map +1 -0
  185. package/dist/rules/effect-source-comments.js +227 -0
  186. package/dist/rules/effect-source-comments.js.map +1 -0
  187. package/dist/rules/effect-source-helpers.d.ts +4 -9
  188. package/dist/rules/effect-source-helpers.d.ts.map +1 -1
  189. package/dist/rules/effect-source-helpers.js +7 -358
  190. package/dist/rules/effect-source-helpers.js.map +1 -1
  191. package/dist/rules/effect-source-navigation.d.ts +25 -0
  192. package/dist/rules/effect-source-navigation.d.ts.map +1 -0
  193. package/dist/rules/effect-source-navigation.js +244 -0
  194. package/dist/rules/effect-source-navigation.js.map +1 -0
  195. package/dist/rules/effect-source-scan.d.ts +30 -7
  196. package/dist/rules/effect-source-scan.d.ts.map +1 -1
  197. package/dist/rules/effect-source-scan.js +372 -300
  198. package/dist/rules/effect-source-scan.js.map +1 -1
  199. package/dist/rules/effect-strict-ast-specs.d.ts +8 -0
  200. package/dist/rules/effect-strict-ast-specs.d.ts.map +1 -0
  201. package/dist/rules/effect-strict-ast-specs.js +166 -0
  202. package/dist/rules/effect-strict-ast-specs.js.map +1 -0
  203. package/dist/rules/effect-strict-boundary-helpers.d.ts +25 -0
  204. package/dist/rules/effect-strict-boundary-helpers.d.ts.map +1 -0
  205. package/dist/rules/effect-strict-boundary-helpers.js +127 -0
  206. package/dist/rules/effect-strict-boundary-helpers.js.map +1 -0
  207. package/dist/rules/effect-strict-core-specs.d.ts +8 -0
  208. package/dist/rules/effect-strict-core-specs.d.ts.map +1 -0
  209. package/dist/rules/effect-strict-core-specs.js +334 -0
  210. package/dist/rules/effect-strict-core-specs.js.map +1 -0
  211. package/dist/rules/effect-strict-external-helpers.d.ts +25 -0
  212. package/dist/rules/effect-strict-external-helpers.d.ts.map +1 -0
  213. package/dist/rules/effect-strict-external-helpers.js +87 -0
  214. package/dist/rules/effect-strict-external-helpers.js.map +1 -0
  215. package/dist/rules/effect-strict-helpers.d.ts +75 -33
  216. package/dist/rules/effect-strict-helpers.d.ts.map +1 -1
  217. package/dist/rules/effect-strict-helpers.js +93 -384
  218. package/dist/rules/effect-strict-helpers.js.map +1 -1
  219. package/dist/rules/effect-strict-internals.d.ts +198 -0
  220. package/dist/rules/effect-strict-internals.d.ts.map +1 -0
  221. package/dist/rules/effect-strict-internals.js +477 -0
  222. package/dist/rules/effect-strict-internals.js.map +1 -0
  223. package/dist/rules/effect-strict-segment-helpers.d.ts +79 -0
  224. package/dist/rules/effect-strict-segment-helpers.d.ts.map +1 -0
  225. package/dist/rules/effect-strict-segment-helpers.js +308 -0
  226. package/dist/rules/effect-strict-segment-helpers.js.map +1 -0
  227. package/dist/rules/effect-strict.d.ts +1 -1
  228. package/dist/rules/effect-strict.d.ts.map +1 -1
  229. package/dist/rules/effect-strict.js +10 -725
  230. package/dist/rules/effect-strict.js.map +1 -1
  231. package/dist/rules/max-import-depth.d.ts +2 -2
  232. package/dist/rules/max-import-depth.d.ts.map +1 -1
  233. package/dist/rules/max-import-depth.js +52 -17
  234. package/dist/rules/max-import-depth.js.map +1 -1
  235. package/dist/rules/max-line-length.d.ts +9 -2
  236. package/dist/rules/max-line-length.d.ts.map +1 -1
  237. package/dist/rules/max-line-length.js +52 -15
  238. package/dist/rules/max-line-length.js.map +1 -1
  239. package/dist/rules/no-commented-out-code.d.ts +3 -7
  240. package/dist/rules/no-commented-out-code.d.ts.map +1 -1
  241. package/dist/rules/no-commented-out-code.js +157 -102
  242. package/dist/rules/no-commented-out-code.js.map +1 -1
  243. package/dist/rules/pascal-case-types.d.ts +1 -1
  244. package/dist/rules/pascal-case-types.d.ts.map +1 -1
  245. package/dist/rules/pascal-case-types.js +65 -46
  246. package/dist/rules/pascal-case-types.js.map +1 -1
  247. package/dist/rules/plugin-commented-out-code-rule.d.ts +32 -0
  248. package/dist/rules/plugin-commented-out-code-rule.d.ts.map +1 -0
  249. package/dist/rules/plugin-commented-out-code-rule.js +135 -0
  250. package/dist/rules/plugin-commented-out-code-rule.js.map +1 -0
  251. package/dist/rules/plugin.d.ts +5 -0
  252. package/dist/rules/plugin.d.ts.map +1 -1
  253. package/dist/rules/plugin.js +168 -154
  254. package/dist/rules/plugin.js.map +1 -1
  255. package/dist/rules/private-underscore.d.ts +1 -1
  256. package/dist/rules/private-underscore.d.ts.map +1 -1
  257. package/dist/rules/private-underscore.js +11 -4
  258. package/dist/rules/private-underscore.js.map +1 -1
  259. package/dist/rules/require-file-doc.d.ts +5 -6
  260. package/dist/rules/require-file-doc.d.ts.map +1 -1
  261. package/dist/rules/require-file-doc.js +127 -78
  262. package/dist/rules/require-file-doc.js.map +1 -1
  263. package/dist/rules/require-function-doc-ignored-text.d.ts +7 -0
  264. package/dist/rules/require-function-doc-ignored-text.d.ts.map +1 -0
  265. package/dist/rules/require-function-doc-ignored-text.js +67 -0
  266. package/dist/rules/require-function-doc-ignored-text.js.map +1 -0
  267. package/dist/rules/require-function-doc-local-exports.d.ts +7 -0
  268. package/dist/rules/require-function-doc-local-exports.d.ts.map +1 -0
  269. package/dist/rules/require-function-doc-local-exports.js +114 -0
  270. package/dist/rules/require-function-doc-local-exports.js.map +1 -0
  271. package/dist/rules/require-function-doc.d.ts +3 -18
  272. package/dist/rules/require-function-doc.d.ts.map +1 -1
  273. package/dist/rules/require-function-doc.js +396 -221
  274. package/dist/rules/require-function-doc.js.map +1 -1
  275. package/dist/rules/source-cache.d.ts +13 -5
  276. package/dist/rules/source-cache.d.ts.map +1 -1
  277. package/dist/rules/source-cache.js +35 -22
  278. package/dist/rules/source-cache.js.map +1 -1
  279. package/package.json +10 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.1 - 2026-05-25
4
+
5
+ ### Changes
6
+
7
+ - chore(ts): consume published oxlint config (#8) (5a1b72a)
8
+
9
+ ## 0.3.0 - 2026-05-25
10
+
11
+ ### Features
12
+
13
+ - feat(ci): keep performance gate local (#7) (635fdfe)
14
+ - feat(ts): rewrite codemod fixers with jscodeshift (#6) (989d924)
15
+
3
16
  ## 0.2.1 - 2026-05-24
4
17
 
5
18
  ### Changes
package/README.md CHANGED
@@ -1,25 +1,96 @@
1
1
  # @thethracian/oxlint-config
2
2
 
3
- Importable Oxlint config for TypeScript projects.
3
+ <p align="center">
4
+ <a href="https://www.npmjs.com/package/@thethracian/oxlint-config"><img alt="npm version" src="https://img.shields.io/npm/v/@thethracian/oxlint-config?style=flat-square"></a>
5
+ <a href="https://www.npmjs.com/package/@thethracian/oxlint-config"><img alt="npm downloads" src="https://img.shields.io/npm/dw/@thethracian/oxlint-config?style=flat-square"></a>
6
+ <a href="https://socket.dev/npm/package/%40thethracian/oxlint-config"><img alt="Socket package analysis" src="https://socket.dev/api/badge/npm/package/@thethracian/oxlint-config"></a>
7
+ <a href="https://github.com/stefan-vatov/code-quality/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/stefan-vatov/code-quality/ci.yml?branch=main&style=flat-square"></a>
8
+ <a href="https://github.com/stefan-vatov/code-quality/blob/main/LICENSE"><img alt="MIT license" src="https://img.shields.io/badge/license-MIT-blue?style=flat-square"></a>
9
+ </p>
4
10
 
5
- The config errors on lines over 150 characters, files over 500 lines, functions over 75 lines, nesting deeper than 3 levels, callback nesting deeper than 4 levels (max-nested-callbacks), more than 5 parameters, cyclomatic complexity over 10, requires strict equality (eqeqeq), denies eval and dynamic code execution (no-eval, no-implied-eval when type-aware), denies debug artifacts (no-console, no-debugger), bans silent catch blocks (no-empty), bans commented-out code (custom thethracian/no-commented-out-code rule), bans inline comments and warning comments (no-inline-comments, no-warning-comments), bans `any` and untyped escape hatches (no-explicit-any, no-unsafe-call, no-unsafe-member-access, plus no-unsafe-assignment/return/argument when type-aware), denies unhandled promises (no-floating-promises, no-misused-promises when type-aware), and enforces immutability with prefer-const and no-param-reassign (including property mutations).
11
+ The Thracian Oxlint config is an experimental, painfully strict, very opinionated TypeScript lint profile for teams that want AI-generated code reviewed like production code.
6
12
 
7
- The package uses Oxlint's native complexity rule and ships the Oxlint type-aware runner needed by
8
- the `typeAware` profile.
13
+ ```text
14
+ oxlint.config.mjs
15
+ import theThracian from '@thethracian/oxlint-config';
16
+
17
+ export default theThracian({ typeAware: true });
18
+
19
+ Result: native Oxlint rules + The Thracian custom rules + optional Effect policy checks.
20
+ ```
21
+
22
+ ## Why Use It
23
+
24
+ - Strict by default: every rule is an error, not a suggestion.
25
+ - Agent-ready TypeScript: catches debug artifacts, unsafe escape hatches, silent catches, mutation, deep nesting, and oversized code.
26
+ - Effect-aware out of the box: 81 always-on Effect rules target lazy values, generator style, Promise boundaries, typed errors, Schema boundaries, resources, tests, and common hallucinated APIs.
27
+ - Strict Effect mode when you want it: opt in to 60 additional project-boundary rules for entrypoints, adapters, config layers, domain modules, service wiring, external calls, and test ownership.
28
+ - Importable config: consumers import one package instead of copying linter files around a codebase.
29
+
30
+ ## Install
9
31
 
10
32
  ```sh
11
33
  pnpm add -D @thethracian/oxlint-config oxlint@^1.63.0
12
34
  ```
13
35
 
14
- ```ts
36
+ Create `oxlint.config.mjs`:
37
+
38
+ ```js
15
39
  import theThracian from '@thethracian/oxlint-config';
16
40
 
17
41
  export default theThracian();
18
42
  ```
19
43
 
20
- Enable type-aware Oxlint execution and the matching type-aware rules from the shared config:
44
+ Run Oxlint:
45
+
46
+ ```sh
47
+ pnpm oxlint .
48
+ ```
49
+
50
+ Add package scripts for normal linting, type-aware linting, and the combined fixer:
51
+
52
+ ```json
53
+ {
54
+ "scripts": {
55
+ "lint": "oxlint src",
56
+ "lint:fix": "thx-codemod-fix src && oxlint src --fix && thx-codemod-fix src",
57
+ "lint:type-aware": "oxlint src --type-aware --type-check",
58
+ "lint:fix:type-aware": "thx-codemod-fix src && oxlint src --type-aware --type-check --fix && thx-codemod-fix src"
59
+ }
60
+ }
61
+ ```
62
+
63
+ `thx-codemod-fix` is intentionally separate from `oxlint --fix` because Oxlint owns native rule fixes and the package CLI owns larger AST codemods. Running it before and after Oxlint is safe because the codemods are idempotent. The CLI defaults to `src`, but you can pass any files or directories your project wants fixed.
64
+
65
+ For staged files, wire the same package tools through `lint-staged`:
66
+
67
+ ```json
68
+ {
69
+ "lint-staged": {
70
+ "*.{ts,tsx,mts,cts}": [
71
+ "thx-codemod-fix",
72
+ "oxlint --type-aware --type-check --fix --no-error-on-unmatched-pattern",
73
+ "thx-codemod-fix"
74
+ ]
75
+ }
76
+ }
77
+ ```
78
+
79
+ Programmatic consumers can use the same codemod runner:
21
80
 
22
81
  ```ts
82
+ import { codemodFix } from '@thethracian/oxlint-config/codemod-fix';
83
+
84
+ codemodFix({
85
+ paths: ['src', 'scripts'],
86
+ });
87
+ ```
88
+
89
+ ## Type-Aware Mode
90
+
91
+ Type-aware mode enables Oxlint's semantic TypeScript checks and the matching strict rules from this config.
92
+
93
+ ```js
23
94
  import theThracian from '@thethracian/oxlint-config';
24
95
 
25
96
  export default theThracian({
@@ -27,14 +98,26 @@ export default theThracian({
27
98
  });
28
99
  ```
29
100
 
30
- The 81-rule always-on default Effect bucket is enabled by default for this config. These rules
31
- target lazy Effect values, generator style, Promise boundaries, typed errors, resource safety,
32
- Schema boundaries, test determinism, stale APIs, platform escape hatches, unsafe Effect type
33
- assertions, service self-type drift, and common AI-generated Effect hallucinations.
101
+ Use this when you want checks such as unsafe calls, unsafe member access, floating promises, misused promises, and exhaustive switch handling. It is slower than syntax-only linting because Oxlint has to load TypeScript project information.
34
102
 
35
- Non-Effect projects can disable that bucket explicitly:
103
+ ## Effect Defaults
36
104
 
37
- ```ts
105
+ Effect rules are enabled by default. They are designed for codebases where agents may produce plausible-looking but semantically weak Effect code.
106
+
107
+ The default bucket checks for patterns such as:
108
+
109
+ - floating `Effect` values that are never run, yielded, returned, or composed
110
+ - missing `yield*` inside `Effect.gen`
111
+ - nested `flatMap` code that should be `Effect.gen`
112
+ - string errors and untagged error channels
113
+ - unsafe Promise, throw, runtime, and sync boundaries
114
+ - Schema decode misuse at external data boundaries
115
+ - resource, fiber, stream, concurrency, and test determinism mistakes
116
+ - deprecated or invented Effect APIs
117
+
118
+ Disable the Effect bucket for non-Effect projects:
119
+
120
+ ```js
38
121
  import theThracian from '@thethracian/oxlint-config';
39
122
 
40
123
  export default theThracian({
@@ -42,10 +125,11 @@ export default theThracian({
42
125
  });
43
126
  ```
44
127
 
45
- Effect projects that want strict project-boundary enforcement can opt in to the 60-rule strict
46
- bucket:
128
+ ## Strict Effect Mode
47
129
 
48
- ```ts
130
+ Strict mode adds project-boundary checks. It is intentionally opinionated and is best for Effect services with clear layers.
131
+
132
+ ```js
49
133
  import theThracian from '@thethracian/oxlint-config';
50
134
 
51
135
  export default theThracian({
@@ -55,10 +139,9 @@ export default theThracian({
55
139
  });
56
140
  ```
57
141
 
58
- Strict mode uses conventional project globs for entrypoints, composition roots, config layers,
59
- domain modules, adapters, and test types. Override them when a project uses a different layout:
142
+ Override the default project layout when your repository uses different paths:
60
143
 
61
- ```ts
144
+ ```js
62
145
  import theThracian from '@thethracian/oxlint-config';
63
146
 
64
147
  export default theThracian({
@@ -75,3 +158,26 @@ export default theThracian({
75
158
  },
76
159
  });
77
160
  ```
161
+
162
+ ## What It Enforces
163
+
164
+ | Area | Policy |
165
+ | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
166
+ | Size and shape | 150-character lines, 500-line files, 75-line functions, max nesting depth 3, max 5 parameters, cyclomatic complexity 10 |
167
+ | TypeScript safety | no `any` escape hatches, no unsafe calls/member access, explicit function return types, strict equality |
168
+ | Async safety | no floating promises in type-aware mode, no misused promises, no unhandled Effect values |
169
+ | Debug and dynamic code | no `console`, `debugger`, `eval`, `new Function`, script URLs, warning comments, or commented-out code |
170
+ | Immutability | `prefer-const` and no parameter reassignment, including property mutation |
171
+ | Naming | PascalCase types, camelCase identifiers, boolean prefixes, private underscores, and consistent acronym casing |
172
+ | Effect | generator style, typed errors, Schema validation, resource safety, bounded concurrency, test determinism, and project boundaries |
173
+
174
+ ## Registry Links
175
+
176
+ - npm: <https://www.npmjs.com/package/@thethracian/oxlint-config>
177
+ - Socket package analysis: <https://socket.dev/npm/package/%40thethracian/oxlint-config>
178
+ - Source: <https://github.com/stefan-vatov/code-quality/tree/main/ts>
179
+ - Issues: <https://github.com/stefan-vatov/code-quality/issues>
180
+
181
+ ## License
182
+
183
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/codemod-fix/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ /* -------------------------------------------------------------------------- */
3
+ /* CLI entry point for running The Thracian codemod fixes. */
4
+ /* -------------------------------------------------------------------------- */
5
+ import { codemodFix } from './index.js';
6
+ const dryRunFlag = '--dry-run';
7
+ const rawArgs = process.argv.slice(2);
8
+ const dryRun = rawArgs.includes(dryRunFlag);
9
+ const paths = rawArgs.filter((arg) => arg !== dryRunFlag);
10
+ const result = codemodFix({ dryRun, paths });
11
+ const mode = (() => {
12
+ if (dryRun) {
13
+ return 'Would apply';
14
+ }
15
+ return 'Applied';
16
+ })();
17
+ process.stdout.write(`${mode} The Thracian codemod fixes to ${result.changedFiles.length} file(s); ` +
18
+ `scanned ${result.scannedFiles} file(s).\n`);
19
+ if (dryRun && result.changedFiles.length > 0) {
20
+ process.exitCode = 1;
21
+ }
22
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/codemod-fix/cli.ts"],"names":[],"mappings":";AACA,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAErC,MAAM,UAAU,GAAG,WAAW,CAAC;AAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtC,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAW,EAAE,CAAC,GAAG,KAAK,UAAU,CAAC,CAAC;AACnE,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;AAC7C,MAAM,IAAI,GAAG,CAAC,GAAW,EAAE;IACzB,IAAI,MAAM,EAAE,CAAC;QACX,OAAO,aAAa,CAAC;IACvB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC,EAAE,CAAC;AAEL,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,GAAG,IAAI,kCAAkC,MAAM,CAAC,YAAY,CAAC,MAAM,YAAY;IAC7E,WAAW,MAAM,CAAC,YAAY,aAAa,CAC9C,CAAC;AAEF,IAAI,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;IAC7C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Options for running The Thracian codemod fixer.
3
+ *
4
+ * @public
5
+ */
6
+ export interface CodemodFixOptions {
7
+ cwd?: string;
8
+ dryRun?: boolean;
9
+ paths?: readonly string[];
10
+ }
11
+ /**
12
+ * Summary returned after scanning and optionally rewriting source files.
13
+ *
14
+ * @public
15
+ */
16
+ export interface CodemodFixResult {
17
+ changedFiles: string[];
18
+ scannedFiles: number;
19
+ }
20
+ /**
21
+ * Lists TypeScript source files under a root directory.
22
+ *
23
+ * @public
24
+ */
25
+ export declare const sourceFilesUnder: (root: string) => string[];
26
+ /**
27
+ * Applies all safe codemod fixes to a single source string.
28
+ *
29
+ * @public
30
+ */
31
+ export declare const applyCodemodFixToSource: (source: string) => string;
32
+ /**
33
+ * Applies all safe codemod fixes to one file.
34
+ *
35
+ * @public
36
+ */
37
+ export declare const applyCodemodFixToFile: (path: string, dryRun: boolean) => boolean;
38
+ /**
39
+ * Runs The Thracian codemod fixer across configured paths.
40
+ *
41
+ * @public
42
+ */
43
+ export declare const codemodFix: (options?: CodemodFixOptions) => CodemodFixResult;
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/codemod-fix/index.ts"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAKD;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAAM,EAoBrD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAAI,QAAQ,MAAM,KAAG,MAatD,CAAC;AAEJ;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,EAAE,QAAQ,OAAO,KAAG,OAYrE,CAAC;AAUF;;;;GAIG;AACH,eAAO,MAAM,UAAU,GAAI,UAAS,iBAAsB,KAAG,gBAiB5D,CAAC"}
@@ -0,0 +1,110 @@
1
+ /* -------------------------------------------------------------------------- */
2
+ /* Public API for running The Thracian codemod fixes from package scripts or */
3
+ /* Tools. */
4
+ /* -------------------------------------------------------------------------- */
5
+ import { readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
6
+ import { addInternalExportDocs } from '../codemods/internal-export-docs.js';
7
+ import { addVoidReturnTypes } from '../codemods/explicit-return-types.js';
8
+ import { formatFileHeaderComment } from '../codemods/format-file-header.js';
9
+ import { formatJSDocComments } from '../codemods/format-jsdoc-comments.js';
10
+ import { inlineLocalExportLists } from '../codemods/inline-export-lists.js';
11
+ import { preferConciseArrowBodies } from '../codemods/arrow-body-style.js';
12
+ import { preferExplicitBranches } from '../codemods/no-ternary.js';
13
+ import { preferFunctionExpressions } from '../codemods/function-declarations.js';
14
+ import { renameMisCasedAcronyms } from '../codemods/rename-acronyms.js';
15
+ import { resolve } from 'node:path';
16
+ import { sortImportDeclarations } from '../codemods/sort-imports.js';
17
+ const defaultPaths = ['src'];
18
+ const sourceExtensions = new Set(['.ts', '.tsx', '.mts', '.cts']);
19
+ const ignoredDirectories = new Set(['bench', 'dist', 'fixtures', 'node_modules', 'test']);
20
+ const hasSourceExtension = (path) => [...sourceExtensions].some((extension) => path.endsWith(extension));
21
+ /**
22
+ * Lists TypeScript source files under a root directory.
23
+ *
24
+ * @public
25
+ */
26
+ export const sourceFilesUnder = (root) => {
27
+ const files = [];
28
+ const visit = (directory) => {
29
+ for (const entry of readdirSync(directory)) {
30
+ const path = resolve(directory, entry);
31
+ const stats = statSync(path);
32
+ if (stats.isDirectory()) {
33
+ if (!ignoredDirectories.has(entry)) {
34
+ visit(path);
35
+ }
36
+ }
37
+ else if (stats.isFile() && hasSourceExtension(path)) {
38
+ files.push(path);
39
+ }
40
+ }
41
+ };
42
+ visit(root);
43
+ return files;
44
+ };
45
+ /**
46
+ * Applies all safe codemod fixes to a single source string.
47
+ *
48
+ * @public
49
+ */
50
+ export const applyCodemodFixToSource = (source) => formatJSDocComments(addInternalExportDocs(inlineLocalExportLists(addVoidReturnTypes(preferConciseArrowBodies(preferExplicitBranches(preferFunctionExpressions(sortImportDeclarations(renameMisCasedAcronyms(source)))))))));
51
+ /**
52
+ * Applies all safe codemod fixes to one file.
53
+ *
54
+ * @public
55
+ */
56
+ export const applyCodemodFixToFile = (path, dryRun) => {
57
+ const before = readFileSync(path, 'utf8');
58
+ const after = formatFileHeaderComment(applyCodemodFixToSource(before));
59
+ if (after === before) {
60
+ return false;
61
+ }
62
+ if (!dryRun) {
63
+ writeFileSync(path, after);
64
+ }
65
+ return true;
66
+ };
67
+ const candidateFiles = (path) => {
68
+ const stats = statSync(path);
69
+ if (stats.isDirectory()) {
70
+ return sourceFilesUnder(path);
71
+ }
72
+ return [path];
73
+ };
74
+ /**
75
+ * Runs The Thracian codemod fixer across configured paths.
76
+ *
77
+ * @public
78
+ */
79
+ export const codemodFix = (options = {}) => {
80
+ const cwd = options.cwd ?? process.cwd();
81
+ const paths = (() => {
82
+ if (options.paths && options.paths.length > 0) {
83
+ return options.paths;
84
+ }
85
+ return defaultPaths;
86
+ })();
87
+ const dryRun = options.dryRun ?? false;
88
+ const changedFiles = [];
89
+ let scannedFiles = 0;
90
+ for (const path of paths) {
91
+ scannedFiles += scanPath(cwd, path, dryRun, changedFiles);
92
+ }
93
+ return { changedFiles, scannedFiles };
94
+ };
95
+ const collectChangedFile = (changedFiles, file, dryRun) => {
96
+ if (applyCodemodFixToFile(file, dryRun)) {
97
+ changedFiles.push(file);
98
+ }
99
+ };
100
+ const scanPath = (cwd, path, dryRun, changedFiles) => {
101
+ let scannedFiles = 0;
102
+ for (const file of candidateFiles(resolve(cwd, path))) {
103
+ if (hasSourceExtension(file)) {
104
+ scannedFiles += 1;
105
+ collectChangedFile(changedFiles, file, dryRun);
106
+ }
107
+ }
108
+ return scannedFiles;
109
+ };
110
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/codemod-fix/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAChF,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAElE,MAAM,YAAY,GAAG,CAAC,KAAK,CAAU,CAAC;AACtC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAClE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC,CAAC;AAuB1F,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAW,EAAE,CACnD,CAAC,GAAG,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;AAEtE;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAY,EAAE;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,MAAM,KAAK,GAAG,CAAC,SAAiB,EAAQ,EAAE;QACxC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;YAE7B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;oBACnC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACd,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IAEF,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,MAAc,EAAU,EAAE,CAChE,mBAAmB,CACjB,qBAAqB,CACnB,sBAAsB,CACpB,kBAAkB,CAChB,wBAAwB,CACtB,sBAAsB,CACpB,yBAAyB,CAAC,sBAAsB,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC,CAClF,CACF,CACF,CACF,CACF,CACF,CAAC;AAEJ;;;;GAIG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAE,MAAe,EAAW,EAAE;IAC9E,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,uBAAuB,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvE,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,aAAa,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,IAAY,EAAY,EAAE;IAChD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAA6B,EAAE,EAAoB,EAAE;IAC9E,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,CAAC,GAAsB,EAAE;QACrC,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,OAAO,OAAO,CAAC,KAAK,CAAC;QACvB,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC,CAAC,EAAE,CAAC;IACL,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,KAAK,CAAC;IACvC,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,YAAY,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AACxC,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,YAAsB,EAAE,IAAY,EAAE,MAAe,EAAQ,EAAE;IACzF,IAAI,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC;QACxC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,MAAe,EAAE,YAAsB,EAAU,EAAE;IAC9F,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;QACtD,IAAI,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,YAAY,IAAI,CAAC,CAAC;YAClB,kBAAkB,CAAC,YAAY,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Internal helper exported for package-local composition.
3
+ *
4
+ * @internal
5
+ */
6
+ export declare const preferConciseArrowBodies: (source: string) => string;
7
+ //# sourceMappingURL=arrow-body-style.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrow-body-style.d.ts","sourceRoot":"","sources":["../../src/codemods/arrow-body-style.ts"],"names":[],"mappings":"AAmJA;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,QAAQ,MAAM,KAAG,MAazD,CAAC"}
@@ -0,0 +1,106 @@
1
+ import jscodeshift from 'jscodeshift';
2
+ const MAX_LINE_LENGTH = 150;
3
+ const NOT_FOUND_INDEX = -1;
4
+ const codemodAPI = jscodeshift.withParser('ts');
5
+ const isObjectRecord = (value) => typeof value === 'object' && value !== null;
6
+ const applyReplacements = (source, replacements) => [...replacements]
7
+ .sort((left, right) => right.start - left.start)
8
+ .reduce((current, replacement) => current.slice(0, replacement.start) + replacement.text + current.slice(replacement.end), source);
9
+ const nodeStart = (node) => {
10
+ if (isObjectRecord(node)) {
11
+ const { start } = node;
12
+ if (typeof start === 'number') {
13
+ return start;
14
+ }
15
+ }
16
+ throw new Error('jscodeshift node is missing a start offset');
17
+ };
18
+ const nodeEnd = (node) => {
19
+ if (isObjectRecord(node)) {
20
+ const { end } = node;
21
+ if (typeof end === 'number') {
22
+ return end;
23
+ }
24
+ }
25
+ throw new Error('jscodeshift node is missing an end offset');
26
+ };
27
+ const sourceForNode = (source, node) => source.slice(nodeStart(node), nodeEnd(node));
28
+ const hasAttachedComments = (node) => Boolean(node.comments?.length ||
29
+ (isObjectRecord(node) &&
30
+ Array.isArray(node.leadingComments) &&
31
+ node.leadingComments.length > 0) ||
32
+ (isObjectRecord(node) &&
33
+ Array.isArray(node.trailingComments) &&
34
+ node.trailingComments.length > 0));
35
+ const expressionNeedsParentheses = (expression) => expression.type === 'ObjectExpression';
36
+ const lineEndAfter = (source, end) => {
37
+ const nextLineBreak = source.indexOf('\n', end);
38
+ if (nextLineBreak === NOT_FOUND_INDEX) {
39
+ return source.length;
40
+ }
41
+ return nextLineBreak;
42
+ };
43
+ const wouldExceedLineLimit = (source, start, end, replacementText) => {
44
+ if (replacementText.includes('\n')) {
45
+ return false;
46
+ }
47
+ const lineStart = source.lastIndexOf('\n', start) + 1;
48
+ const lineEnd = lineEndAfter(source, end);
49
+ const line = source.slice(lineStart, start) + replacementText + source.slice(end, lineEnd);
50
+ return line.length > MAX_LINE_LENGTH;
51
+ };
52
+ const replacementTextForExpression = (source, expression) => {
53
+ const expressionText = sourceForNode(source, expression);
54
+ if (expressionNeedsParentheses(expression)) {
55
+ return `(${expressionText})`;
56
+ }
57
+ return expressionText;
58
+ };
59
+ const onlyReturnStatement = (body) => {
60
+ if (body.body.length !== 1) {
61
+ return undefined;
62
+ }
63
+ const [statement] = body.body;
64
+ if (statement?.type === 'ReturnStatement' && statement.argument) {
65
+ return { expression: statement.argument, statement };
66
+ }
67
+ return undefined;
68
+ };
69
+ const replacementForReturnExpression = (source, node, expression) => {
70
+ const text = replacementTextForExpression(source, expression);
71
+ if (wouldExceedLineLimit(source, nodeStart(node.body), nodeEnd(node.body), text)) {
72
+ return undefined;
73
+ }
74
+ return { end: nodeEnd(node.body), start: nodeStart(node.body), text };
75
+ };
76
+ const replacementForArrow = (source, node) => {
77
+ if (node.body.type !== 'BlockStatement') {
78
+ return undefined;
79
+ }
80
+ const result = onlyReturnStatement(node.body);
81
+ if (!result) {
82
+ return undefined;
83
+ }
84
+ if (hasAttachedComments(result.statement)) {
85
+ return undefined;
86
+ }
87
+ return replacementForReturnExpression(source, node, result.expression);
88
+ };
89
+ /**
90
+ * Internal helper exported for package-local composition.
91
+ *
92
+ * @internal
93
+ */
94
+ export const preferConciseArrowBodies = (source) => {
95
+ const replacements = [];
96
+ codemodAPI(source)
97
+ .find(codemodAPI.ArrowFunctionExpression)
98
+ .forEach((path) => {
99
+ const replacement = replacementForArrow(source, path.value);
100
+ if (replacement) {
101
+ replacements.push(replacement);
102
+ }
103
+ });
104
+ return applyReplacements(source, replacements);
105
+ };
106
+ //# sourceMappingURL=arrow-body-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arrow-body-style.js","sourceRoot":"","sources":["../../src/codemods/arrow-body-style.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ interface JSDocInput {
2
+ summary: string;
3
+ tags?: readonly string[];
4
+ }
5
+ /**
6
+ * Formats a classic multi-line JSDoc block.
7
+ *
8
+ * @internal
9
+ */
10
+ export declare const formatJSDoc: (input: JSDocInput) => string;
11
+ /**
12
+ * Formats a three-line fixed-width section header.
13
+ *
14
+ * @internal
15
+ */
16
+ export declare const formatMainHeader: (text: string) => string;
17
+ /**
18
+ * Formats a one-line fixed-width section header.
19
+ *
20
+ * @internal
21
+ */
22
+ export declare const formatSubheader: (text: string) => string;
23
+ export {};
24
+ //# sourceMappingURL=comment-format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-format.d.ts","sourceRoot":"","sources":["../../src/codemods/comment-format.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAgFD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GAAI,OAAO,UAAU,KAAG,MAW/C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MAOlC,CAAC;AAEf;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,KAAG,MAM9C,CAAC"}