This commit is contained in:
Morten Olsen
2025-07-28 22:24:51 +02:00
commit b35782a7d8
28 changed files with 3186 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
class ConfigService {
public get postgres() {
const host = process.env.POSTGRES_HOST;
const user = process.env.POSTGRES_USER;
const password = process.env.POSTGRES_PASSWORD;
const port = process.env.POSTGRES_PORT ? parseInt(process.env.POSTGRES_PORT, 10) : 5432;
if (!host || !user || !password) {
throw new Error('POSTGRES_HOST, POSTGRES_USER, and POSTGRES_PASSWORD must be set');
}
return { host, user, password, port };
}
}
export { ConfigService };

34
src/services/k8s.ts Normal file
View File

@@ -0,0 +1,34 @@
import { KubeConfig, CoreV1Api, ApiextensionsV1Api, CustomObjectsApi } from '@kubernetes/client-node';
class K8sService {
#kc: KubeConfig;
#k8sApi: CoreV1Api;
#k8sExtensionsApi: ApiextensionsV1Api;
#k8sCustomObjectsApi: CustomObjectsApi;
constructor() {
this.#kc = new KubeConfig();
this.#kc.loadFromDefault();
this.#k8sApi = this.#kc.makeApiClient(CoreV1Api);
this.#k8sExtensionsApi = this.#kc.makeApiClient(ApiextensionsV1Api);
this.#k8sCustomObjectsApi = this.#kc.makeApiClient(CustomObjectsApi);
}
public get config() {
return this.#kc;
}
public get api() {
return this.#k8sApi;
}
public get extensionsApi() {
return this.#k8sExtensionsApi;
}
public get customObjectsApi() {
return this.#k8sCustomObjectsApi;
}
}
export { K8sService };

19
src/services/log/log.ts Normal file
View File

@@ -0,0 +1,19 @@
class LogService {
public debug = (message: string, data?: Record<string, unknown>) => {
console.debug(message, data);
}
public info = (message: string, data?: Record<string, unknown>) => {
console.info(message, data);
}
public warn = (message: string, data?: Record<string, unknown>) => {
console.warn(message, data);
}
public error = (message: string, data?: Record<string, unknown>) => {
console.error(message, data);
}
}
export { LogService };

View File

@@ -0,0 +1,59 @@
import knex, { type Knex } from "knex";
import type { PostgresDatabase, PostgresRole } from "./postgres.types.ts";
import { Services } from "../../utils/service.ts";
import { ConfigService } from "../config/config.ts";
class PostgresService {
#db: Knex;
constructor(services: Services) {
const configService = services.get(ConfigService);
const config = configService.postgres;
this.#db = knex({
client: 'pg',
connection: {
host: config.host,
user: config.user,
password: config.password,
port: config.port,
},
});
}
public upsertRole = async (role: PostgresRole) => {
const existingRole = await this.#db.raw(
'SELECT 1 FROM pg_roles WHERE rolname = ?',
[role.name]
);
if (existingRole.rows.length === 0) {
await this.#db.raw(
`CREATE ROLE ${role.name} WITH LOGIN PASSWORD '${role.password}'`,
);
} else {
await this.#db.raw(
`ALTER ROLE ${role.name} WITH PASSWORD '${role.password}'`,
);
}
}
public upsertDatabase = async (database: PostgresDatabase) => {
const existingDatabase = await this.#db.raw(
'SELECT * FROM pg_database WHERE datname = ?',
[database.name]
);
if (existingDatabase.rows.length === 0) {
await this.#db.raw(
`CREATE DATABASE ${database.name} OWNER ${database.owner}`,
);
} else {
await this.#db.raw(
`ALTER DATABASE ${database.name} OWNER TO ${database.owner}`,
);
}
}
}
export { PostgresService };

View File

@@ -0,0 +1,11 @@
type PostgresRole = {
name: string;
password: string;
};
type PostgresDatabase = {
name: string;
owner: string;
};
export type { PostgresRole, PostgresDatabase };

View File

@@ -0,0 +1,2 @@
class SecretsService {
}