@imranbarbhuiya/oxc-config 0.2.3 → 0.3.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 +44 -1
- package/dist/cli/index.js +86 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.js +7 -1
- package/dist/config.js.map +1 -1
- package/dist/effect-types-only.d.ts +21 -0
- package/dist/effect-types-only.js +24 -0
- package/dist/effect-types-only.js.map +1 -0
- package/dist/effect.d.ts +15 -0
- package/dist/effect.js +80 -0
- package/dist/effect.js.map +1 -0
- package/dist/plugins/effect.d.ts +5 -0
- package/dist/plugins/effect.js +247 -0
- package/dist/plugins/effect.js.map +1 -0
- package/dist/plugins/unistyles.d.ts +5 -0
- package/dist/plugins/unistyles.js +204 -0
- package/dist/plugins/unistyles.js.map +1 -0
- package/dist/unistyles.d.ts +9 -0
- package/dist/unistyles.js +18 -0
- package/dist/unistyles.js.map +1 -0
- package/package.json +45 -16
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ Opinionated shared Oxlint and Oxfmt configuration for JavaScript and TypeScript
|
|
|
8
8
|
## Requirements
|
|
9
9
|
|
|
10
10
|
- Node.js 24
|
|
11
|
+
- The `typescript` fragment loads `eslint-plugin-sonarjs`, which needs the TypeScript 5 or 6 JavaScript API. TypeScript 7 has no JavaScript API, so when you also need TypeScript 7 (for example for `@effect/tsgo`), keep `typescript@6` installed as `typescript` and install TypeScript 7 under an alias such as `"@typescript/native": "npm:typescript@7"`
|
|
11
12
|
|
|
12
13
|
## Quick setup
|
|
13
14
|
|
|
@@ -34,13 +35,15 @@ npx @imranbarbhuiya/oxc-config -p react -y
|
|
|
34
35
|
|
|
35
36
|
Available options:
|
|
36
37
|
|
|
37
|
-
- `-p, --preset <name>` selects `nextjs`, `react`, `node`, `native`, `library`, or `
|
|
38
|
+
- `-p, --preset <name>` selects `nextjs`, `react`, `node`, `native`, `library`, `nest`, or `effect-node`
|
|
38
39
|
- `-t, --tailwind` / `--no-tailwind`
|
|
39
40
|
- `--i18n` / `--no-i18n`
|
|
40
41
|
- `--native-tailwind` / `--no-native-tailwind`
|
|
41
42
|
- `--central-icons` / `--no-central-icons`
|
|
42
43
|
- `--api-error` / `--no-api-error`
|
|
43
44
|
- `--query` / `--no-query`
|
|
45
|
+
- `--unistyles` / `--no-unistyles` (native only, cannot be combined with `--native-tailwind`)
|
|
46
|
+
- `--effect-types-only` (Next.js, React and React Native)
|
|
44
47
|
- `-y, --yes` skips prompts and uses detected defaults
|
|
45
48
|
- `--cwd <path>` changes the target directory
|
|
46
49
|
- `-h, --help` shows help
|
|
@@ -115,6 +118,9 @@ Add scripts to `package.json`:
|
|
|
115
118
|
- `native-tailwind` contains React Native Tailwind class-name rules
|
|
116
119
|
- `central-icons` prevents barrel imports from `@central-icons-react*` packages
|
|
117
120
|
- `api-error` requires allowed error classes in TanStack Query functions
|
|
121
|
+
- `effect` contains Effect v4 rules for backend code
|
|
122
|
+
- `effect-types-only` allows only type imports from Effect, for UI packages
|
|
123
|
+
- `unistyles` contains Unistyles 3 rules for React Native
|
|
118
124
|
|
|
119
125
|
Fragments can be combined through `defineConfig({ extends: [...] })`. The Tailwind plugin ships with this package. Install a third-party plugin only when you add it yourself, such as TanStack Query.
|
|
120
126
|
|
|
@@ -136,6 +142,43 @@ export default defineConfig({
|
|
|
136
142
|
});
|
|
137
143
|
```
|
|
138
144
|
|
|
145
|
+
## Effect
|
|
146
|
+
|
|
147
|
+
The `effect-node` CLI preset extends `common`, `node`, `typescript`, `module` and `effect`. Type diagnostics such as floating Effects and missing services come from `@effect/tsgo`; the `effect` fragment covers what it does not:
|
|
148
|
+
|
|
149
|
+
- `mahir-effect/no-gen-wrapper` flags functions that only wrap and return `Effect.gen`. Use `Effect.fn("name")` or `Effect.fnUntraced`. Callbacks passed to combinators are not flagged
|
|
150
|
+
- `mahir-effect/fn-name-matches` requires the `Effect.fn` name to match the binding, either `name` or `Service.name`, and fixes it
|
|
151
|
+
- `mahir-effect/return-yield-error` requires `return yield*` before `yield* new SomeError(...)` and `yield* Effect.fail(...)`, and fixes it
|
|
152
|
+
- `mahir-effect/no-pipe-on-fn` flags `.pipe` on `Effect.fn(...)(...)`; pass combinators as extra arguments instead
|
|
153
|
+
- `mahir-effect/no-throw-in-gen` flags `throw` directly inside `Effect.gen` / `Effect.fn` / `Effect.fnUntraced` generators
|
|
154
|
+
- `mahir-effect/no-run-outside-edge` flags `Effect.runPromise`, `runSync`, `runFork` and the other `run*` functions outside `**/main.ts`, `**/*.test.ts` and `**/scripts/**`
|
|
155
|
+
- `no-restricted-imports` rejects v3-era paths: `effect/Either`, `effect/unstable/*`, `@effect/platform`, `@effect/schema`, `@effect/rpc`, `@effect/cluster`, `@effect/sql` and their subpaths
|
|
156
|
+
- `node-js/no-process-env` rejects `process.env`; use `Config`. It is off under `**/scripts/**`
|
|
157
|
+
|
|
158
|
+
The fragment also relaxes rules that fire on idiomatic Effect code: `func-names` ignores generators, `require-yield` and `unicorn/throw-new-error` are off, and `no-use-before-define` allows classes referenced from inner scopes, so errors can be declared after the services that use them.
|
|
159
|
+
|
|
160
|
+
Change the allowed run files:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
export default defineConfig({
|
|
164
|
+
extends: [common, node, typescript, module, effect],
|
|
165
|
+
rules: {
|
|
166
|
+
'mahir-effect/no-run-outside-edge': [2, { allow: ['**/main.ts', '**/bin/**'] }],
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`effect-types-only` is for UI packages that share types with an Effect backend but should not ship the Effect runtime. It sets `no-restricted-imports` for `effect`, `effect/*` and `@effect/*` with `allowTypeImports: true`. Do not combine it with `effect`, because both configure `no-restricted-imports` and the last one wins.
|
|
172
|
+
|
|
173
|
+
## Unistyles
|
|
174
|
+
|
|
175
|
+
The `unistyles` fragment replaces `tailwind` and `native-tailwind` in Unistyles 3 apps:
|
|
176
|
+
|
|
177
|
+
- `mahir-unistyles/stylesheet-import` requires `StyleSheet` from `react-native-unistyles` instead of `react-native`, and fixes the import
|
|
178
|
+
- `mahir-unistyles/no-raw-colors` flags hex, `rgb()`, `hsl()` and similar colour strings, plus named colours on colour properties, inside `StyleSheet.create(...)` and `style` props. Files under `**/theme/**` and `**/tokens/**` are skipped; change this with `{ allow: [...] }`
|
|
179
|
+
- `mahir-unistyles/no-inline-style-objects` flags inline object literals in `style` and `*Style` props unless every value is a variable or member access such as `theme.colors.text`
|
|
180
|
+
- `mahir-unistyles/create-uses-theme` warns when a file that imports the theme (an import from a `theme` or `tokens` path, an import whose name contains `theme`, or `useUnistyles`) calls `StyleSheet.create` with a plain object instead of `StyleSheet.create((theme, rt) => ({ ... }))`
|
|
181
|
+
|
|
139
182
|
## MDX
|
|
140
183
|
|
|
141
184
|
Oxfmt formats MDX files with the shared formatter config. Oxlint does not lint MDX, so this package does not provide an MDX lint fragment.
|
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
2
|
import path from "node:path";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
4
|
import process from "node:process";
|
|
5
5
|
import { parseArgs } from "node:util";
|
|
6
6
|
import * as p from "@clack/prompts";
|
|
@@ -70,6 +70,16 @@ const PRESETS = {
|
|
|
70
70
|
"nest"
|
|
71
71
|
],
|
|
72
72
|
description: "NestJS application with TypeScript"
|
|
73
|
+
},
|
|
74
|
+
"effect-node": {
|
|
75
|
+
configs: [
|
|
76
|
+
"common",
|
|
77
|
+
"node",
|
|
78
|
+
"typescript",
|
|
79
|
+
"module",
|
|
80
|
+
"effect"
|
|
81
|
+
],
|
|
82
|
+
description: "Effect v4 Node.js backend with TypeScript"
|
|
73
83
|
}
|
|
74
84
|
};
|
|
75
85
|
const DEFAULT_IGNORES = {
|
|
@@ -112,19 +122,27 @@ const DEFAULT_IGNORES = {
|
|
|
112
122
|
".yarn/**",
|
|
113
123
|
"node_modules/**",
|
|
114
124
|
"dist/**"
|
|
125
|
+
],
|
|
126
|
+
"effect-node": [
|
|
127
|
+
".github/**",
|
|
128
|
+
".yarn/**",
|
|
129
|
+
"node_modules/**",
|
|
130
|
+
"dist/**"
|
|
115
131
|
]
|
|
116
132
|
};
|
|
117
133
|
const PACKAGE_PRESET_MAP = {
|
|
118
134
|
next: "nextjs",
|
|
119
135
|
"react-native": "native",
|
|
120
136
|
react: "react",
|
|
121
|
-
"@nestjs/core": "nest"
|
|
137
|
+
"@nestjs/core": "nest",
|
|
138
|
+
effect: "effect-node"
|
|
122
139
|
};
|
|
123
140
|
const DETECTION_PRIORITY = [
|
|
124
141
|
"next",
|
|
125
142
|
"react-native",
|
|
126
143
|
"react",
|
|
127
|
-
"@nestjs/core"
|
|
144
|
+
"@nestjs/core",
|
|
145
|
+
"effect"
|
|
128
146
|
];
|
|
129
147
|
const { values: options } = parseArgs({
|
|
130
148
|
options: {
|
|
@@ -181,6 +199,18 @@ const { values: options } = parseArgs({
|
|
|
181
199
|
type: "boolean",
|
|
182
200
|
default: false
|
|
183
201
|
},
|
|
202
|
+
unistyles: {
|
|
203
|
+
type: "boolean",
|
|
204
|
+
default: false
|
|
205
|
+
},
|
|
206
|
+
"no-unistyles": {
|
|
207
|
+
type: "boolean",
|
|
208
|
+
default: false
|
|
209
|
+
},
|
|
210
|
+
"effect-types-only": {
|
|
211
|
+
type: "boolean",
|
|
212
|
+
default: false
|
|
213
|
+
},
|
|
184
214
|
yes: {
|
|
185
215
|
type: "boolean",
|
|
186
216
|
short: "y",
|
|
@@ -204,7 +234,7 @@ Usage:
|
|
|
204
234
|
npx @imranbarbhuiya/oxc-config [options]
|
|
205
235
|
|
|
206
236
|
Options:
|
|
207
|
-
-p, --preset <name> Preset to use (nextjs, react, node, native, library, nest)
|
|
237
|
+
-p, --preset <name> Preset to use (nextjs, react, node, native, library, nest, effect-node)
|
|
208
238
|
-t, --tailwind Include Tailwind CSS support
|
|
209
239
|
--no-tailwind Exclude Tailwind CSS support
|
|
210
240
|
--i18n Include next-intl i18n rules (Next.js)
|
|
@@ -217,6 +247,9 @@ Options:
|
|
|
217
247
|
--no-api-error Exclude ApiError rules
|
|
218
248
|
--query Include TanStack Query rules
|
|
219
249
|
--no-query Exclude TanStack Query rules
|
|
250
|
+
--unistyles Include Unistyles 3 rules (native, not with --native-tailwind)
|
|
251
|
+
--no-unistyles Exclude Unistyles 3 rules
|
|
252
|
+
--effect-types-only Allow only type imports from Effect (nextjs, react, native)
|
|
220
253
|
-y, --yes Skip prompts and use defaults
|
|
221
254
|
--cwd <path> Working directory (defaults to current directory)
|
|
222
255
|
-h, --help Show this help message
|
|
@@ -234,8 +267,11 @@ function generateOxlintConfig(preset, includeTailwind, extras) {
|
|
|
234
267
|
if (extras.nativeTailwind) configs.push("nativeTailwind");
|
|
235
268
|
if (extras.centralIcons) configs.push("centralIcons");
|
|
236
269
|
if (extras.apiError) configs.push("apiError");
|
|
270
|
+
if (extras.unistyles) configs.push("unistyles");
|
|
271
|
+
if (extras.effectTypesOnly) configs.push("effectTypesOnly");
|
|
237
272
|
const imports = configs.map((name) => {
|
|
238
|
-
|
|
273
|
+
const fragment = name.replaceAll(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
|
|
274
|
+
return `import ${name} from '${PACKAGE_NAME}/${fragment}';`;
|
|
239
275
|
});
|
|
240
276
|
const ignores = DEFAULT_IGNORES[preset].map((ignore) => `'${ignore}'`).join(", ");
|
|
241
277
|
const queryBlock = extras.query ? `
|
|
@@ -306,6 +342,9 @@ function hasCentralIcons(dependencies) {
|
|
|
306
342
|
function hasTanstackQuery(dependencies) {
|
|
307
343
|
return Boolean(dependencies["@tanstack/react-query"]);
|
|
308
344
|
}
|
|
345
|
+
function hasUnistyles(dependencies) {
|
|
346
|
+
return Boolean(dependencies["react-native-unistyles"]);
|
|
347
|
+
}
|
|
309
348
|
function hasTailwind(dependencies) {
|
|
310
349
|
return Boolean(dependencies.tailwindcss || dependencies.nativewind);
|
|
311
350
|
}
|
|
@@ -376,6 +415,12 @@ let includeNativeTailwind = options["no-native-tailwind"] ? false : options["nat
|
|
|
376
415
|
let includeCentralIcons = options["no-central-icons"] ? false : options["central-icons"] ? true : void 0;
|
|
377
416
|
let includeApiError = options["no-api-error"] ? false : options["api-error"] ? true : void 0;
|
|
378
417
|
let includeQuery = options["no-query"] ? false : options.query ? true : void 0;
|
|
418
|
+
let includeUnistyles = options["no-unistyles"] ? false : options.unistyles ? true : void 0;
|
|
419
|
+
let includeEffectTypesOnly = options["effect-types-only"] ? true : void 0;
|
|
420
|
+
if (includeUnistyles && includeNativeTailwind) {
|
|
421
|
+
p.log.error("--unistyles and --native-tailwind cannot be used together.");
|
|
422
|
+
process.exit(1);
|
|
423
|
+
}
|
|
379
424
|
if (!preset) {
|
|
380
425
|
const detectedPreset = detectPresetFromDependencies(dependencies);
|
|
381
426
|
if (skipPrompts) preset = detectedPreset ?? "node";
|
|
@@ -438,8 +483,23 @@ if (includeI18n === void 0) {
|
|
|
438
483
|
includeI18n = result;
|
|
439
484
|
}
|
|
440
485
|
}
|
|
486
|
+
if (includeUnistyles === void 0) {
|
|
487
|
+
if (preset !== "native" || includeNativeTailwind) includeUnistyles = false;
|
|
488
|
+
else if (skipPrompts) includeUnistyles = hasUnistyles(dependencies);
|
|
489
|
+
else {
|
|
490
|
+
const result = await p.confirm({
|
|
491
|
+
message: "Include Unistyles 3 rules?",
|
|
492
|
+
initialValue: hasUnistyles(dependencies)
|
|
493
|
+
});
|
|
494
|
+
if (p.isCancel(result)) {
|
|
495
|
+
p.cancel("Operation cancelled.");
|
|
496
|
+
process.exit(0);
|
|
497
|
+
}
|
|
498
|
+
includeUnistyles = result;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
441
501
|
if (includeNativeTailwind === void 0) {
|
|
442
|
-
if (preset !== "native" || !includeTailwind) includeNativeTailwind = false;
|
|
502
|
+
if (preset !== "native" || !includeTailwind || includeUnistyles) includeNativeTailwind = false;
|
|
443
503
|
else if (skipPrompts) includeNativeTailwind = true;
|
|
444
504
|
else {
|
|
445
505
|
const result = await p.confirm({
|
|
@@ -498,6 +558,21 @@ if (includeApiError === void 0) {
|
|
|
498
558
|
includeApiError = result;
|
|
499
559
|
}
|
|
500
560
|
}
|
|
561
|
+
if (includeEffectTypesOnly === void 0) {
|
|
562
|
+
if (preset !== "native" && preset !== "react" && preset !== "nextjs") includeEffectTypesOnly = false;
|
|
563
|
+
else if (skipPrompts) includeEffectTypesOnly = false;
|
|
564
|
+
else {
|
|
565
|
+
const result = await p.confirm({
|
|
566
|
+
message: "Allow only type imports from Effect (no Effect runtime in the UI)?",
|
|
567
|
+
initialValue: false
|
|
568
|
+
});
|
|
569
|
+
if (p.isCancel(result)) {
|
|
570
|
+
p.cancel("Operation cancelled.");
|
|
571
|
+
process.exit(0);
|
|
572
|
+
}
|
|
573
|
+
includeEffectTypesOnly = result;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
501
576
|
p.log.step(`Setting up Oxlint and Oxfmt with preset: ${preset}`);
|
|
502
577
|
if (includeTailwind) p.log.info("Including Tailwind CSS support");
|
|
503
578
|
if (includeI18n) p.log.info("Including next-intl i18n rules");
|
|
@@ -505,6 +580,8 @@ if (includeNativeTailwind) p.log.info("Including React Native Tailwind className
|
|
|
505
580
|
if (includeCentralIcons) p.log.info("Including central-icons barrel-import rules");
|
|
506
581
|
if (includeQuery) p.log.info("Including TanStack Query rules");
|
|
507
582
|
if (includeApiError) p.log.info("Including ApiError rules for queryFn/mutationFn");
|
|
583
|
+
if (includeUnistyles) p.log.info("Including Unistyles 3 rules");
|
|
584
|
+
if (includeEffectTypesOnly) p.log.info("Including Effect type-only import rules");
|
|
508
585
|
const oxlintConfigPath = path.join(cwd, "oxlint.config.ts");
|
|
509
586
|
const oxfmtConfigPath = path.join(cwd, "oxfmt.config.ts");
|
|
510
587
|
const packageJsonPath = path.join(cwd, "package.json");
|
|
@@ -515,7 +592,9 @@ await fs.writeFile(oxlintConfigPath, generateOxlintConfig(preset, includeTailwin
|
|
|
515
592
|
nativeTailwind: includeNativeTailwind,
|
|
516
593
|
centralIcons: includeCentralIcons,
|
|
517
594
|
query: includeQuery,
|
|
518
|
-
apiError: includeApiError
|
|
595
|
+
apiError: includeApiError,
|
|
596
|
+
unistyles: includeUnistyles,
|
|
597
|
+
effectTypesOnly: includeEffectTypesOnly
|
|
519
598
|
}));
|
|
520
599
|
await fs.writeFile(oxfmtConfigPath, generateOxfmtConfig());
|
|
521
600
|
p.log.success("Created oxlint.config.ts and oxfmt.config.ts");
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { parseArgs } from 'node:util';\n\nimport * as p from '@clack/prompts';\nimport { addDevDependency, detectPackageManager } from 'nypm';\n\ninterface PresetConfig {\n\tconfigs: string[];\n\tdescription: string;\n}\n\ninterface ExtraConfigs {\n\tapiError: boolean;\n\tcentralIcons: boolean;\n\ti18n: boolean;\n\tnativeTailwind: boolean;\n\tquery: boolean;\n}\n\nconst PACKAGE_NAME = '@imranbarbhuiya/oxc-config';\n\nconst PRESETS: Record<string, PresetConfig> = {\n\tnextjs: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'react', 'next', 'edge'],\n\t\tdescription: 'Next.js application with React, TypeScript, and edge runtime support',\n\t},\n\treact: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'react'],\n\t\tdescription: 'React application with TypeScript',\n\t},\n\tnode: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module'],\n\t\tdescription: 'Node.js application with TypeScript',\n\t},\n\tnative: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'react', 'native'],\n\t\tdescription: 'React Native application with TypeScript',\n\t},\n\tlibrary: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'tsdoc'],\n\t\tdescription: 'TypeScript library with TSDoc support',\n\t},\n\tnest: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'nest'],\n\t\tdescription: 'NestJS application with TypeScript',\n\t},\n};\n\nconst DEFAULT_IGNORES: Record<string, string[]> = {\n\tnextjs: ['.github/**', '.yarn/**', '.next/**', 'node_modules/**', 'next-env.d.ts'],\n\treact: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**', 'build/**'],\n\tnode: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n\tnative: ['.github/**', '.yarn/**', 'node_modules/**', '.expo/**', 'android/**', 'ios/**'],\n\tlibrary: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n\tnest: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n};\n\nconst PACKAGE_PRESET_MAP: Record<string, string> = {\n\tnext: 'nextjs',\n\t'react-native': 'native',\n\treact: 'react',\n\t'@nestjs/core': 'nest',\n};\n\nconst DETECTION_PRIORITY = ['next', 'react-native', 'react', '@nestjs/core'];\n\nconst { values: options } = parseArgs({\n\toptions: {\n\t\tpreset: { type: 'string', short: 'p' },\n\t\ttailwind: { type: 'boolean', short: 't', default: false },\n\t\t'no-tailwind': { type: 'boolean', default: false },\n\t\ti18n: { type: 'boolean', default: false },\n\t\t'no-i18n': { type: 'boolean', default: false },\n\t\t'native-tailwind': { type: 'boolean', default: false },\n\t\t'no-native-tailwind': { type: 'boolean', default: false },\n\t\t'central-icons': { type: 'boolean', default: false },\n\t\t'no-central-icons': { type: 'boolean', default: false },\n\t\t'api-error': { type: 'boolean', default: false },\n\t\t'no-api-error': { type: 'boolean', default: false },\n\t\tquery: { type: 'boolean', default: false },\n\t\t'no-query': { type: 'boolean', default: false },\n\t\tyes: { type: 'boolean', short: 'y', default: false },\n\t\tcwd: { type: 'string' },\n\t\thelp: { type: 'boolean', short: 'h', default: false },\n\t},\n\tstrict: true,\n\tallowPositionals: false,\n});\n\nfunction printHelp(): void {\n\tconsole.log(`\n@imranbarbhuiya/oxc-config - Setup Oxlint and Oxfmt\n\nUsage:\n npx @imranbarbhuiya/oxc-config [options]\n\nOptions:\n -p, --preset <name> Preset to use (nextjs, react, node, native, library, nest)\n -t, --tailwind Include Tailwind CSS support\n --no-tailwind Exclude Tailwind CSS support\n --i18n Include next-intl i18n rules (Next.js)\n --no-i18n Exclude next-intl i18n rules\n --native-tailwind Include React Native Tailwind className rules\n --no-native-tailwind Exclude React Native Tailwind className rules\n --central-icons Include central-icons barrel-import rules\n --no-central-icons Exclude central-icons barrel-import rules\n --api-error Include ApiError rules for queryFn/mutationFn\n --no-api-error Exclude ApiError rules\n --query Include TanStack Query rules\n --no-query Exclude TanStack Query rules\n -y, --yes Skip prompts and use defaults\n --cwd <path> Working directory (defaults to current directory)\n -h, --help Show this help message\n\nExamples:\n npx @imranbarbhuiya/oxc-config\n npx @imranbarbhuiya/oxc-config --preset nextjs --tailwind\n npx @imranbarbhuiya/oxc-config -p react -y\n`);\n}\n\nfunction generateOxlintConfig(preset: string, includeTailwind: boolean, extras: ExtraConfigs): string {\n\tconst configs = [...PRESETS[preset].configs];\n\n\tif (includeTailwind) configs.push('tailwind');\n\tif (extras.i18n) configs.push('i18n');\n\tif (extras.nativeTailwind) configs.push('nativeTailwind');\n\tif (extras.centralIcons) configs.push('centralIcons');\n\tif (extras.apiError) configs.push('apiError');\n\n\tconst imports = configs.map((name) => {\n\t\tconst fragment = name === 'nativeTailwind' ? 'native-tailwind' : name;\n\t\treturn `import ${name} from '${PACKAGE_NAME}/${fragment}';`;\n\t});\n\n\tconst ignores = DEFAULT_IGNORES[preset].map((ignore) => `'${ignore}'`).join(', ');\n\tconst queryBlock = extras.query\n\t\t? `\n\tjsPlugins: [{ name: 'query', specifier: '@tanstack/eslint-plugin-query' }],\n\trules: {\n\t\t'query/exhaustive-deps': 'error',\n\t\t'query/no-rest-destructuring': 'error',\n\t\t'query/stable-query-client': 'error',\n\t},`\n\t\t: '';\n\n\tconst env =\n\t\tpreset === 'nextjs' || preset === 'react' || preset === 'native'\n\t\t\t? `{\n\t\tnode: true,\n\t\tbrowser: true,\n\t\tserviceworker: true,\n\t}`\n\t\t\t: `{\n\t\tnode: true,\n\t}`;\n\n\treturn `import { defineConfig } from 'oxlint';\n\n${imports.join('\\n')}\n\nexport default defineConfig({\n\textends: [${configs.join(', ')}],\n\tignorePatterns: [${ignores}],\n\tenv: ${env},\n\toptions: {\n\t\ttypeAware: true,\n\t},${queryBlock}\n});\n`;\n}\n\nfunction generateOxfmtConfig(): string {\n\treturn `import { defineConfig } from 'oxfmt';\n\nimport config from '${PACKAGE_NAME}/oxfmt';\n\nexport default defineConfig({\n\t...config,\n});\n`;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n\ttry {\n\t\tawait fs.access(filePath);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function getDependencies(cwd: string): Promise<Record<string, string>> {\n\tconst packageJsonPath = path.join(cwd, 'package.json');\n\tif (!(await fileExists(packageJsonPath))) return {};\n\n\tconst content = await fs.readFile(packageJsonPath, 'utf8');\n\tconst packageJson = JSON.parse(content) as Record<string, unknown>;\n\n\treturn {\n\t\t...(packageJson.dependencies as Record<string, string> | undefined),\n\t\t...(packageJson.devDependencies as Record<string, string> | undefined),\n\t};\n}\n\nfunction detectPresetFromDependencies(dependencies: Record<string, string>): string | undefined {\n\tfor (const name of DETECTION_PRIORITY) if (dependencies[name]) return PACKAGE_PRESET_MAP[name];\n\treturn undefined;\n}\n\nfunction hasNextIntl(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies['next-intl']);\n}\n\nfunction hasCentralIcons(dependencies: Record<string, string>): boolean {\n\treturn Object.keys(dependencies).some(\n\t\t(name) => name.startsWith('@central-icons-react/') || name.startsWith('@central-icons-react-native/'),\n\t);\n}\n\nfunction hasTanstackQuery(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies['@tanstack/react-query']);\n}\n\nfunction hasTailwind(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies.tailwindcss || dependencies.nativewind);\n}\n\nasync function updateScripts(packageJsonPath: string): Promise<void> {\n\tif (!(await fileExists(packageJsonPath))) {\n\t\tp.log.error('No package.json found. Run this command in a project with package.json.');\n\t\tprocess.exit(1);\n\t}\n\n\tconst content = await fs.readFile(packageJsonPath, 'utf8');\n\tconst packageJson = JSON.parse(content) as Record<string, unknown>;\n\tconst scripts = (packageJson.scripts as Record<string, string> | undefined) ?? {};\n\n\tscripts.lint = 'oxlint --fix .';\n\tscripts['lint:check'] = 'oxlint .';\n\tscripts.format = 'oxfmt';\n\tscripts['format:check'] = 'oxfmt --check';\n\tpackageJson.scripts = scripts;\n\n\tawait fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, '\\t') + '\\n');\n}\n\nasync function installDependencies(cwd: string, includeQuery: boolean): Promise<string> {\n\tconst pm = await detectPackageManager(cwd);\n\tconst pmName = pm?.name ?? 'npm';\n\tconst dependencies = [PACKAGE_NAME, 'oxlint', 'oxlint-tsgolint', 'oxfmt'];\n\n\tif (includeQuery) dependencies.push('@tanstack/eslint-plugin-query');\n\n\tp.log.info(`Detected package manager: ${pmName}`);\n\tconst spinner = p.spinner();\n\tspinner.start('Installing dependencies');\n\n\tfor (const dependency of dependencies) {\n\t\tspinner.message(`Installing ${dependency}`);\n\t\tawait addDevDependency(dependency, { cwd, silent: true });\n\t}\n\n\tspinner.stop('Dependencies installed');\n\treturn pmName;\n}\n\nasync function confirmOverwrite(filePath: string, skipPrompts: boolean): Promise<void> {\n\tif (!(await fileExists(filePath)) || skipPrompts) return;\n\n\tconst result = await p.confirm({\n\t\tmessage: `${path.basename(filePath)} already exists. Overwrite?`,\n\t\tinitialValue: false,\n\t});\n\n\tif (p.isCancel(result)) {\n\t\tp.cancel('Operation cancelled.');\n\t\tprocess.exit(0);\n\t}\n\n\tif (!result) {\n\t\tp.cancel('Aborted.');\n\t\tprocess.exit(0);\n\t}\n}\n\nif (options.help) {\n\tprintHelp();\n\tprocess.exit(0);\n}\n\np.intro('@imranbarbhuiya/oxc-config setup');\n\nconst cwd = options.cwd ? path.resolve(options.cwd) : process.cwd();\nconst skipPrompts = options.yes;\nconst dependencies = await getDependencies(cwd);\n\nlet preset = options.preset;\nlet includeTailwind = options['no-tailwind'] ? false : options.tailwind ? true : undefined;\nlet includeI18n = options['no-i18n'] ? false : options.i18n ? true : undefined;\nlet includeNativeTailwind = options['no-native-tailwind'] ? false : options['native-tailwind'] ? true : undefined;\nlet includeCentralIcons = options['no-central-icons'] ? false : options['central-icons'] ? true : undefined;\nlet includeApiError = options['no-api-error'] ? false : options['api-error'] ? true : undefined;\nlet includeQuery = options['no-query'] ? false : options.query ? true : undefined;\n\nif (!preset) {\n\tconst detectedPreset = detectPresetFromDependencies(dependencies);\n\tif (skipPrompts) preset = detectedPreset ?? 'node';\n\telse {\n\t\tconst presetOptions = Object.entries(PRESETS).map(([value, config]) => ({\n\t\t\tvalue,\n\t\t\tlabel: value,\n\t\t\thint: config.description,\n\t\t}));\n\n\t\tif (detectedPreset) {\n\t\t\tconst detected = presetOptions.find((option) => option.value === detectedPreset);\n\t\t\tif (detected) {\n\t\t\t\tdetected.hint = `Detected: ${detected.hint}`;\n\t\t\t\tpresetOptions.splice(\n\t\t\t\t\t0,\n\t\t\t\t\tpresetOptions.length,\n\t\t\t\t\tdetected,\n\t\t\t\t\t...presetOptions.filter(({ value }) => value !== detectedPreset),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst selected = await p.select({\n\t\t\tmessage: 'Select a preset',\n\t\t\toptions: presetOptions,\n\t\t});\n\n\t\tif (p.isCancel(selected)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\tpreset = selected;\n\t}\n}\n\nif (!(preset in PRESETS)) {\n\tp.log.error(`Unknown preset: ${preset}`);\n\tp.log.info(`Available presets: ${Object.keys(PRESETS).join(', ')}`);\n\tprocess.exit(1);\n}\n\nif (includeTailwind === undefined) {\n\tif (preset === 'node' || preset === 'library' || preset === 'nest') includeTailwind = false;\n\telse if (skipPrompts) includeTailwind = hasTailwind(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include Tailwind CSS support?',\n\t\t\tinitialValue: hasTailwind(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeTailwind = result;\n\t}\n}\n\nif (includeI18n === undefined) {\n\tif (preset !== 'nextjs') includeI18n = false;\n\telse if (skipPrompts) includeI18n = hasNextIntl(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include next-intl i18n rules?',\n\t\t\tinitialValue: hasNextIntl(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeI18n = result;\n\t}\n}\n\nif (includeNativeTailwind === undefined) {\n\tif (preset !== 'native' || !includeTailwind) includeNativeTailwind = false;\n\telse if (skipPrompts) includeNativeTailwind = true;\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include React Native Tailwind className rules?',\n\t\t\tinitialValue: true,\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeNativeTailwind = result;\n\t}\n}\n\nif (includeCentralIcons === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeCentralIcons = false;\n\telse if (skipPrompts) includeCentralIcons = hasCentralIcons(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include central-icons barrel-import rules?',\n\t\t\tinitialValue: hasCentralIcons(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeCentralIcons = result;\n\t}\n}\n\nif (includeQuery === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeQuery = false;\n\telse if (skipPrompts) includeQuery = hasTanstackQuery(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include TanStack Query rules?',\n\t\t\tinitialValue: hasTanstackQuery(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeQuery = result;\n\t}\n}\n\nif (includeApiError === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeApiError = false;\n\telse if (skipPrompts) includeApiError = hasTanstackQuery(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include ApiError rules for queryFn/mutationFn?',\n\t\t\tinitialValue: hasTanstackQuery(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeApiError = result;\n\t}\n}\n\np.log.step(`Setting up Oxlint and Oxfmt with preset: ${preset}`);\nif (includeTailwind) p.log.info('Including Tailwind CSS support');\nif (includeI18n) p.log.info('Including next-intl i18n rules');\nif (includeNativeTailwind) p.log.info('Including React Native Tailwind className rules');\nif (includeCentralIcons) p.log.info('Including central-icons barrel-import rules');\nif (includeQuery) p.log.info('Including TanStack Query rules');\nif (includeApiError) p.log.info('Including ApiError rules for queryFn/mutationFn');\n\nconst oxlintConfigPath = path.join(cwd, 'oxlint.config.ts');\nconst oxfmtConfigPath = path.join(cwd, 'oxfmt.config.ts');\nconst packageJsonPath = path.join(cwd, 'package.json');\n\nawait confirmOverwrite(oxlintConfigPath, skipPrompts);\nawait confirmOverwrite(oxfmtConfigPath, skipPrompts);\nawait fs.writeFile(\n\toxlintConfigPath,\n\tgenerateOxlintConfig(preset, includeTailwind, {\n\t\ti18n: includeI18n,\n\t\tnativeTailwind: includeNativeTailwind,\n\t\tcentralIcons: includeCentralIcons,\n\t\tquery: includeQuery,\n\t\tapiError: includeApiError,\n\t}),\n);\nawait fs.writeFile(oxfmtConfigPath, generateOxfmtConfig());\np.log.success('Created oxlint.config.ts and oxfmt.config.ts');\n\nawait updateScripts(packageJsonPath);\np.log.success('Updated package.json scripts');\n\nconst pmName = await installDependencies(cwd, includeQuery);\nconst runPrefix = pmName === 'npm' ? 'npm run' : pmName;\np.outro(`Setup complete! Run \\`${runPrefix} lint && ${runPrefix} format\\``);\n\nprocess.exit(0);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport process from 'node:process';\nimport { parseArgs } from 'node:util';\n\nimport * as p from '@clack/prompts';\nimport { addDevDependency, detectPackageManager } from 'nypm';\n\ninterface PresetConfig {\n\tconfigs: string[];\n\tdescription: string;\n}\n\ninterface ExtraConfigs {\n\tapiError: boolean;\n\tcentralIcons: boolean;\n\teffectTypesOnly: boolean;\n\ti18n: boolean;\n\tnativeTailwind: boolean;\n\tquery: boolean;\n\tunistyles: boolean;\n}\n\nconst PACKAGE_NAME = '@imranbarbhuiya/oxc-config';\n\nconst PRESETS: Record<string, PresetConfig> = {\n\tnextjs: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'react', 'next', 'edge'],\n\t\tdescription: 'Next.js application with React, TypeScript, and edge runtime support',\n\t},\n\treact: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'react'],\n\t\tdescription: 'React application with TypeScript',\n\t},\n\tnode: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module'],\n\t\tdescription: 'Node.js application with TypeScript',\n\t},\n\tnative: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'react', 'native'],\n\t\tdescription: 'React Native application with TypeScript',\n\t},\n\tlibrary: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'tsdoc'],\n\t\tdescription: 'TypeScript library with TSDoc support',\n\t},\n\tnest: {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'nest'],\n\t\tdescription: 'NestJS application with TypeScript',\n\t},\n\t'effect-node': {\n\t\tconfigs: ['common', 'node', 'typescript', 'module', 'effect'],\n\t\tdescription: 'Effect v4 Node.js backend with TypeScript',\n\t},\n};\n\nconst DEFAULT_IGNORES: Record<string, string[]> = {\n\tnextjs: ['.github/**', '.yarn/**', '.next/**', 'node_modules/**', 'next-env.d.ts'],\n\treact: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**', 'build/**'],\n\tnode: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n\tnative: ['.github/**', '.yarn/**', 'node_modules/**', '.expo/**', 'android/**', 'ios/**'],\n\tlibrary: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n\tnest: ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n\t'effect-node': ['.github/**', '.yarn/**', 'node_modules/**', 'dist/**'],\n};\n\nconst PACKAGE_PRESET_MAP: Record<string, string> = {\n\tnext: 'nextjs',\n\t'react-native': 'native',\n\treact: 'react',\n\t'@nestjs/core': 'nest',\n\teffect: 'effect-node',\n};\n\nconst DETECTION_PRIORITY = ['next', 'react-native', 'react', '@nestjs/core', 'effect'];\n\nconst { values: options } = parseArgs({\n\toptions: {\n\t\tpreset: { type: 'string', short: 'p' },\n\t\ttailwind: { type: 'boolean', short: 't', default: false },\n\t\t'no-tailwind': { type: 'boolean', default: false },\n\t\ti18n: { type: 'boolean', default: false },\n\t\t'no-i18n': { type: 'boolean', default: false },\n\t\t'native-tailwind': { type: 'boolean', default: false },\n\t\t'no-native-tailwind': { type: 'boolean', default: false },\n\t\t'central-icons': { type: 'boolean', default: false },\n\t\t'no-central-icons': { type: 'boolean', default: false },\n\t\t'api-error': { type: 'boolean', default: false },\n\t\t'no-api-error': { type: 'boolean', default: false },\n\t\tquery: { type: 'boolean', default: false },\n\t\t'no-query': { type: 'boolean', default: false },\n\t\tunistyles: { type: 'boolean', default: false },\n\t\t'no-unistyles': { type: 'boolean', default: false },\n\t\t'effect-types-only': { type: 'boolean', default: false },\n\t\tyes: { type: 'boolean', short: 'y', default: false },\n\t\tcwd: { type: 'string' },\n\t\thelp: { type: 'boolean', short: 'h', default: false },\n\t},\n\tstrict: true,\n\tallowPositionals: false,\n});\n\nfunction printHelp(): void {\n\tconsole.log(`\n@imranbarbhuiya/oxc-config - Setup Oxlint and Oxfmt\n\nUsage:\n npx @imranbarbhuiya/oxc-config [options]\n\nOptions:\n -p, --preset <name> Preset to use (nextjs, react, node, native, library, nest, effect-node)\n -t, --tailwind Include Tailwind CSS support\n --no-tailwind Exclude Tailwind CSS support\n --i18n Include next-intl i18n rules (Next.js)\n --no-i18n Exclude next-intl i18n rules\n --native-tailwind Include React Native Tailwind className rules\n --no-native-tailwind Exclude React Native Tailwind className rules\n --central-icons Include central-icons barrel-import rules\n --no-central-icons Exclude central-icons barrel-import rules\n --api-error Include ApiError rules for queryFn/mutationFn\n --no-api-error Exclude ApiError rules\n --query Include TanStack Query rules\n --no-query Exclude TanStack Query rules\n --unistyles Include Unistyles 3 rules (native, not with --native-tailwind)\n --no-unistyles Exclude Unistyles 3 rules\n --effect-types-only Allow only type imports from Effect (nextjs, react, native)\n -y, --yes Skip prompts and use defaults\n --cwd <path> Working directory (defaults to current directory)\n -h, --help Show this help message\n\nExamples:\n npx @imranbarbhuiya/oxc-config\n npx @imranbarbhuiya/oxc-config --preset nextjs --tailwind\n npx @imranbarbhuiya/oxc-config -p react -y\n`);\n}\n\nfunction generateOxlintConfig(preset: string, includeTailwind: boolean, extras: ExtraConfigs): string {\n\tconst configs = [...PRESETS[preset].configs];\n\n\tif (includeTailwind) configs.push('tailwind');\n\tif (extras.i18n) configs.push('i18n');\n\tif (extras.nativeTailwind) configs.push('nativeTailwind');\n\tif (extras.centralIcons) configs.push('centralIcons');\n\tif (extras.apiError) configs.push('apiError');\n\tif (extras.unistyles) configs.push('unistyles');\n\tif (extras.effectTypesOnly) configs.push('effectTypesOnly');\n\n\tconst imports = configs.map((name) => {\n\t\tconst fragment = name.replaceAll(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n\t\treturn `import ${name} from '${PACKAGE_NAME}/${fragment}';`;\n\t});\n\n\tconst ignores = DEFAULT_IGNORES[preset].map((ignore) => `'${ignore}'`).join(', ');\n\tconst queryBlock = extras.query\n\t\t? `\n\tjsPlugins: [{ name: 'query', specifier: '@tanstack/eslint-plugin-query' }],\n\trules: {\n\t\t'query/exhaustive-deps': 'error',\n\t\t'query/no-rest-destructuring': 'error',\n\t\t'query/stable-query-client': 'error',\n\t},`\n\t\t: '';\n\n\tconst env =\n\t\tpreset === 'nextjs' || preset === 'react' || preset === 'native'\n\t\t\t? `{\n\t\tnode: true,\n\t\tbrowser: true,\n\t\tserviceworker: true,\n\t}`\n\t\t\t: `{\n\t\tnode: true,\n\t}`;\n\n\treturn `import { defineConfig } from 'oxlint';\n\n${imports.join('\\n')}\n\nexport default defineConfig({\n\textends: [${configs.join(', ')}],\n\tignorePatterns: [${ignores}],\n\tenv: ${env},\n\toptions: {\n\t\ttypeAware: true,\n\t},${queryBlock}\n});\n`;\n}\n\nfunction generateOxfmtConfig(): string {\n\treturn `import { defineConfig } from 'oxfmt';\n\nimport config from '${PACKAGE_NAME}/oxfmt';\n\nexport default defineConfig({\n\t...config,\n});\n`;\n}\n\nasync function fileExists(filePath: string): Promise<boolean> {\n\ttry {\n\t\tawait fs.access(filePath);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nasync function getDependencies(cwd: string): Promise<Record<string, string>> {\n\tconst packageJsonPath = path.join(cwd, 'package.json');\n\tif (!(await fileExists(packageJsonPath))) return {};\n\n\tconst content = await fs.readFile(packageJsonPath, 'utf8');\n\tconst packageJson = JSON.parse(content) as Record<string, unknown>;\n\n\treturn {\n\t\t...(packageJson.dependencies as Record<string, string> | undefined),\n\t\t...(packageJson.devDependencies as Record<string, string> | undefined),\n\t};\n}\n\nfunction detectPresetFromDependencies(dependencies: Record<string, string>): string | undefined {\n\tfor (const name of DETECTION_PRIORITY) if (dependencies[name]) return PACKAGE_PRESET_MAP[name];\n\treturn undefined;\n}\n\nfunction hasNextIntl(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies['next-intl']);\n}\n\nfunction hasCentralIcons(dependencies: Record<string, string>): boolean {\n\treturn Object.keys(dependencies).some(\n\t\t(name) => name.startsWith('@central-icons-react/') || name.startsWith('@central-icons-react-native/'),\n\t);\n}\n\nfunction hasTanstackQuery(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies['@tanstack/react-query']);\n}\n\nfunction hasUnistyles(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies['react-native-unistyles']);\n}\n\nfunction hasTailwind(dependencies: Record<string, string>): boolean {\n\treturn Boolean(dependencies.tailwindcss || dependencies.nativewind);\n}\n\nasync function updateScripts(packageJsonPath: string): Promise<void> {\n\tif (!(await fileExists(packageJsonPath))) {\n\t\tp.log.error('No package.json found. Run this command in a project with package.json.');\n\t\tprocess.exit(1);\n\t}\n\n\tconst content = await fs.readFile(packageJsonPath, 'utf8');\n\tconst packageJson = JSON.parse(content) as Record<string, unknown>;\n\tconst scripts = (packageJson.scripts as Record<string, string> | undefined) ?? {};\n\n\tscripts.lint = 'oxlint --fix .';\n\tscripts['lint:check'] = 'oxlint .';\n\tscripts.format = 'oxfmt';\n\tscripts['format:check'] = 'oxfmt --check';\n\tpackageJson.scripts = scripts;\n\n\tawait fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, '\\t') + '\\n');\n}\n\nasync function installDependencies(cwd: string, includeQuery: boolean): Promise<string> {\n\tconst pm = await detectPackageManager(cwd);\n\tconst pmName = pm?.name ?? 'npm';\n\tconst dependencies = [PACKAGE_NAME, 'oxlint', 'oxlint-tsgolint', 'oxfmt'];\n\n\tif (includeQuery) dependencies.push('@tanstack/eslint-plugin-query');\n\n\tp.log.info(`Detected package manager: ${pmName}`);\n\tconst spinner = p.spinner();\n\tspinner.start('Installing dependencies');\n\n\tfor (const dependency of dependencies) {\n\t\tspinner.message(`Installing ${dependency}`);\n\t\tawait addDevDependency(dependency, { cwd, silent: true });\n\t}\n\n\tspinner.stop('Dependencies installed');\n\treturn pmName;\n}\n\nasync function confirmOverwrite(filePath: string, skipPrompts: boolean): Promise<void> {\n\tif (!(await fileExists(filePath)) || skipPrompts) return;\n\n\tconst result = await p.confirm({\n\t\tmessage: `${path.basename(filePath)} already exists. Overwrite?`,\n\t\tinitialValue: false,\n\t});\n\n\tif (p.isCancel(result)) {\n\t\tp.cancel('Operation cancelled.');\n\t\tprocess.exit(0);\n\t}\n\n\tif (!result) {\n\t\tp.cancel('Aborted.');\n\t\tprocess.exit(0);\n\t}\n}\n\nif (options.help) {\n\tprintHelp();\n\tprocess.exit(0);\n}\n\np.intro('@imranbarbhuiya/oxc-config setup');\n\nconst cwd = options.cwd ? path.resolve(options.cwd) : process.cwd();\nconst skipPrompts = options.yes;\nconst dependencies = await getDependencies(cwd);\n\nlet preset = options.preset;\nlet includeTailwind = options['no-tailwind'] ? false : options.tailwind ? true : undefined;\nlet includeI18n = options['no-i18n'] ? false : options.i18n ? true : undefined;\nlet includeNativeTailwind = options['no-native-tailwind'] ? false : options['native-tailwind'] ? true : undefined;\nlet includeCentralIcons = options['no-central-icons'] ? false : options['central-icons'] ? true : undefined;\nlet includeApiError = options['no-api-error'] ? false : options['api-error'] ? true : undefined;\nlet includeQuery = options['no-query'] ? false : options.query ? true : undefined;\nlet includeUnistyles = options['no-unistyles'] ? false : options.unistyles ? true : undefined;\nlet includeEffectTypesOnly = options['effect-types-only'] ? true : undefined;\n\nif (includeUnistyles && includeNativeTailwind) {\n\tp.log.error('--unistyles and --native-tailwind cannot be used together.');\n\tprocess.exit(1);\n}\n\nif (!preset) {\n\tconst detectedPreset = detectPresetFromDependencies(dependencies);\n\tif (skipPrompts) preset = detectedPreset ?? 'node';\n\telse {\n\t\tconst presetOptions = Object.entries(PRESETS).map(([value, config]) => ({\n\t\t\tvalue,\n\t\t\tlabel: value,\n\t\t\thint: config.description,\n\t\t}));\n\n\t\tif (detectedPreset) {\n\t\t\tconst detected = presetOptions.find((option) => option.value === detectedPreset);\n\t\t\tif (detected) {\n\t\t\t\tdetected.hint = `Detected: ${detected.hint}`;\n\t\t\t\tpresetOptions.splice(\n\t\t\t\t\t0,\n\t\t\t\t\tpresetOptions.length,\n\t\t\t\t\tdetected,\n\t\t\t\t\t...presetOptions.filter(({ value }) => value !== detectedPreset),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tconst selected = await p.select({\n\t\t\tmessage: 'Select a preset',\n\t\t\toptions: presetOptions,\n\t\t});\n\n\t\tif (p.isCancel(selected)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\n\t\tpreset = selected;\n\t}\n}\n\nif (!(preset in PRESETS)) {\n\tp.log.error(`Unknown preset: ${preset}`);\n\tp.log.info(`Available presets: ${Object.keys(PRESETS).join(', ')}`);\n\tprocess.exit(1);\n}\n\nif (includeTailwind === undefined) {\n\tif (preset === 'node' || preset === 'library' || preset === 'nest') includeTailwind = false;\n\telse if (skipPrompts) includeTailwind = hasTailwind(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include Tailwind CSS support?',\n\t\t\tinitialValue: hasTailwind(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeTailwind = result;\n\t}\n}\n\nif (includeI18n === undefined) {\n\tif (preset !== 'nextjs') includeI18n = false;\n\telse if (skipPrompts) includeI18n = hasNextIntl(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include next-intl i18n rules?',\n\t\t\tinitialValue: hasNextIntl(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeI18n = result;\n\t}\n}\n\nif (includeUnistyles === undefined) {\n\tif (preset !== 'native' || includeNativeTailwind) includeUnistyles = false;\n\telse if (skipPrompts) includeUnistyles = hasUnistyles(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include Unistyles 3 rules?',\n\t\t\tinitialValue: hasUnistyles(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeUnistyles = result;\n\t}\n}\n\nif (includeNativeTailwind === undefined) {\n\tif (preset !== 'native' || !includeTailwind || includeUnistyles) includeNativeTailwind = false;\n\telse if (skipPrompts) includeNativeTailwind = true;\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include React Native Tailwind className rules?',\n\t\t\tinitialValue: true,\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeNativeTailwind = result;\n\t}\n}\n\nif (includeCentralIcons === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeCentralIcons = false;\n\telse if (skipPrompts) includeCentralIcons = hasCentralIcons(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include central-icons barrel-import rules?',\n\t\t\tinitialValue: hasCentralIcons(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeCentralIcons = result;\n\t}\n}\n\nif (includeQuery === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeQuery = false;\n\telse if (skipPrompts) includeQuery = hasTanstackQuery(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include TanStack Query rules?',\n\t\t\tinitialValue: hasTanstackQuery(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeQuery = result;\n\t}\n}\n\nif (includeApiError === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeApiError = false;\n\telse if (skipPrompts) includeApiError = hasTanstackQuery(dependencies);\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Include ApiError rules for queryFn/mutationFn?',\n\t\t\tinitialValue: hasTanstackQuery(dependencies),\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeApiError = result;\n\t}\n}\n\nif (includeEffectTypesOnly === undefined) {\n\tif (preset !== 'native' && preset !== 'react' && preset !== 'nextjs') includeEffectTypesOnly = false;\n\telse if (skipPrompts) includeEffectTypesOnly = false;\n\telse {\n\t\tconst result = await p.confirm({\n\t\t\tmessage: 'Allow only type imports from Effect (no Effect runtime in the UI)?',\n\t\t\tinitialValue: false,\n\t\t});\n\t\tif (p.isCancel(result)) {\n\t\t\tp.cancel('Operation cancelled.');\n\t\t\tprocess.exit(0);\n\t\t}\n\t\tincludeEffectTypesOnly = result;\n\t}\n}\n\np.log.step(`Setting up Oxlint and Oxfmt with preset: ${preset}`);\nif (includeTailwind) p.log.info('Including Tailwind CSS support');\nif (includeI18n) p.log.info('Including next-intl i18n rules');\nif (includeNativeTailwind) p.log.info('Including React Native Tailwind className rules');\nif (includeCentralIcons) p.log.info('Including central-icons barrel-import rules');\nif (includeQuery) p.log.info('Including TanStack Query rules');\nif (includeApiError) p.log.info('Including ApiError rules for queryFn/mutationFn');\nif (includeUnistyles) p.log.info('Including Unistyles 3 rules');\nif (includeEffectTypesOnly) p.log.info('Including Effect type-only import rules');\n\nconst oxlintConfigPath = path.join(cwd, 'oxlint.config.ts');\nconst oxfmtConfigPath = path.join(cwd, 'oxfmt.config.ts');\nconst packageJsonPath = path.join(cwd, 'package.json');\n\nawait confirmOverwrite(oxlintConfigPath, skipPrompts);\nawait confirmOverwrite(oxfmtConfigPath, skipPrompts);\nawait fs.writeFile(\n\toxlintConfigPath,\n\tgenerateOxlintConfig(preset, includeTailwind, {\n\t\ti18n: includeI18n,\n\t\tnativeTailwind: includeNativeTailwind,\n\t\tcentralIcons: includeCentralIcons,\n\t\tquery: includeQuery,\n\t\tapiError: includeApiError,\n\t\tunistyles: includeUnistyles,\n\t\teffectTypesOnly: includeEffectTypesOnly,\n\t}),\n);\nawait fs.writeFile(oxfmtConfigPath, generateOxfmtConfig());\np.log.success('Created oxlint.config.ts and oxfmt.config.ts');\n\nawait updateScripts(packageJsonPath);\np.log.success('Updated package.json scripts');\n\nconst pmName = await installDependencies(cwd, includeQuery);\nconst runPrefix = pmName === 'npm' ? 'npm run' : pmName;\np.outro(`Setup complete! Run \\`${runPrefix} lint && ${runPrefix} format\\``);\n\nprocess.exit(0);\n"],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -3,5 +3,9 @@ import { ExternalPluginEntry, OxlintConfig } from "oxlint";
|
|
|
3
3
|
export declare const nativePlugins: NonNullable<OxlintConfig['plugins']>;
|
|
4
4
|
export declare function packagePlugin(name: string, specifier: string): ExternalPluginEntry;
|
|
5
5
|
export declare function localPlugin(name: string, path: string): ExternalPluginEntry;
|
|
6
|
+
export declare function matchesFileGlob(context: {
|
|
7
|
+
cwd: string;
|
|
8
|
+
filename: string;
|
|
9
|
+
}, patterns: readonly string[]): boolean;
|
|
6
10
|
//#endregion
|
|
7
11
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isAbsolute, matchesGlob, relative } from "node:path";
|
|
1
2
|
import { URL, fileURLToPath } from "node:url";
|
|
2
3
|
|
|
3
4
|
//#region src/config.ts
|
|
@@ -25,7 +26,12 @@ function localPlugin(name, path) {
|
|
|
25
26
|
specifier: fileURLToPath(new URL(path, import.meta.url))
|
|
26
27
|
};
|
|
27
28
|
}
|
|
29
|
+
function matchesFileGlob(context, patterns) {
|
|
30
|
+
const fromCwd = relative(context.cwd, context.filename);
|
|
31
|
+
const file = (fromCwd.startsWith("..") || isAbsolute(fromCwd) ? context.filename : fromCwd).replaceAll("\\", "/");
|
|
32
|
+
return patterns.some((pattern) => matchesGlob(file, pattern));
|
|
33
|
+
}
|
|
28
34
|
|
|
29
35
|
//#endregion
|
|
30
|
-
export { localPlugin, nativePlugins, packagePlugin };
|
|
36
|
+
export { localPlugin, matchesFileGlob, nativePlugins, packagePlugin };
|
|
31
37
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { fileURLToPath, URL } from 'node:url';\n\nimport type { ExternalPluginEntry, OxlintConfig } from 'oxlint';\n\nexport const nativePlugins: NonNullable<OxlintConfig['plugins']> = [\n\t'eslint',\n\t'typescript',\n\t'unicorn',\n\t'oxc',\n\t'import',\n\t'jsdoc',\n\t'react',\n\t'nextjs',\n\t'promise',\n\t'node',\n];\n\nexport function packagePlugin(name: string, specifier: string): ExternalPluginEntry {\n\treturn { name, specifier: fileURLToPath(import.meta.resolve(specifier)) };\n}\n\nexport function localPlugin(name: string, path: string): ExternalPluginEntry {\n\treturn { name, specifier: fileURLToPath(new URL(path, import.meta.url)) };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.js","names":[],"sources":["../src/config.ts"],"sourcesContent":["import { isAbsolute, matchesGlob, relative } from 'node:path';\nimport { fileURLToPath, URL } from 'node:url';\n\nimport type { ExternalPluginEntry, OxlintConfig } from 'oxlint';\n\nexport const nativePlugins: NonNullable<OxlintConfig['plugins']> = [\n\t'eslint',\n\t'typescript',\n\t'unicorn',\n\t'oxc',\n\t'import',\n\t'jsdoc',\n\t'react',\n\t'nextjs',\n\t'promise',\n\t'node',\n];\n\nexport function packagePlugin(name: string, specifier: string): ExternalPluginEntry {\n\treturn { name, specifier: fileURLToPath(import.meta.resolve(specifier)) };\n}\n\nexport function localPlugin(name: string, path: string): ExternalPluginEntry {\n\treturn { name, specifier: fileURLToPath(new URL(path, import.meta.url)) };\n}\n\nexport function matchesFileGlob(context: { cwd: string; filename: string }, patterns: readonly string[]) {\n\tconst fromCwd = relative(context.cwd, context.filename);\n\tconst file = (fromCwd.startsWith('..') || isAbsolute(fromCwd) ? context.filename : fromCwd).replaceAll('\\\\', '/');\n\treturn patterns.some((pattern) => matchesGlob(file, pattern));\n}\n"],"mappings":";;;;AAKA,MAAa,gBAAsD;CAClE;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACD;AAEA,SAAgB,cAAc,MAAc,WAAwC;CACnF,OAAO;EAAE;EAAM,WAAW,cAAc,YAAY,QAAQ,SAAS,CAAC;CAAE;AACzE;AAEA,SAAgB,YAAY,MAAc,MAAmC;CAC5E,OAAO;EAAE;EAAM,WAAW,cAAc,IAAI,IAAI,MAAM,YAAY,GAAG,CAAC;CAAE;AACzE;AAEA,SAAgB,gBAAgB,SAA4C,UAA6B;CACxG,MAAM,UAAU,SAAS,QAAQ,KAAK,QAAQ,QAAQ;CACtD,MAAM,QAAQ,QAAQ,WAAW,IAAI,KAAK,WAAW,OAAO,IAAI,QAAQ,WAAW,QAAO,CAAE,WAAW,MAAM,GAAG;CAChH,OAAO,SAAS,MAAM,YAAY,YAAY,MAAM,OAAO,CAAC;AAC7D"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
//#region src/effect-types-only.d.ts
|
|
2
|
+
declare const config: {
|
|
3
|
+
plugins: ("eslint" | "react" | "unicorn" | "typescript" | "oxc" | "import" | "jsdoc" | "jest" | "vitest" | "jsx-a11y" | "nextjs" | "react-perf" | "promise" | "node" | "vue")[];
|
|
4
|
+
rules: {
|
|
5
|
+
'no-restricted-imports': [number, {
|
|
6
|
+
paths: {
|
|
7
|
+
name: string;
|
|
8
|
+
message: string;
|
|
9
|
+
allowTypeImports: true;
|
|
10
|
+
}[];
|
|
11
|
+
patterns: {
|
|
12
|
+
group: string[];
|
|
13
|
+
message: string;
|
|
14
|
+
allowTypeImports: true;
|
|
15
|
+
}[];
|
|
16
|
+
}];
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { config as default };
|
|
21
|
+
//# sourceMappingURL=effect-types-only.d.ts.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { nativePlugins } from "./config.js";
|
|
2
|
+
import { defineConfig } from "oxlint";
|
|
3
|
+
|
|
4
|
+
//#region src/effect-types-only.ts
|
|
5
|
+
const message = "UI uses generated OpenAPI types and openapi-fetch; import Effect types only.";
|
|
6
|
+
const config = defineConfig({
|
|
7
|
+
plugins: nativePlugins,
|
|
8
|
+
rules: { "no-restricted-imports": [2, {
|
|
9
|
+
paths: [{
|
|
10
|
+
name: "effect",
|
|
11
|
+
message,
|
|
12
|
+
allowTypeImports: true
|
|
13
|
+
}],
|
|
14
|
+
patterns: [{
|
|
15
|
+
group: ["effect/*", "@effect/*"],
|
|
16
|
+
message,
|
|
17
|
+
allowTypeImports: true
|
|
18
|
+
}]
|
|
19
|
+
}] }
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
//#endregion
|
|
23
|
+
export { config as default };
|
|
24
|
+
//# sourceMappingURL=effect-types-only.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect-types-only.js","names":[],"sources":["../src/effect-types-only.ts"],"sourcesContent":["import { defineConfig } from 'oxlint';\n\nimport { nativePlugins } from './config.js';\n\nconst message = 'UI uses generated OpenAPI types and openapi-fetch; import Effect types only.';\n\nconst config = defineConfig({\n\tplugins: nativePlugins,\n\trules: {\n\t\t'no-restricted-imports': [\n\t\t\t2,\n\t\t\t{\n\t\t\t\tpaths: [{ name: 'effect', message, allowTypeImports: true }],\n\t\t\t\tpatterns: [{ group: ['effect/*', '@effect/*'], message, allowTypeImports: true }],\n\t\t\t},\n\t\t],\n\t},\n});\n\nexport default config;\n"],"mappings":";;;;AAIA,MAAM,UAAU;AAEhB,MAAM,SAAS,aAAa;CAC3B,SAAS;CACT,OAAO,EACN,yBAAyB,CACxB,GACA;EACC,OAAO,CAAC;GAAE,MAAM;GAAU;GAAS,kBAAkB;EAAK,CAAC;EAC3D,UAAU,CAAC;GAAE,OAAO,CAAC,YAAY,WAAW;GAAG;GAAS,kBAAkB;EAAK,CAAC;CACjF,CACD,EACD;AACD,CAAC"}
|
package/dist/effect.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/effect.d.ts
|
|
2
|
+
declare const config: {
|
|
3
|
+
plugins: ("eslint" | "react" | "unicorn" | "typescript" | "oxc" | "import" | "jsdoc" | "jest" | "vitest" | "jsx-a11y" | "nextjs" | "react-perf" | "promise" | "node" | "vue")[];
|
|
4
|
+
jsPlugins: import("oxlint").ExternalPluginEntry[];
|
|
5
|
+
rules: import("oxlint").DummyRuleMap;
|
|
6
|
+
overrides: {
|
|
7
|
+
files: string[];
|
|
8
|
+
rules: {
|
|
9
|
+
'node-js/no-process-env': number;
|
|
10
|
+
};
|
|
11
|
+
}[];
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
export { config as default };
|
|
15
|
+
//# sourceMappingURL=effect.d.ts.map
|
package/dist/effect.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { localPlugin, nativePlugins, packagePlugin } from "./config.js";
|
|
2
|
+
import { defineConfig } from "oxlint";
|
|
3
|
+
|
|
4
|
+
//#region src/effect.ts
|
|
5
|
+
const V3_MESSAGE = "This is an Effect v3 import path that does not exist in Effect v4.";
|
|
6
|
+
const rules = {
|
|
7
|
+
"mahir-effect/fn-name-matches": 2,
|
|
8
|
+
"mahir-effect/no-gen-wrapper": 2,
|
|
9
|
+
"mahir-effect/no-pipe-on-fn": 2,
|
|
10
|
+
"mahir-effect/no-run-outside-edge": 2,
|
|
11
|
+
"mahir-effect/no-throw-in-gen": 2,
|
|
12
|
+
"mahir-effect/return-yield-error": 2,
|
|
13
|
+
"no-restricted-imports": [2, {
|
|
14
|
+
paths: [
|
|
15
|
+
{
|
|
16
|
+
name: "effect/Either",
|
|
17
|
+
message: "Effect v4 replaced `effect/Either` with `effect/Result`."
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: "@effect/platform",
|
|
21
|
+
message: `${V3_MESSAGE} Import from \`effect\` or \`effect/<module>\`.`
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
name: "@effect/schema",
|
|
25
|
+
message: `${V3_MESSAGE} Import \`Schema\` from \`effect\`.`
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "@effect/rpc",
|
|
29
|
+
message: `${V3_MESSAGE} Import from \`effect/rpc\`.`
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: "@effect/cluster",
|
|
33
|
+
message: `${V3_MESSAGE} Import from \`effect/cluster\`.`
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
name: "@effect/sql",
|
|
37
|
+
message: `${V3_MESSAGE} Import from \`effect/sql\`.`
|
|
38
|
+
}
|
|
39
|
+
],
|
|
40
|
+
patterns: [{
|
|
41
|
+
group: ["effect/unstable/*"],
|
|
42
|
+
message: "Effect v4 dropped the `unstable` segment. Import from `effect/<module>`."
|
|
43
|
+
}, {
|
|
44
|
+
group: [
|
|
45
|
+
"@effect/platform/*",
|
|
46
|
+
"@effect/schema/*",
|
|
47
|
+
"@effect/rpc/*",
|
|
48
|
+
"@effect/cluster/*",
|
|
49
|
+
"@effect/sql/*"
|
|
50
|
+
],
|
|
51
|
+
message: `${V3_MESSAGE} Import from \`effect\` or \`effect/<module>\`.`
|
|
52
|
+
}]
|
|
53
|
+
}],
|
|
54
|
+
"node-js/no-process-env": 2,
|
|
55
|
+
"func-names": [
|
|
56
|
+
2,
|
|
57
|
+
"as-needed",
|
|
58
|
+
{ generators: "never" }
|
|
59
|
+
],
|
|
60
|
+
"no-use-before-define": [2, {
|
|
61
|
+
classes: false,
|
|
62
|
+
functions: false,
|
|
63
|
+
variables: true
|
|
64
|
+
}],
|
|
65
|
+
"require-yield": 0,
|
|
66
|
+
"unicorn/throw-new-error": 0
|
|
67
|
+
};
|
|
68
|
+
const config = defineConfig({
|
|
69
|
+
plugins: nativePlugins,
|
|
70
|
+
jsPlugins: [localPlugin("mahir-effect", "./plugins/effect.js"), packagePlugin("node-js", "eslint-plugin-n")],
|
|
71
|
+
rules,
|
|
72
|
+
overrides: [{
|
|
73
|
+
files: ["**/scripts/**"],
|
|
74
|
+
rules: { "node-js/no-process-env": 0 }
|
|
75
|
+
}]
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { config as default };
|
|
80
|
+
//# sourceMappingURL=effect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effect.js","names":[],"sources":["../src/effect.ts"],"sourcesContent":["import { defineConfig } from 'oxlint';\n\nimport { localPlugin, nativePlugins, packagePlugin } from './config.js';\n\nimport type { OxlintConfig } from 'oxlint';\n\nconst V3_MESSAGE = 'This is an Effect v3 import path that does not exist in Effect v4.';\n\nconst rules: NonNullable<OxlintConfig['rules']> = {\n\t'mahir-effect/fn-name-matches': 2,\n\t'mahir-effect/no-gen-wrapper': 2,\n\t'mahir-effect/no-pipe-on-fn': 2,\n\t'mahir-effect/no-run-outside-edge': 2,\n\t'mahir-effect/no-throw-in-gen': 2,\n\t'mahir-effect/return-yield-error': 2,\n\t'no-restricted-imports': [\n\t\t2,\n\t\t{\n\t\t\tpaths: [\n\t\t\t\t{ name: 'effect/Either', message: 'Effect v4 replaced `effect/Either` with `effect/Result`.' },\n\t\t\t\t{ name: '@effect/platform', message: `${V3_MESSAGE} Import from \\`effect\\` or \\`effect/<module>\\`.` },\n\t\t\t\t{ name: '@effect/schema', message: `${V3_MESSAGE} Import \\`Schema\\` from \\`effect\\`.` },\n\t\t\t\t{ name: '@effect/rpc', message: `${V3_MESSAGE} Import from \\`effect/rpc\\`.` },\n\t\t\t\t{ name: '@effect/cluster', message: `${V3_MESSAGE} Import from \\`effect/cluster\\`.` },\n\t\t\t\t{ name: '@effect/sql', message: `${V3_MESSAGE} Import from \\`effect/sql\\`.` },\n\t\t\t],\n\t\t\tpatterns: [\n\t\t\t\t{\n\t\t\t\t\tgroup: ['effect/unstable/*'],\n\t\t\t\t\tmessage: 'Effect v4 dropped the `unstable` segment. Import from `effect/<module>`.',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tgroup: ['@effect/platform/*', '@effect/schema/*', '@effect/rpc/*', '@effect/cluster/*', '@effect/sql/*'],\n\t\t\t\t\tmessage: `${V3_MESSAGE} Import from \\`effect\\` or \\`effect/<module>\\`.`,\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t],\n\t'node-js/no-process-env': 2,\n\t'func-names': [2, 'as-needed', { generators: 'never' }],\n\t'no-use-before-define': [\n\t\t2,\n\t\t{\n\t\t\tclasses: false,\n\t\t\tfunctions: false,\n\t\t\tvariables: true,\n\t\t},\n\t],\n\t'require-yield': 0,\n\t'unicorn/throw-new-error': 0,\n};\n\nconst config = defineConfig({\n\tplugins: nativePlugins,\n\tjsPlugins: [localPlugin('mahir-effect', './plugins/effect.js'), packagePlugin('node-js', 'eslint-plugin-n')],\n\trules,\n\toverrides: [\n\t\t{\n\t\t\tfiles: ['**/scripts/**'],\n\t\t\trules: {\n\t\t\t\t'node-js/no-process-env': 0,\n\t\t\t},\n\t\t},\n\t],\n});\n\nexport default config;\n"],"mappings":";;;;AAMA,MAAM,aAAa;AAEnB,MAAM,QAA4C;CACjD,gCAAgC;CAChC,+BAA+B;CAC/B,8BAA8B;CAC9B,oCAAoC;CACpC,gCAAgC;CAChC,mCAAmC;CACnC,yBAAyB,CACxB,GACA;EACC,OAAO;GACN;IAAE,MAAM;IAAiB,SAAS;GAA2D;GAC7F;IAAE,MAAM;IAAoB,SAAS,GAAG,WAAW;GAAiD;GACpG;IAAE,MAAM;IAAkB,SAAS,GAAG,WAAW;GAAqC;GACtF;IAAE,MAAM;IAAe,SAAS,GAAG,WAAW;GAA8B;GAC5E;IAAE,MAAM;IAAmB,SAAS,GAAG,WAAW;GAAkC;GACpF;IAAE,MAAM;IAAe,SAAS,GAAG,WAAW;GAA8B;EAC7E;EACA,UAAU,CACT;GACC,OAAO,CAAC,mBAAmB;GAC3B,SAAS;EACV,GACA;GACC,OAAO;IAAC;IAAsB;IAAoB;IAAiB;IAAqB;GAAe;GACvG,SAAS,GAAG,WAAW;EACxB,CACD;CACD,CACD;CACA,0BAA0B;CAC1B,cAAc;EAAC;EAAG;EAAa,EAAE,YAAY,QAAQ;CAAC;CACtD,wBAAwB,CACvB,GACA;EACC,SAAS;EACT,WAAW;EACX,WAAW;CACZ,CACD;CACA,iBAAiB;CACjB,2BAA2B;AAC5B;AAEA,MAAM,SAAS,aAAa;CAC3B,SAAS;CACT,WAAW,CAAC,YAAY,gBAAgB,qBAAqB,GAAG,cAAc,WAAW,iBAAiB,CAAC;CAC3G;CACA,WAAW,CACV;EACC,OAAO,CAAC,eAAe;EACvB,OAAO,EACN,0BAA0B,EAC3B;CACD,CACD;AACD,CAAC"}
|