@eimerreis/linting 0.1.0 → 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
@@ -2,6 +2,10 @@
2
2
 
3
3
  Personal linting and formatting defaults for new JavaScript/TypeScript projects.
4
4
 
5
+ Requires Node `^20.19.0 || >=22.12.0`.
6
+
7
+ Zero peer-dependency setup for consumers: install only `@eimerreis/linting`.
8
+
5
9
  Built on:
6
10
 
7
11
  - `oxlint` for linting
@@ -17,7 +21,13 @@ Default focus:
17
21
  ## Install
18
22
 
19
23
  ```bash
20
- npm add -D @eimerreis/linting oxlint oxfmt
24
+ npm add -D @eimerreis/linting
25
+ ```
26
+
27
+ `lint` also executes react-doctor via:
28
+
29
+ ```bash
30
+ npx react-doctor -y .
21
31
  ```
22
32
 
23
33
  ## Quick Start
@@ -39,7 +49,7 @@ This creates:
39
49
  - `.oxlintrc.json`
40
50
  - `.oxfmtrc.json`
41
51
 
42
- And updates `package.json` scripts (if present):
52
+ And updates `package.json` scripts (if present) so linting is executed through this package:
43
53
 
44
54
  - `lint`
45
55
  - `lint:fix`
@@ -49,11 +59,30 @@ And updates `package.json` scripts (if present):
49
59
  ### CLI options
50
60
 
51
61
  ```bash
52
- eimerreis-linting [init] [targetDir] [--force]
62
+ eimerreis-linting init [targetDir] [--force]
63
+ eimerreis-linting lint [targetDir] [--fix]
64
+ eimerreis-linting format [targetDir] [--check]
53
65
  ```
54
66
 
55
- - `targetDir`: scaffold config in another directory
56
- - `--force`: overwrite existing `.oxlintrc.json` / `.oxfmtrc.json` and script values
67
+ - `init --force`: overwrite existing `.oxlintrc.json` / `.oxfmtrc.json` and script values
68
+ - `lint --fix`: run `oxlint --fix .` and then run react-doctor
69
+ - `format --check`: run `oxfmt --check .`
70
+
71
+ `react-doctor` runs only when the target package has `react`, `react-dom`, or `next` in dependencies/devDependencies/peerDependencies.
72
+
73
+ ### First-time one-shot usage
74
+
75
+ You do not need to run `init` first.
76
+
77
+ ```bash
78
+ npx @eimerreis/linting lint
79
+ npx @eimerreis/linting format --check
80
+ ```
81
+
82
+ Behavior:
83
+
84
+ - If project config exists (`.oxlintrc.*` / `oxlint.config.*`, `.oxfmtrc.*` / `oxfmt.config.*`), it uses that.
85
+ - If not, it falls back to the package's built-in defaults.
57
86
 
58
87
  ## Manual Setup
59
88
 
@@ -63,7 +92,7 @@ If you do not want to use the init script, create the config files manually.
63
92
 
64
93
  ```json
65
94
  {
66
- "extends": ["./node_modules/@eimerreis/linting/oxlint.config.json"]
95
+ "extends": ["./node_modules/@eimerreis/linting/oxlint.config.json"]
67
96
  }
68
97
  ```
69
98
 
@@ -71,6 +100,55 @@ If you do not want to use the init script, create the config files manually.
71
100
 
72
101
  ```json
73
102
  {
74
- "extends": ["./node_modules/@eimerreis/linting/oxfmt.config.json"]
103
+ "extends": ["./node_modules/@eimerreis/linting/oxfmt.config.json"]
75
104
  }
76
105
  ```
