From 63267914e9323c91740db7b736436b0d5843a26c Mon Sep 17 00:00:00 2001 From: Dirk de Visser Date: Wed, 6 Mar 2024 16:21:44 +0100 Subject: [PATCH] feat(eslint-config): fully add the Prettier options and reformat (#21) Signed-off-by: Dirk de Visser --- .github/CODEOWNERS | 3 + .github/workflows/ci.yml | 4 +- apps/backend/package.json | 64 ++++++------ apps/backend/tsconfig.json | 8 +- package.json | 44 ++++---- packages/eslint-config/README.md | 33 +++++- packages/eslint-config/package.json | 66 ++++++------ packages/eslint-config/src/index.ts | 77 ++------------ packages/eslint-config/src/markdown.ts | 15 +++ packages/eslint-config/src/prettier.ts | 133 +++++++++++++++++++++++++ packages/eslint-config/src/utils.ts | 9 ++ packages/eslint-config/tsconfig.json | 8 +- packages/tsconfig/node-backend.json | 36 +++---- packages/tsconfig/node-package.json | 42 ++++---- packages/tsconfig/package.json | 35 +++---- tsconfig.json | 38 ++++--- 16 files changed, 369 insertions(+), 246 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 packages/eslint-config/src/markdown.ts create mode 100644 packages/eslint-config/src/prettier.ts create mode 100644 packages/eslint-config/src/utils.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..fd84193 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Automatically assign pull requests + +* @lightbasenl/core diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13f78dd..a513d0e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,9 @@ on: pull_request: concurrency: - group: "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}" + group: + "${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref + || github.ref }}" cancel-in-progress: true jobs: diff --git a/apps/backend/package.json b/apps/backend/package.json index ca87a94..d3736e3 100644 --- a/apps/backend/package.json +++ b/apps/backend/package.json @@ -1,34 +1,34 @@ { - "name": "@workspace/backend", - "type": "module", - "private": true, - "license": "MIT", - "scripts": { - "build": "tsc -p ./tsconfig.json", - "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", - "lint:ci": "eslint .", - "pretest": "npm run build", - "test": "node --test" - }, - "dependencies": { - "@fastify/helmet": "^11.1.1", - "@fastify/multipart": "^8.1.0", - "close-with-grace": "^1.2.0", - "dotenv": "^16.4.4", - "fastify": "^4.26.0", - "fastify-custom-healthcheck": "^3.1.0", - "fastify-plugin": "^4.5.1", - "fastify-type-provider-zod": "^1.1.9", - "zod": "^3.22.4" - }, - "devDependencies": { - "@types/node": "^20.11.17", - "@lightbase/tsconfig": "0.1.0", - "@lightbase/eslint-config": "0.1.0", - "pino-pretty": "^10.3.1", - "typescript": "5.3.3" - }, - "engines": { - "node": ">=20" - } + "name": "@workspace/backend", + "type": "module", + "private": true, + "license": "MIT", + "scripts": { + "build": "tsc -p ./tsconfig.json", + "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", + "lint:ci": "eslint .", + "pretest": "npm run build", + "test": "node --test" + }, + "dependencies": { + "@fastify/helmet": "^11.1.1", + "@fastify/multipart": "^8.1.0", + "close-with-grace": "^1.2.0", + "dotenv": "^16.4.4", + "fastify": "^4.26.0", + "fastify-custom-healthcheck": "^3.1.0", + "fastify-plugin": "^4.5.1", + "fastify-type-provider-zod": "^1.1.9", + "zod": "^3.22.4" + }, + "devDependencies": { + "@types/node": "^20.11.17", + "@lightbase/tsconfig": "0.1.0", + "@lightbase/eslint-config": "0.1.0", + "pino-pretty": "^10.3.1", + "typescript": "5.3.3" + }, + "engines": { + "node": ">=20" + } } diff --git a/apps/backend/tsconfig.json b/apps/backend/tsconfig.json index 97757f8..1dd457e 100644 --- a/apps/backend/tsconfig.json +++ b/apps/backend/tsconfig.json @@ -1,6 +1,6 @@ { - "extends": "@lightbase/tsconfig/node-package.json", - "compilerOptions": { - "outDir": "dist", - } + "extends": "@lightbase/tsconfig/node-package.json", + "compilerOptions": { + "outDir": "dist" + } } diff --git a/package.json b/package.json index 2bab03c..1459baf 100644 --- a/package.json +++ b/package.json @@ -1,24 +1,24 @@ { - "name": "@lightbase/platforms", - "type": "module", - "private": true, - "license": "MIT", - "scripts": { - "lint:ws": "npm run lint --workspaces --if-present --include-workspace-root", - "lint:ci:ws": "npm run lint:ci --workspaces --if-present --include-workspace-root", - "build:ws": "npm run build && npm run build --workspaces --if-present", - "test:ws": "npm run test --workspaces --if-present --include-workspace-root", - "build": "tsc --build", - "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", - "lint:ci": "eslint ." - }, - "devDependencies": { - "@lightbase/tsconfig": "0.1.0", - "@lightbase/eslint-config": "0.1.0", - "typescript": "5.3.3" - }, - "engines": { - "node": ">=20" - }, - "workspaces": ["packages/*", "apps/*"] + "name": "@lightbase/platforms", + "type": "module", + "private": true, + "license": "MIT", + "scripts": { + "lint:ws": "npm run lint --workspaces --if-present --include-workspace-root", + "lint:ci:ws": "npm run lint:ci --workspaces --if-present --include-workspace-root", + "build:ws": "npm run build && npm run build --workspaces --if-present", + "test:ws": "npm run test --workspaces --if-present --include-workspace-root", + "build": "tsc --build", + "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", + "lint:ci": "eslint ." + }, + "devDependencies": { + "@lightbase/eslint-config": "0.1.0", + "@lightbase/tsconfig": "0.1.0", + "typescript": "5.3.3" + }, + "engines": { + "node": ">=20" + }, + "workspaces": ["packages/*", "apps/*"] } diff --git a/packages/eslint-config/README.md b/packages/eslint-config/README.md index 0a8dbc9..acef063 100644 --- a/packages/eslint-config/README.md +++ b/packages/eslint-config/README.md @@ -56,9 +56,38 @@ alpha. - Use `eslint.config.mjs` instead of `eslint.config.js` - Specify `--config eslint.config.mjs` in the `package.json` scripts. -## Options +## Default configuration and options -None yet... +### Markdown + +A Markdown parser is installed by default. One of its purposes is to extract code-blocks +and present them as virtual files. Other configurations will automatically handle these +since they glob on `**/`. + +### Prettier + +Prettier is configured to run on all markdown, json, yaml, JavaScript and TypeScript +files. We support the following configuration to override this: + +```js +import { defineConfig } from "@lightbase/eslint-config"; + +export default defineConfig({ + prettier: { + globalOverride: { + // Override Prettier options for all supported files. + }, + languageOverrides: { + ts: { + // Override Prettier options for a specific file + // group. + }, + }, + }, +}); +``` + +None of these options are required. ## Custom configuration diff --git a/packages/eslint-config/package.json b/packages/eslint-config/package.json index c795a99..17d8953 100644 --- a/packages/eslint-config/package.json +++ b/packages/eslint-config/package.json @@ -1,35 +1,35 @@ { - "name": "@lightbase/eslint-config", - "version": "0.1.0", - "type": "module", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "exports": { - ".": { - "import": "./dist/src/index.js" - } - }, - "main": "./dist/src/index.js", - "types": "./dist/src/index.d.ts", - "files": ["README.md", "LICENSE", "dist/"], - "engines": { - "node": ">=20" - }, - "scripts": { - "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", - "lint:ci": "eslint ." - }, - "dependencies": { - "eslint-plugin-format": "^0.1.0", - "eslint-plugin-markdown": "^3.0.1" - }, - "peerDependencies": { - "eslint": ">=8.56.0" - }, - "devDependencies": { - "@types/eslint": "^8.56.2", - "@types/eslint-plugin-markdown": "^2.0.2" - } + "name": "@lightbase/eslint-config", + "version": "0.1.0", + "type": "module", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "exports": { + ".": { + "import": "./dist/src/index.js" + } + }, + "main": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "files": ["README.md", "LICENSE", "dist/"], + "engines": { + "node": ">=20" + }, + "scripts": { + "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", + "lint:ci": "eslint ." + }, + "dependencies": { + "eslint-plugin-format": "^0.1.0", + "eslint-plugin-markdown": "^3.0.1" + }, + "peerDependencies": { + "eslint": ">=8.56.0" + }, + "devDependencies": { + "@types/eslint": "^8.56.2", + "@types/eslint-plugin-markdown": "^2.0.2" + } } diff --git a/packages/eslint-config/src/index.ts b/packages/eslint-config/src/index.ts index 91aee7a..30718e2 100644 --- a/packages/eslint-config/src/index.ts +++ b/packages/eslint-config/src/index.ts @@ -1,32 +1,16 @@ import { Linter } from "eslint"; -import format from "eslint-plugin-format"; -import markdown from "eslint-plugin-markdown"; +import { markdownConfig } from "./markdown.js"; +import { PrettierConfig, prettierConfig } from "./prettier.js"; -interface Opts {} +interface Opts { + prettier?: PrettierConfig; +} export function defineConfig(opts: Opts, ...config: Linter.FlatConfig[]) { - // TODO: Global prettier config - - // TODO: Prettier config overrides per supported file type. - - const prettierConfig = { - printWidth: 90, - useTabs: true, - semi: true, - singleQuote: false, - quoteProps: "consistent", - trailingComma: "all", - bracketSpacing: true, - arrowParens: "always", - proseWrap: "always", - endOfLine: "lf", - experimentalTernaries: true, - }; - const conf: Linter.FlatConfig[] = [ { // TODO: Add automatic ignores based on .gitignore - ignores: [".cache", ".idea", ".next", "dist", "out"], + ignores: [".cache", ".idea", ".next", "dist", "out", "package-lock.json"], }, { @@ -36,53 +20,8 @@ export function defineConfig(opts: Opts, ...config: Linter.FlatConfig[]) { }, }, - { - plugins: { - markdown, - }, - }, - { - files: ["**/*.md"], - languageOptions: { - parser: format.parserPlain, - }, - }, - { - files: ["**/*.md"], - languageOptions: { - parser: format.parserPlain, - }, - plugins: { - format, - }, - rules: { - "format/prettier": ["error", { parser: "markdown", ...prettierConfig }], - }, - }, - { - files: ["**/*.[yml,yaml]"], - languageOptions: { - parser: format.parserPlain, - }, - plugins: { - format, - }, - rules: { - "format/prettier": ["error", { parser: "yaml", ...prettierConfig }], - }, - }, - { - files: ["**/*.?([cm])[jt]s?(x)"], - languageOptions: { - parser: format.parserPlain, - }, - plugins: { - format, - }, - rules: { - "format/prettier": ["error", { parser: "typescript", ...prettierConfig }], - }, - }, + ...markdownConfig(), + ...prettierConfig(opts.prettier), ]; return conf.concat(...config); diff --git a/packages/eslint-config/src/markdown.ts b/packages/eslint-config/src/markdown.ts new file mode 100644 index 0000000..ae2057e --- /dev/null +++ b/packages/eslint-config/src/markdown.ts @@ -0,0 +1,15 @@ +import { Linter } from "eslint"; +import markdown from "eslint-plugin-markdown"; + +/** + * Allows parsing of markdown files, adding code blocks as virtual files. + */ +export function markdownConfig(): Linter.FlatConfig[] { + return [ + { + plugins: { + markdown, + }, + }, + ]; +} diff --git a/packages/eslint-config/src/prettier.ts b/packages/eslint-config/src/prettier.ts new file mode 100644 index 0000000..92ae48e --- /dev/null +++ b/packages/eslint-config/src/prettier.ts @@ -0,0 +1,133 @@ +import { Linter } from "eslint"; +import format from "eslint-plugin-format"; +import type { Options } from "prettier"; +import { GLOB_ALL_JS, GLOB_ALL_JSON, GLOB_ALL_TS, GLOB_ALL_YAML } from "./utils.js"; + +type PrettierConfigLanguages = "js" | "ts" | "md" | "yaml" | "json"; + +export interface PrettierConfig { + globalOverride?: Options; + languageOverrides?: { [K in PrettierConfigLanguages]?: Options }; +} + +/** + * Apply Prettier formatting to all files. + */ +export function prettierConfig(config?: PrettierConfig): Linter.FlatConfig[] { + // TODO: css + tailwind plugin + + config ??= {}; + + const defaultConfig = { + printWidth: 90, + useTabs: true, + semi: true, + singleQuote: false, + quoteProps: "consistent", + trailingComma: "all", + bracketSpacing: true, + arrowParens: "always", + proseWrap: "always", + endOfLine: "lf", + experimentalTernaries: true, + + ...config.globalOverride, + }; + + config.languageOverrides ??= {}; + + return [ + { + files: ["**/*.md"], + plugins: { + format, + }, + languageOptions: { + parser: format.parserPlain, + }, + rules: { + "format/prettier": [ + "error", + { + parser: "markdown", + ...defaultConfig, + ...config.languageOverrides.md, + }, + ], + }, + }, + { + files: [GLOB_ALL_YAML], + plugins: { + format, + }, + languageOptions: { + parser: format.parserPlain, + }, + rules: { + "format/prettier": [ + "error", + { + parser: "yaml", + ...defaultConfig, + ...config.languageOverrides.yaml, + }, + ], + }, + }, + { + files: [GLOB_ALL_JSON], + plugins: { + format, + }, + languageOptions: { + parser: format.parserPlain, + }, + rules: { + "format/prettier": [ + "error", + { + parser: "json", + ...defaultConfig, + ...config.languageOverrides.json, + trailingComma: "none", + }, + ], + }, + }, + { + files: [GLOB_ALL_TS], + plugins: { + format, + }, + languageOptions: { + parser: format.parserPlain, + }, + rules: { + "format/prettier": [ + "error", + { parser: "typescript", ...defaultConfig, ...config.languageOverrides.ts }, + ], + }, + }, + { + files: [GLOB_ALL_JS], + plugins: { + format, + }, + languageOptions: { + parser: format.parserPlain, + }, + rules: { + "format/prettier": [ + "error", + { + parser: "typescript", + ...defaultConfig, + ...config.languageOverrides.js, + }, + ], + }, + }, + ]; +} diff --git a/packages/eslint-config/src/utils.ts b/packages/eslint-config/src/utils.ts new file mode 100644 index 0000000..2c04112 --- /dev/null +++ b/packages/eslint-config/src/utils.ts @@ -0,0 +1,9 @@ +export const GLOB_ALL_JS = "**/*.?(c|m)js?(x)"; + +export const GLOB_ALL_TS = "**/*.?(c|m)ts?(x)"; + +export const GLOB_ALL_JS_AND_TS = "**/*.?(c|m)[jt]s?(x)"; + +export const GLOB_ALL_YAML = "**/*.y?(a)ml"; + +export const GLOB_ALL_JSON = "**/*.json?(5|c)"; diff --git a/packages/eslint-config/tsconfig.json b/packages/eslint-config/tsconfig.json index 7073275..1dd457e 100644 --- a/packages/eslint-config/tsconfig.json +++ b/packages/eslint-config/tsconfig.json @@ -1,6 +1,6 @@ { - "extends": "@lightbase/tsconfig/node-package.json", - "compilerOptions": { - "outDir": "dist" - } + "extends": "@lightbase/tsconfig/node-package.json", + "compilerOptions": { + "outDir": "dist" + } } diff --git a/packages/tsconfig/node-backend.json b/packages/tsconfig/node-backend.json index 82acd2e..6f65403 100644 --- a/packages/tsconfig/node-backend.json +++ b/packages/tsconfig/node-backend.json @@ -1,23 +1,23 @@ { - "$schema": "https://json.schemastore.org/tsconfig.json", - "compilerOptions": { - "esModuleInterop": true, - "skipLibCheck": true, - "target": "es2022", - "allowJs": true, - "checkJs": true, - "resolveJsonModule": true, - "moduleDetection": "force", - "isolatedModules": true, - "forceConsistentCasingInFileNames": true, + "$schema": "https://json.schemastore.org/tsconfig.json", + "compilerOptions": { + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "allowJs": true, + "checkJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "forceConsistentCasingInFileNames": true, - "strict": true, - "noUncheckedIndexedAccess": true, + "strict": true, + "noUncheckedIndexedAccess": true, - "moduleResolution": "NodeNext", - "module": "NodeNext", - "sourceMap": true, + "moduleResolution": "NodeNext", + "module": "NodeNext", + "sourceMap": true, - "lib": ["es2022"] - } + "lib": ["es2022"] + } } diff --git a/packages/tsconfig/node-package.json b/packages/tsconfig/node-package.json index 769251b..7854e9d 100644 --- a/packages/tsconfig/node-package.json +++ b/packages/tsconfig/node-package.json @@ -1,27 +1,27 @@ { - "$schema": "https://json.schemastore.org/tsconfig.json", - "compilerOptions": { - "esModuleInterop": true, - "skipLibCheck": true, - "target": "es2022", - "allowJs": true, - "checkJs": true, - "resolveJsonModule": true, - "moduleDetection": "force", - "isolatedModules": true, - "forceConsistentCasingInFileNames": true, + "$schema": "https://json.schemastore.org/tsconfig.json", + "compilerOptions": { + "esModuleInterop": true, + "skipLibCheck": true, + "target": "es2022", + "allowJs": true, + "checkJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "forceConsistentCasingInFileNames": true, - "strict": true, - "noUncheckedIndexedAccess": true, + "strict": true, + "noUncheckedIndexedAccess": true, - "moduleResolution": "NodeNext", - "module": "NodeNext", - "sourceMap": true, + "moduleResolution": "NodeNext", + "module": "NodeNext", + "sourceMap": true, - "declaration": true, - "composite": true, - "declarationMap": true, + "declaration": true, + "composite": true, + "declarationMap": true, - "lib": ["es2022"] - } + "lib": ["es2022"] + } } diff --git a/packages/tsconfig/package.json b/packages/tsconfig/package.json index 34bf5bb..c6f4d45 100644 --- a/packages/tsconfig/package.json +++ b/packages/tsconfig/package.json @@ -1,22 +1,17 @@ { - "name": "@lightbase/tsconfig", - "version": "0.1.0", - "type": "module", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "files": [ - "README.md", - "LICENSE", - "node-backend.json", - "node-package.json" - ], - "engines": { - "node": ">=20" - }, - "scripts": { - "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", - "lint:ci": "eslint ." - } + "name": "@lightbase/tsconfig", + "version": "0.1.0", + "type": "module", + "license": "MIT", + "publishConfig": { + "access": "public" + }, + "files": ["README.md", "LICENSE", "node-backend.json", "node-package.json"], + "engines": { + "node": ">=20" + }, + "scripts": { + "lint": "eslint . --fix --cache --cache-strategy content --cache-location .cache/eslint/ --color", + "lint:ci": "eslint ." + } } diff --git a/tsconfig.json b/tsconfig.json index 546ea5a..413ac8c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,23 +1,21 @@ { - "extends": "@lightbase/tsconfig/node-package.json", - "compilerOptions": { - // Only used to check JS files - "noEmit": true, + "extends": "@lightbase/tsconfig/node-package.json", + "compilerOptions": { + // Only used to check JS files + "noEmit": true, - // Disable monorepo support here - "declarationMap": false, - "composite": false, - "declaration": false - }, - "files": [ - "./eslint.config.js" - ], - "references": [ - { - "path": "./packages/eslint-config", - }, - { - "path": "./apps/backend", - }, - ] + // Disable monorepo support here + "declarationMap": false, + "composite": false, + "declaration": false + }, + "files": ["./eslint.config.js"], + "references": [ + { + "path": "./packages/eslint-config" + }, + { + "path": "./apps/backend" + } + ] }