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.
@@ -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 = createRequire(import.meta.url);
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: {
@@ -10,6 +10,8 @@ export interface SchemasLocalOptions {
10
10
  calls?: string[];
11
11
  allow?: string[];
12
12
  patterns?: string[];
13
+ imports?: boolean;
14
+ values?: boolean;
13
15
  message?: string;
14
16
  importMessage?: string;
15
17
  constructionMessage?: string;
@@ -22,3 +22,7 @@ export interface TypesNamespaceImportOptions {
22
22
  max: number;
23
23
  names: Record<string, string>;
24
24
  }
25
+ export interface TypesDuplicateOptions {
26
+ structs?: string[];
27
+ min?: number;
28
+ }
@@ -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;
@@ -1,3 +1,6 @@
1
+ import { createRequire } from "node:module";
2
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+
1
4
  // src/vendor/dillon-anti-slop/index.ts
2
5
  import { eslintCompatPlugin } from "@oxlint/plugins";
3
6
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-plugin-arch",
3
- "version": "0.12.5",
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
  },