@gspothq/cli 0.0.0-stage → 0.1.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 (232) hide show
  1. package/README.md +18 -2
  2. package/configurations/database/postgres/manifest.toml +114 -0
  3. package/configurations/database/postgres/rules/POSTGRES.md +78 -0
  4. package/configurations/framework/astro/eslint-presets.json +138 -0
  5. package/configurations/framework/astro/manifest.toml +95 -0
  6. package/configurations/framework/astro/rules/ASTRO.md +39 -0
  7. package/configurations/framework/expo/manifest.toml +43 -0
  8. package/configurations/framework/express/manifest.toml +17 -0
  9. package/configurations/framework/express/rules/EXPRESS.md +73 -0
  10. package/configurations/framework/express/semgrep/express.yml +71 -0
  11. package/configurations/framework/fastapi/manifest.toml +11 -0
  12. package/configurations/framework/fastapi/rules/FASTAPI.md +100 -0
  13. package/configurations/framework/fastapi/semgrep/fastapi.yml +44 -0
  14. package/configurations/framework/nestjs/eslint-presets.json +62 -0
  15. package/configurations/framework/nestjs/manifest.toml +52 -0
  16. package/configurations/framework/nestjs/rules/NESTJS.md +44 -0
  17. package/configurations/framework/nextjs/eslint-presets.json +73 -0
  18. package/configurations/framework/nextjs/manifest.toml +119 -0
  19. package/configurations/framework/nextjs/rules/NEXTJS.md +43 -0
  20. package/configurations/framework/react/eslint-presets.json +77 -0
  21. package/configurations/framework/react/manifest.toml +93 -0
  22. package/configurations/framework/react/rules/REACT.md +108 -0
  23. package/configurations/framework/react-dom/eslint-presets.json +110 -0
  24. package/configurations/framework/react-dom/manifest.toml +24 -0
  25. package/configurations/framework/react-native/manifest.toml +46 -0
  26. package/configurations/framework/react-native/rules/REACT-NATIVE.md +51 -0
  27. package/configurations/framework/site/manifest.toml +170 -0
  28. package/configurations/framework/site/rules/SITE.md +20 -0
  29. package/configurations/framework/svelte/eslint-presets.json +67 -0
  30. package/configurations/framework/svelte/manifest.toml +83 -0
  31. package/configurations/framework/svelte/rules/SVELTE.md +48 -0
  32. package/configurations/framework/vue/eslint-presets.json +180 -0
  33. package/configurations/framework/vue/manifest.toml +83 -0
  34. package/configurations/framework/vue/rules/VUE.md +41 -0
  35. package/configurations/general/commits/manifest.toml +111 -0
  36. package/configurations/general/commits/rules/GIT.md +31 -0
  37. package/configurations/general/coverage/manifest.toml +3 -0
  38. package/configurations/general/dependencies/manifest.toml +159 -0
  39. package/configurations/general/dependencies/rules/DEPENDENCIES.md +30 -0
  40. package/configurations/general/dependencies/syncpack.json +15 -0
  41. package/configurations/general/docs/manifest.toml +79 -0
  42. package/configurations/general/docs/rules/DOCS.md +86 -0
  43. package/configurations/general/duplication/manifest.toml +32 -0
  44. package/configurations/general/engineering/manifest.toml +8 -0
  45. package/configurations/general/engineering/rules/agent/PLANNING.md +42 -0
  46. package/configurations/general/engineering/rules/agent/SUPPRESSIONS.md +16 -0
  47. package/configurations/general/engineering/rules/agent/TALKING.md +3 -0
  48. package/configurations/general/engineering/rules/agent/TASKS.md +19 -0
  49. package/configurations/general/engineering/rules/agent/WORKING.md +83 -0
  50. package/configurations/general/engineering/rules/code/ACCESSIBILITY.md +32 -0
  51. package/configurations/general/engineering/rules/code/CLI.md +37 -0
  52. package/configurations/general/engineering/rules/code/COMMENTS.md +38 -0
  53. package/configurations/general/engineering/rules/code/CONFIGURATION.md +25 -0
  54. package/configurations/general/engineering/rules/code/ERRORS.md +49 -0
  55. package/configurations/general/engineering/rules/code/HTTP.md +46 -0
  56. package/configurations/general/engineering/rules/code/LOGGING.md +55 -0
  57. package/configurations/general/engineering/rules/code/TESTING.md +58 -0
  58. package/configurations/general/files/manifest.toml +141 -0
  59. package/configurations/general/files/rules/YAML.md +19 -0
  60. package/configurations/general/format/manifest.toml +152 -0
  61. package/configurations/general/gspot/manifest.toml +65 -0
  62. package/configurations/general/gspot/rules/GENERATED.md +10 -0
  63. package/configurations/general/licenses/manifest.toml +33 -0
  64. package/configurations/general/naming/defaults.json +423 -0
  65. package/configurations/general/naming/manifest.toml +35 -0
  66. package/configurations/general/naming/rules/NAMING.md +179 -0
  67. package/configurations/general/prose/manifest.toml +86 -0
  68. package/configurations/general/prose/rules/WRITING.md +31 -0
  69. package/configurations/general/prose/vale/styles/LICENSES.md +55 -0
  70. package/configurations/general/prose/vale/styles/gspot/ampm.yml +8 -0
  71. package/configurations/general/prose/vale/styles/gspot/conscious-language.yml +16 -0
  72. package/configurations/general/prose/vale/styles/gspot/contractions.yml +43 -0
  73. package/configurations/general/prose/vale/styles/gspot/currency.yml +8 -0
  74. package/configurations/general/prose/vale/styles/gspot/dashes.yml +8 -0
  75. package/configurations/general/prose/vale/styles/gspot/date-ordinals.yml +41 -0
  76. package/configurations/general/prose/vale/styles/gspot/dates.yml +7 -0
  77. package/configurations/general/prose/vale/styles/gspot/file-paths.yml +7 -0
  78. package/configurations/general/prose/vale/styles/gspot/future.yml +17 -0
  79. package/configurations/general/prose/vale/styles/gspot/hedging.yml +22 -0
  80. package/configurations/general/prose/vale/styles/gspot/history.yml +16 -0
  81. package/configurations/general/prose/vale/styles/gspot/idioms.yml +21 -0
  82. package/configurations/general/prose/vale/styles/gspot/interface-verbs.yml +11 -0
  83. package/configurations/general/prose/vale/styles/gspot/jargon.yml +11 -0
  84. package/configurations/general/prose/vale/styles/gspot/leading-conjunctions.yml +12 -0
  85. package/configurations/general/prose/vale/styles/gspot/link-text.yml +8 -0
  86. package/configurations/general/prose/vale/styles/gspot/locations.yml +14 -0
  87. package/configurations/general/prose/vale/styles/gspot/marketing.yml +26 -0
  88. package/configurations/general/prose/vale/styles/gspot/merge-conflict-markers.yml +13 -0
  89. package/configurations/general/prose/vale/styles/gspot/militaristic-language.yml +22 -0
  90. package/configurations/general/prose/vale/styles/gspot/modals.yml +9 -0
  91. package/configurations/general/prose/vale/styles/gspot/numbered-units.yml +18 -0
  92. package/configurations/general/prose/vale/styles/gspot/obvious-fields.yml +14 -0
  93. package/configurations/general/prose/vale/styles/gspot/ordinal-adverbs.yml +15 -0
  94. package/configurations/general/prose/vale/styles/gspot/percentage-numbers.yml +8 -0
  95. package/configurations/general/prose/vale/styles/gspot/placeholders.yml +7 -0
  96. package/configurations/general/prose/vale/styles/gspot/product-centric-writing.yml +8 -0
  97. package/configurations/general/prose/vale/styles/gspot/punctuated-headings.yml +11 -0
  98. package/configurations/general/prose/vale/styles/gspot/self-reference.yml +15 -0
  99. package/configurations/general/prose/vale/styles/gspot/session-identifiers.yml +11 -0
  100. package/configurations/general/prose/vale/styles/gspot/since.yml +6 -0
  101. package/configurations/general/prose/vale/styles/gspot/straight-quotes.yml +11 -0
  102. package/configurations/general/prose/vale/styles/gspot/suspended-hyphens.yml +8 -0
  103. package/configurations/general/prose/vale/styles/gspot/symbols.yml +8 -0
  104. package/configurations/general/prose/vale/styles/gspot/time-ranges.yml +14 -0
  105. package/configurations/general/prose/vale/styles/gspot/url-prepositions.yml +10 -0
  106. package/configurations/general/prose/vale/styles/gspot/version-range.yml +8 -0
  107. package/configurations/general/repository/manifest.toml +24 -0
  108. package/configurations/general/secrets/gitleaks.toml +2 -0
  109. package/configurations/general/secrets/manifest.toml +125 -0
  110. package/configurations/general/secrets/rules/SECRETS.md +13 -0
  111. package/configurations/general/security/manifest.toml +77 -0
  112. package/configurations/general/security/rules/SECURITY.md +55 -0
  113. package/configurations/general/spelling/manifest.toml +46 -0
  114. package/configurations/general/structure/manifest.toml +70 -0
  115. package/configurations/infrastructure/ansible/manifest.toml +33 -0
  116. package/configurations/infrastructure/docker/manifest.toml +127 -0
  117. package/configurations/infrastructure/docker/rules/DOCKER.md +135 -0
  118. package/configurations/infrastructure/docker/trivyignore +2 -0
  119. package/configurations/infrastructure/github-actions/manifest.toml +76 -0
  120. package/configurations/infrastructure/github-actions/rules/GITHUB-ACTIONS.md +43 -0
  121. package/configurations/infrastructure/github-actions/zizmor.yml +3 -0
  122. package/configurations/infrastructure/nginx/manifest.toml +51 -0
  123. package/configurations/infrastructure/nginx/rules/NGINX.md +38 -0
  124. package/configurations/infrastructure/openapi/manifest.toml +50 -0
  125. package/configurations/infrastructure/openapi/rules/OPENAPI.md +39 -0
  126. package/configurations/infrastructure/xcode/manifest.toml +131 -0
  127. package/configurations/infrastructure/xcode/rules/XCODE.md +34 -0
  128. package/configurations/language/bash/manifest.toml +261 -0
  129. package/configurations/language/bash/rules/BASH.md +106 -0
  130. package/configurations/language/bash/rules/LANGUAGE.md +213 -0
  131. package/configurations/language/bash/rules/NAMING.md +62 -0
  132. package/configurations/language/bash/rules/OPERATIONS.md +77 -0
  133. package/configurations/language/bash/rules/SAFETY.md +222 -0
  134. package/configurations/language/bash/semgrep/bash.yml +30 -0
  135. package/configurations/language/css/manifest.toml +98 -0
  136. package/configurations/language/css/rules/CSS.md +28 -0
  137. package/configurations/language/css/rules/NAMING.md +17 -0
  138. package/configurations/language/css/rules/TAILWIND.md +26 -0
  139. package/configurations/language/css/stylelint-rule-names.json +89 -0
  140. package/configurations/language/html/manifest.toml +59 -0
  141. package/configurations/language/html/rules/HTML.md +27 -0
  142. package/configurations/language/html/rules/NAMING.md +16 -0
  143. package/configurations/language/javascript/eslint-presets.json +997 -0
  144. package/configurations/language/javascript/eslint-rule-names.json +299 -0
  145. package/configurations/language/javascript/eslint-runtime-names.json +61 -0
  146. package/configurations/language/javascript/manifest.toml +393 -0
  147. package/configurations/language/javascript/rules/BUN.md +13 -0
  148. package/configurations/language/javascript/rules/COMPONENTS.md +18 -0
  149. package/configurations/language/javascript/rules/DENO.md +15 -0
  150. package/configurations/language/javascript/rules/JAVASCRIPT.md +60 -0
  151. package/configurations/language/javascript/rules/NAMING.md +31 -0
  152. package/configurations/language/javascript/rules/NODE.md +21 -0
  153. package/configurations/language/javascript/rules/PLAYWRIGHT.md +34 -0
  154. package/configurations/language/javascript/semgrep/javascript.yml +84 -0
  155. package/configurations/language/markdown/manifest.toml +85 -0
  156. package/configurations/language/markdown/markdownlint-cli2.mjs +19 -0
  157. package/configurations/language/python/manifest.toml +621 -0
  158. package/configurations/language/python/rules/DESIGN.md +136 -0
  159. package/configurations/language/python/rules/FLOW.md +124 -0
  160. package/configurations/language/python/rules/NAMING.md +53 -0
  161. package/configurations/language/python/rules/PACKAGING.md +49 -0
  162. package/configurations/language/python/rules/PYTHON.md +136 -0
  163. package/configurations/language/python/rules/TYPING.md +132 -0
  164. package/configurations/language/sql/manifest.toml +68 -0
  165. package/configurations/language/sql/rules/NAMING.md +90 -0
  166. package/configurations/language/sql/rules/SQL.md +9 -0
  167. package/configurations/language/swift/manifest.toml +164 -0
  168. package/configurations/language/swift/rules/NAMING.md +88 -0
  169. package/configurations/language/swift/rules/SWIFT.md +134 -0
  170. package/configurations/language/swift/rules/SWIFTUI.md +61 -0
  171. package/configurations/language/swift/rules/UIKIT.md +99 -0
  172. package/configurations/language/swift/semgrep/swift.yml +126 -0
  173. package/configurations/language/typescript/eslint-presets.json +215 -0
  174. package/configurations/language/typescript/manifest.toml +72 -0
  175. package/configurations/language/typescript/rules/NAMING.md +73 -0
  176. package/configurations/language/typescript/rules/TYPESCRIPT.md +79 -0
  177. package/configurations/library/drizzle/manifest.toml +68 -0
  178. package/configurations/library/drizzle/rules/DRIZZLE.md +44 -0
  179. package/configurations/library/react-hook-form/manifest.toml +15 -0
  180. package/configurations/library/react-hook-form/rules/REACT-HOOK-FORM.md +48 -0
  181. package/configurations/library/swift-snapshot-testing/manifest.toml +32 -0
  182. package/configurations/library/tanstack-query/eslint-presets.json +21 -0
  183. package/configurations/library/tanstack-query/manifest.toml +26 -0
  184. package/configurations/library/tanstack-query/rules/TANSTACK-QUERY.md +41 -0
  185. package/configurations/library/testing-library/eslint-presets.json +191 -0
  186. package/configurations/library/testing-library/manifest.toml +47 -0
  187. package/configurations/library/translations/manifest.toml +40 -0
  188. package/configurations/library/translations/rules/NEXT-INTL.md +33 -0
  189. package/configurations/library/translations/rules/TRANSLATIONS.md +102 -0
  190. package/configurations/library/trpc/manifest.toml +14 -0
  191. package/configurations/library/trpc/rules/TRPC.md +43 -0
  192. package/configurations/library/zod/manifest.toml +25 -0
  193. package/configurations/library/zod/rules/ZOD.md +44 -0
  194. package/configurations/library/zustand/manifest.toml +18 -0
  195. package/configurations/library/zustand/rules/ZUSTAND.md +106 -0
  196. package/configurations/platform/cloudflare/manifest.toml +94 -0
  197. package/configurations/platform/cloudflare/rules/CLOUDFLARE.md +23 -0
  198. package/configurations/platform/cloudflare/semgrep/cloudflare.yml +12 -0
  199. package/configurations/platform/supabase/manifest.toml +112 -0
  200. package/configurations/platform/supabase/rules/SUPABASE.md +129 -0
  201. package/configurations/platform/supabase/semgrep/supabase.yml +60 -0
  202. package/configurations/testing/jest/manifest.toml +54 -0
  203. package/configurations/testing/pytest/manifest.toml +53 -0
  204. package/configurations/testing/swift-tests/manifest.toml +52 -0
  205. package/configurations/testing/swift-tests/rules/SWIFT-TESTS.md +79 -0
  206. package/configurations/testing/vitest/eslint-presets.json +22 -0
  207. package/configurations/testing/vitest/manifest.toml +69 -0
  208. package/configurations/testing/vitest/rules/VITEST.md +18 -0
  209. package/dist/LICENSE.md +201 -0
  210. package/dist/THIRD-PARTY-NOTICES.md +25 -0
  211. package/dist/eslint-rule-levels.json +10 -0
  212. package/dist/gspot.js +30740 -0
  213. package/dist/linkinator-program.js +65 -0
  214. package/dist/purgecss-program.js +51 -0
  215. package/dist/tool-versions.json +3 -0
  216. package/grammars/bash.wasm +0 -0
  217. package/grammars/css.wasm +0 -0
  218. package/grammars/html.wasm +0 -0
  219. package/grammars/javascript.wasm +0 -0
  220. package/grammars/licenses/tree-sitter-bash.txt +21 -0
  221. package/grammars/licenses/tree-sitter-css.txt +21 -0
  222. package/grammars/licenses/tree-sitter-html.txt +21 -0
  223. package/grammars/licenses/tree-sitter-javascript.txt +21 -0
  224. package/grammars/licenses/tree-sitter-python.txt +21 -0
  225. package/grammars/licenses/tree-sitter-swift.txt +21 -0
  226. package/grammars/licenses/tree-sitter-typescript.txt +21 -0
  227. package/grammars/python.wasm +0 -0
  228. package/grammars/swift.wasm +0 -0
  229. package/grammars/tsx.wasm +0 -0
  230. package/grammars/typescript.wasm +0 -0
  231. package/gspot.schema.json +45991 -0
  232. package/package.json +93 -5
