@privateaim/server-kit 0.8.13 → 0.8.15
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/CHANGELOG.md +37 -0
- package/dist/index.cjs +494 -63
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +452 -65
- package/dist/index.mjs.map +1 -1
- package/dist/services/domain-event/index.d.ts +1 -1
- package/dist/services/domain-event/index.d.ts.map +1 -1
- package/dist/services/domain-event/module.d.ts +4 -4
- package/dist/services/domain-event/module.d.ts.map +1 -1
- package/dist/services/domain-event/redis/module.d.ts +2 -2
- package/dist/services/domain-event/redis/module.d.ts.map +1 -1
- package/dist/services/domain-event/singleton.d.ts +1 -0
- package/dist/services/domain-event/singleton.d.ts.map +1 -1
- package/dist/services/domain-event/socket/module.d.ts +2 -2
- package/dist/services/domain-event/socket/module.d.ts.map +1 -1
- package/dist/services/domain-event/types.d.ts +29 -0
- package/dist/services/domain-event/types.d.ts.map +1 -0
- package/dist/services/domain-event/utils.d.ts +2 -2
- package/dist/services/domain-event/utils.d.ts.map +1 -1
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/log-store/entities/base.d.ts +7 -0
- package/dist/services/log-store/entities/base.d.ts.map +1 -0
- package/dist/services/log-store/entities/index.d.ts +3 -0
- package/dist/services/log-store/entities/index.d.ts.map +1 -0
- package/dist/services/log-store/entities/loki.d.ts +13 -0
- package/dist/services/log-store/entities/loki.d.ts.map +1 -0
- package/dist/services/log-store/entities/memory.d.ts +11 -0
- package/dist/services/log-store/entities/memory.d.ts.map +1 -0
- package/dist/services/log-store/index.d.ts +4 -0
- package/dist/services/log-store/index.d.ts.map +1 -0
- package/dist/services/log-store/singleton.d.ts +6 -0
- package/dist/services/log-store/singleton.d.ts.map +1 -0
- package/dist/services/log-store/types.d.ts +27 -0
- package/dist/services/log-store/types.d.ts.map +1 -0
- package/dist/services/logger/module.d.ts.map +1 -1
- package/dist/services/logger/store.d.ts +14 -0
- package/dist/services/logger/store.d.ts.map +1 -0
- package/dist/services/logger/types.d.ts +3 -0
- package/dist/services/logger/types.d.ts.map +1 -1
- package/dist/services/loki/index.d.ts +3 -0
- package/dist/services/loki/index.d.ts.map +1 -0
- package/dist/services/loki/module.d.ts +3 -0
- package/dist/services/loki/module.d.ts.map +1 -0
- package/dist/services/loki/singleton.d.ts +6 -0
- package/dist/services/loki/singleton.d.ts.map +1 -0
- package/package.json +12 -9
- package/src/services/domain-event/index.ts +1 -1
- package/src/services/domain-event/module.ts +8 -8
- package/src/services/domain-event/redis/module.ts +28 -9
- package/src/services/domain-event/singleton.ts +6 -2
- package/src/services/domain-event/socket/module.ts +20 -9
- package/src/services/domain-event/types.ts +50 -0
- package/src/services/domain-event/utils.ts +2 -2
- package/src/services/index.ts +2 -0
- package/src/services/log-store/entities/base.ts +25 -0
- package/src/services/log-store/entities/index.ts +9 -0
- package/src/services/log-store/entities/loki.ts +158 -0
- package/src/services/log-store/entities/memory.ts +100 -0
- package/src/services/log-store/index.ts +10 -0
- package/src/services/log-store/singleton.ts +36 -0
- package/src/services/log-store/types.ts +42 -0
- package/src/services/logger/module.ts +20 -5
- package/src/services/logger/store.ts +70 -0
- package/src/services/logger/types.ts +4 -1
- package/src/services/loki/index.ts +9 -0
- package/src/services/loki/module.ts +30 -0
- package/src/services/loki/singleton.ts +26 -0
- package/test/unit/log-store.spec.ts +21 -0
- package/test/unit/logger.spec.ts +36 -0
- package/dist/services/domain-event/type.d.ts +0 -15
- package/dist/services/domain-event/type.d.ts.map +0 -1
- package/src/services/domain-event/type.ts +0 -27
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Log, LogLevel } from '@privateaim/kit';
|
|
2
|
+
export type LogStoreQueryOptions = {
|
|
3
|
+
labels?: Record<string, string>;
|
|
4
|
+
start?: number;
|
|
5
|
+
end?: number;
|
|
6
|
+
sort?: 'DESC' | 'ASC';
|
|
7
|
+
limit?: number;
|
|
8
|
+
};
|
|
9
|
+
export type LogStoreDeleteOptions = {
|
|
10
|
+
labels?: Record<string, string>;
|
|
11
|
+
start?: number;
|
|
12
|
+
end?: number;
|
|
13
|
+
};
|
|
14
|
+
export type LogInput = Omit<Log, 'labels' | 'time' | 'level'> & {
|
|
15
|
+
time?: bigint;
|
|
16
|
+
level?: `${LogLevel}`;
|
|
17
|
+
labels?: Record<string, string>;
|
|
18
|
+
};
|
|
19
|
+
export interface LogStore {
|
|
20
|
+
setLabels(labels: Record<string, string>): void;
|
|
21
|
+
getLabels(): Record<string, string>;
|
|
22
|
+
extendLabels(labels: Record<string, string>): void;
|
|
23
|
+
write(message: string | LogInput, labels?: Record<string, string>): Promise<Log>;
|
|
24
|
+
query(options?: LogStoreQueryOptions): Promise<[Log[], number]>;
|
|
25
|
+
delete(options?: LogStoreDeleteOptions): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/log-store/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,MAAM,oBAAoB,GAAG;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC,CAAC;AAEF,MAAM,WAAW,QAAQ;IACrB,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAEhD,SAAS,IAAK,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAEnD,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAI,OAAO,CAAC,GAAG,CAAC,CAAC;IAElF,KAAK,CAAC,OAAO,CAAC,EAAE,oBAAoB,GAAI,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC;IAEjE,MAAM,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/services/logger/module.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/services/logger/module.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,SAAS,CAAC;AAIrE,wBAAgB,YAAY,CAAC,GAAG,GAAE,mBAAwB,GAAI,MAAM,CAuDnE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TransportStreamOptions } from 'winston-transport';
|
|
2
|
+
import WinstonTransport from 'winston-transport';
|
|
3
|
+
import type { LogStore } from '../log-store';
|
|
4
|
+
type LogStoreTransportOptions = TransportStreamOptions & {
|
|
5
|
+
labels?: Record<string, string>;
|
|
6
|
+
};
|
|
7
|
+
export declare class LogStoreTransport extends WinstonTransport {
|
|
8
|
+
protected instance: LogStore;
|
|
9
|
+
protected labels: Record<string, string>;
|
|
10
|
+
constructor(store: LogStore, options?: LogStoreTransportOptions);
|
|
11
|
+
log(info: Record<PropertyKey, any>, next: () => void): any;
|
|
12
|
+
}
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/services/logger/store.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAChE,OAAO,gBAAgB,MAAM,mBAAmB,CAAC;AACjD,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEvD,KAAK,wBAAwB,GAAG,sBAAsB,GAAG;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,gBAAgB;IACnD,SAAS,CAAC,QAAQ,EAAG,QAAQ,CAAC;IAE9B,SAAS,CAAC,MAAM,EAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAE9B,KAAK,EAAE,QAAQ,EAAE,OAAO,GAAE,wBAA6B;IAOnE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,WAAW,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,MAAM,IAAI,GAAG,GAAG;CA0C7D"}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Logger, LoggerOptions } from 'winston';
|
|
2
|
+
import type { LogStore } from '../log-store';
|
|
2
3
|
export type LoggerCreateContext = {
|
|
3
4
|
directory?: string;
|
|
4
5
|
options?: Partial<LoggerOptions>;
|
|
6
|
+
store?: LogStore;
|
|
7
|
+
labels?: Record<string, string>;
|
|
5
8
|
};
|
|
6
9
|
export type LoggerTransports = LoggerOptions['transports'];
|
|
7
10
|
export type { Logger, };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/logger/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/logger/types.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;AAE3D,YAAY,EACR,MAAM,GACT,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/loki/index.ts"],"names":[],"mappings":"AAOA,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { LokiClient, CompactorDeletionRequestCreate as LokiCompactorDeletionRequestCreate, Config as LokiConfig, ConfigInput as LokiConfigInput, DistributorPushStream as LokiDistributorPushStream, QuerierQueryRangeOptions as LokiQuerierQueryRangeOptions, QuerierQueryResult as LokiQuerierQueryResult, createClient as createLokiClient, nanoSeconds } from '@hapic/loki';
|
|
2
|
+
export { LokiClient, LokiConfig, LokiConfigInput, LokiCompactorDeletionRequestCreate, LokiDistributorPushStream, LokiQuerierQueryRangeOptions, LokiQuerierQueryResult, createLokiClient, nanoSeconds, };
|
|
3
|
+
//# sourceMappingURL=module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../../../src/services/loki/module.ts"],"names":[],"mappings":"AAOA,OAAO,EACH,UAAU,EACV,8BAA8B,IAAI,kCAAkC,EACpE,MAAM,IAAI,UAAU,EACpB,WAAW,IAAI,eAAe,EAC9B,qBAAqB,IAAI,yBAAyB,EAClD,wBAAwB,IAAI,4BAA4B,EACxD,kBAAkB,IAAI,sBAAsB,EAC5C,YAAY,IAAI,gBAAgB,EAChC,WAAW,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,EACH,UAAU,EACV,UAAU,EACV,eAAe,EACf,kCAAkC,EAClC,yBAAyB,EACzB,4BAA4B,EAC5B,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,GACd,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Factory } from 'singa';
|
|
2
|
+
import type { LokiClient } from '@hapic/loki';
|
|
3
|
+
export declare function setLokiFactory(factory: Factory<LokiClient>): void;
|
|
4
|
+
export declare function isLokiClientUsable(): boolean;
|
|
5
|
+
export declare function useLokiClient(): LokiClient;
|
|
6
|
+
//# sourceMappingURL=singleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton.d.ts","sourceRoot":"","sources":["../../../src/services/loki/singleton.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAErC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAM9C,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,QAE1D;AAED,wBAAgB,kBAAkB,YAEjC;AAED,wBAAgB,aAAa,eAE5B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@privateaim/server-kit",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.15",
|
|
4
4
|
"exports": {
|
|
5
5
|
"./package.json": "./package.json",
|
|
6
6
|
".": {
|
|
@@ -28,24 +28,27 @@
|
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@ebec/http": "^2.3.0",
|
|
31
|
+
"@hapic/loki": "^1.2.0",
|
|
31
32
|
"@isaacs/ttlcache": "^1.4.1",
|
|
32
|
-
"@privateaim/kit": "^0.8.
|
|
33
|
+
"@privateaim/kit": "^0.8.15",
|
|
33
34
|
"@socket.io/redis-emitter": "^5.1.0",
|
|
34
35
|
"envix": "^1.5.0",
|
|
35
|
-
"hapic": "^2.
|
|
36
|
-
"singa": "^1.
|
|
37
|
-
"
|
|
36
|
+
"hapic": "^2.7.0",
|
|
37
|
+
"singa": "^1.1.0",
|
|
38
|
+
"triple-beam": "^1.4.1",
|
|
39
|
+
"winston": "^3.17.0",
|
|
40
|
+
"winston-transport": "^4.9.0"
|
|
38
41
|
},
|
|
39
42
|
"devDependencies": {
|
|
40
|
-
"@authup/core-http-kit": "^1.0.0-beta.
|
|
41
|
-
"@hapic/vault": "^2.3.
|
|
43
|
+
"@authup/core-http-kit": "^1.0.0-beta.27",
|
|
44
|
+
"@hapic/vault": "^2.3.9",
|
|
42
45
|
"amqp-extension": "^4.0.0",
|
|
43
46
|
"redis-extension": "^2.0.2",
|
|
44
47
|
"typeorm-extension": "^3.7.1"
|
|
45
48
|
},
|
|
46
49
|
"peerDependencies": {
|
|
47
|
-
"@authup/core-http-kit": "^1.0.0-beta.
|
|
48
|
-
"@hapic/vault": "^2.3.
|
|
50
|
+
"@authup/core-http-kit": "^1.0.0-beta.27",
|
|
51
|
+
"@hapic/vault": "^2.3.9",
|
|
49
52
|
"amqp-extension": "^4.0.0",
|
|
50
53
|
"redis-extension": "^2.0.2",
|
|
51
54
|
"typeorm-extension": "^3.7.1"
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* view the LICENSE file that was distributed with this source code.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
8
|
+
import type { ObjectLiteral } from '@privateaim/kit';
|
|
9
9
|
import { buildDomainEventFullName } from '@privateaim/kit';
|
|
10
10
|
import { isLoggerUsable, useLogger } from '../logger';
|
|
11
|
-
import type {
|
|
11
|
+
import type { DomainEventPublishOptions, IDomainEventPublisher } from './types';
|
|
12
12
|
|
|
13
13
|
export class DomainEventPublisher implements IDomainEventPublisher {
|
|
14
14
|
protected publishers : Set<IDomainEventPublisher>;
|
|
@@ -21,24 +21,24 @@ export class DomainEventPublisher implements IDomainEventPublisher {
|
|
|
21
21
|
this.publishers.add(publisher);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
async safePublish<T extends
|
|
25
|
-
ctx:
|
|
24
|
+
async safePublish<T extends ObjectLiteral = ObjectLiteral>(
|
|
25
|
+
ctx: DomainEventPublishOptions<T>,
|
|
26
26
|
) : Promise<void> {
|
|
27
27
|
try {
|
|
28
28
|
await this.publish(ctx);
|
|
29
29
|
} catch (e) {
|
|
30
30
|
if (isLoggerUsable()) {
|
|
31
|
-
useLogger().error(`Publishing event ${buildDomainEventFullName(ctx.
|
|
31
|
+
useLogger().error(`Publishing event ${buildDomainEventFullName(ctx.metadata.domain, ctx.metadata.event)} failed`);
|
|
32
32
|
useLogger().error(e);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
async publish<T extends
|
|
38
|
-
ctx:
|
|
37
|
+
async publish<T extends ObjectLiteral = ObjectLiteral>(
|
|
38
|
+
ctx: DomainEventPublishOptions<T>,
|
|
39
39
|
) : Promise<void> {
|
|
40
40
|
if (isLoggerUsable()) {
|
|
41
|
-
useLogger().info(`Publishing event ${buildDomainEventFullName(ctx.
|
|
41
|
+
useLogger().info(`Publishing event ${buildDomainEventFullName(ctx.metadata.domain, ctx.metadata.event)}`);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const publishers = this.publishers.values();
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { Client } from 'redis-extension';
|
|
9
|
-
import type {
|
|
9
|
+
import type { DomainEventRecord } from '@privateaim/kit';
|
|
10
|
+
import type { DomainEventPublishOptions, IDomainEventPublisher } from '../types';
|
|
10
11
|
import { buildEventChannelName, transformEventData } from '../utils';
|
|
11
12
|
|
|
12
13
|
export class DomainEventRedisPublisher implements IDomainEventPublisher {
|
|
@@ -16,19 +17,37 @@ export class DomainEventRedisPublisher implements IDomainEventPublisher {
|
|
|
16
17
|
this.driver = client;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
async publish(ctx:
|
|
20
|
-
const
|
|
20
|
+
async publish(ctx: DomainEventPublishOptions) : Promise<void> {
|
|
21
|
+
const payload : DomainEventRecord = {
|
|
22
|
+
type: ctx.metadata.domain,
|
|
23
|
+
event: ctx.metadata.event,
|
|
24
|
+
data: transformEventData(ctx.data),
|
|
25
|
+
};
|
|
26
|
+
const payloadSerialized = JSON.stringify(payload);
|
|
21
27
|
|
|
22
28
|
const pipeline = this.driver.pipeline();
|
|
23
29
|
for (let i = 0; i < ctx.destinations.length; i++) {
|
|
24
|
-
const
|
|
30
|
+
const destination = ctx.destinations[i];
|
|
25
31
|
|
|
26
|
-
let
|
|
27
|
-
|
|
32
|
+
let keyPrefix : string | undefined;
|
|
33
|
+
if (destination.namespace) {
|
|
34
|
+
keyPrefix = typeof destination.namespace === 'function' ?
|
|
35
|
+
destination.namespace(ctx.data) :
|
|
36
|
+
destination.namespace;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
let key : string;
|
|
40
|
+
if (keyPrefix) {
|
|
41
|
+
key = keyPrefix + buildEventChannelName(destination.channel);
|
|
42
|
+
} else {
|
|
43
|
+
key = buildEventChannelName(destination.channel);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
pipeline.publish(key, payloadSerialized);
|
|
28
47
|
|
|
29
|
-
if (typeof
|
|
30
|
-
key = keyPrefix + buildEventChannelName(
|
|
31
|
-
pipeline.publish(key,
|
|
48
|
+
if (typeof destination.channel === 'function') {
|
|
49
|
+
key = keyPrefix + buildEventChannelName(destination.channel, ctx.data.id);
|
|
50
|
+
pipeline.publish(key, payloadSerialized);
|
|
32
51
|
}
|
|
33
52
|
}
|
|
34
53
|
|
|
@@ -11,7 +11,7 @@ import { DomainEventPublisher } from './module';
|
|
|
11
11
|
import { DomainEventRedisPublisher } from './redis';
|
|
12
12
|
import { DomainEventSocketPublisher } from './socket';
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const singaInstance = singa<DomainEventPublisher>({
|
|
15
15
|
name: 'domainEventPublisher',
|
|
16
16
|
factory: () => {
|
|
17
17
|
const publisher = new DomainEventPublisher();
|
|
@@ -27,6 +27,10 @@ const instance = singa<DomainEventPublisher>({
|
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
+
export function useDomainEventPublisherSinga() {
|
|
31
|
+
return singaInstance;
|
|
32
|
+
}
|
|
33
|
+
|
|
30
34
|
export function useDomainEventPublisher() {
|
|
31
|
-
return
|
|
35
|
+
return singaInstance.use();
|
|
32
36
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { buildDomainEventFullName } from '@privateaim/kit';
|
|
9
9
|
import { Emitter } from '@socket.io/redis-emitter';
|
|
10
10
|
import type { Client } from 'redis-extension';
|
|
11
|
-
import type {
|
|
11
|
+
import type { DomainEventPublishOptions, IDomainEventPublisher } from '../types';
|
|
12
12
|
import { buildEventChannelName, transformEventData } from '../utils';
|
|
13
13
|
|
|
14
14
|
export class DomainEventSocketPublisher implements IDomainEventPublisher {
|
|
@@ -18,34 +18,45 @@ export class DomainEventSocketPublisher implements IDomainEventPublisher {
|
|
|
18
18
|
this.client = client;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
async publish(ctx:
|
|
21
|
+
async publish(ctx: DomainEventPublishOptions) : Promise<void> {
|
|
22
22
|
ctx.data = transformEventData(ctx.data);
|
|
23
23
|
|
|
24
24
|
for (let i = 0; i < ctx.destinations.length; i++) {
|
|
25
|
+
const destination = ctx.destinations[i];
|
|
26
|
+
|
|
25
27
|
let namespace : string;
|
|
26
|
-
if (
|
|
27
|
-
namespace =
|
|
28
|
+
if (destination.namespace) {
|
|
29
|
+
namespace = typeof destination.namespace === 'function' ?
|
|
30
|
+
destination.namespace(ctx.data) :
|
|
31
|
+
destination.namespace;
|
|
28
32
|
} else {
|
|
29
33
|
namespace = '/';
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
const emitter = new Emitter(this.client, {}, namespace);
|
|
33
37
|
|
|
34
|
-
const fullEventName = buildDomainEventFullName(
|
|
38
|
+
const fullEventName = buildDomainEventFullName(
|
|
39
|
+
ctx.metadata.domain,
|
|
40
|
+
ctx.metadata.event,
|
|
41
|
+
);
|
|
35
42
|
|
|
36
43
|
const rooms : string[] = [
|
|
37
|
-
buildEventChannelName(
|
|
44
|
+
buildEventChannelName(destination.channel),
|
|
38
45
|
];
|
|
39
46
|
|
|
40
|
-
if (typeof
|
|
41
|
-
rooms.push(buildEventChannelName(
|
|
47
|
+
if (typeof destination.channel === 'function') {
|
|
48
|
+
rooms.push(buildEventChannelName(destination.channel, ctx.data.id));
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
for (let j = 0; j < rooms.length; j++) {
|
|
45
52
|
emitter
|
|
46
53
|
.in(rooms[j])
|
|
47
54
|
.emit(fullEventName, {
|
|
48
|
-
|
|
55
|
+
data: {
|
|
56
|
+
data: ctx.data,
|
|
57
|
+
type: ctx.metadata.domain,
|
|
58
|
+
event: ctx.metadata.event,
|
|
59
|
+
},
|
|
49
60
|
meta: {
|
|
50
61
|
namespace,
|
|
51
62
|
roomName: rooms[j],
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2022-2024.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ObjectLiteral } from '@privateaim/kit';
|
|
9
|
+
|
|
10
|
+
export type DomainEventChannelName = string | ((id?: string) => string);
|
|
11
|
+
export type DomainEventNamespaceName<
|
|
12
|
+
T extends ObjectLiteral = ObjectLiteral,
|
|
13
|
+
> = string | ((data: T) => string);
|
|
14
|
+
|
|
15
|
+
export type DomainEventDestination<
|
|
16
|
+
T extends ObjectLiteral = ObjectLiteral,
|
|
17
|
+
> = {
|
|
18
|
+
namespace?: DomainEventNamespaceName<T>,
|
|
19
|
+
channel: DomainEventChannelName
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export type DomainEventDestinations<
|
|
23
|
+
T extends ObjectLiteral =ObjectLiteral,
|
|
24
|
+
> = DomainEventDestination<T>[];
|
|
25
|
+
|
|
26
|
+
export type DomainEventIdentity = {
|
|
27
|
+
id?: string,
|
|
28
|
+
name?: string,
|
|
29
|
+
type?: string,
|
|
30
|
+
ipAddress?: string,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type DomainEventMetadata = {
|
|
34
|
+
domain: string,
|
|
35
|
+
event: string,
|
|
36
|
+
identity?: DomainEventIdentity,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export type DomainEventPublishOptions<
|
|
40
|
+
T extends ObjectLiteral = ObjectLiteral,
|
|
41
|
+
> = {
|
|
42
|
+
data: T,
|
|
43
|
+
dataPrevious?: T,
|
|
44
|
+
metadata: DomainEventMetadata,
|
|
45
|
+
destinations: DomainEventDestinations<T['data']>
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export interface IDomainEventPublisher {
|
|
49
|
+
publish(ctx: DomainEventPublishOptions) : Promise<void>;
|
|
50
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { isObject } from '@privateaim/kit';
|
|
9
|
-
import type { DomainEventChannelName } from './
|
|
9
|
+
import type { DomainEventChannelName } from './types';
|
|
10
10
|
|
|
11
11
|
export function transformEventData<T>(input: T) : T {
|
|
12
12
|
if (isObject(input)) {
|
|
@@ -24,7 +24,7 @@ export function transformEventData<T>(input: T) : T {
|
|
|
24
24
|
|
|
25
25
|
export function buildEventChannelName(
|
|
26
26
|
input: DomainEventChannelName,
|
|
27
|
-
id?: string
|
|
27
|
+
id?: string,
|
|
28
28
|
) : string {
|
|
29
29
|
if (typeof input === 'string') {
|
|
30
30
|
return input;
|
package/src/services/index.ts
CHANGED
|
@@ -10,6 +10,8 @@ export * from './authup';
|
|
|
10
10
|
export * from './authup-client-authentication-hook';
|
|
11
11
|
export * from './cache';
|
|
12
12
|
export * from './domain-event';
|
|
13
|
+
export * from './loki';
|
|
14
|
+
export * from './log-store';
|
|
13
15
|
export * from './logger';
|
|
14
16
|
export * from './redis';
|
|
15
17
|
export * from './vault';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export abstract class BaseLogStore {
|
|
9
|
+
protected labels: Record<string, string>;
|
|
10
|
+
|
|
11
|
+
setLabels(labels: Record<string, string>): void {
|
|
12
|
+
this.labels = labels;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getLabels() : Record<string, string> {
|
|
16
|
+
return this.labels;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
extendLabels(labels: Record<string, string>): void {
|
|
20
|
+
const keys = Object.keys(labels);
|
|
21
|
+
for (let i = 0; i < keys.length; i++) {
|
|
22
|
+
this.labels[keys[i]] = labels[keys[i]];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025.
|
|
3
|
+
* Author Peter Placzek (tada5hi)
|
|
4
|
+
* For the full copyright and license information,
|
|
5
|
+
* view the LICENSE file that was distributed with this source code.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { Log } from '@privateaim/kit';
|
|
9
|
+
import { LogLevel } from '@privateaim/kit';
|
|
10
|
+
import type { LokiClient, LokiDistributorPushStream, LokiQuerierQueryRangeOptions } from '../../loki';
|
|
11
|
+
import { nanoSeconds } from '../../loki';
|
|
12
|
+
import type {
|
|
13
|
+
LogInput, LogStore, LogStoreDeleteOptions, LogStoreQueryOptions,
|
|
14
|
+
} from '../types';
|
|
15
|
+
import { BaseLogStore } from './base';
|
|
16
|
+
|
|
17
|
+
export class LokiLogStore extends BaseLogStore implements LogStore {
|
|
18
|
+
protected instance : LokiClient;
|
|
19
|
+
|
|
20
|
+
constructor(instance: LokiClient, labels?: Record<string, string>) {
|
|
21
|
+
super();
|
|
22
|
+
|
|
23
|
+
this.instance = instance;
|
|
24
|
+
this.labels = labels || {};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async write(message: string | LogInput, labels?: Record<string, string>): Promise<Log> {
|
|
28
|
+
let data : Log;
|
|
29
|
+
|
|
30
|
+
if (typeof message === 'string') {
|
|
31
|
+
const labelsNormalized = {
|
|
32
|
+
...this.labels,
|
|
33
|
+
...(labels || {}),
|
|
34
|
+
};
|
|
35
|
+
const level = (labelsNormalized.level || LogLevel.DEBUG) as LogLevel;
|
|
36
|
+
delete labelsNormalized.level;
|
|
37
|
+
|
|
38
|
+
data = {
|
|
39
|
+
message,
|
|
40
|
+
level,
|
|
41
|
+
time: nanoSeconds(),
|
|
42
|
+
labels: labelsNormalized,
|
|
43
|
+
};
|
|
44
|
+
} else {
|
|
45
|
+
const labelsNormalized = {
|
|
46
|
+
...this.labels,
|
|
47
|
+
...(message.labels || {}),
|
|
48
|
+
...(labels || {}),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const level = (message.level || labelsNormalized.level || LogLevel.DEBUG) as LogLevel;
|
|
52
|
+
delete labelsNormalized.level;
|
|
53
|
+
|
|
54
|
+
data = {
|
|
55
|
+
...message,
|
|
56
|
+
level,
|
|
57
|
+
time: message.time || nanoSeconds(),
|
|
58
|
+
labels: labelsNormalized,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stream : LokiDistributorPushStream = {
|
|
63
|
+
stream: data.labels,
|
|
64
|
+
values: [
|
|
65
|
+
[data.time, data.message, { level: data.level }],
|
|
66
|
+
],
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
await this.instance.distributor.push(stream);
|
|
70
|
+
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async delete(options: LogStoreDeleteOptions): Promise<void> {
|
|
75
|
+
await this.instance.compactor.createDeletionRequest({
|
|
76
|
+
start: options.start,
|
|
77
|
+
...(options.end ? { end: options.end } : {}),
|
|
78
|
+
query: this.buildQuery({
|
|
79
|
+
...this.labels,
|
|
80
|
+
...(options.labels || {}),
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async query(input: LogStoreQueryOptions): Promise<[Log[], number]> {
|
|
86
|
+
const options : LokiQuerierQueryRangeOptions = {
|
|
87
|
+
query: this.buildQuery({
|
|
88
|
+
...this.labels,
|
|
89
|
+
...(input.labels || {}),
|
|
90
|
+
}),
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
if (input.sort) {
|
|
94
|
+
options.direction = input.sort === 'DESC' ? 'forward' : 'backward';
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (input.limit) {
|
|
98
|
+
options.limit = input.limit;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (input.start) {
|
|
102
|
+
options.start = BigInt(new Date(`${input.start}`).getTime()) * 1_000_000n;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (input.end) {
|
|
106
|
+
options.end = BigInt(new Date(`${input.end}`).getTime()) * 1_000_000n;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const output : Log[] = [];
|
|
110
|
+
|
|
111
|
+
const response = await this.instance.querier.queryRange(options);
|
|
112
|
+
if (response.data.resultType === 'streams') {
|
|
113
|
+
for (let i = 0; i < response.data.result.length; i++) {
|
|
114
|
+
const set = response.data.result[i];
|
|
115
|
+
|
|
116
|
+
const labels = set.stream;
|
|
117
|
+
let level : LogLevel;
|
|
118
|
+
|
|
119
|
+
if (labels.level) {
|
|
120
|
+
level = labels.level as LogLevel;
|
|
121
|
+
} else {
|
|
122
|
+
level = labels.detected_level as LogLevel;
|
|
123
|
+
}
|
|
124
|
+
delete labels.level;
|
|
125
|
+
delete labels.detected_level;
|
|
126
|
+
|
|
127
|
+
if (!labels.service) {
|
|
128
|
+
labels.service = labels.service_name;
|
|
129
|
+
}
|
|
130
|
+
delete labels.service_name;
|
|
131
|
+
|
|
132
|
+
for (let j = 0; j < set.values.length; j++) {
|
|
133
|
+
output.push({
|
|
134
|
+
time: BigInt(set.values[j][0]),
|
|
135
|
+
message: set.values[j][1],
|
|
136
|
+
level,
|
|
137
|
+
labels,
|
|
138
|
+
} satisfies Log);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return [output, output.length];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// ----------------------------------------------
|
|
147
|
+
|
|
148
|
+
protected buildQuery(labels: Record<string, any>) : string {
|
|
149
|
+
const output : string[] = [];
|
|
150
|
+
|
|
151
|
+
const keys = Object.keys(labels);
|
|
152
|
+
for (let i = 0; i < keys.length; i++) {
|
|
153
|
+
output.push(`${keys[i]}="${labels[keys[i]]}"`);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return `{${output.join(',')}}`;
|
|
157
|
+
}
|
|
158
|
+
}
|