106
+
107
+ ## Scripts
108
+
109
+ Generated project scripts:
110
+
111
+ ```json
112
+ {
113
+ "scripts": {
114
+ "lint": "eimerreis-linting lint",
115
+ "lint:fix": "eimerreis-linting lint --fix",
116
+ "format": "eimerreis-linting format",
117
+ "format:check": "eimerreis-linting format --check"
118
+ }
119
+ }
120
+ ```
121
+
122
+ `init` also adds this dev dependency automatically (if missing):
123
+
124
+ ```json
125
+ {
126
+ "devDependencies": {
127
+ "@eimerreis/linting": "^<current-version>"
128
+ }
129
+ }
130
+ ```
131
+
132
+ ## Publish
133
+
134
+ ### Git-based release workflow (Changesets + GitHub Actions)
135
+
136
+ 1. Create a changeset:
137
+
138
+ ```bash
139
+ npm run changeset
140
+ ```
141
+
142
+ 2. Commit `.changeset/*.md` and push to `main`.
143
+ 3. Workflow `Release` checks for pending changesets.
144
+ 4. If changesets exist, it versions, publishes via npm trusted publishing (OIDC), and commits `chore: version packages`.
145
+
146
+ Trusted publishing setup (one-time on npmjs.com):
147
+
148
+ 1. Package `@eimerreis/linting` -> Settings -> Trusted Publisher
149
+ 2. Provider: GitHub Actions
150
+ 3. Organization/user: `eimerreis`
151
+ 4. Repository: `eimerreis-linting`
152
+ 5. Workflow filename: `release.yml`
153
+
154
+ No `NPM_TOKEN` secret is required for publishing.
package/bin/init.mjs CHANGED
@@ -1,102 +1,397 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ import { spawn } from "node:child_process";
3
4
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
- import { fileURLToPath } from "node:url";
5
+ import { createRequire } from "node:module";
5
6
  import { dirname, resolve } from "node:path";
6
7
  import process from "node:process";
8
+ import { fileURLToPath } from "node:url";
7
9
 
8
10
  const packageName = "@eimerreis/linting";
9
11
  const packageRoot = resolve(dirname(fileURLToPath(import.meta.url)), "..");
12
+ const requireFromHere = createRequire(import.meta.url);
10
13
 
11
- const rawArgs = process.argv.slice(2);
14
+ function ensureDirectory(filePath) {
15
+ const dir = dirname(filePath);
16
+ if (!existsSync(dir)) {
17
+ mkdirSync(dir, { recursive: true });
18
+ }
19
+ }
12
20
 
13
- if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
14
- console.log("Usage: eimerreis-linting [init] [targetDir] [--force]");
15
- process.exit(0);
21
+ function writeJson(filePath, data) {
22
+ ensureDirectory(filePath);
23
+ writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
16
24
  }
17
25
 
18
- const args = rawArgs[0] === "init" ? rawArgs.slice(1) : rawArgs;
19
- const force = args.includes("--force");
20
- const targetArg = args.find((arg) => !arg.startsWith("-"));
21
- const targetDir = resolve(process.cwd(), targetArg ?? ".");
26
+ function readJson(filePath) {
27
+ return JSON.parse(readFileSync(filePath, "utf8"));
28
+ }
22
29
 
