chore(development): add dev mode, update packages and test framework

This commit is contained in:
Sergo
2025-12-13 16:29:14 +02:00
parent c77eaf2968
commit d3b3b91523
12 changed files with 3955 additions and 1842 deletions

View File

@@ -1,4 +1,4 @@
FROM mirror.gcr.io/library/node:18-alpine as dev
FROM mirror.gcr.io/library/node:24-alpine as dev
RUN apk add netcat-openbsd
RUN npm config set update-notifier false
@@ -12,7 +12,7 @@ RUN npm run compile
ENTRYPOINT npm run start
FROM mirror.gcr.io/node:18-alpine AS prod
FROM mirror.gcr.io/node:24-alpine AS prod
RUN npm config set update-notifier false
WORKDIR /app

View File

@@ -6,5 +6,8 @@
"host": "HOSTNAME",
"authentication": {
"secret": "FEATHERS_SECRET"
},
"wildDuck": {
"url": "WILDDUCK_URL"
}
}

5
config/development.json Normal file
View File

@@ -0,0 +1,5 @@
{
"wildDuck": {
"url": "http://localhost:3031"
}
}

10
docker-compose.yml Normal file
View File

@@ -0,0 +1,10 @@
services:
mockserver:
image: mockserver/mockserver:5.15.0
ports:
- "3031:1080"
environment:
- MOCKSERVER_INITIALIZATION_JSON_PATH=/config/initializerJson.json
volumes:
- ./mockserver-config:/config
command: ["-serverPort", "1080", "-logLevel", "INFO"]

View File

@@ -0,0 +1,107 @@
[
{
"httpRequest": {
"method": "GET",
"path": "/users/dev-user/addresses"
},
"httpResponse": {
"statusCode": 200,
"headers": {
"Content-Type": [
"application/json"
]
},
"body": {
"success": true,
"results": [
{
"id": "alias1@test-codemowers.eu",
"address": "alias1@test-codemowers.eu",
"main": false,
"user": "dev-user",
"tags": [
"color"
],
"created": "2023-01-01T00:00:00.000Z"
},
{
"id": "alias2@test-codemowers.eu",
"address": "alias2@test-codemowers.eu",
"main": false,
"user": "dev-user",
"tags": [
"animal"
],
"created": "2023-01-02T00:00:00.000Z"
},
{
"id": "alias3@test-codemowers.eu",
"address": "alias3@test-codemowers.eu",
"main": false,
"user": "dev-user",
"tags": [],
"created": "2023-01-03T00:00:00.000Z"
}
]
}
}
},
{
"httpRequest": {
"method": "POST",
"path": "/users/dev-user/addresses"
},
"httpResponse": {
"statusCode": 200,
"headers": {
"Content-Type": [
"application/json"
]
},
"body": {
"success": true,
"id": "new-alias@test-codemowers.eu"
}
}
},
{
"httpRequest": {
"method": "GET",
"path": "/addresses/resolve/.*"
},
"httpResponse": {
"statusCode": 200,
"headers": {
"Content-Type": [
"application/json"
]
},
"body": {
"success": true,
"user": "dev-user",
"address": "{{request.pathSegments.[2]}}",
"id": "{{request.pathSegments.[2]}}",
"main": false,
"tags": [],
"created": "2023-01-01T00:00:00.000Z"
}
}
},
{
"httpRequest": {
"method": "DELETE",
"path": "/users/dev-user/addresses/.*"
},
"httpResponse": {
"statusCode": 200,
"headers": {
"Content-Type": [
"application/json"
]
},
"body": {
"success": true
}
}
}
]

