mirror of
https://github.com/harivansh-afk/betterNAS.git
synced 2026-04-16 00:03:00 +00:00
add control plane service
Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
679fd504a2
commit
57f221fb72
8 changed files with 766 additions and 0 deletions
15
exapps/control-plane/Dockerfile
Normal file
15
exapps/control-plane/Dockerfile
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json package-lock.json tsconfig.base.json ./
|
||||
COPY packages/contracts ./packages/contracts
|
||||
COPY exapps/control-plane ./exapps/control-plane
|
||||
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
|
||||
WORKDIR /app/exapps/control-plane
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
|
||||
21
exapps/control-plane/package.json
Normal file
21
exapps/control-plane/package.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"name": "@ainas/control-plane",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"scripts": {
|
||||
"dev": "tsx watch src/index.ts",
|
||||
"build": "tsc -p tsconfig.json",
|
||||
"start": "node dist/index.js",
|
||||
"typecheck": "tsc --noEmit -p tsconfig.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ainas/contracts": "file:../../packages/contracts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.18.6",
|
||||
"tsx": "^4.20.6",
|
||||
"typescript": "^5.9.3"
|
||||
}
|
||||
}
|
||||
14
exapps/control-plane/src/adapters/nextcloud-backend.ts
Normal file
14
exapps/control-plane/src/adapters/nextcloud-backend.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import type { NextcloudBackendStatus } from "@ainas/contracts";
|
||||
|
||||
export class NextcloudBackendAdapter {
|
||||
constructor(private readonly baseUrl: string) {}
|
||||
|
||||
describe(): NextcloudBackendStatus {
|
||||
return {
|
||||
configured: this.baseUrl.length > 0,
|
||||
baseUrl: this.baseUrl,
|
||||
provider: "nextcloud"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
59
exapps/control-plane/src/app.ts
Normal file
59
exapps/control-plane/src/app.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
|
||||
import {
|
||||
CONTROL_PLANE_ROUTES,
|
||||
type ControlPlaneHealthResponse,
|
||||
type ControlPlaneVersionResponse
|
||||
} from "@ainas/contracts";
|
||||
|
||||
import type { ControlPlaneConfig } from "./config.js";
|
||||
import { NextcloudBackendAdapter } from "./adapters/nextcloud-backend.js";
|
||||
|
||||
export function createApp(config: ControlPlaneConfig) {
|
||||
const startedAt = Date.now();
|
||||
const nextcloudBackend = new NextcloudBackendAdapter(config.nextcloudBaseUrl);
|
||||
|
||||
return createServer((request, response) => {
|
||||
if (request.method !== "GET" || !request.url) {
|
||||
writeJson(response, 405, { error: "Method not allowed" });
|
||||
return;
|
||||
}
|
||||
|
||||
const url = new URL(request.url, "http://localhost");
|
||||
|
||||
if (url.pathname === CONTROL_PLANE_ROUTES.health) {
|
||||
const payload: ControlPlaneHealthResponse = {
|
||||
service: "control-plane",
|
||||
status: "ok",
|
||||
timestamp: new Date().toISOString(),
|
||||
uptimeSeconds: Math.floor((Date.now() - startedAt) / 1000),
|
||||
nextcloud: nextcloudBackend.describe()
|
||||
};
|
||||
|
||||
writeJson(response, 200, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.pathname === CONTROL_PLANE_ROUTES.version) {
|
||||
const payload: ControlPlaneVersionResponse = {
|
||||
service: "control-plane",
|
||||
version: config.version,
|
||||
apiVersion: "v1"
|
||||
};
|
||||
|
||||
writeJson(response, 200, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
writeJson(response, 404, {
|
||||
error: "Not found"
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function writeJson(response: ServerResponse<IncomingMessage>, statusCode: number, payload: unknown) {
|
||||
response.writeHead(statusCode, {
|
||||
"content-type": "application/json; charset=utf-8"
|
||||
});
|
||||
response.end(JSON.stringify(payload));
|
||||
}
|
||||
|
||||
25
exapps/control-plane/src/config.ts
Normal file
25
exapps/control-plane/src/config.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
export interface ControlPlaneConfig {
|
||||
port: number;
|
||||
version: string;
|
||||
nextcloudBaseUrl: string;
|
||||
}
|
||||
|
||||
export function loadConfig(env: NodeJS.ProcessEnv = process.env): ControlPlaneConfig {
|
||||
const portValue = env.PORT ?? "3000";
|
||||
const port = Number.parseInt(portValue, 10);
|
||||
|
||||
if (Number.isNaN(port)) {
|
||||
throw new Error(`Invalid PORT value: ${portValue}`);
|
||||
}
|
||||
|
||||
return {
|
||||
port,
|
||||
version: env.AINAS_VERSION ?? "0.1.0-dev",
|
||||
nextcloudBaseUrl: normalizeBaseUrl(env.NEXTCLOUD_BASE_URL ?? "http://nextcloud")
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeBaseUrl(url: string): string {
|
||||
return url.replace(/\/+$/, "");
|
||||
}
|
||||
|
||||
10
exapps/control-plane/src/index.ts
Normal file
10
exapps/control-plane/src/index.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { createApp } from "./app.js";
|
||||
import { loadConfig } from "./config.js";
|
||||
|
||||
const config = loadConfig();
|
||||
const app = createApp(config);
|
||||
|
||||
app.listen(config.port, "0.0.0.0", () => {
|
||||
console.log(`aiNAS control plane listening on port ${config.port}`);
|
||||
});
|
||||
|
||||
11
exapps/control-plane/tsconfig.json
Normal file
11
exapps/control-plane/tsconfig.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "src",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue