@geonosis/oxlint-plugin-biological-architecture 3.1.0 → 3.3.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 (248) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +75 -6
  3. package/RULES.md +202 -101
  4. package/corpus/.oxlintrc.json +5 -0
  5. package/corpus/data/bad-dynamic-orm.ts +5 -0
  6. package/corpus/data/bad-type-only-orm.ts +3 -0
  7. package/corpus/e2e/bad-list-response.spec.ts +5 -0
  8. package/corpus/e2e/bad-timeout.spec.ts +5 -0
  9. package/corpus/e2e/good-detail-response.spec.ts +5 -0
  10. package/corpus/e2e/good-state.spec.ts +5 -0
  11. package/corpus/manifest.json +2 -0
  12. package/corpus/medusa/queries/bad-silent-cap.ts +11 -0
  13. package/corpus/medusa/queries/good-paged-through.ts +19 -0
  14. package/corpus/medusa/queries/integration-tests/any-row.ts +10 -0
  15. package/corpus/tissues/bad-awaits-data.tsx +8 -0
  16. package/corpus/tissues/bad-fetches-data.tsx +7 -0
  17. package/corpus/tissues/good-takes-products.tsx +5 -0
  18. package/dist/discover-atoms.d.ts +2 -37
  19. package/dist/discover-atoms.js +1 -104
  20. package/dist/index.d.ts +3 -12
  21. package/dist/index.js +21 -176
  22. package/dist/presets.d.ts +11 -19
  23. package/dist/presets.js +94 -4
  24. package/dist/registry.d.ts +2 -0
  25. package/dist/registry.js +172 -0
  26. package/dist/rules/atom-no-deps.d.ts +1 -0
  27. package/dist/rules/atom-no-deps.js +10 -11
  28. package/dist/rules/boundary-time-is-primitive.d.ts +0 -7
  29. package/dist/rules/cell-must-be-stateful.d.ts +2 -2
  30. package/dist/rules/cell-must-be-stateful.js +24 -23
  31. package/dist/rules/cell-must-not-compose-cell.d.ts +1 -0
  32. package/dist/rules/cell-must-not-compose-cell.js +10 -3
  33. package/dist/rules/cell-no-cross-feature-organelles.d.ts +1 -0
  34. package/dist/rules/cell-no-cross-feature-organelles.js +7 -0
  35. package/dist/rules/cell-no-tissues.d.ts +1 -0
  36. package/dist/rules/cell-no-tissues.js +11 -7
  37. package/dist/rules/cells-folder-index-is-barrel.d.ts +12 -10
  38. package/dist/rules/cells-folder-index-is-barrel.js +66 -34
  39. package/dist/rules/compound-must-be-stateless.d.ts +2 -0
  40. package/dist/rules/compound-must-be-stateless.js +24 -26
  41. package/dist/rules/compound-no-stores.d.ts +1 -0
  42. package/dist/rules/compound-no-stores.js +12 -10
  43. package/dist/rules/constants-in-constants-file.d.ts +2 -8
  44. package/dist/rules/constants-in-constants-file.js +5 -6
  45. package/dist/rules/dialect-through-the-seam.d.ts +0 -13
  46. package/dist/rules/durable-body-reads-through-steps.d.ts +0 -14
  47. package/dist/rules/durable-body-reads-through-steps.js +8 -3
  48. package/dist/rules/effect-hook-naming.d.ts +9 -11
  49. package/dist/rules/effect-hook-naming.js +33 -31
  50. package/dist/rules/emit-declares-attempts.d.ts +0 -17
  51. package/dist/rules/emit-declares-attempts.js +5 -10
  52. package/dist/rules/font-roles-only.d.ts +0 -18
  53. package/dist/rules/font-roles-only.js +19 -22
  54. package/dist/rules/hermetic-e2e-no-wall-clock-waits.d.ts +53 -0
  55. package/dist/rules/hermetic-e2e-no-wall-clock-waits.js +100 -0
  56. package/dist/rules/icon-control-has-name.js +7 -1
  57. package/dist/rules/layer-walls.d.ts +0 -25
  58. package/dist/rules/layer-walls.js +7 -13
  59. package/dist/rules/lib/atom-map.d.ts +24 -0
  60. package/dist/rules/lib/atom-map.js +16 -0
  61. package/dist/rules/lib/cells-barrel.d.ts +0 -1
  62. package/dist/rules/lib/colors.d.ts +0 -19
  63. package/dist/rules/lib/colors.js +10 -243
  64. package/dist/rules/lib/comments.d.ts +19 -0
  65. package/dist/rules/lib/comments.js +5 -0
  66. package/dist/rules/lib/context.d.ts +0 -10
  67. package/dist/rules/lib/direction-rule.d.ts +4 -21
  68. package/dist/rules/lib/direction-rule.js +25 -4
  69. package/dist/rules/lib/doors.d.ts +2 -18
  70. package/dist/rules/lib/doors.js +81 -41
  71. package/dist/rules/lib/fresh.d.ts +5 -0
  72. package/dist/rules/lib/fresh.js +15 -0
  73. package/dist/rules/lib/hooks.d.ts +2 -17
  74. package/dist/rules/lib/hooks.js +14 -9
  75. package/dist/rules/lib/imports.d.ts +2 -23
  76. package/dist/rules/lib/imports.js +7 -2
  77. package/dist/rules/lib/jsx.d.ts +31 -0
  78. package/dist/rules/lib/jsx.js +11 -0
  79. package/dist/rules/lib/landing.d.ts +0 -40
  80. package/dist/rules/lib/literal-call.d.ts +1 -0
  81. package/dist/rules/lib/literal-call.js +2 -0
  82. package/dist/rules/lib/module-text.d.ts +3 -27
  83. package/dist/rules/lib/module-text.js +19 -4
  84. package/dist/rules/lib/mutations.d.ts +0 -14
  85. package/dist/rules/lib/nodes.d.ts +1 -18
  86. package/dist/rules/lib/nodes.js +1 -0
  87. package/dist/rules/lib/objects.d.ts +2 -11
  88. package/dist/rules/lib/objects.js +21 -0
  89. package/dist/rules/lib/options.d.ts +3 -52
  90. package/dist/rules/lib/options.js +49 -18
  91. package/dist/rules/lib/package-imports.d.ts +0 -5
  92. package/dist/rules/lib/package-imports.js +4 -10
  93. package/dist/rules/lib/paths.d.ts +15 -41
  94. package/dist/rules/lib/paths.js +34 -1
  95. package/dist/rules/lib/pattern-match.d.ts +2 -12
  96. package/dist/rules/lib/pattern-match.js +5 -1
  97. package/dist/rules/lib/probe.d.ts +0 -43
  98. package/dist/rules/lib/reexports.d.ts +0 -18
  99. package/dist/rules/lib/render-tracking.d.ts +0 -8
  100. package/dist/rules/lib/run-files.d.ts +18 -0
  101. package/dist/rules/lib/run-files.js +144 -0
  102. package/dist/rules/lib/shared-features.d.ts +0 -8
  103. package/dist/rules/lib/shared-features.js +2 -9
  104. package/dist/rules/lib/state-sources.d.ts +8 -0
  105. package/dist/rules/lib/state-sources.js +55 -0
  106. package/dist/rules/lib/steps.d.ts +3 -5
  107. package/dist/rules/lib/steps.js +6 -1
  108. package/dist/rules/lib/styling.d.ts +9 -42
  109. package/dist/rules/lib/styling.js +36 -10
  110. package/dist/rules/lib/tiers.d.ts +11 -24
  111. package/dist/rules/lib/tiers.js +41 -1
  112. package/dist/rules/lib/tissue-entrypoint.d.ts +0 -1
  113. package/dist/rules/lib/tissue-entrypoint.js +4 -5
  114. package/dist/rules/lib/token-layer.d.ts +19 -0
  115. package/dist/rules/lib/token-layer.js +170 -0
  116. package/dist/rules/lib/tsconfig-paths.d.ts +0 -4
  117. package/dist/rules/lib/tsconfig-paths.js +47 -15
  118. package/dist/rules/lib/type-members.d.ts +6 -0
  119. package/dist/rules/lib/type-members.js +165 -0
  120. package/dist/rules/lib/visitors.d.ts +0 -22
  121. package/dist/rules/lib/workspace-members.d.ts +2 -0
  122. package/dist/rules/lib/workspace-members.js +113 -0
  123. package/dist/rules/list-take-without-order.d.ts +24 -0
  124. package/dist/rules/list-take-without-order.js +293 -16
  125. package/dist/rules/max-comment-density.d.ts +3 -18
  126. package/dist/rules/max-comment-density.js +3 -3
  127. package/dist/rules/molecule-atoms-only.d.ts +1 -0
  128. package/dist/rules/molecule-atoms-only.js +11 -7
  129. package/dist/rules/molecule-must-compose.d.ts +2 -0
  130. package/dist/rules/molecule-must-compose.js +17 -21
  131. package/dist/rules/mutating-step-declares-retry.d.ts +2 -7
  132. package/dist/rules/mutating-step-declares-retry.js +29 -11
  133. package/dist/rules/named-when-block.d.ts +0 -2
  134. package/dist/rules/named-when-block.js +2 -8
  135. package/dist/rules/next-route-segment-is-thin-delegate.d.ts +4 -19
  136. package/dist/rules/next-route-segment-is-thin-delegate.js +47 -71
  137. package/dist/rules/no-brand-names.d.ts +0 -9
  138. package/dist/rules/no-brand-names.js +1 -1
  139. package/dist/rules/no-card-shaped-div.d.ts +4 -42
  140. package/dist/rules/no-card-shaped-div.js +12 -4
  141. package/dist/rules/no-cross-feature-stores.d.ts +1 -0
  142. package/dist/rules/no-cross-feature-stores.js +9 -5
  143. package/dist/rules/no-d1-transaction.d.ts +2 -5
  144. package/dist/rules/no-d1-transaction.js +7 -0
  145. package/dist/rules/no-date-string-compare.d.ts +2 -0
  146. package/dist/rules/no-date-string-compare.js +14 -8
  147. package/dist/rules/no-duplicate-jsx-patterns.d.ts +3 -1
  148. package/dist/rules/no-duplicate-jsx-patterns.js +16 -1
  149. package/dist/rules/no-generic-utility-package.d.ts +48 -2
  150. package/dist/rules/no-generic-utility-package.js +48 -9
  151. package/dist/rules/no-hook-in-component-disguise.d.ts +27 -13
  152. package/dist/rules/no-hook-in-component-disguise.js +38 -30
  153. package/dist/rules/no-index-count-as-exact.d.ts +0 -3
  154. package/dist/rules/no-inert-hidden-jsx.d.ts +4 -21
  155. package/dist/rules/no-inert-hidden-jsx.js +13 -12
  156. package/dist/rules/no-inline-data-in-jsx.d.ts +2 -0
  157. package/dist/rules/no-inline-data-in-jsx.js +17 -2
  158. package/dist/rules/no-invalid-feature-folders.d.ts +2 -0
  159. package/dist/rules/no-invalid-feature-folders.js +12 -4
  160. package/dist/rules/no-loader-side-effect-in-index-file.d.ts +2 -9
  161. package/dist/rules/no-logic-in-component-files.d.ts +6 -5
  162. package/dist/rules/no-logic-in-component-files.js +52 -31
  163. package/dist/rules/no-mock-db-in-integration.d.ts +0 -15
  164. package/dist/rules/no-mock-db-in-integration.js +3 -4
  165. package/dist/rules/no-orm-outside-db.d.ts +1 -0
  166. package/dist/rules/no-orm-outside-db.js +10 -7
  167. package/dist/rules/no-raw-html-atoms.d.ts +3 -22
  168. package/dist/rules/no-raw-html-atoms.js +5 -17
  169. package/dist/rules/no-raw-sql-outside-allowed.d.ts +2 -0
  170. package/dist/rules/no-raw-sql-outside-allowed.js +10 -15
  171. package/dist/rules/no-react-namespace.d.ts +2 -0
  172. package/dist/rules/no-react-namespace.js +13 -0
  173. package/dist/rules/no-renamed-html-props.d.ts +2 -0
  174. package/dist/rules/no-renamed-html-props.js +11 -2
  175. package/dist/rules/no-render-prop-reader.d.ts +4 -20
  176. package/dist/rules/no-render-prop-reader.js +13 -5
  177. package/dist/rules/no-runtime-dead-affordance.d.ts +3 -26
  178. package/dist/rules/no-runtime-dead-affordance.js +7 -20
  179. package/dist/rules/no-swallowed-catch.js +2 -8
  180. package/dist/rules/no-trivial-wrapper-component.d.ts +4 -19
  181. package/dist/rules/no-trivial-wrapper-component.js +24 -33
  182. package/dist/rules/no-ts-in-bio-folders.d.ts +2 -13
  183. package/dist/rules/no-ts-in-bio-folders.js +9 -7
  184. package/dist/rules/no-type-definitions-in-components.d.ts +2 -0
  185. package/dist/rules/no-type-definitions-in-components.js +12 -1
  186. package/dist/rules/no-unregistered-plugin-dir.d.ts +0 -41
  187. package/dist/rules/no-unregistered-plugin-dir.js +1 -9
  188. package/dist/rules/no-void-port.d.ts +2 -4
  189. package/dist/rules/no-void-port.js +7 -0
  190. package/dist/rules/organelle-dependency.d.ts +1 -0
  191. package/dist/rules/organelle-dependency.js +10 -8
  192. package/dist/rules/organelle-single-source.d.ts +2 -0
  193. package/dist/rules/organelle-single-source.js +58 -9
  194. package/dist/rules/plugin-route-namespaced.d.ts +0 -11
  195. package/dist/rules/plugin-route-namespaced.js +2 -2
  196. package/dist/rules/queries-require-org-scope.d.ts +0 -3
  197. package/dist/rules/queries-require-org-scope.js +3 -10
  198. package/dist/rules/queue-loop-is-the-library.js +3 -2
  199. package/dist/rules/route-no-inline-mutation.d.ts +1 -25
  200. package/dist/rules/route-no-inline-mutation.js +2 -7
  201. package/dist/rules/router-schema-parity.d.ts +0 -9
  202. package/dist/rules/router-schema-parity.js +5 -9
  203. package/dist/rules/service-name-not-reserved.d.ts +0 -3
  204. package/dist/rules/service-name-not-reserved.js +1 -34
  205. package/dist/rules/ssot-no-inline-facts.js +2 -5
  206. package/dist/rules/ssot-no-process-env.js +4 -12
  207. package/dist/rules/step-declares-compensation-or-none.d.ts +2 -1
  208. package/dist/rules/step-declares-compensation-or-none.js +17 -1
  209. package/dist/rules/step-opens-its-own-cell.d.ts +3 -26
  210. package/dist/rules/step-opens-its-own-cell.js +8 -13
  211. package/dist/rules/store-route-scopes-tenant-data.js +8 -26
  212. package/dist/rules/subpath-over-barrel.d.ts +3 -10
  213. package/dist/rules/subpath-over-barrel.js +55 -10
  214. package/dist/rules/subscriber-declares-id.d.ts +0 -2
  215. package/dist/rules/subscriber-declares-id.js +2 -8
  216. package/dist/rules/tables-declare-their-plane.d.ts +0 -2
  217. package/dist/rules/tables-declare-their-plane.js +4 -10
  218. package/dist/rules/tenant-tables-carry-org-id.d.ts +1 -4
  219. package/dist/rules/tenant-tables-carry-org-id.js +5 -12
  220. package/dist/rules/test-no-clock-polling-for-promise-flips.d.ts +7 -1
  221. package/dist/rules/test-no-clock-polling-for-promise-flips.js +21 -1
  222. package/dist/rules/time-through-the-door.d.ts +0 -24
  223. package/dist/rules/time-through-the-door.js +5 -5
  224. package/dist/rules/tissue-must-compose.d.ts +4 -2
  225. package/dist/rules/tissue-must-compose.js +25 -20
  226. package/dist/rules/tissue-no-data-props.d.ts +57 -1
  227. package/dist/rules/tissue-no-data-props.js +114 -32
  228. package/dist/rules/tissue-no-fetch.d.ts +26 -0
  229. package/dist/rules/tissue-no-fetch.js +57 -0
  230. package/dist/rules/tissue-no-hooks.d.ts +21 -23
  231. package/dist/rules/tissue-no-hooks.js +22 -4
  232. package/dist/rules/tissue-no-organelles.d.ts +1 -0
  233. package/dist/rules/tissue-no-organelles.js +9 -1
  234. package/dist/rules/tissue-no-stores.d.ts +1 -0
  235. package/dist/rules/tissue-no-stores.js +9 -1
  236. package/dist/rules/todo-names-its-plan.d.ts +1 -28
  237. package/dist/rules/todo-names-its-plan.js +2 -2
  238. package/dist/rules/tokens-only-colors.d.ts +8 -46
  239. package/dist/rules/tokens-only-colors.js +64 -20
  240. package/dist/rules/unique-query-step-name.d.ts +0 -7
  241. package/dist/rules/unique-query-step-name.js +6 -10
  242. package/dist/rules/worker-handles-are-scoped.d.ts +11 -8
  243. package/dist/rules/worker-handles-are-scoped.js +12 -5
  244. package/dist/rules/zustand-v5-best-practices.d.ts +8 -18
  245. package/dist/rules/zustand-v5-best-practices.js +32 -56
  246. package/dist/timing.d.ts +18 -0
  247. package/dist/timing.js +75 -0
  248. package/package.json +2 -2
