diff --git a/.cursor/rules/README.mdc b/.cursor/rules/README.mdc index 6b2dabd231..ea05636131 100644 --- a/.cursor/rules/README.mdc +++ b/.cursor/rules/README.mdc @@ -56,8 +56,8 @@ npx nx storybook:build twenty-front # Build Storybook npx nx storybook:serve-and-test:static # Run Storybook tests # Development -npx nx lint:changed twenty-front # Lint changed files only (fastest) -npx nx lint:changed twenty-front --configuration=fix # Auto-fix changed files +npx nx lint:diff-with-main twenty-front # Lint files changed vs main (fastest) +npx nx lint:diff-with-main twenty-front --configuration=fix # Auto-fix changed files npx nx lint twenty-front # Lint all files (slower) npx nx typecheck twenty-front # Type checking npx nx run twenty-front:graphql:generate # Generate GraphQL types @@ -72,8 +72,8 @@ npx nx run twenty-server:database:migrate:prod # Run migrations # Development npx nx run twenty-server:start # Start the server -npx nx lint:changed twenty-server # Lint changed files only (fastest) -npx nx lint:changed twenty-server --configuration=fix # Auto-fix changed files +npx nx lint:diff-with-main twenty-server # Lint files changed vs main (fastest) +npx nx lint:diff-with-main twenty-server --configuration=fix # Auto-fix changed files npx nx run twenty-server:lint # Lint all files (slower) npx nx run twenty-server:typecheck # Type checking npx nx run twenty-server:test # Run unit tests diff --git a/.cursor/rules/nx-rules.mdc b/.cursor/rules/nx-rules.mdc index b1ecab9182..3c5851b896 100644 --- a/.cursor/rules/nx-rules.mdc +++ b/.cursor/rules/nx-rules.mdc @@ -12,11 +12,10 @@ alwaysApply: true npx nx run twenty-front:build npx nx run twenty-server:test -# Lint changed files only (recommended - much faster!) -npx nx lint:changed twenty-front # Lint only files changed vs main -npx nx lint:changed twenty-server -npx nx lint:changed twenty-front --configuration=fix # Auto-fix changed files -npx nx lint:changed twenty-front --configuration=staged # Lint staged files +# Lint diff with main (recommended - much faster!) +npx nx lint:diff-with-main twenty-front # Lint only files changed vs main +npx nx lint:diff-with-main twenty-server +npx nx lint:diff-with-main twenty-front --configuration=fix # Auto-fix changed files # Run target for all projects (slower) npx nx run-many --target=build --all @@ -51,9 +50,8 @@ npx nx g @nx/react:component my-component ## Linting Strategy For faster development, always prefer linting only changed files: -- Use `npx nx lint:changed ` to lint only files changed vs main branch +- Use `npx nx lint:diff-with-main ` to lint only files changed vs main branch - Use `--configuration=fix` to auto-fix issues in changed files -- Use `--configuration=staged` to lint only staged files (useful for pre-commit hooks) - Only use `npx nx lint ` when you need to lint the entire project ## Dependency Graph diff --git a/CLAUDE.md b/CLAUDE.md index c00067f866..10a601c893 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -36,11 +36,10 @@ When testing the UI end to end, click on "Continue with Email" and use the prefi ### Code Quality ```bash -# Linting (changed files only - fastest) -npx nx lint:changed twenty-front # Lint only changed files vs main -npx nx lint:changed twenty-server # Lint only changed files vs main -npx nx lint:changed twenty-front --configuration=fix # Auto-fix changed files -npx nx lint:changed twenty-front --configuration=staged # Lint staged files only +# Linting (diff with main - fastest) +npx nx lint:diff-with-main twenty-front # Lint only files changed vs main +npx nx lint:diff-with-main twenty-server # Lint only files changed vs main +npx nx lint:diff-with-main twenty-front --configuration=fix # Auto-fix files changed vs main # Linting (full project) npx nx lint twenty-front # Lint all files in frontend diff --git a/nx.json b/nx.json index bb94a73d3b..02cac1a0b7 100644 --- a/nx.json +++ b/nx.json @@ -4,7 +4,9 @@ "libsDir": "packages" }, "namedInputs": { - "default": ["{projectRoot}/**/*"], + "default": [ + "{projectRoot}/**/*" + ], "excludeStories": [ "default", "!{projectRoot}/.storybook/*", @@ -32,17 +34,26 @@ "targetDefaults": { "build": { "cache": true, - "inputs": ["^production", "production"], - "dependsOn": ["^build"] + "inputs": [ + "^production", + "production" + ], + "dependsOn": [ + "^build" + ] }, "start": { "cache": false, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "lint": { "executor": "@nx/eslint:lint", "cache": true, - "outputs": ["{options.outputFile}"], + "outputs": [ + "{options.outputFile}" + ], "options": { "eslintConfig": "{projectRoot}/eslint.config.mjs", "cache": true, @@ -56,7 +67,22 @@ "fix": true } }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] + }, + "lint:diff-with-main": { + "executor": "nx:run-commands", + "cache": false, + "options": { + "command": "git diff --name-only --diff-filter=d main | grep -E '{args.pattern}' | grep '^{projectRoot}/' | xargs sh -c 'if [ $# -gt 0 ]; then npx eslint --config {projectRoot}/eslint.config.mjs \"$@\"; fi' _", + "pattern": "\\.(ts|tsx|js|jsx)$" + }, + "configurations": { + "fix": { + "command": "git diff --name-only --diff-filter=d main | grep -E '{args.pattern}' | grep '^{projectRoot}/' | xargs sh -c 'if [ $# -gt 0 ]; then npx eslint --config {projectRoot}/eslint.config.mjs --fix \"$@\"; fi' _" + } + } }, "fmt": { "executor": "nx:run-commands", @@ -77,7 +103,9 @@ "write": true } }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "typecheck": { "executor": "nx:run-commands", @@ -91,22 +119,30 @@ "watch": true } }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "test": { "executor": "@nx/jest:jest", "cache": true, - "dependsOn": ["^build"], + "dependsOn": [ + "^build" + ], "inputs": [ "^default", "excludeStories", "{workspaceRoot}/jest.preset.js" ], - "outputs": ["{projectRoot}/coverage"], + "outputs": [ + "{projectRoot}/coverage" + ], "options": { "jestConfig": "{projectRoot}/jest.config.mjs", "coverage": true, - "coverageReporters": ["text-summary"], + "coverageReporters": [ + "text-summary" + ], "cacheDirectory": "../../.cache/jest/{projectRoot}" }, "configurations": { @@ -115,7 +151,10 @@ "maxWorkers": 3 }, "coverage": { - "coverageReporters": ["lcov", "text"] + "coverageReporters": [ + "lcov", + "text" + ] }, "watch": { "watch": true @@ -124,25 +163,36 @@ }, "test:e2e": { "cache": true, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "storybook:build": { "executor": "nx:run-commands", "cache": true, - "inputs": ["^default", "excludeTests"], - "outputs": ["{projectRoot}/{options.output-dir}"], + "inputs": [ + "^default", + "excludeTests" + ], + "outputs": [ + "{projectRoot}/{options.output-dir}" + ], "options": { "cwd": "{projectRoot}", "command": "VITE_DISABLE_TYPESCRIPT_CHECKER=true storybook build --test", "output-dir": "storybook-static", "config-dir": ".storybook" }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "storybook:serve:dev": { "executor": "nx:run-commands", "cache": true, - "dependsOn": ["^build"], + "dependsOn": [ + "^build" + ], "options": { "cwd": "{projectRoot}", "command": "storybook dev", @@ -151,7 +201,9 @@ }, "storybook:serve:static": { "executor": "nx:run-commands", - "dependsOn": ["storybook:build"], + "dependsOn": [ + "storybook:build" + ], "options": { "cwd": "{projectRoot}", "command": "npx http-server {args.staticDir} -a={args.host} --port={args.port} --silent={args.silent}", @@ -164,8 +216,13 @@ "storybook:test": { "executor": "nx:run-commands", "cache": true, - "inputs": ["^default", "excludeTests"], - "outputs": ["{projectRoot}/coverage/storybook"], + "inputs": [ + "^default", + "excludeTests" + ], + "outputs": [ + "{projectRoot}/coverage/storybook" + ], "options": { "cwd": "{projectRoot}", "commands": [ @@ -181,7 +238,10 @@ }, "storybook:test:no-coverage": { "executor": "nx:run-commands", - "inputs": ["^default", "excludeTests"], + "inputs": [ + "^default", + "excludeTests" + ], "options": { "cwd": "{projectRoot}", "commands": [ @@ -271,12 +331,20 @@ }, "@nx/vite:test": { "cache": true, - "inputs": ["default", "^default"] + "inputs": [ + "default", + "^default" + ] }, "@nx/vite:build": { "cache": true, - "dependsOn": ["^build"], - "inputs": ["default", "^default"] + "dependsOn": [ + "^build" + ], + "inputs": [ + "default", + "^default" + ] } }, "installation": { @@ -308,7 +376,9 @@ "tasksRunnerOptions": { "default": { "options": { - "cacheableOperations": ["storybook:build"] + "cacheableOperations": [ + "storybook:build" + ] } } }, diff --git a/packages/twenty-front/project.json b/packages/twenty-front/project.json index b42edb66de..bca175039b 100644 --- a/packages/twenty-front/project.json +++ b/packages/twenty-front/project.json @@ -2,21 +2,31 @@ "name": "twenty-front", "$schema": "../../node_modules/nx/schemas/project-schema.json", "projectType": "application", - "tags": ["scope:frontend"], + "tags": [ + "scope:frontend" + ], "targets": { "build": { - "outputs": ["{options.outputPath}"], + "outputs": [ + "{options.outputPath}" + ], "options": { "outputPath": "{projectRoot}/build" }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "build:sourcemaps": { - "outputs": ["{options.outputPath}"], + "outputs": [ + "{options.outputPath}" + ], "options": { "outputPath": "{projectRoot}/build" }, - "dependsOn": ["^build"] + "dependsOn": [ + "^build" + ] }, "serve": { "executor": "nx:run-commands", @@ -41,8 +51,12 @@ }, "reset:env": { "executor": "nx:run-commands", - "inputs": ["{projectRoot}/.env.example"], - "outputs": ["{projectRoot}/.env"], + "inputs": [ + "{projectRoot}/.env.example" + ], + "outputs": [ + "{projectRoot}/.env" + ], "cache": true, "options": { "cwd": "{projectRoot}", @@ -59,22 +73,7 @@ "fix": {} } }, - "lint:changed": { - "executor": "nx:run-commands", - "cache": false, - "options": { - "command": "git diff --name-only --diff-filter=d {args.base} | grep -E '\\.(ts|tsx|js|jsx)$' | grep '^packages/twenty-front/' | xargs -r npx eslint --config packages/twenty-front/eslint.config.mjs", - "base": "main" - }, - "configurations": { - "fix": { - "command": "git diff --name-only --diff-filter=d {args.base} | grep -E '\\.(ts|tsx|js|jsx)$' | grep '^packages/twenty-front/' | xargs -r npx eslint --config packages/twenty-front/eslint.config.mjs --fix" - }, - "staged": { - "command": "git diff --cached --name-only --diff-filter=d | grep -E '\\.(ts|tsx|js|jsx)$' | grep '^packages/twenty-front/' | xargs -r npx eslint --config packages/twenty-front/eslint.config.mjs" - } - } - }, + "lint:diff-with-main": {}, "fmt": { "options": { "files": "src" @@ -86,49 +85,137 @@ "test": {}, "storybook:build": { "options": { - "env": { "NODE_OPTIONS": "--max_old_space_size=8000" } + "env": { + "NODE_OPTIONS": "--max_old_space_size=8000" + } }, "configurations": { - "docs": { "env": { "STORYBOOK_SCOPE": "ui-docs" } }, - "modules": { "env": { "STORYBOOK_SCOPE": "modules" } }, - "pages": { "env": { "STORYBOOK_SCOPE": "pages" } }, - "performance": { "env": { "STORYBOOK_SCOPE": "performance" } } + "docs": { + "env": { + "STORYBOOK_SCOPE": "ui-docs" + } + }, + "modules": { + "env": { + "STORYBOOK_SCOPE": "modules" + } + }, + "pages": { + "env": { + "STORYBOOK_SCOPE": "pages" + } + }, + "performance": { + "env": { + "STORYBOOK_SCOPE": "performance" + } + } } }, "storybook:serve:dev": { - "options": { "port": 6006 }, + "options": { + "port": 6006 + }, "configurations": { - "docs": { "env": { "STORYBOOK_SCOPE": "ui-docs" } }, - "modules": { "env": { "STORYBOOK_SCOPE": "modules" } }, - "pages": { "env": { "STORYBOOK_SCOPE": "pages" } }, - "performance": { "env": { "STORYBOOK_SCOPE": "performance" } } + "docs": { + "env": { + "STORYBOOK_SCOPE": "ui-docs" + } + }, + "modules": { + "env": { + "STORYBOOK_SCOPE": "modules" + } + }, + "pages": { + "env": { + "STORYBOOK_SCOPE": "pages" + } + }, + "performance": { + "env": { + "STORYBOOK_SCOPE": "performance" + } + } } }, "storybook:serve:static": { - "options": { "port": 6006 }, + "options": { + "port": 6006 + }, "configurations": { - "docs": { "env": { "STORYBOOK_SCOPE": "ui-docs" } }, - "modules": { "env": { "STORYBOOK_SCOPE": "modules" } }, - "pages": { "env": { "STORYBOOK_SCOPE": "pages" } }, - "performance": { "env": { "STORYBOOK_SCOPE": "performance" } } + "docs": { + "env": { + "STORYBOOK_SCOPE": "ui-docs" + } + }, + "modules": { + "env": { + "STORYBOOK_SCOPE": "modules" + } + }, + "pages": { + "env": { + "STORYBOOK_SCOPE": "pages" + } + }, + "performance": { + "env": { + "STORYBOOK_SCOPE": "performance" + } + } } }, "storybook:coverage": { "configurations": { "text": {}, - "docs": { "env": { "STORYBOOK_SCOPE": "ui-docs" } }, - "modules": { "env": { "STORYBOOK_SCOPE": "modules" } }, - "pages": { "env": { "STORYBOOK_SCOPE": "pages" } }, - "performance": { "env": { "STORYBOOK_SCOPE": "performance" } } + "docs": { + "env": { + "STORYBOOK_SCOPE": "ui-docs" + } + }, + "modules": { + "env": { + "STORYBOOK_SCOPE": "modules" + } + }, + "pages": { + "env": { + "STORYBOOK_SCOPE": "pages" + } + }, + "performance": { + "env": { + "STORYBOOK_SCOPE": "performance" + } + } } }, "storybook:test": { - "options": { "port": 6006 }, + "options": { + "port": 6006 + }, "configurations": { - "docs": { "env": { "STORYBOOK_SCOPE": "ui-docs" } }, - "modules": { "env": { "STORYBOOK_SCOPE": "modules" } }, - "pages": { "env": { "STORYBOOK_SCOPE": "pages" } }, - "performance": { "env": { "STORYBOOK_SCOPE": "performance" } } + "docs": { + "env": { + "STORYBOOK_SCOPE": "ui-docs" + } + }, + "modules": { + "env": { + "STORYBOOK_SCOPE": "modules" + } + }, + "pages": { + "env": { + "STORYBOOK_SCOPE": "pages" + } + }, + "performance": { + "env": { + "STORYBOOK_SCOPE": "performance" + } + } } }, "storybook:serve-and-test:static": { @@ -136,10 +223,18 @@ "port": 6006 }, "configurations": { - "docs": { "scope": "ui-docs" }, - "modules": { "scope": "modules" }, - "pages": { "scope": "pages" }, - "performance": { "scope": "performance" } + "docs": { + "scope": "ui-docs" + }, + "modules": { + "scope": "modules" + }, + "pages": { + "scope": "pages" + }, + "performance": { + "scope": "performance" + } } }, "graphql:generate": { diff --git a/packages/twenty-server/project.json b/packages/twenty-server/project.json index 538beff5f0..cb1edb47c6 100644 --- a/packages/twenty-server/project.json +++ b/packages/twenty-server/project.json @@ -156,20 +156,9 @@ "fix": {} } }, - "lint:changed": { - "executor": "nx:run-commands", - "cache": false, + "lint:diff-with-main": { "options": { - "command": "git diff --name-only --diff-filter=d {args.base} | grep -E '\\.(ts|tsx|js|jsx|json)$' | grep '^packages/twenty-server/' | xargs -r npx eslint", - "base": "main" - }, - "configurations": { - "fix": { - "command": "git diff --name-only --diff-filter=d {args.base} | grep -E '\\.(ts|tsx|js|jsx|json)$' | grep '^packages/twenty-server/' | xargs -r npx eslint --fix" - }, - "staged": { - "command": "git diff --cached --name-only --diff-filter=d | grep -E '\\.(ts|tsx|js|jsx|json)$' | grep '^packages/twenty-server/' | xargs -r npx eslint" - } + "pattern": "\\.(ts|tsx|js|jsx|json)$" } }, "test": {},