@jameswyse/oxc-config 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -186
- package/REFERENCE.md +105 -132
- package/dist/index.js +26 -0
- package/dist/lint.d.ts +1 -0
- package/dist/lint.js +124 -4
- package/dist/rules/electron-no-remote-module.js +3 -6
- package/dist/rules/explicit-api-states.js +7 -1
- package/dist/rules/import-boundaries.js +31 -6
- package/dist/rules/no-ambient-clock.js +104 -8
- package/dist/rules/no-derived-test-expectation.d.ts +1 -0
- package/dist/rules/no-derived-test-expectation.js +136 -0
- package/dist/rules/no-disabled-tls-verification.d.ts +1 -0
- package/dist/rules/no-disabled-tls-verification.js +42 -0
- package/dist/rules/no-env-access.js +62 -5
- package/dist/rules/no-fixed-test-delay.js +46 -5
- package/dist/rules/no-generic-object-guard.d.ts +1 -0
- package/dist/rules/no-generic-object-guard.js +279 -0
- package/dist/rules/no-get-password-form.d.ts +1 -0
- package/dist/rules/no-get-password-form.js +113 -0
- package/dist/rules/no-hardcoded-credential.d.ts +1 -0
- package/dist/rules/no-hardcoded-credential.js +45 -0
- package/dist/rules/no-import-time-effects.d.ts +1 -0
- package/dist/rules/no-import-time-effects.js +90 -0
- package/dist/rules/no-optional-test-action.d.ts +1 -0
- package/dist/rules/no-optional-test-action.js +45 -0
- package/dist/rules/no-secret-fallback.d.ts +1 -0
- package/dist/rules/no-secret-fallback.js +64 -0
- package/dist/rules/no-swallowed-errors.js +131 -16
- package/dist/rules/no-test-timeout-overrides.js +22 -9
- package/dist/rules/no-unchecked-fetch-response.d.ts +1 -0
- package/dist/rules/no-unchecked-fetch-response.js +91 -0
- package/dist/rules/no-unchecked-index-search.d.ts +1 -0
- package/dist/rules/no-unchecked-index-search.js +41 -0
- package/dist/rules/no-uncontrolled-test-clock.d.ts +1 -0
- package/dist/rules/no-uncontrolled-test-clock.js +112 -0
- package/dist/rules/no-unsettled-promise.d.ts +1 -0
- package/dist/rules/no-unsettled-promise.js +64 -0
- package/dist/rules/require-suppression-reason.d.ts +1 -0
- package/dist/rules/require-suppression-reason.js +32 -0
- package/dist/shared/index.d.ts +14 -1
- package/dist/shared/index.js +231 -91
- package/dist/vendor/anti-slop/effect/rules/no-service-constructor-imports.js +10 -2
- package/dist/vendor/anti-slop/rules/no-known-value-widening.js +1 -1
- package/dist/vendor/anti-slop/rules/no-module-mocking.js +56 -1
- package/dist/vendor/anti-slop/rules/no-runtime-typeof.js +30 -1
- package/dist/vendor/anti-slop/rules/no-shape-in-symbol-names.js +28 -1
- package/dist/vendor/anti-slop/rules/no-unknown-returns.js +1 -1
- package/dist/vendor/anti-slop/rules/no-unsafe-dictionary-type.js +2 -2
- package/dist/vendor/anti-slop/shared/dictionary-types.js +72 -89
- package/dist/vendor/anti-slop/shared/type-alias-resolution.d.ts +8 -2
- package/dist/vendor/anti-slop/shared/type-alias-resolution.js +2 -2
- package/package.json +7 -7
package/REFERENCE.md
CHANGED
|
@@ -1,134 +1,107 @@
|
|
|
1
1
|
# Rule reference
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
no-
|
|
86
|
-
no-
|
|
87
|
-
no-
|
|
88
|
-
no-
|
|
89
|
-
no-
|
|
90
|
-
no-
|
|
91
|
-
no-
|
|
92
|
-
|
|
93
|
-
no-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
no-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
`no-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
These policies are enforced once a project names the actual owners. They are intentionally not universal defaults:
|
|
110
|
-
|
|
111
|
-
| Policy | Mechanism | Required project information |
|
|
112
|
-
| --------------------------------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------- |
|
|
113
|
-
| Parse configuration at startup | `env` option | Modules that own configuration parsing |
|
|
114
|
-
| Keep privileged modules out of other runtimes | `boundaries` option | Each runtime's file scope, and the packages, aliases and paths it must not import |
|
|
115
|
-
| Require access checks before server actions | `serverActionGuards` option | The guard functions that perform authorisation |
|
|
116
|
-
| Control time and randomness | `clock` and `random` options | Modules that own the clock and ID or random generation |
|
|
117
|
-
| Harden Electron apps | `electron` option | Renderer globs when they are not `src/renderer/**` |
|
|
118
|
-
| Generated assets and style imports | Shared ignores plus local patterns; Oxfmt Tailwind configuration | Actual generators, CSS preprocessors, Tailwind config or stylesheet |
|
|
119
|
-
|
|
120
|
-
## Compiler settings and review work
|
|
121
|
-
|
|
122
|
-
For new TypeScript projects, use `strict`, `noUncheckedIndexedAccess`, `exactOptionalPropertyTypes`, `noImplicitOverride` and `noFallthroughCasesInSwitch`. The package exports them as `@jameswyse/oxc-config/tsconfig` for a project's `tsconfig.json` to extend. Lint configuration never applies them, because changing them in an existing project is a deliberate migration.
|
|
123
|
-
|
|
124
|
-
Lint cannot establish correct authorisation, tenant isolation, schema validation, secret redaction, transaction boundaries, idempotency, crash recovery, concurrency ownership, dependency justification, useful module depth, constructive domain modelling or independent test oracles. These remain review and verification work. File naming, positional parameters, boolean inputs, `Partial<T>`, wrappers and abstraction counts have legitimate domain/framework exceptions and are not rejected through universal heuristics.
|
|
125
|
-
|
|
126
|
-
## Oxc API references
|
|
127
|
-
|
|
128
|
-
The implementation follows the current [Oxlint configuration API](https://oxc.rs/docs/guide/usage/linter/config.html), [JS plugin API](https://oxc.rs/docs/guide/usage/linter/writing-js-plugins.html), [type-aware setup](https://oxc.rs/docs/guide/usage/linter/type-aware.html), and [Oxfmt options](https://oxc.rs/docs/guide/usage/formatter/config-file-reference.html). Absolute plugin specifiers keep imported configs independent of the consumer's working directory. Side-effect import sorting is explicitly disabled.
|
|
129
|
-
|
|
130
|
-
## Rules considered and dropped
|
|
131
|
-
|
|
132
|
-
`no-call-count-assertions` would have rejected `toHaveBeenCalledTimes`, `toHaveBeenNthCalledWith` and `mock.calls` counting. On three codebases, 36 of 40 sampled findings were legitimate: the count was the behaviour under test, such as caching, retry, deduplication or firing once. No syntax separated them from incidental counts, so it was dropped.
|
|
133
|
-
|
|
134
|
-
Rules for safety comments on type assertions, a blank line between every top-level statement, and rejecting `unknown` parameters are not included. The first conflicts with `no-comments`, the second split deliberate groups of related declarations, and the third rejected legitimate unparsed input seams. Effect rules that reject `_tag` comparisons, prefer `Match` or reject literal tagged construction are not included either, because discriminant checks are the preferred way to narrow a union and TypeScript already checks literal variants.
|
|
3
|
+
Rules are errors, which fail the run, unless marked as warnings. Warnings flag patterns that have legitimate uses, so they report without failing. Custom rules use the `wyse/` prefix. Each one's tests sit beside it in `src/rules` or `src/vendor/anti-slop/rules` and show exactly what it reports.
|
|
4
|
+
|
|
5
|
+
Framework profiles and project options add rules only when enabled. The [configuration guide](docs/configuration.md) explains how to turn them on.
|
|
6
|
+
|
|
7
|
+
## Base rules
|
|
8
|
+
|
|
9
|
+
Oxlint's correctness and suspicious categories are errors. Unused variables are errors unless their names start with `_`, and suppression comments that no longer suppress anything are errors too. `no-underscore-dangle` is off, so fields such as `_id` and `__typename` stay valid.
|
|
10
|
+
|
|
11
|
+
Native rules also catch legacy and error-prone built-ins: `no-var`, `no-proto`, `no-new-func`, `no-new-wrappers`, `no-array-constructor`, `no-prototype-builtins`, `prefer-object-has-own`, `prefer-rest-params`, `prefer-regex-literals`, `import/no-mutable-exports`, `oxc/no-const-enum`, and Unicorn's `new-for-builtins`, `no-instanceof-array`, `no-new-buffer`, `prefer-node-protocol`, `prefer-import-meta-properties`, `prefer-response-static-json`, `prefer-string-trim-start-end`, `prefer-array-find`, `prefer-array-flat-map` and `prefer-array-some`.
|
|
12
|
+
|
|
13
|
+
## Types and external data
|
|
14
|
+
|
|
15
|
+
Native rules: `typescript/no-explicit-any`, `no-non-null-assertion`, `no-unsafe-function-type` and `no-import-type-side-effects`. `consistent-type-assertions` allows only `as` assertions and rejects them on object and array literals, and `method-signature-style` requires property signatures such as `run: () => void`. `ban-ts-comment` rejects `@ts-ignore` and `@ts-nocheck`, and requires a reason after `--` on `@ts-expect-error`.
|
|
16
|
+
|
|
17
|
+
Type-aware checking, which is on by default, adds the `no-unsafe-*` rules, `no-unsafe-type-assertion`, `no-unnecessary-type-assertion`, `switch-exhaustiveness-check`, `prefer-reduce-type-parameter`, `restrict-plus-operands` with every mixed-type allowance turned off, and `no-unnecessary-condition`, a nursery rule in Oxlint 1.86. `typescript/no-deprecated` is a warning outside tests.
|
|
18
|
+
|
|
19
|
+
- `wyse/no-runtime-typeof` (warning): `typeof` outside a type guard. `typeof x === "undefined"` passes, as does `typeof` on a variable or parameter declared in the same file with a union type that has no `unknown` or `any` member. Turn it off in modules that validate external input.
|
|
20
|
+
- `wyse/no-generic-object-guard`: a named helper such as `isRecord` whose whole body proves only that a value is a non-null object, through `typeof`, `instanceof Object`, prototype or `Object.prototype.toString` checks. Guards that also check a field pass, as do inline callbacks. It also reports any guard that takes `unknown` or `any` and claims a specific type while only checking that the value exists, or always returns `true`.
|
|
21
|
+
- `wyse/no-hardcoded-credential`: a string containing a private key or a token in a well-known format, such as an AWS access key or a GitHub, Stripe live, Slack, Google, Anthropic or OpenAI key. Placeholders containing `example`, `fake`, `dummy`, `placeholder`, `redacted` or a run such as `abcdefgh` pass.
|
|
22
|
+
- `wyse/no-disabled-tls-verification`: `rejectUnauthorized: false`, or setting `NODE_TLS_REJECT_UNAUTHORIZED` to `"0"`.
|
|
23
|
+
- `wyse/no-secret-fallback`: a string fallback for an environment variable whose name contains `SECRET`, `TOKEN`, `PASSWORD`, `PRIVATE`, `CREDENTIAL`, `SALT`, `SIGNING` or `API_KEY`, or ends in `KEY`, such as `process.env.SESSION_SECRET ?? "dev"` or a destructuring default.
|
|
24
|
+
- `wyse/type-guard-name`: a named type predicate such as `checkUser(value): value is User`. Names such as `isUser` and `hasId` pass, as do assertion functions and anonymous callbacks.
|
|
25
|
+
- `wyse/no-unknown-returns`: a declared return type of `unknown` or `Promise<unknown>`.
|
|
26
|
+
- `wyse/no-unknown-type-aliases`: a type alias that resolves to `unknown`.
|
|
27
|
+
- `wyse/no-unsafe-dictionary-type`: a dictionary type whose values are `unknown`, `any`, `object` or `{}`.
|
|
28
|
+
- `wyse/no-object-parameters`: a parameter typed `object`, directly or through an alias.
|
|
29
|
+
- `wyse/no-known-value-widening`: a known value stored under a broader declared type, such as `const value: unknown = {}`.
|
|
30
|
+
- `wyse/no-widen-then-assert`: widening a known value, then asserting it to a narrower type.
|
|
31
|
+
- `wyse/no-chained-type-assertions`: chained assertions such as `value as unknown as User`.
|
|
32
|
+
- `wyse/no-reflect-apply` and `wyse/no-reflect-get`: `Reflect.apply` and `Reflect.get`.
|
|
33
|
+
|
|
34
|
+
These custom rules check one file at a time, without type information from other files. None of them bans `unknown` outright or rejects `as const`.
|
|
35
|
+
|
|
36
|
+
## Control flow and errors
|
|
37
|
+
|
|
38
|
+
Native rules: `curly`, `eqeqeq`, `no-empty`, `no-useless-catch`, Oxlint's promise checks, `array-callback-return`, `no-case-declarations`, `no-constructor-return`, `no-fallthrough`, `no-loop-func`, `no-self-compare`, `no-unreachable-loop`, `no-useless-assignment` and `unicorn/error-message`. JavaScript files also get `no-throw-literal` and `prefer-promise-reject-errors`. Type-aware checking adds floating and misused promise checks, `await-thenable`, `return-await`, `only-throw-error`, `prefer-promise-reject-errors` and `use-unknown-in-catch-callback-variable`.
|
|
39
|
+
|
|
40
|
+
- `wyse/no-deep-ternary`: a ternary nested inside two others. It replaces Oxlint's nested-ternary rule, which conflicts with Oxfmt over parentheses.
|
|
41
|
+
- `wyse/no-swallowed-errors` (warning): a `catch` that only returns a fallback literal, a `.catch` callback or `.then` rejection callback that is empty or only returns one, and `Promise.allSettled` results that are never read. Effect's `orElseSucceed`, `orElse`, `catchAll` and `catchAllCause` count when they recover to a fallback literal or `Effect.void`. Built-in parser and filesystem-probe `try` blocks, `response.json()`, `.catch` on a promise another caller also receives, and Effect's `catchTag` all pass.
|
|
42
|
+
- `wyse/explicit-api-states` (warning): a boolean parameter on an exported function, exported class constructor or public method. Destructured parameters, accessors, private members, overloads, the subject of an `asserts` or `is` return type, and the final boolean of a `set*` or `update*` function pass.
|
|
43
|
+
- `wyse/no-unsettled-promise`: a `new Promise` executor that runs code but never calls `resolve` or `reject`, or calls them only inside an optional call such as `server?.close(resolve)`. Executors that do nothing, such as `() => {}`, pass. Test files aren't checked.
|
|
44
|
+
- `wyse/no-unchecked-index-search`: an `indexOf`, `lastIndexOf`, `findIndex` or `findLastIndex` result passed straight to `splice`, `toSpliced`, `with`, `at` or `slice`, where -1 counts from the end.
|
|
45
|
+
- `wyse/no-unchecked-fetch-response`: reading a `fetch` response body with `json()`, `text()` or a similar method without checking `ok` or `status`. A response passed to another function passes. Test files aren't checked.
|
|
46
|
+
|
|
47
|
+
## Modules, files and names
|
|
48
|
+
|
|
49
|
+
Native rules: `import/first`, `import/no-default-export`, `import/no-duplicates`, `import/no-self-import` and `import/no-unassigned-import`. `import/no-cycle` and `oxc/no-barrel-file` are warnings. Default exports are allowed in the files that tools load them from, listed in the [configuration guide](docs/configuration.md#select-framework-and-runtime-profiles).
|
|
50
|
+
|
|
51
|
+
- `wyse/no-forwarding-module` (warning): a module made only of re-exports, or one that re-exports its imports unchanged. Package entrypoints, Next.js `app` special files and `pages`, root `middleware`, `proxy` and `instrumentation` files, and modules with directives or side-effect imports pass.
|
|
52
|
+
- `wyse/no-import-time-effects` (warning): starting a timer, `fetch`, top-level `await`, opening a `BroadcastChannel`, `WebSocket`, `EventSource` or `Worker`, calling `addEventListener` or `listen`, or registering `process.on` handlers when a module is imported, including inside immediately invoked functions and static class members. Config files, scripts, tests, and entrypoints such as `main`, `server`, `worker` and `instrumentation` files and `bin`, `cli`, `deploy`, `tools`, `test`, `e2e` and `fixtures` directories pass.
|
|
53
|
+
- `wyse/no-pass-through-function` (warning): a named function whose body only calls another function with its own parameters, in order. Zero-parameter functions, method calls, type predicates and `useEffectEvent` callees pass.
|
|
54
|
+
- `wyse/no-generic-file-suffix`: a file named `*Contract`, `*Policy`, `policy` or `contract`, in any case style. Test and story files pass, as do header policies such as a content security policy and files that export a binding with the file's name, such as `agentPolicy.ts` exporting `AgentPolicy`.
|
|
55
|
+
- `wyse/no-shape-in-symbol-names`: a name containing "shape", in any letter case.
|
|
56
|
+
|
|
57
|
+
## Comments, suppressions and logging
|
|
58
|
+
|
|
59
|
+
- `wyse/no-comments`: line, block and JSDoc comments. Shebangs, JSDoc type tags in JavaScript files and tool directives pass. The directives include lint suppressions, `@ts-expect-error`, triple-slash references, `#__PURE__`, formatter and coverage ignores, bundler magic comments, and test-environment and JSX pragmas. The `allow` option adds more patterns.
|
|
60
|
+
- `wyse/require-suppression-reason`: an `oxlint-disable` or `eslint-disable` directive that names no rule, or gives no reason after `--`. Oxlint applies a blanket `oxlint-disable` or `oxlint-disable-line` to this rule too, so it can't report those two forms. It does report a blanket `oxlint-disable-next-line`.
|
|
61
|
+
- `eslint/no-console`: console calls outside config files and scripts.
|
|
62
|
+
|
|
63
|
+
## Mutation and copying
|
|
64
|
+
|
|
65
|
+
Native rules: `prefer-const`, `no-param-reassign` and `oxc/no-accumulating-spread`. Type-aware checking adds `prefer-readonly`.
|
|
66
|
+
|
|
67
|
+
- `wyse/no-array-filter-map`: adjacent `filter` and `map` passes over an array.
|
|
68
|
+
- `wyse/no-reduce-accumulator-copy`: copying a reducer's accumulator with `Object.assign`, `Array.from` or an array copy method.
|
|
69
|
+
- `wyse/no-conditional-empty-object-spread`: spreading a conditional empty object to omit fields, such as `...(id ? { id } : {})`.
|
|
70
|
+
|
|
71
|
+
## Project ownership
|
|
72
|
+
|
|
73
|
+
These rules run only once the project names its owners through the [project boundary options](docs/configuration.md#enforce-project-boundaries).
|
|
74
|
+
|
|
75
|
+
- `wyse/no-env-access` (`env`): reading `process.env` or `import.meta.env` outside the owners, config files and scripts. That includes destructuring `env`, `globalThis.process.env`, `global.process.env`, `process["env"]` and `Reflect.get(process, "env")`, including with `"env" as const`, importing `env` from `node:process` or `process`, reading `env` from those modules' default, namespace or literal dynamic import, and re-exporting `env`, the default or the whole module from them with `export { ... } from` or `export * from`. Other `node:process` imports and re-exports, such as `argv`, type-only re-exports, and a `process` property on `window` or `self` pass. It doesn't check that the owner validates what it reads.
|
|
76
|
+
- `wyse/import-boundaries` (`boundaries`): a value import, re-export, literal dynamic import, or `require` call, including a loader made with `createRequire` from `node:module`, that matches a `deny` glob. Type-only imports and `import("…")` types pass unless the boundary sets `types: true`. It doesn't check computed imports.
|
|
77
|
+
- `wyse/server-action-guard` (`serverActionGuards`): a `"use server"` action that doesn't start by awaiting a guard, and indirect or default exports from server-action modules. Non-exported helpers and test files pass.
|
|
78
|
+
- `wyse/no-ambient-clock` (`clock`): `Date.now()`, `Date()` and argument-less `new Date()`, including through `globalThis` or `window`. It also reports argument-less `new TZDate()` and `new TZDateMini()` and one-argument `TZDate.tz(zone)` from `@date-fns/tz`, `@date-fns/tz/date` or `@date-fns/tz/date/mini`, and calls to the date-fns helpers that read the current time: `constructNow`, the `startOf` and `endOf` helpers for today, tomorrow and yesterday, `isToday`, `isTomorrow`, `isYesterday`, `isPast`, `isFuture`, the `isThis*` helpers, `formatDistanceToNow`, `formatDistanceToNowStrict`, `isMatch`, and `isMatch` and `isMatchWithOptions` from `date-fns/fp` at the call that supplies their last curried argument. Helpers count whether they're imported by name, through a namespace, from a `date-fns/<name>` subpath or by literal dynamic import. Re-exporting one of these helpers with `export { ... } from`, or a module that contains one, such as `date-fns` or `date-fns/fp`, with `export * from`, also reports, because calls through the re-export no longer resolve to date-fns. Helpers that compare with a given date, such as `isSameDay`, partly applied `date-fns/fp` helpers, and re-exports of `TZDate`, `TZDateMini`, other date-fns helpers or types pass. Parameter defaults, uncalled `Date.now`, provider functions that only return the read, and test files pass. Parentheses, `as`, `satisfies` and `!` don't change the result, so `(Date.now as typeof Date.now)()` reports and `{ now: () => startOfToday() as Date }` passes.
|
|
79
|
+
- `wyse/no-ambient-random` (`random`): `Math.random()`, `crypto.randomUUID()`, and `randomUUID` or `randomInt` from `node:crypto`. The same exceptions and wrapper handling apply. `randomBytes` and `getRandomValues` pass because they generate secrets.
|
|
80
|
+
|
|
81
|
+
## Tests
|
|
82
|
+
|
|
83
|
+
These rules run on the default test globs, the `tests` paths and the Jest and Vitest profile scopes. The `vitest` and `jest` profiles add native checks for focused, disabled and conditional tests, standalone expectations, valid `expect` calls, interpolated snapshots and redundant async `expect` callbacks. They also require the specific matcher, such as `toStrictEqual` over `toEqual`, `toHaveLength`, `toContain`, and comparison or equality matchers over `toBe(true)`. The `jest` profile rejects `done` callbacks.
|
|
84
|
+
|
|
85
|
+
- `wyse/no-fixed-test-delay`: an awaited literal timer delay, Playwright's `waitForTimeout`, or `yield* Effect.sleep` with a fixed duration. Genuine timer tests need a scoped exception.
|
|
86
|
+
- `wyse/no-vacuous-test-assertions`: an expectation that compares two literals, or the same identifier on both sides of `toBe`, `toEqual` or `toStrictEqual`.
|
|
87
|
+
- `wyse/no-edit-proof-assertions`: an assertion that only proves an import exists or is a function, such as `toBeDefined` on an import, `toBeTypeOf("function")` or `toHaveProperty` on a namespace.
|
|
88
|
+
- `wyse/no-optional-test-action`: a statement directly in a test body that an optional call can skip, such as `button?.click()` or `await dismiss?.click()`. Hooks and callbacks inside the test pass.
|
|
89
|
+
- `wyse/no-derived-test-expectation` (warning): an expected value that calls a function imported from production code, such as `toBe(formatLabel(input))`, directly, through a namespace import or through a `const` such as `expected`. `.not` assertions, functions the actual value also calls, and imports from test, fixture, e2e and helper paths pass.
|
|
90
|
+
- `wyse/no-uncontrolled-test-clock`: `Date.now()` or argument-less `new Date()` in a test file that never calls `useFakeTimers`, `setSystemTime`, `mock.timers.enable`, `clock.install` or `clock.setFixedTime`. Fake timers set up with `apis`, `toFake` or `doNotFake` options that leave `Date` real don't count, and neither does Effect's `TestClock`, which doesn't control `Date`. Playwright and end-to-end files pass.
|
|
91
|
+
- `wyse/no-test-timeout-overrides` (warning): timeout and retry overrides such as `test.setTimeout`, `test.slow()`, `describe.configure`, `vi.setConfig`, `jest.setTimeout` and `jest.retryTimes`. Setting retries to 0 passes. End-to-end files under `e2e/` or named `*.e2e.*` pass.
|
|
92
|
+
- `wyse/companion-has-owner` (warning): a `.test`, `.spec` or `.bench` file with no matching sibling module or directory. Files with an `integration` or `e2e` segment, and files under `tests/`, `test/`, `__tests__/` or `e2e/`, pass.
|
|
93
|
+
- `wyse/no-module-mocking`: Vitest, Jest and `node:test` module mocking. Replace dependencies through real interfaces, or add a file-scoped exception for an external system.
|
|
94
|
+
|
|
95
|
+
## Framework profiles
|
|
96
|
+
|
|
97
|
+
- `react` adds React and React Compiler rules, `jsx-a11y` correctness and suspicious rules, `react-you-might-not-need-an-effect`, and e18e performance rules outside tests. It includes `react/rules-of-hooks` outside end-to-end and `tests` paths, `no-unknown-property`, `checked-requires-onchange-or-readonly` and `jsx-no-useless-fragment`. It also adds `wyse/no-get-password-form`: a `<form>` with a password or one-time-code input that can submit by GET. An input belongs to the form it sits inside, or to the form its `form` attribute names. The form submits by GET when its `action` is missing or a string and its `method` is missing or anything but `post` or `dialog`, or when one of its submit buttons sets `formMethod` to anything but `post` or `dialog`.
|
|
98
|
+
- `nextjs` adds the React rules plus Next.js rules.
|
|
99
|
+
- `effect` adds `wyse/no-manual-effect-error-tag` and `wyse/no-service-constructor-imports`. The second reports a project-local `make*` import used as an uncalled value, such as `yield* makeIssueService`. Calling a `make*` factory with arguments passes.
|
|
100
|
+
- `electron` adds a renderer import boundary and these rules:
|
|
101
|
+
- `wyse/electron-no-remote-module`: `remote` from `electron`, or `@electron/remote`, by import, `require`, dynamic import or re-export.
|
|
102
|
+
- `wyse/electron-secure-web-preferences`: `webPreferences` without literal `contextIsolation: true`, `sandbox: true` and `nodeIntegration: false`, or with web security disabled, insecure content, or experimental or Blink features enabled. Later keys, spreads and computed keys that override these settings are reported too. Preferences passed from a variable the rule can't resolve pass.
|
|
103
|
+
- `wyse/electron-no-raw-ipc-renderer-exposure`: exposing `ipcRenderer` or its methods through `contextBridge`, forwarding renderer-chosen channels or arguments, or passing renderer callbacks straight to `on` or `once`.
|
|
104
|
+
|
|
105
|
+
## Formatting
|
|
106
|
+
|
|
107
|
+
Oxfmt formats the code. `wyse/statement-spacing` requires a blank line after the imports, around multiline blocks and declarations, and before `return`. Consecutive imports, consecutive one-line statements, and a type alias directly after the multiline declaration it derives from stay together. It's the only custom rule with an autofix.
|
package/dist/index.js
CHANGED
|
@@ -10,15 +10,28 @@ import { noAmbientClock } from "./rules/no-ambient-clock.js";
|
|
|
10
10
|
import { noAmbientRandom } from "./rules/no-ambient-random.js";
|
|
11
11
|
import { noComments } from "./rules/no-comments.js";
|
|
12
12
|
import { noDeepTernary } from "./rules/no-deep-ternary.js";
|
|
13
|
+
import { noDerivedTestExpectation } from "./rules/no-derived-test-expectation.js";
|
|
14
|
+
import { noDisabledTlsVerification } from "./rules/no-disabled-tls-verification.js";
|
|
13
15
|
import { noEditProofAssertions } from "./rules/no-edit-proof-assertions.js";
|
|
14
16
|
import { noEnvAccess } from "./rules/no-env-access.js";
|
|
15
17
|
import { noFixedTestDelay } from "./rules/no-fixed-test-delay.js";
|
|
16
18
|
import { noForwardingModule } from "./rules/no-forwarding-module.js";
|
|
17
19
|
import { noGenericFileSuffix } from "./rules/no-generic-file-suffix.js";
|
|
20
|
+
import { noGenericObjectGuard } from "./rules/no-generic-object-guard.js";
|
|
21
|
+
import { noGetPasswordForm } from "./rules/no-get-password-form.js";
|
|
22
|
+
import { noHardcodedCredential } from "./rules/no-hardcoded-credential.js";
|
|
23
|
+
import { noImportTimeEffects } from "./rules/no-import-time-effects.js";
|
|
24
|
+
import { noOptionalTestAction } from "./rules/no-optional-test-action.js";
|
|
18
25
|
import { noPassThroughFunction } from "./rules/no-pass-through-function.js";
|
|
26
|
+
import { noSecretFallback } from "./rules/no-secret-fallback.js";
|
|
19
27
|
import { noSwallowedErrors } from "./rules/no-swallowed-errors.js";
|
|
20
28
|
import { noTestTimeoutOverrides } from "./rules/no-test-timeout-overrides.js";
|
|
29
|
+
import { noUncheckedFetchResponse } from "./rules/no-unchecked-fetch-response.js";
|
|
30
|
+
import { noUncheckedIndexSearch } from "./rules/no-unchecked-index-search.js";
|
|
31
|
+
import { noUncontrolledTestClock } from "./rules/no-uncontrolled-test-clock.js";
|
|
32
|
+
import { noUnsettledPromise } from "./rules/no-unsettled-promise.js";
|
|
21
33
|
import { noVacuousTestAssertions } from "./rules/no-vacuous-test-assertions.js";
|
|
34
|
+
import { requireSuppressionReason } from "./rules/require-suppression-reason.js";
|
|
22
35
|
import { serverActionGuard } from "./rules/server-action-guard.js";
|
|
23
36
|
import { statementSpacing } from "./rules/statement-spacing.js";
|
|
24
37
|
import { typeGuardName } from "./rules/type-guard-name.js";
|
|
@@ -66,29 +79,42 @@ const wyse = definePlugin({
|
|
|
66
79
|
"no-comments": noComments,
|
|
67
80
|
"no-conditional-empty-object-spread": noConditionalEmptyObjectSpread,
|
|
68
81
|
"no-deep-ternary": noDeepTernary,
|
|
82
|
+
"no-derived-test-expectation": noDerivedTestExpectation,
|
|
83
|
+
"no-disabled-tls-verification": noDisabledTlsVerification,
|
|
69
84
|
"no-edit-proof-assertions": noEditProofAssertions,
|
|
70
85
|
"no-env-access": noEnvAccess,
|
|
71
86
|
"no-fixed-test-delay": noFixedTestDelay,
|
|
72
87
|
"no-forwarding-module": noForwardingModule,
|
|
73
88
|
"no-generic-file-suffix": noGenericFileSuffix,
|
|
89
|
+
"no-generic-object-guard": noGenericObjectGuard,
|
|
90
|
+
"no-get-password-form": noGetPasswordForm,
|
|
91
|
+
"no-hardcoded-credential": noHardcodedCredential,
|
|
92
|
+
"no-import-time-effects": noImportTimeEffects,
|
|
74
93
|
"no-known-value-widening": noKnownValueWidening,
|
|
75
94
|
"no-manual-effect-error-tag": noManualEffectErrorTag,
|
|
76
95
|
"no-module-mocking": noModuleMocking,
|
|
77
96
|
"no-object-parameters": noObjectParameters,
|
|
97
|
+
"no-optional-test-action": noOptionalTestAction,
|
|
78
98
|
"no-pass-through-function": noPassThroughFunction,
|
|
79
99
|
"no-reduce-accumulator-copy": noReduceAccumulatorCopy,
|
|
80
100
|
"no-reflect-apply": noReflectApply,
|
|
81
101
|
"no-reflect-get": noReflectGet,
|
|
82
102
|
"no-runtime-typeof": noRuntimeTypeof,
|
|
103
|
+
"no-secret-fallback": noSecretFallback,
|
|
83
104
|
"no-service-constructor-imports": noServiceConstructorImports,
|
|
84
105
|
"no-shape-in-symbol-names": noForbiddenTermInSymbolNames,
|
|
85
106
|
"no-swallowed-errors": noSwallowedErrors,
|
|
86
107
|
"no-test-timeout-overrides": noTestTimeoutOverrides,
|
|
108
|
+
"no-unchecked-fetch-response": noUncheckedFetchResponse,
|
|
109
|
+
"no-unchecked-index-search": noUncheckedIndexSearch,
|
|
110
|
+
"no-uncontrolled-test-clock": noUncontrolledTestClock,
|
|
87
111
|
"no-unknown-returns": noUnknownReturns,
|
|
88
112
|
"no-unknown-type-aliases": noUnknownTypeAliases,
|
|
89
113
|
"no-unsafe-dictionary-type": noUnsafeDictionaryType,
|
|
114
|
+
"no-unsettled-promise": noUnsettledPromise,
|
|
90
115
|
"no-vacuous-test-assertions": noVacuousTestAssertions,
|
|
91
116
|
"no-widen-then-assert": noWidenThenAssert,
|
|
117
|
+
"require-suppression-reason": requireSuppressionReason,
|
|
92
118
|
"server-action-guard": serverActionGuard,
|
|
93
119
|
"statement-spacing": statementSpacing,
|
|
94
120
|
"type-guard-name": typeGuardName,
|