@@ -0,0 +1,77 @@
1
+ {
2
+ "recommended": {
3
+ "package": "eslint-plugin-react",
4
+ "version": "7.37.5",
5
+ "source": "configs.flat.recommended",
6
+ "blocks": [
7
+ {
8
+ "parser": false,
9
+ "rules": {
10
+ "react/display-name": 2,
11
+ "react/jsx-key": 2,
12
+ "react/jsx-no-comment-textnodes": 2,
13
+ "react/jsx-no-duplicate-props": 2,
14
+ "react/jsx-no-target-blank": 2,
15
+ "react/jsx-no-undef": 2,
16
+ "react/jsx-uses-react": 2,
17
+ "react/jsx-uses-vars": 2,
18
+ "react/no-children-prop": 2,
19
+ "react/no-danger-with-children": 2,
20
+ "react/no-deprecated": 2,
21
+ "react/no-direct-mutation-state": 2,
22
+ "react/no-find-dom-node": 2,
23
+ "react/no-is-mounted": 2,
24
+ "react/no-render-return-value": 2,
25
+ "react/no-string-refs": 2,
26
+ "react/no-unescaped-entities": 2,
27
+ "react/no-unknown-property": 2,
28
+ "react/no-unsafe": 0,
29
+ "react/prop-types": 2,
30
+ "react/react-in-jsx-scope": 2,
31
+ "react/require-render-return": 2
32
+ }
33
+ }
34
+ ]
35
+ },
36
+ "jsx": {
37
+ "package": "eslint-plugin-react",
38
+ "version": "7.37.5",
39
+ "source": "configs.flat.jsx-runtime",
40
+ "blocks": [{ "parser": false, "rules": { "react/react-in-jsx-scope": 0, "react/jsx-uses-react": 0 } }]
41
+ },
42
+ "hooks": {
43
+ "package": "eslint-plugin-react-hooks",
44
+ "version": "7.1.1",
45
+ "source": "configs.flat.recommended-latest",
46
+ "blocks": [
47
+ {
48
+ "parser": false,
49
+ "rules": {
50
+ "react-hooks/rules-of-hooks": "error",
51
+ "react-hooks/exhaustive-deps": "warn",
52
+ "react-hooks/static-components": "error",
53
+ "react-hooks/use-memo": "error",
54
+ "react-hooks/void-use-memo": "error",
55
+ "react-hooks/preserve-manual-memoization": "error",
56
+ "react-hooks/incompatible-library": "warn",
57
+ "react-hooks/immutability": "error",
58
+ "react-hooks/globals": "error",
59
+ "react-hooks/refs": "error",
60
+ "react-hooks/set-state-in-effect": "error",
61
+ "react-hooks/error-boundaries": "error",
62
+ "react-hooks/purity": "error",
63
+ "react-hooks/set-state-in-render": "error",
64
+ "react-hooks/unsupported-syntax": "warn",
65
+ "react-hooks/config": "error",
66
+ "react-hooks/gating": "error"
67
+ }
68
+ }
69
+ ]
70
+ },
71
+ "refresh": {
72
+ "package": "eslint-plugin-react-refresh",
73
+ "version": "0.5.7",
74
+ "source": "configs.recommended",
75
+ "blocks": [{ "parser": false, "rules": { "react-refresh/only-export-components": ["error", {}] } }]
76
+ }
77
+ }
@@ -0,0 +1,93 @@
1
+ allowed_words = ["React"]
2
+
3
+ [configuration]
4
+ title = "React"
5
+ requires = ["javascript"]
6
+ suggests = ["typescript", "css", "react-dom"]
7
+ description = "React components: the recommended React and hooks rules as errors, component files that keep their state on a reload."
8
+
9
+ [detect]
10
+ dependencies = ["react"]
11
+
12
+ [[tool]]
13
+ name = "eslint-plugin-react-hooks"
14
+ rule_prefix = "react-hooks"
15
+ kind = "library"
16
+ version = "7.1.1"
17
+ npm = "eslint-plugin-react-hooks"
18
+
19
+ [[tool]]
20
+ name = "eslint-plugin-react"
21
+ rule_prefix = "react"
22
+ kind = "library"
23
+ version = "7.37.5"
24
+ npm = "eslint-plugin-react"
25
+
26
+ [[tool]]
27
+ name = "eslint-plugin-react-refresh"
28
+ rule_prefix = "react-refresh"
29
+ kind = "library"
30
+ version = "0.5.7"
31
+ npm = "eslint-plugin-react-refresh"
32
+
33
+ [[check]]
34
+ name = "version-pairs"
35
+ example = "Different installed versions of react and react-dom report an alignment finding. Install the same version of both and update the lockfile with the package manager."
36
+ level = "recommended"
37
+ stage = "commit"
38
+ runs = "once"
39
+ summary = "Checks that react and react-dom use the same installed version."
40
+ why = "React and its DOM renderer ship together and expect matching versions."
41
+ help = "Install the same version of react and react-dom."
42
+
43
+ [[naming.override]]
44
+ paths = ["**/*.tsx", "**/*.jsx"]
45
+ categories = ["files"]
46
+ cases = ["pascal", "kebab"]
47
+ reason = "A component file takes the component's name."
48
+
49
+ [[naming.override]]
50
+ paths = ["**/*.tsx", "**/*.jsx"]
51
+ categories = ["functions"]
52
+ cases = ["pascal", "camel"]
53
+ reason = "A function that returns JSX is a component and takes a capital."
54
+
55
+ [[naming.override]]
56
+ paths = ["**"]
57
+ languages = ["typescript", "javascript"]
58
+ categories = ["functions", "methods", "variables"]
59
+ allowed_names = ["useSyncExternalStore", "getSnapshot", "getServerSnapshot"]
60
+ reason = "React defines these subscription and snapshot callback names."
61
+
62
+ [eslint]
63
+ all_level_rules = ["react/self-closing-comp", "react/display-name", "react/no-array-index-key", "react/prop-types"]
64
+
65
+ [eslint.presets.recommended]
66
+ package = "eslint-plugin-react"
67
+ source = "configs.flat.recommended"
68
+
69
+ [eslint.presets.jsx]
70
+ package = "eslint-plugin-react"
71
+ source = "configs.flat.jsx-runtime"
72
+
73
+ [eslint.presets.hooks]
74
+ package = "eslint-plugin-react-hooks"
75
+ source = "configs.flat.recommended-latest"
76
+
77
+ [eslint.presets.refresh]
78
+ package = "eslint-plugin-react-refresh"
79
+ source = "configs.recommended"
80
+
81
+ [[eslint.rules_off]]
82
+ rules = ["gspot/no-trivial-files", "gspot/no-trivial-functions"]
83
+ files = ["**/*.tsx", "**/*.jsx"]
84
+ reason = "React renders a component by its name, so a component of one statement, alone in its file, is the shape React asks for."
85
+
86
+ [defaults]
87
+ "tools.eslint.import_extension" = "extensionless"
88
+
89
+ [[tool_file]]
90
+ target = ".gspot/config/eslint.config.mjs"
91
+ tool = "eslint"
92
+ fragment = true
93
+ required_tools = ["eslint-plugin-react-hooks", "eslint-plugin-react", "eslint-plugin-react-refresh"]
@@ -0,0 +1,108 @@
1
+ # React
2
+
3
+ Rules that hold for any React application: Next.js, Vite, Expo, or a library. The framework file
4
+ adds routing, server components, and caching on top of these.
5
+
6
+ ## Components
7
+
8
+ - A component renders props and state. Data fetching, business rules, and persistence live in
9
+ hooks, server modules, or the query layer, never in the render body.
10
+ - Props have a type beside their component; a component never takes an untyped object.
11
+
12
+ ### Component conventions
13
+
14
+ <!-- level: all -->
15
+
16
+ - Compose downward: a component imports children and shared primitives, never its parent, its
17
+ section, or its route.
18
+ - Domain-neutral primitives such as button, input, dialog, popover, and tooltip live in the shared UI owner
19
+ and take values and callbacks. They never fetch or import a feature.
20
+ - Keep a component small enough that its JSX reads as one screen region. Extract by visual
21
+ responsibility, not by line count.
22
+
23
+ - Keep one primary component per file and name it for what it renders.
24
+ - Declare the props type on the parameter rather than using `React.FC`.
25
+
26
+ ## Hooks
27
+
28
+ - Every custom hook starts with `use` and owns one concern.
29
+ - Memoize such as `useMemo`, `useCallback`, `memo` when a measurement shows expensive work or a
30
+ consumer needs a stable reference, not by default.
31
+
32
+ ## Effects and state
33
+
34
+ - Keep renders pure. Effects synchronize external systems; handlers own user-triggered work. Derive
35
+ ordinary values during render rather than synchronizing duplicate state with effects. Clean up
36
+ timers, observers, subscriptions, animation frames, and requests.
37
+ - Use refs for mutable controller values and state for values displayed in the UI.
38
+
39
+ - Give each state value one owner: URL state for navigation, query cache for server snapshots, form/local
40
+ state for editing, and client store for truly shared client state.
41
+
42
+ - Reset private state across identity and tenant changes; give each request its own server stores.
43
+
44
+ - Handle every promise by awaiting, returning, or explicitly catching failure. A `void` expression
45
+ alone does not handle rejection. Retries need a retry-safe operation and bounded policy.
46
+ Cancellation must not look like confirmed success.
47
+
48
+ ## Read states and writes
49
+
50
+ - Keep the first pending request, an empty result, and a failed request distinct. Show a stable
51
+ fallback, an explanation of the empty result, or safe error and retry UI for the matching state.
52
+ - Keep existing content during a background refresh or a pending next page. A failed refresh does
53
+ not erase a successful result. Revoked access removes stale private content.
54
+ - Capture the resource identity when work starts. A superseded request must not overwrite the
55
+ currently selected resource.
56
+ - An optimistic update defines how to confirm or undo the operation.
57
+ - Present the result of a save separately from the result of a refresh.
58
+
59
+ ## URL state
60
+
61
+ - The URL owns filters, sorting, and other shareable navigation values. It carries a selected,
62
+ versioned representation, never credentials, private drafts, or the whole store.
63
+ - Validate parsed values, and handle missing or malformed input without assertions or an unchecked
64
+ `JSON.parse`.
65
+ - Define the precedence among URL values, stored preferences, and defaults. When the URL owns a
66
+ value, back and forward navigation reach the state owner.
67
+ - One synchronization path compares values before writing, so store-to-URL and URL-to-store updates
68
+ never loop.
69
+ - Keep unrelated query parameters and fragments. Use the installed router or the History API to replace history for transient edits and to push an entry when back navigation restores the previous state.
70
+ - Read hash values only in the browser. Never use them to shape the server-rendered snapshot.
71
+
72
+ ## Hydration and browser synchronization
73
+
74
+ Hydration attaches React behavior to the server-rendered HTML. Give the server and the first browser
75
+ render matching output. Browser storage, viewport dimensions, generated IDs, time zones, current
76
+ time, and random values can make them differ. Define when each value becomes available and how the
77
+ UI updates after hydration. Fix the mismatch instead of hiding warnings globally.
78
+
79
+ - Use deterministic initial props for server-rendered content. Read browser-only state after
80
+ hydration or through a supported external-store pattern.
81
+ - Use stable entity identifiers for data identity and the supported React ID mechanism for
82
+ relationships between controls and labels.
83
+ - Give date/time formatting the same initial locale, time zone, and reference time where relative output otherwise differs.
84
+ - Do not branch rendered markup on `typeof window` as a routine hydration fix. Server and first
85
+ browser output agree on the visible tree.
86
+ - Theme initialization may need the theme library's documented early script and a narrow hydration
87
+ exception. Keep that exception local to the affected node.
88
+ - Do not mutate React-owned DOM to coordinate application state. Controlled state, refs, and
89
+ third-party imperative APIs have explicit ownership boundaries.
90
+ - Treat a hydration warning as a bug until you identify its source and justify an exception. A
91
+ development-only warning can reveal a production race.
92
+
93
+ ## Lists and keys
94
+
95
+ - Use stable IDs for keys, never indices.
96
+ - Virtualize a list only when it can grow without bound. Subscribe to the data each row needs.
97
+
98
+ ## Forms and inputs
99
+
100
+ - Keep each input controlled or uncontrolled, never both. Choose per form and keep it.
101
+ - Validate input against the declared contract and expose its errors to the user. When the application uses a form
102
+ library, use its supported validation and state APIs.
103
+ - A form awaits the save and reports its result.
104
+
105
+ ## Accessibility
106
+
107
+ - Use native interactive elements such as `button`, `a`, and `input`, or give each element the matching role,
108
+ keyboard handling, and focus management.
@@ -0,0 +1,110 @@
1
+ {
2
+ "accessibility": {
3
+ "package": "eslint-plugin-jsx-a11y",
4
+ "version": "6.10.2",
5
+ "source": "flatConfigs.recommended",
6
+ "blocks": [
7
+ {
8
+ "parser": false,
9
+ "rules": {
10
+ "jsx-a11y/alt-text": "error",
11
+ "jsx-a11y/anchor-ambiguous-text": "off",
12
+ "jsx-a11y/anchor-has-content": "error",
13
+ "jsx-a11y/anchor-is-valid": "error",
14
+ "jsx-a11y/aria-activedescendant-has-tabindex": "error",
15
+ "jsx-a11y/aria-props": "error",
16
+ "jsx-a11y/aria-proptypes": "error",
17
+ "jsx-a11y/aria-role": "error",
18
+ "jsx-a11y/aria-unsupported-elements": "error",
19
+ "jsx-a11y/autocomplete-valid": "error",
20
+ "jsx-a11y/click-events-have-key-events": "error",
21
+ "jsx-a11y/control-has-associated-label": [
22
+ "off",
23
+ {
24
+ "ignoreElements": ["audio", "canvas", "embed", "input", "textarea", "tr", "video"],
25
+ "ignoreRoles": [
26
+ "grid",
27
+ "listbox",
28
+ "menu",
29
+ "menubar",
30
+ "radiogroup",
31
+ "row",
32
+ "tablist",
33
+ "toolbar",
34
+ "tree",
35
+ "treegrid"
36
+ ],
37
+ "includeRoles": ["alert", "dialog"]
38
+ }
39
+ ],
40
+ "jsx-a11y/heading-has-content": "error",
41
+ "jsx-a11y/html-has-lang": "error",
42
+ "jsx-a11y/iframe-has-title": "error",
43
+ "jsx-a11y/img-redundant-alt": "error",
44
+ "jsx-a11y/interactive-supports-focus": [
45
+ "error",
46
+ { "tabbable": ["button", "checkbox", "link", "searchbox", "spinbutton", "switch", "textbox"] }
47
+ ],
48
+ "jsx-a11y/label-has-associated-control": "error",
49
+ "jsx-a11y/label-has-for": "off",
50
+ "jsx-a11y/media-has-caption": "error",
51
+ "jsx-a11y/mouse-events-have-key-events": "error",
52
+ "jsx-a11y/no-access-key": "error",
53
+ "jsx-a11y/no-autofocus": "error",
54
+ "jsx-a11y/no-distracting-elements": "error",
55
+ "jsx-a11y/no-interactive-element-to-noninteractive-role": [
56
+ "error",
57
+ { "tr": ["none", "presentation"], "canvas": ["img"] }
58
+ ],
59
+ "jsx-a11y/no-noninteractive-element-interactions": [
60
+ "error",
61
+ {
62
+ "handlers": [
63
+ "onClick",
64
+ "onError",
65
+ "onLoad",
66
+ "onMouseDown",
67
+ "onMouseUp",
68
+ "onKeyPress",
69
+ "onKeyDown",
70
+ "onKeyUp"
71
+ ],
72
+ "alert": ["onKeyUp", "onKeyDown", "onKeyPress"],
73
+ "body": ["onError", "onLoad"],
74
+ "dialog": ["onKeyUp", "onKeyDown", "onKeyPress"],
75
+ "iframe": ["onError", "onLoad"],
76
+ "img": ["onError", "onLoad"]
77
+ }
78
+ ],
79
+ "jsx-a11y/no-noninteractive-element-to-interactive-role": [
80
+ "error",
81
+ {
82
+ "ul": ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"],
83
+ "ol": ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"],
84
+ "li": ["menuitem", "menuitemradio", "menuitemcheckbox", "option", "row", "tab", "treeitem"],
85
+ "table": ["grid"],
86
+ "td": ["gridcell"],
87
+ "fieldset": ["radiogroup", "presentation"]
88
+ }
89
+ ],
90
+ "jsx-a11y/no-noninteractive-tabindex": [
91
+ "error",
92
+ { "tags": [], "roles": ["tabpanel"], "allowExpressionValues": true }
93
+ ],
94
+ "jsx-a11y/no-redundant-roles": "error",
95
+ "jsx-a11y/no-static-element-interactions": [
96
+ "error",
97
+ {
98
+ "allowExpressionValues": true,
99
+ "handlers": ["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"]
100
+ }
101
+ ],
102
+ "jsx-a11y/role-has-required-aria-props": "error",
103
+ "jsx-a11y/role-supports-aria-props": "error",
104
+ "jsx-a11y/scope": "error",
105
+ "jsx-a11y/tabindex-no-positive": "error"
106
+ }
107
+ }
108
+ ]
109
+ }
110
+ }
@@ -0,0 +1,24 @@
1
+ [configuration]
2
+ title = "React DOM"
3
+ requires = ["react"]
4
+ description = "React applications rendered into the DOM: JSX accessibility rules for labels, alternative text, keyboard access, and valid ARIA attributes. Native-only applications retain React without these browser rules."
5
+
6
+ [detect]
7
+ dependencies = ["react-dom"]
8
+
9
+ [[tool]]
10
+ name = "eslint-plugin-jsx-a11y"
11
+ rule_prefix = "jsx-a11y"
12
+ kind = "library"
13
+ version = "6.10.2"
14
+ npm = "eslint-plugin-jsx-a11y"
15
+
16
+ [eslint.presets.accessibility]
17
+ package = "eslint-plugin-jsx-a11y"
18
+ source = "flatConfigs.recommended"
19
+
20
+ [[tool_file]]
21
+ target = ".gspot/config/eslint.config.mjs"
22
+ tool = "eslint"
23
+ fragment = true
24
+ required_tools = ["eslint-plugin-jsx-a11y"]
@@ -0,0 +1,46 @@
1
+ [configuration]
2
+ title = "React Native"
3
+ requires = ["react"]
4
+ suggests = ["typescript"]
5
+ description = "React Native components, styles, and native APIs. Lists use stable keys and virtualized rendering, touch targets use Pressable, and AsyncStorage stores no credentials."
6
+
7
+ [detect]
8
+ dependencies = ["react-native"]
9
+
10
+ [files]
11
+ filenames = ["app.json", "app.config.js", "app.config.ts", "metro.config.js", "eas.json"]
12
+
13
+ [[tool]]
14
+ name = "@react-native/eslint-plugin"
15
+ rule_prefix = "@react-native"
16
+ kind = "library"
17
+ version = "0.87.1"
18
+ npm = "@react-native/eslint-plugin"
19
+
20
+ [[tool]]
21
+ name = "eslint-plugin-react-native"
22
+ rule_prefix = "react-native"
23
+ kind = "library"
24
+ version = "5.0.0"
25
+ npm = "eslint-plugin-react-native"
26
+
27
+ [eslint]
28
+ all_level_rules = ["react-native/no-color-literals", "react-native/no-inline-styles", "react-native/split-platform-components"]
29
+
30
+ [[eslint.selectors]]
31
+ selector = "ImportDeclaration[source.value='react-native'] > ImportSpecifier[imported.name=/^Touchable(Opacity|Highlight|WithoutFeedback|NativeFeedback)$/]"
32
+ message = "Use Pressable. The Touchable components are kept for old code and get no new behavior."
33
+
34
+ [[eslint.selectors]]
35
+ selector = "JSXElement[openingElement.name.name='ScrollView'] > JSXExpressionContainer > CallExpression[callee.property.name='map']"
36
+ message = "A ScrollView renders every row at once. Render a list that grows through FlatList."
37
+
38
+ [[eslint.selectors]]
39
+ selector = "CallExpression[callee.object.name='AsyncStorage'][callee.property.name='setItem'] > Literal:first-child[value=/token|secret|password|credential/i]"
40
+ message = "AsyncStorage is plain text on the device. Keep a secret in the secure store of the platform."
41
+
42
+ [[tool_file]]
43
+ target = ".gspot/config/eslint.config.mjs"
44
+ tool = "eslint"
45
+ fragment = true
46
+ required_tools = ["@react-native/eslint-plugin", "eslint-plugin-react-native"]
@@ -0,0 +1,51 @@
1
+ # React Native
2
+
3
+ These rules cover React Native and Expo apps: components, lists, styles, navigation, native data, and releases.
4
+ The React rules apply first. These add what a phone changes.
5
+
6
+ ## Components and touch
7
+
8
+ - Give every touch target a size of at least 44 points on iOS or 48 dp on Android, with `hitSlop` where the drawing takes less space.
9
+ - Do not read `Dimensions` at module load. Use `useWindowDimensions`, which follows rotation and split view.
10
+ - Respect the safe area on every screen, through the safe area context.
11
+
12
+ ## Lists
13
+
14
+ - Keep `renderItem` and the row component stable: define them outside the render, or memoize them.
15
+ - Give a list of fixed row height `getItemLayout`, so it scrolls to an index without measuring.
16
+
17
+ ## Styles
18
+
19
+ - Build layouts that adapt to the available screen size and font scale.
20
+
21
+ ### Style conventions
22
+
23
+ <!-- level: all -->
24
+
25
+ - Branch on `Platform.OS` in one place for one concern. Split a component full of platform checks into two components.
26
+
27
+ ## Navigation and state
28
+
29
+ - Type the route parameters of every screen, and pass ids through them, not whole objects.
30
+ - A screen loads its own data from the id it receives.
31
+ - Do not keep server data in a global store by hand. Use a query cache that knows about refetching and staleness.
32
+ - Stop a subscription, a timer, and a listener when the screen loses focus or unmounts.
33
+
34
+ ## Native data and secrets
35
+
36
+ - The bundle holds no secret. A key that ships in the app belongs to everyone who downloads it.
37
+ - Ask for a permission at the moment the feature needs it, and handle the refusal.
38
+ - Validate a deep link before it navigates or acts. A link supplies input from outside.
39
+
40
+ ## Performance
41
+
42
+ - Keep work off the JavaScript thread during a gesture or an animation. Run animations on the native driver or the UI thread.
43
+ - Size an image to the box it fills, and cache remote images.
44
+ - Do not log in a hot path, and strip console output from a release build.
45
+ - Tell the user to measure on a low-end Android device in a release build.
46
+
47
+ ## Releases
48
+
49
+ - Version the native build and the JavaScript bundle together, and know which bundles a given native build accepts.
50
+ - An over-the-air update never changes native code or a permission.
51
+ - Tell the user to check the upgrade path from the last release with its stored data.