@@ -0,0 +1,5 @@
1
+ declare const page: { waitForTimeout: (ms: number) => Promise<void> }
2
+
3
+ export const buys = async (): Promise<void> => {
4
+ await page.waitForTimeout(2000)
5
+ }
@@ -0,0 +1,5 @@
1
+ declare const page: { waitForResponse: (match: RegExp) => Promise<void> }
2
+
3
+ export const buys = async (): Promise<void> => {
4
+ await page.waitForResponse(/corpus-orders-one/)
5
+ }
@@ -0,0 +1,5 @@
1
+ declare const expectVisible: (name: string) => Promise<void>
2
+
3
+ export const buys = async (): Promise<void> => {
4
+ await expectVisible('order placed')
5
+ }
@@ -16,6 +16,7 @@
16
16
  "biological-architecture/effect-hook-naming",
17
17
  "biological-architecture/emit-declares-attempts",
18
18
  "biological-architecture/font-roles-only",
19
+ "biological-architecture/hermetic-e2e-no-wall-clock-waits",
19
20
  "biological-architecture/icon-control-has-name",
20
21
  "biological-architecture/layer-walls",
21
22
  "biological-architecture/list-take-without-order",
@@ -74,6 +75,7 @@
74
75
  "biological-architecture/time-through-the-door",
