diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ad28239 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [24.x] + + env: + AUTH0_SECRET: ${{ secrets.AUTH0_SECRET }} + APP_BASE_URL: ${{ secrets.APP_BASE_URL }} + AUTH0_DOMAIN: ${{ secrets.AUTH0_DOMAIN }} + AUTH0_CLIENT_ID: ${{ secrets.AUTH0_CLIENT_ID }} + AUTH0_CLIENT_SECRET: ${{ secrets.AUTH0_CLIENT_SECRET }} + DATABASE_URL: ${{ secrets.DATABASE_URL }} + + steps: + - uses: actions/checkout@v6 + + - name: Install pnpm + uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 + with: + version: 10.27.0 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Run lint + run: pnpm lint + + - name: Run typecheck + run: pnpm typecheck + + - name: Check code format + run: pnpm format:check + + - name: Build app + run: pnpm build diff --git a/eslint.config.js b/eslint.config.js index a57ce28..c18edfd 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,22 +1,19 @@ -// @ts-check const eslint = require('@eslint/js'); -const { defineConfig } = require('eslint/config'); const tseslint = require('typescript-eslint'); const angular = require('angular-eslint'); -module.exports = defineConfig([ +module.exports = tseslint.config( { files: ['**/*.ts'], extends: [ eslint.configs.recommended, - tseslint.configs.recommended, - tseslint.configs.stylistic, - angular.configs.tsRecommended, - 'plugin:@angular-eslint/recommended', - 'plugin:prettier/recommended', + ...tseslint.configs.recommended, + ...tseslint.configs.stylistic, + ...angular.configs.tsRecommended, ], processor: angular.processInlineTemplates, rules: { + '@angular-eslint/component-class-suffix': 'off', '@angular-eslint/directive-selector': [ 'error', { @@ -33,12 +30,39 @@ module.exports = defineConfig([ style: 'kebab-case', }, ], - 'prettier/prettier': 'error', + '@typescript-eslint/explicit-member-accessibility': 'error', + '@typescript-eslint/explicit-function-return-type': [ + 'error', + { + allowExpressions: true, + }, + ], + '@typescript-eslint/no-empty-function': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/no-inferrable-types': 'off', + '@typescript-eslint/typedef': [ + 'error', + { + memberVariableDeclaration: true, + propertyDeclaration: false, + parameter: true, + variableDeclaration: false, + arrowParameter: false, + }, + ], + 'no-console': 'warn', }, }, { files: ['**/*.html'], - extends: [angular.configs.templateRecommended, angular.configs.templateAccessibility], - rules: {}, + extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility], + rules: { + '@angular-eslint/template/alt-text': 'error', + '@angular-eslint/template/elements-content': 'error', + '@angular-eslint/template/label-has-associated-control': 'error', + '@angular-eslint/template/table-scope': 'error', + '@angular-eslint/template/valid-aria': 'error', + }, }, -]); +); diff --git a/package.json b/package.json index 4e018df..29e4ef8 100644 --- a/package.json +++ b/package.json @@ -1,63 +1,63 @@ { - "name": "admin-web", - "version": "0.0.0", - "scripts": { - "ng": "ng", - "start": "ng serve", - "build": "ng build", - "watch": "ng build --watch --configuration development", - "test": "ng test", - "lint": "ng lint", - "format": "prettier --write .", - "format:check": "prettier --check ." - }, - "prettier": { - "printWidth": 100, - "singleQuote": true, - "overrides": [ - { - "files": "*.html", - "options": { - "parser": "angular" - } - } - ] - }, - "private": true, - "packageManager": "pnpm@10.27.0", - "dependencies": { - "@angular-architects/ngrx-toolkit": "^21.0.1", - "@angular/common": "^21.1.0", - "@angular/compiler": "^21.1.0", - "@angular/core": "^21.1.0", - "@angular/forms": "^21.1.0", - "@angular/platform-browser": "^21.1.0", - "@angular/router": "^21.1.0", - "@auth0/auth0-angular": "^2.8.0", - "@ngrx/signals": "^21.1.0", - "@primeuix/themes": "^2.0.3", - "primeicons": "^7.0.0", - "primeng": "^21.1.6", - "rxjs": "~7.8.0", - "tailwindcss-primeui": "^0.6.1", - "tslib": "^2.3.0" - }, - "devDependencies": { - "@angular-eslint/builder": "21.4.0", - "@angular/build": "^21.1.2", - "@angular/cli": "^21.1.2", - "@angular/compiler-cli": "^21.1.0", - "@eslint/js": "^10.0.1", - "@ngx-env/builder": "^21.0.1", - "@tailwindcss/postcss": "^4.1.12", - "angular-eslint": "21.4.0", - "eslint": "^10.3.0", - "jsdom": "^27.1.0", - "postcss": "^8.5.3", - "prettier": "3.8.3", - "tailwindcss": "^4.1.12", - "typescript": "~5.9.2", - "typescript-eslint": "8.59.2", - "vitest": "^4.0.8" - } + "name": "admin-web", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "lint": "ng lint", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "prettier": { + "printWidth": 100, + "singleQuote": true, + "overrides": [ + { + "files": "*.html", + "options": { + "parser": "angular" + } + } + ] + }, + "private": true, + "packageManager": "pnpm@10.27.0", + "dependencies": { + "@angular-architects/ngrx-toolkit": "^21.0.1", + "@angular/common": "^21.1.0", + "@angular/compiler": "^21.1.0", + "@angular/core": "^21.1.0", + "@angular/forms": "^21.1.0", + "@angular/platform-browser": "^21.1.0", + "@angular/router": "^21.1.0", + "@auth0/auth0-angular": "^2.8.0", + "@ngrx/signals": "^21.1.0", + "@primeuix/themes": "^2.0.3", + "primeicons": "^7.0.0", + "primeng": "^21.1.6", + "rxjs": "~7.8.0", + "tailwindcss-primeui": "^0.6.1", + "tslib": "^2.3.0" + }, + "devDependencies": { + "@angular-eslint/builder": "21.4.0", + "@angular/build": "^21.1.2", + "@angular/cli": "^21.1.2", + "@angular/compiler-cli": "^21.1.0", + "@eslint/js": "^10.0.1", + "@ngx-env/builder": "^21.0.1", + "@tailwindcss/postcss": "^4.1.12", + "angular-eslint": "21.4.0", + "eslint": "^10.3.0", + "jsdom": "^27.1.0", + "postcss": "^8.5.3", + "prettier": "3.8.3", + "tailwindcss": "^4.1.12", + "typescript": "~5.9.2", + "typescript-eslint": "8.59.2", + "vitest": "^4.0.8" + } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7ddbcac..35237ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2752,10 +2752,6 @@ packages: resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==} engines: {node: '>= 0.6'} - mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - mime-types@3.0.2: resolution: {integrity: sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==} engines: {node: '>=18'} @@ -6325,11 +6321,6 @@ snapshots: mime-db@1.54.0: {} - mime-types@2.1.35: - dependencies: - mime-db: 1.52.0 - optional: true - mime-types@3.0.2: dependencies: mime-db: 1.54.0 diff --git a/src/env.d.ts b/src/env.d.ts index f27c3a9..7f80203 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ // Define the type of the environment variables. declare interface Env { readonly NODE_ENV: string; diff --git a/src/environments/environment.development.ts b/src/environments/environment.development.ts index a63fdd7..2bb9da4 100644 --- a/src/environments/environment.development.ts +++ b/src/environments/environment.development.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ export const environment = { production: false, apiServerUrl: import.meta.env['NG_APP_API_SERVER_URL'], diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 2e7f03c..6c3df2e 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ export const environment = { production: true, apiServerUrl: import.meta.env['NG_APP_API_SERVER_URL'],