@sarj/eslint-plugin 10.0.0 → 11.0.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.
- package/README.md +30 -356
- package/dist/index.cjs +64 -64
- package/dist/index.d.cts +65 -65
- package/dist/index.d.ts +65 -65
- package/dist/index.js +64 -64
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,375 +1,49 @@
|
|
|
1
1
|
# @sarj/eslint-plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Deterministic ESLint rules and presets for TypeScript, React, and modern Node.js
|
|
4
|
+
applications. The plugin complements ESLint's core and TypeScript ESLint rules;
|
|
5
|
+
it does not duplicate them.
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
`assert(...)` calls. A disabled assertion leaves a collected test passing while
|
|
7
|
-
verifying nothing. JSDoc and assertion examples introduced by prose remain
|
|
8
|
-
exempt, as do active assertions.
|
|
7
|
+
## Use
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
`middleware.ts` and `proxy.ts` matcher configuration. Next.js reads these values
|
|
14
|
-
during static analysis, so identifiers, calls, concatenation, interpolated
|
|
15
|
-
templates, and spreads can pass type checking but fail the production build.
|
|
16
|
-
|
|
17
|
-
Custom ESLint rules for hypermodern TypeScript / React / Next.js projects.
|
|
18
|
-
|
|
19
|
-
```bash
|
|
20
|
-
pnpm add -D @sarj/eslint-plugin
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
```js
|
|
24
|
-
// eslint.config.mjs
|
|
25
|
-
import sarj from "@sarj/eslint-plugin";
|
|
26
|
-
export default [sarj.configs.recommended];
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
66 rules. Each source under `src/rules/` states one concise claim and links to
|
|
30
|
-
its paired tests. The definition and named test cases are the complete rule
|
|
31
|
-
specification, and `meta.docs.url` points directly to those executable examples.
|
|
32
|
-
|
|
33
|
-
Presets: `recommended` (warn-first), `strict` (every general-profile rule at its declared strict severity), `style-guide` (formatting/naming subset). Application-only rules are exported through `applicationOnlyRules` and configured by the application profile. The two-sentence comment rule warns; its three-sentence companion errors.
|
|
34
|
-
|
|
35
|
-
## New in 9.8.0 — application library policy adapters
|
|
36
|
-
|
|
37
|
-
`no-restricted-library-load` extends a configured dependency policy to runtime
|
|
38
|
-
loading forms that ESLint's `no-restricted-imports` does not cover: literal
|
|
39
|
-
`import()`, unshadowed `require()` / `require.resolve()`, and TypeScript
|
|
40
|
-
`import x = require(...)`. It matches a package and all of its subpaths, but
|
|
41
|
-
deliberately ignores computed names and shadowed local `require` functions.
|
|
42
|
-
|
|
43
|
-
`prefer-native-random-uuid` reports resolved, zero-argument UUID v4 calls from
|
|
44
|
-
the `uuid` package and suggests `globalThis.crypto.randomUUID()`. The suggestion
|
|
45
|
-
changes only the call; import cleanup remains explicit. Other UUID versions,
|
|
46
|
-
custom-randomness arguments, re-exports, and function references are untouched.
|
|
47
|
-
|
|
48
|
-
Neither rule is in the general presets. The application profile configures them
|
|
49
|
-
for its Node 22.13+ runtime contract and supplies catalog entries to the loader
|
|
50
|
-
rule:
|
|
51
|
-
|
|
52
|
-
```js
|
|
53
|
-
rules: {
|
|
54
|
-
"@sarj/no-restricted-library-load": [
|
|
55
|
-
"error",
|
|
56
|
-
{
|
|
57
|
-
libraries: [
|
|
58
|
-
{
|
|
59
|
-
id: "LIB101",
|
|
60
|
-
module: "axios",
|
|
61
|
-
replacement: "Ky",
|
|
62
|
-
note: "The APIs are not drop-in equivalents.",
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
"@sarj/prefer-native-random-uuid": "error",
|
|
68
|
-
}
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
## Renamed in 7.0.0, aliases deleted in 9.0.0 (breaking)
|
|
72
|
-
|
|
73
|
-
| Old name | New name |
|
|
74
|
-
| --- | --- |
|
|
75
|
-
| `@sarj/jsdoc-restates-signature` | `@sarj/no-restated-jsdoc` |
|
|
76
|
-
| `@sarj/no-async-callback-in-waitfor` | `@sarj/no-async-callback-in-wait-for` |
|
|
77
|
-
| `@sarj/strict-test-assertions` | `@sarj/prefer-whole-object-assertion` |
|
|
78
|
-
| `@sarj/trailing-value-narration` | `@sarj/no-trailing-value-narration` |
|
|
79
|
-
|
|
80
|
-
7.0.0 kept each old name registered as a deprecated alias. 9.0.0 deletes them, so
|
|
81
|
-
the new names are the only names — and an old name left in a config, an
|
|
82
|
-
`eslint-disable` comment or a suppressions baseline now makes ESLint exit 2 with
|
|
83
|
-
`Could not find "@sarj/<rule>" in plugin "@sarj"` before it reads a file.
|
|
84
|
-
|
|
85
|
-
Run `sarj-lint-configs doctor` before upgrading: it reads the shipped rule ledger
|
|
86
|
-
and names every file holding an old name, with the replacement. The map is also
|
|
87
|
-
exported for codemods:
|
|
88
|
-
|
|
89
|
-
```js
|
|
90
|
-
import { renamedRules } from "@sarj/eslint-plugin";
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
The rename map and migration behavior live in
|
|
94
|
-
[`src/rules/_renames.ts`](src/rules/_renames.ts) and its tests.
|
|
95
|
-
|
|
96
|
-
## New in 4.1.0 — `no-hand-rolled-sleep`
|
|
97
|
-
|
|
98
|
-
`new Promise((resolve) => setTimeout(resolve, ms))` is `node:timers/promises`'s
|
|
99
|
-
`setTimeout` rewritten by hand, minus the `AbortSignal` — so it is a capability
|
|
100
|
-
loss, not verbosity. The hand-rolled sleep holds a live timer that nothing can
|
|
101
|
-
clear, and its mirror image, the `Promise.race([work, rejectAfter(ms)])` timeout
|
|
102
|
-
arm, leaks the timer the other way: when `work` wins, nothing clears it and it
|
|
103
|
-
keeps the event loop alive until it fires.
|
|
104
|
-
|
|
105
|
-
Shipped only after confirming nothing already enabled reports this position. The
|
|
106
|
-
enabled set was resolved with `ESLint#calculateConfigForFile` against the shipped
|
|
107
|
-
`eslint.strict.mjs` (204 rules before this one) and a file containing every
|
|
108
|
-
shape was linted through it: no report. `eslint-plugin-unicorn` 72 has no
|
|
109
|
-
promisified-timer rule among its 341; `unicorn/prefer-abort-signal-timeout` covers the
|
|
110
|
-
`AbortController` + `setTimeout` idiom and not the race arm; core
|
|
111
|
-
`no-promise-executor-return` fires on the concise-arrow spelling only and its
|
|
112
|
-
remedy ("add braces") entrenches the hand-rolled sleep. The polling-loop variant
|
|
113
|
-
(`while (!done) await sleep(ms)`) is deliberately absent — core `no-await-in-loop`
|
|
114
|
-
is already enabled and reports that exact position.
|
|
115
|
-
|
|
116
|
-
Measured over 1,471 files containing `setTimeout` across 15 OSS repos (hono,
|
|
117
|
-
tRPC, drizzle-orm, undici, vitest, got, cal.com, documenso, dub, formbricks,
|
|
118
|
-
midday, openstatus, papermark, unkey, zod) and seven internal ones: 85 + 11
|
|
119
|
-
sleeps and 2 + 1 leaky race arms at the default settings, **0 false positives**.
|
|
120
|
-
|
|
121
|
-
`checkClientModules` is the option that matters. A browser or React Native
|
|
122
|
-
bundle cannot import `node:timers/promises` and the web platform ships no
|
|
123
|
-
equivalent, so client modules are skipped by default — 79% of the internal
|
|
124
|
-
corpus's occurrences live in `.tsx` components where the fix cannot be applied.
|
|
125
|
-
Turn it on only in a tree where every file resolves `node:` builtins. The race
|
|
126
|
-
message is reported everywhere regardless: `AbortSignal.timeout` is on the web
|
|
127
|
-
platform too.
|
|
128
|
-
|
|
129
|
-
| Rule | What it catches | Preset |
|
|
130
|
-
|---|---|---|
|
|
131
|
-
| `no-hand-rolled-spinner` | Intrinsic elements styled as Tailwind border-ring loading spinners outside the design system. | error / error |
|
|
132
|
-
| `prefer-input-group-search` | Search icons and shared Input controls composed without the shared InputGroup primitive. | error / error |
|
|
133
|
-
| `prefer-shadcn-primitives` | Deterministically visible raw JSX controls used instead of shared shadcn primitives. Unknown and hidden input types are excluded. | application profile: warn |
|
|
134
|
-
| `require-static-next-matcher` | Dynamic values in exported Next.js middleware and proxy matcher configuration. | error / error |
|
|
135
|
-
| `no-hand-rolled-sleep` | `new Promise((r) => setTimeout(r, ms))` in any spelling, and an uncleared `Promise.race`/`Promise.any` timeout arm. Options: `checkClientModules` (default `false`), `allowIn`. | warn / error |
|
|
136
|
-
|
|
137
|
-
`prefer-shadcn-primitives` is application-only because generic plugin consumers
|
|
138
|
-
may use another design system or intentionally expose native controls. It starts
|
|
139
|
-
at warning with 53 measured adoption findings across four application-profile
|
|
140
|
-
consumers; two additional consumers are clean. Promote it only after those
|
|
141
|
-
findings are removed, and keep it disabled inside `components/ui` and
|
|
142
|
-
`components/design-system`, where shared primitives must wrap native elements.
|
|
143
|
-
|
|
144
|
-
## New in 2.14.0 — `no-tautological-expect`
|
|
145
|
-
|
|
146
|
-
The TS half of SARJ057. An `expect(...)` whose operands are all literals has
|
|
147
|
-
already decided its outcome before the test runs — `expect(true).toBe(true)`
|
|
148
|
-
passes if you delete the module under test.
|
|
149
|
-
|
|
150
|
-
Python has caught the assertion-*free* test since 0.15.0 (`SARJ043
|
|
151
|
-
zero-assertion-test`) and had no TypeScript counterpart, which is exactly how
|
|
152
|
-
`expect(true).toBe(true); // placeholder` survived in an internal suite named for
|
|
153
|
-
the behaviour it was supposed to check: the file *has* an assertion, so nothing
|
|
154
|
-
was looking at it.
|
|
155
|
-
|
|
156
|
-
| Rule | What it catches | Preset |
|
|
157
|
-
|---|---|---|
|
|
158
|
-
| `no-tautological-expect` | `expect(<literal>).toBe/toEqual/toStrictEqual(<textually identical literal>)`, and `expect(<literal>).toBeDefined()/toBeTruthy()/toBeNull()/…` — a zero-argument matcher on a literal receiver. | warn / error |
|
|
159
|
-
|
|
160
|
-
**The narrowness is the rule.** The obvious generalisation — "flag a comparison
|
|
161
|
-
of a thing with itself" — measures ~95% false positives:
|
|
162
|
-
`expect(hash([o])).toEqual(hash([o]))` is a *determinism* test,
|
|
163
|
-
`expect(memo(x)).toBe(memo(x))` a *memoization* test, `expect(a).toEqual(a)` on a
|
|
164
|
-
value with custom equality a *reflexivity* test. All three can genuinely fail. So
|
|
165
|
-
an identifier, member-expression or call operand is never enough: both sides must
|
|
166
|
-
be literals, and textually identical ones. A modified chain (`.not`, `.resolves`,
|
|
167
|
-
`.rejects`), a spread, an interpolated template literal, and two *different*
|
|
168
|
-
literals are all left alone.
|
|
169
|
-
|
|
170
|
-
Measured before shipping: **3 hits across 5,819 `.ts`/`.tsx` files** (1,003 of
|
|
171
|
-
them test files, where the rule is active) — six internal repos plus `got`,
|
|
172
|
-
`hono`, `swr` and `trpc`. 3 true positives, **0 false positives**; every hit is
|
|
173
|
-
an abandoned placeholder.
|
|
174
|
-
|
|
175
|
-
## New in 2.13.0 — the anti-comment-verbosity family
|
|
176
|
-
|
|
177
|
-
From a 37,918-comment, nine-repo measurement study. All three are
|
|
178
|
-
deletion-class, so each was validated against zod / swr / zustand / TanStack
|
|
179
|
-
Query as well as the maintained repos. Each paired test suite records the
|
|
180
|
-
false-positive shapes guarded by the implementation.
|
|
181
|
-
|
|
182
|
-
| Rule | What it catches | Preset |
|
|
183
|
-
|---|---|---|
|
|
184
|
-
| `no-restated-comment` | A single-line comment whose every content word already appears on the statement below it. Defers to `no-comment-cruft` for the verb-led shape, so a comment is never reported twice. | warn / error |
|
|
185
|
-
| `no-restated-jsdoc` | A JSDoc block whose description and `@param`/`@returns` only re-spell the signature. Offers a delete SUGGESTION, never an auto-`--fix`. | warn / error |
|
|
186
|
-
| `no-trailing-value-narration` | `staleTime: 5 * 60 * 1000, // 5 minutes` — the unit belongs in the name, where it cannot drift. | warn / error |
|
|
187
|
-
| `no-declaration-comment-wall` | The same judgement for an ENUM BODY or a CLASS BODY, which the rule below structurally cannot see. | warn / error |
|
|
188
|
-
| `no-union-in-comment` | `kind: string; // 'pending' \| 'approved'` — the comment IS the union; write it as one so the compiler enforces it. | warn / error |
|
|
189
|
-
| `no-type-member-comment-wall` | An object type whose member comments mostly re-spell the members' own names and types — the VOLUME arm of the family, reported once for the type. | warn / error |
|
|
190
|
-
|
|
191
|
-
## New in 2.9.0
|
|
192
|
-
|
|
193
|
-
Both distilled from two years of PR-review comments across ~1,065 PRs.
|
|
194
|
-
|
|
195
|
-
| Rule | What it catches | Preset |
|
|
196
|
-
|---|---|---|
|
|
197
|
-
| `no-zod-native-enum` | `z.nativeEnum(...)` and `z.enum(SomeTsEnum)` — the schema-layer back door around `no-enum`. Autofixes an inline string-literal object to `z.enum([...])`. | warn / error |
|
|
198
|
-
| `prefer-zod-enum` | `z.union([z.literal("a"), z.literal("b")])` — autofixes closed string choices to the shorter, equivalent `z.enum(["a", "b"])`. | warn / error |
|
|
199
|
-
| `prefer-zod-infer` | An `interface`/`type` that restates a Zod schema declared in the same module instead of deriving it with `z.infer`. Options: `ignoreTypeNames`, `requireIdenticalShape` (default `true`). | warn / error |
|
|
200
|
-
| `prefer-module-level-constant` | A literal-only `const` collection (array, object, `Set`, `Map`, `Object.freeze`) or non-global regex declared inside a function body, never mutated and never escaping — hoist it to module scope. Options: `minElements` (default 3), `checkRegex`, `ignoreTestFiles`. | warn / error |
|
|
201
|
-
| `prefer-module-level-schema` | A Zod schema built inside a function body that closes over nothing the function owns — hoist it to module scope instead of rebuilding it per call, per request, per render. Silent when it references a parameter, local, type parameter, local type, or `this` (that is a schema FACTORY), when it is already memoized, and inside `z.lazy`. Options: `factories` (default: the object-like composites), `minProperties` (default 1), `ignoreTestFiles`. | warn / error |
|
|
202
|
-
| `prefer-non-nullable-collection` | A required array property or direct alias explicitly combined with `null`/`undefined`, creating two equivalent empty states. Optional API fields are excluded because omission can be meaningful. | warn / error |
|
|
203
|
-
|
|
204
|
-
## Options
|
|
205
|
-
|
|
206
|
-
### Declare your logger (`loggerNames` / `logFunctions`)
|
|
207
|
-
|
|
208
|
-
Three rules decide whether a call writes to a log sink: `no-log-only-catch`,
|
|
209
|
-
`no-sentinel-return-on-catch`, `no-secret-in-log`. Out of the box they recognise
|
|
210
|
-
a log method on a logger *receiver* (`console.error`, `logger.warn`,
|
|
211
|
-
`this.logger.info`). A structured logger is usually a free *function* taking a
|
|
212
|
-
meta object, which has no receiver — declare it once and all of them see it:
|
|
9
|
+
Sarj repositories should let `sarj-standards setup` install the tested peer set
|
|
10
|
+
and generate the integration. Direct ESLint consumers can install the package
|
|
11
|
+
and select a preset:
|
|
213
12
|
|
|
214
13
|
```js
|
|
215
|
-
const logging = { logFunctions: ["logEvent"], loggerNames: ["obs"] };
|
|
216
|
-
|
|
217
|
-
rules: {
|
|
218
|
-
"@sarj/no-log-only-catch": ["error", logging],
|
|
219
|
-
"@sarj/no-sentinel-return-on-catch": ["error", logging],
|
|
220
|
-
"@sarj/no-secret-in-log": ["error", logging],
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
- `logFunctions` — free functions (or methods) that log: `logEvent("x", { err })`.
|
|
225
|
-
- `loggerNames` — extra logger *receiver* names, added to the built-in set.
|
|
226
|
-
|
|
227
|
-
This suppresses "swallows the error without logging it" on a correctly-logged
|
|
228
|
-
degraded return, and — importantly — makes `no-secret-in-log` inspect those
|
|
229
|
-
calls, which it could not do before: `logEvent("slack.auth", { botToken })` was
|
|
230
|
-
previously never examined.
|
|
231
|
-
|
|
232
|
-
### `zod-naming-convention`: `convention`
|
|
233
|
-
|
|
234
|
-
`"either"` (default) accepts both the `Z`-prefix (`ZUser`) and the `Schema`
|
|
235
|
-
suffix (`userSchema`) — the two conventions `require-zod-form-validation`
|
|
236
|
-
already recognises. Set `"prefix"` or `"suffix"` to pin one:
|
|
237
|
-
|
|
238
|
-
```js
|
|
239
|
-
"@sarj/zod-naming-convention": ["error", { convention: "suffix" }]
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### `prefer-zod-infer`: `requireIdenticalShape` / `ignoreTypeNames`
|
|
243
|
-
|
|
244
|
-
By default the rule only reports a type whose members match its schema's keys
|
|
245
|
-
one for one — same names, same optionality, same nullability, no `.transform()`
|
|
246
|
-
anywhere in the pair. On a 30,759-file, 17-repo sweep that is 5 reports and 5
|
|
247
|
-
true positives. Drop the shape comparison to report on name correlation alone
|
|
248
|
-
(8 reports on the same corpus, 1 of them noise, and it catches twins that have
|
|
249
|
-
already drifted):
|
|
250
|
-
|
|
251
|
-
```js
|
|
252
|
-
"@sarj/prefer-zod-infer": ["error", { requireIdenticalShape: false }]
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
`ignoreTypeNames` takes regex sources matched against the declared type name,
|
|
256
|
-
for the pair that is genuinely meant to be maintained by hand:
|
|
257
|
-
|
|
258
|
-
```js
|
|
259
|
-
"@sarj/prefer-zod-infer": ["error", { ignoreTypeNames: ["^LegacyUser$"] }]
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### `prefer-string-literal-union`: `ignoreFields`
|
|
263
|
-
|
|
264
|
-
Field names whose value set is owned by a vendor and genuinely open (a Slack
|
|
265
|
-
`event.subtype`, a Resend `bounceType`). Narrowing to a union you don't control
|
|
266
|
-
would be wrong, not better:
|
|
267
|
-
|
|
268
|
-
```js
|
|
269
|
-
"@sarj/prefer-string-literal-union": ["warn", { ignoreFields: ["subtype", "bounceType"] }]
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### `no-enum`: `ignoreFiles`
|
|
273
|
-
|
|
274
|
-
Glob patterns whose files opt out (generated code already opts out by default).
|
|
275
|
-
|
|
276
|
-
## Configurable rules
|
|
277
|
-
|
|
278
|
-
Most rules take no options. These do, because they encode a codebase's
|
|
279
|
-
architecture rather than a language fact — the defaults describe one convention
|
|
280
|
-
and every repo gets to name its own.
|
|
281
|
-
|
|
282
|
-
| Rule | Option | Default | Effect |
|
|
283
|
-
|---|---|---|---|
|
|
284
|
-
| `no-raw-fetch-outside-clients` | `allow` | client / vendor-wrapper path patterns | Extra files exempt from the "no bare `fetch`" rule (test files are exempt unconditionally) |
|
|
285
|
-
| `no-dynamic-sql` | `methods` | `["prepare", "exec", "query"]` | Statement-taking methods to inspect |
|
|
286
|
-
| `no-storage-in-stateless-modules` | `modules` | `[]` (rule off) | Directories declared stateless |
|
|
287
|
-
| `no-storage-in-stateless-modules` | `methods` | `["prepare", "put", "getWithMetadata"]` | Storage methods to flag |
|
|
288
|
-
| `no-hand-rolled-sleep` | `checkClientModules` | `false` | Also report the sleep form in browser/React Native modules |
|
|
289
|
-
| `no-hand-rolled-sleep` | `allowIn` | `[]` | Glob patterns for a sanctioned sleep wrapper module |
|
|
290
|
-
|
|
291
|
-
The path options on the first three rules are **regular-expression sources
|
|
292
|
-
matched against the absolute filename**, not globs — so they can express both
|
|
293
|
-
path separators. Test files no longer need to appear there: the rule delegates
|
|
294
|
-
to the shared `isTestFile` predicate, so supplying `allow` replaces only the
|
|
295
|
-
production exemptions and cannot accidentally un-exempt a test tree.
|
|
296
|
-
`allowIn` is the exception, on `no-hand-rolled-sleep` as on
|
|
297
|
-
`require-fetch-timeout`: it takes minimatch-ish **globs**, also matched against
|
|
298
|
-
the absolute path, so anchor them with a `**/` prefix. Supplying an option
|
|
299
|
-
**replaces** the default rather than extending it.
|
|
300
|
-
|
|
301
|
-
`no-storage-in-stateless-modules` is a **no-op until `modules` is set**. The
|
|
302
|
-
method names alone (`put`, `prepare`) carry no type information, so the rule is
|
|
303
|
-
only meaningful once it is pointed at the directories a team has actually
|
|
304
|
-
declared stateless.
|
|
305
|
-
|
|
306
|
-
```js
|
|
307
|
-
// eslint.config.mjs
|
|
308
14
|
import sarj from "@sarj/eslint-plugin";
|
|
309
15
|
|
|
310
16
|
export default [
|
|
311
17
|
sarj.configs.strict,
|
|
312
|
-
{
|
|
313
|
-
rules: {
|
|
314
|
-
// This repo keeps its HTTP layer in `lib/api/`, not `clients/`.
|
|
315
|
-
"@sarj/no-raw-fetch-outside-clients": [
|
|
316
|
-
"error",
|
|
317
|
-
{ allow: ["[\\\\/]lib[\\\\/]api[\\\\/]"] },
|
|
318
|
-
],
|
|
319
|
-
// Declare which modules must stay stateless.
|
|
320
|
-
"@sarj/no-storage-in-stateless-modules": [
|
|
321
|
-
"error",
|
|
322
|
-
{ modules: ["[\\\\/]engineer-digest[\\\\/]"] },
|
|
323
|
-
],
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
18
|
];
|
|
327
|
-
```
|
|
328
19
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
anything useful.
|
|
333
|
-
|
|
334
|
-
`no-generic-single-export-module` warns when a `utils`, `helpers`, `common`,
|
|
335
|
-
`constants`, or similarly generic module has one runtime export that already
|
|
336
|
-
provides a precise filename. Ambiguous re-exports, type-only modules,
|
|
337
|
-
conventional framework filenames, tests, generated files, and CommonJS modules
|
|
338
|
-
are excluded. It is warning-first while corpus evidence accumulates.
|
|
20
|
+
// For staged adoption:
|
|
21
|
+
// export default [sarj.configs.recommended];
|
|
22
|
+
```
|
|
339
23
|
|
|
340
|
-
`
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
and disables `perfectionist/sort-classes`, avoiding contradictory owners. The
|
|
344
|
-
rule resolves module helpers, private methods, recursion and cycles, but leaves
|
|
345
|
-
function-valued private fields and mutable receiver aliases alone.
|
|
24
|
+
Available presets are `recommended` for staged adoption and `strict` for the
|
|
25
|
+
full general policy. Application-only rules are exported separately because
|
|
26
|
+
they depend on an explicit runtime and library policy.
|
|
346
27
|
|
|
347
|
-
`
|
|
348
|
-
|
|
349
|
-
hook-style, interface, function-type, declaration and abstract-method returns.
|
|
350
|
-
The runtime alternative is a named object. Private/local implementation helpers
|
|
351
|
-
and sequence-shaped arrays remain outside the public-boundary rule.
|
|
28
|
+
Use `sarj-standards show peers` for the tested ESLint and parser dependency set.
|
|
29
|
+
Do not combine independent `latest` versions and assume they are compatible.
|
|
352
30
|
|
|
353
|
-
##
|
|
31
|
+
## Rules and suppressions
|
|
354
32
|
|
|
355
|
-
|
|
33
|
+
Every rule is registered in `src/index.ts`; its source under `src/rules/` and
|
|
34
|
+
paired test under `tests/rules/` are the authoritative specification. Run
|
|
35
|
+
`sarj-standards show rules` for the current machine-readable catalog.
|
|
356
36
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
| `no-secret-in-log` | SARJ012 | Credentials persisted into log sinks. |
|
|
361
|
-
| `store-insert-requires-on-conflict` | SARJ018 | Duplicate rows — or unique-constraint failures that re-trigger the handler — when a cron re-runs or a queue message is redelivered. |
|
|
362
|
-
| `no-select-star` | SARJ021 | An implicit row contract that changes silently when a column is added or reordered. |
|
|
363
|
-
| `no-offset-pagination` | SARJ025 | O(N)-per-page scans, and rows repeated or skipped when the offset window shifts under concurrent inserts. |
|
|
364
|
-
| `no-repeated-string-literal` | SARJ024 | Copies of a structured literal (SQL, column lists, prompt templates) drifting apart when only one is edited. |
|
|
365
|
-
| `no-positional-tuple-return` | SARJ026 | Public APIs exposing multi-field tuples—even labelled or hook-style tuples—instead of named objects. |
|
|
366
|
-
| `no-sleep-in-test-body` | SARJ031 | Tests that assert on wall-clock time and flake under CI load. |
|
|
367
|
-
| `no-fat-try-blocks` | SARJ007 | Over-broad `catch` handlers swallowing unrelated failures. |
|
|
368
|
-
| `no-cors-wildcard-with-credentials` | SARJ008 | Credentialed cross-origin requests from any origin. |
|
|
369
|
-
| `single-public-export` | SARJ022 | Modules with no single obvious entry point. |
|
|
370
|
-
| `stepdown` | SARJ023 | A private helper placed above its only direct same-scope caller. Indirect references, callbacks, cycles, overloads, and multi-caller helpers are excluded. |
|
|
371
|
-
| `prefer-string-literal-union` | SARJ006 | An open `string` where a closed set is intended. |
|
|
37
|
+
Prefer the smallest line-scoped `eslint-disable-next-line @sarj/rule-name`
|
|
38
|
+
suppression and explain why the exceptional code is intentional. Unknown or
|
|
39
|
+
retired rule names are configuration errors.
|
|
372
40
|
|
|
373
|
-
|
|
41
|
+
New rules must prove that upstream ESLint and TypeScript ESLint cannot express
|
|
42
|
+
the policy and must pass focused tests plus the repository corpus evaluation
|
|
43
|
+
described in the root contribution guide.
|
|
374
44
|
|
|
375
|
-
|
|
45
|
+
Renamed rules fail closed. Replace `jsdoc-restates-signature` with
|
|
46
|
+
`no-restated-jsdoc`, `no-async-callback-in-waitfor` with
|
|
47
|
+
`no-async-callback-in-wait-for`, `strict-test-assertions` with
|
|
48
|
+
`prefer-whole-object-assertion`, and `trailing-value-narration` with
|
|
49
|
+
`no-trailing-value-narration`.
|
package/dist/index.cjs
CHANGED
|
@@ -12382,7 +12382,7 @@ var rules = {
|
|
|
12382
12382
|
};
|
|
12383
12383
|
var meta = {
|
|
12384
12384
|
name: "@sarj/eslint-plugin",
|
|
12385
|
-
version: "
|
|
12385
|
+
version: "11.0.1"
|
|
12386
12386
|
};
|
|
12387
12387
|
var applicationOnlyRules = [
|
|
12388
12388
|
"no-restricted-library-load",
|
|
@@ -12390,68 +12390,68 @@ var applicationOnlyRules = [
|
|
|
12390
12390
|
"prefer-shadcn-primitives"
|
|
12391
12391
|
];
|
|
12392
12392
|
var recommendedRules = {
|
|
12393
|
-
"@sarj/duplicate-test-body": "
|
|
12394
|
-
"@sarj/enforce-file-structure": "
|
|
12395
|
-
"@sarj/no-async-callback-in-wait-for": "
|
|
12396
|
-
"@sarj/no-client-side-data-fetching": "
|
|
12397
|
-
"@sarj/no-comment-cruft": "
|
|
12398
|
-
"@sarj/no-conditional-in-test": "
|
|
12399
|
-
"@sarj/no-cors-wildcard-with-credentials": "
|
|
12400
|
-
"@sarj/no-dynamic-sql": "
|
|
12401
|
-
"@sarj/no-fat-try-blocks": "
|
|
12402
|
-
"@sarj/no-hand-rolled-sleep": "
|
|
12393
|
+
"@sarj/duplicate-test-body": "error",
|
|
12394
|
+
"@sarj/enforce-file-structure": "error",
|
|
12395
|
+
"@sarj/no-async-callback-in-wait-for": "error",
|
|
12396
|
+
"@sarj/no-client-side-data-fetching": "error",
|
|
12397
|
+
"@sarj/no-comment-cruft": "error",
|
|
12398
|
+
"@sarj/no-conditional-in-test": "error",
|
|
12399
|
+
"@sarj/no-cors-wildcard-with-credentials": "error",
|
|
12400
|
+
"@sarj/no-dynamic-sql": "error",
|
|
12401
|
+
"@sarj/no-fat-try-blocks": "error",
|
|
12402
|
+
"@sarj/no-hand-rolled-sleep": "error",
|
|
12403
12403
|
"@sarj/no-hand-rolled-spinner": "error",
|
|
12404
|
-
"@sarj/no-insecure-random-id": "
|
|
12405
|
-
"@sarj/no-json-stringify-error": "
|
|
12406
|
-
"@sarj/no-log-only-catch": "
|
|
12407
|
-
"@sarj/no-long-comment": "
|
|
12408
|
-
"@sarj/no-generic-single-export-module": "
|
|
12409
|
-
"@sarj/no-offset-pagination": "
|
|
12410
|
-
"@sarj/no-positional-tuple-return": "
|
|
12411
|
-
"@sarj/no-repeated-string-literal": "
|
|
12412
|
-
"@sarj/no-restated-comment": "
|
|
12413
|
-
"@sarj/no-restated-jsdoc": "
|
|
12414
|
-
"@sarj/no-secret-in-log": "
|
|
12415
|
-
"@sarj/no-select-star": "
|
|
12416
|
-
"@sarj/no-sentinel-return-on-catch": "
|
|
12417
|
-
"@sarj/no-silent-promise-catch": "
|
|
12418
|
-
"@sarj/no-sleep-in-test-body": "
|
|
12419
|
-
"@sarj/no-string-concat-in-loop": "
|
|
12420
|
-
"@sarj/no-tautological-expect": "
|
|
12421
|
-
"@sarj/no-typed-doc-sections": "
|
|
12422
|
-
"@sarj/no-trailing-value-narration": "
|
|
12423
|
-
"@sarj/no-declaration-comment-wall": "
|
|
12424
|
-
"@sarj/no-union-in-comment": "
|
|
12425
|
-
"@sarj/no-type-member-comment-wall": "
|
|
12426
|
-
"@sarj/no-unnecessary-use-client": "
|
|
12427
|
-
"@sarj/no-unsafe-mock-casting": "
|
|
12428
|
-
"@sarj/no-zod-native-enum": "
|
|
12429
|
-
"@sarj/test-loops-over-literal-cases": "
|
|
12404
|
+
"@sarj/no-insecure-random-id": "error",
|
|
12405
|
+
"@sarj/no-json-stringify-error": "error",
|
|
12406
|
+
"@sarj/no-log-only-catch": "error",
|
|
12407
|
+
"@sarj/no-long-comment": "error",
|
|
12408
|
+
"@sarj/no-generic-single-export-module": "error",
|
|
12409
|
+
"@sarj/no-offset-pagination": "error",
|
|
12410
|
+
"@sarj/no-positional-tuple-return": "error",
|
|
12411
|
+
"@sarj/no-repeated-string-literal": "error",
|
|
12412
|
+
"@sarj/no-restated-comment": "error",
|
|
12413
|
+
"@sarj/no-restated-jsdoc": "error",
|
|
12414
|
+
"@sarj/no-secret-in-log": "error",
|
|
12415
|
+
"@sarj/no-select-star": "error",
|
|
12416
|
+
"@sarj/no-sentinel-return-on-catch": "error",
|
|
12417
|
+
"@sarj/no-silent-promise-catch": "error",
|
|
12418
|
+
"@sarj/no-sleep-in-test-body": "error",
|
|
12419
|
+
"@sarj/no-string-concat-in-loop": "error",
|
|
12420
|
+
"@sarj/no-tautological-expect": "error",
|
|
12421
|
+
"@sarj/no-typed-doc-sections": "error",
|
|
12422
|
+
"@sarj/no-trailing-value-narration": "error",
|
|
12423
|
+
"@sarj/no-declaration-comment-wall": "error",
|
|
12424
|
+
"@sarj/no-union-in-comment": "error",
|
|
12425
|
+
"@sarj/no-type-member-comment-wall": "error",
|
|
12426
|
+
"@sarj/no-unnecessary-use-client": "error",
|
|
12427
|
+
"@sarj/no-unsafe-mock-casting": "error",
|
|
12428
|
+
"@sarj/no-zod-native-enum": "error",
|
|
12429
|
+
"@sarj/test-loops-over-literal-cases": "error",
|
|
12430
12430
|
"@sarj/prefer-constant-time-secret-compare": "error",
|
|
12431
|
-
"@sarj/prefer-discriminated-union": "
|
|
12431
|
+
"@sarj/prefer-discriminated-union": "error",
|
|
12432
12432
|
"@sarj/prefer-input-group-search": "error",
|
|
12433
|
-
"@sarj/prefer-immutable-module-constant": "
|
|
12434
|
-
"@sarj/prefer-module-level-constant": "
|
|
12435
|
-
"@sarj/prefer-module-level-schema": "
|
|
12436
|
-
"@sarj/prefer-non-nullable-collection": "
|
|
12437
|
-
"@sarj/prefer-schema-for-api-payload": "
|
|
12438
|
-
"@sarj/prefer-semantic-colors": ["
|
|
12439
|
-
"@sarj/prefer-server-actions": "
|
|
12440
|
-
"@sarj/prefer-string-literal-union": "
|
|
12441
|
-
"@sarj/prefer-whole-object-assertion": "
|
|
12442
|
-
"@sarj/prefer-zod-enum": "
|
|
12443
|
-
"@sarj/prefer-zod-infer": "
|
|
12444
|
-
"@sarj/require-assert-never": "
|
|
12445
|
-
"@sarj/require-fetch-timeout": "
|
|
12446
|
-
"@sarj/require-interface-for-injected-service": "
|
|
12433
|
+
"@sarj/prefer-immutable-module-constant": "error",
|
|
12434
|
+
"@sarj/prefer-module-level-constant": "error",
|
|
12435
|
+
"@sarj/prefer-module-level-schema": "error",
|
|
12436
|
+
"@sarj/prefer-non-nullable-collection": "error",
|
|
12437
|
+
"@sarj/prefer-schema-for-api-payload": "error",
|
|
12438
|
+
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
12439
|
+
"@sarj/prefer-server-actions": "error",
|
|
12440
|
+
"@sarj/prefer-string-literal-union": "error",
|
|
12441
|
+
"@sarj/prefer-whole-object-assertion": "error",
|
|
12442
|
+
"@sarj/prefer-zod-enum": "error",
|
|
12443
|
+
"@sarj/prefer-zod-infer": "error",
|
|
12444
|
+
"@sarj/require-assert-never": "error",
|
|
12445
|
+
"@sarj/require-fetch-timeout": "error",
|
|
12446
|
+
"@sarj/require-interface-for-injected-service": "error",
|
|
12447
12447
|
"@sarj/require-static-next-matcher": "error",
|
|
12448
12448
|
"@sarj/require-zod-form-validation": "error",
|
|
12449
|
-
"@sarj/store-insert-requires-on-conflict": "
|
|
12450
|
-
"@sarj/stepdown": "
|
|
12451
|
-
"@sarj/zod-naming-convention": "
|
|
12449
|
+
"@sarj/store-insert-requires-on-conflict": "error",
|
|
12450
|
+
"@sarj/stepdown": "error",
|
|
12451
|
+
"@sarj/zod-naming-convention": "error"
|
|
12452
12452
|
};
|
|
12453
12453
|
var strictRules = {
|
|
12454
|
-
"@sarj/duplicate-test-body": "
|
|
12454
|
+
"@sarj/duplicate-test-body": "error",
|
|
12455
12455
|
"@sarj/enforce-file-structure": "error",
|
|
12456
12456
|
"@sarj/no-async-callback-in-wait-for": "error",
|
|
12457
12457
|
"@sarj/no-client-side-data-fetching": "error",
|
|
@@ -12467,7 +12467,7 @@ var strictRules = {
|
|
|
12467
12467
|
"@sarj/no-json-stringify-error": "error",
|
|
12468
12468
|
"@sarj/no-log-only-catch": "error",
|
|
12469
12469
|
"@sarj/no-long-comment": "error",
|
|
12470
|
-
"@sarj/no-generic-single-export-module": "
|
|
12470
|
+
"@sarj/no-generic-single-export-module": "error",
|
|
12471
12471
|
"@sarj/no-offset-pagination": "error",
|
|
12472
12472
|
"@sarj/no-positional-tuple-return": "error",
|
|
12473
12473
|
"@sarj/no-raw-env": "error",
|
|
@@ -12491,14 +12491,14 @@ var strictRules = {
|
|
|
12491
12491
|
"@sarj/no-unnecessary-use-client": "error",
|
|
12492
12492
|
"@sarj/no-unsafe-mock-casting": "error",
|
|
12493
12493
|
"@sarj/no-zod-native-enum": "error",
|
|
12494
|
-
"@sarj/test-loops-over-literal-cases": "
|
|
12494
|
+
"@sarj/test-loops-over-literal-cases": "error",
|
|
12495
12495
|
"@sarj/prefer-constant-time-secret-compare": "error",
|
|
12496
|
-
"@sarj/prefer-discriminated-union": "
|
|
12496
|
+
"@sarj/prefer-discriminated-union": "error",
|
|
12497
12497
|
"@sarj/prefer-input-group-search": "error",
|
|
12498
|
-
"@sarj/prefer-immutable-module-constant": "
|
|
12498
|
+
"@sarj/prefer-immutable-module-constant": "error",
|
|
12499
12499
|
"@sarj/prefer-module-level-constant": "error",
|
|
12500
12500
|
"@sarj/prefer-module-level-schema": "error",
|
|
12501
|
-
"@sarj/prefer-non-nullable-collection": "
|
|
12501
|
+
"@sarj/prefer-non-nullable-collection": "error",
|
|
12502
12502
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
12503
12503
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
12504
12504
|
"@sarj/prefer-server-actions": "error",
|
|
@@ -12506,13 +12506,13 @@ var strictRules = {
|
|
|
12506
12506
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
12507
12507
|
"@sarj/prefer-zod-enum": "error",
|
|
12508
12508
|
"@sarj/prefer-zod-infer": "error",
|
|
12509
|
-
"@sarj/require-assert-never": "
|
|
12509
|
+
"@sarj/require-assert-never": "error",
|
|
12510
12510
|
"@sarj/require-fetch-timeout": "error",
|
|
12511
|
-
"@sarj/require-interface-for-injected-service": "
|
|
12511
|
+
"@sarj/require-interface-for-injected-service": "error",
|
|
12512
12512
|
"@sarj/require-static-next-matcher": "error",
|
|
12513
12513
|
"@sarj/require-zod-form-validation": "error",
|
|
12514
12514
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
12515
|
-
"@sarj/stepdown": "
|
|
12515
|
+
"@sarj/stepdown": "error",
|
|
12516
12516
|
"@sarj/zod-naming-convention": "error"
|
|
12517
12517
|
};
|
|
12518
12518
|
var plugin = {
|
package/dist/index.d.cts
CHANGED
|
@@ -77,7 +77,7 @@ interface RuleOptions {
|
|
|
77
77
|
/**
|
|
78
78
|
* @fileoverview _renames — every rule this plugin has renamed, old name to new; the old names no longer resolve, so this map is what says what to write instead.
|
|
79
79
|
*
|
|
80
|
-
* `sarj-standards
|
|
80
|
+
* `sarj-standards maintain sync-ledger` turns each entry into the consumer-facing ledger row.
|
|
81
81
|
*
|
|
82
82
|
*/
|
|
83
83
|
declare const renamedRules: {
|
|
@@ -316,70 +316,70 @@ declare const rules: {
|
|
|
316
316
|
/** Rules registered for application-profile configs but intentionally absent from general presets. */
|
|
317
317
|
declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
|
|
318
318
|
declare const recommendedRules: {
|
|
319
|
-
readonly "@sarj/duplicate-test-body": "
|
|
320
|
-
readonly "@sarj/enforce-file-structure": "
|
|
321
|
-
readonly "@sarj/no-async-callback-in-wait-for": "
|
|
322
|
-
readonly "@sarj/no-client-side-data-fetching": "
|
|
323
|
-
readonly "@sarj/no-comment-cruft": "
|
|
324
|
-
readonly "@sarj/no-conditional-in-test": "
|
|
325
|
-
readonly "@sarj/no-cors-wildcard-with-credentials": "
|
|
326
|
-
readonly "@sarj/no-dynamic-sql": "
|
|
327
|
-
readonly "@sarj/no-fat-try-blocks": "
|
|
328
|
-
readonly "@sarj/no-hand-rolled-sleep": "
|
|
319
|
+
readonly "@sarj/duplicate-test-body": "error";
|
|
320
|
+
readonly "@sarj/enforce-file-structure": "error";
|
|
321
|
+
readonly "@sarj/no-async-callback-in-wait-for": "error";
|
|
322
|
+
readonly "@sarj/no-client-side-data-fetching": "error";
|
|
323
|
+
readonly "@sarj/no-comment-cruft": "error";
|
|
324
|
+
readonly "@sarj/no-conditional-in-test": "error";
|
|
325
|
+
readonly "@sarj/no-cors-wildcard-with-credentials": "error";
|
|
326
|
+
readonly "@sarj/no-dynamic-sql": "error";
|
|
327
|
+
readonly "@sarj/no-fat-try-blocks": "error";
|
|
328
|
+
readonly "@sarj/no-hand-rolled-sleep": "error";
|
|
329
329
|
readonly "@sarj/no-hand-rolled-spinner": "error";
|
|
330
|
-
readonly "@sarj/no-insecure-random-id": "
|
|
331
|
-
readonly "@sarj/no-json-stringify-error": "
|
|
332
|
-
readonly "@sarj/no-log-only-catch": "
|
|
333
|
-
readonly "@sarj/no-long-comment": "
|
|
334
|
-
readonly "@sarj/no-generic-single-export-module": "
|
|
335
|
-
readonly "@sarj/no-offset-pagination": "
|
|
336
|
-
readonly "@sarj/no-positional-tuple-return": "
|
|
337
|
-
readonly "@sarj/no-repeated-string-literal": "
|
|
338
|
-
readonly "@sarj/no-restated-comment": "
|
|
339
|
-
readonly "@sarj/no-restated-jsdoc": "
|
|
340
|
-
readonly "@sarj/no-secret-in-log": "
|
|
341
|
-
readonly "@sarj/no-select-star": "
|
|
342
|
-
readonly "@sarj/no-sentinel-return-on-catch": "
|
|
343
|
-
readonly "@sarj/no-silent-promise-catch": "
|
|
344
|
-
readonly "@sarj/no-sleep-in-test-body": "
|
|
345
|
-
readonly "@sarj/no-string-concat-in-loop": "
|
|
346
|
-
readonly "@sarj/no-tautological-expect": "
|
|
347
|
-
readonly "@sarj/no-typed-doc-sections": "
|
|
348
|
-
readonly "@sarj/no-trailing-value-narration": "
|
|
349
|
-
readonly "@sarj/no-declaration-comment-wall": "
|
|
350
|
-
readonly "@sarj/no-union-in-comment": "
|
|
351
|
-
readonly "@sarj/no-type-member-comment-wall": "
|
|
352
|
-
readonly "@sarj/no-unnecessary-use-client": "
|
|
353
|
-
readonly "@sarj/no-unsafe-mock-casting": "
|
|
354
|
-
readonly "@sarj/no-zod-native-enum": "
|
|
355
|
-
readonly "@sarj/test-loops-over-literal-cases": "
|
|
330
|
+
readonly "@sarj/no-insecure-random-id": "error";
|
|
331
|
+
readonly "@sarj/no-json-stringify-error": "error";
|
|
332
|
+
readonly "@sarj/no-log-only-catch": "error";
|
|
333
|
+
readonly "@sarj/no-long-comment": "error";
|
|
334
|
+
readonly "@sarj/no-generic-single-export-module": "error";
|
|
335
|
+
readonly "@sarj/no-offset-pagination": "error";
|
|
336
|
+
readonly "@sarj/no-positional-tuple-return": "error";
|
|
337
|
+
readonly "@sarj/no-repeated-string-literal": "error";
|
|
338
|
+
readonly "@sarj/no-restated-comment": "error";
|
|
339
|
+
readonly "@sarj/no-restated-jsdoc": "error";
|
|
340
|
+
readonly "@sarj/no-secret-in-log": "error";
|
|
341
|
+
readonly "@sarj/no-select-star": "error";
|
|
342
|
+
readonly "@sarj/no-sentinel-return-on-catch": "error";
|
|
343
|
+
readonly "@sarj/no-silent-promise-catch": "error";
|
|
344
|
+
readonly "@sarj/no-sleep-in-test-body": "error";
|
|
345
|
+
readonly "@sarj/no-string-concat-in-loop": "error";
|
|
346
|
+
readonly "@sarj/no-tautological-expect": "error";
|
|
347
|
+
readonly "@sarj/no-typed-doc-sections": "error";
|
|
348
|
+
readonly "@sarj/no-trailing-value-narration": "error";
|
|
349
|
+
readonly "@sarj/no-declaration-comment-wall": "error";
|
|
350
|
+
readonly "@sarj/no-union-in-comment": "error";
|
|
351
|
+
readonly "@sarj/no-type-member-comment-wall": "error";
|
|
352
|
+
readonly "@sarj/no-unnecessary-use-client": "error";
|
|
353
|
+
readonly "@sarj/no-unsafe-mock-casting": "error";
|
|
354
|
+
readonly "@sarj/no-zod-native-enum": "error";
|
|
355
|
+
readonly "@sarj/test-loops-over-literal-cases": "error";
|
|
356
356
|
readonly "@sarj/prefer-constant-time-secret-compare": "error";
|
|
357
|
-
readonly "@sarj/prefer-discriminated-union": "
|
|
357
|
+
readonly "@sarj/prefer-discriminated-union": "error";
|
|
358
358
|
readonly "@sarj/prefer-input-group-search": "error";
|
|
359
|
-
readonly "@sarj/prefer-immutable-module-constant": "
|
|
360
|
-
readonly "@sarj/prefer-module-level-constant": "
|
|
361
|
-
readonly "@sarj/prefer-module-level-schema": "
|
|
362
|
-
readonly "@sarj/prefer-non-nullable-collection": "
|
|
363
|
-
readonly "@sarj/prefer-schema-for-api-payload": "
|
|
364
|
-
readonly "@sarj/prefer-semantic-colors": readonly ["
|
|
359
|
+
readonly "@sarj/prefer-immutable-module-constant": "error";
|
|
360
|
+
readonly "@sarj/prefer-module-level-constant": "error";
|
|
361
|
+
readonly "@sarj/prefer-module-level-schema": "error";
|
|
362
|
+
readonly "@sarj/prefer-non-nullable-collection": "error";
|
|
363
|
+
readonly "@sarj/prefer-schema-for-api-payload": "error";
|
|
364
|
+
readonly "@sarj/prefer-semantic-colors": readonly ["error", {
|
|
365
365
|
readonly requireSemanticTokens: true;
|
|
366
366
|
}];
|
|
367
|
-
readonly "@sarj/prefer-server-actions": "
|
|
368
|
-
readonly "@sarj/prefer-string-literal-union": "
|
|
369
|
-
readonly "@sarj/prefer-whole-object-assertion": "
|
|
370
|
-
readonly "@sarj/prefer-zod-enum": "
|
|
371
|
-
readonly "@sarj/prefer-zod-infer": "
|
|
372
|
-
readonly "@sarj/require-assert-never": "
|
|
373
|
-
readonly "@sarj/require-fetch-timeout": "
|
|
374
|
-
readonly "@sarj/require-interface-for-injected-service": "
|
|
367
|
+
readonly "@sarj/prefer-server-actions": "error";
|
|
368
|
+
readonly "@sarj/prefer-string-literal-union": "error";
|
|
369
|
+
readonly "@sarj/prefer-whole-object-assertion": "error";
|
|
370
|
+
readonly "@sarj/prefer-zod-enum": "error";
|
|
371
|
+
readonly "@sarj/prefer-zod-infer": "error";
|
|
372
|
+
readonly "@sarj/require-assert-never": "error";
|
|
373
|
+
readonly "@sarj/require-fetch-timeout": "error";
|
|
374
|
+
readonly "@sarj/require-interface-for-injected-service": "error";
|
|
375
375
|
readonly "@sarj/require-static-next-matcher": "error";
|
|
376
376
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
377
|
-
readonly "@sarj/store-insert-requires-on-conflict": "
|
|
378
|
-
readonly "@sarj/stepdown": "
|
|
379
|
-
readonly "@sarj/zod-naming-convention": "
|
|
377
|
+
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
378
|
+
readonly "@sarj/stepdown": "error";
|
|
379
|
+
readonly "@sarj/zod-naming-convention": "error";
|
|
380
380
|
};
|
|
381
381
|
declare const strictRules: {
|
|
382
|
-
readonly "@sarj/duplicate-test-body": "
|
|
382
|
+
readonly "@sarj/duplicate-test-body": "error";
|
|
383
383
|
readonly "@sarj/enforce-file-structure": "error";
|
|
384
384
|
readonly "@sarj/no-async-callback-in-wait-for": "error";
|
|
385
385
|
readonly "@sarj/no-client-side-data-fetching": "error";
|
|
@@ -395,7 +395,7 @@ declare const strictRules: {
|
|
|
395
395
|
readonly "@sarj/no-json-stringify-error": "error";
|
|
396
396
|
readonly "@sarj/no-log-only-catch": "error";
|
|
397
397
|
readonly "@sarj/no-long-comment": "error";
|
|
398
|
-
readonly "@sarj/no-generic-single-export-module": "
|
|
398
|
+
readonly "@sarj/no-generic-single-export-module": "error";
|
|
399
399
|
readonly "@sarj/no-offset-pagination": "error";
|
|
400
400
|
readonly "@sarj/no-positional-tuple-return": "error";
|
|
401
401
|
readonly "@sarj/no-raw-env": "error";
|
|
@@ -419,14 +419,14 @@ declare const strictRules: {
|
|
|
419
419
|
readonly "@sarj/no-unnecessary-use-client": "error";
|
|
420
420
|
readonly "@sarj/no-unsafe-mock-casting": "error";
|
|
421
421
|
readonly "@sarj/no-zod-native-enum": "error";
|
|
422
|
-
readonly "@sarj/test-loops-over-literal-cases": "
|
|
422
|
+
readonly "@sarj/test-loops-over-literal-cases": "error";
|
|
423
423
|
readonly "@sarj/prefer-constant-time-secret-compare": "error";
|
|
424
|
-
readonly "@sarj/prefer-discriminated-union": "
|
|
424
|
+
readonly "@sarj/prefer-discriminated-union": "error";
|
|
425
425
|
readonly "@sarj/prefer-input-group-search": "error";
|
|
426
|
-
readonly "@sarj/prefer-immutable-module-constant": "
|
|
426
|
+
readonly "@sarj/prefer-immutable-module-constant": "error";
|
|
427
427
|
readonly "@sarj/prefer-module-level-constant": "error";
|
|
428
428
|
readonly "@sarj/prefer-module-level-schema": "error";
|
|
429
|
-
readonly "@sarj/prefer-non-nullable-collection": "
|
|
429
|
+
readonly "@sarj/prefer-non-nullable-collection": "error";
|
|
430
430
|
readonly "@sarj/prefer-schema-for-api-payload": "error";
|
|
431
431
|
readonly "@sarj/prefer-semantic-colors": readonly ["error", {
|
|
432
432
|
readonly requireSemanticTokens: true;
|
|
@@ -436,13 +436,13 @@ declare const strictRules: {
|
|
|
436
436
|
readonly "@sarj/prefer-whole-object-assertion": "error";
|
|
437
437
|
readonly "@sarj/prefer-zod-enum": "error";
|
|
438
438
|
readonly "@sarj/prefer-zod-infer": "error";
|
|
439
|
-
readonly "@sarj/require-assert-never": "
|
|
439
|
+
readonly "@sarj/require-assert-never": "error";
|
|
440
440
|
readonly "@sarj/require-fetch-timeout": "error";
|
|
441
|
-
readonly "@sarj/require-interface-for-injected-service": "
|
|
441
|
+
readonly "@sarj/require-interface-for-injected-service": "error";
|
|
442
442
|
readonly "@sarj/require-static-next-matcher": "error";
|
|
443
443
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
444
444
|
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
445
|
-
readonly "@sarj/stepdown": "
|
|
445
|
+
readonly "@sarj/stepdown": "error";
|
|
446
446
|
readonly "@sarj/zod-naming-convention": "error";
|
|
447
447
|
};
|
|
448
448
|
type FlatPreset = {
|
|
@@ -453,7 +453,7 @@ type FlatPreset = {
|
|
|
453
453
|
declare const plugin: {
|
|
454
454
|
readonly meta: {
|
|
455
455
|
readonly name: "@sarj/eslint-plugin";
|
|
456
|
-
readonly version: "
|
|
456
|
+
readonly version: "11.0.1";
|
|
457
457
|
};
|
|
458
458
|
readonly rules: {
|
|
459
459
|
readonly "duplicate-test-body": _typescript_eslint_utils_ts_eslint.RuleModule<"duplicateTestBody", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
package/dist/index.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ interface RuleOptions {
|
|
|
77
77
|
/**
|
|
78
78
|
* @fileoverview _renames — every rule this plugin has renamed, old name to new; the old names no longer resolve, so this map is what says what to write instead.
|
|
79
79
|
*
|
|
80
|
-
* `sarj-standards
|
|
80
|
+
* `sarj-standards maintain sync-ledger` turns each entry into the consumer-facing ledger row.
|
|
81
81
|
*
|
|
82
82
|
*/
|
|
83
83
|
declare const renamedRules: {
|
|
@@ -316,70 +316,70 @@ declare const rules: {
|
|
|
316
316
|
/** Rules registered for application-profile configs but intentionally absent from general presets. */
|
|
317
317
|
declare const applicationOnlyRules: readonly ["no-restricted-library-load", "prefer-native-random-uuid", "prefer-shadcn-primitives"];
|
|
318
318
|
declare const recommendedRules: {
|
|
319
|
-
readonly "@sarj/duplicate-test-body": "
|
|
320
|
-
readonly "@sarj/enforce-file-structure": "
|
|
321
|
-
readonly "@sarj/no-async-callback-in-wait-for": "
|
|
322
|
-
readonly "@sarj/no-client-side-data-fetching": "
|
|
323
|
-
readonly "@sarj/no-comment-cruft": "
|
|
324
|
-
readonly "@sarj/no-conditional-in-test": "
|
|
325
|
-
readonly "@sarj/no-cors-wildcard-with-credentials": "
|
|
326
|
-
readonly "@sarj/no-dynamic-sql": "
|
|
327
|
-
readonly "@sarj/no-fat-try-blocks": "
|
|
328
|
-
readonly "@sarj/no-hand-rolled-sleep": "
|
|
319
|
+
readonly "@sarj/duplicate-test-body": "error";
|
|
320
|
+
readonly "@sarj/enforce-file-structure": "error";
|
|
321
|
+
readonly "@sarj/no-async-callback-in-wait-for": "error";
|
|
322
|
+
readonly "@sarj/no-client-side-data-fetching": "error";
|
|
323
|
+
readonly "@sarj/no-comment-cruft": "error";
|
|
324
|
+
readonly "@sarj/no-conditional-in-test": "error";
|
|
325
|
+
readonly "@sarj/no-cors-wildcard-with-credentials": "error";
|
|
326
|
+
readonly "@sarj/no-dynamic-sql": "error";
|
|
327
|
+
readonly "@sarj/no-fat-try-blocks": "error";
|
|
328
|
+
readonly "@sarj/no-hand-rolled-sleep": "error";
|
|
329
329
|
readonly "@sarj/no-hand-rolled-spinner": "error";
|
|
330
|
-
readonly "@sarj/no-insecure-random-id": "
|
|
331
|
-
readonly "@sarj/no-json-stringify-error": "
|
|
332
|
-
readonly "@sarj/no-log-only-catch": "
|
|
333
|
-
readonly "@sarj/no-long-comment": "
|
|
334
|
-
readonly "@sarj/no-generic-single-export-module": "
|
|
335
|
-
readonly "@sarj/no-offset-pagination": "
|
|
336
|
-
readonly "@sarj/no-positional-tuple-return": "
|
|
337
|
-
readonly "@sarj/no-repeated-string-literal": "
|
|
338
|
-
readonly "@sarj/no-restated-comment": "
|
|
339
|
-
readonly "@sarj/no-restated-jsdoc": "
|
|
340
|
-
readonly "@sarj/no-secret-in-log": "
|
|
341
|
-
readonly "@sarj/no-select-star": "
|
|
342
|
-
readonly "@sarj/no-sentinel-return-on-catch": "
|
|
343
|
-
readonly "@sarj/no-silent-promise-catch": "
|
|
344
|
-
readonly "@sarj/no-sleep-in-test-body": "
|
|
345
|
-
readonly "@sarj/no-string-concat-in-loop": "
|
|
346
|
-
readonly "@sarj/no-tautological-expect": "
|
|
347
|
-
readonly "@sarj/no-typed-doc-sections": "
|
|
348
|
-
readonly "@sarj/no-trailing-value-narration": "
|
|
349
|
-
readonly "@sarj/no-declaration-comment-wall": "
|
|
350
|
-
readonly "@sarj/no-union-in-comment": "
|
|
351
|
-
readonly "@sarj/no-type-member-comment-wall": "
|
|
352
|
-
readonly "@sarj/no-unnecessary-use-client": "
|
|
353
|
-
readonly "@sarj/no-unsafe-mock-casting": "
|
|
354
|
-
readonly "@sarj/no-zod-native-enum": "
|
|
355
|
-
readonly "@sarj/test-loops-over-literal-cases": "
|
|
330
|
+
readonly "@sarj/no-insecure-random-id": "error";
|
|
331
|
+
readonly "@sarj/no-json-stringify-error": "error";
|
|
332
|
+
readonly "@sarj/no-log-only-catch": "error";
|
|
333
|
+
readonly "@sarj/no-long-comment": "error";
|
|
334
|
+
readonly "@sarj/no-generic-single-export-module": "error";
|
|
335
|
+
readonly "@sarj/no-offset-pagination": "error";
|
|
336
|
+
readonly "@sarj/no-positional-tuple-return": "error";
|
|
337
|
+
readonly "@sarj/no-repeated-string-literal": "error";
|
|
338
|
+
readonly "@sarj/no-restated-comment": "error";
|
|
339
|
+
readonly "@sarj/no-restated-jsdoc": "error";
|
|
340
|
+
readonly "@sarj/no-secret-in-log": "error";
|
|
341
|
+
readonly "@sarj/no-select-star": "error";
|
|
342
|
+
readonly "@sarj/no-sentinel-return-on-catch": "error";
|
|
343
|
+
readonly "@sarj/no-silent-promise-catch": "error";
|
|
344
|
+
readonly "@sarj/no-sleep-in-test-body": "error";
|
|
345
|
+
readonly "@sarj/no-string-concat-in-loop": "error";
|
|
346
|
+
readonly "@sarj/no-tautological-expect": "error";
|
|
347
|
+
readonly "@sarj/no-typed-doc-sections": "error";
|
|
348
|
+
readonly "@sarj/no-trailing-value-narration": "error";
|
|
349
|
+
readonly "@sarj/no-declaration-comment-wall": "error";
|
|
350
|
+
readonly "@sarj/no-union-in-comment": "error";
|
|
351
|
+
readonly "@sarj/no-type-member-comment-wall": "error";
|
|
352
|
+
readonly "@sarj/no-unnecessary-use-client": "error";
|
|
353
|
+
readonly "@sarj/no-unsafe-mock-casting": "error";
|
|
354
|
+
readonly "@sarj/no-zod-native-enum": "error";
|
|
355
|
+
readonly "@sarj/test-loops-over-literal-cases": "error";
|
|
356
356
|
readonly "@sarj/prefer-constant-time-secret-compare": "error";
|
|
357
|
-
readonly "@sarj/prefer-discriminated-union": "
|
|
357
|
+
readonly "@sarj/prefer-discriminated-union": "error";
|
|
358
358
|
readonly "@sarj/prefer-input-group-search": "error";
|
|
359
|
-
readonly "@sarj/prefer-immutable-module-constant": "
|
|
360
|
-
readonly "@sarj/prefer-module-level-constant": "
|
|
361
|
-
readonly "@sarj/prefer-module-level-schema": "
|
|
362
|
-
readonly "@sarj/prefer-non-nullable-collection": "
|
|
363
|
-
readonly "@sarj/prefer-schema-for-api-payload": "
|
|
364
|
-
readonly "@sarj/prefer-semantic-colors": readonly ["
|
|
359
|
+
readonly "@sarj/prefer-immutable-module-constant": "error";
|
|
360
|
+
readonly "@sarj/prefer-module-level-constant": "error";
|
|
361
|
+
readonly "@sarj/prefer-module-level-schema": "error";
|
|
362
|
+
readonly "@sarj/prefer-non-nullable-collection": "error";
|
|
363
|
+
readonly "@sarj/prefer-schema-for-api-payload": "error";
|
|
364
|
+
readonly "@sarj/prefer-semantic-colors": readonly ["error", {
|
|
365
365
|
readonly requireSemanticTokens: true;
|
|
366
366
|
}];
|
|
367
|
-
readonly "@sarj/prefer-server-actions": "
|
|
368
|
-
readonly "@sarj/prefer-string-literal-union": "
|
|
369
|
-
readonly "@sarj/prefer-whole-object-assertion": "
|
|
370
|
-
readonly "@sarj/prefer-zod-enum": "
|
|
371
|
-
readonly "@sarj/prefer-zod-infer": "
|
|
372
|
-
readonly "@sarj/require-assert-never": "
|
|
373
|
-
readonly "@sarj/require-fetch-timeout": "
|
|
374
|
-
readonly "@sarj/require-interface-for-injected-service": "
|
|
367
|
+
readonly "@sarj/prefer-server-actions": "error";
|
|
368
|
+
readonly "@sarj/prefer-string-literal-union": "error";
|
|
369
|
+
readonly "@sarj/prefer-whole-object-assertion": "error";
|
|
370
|
+
readonly "@sarj/prefer-zod-enum": "error";
|
|
371
|
+
readonly "@sarj/prefer-zod-infer": "error";
|
|
372
|
+
readonly "@sarj/require-assert-never": "error";
|
|
373
|
+
readonly "@sarj/require-fetch-timeout": "error";
|
|
374
|
+
readonly "@sarj/require-interface-for-injected-service": "error";
|
|
375
375
|
readonly "@sarj/require-static-next-matcher": "error";
|
|
376
376
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
377
|
-
readonly "@sarj/store-insert-requires-on-conflict": "
|
|
378
|
-
readonly "@sarj/stepdown": "
|
|
379
|
-
readonly "@sarj/zod-naming-convention": "
|
|
377
|
+
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
378
|
+
readonly "@sarj/stepdown": "error";
|
|
379
|
+
readonly "@sarj/zod-naming-convention": "error";
|
|
380
380
|
};
|
|
381
381
|
declare const strictRules: {
|
|
382
|
-
readonly "@sarj/duplicate-test-body": "
|
|
382
|
+
readonly "@sarj/duplicate-test-body": "error";
|
|
383
383
|
readonly "@sarj/enforce-file-structure": "error";
|
|
384
384
|
readonly "@sarj/no-async-callback-in-wait-for": "error";
|
|
385
385
|
readonly "@sarj/no-client-side-data-fetching": "error";
|
|
@@ -395,7 +395,7 @@ declare const strictRules: {
|
|
|
395
395
|
readonly "@sarj/no-json-stringify-error": "error";
|
|
396
396
|
readonly "@sarj/no-log-only-catch": "error";
|
|
397
397
|
readonly "@sarj/no-long-comment": "error";
|
|
398
|
-
readonly "@sarj/no-generic-single-export-module": "
|
|
398
|
+
readonly "@sarj/no-generic-single-export-module": "error";
|
|
399
399
|
readonly "@sarj/no-offset-pagination": "error";
|
|
400
400
|
readonly "@sarj/no-positional-tuple-return": "error";
|
|
401
401
|
readonly "@sarj/no-raw-env": "error";
|
|
@@ -419,14 +419,14 @@ declare const strictRules: {
|
|
|
419
419
|
readonly "@sarj/no-unnecessary-use-client": "error";
|
|
420
420
|
readonly "@sarj/no-unsafe-mock-casting": "error";
|
|
421
421
|
readonly "@sarj/no-zod-native-enum": "error";
|
|
422
|
-
readonly "@sarj/test-loops-over-literal-cases": "
|
|
422
|
+
readonly "@sarj/test-loops-over-literal-cases": "error";
|
|
423
423
|
readonly "@sarj/prefer-constant-time-secret-compare": "error";
|
|
424
|
-
readonly "@sarj/prefer-discriminated-union": "
|
|
424
|
+
readonly "@sarj/prefer-discriminated-union": "error";
|
|
425
425
|
readonly "@sarj/prefer-input-group-search": "error";
|
|
426
|
-
readonly "@sarj/prefer-immutable-module-constant": "
|
|
426
|
+
readonly "@sarj/prefer-immutable-module-constant": "error";
|
|
427
427
|
readonly "@sarj/prefer-module-level-constant": "error";
|
|
428
428
|
readonly "@sarj/prefer-module-level-schema": "error";
|
|
429
|
-
readonly "@sarj/prefer-non-nullable-collection": "
|
|
429
|
+
readonly "@sarj/prefer-non-nullable-collection": "error";
|
|
430
430
|
readonly "@sarj/prefer-schema-for-api-payload": "error";
|
|
431
431
|
readonly "@sarj/prefer-semantic-colors": readonly ["error", {
|
|
432
432
|
readonly requireSemanticTokens: true;
|
|
@@ -436,13 +436,13 @@ declare const strictRules: {
|
|
|
436
436
|
readonly "@sarj/prefer-whole-object-assertion": "error";
|
|
437
437
|
readonly "@sarj/prefer-zod-enum": "error";
|
|
438
438
|
readonly "@sarj/prefer-zod-infer": "error";
|
|
439
|
-
readonly "@sarj/require-assert-never": "
|
|
439
|
+
readonly "@sarj/require-assert-never": "error";
|
|
440
440
|
readonly "@sarj/require-fetch-timeout": "error";
|
|
441
|
-
readonly "@sarj/require-interface-for-injected-service": "
|
|
441
|
+
readonly "@sarj/require-interface-for-injected-service": "error";
|
|
442
442
|
readonly "@sarj/require-static-next-matcher": "error";
|
|
443
443
|
readonly "@sarj/require-zod-form-validation": "error";
|
|
444
444
|
readonly "@sarj/store-insert-requires-on-conflict": "error";
|
|
445
|
-
readonly "@sarj/stepdown": "
|
|
445
|
+
readonly "@sarj/stepdown": "error";
|
|
446
446
|
readonly "@sarj/zod-naming-convention": "error";
|
|
447
447
|
};
|
|
448
448
|
type FlatPreset = {
|
|
@@ -453,7 +453,7 @@ type FlatPreset = {
|
|
|
453
453
|
declare const plugin: {
|
|
454
454
|
readonly meta: {
|
|
455
455
|
readonly name: "@sarj/eslint-plugin";
|
|
456
|
-
readonly version: "
|
|
456
|
+
readonly version: "11.0.1";
|
|
457
457
|
};
|
|
458
458
|
readonly rules: {
|
|
459
459
|
readonly "duplicate-test-body": _typescript_eslint_utils_ts_eslint.RuleModule<"duplicateTestBody", readonly [], unknown, _typescript_eslint_utils_ts_eslint.RuleListener> & {
|
package/dist/index.js
CHANGED
|
@@ -12346,7 +12346,7 @@ var rules = {
|
|
|
12346
12346
|
};
|
|
12347
12347
|
var meta = {
|
|
12348
12348
|
name: "@sarj/eslint-plugin",
|
|
12349
|
-
version: "
|
|
12349
|
+
version: "11.0.1"
|
|
12350
12350
|
};
|
|
12351
12351
|
var applicationOnlyRules = [
|
|
12352
12352
|
"no-restricted-library-load",
|
|
@@ -12354,68 +12354,68 @@ var applicationOnlyRules = [
|
|
|
12354
12354
|
"prefer-shadcn-primitives"
|
|
12355
12355
|
];
|
|
12356
12356
|
var recommendedRules = {
|
|
12357
|
-
"@sarj/duplicate-test-body": "
|
|
12358
|
-
"@sarj/enforce-file-structure": "
|
|
12359
|
-
"@sarj/no-async-callback-in-wait-for": "
|
|
12360
|
-
"@sarj/no-client-side-data-fetching": "
|
|
12361
|
-
"@sarj/no-comment-cruft": "
|
|
12362
|
-
"@sarj/no-conditional-in-test": "
|
|
12363
|
-
"@sarj/no-cors-wildcard-with-credentials": "
|
|
12364
|
-
"@sarj/no-dynamic-sql": "
|
|
12365
|
-
"@sarj/no-fat-try-blocks": "
|
|
12366
|
-
"@sarj/no-hand-rolled-sleep": "
|
|
12357
|
+
"@sarj/duplicate-test-body": "error",
|
|
12358
|
+
"@sarj/enforce-file-structure": "error",
|
|
12359
|
+
"@sarj/no-async-callback-in-wait-for": "error",
|
|
12360
|
+
"@sarj/no-client-side-data-fetching": "error",
|
|
12361
|
+
"@sarj/no-comment-cruft": "error",
|
|
12362
|
+
"@sarj/no-conditional-in-test": "error",
|
|
12363
|
+
"@sarj/no-cors-wildcard-with-credentials": "error",
|
|
12364
|
+
"@sarj/no-dynamic-sql": "error",
|
|
12365
|
+
"@sarj/no-fat-try-blocks": "error",
|
|
12366
|
+
"@sarj/no-hand-rolled-sleep": "error",
|
|
12367
12367
|
"@sarj/no-hand-rolled-spinner": "error",
|
|
12368
|
-
"@sarj/no-insecure-random-id": "
|
|
12369
|
-
"@sarj/no-json-stringify-error": "
|
|
12370
|
-
"@sarj/no-log-only-catch": "
|
|
12371
|
-
"@sarj/no-long-comment": "
|
|
12372
|
-
"@sarj/no-generic-single-export-module": "
|
|
12373
|
-
"@sarj/no-offset-pagination": "
|
|
12374
|
-
"@sarj/no-positional-tuple-return": "
|
|
12375
|
-
"@sarj/no-repeated-string-literal": "
|
|
12376
|
-
"@sarj/no-restated-comment": "
|
|
12377
|
-
"@sarj/no-restated-jsdoc": "
|
|
12378
|
-
"@sarj/no-secret-in-log": "
|
|
12379
|
-
"@sarj/no-select-star": "
|
|
12380
|
-
"@sarj/no-sentinel-return-on-catch": "
|
|
12381
|
-
"@sarj/no-silent-promise-catch": "
|
|
12382
|
-
"@sarj/no-sleep-in-test-body": "
|
|
12383
|
-
"@sarj/no-string-concat-in-loop": "
|
|
12384
|
-
"@sarj/no-tautological-expect": "
|
|
12385
|
-
"@sarj/no-typed-doc-sections": "
|
|
12386
|
-
"@sarj/no-trailing-value-narration": "
|
|
12387
|
-
"@sarj/no-declaration-comment-wall": "
|
|
12388
|
-
"@sarj/no-union-in-comment": "
|
|
12389
|
-
"@sarj/no-type-member-comment-wall": "
|
|
12390
|
-
"@sarj/no-unnecessary-use-client": "
|
|
12391
|
-
"@sarj/no-unsafe-mock-casting": "
|
|
12392
|
-
"@sarj/no-zod-native-enum": "
|
|
12393
|
-
"@sarj/test-loops-over-literal-cases": "
|
|
12368
|
+
"@sarj/no-insecure-random-id": "error",
|
|
12369
|
+
"@sarj/no-json-stringify-error": "error",
|
|
12370
|
+
"@sarj/no-log-only-catch": "error",
|
|
12371
|
+
"@sarj/no-long-comment": "error",
|
|
12372
|
+
"@sarj/no-generic-single-export-module": "error",
|
|
12373
|
+
"@sarj/no-offset-pagination": "error",
|
|
12374
|
+
"@sarj/no-positional-tuple-return": "error",
|
|
12375
|
+
"@sarj/no-repeated-string-literal": "error",
|
|
12376
|
+
"@sarj/no-restated-comment": "error",
|
|
12377
|
+
"@sarj/no-restated-jsdoc": "error",
|
|
12378
|
+
"@sarj/no-secret-in-log": "error",
|
|
12379
|
+
"@sarj/no-select-star": "error",
|
|
12380
|
+
"@sarj/no-sentinel-return-on-catch": "error",
|
|
12381
|
+
"@sarj/no-silent-promise-catch": "error",
|
|
12382
|
+
"@sarj/no-sleep-in-test-body": "error",
|
|
12383
|
+
"@sarj/no-string-concat-in-loop": "error",
|
|
12384
|
+
"@sarj/no-tautological-expect": "error",
|
|
12385
|
+
"@sarj/no-typed-doc-sections": "error",
|
|
12386
|
+
"@sarj/no-trailing-value-narration": "error",
|
|
12387
|
+
"@sarj/no-declaration-comment-wall": "error",
|
|
12388
|
+
"@sarj/no-union-in-comment": "error",
|
|
12389
|
+
"@sarj/no-type-member-comment-wall": "error",
|
|
12390
|
+
"@sarj/no-unnecessary-use-client": "error",
|
|
12391
|
+
"@sarj/no-unsafe-mock-casting": "error",
|
|
12392
|
+
"@sarj/no-zod-native-enum": "error",
|
|
12393
|
+
"@sarj/test-loops-over-literal-cases": "error",
|
|
12394
12394
|
"@sarj/prefer-constant-time-secret-compare": "error",
|
|
12395
|
-
"@sarj/prefer-discriminated-union": "
|
|
12395
|
+
"@sarj/prefer-discriminated-union": "error",
|
|
12396
12396
|
"@sarj/prefer-input-group-search": "error",
|
|
12397
|
-
"@sarj/prefer-immutable-module-constant": "
|
|
12398
|
-
"@sarj/prefer-module-level-constant": "
|
|
12399
|
-
"@sarj/prefer-module-level-schema": "
|
|
12400
|
-
"@sarj/prefer-non-nullable-collection": "
|
|
12401
|
-
"@sarj/prefer-schema-for-api-payload": "
|
|
12402
|
-
"@sarj/prefer-semantic-colors": ["
|
|
12403
|
-
"@sarj/prefer-server-actions": "
|
|
12404
|
-
"@sarj/prefer-string-literal-union": "
|
|
12405
|
-
"@sarj/prefer-whole-object-assertion": "
|
|
12406
|
-
"@sarj/prefer-zod-enum": "
|
|
12407
|
-
"@sarj/prefer-zod-infer": "
|
|
12408
|
-
"@sarj/require-assert-never": "
|
|
12409
|
-
"@sarj/require-fetch-timeout": "
|
|
12410
|
-
"@sarj/require-interface-for-injected-service": "
|
|
12397
|
+
"@sarj/prefer-immutable-module-constant": "error",
|
|
12398
|
+
"@sarj/prefer-module-level-constant": "error",
|
|
12399
|
+
"@sarj/prefer-module-level-schema": "error",
|
|
12400
|
+
"@sarj/prefer-non-nullable-collection": "error",
|
|
12401
|
+
"@sarj/prefer-schema-for-api-payload": "error",
|
|
12402
|
+
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
12403
|
+
"@sarj/prefer-server-actions": "error",
|
|
12404
|
+
"@sarj/prefer-string-literal-union": "error",
|
|
12405
|
+
"@sarj/prefer-whole-object-assertion": "error",
|
|
12406
|
+
"@sarj/prefer-zod-enum": "error",
|
|
12407
|
+
"@sarj/prefer-zod-infer": "error",
|
|
12408
|
+
"@sarj/require-assert-never": "error",
|
|
12409
|
+
"@sarj/require-fetch-timeout": "error",
|
|
12410
|
+
"@sarj/require-interface-for-injected-service": "error",
|
|
12411
12411
|
"@sarj/require-static-next-matcher": "error",
|
|
12412
12412
|
"@sarj/require-zod-form-validation": "error",
|
|
12413
|
-
"@sarj/store-insert-requires-on-conflict": "
|
|
12414
|
-
"@sarj/stepdown": "
|
|
12415
|
-
"@sarj/zod-naming-convention": "
|
|
12413
|
+
"@sarj/store-insert-requires-on-conflict": "error",
|
|
12414
|
+
"@sarj/stepdown": "error",
|
|
12415
|
+
"@sarj/zod-naming-convention": "error"
|
|
12416
12416
|
};
|
|
12417
12417
|
var strictRules = {
|
|
12418
|
-
"@sarj/duplicate-test-body": "
|
|
12418
|
+
"@sarj/duplicate-test-body": "error",
|
|
12419
12419
|
"@sarj/enforce-file-structure": "error",
|
|
12420
12420
|
"@sarj/no-async-callback-in-wait-for": "error",
|
|
12421
12421
|
"@sarj/no-client-side-data-fetching": "error",
|
|
@@ -12431,7 +12431,7 @@ var strictRules = {
|
|
|
12431
12431
|
"@sarj/no-json-stringify-error": "error",
|
|
12432
12432
|
"@sarj/no-log-only-catch": "error",
|
|
12433
12433
|
"@sarj/no-long-comment": "error",
|
|
12434
|
-
"@sarj/no-generic-single-export-module": "
|
|
12434
|
+
"@sarj/no-generic-single-export-module": "error",
|
|
12435
12435
|
"@sarj/no-offset-pagination": "error",
|
|
12436
12436
|
"@sarj/no-positional-tuple-return": "error",
|
|
12437
12437
|
"@sarj/no-raw-env": "error",
|
|
@@ -12455,14 +12455,14 @@ var strictRules = {
|
|
|
12455
12455
|
"@sarj/no-unnecessary-use-client": "error",
|
|
12456
12456
|
"@sarj/no-unsafe-mock-casting": "error",
|
|
12457
12457
|
"@sarj/no-zod-native-enum": "error",
|
|
12458
|
-
"@sarj/test-loops-over-literal-cases": "
|
|
12458
|
+
"@sarj/test-loops-over-literal-cases": "error",
|
|
12459
12459
|
"@sarj/prefer-constant-time-secret-compare": "error",
|
|
12460
|
-
"@sarj/prefer-discriminated-union": "
|
|
12460
|
+
"@sarj/prefer-discriminated-union": "error",
|
|
12461
12461
|
"@sarj/prefer-input-group-search": "error",
|
|
12462
|
-
"@sarj/prefer-immutable-module-constant": "
|
|
12462
|
+
"@sarj/prefer-immutable-module-constant": "error",
|
|
12463
12463
|
"@sarj/prefer-module-level-constant": "error",
|
|
12464
12464
|
"@sarj/prefer-module-level-schema": "error",
|
|
12465
|
-
"@sarj/prefer-non-nullable-collection": "
|
|
12465
|
+
"@sarj/prefer-non-nullable-collection": "error",
|
|
12466
12466
|
"@sarj/prefer-schema-for-api-payload": "error",
|
|
12467
12467
|
"@sarj/prefer-semantic-colors": ["error", { requireSemanticTokens: true }],
|
|
12468
12468
|
"@sarj/prefer-server-actions": "error",
|
|
@@ -12470,13 +12470,13 @@ var strictRules = {
|
|
|
12470
12470
|
"@sarj/prefer-whole-object-assertion": "error",
|
|
12471
12471
|
"@sarj/prefer-zod-enum": "error",
|
|
12472
12472
|
"@sarj/prefer-zod-infer": "error",
|
|
12473
|
-
"@sarj/require-assert-never": "
|
|
12473
|
+
"@sarj/require-assert-never": "error",
|
|
12474
12474
|
"@sarj/require-fetch-timeout": "error",
|
|
12475
|
-
"@sarj/require-interface-for-injected-service": "
|
|
12475
|
+
"@sarj/require-interface-for-injected-service": "error",
|
|
12476
12476
|
"@sarj/require-static-next-matcher": "error",
|
|
12477
12477
|
"@sarj/require-zod-form-validation": "error",
|
|
12478
12478
|
"@sarj/store-insert-requires-on-conflict": "error",
|
|
12479
|
-
"@sarj/stepdown": "
|
|
12479
|
+
"@sarj/stepdown": "error",
|
|
12480
12480
|
"@sarj/zod-naming-convention": "error"
|
|
12481
12481
|
};
|
|
12482
12482
|
var plugin = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sarj/eslint-plugin",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.1",
|
|
4
4
|
"packageManager": "npm@11.19.0",
|
|
5
5
|
"description": "Custom ESLint rules for hypermodern TypeScript / React / Next.js projects",
|
|
6
6
|
"type": "module",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"build": "tsup",
|
|
37
37
|
"dogfood": "npm run build && eslint --config eslint.dogfood.config.mjs src tests eslint.config.mjs eslint.dogfood.config.mjs tsup.config.ts vitest.config.ts --max-warnings 0 && node -e \"import('./dist/index.js').then(({default:p}) => console.log('dogfood: '+Object.keys(p.rules).length+' TypeScript rules, 0 diagnostics'))\"",
|
|
38
38
|
"lint": "eslint . --max-warnings 0",
|
|
39
|
-
"prepack": "npm run
|
|
39
|
+
"prepack": "npm run verify-package",
|
|
40
40
|
"test": "vitest run",
|
|
41
41
|
"typecheck": "tsc --noEmit",
|
|
42
42
|
"verify-package": "node -e \"const fs=require('node:fs'),p=require('./package.json'),walk=x=>typeof x==='string'?[x]:x&&typeof x==='object'?Object.values(x).flatMap(walk):[];for(const file of new Set([p.main,p.module,p.types,...walk(p.exports)].filter(Boolean).map(x=>x.startsWith('./')?x.slice(2):x))){if(!file.startsWith('dist/'))throw new Error('export must live under dist: '+file);const stat=fs.statSync(file);if(!stat.isFile()||stat.size===0)throw new Error('missing or empty export: '+file)}\""
|
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
"overrides": {
|
|
97
97
|
"brace-expansion@^5.0.0": "5.0.9",
|
|
98
98
|
"esbuild": "^0.28.1",
|
|
99
|
+
"nanoid@<3.3.17": "3.3.17",
|
|
99
100
|
"eslint-plugin-react": {
|
|
100
101
|
"eslint": "$eslint"
|
|
101
102
|
}
|