75
76
  "biological-architecture/tissue-must-compose",
76
77
  "biological-architecture/tissue-no-data-props",
78
+ "biological-architecture/tissue-no-fetch",
77
79
  "biological-architecture/tissue-no-hooks",
78
80
  "biological-architecture/tissue-no-organelles",
79
81
  "biological-architecture/tissue-no-stores",
@@ -0,0 +1,11 @@
1
+ // BREACH: the cap is not a page. The 101st production order is never cancelled, in any order.
2
+ declare const service: {
3
+ listProductionOrders: (filters: unknown, config: unknown) => Promise<{ id: string }[]>
4
+ }
5
+ declare function cancelOrders(ids: string[]): Promise<void>
6
+
7
+ export const cancelAll = async (orderId: string): Promise<void> => {
8
+ const candidates = await service.listProductionOrders({ order_id: orderId }, { take: 100 })
9
+
10
+ await cancelOrders(candidates.map((one) => one.id))
11
+ }
@@ -0,0 +1,19 @@
1
+ // ACCEPTED: every page names its order and the loop reads pages until one comes back short.
2
+ declare const service: {
3
+ listProductionOrders: (filters: unknown, config: unknown) => Promise<{ id: string }[]>
4
+ }
5
+ declare function cancelOrders(ids: string[]): Promise<void>
6
+
7
+ const PAGE = 100
8
+
9
+ export const cancelAll = async (orderId: string): Promise<void> => {
10
+ for (let skip = 0; ; skip += PAGE) {
11
+ const page = await service.listProductionOrders(
12
+ { order_id: orderId },
13
+ { order: { id: 'ASC' }, skip, take: PAGE },
14
+ )
15
+
16
+ await cancelOrders(page.map((one) => one.id))
17
+ if (page.length < PAGE) return
18
+ }
19
+ }
@@ -0,0 +1,10 @@
1
+ // ACCEPTED: a fixture that wants any row; which row comes back does not matter.
2
+ declare const service: {
3
+ listSalesChannels: (filters: unknown, config: unknown) => Promise<{ id: string }[]>
4
+ }
5
+
6
+ export const anyChannel = async (): Promise<unknown> => {
7
+ const [channel] = await service.listSalesChannels({}, { take: 1 })
8
+
9
+ return channel
10
+ }
@@ -0,0 +1,8 @@
1
+ import { ProductGrid } from '../cells/product-grid'
2
+ import { loadProducts } from '../lib/load-products'
3
+
4
+ export async function BadAwaitsData() {
5
+ const products = await loadProducts()
6
+
7
+ return <ProductGrid products={products} />
8
+ }
@@ -0,0 +1,7 @@
1
+ import { ProductGrid } from '../cells/product-grid'
2
+
3
+ export function BadFetchesData() {
4
+ const pending = fetch('/api/products')
5
+
6
+ return <ProductGrid pending={pending} />
7
+ }
@@ -0,0 +1,5 @@
1
+ import { ProductGrid } from '../cells/product-grid'
2
+
3
+ export function GoodTakesProducts({ products }: { products: string[] }) {
4
+ return <ProductGrid products={products} />
5
+ }
@@ -1,50 +1,15 @@
1
+ import type { Restriction } from './rules/lib/atom-map.js';
1
2
  interface AtomMapping {
2
3
  atomFile: string;
3
4
  atomName: string;
4
5
  nativeElement: string;
5
6
  }
