375 lines
12 KiB
JSON
375 lines
12 KiB
JSON
{
|
|
"root": true,
|
|
"env": {
|
|
"browser": true,
|
|
"webextensions": true
|
|
},
|
|
"overrides": [
|
|
{
|
|
"files": ["*.ts", "*.js"],
|
|
"plugins": ["@typescript-eslint", "rxjs", "rxjs-angular", "import"],
|
|
"parser": "@typescript-eslint/parser",
|
|
"parserOptions": {
|
|
"project": ["./tsconfig.eslint.json"],
|
|
"sourceType": "module",
|
|
"ecmaVersion": 2020
|
|
},
|
|
"extends": [
|
|
"eslint:recommended",
|
|
"plugin:@angular-eslint/recommended",
|
|
"plugin:@typescript-eslint/recommended",
|
|
"plugin:import/recommended",
|
|
"plugin:import/typescript",
|
|
"plugin:rxjs/recommended",
|
|
"prettier",
|
|
"plugin:storybook/recommended"
|
|
],
|
|
"settings": {
|
|
"import/parsers": {
|
|
"@typescript-eslint/parser": [".ts"]
|
|
},
|
|
"import/resolver": {
|
|
"typescript": {
|
|
"alwaysTryTypes": true
|
|
}
|
|
}
|
|
},
|
|
"rules": {
|
|
"@angular-eslint/component-class-suffix": 0,
|
|
"@angular-eslint/contextual-lifecycle": 0,
|
|
"@angular-eslint/directive-class-suffix": 0,
|
|
"@angular-eslint/no-empty-lifecycle-method": 0,
|
|
"@angular-eslint/no-host-metadata-property": 0,
|
|
"@angular-eslint/no-input-rename": 0,
|
|
"@angular-eslint/no-inputs-metadata-property": 0,
|
|
"@angular-eslint/no-output-native": 0,
|
|
"@angular-eslint/no-output-on-prefix": 0,
|
|
"@angular-eslint/no-output-rename": 0,
|
|
"@angular-eslint/no-outputs-metadata-property": 0,
|
|
"@angular-eslint/use-lifecycle-interface": "error",
|
|
"@angular-eslint/use-pipe-transform-interface": 0,
|
|
"@typescript-eslint/explicit-member-accessibility": [
|
|
"error",
|
|
{ "accessibility": "no-public" }
|
|
],
|
|
"@typescript-eslint/no-explicit-any": "off", // TODO: This should be re-enabled
|
|
"@typescript-eslint/no-floating-promises": "error",
|
|
"@typescript-eslint/no-misused-promises": ["error", { "checksVoidReturn": false }],
|
|
"@typescript-eslint/no-this-alias": ["error", { "allowedNames": ["self"] }],
|
|
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
|
"no-console": "error",
|
|
"import/no-unresolved": "off", // TODO: Look into turning off once each package is an actual package.
|
|
"import/order": [
|
|
"error",
|
|
{
|
|
"alphabetize": {
|
|
"order": "asc"
|
|
},
|
|
"newlines-between": "always",
|
|
"pathGroups": [
|
|
{
|
|
"pattern": "@bitwarden/**",
|
|
"group": "external",
|
|
"position": "after"
|
|
},
|
|
{
|
|
"pattern": "src/**/*",
|
|
"group": "parent",
|
|
"position": "before"
|
|
}
|
|
],
|
|
"pathGroupsExcludedImportTypes": ["builtin"]
|
|
}
|
|
],
|
|
"rxjs-angular/prefer-takeuntil": ["error", { "alias": ["takeUntilDestroyed"] }],
|
|
"rxjs/no-exposed-subjects": ["error", { "allowProtected": true }],
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
"message": "Calling `svgIcon` directly is not allowed",
|
|
"selector": "CallExpression[callee.name='svgIcon']"
|
|
},
|
|
{
|
|
"message": "Accessing FormGroup using `get` is not allowed, use `.value` instead",
|
|
"selector": "ChainExpression[expression.object.callee.property.name='get'][expression.property.name='value']"
|
|
}
|
|
],
|
|
"curly": ["error", "all"],
|
|
"import/namespace": ["off"], // This doesn't resolve namespace imports correctly, but TS will throw for this anyway
|
|
"import/no-restricted-paths": [
|
|
"error",
|
|
{
|
|
"zones": [
|
|
{
|
|
"target": ["libs/**/*"],
|
|
"from": ["apps/**/*"],
|
|
"message": "Libs should not import app-specific code."
|
|
},
|
|
{
|
|
// avoid specific frameworks or large dependencies in common
|
|
"target": "./libs/common/**/*",
|
|
"from": [
|
|
// Angular
|
|
"./libs/angular/**/*",
|
|
"./node_modules/@angular*/**/*",
|
|
|
|
// Node
|
|
"./libs/node/**/*",
|
|
|
|
//Generator
|
|
"./libs/tools/generator/components/**/*",
|
|
"./libs/tools/generator/core/**/*",
|
|
"./libs/tools/generator/extensions/**/*",
|
|
|
|
// Import/export
|
|
"./libs/importer/**/*",
|
|
"./libs/tools/export/vault-export/vault-export-core/**/*"
|
|
]
|
|
},
|
|
{
|
|
// avoid import of unexported state objects
|
|
"target": [
|
|
"!(libs)/**/*",
|
|
"libs/!(common)/**/*",
|
|
"libs/common/!(src)/**/*",
|
|
"libs/common/src/!(platform)/**/*",
|
|
"libs/common/src/platform/!(state)/**/*"
|
|
],
|
|
"from": ["./libs/common/src/platform/state/**/*"],
|
|
// allow module index import
|
|
"except": ["**/state/index.ts"]
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"no-restricted-imports": ["error", { "patterns": ["src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["*.html"],
|
|
"parser": "@angular-eslint/template-parser",
|
|
"plugins": ["@angular-eslint/template", "tailwindcss"],
|
|
"rules": {
|
|
"@angular-eslint/template/button-has-type": "error",
|
|
"tailwindcss/no-custom-classname": [
|
|
"error",
|
|
{
|
|
// uses negative lookahead to whitelist any class that doesn't start with "tw-"
|
|
// in other words: classnames that start with tw- must be valid TailwindCSS classes
|
|
"whitelist": ["(?!(tw)\\-).*"]
|
|
}
|
|
],
|
|
"tailwindcss/enforces-negative-arbitrary-values": "error",
|
|
"tailwindcss/enforces-shorthand": "error",
|
|
"tailwindcss/no-contradicting-classname": "error"
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/admin-console/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/admin-console/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/angular/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/angular/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/auth/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/auth/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/billing/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/billing/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/common/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/common/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/components/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/components/*", "src/**/*", "@bitwarden/angular/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/generator/components/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/generator-components/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/generator/core/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/generator-core/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/generator/extensions/history/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/generator-history/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/generator/extensions/legacy/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/generator-legacy/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/generator/extensions/navigation/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/generator-navigation/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/export/vault-export/vault-export-core/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/vault-export-core/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/export/vault-export/vault-export-ui/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{ "patterns": ["@bitwarden/vault-export-ui/*", "src/**/*"] }
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/importer/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/importer/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/node/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/node/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/platform/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/platform/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/send/send-ui/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/send-ui/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/tools/card/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/tools-card/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["libs/vault/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/vault/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["apps/browser/src/**/*.ts", "libs/**/*.ts"],
|
|
"excludedFiles": [
|
|
"apps/browser/src/autofill/{content,notification}/**/*.ts",
|
|
"apps/browser/src/**/background/**/*.ts", // It's okay to have long lived listeners in the background
|
|
"apps/browser/src/platform/background.ts"
|
|
],
|
|
"rules": {
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
"message": "Using addListener in the browser popup produces a memory leak in Safari, use `BrowserApi.addListener` instead",
|
|
// This selector covers events like chrome.storage.onChange & chrome.runtime.onMessage
|
|
"selector": "CallExpression > [object.object.object.name='chrome'][property.name='addListener']"
|
|
},
|
|
{
|
|
"message": "Using addListener in the browser popup produces a memory leak in Safari, use `BrowserApi.addListener` instead",
|
|
// This selector covers events like chrome.storage.local.onChange
|
|
"selector": "CallExpression > [object.object.object.object.name='chrome'][property.name='addListener']"
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["**/*.ts"],
|
|
"excludedFiles": ["**/platform/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"patterns": [
|
|
"**/platform/**/internal", // General internal pattern
|
|
// All features that have been converted to barrel files
|
|
"**/platform/messaging/**"
|
|
]
|
|
}
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"files": ["bitwarden_license/bit-common/src/**/*.ts"],
|
|
"rules": {
|
|
"no-restricted-imports": ["error", { "patterns": ["@bitwarden/bit-common/*", "src/**/*"] }]
|
|
}
|
|
},
|
|
{
|
|
"files": ["apps/**/*.ts"],
|
|
"rules": {
|
|
// Catches static imports
|
|
"no-restricted-imports": [
|
|
"error",
|
|
{
|
|
"patterns": ["biwarden_license/**", "@bitwarden/bit-common/*", "@bitwarden/bit-web/*"]
|
|
}
|
|
],
|
|
// Catches dynamic imports, e.g. in routing modules where modules are lazy-loaded
|
|
"no-restricted-syntax": [
|
|
"error",
|
|
{
|
|
"message": "Don't import Bitwarden licensed code into OSS code.",
|
|
"selector": "ImportExpression > Literal.source[value=/.*(bitwarden_license|bit-common|bit-web).*/]"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|