@omnitronix/game-engine-sdk 1.0.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.
Files changed (177) hide show
  1. package/dist/bootstrap/index.d.ts +15 -0
  2. package/dist/bootstrap/index.d.ts.map +1 -0
  3. package/dist/bootstrap/index.js +156 -0
  4. package/dist/common/api-docs/setup-documentation.d.ts +3 -0
  5. package/dist/common/api-docs/setup-documentation.d.ts.map +1 -0
  6. package/dist/common/api-docs/setup-documentation.js +27 -0
  7. package/dist/common/application-bootstrap-options.interface.d.ts +4 -0
  8. package/dist/common/application-bootstrap-options.interface.d.ts.map +1 -0
  9. package/dist/common/application-bootstrap-options.interface.js +2 -0
  10. package/dist/common/error-handling/all-exceptions.filter.d.ts +22 -0
  11. package/dist/common/error-handling/all-exceptions.filter.d.ts.map +1 -0
  12. package/dist/common/error-handling/all-exceptions.filter.js +131 -0
  13. package/dist/common/error-handling/domain.exception.d.ts +8 -0
  14. package/dist/common/error-handling/domain.exception.d.ts.map +1 -0
  15. package/dist/common/error-handling/domain.exception.js +14 -0
  16. package/dist/common/error-handling/error-code-mapper.d.ts +6 -0
  17. package/dist/common/error-handling/error-code-mapper.d.ts.map +1 -0
  18. package/dist/common/error-handling/error-code-mapper.js +93 -0
  19. package/dist/common/error-handling/internal-error-code.d.ts +67 -0
  20. package/dist/common/error-handling/internal-error-code.d.ts.map +1 -0
  21. package/dist/common/error-handling/internal-error-code.js +80 -0
  22. package/dist/common/index.d.ts +21 -0
  23. package/dist/common/index.d.ts.map +1 -0
  24. package/dist/common/index.js +51 -0
  25. package/dist/common/logger/logger.d.ts +24 -0
  26. package/dist/common/logger/logger.d.ts.map +1 -0
  27. package/dist/common/logger/logger.js +137 -0
  28. package/dist/common/logger/logger.module.d.ts +3 -0
  29. package/dist/common/logger/logger.module.d.ts.map +1 -0
  30. package/dist/common/logger/logger.module.js +19 -0
  31. package/dist/common/logger/logging.middleware.d.ts +8 -0
  32. package/dist/common/logger/logging.middleware.d.ts.map +1 -0
  33. package/dist/common/logger/logging.middleware.js +44 -0
  34. package/dist/common/metrics/database-metrics.service.d.ts +8 -0
  35. package/dist/common/metrics/database-metrics.service.d.ts.map +1 -0
  36. package/dist/common/metrics/database-metrics.service.js +39 -0
  37. package/dist/common/metrics/helpers/metrics.helpers.d.ts +5 -0
  38. package/dist/common/metrics/helpers/metrics.helpers.d.ts.map +1 -0
  39. package/dist/common/metrics/helpers/metrics.helpers.js +38 -0
  40. package/dist/common/metrics/metrics.module.d.ts +3 -0
  41. package/dist/common/metrics/metrics.module.d.ts.map +1 -0
  42. package/dist/common/metrics/metrics.module.js +207 -0
  43. package/dist/common/metrics/metrics.port.d.ts +22 -0
  44. package/dist/common/metrics/metrics.port.d.ts.map +1 -0
  45. package/dist/common/metrics/metrics.port.js +4 -0
  46. package/dist/common/metrics/prometheus.service.d.ts +25 -0
  47. package/dist/common/metrics/prometheus.service.d.ts.map +1 -0
  48. package/dist/common/metrics/prometheus.service.js +105 -0
  49. package/dist/common/retry/retry-policies.d.ts +8 -0
  50. package/dist/common/retry/retry-policies.d.ts.map +1 -0
  51. package/dist/common/retry/retry-policies.js +43 -0
  52. package/dist/common/retry/retry-policy.d.ts +25 -0
  53. package/dist/common/retry/retry-policy.d.ts.map +1 -0
  54. package/dist/common/retry/retry-policy.js +65 -0
  55. package/dist/common/secrets-provider/secrets-provider.aws.d.ts +13 -0
  56. package/dist/common/secrets-provider/secrets-provider.aws.d.ts.map +1 -0
  57. package/dist/common/secrets-provider/secrets-provider.aws.js +72 -0
  58. package/dist/common/secrets-provider/secrets-provider.d.ts +5 -0
  59. package/dist/common/secrets-provider/secrets-provider.d.ts.map +1 -0
  60. package/dist/common/secrets-provider/secrets-provider.js +4 -0
  61. package/dist/common/secrets-provider/secrets-provider.local.d.ts +8 -0
  62. package/dist/common/secrets-provider/secrets-provider.local.d.ts.map +1 -0
  63. package/dist/common/secrets-provider/secrets-provider.local.js +75 -0
  64. package/dist/common/secrets-provider/secrets-provider.module.d.ts +5 -0
  65. package/dist/common/secrets-provider/secrets-provider.module.d.ts.map +1 -0
  66. package/dist/common/secrets-provider/secrets-provider.module.js +47 -0
  67. package/dist/esm/bootstrap/index.js +120 -0
  68. package/dist/esm/common/api-docs/setup-documentation.js +23 -0
  69. package/dist/esm/common/application-bootstrap-options.interface.js +1 -0
  70. package/dist/esm/common/error-handling/all-exceptions.filter.js +128 -0
  71. package/dist/esm/common/error-handling/domain.exception.js +10 -0
  72. package/dist/esm/common/error-handling/error-code-mapper.js +89 -0
  73. package/dist/esm/common/error-handling/internal-error-code.js +77 -0
  74. package/dist/esm/common/index.js +25 -0
  75. package/dist/esm/common/logger/logger.js +133 -0
  76. package/dist/esm/common/logger/logger.module.js +16 -0
  77. package/dist/esm/common/logger/logging.middleware.js +41 -0
  78. package/dist/esm/common/metrics/database-metrics.service.js +36 -0
  79. package/dist/esm/common/metrics/helpers/metrics.helpers.js +32 -0
  80. package/dist/esm/common/metrics/metrics.module.js +204 -0
  81. package/dist/esm/common/metrics/metrics.port.js +1 -0
  82. package/dist/esm/common/metrics/prometheus.service.js +102 -0
  83. package/dist/esm/common/retry/retry-policies.js +39 -0
  84. package/dist/esm/common/retry/retry-policy.js +61 -0
  85. package/dist/esm/common/secrets-provider/secrets-provider.aws.js +69 -0
  86. package/dist/esm/common/secrets-provider/secrets-provider.js +1 -0
  87. package/dist/esm/common/secrets-provider/secrets-provider.local.js +39 -0
  88. package/dist/esm/common/secrets-provider/secrets-provider.module.js +44 -0
  89. package/dist/esm/generated/game-engine-registry_pb.js +28 -0
  90. package/dist/esm/generated/game-engine_pb.js +57 -0
  91. package/dist/esm/grpc/connect-router.middleware.js +16 -0
  92. package/dist/esm/grpc/game-engine.grpc.in-adapter.js +109 -0
  93. package/dist/esm/grpc/index.js +2 -0
  94. package/dist/esm/health/application/ports/in/health-in.port.js +1 -0
  95. package/dist/esm/health/application/ports/out/database-health.out-port.js +1 -0
  96. package/dist/esm/health/application/ports/out/shutdown.out-port.js +1 -0
  97. package/dist/esm/health/application/ports/out/system-health.out-port.js +1 -0
  98. package/dist/esm/health/application/services/health.service.js +81 -0
  99. package/dist/esm/health/domain/health.js +7 -0
  100. package/dist/esm/health/health.module.js +65 -0
  101. package/dist/esm/health/index.js +15 -0
  102. package/dist/esm/health/infrastructure/adapters/in/health.http.in-adapter.js +96 -0
  103. package/dist/esm/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.js +45 -0
  104. package/dist/esm/health/infrastructure/adapters/out/system/system-health.out-adapter.js +43 -0
  105. package/dist/esm/index.js +15 -0
  106. package/dist/esm/registration/adapters/game-engine-registry.grpc.out-adapter.js +59 -0
  107. package/dist/esm/registration/index.js +3 -0
  108. package/dist/esm/registration/ports/game-engine-registry.out-port.js +1 -0
  109. package/dist/esm/registration/services/game-engine-auto-register.service.js +78 -0
  110. package/dist/esm/types.js +8 -0
  111. package/dist/generated/game-engine-registry_pb.d.ts +76 -0
  112. package/dist/generated/game-engine-registry_pb.d.ts.map +1 -0
  113. package/dist/generated/game-engine-registry_pb.js +31 -0
  114. package/dist/generated/game-engine_pb.d.ts +171 -0
  115. package/dist/generated/game-engine_pb.d.ts.map +1 -0
  116. package/dist/generated/game-engine_pb.js +60 -0
  117. package/dist/grpc/connect-router.middleware.d.ts +7 -0
  118. package/dist/grpc/connect-router.middleware.d.ts.map +1 -0
  119. package/dist/grpc/connect-router.middleware.js +19 -0
  120. package/dist/grpc/game-engine.grpc.in-adapter.d.ts +21 -0
  121. package/dist/grpc/game-engine.grpc.in-adapter.d.ts.map +1 -0
  122. package/dist/grpc/game-engine.grpc.in-adapter.js +112 -0
  123. package/dist/grpc/index.d.ts +3 -0
  124. package/dist/grpc/index.d.ts.map +1 -0
  125. package/dist/grpc/index.js +7 -0
  126. package/dist/health/application/ports/in/health-in.port.d.ts +7 -0
  127. package/dist/health/application/ports/in/health-in.port.d.ts.map +1 -0
  128. package/dist/health/application/ports/in/health-in.port.js +4 -0
  129. package/dist/health/application/ports/out/database-health.out-port.d.ts +6 -0
  130. package/dist/health/application/ports/out/database-health.out-port.d.ts.map +1 -0
  131. package/dist/health/application/ports/out/database-health.out-port.js +4 -0
  132. package/dist/health/application/ports/out/shutdown.out-port.d.ts +6 -0
  133. package/dist/health/application/ports/out/shutdown.out-port.d.ts.map +1 -0
  134. package/dist/health/application/ports/out/shutdown.out-port.js +4 -0
  135. package/dist/health/application/ports/out/system-health.out-port.d.ts +7 -0
  136. package/dist/health/application/ports/out/system-health.out-port.d.ts.map +1 -0
  137. package/dist/health/application/ports/out/system-health.out-port.js +4 -0
  138. package/dist/health/application/services/health.service.d.ts +13 -0
  139. package/dist/health/application/services/health.service.d.ts.map +1 -0
  140. package/dist/health/application/services/health.service.js +84 -0
  141. package/dist/health/domain/health.d.ts +15 -0
  142. package/dist/health/domain/health.d.ts.map +1 -0
  143. package/dist/health/domain/health.js +11 -0
  144. package/dist/health/health.module.d.ts +10 -0
  145. package/dist/health/health.module.d.ts.map +1 -0
  146. package/dist/health/health.module.js +68 -0
  147. package/dist/health/index.d.ts +11 -0
  148. package/dist/health/index.d.ts.map +1 -0
  149. package/dist/health/index.js +28 -0
  150. package/dist/health/infrastructure/adapters/in/health.http.in-adapter.d.ts +16 -0
  151. package/dist/health/infrastructure/adapters/in/health.http.in-adapter.d.ts.map +1 -0
  152. package/dist/health/infrastructure/adapters/in/health.http.in-adapter.js +99 -0
  153. package/dist/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.d.ts +13 -0
  154. package/dist/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.d.ts.map +1 -0
  155. package/dist/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.js +48 -0
  156. package/dist/health/infrastructure/adapters/out/system/system-health.out-adapter.d.ts +12 -0
  157. package/dist/health/infrastructure/adapters/out/system/system-health.out-adapter.d.ts.map +1 -0
  158. package/dist/health/infrastructure/adapters/out/system/system-health.out-adapter.js +46 -0
  159. package/dist/index.d.ts +9 -0
  160. package/dist/index.d.ts.map +1 -0
  161. package/dist/index.js +43 -0
  162. package/dist/registration/adapters/game-engine-registry.grpc.out-adapter.d.ts +12 -0
  163. package/dist/registration/adapters/game-engine-registry.grpc.out-adapter.d.ts.map +1 -0
  164. package/dist/registration/adapters/game-engine-registry.grpc.out-adapter.js +62 -0
  165. package/dist/registration/index.d.ts +4 -0
  166. package/dist/registration/index.d.ts.map +1 -0
  167. package/dist/registration/index.js +9 -0
  168. package/dist/registration/ports/game-engine-registry.out-port.d.ts +9 -0
  169. package/dist/registration/ports/game-engine-registry.out-port.d.ts.map +1 -0
  170. package/dist/registration/ports/game-engine-registry.out-port.js +4 -0
  171. package/dist/registration/services/game-engine-auto-register.service.d.ts +14 -0
  172. package/dist/registration/services/game-engine-auto-register.service.d.ts.map +1 -0
  173. package/dist/registration/services/game-engine-auto-register.service.js +81 -0
  174. package/dist/types.d.ts +53 -0
  175. package/dist/types.d.ts.map +1 -0
  176. package/dist/types.js +11 -0
  177. package/package.json +159 -0
