streamer-node 1.0.0
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/README.md +11 -0
- package/dist/public/client.png +0 -0
- package/dist/public/ds.png +0 -0
- package/dist/src/application/interfaces/Logger.d.ts +7 -0
- package/dist/src/application/interfaces/Logger.d.ts.map +1 -0
- package/dist/src/application/interfaces/Logger.js +3 -0
- package/dist/src/application/interfaces/Logger.js.map +1 -0
- package/dist/src/application/interfaces/StartStreamUseCase.types.d.ts +36 -0
- package/dist/src/application/interfaces/StartStreamUseCase.types.d.ts.map +1 -0
- package/dist/src/application/interfaces/StartStreamUseCase.types.js +12 -0
- package/dist/src/application/interfaces/StartStreamUseCase.types.js.map +1 -0
- package/dist/src/application/services/HttpClient.d.ts +5 -0
- package/dist/src/application/services/HttpClient.d.ts.map +1 -0
- package/dist/src/application/services/HttpClient.js +30 -0
- package/dist/src/application/services/HttpClient.js.map +1 -0
- package/dist/src/application/services/StreamManagerService.d.ts +38 -0
- package/dist/src/application/services/StreamManagerService.d.ts.map +1 -0
- package/dist/src/application/services/StreamManagerService.js +298 -0
- package/dist/src/application/services/StreamManagerService.js.map +1 -0
- package/dist/src/application/use-cases/StartStreamUseCase.d.ts +27 -0
- package/dist/src/application/use-cases/StartStreamUseCase.d.ts.map +1 -0
- package/dist/src/application/use-cases/StartStreamUseCase.js +195 -0
- package/dist/src/application/use-cases/StartStreamUseCase.js.map +1 -0
- package/dist/src/application/use-cases/StopStreamUseCase.d.ts +18 -0
- package/dist/src/application/use-cases/StopStreamUseCase.d.ts.map +1 -0
- package/dist/src/application/use-cases/StopStreamUseCase.js +96 -0
- package/dist/src/application/use-cases/StopStreamUseCase.js.map +1 -0
- package/dist/src/domain/entities/Stream.d.ts +40 -0
- package/dist/src/domain/entities/Stream.d.ts.map +1 -0
- package/dist/src/domain/entities/Stream.js +115 -0
- package/dist/src/domain/entities/Stream.js.map +1 -0
- package/dist/src/domain/events/StreamEvent.d.ts +48 -0
- package/dist/src/domain/events/StreamEvent.d.ts.map +1 -0
- package/dist/src/domain/events/StreamEvent.js +3 -0
- package/dist/src/domain/events/StreamEvent.js.map +1 -0
- package/dist/src/domain/repositories/StreamRepository.d.ts +41 -0
- package/dist/src/domain/repositories/StreamRepository.d.ts.map +1 -0
- package/dist/src/domain/repositories/StreamRepository.js +3 -0
- package/dist/src/domain/repositories/StreamRepository.js.map +1 -0
- package/dist/src/domain/services/FFmpegService.d.ts +42 -0
- package/dist/src/domain/services/FFmpegService.d.ts.map +1 -0
- package/dist/src/domain/services/FFmpegService.js +3 -0
- package/dist/src/domain/services/FFmpegService.js.map +1 -0
- package/dist/src/domain/services/SSEService.d.ts +42 -0
- package/dist/src/domain/services/SSEService.d.ts.map +1 -0
- package/dist/src/domain/services/SSEService.js +3 -0
- package/dist/src/domain/services/SSEService.js.map +1 -0
- package/dist/src/domain/value-objects/StreamId.d.ts +10 -0
- package/dist/src/domain/value-objects/StreamId.d.ts.map +1 -0
- package/dist/src/domain/value-objects/StreamId.js +31 -0
- package/dist/src/domain/value-objects/StreamId.js.map +1 -0
- package/dist/src/domain/value-objects/StreamState.d.ts +12 -0
- package/dist/src/domain/value-objects/StreamState.d.ts.map +1 -0
- package/dist/src/domain/value-objects/StreamState.js +35 -0
- package/dist/src/domain/value-objects/StreamState.js.map +1 -0
- package/dist/src/domain/value-objects/StreamUrl.d.ts +12 -0
- package/dist/src/domain/value-objects/StreamUrl.d.ts.map +1 -0
- package/dist/src/domain/value-objects/StreamUrl.js +48 -0
- package/dist/src/domain/value-objects/StreamUrl.js.map +1 -0
- package/dist/src/infrastructure/config/Config.d.ts +42 -0
- package/dist/src/infrastructure/config/Config.d.ts.map +1 -0
- package/dist/src/infrastructure/config/Config.js +113 -0
- package/dist/src/infrastructure/config/Config.js.map +1 -0
- package/dist/src/infrastructure/logging/ConsoleLogger.d.ts +12 -0
- package/dist/src/infrastructure/logging/ConsoleLogger.d.ts.map +1 -0
- package/dist/src/infrastructure/logging/ConsoleLogger.js +41 -0
- package/dist/src/infrastructure/logging/ConsoleLogger.js.map +1 -0
- package/dist/src/infrastructure/logging/LogBuffer.d.ts +20 -0
- package/dist/src/infrastructure/logging/LogBuffer.d.ts.map +1 -0
- package/dist/src/infrastructure/logging/LogBuffer.js +95 -0
- package/dist/src/infrastructure/logging/LogBuffer.js.map +1 -0
- package/dist/src/infrastructure/logging/LogShippingService.d.ts +23 -0
- package/dist/src/infrastructure/logging/LogShippingService.d.ts.map +1 -0
- package/dist/src/infrastructure/logging/LogShippingService.js +128 -0
- package/dist/src/infrastructure/logging/LogShippingService.js.map +1 -0
- package/dist/src/infrastructure/logging/RemoteLogger.d.ts +37 -0
- package/dist/src/infrastructure/logging/RemoteLogger.d.ts.map +1 -0
- package/dist/src/infrastructure/logging/RemoteLogger.js +120 -0
- package/dist/src/infrastructure/logging/RemoteLogger.js.map +1 -0
- package/dist/src/infrastructure/logging/types/LogTypes.d.ts +27 -0
- package/dist/src/infrastructure/logging/types/LogTypes.d.ts.map +1 -0
- package/dist/src/infrastructure/logging/types/LogTypes.js +3 -0
- package/dist/src/infrastructure/logging/types/LogTypes.js.map +1 -0
- package/dist/src/infrastructure/repositories/FileSystemStreamRepository.d.ts +22 -0
- package/dist/src/infrastructure/repositories/FileSystemStreamRepository.d.ts.map +1 -0
- package/dist/src/infrastructure/repositories/FileSystemStreamRepository.js +212 -0
- package/dist/src/infrastructure/repositories/FileSystemStreamRepository.js.map +1 -0
- package/dist/src/infrastructure/services/NodeFFmpegService.d.ts +17 -0
- package/dist/src/infrastructure/services/NodeFFmpegService.d.ts.map +1 -0
- package/dist/src/infrastructure/services/NodeFFmpegService.js +306 -0
- package/dist/src/infrastructure/services/NodeFFmpegService.js.map +1 -0
- package/dist/src/infrastructure/services/NodeSSEService.d.ts +30 -0
- package/dist/src/infrastructure/services/NodeSSEService.d.ts.map +1 -0
- package/dist/src/infrastructure/services/NodeSSEService.js +268 -0
- package/dist/src/infrastructure/services/NodeSSEService.js.map +1 -0
- package/dist/src/main.d.ts +3 -0
- package/dist/src/main.d.ts.map +1 -0
- package/dist/src/main.js +87 -0
- package/dist/src/main.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { StreamUrl } from '../value-objects/StreamUrl';
|
|
2
|
+
export interface FFmpegCommand {
|
|
3
|
+
readonly command: string;
|
|
4
|
+
readonly args: string[];
|
|
5
|
+
readonly fullCommand: string;
|
|
6
|
+
}
|
|
7
|
+
export interface FFmpegProcess {
|
|
8
|
+
readonly pid: number;
|
|
9
|
+
readonly command: FFmpegCommand;
|
|
10
|
+
readonly startTime: Date;
|
|
11
|
+
}
|
|
12
|
+
export interface FFmpegService {
|
|
13
|
+
/**
|
|
14
|
+
* Start an FFmpeg stream process
|
|
15
|
+
*/
|
|
16
|
+
startStream(cameraUrl: StreamUrl, streamKey: string, hasAudio: boolean, maxRetries?: number, retryDelayMs?: number, onPidUpdate?: (newPid: number) => Promise<void>): Promise<FFmpegProcess>;
|
|
17
|
+
/**
|
|
18
|
+
* Stop an FFmpeg process by PID
|
|
19
|
+
*/
|
|
20
|
+
stopStream(pid: number): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a process is running
|
|
23
|
+
*/
|
|
24
|
+
isProcessRunning(pid: number): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Detect if a stream has audio
|
|
27
|
+
*/
|
|
28
|
+
detectAudio(cameraUrl: StreamUrl): Promise<boolean>;
|
|
29
|
+
/**
|
|
30
|
+
* Build FFmpeg command for streaming
|
|
31
|
+
*/
|
|
32
|
+
buildStreamCommand(cameraUrl: StreamUrl, streamKey: string, hasAudio: boolean): FFmpegCommand;
|
|
33
|
+
/**
|
|
34
|
+
* Get all running FFmpeg processes managed by this service
|
|
35
|
+
*/
|
|
36
|
+
getRunningProcesses(): Promise<FFmpegProcess[]>;
|
|
37
|
+
/**
|
|
38
|
+
* Kill all FFmpeg processes (cleanup)
|
|
39
|
+
*/
|
|
40
|
+
killAllProcesses(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=FFmpegService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FFmpegService.d.ts","sourceRoot":"","sources":["../../../../src/domain/services/FFmpegService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,WAAW,CACT,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,YAAY,CAAC,EAAE,MAAM,EACrB,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAC9C,OAAO,CAAC,aAAa,CAAC,CAAC;IAE1B;;OAEG;IACH,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvC;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEhD;;OAEG;IACH,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpD;;OAEG;IACH,kBAAkB,CAChB,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,OAAO,GAChB,aAAa,CAAC;IAEjB;;OAEG;IACH,mBAAmB,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAEhD;;OAEG;IACH,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FFmpegService.js","sourceRoot":"","sources":["../../../../src/domain/services/FFmpegService.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SSEStreamEvent } from "../events/StreamEvent";
|
|
2
|
+
export interface SSEConnectionConfig {
|
|
3
|
+
readonly groundId: string;
|
|
4
|
+
readonly baseUrl: string;
|
|
5
|
+
readonly retryInterval: number;
|
|
6
|
+
readonly maxRetries: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SSEService {
|
|
9
|
+
/**
|
|
10
|
+
* Start listening to SSE events
|
|
11
|
+
*/
|
|
12
|
+
start(config: SSEConnectionConfig): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Stop listening to SSE events
|
|
15
|
+
*/
|
|
16
|
+
stop(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Check if the SSE connection is active
|
|
19
|
+
*/
|
|
20
|
+
isConnected(): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Subscribe to SSE stream events
|
|
23
|
+
*/
|
|
24
|
+
onStreamEvent(callback: (event: SSEStreamEvent) => void): void;
|
|
25
|
+
/**
|
|
26
|
+
* Subscribe to connection status changes
|
|
27
|
+
*/
|
|
28
|
+
onConnectionChange(callback: (status: "connected" | "disconnected" | "reconnecting") => void): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get current connection status
|
|
31
|
+
*/
|
|
32
|
+
getConnectionStatus(): "connected" | "disconnected" | "reconnecting";
|
|
33
|
+
/**
|
|
34
|
+
* Get retry count for current connection attempt
|
|
35
|
+
*/
|
|
36
|
+
getRetryCount(): number;
|
|
37
|
+
/**
|
|
38
|
+
* Force reconnection
|
|
39
|
+
*/
|
|
40
|
+
reconnect(): Promise<void>;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=SSEService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SSEService.d.ts","sourceRoot":"","sources":["../../../../src/domain/services/SSEService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAElD;;OAEG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB;;OAEG;IACH,WAAW,IAAI,OAAO,CAAC;IAEvB;;OAEG;IACH,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI,CAAC;IAE/D;;OAEG;IACH,kBAAkB,CAChB,QAAQ,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,cAAc,GAAG,cAAc,KAAK,IAAI,GACxE,IAAI,CAAC;IAER;;OAEG;IACH,mBAAmB,IAAI,WAAW,GAAG,cAAc,GAAG,cAAc,CAAC;IAErE;;OAEG;IACH,aAAa,IAAI,MAAM,CAAC;IAExB;;OAEG;IACH,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SSEService.js","sourceRoot":"","sources":["../../../../src/domain/services/SSEService.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class StreamId {
|
|
2
|
+
private readonly _value;
|
|
3
|
+
private constructor();
|
|
4
|
+
static create(): StreamId;
|
|
5
|
+
static fromString(value: string): StreamId;
|
|
6
|
+
get value(): string;
|
|
7
|
+
equals(other: StreamId): boolean;
|
|
8
|
+
toString(): string;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=StreamId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamId.d.ts","sourceRoot":"","sources":["../../../../src/domain/value-objects/StreamId.ts"],"names":[],"mappings":"AAEA,qBAAa,QAAQ;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAA3C,OAAO;WAMO,MAAM,IAAI,QAAQ;WAMlB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ;IAIjD,IAAW,KAAK,IAAI,MAAM,CAEzB;IAEM,MAAM,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO;IAIhC,QAAQ,IAAI,MAAM;CAG1B"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StreamId = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
class StreamId {
|
|
6
|
+
constructor(_value) {
|
|
7
|
+
this._value = _value;
|
|
8
|
+
if (!_value || _value.trim().length === 0) {
|
|
9
|
+
throw new Error('StreamId cannot be empty');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
static create() {
|
|
13
|
+
const timestamp = Date.now().toString(36);
|
|
14
|
+
const random = (0, crypto_1.randomBytes)(8).toString('hex');
|
|
15
|
+
return new StreamId(`stream_${timestamp}_${random}`);
|
|
16
|
+
}
|
|
17
|
+
static fromString(value) {
|
|
18
|
+
return new StreamId(value);
|
|
19
|
+
}
|
|
20
|
+
get value() {
|
|
21
|
+
return this._value;
|
|
22
|
+
}
|
|
23
|
+
equals(other) {
|
|
24
|
+
return this._value === other._value;
|
|
25
|
+
}
|
|
26
|
+
toString() {
|
|
27
|
+
return this._value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.StreamId = StreamId;
|
|
31
|
+
//# sourceMappingURL=StreamId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamId.js","sourceRoot":"","sources":["../../../../src/domain/value-objects/StreamId.ts"],"names":[],"mappings":";;;AAAA,mCAAqC;AAErC,MAAa,QAAQ;IACnB,YAAqC,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;QACjD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAEM,MAAM,CAAC,MAAM;QAClB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,IAAA,oBAAW,EAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,IAAI,QAAQ,CAAC,UAAU,SAAS,IAAI,MAAM,EAAE,CAAC,CAAC;IACvD,CAAC;IAEM,MAAM,CAAC,UAAU,CAAC,KAAa;QACpC,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEM,MAAM,CAAC,KAAe;QAC3B,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC;IACtC,CAAC;IAEM,QAAQ;QACb,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AA5BD,4BA4BC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare enum StreamState {
|
|
2
|
+
PENDING = "pending",
|
|
3
|
+
RUNNING = "running",
|
|
4
|
+
STOPPED = "stopped",
|
|
5
|
+
FAILED = "failed",
|
|
6
|
+
RECONCILING = "reconciling"
|
|
7
|
+
}
|
|
8
|
+
export declare class StreamStateValidator {
|
|
9
|
+
static isValidTransition(from: StreamState, to: StreamState): boolean;
|
|
10
|
+
static getAllowedTransitions(from: StreamState): StreamState[];
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=StreamState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamState.d.ts","sourceRoot":"","sources":["../../../../src/domain/value-objects/StreamState.ts"],"names":[],"mappings":"AAAA,oBAAY,WAAW;IACrB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,OAAO,YAAY;IACnB,MAAM,WAAW;IACjB,WAAW,gBAAgB;CAC5B;AAED,qBAAa,oBAAoB;WACjB,iBAAiB,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,GAAG,OAAO;WAY9D,qBAAqB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE;CAWtE"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StreamStateValidator = exports.StreamState = void 0;
|
|
4
|
+
var StreamState;
|
|
5
|
+
(function (StreamState) {
|
|
6
|
+
StreamState["PENDING"] = "pending";
|
|
7
|
+
StreamState["RUNNING"] = "running";
|
|
8
|
+
StreamState["STOPPED"] = "stopped";
|
|
9
|
+
StreamState["FAILED"] = "failed";
|
|
10
|
+
StreamState["RECONCILING"] = "reconciling";
|
|
11
|
+
})(StreamState || (exports.StreamState = StreamState = {}));
|
|
12
|
+
class StreamStateValidator {
|
|
13
|
+
static isValidTransition(from, to) {
|
|
14
|
+
const validTransitions = {
|
|
15
|
+
[StreamState.PENDING]: [StreamState.RUNNING, StreamState.FAILED],
|
|
16
|
+
[StreamState.RUNNING]: [StreamState.STOPPED, StreamState.FAILED, StreamState.RECONCILING],
|
|
17
|
+
[StreamState.STOPPED]: [StreamState.RUNNING, StreamState.PENDING],
|
|
18
|
+
[StreamState.FAILED]: [StreamState.PENDING, StreamState.RUNNING],
|
|
19
|
+
[StreamState.RECONCILING]: [StreamState.RUNNING, StreamState.FAILED, StreamState.STOPPED]
|
|
20
|
+
};
|
|
21
|
+
return validTransitions[from]?.includes(to) ?? false;
|
|
22
|
+
}
|
|
23
|
+
static getAllowedTransitions(from) {
|
|
24
|
+
const validTransitions = {
|
|
25
|
+
[StreamState.PENDING]: [StreamState.RUNNING, StreamState.FAILED],
|
|
26
|
+
[StreamState.RUNNING]: [StreamState.STOPPED, StreamState.FAILED, StreamState.RECONCILING],
|
|
27
|
+
[StreamState.STOPPED]: [StreamState.RUNNING, StreamState.PENDING],
|
|
28
|
+
[StreamState.FAILED]: [StreamState.PENDING, StreamState.RUNNING],
|
|
29
|
+
[StreamState.RECONCILING]: [StreamState.RUNNING, StreamState.FAILED, StreamState.STOPPED]
|
|
30
|
+
};
|
|
31
|
+
return validTransitions[from] ?? [];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.StreamStateValidator = StreamStateValidator;
|
|
35
|
+
//# sourceMappingURL=StreamState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamState.js","sourceRoot":"","sources":["../../../../src/domain/value-objects/StreamState.ts"],"names":[],"mappings":";;;AAAA,IAAY,WAMX;AAND,WAAY,WAAW;IACrB,kCAAmB,CAAA;IACnB,kCAAmB,CAAA;IACnB,kCAAmB,CAAA;IACnB,gCAAiB,CAAA;IACjB,0CAA2B,CAAA;AAC7B,CAAC,EANW,WAAW,2BAAX,WAAW,QAMtB;AAED,MAAa,oBAAoB;IACxB,MAAM,CAAC,iBAAiB,CAAC,IAAiB,EAAE,EAAe;QAChE,MAAM,gBAAgB,GAAuC;YAC3D,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;YAChE,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC;YACzF,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;YACjE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;YAChE,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC;SAC1F,CAAC;QAEF,OAAO,gBAAgB,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,IAAI,KAAK,CAAC;IACvD,CAAC;IAEM,MAAM,CAAC,qBAAqB,CAAC,IAAiB;QACnD,MAAM,gBAAgB,GAAuC;YAC3D,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;YAChE,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,WAAW,CAAC;YACzF,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;YACjE,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;YAChE,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC;SAC1F,CAAC;QAEF,OAAO,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACtC,CAAC;CACF;AAxBD,oDAwBC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare class StreamUrl {
|
|
2
|
+
private readonly _value;
|
|
3
|
+
private constructor();
|
|
4
|
+
static create(url: string): StreamUrl;
|
|
5
|
+
private validate;
|
|
6
|
+
get value(): string;
|
|
7
|
+
isRtsp(): boolean;
|
|
8
|
+
isHttp(): boolean;
|
|
9
|
+
equals(other: StreamUrl): boolean;
|
|
10
|
+
toString(): string;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=StreamUrl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamUrl.d.ts","sourceRoot":"","sources":["../../../../src/domain/value-objects/StreamUrl.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAS;IACA,OAAO,CAAC,QAAQ,CAAC,MAAM;IAA3C,OAAO;WAIO,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS;IAI5C,OAAO,CAAC,QAAQ;IAqBhB,IAAW,KAAK,IAAI,MAAM,CAEzB;IAEM,MAAM,IAAI,OAAO;IAIjB,MAAM,IAAI,OAAO;IAKjB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAIjC,QAAQ,IAAI,MAAM;CAG1B"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StreamUrl = void 0;
|
|
4
|
+
class StreamUrl {
|
|
5
|
+
constructor(_value) {
|
|
6
|
+
this._value = _value;
|
|
7
|
+
this.validate(_value);
|
|
8
|
+
}
|
|
9
|
+
static create(url) {
|
|
10
|
+
return new StreamUrl(url);
|
|
11
|
+
}
|
|
12
|
+
validate(url) {
|
|
13
|
+
if (!url || url.trim().length === 0) {
|
|
14
|
+
throw new Error('Stream URL cannot be empty');
|
|
15
|
+
}
|
|
16
|
+
// Basic URL validation - should start with rtsp:// or http://
|
|
17
|
+
const urlPattern = /^(rtsp|http|https):\/\/.+/i;
|
|
18
|
+
if (!urlPattern.test(url)) {
|
|
19
|
+
throw new Error('Invalid stream URL format. Must start with rtsp://, http://, or https://');
|
|
20
|
+
}
|
|
21
|
+
// Additional RTSP validation
|
|
22
|
+
if (url.toLowerCase().startsWith('rtsp://')) {
|
|
23
|
+
// Basic RTSP URL structure validation
|
|
24
|
+
const rtspPattern = /^rtsp:\/\/[^\/\s]+/i;
|
|
25
|
+
if (!rtspPattern.test(url)) {
|
|
26
|
+
throw new Error('Invalid RTSP URL format');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
get value() {
|
|
31
|
+
return this._value;
|
|
32
|
+
}
|
|
33
|
+
isRtsp() {
|
|
34
|
+
return this._value.toLowerCase().startsWith('rtsp://');
|
|
35
|
+
}
|
|
36
|
+
isHttp() {
|
|
37
|
+
return this._value.toLowerCase().startsWith('http://') ||
|
|
38
|
+
this._value.toLowerCase().startsWith('https://');
|
|
39
|
+
}
|
|
40
|
+
equals(other) {
|
|
41
|
+
return this._value === other._value;
|
|
42
|
+
}
|
|
43
|
+
toString() {
|
|
44
|
+
return this._value;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.StreamUrl = StreamUrl;
|
|
48
|
+
//# sourceMappingURL=StreamUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StreamUrl.js","sourceRoot":"","sources":["../../../../src/domain/value-objects/StreamUrl.ts"],"names":[],"mappings":";;;AAAA,MAAa,SAAS;IACpB,YAAqC,MAAc;QAAd,WAAM,GAAN,MAAM,CAAQ;QACjD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;IAEM,MAAM,CAAC,MAAM,CAAC,GAAW;QAC9B,OAAO,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAEO,QAAQ,CAAC,GAAW;QAC1B,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,8DAA8D;QAC9D,MAAM,UAAU,GAAG,4BAA4B,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;QAC9F,CAAC;QAED,6BAA6B;QAC7B,IAAI,GAAG,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,sCAAsC;YACtC,MAAM,WAAW,GAAG,qBAAqB,CAAC;YAC1C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;YAC7C,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAW,KAAK;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,CAAC;IAEM,MAAM;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC;IAEM,MAAM,CAAC,KAAgB;QAC5B,OAAO,IAAI,CAAC,MAAM,KAAK,KAAK,CAAC,MAAM,CAAC;IACtC,CAAC;IAEM,QAAQ;QACb,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAlDD,8BAkDC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface AppConfig {
|
|
2
|
+
server: {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
};
|
|
5
|
+
groundInfo: {
|
|
6
|
+
groundId: string;
|
|
7
|
+
};
|
|
8
|
+
sse: {
|
|
9
|
+
retryInterval: number;
|
|
10
|
+
maxRetries: number;
|
|
11
|
+
};
|
|
12
|
+
stream: {
|
|
13
|
+
persistentStateDir: string;
|
|
14
|
+
tempStateDir: string;
|
|
15
|
+
healthCheckInterval: number;
|
|
16
|
+
};
|
|
17
|
+
logging: {
|
|
18
|
+
level: string;
|
|
19
|
+
file?: string;
|
|
20
|
+
};
|
|
21
|
+
remoteLogging: {
|
|
22
|
+
enabled: boolean;
|
|
23
|
+
sourceId: string;
|
|
24
|
+
batchSize: number;
|
|
25
|
+
batchInterval: number;
|
|
26
|
+
maxMemoryUsage: number;
|
|
27
|
+
retryAttempts: number;
|
|
28
|
+
retryDelay: number;
|
|
29
|
+
};
|
|
30
|
+
environment: string;
|
|
31
|
+
}
|
|
32
|
+
export declare class Config {
|
|
33
|
+
private static instance;
|
|
34
|
+
private config;
|
|
35
|
+
private constructor();
|
|
36
|
+
static getInstance(): Config;
|
|
37
|
+
get(): AppConfig;
|
|
38
|
+
private loadConfig;
|
|
39
|
+
private getEnvVar;
|
|
40
|
+
validate(): void;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=Config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Config.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/config/Config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE;QACN,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;IACF,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,GAAG,EAAE;QACH,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,MAAM,EAAE;QACN,kBAAkB,EAAE,MAAM,CAAC;QAC3B,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,CAAC;IACF,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,aAAa,EAAE;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,aAAa,EAAE,MAAM,CAAC;QACtB,cAAc,EAAE,MAAM,CAAC;QACvB,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,MAAM,CAAY;IAE1B,OAAO;WAIO,WAAW,IAAI,MAAM;IAO5B,GAAG,IAAI,SAAS;IAIvB,OAAO,CAAC,UAAU;IAkDlB,OAAO,CAAC,SAAS;IAQV,QAAQ,IAAI,IAAI;CAuBxB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Config = void 0;
|
|
37
|
+
const dotenv = __importStar(require("dotenv"));
|
|
38
|
+
// Load environment variables
|
|
39
|
+
dotenv.config();
|
|
40
|
+
class Config {
|
|
41
|
+
constructor() {
|
|
42
|
+
this.config = this.loadConfig();
|
|
43
|
+
}
|
|
44
|
+
static getInstance() {
|
|
45
|
+
if (!Config.instance) {
|
|
46
|
+
Config.instance = new Config();
|
|
47
|
+
}
|
|
48
|
+
return Config.instance;
|
|
49
|
+
}
|
|
50
|
+
get() {
|
|
51
|
+
return this.config;
|
|
52
|
+
}
|
|
53
|
+
loadConfig() {
|
|
54
|
+
return {
|
|
55
|
+
server: {
|
|
56
|
+
baseUrl: this.getEnvVar("BASE_URL", "https://api.drop-shot.live/"),
|
|
57
|
+
},
|
|
58
|
+
groundInfo: {
|
|
59
|
+
groundId: this.getEnvVar("GROUND_ID", ""),
|
|
60
|
+
},
|
|
61
|
+
sse: {
|
|
62
|
+
retryInterval: parseInt(this.getEnvVar("SSE_RETRY_INTERVAL", "5000")),
|
|
63
|
+
maxRetries: parseInt(this.getEnvVar("SSE_MAX_RETRIES", "10")),
|
|
64
|
+
},
|
|
65
|
+
stream: {
|
|
66
|
+
persistentStateDir: this.getEnvVar("PERSISTENT_STATE_DIR", "/var/tmp/stream_registry"),
|
|
67
|
+
tempStateDir: this.getEnvVar("TEMP_STATE_DIR", "/tmp/stream_registry"),
|
|
68
|
+
healthCheckInterval: parseInt(this.getEnvVar("HEALTH_CHECK_INTERVAL", "30000")),
|
|
69
|
+
},
|
|
70
|
+
logging: {
|
|
71
|
+
level: this.getEnvVar("LOG_LEVEL", "info"),
|
|
72
|
+
file: process.env.LOG_FILE,
|
|
73
|
+
},
|
|
74
|
+
remoteLogging: {
|
|
75
|
+
enabled: this.getEnvVar("REMOTE_LOGGING_ENABLED", "false") === "true",
|
|
76
|
+
sourceId: this.getEnvVar("REMOTE_LOGGING_SOURCE_ID", "raspberry-pi-001"),
|
|
77
|
+
batchSize: parseInt(this.getEnvVar("REMOTE_LOGGING_BATCH_SIZE", "50")),
|
|
78
|
+
batchInterval: parseInt(this.getEnvVar("REMOTE_LOGGING_BATCH_INTERVAL", "300000")), // 5 minutes
|
|
79
|
+
maxMemoryUsage: parseInt(this.getEnvVar("REMOTE_LOGGING_MAX_MEMORY", "512000")), // 500KB
|
|
80
|
+
retryAttempts: parseInt(this.getEnvVar("REMOTE_LOGGING_RETRY_ATTEMPTS", "999999")), // Infinite for errors
|
|
81
|
+
retryDelay: parseInt(this.getEnvVar("REMOTE_LOGGING_RETRY_DELAY", "5000")), // 5 seconds
|
|
82
|
+
},
|
|
83
|
+
environment: this.getEnvVar("NODE_ENV", "development"),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
getEnvVar(key, defaultValue) {
|
|
87
|
+
const value = process.env[key];
|
|
88
|
+
if (value === undefined) {
|
|
89
|
+
return defaultValue;
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
}
|
|
93
|
+
validate() {
|
|
94
|
+
const errors = [];
|
|
95
|
+
if (!this.config.groundInfo.groundId) {
|
|
96
|
+
errors.push("GROUND_ID is required");
|
|
97
|
+
}
|
|
98
|
+
if (this.config.sse.retryInterval <= 0) {
|
|
99
|
+
errors.push("SSE_RETRY_INTERVAL must be positive");
|
|
100
|
+
}
|
|
101
|
+
if (this.config.sse.maxRetries <= 0) {
|
|
102
|
+
errors.push("SSE_MAX_RETRIES must be positive");
|
|
103
|
+
}
|
|
104
|
+
if (!this.config.server.baseUrl) {
|
|
105
|
+
errors.push("SERVER_BASE_URL is required");
|
|
106
|
+
}
|
|
107
|
+
if (errors.length > 0) {
|
|
108
|
+
throw new Error(`Configuration validation failed: ${errors.join(", ")}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.Config = Config;
|
|
113
|
+
//# sourceMappingURL=Config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Config.js","sourceRoot":"","sources":["../../../../src/infrastructure/config/Config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Logger } from "../../application/interfaces/Logger";
|
|
2
|
+
export declare class ConsoleLogger implements Logger {
|
|
3
|
+
private readonly logLevel;
|
|
4
|
+
constructor(logLevel?: string);
|
|
5
|
+
shouldLog(level: string): boolean;
|
|
6
|
+
private formatMessage;
|
|
7
|
+
info(message: string, meta?: any): void;
|
|
8
|
+
warn(message: string, meta?: any): void;
|
|
9
|
+
error(message: string, meta?: any): void;
|
|
10
|
+
debug(message: string, meta?: any): void;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=ConsoleLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsoleLogger.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/logging/ConsoleLogger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qCAAqC,CAAC;AAE7D,qBAAa,aAAc,YAAW,MAAM;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,GAAE,MAAgB;IAEvD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAOjC,OAAO,CAAC,aAAa;IAMd,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAMvC,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAMvC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;IAMxC,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI;CAKhD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConsoleLogger = void 0;
|
|
4
|
+
class ConsoleLogger {
|
|
5
|
+
constructor(logLevel = "debug") {
|
|
6
|
+
this.logLevel = logLevel;
|
|
7
|
+
}
|
|
8
|
+
shouldLog(level) {
|
|
9
|
+
const levels = ["debug", "info", "warn", "error"];
|
|
10
|
+
const currentLevelIndex = levels.indexOf(this.logLevel);
|
|
11
|
+
const messageLevelIndex = levels.indexOf(level);
|
|
12
|
+
return messageLevelIndex >= currentLevelIndex;
|
|
13
|
+
}
|
|
14
|
+
formatMessage(level, message, meta) {
|
|
15
|
+
const timestamp = new Date().toISOString();
|
|
16
|
+
const metaStr = meta ? ` ${JSON.stringify(meta)}` : "";
|
|
17
|
+
return `[${timestamp}] ${level.toUpperCase()}: ${message}${metaStr}`;
|
|
18
|
+
}
|
|
19
|
+
info(message, meta) {
|
|
20
|
+
if (this.shouldLog("info")) {
|
|
21
|
+
console.log(this.formatMessage("info", message, meta));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
warn(message, meta) {
|
|
25
|
+
if (this.shouldLog("warn")) {
|
|
26
|
+
console.warn(this.formatMessage("warn", message, meta));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
error(message, meta) {
|
|
30
|
+
if (this.shouldLog("error")) {
|
|
31
|
+
console.error(this.formatMessage("error", message, meta));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
debug(message, meta) {
|
|
35
|
+
if (this.shouldLog("debug")) {
|
|
36
|
+
console.debug(this.formatMessage("debug", message, meta));
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.ConsoleLogger = ConsoleLogger;
|
|
41
|
+
//# sourceMappingURL=ConsoleLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConsoleLogger.js","sourceRoot":"","sources":["../../../../src/infrastructure/logging/ConsoleLogger.ts"],"names":[],"mappings":";;;AAEA,MAAa,aAAa;IACxB,YAA6B,WAAmB,OAAO;QAA1B,aAAQ,GAAR,QAAQ,CAAkB;IAAG,CAAC;IAE3D,SAAS,CAAC,KAAa;QACrB,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxD,MAAM,iBAAiB,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAChD,OAAO,iBAAiB,IAAI,iBAAiB,CAAC;IAChD,CAAC;IAEO,aAAa,CAAC,KAAa,EAAE,OAAe,EAAE,IAAU;QAC9D,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACvD,OAAO,IAAI,SAAS,KAAK,KAAK,CAAC,WAAW,EAAE,KAAK,OAAO,GAAG,OAAO,EAAE,CAAC;IACvE,CAAC;IAEM,IAAI,CAAC,OAAe,EAAE,IAAU;QACrC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IAEM,IAAI,CAAC,OAAe,EAAE,IAAU;QACrC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,OAAe,EAAE,IAAU;QACtC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,OAAe,EAAE,IAAU;QACtC,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;CACF;AAvCD,sCAuCC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LogEntry, LogBufferStats } from "./types/LogTypes";
|
|
2
|
+
export declare class LogBuffer {
|
|
3
|
+
private buffer;
|
|
4
|
+
private totalSize;
|
|
5
|
+
private readonly maxSize;
|
|
6
|
+
private readonly maxCount;
|
|
7
|
+
private flushTimer?;
|
|
8
|
+
private readonly flushInterval;
|
|
9
|
+
private readonly onFlush;
|
|
10
|
+
constructor(maxSize: number, maxCount: number, flushInterval: number, onFlush: (logs: LogEntry[]) => Promise<void>);
|
|
11
|
+
add(entry: LogEntry): void;
|
|
12
|
+
flush(): Promise<void>;
|
|
13
|
+
getStats(): LogBufferStats;
|
|
14
|
+
destroy(): void;
|
|
15
|
+
private shouldFlushEarly;
|
|
16
|
+
private estimateLogSize;
|
|
17
|
+
private startFlushTimer;
|
|
18
|
+
private restartFlushTimer;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=LogBuffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LogBuffer.d.ts","sourceRoot":"","sources":["../../../../src/infrastructure/logging/LogBuffer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAe,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEzE,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,SAAS,CAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;gBAG5D,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC;IASvC,GAAG,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAgBpB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB5B,QAAQ,IAAI,cAAc;IAW1B,OAAO,IAAI,IAAI;IActB,OAAO,CAAC,gBAAgB;IAMxB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,iBAAiB;CAM1B"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogBuffer = void 0;
|
|
4
|
+
class LogBuffer {
|
|
5
|
+
constructor(maxSize, maxCount, flushInterval, onFlush) {
|
|
6
|
+
this.buffer = [];
|
|
7
|
+
this.totalSize = 0;
|
|
8
|
+
this.maxSize = maxSize;
|
|
9
|
+
this.maxCount = maxCount;
|
|
10
|
+
this.flushInterval = flushInterval;
|
|
11
|
+
this.onFlush = onFlush;
|
|
12
|
+
this.startFlushTimer();
|
|
13
|
+
}
|
|
14
|
+
add(entry) {
|
|
15
|
+
const estimatedSize = this.estimateLogSize(entry);
|
|
16
|
+
const bufferedLog = {
|
|
17
|
+
entry,
|
|
18
|
+
size: estimatedSize,
|
|
19
|
+
};
|
|
20
|
+
this.buffer.push(bufferedLog);
|
|
21
|
+
this.totalSize += estimatedSize;
|
|
22
|
+
// Check if we need to flush early due to size or count limits
|
|
23
|
+
if (this.shouldFlushEarly()) {
|
|
24
|
+
this.flush();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async flush() {
|
|
28
|
+
if (this.buffer.length === 0) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const logsToFlush = this.buffer.map((bufferedLog) => bufferedLog.entry);
|
|
32
|
+
this.buffer = [];
|
|
33
|
+
this.totalSize = 0;
|
|
34
|
+
try {
|
|
35
|
+
await this.onFlush(logsToFlush);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
// If flush fails, we don't re-add logs to avoid infinite loops
|
|
39
|
+
// The shipping service should handle retries
|
|
40
|
+
console.error("Failed to flush log buffer:", error);
|
|
41
|
+
}
|
|
42
|
+
// Restart the timer after flush
|
|
43
|
+
this.restartFlushTimer();
|
|
44
|
+
}
|
|
45
|
+
getStats() {
|
|
46
|
+
const timestamps = this.buffer.map((log) => log.entry.timestamp);
|
|
47
|
+
return {
|
|
48
|
+
count: this.buffer.length,
|
|
49
|
+
totalSize: this.totalSize,
|
|
50
|
+
oldestTimestamp: timestamps.length > 0 ? timestamps[0] : undefined,
|
|
51
|
+
newestTimestamp: timestamps.length > 0 ? timestamps[timestamps.length - 1] : undefined,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
destroy() {
|
|
55
|
+
if (this.flushTimer) {
|
|
56
|
+
clearTimeout(this.flushTimer);
|
|
57
|
+
this.flushTimer = undefined;
|
|
58
|
+
}
|
|
59
|
+
// Flush any remaining logs before destroying
|
|
60
|
+
if (this.buffer.length > 0) {
|
|
61
|
+
this.flush().catch((error) => {
|
|
62
|
+
console.error("Failed to flush logs during buffer destruction:", error);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
shouldFlushEarly() {
|
|
67
|
+
return (this.totalSize >= this.maxSize || this.buffer.length >= this.maxCount);
|
|
68
|
+
}
|
|
69
|
+
estimateLogSize(entry) {
|
|
70
|
+
// Rough estimation of JSON size in bytes
|
|
71
|
+
const baseSize = JSON.stringify({
|
|
72
|
+
level: entry.level,
|
|
73
|
+
message: entry.message,
|
|
74
|
+
timestamp: entry.timestamp,
|
|
75
|
+
}).length;
|
|
76
|
+
const metadataSize = entry.metadata
|
|
77
|
+
? JSON.stringify(entry.metadata).length
|
|
78
|
+
: 0;
|
|
79
|
+
// Add some overhead for JSON formatting
|
|
80
|
+
return baseSize + metadataSize + 50;
|
|
81
|
+
}
|
|
82
|
+
startFlushTimer() {
|
|
83
|
+
this.flushTimer = setTimeout(() => {
|
|
84
|
+
this.flush();
|
|
85
|
+
}, this.flushInterval);
|
|
86
|
+
}
|
|
87
|
+
restartFlushTimer() {
|
|
88
|
+
if (this.flushTimer) {
|
|
89
|
+
clearTimeout(this.flushTimer);
|
|
90
|
+
}
|
|
91
|
+
this.startFlushTimer();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.LogBuffer = LogBuffer;
|
|
95
|
+
//# sourceMappingURL=LogBuffer.js.map
|