5607
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -20,7 +20,7 @@
"contributors": [],
"bugs": {},
"engines": {
"node": ">= 16.19.1"
"node": ">= 24"
},
"feathers": {
"language": "ts",
@@ -39,16 +39,15 @@
},
"main": "lib/index",
"scripts": {
"dev": "nodemon -x ts-node src/index.ts",
"dev": "cross-env NODE_ENV=development nodemon -x ts-node src/index.ts",
"compile": "shx rm -rf lib/ && tsc",
"start": "node lib/",
"prettier": "npx prettier \"**/*.ts\" --write",
"mocha": "cross-env NODE_ENV=test mocha test/ --require ts-node/register --recursive --extension .ts --exit",
"test": "npm run mocha",
"bundle:client": "npm run compile && npm pack --pack-destination ./public"
"vitest": "vitest run",
"test": "npm run vitest"
},
"dependencies": {
"@faker-js/faker": "^8.0.2",
"@faker-js/faker": "^10.1.0",
"@feathersjs/adapter-commons": "^5.0.8",
"@feathersjs/authentication": "^5.0.8",
"@feathersjs/authentication-client": "^5.0.8",
@@ -61,11 +60,10 @@
"@feathersjs/transport-commons": "^5.0.8",
"axios": "^1.4.0",
"compression": "^1.7.4",
"config": "^3.3.9",
"config": "^4.1.1",
"connect-redis": "^7.1.0",
"cookie-parser": "^1.4.6",
"express-session": "^1.17.3",
"ioredis": "^5.3.2",
"openid-client": "^5.6.5",
"redis": "^4.6.7",
"winston": "^3.10.0"
@@ -76,23 +74,21 @@
"@types/cookie-parser": "^1.4.3",
"@types/express-session": "^1.17.7",
"@types/jsdom": "^27.0.0",
"@types/mocha": "^10.0.1",
"@types/node": "^20.4.5",
"@types/redis": "^4.0.11",
"@types/node": "^25.0.1",
"@types/sinon": "^21.0.0",
"cross-env": "^7.0.3",
"husky": "^8.0.3",
"cross-env": "^10.1.0",
"husky": "^9.1.7",
"jsdom": "^27.0.1",
"lint-staged": "^13.2.3",
"mocha": "^10.2.0",
"lint-staged": "^16.2.7",
"nodemon": "^3.0.1",
"prettier": "^3.0.0",
"shx": "^0.3.4",
"shx": "^0.4.0",
"sinon": "^21.0.0",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
"typescript": "^5.1.6",
"vitest": "^4.0.15"
},
"lint-staged": {
"*.{ts,js,css,md}": "prettier --write"
}
}
}

View File

@@ -84,6 +84,10 @@ export class AliasesService<ServiceParams extends AliasesParams = AliasesParams>
}
private async getUserIdByEmailAddress(params: ServiceParams): Promise<string> {
if (process.env.NODE_ENV === 'development') {
return 'dev-user';
}
const emails = params.session?.user?.emails;
const preferredDomain = config.get('wildDuck.preferredDomain');

View File

@@ -24,6 +24,14 @@ export class AuthOidcService<ServiceParams extends AuthOidcParams = AuthOidcPara
constructor(public options: AuthOidcServiceOptions) {}
async find(params: ServiceParams): Promise<AuthOidcResponse> {
if (process.env.NODE_ENV === 'development') {
// In dev mode, simulate login by setting fake user session
params.session.user = {
emails: ['dev@k-space.ee']
};
return '/';
}
const issuer = await Issuer.discover(config.get('oidc.gatewayUri'));
const client = new issuer.Client({
client_id: config.get('oidc.clientId'),

View File

@@ -2,6 +2,7 @@
import assert from 'assert';
import axios from 'axios';
import type { Server } from 'http';
import { describe, it, beforeAll, afterAll } from 'vitest';
import { app } from '../src/app';
const port = app.get('port');
@@ -10,11 +11,11 @@ const appUrl = `http://${app.get('host')}:${port}`;
describe('Feathers application tests', () => {
let server: Server;
before(async () => {
beforeAll(async () => {
server = await app.listen(port);
});
after(async () => {
afterAll(async () => {
await app.teardown();
});

View File

@@ -1,11 +1,12 @@
import assert from 'assert';
import fs from 'fs';
import path from 'path';
import { describe, it, beforeAll } from 'vitest';
describe('UI tests', () => {
let html: string;
before(async () => {
beforeAll(async () => {
// Load the HTML file
const htmlPath = path.join(__dirname, '../public/index.html');
html = fs.readFileSync(htmlPath, 'utf8');

9
vitest.config.ts Normal file
View File

@@ -0,0 +1,9 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
environment: 'node',
globals: true,
silent: true,
},
});