@commonplaces/oxlint-plugin 0.4.0 → 0.5.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 +96 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/strict-effect.js +17 -0
- package/dist/style.d.ts +4 -0
- package/dist/style.js +38 -0
- package/package.json +13 -8
package/README.md
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
# @commonplaces/oxlint-plugin
|
|
2
2
|
|
|
3
3
|
106 custom Oxlint rules for strict Effect TypeScript, Alchemy and general code
|
|
4
|
-
checks. This package supports **Oxlint 1.
|
|
4
|
+
checks. This package supports **Oxlint 1.86.0 or 1.89.0** and **Node 22.14 or newer**.
|
|
5
5
|
Oxlint's JavaScript plugin API is experimental, so upgrade it only after running
|
|
6
|
-
the rule tests. The development tools use 1.
|
|
7
|
-
|
|
6
|
+
the rule tests. The development tools use 1.89.0; consuming projects may use any supported version.
|
|
7
|
+
Both exact versions are checked with independently installed archives. ESLint is not a supported host.
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
Install
|
|
11
|
+
Install version 0.5.0 and save its exact version:
|
|
12
12
|
|
|
13
13
|
```sh
|
|
14
|
-
npm install --save-dev --save-exact @commonplaces/oxlint-plugin@
|
|
14
|
+
npm install --save-dev --save-exact @commonplaces/oxlint-plugin@0.5.0 oxlint@1.89.0
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Version 0.5.0 adds the optional style preset and the host requirements above.
|
|
18
|
+
Published 0.4.0 keeps its earlier host list. Consumer adoption is a separate step.
|
|
19
|
+
|
|
17
20
|
The manifest and lockfile retain the resolved version. Historical GitHub release
|
|
18
21
|
archives remain separate distribution artefacts; a GitHub release does not publish
|
|
19
22
|
an npm version.
|
|
@@ -46,7 +49,7 @@ project facts.
|
|
|
46
49
|
`defineConfig({ extends: [strict, projectPolicy] })`. It adds no project paths
|
|
47
50
|
or source ignores. Keep exact ownership settings in the consuming project.
|
|
48
51
|
|
|
49
|
-
The root exports these six groups and the `strict` composition. Individual plugins use
|
|
52
|
+
The root exports these six groups, the optional `style` preset and the `strict` composition. Individual plugins use
|
|
50
53
|
the subpaths below. For example, a JSON configuration can enable one rule:
|
|
51
54
|
|
|
52
55
|
```json
|
|
@@ -56,6 +59,93 @@ the subpaths below. For example, a JSON configuration can enable one rule:
|
|
|
56
59
|
}
|
|
57
60
|
```
|
|
58
61
|
|
|
62
|
+
## Optional style preset
|
|
63
|
+
|
|
64
|
+
Add `style` before `strict`, then keep the project's own policy last:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { style, strict } from "@commonplaces/oxlint-plugin";
|
|
68
|
+
import { defineConfig } from "oxlint";
|
|
69
|
+
import project from "./tools/oxlint/project.config.ts";
|
|
70
|
+
|
|
71
|
+
export default defineConfig({ extends: [style, strict, project] });
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Run `oxlint --type-aware --deny-warnings .`. `style` also works alone and is
|
|
75
|
+
available as the default export of `@commonplaces/oxlint-plugin/style`.
|
|
76
|
+
It never imports or extends `strict`; `strict` still contains only its original
|
|
77
|
+
six groups. Adding this release without selecting `style` leaves strict checks
|
|
78
|
+
unchanged. This preset includes more than formatting preferences: Ultracite
|
|
79
|
+
also supplies accessibility, test and correctness checks, browser globals,
|
|
80
|
+
shared ignores and test-file overrides. Its ignores can reduce which files are
|
|
81
|
+
checked; keep the project's own file policy explicit.
|
|
82
|
+
|
|
83
|
+
Ultracite **8.0.1** is an exact regular dependency, selected at the owner's
|
|
84
|
+
request to use the latest releases. It requires no separate consumer install. A peer would
|
|
85
|
+
make consumers choose and install a second package, and could make imports of
|
|
86
|
+
the root package fail when it is missing. The dependency also installs
|
|
87
|
+
Ultracite's CLI dependencies; only the three Oxlint configuration modules run
|
|
88
|
+
when importing this preset. No Ultracite CLI, formatter or Effect runtime runs.
|
|
89
|
+
|
|
90
|
+
### Shared overrides
|
|
91
|
+
|
|
92
|
+
These eleven rules are off in both historical root configurations: Common
|
|
93
|
+
Practice at `3b6beef^` and Site at `dda3820`. File-specific permissions and
|
|
94
|
+
size limits remain in each consumer's project policy.
|
|
95
|
+
|
|
96
|
+
| Rule set to `off` | Reason |
|
|
97
|
+
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
98
|
+
| `unicorn/no-array-for-each` | Allow Effect's immutable `Array.forEach`; strict collection checks cover native mutation. |
|
|
99
|
+
| `unicorn/no-array-sort` | Allow Effect's immutable `Array.sort`; strict collection checks cover native mutation. |
|
|
100
|
+
| `unicorn/throw-new-error` | Allow the `Schema.TaggedError` factory; `strict-effect/error-constructor-new` checks error construction when strict is selected. |
|
|
101
|
+
| `no-redeclare` | Allow TypeScript overloads and merged declarations. |
|
|
102
|
+
| `react/function-component-definition` | Allow the project's existing component declaration forms. |
|
|
103
|
+
| `sort-keys` | Keep related object fields in meaningful order. |
|
|
104
|
+
| `func-names` | Allow unnamed library callbacks and Effect generators. |
|
|
105
|
+
| `func-style` | Allow function declarations and functions stored in constants. |
|
|
106
|
+
| `no-use-before-define` | Allow declarations to refer to later declarations. |
|
|
107
|
+
| `no-inline-comments` | Allow short explanations beside the code they describe. |
|
|
108
|
+
| `typescript/consistent-return` | Leave return types and Effect generator branches to TypeScript. |
|
|
109
|
+
|
|
110
|
+
### Supported-host adjustments
|
|
111
|
+
|
|
112
|
+
The imported configurations need two small adjustments; these are separate
|
|
113
|
+
from the eleven shared overrides above:
|
|
114
|
+
|
|
115
|
+
- React's explicit disables for `jsx-a11y/no-autofocus` and
|
|
116
|
+
`react/forward-ref-uses-ref` are omitted. This lets the host's correctness
|
|
117
|
+
settings apply: selecting `strict` keeps both at error level. Merely putting
|
|
118
|
+
`strict` last would not overcome an explicit upstream disable when strict
|
|
119
|
+
enables a rule through its correctness category.
|
|
120
|
+
- Vitest's file override disabling `vitest/valid-title` is also omitted, so
|
|
121
|
+
strict's correctness setting still applies inside test files.
|
|
122
|
+
|
|
123
|
+
The tests install the packed archive on both supported hosts and compare
|
|
124
|
+
every resolved strict rule, including its options, with `[style, strict]`.
|
|
125
|
+
They also check inherited file overrides. These adjustments import no strict
|
|
126
|
+
settings and leave every other upstream setting intact.
|
|
127
|
+
|
|
128
|
+
### Ultracite 8.0.1 comparison
|
|
129
|
+
|
|
130
|
+
The installed npm archives were compared, including rule options and file
|
|
131
|
+
patterns, rather than relying on release notes. For the three selected presets:
|
|
132
|
+
|
|
133
|
+
| Preset | Rules in 7.12.0 | Rules in 8.0.1 | Change |
|
|
134
|
+
| ------ | --------------: | -------------: | ------------------------------------------------------------- |
|
|
135
|
+
| Core | 536 | 537 | Adds `typescript/no-generated-empty-object-type` as an error. |
|
|
136
|
+
| React | 124 | 124 | `react/jsx-no-target-blank` adds `{ forms: true }`. |
|
|
137
|
+
| Vitest | 74 | 75 | Adds `vitest/consistent-test-it` as an error. |
|
|
138
|
+
|
|
139
|
+
Counts include entries explicitly set to off and entries in file overrides.
|
|
140
|
+
No rule is removed and no other rule severity or option changes. Core's shared
|
|
141
|
+
test overrides and Vitest's test rules also start matching `.mts`, `.cts`,
|
|
142
|
+
`.mjs` and `.cjs` files. Shared ignores, globals and plugin lists are unchanged.
|
|
143
|
+
Both versions contain `no-unmodified-loop-condition` with
|
|
144
|
+
`checkConditionalExpressions: true`; the supported hosts accept that option.
|
|
145
|
+
Ultracite 8 requires Oxlint 1.86 or newer, so 1.80 and 1.85 are no longer
|
|
146
|
+
supported. Its Oxfmt peer requires at least 0.71; repository tooling uses 0.74.0.
|
|
147
|
+
The archive is checked on exactly 1.86.0 and the current 1.89.0.
|
|
148
|
+
|
|
59
149
|
## Project settings
|
|
60
150
|
|
|
61
151
|
Rules that refer to project files, schemas or routes are available but excluded
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/strict-effect.js
CHANGED
|
@@ -596,6 +596,23 @@ const layerExpression = (context, expression, visited = []) => {
|
|
|
596
596
|
if (Array.isReadonlyArrayEmpty(expression.arguments)) {
|
|
597
597
|
return layerExpression(context, expression.callee.object, next);
|
|
598
598
|
}
|
|
599
|
+
// Completed Match.value pipelines return their branch values, including
|
|
600
|
+
// Layers. Inline native callbacks remain allowed; an owned factory does not.
|
|
601
|
+
const completesMatch = Array.last(expression.arguments).pipe(Option.exists((argument) => scopedEffectReference(context, argument.type === "CallExpression" ? argument.callee : argument).pipe(Option.exists((reference) => isExport(reference, "effect/Match", "exhaustive") ||
|
|
602
|
+
isExport(reference, "effect/Match", "orElse")))));
|
|
603
|
+
const valueMatch = expression.callee.object.type === "CallExpression" &&
|
|
604
|
+
scopedEffectReference(context, expression.callee.object.callee).pipe(Option.exists((reference) => isExport(reference, "effect/Match", "value")));
|
|
605
|
+
const branchReturnsLayer = (argument) => argument.type === "CallExpression" &&
|
|
606
|
+
scopedEffectReference(context, argument.callee).pipe(Option.exists((reference) => reference.module === "effect/Match")) &&
|
|
607
|
+
Array.some((callback) => (callback.type === "ArrowFunctionExpression" || callback.type === "FunctionExpression") &&
|
|
608
|
+
Option.fromNullishOr(callback.body).pipe(Option.exists((body) => body.type === "BlockStatement"
|
|
609
|
+
? returnsLayer(context, body)
|
|
610
|
+
: layerExpression(context, body, next))))(argument.arguments);
|
|
611
|
+
if (valueMatch &&
|
|
612
|
+
completesMatch &&
|
|
613
|
+
Array.some(branchReturnsLayer)(expression.arguments)) {
|
|
614
|
+
return true;
|
|
615
|
+
}
|
|
599
616
|
return transforms(expression.arguments);
|
|
600
617
|
}
|
|
601
618
|
return false;
|
package/dist/style.d.ts
ADDED
package/dist/style.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Array, Record } from "effect";
|
|
2
|
+
import core from "ultracite/oxlint/core";
|
|
3
|
+
import react from "ultracite/oxlint/react";
|
|
4
|
+
import vitest from "ultracite/oxlint/vitest";
|
|
5
|
+
/** Optional shared style checks. Extend before strict and the project policy. */
|
|
6
|
+
const style = {
|
|
7
|
+
extends: [
|
|
8
|
+
core,
|
|
9
|
+
{
|
|
10
|
+
...react,
|
|
11
|
+
// Leave these correctness rules to the host category settings. Explicit
|
|
12
|
+
// upstream "off" values would beat strict's correctness category.
|
|
13
|
+
rules: Record.filter(react.rules ?? {}, (_, name) => name !== "jsx-a11y/no-autofocus" && name !== "react/forward-ref-uses-ref"),
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
...vitest,
|
|
17
|
+
// Keep the host's correctness check for test titles in test files too.
|
|
18
|
+
overrides: Array.map(vitest.overrides ?? [], (override) => ({
|
|
19
|
+
...override,
|
|
20
|
+
rules: Record.filter(override.rules ?? {}, (_, name) => name !== "vitest/valid-title"),
|
|
21
|
+
})),
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
rules: {
|
|
25
|
+
"unicorn/no-array-for-each": "off",
|
|
26
|
+
"unicorn/no-array-sort": "off",
|
|
27
|
+
"unicorn/throw-new-error": "off",
|
|
28
|
+
"no-redeclare": "off",
|
|
29
|
+
"react/function-component-definition": "off",
|
|
30
|
+
"sort-keys": "off",
|
|
31
|
+
"func-names": "off",
|
|
32
|
+
"func-style": "off",
|
|
33
|
+
"no-use-before-define": "off",
|
|
34
|
+
"no-inline-comments": "off",
|
|
35
|
+
"typescript/consistent-return": "off",
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
export default style;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commonplaces/oxlint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Shared Oxlint rules for strict Effect TypeScript, Alchemy and repository code.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Cooper Corbett",
|
|
@@ -56,6 +56,10 @@
|
|
|
56
56
|
"./anti-slop-effect": {
|
|
57
57
|
"types": "./dist/anti-slop/effect/index.d.ts",
|
|
58
58
|
"default": "./dist/anti-slop/effect/index.js"
|
|
59
|
+
},
|
|
60
|
+
"./style": {
|
|
61
|
+
"types": "./dist/style.d.ts",
|
|
62
|
+
"default": "./dist/style.js"
|
|
59
63
|
}
|
|
60
64
|
},
|
|
61
65
|
"publishConfig": {
|
|
@@ -68,18 +72,19 @@
|
|
|
68
72
|
"prepack": "bun run build"
|
|
69
73
|
},
|
|
70
74
|
"dependencies": {
|
|
71
|
-
"@oxlint/plugins": "1.
|
|
72
|
-
"effect": "4.0.
|
|
75
|
+
"@oxlint/plugins": "1.89.0",
|
|
76
|
+
"effect": "4.0.5",
|
|
77
|
+
"ultracite": "8.0.1"
|
|
73
78
|
},
|
|
74
79
|
"devDependencies": {
|
|
75
|
-
"@effect/platform-node": "4.0.
|
|
76
|
-
"@effect/vitest": "4.0.
|
|
77
|
-
"@types/bun": "1.4.
|
|
80
|
+
"@effect/platform-node": "4.0.5",
|
|
81
|
+
"@effect/vitest": "4.0.5",
|
|
82
|
+
"@types/bun": "1.4.3",
|
|
78
83
|
"typescript": "7.0.2",
|
|
79
|
-
"vitest": "5.0.
|
|
84
|
+
"vitest": "5.0.5"
|
|
80
85
|
},
|
|
81
86
|
"peerDependencies": {
|
|
82
|
-
"oxlint": "1.
|
|
87
|
+
"oxlint": "1.86.0 || 1.89.0"
|
|
83
88
|
},
|
|
84
89
|
"engines": {
|
|
85
90
|
"node": ">=22.14.0"
|