@commonplaces/oxlint-plugin 0.8.0 → 0.9.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 +18 -11
- package/dist/service-instrumentation.js +39 -21
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @commonplaces/oxlint-plugin
|
|
2
2
|
|
|
3
3
|
108 custom Oxlint rules for strict Effect TypeScript, Alchemy and general code
|
|
4
|
-
checks. Version 0.
|
|
4
|
+
checks. Version 0.9.0 supports **Oxlint 1.88.0, 1.89.0 or 1.90.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.
|
|
6
|
+
the rule tests. The development tools use 1.90.0; consuming projects may use any supported version.
|
|
7
7
|
All three exact versions are checked with independently installed archives. ESLint is not a supported host.
|
|
8
8
|
|
|
9
9
|
Version 0.6.0 adds native Effect correctness and immutable accumulation checks.
|
|
@@ -12,15 +12,17 @@ Effect setup below after dependency installation.
|
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
15
|
-
Install version 0.
|
|
15
|
+
Install version 0.9.0 and save its exact version:
|
|
16
16
|
|
|
17
17
|
```sh
|
|
18
|
-
npm install --save-dev --save-exact @commonplaces/oxlint-plugin@0.
|
|
19
|
-
@effect/tsgo@0.
|
|
18
|
+
npm install --save-dev --save-exact @commonplaces/oxlint-plugin@0.9.0 \
|
|
19
|
+
@effect/tsgo@0.63.0 oxlint@1.90.0 oxlint-tsgolint@7.0.2005 typescript@7.0.2
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
-
Version 0.
|
|
23
|
-
keep their earlier host lists.
|
|
22
|
+
Version 0.9.0 supports exactly Oxlint 1.88.0, 1.89.0 or 1.90.0. Older releases
|
|
23
|
+
keep their earlier host lists. Version 0.9.0 removes 1.87.0 because the native
|
|
24
|
+
Effect checker no longer supports it. Upgrade Oxlint before adopting this release.
|
|
25
|
+
Consumer adoption is a separate step.
|
|
24
26
|
|
|
25
27
|
The manifest and lockfile retain the resolved version. Historical GitHub release
|
|
26
28
|
archives remain separate distribution artefacts; a GitHub release does not publish
|
|
@@ -67,18 +69,18 @@ the subpaths below. For example, a JSON configuration can enable one rule:
|
|
|
67
69
|
## Native Effect correctness
|
|
68
70
|
|
|
69
71
|
Both `effect` and `strict` include every check in the pinned
|
|
70
|
-
`@effect/tsgo` **0.
|
|
72
|
+
`@effect/tsgo` **0.63.0** correctness preset, all at error level. This catches
|
|
71
73
|
forgotten Effect programs, incorrect generator yields, unhandled errors and
|
|
72
74
|
requirements, unchecked Effect type assertions, missing Schema class brands and
|
|
73
75
|
unstable APIs. Type-aware checking is enabled by the group itself; consumers
|
|
74
76
|
do not need to import another preset. Upstream's unrelated style and maintainer
|
|
75
77
|
preferences are not added to the public group.
|
|
76
78
|
|
|
77
|
-
The package ships `@effect/tsgo` **0.
|
|
79
|
+
The package ships `@effect/tsgo` **0.63.0** and `oxlint-tsgolint` **7.0.2005**
|
|
78
80
|
as exact regular dependencies. Full Effect projects should also declare their
|
|
79
81
|
compiler and checker tools directly, as in the install command above. This
|
|
80
82
|
keeps the selected local tools explicit. The pinned checker supports TypeScript
|
|
81
|
-
**7.0.2** or **7.1.0-dev.
|
|
83
|
+
**7.0.2**, **7.1.0-beta** or **7.1.0-dev.20261028.1**, alongside the three Oxlint versions above.
|
|
82
84
|
The archive tests use TypeScript 7.0.2.
|
|
83
85
|
Check the installed checker's supported versions before changing these tools.
|
|
84
86
|
|
|
@@ -250,7 +252,7 @@ Both versions contain `no-unmodified-loop-condition` with
|
|
|
250
252
|
`checkConditionalExpressions: true`; the supported hosts accept that option.
|
|
251
253
|
Ultracite 8 requires Oxlint 1.86 or newer, so 1.80 and 1.85 are no longer
|
|
252
254
|
supported. Its Oxfmt peer requires at least 0.71; repository tooling uses 0.74.0.
|
|
253
|
-
The current archive is checked on exactly 1.
|
|
255
|
+
The current archive is checked on exactly 1.88.0, 1.89.0 and 1.90.0, matching the
|
|
254
256
|
pinned native Effect checker. Published 0.5.0 was qualified on 1.86.0 and 1.89.0.
|
|
255
257
|
|
|
256
258
|
## Project settings
|
|
@@ -301,6 +303,11 @@ plus supplied operations in native `Layer.mock` replacements,
|
|
|
301
303
|
preserving canonical names through named imports, namespace imports and immutable
|
|
302
304
|
aliases. Shadowed names cannot borrow import identity. Every explicit operation
|
|
303
305
|
requires its exact `Effect.fn("Orders.create")` or `Effect.withSpan` name.
|
|
306
|
+
Readonly resource groups are traversed recursively, including local immutable
|
|
307
|
+
aliases: `Orders.session.read` requires that full canonical span. Each supplied
|
|
308
|
+
leaf in `Layer.mock` is checked too. Empty resource groups, cyclic groups,
|
|
309
|
+
spreads and dynamic property names fail closed; local nested contract types
|
|
310
|
+
continue to identify data and Stream members.
|
|
304
311
|
Legacy `serviceNames` selection remains available for existing consumers.
|
|
305
312
|
An empty selector is rejected.
|
|
306
313
|
|
|
@@ -206,30 +206,48 @@ export const requireServiceOperationInstrumentation = defineRule({
|
|
|
206
206
|
context.report({ node, messageId: "unsupportedOperation" });
|
|
207
207
|
return;
|
|
208
208
|
}
|
|
209
|
-
|
|
210
|
-
if (
|
|
211
|
-
|
|
209
|
+
const check = (object, prefix, members, visited = []) => {
|
|
210
|
+
if (Array.contains(visited, object) ||
|
|
211
|
+
(visited.length > 0 && object.properties.length === 0)) {
|
|
212
|
+
context.report({ node: object, messageId: "unsupportedOperation" });
|
|
212
213
|
return;
|
|
213
214
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
context
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
215
|
+
Array.forEach(object.properties, (property) => {
|
|
216
|
+
if (property.type !== "Property") {
|
|
217
|
+
context.report({ node: property, messageId: "unsupportedOperation" });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
const key = property.computed && property.key.type !== "Literal"
|
|
221
|
+
? Option.none()
|
|
222
|
+
: propertyName(property.key);
|
|
223
|
+
Option.match(key, {
|
|
224
|
+
onNone: () => context.report({ node: property, messageId: "unsupportedOperation" }),
|
|
225
|
+
onSome: (member) => {
|
|
226
|
+
if (dataMember(context, members, member) ||
|
|
227
|
+
streamValue(context, property.value))
|
|
228
|
+
return;
|
|
229
|
+
const name = `${prefix}.${member}`;
|
|
230
|
+
const value = valueOf(context, property.value);
|
|
231
|
+
if (Option.isSome(value) && value.value.type === "ObjectExpression") {
|
|
232
|
+
const nested = Array.findFirst(members, (field) => field.type === "TSPropertySignature" &&
|
|
233
|
+
Option.contains(propertyName(field.key), member)).pipe(Option.flatMap((field) => field.type === "TSPropertySignature"
|
|
234
|
+
? Option.fromNullishOr(field.typeAnnotation?.typeAnnotation)
|
|
235
|
+
: Option.none()), Option.filter((type) => type.type === "TSTypeLiteral"), Option.map((type) => (type.type === "TSTypeLiteral" ? type.members : [])), Option.getOrElse(() => []));
|
|
236
|
+
check(value.value, name, nested, [...visited, object]);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
if (!instrumented(context, property.value, name) &&
|
|
240
|
+
!adapted(context, property.value, name, options.operationAdapters ?? []))
|
|
241
|
+
context.report({
|
|
242
|
+
node: property,
|
|
243
|
+
messageId: "missingInstrumentation",
|
|
244
|
+
data: { operation: name },
|
|
245
|
+
});
|
|
246
|
+
},
|
|
247
|
+
});
|
|
231
248
|
});
|
|
232
|
-
}
|
|
249
|
+
};
|
|
250
|
+
check(argument.value, owner.name, fields);
|
|
233
251
|
},
|
|
234
252
|
});
|
|
235
253
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commonplaces/oxlint-plugin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "Shared Oxlint rules for strict Effect TypeScript, Alchemy and repository code.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Cooper Corbett",
|
|
@@ -72,10 +72,10 @@
|
|
|
72
72
|
"prepack": "bun run build"
|
|
73
73
|
},
|
|
74
74
|
"dependencies": {
|
|
75
|
-
"@effect/tsgo": "0.
|
|
76
|
-
"@oxlint/plugins": "1.
|
|
75
|
+
"@effect/tsgo": "0.63.0",
|
|
76
|
+
"@oxlint/plugins": "1.90.0",
|
|
77
77
|
"effect": "4.0.5",
|
|
78
|
-
"oxlint-tsgolint": "7.0.
|
|
78
|
+
"oxlint-tsgolint": "7.0.2005",
|
|
79
79
|
"ultracite": "8.0.1"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
@@ -86,7 +86,7 @@
|
|
|
86
86
|
"vitest": "5.0.5"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
|
-
"oxlint": "1.
|
|
89
|
+
"oxlint": "1.88.0 || 1.89.0 || 1.90.0"
|
|
90
90
|
},
|
|
91
91
|
"engines": {
|
|
92
92
|
"node": ">=22.14.0"
|