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
|
test-results.xml
|
||||||
|
|
||||||
|
# Jenkins generated build metadata
|
||||||
|
src/buildInfo.json
|
||||||
|
|
||||||
DS_STORE
|
DS_STORE
|
||||||
**/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') {
|
stage('Install Dependencies') {
|
||||||
steps {
|
steps {
|
||||||
nodejs(nodeJSInstallationName: 'Node23') {
|
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', () => ({
|
jest.unstable_mockModule('log4js', () => ({
|
||||||
default: {
|
default: {
|
||||||
getLogger: () => ({
|
getLogger: () => ({
|
||||||
@ -116,6 +125,10 @@ describe('SocketUser', () => {
|
|||||||
'disconnect',
|
'disconnect',
|
||||||
expect.any(Function)
|
expect.any(Function)
|
||||||
);
|
);
|
||||||
|
expect(mockSocket.on).toHaveBeenCalledWith(
|
||||||
|
'getServerVersion',
|
||||||
|
expect.any(Function)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('handleAuthenticateEvent', () => {
|
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', () => {
|
describe('handleDisconnect', () => {
|
||||||
it('should remove all listeners', async () => {
|
it('should remove all listeners', async () => {
|
||||||
await socketUser.handleDisconnect();
|
await socketUser.handleDisconnect();
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { ActionManager } from '../actions/actionmanager.js';
|
|||||||
import { EventManager } from '../events/eventmanager.js';
|
import { EventManager } from '../events/eventmanager.js';
|
||||||
import { StatsManager } from '../stats/statsmanager.js';
|
import { StatsManager } from '../stats/statsmanager.js';
|
||||||
import { NotificationManager } from '../notification/notificationmanager.js';
|
import { NotificationManager } from '../notification/notificationmanager.js';
|
||||||
|
import { ServerManager } from '../server/servermanager.js';
|
||||||
|
|
||||||
const config = loadConfig();
|
const config = loadConfig();
|
||||||
|
|
||||||
@ -29,6 +30,7 @@ export class SocketUser {
|
|||||||
this.eventManager = new EventManager(this);
|
this.eventManager = new EventManager(this);
|
||||||
this.statsManager = new StatsManager(this);
|
this.statsManager = new StatsManager(this);
|
||||||
this.notificationManager = new NotificationManager(this);
|
this.notificationManager = new NotificationManager(this);
|
||||||
|
this.serverManager = new ServerManager(this);
|
||||||
this.templateManager = socketManager.templateManager;
|
this.templateManager = socketManager.templateManager;
|
||||||
this.keycloakAuth = new KeycloakAuth();
|
this.keycloakAuth = new KeycloakAuth();
|
||||||
this.setupSocketEventHandlers();
|
this.setupSocketEventHandlers();
|
||||||
@ -84,6 +86,10 @@ export class SocketUser {
|
|||||||
'generateHostOtp',
|
'generateHostOtp',
|
||||||
this.handleGenerateHostOtpEvent.bind(this)
|
this.handleGenerateHostOtpEvent.bind(this)
|
||||||
);
|
);
|
||||||
|
this.socket.on(
|
||||||
|
'getServerVersion',
|
||||||
|
this.handleGetServerVersionEvent.bind(this)
|
||||||
|
);
|
||||||
this.socket.on('objectAction', this.handleObjectActionEvent.bind(this));
|
this.socket.on('objectAction', this.handleObjectActionEvent.bind(this));
|
||||||
this.socket.on('disconnect', this.handleDisconnect.bind(this));
|
this.socket.on('disconnect', this.handleDisconnect.bind(this));
|
||||||
}
|
}
|
||||||
@ -245,6 +251,11 @@ export class SocketUser {
|
|||||||
callback(result);
|
callback(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleGetServerVersionEvent(data, callback) {
|
||||||
|
const responseCallback = typeof callback === 'function' ? callback : data;
|
||||||
|
responseCallback(this.serverManager.getServerVersion());
|
||||||
|
}
|
||||||
|
|
||||||
async handleObjectActionEvent(data, callback) {
|
async handleObjectActionEvent(data, callback) {
|
||||||
await this.actionManager.sendObjectAction(
|
await this.actionManager.sendObjectAction(
|
||||||
data._id,
|
data._id,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user