@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 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 `nest`
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
- return `import ${name} from '${PACKAGE_NAME}/${name === "nativeTailwind" ? "native-tailwind" : name}';`;
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");
@@ -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
@@ -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":";;;AAIA,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"}
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"}
@@ -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"}
@@ -0,0 +1,5 @@
1
+ //#region src/plugins/effect.d.ts
2
+ declare const _default: import("@oxlint/plugins").Plugin;
3
+ //#endregion
4
+ export { _default as default };
5
+ //# sourceMappingURL=effect.d.ts.map