diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f6978f74..8d8e40ee 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,34 +1,28 @@ name: CI on: pull_request: - # types: [opened, synchronize] - # TODO: why is this here? push: branches: - "main" permissions: contents: read jobs: - lint-node: - strategy: - fail-fast: false - matrix: - linter: [eslint, typescript] - name: Lint [${{ matrix.linter }}] + lint-client: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v6 - - name: Setup Node environment + - name: Install npm uses: actions/setup-node@v6 with: + node-version: 24.14.0 cache: npm cache-dependency-path: client/package-lock.json - name: Install packages run: npm ci working-directory: client - - name: Run ${{ matrix.linter }} - run: npm run lint:${{ matrix.linter }} + - name: Run client tests + run: npm run test working-directory: client test-python: name: Test Python diff --git a/client/src/vite-env.d.ts b/client/env.d.ts similarity index 100% rename from client/src/vite-env.d.ts rename to client/env.d.ts diff --git a/client/package-lock.json b/client/package-lock.json index b3cc7e20..c2187b55 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -26,12 +26,16 @@ }, "devDependencies": { "@sentry/vite-plugin": "5.1.1", + "@tsconfig/node24": "^24.0.4", "@types/geojson": "7946.0.16", "@types/lodash": "4.17.24", + "@types/node": "^25.5.0", "@vitejs/plugin-vue": "6.0.5", "@vue/eslint-config-typescript": "14.7.0", + "@vue/tsconfig": "^0.9.0", "eslint": "10.1.0", "eslint-plugin-vue": "10.8.0", + "npm-run-all2": "^8.0.4", "sass-embedded": "1.98.0", "typescript": "5.9.3", "vite": "8.0.3", @@ -3400,6 +3404,13 @@ } } }, + "node_modules/@tsconfig/node24": { + "version": "24.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node24/-/node24-24.0.4.tgz", + "integrity": "sha512-2A933l5P5oCbv6qSxHs7ckKwobs8BDAe9SJ/Xr2Hy+nDlwmLE1GhFh/g/vXGRZWgxBg9nX/5piDtHR9Dkw/XuA==", + "dev": true, + "license": "MIT" + }, "node_modules/@tybys/wasm-util": { "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", @@ -3723,8 +3734,8 @@ "version": "25.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz", "integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "undici-types": "~7.18.0" } @@ -4258,6 +4269,25 @@ "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", "license": "MIT" }, + "node_modules/@vue/tsconfig": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.9.1.tgz", + "integrity": "sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 5.8", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, "node_modules/@vuetify/loader-shared": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@vuetify/loader-shared/-/loader-shared-2.1.2.tgz", @@ -4331,6 +4361,19 @@ "dev": true, "license": "MIT" }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -6418,6 +6461,16 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6869,6 +6922,15 @@ "node": ">= 0.4" } }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7129,6 +7191,69 @@ "devOptional": true, "license": "MIT" }, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-all2": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-8.0.4.tgz", + "integrity": "sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "picomatch": "^4.0.2", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^20.5.0 || >=22.0.0", + "npm": ">= 10" + } + }, + "node_modules/npm-run-all2/node_modules/isexe": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz", + "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/npm-run-all2/node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", @@ -7340,6 +7465,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/pkg-types": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", @@ -7567,6 +7705,20 @@ "node": ">=0.10.0" } }, + "node_modules/read-package-json-fast": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -8267,6 +8419,19 @@ "node": ">=8" } }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", @@ -8638,8 +8803,8 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.1", diff --git a/client/package.json b/client/package.json index 5378adec..1ddf0a64 100644 --- a/client/package.json +++ b/client/package.json @@ -5,12 +5,12 @@ "type": "module", "scripts": { "dev": "vite", - "build": "vite build", "preview": "vite preview", + "build": "vite build", "format": "eslint --fix src", - "lint:eslint": "eslint src", - "lint": "eslint src && vue-tsc --noEmit", - "lint:typescript": "vue-tsc --noEmit" + "test:lint": "eslint --no-fix src", + "test:type": "vue-tsc --build", + "test": "npm-run-all test:lint test:type" }, "dependencies": { "@jamescoyle/vue-icon": "0.1.2", @@ -31,12 +31,16 @@ }, "devDependencies": { "@sentry/vite-plugin": "5.1.1", + "@tsconfig/node24": "^24.0.4", "@types/geojson": "7946.0.16", "@types/lodash": "4.17.24", + "@types/node": "^25.5.0", "@vitejs/plugin-vue": "6.0.5", "@vue/eslint-config-typescript": "14.7.0", + "@vue/tsconfig": "^0.9.0", "eslint": "10.1.0", "eslint-plugin-vue": "10.8.0", + "npm-run-all2": "^8.0.4", "sass-embedded": "1.98.0", "typescript": "5.9.3", "vite": "8.0.3", diff --git a/client/src/api/NABatApi.ts b/client/src/api/NABatApi.ts index 3469d5fd..ef85423b 100644 --- a/client/src/api/NABatApi.ts +++ b/client/src/api/NABatApi.ts @@ -1,4 +1,4 @@ -import { axiosInstance, FileAnnotation, FileAnnotationDetails, ProcessingTask, Spectrogram, UpdateFileAnnotation } from "./api"; +import { axiosInstance, type FileAnnotation, type FileAnnotationDetails, type ProcessingTask, type Spectrogram, type UpdateFileAnnotation } from "./api"; export interface NABatRecordingCompleteResponse { error?: string; diff --git a/client/src/api/api.ts b/client/src/api/api.ts index 2c65fd4f..100da053 100644 --- a/client/src/api/api.ts +++ b/client/src/api/api.ts @@ -1,6 +1,6 @@ import axios from "axios"; import { AxiosError } from "axios"; -import { SpectroInfo } from "@components/geoJS/geoJSUtils"; +import type { SpectroInfo } from "@components/geoJS/geoJSUtils"; import type { FeatureCollection, Point } from "geojson"; export interface Recording { diff --git a/client/src/components/AnnotationEditor.vue b/client/src/components/AnnotationEditor.vue index 44c39dfe..2daa22f4 100644 --- a/client/src/components/AnnotationEditor.vue +++ b/client/src/components/AnnotationEditor.vue @@ -1,7 +1,7 @@