@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,79 @@
1
+ # TypeScript
2
+
3
+ TypeScript checks static types. JavaScript and runtime rules cover modules and execution.
4
+
5
+ ## Philosophy
6
+
7
+ TypeScript makes types explicit at compile time. Plain values, small functions, discriminated
8
+ unions, and clear modules keep types easier to read than elaborate type transformations.
9
+
10
+ ## Files and modules
11
+
12
+ Diagnostics and process termination stay at executable boundaries. Check the effective lint
13
+ configuration for a path before assuming a rule. Follow the project's arrangement for types
14
+ and constants. Infer schema types from their authored schemas.
15
+
16
+ ## Values and shapes
17
+
18
+ `as const` fixes a value set when it improves precision without obscuring
19
+ the runtime shape. Represent grouped data with an object literal. Annotate rather than cast when the type matters,
20
+ and destructure where that names the fields in use. `T[]` serves
21
+ arrays and `Array<T>` or `ReadonlyArray<T>` complex element types; `readonly` marks a
22
+ contract, not decoration. With `noUncheckedIndexedAccess`, an indexed read can have no value;
23
+ narrow it before use.
24
+
25
+ Use `unknown` plus narrowing for untrusted values. Casts give way to runtime narrowing, typed
26
+ helpers, or fixing the source type.
27
+ Represent known variants with discriminated unions.
28
+
29
+ Describe absence precisely: `property?: T` and
30
+ `property: T | undefined` define different types under `exactOptionalPropertyTypes`. A
31
+ nullable alias gets a name only when the domain defines the union. Add nullability
32
+ where the public interface allows absence. Normalize external empty strings,
33
+ missing fields, and nulls where they enter the program.
34
+
35
+ ## Functions and classes
36
+
37
+ Annotate callback parameters when inference does not give a clear type, rely on inference for local details,
38
+ and keep generics minimal. A discriminated union or options object replaces overloads when
39
+ clearer. Make a parameter optional only for an optional input.
40
+
41
+ ## Errors and async work
42
+
43
+ `Promise.all` serves bounded independent fan-out. Order, rate limits, or failure isolation
44
+ call for sequential `await`. Large fan-out, provider calls, and batch work use platform
45
+ concurrency utilities. Detach a promise only deliberately. Log and supervise it; never swallow a rejection.
46
+
47
+ This fragment uses the message and provider types, persistence functions, and lock operations
48
+ that their modules declare.
49
+
50
+ ```ts
51
+ // Bad: forEach does not wait for async callbacks.
52
+ messages.forEach(async (message) => {
53
+ await persistMessage(message);
54
+ });
55
+
56
+ // Good: the caller waits for all writes to finish.
57
+ await Promise.all(messages.map((message) => persistMessage(message)));
58
+
59
+ /**
60
+ * Run a provider operation and release its lock on success or failure.
61
+ * @param request the provider operation to submit
62
+ * @returns the provider's result
63
+ * @throws wraps a provider failure while preserving its cause
64
+ */
65
+ export async function createProviderOperation(request: ProviderOperationRequest): Promise<ProviderOperationResult> {
66
+ try {
67
+ return await postProviderOperation(request);
68
+ } catch (error) {
69
+ throw new Error('Provider operation failed.', { cause: error });
70
+ } finally {
71
+ releaseOperationLock(request.operationId);
72
+ }
73
+ }
74
+ ```
75
+
76
+ ## Comments
77
+
78
+ Comments document purpose, invariants, security boundaries, concurrency behavior, and runtime
79
+ assumptions. Do not restate TypeScript syntax or code.
@@ -0,0 +1,68 @@
1
+ allowed_words = ["Drizzle"]
2
+
3
+ [configuration]
4
+ title = "Drizzle"
5
+ requires = ["javascript"]
6
+ description = "Drizzle: no update or delete without a where, raw SQL only where the settings allow it, relations for every reference, and migrations that match the schema."
7
+
8
+ [detect]
9
+ dependencies = ["drizzle-orm"]
10
+
11
+ [[tool]]
12
+ name = "eslint-plugin-drizzle"
13
+ rule_prefix = "drizzle"
14
+ kind = "library"
15
+ version = "0.2.3"
16
+ npm = "eslint-plugin-drizzle"
17
+
18
+ [[tool]]
19
+ name = "drizzle-kit"
20
+ install_hint = "Run: npm install --save-dev drizzle-kit"
21
+ system = true
22
+ version_command = ["--version"]
23
+ min_version = "0.21.0"
24
+ npm = "drizzle-kit"
25
+
26
+ [[check]]
27
+ name = "relations"
28
+ example = "An exported `orders` table whose column uses `.references(() => users.id)` reports `relations` when the scope has no `relations(orders, ...)` declaration. Add that declaration with the table's actual relationships and rerun. The check recognizes the supported source forms; it does not execute the schema."
29
+ level = "all"
30
+ stage = "commit"
31
+ runs = "scope"
32
+ summary = "Checks that every table with a reference has a relations entry."
33
+ why = "Relational queries through `db.query` read relations. SQL joins do not need them."
34
+ help = "Add a relations call for the table."
35
+
36
+ [check.files]
37
+ extensions = [".ts"]
38
+
39
+ [[check]]
40
+ name = "stale-migrations"
41
+ command = ["drizzle-kit", "generate"]
42
+ example = "Changing a Drizzle schema without generating its migration reports drift. Run `drizzle-kit generate` with the project configuration, inspect the new migration, and retain it before rerunning."
43
+ level = "recommended"
44
+ stage = "push"
45
+ runs = "scope"
46
+ tool = "drizzle-kit"
47
+ summary = "Asks drizzle-kit to write migrations, and fails when it writes one."
48
+ why = "A schema change with no migration works on the machine that pushed the schema and nowhere else."
49
+ help = "Run drizzle-kit generate and commit the migration."
50
+
51
+ [[check.generated_paths]]
52
+ pattern = "**/*"
53
+
54
+ [check.files]
55
+ paths = ["drizzle.config.ts", "drizzle.config.js", "drizzle.config.mts", "drizzle.config.mjs", "drizzle.config.cts", "drizzle.config.cjs"]
56
+
57
+ [rules."DRIZZLE.md"]
58
+ dependencies = ["pg", "postgres"]
59
+
60
+ [[eslint.selectors]]
61
+ selector = "TaggedTemplateExpression[tag.name='sql']"
62
+ message = "Raw SQL skips the types of the schema. Use the query builder, or accept this finding with a rule-specific ignore."
63
+
64
+ [[tool_file]]
65
+ target = ".gspot/config/eslint.config.mjs"
66
+ tool = "eslint"
67
+ fragment = true
68
+ required_tools = ["eslint-plugin-drizzle"]
@@ -0,0 +1,44 @@
1
+ # Drizzle
2
+
3
+ These decisions cover Drizzle with PostgreSQL. Use the adapter and APIs of the installed release.
4
+ Supabase connection and identity decisions remain in the Supabase rules.
5
+
6
+ ## Connections and schema ownership
7
+
8
+ Construct one bounded server-side pool with a clear lifetime. Close a script's connection in
9
+ cleanup, not a shared pool after each query. Budget across instances and keep request identity
10
+ out of shared client state. Schema modules create no connection and run no migration.
11
+
12
+ Database constraints protect every writer. Inferred types, `$type<T>()`, and `sql<T>` validate
13
+ nothing at runtime. Relations assemble results; foreign keys and uniqueness enforce integrity.
14
+ Drizzle-only defaults and update callbacks do not cover another writer. Choose database defaults
15
+ or triggers when the contract must cover every write path.
16
+
17
+ See [column types](https://orm.drizzle.team/docs/column-types)
18
+ and [relations](https://orm.drizzle.team/docs/relations).
19
+
20
+ ## Authorized operations
21
+
22
+ Select only the fields the caller may see. Apply resource and tenant restrictions in the query or
23
+ an enforced policy. A row identifier proves no permission, and an inferred insert type permits
24
+ fields a public request must not set. Keep public schemas apart from persistence types.
25
+
26
+ Scope writes to the authorized resource and verify affected rows. Bound growing collections and
27
+ use deterministic ordering with a unique tie-breaker. An absent filter differs from zero or false.
28
+ Use a version predicate or an atomic expression for concurrent updates.
29
+
30
+ See [queries](https://orm.drizzle.team/docs/select).
31
+
32
+ ## Transactions and migrations
33
+
34
+ Pass `tx` to every participating operation and await it before the transaction returns. Keep
35
+ network calls and irreversible effects outside. Retry only bounded serialization failures or
36
+ deadlocks, and publish success or invalidation after commit. Use a durable outbox when an external
37
+ effect must follow the commit.
38
+
39
+ Review generated SQL for unintended drops, renames, constraints, grants, row level security (RLS), and provider-owned
40
+ objects. Keep one authoritative migration history; push schema changes only in disposable local
41
+ experiments. Reads that must observe a write or current permissions stay on the primary.
42
+
43
+ See [transactions](https://orm.drizzle.team/docs/transactions)
44
+ and [migrations](https://orm.drizzle.team/docs/migrations).
@@ -0,0 +1,15 @@
1
+ [configuration]
2
+ title = "React Hook Form"
3
+ requires = ["javascript"]
4
+ description = "React Hook Form: a form validates through a resolver, and a registered field is not also controlled."
5
+
6
+ [detect]
7
+ dependencies = ["react-hook-form"]
8
+
9
+ [[eslint.selectors]]
10
+ selector = "CallExpression[callee.name='useForm']:not(:has(Property[key.name='resolver']))"
11
+ message = "Give useForm a resolver, so the schema that types the form also validates it."
12
+
13
+ [[eslint.selectors]]
14
+ selector = "JSXOpeningElement:has(JSXSpreadAttribute CallExpression[callee.name=register]):has(JSXAttribute[name.name=value]):not(:has([name.name=type]>[value=/^(checkbox|radio)$/]))"
15
+ message = "Drop value or use Controller."
@@ -0,0 +1,48 @@
1
+ # React Hook Form
2
+
3
+ ## Form ownership and validation
4
+
5
+ - One `useForm` instance owns a form. Use `FormProvider` when nested fields need that instance;
6
+ never create a second form owner for the same submission.
7
+ - The resolver owns schema validation. Keep coercion and validation in that path rather than
8
+ maintaining competing rules in fields and submit handlers.
9
+ - Initialize `defaultValues` with the form's complete starting values. Reset deliberately when the
10
+ edited record changes; an incoming background response must not discard a user's changes.
11
+ - An input uses either `register` or `Controller`. A controlled widget forwards the controller's
12
+ value, change handler, blur handler, ref, and disabled state through its supported interface.
13
+ - Subscribe through `useWatch` or `useFormState` near the consumer instead of making the entire form
14
+ rerender for every field. `getValues` reads a snapshot rather than subscribing.
15
+ - Conditional fields distinguish hidden values that remain part of the submission from values that
16
+ need removal. The schema follows that choice.
17
+
18
+ ## Field arrays
19
+
20
+ - Give each field array one `useFieldArray` owner. Use `field.id` as the React key and the current
21
+ index in a registered path. Store database identity in a separate property.
22
+ - Treat `fields` as row structure. Read live values through the form's value APIs.
23
+ - Add complete rows. Use a leaf `setValue` when an update must preserve the mounted row's focus and
24
+ widget state; `update` remounts the row.
25
+ - Keep one form owner across wizard steps. Validate a step before advancing and the whole payload
26
+ before the final submission.
27
+
28
+ ## Submission and errors
29
+
30
+ - The submit handler awaits the real save. Pending state lasts until that operation settles;
31
+ starting a request and returning early makes `isSubmitting` misleading.
32
+ - Report field errors beside their fields and form errors at the form boundary. Keep entered values
33
+ after a failed save so the user can correct or retry them.
34
+ - A save captures the edited record's identity. Its late result must not reset a different record.
35
+ - When the project uses TanStack Query, await `mutateAsync` when submission needs the mutation result.
36
+ Handle its rejection in the form's error path.
37
+ - When the project uses Next.js Server Actions, await the action and map its returned validation or
38
+ save result into the form's error state.
39
+ - When the project uses an internationalization library, pass error messages through that library's
40
+ message API rather than constructing translated sentences from fragments.
41
+
42
+ ## References
43
+
44
+ - [useForm](https://react-hook-form.com/docs/useform)
45
+ - [Resolvers](https://github.com/react-hook-form/resolvers)
46
+ - [Controller](https://react-hook-form.com/docs/usecontroller/controller)
47
+ - [useFieldArray](https://react-hook-form.com/docs/usefieldarray)
48
+ - [handleSubmit](https://react-hook-form.com/docs/useform/handlesubmit)
@@ -0,0 +1,32 @@
1
+ [configuration]
2
+ title = "Swift Snapshot Testing"
3
+ requires = ["swift"]
4
+ description = "SnapshotTesting comparisons keep recording disabled and retain references only while their test source exists."
5
+
6
+ [detect]
7
+ dependencies = ["swift-snapshot-testing"]
8
+
9
+ [files]
10
+ paths = ["**/*.swift", "**/__Snapshots__/**"]
11
+ kinds = ["source", "binary"]
12
+
13
+ [[check]]
14
+ name = "recording"
15
+ example = "A snapshot test left in recording mode reports a recording finding. Inspect and retain the intended reference images, remove the recording flag, and rerun in comparison mode."
16
+ level = "recommended"
17
+ stage = "commit"
18
+ files = { tags = ["swift-test"] }
19
+ summary = "Refuses a snapshot test left in a recording mode."
20
+ why = "A recording test writes a new reference and passes, so it approves whatever the screen shows."
21
+ help = "Take the recording flag out, and commit the references it wrote after looking at them."
22
+
23
+ [[check]]
24
+ name = "references"
25
+ example = "A snapshot reference folder whose corresponding test file no longer exists reports unused references. Delete the unused references, or rename the folder to match the renamed test file."
26
+ level = "all"
27
+ stage = "commit"
28
+ runs = "scope"
29
+ files = { paths = ["**/*"], kinds = ["source", "binary"] }
30
+ summary = "Checks that __Snapshots__ reference folders name a sibling Swift test file."
31
+ why = "References of a deleted test stay in the repository, and every clone pays for them."
32
+ help = "Delete the references of the test that is gone, or rename the folder after the test file."
@@ -0,0 +1,21 @@
1
+ {
2
+ "recommended": {
3
+ "package": "@tanstack/eslint-plugin-query",
4
+ "version": "5.91.2",
5
+ "source": "configs.flat/recommended",
6
+ "blocks": [
7
+ {
8
+ "parser": false,
9
+ "rules": {
10
+ "@tanstack/query/exhaustive-deps": "error",
11
+ "@tanstack/query/no-rest-destructuring": "warn",
12
+ "@tanstack/query/stable-query-client": "error",
13
+ "@tanstack/query/no-unstable-deps": "error",
14
+ "@tanstack/query/infinite-query-property-order": "error",
15
+ "@tanstack/query/no-void-query-fn": "error",
16
+ "@tanstack/query/mutation-property-order": "error"
17
+ }
18
+ }
19
+ ]
20
+ }
21
+ }
@@ -0,0 +1,26 @@
1
+ allowed_words = ["TanStack"]
2
+
3
+ [configuration]
4
+ title = "TanStack Query"
5
+ requires = ["javascript"]
6
+ description = "TanStack Query: the query rules of ESLint for dependency lists, stable clients, and query options in order."
7
+
8
+ [detect]
9
+ dependencies = ["@tanstack/react-query", "@tanstack/query-core", "@tanstack/vue-query", "@tanstack/svelte-query", "@tanstack/solid-query", "@tanstack/angular-query-experimental"]
10
+
11
+ [[tool]]
12
+ name = "@tanstack/eslint-plugin-query"
13
+ rule_prefix = "@tanstack/query"
14
+ kind = "library"
15
+ version = "5.91.2"
16
+ npm = "@tanstack/eslint-plugin-query"
17
+
18
+ [eslint.presets.recommended]
19
+ package = "@tanstack/eslint-plugin-query"
20
+ source = "configs.flat/recommended"
21
+
22
+ [[tool_file]]
23
+ target = ".gspot/config/eslint.config.mjs"
24
+ tool = "eslint"
25
+ fragment = true
26
+ required_tools = ["@tanstack/eslint-plugin-query"]
@@ -0,0 +1,41 @@
1
+ # TanStack Query
2
+
3
+ Use the integration and release the project has. Query data stays in its cache; do not copy it
4
+ into a second store to share it with another component.
5
+
6
+ ## Ownership and identity
7
+
8
+ Create a server QueryClient per request and keep the browser client stable across rerenders and
9
+ initial suspension. Clear or partition private state when identity or tenant changes. A late
10
+ response must not refill the next session's cache.
11
+
12
+ Include every result-changing input in the key. Give list previews, detail records, and infinite
13
+ pages different identities. When the project uses tRPC, use its generated options and key factories.
14
+ Keep prefetch and consumption on the same keys and serialization contract; dehydrate no private data.
15
+
16
+ See [server rendering and hydration](https://tanstack.com/query/latest/docs/framework/react/guides/advanced-ssr).
17
+
18
+ ## Writes and recovery
19
+
20
+ Apply a save result to the resource captured when the save started, not the current selection.
21
+ An optimistic rollback reverses only its own change; restoring a whole snapshot can erase a newer
22
+ success. Reconcile with the committed response, then invalidate affected lists and aggregates.
23
+ A committed write stays successful when its refresh fails.
24
+
25
+ Required cache updates belong to code that receives every completion, not a per-call callback
26
+ that can disappear on unmount. Retry a write only under an idempotency contract.
27
+
28
+ See [optimistic updates](https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates).
29
+
30
+ ## Display and freshness
31
+
32
+ Distinguish first load, background refresh, and next-page loading. Keep useful data visible during
33
+ a refresh and expose its failure separately. A placeholder supplies display data, not a record ready
34
+ for editing. Reset placeholders and pagination when identity or filters change.
35
+
36
+ Choose freshness from the resource's risk. Never disable refetching globally to conceal duplicate
37
+ requests. Keep permission and account state out of static caches. Preserve both `pages` and
38
+ `pageParams` when changing an infinite query.
39
+
40
+ See [query defaults](https://tanstack.com/query/latest/docs/framework/react/guides/important-defaults)
41
+ and [infinite queries](https://tanstack.com/query/latest/docs/framework/react/guides/infinite-queries).
@@ -0,0 +1,191 @@
1
+ {
2
+ "dom": {
3
+ "package": "eslint-plugin-testing-library",
4
+ "version": "7.16.2",
5
+ "source": "configs.flat/dom",
6
+ "blocks": [
7
+ {
8
+ "parser": false,
9
+ "rules": {
10
+ "testing-library/await-async-events": ["error", { "eventModule": "userEvent" }],
11
+ "testing-library/await-async-queries": "error",
12
+ "testing-library/await-async-utils": "error",
13
+ "testing-library/no-await-sync-events": ["error", { "eventModules": ["fire-event"] }],
14
+ "testing-library/no-await-sync-queries": "error",
15
+ "testing-library/no-global-regexp-flag-in-query": "error",
16
+ "testing-library/no-node-access": "error",
17
+ "testing-library/no-promise-in-fire-event": "error",
18
+ "testing-library/no-wait-for-multiple-assertions": "error",
19
+ "testing-library/no-wait-for-side-effects": "error",
20
+ "testing-library/no-wait-for-snapshot": "error",
21
+ "testing-library/prefer-find-by": "error",
22
+ "testing-library/prefer-presence-queries": "error",
23
+ "testing-library/prefer-query-by-disappearance": "error",
24
+ "testing-library/prefer-screen-queries": "error"
25
+ }
26
+ }
27
+ ]
28
+ },
29
+ "angular": {
30
+ "package": "eslint-plugin-testing-library",
31
+ "version": "7.16.2",
32
+ "source": "configs.flat/angular",
33
+ "blocks": [
34
+ {
35
+ "parser": false,
36
+ "rules": {
37
+ "testing-library/await-async-events": ["error", { "eventModule": "userEvent" }],
38
+ "testing-library/await-async-queries": "error",
39
+ "testing-library/await-async-utils": "error",
40
+ "testing-library/no-await-sync-events": ["error", { "eventModules": ["fire-event"] }],
41
+ "testing-library/no-await-sync-queries": "error",
42
+ "testing-library/no-container": "error",
43
+ "testing-library/no-debugging-utils": "warn",
44
+ "testing-library/no-dom-import": ["error", "angular"],
45
+ "testing-library/no-global-regexp-flag-in-query": "error",
46
+ "testing-library/no-node-access": "error",
47
+ "testing-library/no-promise-in-fire-event": "error",
48
+ "testing-library/no-render-in-lifecycle": "error",
49
+ "testing-library/no-wait-for-multiple-assertions": "error",
50
+ "testing-library/no-wait-for-side-effects": "error",
51
+ "testing-library/no-wait-for-snapshot": "error",
52
+ "testing-library/prefer-find-by": "error",
53
+ "testing-library/prefer-presence-queries": "error",
54
+ "testing-library/prefer-query-by-disappearance": "error",
55
+ "testing-library/prefer-screen-queries": "error",
56
+ "testing-library/render-result-naming-convention": "error"
57
+ }
58
+ }
59
+ ]
60
+ },
61
+ "react": {
62
+ "package": "eslint-plugin-testing-library",
63
+ "version": "7.16.2",
64
+ "source": "configs.flat/react",
65
+ "blocks": [
66
+ {
67
+ "parser": false,
68
+ "rules": {
69
+ "testing-library/await-async-events": ["error", { "eventModule": "userEvent" }],
70
+ "testing-library/await-async-queries": "error",
71
+ "testing-library/await-async-utils": "error",
72
+ "testing-library/no-await-sync-events": ["error", { "eventModules": ["fire-event"] }],
73
+ "testing-library/no-await-sync-queries": "error",
74
+ "testing-library/no-container": "error",
75
+ "testing-library/no-debugging-utils": "warn",
76
+ "testing-library/no-dom-import": ["error", "react"],
77
+ "testing-library/no-global-regexp-flag-in-query": "error",
78
+ "testing-library/no-manual-cleanup": "error",
79
+ "testing-library/no-node-access": "error",
80
+ "testing-library/no-promise-in-fire-event": "error",
81
+ "testing-library/no-render-in-lifecycle": "error",
82
+ "testing-library/no-unnecessary-act": "error",
83
+ "testing-library/no-wait-for-multiple-assertions": "error",
84
+ "testing-library/no-wait-for-side-effects": "error",
85
+ "testing-library/no-wait-for-snapshot": "error",
86
+ "testing-library/prefer-find-by": "error",
87
+ "testing-library/prefer-presence-queries": "error",
88
+ "testing-library/prefer-query-by-disappearance": "error",
89
+ "testing-library/prefer-screen-queries": "error",
90
+ "testing-library/render-result-naming-convention": "error"
91
+ }
92
+ }
93
+ ]
94
+ },
95
+ "vue": {
96
+ "package": "eslint-plugin-testing-library",
97
+ "version": "7.16.2",
98
+ "source": "configs.flat/vue",
99
+ "blocks": [
100
+ {
101
+ "parser": false,
102
+ "rules": {
103
+ "testing-library/await-async-events": ["error", { "eventModule": ["fireEvent", "userEvent"] }],
104
+ "testing-library/await-async-queries": "error",
105
+ "testing-library/await-async-utils": "error",
106
+ "testing-library/no-await-sync-queries": "error",
107
+ "testing-library/no-container": "error",
108
+ "testing-library/no-debugging-utils": "warn",
109
+ "testing-library/no-dom-import": ["error", "vue"],
110
+ "testing-library/no-global-regexp-flag-in-query": "error",
111
+ "testing-library/no-manual-cleanup": "error",
112
+ "testing-library/no-node-access": "error",
113
+ "testing-library/no-promise-in-fire-event": "error",
114
+ "testing-library/no-render-in-lifecycle": "error",
115
+ "testing-library/no-wait-for-multiple-assertions": "error",
116
+ "testing-library/no-wait-for-side-effects": "error",
117
+ "testing-library/no-wait-for-snapshot": "error",
118
+ "testing-library/prefer-find-by": "error",
119
+ "testing-library/prefer-presence-queries": "error",
120
+ "testing-library/prefer-query-by-disappearance": "error",
121
+ "testing-library/prefer-screen-queries": "error",
122
+ "testing-library/render-result-naming-convention": "error"
123
+ }
124
+ }
125
+ ]
126
+ },
127
+ "svelte": {
128
+ "package": "eslint-plugin-testing-library",
129
+ "version": "7.16.2",
130
+ "source": "configs.flat/svelte",
131
+ "blocks": [
132
+ {
133
+ "parser": false,
134
+ "rules": {
135
+ "testing-library/await-async-events": ["error", { "eventModule": ["fireEvent", "userEvent"] }],
136
+ "testing-library/await-async-queries": "error",
137
+ "testing-library/await-async-utils": "error",
138
+ "testing-library/no-await-sync-queries": "error",
139
+ "testing-library/no-container": "error",
140
+ "testing-library/no-debugging-utils": "warn",
141
+ "testing-library/no-dom-import": ["error", "svelte"],
142
+ "testing-library/no-global-regexp-flag-in-query": "error",
143
+ "testing-library/no-manual-cleanup": "error",
144
+ "testing-library/no-node-access": "error",
145
+ "testing-library/no-promise-in-fire-event": "error",
146
+ "testing-library/no-render-in-lifecycle": "error",
147
+ "testing-library/no-wait-for-multiple-assertions": "error",
148
+ "testing-library/no-wait-for-side-effects": "error",
149
+ "testing-library/no-wait-for-snapshot": "error",
150
+ "testing-library/prefer-find-by": "error",
151
+ "testing-library/prefer-presence-queries": "error",
152
+ "testing-library/prefer-query-by-disappearance": "error",
153
+ "testing-library/prefer-screen-queries": "error",
154
+ "testing-library/render-result-naming-convention": "error"
155
+ }
156
+ }
157
+ ]
158
+ },
159
+ "marko": {
160
+ "package": "eslint-plugin-testing-library",
161
+ "version": "7.16.2",
162
+ "source": "configs.flat/marko",
163
+ "blocks": [
164
+ {
165
+ "parser": false,
166
+ "rules": {
167
+ "testing-library/await-async-events": ["error", { "eventModule": ["fireEvent", "userEvent"] }],
168
+ "testing-library/await-async-queries": "error",
169
+ "testing-library/await-async-utils": "error",
170
+ "testing-library/no-await-sync-queries": "error",
171
+ "testing-library/no-container": "error",
172
+ "testing-library/no-debugging-utils": "warn",
173
+ "testing-library/no-dom-import": ["error", "marko"],
174
+ "testing-library/no-global-regexp-flag-in-query": "error",
175
+ "testing-library/no-node-access": "error",
176
+ "testing-library/no-promise-in-fire-event": "error",
177
+ "testing-library/no-render-in-lifecycle": "error",
178
+ "testing-library/no-unnecessary-act": "error",
179
+ "testing-library/no-wait-for-multiple-assertions": "error",
180
+ "testing-library/no-wait-for-side-effects": "error",
181
+ "testing-library/no-wait-for-snapshot": "error",
182
+ "testing-library/prefer-find-by": "error",
183
+ "testing-library/prefer-presence-queries": "error",
184
+ "testing-library/prefer-query-by-disappearance": "error",
185
+ "testing-library/prefer-screen-queries": "error",
186
+ "testing-library/render-result-naming-convention": "error"
187
+ }
188
+ }
189
+ ]
190
+ }
191
+ }
@@ -0,0 +1,47 @@
1
+ [configuration]
2
+ title = "Testing Library"
3
+ requires = ["javascript"]
4
+ description = "Testing Library rules over test files of projects that declare a Testing Library dependency."
5
+
6
+ [detect]
7
+ dependencies = ["@testing-library/*"]
8
+
9
+ [[tool]]
10
+ name = "eslint-plugin-testing-library"
11
+ rule_prefix = "testing-library"
12
+ kind = "library"
13
+ version = "7.16.2"
14
+ npm = "eslint-plugin-testing-library"
15
+
16
+ [eslint]
17
+ all_level_rules = ["testing-library/no-container", "testing-library/no-node-access", "testing-library/no-render-in-lifecycle", "testing-library/prefer-screen-queries", "testing-library/render-result-naming-convention"]
18
+
19
+ [eslint.presets.dom]
20
+ package = "eslint-plugin-testing-library"
21
+ source = "configs.flat/dom"
22
+
23
+ [eslint.presets.angular]
24
+ package = "eslint-plugin-testing-library"
25
+ source = "configs.flat/angular"
26
+
27
+ [eslint.presets.react]
28
+ package = "eslint-plugin-testing-library"
29
+ source = "configs.flat/react"
30
+
31
+ [eslint.presets.vue]
32
+ package = "eslint-plugin-testing-library"
33
+ source = "configs.flat/vue"
34
+
35
+ [eslint.presets.svelte]
36
+ package = "eslint-plugin-testing-library"
37
+ source = "configs.flat/svelte"
38
+
39
+ [eslint.presets.marko]
40
+ package = "eslint-plugin-testing-library"
41
+ source = "configs.flat/marko"
42
+
43
+ [[tool_file]]
44
+ target = ".gspot/config/eslint.config.mjs"
45
+ tool = "eslint"
46
+ fragment = true
47
+ required_tools = ["eslint-plugin-testing-library"]