From 44aee860d97c3085dfadf988bd8218295f86701f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Malfait?= Date: Sat, 18 Oct 2025 12:24:35 +0200 Subject: [PATCH] Consolidate Prettier config and improve consistency (#15191) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 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 --- .gitattributes | 28 +++++++++++++++++++ .prettierrc | 4 +-- .vscode/settings.json | 4 ++- .../isSelectedItemIdComponentFamilyState.ts | 22 +++++++-------- .../states/selectableItemIdsComponentState.ts | 20 ++++++------- .../states/selectedItemIdComponentState.ts | 20 ++++++------- packages/twenty-server/.prettierrc | 5 ---- packages/twenty-zapier/.prettierrc | 4 --- .../rules/component-props-naming.ts | 2 +- tools/eslint-rules/rules/effect-components.ts | 4 +-- .../explicit-boolean-predicates-in-if.ts | 2 +- ...raphql-resolvers-should-be-guarded.spec.ts | 2 +- .../graphql-resolvers-should-be-guarded.ts | 2 +- .../rules/matching-state-variable.ts | 2 +- .../eslint-rules/rules/max-consts-per-file.ts | 2 +- .../rules/no-navigate-prefer-link.ts | 2 +- ...rest-api-methods-should-be-guarded.spec.ts | 2 +- .../rest-api-methods-should-be-guarded.ts | 2 +- .../sort-css-properties-alphabetically.ts | 6 ++-- tools/eslint-rules/utils/createRule.ts | 2 +- tools/eslint-rules/utils/typedTokenHelpers.ts | 2 +- 21 files changed, 80 insertions(+), 59 deletions(-) create mode 100644 .gitattributes delete mode 100644 packages/twenty-server/.prettierrc delete mode 100644 packages/twenty-zapier/.prettierrc diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000000..8b442f40a65 --- /dev/null +++ b/.gitattributes @@ -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 + diff --git a/.prettierrc b/.prettierrc index 9d36f26d83a..6de9cff5b4c 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { "singleQuote": true, "trailingComma": "all", - "endOfLine": "auto" -} \ No newline at end of file + "endOfLine": "lf" +} diff --git a/.vscode/settings.json b/.vscode/settings.json index 7609a1b03eb..812d5af56e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,8 @@ { "editor.formatOnSave": false, - "files.eol": "auto", + "files.eol": "\n", + "files.insertFinalNewline": true, + "files.trimTrailingWhitespace": true, "[typescript]": { "editor.formatOnSave": false, "editor.codeActionsOnSave": { diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts index 70bf3ae36f7..ff1b27efb75 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState.ts @@ -1,11 +1,11 @@ -import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; -import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; - -export const isSelectedItemIdComponentFamilyState = createComponentFamilyState< - boolean, - string ->({ - key: 'isSelectedItemIdComponentFamilyState', - defaultValue: false, - componentInstanceContext: SelectableListComponentInstanceContext, -}); +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState'; + +export const isSelectedItemIdComponentFamilyState = createComponentFamilyState< + boolean, + string +>({ + key: 'isSelectedItemIdComponentFamilyState', + defaultValue: false, + componentInstanceContext: SelectableListComponentInstanceContext, +}); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts index 64f7544efb6..c89f1d70fd2 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectableItemIdsComponentState.ts @@ -1,10 +1,10 @@ -import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const selectableItemIdsComponentState = createComponentState( - { - key: 'selectableItemIdsComponentState', - defaultValue: [[]], - componentInstanceContext: SelectableListComponentInstanceContext, - }, -); +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const selectableItemIdsComponentState = createComponentState( + { + key: 'selectableItemIdsComponentState', + defaultValue: [[]], + componentInstanceContext: SelectableListComponentInstanceContext, + }, +); diff --git a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts index 5b413f3cf1f..9a832bb9b38 100644 --- a/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts +++ b/packages/twenty-front/src/modules/ui/layout/selectable-list/states/selectedItemIdComponentState.ts @@ -1,10 +1,10 @@ -import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; -import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; - -export const selectedItemIdComponentState = createComponentState( - { - key: 'selectedItemIdComponentState', - defaultValue: null, - componentInstanceContext: SelectableListComponentInstanceContext, - }, -); +import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext'; +import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState'; + +export const selectedItemIdComponentState = createComponentState( + { + key: 'selectedItemIdComponentState', + defaultValue: null, + componentInstanceContext: SelectableListComponentInstanceContext, + }, +); diff --git a/packages/twenty-server/.prettierrc b/packages/twenty-server/.prettierrc deleted file mode 100644 index 3519b0676fc..00000000000 --- a/packages/twenty-server/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all", - "brakeBeforeElse": false -} diff --git a/packages/twenty-zapier/.prettierrc b/packages/twenty-zapier/.prettierrc deleted file mode 100644 index a20502b7f06..00000000000 --- a/packages/twenty-zapier/.prettierrc +++ /dev/null @@ -1,4 +0,0 @@ -{ - "singleQuote": true, - "trailingComma": "all" -} diff --git a/tools/eslint-rules/rules/component-props-naming.ts b/tools/eslint-rules/rules/component-props-naming.ts index a9d90340d09..087373f0ce6 100644 --- a/tools/eslint-rules/rules/component-props-naming.ts +++ b/tools/eslint-rules/rules/component-props-naming.ts @@ -3,7 +3,7 @@ import { isIdentifier, isVariableDeclarator, } 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" export const RULE_NAME = 'component-props-naming'; diff --git a/tools/eslint-rules/rules/effect-components.ts b/tools/eslint-rules/rules/effect-components.ts index a7b2c2371a6..218703db78f 100644 --- a/tools/eslint-rules/rules/effect-components.ts +++ b/tools/eslint-rules/rules/effect-components.ts @@ -1,9 +1,9 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; +import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils'; import { isIdentifier, isVariableDeclarator, } 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" export const RULE_NAME = 'effect-components'; diff --git a/tools/eslint-rules/rules/explicit-boolean-predicates-in-if.ts b/tools/eslint-rules/rules/explicit-boolean-predicates-in-if.ts index 54114a41349..35b7ca9a949 100644 --- a/tools/eslint-rules/rules/explicit-boolean-predicates-in-if.ts +++ b/tools/eslint-rules/rules/explicit-boolean-predicates-in-if.ts @@ -1,4 +1,4 @@ -import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; +import { ESLintUtils, type TSESTree } from '@typescript-eslint/utils'; import ts from 'typescript'; export const RULE_NAME = 'explicit-boolean-predicates-in-if'; diff --git a/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.spec.ts b/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.spec.ts index a878df3aa9f..8dee521f7ad 100644 --- a/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.spec.ts +++ b/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.spec.ts @@ -156,4 +156,4 @@ ruleTester.run(RULE_NAME, rule, { ], }, ], -}); \ No newline at end of file +}); diff --git a/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.ts b/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.ts index 8da8998d4d6..79ef2db1109 100644 --- a/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.ts +++ b/tools/eslint-rules/rules/graphql-resolvers-should-be-guarded.ts @@ -67,4 +67,4 @@ export const rule = createRule<[], 'graphqlResolversShouldBeGuarded'>({ }, }; }, -}); \ No newline at end of file +}); diff --git a/tools/eslint-rules/rules/matching-state-variable.ts b/tools/eslint-rules/rules/matching-state-variable.ts index 8afa5ea4ff3..34d3cf19c26 100644 --- a/tools/eslint-rules/rules/matching-state-variable.ts +++ b/tools/eslint-rules/rules/matching-state-variable.ts @@ -1,7 +1,7 @@ import { AST_NODE_TYPES, ESLintUtils, - TSESTree, + type TSESTree, } from '@typescript-eslint/utils'; import { isIdentifier } from '@typescript-eslint/utils/ast-utils'; diff --git a/tools/eslint-rules/rules/max-consts-per-file.ts b/tools/eslint-rules/rules/max-consts-per-file.ts index fec6e8375ed..e4632892ed1 100644 --- a/tools/eslint-rules/rules/max-consts-per-file.ts +++ b/tools/eslint-rules/rules/max-consts-per-file.ts @@ -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" export const RULE_NAME = 'max-consts-per-file'; diff --git a/tools/eslint-rules/rules/no-navigate-prefer-link.ts b/tools/eslint-rules/rules/no-navigate-prefer-link.ts index 80eaf36d050..e4210e06c79 100644 --- a/tools/eslint-rules/rules/no-navigate-prefer-link.ts +++ b/tools/eslint-rules/rules/no-navigate-prefer-link.ts @@ -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" export const RULE_NAME = 'no-navigate-prefer-link'; diff --git a/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.spec.ts b/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.spec.ts index 0d8c8f8c796..38eb7313b29 100644 --- a/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.spec.ts +++ b/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.spec.ts @@ -135,4 +135,4 @@ ruleTester.run(RULE_NAME, rule, { ], }, ], -}); \ No newline at end of file +}); diff --git a/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.ts b/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.ts index e020f382dc9..29a2e11b9e9 100644 --- a/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.ts +++ b/tools/eslint-rules/rules/rest-api-methods-should-be-guarded.ts @@ -67,4 +67,4 @@ export const rule = createRule<[], 'restApiMethodsShouldBeGuarded'>({ }, }; }, -}); \ No newline at end of file +}); diff --git a/tools/eslint-rules/rules/sort-css-properties-alphabetically.ts b/tools/eslint-rules/rules/sort-css-properties-alphabetically.ts index 000f3f9b625..ec264a4637a 100644 --- a/tools/eslint-rules/rules/sort-css-properties-alphabetically.ts +++ b/tools/eslint-rules/rules/sort-css-properties-alphabetically.ts @@ -1,9 +1,9 @@ import { ESLintUtils, TSESTree } from '@typescript-eslint/utils'; import { isIdentifier } from '@typescript-eslint/utils/ast-utils'; import { - RuleFix, - RuleFixer, - SourceCode, + type RuleFix, + type RuleFixer, + type SourceCode, } from '@typescript-eslint/utils/ts-eslint'; import postcss from 'postcss'; diff --git a/tools/eslint-rules/utils/createRule.ts b/tools/eslint-rules/utils/createRule.ts index 901bc483dbb..6fe863434dd 100644 --- a/tools/eslint-rules/utils/createRule.ts +++ b/tools/eslint-rules/utils/createRule.ts @@ -1,3 +1,3 @@ import { ESLintUtils } from '@typescript-eslint/utils'; -export const createRule = ESLintUtils.RuleCreator(() => __filename); \ No newline at end of file +export const createRule = ESLintUtils.RuleCreator(() => __filename); diff --git a/tools/eslint-rules/utils/typedTokenHelpers.ts b/tools/eslint-rules/utils/typedTokenHelpers.ts index 102ae161e0a..bbe697ac565 100644 --- a/tools/eslint-rules/utils/typedTokenHelpers.ts +++ b/tools/eslint-rules/utils/typedTokenHelpers.ts @@ -53,4 +53,4 @@ export const typedTokenHelpers = { return false; }); }, -}; \ No newline at end of file +};