Files
onebox/ts/database/repositories/service.repository.ts
Juergen Kunz ad89f2cc1f feat: Implement repositories for authentication, certificates, metrics, and platform services
- Added AuthRepository for user and settings management with CRUD operations.
- Introduced CertificateRepository to handle domains, certificates, and requirements.
- Created MetricsRepository for managing metrics and logs.
- Developed PlatformRepository for platform services and resources management.
- Established RegistryRepository for registry and token operations.
- Implemented ServiceRepository for CRUD operations on services.
- Defined types and interfaces in types.ts for database interactions.
2025-11-25 23:27:27 +00:00

178 lines
6.2 KiB
TypeScript

/**
* Service Repository
* Handles CRUD operations for services table
*/
import { BaseRepository } from '../base.repository.ts';
import type { TBindValue } from '../types.ts';
import type { IService, IPlatformRequirements } from '../../types.ts';
import { logger } from '../../logging.ts';
import { getErrorMessage } from '../../utils/error.ts';
export class ServiceRepository extends BaseRepository {
async create(service: Omit<IService, 'id'>): Promise<IService> {
const now = Date.now();
this.query(
`INSERT INTO services (
name, image, registry, env_vars, port, domain, container_id, status,
created_at, updated_at,
use_onebox_registry, registry_repository, registry_image_tag,
auto_update_on_push, image_digest, platform_requirements
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
[
service.name,
service.image,
service.registry || null,
JSON.stringify(service.envVars),
service.port,
service.domain || null,
service.containerID || null,
service.status,
now,
now,
service.useOneboxRegistry ? 1 : 0,
service.registryRepository || null,
service.registryImageTag || 'latest',
service.autoUpdateOnPush ? 1 : 0,
service.imageDigest || null,
JSON.stringify(service.platformRequirements || {}),
]
);
return this.getByName(service.name)!;
}
getByName(name: string): IService | null {
const rows = this.query('SELECT * FROM services WHERE name = ?', [name]);
if (rows.length > 0) {
logger.info(`getServiceByName: raw row data: ${JSON.stringify(rows[0])}`);
const service = this.rowToService(rows[0]);
logger.info(`getServiceByName: service object containerID: ${service.containerID}`);
return service;
}
return null;
}
getById(id: number): IService | null {
const rows = this.query('SELECT * FROM services WHERE id = ?', [id]);
return rows.length > 0 ? this.rowToService(rows[0]) : null;
}
getAll(): IService[] {
const rows = this.query('SELECT * FROM services ORDER BY created_at DESC');
return rows.map((row) => this.rowToService(row));
}
update(id: number, updates: Partial<IService>): void {
const fields: string[] = [];
const values: TBindValue[] = [];
if (updates.image !== undefined) {
fields.push('image = ?');
values.push(updates.image);
}
if (updates.registry !== undefined) {
fields.push('registry = ?');
values.push(updates.registry);
}
if (updates.envVars !== undefined) {
fields.push('env_vars = ?');
values.push(JSON.stringify(updates.envVars));
}
if (updates.port !== undefined) {
fields.push('port = ?');
values.push(updates.port);
}
if (updates.domain !== undefined) {
fields.push('domain = ?');
values.push(updates.domain);
}
if (updates.containerID !== undefined) {
fields.push('container_id = ?');
values.push(updates.containerID);
}
if (updates.status !== undefined) {
fields.push('status = ?');
values.push(updates.status);
}
if (updates.useOneboxRegistry !== undefined) {
fields.push('use_onebox_registry = ?');
values.push(updates.useOneboxRegistry ? 1 : 0);
}
if (updates.registryRepository !== undefined) {
fields.push('registry_repository = ?');
values.push(updates.registryRepository);
}
if (updates.registryImageTag !== undefined) {
fields.push('registry_image_tag = ?');
values.push(updates.registryImageTag);
}
if (updates.autoUpdateOnPush !== undefined) {
fields.push('auto_update_on_push = ?');
values.push(updates.autoUpdateOnPush ? 1 : 0);
}
if (updates.imageDigest !== undefined) {
fields.push('image_digest = ?');
values.push(updates.imageDigest);
}
if (updates.platformRequirements !== undefined) {
fields.push('platform_requirements = ?');
values.push(JSON.stringify(updates.platformRequirements));
}
fields.push('updated_at = ?');
values.push(Date.now());
values.push(id);
this.query(`UPDATE services SET ${fields.join(', ')} WHERE id = ?`, values);
}
delete(id: number): void {
this.query('DELETE FROM services WHERE id = ?', [id]);
}
private rowToService(row: any): IService {
let envVars = {};
const envVarsRaw = row.env_vars || row[4];
if (envVarsRaw && envVarsRaw !== 'undefined' && envVarsRaw !== 'null') {
try {
envVars = JSON.parse(String(envVarsRaw));
} catch (e) {
logger.warn(`Failed to parse env_vars for service: ${getErrorMessage(e)}`);
envVars = {};
}
}
let platformRequirements: IPlatformRequirements | undefined;
const platformReqRaw = row.platform_requirements;
if (platformReqRaw && platformReqRaw !== 'undefined' && platformReqRaw !== 'null' && platformReqRaw !== '{}') {
try {
platformRequirements = JSON.parse(String(platformReqRaw));
} catch (e) {
logger.warn(`Failed to parse platform_requirements for service: ${getErrorMessage(e)}`);
platformRequirements = undefined;
}
}
return {
id: Number(row.id || row[0]),
name: String(row.name || row[1]),
image: String(row.image || row[2]),
registry: (row.registry || row[3]) ? String(row.registry || row[3]) : undefined,
envVars,
port: Number(row.port || row[5]),
domain: (row.domain || row[6]) ? String(row.domain || row[6]) : undefined,
containerID: (row.container_id || row[7]) ? String(row.container_id || row[7]) : undefined,
status: String(row.status || row[8]) as IService['status'],
createdAt: Number(row.created_at || row[9]),
updatedAt: Number(row.updated_at || row[10]),
useOneboxRegistry: row.use_onebox_registry ? Boolean(row.use_onebox_registry) : undefined,
registryRepository: row.registry_repository ? String(row.registry_repository) : undefined,
registryImageTag: row.registry_image_tag ? String(row.registry_image_tag) : undefined,
autoUpdateOnPush: row.auto_update_on_push ? Boolean(row.auto_update_on_push) : undefined,
imageDigest: row.image_digest ? String(row.image_digest) : undefined,
platformRequirements,
};
}
}