Consolidate Prettier config and improve consistency (#15191)

## Summary

Clean up and consolidate formatting configuration across the monorepo.

## Changes

### 1. Remove Redundant Configs
-  Delete `packages/twenty-server/.prettierrc` (had invalid
`brakeBeforeElse` typo)
-  Delete `packages/twenty-zapier/.prettierrc`
-  Use root `.prettierrc` only (Prettier searches up directory tree
automatically)

### 2. Improve Root Prettier Config
- Change `endOfLine: 'auto'` → `'lf'` for consistent Unix line endings
across all OSes

### 3. Enhance VSCode Settings
- `files.eol: 'auto'` → `'\\n'` (consistent with Prettier)
- Add `files.insertFinalNewline: true` (explicit editor behavior)
- Add `files.trimTrailingWhitespace: true` (cleaner files)

### 4. Add `.gitattributes`
- Enforce LF line endings at Git level
- Prevents `core.autocrlf` from converting based on contributor's OS
- Mark patch files as binary (they have mixed line endings by design)
- Explicitly define binary file types

### 5. Fix Line Endings
- Convert 3 selectable-list state files from CRLF → LF
- These were the only source files with Windows line endings

## Why These Changes Matter

**Before:**
- 3 different Prettier configs (inconsistent, one had typo)
- Mixed CRLF/LF depending on contributor's OS
- No Git-level enforcement

**After:**
- Single source of truth for formatting
- All files use LF (Unix standard)
- Git enforces line endings regardless of OS
- Prettier warning about invalid option removed

## Result

-  Single `.prettierrc` config
-  Consistent LF line endings enforced by Git
-  Better VSCode defaults
-  No more CRLF files sneaking in from Windows contributors
This commit is contained in:
Félix Malfait 2025-10-18 12:24:35 +02:00 committed by GitHub
parent d76abefdee
commit 44aee860d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 80 additions and 59 deletions

28
.gitattributes vendored Normal file
View file

@ -0,0 +1,28 @@
* text=auto eol=lf
*.ts text eol=lf
*.tsx text eol=lf
*.js text eol=lf
*.jsx text eol=lf
*.json text eol=lf
*.md text eol=lf
*.yml text eol=lf
*.yaml text eol=lf
*.sh text eol=lf
*.mjs text eol=lf
*.cjs text eol=lf
# Patch files may have mixed line endings by design
*.patch -text
*.png binary
*.jpg binary
*.jpeg binary
*.gif binary
*.ico binary
*.svg binary
*.woff binary
*.woff2 binary
*.ttf binary
*.eot binary

View file

@ -1,5 +1,5 @@
{ {
"singleQuote": true, "singleQuote": true,
"trailingComma": "all", "trailingComma": "all",
"endOfLine": "auto" "endOfLine": "lf"
} }

View file

@ -1,6 +1,8 @@
{ {
"editor.formatOnSave": false, "editor.formatOnSave": false,
"files.eol": "auto", "files.eol": "\n",
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"[typescript]": { "[typescript]": {
"editor.formatOnSave": false, "editor.formatOnSave": false,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {

View file

@ -1,11 +1,11 @@
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';
export const isSelectedItemIdComponentFamilyState = createComponentFamilyState< export const isSelectedItemIdComponentFamilyState = createComponentFamilyState<
boolean, boolean,
string string
>({ >({
key: 'isSelectedItemIdComponentFamilyState', key: 'isSelectedItemIdComponentFamilyState',
defaultValue: false, defaultValue: false,
componentInstanceContext: SelectableListComponentInstanceContext, componentInstanceContext: SelectableListComponentInstanceContext,
}); });

View file

@ -1,10 +1,10 @@
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
export const selectableItemIdsComponentState = createComponentState<string[][]>( export const selectableItemIdsComponentState = createComponentState<string[][]>(
{ {
key: 'selectableItemIdsComponentState', key: 'selectableItemIdsComponentState',
defaultValue: [[]], defaultValue: [[]],
componentInstanceContext: SelectableListComponentInstanceContext, componentInstanceContext: SelectableListComponentInstanceContext,
}, },
); );

View file

@ -1,10 +1,10 @@
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
export const selectedItemIdComponentState = createComponentState<string | null>( export const selectedItemIdComponentState = createComponentState<string | null>(
{ {
key: 'selectedItemIdComponentState', key: 'selectedItemIdComponentState',
defaultValue: null, defaultValue: null,
componentInstanceContext: SelectableListComponentInstanceContext, componentInstanceContext: SelectableListComponentInstanceContext,
}, },
); );

View file

@ -1,5 +0,0 @@
{
"singleQuote": true,
"trailingComma": "all",
"brakeBeforeElse": false
}

View file

@ -1,4 +0,0 @@
{
"singleQuote": true,
"trailingComma": "all"
}

View file

@ -3,7 +3,7 @@ import {
isIdentifier, isIdentifier,
isVariableDeclarator, isVariableDeclarator,
} from '@typescript-eslint/utils/ast-utils'; } from '@typescript-eslint/utils/ast-utils';
import { RuleContext } from '@typescript-eslint/utils/ts-eslint'; import { type RuleContext } from '@typescript-eslint/utils/ts-eslint';
// NOTE: The rule will be available in ESLint configs as "@nx/workspace-component-props-naming" // NOTE: The rule will be available in ESLint configs as "@nx/workspace-component-props-naming"
export const RULE_NAME = 'component-props-naming'; export const RULE_NAME = 'component-props-naming';

View file

@ -1,9 +1,9 @@
import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils';
import { import {
isIdentifier, isIdentifier,
isVariableDeclarator, isVariableDeclarator,
} from '@typescript-eslint/utils/ast-utils'; } from '@typescript-eslint/utils/ast-utils';
import { RuleContext } from '@typescript-eslint/utils/ts-eslint'; import { type RuleContext } from '@typescript-eslint/utils/ts-eslint';
// NOTE: The rule will be available in ESLint configs as "@nx/workspace-effect-components" // NOTE: The rule will be available in ESLint configs as "@nx/workspace-effect-components"
export const RULE_NAME = 'effect-components'; export const RULE_NAME = 'effect-components';

View file

@ -1,4 +1,4 @@
import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils';
import ts from 'typescript'; import ts from 'typescript';
export const RULE_NAME = 'explicit-boolean-predicates-in-if'; export const RULE_NAME = 'explicit-boolean-predicates-in-if';

View file

@ -156,4 +156,4 @@ ruleTester.run(RULE_NAME, rule, {
], ],
}, },
], ],
}); });

