@apify/oxlint-config 0.0.1 → 0.2.1

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
@@ -16,13 +16,21 @@ If you want type-aware rules (`typescript/no-floating-promises`, `typescript/awa
16
16
  npm install --save-dev oxlint-tsgolint
17
17
  ```
18
18
 
19
- Add an `.oxlintrc.json` at your project root that extends the shared config. oxlint's `extends` only accepts file paths (not bare specifiers), so reach into `node_modules` directly:
20
-
21
- ```jsonc
22
- {
23
- "$schema": "./node_modules/oxlint/configuration_schema.json",
24
- "extends": ["./node_modules/@apify/oxlint-config/index.json"]
25
- }
19
+ Add an `oxlint.config.ts` (or `.js`/`.mjs`) at your project root and spread the preset into it:
20
+
21
+ ```ts
22
+ import { defineConfig } from 'oxlint';
23
+ import sharedConfig from '@apify/oxlint-config';
24
+
25
+ export default defineConfig({
26
+ ...sharedConfig,
27
+ // local plugin additions, e.g. for React projects:
28
+ plugins: [...sharedConfig.plugins, 'react'],
29
+ overrides: [
30
+ ...sharedConfig.overrides,
31
+ // local overrides
32
+ ],
33
+ });
26
34
  ```
27
35
 
28
36
  Run lint:
@@ -35,7 +43,7 @@ npx oxlint --type-aware
35
43
 
36
44
  The shared config provides:
37
45
 
38
- - **Plugins** — `typescript`, `import`, `unicorn`, `jest`, `promise` (Rust-side, no install required). React plugins (`react`, `react-hooks`) are intentionally **not** included; enable them in your own `.oxlintrc.json` if your project uses React.
46
+ - **Plugins** — `typescript`, `import`, `unicorn`, `jest`, `promise` (Rust-side, no install required). React plugins are intentionally **not** included; consumers add `'react'` to `plugins` if their project uses React. (Note: oxlint's `react` plugin already covers React Hooks rules; there's no separate `react-hooks` plugin.)
39
47
  - **Rules** — the Apify house rules: `typescript/consistent-type-imports`, `typescript/no-floating-promises`, `unicorn/prefer-node-protocol`, `import/no-default-export`, `unicorn/no-await-in-promise-methods`, plus the curated `off` list of TypeScript strict rules we don't want.
40
48
  - **Overrides** — relaxed rules for test files, vite/jest/vitest config files, story files, and integration test directories.
41
49
 
@@ -43,30 +51,30 @@ Test framework helpers (`describe`, `it`, `expect`, `vi`, ...) are intentionally
43
51
 
44
52
  ## What's NOT included
45
53
 
46
- The shared config intentionally does **not** declare `jsPlugins` (the JS-side plugins like `eslint-plugin-storybook`, `eslint-plugin-cypress`, `eslint-plugin-playwright`, `@tanstack/eslint-plugin-query`). Those carry their own peer dependencies and are project-specific. Add them in your own `.oxlintrc.json` if you need them:
47
-
48
- ```jsonc
49
- {
50
- "$schema": "./node_modules/oxlint/configuration_schema.json",
51
- "extends": ["./node_modules/@apify/oxlint-config/index.json"],
52
- "jsPlugins": [
53
- { "name": "storybook", "specifier": "eslint-plugin-storybook" },
54
- { "name": "playwright", "specifier": "eslint-plugin-playwright" }
55
- ]
56
- }
54
+ The shared config does **not** declare `jsPlugins` (the JS-side plugins like `eslint-plugin-storybook`, `eslint-plugin-cypress`, `eslint-plugin-playwright`, `@tanstack/eslint-plugin-query`). Those carry their own peer dependencies and are project-specific. Add them in your own config:
55
+
56
+ ```ts
57
+ export default defineConfig({
58
+ ...sharedConfig,
59
+ jsPlugins: [
60
+ { name: 'storybook', specifier: 'eslint-plugin-storybook' },
61
+ { name: 'playwright', specifier: 'eslint-plugin-playwright' },
62
+ ],
63
+ });
57
64
  ```
58
65
 
59
66
  ## Overriding rules
60
67
 
61
- oxlint merges configs from extends-first to consumer-last; the consumer wins. Tighten or loosen a rule in your `.oxlintrc.json`:
68
+ Spread the preset and add your own `rules` block yours win over the preset:
62
69
 
63
- ```jsonc
64
- {
65
- "extends": ["./node_modules/@apify/oxlint-config/index.json"],
66
- "rules": {
67
- "no-console": "off"
68
- }
69
- }
70
+ ```ts
71
+ export default defineConfig({
72
+ ...sharedConfig,
73
+ rules: {
74
+ ...sharedConfig.rules,
75
+ 'no-console': 'off',
76
+ },
77
+ });
70
78
  ```
71
79
 
72
80
  ## License
package/index.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ import type { OxlintConfig } from 'oxlint';
2
+
3
+ /**
4
+ * Narrow {@link OxlintConfig} so the keys this preset always populates
5
+ * (`plugins`, `overrides`, `rules`, `env`) are non-optional. That lets
6
+ * consumers spread them directly without a non-null assertion:
7
+ *
8
+ * export default defineConfig({
9
+ * ...sharedConfig,
10
+ * plugins: [...sharedConfig.plugins, 'react'],
11
+ * overrides: [...sharedConfig.overrides, { ... }],
12
+ * });
13
+ */
14
+ export type ApifyOxlintConfig = OxlintConfig & {
15
+ plugins: NonNullable<OxlintConfig['plugins']>;
16
+ overrides: NonNullable<OxlintConfig['overrides']>;
17
+ rules: NonNullable<OxlintConfig['rules']>;
18
+ env: NonNullable<OxlintConfig['env']>;
19
+ };
20
+
21
+ declare const config: ApifyOxlintConfig;
22
+ export default config;
package/index.js ADDED
@@ -0,0 +1,169 @@
1
+ /**
2
+ * Shared oxlint preset for Apify projects.
3
+ *
4
+ * Spread it into your `oxlint.config.{ts,js,mjs}`:
5
+ *
6
+ * import { defineConfig } from 'oxlint';
7
+ * import sharedConfig from '@apify/oxlint-config';
8
+ *
9
+ * export default defineConfig({
10
+ * ...sharedConfig,
11
+ * plugins: [...sharedConfig.plugins, 'react'],
12
+ * overrides: [
13
+ * ...sharedConfig.overrides,
14
+ * // local overrides go here
15
+ * ],
16
+ * });
17
+ */
18
+ export default {
19
+ plugins: ['typescript', 'import', 'unicorn', 'jest', 'promise'],
20
+ env: {
21
+ node: true,
22
+ browser: true,
23
+ es2022: true,
24
+ },
25
+ rules: {
26
+ 'no-console': 'error',
27
+ 'no-plusplus': 'off',
28
+ 'no-await-in-loop': 'off',
29
+ 'no-continue': 'off',
30
+ 'no-void': ['error', { allowAsStatement: true }],
31
+ 'no-use-before-define': [
32
+ 'error',
33
+ { functions: false, classes: true, variables: true, allowNamedExports: false },
34
+ ],
35
+ 'prefer-destructuring': [
36
+ 'error',
37
+ {
38
+ VariableDeclarator: { array: false, object: true },
39
+ AssignmentExpression: { array: false, object: false },
40
+ },
41
+ { enforceForRenamedProperties: false },
42
+ ],
43
+ 'no-labels': 'error',
44
+ 'guard-for-in': 'error',
45
+ 'import-js/no-extraneous-dependencies': [
46
+ 'error',
47
+ {
48
+ devDependencies: [
49
+ '**/vite.config.{js,ts,mjs,mts}',
50
+ '**/vitest.config.{js,ts,mjs,mts}',
51
+ '**/*.test.{js,ts,jsx,tsx}',
52
+ '**/*.spec.{js,ts,jsx,tsx}',
53
+ '**/{test,tests,integration_tests}/**/*.{js,ts,jsx,tsx,mjs,mts,cjs,cts}',
54
+ '**/.storybook/**/*.{js,ts,jsx,tsx}',
55
+ '**/*.stories.{js,jsx,ts,tsx}',
56
+ ],
57
+ },
58
+ ],
59
+ 'typescript/no-shadow': 'error',
60
+ 'no-shadow': 'off',
61
+ 'typescript/no-non-null-assertion': 'off',
62
+ 'typescript/no-useless-constructor': 'error',
63
+ 'no-useless-constructor': 'off',
64
+ 'typescript/default-param-last': 'error',
65
+ 'default-param-last': 'off',
66
+ 'typescript/no-floating-promises': 'error',
67
+ 'typescript/await-thenable': 'error',
68
+ 'typescript/no-misused-promises': [
69
+ 'error',
70
+ { checksVoidReturn: { arguments: false, attributes: false } },
71
+ ],
72
+ 'typescript/promise-function-async': 'error',
73
+ 'typescript/consistent-type-imports': 'error',
74
+ 'typescript/array-type': 'error',
75
+ 'typescript/adjacent-overload-signatures': 'error',
76
+ 'typescript/no-for-in-array': 'error',
77
+ 'typescript/no-implied-eval': 'error',
78
+ 'typescript/no-inferrable-types': 'error',
79
+ 'typescript/no-confusing-non-null-assertion': 'error',
80
+ 'typescript/prefer-includes': 'error',
81
+ 'no-unused-vars': 'off',
82
+ 'typescript/no-unused-vars': [
83
+ 'error',
84
+ { argsIgnorePattern: '^_', ignoreRestSiblings: true },
85
+ ],
86
+ 'typescript/no-empty-function': 'error',
87
+ 'no-empty-function': 'off',
88
+ 'typescript/consistent-return': 'error',
89
+ 'consistent-return': 'off',
90
+ 'typescript/dot-notation': 'error',
91
+ 'dot-notation': 'off',
92
+ 'import/no-default-export': 'error',
93
+ 'import/named': 'off',
94
+ 'unicorn/prefer-node-protocol': 'error',
95
+ 'unicorn/no-await-in-promise-methods': 'error',
96
+ 'jest/require-to-throw-message': 'off',
97
+ 'jest/prefer-snapshot-hint': 'off',
98
+ 'typescript/unbound-method': 'off',
99
+ 'typescript/restrict-template-expressions': 'off',
100
+ 'typescript/no-useless-default-assignment': 'off',
101
+ 'typescript/no-duplicate-type-constituents': 'off',
102
+ 'typescript/no-redundant-type-constituents': 'off',
103
+ 'typescript/no-misused-spread': 'off',
104
+ 'typescript/require-array-sort-compare': 'off',
105
+ 'typescript/no-base-to-string': 'off',
106
+ 'typescript/no-array-delete': 'off',
107
+ 'typescript/no-unnecessary-parameter-property-assignment': 'off',
108
+ 'typescript/no-meaningless-void-operator': 'off',
109
+ 'typescript/restrict-plus-operands': 'off',
110
+ 'typescript/no-unsafe-argument': 'off',
111
+ 'typescript/no-unsafe-assignment': 'off',
112
+ 'typescript/no-unsafe-call': 'off',
113
+ 'typescript/no-unsafe-member-access': 'off',
114
+ 'typescript/no-unsafe-return': 'off',
115
+ 'typescript/prefer-nullish-coalescing': 'off',
116
+ 'typescript/prefer-optional-chain': 'off',
117
+ 'typescript/strict-boolean-expressions': 'off',
118
+ 'unicorn/no-new-array': 'off',
119
+ 'unicorn/no-useless-fallback-in-spread': 'off',
120
+ 'unicorn/no-useless-spread': 'off',
121
+ 'unicorn/no-thenable': 'off',
122
+ 'unicorn/prefer-module': 'off',
123
+ 'unicorn/filename-case': 'off',
124
+ 'promise/no-callback-in-promise': 'off',
125
+ 'promise/always-return': 'off',
126
+ 'promise/catch-or-return': 'off',
127
+ 'promise/param-names': 'off',
128
+ 'promise/no-nesting': 'off',
129
+ 'promise/no-promise-in-callback': 'off',
130
+ 'promise/no-return-wrap': 'off',
131
+ 'promise/prefer-await-to-callbacks': 'off',
132
+ 'promise/prefer-await-to-then': 'off',
133
+ },
134
+ overrides: [
135
+ {
136
+ files: ['**/*.spec.*', '**/*.test.*', '**/test/**', '**/tests/**', '**/integration_tests/**'],
137
+ rules: {
138
+ 'no-console': 'off',
139
+ 'typescript/no-inferrable-types': 'off',
140
+ 'typescript/promise-function-async': 'off',
141
+ 'typescript/await-thenable': 'off',
142
+ 'typescript/no-floating-promises': 'off',
143
+ 'typescript/no-misused-promises': 'off',
144
+ 'import-js/no-extraneous-dependencies': 'off',
145
+ 'jest/no-disabled-tests': 'error',
146
+ 'jest/no-conditional-expect': 'error',
147
+ 'jest/no-focused-tests': 'error',
148
+ 'jest/valid-expect': 'off',
149
+ 'import/no-default-export': 'off',
150
+ },
151
+ },
152
+ {
153
+ files: [
154
+ '**/vite.config*.{ts,mts,js,mjs}',
155
+ '**/vitest.config*.{ts,mts,js,mjs}',
156
+ '**/jest.config*.{js,mjs}',
157
+ ],
158
+ rules: { 'import/no-default-export': 'off' },
159
+ },
160
+ {
161
+ files: ['**/*.stories.{js,jsx,ts,tsx,mjs,cjs}'],
162
+ rules: { 'no-console': 'off', 'import/no-default-export': 'off' },
163
+ },
164
+ {
165
+ files: ['**/integration_tests/**'],
166
+ rules: { 'jest/expect-expect': 'off' },
167
+ },
168
+ ],
169
+ };
package/package.json CHANGED
@@ -1,17 +1,22 @@
1
1
  {
2
2
  "name": "@apify/oxlint-config",
3
- "version": "0.0.1",
3
+ "version": "0.2.1",
4
4
  "description": "Apify oxlint preset to be shared between projects.",
5
5
  "repository": {
6
6
  "url": "https://github.com/apify/apify-oxlint-config"
7
7
  },
8
- "main": "index.json",
8
+ "type": "module",
9
+ "main": "index.js",
10
+ "types": "./index.d.ts",
9
11
  "exports": {
10
- ".": "./index.json",
11
- "./index.json": "./index.json"
12
+ ".": {
13
+ "types": "./index.d.ts",
14
+ "default": "./index.js"
15
+ }
12
16
  },
13
17
  "files": [
14
- "index.json"
18
+ "index.js",
19
+ "index.d.ts"
15
20
  ],
16
21
  "scripts": {
17
22
  "test": "echo \"No tests specified\" && exit 0"
package/index.json DELETED
@@ -1,202 +0,0 @@
1
- {
2
- "$schema": "https://raw.githubusercontent.com/oxc-project/oxc/main/npm/oxlint/configuration_schema.json",
3
- "plugins": [
4
- "typescript",
5
- "import",
6
- "unicorn",
7
- "jest",
8
- "promise"
9
- ],
10
- "env": {
11
- "node": true,
12
- "browser": true,
13
- "es2022": true
14
- },
15
- "rules": {
16
- "no-console": "error",
17
- "no-plusplus": "off",
18
- "no-await-in-loop": "off",
19
- "no-continue": "off",
20
- "no-void": [
21
- "error",
22
- {
23
- "allowAsStatement": true
24
- }
25
- ],
26
- "no-use-before-define": [
27
- "error",
28
- {
29
- "functions": false,
30
- "classes": true,
31
- "variables": true,
32
- "allowNamedExports": false
33
- }
34
- ],
35
- "prefer-destructuring": [
36
- "error",
37
- {
38
- "VariableDeclarator": {
39
- "array": false,
40
- "object": true
41
- },
42
- "AssignmentExpression": {
43
- "array": false,
44
- "object": false
45
- }
46
- },
47
- {
48
- "enforceForRenamedProperties": false
49
- }
50
- ],
51
- "no-labels": "error",
52
- "guard-for-in": "error",
53
- "import-js/no-extraneous-dependencies": [
54
- "error",
55
- {
56
- "devDependencies": [
57
- "**/vite.config.{js,ts,mjs,mts}",
58
- "**/vitest.config.{js,ts,mjs,mts}",
59
- "**/*.test.{js,ts,jsx,tsx}",
60
- "**/*.spec.{js,ts,jsx,tsx}",
61
- "**/{test,tests,integration_tests}/**/*.{js,ts,jsx,tsx,mjs,mts,cjs,cts}",
62
- "**/.storybook/**/*.{js,ts,jsx,tsx}",
63
- "**/*.stories.{js,jsx,ts,tsx}"
64
- ]
65
- }
66
- ],
67
- "typescript/no-shadow": "error",
68
- "no-shadow": "off",
69
- "typescript/no-non-null-assertion": "off",
70
- "typescript/no-useless-constructor": "error",
71
- "no-useless-constructor": "off",
72
- "typescript/default-param-last": "error",
73
- "default-param-last": "off",
74
- "typescript/no-floating-promises": "error",
75
- "typescript/await-thenable": "error",
76
- "typescript/no-misused-promises": [
77
- "error",
78
- {
79
- "checksVoidReturn": {
80
- "arguments": false,
81
- "attributes": false
82
- }
83
- }
84
- ],
85
- "typescript/promise-function-async": "error",
86
- "typescript/consistent-type-imports": "error",
87
- "typescript/array-type": "error",
88
- "typescript/adjacent-overload-signatures": "error",
89
- "typescript/no-for-in-array": "error",
90
- "typescript/no-implied-eval": "error",
91
- "typescript/no-inferrable-types": "error",
92
- "typescript/no-confusing-non-null-assertion": "error",
93
- "typescript/prefer-includes": "error",
94
- "no-unused-vars": "off",
95
- "typescript/no-unused-vars": [
96
- "error",
97
- {
98
- "argsIgnorePattern": "^_",
99
- "ignoreRestSiblings": true
100
- }
101
- ],
102
- "typescript/no-empty-function": "error",
103
- "no-empty-function": "off",
104
- "typescript/consistent-return": "error",
105
- "consistent-return": "off",
106
- "typescript/dot-notation": "error",
107
- "dot-notation": "off",
108
- "import/no-default-export": "error",
109
- "import/named": "off",
110
- "unicorn/prefer-node-protocol": "error",
111
- "unicorn/no-await-in-promise-methods": "error",
112
- "jest/require-to-throw-message": "off",
113
- "jest/prefer-snapshot-hint": "off",
114
- "typescript/unbound-method": "off",
115
- "typescript/restrict-template-expressions": "off",
116
- "typescript/no-useless-default-assignment": "off",
117
- "typescript/no-duplicate-type-constituents": "off",
118
- "typescript/no-redundant-type-constituents": "off",
119
- "typescript/no-misused-spread": "off",
120
- "typescript/require-array-sort-compare": "off",
121
- "typescript/no-base-to-string": "off",
122
- "typescript/no-array-delete": "off",
123
- "typescript/no-unnecessary-parameter-property-assignment": "off",
124
- "typescript/no-meaningless-void-operator": "off",
125
- "typescript/restrict-plus-operands": "off",
126
- "typescript/no-unsafe-argument": "off",
127
- "typescript/no-unsafe-assignment": "off",
128
- "typescript/no-unsafe-call": "off",
129
- "typescript/no-unsafe-member-access": "off",
130
- "typescript/no-unsafe-return": "off",
131
- "typescript/prefer-nullish-coalescing": "off",
132
- "typescript/prefer-optional-chain": "off",
133
- "typescript/strict-boolean-expressions": "off",
134
- "unicorn/no-new-array": "off",
135
- "unicorn/no-useless-fallback-in-spread": "off",
136
- "unicorn/no-useless-spread": "off",
137
- "unicorn/no-thenable": "off",
138
- "unicorn/prefer-module": "off",
139
- "unicorn/filename-case": "off",
140
- "promise/no-callback-in-promise": "off",
141
- "promise/always-return": "off",
142
- "promise/catch-or-return": "off",
143
- "promise/param-names": "off",
144
- "promise/no-nesting": "off",
145
- "promise/no-promise-in-callback": "off",
146
- "promise/no-return-wrap": "off",
147
- "promise/prefer-await-to-callbacks": "off",
148
- "promise/prefer-await-to-then": "off"
149
- },
150
- "overrides": [
151
- {
152
- "files": [
153
- "**/*.spec.*",
154
- "**/*.test.*",
155
- "**/test/**",
156
- "**/tests/**",
157
- "**/integration_tests/**"
158
- ],
159
- "rules": {
160
- "no-console": "off",
161
- "typescript/no-inferrable-types": "off",
162
- "typescript/promise-function-async": "off",
163
- "typescript/await-thenable": "off",
164
- "typescript/no-floating-promises": "off",
165
- "typescript/no-misused-promises": "off",
166
- "import-js/no-extraneous-dependencies": "off",
167
- "jest/no-disabled-tests": "error",
168
- "jest/no-conditional-expect": "error",
169
- "jest/no-focused-tests": "error",
170
- "jest/valid-expect": "off",
171
- "import/no-default-export": "off"
172
- }
173
- },
174
- {
175
- "files": [
176
- "**/vite.config*.{ts,mts,js,mjs}",
177
- "**/vitest.config*.{ts,mts,js,mjs}",
178
- "**/jest.config*.{js,mjs}"
179
- ],
180
- "rules": {
181
- "import/no-default-export": "off"
182
- }
183
- },
184
- {
185
- "files": [
186
- "**/*.stories.{js,jsx,ts,tsx,mjs,cjs}"
187
- ],
188
- "rules": {
189
- "no-console": "off",
190
- "import/no-default-export": "off"
191
- }
192
- },
193
- {
194
- "files": [
195
- "**/integration_tests/**"
196
- ],
197
- "rules": {
198
- "jest/expect-expect": "off"
199
- }
200
- }
201
- ]
202
- }