@luxfi/biome-config 1.0.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/base.jsonc ADDED
@@ -0,0 +1,1047 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
3
+ // Generic Biome Config Marker System:
4
+ // This config uses __INCLUDE_GLOBAL_VALUES__ markers in overrides to merge values from the main linter config.
5
+ // When scripts/generate.js runs, it:
6
+ // 1. Extracts all rule values from the main linter.rules section
7
+ // 2. Looks for __INCLUDE_GLOBAL_VALUES__ markers in override sections
8
+ // 3. Merges the global values into the override at the same rule path
9
+ // 4. Removes the markers from the compiled output
10
+ //
11
+ // First-level merging:
12
+ // - Only merges top-level keys (e.g., path names in "paths", keys in "deniedGlobals")
13
+ // - Does NOT merge nested properties within each key's value
14
+ // - When both global and override define the same key, the override value completely replaces the global value
15
+ //
16
+ // Special behaviors:
17
+ // - Setting a key to "off" removes that specific global entry from the override
18
+ // - Array options (like "patterns") are deduplicated by comparing JSON serialization
19
+ //
20
+ // Overrides structure:
21
+ // - Overrides are grouped by package/app with inline comments marking each section
22
+ // - Groups: GLOBAL (test files, JS files), packages/*, apps/*
23
+ //
24
+ // Example usage in an override:
25
+ // "noRestrictedImports": {
26
+ // "options": {
27
+ // "paths": {
28
+ // "__INCLUDE_GLOBAL_VALUES__": true, // Include all global paths
29
+ // "some-global-path": "off", // Except this one
30
+ // "override-specific-path": { ... } // Plus override-specific restrictions
31
+ // },
32
+ // "patterns": ["__INCLUDE_GLOBAL_VALUES__"] // Include all global patterns
33
+ // }
34
+ // }
35
+ "vcs": {
36
+ "enabled": true,
37
+ "clientKind": "git",
38
+ "useIgnoreFile": true
39
+ },
40
+ "files": {
41
+ "ignoreUnknown": false,
42
+ "includes": [
43
+ "**/*.ts",
44
+ "**/*.tsx",
45
+ "**/*.js",
46
+ "**/*.jsx",
47
+ "**/*.json",
48
+ "**/*.jsonc",
49
+ "!.vscode/settings.json",
50
+ "!.vscode/extensions.json",
51
+ "!tools/uniswap-nx/src/generators"
52
+ ],
53
+ "experimentalScannerIgnores": [
54
+ "*.tsbuildinfo",
55
+ "__generated__/**",
56
+ "__mocks__/**",
57
+ ".bun/**",
58
+ ".detoxrc.js",
59
+ ".tamagui/**",
60
+ "@types/**",
61
+ "*.graphql",
62
+ "*.html",
63
+ "*.inc",
64
+ "*.json",
65
+ "*.jsonc",
66
+ "*.md",
67
+ "*.yml",
68
+ "craco.config.cjs",
69
+ "jest-setup.js",
70
+ "jest.config.js",
71
+ "metro.config.js",
72
+ "types/**",
73
+ "**/lcov-report/**",
74
+ "**/coverage/**",
75
+ "apps/extension/.storybook/storybook.requires.ts",
76
+ "apps/extension/.maestro/**",
77
+ "apps/extension/dev/**",
78
+ "apps/mobile/.storybook/storybook.requires.ts",
79
+ "apps/mobile/.maestro/**",
80
+ "apps/web/playwright/**",
81
+ "apps/web/cypress/**",
82
+ "apps/web/public/**",
83
+ "apps/web/functions/**",
84
+ "apps/web/vite/**",
85
+ "apps/web/scripts/**",
86
+ "apps/web/twist-configs/**",
87
+ "apps/web/test-results/**",
88
+ "apps/web/**/*.native.*",
89
+ "apps/web/**/*.ios.*",
90
+ "apps/web/**/*.android.*",
91
+ "apps/web/**/*.mts"
92
+ ]
93
+ },
94
+ "formatter": {
95
+ "enabled": true,
96
+ "formatWithErrors": false,
97
+ "indentStyle": "space",
98
+ "indentWidth": 2,
99
+ "lineEnding": "lf",
100
+ "lineWidth": 120,
101
+ "attributePosition": "auto",
102
+ "bracketSameLine": false,
103
+ "bracketSpacing": true,
104
+ "expand": "auto",
105
+ "useEditorconfig": true,
106
+ "includes": [
107
+ "**",
108
+ "!**/*.tsbuildinfo",
109
+ "!**/__generated__",
110
+ "!**/__mocks__",
111
+ "!**/.bun",
112
+ "!**/.detoxrc.js",
113
+ "!**/.tamagui",
114
+ "!**/@types",
115
+ "!**/*.graphql",
116
+ "!**/*.html",
117
+ "!**/*.inc",
118
+ "!**/*.md",
119
+ "!**/*.yml",
120
+ "!**/craco.config.cjs",
121
+ "!**/jest-setup.js",
122
+ "!**/jest.config.js",
123
+ "!**/metro.config.js",
124
+ "!**/types",
125
+ "!**/lcov-report",
126
+ "!**/coverage",
127
+ "!apps/mobile/ios/**",
128
+ "!apps/mobile/android/**",
129
+ "!apps/mobile/.storybook/storybook.requires.ts",
130
+ "!apps/mobile/**/metro.config.js",
131
+ "!apps/web/playwright/**",
132
+ "!apps/web/cypress/**",
133
+ "!apps/web/public/**",
134
+ "!apps/web/functions/**",
135
+ "!apps/web/scripts/**",
136
+ "!apps/web/twist-configs/**",
137
+ "!apps/web/test-results/**"
138
+ ]
139
+ },
140
+ "linter": {
141
+ "enabled": true,
142
+ "rules": {
143
+ "recommended": false,
144
+ "complexity": {
145
+ "noAdjacentSpacesInRegex": "warn",
146
+ "noArguments": "error",
147
+ "noBannedTypes": "error",
148
+ "noCommaOperator": "warn",
149
+ "noExtraBooleanCast": "warn",
150
+ "noUselessCatch": "error",
151
+ "noUselessEscapeInRegex": "warn",
152
+ "noUselessLoneBlockStatements": "warn",
153
+ "noUselessTypeConstraint": "error",
154
+ "noUselessUndefinedInitialization": "warn",
155
+ "noVoid": "warn",
156
+ "useLiteralKeys": "off" // Disable to allow TypeScript's noPropertyAccessFromIndexSignature
157
+ },
158
+ "correctness": {
159
+ "noChildrenProp": "error",
160
+ "noEmptyCharacterClassInRegex": "warn",
161
+ "noEmptyPattern": "error",
162
+ "noNonoctalDecimalEscape": "error",
163
+ "noPrecisionLoss": "error",
164
+ "noRestrictedElements": {
165
+ "level": "error",
166
+ "options": {
167
+ "elements": {
168
+ "div": "Please avoid using div when possible, even in web code! Use `Flex` or Fragments (`<>`)"
169
+ }
170
+ }
171
+ },
172
+ "noSelfAssign": "error",
173
+ "noSwitchDeclarations": "error",
174
+ "noUnsafeFinally": "error",
175
+ "noUnsafeOptionalChaining": "error",
176
+ "noUnusedImports": {
177
+ "level": "error",
178
+ "fix": "safe"
179
+ },
180
+ "noUnusedLabels": "error",
181
+ "noUnusedVariables": "error",
182
+ "useExhaustiveDependencies": {
183
+ "level": "error",
184
+ "options": {
185
+ "hooks": [
186
+ // React Native Reanimated hooks with stable results
187
+ { "name": "useSharedValue", "stableResult": true },
188
+ { "name": "useDerivedValue", "stableResult": true },
189
+ { "name": "useAnimatedRef", "stableResult": true }
190
+ ]
191
+ }
192
+ },
193
+ "useHookAtTopLevel": "error",
194
+ "useIsNan": "warn",
195
+ "useJsxKeyInIterable": "error",
196
+ "useValidForDirection": "error",
197
+ "useValidTypeof": "warn",
198
+ "useYield": "error"
199
+ },
200
+ "security": {
201
+ "noDangerouslySetInnerHtml": "error",
202
+ "noDangerouslySetInnerHtmlWithChildren": "error",
203
+ "noGlobalEval": "error"
204
+ },
205
+ "style": {
206
+ "noDoneCallback": "error",
207
+ "noNamespace": "error",
208
+ "noNonNullAssertion": "error",
209
+ "noRestrictedImports": {
210
+ "level": "error",
211
+ "options": {
212
+ // Global path restrictions that can be included in overrides using __INCLUDE_GLOBAL_VALUES__
213
+ "paths": {
214
+ "utilities/src/telemetry/analytics/analytics": {
215
+ "message": "Please only use this for initialization, tests, flushing, and internal usage. Otherwise use `packages/uniswap/src/features/telemetry`"
216
+ },
217
+ "utilities/src/telemetry/trace/Trace": {
218
+ "message": "Please use the Trace in 'uniswap/src/features/telemetry/Trace' for app level usage!"
219
+ },
220
+ "ui/src/components/modal/AdaptiveWebModal": {
221
+ "message": "Please import Modal from `uniswap/src/components/modals/Modal` instead. Modal uses AdaptiveWebModal under the hood but has extra logic for handling animation, mounting, and dismounting."
222
+ },
223
+ "react-native": {
224
+ "importNames": ["Switch", "Keyboard"],
225
+ "message": "Use our custom Switch component instead of Switch. Please use dismissNativeKeyboard() for keyboard dismissals."
226
+ },
227
+ "ui/src/hooks/useDeviceInsets": {
228
+ "importNames": ["useDeviceInsets"],
229
+ "message": "Use `useAppInsets` instead."
230
+ },
231
+ "react-native-safe-area-context": {
232
+ "importNames": ["useSafeAreaInsets"],
233
+ "message": "Use our internal useAppInsets hook instead."
234
+ },
235
+ "react-native-device-info": {
236
+ "importNames": ["getUniqueId"],
237
+ "message": "Not supported for web/extension, use `getUniqueId` from `utilities/src/device/getUniqueId` instead."
238
+ },
239
+ "wallet/src/data/apollo/usePersistedApolloClient": {
240
+ "importNames": ["usePersistedApolloClient"],
241
+ "message": "This hook should only be used once at the top level where the React app is initialized . You can use `import { useApolloClient } from '@apollo/client'` to get the default apollo client from the provider elsewhere in React. If you need access to apollo outside of React, you can use `import { apolloClientRef } from 'wallet/src/data/apollo/usePersistedApolloClient''`."
242
+ },
243
+ "expo-localization": {
244
+ "message": "Avoid using due to issue with unsupported locales. Use utilities/src/device/locales.ts getDeviceLocales instead"
245
+ },
246
+ "utilities/src/format/localeBased": {
247
+ "message": "Use via `useLocalizationContext` instead."
248
+ },
249
+ "uniswap/src/features/fiatCurrency/conversion": {
250
+ "importNames": ["useFiatConverter"],
251
+ "message": "Use via `useLocalizationContext` instead."
252
+ },
253
+ "uniswap/src/features/language/formatter": {
254
+ "importNames": ["useLocalizedFormatter"],
255
+ "message": "Use via `useLocalizationContext` instead."
256
+ },
257
+ "uniswap/src/features/dataApi/balances/balances": {
258
+ "importNames": ["usePortfolioValueModifiers"],
259
+ "message": "Use the wrapper hooks `usePortfolioTotalValue`, `useAccountListData` or `usePortfolioBalances` instead of `usePortfolioValueModifiers` directly."
260
+ },
261
+ "@gorhom/bottom-sheet": {
262
+ "importNames": ["BottomSheetTextInput"],
263
+ "message": "Use our internal BottomSheetTextInput wrapper from /uniswap/src/components/modals/Modal."
264
+ },
265
+ "expo-haptics": {
266
+ "message": "Use our internal HapticFeedback wrapper instead: import { HapticFeedback } from packages/uniswap/src/features/settings/useHapticFeedback/types"
267
+ },
268
+ "@uniswap/analytics": {
269
+ "importNames": ["sendAnalyticsEvent"],
270
+ "message": "Please use the typed `sendAnalyticsEvent` in 'uniswap/src/features/telemetry/send'"
271
+ },
272
+ "@tamagui/core": {
273
+ "message": "Please import from 'tamagui' directly to prevent mismatches."
274
+ }
275
+ },
276
+ "patterns": [
277
+ {
278
+ "group": ["ui/src/assets/icons/*.svg"],
279
+ "message": "Please do not import SVG files directly from `ui/src/assets/icons/*.svg`. Use generated icon components instead, e.g., `ui/src/components/icons/{iconName}`."
280
+ },
281
+ {
282
+ "group": ["@universe/*/src", "@universe/*/src/*"],
283
+ "message": "Deep imports from @universe/* packages are forbidden. Import from the package root instead (e.g., '@universe/api', '@universe/config'). All public APIs are exported from package roots."
284
+ }
285
+ ]
286
+ }
287
+ },
288
+ "noRestrictedGlobals": {
289
+ "level": "error",
290
+ "options": {
291
+ "deniedGlobals": {
292
+ // Denied globals that can be included in overrides using __INCLUDE_GLOBAL_VALUES__
293
+ "defaultStatus": "Use of this global variable is restricted.",
294
+ "status": "Use of this global variable is restricted.",
295
+ "scroll": "Use of this global variable is restricted.",
296
+ "outerHeight": "Use of this global variable is restricted.",
297
+ "screenX": "Use of this global variable is restricted.",
298
+ "opener": "Use of this global variable is restricted.",
299
+ "onfocus": "Use of this global variable is restricted.",
300
+ "pageYOffset": "Use of this global variable is restricted.",
301
+ "addEventListener": "Use of this global variable is restricted.",
302
+ "defaultstatus": "Use of this global variable is restricted.",
303
+ "history": "Use of this global variable is restricted.",
304
+ "frames": "Use of this global variable is restricted.",
305
+ "screenY": "Use of this global variable is restricted.",
306
+ "focus": "Use of this global variable is restricted.",
307
+ "outerWidth": "Use of this global variable is restricted.",
308
+ "opera": "Use of this global variable is restricted.",
309
+ "external": "Use of this global variable is restricted.",
310
+ "innerHeight": "Use of this global variable is restricted.",
311
+ "closed": "Use of this global variable is restricted.",
312
+ "frameElement": "Use of this global variable is restricted.",
313
+ "scrollY": "Use of this global variable is restricted.",
314
+ "self": "Use of this global variable is restricted.",
315
+ "chrome": "Direct `chrome` access is restricted to prevent accidental usage in the wrong context. Use `getChrome()` or `getChromeWithThrow()` instead.",
316
+ "onblur": "Use of this global variable is restricted.",
317
+ "find": "Use of this global variable is restricted.",
318
+ "parent": "Use of this global variable is restricted.",
319
+ "top": "Use of this global variable is restricted.",
320
+ "moveBy": "Use of this global variable is restricted.",
321
+ "menubar": "Use of this global variable is restricted.",
322
+ "length": "Use of this global variable is restricted.",
323
+ "onerror": "Use of this global variable is restricted.",
324
+ "onresize": "Use of this global variable is restricted.",
325
+ "removeEventListener": "Use of this global variable is restricted.",
326
+ "onload": "Use of this global variable is restricted.",
327
+ "scrollTo": "Use of this global variable is restricted.",
328
+ "moveTo": "Use of this global variable is restricted.",
329
+ "scrollX": "Use of this global variable is restricted.",
330
+ "name": "Use of this global variable is restricted.",
331
+ "toolbar": "Use of this global variable is restricted.",
332
+ "innerWidth": "Use of this global variable is restricted.",
333
+ "location": "Use of this global variable is restricted.",
334
+ "locationbar": "Use of this global variable is restricted.",
335
+ "scrollBy": "Use of this global variable is restricted.",
336
+ "resizeTo": "Use of this global variable is restricted.",
337
+ "stop": "Use of this global variable is restricted.",
338
+ "scrollbars": "Use of this global variable is restricted.",
339
+ "blur": "Use of this global variable is restricted.",
340
+ "screenTop": "Use of this global variable is restricted.",
341
+ "confirm": "Use of this global variable is restricted.",
342
+ "screen": "Use of this global variable is restricted.",
343
+ "screenLeft": "Use of this global variable is restricted.",
344
+ "event": "Use of this global variable is restricted.",
345
+ "onunload": "Use of this global variable is restricted.",
346
+ "pageXOffset": "Use of this global variable is restricted.",
347
+ "resizeBy": "Use of this global variable is restricted.",
348
+ "statusbar": "Use of this global variable is restricted.",
349
+ "close": "Use of this global variable is restricted.",
350
+ "open": "Use of this global variable is restricted.",
351
+ "print": "Use of this global variable is restricted."
352
+ }
353
+ }
354
+ },
355
+ "noYodaExpression": "warn",
356
+ "useArrayLiterals": "error",
357
+ "useAsConstAssertion": "error",
358
+ "useBlockStatements": "warn",
359
+ "useConst": "error",
360
+ "useEnumInitializers": "error"
361
+ },
362
+ "suspicious": {
363
+ "noAlert": "warn",
364
+ "noAsyncPromiseExecutor": "error",
365
+ "noBitwiseOperators": "warn",
366
+ "noCatchAssign": "warn",
367
+ "noClassAssign": "error",
368
+ "noCommentText": "error",
369
+ "noCompareNegZero": "error",
370
+ "noConsole": "error",
371
+ "noControlCharactersInRegex": "warn",
372
+ "noDebugger": "warn",
373
+ "noDoubleEquals": "warn",
374
+ "noDuplicateCase": "error",
375
+ "noDuplicateElseIf": "error",
376
+ "noDuplicateJsxProps": "error",
377
+ "noEmptyInterface": "error",
378
+ "noExplicitAny": "error",
379
+ "noExtraNonNullAssertion": "error",
380
+ "noFallthroughSwitchClause": "warn",
381
+ "noGlobalAssign": "error",
382
+ "noIrregularWhitespace": "error",
383
+ "noLabelVar": "warn",
384
+ "noMisleadingCharacterClass": "error",
385
+ "noMisleadingInstantiator": "error",
386
+ "noOctalEscape": "warn",
387
+ "noPrototypeBuiltins": "error",
388
+ "noSelfCompare": "warn",
389
+ "noShadowRestrictedNames": "warn",
390
+ "noSparseArray": "warn",
391
+ "noUnsafeDeclarationMerging": "error",
392
+ "noUselessRegexBackrefs": "error",
393
+ "noVar": "error",
394
+ "noWith": "warn"
395
+ }
396
+ },
397
+ "includes": [
398
+ "**",
399
+ "!**/.eslintrc.js",
400
+ "!**/babel.config.js",
401
+ "!**/jest.config.js",
402
+ "!**/metro.config.js",
403
+ "!**/node_modules",
404
+ "!**/storybook-static",
405
+ "!**/coverage",
406
+ "!.maestro/scripts/dist",
407
+ "!.maestro/scripts/performance/dist",
408
+ "!.maestro/scripts/performance/**/*.js",
409
+ "!**/__mocks__/**",
410
+ "!scripts/**",
411
+ "!.vscode/extensions.json"
412
+ ]
413
+ },
414
+ "javascript": {
415
+ "formatter": {
416
+ "jsxQuoteStyle": "double",
417
+ "quoteProperties": "asNeeded",
418
+ "trailingCommas": "all",
419
+ "semicolons": "asNeeded",
420
+ "arrowParentheses": "always",
421
+ "bracketSameLine": false,
422
+ "quoteStyle": "single",
423
+ "attributePosition": "auto",
424
+ "bracketSpacing": true
425
+ }
426
+ },
427
+ "json": {
428
+ "formatter": {
429
+ "trailingCommas": "none"
430
+ }
431
+ },
432
+ "html": {
433
+ "formatter": {
434
+ "selfCloseVoidElements": "always"
435
+ }
436
+ },
437
+ "assist": {
438
+ "enabled": true,
439
+ "actions": {
440
+ "source": {
441
+ "organizeImports": {
442
+ "level": "on",
443
+ "options": {
444
+ "identifierOrder": "natural"
445
+ }
446
+ }
447
+ }
448
+ }
449
+ },
450
+ // ===================================================================
451
+ // OVERRIDES
452
+ // ===================================================================
453
+ "overrides": [
454
+ // Auto-generate overrides for @universe/* packages
455
+ // This marker is replaced by the generator script with actual override configurations
456
+ "__AUTO_GENERATE_UNIVERSE_OVERRIDES__",
457
+ // packages/prices
458
+ {
459
+ "includes": ["packages/prices/src/index.ts"],
460
+ "linter": {
461
+ "rules": {}
462
+ }
463
+ },
464
+ // GLOBAL: Test files
465
+ {
466
+ "includes": ["**/*.test.ts", "**/*.test.tsx", "**/test/**", "**/tests/**", "**/*.spec.ts", "**/*.spec.tsx"],
467
+ "linter": {
468
+ "rules": {
469
+ "correctness": {
470
+ "noRestrictedElements": "off",
471
+ "noUnusedVariables": "off",
472
+ "noUnusedImports": "off",
473
+ "useExhaustiveDependencies": "off"
474
+ },
475
+ "style": {
476
+ "useEnumInitializers": "off",
477
+ "noNonNullAssertion": "off",
478
+ "noRestrictedImports": "off",
479
+ "noRestrictedGlobals": "off"
480
+ },
481
+ "suspicious": {
482
+ "noEmptyInterface": "off",
483
+ "noExplicitAny": "off",
484
+ "noShadowRestrictedNames": "off",
485
+ "noConsole": "off"
486
+ },
487
+ "complexity": {
488
+ "noUselessLoneBlockStatements": "off"
489
+ }
490
+ }
491
+ }
492
+ },
493
+ // GLOBAL: JavaScript files
494
+ {
495
+ "includes": ["**/*.js", "**/*.jsx"],
496
+ "linter": {
497
+ "rules": {
498
+ "suspicious": {
499
+ "noConsole": "off"
500
+ }
501
+ }
502
+ }
503
+ },
504
+ // packages/ui
505
+ {
506
+ "includes": [
507
+ "packages/ui/**",
508
+ "!packages/ui/**/*.test.ts",
509
+ "!packages/ui/**/*.test.tsx",
510
+ "!packages/ui/**/test/**",
511
+ "!packages/ui/**/tests/**"
512
+ ],
513
+ "linter": {
514
+ "rules": {
515
+ "style": {
516
+ "noRestrictedImports": {
517
+ "level": "error",
518
+ "options": {
519
+ "paths": {
520
+ "__INCLUDE_GLOBAL_VALUES__": true,
521
+ "ui/src": {
522
+ "message": "Avoid importing directly from ui/src from within the ui package which causes circular imports."
523
+ }
524
+ },
525
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
526
+ }
527
+ }
528
+ }
529
+ }
530
+ }
531
+ },
532
+ // packages/utilities
533
+ {
534
+ "includes": [
535
+ "packages/utilities/**",
536
+ "!packages/utilities/**/*.test.ts",
537
+ "!packages/utilities/**/*.test.tsx",
538
+ "!packages/utilities/**/test/**",
539
+ "!packages/utilities/**/tests/**"
540
+ ],
541
+ "linter": {
542
+ "rules": {
543
+ "style": {
544
+ "noRestrictedImports": {
545
+ "level": "error",
546
+ "options": {
547
+ "paths": {
548
+ "__INCLUDE_GLOBAL_VALUES__": true,
549
+ "utilities/src": {
550
+ "message": "Avoid importing directly from utilities/src from within the utilities package which causes circular imports."
551
+ }
552
+ },
553
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
554
+ }
555
+ }
556
+ }
557
+ }
558
+ }
559
+ },
560
+ {
561
+ "includes": [
562
+ "packages/utilities/src/index.ts",
563
+ "packages/utilities/src/platform/*",
564
+ "packages/utilities/src/addresses/*",
565
+ "packages/utilities/src/errors/*"
566
+ ],
567
+ "linter": {
568
+ "rules": {}
569
+ }
570
+ },
571
+ // packages/uniswap
572
+ {
573
+ "includes": [
574
+ "packages/uniswap/**",
575
+ "!packages/uniswap/**/*.test.ts",
576
+ "!packages/uniswap/**/*.test.tsx",
577
+ "!packages/uniswap/**/test/**",
578
+ "!packages/uniswap/**/tests/**"
579
+ ],
580
+ "linter": {
581
+ "rules": {
582
+ "style": {
583
+ "noRestrictedImports": {
584
+ "level": "error",
585
+ "options": {
586
+ "paths": {
587
+ "__INCLUDE_GLOBAL_VALUES__": true,
588
+ "uniswap/src": {
589
+ "message": "Avoid importing directly from uniswap/src from within the uniswap package which causes circular imports."
590
+ },
591
+ "@uniswap/sdk-core": {
592
+ "importNames": ["ChainId"],
593
+ "message": "Don't use ChainId from @uniswap/sdk-core. Use the UniverseChainId from universe/uniswap."
594
+ },
595
+ "uniswap/src/features/chains/hooks/useOrderedChainIds": {
596
+ "importNames": ["useOrderedChainIds"],
597
+ "message": "Use `useEnabledChains` instead, which returns the ordered chains that are currently enabled."
598
+ },
599
+ "uniswap/src/features/settings/selectors": {
600
+ "importNames": ["selectIsTestnetModeEnabled"],
601
+ "message": "Use `useEnabledChains` instead."
602
+ },
603
+ "uniswap/src/features/chains/chainInfo": {
604
+ "importNames": ["UNIVERSE_CHAIN_INFO"],
605
+ "message": "Use useChainInfo or helpers in packages/uniswap/src/features/chains/utils.ts when possible!"
606
+ },
607
+ "uniswap/src/data/graphql/uniswap-data-api/__generated__/react-hooks": {
608
+ "importNames": ["useAccountListQuery"],
609
+ "message": "Use `useAccountListData` instead."
610
+ }
611
+ },
612
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
613
+ }
614
+ }
615
+ }
616
+ }
617
+ }
618
+ },
619
+ {
620
+ "includes": [
621
+ "packages/uniswap/src/index.ts",
622
+ "packages/uniswap/src/features/telemetry/constants/index.ts",
623
+ "packages/uniswap/src/features/telemetry/constants/trace/index.ts",
624
+ "packages/uniswap/src/i18n/index.ts",
625
+ "packages/uniswap/src/state/index.ts",
626
+ "packages/uniswap/src/test/**"
627
+ ],
628
+ "linter": {
629
+ "rules": {
630
+ "style": {
631
+ "noRestrictedImports": {
632
+ "level": "error",
633
+ "options": {
634
+ "paths": {
635
+ "__INCLUDE_GLOBAL_VALUES__": true,
636
+ "uniswap/src": "off",
637
+ "utilities/src/format/localeBased": "off"
638
+ },
639
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
640
+ }
641
+ }
642
+ }
643
+ }
644
+ }
645
+ },
646
+ {
647
+ "includes": ["packages/uniswap/src/data/**/__generated__/**", "packages/uniswap/src/abis/types/**"],
648
+ "linter": {
649
+ "enabled": false
650
+ }
651
+ },
652
+ {
653
+ "includes": ["packages/uniswap/vite/**"],
654
+ "linter": {
655
+ "enabled": false
656
+ }
657
+ },
658
+ // packages/api
659
+ {
660
+ "includes": [
661
+ "packages/api/.eslintrc.js",
662
+ "packages/api/codegen.ts",
663
+ "packages/api/scripts/**",
664
+ "packages/api/src/**/__generated__/**"
665
+ ],
666
+ "linter": {
667
+ "enabled": false
668
+ }
669
+ },
670
+ {
671
+ "includes": ["packages/api/src/clients/trading/api.json"],
672
+ "formatter": {
673
+ "enabled": false
674
+ }
675
+ },
676
+ // packages/docker-image-builder
677
+ {
678
+ "includes": ["packages/docker-image-builder/**"],
679
+ "linter": {
680
+ "rules": {
681
+ "suspicious": {
682
+ "noConsole": "off"
683
+ }
684
+ }
685
+ }
686
+ },
687
+ // apps/extension
688
+ {
689
+ "includes": [
690
+ "apps/extension/**",
691
+ "!apps/extension/**/*.test.ts",
692
+ "!apps/extension/**/*.test.tsx",
693
+ "!apps/extension/**/test/**",
694
+ "!apps/extension/**/tests/**",
695
+ "!apps/extension/jest-setup.js",
696
+ "!apps/extension/scripts/**",
697
+ "!apps/extension/ReactotronConfig.ts",
698
+ "!apps/extension/index.js"
699
+ ],
700
+ "linter": {
701
+ "rules": {
702
+ "style": {
703
+ "noRestrictedGlobals": "off",
704
+ "noRestrictedImports": {
705
+ "level": "error",
706
+ "options": {
707
+ "paths": {
708
+ "__INCLUDE_GLOBAL_VALUES__": true,
709
+ "ethers": {
710
+ "message": "Please import from '@ethersproject/module' directly to support tree-shaking."
711
+ }
712
+ },
713
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
714
+ }
715
+ }
716
+ }
717
+ }
718
+ },
719
+ "javascript": {
720
+ "jsxRuntime": "reactClassic"
721
+ }
722
+ },
723
+ {
724
+ "includes": ["apps/extension/**/contentScript/**"],
725
+ "linter": {
726
+ "rules": {
727
+ "style": {
728
+ "noRestrictedGlobals": {
729
+ "level": "error",
730
+ "options": {
731
+ "deniedGlobals": {
732
+ "chrome": "Direct `chrome` access is restricted to prevent accidental usage in the wrong context. Use `getChrome()` or `getChromeWithThrow()` instead."
733
+ }
734
+ }
735
+ }
736
+ }
737
+ }
738
+ }
739
+ },
740
+ {
741
+ "includes": ["apps/extension/**/extensionMigrations.ts", "apps/extension/**/extensionMigrationsTests.ts"],
742
+ "linter": {
743
+ "rules": {
744
+ "style": {
745
+ "useEnumInitializers": "off",
746
+ "noNonNullAssertion": "off"
747
+ },
748
+ "suspicious": {
749
+ "noEmptyInterface": "off",
750
+ "noExplicitAny": "off"
751
+ }
752
+ }
753
+ }
754
+ },
755
+ // apps/mobile
756
+ {
757
+ "includes": [
758
+ "apps/mobile/**",
759
+ "!apps/mobile/**/*.test.ts",
760
+ "!apps/mobile/**/*.test.tsx",
761
+ "!apps/mobile/**/test/**",
762
+ "!apps/mobile/**/tests/**",
763
+ "!apps/mobile/ios/**",
764
+ "!apps/mobile/android/**",
765
+ "!apps/mobile/.storybook/storybook.requires.ts",
766
+ "!apps/mobile/scripts/**",
767
+ "!apps/mobile/ReactotronConfig.ts",
768
+ "!apps/mobile/index.js"
769
+ ],
770
+ "linter": {
771
+ "rules": {
772
+ "style": {
773
+ "noRestrictedImports": {
774
+ "level": "error",
775
+ "options": {
776
+ "paths": {
777
+ "__INCLUDE_GLOBAL_VALUES__": true,
778
+ "react-router": {
779
+ "message": "Do not import react-router in native code. Use react-navigation instead."
780
+ }
781
+ },
782
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
783
+ }
784
+ }
785
+ }
786
+ }
787
+ },
788
+ "javascript": {
789
+ "jsxRuntime": "reactClassic"
790
+ }
791
+ },
792
+ {
793
+ "includes": ["apps/mobile/**/utils/haptics/**"],
794
+ "linter": {
795
+ "rules": {
796
+ "style": {
797
+ "noRestrictedImports": {
798
+ "level": "error",
799
+ "options": {
800
+ "paths": {
801
+ "expo-haptics": "Allow expo-haptics in haptics utility files"
802
+ }
803
+ }
804
+ }
805
+ }
806
+ }
807
+ }
808
+ },
809
+ {
810
+ "includes": ["apps/mobile/.maestro/scripts/**"],
811
+ "linter": {
812
+ "rules": {
813
+ "style": {
814
+ "noRestrictedImports": "off",
815
+ "useBlockStatements": "off"
816
+ },
817
+ "suspicious": {
818
+ "noConsole": "off"
819
+ },
820
+ "complexity": {
821
+ "noUselessLoneBlockStatements": "off"
822
+ },
823
+ "correctness": {
824
+ "noSwitchDeclarations": "off",
825
+ "noUnusedVariables": "off"
826
+ }
827
+ }
828
+ }
829
+ },
830
+ {
831
+ "includes": ["apps/mobile/scripts/**", "apps/mobile/ReactotronConfig.ts", "apps/mobile/index.js"],
832
+ "linter": {
833
+ "enabled": false
834
+ }
835
+ },
836
+ {
837
+ "includes": ["apps/mobile/migrations.ts"],
838
+ "linter": {
839
+ "rules": {
840
+ "style": {
841
+ "useEnumInitializers": "off",
842
+ "noNonNullAssertion": "off"
843
+ },
844
+ "suspicious": {
845
+ "noEmptyInterface": "off",
846
+ "noExplicitAny": "off"
847
+ }
848
+ }
849
+ }
850
+ },
851
+ {
852
+ "includes": ["apps/mobile/**/*saga*.ts", "apps/mobile/**/*Saga.ts", "apps/mobile/**/handleDeepLink.ts"],
853
+ "linter": {
854
+ "rules": {
855
+ "style": {
856
+ "useEnumInitializers": "off"
857
+ }
858
+ }
859
+ }
860
+ },
861
+ // apps/web
862
+ {
863
+ "includes": [
864
+ "apps/web/.storybook/**",
865
+ "apps/web/functions/**",
866
+ "apps/web/vite/**",
867
+ "apps/web/**/*.config.*",
868
+ "apps/web/**/*.d.ts"
869
+ ],
870
+ "linter": {
871
+ "enabled": false
872
+ }
873
+ },
874
+ {
875
+ "includes": [
876
+ "apps/web/src/**",
877
+ "!apps/web/src/**/*.test.ts",
878
+ "!apps/web/src/**/*.test.tsx",
879
+ "!apps/web/src/**/test/**",
880
+ "!apps/web/src/**/tests/**"
881
+ ],
882
+ "linter": {
883
+ "rules": {
884
+ "suspicious": {
885
+ "noExplicitAny": "off",
886
+ "noBitwiseOperators": "off"
887
+ },
888
+ "style": {
889
+ "noNonNullAssertion": "off",
890
+ "noRestrictedImports": {
891
+ "level": "error",
892
+ "options": {
893
+ "paths": {
894
+ "__INCLUDE_GLOBAL_VALUES__": true,
895
+ "src/nft/components/icons": {
896
+ "message": "Please import icons from nft/components/iconExports instead of directly from icons.tsx"
897
+ },
898
+ "nft/components/icons": {
899
+ "message": "Please import icons from nft/components/iconExports instead of directly from icons.tsx"
900
+ },
901
+ "@playwright/test": {
902
+ "message": "Import test and expect from playwright/fixtures instead."
903
+ },
904
+ "styled-components": {
905
+ "message": "Styled components is deprecated, please use Flex or styled from \"ui/src\" instead."
906
+ },
907
+ "ethers": {
908
+ "message": "Please import from '@ethersproject/module' directly to support tree-shaking."
909
+ },
910
+ "ui/src/components/icons": {
911
+ "message": "Please import icons directly from their respective files, e.g. `ui/src/components/icons/SpecificIcon`. This is to avoid importing the entire icons folder when only some icons are needed, which increases bundle size"
912
+ },
913
+ "utilities/src/platform": {
914
+ "importNames": ["isIOS", "isAndroid"],
915
+ "message": "Importing isIOS and isAndroid from platform is not allowed. Use isWebIOS and isWebAndroid instead."
916
+ },
917
+ "src/test-utils": {
918
+ "message": "test-utils should not be imported in non-test files"
919
+ },
920
+ "wagmi": {
921
+ "importNames": [
922
+ "useChainId",
923
+ "useAccount",
924
+ "useConnect",
925
+ "useDisconnect",
926
+ "useBlockNumber",
927
+ "useWatchBlockNumber"
928
+ ],
929
+ "message": "Import wrapped utilities from internal hooks instead: useAccount from `hooks/useAccount`, useConnect from `hooks/useConnect`, useDisconnect from `hooks/useDisconnect`, useBlockNumber from `hooks/useBlockNumber`."
930
+ },
931
+ "uniswap/src/features/chains/chainInfo": {
932
+ "importNames": ["UNIVERSE_CHAIN_INFO"],
933
+ "message": "Use useChainInfo or helpers in packages/uniswap/src/features/chains/utils.ts when possible!"
934
+ }
935
+ },
936
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
937
+ }
938
+ }
939
+ }
940
+ }
941
+ },
942
+ "javascript": {
943
+ "jsxRuntime": "reactClassic"
944
+ }
945
+ },
946
+ {
947
+ "includes": ["apps/web/src/playwright/**"],
948
+ "linter": {
949
+ "rules": {
950
+ "suspicious": {
951
+ "noConsole": "off"
952
+ }
953
+ }
954
+ }
955
+ },
956
+ {
957
+ "includes": ["apps/web/src/**/*.e2e.test.ts", "!apps/web/src/**/*.anvil.e2e.test.ts"],
958
+ "linter": {
959
+ "rules": {
960
+ "style": {
961
+ "noRestrictedImports": {
962
+ "level": "error",
963
+ "options": {
964
+ "patterns": [
965
+ {
966
+ "group": ["**/playwright/anvil/**", "**/playwright/fixtures/anvil"],
967
+ "message": "Anvil imports must only be used in *.anvil.e2e.test.ts files."
968
+ }
969
+ ]
970
+ }
971
+ }
972
+ }
973
+ }
974
+ }
975
+ },
976
+ // packages/wallet
977
+ {
978
+ "includes": [
979
+ "packages/wallet/**",
980
+ "!packages/wallet/**/*.test.ts",
981
+ "!packages/wallet/**/*.test.tsx",
982
+ "!packages/wallet/**/test/**",
983
+ "!packages/wallet/**/tests/**"
984
+ ],
985
+ "linter": {
986
+ "rules": {
987
+ "style": {
988
+ "noRestrictedImports": {
989
+ "level": "error",
990
+ "options": {
991
+ "paths": {
992
+ "__INCLUDE_GLOBAL_VALUES__": true,
993
+ "wallet/src": {
994
+ "message": "Avoid importing directly from wallet/src from within the wallet package which causes circular imports."
995
+ },
996
+ "uniswap/src/features/dataApi/balances/balancesRest": {
997
+ "importNames": ["useRESTPortfolioTotalValue"],
998
+ "message": "Use the wrapper hooks `usePortfolioTotalValue`, `useAccountListData` or `usePortfolioBalances` instead of `useRESTPortfolioTotalValue` directly."
999
+ },
1000
+ "wallet/src/components/ErrorBoundary/restart": {
1001
+ "message": "Use `wallet/src/components/ErrorBoundary/restartApp` instead."
1002
+ }
1003
+ },
1004
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+ }
1010
+ },
1011
+ {
1012
+ "includes": [
1013
+ "packages/wallet/src/components/landing/elements/index.tsx",
1014
+ "packages/wallet/src/index.ts",
1015
+ "packages/wallet/src/state/index.ts",
1016
+ "packages/wallet/src/test/**"
1017
+ ],
1018
+ "linter": {
1019
+ "rules": {
1020
+ "style": {
1021
+ "noRestrictedImports": {
1022
+ "level": "error",
1023
+ "options": {
1024
+ "paths": {
1025
+ "__INCLUDE_GLOBAL_VALUES__": true,
1026
+ "wallet/src": "off"
1027
+ },
1028
+ "patterns": ["__INCLUDE_GLOBAL_VALUES__"]
1029
+ }
1030
+ }
1031
+ }
1032
+ }
1033
+ }
1034
+ },
1035
+ // apps/cli
1036
+ {
1037
+ "includes": ["apps/cli/**"],
1038
+ "linter": {
1039
+ "rules": {
1040
+ "suspicious": {
1041
+ "noConsole": "off"
1042
+ }
1043
+ }
1044
+ }
1045
+ }
1046
+ ]
1047
+ }