diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..d2123db --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,30 @@ +name: Lint and Format Check + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + lint-and-format: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + cache: 'yarn' + + - name: Install dependencies + run: yarn install --immutable + + - name: Run Prettier check + run: yarn format:check + + - name: Run ESLint + run: yarn lint diff --git a/nx.json b/nx.json index 4a3b6cb..62c5f29 100644 --- a/nx.json +++ b/nx.json @@ -11,6 +11,12 @@ }, "lint": { "cache": true + }, + "lint:fix": { + "cache": true + }, + "format:check": { + "cache": true } }, "defaultBase": "main", diff --git a/package.json b/package.json index 6985a89..d9bf03c 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,10 @@ "packages/*" ], "scripts": { + "lint": "nx run-many --target=lint", + "lint:fix": "nx run-many --target=lint:fix", "format": "nx run-many --target=format", + "format:check": "nx run-many --target=format:check", "dev": "yarn workspaces foreach --all --interlaced --parallel run dev", "build": "nx run-many --target=build", "start": "nx run-many --target=start", diff --git a/packages/executor/package.json b/packages/executor/package.json index 211cbba..4904eaa 100644 --- a/packages/executor/package.json +++ b/packages/executor/package.json @@ -12,7 +12,8 @@ "build": "tsc", "compile": "yarn build", "start": "yarn build && LOG_LEVEL=debug DEBUG='*,-puppeteer:protocol*' MONGODB_URI=mongodb://localhost:27017/extension-a11y-checker node --no-experimental-require-module dist/index.js", - "format": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --write" + "format": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --write", + "format:check": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --check" }, "dependencies": { "extension-a11y-checker-storage": "workspace:*", diff --git a/packages/storage/package.json b/packages/storage/package.json index 8a22e8c..7b46c9c 100644 --- a/packages/storage/package.json +++ b/packages/storage/package.json @@ -22,8 +22,8 @@ "dev": "tsc --watch", "build": "tsc", "compile": "yarn build", - "lint": "exit 1", - "format": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --write" + "format": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --write", + "format:check": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --check" }, "dependencies": { "@typegoose/typegoose": "^12.11.0", diff --git a/packages/web2/.prettierignore b/packages/web2/.prettierignore new file mode 100644 index 0000000..0bd1a0d --- /dev/null +++ b/packages/web2/.prettierignore @@ -0,0 +1 @@ +**/*.gen.ts diff --git a/packages/web2/app/actions/commons.ts b/packages/web2/app/actions/commons.ts index 3ef9a60..a623bdd 100644 --- a/packages/web2/app/actions/commons.ts +++ b/packages/web2/app/actions/commons.ts @@ -35,7 +35,7 @@ export const validateCron = (cronExpression: string | undefined) => { { status: 400 }, ); } - } catch (e) { + } catch { return new Response("Invalid cron expression", { status: 400 }); } } diff --git a/packages/web2/app/actions/profile.ts b/packages/web2/app/actions/profile.ts index 9a6b678..5eadcfd 100644 --- a/packages/web2/app/actions/profile.ts +++ b/packages/web2/app/actions/profile.ts @@ -115,7 +115,7 @@ export const updateProfileDomain = createServerFn({ method: "POST" }) domain: z .string() .regex( - /^(((?!-))(xn--|_)?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9\-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$/, + /^(((?!-))(xn--|_)?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$/, "Not a valid domain name.", ), }), diff --git a/packages/web2/app/components/create/components/domain.tsx b/packages/web2/app/components/create/components/domain.tsx index 220ec3d..e62d1b5 100644 --- a/packages/web2/app/components/create/components/domain.tsx +++ b/packages/web2/app/components/create/components/domain.tsx @@ -27,7 +27,7 @@ export const Domain = ({ rules={{ pattern: { value: - /^(((?!-))(xn--|_)?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9\-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$/, + /^(((?!-))(xn--|_)?[a-z0-9-]{0,61}[a-z0-9]{1,1}\.)*(xn--)?([a-z0-9][a-z0-9-]{0,60}|[a-z0-9-]{1,30}\.[a-z]{2,})$/, message: "Bitte gib die Domain ohne Protokoll ein. Beispiel: www.example.com oder example.com", }, diff --git a/packages/web2/app/components/create/components/pathsList.tsx b/packages/web2/app/components/create/components/pathsList.tsx index 7176e1a..4a00090 100644 --- a/packages/web2/app/components/create/components/pathsList.tsx +++ b/packages/web2/app/components/create/components/pathsList.tsx @@ -54,13 +54,13 @@ export const PathsList = ({ setTouched(false); } - const removePathFromFormValues = (value: string | String) => { + const removePathFromFormValues = (value: string) => { const values = form.getValues("paths"); values.delete(value.toString()); form.setValue("paths", values); }; - const PathList = typedList(); + const PathList = typedList(); const pathsList = ( diff --git a/packages/web2/app/components/create/helpers.ts b/packages/web2/app/components/create/helpers.ts index eb3dc2a..551a428 100644 --- a/packages/web2/app/components/create/helpers.ts +++ b/packages/web2/app/components/create/helpers.ts @@ -1,7 +1,7 @@ export function extractDomainFromUrl(url: string): string { try { return new URL(url).hostname; - } catch (error) { + } catch { return url; } } @@ -9,7 +9,7 @@ export function extractDomainFromUrl(url: string): string { export function extractPathFromUrl(url: string): string { try { return new URL(url).pathname; - } catch (error) { + } catch { return url; } } diff --git a/packages/web2/app/components/profile/CronFields/CronFields.tsx b/packages/web2/app/components/profile/CronFields/CronFields.tsx index cc041fb..8a71be4 100644 --- a/packages/web2/app/components/profile/CronFields/CronFields.tsx +++ b/packages/web2/app/components/profile/CronFields/CronFields.tsx @@ -53,7 +53,9 @@ export const CronFields: FC = (props) => { showTimeField ? watchedCronTime : undefined, ); form.setValue(name, newValue.cron); - newValue.time && form.setValue("cronTime", newValue.time); + if (newValue.time) { + form.setValue("cronTime", newValue.time); + } }, [watchedCronInterval]); useEffect(() => { @@ -61,7 +63,9 @@ export const CronFields: FC = (props) => { watchedCronInterval === "custom" ? getTimeFromCron(watchedCron) : undefined; - newValue && form.setValue("cronTime", newValue); + if (newValue) { + form.setValue("cronTime", newValue); + } }, [watchedCron]); return ( diff --git a/packages/web2/app/components/profile/CronFields/NextExecutionsLabeledValue.tsx b/packages/web2/app/components/profile/CronFields/NextExecutionsLabeledValue.tsx index 7dd4387..d4dc409 100644 --- a/packages/web2/app/components/profile/CronFields/NextExecutionsLabeledValue.tsx +++ b/packages/web2/app/components/profile/CronFields/NextExecutionsLabeledValue.tsx @@ -14,12 +14,12 @@ interface Props { export const NextExecutionsLabeledValue: FC = (props) => { const { cron } = props; + const executions = useMemo(() => getExecutions(cron), [cron]); + if (cron === "" || !isValidCron(cron)) { return null; } - const executions = useMemo(() => getExecutions(cron), [cron]); - const nextExecutions = executions.map((date) => { return ( diff --git a/packages/web2/app/components/profile/CronFields/lib.ts b/packages/web2/app/components/profile/CronFields/lib.ts index d01911d..c9e8990 100644 --- a/packages/web2/app/components/profile/CronFields/lib.ts +++ b/packages/web2/app/components/profile/CronFields/lib.ts @@ -10,7 +10,7 @@ export const getCronText = (cronSyntax: string) => { locale: "de", verbose: true, })}`; - } catch (ignoredError) { + } catch { return undefined; } }; @@ -163,7 +163,7 @@ export const isSmallIntervall = (schedule: string) => { const dayInHours = 24; return hoursDiff < dayInHours * 5; - } catch (ignoredError) { + } catch { return false; } }; @@ -179,7 +179,7 @@ export const getExecutions = (cron: string) => { } return executions; - } catch (ignoredError) { + } catch { return []; } }; diff --git a/packages/web2/app/ssr.tsx b/packages/web2/app/ssr.tsx index d3832ea..698b71a 100644 --- a/packages/web2/app/ssr.tsx +++ b/packages/web2/app/ssr.tsx @@ -4,7 +4,6 @@ import { defaultStreamHandler, } from "@tanstack/react-start/server"; import { getRouterManifest } from "@tanstack/react-start/router-manifest"; -import React from "react"; import { createRouter } from "./router"; diff --git a/packages/web2/eslint.config.js b/packages/web2/eslint.config.js index 092408a..360bd2b 100644 --- a/packages/web2/eslint.config.js +++ b/packages/web2/eslint.config.js @@ -1,28 +1,28 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' +import js from "@eslint/js"; +import globals from "globals"; +import reactHooks from "eslint-plugin-react-hooks"; +import reactRefresh from "eslint-plugin-react-refresh"; +import tseslint from "typescript-eslint"; export default tseslint.config( - { ignores: ['dist'] }, + { ignores: ["dist", ".vinxi", ".output", "node_modules"] }, { extends: [js.configs.recommended, ...tseslint.configs.recommended], - files: ['**/*.{ts,tsx}'], + files: ["**/*.{ts,tsx}"], languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, plugins: { - 'react-hooks': reactHooks, - 'react-refresh': reactRefresh, + "react-hooks": reactHooks, + "react-refresh": reactRefresh, }, rules: { ...reactHooks.configs.recommended.rules, - 'react-refresh/only-export-components': [ - 'warn', + "react-refresh/only-export-components": [ + "warn", { allowConstantExport: true }, ], }, }, -) +); diff --git a/packages/web2/package.json b/packages/web2/package.json index 2da6012..577f0cc 100644 --- a/packages/web2/package.json +++ b/packages/web2/package.json @@ -9,8 +9,10 @@ "start": "vinxi start", "compile": "yarn build", "lint": "eslint .", + "lint:fix": "eslint . --fix", "preview": "nx vite:preview", - "format": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --write" + "format": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --write", + "format:check": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}' --check" }, "dependencies": { "@mittwald/api-client": "^4.131.0",