@@ -0,0 +1,133 @@
1
+ import { DomainException } from '../error-handling/domain.exception';
2
+ import { createLogger, format, transports } from 'winston';
3
+ export class Logger {
4
+ constructor(context, logFormat) {
5
+ this.context = context;
6
+ const format = logFormat ?? this.detectLogFormat();
7
+ this.logger = this.createWinstonLogger(format);
8
+ }
9
+ detectLogFormat() {
10
+ const envFormat = process.env.LOG_FORMAT?.toLowerCase();
11
+ switch (envFormat) {
12
+ case 'pretty':
13
+ return 'pretty';
14
+ case 'json':
15
+ return 'json';
16
+ default:
17
+ return 'json';
18
+ }
19
+ }
20
+ createWinstonLogger(logFormat) {
21
+ const winstonFormat = this.getLogFormat(logFormat);
22
+ return createLogger({
23
+ level: 'info',
24
+ format: winstonFormat,
25
+ transports: this.getTransports(),
26
+ });
27
+ }
28
+ getLogFormat(logFormat) {
29
+ return format.combine(format.timestamp(), this.selectFormat(logFormat));
30
+ }
31
+ selectFormat(logFormat) {
32
+ switch (logFormat) {
33
+ case 'pretty':
34
+ return this.getPrettyFormat();
35
+ case 'json':
36
+ return this.getJsonFormat();
37
+ default:
38
+ return this.getJsonFormat();
39
+ }
40
+ }
41
+ getJsonFormat() {
42
+ return format.combine(format(info => {
43
+ if (this.context) {
44
+ info.message = `[${this.context}] ${info.message}`;
45
+ }
46
+ return info;
47
+ })(), format.json());
48
+ }
49
+ getPrettyFormat() {
50
+ return format.combine(format.colorize(), format.printf(({ timestamp, level, message, error, ...meta }) => {
51
+ const contextStr = this.context ? `[${this.context}] ` : '';
52
+ let output = `${timestamp} ${level}: ${contextStr}${message}`;
53
+ if (error && typeof error === 'object' && 'name' in error && 'message' in error) {
54
+ output += `\n Error: ${error.name}: ${error.message}`;
55
+ if (error.name === 'DomainException' && 'errorCode' in error) {
56
+ output += `\n Internal Code: ${error.errorCode}`;
57
+ }
58
+ if ('stack' in error && error.stack) {
59
+ output += `\n Stack: ${error.stack}`;
60
+ }
61
+ }
62
+ const metaKeys = Object.keys(meta).filter(key => key !== 'timestamp' && key !== 'level' && key !== 'message');
63
+ if (metaKeys.length > 0) {
64
+ output += `\n Meta: ${JSON.stringify(meta, null, 2)}`;
65
+ }
66
+ return output;
67
+ }));
68
+ }
69
+ safeStringify(obj) {
70
+ try {
71
+ return JSON.stringify(obj, (key, value) => {
72
+ if (typeof value === 'bigint') {
73
+ return value.toString();
74
+ }
75
+ return value;
76
+ });
77
+ }
78
+ catch (_error) {
79
+ return '[Object cannot be serialized]';
80
+ }
81
+ }
82
+ getTransports() {
83
+ return [new transports.Console(), new transports.File({ filename: 'logs/app.log' })];
84
+ }
85
+ log(message, { level = 'info', ...rest } = {}) {
86
+ switch (level) {
87
+ case 'error':
88
+ this.logger.error(message, rest);
89
+ break;
90
+ case 'warn':
91
+ this.logger.warn(message, rest);
92
+ break;
93
+ case 'debug':
94
+ this.logger.debug(message, rest);
95
+ break;
96
+ case 'verbose':
97
+ this.logger.verbose(message, rest);
98
+ break;
99
+ default:
100
+ this.logger.info(message, rest);
101
+ break;
102
+ }
103
+ }
104
+ error(message, ...optionalParams) {
105
+ if (optionalParams.length > 0 && optionalParams[0] instanceof Error) {
106
+ const error = optionalParams[0];
107
+ const errorData = {
108
+ name: error.name,
109
+ message: error.message,
110
+ stack: error.stack,
111
+ };
112
+ if (error instanceof DomainException) {
113
+ errorData.errorCode = error.errorCode;
114
+ }
115
+ this.logger.error(message, {
116
+ error: errorData,
117
+ ...optionalParams.slice(1),
118
+ });
119
+ }
120
+ else {
121
+ this.logger.error(message, ...optionalParams);
122
+ }
123
+ }
124
+ warn(message, ...optionalParams) {
125
+ this.logger.warn(message, ...optionalParams);
126
+ }
127
+ debug(message, ...optionalParams) {
128
+ this.logger.debug(message, ...optionalParams);
129
+ }
130
+ verbose(message, ...optionalParams) {
131
+ this.logger.verbose(message, ...optionalParams);
132
+ }
133
+ }
@@ -0,0 +1,16 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Module } from '@nestjs/common';
8
+ import { ConfigModule } from '@nestjs/config';
9
+ let LoggerModule = class LoggerModule {
10
+ };
11
+ LoggerModule = __decorate([
12
+ Module({
13
+ imports: [ConfigModule],
14
+ })
15
+ ], LoggerModule);
16
+ export { LoggerModule };
@@ -0,0 +1,41 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var LoggingMiddleware_1;
11
+ import { Injectable } from '@nestjs/common';
12
+ import { Logger } from './logger';
13
+ const BLOCKED_ENDPOINTS = ['/api/races/active'];
14
+ let LoggingMiddleware = LoggingMiddleware_1 = class LoggingMiddleware {
15
+ constructor() {
16
+ this.logger = new Logger(LoggingMiddleware_1.name);
17
+ }
18
+ use(req, res, next) {
19
+ const { method, originalUrl, body } = req;
20
+ const sanitizedBody = { ...body };
21
+ if (sanitizedBody.password) {
22
+ sanitizedBody.password = '***';
23
+ }
24
+ if (sanitizedBody.token) {
25
+ sanitizedBody.token = '***';
26
+ }
27
+ res.on('finish', () => {
28
+ const isBlockedEndpoint = BLOCKED_ENDPOINTS.some(endpoint => originalUrl.includes(endpoint));
29
+ const isSuccessfulRequest = res.statusCode < 400;
30
+ if (!(isBlockedEndpoint && isSuccessfulRequest)) {
31
+ this.logger.log(`Request: ${method} ${originalUrl} | Body: ${JSON.stringify(sanitizedBody)}`);
32
+ }
33
+ });
34
+ next();
35
+ }
36
+ };
37
+ LoggingMiddleware = LoggingMiddleware_1 = __decorate([
38
+ Injectable(),
39
+ __metadata("design:paramtypes", [])
40
+ ], LoggingMiddleware);
41
+ export { LoggingMiddleware };
@@ -0,0 +1,36 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { METRICS_PORT } from './metrics.port';
14
+ import { Inject, Injectable } from '@nestjs/common';
15
+ let DatabaseMetricsService = class DatabaseMetricsService {
16
+ constructor(metricsPort) {
17
+ this.metricsPort = metricsPort;
18
+ }
19
+ updateConnectionPoolSize(poolType, state, size) {
20
+ this.metricsPort.getGauge('rgs_db_connection_pool_size').set({
21
+ pool_type: poolType,
22
+ state,
23
+ }, size);
24
+ }
25
+ trackConnectionError(errorType) {
26
+ this.metricsPort.getCounter('rgs_db_connection_errors_total').inc({
27
+ error_type: errorType,
28
+ });
29
+ }
30
+ };
31
+ DatabaseMetricsService = __decorate([
32
+ Injectable(),
33
+ __param(0, Inject(METRICS_PORT)),
34
+ __metadata("design:paramtypes", [Object])
35
+ ], DatabaseMetricsService);
36
+ export { DatabaseMetricsService };
@@ -0,0 +1,32 @@
1
+ export function toMinorUnits(amount) {
2
+ return Math.round(amount * 100);
3
+ }
4
+ export function getEventCountBucket(count) {
5
+ if (count <= 5)
6
+ return '1-5';
7
+ if (count <= 10)
8
+ return '6-10';
9
+ if (count <= 25)
10
+ return '11-25';
11
+ if (count <= 50)
12
+ return '26-50';
13
+ if (count <= 100)
14
+ return '51-100';
15
+ return '100+';
16
+ }
17
+ export function getStreamVersionBucket(version) {
18
+ if (version <= 10)
19
+ return '1-10';
20
+ if (version <= 50)
21
+ return '11-50';
22
+ if (version <= 100)
23
+ return '51-100';
24
+ if (version <= 500)
25
+ return '101-500';
26
+ return '500+';
27
+ }
28
+ export function sanitizeRoute(route) {
29
+ return route
30
+ .replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '/:id')
31
+ .replace(/\/\d+/g, '/:id');
32
+ }
@@ -0,0 +1,204 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { ExceptionsFilter } from '../error-handling/all-exceptions.filter';
8
+ import { Module } from '@nestjs/common';
9
+ import { makeCounterProvider, makeGaugeProvider, makeHistogramProvider, } from '@willsoto/nestjs-prometheus';
10
+ import { METRICS_PORT } from './metrics.port';
11
+ import { PrometheusService } from './prometheus.service';
12
+ let MetricsModule = class MetricsModule {
13
+ };
14
+ MetricsModule = __decorate([
15
+ Module({
16
+ providers: [
17
+ {
18
+ provide: METRICS_PORT,
19
+ useClass: PrometheusService,
20
+ },
21
+ ExceptionsFilter,
22
+ makeHistogramProvider({
23
+ name: 'rgs_http_server_requests_duration_ms',
24
+ help: 'Duration of HTTP requests in milliseconds',
25
+ labelNames: ['method', 'route', 'status_code', 'operator_code'],
26
+ buckets: [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],
27
+ }),
28
+ makeGaugeProvider({
29
+ name: 'rgs_ws_connections',
30
+ help: 'Current number of WebSocket connections',
31
+ labelNames: ['state', 'operator_code'],
32
+ }),
33
+ makeCounterProvider({
34
+ name: 'rgs_ws_messages_total',
35
+ help: 'Total WebSocket messages sent or received',
36
+ labelNames: ['type', 'operator_code', 'event_name'],
37
+ }),
38
+ makeHistogramProvider({
39
+ name: 'rgs_ws_event_duration_ms',
40
+ help: 'Duration of WebSocket event processing in milliseconds',
41
+ labelNames: ['event_name', 'operator_code'],
42
+ buckets: [5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],
43
+ }),
44
+ makeCounterProvider({
45
+ name: 'rgs_sessions_total',
46
+ help: 'Total number of game sessions by final status',
47
+ labelNames: ['operator_code', 'game_code', 'jurisdiction', 'status'],
48
+ }),
49
+ makeGaugeProvider({
50
+ name: 'rgs_sessions_active',
51
+ help: 'Current number of active game sessions',
52
+ labelNames: ['operator_code', 'game_code', 'jurisdiction'],
53
+ }),
54
+ makeHistogramProvider({
55
+ name: 'rgs_session_duration_ms',
56
+ help: 'Game session duration from init to end in milliseconds',
57
+ labelNames: ['operator_code', 'game_code', 'jurisdiction', 'end_status'],
58
+ buckets: [10000, 30000, 60000, 120000, 300000, 600000, 1800000, 3600000],
59
+ }),
60
+ makeCounterProvider({
61
+ name: 'rgs_rounds_completed_total',
62
+ help: 'Total game rounds completed',
63
+ labelNames: ['operator_code', 'game_code', 'jurisdiction', 'result'],
64
+ }),
65
+ makeHistogramProvider({
66
+ name: 'rgs_wager_minor_units',
67
+ help: 'Wager amounts in minor units',
68
+ labelNames: ['operator_code', 'game_code', 'jurisdiction', 'currency'],
69
+ buckets: [10, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000],
70
+ }),
71
+ makeHistogramProvider({
72
+ name: 'rgs_win_minor_units',
73
+ help: 'Win amounts in minor units',
74
+ labelNames: ['operator_code', 'game_code', 'jurisdiction', 'currency'],
75
+ buckets: [10, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000],
76
+ }),
77
+ makeCounterProvider({
78
+ name: 'rgs_wallet_requests_total',
79
+ help: 'Total wallet API requests',
80
+ labelNames: ['operation_type', 'operator_code', 'currency', 'status'],
81
+ }),
82
+ makeHistogramProvider({
83
+ name: 'rgs_wallet_requests_duration_ms',
84
+ help: 'Duration of wallet API requests in milliseconds',
85
+ labelNames: ['operation_type', 'operator_code', 'status'],
86
+ buckets: [10, 50, 100, 250, 500, 1000, 2000, 5000, 10000],
87
+ }),
88
+ makeHistogramProvider({
89
+ name: 'game_engine_command_duration_ms',
90
+ help: 'Duration of game engine command processing in milliseconds',
91
+ labelNames: ['command_type', 'game_code', 'game_version'],
92
+ buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000],
93
+ }),
94
+ makeCounterProvider({
95
+ name: 'game_engine_commands_total',
96
+ help: 'Total game engine commands processed',
97
+ labelNames: ['command_type', 'game_code', 'game_version'],
98
+ }),
99
+ makeCounterProvider({
100
+ name: 'game_engine_errors_total',
101
+ help: 'Total game engine errors or exceptions',
102
+ labelNames: ['game_code', 'game_version', 'error_type'],
103
+ }),
104
+ makeCounterProvider({
105
+ name: 'game_engine_rng_calls_total',
106
+ help: 'Total RNG calls made by game engine',
107
+ labelNames: ['game_code', 'game_version'],
108
+ }),
109
+ makeHistogramProvider({
110
+ name: 'rgs_event_store_write_duration_ms',
111
+ help: 'Event store write duration',
112
+ labelNames: ['aggregate_type', 'event_count_bucket'],
113
+ buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2000],
114
+ }),
115
+ makeHistogramProvider({
116
+ name: 'rgs_event_store_read_duration_ms',
117
+ help: 'Event store read duration',
118
+ labelNames: ['aggregate_type', 'stream_version_bucket'],
119
+ buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2000],
120
+ }),
121
+ makeHistogramProvider({
122
+ name: 'rgs_aggregate_reconstruction_duration_ms',
123
+ help: 'Aggregate reconstruction time',
124
+ labelNames: ['aggregate_type', 'events_count_bucket'],
125
+ buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2000],
126
+ }),
127
+ makeHistogramProvider({
128
+ name: 'rgs_aggregate_reconstruction_events',
129
+ help: 'Number of events in reconstruction',
130
+ labelNames: ['aggregate_type'],
131
+ buckets: [1, 5, 10, 25, 50, 100, 250, 500],
132
+ }),
133
+ makeGaugeProvider({
134
+ name: 'rgs_db_connection_pool_size',
135
+ help: 'Connection pool size',
136
+ labelNames: ['pool_type', 'state'],
137
+ }),
138
+ makeCounterProvider({
139
+ name: 'rgs_db_connection_errors_total',
140
+ help: 'Database connection errors',
141
+ labelNames: ['error_type'],
142
+ }),
143
+ makeGaugeProvider({
144
+ name: 'rgs_games_total',
145
+ help: 'Total games in catalog',
146
+ labelNames: ['status'],
147
+ }),
148
+ makeGaugeProvider({
149
+ name: 'rgs_game_configs_total',
150
+ help: 'Total game configurations per jurisdiction',
151
+ labelNames: ['jurisdiction'],
152
+ }),
153
+ makeGaugeProvider({
154
+ name: 'rgs_enabled_games_per_operator',
155
+ help: 'Enabled games count per operator',
156
+ labelNames: ['operator_code', 'jurisdiction'],
157
+ }),
158
+ makeGaugeProvider({
159
+ name: 'rng_buffer_capacity',
160
+ help: 'Capacity of the RNG buffer',
161
+ labelNames: ['rng_range', 'engine_type', 'game_code'],
162
+ }),
163
+ makeGaugeProvider({
164
+ name: 'rng_buffer_fill_level',
165
+ help: 'Current fill level of the RNG buffer',
166
+ labelNames: ['rng_range', 'engine_type', 'game_code'],
167
+ }),
168
+ makeGaugeProvider({
169
+ name: 'rng_buffer_fill_ratio',
170
+ help: 'Current fill ratio of the RNG buffer',
171
+ labelNames: ['rng_range', 'engine_type', 'game_code'],
172
+ }),
173
+ makeCounterProvider({
174
+ name: 'rng_buffer_refill_requests_total',
175
+ help: 'Total number of RNG buffer refill requests',
176
+ labelNames: ['rng_range', 'engine_type', 'reason', 'game_code'],
177
+ }),
178
+ makeCounterProvider({
179
+ name: 'rng_buffer_refill_failures_total',
180
+ help: 'Total number of failed RNG buffer refill requests',
181
+ labelNames: ['rng_range', 'engine_type', 'reason', 'error', 'game_code'],
182
+ }),
183
+ makeHistogramProvider({
184
+ name: 'rng_buffer_refill_duration_ms',
185
+ help: 'Duration of RNG buffer refill operations in milliseconds',
186
+ labelNames: ['rng_range', 'engine_type', 'game_code'],
187
+ buckets: [1, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],
188
+ }),
189
+ makeCounterProvider({
190
+ name: 'rng_buffer_starvation_events_total',
191
+ help: 'Total number of RNG buffer starvation events',
192
+ labelNames: ['rng_range', 'engine_type', 'game_code'],
193
+ }),
194
+ makeHistogramProvider({
195
+ name: 'rng_buffer_latency_ms',
196
+ help: 'Latency of RNG buffer operations in milliseconds',
197
+ labelNames: ['rng_range', 'engine_type', 'game_code'],
198
+ buckets: [1, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000],
199
+ }),
200
+ ],
201
+ exports: [METRICS_PORT],
202
+ })
203
+ ], MetricsModule);
204
+ export { MetricsModule };
@@ -0,0 +1 @@
1
+ export const METRICS_PORT = Symbol('METRICS_PORT');
@@ -0,0 +1,102 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Injectable } from '@nestjs/common';
14
+ import { InjectMetric } from '@willsoto/nestjs-prometheus';
15
+ import { Counter as PromCounter, Gauge as PromGauge, Histogram as PromHistogram, } from 'prom-client';
16
+ let PrometheusService = class PrometheusService {
17
+ constructor(engineCommandsTotal, engineErrorsTotal, engineRngCallsTotal, engineCommandDuration, rngBufferCapacity, rngBufferFillLevel, rngBufferFillRatio, rngBufferRefillRequestsTotal, rngBufferRefillFailuresTotal, rngBufferRefillDuration, rngBufferStarvationEventsTotal, rngBufferLatency) {
18
+ this.engineCommandsTotal = engineCommandsTotal;
19
+ this.engineErrorsTotal = engineErrorsTotal;
20
+ this.engineRngCallsTotal = engineRngCallsTotal;
21
+ this.engineCommandDuration = engineCommandDuration;
22
+ this.rngBufferCapacity = rngBufferCapacity;
23
+ this.rngBufferFillLevel = rngBufferFillLevel;
24
+ this.rngBufferFillRatio = rngBufferFillRatio;
25
+ this.rngBufferRefillRequestsTotal = rngBufferRefillRequestsTotal;
26
+ this.rngBufferRefillFailuresTotal = rngBufferRefillFailuresTotal;
27
+ this.rngBufferRefillDuration = rngBufferRefillDuration;
28
+ this.rngBufferStarvationEventsTotal = rngBufferStarvationEventsTotal;
29
+ this.rngBufferLatency = rngBufferLatency;
30
+ this.metricsRegistry = new Map();
31
+ this.initializeRegistry();
32
+ }
33
+ initializeMetricsFromDatabase() {
34
+ throw new Error('Method not implemented.');
35
+ }
36
+ initializeRegistry() {
37
+ this.metricsRegistry.set('game_engine_commands_total', this.engineCommandsTotal);
38
+ this.metricsRegistry.set('game_engine_errors_total', this.engineErrorsTotal);
39
+ this.metricsRegistry.set('game_engine_rng_calls_total', this.engineRngCallsTotal);
40
+ this.metricsRegistry.set('game_engine_command_duration_ms', this.engineCommandDuration);
41
+ this.metricsRegistry.set('rng_buffer_capacity', this.rngBufferCapacity);
42
+ this.metricsRegistry.set('rng_buffer_fill_level', this.rngBufferFillLevel);
43
+ this.metricsRegistry.set('rng_buffer_fill_ratio', this.rngBufferFillRatio);
44
+ this.metricsRegistry.set('rng_buffer_refill_requests_total', this.rngBufferRefillRequestsTotal);
45
+ this.metricsRegistry.set('rng_buffer_refill_failures_total', this.rngBufferRefillFailuresTotal);
46
+ this.metricsRegistry.set('rng_buffer_refill_duration_ms', this.rngBufferRefillDuration);
47
+ this.metricsRegistry.set('rng_buffer_starvation_events_total', this.rngBufferStarvationEventsTotal);
48
+ this.metricsRegistry.set('rng_buffer_latency_ms', this.rngBufferLatency);
49
+ }
50
+ getCounter(name) {
51
+ const metric = this.metricsRegistry.get(name);
52
+ if (!metric) {
53
+ throw new Error(`Counter ${name} not found in metrics registry`);
54
+ }
55
+ return metric;
56
+ }
57
+ getGauge(name) {
58
+ const metric = this.metricsRegistry.get(name);
59
+ if (!metric) {
60
+ throw new Error(`Gauge ${name} not found in metrics registry`);
61
+ }
62
+ return metric;
63
+ }
64
+ getHistogram(name) {
65
+ const metric = this.metricsRegistry.get(name);
66
+ if (!metric) {
67
+ throw new Error(`Histogram ${name} not found in metrics registry`);
68
+ }
69
+ return metric;
70
+ }
71
+ async getMetrics() {
72
+ return '';
73
+ }
74
+ };
75
+ PrometheusService = __decorate([
76
+ Injectable(),
77
+ __param(0, InjectMetric('game_engine_commands_total')),
78
+ __param(1, InjectMetric('game_engine_errors_total')),
79
+ __param(2, InjectMetric('game_engine_rng_calls_total')),
80
+ __param(3, InjectMetric('game_engine_command_duration_ms')),
81
+ __param(4, InjectMetric('rng_buffer_capacity')),
82
+ __param(5, InjectMetric('rng_buffer_fill_level')),
83
+ __param(6, InjectMetric('rng_buffer_fill_ratio')),
84
+ __param(7, InjectMetric('rng_buffer_refill_requests_total')),
85
+ __param(8, InjectMetric('rng_buffer_refill_failures_total')),
86
+ __param(9, InjectMetric('rng_buffer_refill_duration_ms')),
87
+ __param(10, InjectMetric('rng_buffer_starvation_events_total')),
88
+ __param(11, InjectMetric('rng_buffer_latency_ms')),
89
+ __metadata("design:paramtypes", [PromCounter,
90
+ PromCounter,
91
+ PromCounter,
92
+ PromHistogram,
93
+ PromGauge,
94
+ PromGauge,
95
+ PromGauge,
96
+ PromCounter,
97
+ PromCounter,
98
+ PromHistogram,
99
+ PromCounter,
100
+ PromHistogram])
101
+ ], PrometheusService);
102
+ export { PrometheusService };
@@ -0,0 +1,39 @@
1
+ import { RetryPolicy } from './retry-policy';
2
+ export const HTTP_RETRYABLE_ERRORS = [
3
+ 'TIMEOUT',
4
+ 'ETIMEDOUT',
5
+ 'ECONNRESET',
6
+ 'ECONNREFUSED',
7
+ 'EAI_AGAIN',
8
+ 'ENOTFOUND',
9
+ 'NETWORK',
10
+ ];
11
+ export class RetryPolicies {
12
+ static walletOperation() {
13
+ return new RetryPolicy({
14
+ maxAttempts: 5,
15
+ delayMs: 200,
16
+ backoffMultiplier: 2,
17
+ maxDelayMs: 3000,
18
+ retryableErrors: HTTP_RETRYABLE_ERRORS,
19
+ });
20
+ }
21
+ static externalApi() {
22
+ return new RetryPolicy({
23
+ maxAttempts: 3,
24
+ delayMs: 100,
25
+ backoffMultiplier: 2,
26
+ maxDelayMs: 1000,
27
+ retryableErrors: HTTP_RETRYABLE_ERRORS,
28
+ });
29
+ }
30
+ static database() {
31
+ return new RetryPolicy({
32
+ maxAttempts: 3,
33
+ delayMs: 50,
34
+ backoffMultiplier: 2,
35
+ maxDelayMs: 500,
36
+ retryableErrors: ['deadlock', 'serialization', 'timeout'],
37
+ });
38
+ }
39
+ }
@@ -0,0 +1,61 @@
1
+ import { Logger } from '../logger/logger';
2
+ export class RetryPolicy {
3
+ constructor(options) {
4
+ this.logger = new Logger(RetryPolicy.name);
5
+ this.maxAttempts = Math.max(1, options.maxAttempts);
6
+ this.delayMs = Math.max(0, options.delayMs);
7
+ this.backoffMultiplier = options.backoffMultiplier ?? 1;
8
+ this.maxDelayMs = options.maxDelayMs ?? Number.POSITIVE_INFINITY;
9
+ this.retryableErrors = options.retryableErrors;
10
+ this.onRetry = options.onRetry;
11
+ this.operationName = options.operationName;
12
+ }
13
+ async execute(fn) {
14
+ let lastError = null;
15
+ for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
16
+ try {
17
+ const result = await fn();
18
+ if (attempt > 1) {
19
+ this.logger.log(`${this.operationName ?? 'operation'} succeeded on attempt ${attempt}`);
20
+ }
21
+ return result;
22
+ }
23
+ catch (error) {
24
+ const err = error;
25
+ lastError = err;
26
+ if (!this.isRetryable(err)) {
27
+ throw err;
28
+ }
29
+ if (attempt === this.maxAttempts) {
30
+ this.logger.error(`${this.operationName ?? 'operation'} failed after ${attempt} attempts: ${err.message}`, err);
31
+ break;
32
+ }
33
+ const delay = this.calculateDelay(attempt);
34
+ this.logger.warn(`${this.operationName ?? 'operation'} failed on attempt ${attempt}/${this.maxAttempts} with error: ${err.message}. Retrying in ${delay}ms...`);
35
+ if (this.onRetry) {
36
+ try {
37
+ this.onRetry(attempt, err);
38
+ }
39
+ catch { }
40
+ }
41
+ await this.sleep(delay);
42
+ }
43
+ }
44
+ throw lastError ?? new Error('RetryPolicy failed without error');
45
+ }
46
+ isRetryable(error) {
47
+ if (!this.retryableErrors || this.retryableErrors.length === 0)
48
+ return true;
49
+ const causeCode = error?.cause?.code ?? '';
50
+ const text = `${error?.code ?? ''} ${error?.name ?? ''} ${error.message} ${causeCode}`;
51
+ return this.retryableErrors.some(pattern => text.includes(pattern));
52
+ }
53
+ calculateDelay(attempt) {
54
+ const factor = Math.max(1, this.backoffMultiplier);
55
+ const raw = this.delayMs * Math.pow(factor, attempt - 1);
56
+ return Math.min(raw, this.maxDelayMs);
57
+ }
58
+ async sleep(ms) {
59
+ await new Promise(resolve => setTimeout(resolve, ms));
60
+ }
61
+ }