Files
twenty/packages/twenty-server/eslint.config.mjs
T
Félix MalfaitandGitHub 30a2164980 First Application POC (#14382)
Quick proof of concept for twenty-apps + twenty-cli, with local
development / hot reload

Let's discuss it!



https://github.com/user-attachments/assets/c6789936-cd5f-4110-a265-863a6ac1af2d
2025-09-10 15:12:38 +02:00

296 lines
8.1 KiB
JavaScript

import js from '@eslint/js';
import nxPlugin from '@nx/eslint-plugin';
import stylisticPlugin from '@stylistic/eslint-plugin';
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import typescriptParser from '@typescript-eslint/parser';
import importPlugin from 'eslint-plugin-import';
import linguiPlugin from 'eslint-plugin-lingui';
import preferArrowPlugin from 'eslint-plugin-prefer-arrow';
import prettierPlugin from 'eslint-plugin-prettier';
import unicornPlugin from 'eslint-plugin-unicorn';
import unusedImportsPlugin from 'eslint-plugin-unused-imports';
import jsoncParser from 'jsonc-eslint-parser';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export default [
// Base JavaScript configuration
js.configs.recommended,
// Lingui recommended rules
linguiPlugin.configs['flat/recommended'],
// Global ignores
{
ignores: [
'packages/twenty-server/node_modules/**',
'packages/twenty-server/dist/**',
'**/node_modules/**',
'**/.local-storage/**',
'src/engine/workspace-manager/dev-seeder/data/constants/**',
'src/engine/workspace-manager/dev-seeder/data/seeds/**',
'src/utils/email-providers.ts',
'src/engine/core-modules/i18n/locales/generated/**',
'src/engine/core-modules/serverless/drivers/constants/base-typescript-project/src/index.ts',
'packages/twenty-server/src/engine/core-modules/i18n/locales/**'
],
},
// Base configuration for all files
{
files: ['**/*.{js,jsx,ts,tsx}'],
plugins: {
'prettier': prettierPlugin,
'lingui': linguiPlugin,
'@nx': nxPlugin,
'prefer-arrow': preferArrowPlugin,
'import': importPlugin,
'unused-imports': unusedImportsPlugin,
'unicorn': unicornPlugin,
'@stylistic': stylisticPlugin,
},
rules: {
'prettier/prettier': 'error',
// General rules
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
'no-console': ['warn', { allow: ['group', 'groupCollapsed', 'groupEnd'] }],
'no-control-regex': 0,
'no-debugger': 'error',
'no-duplicate-imports': 'error',
'no-undef': 'off',
'no-unused-vars': 'off',
// Nx rules
'@nx/enforce-module-boundaries': [
'error',
{
enforceBuildableLibDependency: true,
allow: [],
depConstraints: [
{
sourceTag: 'scope:shared',
onlyDependOnLibsWithTags: ['scope:shared'],
},
{
sourceTag: 'scope:backend',
onlyDependOnLibsWithTags: ['scope:shared', 'scope:backend'],
},
{
sourceTag: 'scope:frontend',
onlyDependOnLibsWithTags: ['scope:shared', 'scope:frontend'],
},
{
sourceTag: 'scope:zapier',
onlyDependOnLibsWithTags: ['scope:shared'],
},
],
},
],
// Import rules
'import/no-relative-packages': 'error',
'import/no-useless-path-segments': 'error',
'import/no-duplicates': ['error', { considerQueryString: true }],
// Prefer arrow functions
'prefer-arrow/prefer-arrow-functions': [
'error',
{
disallowPrototype: true,
singleReturnOnly: false,
classPropertiesAllowed: false,
},
],
// Unused imports
'unused-imports/no-unused-imports': 'warn',
'unused-imports/no-unused-vars': [
'warn',
{
vars: 'all',
varsIgnorePattern: '^_',
args: 'after-used',
argsIgnorePattern: '^_',
},
],
},
},
// TypeScript specific configuration
{
files: ['**/*.ts'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
project: [path.resolve(__dirname, 'tsconfig.json')],
},
},
plugins: {
'@typescript-eslint': typescriptEslint,
},
rules: {
// TypeScript rules
'@typescript-eslint/ban-ts-comment': 'error',
'@typescript-eslint/consistent-type-imports': [
'error',
{
prefer: 'type-imports',
fixStyle: 'inline-type-imports'
},
],
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/no-empty-interface': [
'error',
{
allowSingleExtends: true,
},
],
'@typescript-eslint/no-explicit-any': 'error', // Stricter for server
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/no-unused-vars': 'off',
// Import restrictions
'no-restricted-imports': [
'error',
{
patterns: [
{
group: ['**../'],
message: 'Relative imports are not allowed.',
},
{
group: ['lodash'],
message: "Please use the standalone lodash package (for instance: `import groupBy from 'lodash.groupby'` instead of `import { groupBy } from 'lodash'`)",
},
],
},
],
// Stylistic rules
'@stylistic/linebreak-style': ['error', 'unix'],
'@stylistic/lines-between-class-members': [
'error',
{
enforce: [{ blankLine: 'always', prev: 'method', next: 'method' }],
},
],
'@stylistic/padding-line-between-statements': [
'error',
{ blankLine: 'always', prev: '*', next: 'return' },
{ blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' },
{
blankLine: 'any',
prev: ['const', 'let', 'var'],
next: ['const', 'let', 'var'],
},
{ blankLine: 'always', prev: '*', next: ['interface', 'type'] },
],
// Import order
'import/order': [
'error',
{
'newlines-between': 'always',
groups: [
'builtin',
'external',
'internal',
'type',
'parent',
'sibling',
'object',
'index',
],
pathGroups: [
{
pattern: '@nestjs/**',
group: 'builtin',
position: 'before',
},
{
pattern: '**/interfaces/**',
group: 'type',
position: 'before',
},
{
pattern: 'src/**',
group: 'parent',
position: 'before',
},
{
pattern: './*',
group: 'sibling',
position: 'before',
},
],
distinctGroup: true,
warnOnUnassignedImports: true,
pathGroupsExcludedImportTypes: ['@nestjs/**'],
},
],
// Disable conflicting rules
'simple-import-sort/imports': 'off',
'unicorn/filename-case': 'off',
'prefer-arrow/prefer-arrow-functions': 'off',
'@nx/workspace-max-consts-per-file': 'off',
// Custom workspace rules
'@nx/workspace-inject-workspace-repository': 'warn',
'@nx/workspace-rest-api-methods-should-be-guarded': 'error',
'@nx/workspace-graphql-resolvers-should-be-guarded': 'error',
},
},
// Test files
{
files: [
'**/*.spec.ts',
'**/*.integration-spec.ts',
'**/__tests__/**',
'**/test/integration/**',
'**/test/utils/**',
],
languageOptions: {
globals: {
jest: true,
describe: true,
it: true,
expect: true,
beforeEach: true,
afterEach: true,
beforeAll: true,
afterAll: true,
},
},
rules: {
'@typescript-eslint/no-explicit-any': 'off',
},
},
// Scripts files
{
files: ['scripts/**/*.ts'],
languageOptions: {
parser: typescriptParser,
parserOptions: {
project: [path.resolve(__dirname, 'tsconfig.scripts.json')],
},
},
},
// JSON files
{
files: ['**/*.json'],
languageOptions: {
parser: jsoncParser,
},
},
];