6
- interface AtomRestriction {
7
- atom: string;
8
- element: string;
9
- importPath: string;
10
- }
11
7
  interface RestrictedSyntaxEntry {
12
8
  message: string;
13
9
  selector: string;
14
10
  }
15
- /**
16
- * Build no-restricted-syntax entries that forbid raw native HTML usage
17
- * for every native element wrapped by an atom. Apply these entries to
18
- * molecules, compounds, cells, and tissues (NOT atoms themselves).
19
- */
20
11
  export declare function buildAtomRestrictions(atomsDir: string, importPathPrefix?: string): RestrictedSyntaxEntry[];
21
- /**
22
- * Build atom restrictions in the format expected by the no-raw-html-atoms rule.
23
- * This replaces no-restricted-syntax for linters that don't support it (e.g. oxlint).
24
- */
25
- export declare function buildAtomRuleRestrictions(atomsDir: string, importPathPrefix?: string): AtomRestriction[];
26
- /**
27
- * Scan the atoms directory and build a mapping from native HTML element
28
- * to the atom that wraps it. This is used to generate no-restricted-syntax
29
- * entries that forbid raw native HTML usage in higher-level components.
30
- *
31
- * When multiple atoms wrap the same element (e.g. `input.tsx` and
32
- * `inline-input.tsx` both wrap `<input>`), the atom whose filename
33
- * exactly matches the element name is preferred as the canonical one.
34
- * Variants are kept as alternatives in the error message.
35
- */
12
+ export declare function buildAtomRuleRestrictions(atomsDir: string, importPathPrefix?: string): Restriction[];
36
13
  export declare function scanAtomMappings(atomsDir: string): AtomMapping[];
