Implemented about page.
All checks were successful
farmcontrol/farmcontrol-ws/pipeline/head This commit looks good
All checks were successful
farmcontrol/farmcontrol-ws/pipeline/head This commit looks good
This commit is contained in:
parent
a1e4bcaf18
commit
4bfc7fae2a
3
.gitignore
vendored
3
.gitignore
vendored
@ -135,6 +135,9 @@ dist
|
||||
|
||||
test-results.xml
|
||||
|
||||
# Jenkins generated build metadata
|
||||
src/buildInfo.json
|
||||
|
||||
DS_STORE
|
||||
**/DS_Store
|
||||
|
||||
|
||||
10
Jenkinsfile
vendored
10
Jenkinsfile
vendored
@ -23,6 +23,16 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('Write Build Metadata') {
|
||||
steps {
|
||||
nodejs(nodeJSInstallationName: 'Node23') {
|
||||
sh '''
|
||||
node -e "const fs = require('fs'); fs.writeFileSync('src/buildInfo.json', JSON.stringify({ buildNumber: process.env.BUILD_NUMBER || 'dev' }, null, 2) + '\\n');"
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Install Dependencies') {
|
||||
steps {
|
||||
nodejs(nodeJSInstallationName: 'Node23') {
|
||||
|
||||
42
src/server/servermanager.js
Normal file
42
src/server/servermanager.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import log4js from 'log4js';
|
||||
import { loadConfig } from '../config.js';
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
// Setup logger
|
||||
const logger = log4js.getLogger('Server Manager');
|
||||
logger.level = config.server.logLevel;
|
||||
|
||||
const readJsonFile = fileUrl => {
|
||||
try {
|
||||
return JSON.parse(readFileSync(fileUrl, 'utf8'));
|
||||
} catch (error) {
|
||||
if (error?.code !== 'ENOENT') {
|
||||
logger.debug('Failed to read server metadata:', error?.message);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
const packageJsonUrl = new URL('../../package.json', import.meta.url);
|
||||
const buildInfoUrl = new URL('../buildInfo.json', import.meta.url);
|
||||
|
||||
/**
|
||||
* ServerManager exposes websocket server metadata to authenticated socket users.
|
||||
*/
|
||||
export class ServerManager {
|
||||
constructor(socketClient) {
|
||||
this.socketClient = socketClient;
|
||||
}
|
||||
|
||||
getServerVersion() {
|
||||
const packageJson = readJsonFile(packageJsonUrl);
|
||||
const buildInfo = readJsonFile(buildInfoUrl);
|
||||
|
||||
return {
|
||||
version: packageJson.version ?? 'dev',
|
||||
buildNumber: buildInfo.buildNumber ?? 'dev'
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -67,6 +67,15 @@ jest.unstable_mockModule('../../notification/notificationmanager.js', () => ({
|
||||
}))
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('../../server/servermanager.js', () => ({
|
||||
ServerManager: jest.fn().mockImplementation(() => ({
|
||||
getServerVersion: jest.fn(() => ({
|
||||
version: '1.0.0',
|
||||
buildNumber: 'dev'
|
||||
}))
|
||||
}))
|
||||
}));
|
||||
|
||||
jest.unstable_mockModule('log4js', () => ({
|
||||
default: {
|
||||
getLogger: () => ({
|
||||
@ -116,6 +125,10 @@ describe('SocketUser', () => {
|
||||
'disconnect',
|
||||
expect.any(Function)
|
||||
);
|
||||
expect(mockSocket.on).toHaveBeenCalledWith(
|
||||
'getServerVersion',
|
||||
expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
describe('handleAuthenticateEvent', () => {
|
||||
@ -224,6 +237,20 @@ describe('SocketUser', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleGetServerVersionEvent', () => {
|
||||
it('should return server version details', async () => {
|
||||
const callback = jest.fn();
|
||||
|
||||
await socketUser.handleGetServerVersionEvent({}, callback);
|
||||
|
||||
expect(socketUser.serverManager.getServerVersion).toHaveBeenCalled();
|
||||
expect(callback).toHaveBeenCalledWith({
|
||||
version: '1.0.0',
|
||||
buildNumber: 'dev'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handleDisconnect', () => {
|
||||
it('should remove all listeners', async () => {
|
||||
await socketUser.handleDisconnect();
|
||||
|
||||
@ -9,6 +9,7 @@ import { ActionManager } from '../actions/actionmanager.js';
|
||||
import { EventManager } from '../events/eventmanager.js';
|
||||
import { StatsManager } from '../stats/statsmanager.js';
|
||||
import { NotificationManager } from '../notification/notificationmanager.js';
|
||||
import { ServerManager } from '../server/servermanager.js';
|
||||
|
||||
const config = loadConfig();
|
||||
|
||||
@ -29,6 +30,7 @@ export class SocketUser {
|
||||
this.eventManager = new EventManager(this);
|
||||
this.statsManager = new StatsManager(this);
|
||||
this.notificationManager = new NotificationManager(this);
|
||||
this.serverManager = new ServerManager(this);
|
||||
this.templateManager = socketManager.templateManager;
|
||||
this.keycloakAuth = new KeycloakAuth();
|
||||
this.setupSocketEventHandlers();
|
||||
@ -84,6 +86,10 @@ export class SocketUser {
|
||||
'generateHostOtp',
|
||||
this.handleGenerateHostOtpEvent.bind(this)
|
||||
);
|
||||
this.socket.on(
|
||||
'getServerVersion',
|
||||
this.handleGetServerVersionEvent.bind(this)
|
||||
);
|
||||
this.socket.on('objectAction', this.handleObjectActionEvent.bind(this));
|
||||
this.socket.on('disconnect', this.handleDisconnect.bind(this));
|
||||
}
|
||||
@ -245,6 +251,11 @@ export class SocketUser {
|
||||
callback(result);
|
||||
}
|
||||
|
||||
async handleGetServerVersionEvent(data, callback) {
|
||||
const responseCallback = typeof callback === 'function' ? callback : data;
|
||||
responseCallback(this.serverManager.getServerVersion());
|
||||
}
|
||||
|
||||
async handleObjectActionEvent(data, callback) {
|
||||
await this.actionManager.sendObjectAction(
|
||||
data._id,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user