@kici-dev/shared 0.0.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +1 -6
- package/dist/chunk-gOLHoazu.js +4 -0
- package/dist/cold-store/bucket.d.ts +26 -0
- package/dist/cold-store/bucket.js +40 -0
- package/dist/cold-store/bucket.test.d.ts +2 -0
- package/dist/cold-store/chunk-encoder.d.ts +63 -0
- package/dist/cold-store/chunk-encoder.js +94 -0
- package/dist/cold-store/chunk-encoder.test.d.ts +2 -0
- package/dist/cold-store/chunk-id.d.ts +10 -0
- package/dist/cold-store/chunk-id.js +29 -0
- package/dist/cold-store/chunk-id.test.d.ts +2 -0
- package/dist/cold-store/cold-store.d.ts +345 -0
- package/dist/cold-store/cold-store.js +1078 -0
- package/dist/cold-store/cold-store.test.d.ts +2 -0
- package/dist/cold-store/config.d.ts +62 -0
- package/dist/cold-store/config.js +28 -0
- package/dist/cold-store/index.d.ts +20 -0
- package/dist/cold-store/index.js +11 -0
- package/dist/cold-store/key.d.ts +89 -0
- package/dist/cold-store/key.js +88 -0
- package/dist/cold-store/key.test.d.ts +2 -0
- package/dist/cold-store/lru.d.ts +33 -0
- package/dist/cold-store/lru.js +59 -0
- package/dist/cold-store/lru.test.d.ts +2 -0
- package/dist/cold-store/manifest.d.ts +11 -0
- package/dist/cold-store/manifest.js +57 -0
- package/dist/cold-store/manifest.test.d.ts +2 -0
- package/dist/cold-store/metrics.d.ts +103 -0
- package/dist/cold-store/metrics.js +179 -0
- package/dist/cold-store/table-adapter.d.ts +229 -0
- package/dist/cold-store/table-adapter.js +2 -0
- package/dist/cold-store/types.d.ts +111 -0
- package/dist/cold-store/types.js +2 -0
- package/dist/crypto.d.ts +33 -0
- package/dist/crypto.js +67 -0
- package/dist/db-admin.d.ts +1422 -0
- package/dist/db-admin.js +2525 -0
- package/dist/db-admin.test.d.ts +2 -0
- package/dist/db.d.ts +14 -0
- package/dist/db.js +23 -0
- package/dist/env/allowlist.d.ts +79 -0
- package/dist/env/allowlist.js +86 -0
- package/dist/env/define-env.d.ts +172 -0
- package/dist/env/define-env.js +295 -0
- package/dist/env/define-env.test.d.ts +2 -0
- package/dist/env/env-rule-allowlist.test.d.ts +2 -0
- package/dist/env/index.d.ts +11 -0
- package/dist/env/index.js +4 -0
- package/dist/env/logger-env.d.ts +30 -0
- package/dist/env/logger-env.js +95 -0
- package/dist/error.d.ts +16 -0
- package/dist/error.js +58 -0
- package/dist/error.test.d.ts +2 -0
- package/dist/format-bytes.d.ts +5 -0
- package/dist/format-bytes.js +15 -0
- package/dist/format-bytes.test.d.ts +2 -0
- package/dist/format-duration.d.ts +11 -0
- package/dist/format-duration.js +32 -0
- package/dist/format-duration.test.d.ts +2 -0
- package/dist/graceful-shutdown.d.ts +58 -0
- package/dist/graceful-shutdown.js +71 -0
- package/dist/graceful-shutdown.test.d.ts +2 -0
- package/dist/idempotency-files.d.ts +113 -0
- package/dist/idempotency-files.js +190 -0
- package/dist/idempotency-files.test.d.ts +2 -0
- package/dist/idempotency.d.ts +68 -0
- package/dist/idempotency.js +49 -0
- package/dist/idempotency.test.d.ts +2 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +31 -0
- package/dist/logger.d.ts +57 -0
- package/dist/logger.js +175 -0
- package/dist/logger.test.d.ts +2 -0
- package/dist/reconnect-delay.d.ts +11 -0
- package/dist/reconnect-delay.js +22 -0
- package/dist/request-context.d.ts +42 -0
- package/dist/request-context.js +37 -0
- package/dist/ring-buffer.d.ts +35 -0
- package/dist/ring-buffer.js +62 -0
- package/dist/ring-buffer.test.d.ts +2 -0
- package/dist/routes/health.d.ts +26 -0
- package/dist/routes/health.js +45 -0
- package/dist/routes/health.test.d.ts +2 -0
- package/dist/routes/metrics.d.ts +20 -0
- package/dist/routes/metrics.js +38 -0
- package/dist/s3-client.d.ts +42 -0
- package/dist/s3-client.js +25 -0
- package/dist/telemetry/index.d.ts +3 -0
- package/dist/telemetry/index.js +4 -0
- package/dist/telemetry/init.d.ts +20 -0
- package/dist/telemetry/init.js +42 -0
- package/dist/telemetry/init.test.d.ts +2 -0
- package/dist/telemetry/metrics.d.ts +8 -0
- package/dist/telemetry/metrics.js +16 -0
- package/dist/tool-check.d.ts +33 -0
- package/dist/tool-check.js +60 -0
- package/dist/tool-check.test.d.ts +2 -0
- package/dist/ts-loader-hook.d.ts +26 -0
- package/dist/ts-loader-hook.js +48 -0
- package/dist/zx.d.ts +8 -0
- package/dist/zx.js +78 -0
- package/package.json +69 -5
- package/sbom.spdx.json +8775 -0
- package/index.js +0 -3
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
+
/** Trace context fields propagated through the request lifecycle. */
|
|
3
|
+
export interface RequestContext {
|
|
4
|
+
/** Unique trace ID for a webhook event (UUIDv4). Always present once set. */
|
|
5
|
+
requestId: string;
|
|
6
|
+
/** Workflow run ID, set when a workflow run is created. */
|
|
7
|
+
runId?: string;
|
|
8
|
+
/** Job ID, set when processing a specific job. */
|
|
9
|
+
jobId?: string;
|
|
10
|
+
/** Routing key (e.g. "github:12345"), set when handling a webhook for a source. */
|
|
11
|
+
routingKey?: string;
|
|
12
|
+
/** OTel trace ID, set when telemetry is active. */
|
|
13
|
+
traceId?: string;
|
|
14
|
+
/** OTel span ID, set when telemetry is active. */
|
|
15
|
+
spanId?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* AsyncLocalStorage instance for propagating request context
|
|
19
|
+
* through async call chains without explicit parameter passing.
|
|
20
|
+
*
|
|
21
|
+
* Usage:
|
|
22
|
+
* ```ts
|
|
23
|
+
* requestContext.run({ requestId: crypto.randomUUID() }, async () => {
|
|
24
|
+
* // All code in this callback (and its async descendants) can read the context
|
|
25
|
+
* log.info('Processing webhook'); // auto-enriched with requestId
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare const requestContext: AsyncLocalStorage<RequestContext>;
|
|
30
|
+
/**
|
|
31
|
+
* Get the current request context, or an empty object if outside a `run()` scope.
|
|
32
|
+
* Safe to call anywhere -- never throws.
|
|
33
|
+
*/
|
|
34
|
+
export declare function getRequestContext(): Partial<RequestContext>;
|
|
35
|
+
/**
|
|
36
|
+
* Merge additional fields into the current request context.
|
|
37
|
+
* No-op if called outside a `run()` scope.
|
|
38
|
+
*
|
|
39
|
+
* @param fields - Partial context fields to merge into the current store
|
|
40
|
+
*/
|
|
41
|
+
export declare function enrichRequestContext(fields: Partial<RequestContext>): void;
|
|
42
|
+
//# sourceMappingURL=request-context.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import "./chunk-gOLHoazu.js";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
//#region src/request-context.ts
|
|
4
|
+
/**
|
|
5
|
+
* AsyncLocalStorage instance for propagating request context
|
|
6
|
+
* through async call chains without explicit parameter passing.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```ts
|
|
10
|
+
* requestContext.run({ requestId: crypto.randomUUID() }, async () => {
|
|
11
|
+
* // All code in this callback (and its async descendants) can read the context
|
|
12
|
+
* log.info('Processing webhook'); // auto-enriched with requestId
|
|
13
|
+
* });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
const requestContext = new AsyncLocalStorage();
|
|
17
|
+
/**
|
|
18
|
+
* Get the current request context, or an empty object if outside a `run()` scope.
|
|
19
|
+
* Safe to call anywhere -- never throws.
|
|
20
|
+
*/
|
|
21
|
+
function getRequestContext() {
|
|
22
|
+
return requestContext.getStore() ?? {};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Merge additional fields into the current request context.
|
|
26
|
+
* No-op if called outside a `run()` scope.
|
|
27
|
+
*
|
|
28
|
+
* @param fields - Partial context fields to merge into the current store
|
|
29
|
+
*/
|
|
30
|
+
function enrichRequestContext(fields) {
|
|
31
|
+
const store = requestContext.getStore();
|
|
32
|
+
if (store) Object.assign(store, fields);
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { enrichRequestContext, getRequestContext, requestContext };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=request-context.js.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic ring buffer with a configurable maximum size.
|
|
3
|
+
*
|
|
4
|
+
* When the buffer reaches its maximum size, adding a new item drops the oldest
|
|
5
|
+
* item (FIFO overflow). This prevents unbounded memory growth for buffered
|
|
6
|
+
* messages or log lines during temporary disconnections.
|
|
7
|
+
*/
|
|
8
|
+
export declare class RingBuffer<T> {
|
|
9
|
+
private buffer;
|
|
10
|
+
private readonly maxSize;
|
|
11
|
+
private _droppedCount;
|
|
12
|
+
constructor(options?: {
|
|
13
|
+
maxSize?: number;
|
|
14
|
+
});
|
|
15
|
+
/**
|
|
16
|
+
* Add an item to the buffer.
|
|
17
|
+
* Returns true if the item was added normally, false if the oldest item
|
|
18
|
+
* was dropped to make room (ring buffer overflow).
|
|
19
|
+
*/
|
|
20
|
+
add(item: T): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Flush all buffered items in insertion order, clearing the buffer.
|
|
23
|
+
* Does NOT reset droppedCount -- caller must explicitly call resetDroppedCount() after processing.
|
|
24
|
+
*/
|
|
25
|
+
flush(): T[];
|
|
26
|
+
/** Current number of buffered items. */
|
|
27
|
+
size(): number;
|
|
28
|
+
/** Number of items dropped due to overflow since last reset. */
|
|
29
|
+
get droppedCount(): number;
|
|
30
|
+
/** Reset the dropped count to 0. Call after processing overflow metrics. */
|
|
31
|
+
resetDroppedCount(): void;
|
|
32
|
+
/** Clear all buffered items without returning them. Also resets droppedCount. */
|
|
33
|
+
clear(): void;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=ring-buffer.d.ts.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import "./chunk-gOLHoazu.js";
|
|
2
|
+
//#region src/ring-buffer.ts
|
|
3
|
+
/**
|
|
4
|
+
* Generic ring buffer with a configurable maximum size.
|
|
5
|
+
*
|
|
6
|
+
* When the buffer reaches its maximum size, adding a new item drops the oldest
|
|
7
|
+
* item (FIFO overflow). This prevents unbounded memory growth for buffered
|
|
8
|
+
* messages or log lines during temporary disconnections.
|
|
9
|
+
*/
|
|
10
|
+
var RingBuffer = class {
|
|
11
|
+
buffer = [];
|
|
12
|
+
maxSize;
|
|
13
|
+
_droppedCount = 0;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.maxSize = options?.maxSize ?? 1e4;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Add an item to the buffer.
|
|
19
|
+
* Returns true if the item was added normally, false if the oldest item
|
|
20
|
+
* was dropped to make room (ring buffer overflow).
|
|
21
|
+
*/
|
|
22
|
+
add(item) {
|
|
23
|
+
if (this.buffer.length >= this.maxSize) {
|
|
24
|
+
this.buffer.shift();
|
|
25
|
+
this.buffer.push(item);
|
|
26
|
+
this._droppedCount++;
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
this.buffer.push(item);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Flush all buffered items in insertion order, clearing the buffer.
|
|
34
|
+
* Does NOT reset droppedCount -- caller must explicitly call resetDroppedCount() after processing.
|
|
35
|
+
*/
|
|
36
|
+
flush() {
|
|
37
|
+
const items = this.buffer;
|
|
38
|
+
this.buffer = [];
|
|
39
|
+
return items;
|
|
40
|
+
}
|
|
41
|
+
/** Current number of buffered items. */
|
|
42
|
+
size() {
|
|
43
|
+
return this.buffer.length;
|
|
44
|
+
}
|
|
45
|
+
/** Number of items dropped due to overflow since last reset. */
|
|
46
|
+
get droppedCount() {
|
|
47
|
+
return this._droppedCount;
|
|
48
|
+
}
|
|
49
|
+
/** Reset the dropped count to 0. Call after processing overflow metrics. */
|
|
50
|
+
resetDroppedCount() {
|
|
51
|
+
this._droppedCount = 0;
|
|
52
|
+
}
|
|
53
|
+
/** Clear all buffered items without returning them. Also resets droppedCount. */
|
|
54
|
+
clear() {
|
|
55
|
+
this.buffer = [];
|
|
56
|
+
this._droppedCount = 0;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
//#endregion
|
|
60
|
+
export { RingBuffer };
|
|
61
|
+
|
|
62
|
+
//# sourceMappingURL=ring-buffer.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
export interface HealthRoutesDeps {
|
|
3
|
+
/**
|
|
4
|
+
* Optional extra fields to include in the liveness response.
|
|
5
|
+
* Called on every `/health` request.
|
|
6
|
+
*/
|
|
7
|
+
livenessInfo?: () => Record<string, unknown>;
|
|
8
|
+
/**
|
|
9
|
+
* Optional readiness checks. Each key is a check name, each value
|
|
10
|
+
* indicates whether that check passed.
|
|
11
|
+
* Called on every `/ready` request.
|
|
12
|
+
* If omitted, the service is always considered ready.
|
|
13
|
+
*/
|
|
14
|
+
readinessCheck?: () => Promise<Record<string, boolean>>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Create health and readiness routes.
|
|
18
|
+
*
|
|
19
|
+
* - GET /health - Liveness probe (always 200)
|
|
20
|
+
* - GET /ready - Readiness probe (200 if all checks pass, 503 if any fail)
|
|
21
|
+
*
|
|
22
|
+
* @param deps - Optional liveness info provider and readiness check function
|
|
23
|
+
* @returns Hono app with /health and /ready endpoints
|
|
24
|
+
*/
|
|
25
|
+
export declare function createHealthRoutes(deps?: HealthRoutesDeps): Hono;
|
|
26
|
+
//# sourceMappingURL=health.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
//#region src/routes/health.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create health and readiness routes.
|
|
6
|
+
*
|
|
7
|
+
* - GET /health - Liveness probe (always 200)
|
|
8
|
+
* - GET /ready - Readiness probe (200 if all checks pass, 503 if any fail)
|
|
9
|
+
*
|
|
10
|
+
* @param deps - Optional liveness info provider and readiness check function
|
|
11
|
+
* @returns Hono app with /health and /ready endpoints
|
|
12
|
+
*/
|
|
13
|
+
function createHealthRoutes(deps = {}) {
|
|
14
|
+
const app = new Hono();
|
|
15
|
+
/**
|
|
16
|
+
* Liveness probe - always returns 200.
|
|
17
|
+
* Includes timestamp, uptime, and any extra info from livenessInfo().
|
|
18
|
+
*/
|
|
19
|
+
app.get("/health", (c) => {
|
|
20
|
+
const extra = deps.livenessInfo?.() ?? {};
|
|
21
|
+
return c.json({
|
|
22
|
+
status: "ok",
|
|
23
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
24
|
+
uptime: process.uptime(),
|
|
25
|
+
...extra
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
/**
|
|
29
|
+
* Readiness probe - returns 200 when all checks pass, 503 otherwise.
|
|
30
|
+
* If no readiness check is provided, always returns 200.
|
|
31
|
+
*/
|
|
32
|
+
app.get("/ready", async (c) => {
|
|
33
|
+
const checks = deps.readinessCheck ? await deps.readinessCheck() : {};
|
|
34
|
+
const ready = Object.values(checks).every((v) => v);
|
|
35
|
+
return c.json({
|
|
36
|
+
status: ready ? "ready" : "not ready",
|
|
37
|
+
checks
|
|
38
|
+
}, ready ? 200 : 503);
|
|
39
|
+
});
|
|
40
|
+
return app;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { createHealthRoutes };
|
|
44
|
+
|
|
45
|
+
//# sourceMappingURL=health.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Hono } from 'hono';
|
|
2
|
+
export interface MetricsRoutesDeps {
|
|
3
|
+
/** Callback that returns the Prometheus metrics response. */
|
|
4
|
+
getMetrics: () => Promise<{
|
|
5
|
+
contentType: string;
|
|
6
|
+
body: string;
|
|
7
|
+
}>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create Prometheus metrics route.
|
|
11
|
+
*
|
|
12
|
+
* The caller provides a getMetrics callback that returns the content type
|
|
13
|
+
* and body. This decouples the route from any specific metrics library
|
|
14
|
+
* (prom-client, OTel PrometheusExporter, etc.).
|
|
15
|
+
*
|
|
16
|
+
* @param deps - Dependencies (metrics callback)
|
|
17
|
+
* @returns Hono app with /metrics endpoint
|
|
18
|
+
*/
|
|
19
|
+
export declare function createMetricsRoutes(deps: MetricsRoutesDeps): Hono;
|
|
20
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { Hono } from "hono";
|
|
3
|
+
//#region src/routes/metrics.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create Prometheus metrics route.
|
|
6
|
+
*
|
|
7
|
+
* The caller provides a getMetrics callback that returns the content type
|
|
8
|
+
* and body. This decouples the route from any specific metrics library
|
|
9
|
+
* (prom-client, OTel PrometheusExporter, etc.).
|
|
10
|
+
*
|
|
11
|
+
* @param deps - Dependencies (metrics callback)
|
|
12
|
+
* @returns Hono app with /metrics endpoint
|
|
13
|
+
*/
|
|
14
|
+
function createMetricsRoutes(deps) {
|
|
15
|
+
const app = new Hono();
|
|
16
|
+
app.get("/metrics", async (c) => {
|
|
17
|
+
const { contentType, body } = await deps.getMetrics();
|
|
18
|
+
const filteredBody = body.split("\n").filter((line) => !line.startsWith("# UNIT ") && line !== "# EOF").map((line) => {
|
|
19
|
+
if (line.startsWith("# TYPE ") || line.startsWith("# HELP ")) {
|
|
20
|
+
const prefix = line.startsWith("# TYPE ") ? "# TYPE " : "# HELP ";
|
|
21
|
+
const rest = line.slice(prefix.length);
|
|
22
|
+
const spaceIdx = rest.indexOf(" ");
|
|
23
|
+
if (spaceIdx > 0) return prefix + rest.slice(0, spaceIdx).replace(/\./g, "_") + rest.slice(spaceIdx);
|
|
24
|
+
} else if (line && !line.startsWith("#")) {
|
|
25
|
+
const match = line.match(/^([a-zA-Z_:.][a-zA-Z0-9_:.]*)/);
|
|
26
|
+
if (match && match[1].includes(".")) return line.replace(match[1], match[1].replace(/\./g, "_"));
|
|
27
|
+
}
|
|
28
|
+
return line;
|
|
29
|
+
}).join("\n");
|
|
30
|
+
const safeContentType = contentType.includes("openmetrics") ? "text/plain; version=0.0.4; charset=utf-8" : contentType;
|
|
31
|
+
return c.text(filteredBody, 200, { "Content-Type": safeContentType });
|
|
32
|
+
});
|
|
33
|
+
return app;
|
|
34
|
+
}
|
|
35
|
+
//#endregion
|
|
36
|
+
export { createMetricsRoutes };
|
|
37
|
+
|
|
38
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared S3 client construction helper.
|
|
3
|
+
*
|
|
4
|
+
* Avoids duplicating the region/endpoint/forcePathStyle config pattern
|
|
5
|
+
* across S3LogStorage, S3CacheStorage, the cold-store framework, and any
|
|
6
|
+
* future S3 consumers.
|
|
7
|
+
*
|
|
8
|
+
* The exported `SharedS3Config` is the generic, TTL-free base config —
|
|
9
|
+
* domain-specific consumers extend it (e.g., adding `ttlMs` + discriminant
|
|
10
|
+
* for cache-storage variants).
|
|
11
|
+
*/
|
|
12
|
+
import { S3Client } from '@aws-sdk/client-s3';
|
|
13
|
+
/**
|
|
14
|
+
* Generic S3-compatible configuration shared across KiCI consumers.
|
|
15
|
+
*
|
|
16
|
+
* Callers layer domain-specific fields on top (e.g. orchestrator's
|
|
17
|
+
* CacheStorageConfig adds `ttlMs`, cold-store's ColdStoreConfig adds
|
|
18
|
+
* table-level tuning).
|
|
19
|
+
*/
|
|
20
|
+
export interface SharedS3Config {
|
|
21
|
+
bucket: string;
|
|
22
|
+
prefix: string;
|
|
23
|
+
region?: string;
|
|
24
|
+
/** Custom endpoint URL for S3-compatible services (e.g., SeaweedFS, LocalStack) */
|
|
25
|
+
endpoint?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Separate endpoint for pre-signed URLs (upload and download).
|
|
28
|
+
* When set, pre-signed URLs use this endpoint instead of `endpoint`.
|
|
29
|
+
* Useful when the server accesses S3 internally but clients need a
|
|
30
|
+
* different address (e.g., container-routable DNS name).
|
|
31
|
+
*/
|
|
32
|
+
externalEndpoint?: string;
|
|
33
|
+
/** Use path-style access (required for most S3-compatible services). Default: false */
|
|
34
|
+
forcePathStyle?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface CreateS3ClientOptions {
|
|
37
|
+
region?: string;
|
|
38
|
+
endpoint?: string;
|
|
39
|
+
forcePathStyle?: boolean;
|
|
40
|
+
}
|
|
41
|
+
export declare function createS3Client(options: CreateS3ClientOptions): S3Client;
|
|
42
|
+
//# sourceMappingURL=s3-client.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import "./chunk-gOLHoazu.js";
|
|
2
|
+
import { S3Client } from "@aws-sdk/client-s3";
|
|
3
|
+
//#region src/s3-client.ts
|
|
4
|
+
/**
|
|
5
|
+
* Shared S3 client construction helper.
|
|
6
|
+
*
|
|
7
|
+
* Avoids duplicating the region/endpoint/forcePathStyle config pattern
|
|
8
|
+
* across S3LogStorage, S3CacheStorage, the cold-store framework, and any
|
|
9
|
+
* future S3 consumers.
|
|
10
|
+
*
|
|
11
|
+
* The exported `SharedS3Config` is the generic, TTL-free base config —
|
|
12
|
+
* domain-specific consumers extend it (e.g., adding `ttlMs` + discriminant
|
|
13
|
+
* for cache-storage variants).
|
|
14
|
+
*/
|
|
15
|
+
function createS3Client(options) {
|
|
16
|
+
const config = {};
|
|
17
|
+
if (options.region) config.region = options.region;
|
|
18
|
+
if (options.endpoint) config.endpoint = options.endpoint;
|
|
19
|
+
if (options.forcePathStyle !== void 0) config.forcePathStyle = options.forcePathStyle;
|
|
20
|
+
return new S3Client(config);
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
export { createS3Client };
|
|
24
|
+
|
|
25
|
+
//# sourceMappingURL=s3-client.js.map
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
2
|
+
import { PrometheusExporter } from '@opentelemetry/exporter-prometheus';
|
|
3
|
+
export interface TelemetryConfig {
|
|
4
|
+
serviceName: string;
|
|
5
|
+
serviceVersion?: string;
|
|
6
|
+
/** OTLP endpoint URL. If not set, OTLP trace export is disabled. */
|
|
7
|
+
otlpEndpoint?: string;
|
|
8
|
+
/** Metric prefix to match existing prom-client metrics (e.g., 'kici_', 'kici_orch_') */
|
|
9
|
+
metricPrefix?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Initialize the OpenTelemetry SDK with Prometheus metrics and optional OTLP trace export.
|
|
13
|
+
*
|
|
14
|
+
* Call once at service startup. The Prometheus exporter is configured with
|
|
15
|
+
* preventServerStart: true -- metrics are served via the existing /metrics route.
|
|
16
|
+
*/
|
|
17
|
+
export declare function initTelemetry(config: TelemetryConfig): NodeSDK;
|
|
18
|
+
/** Get the PrometheusExporter instance created by initTelemetry(). */
|
|
19
|
+
export declare function getPrometheusExporter(): PrometheusExporter | undefined;
|
|
20
|
+
//# sourceMappingURL=init.d.ts.map
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { NodeSDK } from "@opentelemetry/sdk-node";
|
|
3
|
+
import { PrometheusExporter } from "@opentelemetry/exporter-prometheus";
|
|
4
|
+
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
5
|
+
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
6
|
+
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from "@opentelemetry/semantic-conventions";
|
|
7
|
+
import { RuntimeNodeInstrumentation } from "@opentelemetry/instrumentation-runtime-node";
|
|
8
|
+
//#region src/telemetry/init.ts
|
|
9
|
+
let _prometheusExporter;
|
|
10
|
+
/**
|
|
11
|
+
* Initialize the OpenTelemetry SDK with Prometheus metrics and optional OTLP trace export.
|
|
12
|
+
*
|
|
13
|
+
* Call once at service startup. The Prometheus exporter is configured with
|
|
14
|
+
* preventServerStart: true -- metrics are served via the existing /metrics route.
|
|
15
|
+
*/
|
|
16
|
+
function initTelemetry(config) {
|
|
17
|
+
const resource = resourceFromAttributes({
|
|
18
|
+
[ATTR_SERVICE_NAME]: config.serviceName,
|
|
19
|
+
[ATTR_SERVICE_VERSION]: config.serviceVersion ?? "0.0.0"
|
|
20
|
+
});
|
|
21
|
+
const prometheusExporter = new PrometheusExporter({
|
|
22
|
+
preventServerStart: true,
|
|
23
|
+
prefix: config.metricPrefix
|
|
24
|
+
});
|
|
25
|
+
_prometheusExporter = prometheusExporter;
|
|
26
|
+
const sdk = new NodeSDK({
|
|
27
|
+
resource,
|
|
28
|
+
metricReader: prometheusExporter,
|
|
29
|
+
traceExporter: config.otlpEndpoint ? new OTLPTraceExporter({ url: `${config.otlpEndpoint}/v1/traces` }) : void 0,
|
|
30
|
+
instrumentations: [new RuntimeNodeInstrumentation()]
|
|
31
|
+
});
|
|
32
|
+
sdk.start();
|
|
33
|
+
return sdk;
|
|
34
|
+
}
|
|
35
|
+
/** Get the PrometheusExporter instance created by initTelemetry(). */
|
|
36
|
+
function getPrometheusExporter() {
|
|
37
|
+
return _prometheusExporter;
|
|
38
|
+
}
|
|
39
|
+
//#endregion
|
|
40
|
+
export { getPrometheusExporter, initTelemetry };
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create an OTel Meter for a given service.
|
|
3
|
+
*
|
|
4
|
+
* @param serviceName - Name of the service (e.g., 'orchestrator')
|
|
5
|
+
* @returns An OTel Meter instance for creating instruments
|
|
6
|
+
*/
|
|
7
|
+
export declare function createMeter(serviceName: string): import("@opentelemetry/api").Meter;
|
|
8
|
+
//# sourceMappingURL=metrics.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import "../chunk-gOLHoazu.js";
|
|
2
|
+
import { metrics } from "@opentelemetry/api";
|
|
3
|
+
//#region src/telemetry/metrics.ts
|
|
4
|
+
/**
|
|
5
|
+
* Create an OTel Meter for a given service.
|
|
6
|
+
*
|
|
7
|
+
* @param serviceName - Name of the service (e.g., 'orchestrator')
|
|
8
|
+
* @returns An OTel Meter instance for creating instruments
|
|
9
|
+
*/
|
|
10
|
+
function createMeter(serviceName) {
|
|
11
|
+
return metrics.getMeter(serviceName);
|
|
12
|
+
}
|
|
13
|
+
//#endregion
|
|
14
|
+
export { createMeter };
|
|
15
|
+
|
|
16
|
+
//# sourceMappingURL=metrics.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup validation for required external tools and binaries.
|
|
3
|
+
*
|
|
4
|
+
* Used by the orchestrator (scaler backends) and agent to verify that all
|
|
5
|
+
* required system tools are available before accepting work. Missing tools
|
|
6
|
+
* cause a clear fatal error at startup rather than cryptic runtime failures.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* A single tool requirement declaration.
|
|
10
|
+
*
|
|
11
|
+
* - `path-binary`: a binary that must be found on PATH (e.g., 'git', 'ip', 'bash')
|
|
12
|
+
* - `file-access`: an absolute path that must exist with the specified access mode
|
|
13
|
+
*/
|
|
14
|
+
export type ToolRequirement = {
|
|
15
|
+
type: 'path-binary';
|
|
16
|
+
name: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'file-access';
|
|
20
|
+
path: string;
|
|
21
|
+
mode: 'executable' | 'readable';
|
|
22
|
+
reason: string;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Validate a list of tool requirements.
|
|
26
|
+
*
|
|
27
|
+
* Deduplicates requirements, checks each one, and returns ALL errors
|
|
28
|
+
* (not fail-on-first) so the operator sees every missing tool at once.
|
|
29
|
+
*
|
|
30
|
+
* @returns Array of error messages. Empty array means all tools are available.
|
|
31
|
+
*/
|
|
32
|
+
export declare function validateRequiredTools(requirements: ToolRequirement[]): string[];
|
|
33
|
+
//# sourceMappingURL=tool-check.d.ts.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import "./chunk-gOLHoazu.js";
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { accessSync, constants } from "node:fs";
|
|
4
|
+
//#region src/tool-check.ts
|
|
5
|
+
/**
|
|
6
|
+
* Startup validation for required external tools and binaries.
|
|
7
|
+
*
|
|
8
|
+
* Used by the orchestrator (scaler backends) and agent to verify that all
|
|
9
|
+
* required system tools are available before accepting work. Missing tools
|
|
10
|
+
* cause a clear fatal error at startup rather than cryptic runtime failures.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Validate a list of tool requirements.
|
|
14
|
+
*
|
|
15
|
+
* Deduplicates requirements, checks each one, and returns ALL errors
|
|
16
|
+
* (not fail-on-first) so the operator sees every missing tool at once.
|
|
17
|
+
*
|
|
18
|
+
* @returns Array of error messages. Empty array means all tools are available.
|
|
19
|
+
*/
|
|
20
|
+
function validateRequiredTools(requirements) {
|
|
21
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22
|
+
const errors = [];
|
|
23
|
+
for (const req of requirements) {
|
|
24
|
+
const key = req.type === "path-binary" ? `path:${req.name}` : `file:${req.path}`;
|
|
25
|
+
if (seen.has(key)) continue;
|
|
26
|
+
seen.add(key);
|
|
27
|
+
if (req.type === "path-binary") {
|
|
28
|
+
if (!isBinaryOnPath(req.name)) errors.push(`'${req.name}' not found on PATH — ${req.reason}`);
|
|
29
|
+
} else {
|
|
30
|
+
const mode = req.mode === "executable" ? constants.X_OK : constants.R_OK;
|
|
31
|
+
try {
|
|
32
|
+
accessSync(req.path, mode);
|
|
33
|
+
} catch {
|
|
34
|
+
const modeLabel = req.mode === "executable" ? "executable" : "readable";
|
|
35
|
+
errors.push(`'${req.path}' not ${modeLabel} — ${req.reason}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return errors;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Check if a binary is available on PATH.
|
|
43
|
+
* Uses `where` on Windows, `which` on Unix.
|
|
44
|
+
*/
|
|
45
|
+
function isBinaryOnPath(name) {
|
|
46
|
+
const cmd = process.platform === "win32" ? "where" : "which";
|
|
47
|
+
try {
|
|
48
|
+
execFileSync(cmd, [name], {
|
|
49
|
+
stdio: "pipe",
|
|
50
|
+
timeout: 5e3
|
|
51
|
+
});
|
|
52
|
+
return true;
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { validateRequiredTools };
|
|
59
|
+
|
|
60
|
+
//# sourceMappingURL=tool-check.js.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
type ResolveContext = {
|
|
2
|
+
parentURL?: string;
|
|
3
|
+
conditions: string[];
|
|
4
|
+
importAttributes: Record<string, string>;
|
|
5
|
+
};
|
|
6
|
+
type ResolveResult = {
|
|
7
|
+
url: string;
|
|
8
|
+
shortCircuit?: boolean;
|
|
9
|
+
format?: string | null;
|
|
10
|
+
};
|
|
11
|
+
type NextResolve = (specifier: string, context?: ResolveContext) => ResolveResult | Promise<ResolveResult>;
|
|
12
|
+
type LoadContext = {
|
|
13
|
+
format?: string | null;
|
|
14
|
+
importAttributes: Record<string, string>;
|
|
15
|
+
conditions: string[];
|
|
16
|
+
};
|
|
17
|
+
type LoadResult = {
|
|
18
|
+
format: string;
|
|
19
|
+
source?: string | ArrayBuffer | Uint8Array;
|
|
20
|
+
shortCircuit?: boolean;
|
|
21
|
+
};
|
|
22
|
+
type NextLoad = (url: string, context?: LoadContext) => LoadResult | Promise<LoadResult>;
|
|
23
|
+
export declare function resolve(specifier: string, context: ResolveContext, nextResolve: NextResolve): ResolveResult | Promise<ResolveResult>;
|
|
24
|
+
export declare function load(url: string, context: LoadContext, nextLoad: NextLoad): Promise<LoadResult>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=ts-loader-hook.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import "./chunk-gOLHoazu.js";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { transformSync } from "oxc-transform";
|
|
6
|
+
//#region src/ts-loader-hook.ts
|
|
7
|
+
function resolve(specifier, context, nextResolve) {
|
|
8
|
+
if (specifier.endsWith(".js") && (specifier.startsWith("./") || specifier.startsWith("../"))) try {
|
|
9
|
+
if (context.parentURL) {
|
|
10
|
+
if (!existsSync(fileURLToPath(new URL(specifier, context.parentURL)))) {
|
|
11
|
+
const tsSpecifier = specifier.slice(0, -3) + ".ts";
|
|
12
|
+
if (existsSync(fileURLToPath(new URL(tsSpecifier, context.parentURL)))) return nextResolve(tsSpecifier, context);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
} catch {}
|
|
16
|
+
return nextResolve(specifier, context);
|
|
17
|
+
}
|
|
18
|
+
async function load(url, context, nextLoad) {
|
|
19
|
+
if (!url.startsWith("file:")) return nextLoad(url, context);
|
|
20
|
+
const bareUrl = url.split("?")[0].split("#")[0];
|
|
21
|
+
const isTs = bareUrl.endsWith(".ts");
|
|
22
|
+
const isTsx = bareUrl.endsWith(".tsx");
|
|
23
|
+
if (!isTs && !isTsx) return nextLoad(url, context);
|
|
24
|
+
const filePath = fileURLToPath(bareUrl);
|
|
25
|
+
const result = transformSync(filePath, await readFile(filePath, "utf8"), {
|
|
26
|
+
lang: isTsx ? "tsx" : "ts",
|
|
27
|
+
sourcemap: true,
|
|
28
|
+
typescript: { allowNamespaces: true }
|
|
29
|
+
});
|
|
30
|
+
if (result.errors.length) {
|
|
31
|
+
const msg = result.errors.map((e) => e.message).join("\n");
|
|
32
|
+
throw new Error(`oxc-transform failed for ${filePath}:\n${msg}`);
|
|
33
|
+
}
|
|
34
|
+
let code = result.code;
|
|
35
|
+
if (result.map) {
|
|
36
|
+
const b64 = Buffer.from(JSON.stringify(result.map)).toString("base64");
|
|
37
|
+
code += `\n//# sourceMappingURL=data:application/json;base64,${b64}\n`;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
format: "module",
|
|
41
|
+
source: code,
|
|
42
|
+
shortCircuit: true
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
46
|
+
export { load, resolve };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=ts-loader-hook.js.map
|