oxlint-plugin-arch 0.12.5 → 0.12.6
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/CHANGELOG.md +16 -0
- package/README.md +2 -2
- package/dist/index.js +874 -87
- package/dist/preset/preset.js +79 -6
- package/dist/preset/preset.utils.d.ts +1 -0
- package/dist/rules/effect/effect-layer-file.d.ts +1 -0
- package/dist/rules/effect/effect-layers.d.ts +1 -0
- package/dist/rules/effect/effect-merge-pipe.d.ts +1 -0
- package/dist/rules/effect/effect-schema-first.d.ts +1 -0
- package/dist/rules/effect/effect-values-first.d.ts +1 -0
- package/dist/rules/types/types-duplicate.d.ts +1 -0
- package/dist/types/effect.types.d.ts +46 -0
- package/dist/types/preset.types.d.ts +9 -0
- package/dist/types/schemas.types.d.ts +2 -0
- package/dist/types/types.types.d.ts +4 -0
- package/dist/utils/effect.utils.d.ts +5 -0
- package/dist/vendor/dillon-anti-slop/index.js +3 -0
- package/package.json +11 -1
package/dist/preset/preset.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
// src/preset/preset.ts
|
|
2
1
|
import { createRequire } from "node:module";
|
|
2
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
3
|
+
|
|
4
|
+
// src/preset/preset.ts
|
|
5
|
+
import { createRequire as createRequire2 } from "node:module";
|
|
3
6
|
|
|
4
7
|
// src/preset/groups/backend.ts
|
|
5
8
|
import { posix as posix3, resolve as resolve3 } from "node:path";
|
|
@@ -462,7 +465,7 @@ var presetGroupOptions = {
|
|
|
462
465
|
schemas: { level: "error" },
|
|
463
466
|
forms: { level: "error", resolver: "standardSchemaResolver" },
|
|
464
467
|
sql: { level: "error", sanitizers: ["escapeLikeWildcards"] },
|
|
465
|
-
effect: { level: "error", width: 160, exports: undefined, skip: undefined },
|
|
468
|
+
effect: { level: "error", width: 160, exports: undefined, skip: undefined, entries: [] },
|
|
466
469
|
console: { level: "error" },
|
|
467
470
|
deny: { level: "error", imports: {}, calls: {} },
|
|
468
471
|
externals: { level: "error", packages: presetExternals }
|
|
@@ -534,6 +537,24 @@ import { readFileSync, statSync } from "node:fs";
|
|
|
534
537
|
import { posix, resolve } from "node:path";
|
|
535
538
|
class PresetError extends Error {
|
|
536
539
|
}
|
|
540
|
+
async function presetEffectImport(load) {
|
|
541
|
+
try {
|
|
542
|
+
return await load;
|
|
543
|
+
} catch (error) {
|
|
544
|
+
if (error instanceof Error && "code" in error && error.code === "ERR_MODULE_NOT_FOUND") {
|
|
545
|
+
return null;
|
|
546
|
+
}
|
|
547
|
+
throw error;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
var presetEffectTsgo = await presetEffectImport(import("@effect/tsgo/oxlint-presets"));
|
|
551
|
+
var presetEffectLinteffect = await presetEffectImport(import("@opsydyn/oxlint-effect"));
|
|
552
|
+
function presetEffectPackages() {
|
|
553
|
+
if (!presetEffectTsgo || !presetEffectLinteffect) {
|
|
554
|
+
throw new PresetError("The effect group needs @effect/tsgo and @opsydyn/oxlint-effect: bun add -d @effect/tsgo @opsydyn/oxlint-effect");
|
|
555
|
+
}
|
|
556
|
+
return { tsgo: presetEffectTsgo, linteffect: presetEffectLinteffect };
|
|
557
|
+
}
|
|
537
558
|
function presetScopes(roots, suffix = `**/${presetExtensions}`) {
|
|
538
559
|
return roots.map((root) => root === "." ? suffix : `${root}/${suffix}`);
|
|
539
560
|
}
|
|
@@ -1075,16 +1096,62 @@ var denyGroup = (project, settings) => {
|
|
|
1075
1096
|
};
|
|
1076
1097
|
|
|
1077
1098
|
// src/preset/groups/effect.ts
|
|
1099
|
+
var effectOff = {
|
|
1100
|
+
"linteffect/no-effect-fn-generator": "off",
|
|
1101
|
+
"linteffect/prefer-extracted-concept": "off",
|
|
1102
|
+
"linteffect/no-clever-effect-expression": "off",
|
|
1103
|
+
"linteffect/no-mixed-pillar-function": "off",
|
|
1104
|
+
"linteffect/no-piped-yield-in-gen": "off",
|
|
1105
|
+
"linteffect/no-domain-logic-in-conditional": "off",
|
|
1106
|
+
"linteffect/prefer-pipe-for-behavior": "off",
|
|
1107
|
+
"linteffect/no-ternary": "off",
|
|
1108
|
+
"linteffect/no-effect-as": "off",
|
|
1109
|
+
"linteffect/no-namespace-effect-import": "off",
|
|
1110
|
+
"linteffect/no-manual-effect-channels": "off",
|
|
1111
|
+
"linteffect/no-or-die-outside-boundary": "off",
|
|
1112
|
+
"linteffect/no-call-tower": "off",
|
|
1113
|
+
"linteffect/no-pipe-ladder": "off",
|
|
1114
|
+
"linteffect/no-nested-effect-gen": "off",
|
|
1115
|
+
"linteffect/no-branch-in-object": "off",
|
|
1116
|
+
"linteffect/no-magic-domain-string": "off",
|
|
1117
|
+
"linteffect/no-return-in-arrow": "off",
|
|
1118
|
+
"linteffect/no-effect-succeed-variable": "off",
|
|
1119
|
+
"linteffect/no-match-effect-branch": "off"
|
|
1120
|
+
};
|
|
1121
|
+
var effectEntryOff = {
|
|
1122
|
+
"effecttsgo/strict-effect-provide": "off",
|
|
1123
|
+
"linteffect/no-inline-runtime-provide": "off",
|
|
1124
|
+
"linteffect/no-inline-layer-provide-in-program": "off"
|
|
1125
|
+
};
|
|
1126
|
+
var effectTestOff = {
|
|
1127
|
+
...effectEntryOff,
|
|
1128
|
+
"linteffect/no-string-sentinel-return": "off",
|
|
1129
|
+
"linteffect/no-effect-never": "off",
|
|
1130
|
+
"linteffect/no-gen-for-mapping": "off",
|
|
1131
|
+
"linteffect/no-adhoc-domain-error": "off"
|
|
1132
|
+
};
|
|
1078
1133
|
var effectGroup = (project, settings) => {
|
|
1079
1134
|
const files = [`**/${presetExtensions}`];
|
|
1080
1135
|
const max = settings.width;
|
|
1136
|
+
const { tsgo, linteffect } = presetEffectPackages();
|
|
1137
|
+
const tsgoRules = [tsgo.correctness, tsgo.antipattern, tsgo.effectNative, tsgo.style].flatMap((config) => Object.keys(config.rules ?? {}));
|
|
1081
1138
|
return [
|
|
1139
|
+
presetOverride(files, {
|
|
1140
|
+
...Object.fromEntries(tsgoRules.map((rule) => [rule, "error"])),
|
|
1141
|
+
...linteffect.recommended.rules,
|
|
1142
|
+
...effectOff
|
|
1143
|
+
}),
|
|
1144
|
+
presetOverride(project.testFiles, effectTestOff),
|
|
1145
|
+
...settings.entries.length > 0 ? [presetOverride(settings.entries, effectEntryOff)] : [],
|
|
1082
1146
|
presetOverride(files, {
|
|
1083
1147
|
"arch/code-trivial-functions": "off",
|
|
1084
1148
|
"arch/code-branch-once": "error",
|
|
1085
1149
|
"arch/code-function-nesting": ["error", { max: 4 }],
|
|
1086
1150
|
"arch/code-inline": ["error", { max, nesting: 2, keep: ["^[A-Z]", "^layer"], allow: "^(?:decode|encode)[A-Z]", services: ["of"] }],
|
|
1087
1151
|
"arch/code-yield-argument": "error",
|
|
1152
|
+
"arch/effect-layers": "error",
|
|
1153
|
+
"arch/effect-merge-pipe": "error",
|
|
1154
|
+
"arch/effect-values-first": "error",
|
|
1088
1155
|
"arch/layout-arrow-body": ["error", { max }],
|
|
1089
1156
|
"arch/layout-call-arguments": ["error", { split: false, hug: { max }, join: { max, nesting: 2, keep: ["Layer.mergeAll"] } }],
|
|
1090
1157
|
"arch/layout-call-depth": ["error", { max: 2 }],
|
|
@@ -2195,7 +2262,7 @@ function presetProject(config) {
|
|
|
2195
2262
|
var recipes = presetRecipes;
|
|
2196
2263
|
var templates = presetTemplates;
|
|
2197
2264
|
var externals = presetExternals;
|
|
2198
|
-
var require2 =
|
|
2265
|
+
var require2 = createRequire2(import.meta.url);
|
|
2199
2266
|
function presetOptional(name, group) {
|
|
2200
2267
|
try {
|
|
2201
2268
|
return require2.resolve(name);
|
|
@@ -2278,6 +2345,7 @@ function presetEmit(project, name, builder) {
|
|
|
2278
2345
|
}
|
|
2279
2346
|
function presetPlugins(project) {
|
|
2280
2347
|
const react = project.scopes.some((scope) => scope.effective.react);
|
|
2348
|
+
const effect = project.scopes.some((scope) => scope.effective.effect);
|
|
2281
2349
|
const tailwinds = project.scopes.flatMap((scope) => scope.effective.tailwind ? [scope.effective.tailwind] : []);
|
|
2282
2350
|
const shadcns = project.scopes.flatMap((scope) => scope.effective.shadcn ? [scope.effective.shadcn] : []);
|
|
2283
2351
|
const tailwind = tailwinds.at(0);
|
|
@@ -2299,6 +2367,12 @@ function presetPlugins(project) {
|
|
|
2299
2367
|
{ name: "arch", specifier: require2.resolve("oxlint-plugin-arch") },
|
|
2300
2368
|
{ name: "dillon-anti-slop", specifier: require2.resolve("oxlint-plugin-arch/dillon-anti-slop") }
|
|
2301
2369
|
];
|
|
2370
|
+
const plugins = ["typescript", "react", "react-perf", "jsx-a11y", "import", "unicorn", "promise", "vitest", "node", "oxc"];
|
|
2371
|
+
if (effect) {
|
|
2372
|
+
const { tsgo, linteffect } = presetEffectPackages();
|
|
2373
|
+
plugins.push(...tsgo.correctness.plugins ?? []);
|
|
2374
|
+
jsPlugins.push(...linteffect.recommended.jsPlugins);
|
|
2375
|
+
}
|
|
2302
2376
|
const settings = {
|
|
2303
2377
|
react: { version: "19" },
|
|
2304
2378
|
"import/resolver": { node: { extensions: [".js", ".jsx", ".ts", ".tsx", ".mts", ".cts"] } }
|
|
@@ -2307,7 +2381,7 @@ function presetPlugins(project) {
|
|
|
2307
2381
|
jsPlugins.push({ name: "react-extra", specifier: presetOptional("eslint-plugin-react", "react") }, presetOptional("eslint-plugin-react-you-might-not-need-an-effect", "react"), presetOptional("eslint-plugin-svg-jsx", "react"));
|
|
2308
2382
|
}
|
|
2309
2383
|
if (!tailwind || Object.keys(project.css).length === 0) {
|
|
2310
|
-
return { jsPlugins, settings };
|
|
2384
|
+
return { plugins, jsPlugins, settings };
|
|
2311
2385
|
}
|
|
2312
2386
|
jsPlugins.push(presetOptional("oxlint-tailwindcss", "tailwind"));
|
|
2313
2387
|
settings.tailwindcss = { rootFontSize: tailwind.rem };
|
|
@@ -2315,7 +2389,7 @@ function presetPlugins(project) {
|
|
|
2315
2389
|
jsPlugins.push(presetOptional("@shadcn/lint", "shadcn"));
|
|
2316
2390
|
settings.shadcn = { ui: shadcn.ui, componentImports: shadcn.components };
|
|
2317
2391
|
}
|
|
2318
|
-
return { jsPlugins, settings };
|
|
2392
|
+
return { plugins, jsPlugins, settings };
|
|
2319
2393
|
}
|
|
2320
2394
|
function preset(config) {
|
|
2321
2395
|
const project = presetProject(config);
|
|
@@ -2335,7 +2409,6 @@ function preset(config) {
|
|
|
2335
2409
|
return {
|
|
2336
2410
|
options: { typeAware: true },
|
|
2337
2411
|
categories: { correctness: level },
|
|
2338
|
-
plugins: ["typescript", "react", "react-perf", "jsx-a11y", "import", "unicorn", "promise", "vitest", "node", "oxc"],
|
|
2339
2412
|
ignorePatterns: [
|
|
2340
2413
|
"**/node_modules/**",
|
|
2341
2414
|
...project.outputs,
|
|
@@ -2,6 +2,7 @@ import type * as PresetTypes from '../types/preset.types.ts';
|
|
|
2
2
|
import type { OxlintOverride } from 'oxlint';
|
|
3
3
|
export declare class PresetError extends Error {
|
|
4
4
|
}
|
|
5
|
+
export declare function presetEffectPackages(): PresetTypes.PresetEffectPackages;
|
|
5
6
|
export declare function presetScopes(roots: string[], suffix?: string): string[];
|
|
6
7
|
export declare function presetServiceScopes(folders: Record<string, string>, sources: string[], suffix?: string): string[];
|
|
7
8
|
export declare function presetOverride(files: string[], rules: PresetTypes.PresetRules, excludeFiles?: string[]): OxlintOverride;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const effectLayerFile: import("@oxlint/plugins").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const effectLayers: import("@oxlint/plugins").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const effectMergePipe: import("@oxlint/plugins").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const effectSchemaFirst: import("@oxlint/plugins").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const effectValuesFirst: import("@oxlint/plugins").Rule;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const typesDuplicate: import("@oxlint/plugins").Rule;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { OptionsPattern } from './options.types.ts';
|
|
2
|
+
import type { SourceIndent } from './source.types.ts';
|
|
3
|
+
export interface EffectLayersGroup {
|
|
4
|
+
callees?: string[];
|
|
5
|
+
min?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface EffectLayersOptions {
|
|
8
|
+
merge?: EffectLayersGroup;
|
|
9
|
+
provide?: EffectLayersGroup;
|
|
10
|
+
indent?: SourceIndent;
|
|
11
|
+
}
|
|
12
|
+
export interface EffectMergePipeOptions {
|
|
13
|
+
merge?: string[];
|
|
14
|
+
pipe?: string[];
|
|
15
|
+
methods?: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface EffectValuesFirstOptions {
|
|
18
|
+
builders?: string[];
|
|
19
|
+
pinned?: OptionsPattern;
|
|
20
|
+
}
|
|
21
|
+
export interface EffectLayerFileOptions {
|
|
22
|
+
layer?: string;
|
|
23
|
+
make?: string;
|
|
24
|
+
prefix?: string;
|
|
25
|
+
builders?: string[];
|
|
26
|
+
layers?: OptionsPattern;
|
|
27
|
+
services?: OptionsPattern;
|
|
28
|
+
constructors?: string[];
|
|
29
|
+
}
|
|
30
|
+
export interface EffectSchemaFirstRows {
|
|
31
|
+
types?: string[];
|
|
32
|
+
suffix?: string;
|
|
33
|
+
}
|
|
34
|
+
export type EffectSchemaFirstSection = 'values' | 'interfaces' | 'modules' | 'aliases';
|
|
35
|
+
export interface EffectSchemaFirstDerived {
|
|
36
|
+
first?: boolean;
|
|
37
|
+
sorted?: boolean;
|
|
38
|
+
}
|
|
39
|
+
export interface EffectSchemaFirstOptions {
|
|
40
|
+
member?: string;
|
|
41
|
+
keep?: OptionsPattern;
|
|
42
|
+
runtime?: string[];
|
|
43
|
+
rows?: EffectSchemaFirstRows;
|
|
44
|
+
order?: (EffectSchemaFirstSection | EffectSchemaFirstSection[])[];
|
|
45
|
+
derived?: EffectSchemaFirstDerived;
|
|
46
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { OptionsPattern } from './options.types.ts';
|
|
2
|
+
import type * as EffectTsgo from '@effect/tsgo/oxlint-presets';
|
|
3
|
+
import type * as EffectLinteffect from '@opsydyn/oxlint-effect';
|
|
2
4
|
import type { OxlintConfig, OxlintOverride } from 'oxlint';
|
|
3
5
|
export type PresetLevel = 'error' | 'warn';
|
|
4
6
|
export type PresetSwitch = boolean | 'warn';
|
|
@@ -125,6 +127,11 @@ export interface PresetEffectOptions {
|
|
|
125
127
|
width?: number;
|
|
126
128
|
exports?: OptionsPattern;
|
|
127
129
|
skip?: OptionsPattern;
|
|
130
|
+
entries?: string[];
|
|
131
|
+
}
|
|
132
|
+
export interface PresetEffectPackages {
|
|
133
|
+
tsgo: typeof EffectTsgo;
|
|
134
|
+
linteffect: typeof EffectLinteffect;
|
|
128
135
|
}
|
|
129
136
|
export interface PresetSqlOptions {
|
|
130
137
|
sanitizers?: string[];
|
|
@@ -172,6 +179,7 @@ export interface PresetConfig {
|
|
|
172
179
|
export type PresetRecipe = PresetGroups;
|
|
173
180
|
export type PresetRules = NonNullable<OxlintConfig['rules']>;
|
|
174
181
|
export type PresetJsPlugins = NonNullable<OxlintConfig['jsPlugins']>;
|
|
182
|
+
export type PresetPlugins = NonNullable<OxlintConfig['plugins']>;
|
|
175
183
|
export type PresetSettings = NonNullable<OxlintConfig['settings']>;
|
|
176
184
|
export interface PresetResolvedGroups {
|
|
177
185
|
layout: PresetLayoutOptions & Required<Pick<PresetLayoutOptions, 'suffixes' | 'strict' | 'operations' | 'service'>>;
|
|
@@ -199,6 +207,7 @@ export interface PresetResolvedGroups {
|
|
|
199
207
|
sql: Required<PresetSqlOptions>;
|
|
200
208
|
effect: Pick<PresetEffectOptions, 'exports' | 'skip'> & {
|
|
201
209
|
width: number;
|
|
210
|
+
entries: string[];
|
|
202
211
|
};
|
|
203
212
|
console: PresetEmptyOptions;
|
|
204
213
|
deny: {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ESTree } from '@oxlint/plugins';
|
|
2
|
+
export declare const effectBuilders: string[];
|
|
3
|
+
export declare function effectIsBuilder(node: ESTree.Expression | null | undefined, builders: ReadonlySet<string>): node is ESTree.CallExpression;
|
|
4
|
+
export declare function effectGenerator(node: ESTree.Expression | null | undefined, builders: ReadonlySet<string>): ESTree.Function | undefined;
|
|
5
|
+
export declare function effectMatches(node: ESTree.Expression | ESTree.Super | null | undefined, patterns: RegExp[]): boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oxlint-plugin-arch",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.6",
|
|
4
4
|
"description": "Configurable architecture rules for Oxlint JavaScript plugins.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
"oxlint-plugin-eslint": "1.89.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
+
"@effect/tsgo": ">=0.67.1",
|
|
58
|
+
"@opsydyn/oxlint-effect": ">=2.0.1",
|
|
57
59
|
"@shadcn/lint": ">=0.2.3",
|
|
58
60
|
"eslint-plugin-react": ">=7.37.5",
|
|
59
61
|
"eslint-plugin-react-you-might-not-need-an-effect": ">=1.0.2",
|
|
@@ -63,6 +65,8 @@
|
|
|
63
65
|
"oxlint-tsgolint": ">=7.0.2003"
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
|
68
|
+
"@effect/tsgo": "0.67.1",
|
|
69
|
+
"@opsydyn/oxlint-effect": "2.0.1",
|
|
66
70
|
"@shadcn/lint": "0.2.3",
|
|
67
71
|
"@types/node": "26.6.5",
|
|
68
72
|
"bumpp": "12.3.0",
|
|
@@ -98,6 +102,12 @@
|
|
|
98
102
|
"plugin"
|
|
99
103
|
],
|
|
100
104
|
"peerDependenciesMeta": {
|
|
105
|
+
"@effect/tsgo": {
|
|
106
|
+
"optional": true
|
|
107
|
+
},
|
|
108
|
+
"@opsydyn/oxlint-effect": {
|
|
109
|
+
"optional": true
|
|
110
|
+
},
|
|
101
111
|
"@shadcn/lint": {
|
|
102
112
|
"optional": true
|
|
103
113
|
},
|