View file

@ -67,4 +67,4 @@ export const rule = createRule<[], 'graphqlResolversShouldBeGuarded'>({
}, },
}; };
}, },
}); });

View file

@ -1,7 +1,7 @@
import { import {
AST_NODE_TYPES, AST_NODE_TYPES,
ESLintUtils, ESLintUtils,
TSESTree, type TSESTree,
} from '@typescript-eslint/utils'; } from '@typescript-eslint/utils';
import { isIdentifier } from '@typescript-eslint/utils/ast-utils'; import { isIdentifier } from '@typescript-eslint/utils/ast-utils';

View file

@ -1,4 +1,4 @@
import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as "@nx/workspace-max-consts-per-file" // NOTE: The rule will be available in ESLint configs as "@nx/workspace-max-consts-per-file"
export const RULE_NAME = 'max-consts-per-file'; export const RULE_NAME = 'max-consts-per-file';

View file

@ -1,4 +1,4 @@
import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils';
// NOTE: The rule will be available in ESLint configs as "@nx/workspace-no-navigate-prefer-link" // NOTE: The rule will be available in ESLint configs as "@nx/workspace-no-navigate-prefer-link"
export const RULE_NAME = 'no-navigate-prefer-link'; export const RULE_NAME = 'no-navigate-prefer-link';

View file

@ -135,4 +135,4 @@ ruleTester.run(RULE_NAME, rule, {
], ],
}, },
], ],
}); });

View file

@ -67,4 +67,4 @@ export const rule = createRule<[], 'restApiMethodsShouldBeGuarded'>({
}, },
}; };
}, },
}); });

View file

@ -1,9 +1,9 @@
import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; import { ESLintUtils, TSESTree } from '@typescript-eslint/utils';
import { isIdentifier } from '@typescript-eslint/utils/ast-utils'; import { isIdentifier } from '@typescript-eslint/utils/ast-utils';
import { import {
RuleFix, type RuleFix,
RuleFixer, type RuleFixer,
SourceCode, type SourceCode,
} from '@typescript-eslint/utils/ts-eslint'; } from '@typescript-eslint/utils/ts-eslint';
import postcss from 'postcss'; import postcss from 'postcss';

View file

@ -1,3 +1,3 @@
import { ESLintUtils } from '@typescript-eslint/utils'; import { ESLintUtils } from '@typescript-eslint/utils';
export const createRule = ESLintUtils.RuleCreator(() => __filename); export const createRule = ESLintUtils.RuleCreator(() => __filename);

View file

@ -53,4 +53,4 @@ export const typedTokenHelpers = {
return false; return false;
}); });
}, },
}; };