feat: topology, and improves handling

This commit is contained in:
2026-02-17 18:12:02 +07:00
parent e8dbefde43
commit d14f043e7c
145 changed files with 4213 additions and 2861 deletions

View File

@@ -0,0 +1,23 @@
{
"name": "@minikura/shared",
"version": "1.0.0",
"type": "module",
"exports": {
".": "./src/index.ts",
"./kube-auth": "./src/kube-auth.ts",
"./errors": "./src/errors.ts",
"./logger": "./src/logger.ts",
"./*": "./src/*.ts"
},
"dependencies": {
"@kubernetes/client-node": "^1.4.0",
"pino": "^10.3.1",
"pino-pretty": "^13.1.3",
"undici": "^7.18.2",
"yaml": "^2.7.0"
},
"devDependencies": {
"@types/node": "^25.0.9",
"typescript": "^5.9.3"
}
}

View File

@@ -0,0 +1,28 @@
export function getErrorMessage(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
if (typeof error === "string") {
return error;
}
return String(error);
}
/** Returns age string like "3d", "12h", "5m" */
export function getAge(timestamp: Date | string | undefined): string {
if (!timestamp) return "unknown";
const now = new Date();
const created = new Date(timestamp);
const diff = now.getTime() - created.getTime();
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0) return `${days}d`;
if (hours > 0) return `${hours}h`;
if (minutes > 0) return `${minutes}m`;
return `${seconds}s`;
}

View File

@@ -0,0 +1,3 @@
export * from "./errors";
export * from "./kube-auth";
export * from "./logger";

View File

@@ -0,0 +1,24 @@
import { existsSync } from "node:fs";
import { KubeConfig } from "@kubernetes/client-node";
import { createLogger } from "./logger";
const logger = createLogger("kube-auth");
export function buildKubeConfig(): KubeConfig {
const kc = new KubeConfig();
const isInCluster =
process.env.KUBERNETES_SERVICE_HOST &&
existsSync("/var/run/secrets/kubernetes.io/serviceaccount/token");
if (isInCluster) {
logger.info("Running in-cluster, loading from service account");
kc.loadFromCluster();
} else {
logger.info("Running locally, loading from kubeconfig");
kc.loadFromDefault();
logger.info({ context: kc.getCurrentContext() }, "Using context");
}
return kc;
}

View File

@@ -0,0 +1,33 @@
import pino from "pino";
export function createLogger(component: string): pino.Logger;
export function createLogger(
context: Record<string, string | number>,
): pino.Logger;
export function createLogger(
componentOrContext: string | Record<string, string | number>,
): pino.Logger {
const isString = typeof componentOrContext === "string";
const baseContext = isString
? { component: componentOrContext }
: componentOrContext;
return pino({
level: process.env.LOG_LEVEL || "info",
transport:
process.env.NODE_ENV !== "production"
? {
target: "pino-pretty",
options: {
colorize: true,
translateTime: "HH:MM:ss.l",
ignore: "pid,hostname",
singleLine: false,
},
}
: undefined,
base: baseContext,
});
}
export const logger = createLogger("shared");

View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"allowJs": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}