37
- /**
38
- * The native element an atom wraps, read from the one place every atom says so: its props type.
39
- *
40
- * `ComponentProps<'button'>`, `ComponentPropsWithoutRef<'textarea'>`,
41
- * `HTMLAttributes<HTMLSelectElement>` and `React.ButtonHTMLAttributes<HTMLButtonElement>` all name
42
- * the element outright, and an atom that types its props any other way is an atom nobody can
43
- * compose. The Radix `asChild ? Slot.Root : 'button'` form comes next, and the JSX-tag scan is
44
- * only the fallback — it was the whole detector once, and on a real tree it returned `string`,
45
- * `typeof` and `path` while missing every shadcn button in the repo.
46
- *
47
- * The name is kept because consumers import it.
48
- */
49
14
  export declare function detectFirstNativeJsxElement(source: string): null | string;
50
15
  export {};
@@ -3,110 +3,7 @@ import { readdirSync, readFileSync } from "node:fs";
3
3
  import { basename, join } from "node:path";
4
4
  import { stripComments } from "./rules/lib/module-text.js";
5
5
  var GENERIC_ELEMENTS = new Set(["div", "span"]);
6
- var HTML_ELEMENTS = new Set([
7
- "a",
8
- "abbr",
9
- "address",
10
- "area",
11
- "article",
12
- "aside",
13
- "audio",
14
- "b",
15
- "bdi",
16
- "bdo",
17
- "blockquote",
18
- "br",
19
- "button",
20
- "canvas",
21
- "caption",
22
- "cite",
23
- "code",
24
- "col",
25
- "colgroup",
26
- "data",
27
- "datalist",
28
- "dd",
29
- "del",
30
- "details",
31
- "dfn",
32
- "dialog",
33
- "div",
34
- "dl",
35
- "dt",
36
- "em",
37
- "embed",
38
- "fieldset",
39
- "figcaption",
40
- "figure",
41
- "footer",
42
- "form",
43
- "h1",
44
- "h2",
45
- "h3",
46
- "h4",
47
- "h5",
48
- "h6",
49
- "header",
50
- "hgroup",
51
- "hr",
52
- "i",
53
- "iframe",
54
- "img",
55
- "input",
56
- "ins",
57
- "kbd",
58
- "label",
59
- "legend",
60
- "li",
61
- "main",
62
- "map",
63
- "mark",
64
- "menu",
65
- "meter",
66
- "nav",
67
- "noscript",
68
- "object",
69
- "ol",
70
- "optgroup",
71
- "option",
72
- "output",
73
- "p",
74
- "picture",
75
- "pre",
76
- "progress",
77
- "q",
78
- "rp",
79
- "rt",
80
- "ruby",
81
- "s",
82
- "samp",
83
- "search",
84
- "section",
85
- "select",
86
- "small",
87
- "source",
88
- "span",
89
- "strong",
90
- "sub",
91
- "summary",
92
- "sup",
93
- "table",
94
- "tbody",
95
- "td",
96
- "template",
97
- "textarea",
98
- "tfoot",
99
- "th",
100
- "thead",
101
- "time",
102
- "tr",
103
- "track",
104
- "u",
105
- "ul",
106
- "var",
107
- "video",
108
- "wbr"
109
- ]);
6
+ var HTML_ELEMENTS = new Set("a abbr address area article aside audio b bdi bdo blockquote br button canvas caption cite code col colgroup data datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hgroup hr i iframe img input ins kbd label legend li main map mark menu meter nav noscript object ol optgroup option output p picture pre progress q rp rt ruby s samp search section select small source span strong sub summary sup table tbody td template textarea tfoot th thead time tr track u ul var video wbr".split(" "));
110
7
  var TAG_OF_DOM_INTERFACE = {
111
8
  HTMLAnchorElement: "a",
112
9
  HTMLAreaElement: "area",
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { ProbeFn } from './rules/lib/probe.js';
2
+ import { type Tier } from './rules/lib/tiers.js';
2
3
  export type Rule = {
3
4
  create: (context: never) => Record<string, unknown>;
4
5
  fixShape: string;
@@ -10,25 +11,15 @@ export type Rule = {
10
11
  schema: unknown[];
11
12
  type: string;
12
13
  };
13
- /**
14
- * Present only on a rule whose REACH depends on an option. It answers with the smallest source
15
- * that must fire the rule under the options it is handed, so a repo whose corpus carries no such
16
- * file can still be shown the rule reaching something — and a rule with no probe that fires
17
- * nowhere stays a failure, which is the whole point of the check that reads this.
18
- */
19
14
  probe?: ProbeFn;
20
- /**
21
- * The engine this rule presumes, and the packages a workspace's manifest proves it with. Present
22
- * only on a rule that reaches ONE engine: enabled where the engine is absent, it has zero
23
- * possible findings and reads exactly like compliance (#159). Declared once in `presets.ts`.
24
- */
25
15
  presumes?: {
26
16
  engine: string;
27
17
  packages: readonly string[];
28
18
  };
19
+ tier?: Tier;
29
20
  };
30
21
  export declare const rules: Record<string, Rule>;
31
- export { PRESETS, RENAMED_TO, rulesOfPreset } from './presets.js';
22
+ export { PRESETS, presetSections, RENAMED_TO, rulesOfPreset } from './presets.js';
32
23
  export type { Preset, PresetName } from './presets.js';
33
24
  declare const plugin: {
34
25
  configs: {
package/dist/index.js CHANGED
@@ -1,182 +1,26 @@
1
1
  // src/index.ts
2
2
  import { createRequire } from "node:module";
3
- import { PRESETS, PRESUMED_ENGINES } from "./presets.js";
4
- import atomNoDeps from "./rules/atom-no-deps.js";
5
- import boundaryTimeIsPrimitive from "./rules/boundary-time-is-primitive.js";
6
- import cellMustBeStateful from "./rules/cell-must-be-stateful.js";
7
- import cellMustNotComposeCell from "./rules/cell-must-not-compose-cell.js";
8
- import cellNoCrossFeatureOrganelles from "./rules/cell-no-cross-feature-organelles.js";
9
- import cellNoTissues from "./rules/cell-no-tissues.js";
10
- import cellsFolderIndexIsBarrel from "./rules/cells-folder-index-is-barrel.js";
11
- import compoundMustBeStateless from "./rules/compound-must-be-stateless.js";
12
- import compoundNoStores from "./rules/compound-no-stores.js";
13
- import constantsInConstantsFile from "./rules/constants-in-constants-file.js";
14
- import dialectThroughTheSeam from "./rules/dialect-through-the-seam.js";
15
- import durableBodyReadsThroughSteps from "./rules/durable-body-reads-through-steps.js";
16
- import effectHookNaming from "./rules/effect-hook-naming.js";
17
- import emitDeclaresAttempts from "./rules/emit-declares-attempts.js";
18
- import fontRolesOnly from "./rules/font-roles-only.js";
19
- import iconControlHasName from "./rules/icon-control-has-name.js";
20
- import layerWalls from "./rules/layer-walls.js";
3
+ import { PRESETS, PRESUMED_ENGINES, TIER_RULES } from "./presets.js";
4
+ import { registered } from "./registry.js";
21
5
  import { reportingOncePerRun } from "./rules/lib/options.js";
22
- import listTakeWithoutOrder from "./rules/list-take-without-order.js";
23
- import maxCommentDensity from "./rules/max-comment-density.js";
24
- import moleculeAtomsOnly from "./rules/molecule-atoms-only.js";
25
- import moleculeMustCompose from "./rules/molecule-must-compose.js";
26
- import mutatingStepDeclaresRetry from "./rules/mutating-step-declares-retry.js";
27
- import namedWhenBlock from "./rules/named-when-block.js";
28
- import nextRouteSegmentIsThinDelegate from "./rules/next-route-segment-is-thin-delegate.js";
29
- import noBrandNames from "./rules/no-brand-names.js";
30
- import noCardShapedDiv from "./rules/no-card-shaped-div.js";
31
- import noCrossFeatureStores from "./rules/no-cross-feature-stores.js";
32
- import noD1Transaction from "./rules/no-d1-transaction.js";
33
- import noDateStringCompare from "./rules/no-date-string-compare.js";
34
- import noDuplicateJsxPatterns from "./rules/no-duplicate-jsx-patterns.js";
35
- import noGenericUtilityPackage from "./rules/no-generic-utility-package.js";
36
- import noHookInComponentDisguise from "./rules/no-hook-in-component-disguise.js";
37
- import noIndexCountAsExact from "./rules/no-index-count-as-exact.js";
38
- import noInertHiddenJsx from "./rules/no-inert-hidden-jsx.js";
39
- import noInlineDataInJsx from "./rules/no-inline-data-in-jsx.js";
40
- import noInvalidFeatureFolders from "./rules/no-invalid-feature-folders.js";
41
- import noLoaderSideEffectInIndexFile from "./rules/no-loader-side-effect-in-index-file.js";
42
- import noLogicInComponentFiles from "./rules/no-logic-in-component-files.js";
43
- import noMockDbInIntegration from "./rules/no-mock-db-in-integration.js";
44
- import noOrmOutsideDb from "./rules/no-orm-outside-db.js";
45
- import noRawHtmlAtoms from "./rules/no-raw-html-atoms.js";
46
- import noRawSqlOutsideAllowed from "./rules/no-raw-sql-outside-allowed.js";
47
- import noReactNamespace from "./rules/no-react-namespace.js";
48
- import noRenamedHtmlProps from "./rules/no-renamed-html-props.js";
49
- import noRenderPropReader from "./rules/no-render-prop-reader.js";
50
- import noRuntimeDeadAffordance from "./rules/no-runtime-dead-affordance.js";
51
- import noSwallowedCatch from "./rules/no-swallowed-catch.js";
52
- import noTrivialWrapperComponent from "./rules/no-trivial-wrapper-component.js";
53
- import noTsInBioFolders from "./rules/no-ts-in-bio-folders.js";
54
- import noTypeDefinitionsInComponents from "./rules/no-type-definitions-in-components.js";
55
- import noUnregisteredPluginDir from "./rules/no-unregistered-plugin-dir.js";
56
- import noVoidPort from "./rules/no-void-port.js";
57
- import organelleDependency from "./rules/organelle-dependency.js";
58
- import organelleSingleSource from "./rules/organelle-single-source.js";
59
- import pluginRouteNamespaced from "./rules/plugin-route-namespaced.js";
60
- import queriesRequireOrgScope from "./rules/queries-require-org-scope.js";
61
- import queueLoopIsTheLibrary from "./rules/queue-loop-is-the-library.js";
62
- import routeNoInlineMutation from "./rules/route-no-inline-mutation.js";
63
- import routerSchemaParity from "./rules/router-schema-parity.js";
64
- import serviceNameNotReserved from "./rules/service-name-not-reserved.js";
65
- import ssotNoInlineFacts from "./rules/ssot-no-inline-facts.js";
66
- import ssotNoProcessEnv from "./rules/ssot-no-process-env.js";
67
- import stepDeclaresCompensationOrNone from "./rules/step-declares-compensation-or-none.js";
68
- import stepOpensItsOwnCell from "./rules/step-opens-its-own-cell.js";
69
- import storeRouteScopesTenantData from "./rules/store-route-scopes-tenant-data.js";
70
- import subpathOverBarrel from "./rules/subpath-over-barrel.js";
71
- import subscriberDeclaresId from "./rules/subscriber-declares-id.js";
72
- import tablesDeclareTheirPlane from "./rules/tables-declare-their-plane.js";
73
- import tenantTablesCarryOrgId from "./rules/tenant-tables-carry-org-id.js";
74
- import testNoClockPollingForPromiseFlips from "./rules/test-no-clock-polling-for-promise-flips.js";
75
- import timeThroughTheDoor from "./rules/time-through-the-door.js";
76
- import tissueMustCompose from "./rules/tissue-must-compose.js";
77
- import tissueNoDataProps from "./rules/tissue-no-data-props.js";
78
- import tissueNoHooks from "./rules/tissue-no-hooks.js";
79
- import tissueNoOrganelles from "./rules/tissue-no-organelles.js";
80
- import tissueNoStores from "./rules/tissue-no-stores.js";
81
- import todoNamesItsPlan from "./rules/todo-names-its-plan.js";
82
- import tokensOnlyColors from "./rules/tokens-only-colors.js";
83
- import uniqueQueryStepName from "./rules/unique-query-step-name.js";
84
- import workerHandlesAreScoped from "./rules/worker-handles-are-scoped.js";
85
- import zustandV5BestPractices from "./rules/zustand-v5-best-practices.js";
86
- import { PRESETS as PRESETS2, RENAMED_TO, rulesOfPreset } from "./presets.js";
87
- var reportingOnce = (declared) => Object.fromEntries(Object.entries(declared).map(([name, rule]) => [
88
- name,
89
- { ...rule, create: reportingOncePerRun(rule.create) }
90
- ]));
91
- var withEngines = (declared) => {
92
- const presumed = new Map(PRESUMED_ENGINES.flatMap((one) => one.rules.map((name) => [name, { engine: one.engine, packages: one.packages }])));
93
- return Object.fromEntries(Object.entries(declared).map(([name, rule]) => {
94
- const engine = presumed.get(name);
95
- return [name, engine === undefined ? rule : { ...rule, presumes: engine }];
96
- }));
97
- };
98
- var rules = reportingOnce(withEngines({
99
- "atom-no-deps": atomNoDeps,
100
- "boundary-time-is-primitive": boundaryTimeIsPrimitive,
101
- "cell-must-be-stateful": cellMustBeStateful,
102
- "cell-must-not-compose-cell": cellMustNotComposeCell,
103
- "cell-no-cross-feature-organelles": cellNoCrossFeatureOrganelles,
104
- "cell-no-tissues": cellNoTissues,
105
- "cells-folder-index-is-barrel": cellsFolderIndexIsBarrel,
106
- "compound-must-be-stateless": compoundMustBeStateless,
107
- "compound-no-stores": compoundNoStores,
108
- "constants-in-constants-file": constantsInConstantsFile,
109
- "dialect-through-the-seam": dialectThroughTheSeam,
110
- "durable-body-reads-through-steps": durableBodyReadsThroughSteps,
111
- "effect-hook-naming": effectHookNaming,
112
- "emit-declares-attempts": emitDeclaresAttempts,
113
- "font-roles-only": fontRolesOnly,
114
- "icon-control-has-name": iconControlHasName,
115
- "layer-walls": layerWalls,
116
- "list-take-without-order": listTakeWithoutOrder,
117
- "max-comment-density": maxCommentDensity,
118
- "molecule-atoms-only": moleculeAtomsOnly,
119
- "molecule-must-compose": moleculeMustCompose,
120
- "mutating-step-declares-retry": mutatingStepDeclaresRetry,
121
- "plugin-route-namespaced": pluginRouteNamespaced,
122
- "route-no-inline-mutation": routeNoInlineMutation,
123
- "unique-query-step-name": uniqueQueryStepName,
124
- "named-when-block": namedWhenBlock,
125
- "next-route-segment-is-thin-delegate": nextRouteSegmentIsThinDelegate,
126
- "no-brand-names": noBrandNames,
127
- "no-card-shaped-div": noCardShapedDiv,
128
- "no-cross-feature-stores": noCrossFeatureStores,
129
- "no-d1-transaction": noD1Transaction,
130
- "no-date-string-compare": noDateStringCompare,
131
- "no-duplicate-jsx-patterns": noDuplicateJsxPatterns,
132
- "no-generic-utility-package": noGenericUtilityPackage,
133
- "no-hook-in-component-disguise": noHookInComponentDisguise,
134
- "no-index-count-as-exact": noIndexCountAsExact,
135
- "no-inert-hidden-jsx": noInertHiddenJsx,
136
- "no-inline-data-in-jsx": noInlineDataInJsx,
137
- "no-invalid-feature-folders": noInvalidFeatureFolders,
138
- "no-loader-side-effect-in-index-file": noLoaderSideEffectInIndexFile,
139
- "no-logic-in-component-files": noLogicInComponentFiles,
140
- "no-mock-db-in-integration": noMockDbInIntegration,
141
- "no-orm-outside-db": noOrmOutsideDb,
142
- "no-raw-html-atoms": noRawHtmlAtoms,
143
- "no-raw-sql-outside-allowed": noRawSqlOutsideAllowed,
144
- "no-react-namespace": noReactNamespace,
145
- "no-renamed-html-props": noRenamedHtmlProps,
146
- "no-render-prop-reader": noRenderPropReader,
147
- "no-swallowed-catch": noSwallowedCatch,
148
- "no-runtime-dead-affordance": noRuntimeDeadAffordance,
149
- "no-trivial-wrapper-component": noTrivialWrapperComponent,
150
- "no-ts-in-bio-folders": noTsInBioFolders,
151
- "no-type-definitions-in-components": noTypeDefinitionsInComponents,
152
- "no-unregistered-plugin-dir": noUnregisteredPluginDir,
153
- "no-void-port": noVoidPort,
154
- "organelle-dependency": organelleDependency,
155
- "organelle-single-source": organelleSingleSource,
156
- "queries-require-org-scope": queriesRequireOrgScope,
157
- "queue-loop-is-the-library": queueLoopIsTheLibrary,
158
- "router-schema-parity": routerSchemaParity,
159
- "service-name-not-reserved": serviceNameNotReserved,
160
- "ssot-no-inline-facts": ssotNoInlineFacts,
161
- "ssot-no-process-env": ssotNoProcessEnv,
162
- "step-declares-compensation-or-none": stepDeclaresCompensationOrNone,
163
- "step-opens-its-own-cell": stepOpensItsOwnCell,
164
- "store-route-scopes-tenant-data": storeRouteScopesTenantData,
165
- "subpath-over-barrel": subpathOverBarrel,
166
- "subscriber-declares-id": subscriberDeclaresId,
167
- "tables-declare-their-plane": tablesDeclareTheirPlane,
168
- "tenant-tables-carry-org-id": tenantTablesCarryOrgId,
169
- "test-no-clock-polling-for-promise-flips": testNoClockPollingForPromiseFlips,
170
- "time-through-the-door": timeThroughTheDoor,
171
- "tokens-only-colors": tokensOnlyColors,
172
- "tissue-must-compose": tissueMustCompose,
173
- "tissue-no-data-props": tissueNoDataProps,
174
- "tissue-no-hooks": tissueNoHooks,
175
- "tissue-no-organelles": tissueNoOrganelles,
176
- "tissue-no-stores": tissueNoStores,
177
- "todo-names-its-plan": todoNamesItsPlan,
178
- "worker-handles-are-scoped": workerHandlesAreScoped,
179
- "zustand-v5-best-practices": zustandV5BestPractices
6
+ import { TIERS } from "./rules/lib/tiers.js";
7
+ import { timingRequested, withTiming } from "./timing.js";
8
+ import { PRESETS as PRESETS2, presetSections, RENAMED_TO, rulesOfPreset } from "./presets.js";
9
+ var presumed = new Map(PRESUMED_ENGINES.flatMap((one) => one.rules.map((name) => [name, { engine: one.engine, packages: one.packages }])));
10
+ var reached = new Map(TIERS.flatMap((tier) => TIER_RULES[tier].map((name) => [name, tier])));
11
+ var timed = timingRequested();
12
+ var rules = Object.fromEntries(Object.entries(registered).map(([name, rule]) => {
13
+ const presumes = presumed.get(name);
14
+ const tier = reached.get(name);
15
+ return [
16
+ name,
17
+ {
18
+ ...rule,
19
+ ...presumes === undefined ? {} : { presumes },
20
+ ...tier === undefined ? {} : { tier },
21
+ create: timed ? withTiming(reportingOncePerRun(rule.create, name), name) : reportingOncePerRun(rule.create, name)
22
+ }
23
+ ];
180
24
  }));
181
25
  var { version } = createRequire(import.meta.url)("../package.json");
182
26
  var plugin = {
@@ -192,6 +36,7 @@ export {
192
36
  PRESETS2 as PRESETS,
193
37
  RENAMED_TO,
194
38
  src_default as default,
39
+ presetSections,
195
40
  rules,
196
41
  rulesOfPreset
197
42
  };
package/dist/presets.d.ts CHANGED
@@ -1,30 +1,14 @@
1
- /**
2
- * #197: the preset was named after `sagaflow-js`, which `@geonosis/workflows` replaced. A config
3
- * naming the old name resolves to the same rules until the next major — a rename that breaks every
4
- * consumer's config the day it ships is a rename nobody adopts — and the reading says so ONCE per
5
- * process, whatever door read it and however many rules it resolved.
6
- */
1
+ import type { Tier } from './rules/lib/tiers.js';
7
2
  export declare const RENAMED_TO: Record<string, string>;
8
3
  export type Preset = {
9
- /** Rule ids that belong to this preset but are not ours — enabled alongside, never instead. */
10
4
  rules: Record<string, string>;
11
5
  };
12
- /**
13
- * The engine a rule PRESUMES, and the packages a manifest proves it with.
14
- *
15
- * A rule that presumes an engine can sit at "error" over a tree that has none, with zero possible
16
- * findings, and read exactly like compliance — a Workers + D1 app ran three of these over sagaflow trees
17
- * (#159). It is written down ONCE, here beside the presets that already knew it, and projected onto
18
- * the rules so `geonosis-doctor` can ask a workspace's manifest without carrying a second list.
19
- *
20
- * The two step rules that appear in `backend-workflows` as well are deliberately NOT here: 026-W2
21
- * measured them reaching both engines' spellings, and a rule that reaches both presumes neither.
22
- */
23
6
  export declare const PRESUMED_ENGINES: readonly {
24
7
  engine: string;
25
8
  packages: readonly string[];
26
9
  rules: readonly string[];
27
10
  }[];
11
+ export declare const TIER_RULES: Record<Tier, readonly string[]>;
28
12
  export declare const PRESETS: {
29
13
  'backend-d1': {
30
14
  rules: Record<string, "error">;
@@ -74,5 +58,13 @@ export declare const PRESETS: {
74
58
  };
75
59
  };
76
60
  export type PresetName = keyof typeof PRESETS;
77
- /** The rule names a preset carries, stripped of the plugin namespace. */
78
61
  export declare const rulesOfPreset: (preset: PresetName) => string[];
62
+ export type PresetDoc = {
63
+ blurb: string;
64
+ order: number;
65
+ };
66
+ export declare const presetSections: () => {
67
+ blurb: string;
68
+ name: PresetName;
69
+ order: number;
70
+ }[];