23
- const targetPackageJsonPath = resolve(targetDir, "package.json");
24
- const oxlintPath = resolve(targetDir, ".oxlintrc.json");
25
- const oxfmtPath = resolve(targetDir, ".oxfmtrc.json");
30
+ function getSelfDependencyRange() {
31
+ try {
32
+ const selfPackageJsonPath = resolve(packageRoot, "package.json");
33
+ const selfPackageJson = readJson(selfPackageJsonPath);
34
+ if (selfPackageJson.version) {
35
+ return `^${selfPackageJson.version}`;
36
+ }
37
+ } catch {
38
+ // ignore
39
+ }
26
40
 
27
- function ensureDirectory(filePath) {
28
- const dir = dirname(filePath);
29
- if (!existsSync(dir)) {
30
- mkdirSync(dir, { recursive: true });
31
- }
41
+ return "latest";
32
42
  }
33
43
 
34
- function writeJson(filePath, data) {
35
- ensureDirectory(filePath);
36
- writeFileSync(filePath, `${JSON.stringify(data, null, 2)}\n`, "utf8");
44
+ function resolvePackageBin(dependencyName, binRelativePath) {
45
+ const entryPointPath = requireFromHere.resolve(dependencyName);
46
+ let cursor = dirname(entryPointPath);
47
+
48
+ while (cursor !== dirname(cursor)) {
49
+ const packageJsonPath = resolve(cursor, "package.json");
50
+ if (existsSync(packageJsonPath)) {
51
+ const packageJson = readJson(packageJsonPath);
52
+ if (packageJson.name === dependencyName) {
53
+ const binPath = resolve(cursor, binRelativePath);
54
+ if (!existsSync(binPath)) {
55
+ throw new Error(`Cannot find ${dependencyName} binary at ${binPath}`);
56
+ }
57
+ return binPath;
58
+ }
59
+ }
60
+ cursor = dirname(cursor);
61
+ }
62
+
63
+ throw new Error(`Unable to resolve package root for ${dependencyName}`);
37
64
  }
38
65
 
39
- function readJson(filePath) {
40
- return JSON.parse(readFileSync(filePath, "utf8"));
66
+ function resolvePackageEntry(dependencyName) {
67
+ return requireFromHere.resolve(dependencyName);
68
+ }
69
+
70
+ function hasInstalledPackage(dependencyName) {
71
+ try {
72
+ resolvePackageEntry(dependencyName);
73
+ return true;
74
+ } catch {
75
+ return false;
76
+ }
77
+ }
78
+
79
+ function resolveExistingConfigPath(targetDir, configCandidates) {
80
+ for (const candidate of configCandidates) {
81
+ const candidatePath = resolve(targetDir, candidate);
82
+ if (existsSync(candidatePath)) {
83
+ return candidatePath;
84
+ }
85
+ }
86
+
87
+ return null;
88
+ }
89
+
90
+ function resolveLintConfigPath(targetDir) {
91
+ const localConfigPath = resolveExistingConfigPath(targetDir, [
92
+ ".oxlintrc.json",
93
+ ".oxlintrc.jsonc",
94
+ ".oxlintrc.js",
95
+ ".oxlintrc.mjs",
96
+ ".oxlintrc.cjs",
97
+ ".oxlintrc.ts",
98
+ ".oxlintrc.mts",
99
+ ".oxlintrc.cts",
100
+ "oxlint.config.js",
101
+ "oxlint.config.mjs",
102
+ "oxlint.config.cjs",
103
+ "oxlint.config.ts",
104
+ "oxlint.config.mts",
105
+ "oxlint.config.cts",
106
+ ]);
107
+
108
+ if (localConfigPath) {
109
+ return localConfigPath;
110
+ }
111
+
112
+ return resolve(packageRoot, "oxlint.config.json");
113
+ }
114
+
115
+ function resolveFormatConfigPath(targetDir) {
116
+ const localConfigPath = resolveExistingConfigPath(targetDir, [
117
+ ".oxfmtrc.json",
118
+ ".oxfmtrc.jsonc",
119
+ ".oxfmtrc.js",
120
+ ".oxfmtrc.mjs",
121
+ ".oxfmtrc.cjs",
122
+ ".oxfmtrc.ts",
123
+ ".oxfmtrc.mts",
124
+ ".oxfmtrc.cts",
125
+ "oxfmt.config.js",
126
+ "oxfmt.config.mjs",
127
+ "oxfmt.config.cjs",
128
+ "oxfmt.config.ts",
129
+ "oxfmt.config.mts",
130
+ "oxfmt.config.cts",
131
+ ]);
132
+
133
+ if (localConfigPath) {
134
+ return localConfigPath;
135
+ }
136
+
137
+ return resolve(packageRoot, "oxfmt.config.json");
138
+ }
139
+
140
+ function printUsage() {
141
+ console.log("Usage:");
142
+ console.log(" eimerreis-linting init [targetDir] [--force]");
143
+ console.log(" eimerreis-linting lint [targetDir] [--fix]");
144
+ console.log(" eimerreis-linting format [targetDir] [--check]");
145
+ }
146
+
147
+ function parseCommand(rawArgs) {
148
+ const firstArg = rawArgs[0];
149
+ if (!firstArg || firstArg === "init" || firstArg.startsWith("-")) {
150
+ return {
151
+ command: "init",
152
+ args: firstArg === "init" ? rawArgs.slice(1) : rawArgs,
153
+ };
154
+ }
155
+
156
+ return {
157
+ command: firstArg,
158
+ args: rawArgs.slice(1),
159
+ };
160
+ }
161
+
162
+ function parsePathAndFlags(args, allowedFlags) {
163
+ let targetDirArg;
164
+ const flags = new Set();
165
+
166
+ for (const arg of args) {
167
+ if (arg.startsWith("-")) {
168
+ if (!allowedFlags.includes(arg)) {
169
+ throw new Error(`Unknown flag: ${arg}`);
170
+ }
171
+ flags.add(arg);
172
+ continue;
173
+ }
174
+
175
+ if (targetDirArg) {
176
+ throw new Error(`Unexpected argument: ${arg}`);
177
+ }
178
+
179
+ targetDirArg = arg;
180
+ }
181
+
182
+ return {
183
+ targetDir: resolve(process.cwd(), targetDirArg ?? "."),
184
+ flags,
185
+ };
41
186
  }
42
187
 
43
- function upsertScript(packageJson, name, command) {
44
- if (!packageJson.scripts || typeof packageJson.scripts !== "object") {
45
- packageJson.scripts = {};
46
- }
47
- if (!packageJson.scripts[name] || force) {
48
- packageJson.scripts[name] = command;
49
- }
188
+ function runCommand(command, commandArgs, cwd) {
189
+ return new Promise((resolvePromise) => {
190
+ const child = spawn(command, commandArgs, {
191
+ cwd,
192
+ stdio: "inherit",
193
+ shell: process.platform === "win32",
194
+ });
195
+
196
+ child.on("error", (error) => {
197
+ console.error(`failed to run ${command}: ${error.message}`);
198
+ resolvePromise(1);
199
+ });
200
+
201
+ child.on("close", (code) => {
202
+ resolvePromise(code ?? 1);
203
+ });
204
+ });
205
+ }
206
+
207
+ function hasReactProject(cwd) {
208
+ const packageJsonPath = resolve(cwd, "package.json");
209
+
210
+ if (!existsSync(packageJsonPath)) {
211
+ return false;
212
+ }
213
+
214
+ try {
215
+ const packageJson = readJson(packageJsonPath);
216
+ const dependencyFields = ["dependencies", "devDependencies", "peerDependencies"];
217
+
218
+ return dependencyFields.some((field) => {
219
+ const deps = packageJson[field];
220
+ return Boolean(deps?.react || deps?.["react-dom"] || deps?.next);
221
+ });
222
+ } catch {
223
+ return false;
224
+ }
225
+ }
226
+
227
+ function upsertScript(packageJson, name, command, force) {
228
+ if (!packageJson.scripts || typeof packageJson.scripts !== "object") {
229
+ packageJson.scripts = {};
230
+ }
231
+ if (!packageJson.scripts[name] || force) {
232
+ packageJson.scripts[name] = command;
233
+ }
234
+ }
235
+
236
+ function createExtendsConfig(targetPath, exportPath, force) {
237
+ if (existsSync(targetPath) && !force) {
238
+ console.log(`skip ${targetPath} (already exists)`);
239
+ return;
240
+ }
241
+
242
+ writeJson(targetPath, {
243
+ extends: [`./node_modules/${packageName}/${exportPath}`],
244
+ });
245
+ console.log(`write ${targetPath}`);
246
+ }
247
+
248
+ function maybeUpdatePackageJson(targetPackageJsonPath, force) {
249
+ if (!existsSync(targetPackageJsonPath)) {
250
+ console.log("skip package.json (not found)");
251
+ return;
252
+ }
253
+
254
+ const packageJson = readJson(targetPackageJsonPath);
255
+
256
+ if (!packageJson.devDependencies || typeof packageJson.devDependencies !== "object") {
257
+ packageJson.devDependencies = {};
258
+ }
259
+
260
+ const selfDependencyRange = getSelfDependencyRange();
261
+ if (!packageJson.devDependencies[packageName] || force) {
262
+ packageJson.devDependencies[packageName] = selfDependencyRange;
263
+ }
264
+
265
+ upsertScript(packageJson, "lint", "eimerreis-linting lint", force);
266
+ upsertScript(packageJson, "lint:fix", "eimerreis-linting lint --fix", force);
267
+ upsertScript(packageJson, "format", "eimerreis-linting format", force);
268
+ upsertScript(packageJson, "format:check", "eimerreis-linting format --check", force);
269
+
270
+ writeJson(targetPackageJsonPath, packageJson);
271
+ console.log(`update ${targetPackageJsonPath}`);
272
+ }
273
+
274
+ function printNextSteps(targetDir) {
275
+ const relativePath = targetDir === process.cwd() ? "." : targetDir;
276
+ console.log("done");
277
+ console.log("next steps:");
278
+ console.log(`1) cd ${relativePath}`);
279
+ console.log("2) npm install");
280
+ console.log("3) npm run lint && npm run format:check");
50
281
  }
51
282
 
52
- function createExtendsConfig(targetPath, exportPath) {
53
- if (existsSync(targetPath) && !force) {
54
- console.log(`skip ${targetPath} (already exists)`);
55
- return;
56
- }
283
+ async function runInit(args) {
284
+ const { targetDir, flags } = parsePathAndFlags(args, ["--force"]);
285
+ const force = flags.has("--force");
286
+ const targetPackageJsonPath = resolve(targetDir, "package.json");
287
+ const oxlintPath = resolve(targetDir, ".oxlintrc.json");
288
+ const oxfmtPath = resolve(targetDir, ".oxfmtrc.json");
289
+
290
+ if (!existsSync(packageRoot)) {
291
+ console.error("init failed: package root not found");
292
+ process.exit(1);
293
+ }
294
+
295
+ createExtendsConfig(oxlintPath, "oxlint.config.json", force);
296
+ createExtendsConfig(oxfmtPath, "oxfmt.config.json", force);
297
+ maybeUpdatePackageJson(targetPackageJsonPath, force);
57
298
 
58
- writeJson(targetPath, {
59
- extends: [`./node_modules/${packageName}/${exportPath}`],
60
- });
61
- console.log(`write ${targetPath}`);
299
+ printNextSteps(targetDir);
62
300
  }
63
301
 
64
- function maybeUpdatePackageJson() {
65
- if (!existsSync(targetPackageJsonPath)) {
66
- console.log("skip package.json (not found)");
67
- return;
68
- }
302
+ async function runLint(args) {
303
+ if (!hasInstalledPackage("oxlint")) {
304
+ console.error("oxlint is not installed. Run: npm install");
305
+ process.exit(1);
306
+ }
307
+
308
+ const { targetDir, flags } = parsePathAndFlags(args, ["--fix"]);
309
+ const oxlintBinPath = resolvePackageBin("oxlint", "bin/oxlint");
310
+ const lintArgs = [oxlintBinPath];
311
+ const lintConfigPath = resolveLintConfigPath(targetDir);
312
+
313
+ lintArgs.push("-c", lintConfigPath);
314
+
315
+ if (flags.has("--fix")) {
316
+ lintArgs.push("--fix");
317
+ }
318
+
319
+ lintArgs.push(".");
69
320
 
70
- const packageJson = readJson(targetPackageJsonPath);
321
+ const lintExitCode = await runCommand(process.execPath, lintArgs, targetDir);
322
+ if (lintExitCode !== 0) {
323
+ process.exit(lintExitCode);
324
+ }
71
325
 
72
- upsertScript(packageJson, "lint", "oxlint .");
73
- upsertScript(packageJson, "lint:fix", "oxlint --fix .");
74
- upsertScript(packageJson, "format", "oxfmt .");
75
- upsertScript(packageJson, "format:check", "oxfmt --check .");
326
+ if (!hasReactProject(targetDir)) {
327
+ console.log("skip react-doctor (no react/next dependency found)");
328
+ return;
329
+ }
76
330
 
77
- writeJson(targetPackageJsonPath, packageJson);
78
- console.log(`update ${targetPackageJsonPath}`);
331
+ const reactDoctorEntryPath = resolvePackageEntry("react-doctor");
332
+ const doctorExitCode = await runCommand(process.execPath, [reactDoctorEntryPath, "-y", "."], targetDir);
333
+ if (doctorExitCode !== 0) {
334
+ process.exit(doctorExitCode);
335
+ }
79
336
  }
80
337
 
81
- function printNextSteps() {
82
- const relativePath = targetDir === process.cwd() ? "." : targetDir;
83
- console.log("done");
84
- console.log("next steps:");
85
- console.log(`1) cd ${relativePath}`);
86
- console.log("2) npm add -D @eimerreis/linting oxlint oxfmt");
87
- console.log("3) npm run lint && npm run format:check");
338
+ async function runFormat(args) {
339
+ if (!hasInstalledPackage("oxfmt")) {
340
+ console.error("oxfmt is not installed. Run: npm install");
341
+ process.exit(1);
342
+ }
343
+
344
+ const { targetDir, flags } = parsePathAndFlags(args, ["--check"]);
345
+ const oxfmtBinPath = resolvePackageBin("oxfmt", "bin/oxfmt");
346
+ const formatArgs = [oxfmtBinPath];
347
+ const formatConfigPath = resolveFormatConfigPath(targetDir);
348
+
349
+ formatArgs.push("-c", formatConfigPath);
350
+
351
+ if (flags.has("--check")) {
352
+ formatArgs.push("--check");
353
+ }
354
+
355
+ formatArgs.push(".");
356
+
357
+ const formatExitCode = await runCommand(process.execPath, formatArgs, targetDir);
358
+ if (formatExitCode !== 0) {
359
+ process.exit(formatExitCode);
360
+ }
88
361
  }
89
362
 
90
- function main() {
91
- if (!existsSync(packageRoot)) {
92
- console.error("init failed: package root not found");
93
- process.exit(1);
94
- }
363
+ async function main() {
364
+ try {
365
+ const rawArgs = process.argv.slice(2);
366
+ if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
367
+ printUsage();
368
+ process.exit(0);
369
+ }
370
+
371
+ const { command, args } = parseCommand(rawArgs);
372
+
373
+ if (command === "init") {
374
+ await runInit(args);
375
+ return;
376
+ }
377
+
378
+ if (command === "lint") {
379
+ await runLint(args);
380
+ return;
381
+ }
382
+
383
+ if (command === "format") {
384
+ await runFormat(args);
385
+ return;
386
+ }
95
387
 
96
- createExtendsConfig(oxlintPath, "oxlint.config.json");
97
- createExtendsConfig(oxfmtPath, "oxfmt.config.json");
98
- maybeUpdatePackageJson();
99
- printNextSteps();
388
+ console.error(`Unknown command: ${command}`);
389
+ printUsage();
390
+ process.exit(1);
391
+ } catch (error) {
392
+ console.error(error instanceof Error ? error.message : String(error));
393
+ process.exit(1);
394
+ }
100
395
  }
101
396
 
102
397
  main();
package/oxfmt.config.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
- "$schema": "./node_modules/oxfmt/configuration_schema.json",
3
- "printWidth": 125,
4
- "tabWidth": 4,
5
- "semi": true,
6
- "singleQuote": false,
7
- "trailingComma": "es5",
8
- "sortImports": {
9
- "order": "asc",
10
- "ignoreCase": true,
11
- "newlinesBetween": true,
12
- "groups": ["builtin", "external", "internal", ["parent", "sibling", "index"]],
13
- "internalPattern": ["@/", "~/"]
14
- },
15
- "sortTailwindcss": {
16
- "functions": ["cn", "clsx", "cva", "tw"]
17
- },
18
- "ignorePatterns": ["node_modules/**", ".next/**", "dist/**", "build/**", "coverage/**", "out/**"]
2
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
3
+ "printWidth": 125,
4
+ "tabWidth": 4,
5
+ "semi": true,
6
+ "singleQuote": false,
7
+ "trailingComma": "es5",
8
+ "sortImports": {
9
+ "order": "asc",
10
+ "ignoreCase": true,
11
+ "newlinesBetween": true,
12
+ "groups": ["builtin", "external", "internal", ["parent", "sibling", "index"]],
13
+ "internalPattern": ["@/", "~/"]
14
+ },
15
+ "sortTailwindcss": {
16
+ "functions": ["cn", "clsx", "cva", "tw"]
17
+ },
18
+ "ignorePatterns": ["node_modules/**", ".next/**", "dist/**", "build/**", "coverage/**", "out/**"]
19
19
  }
@@ -1,38 +1,38 @@
1
1
  {
2
- "$schema": "./node_modules/oxlint/configuration_schema.json",
3
- "plugins": ["eslint", "typescript", "unicorn", "oxc", "react", "nextjs", "import", "vitest"],
4
- "categories": {
5
- "correctness": "error",
6
- "suspicious": "warn"
7
- },
8
- "env": {
9
- "browser": true,
10
- "node": true,
11
- "es6": true
12
- },
13
- "rules": {
14
- "eslint/no-unused-vars": [
15
- "warn",
16
- {
17
- "varsIgnorePattern": "_"
18
- }
19
- ],
20
- "typescript/no-explicit-any": "off",
21
- "react/prop-types": "off",
22
- "react/react-in-jsx-scope": "off",
23
- "react-hooks/refs": "off",
24
- "react-hooks/incompatible-library": "off",
25
- "import/no-duplicates": "error",
26
- "import/no-self-import": "error",
27
- "import/no-cycle": "warn"
28
- },
29
- "ignorePatterns": ["node_modules/**", ".next/**", "dist/**", "build/**", "coverage/**", "out/**"],
30
- "overrides": [
31
- {
32
- "files": ["**/*.{test,spec}.{js,jsx,ts,tsx}", "**/__tests__/**/*.{js,jsx,ts,tsx}"],
33
- "rules": {
34
- "typescript/no-explicit-any": "off"
35
- }
36
- }
37
- ]
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "plugins": ["eslint", "typescript", "unicorn", "oxc", "react", "nextjs", "import", "vitest"],
4
+ "categories": {
5
+ "correctness": "error",
6
+ "suspicious": "warn"
7
+ },
8
+ "env": {
9
+ "browser": true,
10
+ "node": true,
11
+ "es6": true
12
+ },
13
+ "rules": {
14
+ "eslint/no-unused-vars": [
15
+ "warn",
16
+ {
17
+ "varsIgnorePattern": "_"
18
+ }
19
+ ],
20
+ "typescript/no-explicit-any": "off",
21
+ "react/prop-types": "off",
22
+ "react/react-in-jsx-scope": "off",
23
+ "react-hooks/refs": "off",
24
+ "react-hooks/incompatible-library": "off",
25
+ "import/no-duplicates": "error",
26
+ "import/no-self-import": "error",
27
+ "import/no-cycle": "warn"
28
+ },
29
+ "ignorePatterns": ["node_modules/**", ".next/**", "dist/**", "build/**", "coverage/**", "out/**"],
30
+ "overrides": [
31
+ {
32
+ "files": ["**/*.{test,spec}.{js,jsx,ts,tsx}", "**/__tests__/**/*.{js,jsx,ts,tsx}"],
33
+ "rules": {
34
+ "typescript/no-explicit-any": "off"
35
+ }
36
+ }
37
+ ]
38
38
  }
package/package.json CHANGED
@@ -1,57 +1,59 @@
1
1
  {
2
- "name": "@eimerreis/linting",
3
- "version": "0.1.0",
4
- "description": "Personal OXC linting and formatting defaults",
5
- "keywords": [
6
- "format",
7
- "lint",
8
- "nextjs",
9
- "oxc",
10
- "oxfmt",
11
- "oxlint",
12
- "react",
13
- "tailwind",
14
- "typescript"
15
- ],
16
- "license": "MIT",
17
- "bin": {
18
- "eimerreis-linting": "bin/init.mjs"
19
- },
20
- "files": [
21
- "bin",
22
- "oxlint.config.json",
23
- "oxfmt.config.json",
24
- "README.md",
25
- "LICENSE"
26
- ],
27
- "type": "module",
28
- "exports": {
29
- "./oxlint": "./oxlint.config.json",
30
- "./oxfmt": "./oxfmt.config.json",
31
- "./package.json": "./package.json"
32
- },
33
- "publishConfig": {
34
- "access": "public"
35
- },
36
- "scripts": {
37
- "changeset": "changeset",
38
- "lint": "oxlint .",
39
- "lint:fix": "oxlint --fix .",
40
- "format": "oxfmt .",
41
- "format:check": "oxfmt --check .",
42
- "version-packages": "changeset version",
43
- "release": "changeset publish"
44
- },
45
- "devDependencies": {
46
- "@changesets/cli": "^2.29.7",
47
- "oxfmt": "^0.41.0",
48
- "oxlint": "^1.56.0"
49
- },
50
- "peerDependencies": {
51
- "oxfmt": "^0.41.0",
52
- "oxlint": "^1.56.0"
53
- },
54
- "engines": {
55
- "node": "^20.19.0 || >=22.12.0"
56
- }
2
+ "name": "@eimerreis/linting",
3
+ "version": "0.3.0",
4
+ "description": "Personal OXC linting and formatting defaults",
5
+ "keywords": [
6
+ "format",
7
+ "lint",
8
+ "nextjs",
9
+ "oxc",
10
+ "oxfmt",
11
+ "oxlint",
12
+ "react",
13
+ "tailwind",
14
+ "typescript"
15
+ ],
16
+ "license": "MIT",
17
+ "repository": {
18
+ "url": "https://github.com/eimerreis/linting"
19
+ },
20
+ "bin": {
21
+ "eimerreis-linting": "bin/init.mjs"
22
+ },
23
+ "files": [
24
+ "bin",
25
+ "oxlint.config.json",
26
+ "oxfmt.config.json",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "type": "module",
31
+ "exports": {
32
+ "./oxlint": "./oxlint.config.json",
33
+ "./oxfmt": "./oxfmt.config.json",
34
+ "./package.json": "./package.json"
35
+ },
36
+ "publishConfig": {
37
+ "access": "public"
38
+ },
39
+ "scripts": {
40
+ "changeset": "changeset",
41
+ "lint": "node ./bin/init.mjs lint",
42
+ "lint:fix": "node ./bin/init.mjs lint --fix",
43
+ "format": "node ./bin/init.mjs format",
44
+ "format:check": "node ./bin/init.mjs format --check",
45
+ "version-packages": "changeset version",
46
+ "release": "changeset publish"
47
+ },
48
+ "dependencies": {
49
+ "oxfmt": "^0.41.0",
50
+ "oxlint": "^1.56.0",
51
+ "react-doctor": "^0.0.30"
52
+ },
53
+ "devDependencies": {
54
+ "@changesets/cli": "^2.29.7"
55
+ },
56
+ "engines": {
57
+ "node": "^20.19.0 || >=22.12.0"
58
+ }
57
59
  }