Skip to content
File

Blob: tools/base.eslint.config.mjs

javascript193 lines
1import { defineConfig } from "eslint/config";
2import eslint from '@eslint/js';
3import tseslint from 'typescript-eslint';
4import customRules from './custom-eslint-rules.mjs';
5 
6// Web platform and Workers runtime globals available in the execution
7// environment. Listed here so `no-undef` stays enabled for real typos.
8const workerdGlobals = {
9 // Web platform
10 AbortController: 'readonly',
11 AbortSignal: 'readonly',
12 Blob: 'readonly',
13 ByteLengthQueuingStrategy: 'readonly',
14 CloseEvent: 'readonly',
15 CompressionStream: 'readonly',
16 CountQueuingStrategy: 'readonly',
17 CryptoKey: 'readonly',
18 CustomEvent: 'readonly',
19 DecompressionStream: 'readonly',
20 DOMException: 'readonly',
21 Event: 'readonly',
22 EventSource: 'readonly',
23 EventTarget: 'readonly',
24 ExtendableEvent: 'readonly',
25 File: 'readonly',
26 FileSystemDirectoryHandle: 'readonly',
27 FileSystemFileHandle: 'readonly',
28 FileSystemWritableFileStream: 'readonly',
29 FormData: 'readonly',
30 Headers: 'readonly',
31 HTMLRewriter: 'readonly',
32 MessageChannel: 'readonly',
33 MessageEvent: 'readonly',
34 MessagePort: 'readonly',
35 Navigator: 'readonly',
36 ReadableByteStreamController: 'readonly',
37 ReadableStream: 'readonly',
38 ReadableStreamBYOBReader: 'readonly',
39 ReadableStreamBYOBRequest: 'readonly',
40 ReadableStreamDefaultController: 'readonly',
41 ReadableStreamDefaultReader: 'readonly',
42 Request: 'readonly',
43 Response: 'readonly',
44 StorageManager: 'readonly',
45 TextDecoder: 'readonly',
46 TextDecoderStream: 'readonly',
47 TextEncoder: 'readonly',
48 TextEncoderStream: 'readonly',
49 TransformStream: 'readonly',
50 URL: 'readonly',
51 URLPattern: 'readonly',
52 URLSearchParams: 'readonly',
53 WebAssembly: 'readonly',
54 WebSocket: 'readonly',
55 WebSocketPair: 'readonly',
56 WritableStream: 'readonly',
57 WritableStreamDefaultController: 'readonly',
58 WritableStreamDefaultWriter: 'readonly',
59 // Workers-specific
60 Cloudflare: 'readonly',
61 FixedLengthStream: 'readonly',
62 IdentityTransformStream: 'readonly',
63 ScheduledController: 'readonly',
64 // Node.js globals
65 Buffer: 'readonly',
66 global: 'readonly',
67 process: 'readonly',
68 // Web APIs
69 addEventListener: 'readonly',
70 atob: 'readonly',
71 btoa: 'readonly',
72 caches: 'readonly',
73 console: 'readonly',
74 crypto: 'readonly',
75 dispatchEvent: 'readonly',
76 fetch: 'readonly',
77 gc: 'readonly',
78 navigator: 'readonly',
79 performance: 'readonly',
80 queueMicrotask: 'readonly',
81 removeEventListener: 'readonly',
82 reportError: 'readonly',
83 scheduler: 'writable',
84 self: 'readonly',
85 setTimeout: 'readonly',
86 setInterval: 'readonly',
87 clearImmediate: 'readonly',
88 clearTimeout: 'readonly',
89 clearInterval: 'readonly',
90 setImmediate: 'readonly',
91 structuredClone: 'readonly',
92};
93 
94/**
95 * @returns {import('eslint/config').Config}
96 */
97export function baseConfig() {
98 return defineConfig([
99 eslint.configs.recommended,
100 ...tseslint.configs.strictTypeChecked,
101 {
102 plugins: {
103 workerd: customRules,
104 },
105 rules: {
106 'workerd/require-copyright-header': 'error',
107 },
108 },
109 {
110 languageOptions: {
111 globals: workerdGlobals,
112 parserOptions: {
113 ecmaVersion: 'latest',
114 sourceType: 'module',
115 projectService: true,
116 tsconfigRootDir: import.meta.dirname,
117 jsDocParsingMode: 'all',
118 },
119 },
120 rules: {
121 '@typescript-eslint/explicit-function-return-type': 'error',
122 '@typescript-eslint/explicit-member-accessibility': [
123 'error',
124 { accessibility: 'no-public' },
125 ],
126 '@typescript-eslint/explicit-module-boundary-types': 'off',
127 '@typescript-eslint/no-require-imports': 'error',
128 '@typescript-eslint/prefer-enum-initializers': 'error',
129 '@typescript-eslint/restrict-template-expressions': 'off',
130 '@typescript-eslint/no-non-null-assertion': 'error',
131 '@typescript-eslint/no-extraneous-class': 'off',
132 '@typescript-eslint/unified-signatures': 'off',
133 '@typescript-eslint/no-unused-vars': [
134 'error',
135 {
136 args: 'all',
137 argsIgnorePattern: '^_',
138 caughtErrors: 'all',
139 caughtErrorsIgnorePattern: '^_',
140 destructuredArrayIgnorePattern: '^_',
141 varsIgnorePattern: '^_',
142 ignoreRestSiblings: true,
143 },
144 ],
145 'no-restricted-syntax': [
146 'error',
147 {
148 selector: "MethodDefinition[accessibility='private']",
149 message:
150 "Use private field syntax (#) instead of 'private' keyword for methods",
151 },
152 {
153 selector:
154 "PropertyDefinition[accessibility='private']:not([computed=true])",
155 message:
156 "Use private field syntax (#) instead of 'private' keyword for simple properties",
157 },
158 {
159 selector: "TSParameterProperty[accessibility='private']",
160 message:
161 "Use private field syntax (#) instead of 'private' keyword for constructor parameters",
162 },
163 ],
164 },
165 },
166 {
167 files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
168 ...tseslint.configs.disableTypeChecked,
169 },
170 {
171 files: ['**/*.js', '**/*.mjs', '**/*.cjs'],
172 rules: {
173 '@typescript-eslint/explicit-function-return-type': 'off',
174 // Handler signatures (request, env, ctx) are framework-dictated; leading
175 // unused args are common and intentional in JS.
176 '@typescript-eslint/no-unused-vars': [
177 'error',
178 {
179 args: 'none',
180 caughtErrors: 'all',
181 caughtErrorsIgnorePattern: '^_',
182 destructuredArrayIgnorePattern: '^_',
183 varsIgnorePattern: '^_',
184 ignoreRestSiblings: true,
185 },
186 ],
187 },
188 },
189 ]);
190}
191 
192export default baseConfig();