@omnitronix/game-engine-sdk 1.0.4 → 2.0.2
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 +86 -0
- package/MIGRATION.md +126 -0
- package/dist/bootstrap/index.d.ts +4 -1
- package/dist/bootstrap/index.d.ts.map +1 -1
- package/dist/bootstrap/index.js +32 -32
- package/dist/common/api-docs/setup-documentation.d.ts +1 -1
- package/dist/common/api-docs/setup-documentation.d.ts.map +1 -1
- package/dist/common/error-handling/all-exceptions.filter.d.ts +0 -3
- package/dist/common/error-handling/all-exceptions.filter.d.ts.map +1 -1
- package/dist/common/error-handling/all-exceptions.filter.js +35 -21
- package/dist/common/error-handling/error-code-mapper.d.ts.map +1 -1
- package/dist/common/error-handling/error-code-mapper.js +15 -70
- package/dist/common/error-handling/internal-error-code.d.ts +13 -59
- package/dist/common/error-handling/internal-error-code.d.ts.map +1 -1
- package/dist/common/error-handling/internal-error-code.js +16 -68
- package/dist/common/logger/logger.d.ts +2 -3
- package/dist/common/logger/logger.d.ts.map +1 -1
- package/dist/common/logger/logger.js +3 -16
- package/dist/common/logger/logging.middleware.d.ts.map +1 -1
- package/dist/common/logger/logging.middleware.js +16 -4
- package/dist/common/metrics/prometheus.service.d.ts +5 -0
- package/dist/common/metrics/prometheus.service.d.ts.map +1 -1
- package/dist/common/metrics/prometheus.service.js +43 -3
- package/dist/common/retry/retry-policy.d.ts.map +1 -1
- package/dist/common/retry/retry-policy.js +9 -4
- package/dist/common/secrets-provider/secrets-provider.aws.d.ts.map +1 -1
- package/dist/common/secrets-provider/secrets-provider.aws.js +2 -1
- package/dist/esm/bootstrap/index.js +33 -33
- package/dist/esm/common/error-handling/all-exceptions.filter.js +36 -22
- package/dist/esm/common/error-handling/error-code-mapper.js +15 -70
- package/dist/esm/common/error-handling/internal-error-code.js +16 -68
- package/dist/esm/common/logger/logger.js +3 -16
- package/dist/esm/common/logger/logging.middleware.js +16 -4
- package/dist/esm/common/metrics/prometheus.service.js +10 -3
- package/dist/esm/common/retry/retry-policy.js +9 -4
- package/dist/esm/common/secrets-provider/secrets-provider.aws.js +2 -1
- package/dist/esm/generated/game-engine-registry_pb.js +5 -11
- package/dist/esm/generated/game-engine_pb.js +10 -24
- package/dist/esm/grpc/connect-router.middleware.js +7 -1
- package/dist/esm/grpc/game-engine.grpc.in-adapter.js +64 -20
- package/dist/esm/health/application/services/health.service.js +33 -39
- package/dist/esm/health/health.module.js +1 -1
- package/dist/esm/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.js +19 -4
- package/dist/esm/registration/adapters/game-engine-registry.grpc.out-adapter.js +3 -4
- package/dist/esm/registration/services/game-engine-auto-register.service.js +11 -8
- package/dist/generated/game-engine-registry_pb.d.ts +5 -5
- package/dist/generated/game-engine-registry_pb.d.ts.map +1 -1
- package/dist/generated/game-engine-registry_pb.js +4 -10
- package/dist/generated/game-engine_pb.d.ts +26 -10
- package/dist/generated/game-engine_pb.d.ts.map +1 -1
- package/dist/generated/game-engine_pb.js +8 -22
- package/dist/grpc/connect-router.middleware.d.ts +9 -1
- package/dist/grpc/connect-router.middleware.d.ts.map +1 -1
- package/dist/grpc/connect-router.middleware.js +7 -1
- package/dist/grpc/game-engine.grpc.in-adapter.d.ts +18 -3
- package/dist/grpc/game-engine.grpc.in-adapter.d.ts.map +1 -1
- package/dist/grpc/game-engine.grpc.in-adapter.js +64 -20
- package/dist/grpc/index.d.ts +1 -1
- package/dist/grpc/index.d.ts.map +1 -1
- package/dist/health/application/ports/out/shutdown.out-port.d.ts +2 -0
- package/dist/health/application/ports/out/shutdown.out-port.d.ts.map +1 -1
- package/dist/health/application/services/health.service.d.ts.map +1 -1
- package/dist/health/application/services/health.service.js +33 -39
- package/dist/health/domain/health.d.ts +1 -1
- package/dist/health/domain/health.d.ts.map +1 -1
- package/dist/health/health.module.js +1 -1
- package/dist/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.d.ts +2 -1
- package/dist/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.d.ts.map +1 -1
- package/dist/health/infrastructure/adapters/out/shutdown/shutdown.out-adapter.js +19 -4
- package/dist/registration/adapters/game-engine-registry.grpc.out-adapter.d.ts.map +1 -1
- package/dist/registration/adapters/game-engine-registry.grpc.out-adapter.js +3 -4
- package/dist/registration/services/game-engine-auto-register.service.d.ts.map +1 -1
- package/dist/registration/services/game-engine-auto-register.service.js +11 -8
- package/dist/types.d.ts +6 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +5 -3
|
@@ -4,22 +4,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
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
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
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
7
|
var ExceptionsFilter_1;
|
|
14
8
|
import { Logger } from '../logger/logger';
|
|
15
|
-
import {
|
|
16
|
-
import { Catch, HttpException, HttpStatus, Inject, } from '@nestjs/common';
|
|
9
|
+
import { Catch, HttpException, HttpStatus } from '@nestjs/common';
|
|
17
10
|
import { DomainException } from './domain.exception';
|
|
18
11
|
import { ErrorCodeMapper } from './error-code-mapper';
|
|
19
12
|
import { InternalErrorCode } from './internal-error-code';
|
|
20
13
|
let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
|
|
21
|
-
constructor(
|
|
22
|
-
this.metricsPort = metricsPort;
|
|
14
|
+
constructor() {
|
|
23
15
|
this.logger = new Logger(ExceptionsFilter_1.name);
|
|
24
16
|
}
|
|
25
17
|
catch(exception, host) {
|
|
@@ -44,14 +36,17 @@ let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
|
|
|
44
36
|
handleDomainException(exception, request) {
|
|
45
37
|
const status = ErrorCodeMapper.mapToHttpStatus(exception.errorCode);
|
|
46
38
|
const level = status >= 500 ? 'error' : 'warn';
|
|
39
|
+
// Log full internal details for debugging — never sent to client
|
|
47
40
|
this.logger.log(`DomainException (status: ${status} at ${request.method} ${request.url}): Internal Code ${exception.errorCode} Message: ${exception.message}`, { level });
|
|
48
41
|
if (exception.cause) {
|
|
49
42
|
this.logger.error('Exception cause:', exception.cause);
|
|
50
43
|
}
|
|
44
|
+
// OWASP A01: Return error code only — never expose internal error.message to clients.
|
|
45
|
+
// Consistent with gRPC error sanitization in GameEngineGrpcInAdapter.
|
|
51
46
|
return this.buildResponsePayload({
|
|
52
47
|
status,
|
|
53
48
|
internalCode: exception.errorCode,
|
|
54
|
-
message: exception.
|
|
49
|
+
message: exception.errorCode,
|
|
55
50
|
path: request.url,
|
|
56
51
|
});
|
|
57
52
|
}
|
|
@@ -59,17 +54,29 @@ let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
|
|
|
59
54
|
const status = exception.getStatus();
|
|
60
55
|
const responseData = exception.getResponse();
|
|
61
56
|
// Check if this is a custom validation error response
|
|
62
|
-
|
|
63
|
-
responseData
|
|
64
|
-
|
|
65
|
-
|
|
57
|
+
const responseRecord = typeof responseData === 'object' && responseData !== null
|
|
58
|
+
? responseData
|
|
59
|
+
: null;
|
|
60
|
+
if (responseRecord &&
|
|
61
|
+
typeof responseRecord.internalCode === 'string' &&
|
|
62
|
+
typeof responseRecord.statusCode === 'number' &&
|
|
63
|
+
typeof responseRecord.message !== 'undefined') {
|
|
64
|
+
return {
|
|
65
|
+
statusCode: responseRecord.statusCode,
|
|
66
|
+
internalCode: responseRecord.internalCode,
|
|
67
|
+
message: String(responseRecord.message),
|
|
68
|
+
timestamp: typeof responseRecord.timestamp === 'string'
|
|
69
|
+
? responseRecord.timestamp
|
|
70
|
+
: new Date().toISOString(),
|
|
71
|
+
path: typeof responseRecord.path === 'string' ? responseRecord.path : request.url,
|
|
72
|
+
};
|
|
66
73
|
}
|
|
67
74
|
let message = 'HTTP Exception';
|
|
68
75
|
if (typeof responseData === 'string') {
|
|
69
76
|
message = responseData;
|
|
70
77
|
}
|
|
71
|
-
else if (typeof
|
|
72
|
-
message =
|
|
78
|
+
else if (responseRecord && typeof responseRecord.message === 'string') {
|
|
79
|
+
message = responseRecord.message;
|
|
73
80
|
}
|
|
74
81
|
const level = status >= 500 ? 'error' : 'warn';
|
|
75
82
|
this.logger.log(`HttpException (status: ${status} at ${request.method} ${request.url}): ${message}`, { level });
|
|
@@ -82,12 +89,21 @@ let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
|
|
|
82
89
|
path: request.url,
|
|
83
90
|
});
|
|
84
91
|
}
|
|
85
|
-
|
|
92
|
+
// OWASP A01: Never expose internal error details for server errors.
|
|
93
|
+
// 5xx messages may contain stack traces, DB errors, or internal details.
|
|
94
|
+
if (status >= 500) {
|
|
86
95
|
this.logger.error('HttpException stack:', exception.stack);
|
|
96
|
+
return this.buildResponsePayload({
|
|
97
|
+
status,
|
|
98
|
+
internalCode: InternalErrorCode.INTERNAL_SERVER_ERROR,
|
|
99
|
+
message: 'Internal server error',
|
|
100
|
+
path: request.url,
|
|
101
|
+
});
|
|
87
102
|
}
|
|
103
|
+
// 4xx client errors — framework messages are safe (e.g., "Not Found", "Bad Request")
|
|
88
104
|
return this.buildResponsePayload({
|
|
89
105
|
status,
|
|
90
|
-
internalCode: InternalErrorCode.
|
|
106
|
+
internalCode: InternalErrorCode.VALIDATION_ERROR,
|
|
91
107
|
message,
|
|
92
108
|
path: request.url,
|
|
93
109
|
});
|
|
@@ -121,8 +137,6 @@ let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
|
|
|
121
137
|
}
|
|
122
138
|
};
|
|
123
139
|
ExceptionsFilter = ExceptionsFilter_1 = __decorate([
|
|
124
|
-
Catch()
|
|
125
|
-
__param(0, Inject(METRICS_PORT)),
|
|
126
|
-
__metadata("design:paramtypes", [Object])
|
|
140
|
+
Catch()
|
|
127
141
|
], ExceptionsFilter);
|
|
128
142
|
export { ExceptionsFilter };
|
|
@@ -2,88 +2,33 @@ import { InternalErrorCode } from './internal-error-code';
|
|
|
2
2
|
// HTTP status codes
|
|
3
3
|
const HttpStatus = {
|
|
4
4
|
BAD_REQUEST: 400,
|
|
5
|
-
|
|
5
|
+
UNAUTHORIZED: 401,
|
|
6
6
|
FORBIDDEN: 403,
|
|
7
7
|
NOT_FOUND: 404,
|
|
8
|
+
CONFLICT: 409,
|
|
8
9
|
UNPROCESSABLE_ENTITY: 422,
|
|
9
10
|
INTERNAL_SERVER_ERROR: 500,
|
|
10
11
|
SERVICE_UNAVAILABLE: 503,
|
|
11
12
|
};
|
|
12
13
|
export class ErrorCodeMapper {
|
|
13
14
|
static mapToHttpStatus(errorCode) {
|
|
14
|
-
return this.ERROR_CODE_TO_HTTP_MAP[errorCode]
|
|
15
|
+
return this.ERROR_CODE_TO_HTTP_MAP[errorCode] ?? HttpStatus.INTERNAL_SERVER_ERROR;
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
ErrorCodeMapper.ERROR_CODE_TO_HTTP_MAP = {
|
|
18
|
-
|
|
19
|
-
[InternalErrorCode.
|
|
20
|
-
[InternalErrorCode.INSUFFICIENT_FUNDS]: HttpStatus.UNPROCESSABLE_ENTITY,
|
|
21
|
-
[InternalErrorCode.INTERNAL_SERVER_ERROR]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
22
|
-
// Game Catalog errors
|
|
23
|
-
[InternalErrorCode.GAME_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
24
|
-
[InternalErrorCode.GAME_CONFIG_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
25
|
-
[InternalErrorCode.GAME_CONFIG_ALREADY_EXISTS_WITH_SAME_JURISDICTION_AND_RTP]: HttpStatus.BAD_REQUEST,
|
|
26
|
-
[InternalErrorCode.OPERATOR_GAME_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
27
|
-
[InternalErrorCode.OPERATOR_GAME_ALREADY_ENABLED]: HttpStatus.BAD_REQUEST,
|
|
28
|
-
[InternalErrorCode.INVALID_GAME_CONFIG_DATA]: HttpStatus.BAD_REQUEST,
|
|
29
|
-
[InternalErrorCode.INVALID_GAME_UPDATE_DATA]: HttpStatus.BAD_REQUEST,
|
|
30
|
-
[InternalErrorCode.GAME_CODE_ALREADY_EXISTS]: HttpStatus.BAD_REQUEST,
|
|
31
|
-
[InternalErrorCode.GAME_OR_GAME_CONFIG_DISABLED]: HttpStatus.BAD_REQUEST,
|
|
19
|
+
// Core game engine errors
|
|
20
|
+
[InternalErrorCode.GAME_ENGINE_ERROR]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
32
21
|
[InternalErrorCode.DEBUG_COMMANDS_DISABLED]: HttpStatus.FORBIDDEN,
|
|
33
|
-
|
|
34
|
-
[InternalErrorCode.
|
|
35
|
-
|
|
36
|
-
[InternalErrorCode.
|
|
37
|
-
|
|
38
|
-
[InternalErrorCode.
|
|
39
|
-
[InternalErrorCode.
|
|
40
|
-
[InternalErrorCode.
|
|
41
|
-
[InternalErrorCode.UNKNOWN_COMMAND]: HttpStatus.NOT_FOUND,
|
|
42
|
-
// Operator errors
|
|
43
|
-
[InternalErrorCode.MISSING_OPERATOR_CODE]: HttpStatus.BAD_REQUEST,
|
|
44
|
-
[InternalErrorCode.INVALID_OPERATOR_CODE]: HttpStatus.BAD_REQUEST,
|
|
45
|
-
[InternalErrorCode.OPERATOR_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
46
|
-
[InternalErrorCode.OPERATOR_INACTIVE]: HttpStatus.FORBIDDEN,
|
|
47
|
-
[InternalErrorCode.COUNTRY_CODE_RESTRICTED]: HttpStatus.BAD_REQUEST,
|
|
48
|
-
[InternalErrorCode.UNAUTHORIZED]: HttpStatus.FORBIDDEN,
|
|
49
|
-
[InternalErrorCode.AUTH_VALIDATION_FAILED]: HttpStatus.FORBIDDEN,
|
|
50
|
-
[InternalErrorCode.BALANCE_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
51
|
-
[InternalErrorCode.INVALID_AUTH_DATA]: HttpStatus.BAD_REQUEST,
|
|
22
|
+
[InternalErrorCode.UNKNOWN_COMMAND]: HttpStatus.BAD_REQUEST,
|
|
23
|
+
[InternalErrorCode.INVALID_COMMAND]: HttpStatus.BAD_REQUEST,
|
|
24
|
+
// RNG integrity (GLI-19)
|
|
25
|
+
[InternalErrorCode.INVALID_RNG_SEED]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
26
|
+
// Infrastructure errors
|
|
27
|
+
[InternalErrorCode.INTERNAL_SERVER_ERROR]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
28
|
+
[InternalErrorCode.FORBIDDEN]: HttpStatus.FORBIDDEN,
|
|
29
|
+
[InternalErrorCode.UNAUTHORIZED]: HttpStatus.UNAUTHORIZED,
|
|
52
30
|
[InternalErrorCode.VALIDATION_ERROR]: HttpStatus.BAD_REQUEST,
|
|
53
|
-
[InternalErrorCode.JURISDICTION_CONFIG_ALREADY_EXISTS]: HttpStatus.BAD_REQUEST,
|
|
54
|
-
[InternalErrorCode.JURISDICTION_CONFIG_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
55
|
-
[InternalErrorCode.OPERATOR_JURISDICTION_CONFIG_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
56
|
-
[InternalErrorCode.GAME_ENGINE_ERROR]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
57
|
-
[InternalErrorCode.DEBIT_FAILED]: HttpStatus.BAD_REQUEST,
|
|
58
|
-
[InternalErrorCode.CREDIT_FAILED]: HttpStatus.BAD_REQUEST,
|
|
59
|
-
[InternalErrorCode.GAME_ROUND_LOG_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
60
|
-
// Geo Validation errors
|
|
61
|
-
[InternalErrorCode.COUNTRY_NOT_PERMITTED]: HttpStatus.FORBIDDEN,
|
|
62
|
-
[InternalErrorCode.GEO_VALIDATION_SERVICE_UNAVAILABLE]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
63
|
-
[InternalErrorCode.RESOURCE_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
64
|
-
[InternalErrorCode.FINANCIAL_TRANSACTION_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
65
|
-
[InternalErrorCode.SESSION_TERMINATED]: HttpStatus.BAD_REQUEST,
|
|
66
|
-
[InternalErrorCode.SESSION_CANNOT_BE_TERMINATED]: HttpStatus.BAD_REQUEST,
|
|
67
|
-
[InternalErrorCode.SESSION_AUTO_RESOLVE_FAILED]: HttpStatus.BAD_REQUEST,
|
|
68
|
-
[InternalErrorCode.SESSION_ALREADY_EXISTS]: HttpStatus.BAD_REQUEST,
|
|
69
|
-
[InternalErrorCode.INCOMPATIBLE_GAMEPLAY_CONFIG]: HttpStatus.BAD_REQUEST,
|
|
70
|
-
// Health check errors
|
|
71
|
-
[InternalErrorCode.HEALTH_CHECK_FAILED]: HttpStatus.SERVICE_UNAVAILABLE,
|
|
72
|
-
//Jackpot errors
|
|
73
|
-
[InternalErrorCode.JACKPOT_TYPE_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
74
|
-
[InternalErrorCode.JACKPOT_TIER_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
75
|
-
[InternalErrorCode.JACKPOT_CONFIGURATION_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
76
|
-
[InternalErrorCode.JACKPOT_CONFIGURATION_IS_ACTIVE]: HttpStatus.BAD_REQUEST,
|
|
77
|
-
// RNG and Replay errors
|
|
78
|
-
[InternalErrorCode.RNG_SEED_NOT_FOUND]: HttpStatus.NOT_FOUND,
|
|
79
|
-
[InternalErrorCode.RNG_SEED_MISMATCH]: HttpStatus.BAD_REQUEST,
|
|
80
|
-
[InternalErrorCode.MASTER_HASH_INVALID]: HttpStatus.BAD_REQUEST,
|
|
81
|
-
[InternalErrorCode.REPLAY_OUTCOME_MISMATCH]: HttpStatus.BAD_REQUEST,
|
|
82
|
-
[InternalErrorCode.JACKPOT_POOL_CONTRIBUTION_ALREADY_PROCESSED]: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
83
|
-
[InternalErrorCode.JACKPOT_TYPE_DOES_NOT_SUPPORT_TIERS]: HttpStatus.BAD_REQUEST,
|
|
84
|
-
[InternalErrorCode.CONCURRENT_MODIFICATION]: HttpStatus.CONFLICT,
|
|
85
|
-
[InternalErrorCode.ACCOUNT_LOCKED]: HttpStatus.FORBIDDEN,
|
|
86
|
-
[InternalErrorCode.DAILY_LIMIT_EXCEEDED]: HttpStatus.UNPROCESSABLE_ENTITY,
|
|
87
|
-
[InternalErrorCode.INVALID_AMOUNT]: HttpStatus.BAD_REQUEST,
|
|
88
31
|
[InternalErrorCode.SERVICE_UNAVAILABLE]: HttpStatus.SERVICE_UNAVAILABLE,
|
|
32
|
+
// Health check
|
|
33
|
+
[InternalErrorCode.HEALTH_CHECK_FAILED]: HttpStatus.SERVICE_UNAVAILABLE,
|
|
89
34
|
};
|
|
@@ -1,77 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes relevant to game engine services.
|
|
3
|
+
*
|
|
4
|
+
* Scoped to game-engine SDK concerns only.
|
|
5
|
+
* Platform-level codes (sessions, operators, jackpots, geo, etc.)
|
|
6
|
+
* belong in the RGS platform, not in individual engine services.
|
|
7
|
+
*/
|
|
1
8
|
export var InternalErrorCode;
|
|
2
9
|
(function (InternalErrorCode) {
|
|
3
|
-
|
|
4
|
-
InternalErrorCode["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR";
|
|
5
|
-
InternalErrorCode["INSUFFICIENT_FUNDS"] = "INSUFFICIENT_FUNDS";
|
|
6
|
-
InternalErrorCode["INVALID_CURRENCY_CODE"] = "INVALID_CURRENCY_CODE";
|
|
7
|
-
// Game Catalog errors
|
|
8
|
-
InternalErrorCode["GAME_NOT_FOUND"] = "GAME_NOT_FOUND";
|
|
9
|
-
InternalErrorCode["GAME_CONFIG_NOT_FOUND"] = "GAME_CONFIG_NOT_FOUND";
|
|
10
|
-
InternalErrorCode["GAME_CONFIG_ALREADY_EXISTS_WITH_SAME_JURISDICTION_AND_RTP"] = "GAME_CONFIG_ALREADY_EXISTS_WITH_SAME_JURISDICTION_AND_RTP";
|
|
11
|
-
InternalErrorCode["OPERATOR_GAME_NOT_FOUND"] = "OPERATOR_GAME_NOT_FOUND";
|
|
12
|
-
InternalErrorCode["OPERATOR_GAME_ALREADY_ENABLED"] = "OPERATOR_GAME_ALREADY_ENABLED";
|
|
13
|
-
InternalErrorCode["INVALID_GAME_CONFIG_DATA"] = "INVALID_GAME_CONFIG_DATA";
|
|
14
|
-
InternalErrorCode["INVALID_GAME_UPDATE_DATA"] = "INVALID_GAME_UPDATE_DATA";
|
|
15
|
-
InternalErrorCode["GAME_CODE_ALREADY_EXISTS"] = "GAME_CODE_ALREADY_EXISTS";
|
|
10
|
+
// Core game engine errors
|
|
16
11
|
InternalErrorCode["GAME_ENGINE_ERROR"] = "GAME_ENGINE_ERROR";
|
|
17
|
-
InternalErrorCode["GAME_OR_GAME_CONFIG_DISABLED"] = "GAME_OR_GAME_CONFIG_DISABLED";
|
|
18
12
|
InternalErrorCode["DEBUG_COMMANDS_DISABLED"] = "DEBUG_COMMANDS_DISABLED";
|
|
19
|
-
// Game Orchestrator errors
|
|
20
|
-
InternalErrorCode["INVALID_SESSION"] = "INVALID_SESSION";
|
|
21
|
-
InternalErrorCode["SESSION_NOT_FOUND"] = "SESSION_NOT_FOUND";
|
|
22
|
-
InternalErrorCode["SESSION_NOT_ACTIVE"] = "SESSION_NOT_ACTIVE";
|
|
23
|
-
InternalErrorCode["SESSION_MISMATCH"] = "SESSION_MISMATCH";
|
|
24
|
-
InternalErrorCode["INVALID_STATE_TRANSITION"] = "INVALID_STATE_TRANSITION";
|
|
25
|
-
InternalErrorCode["INVALID_BET_AMOUNT"] = "INVALID_BET_AMOUNT";
|
|
26
|
-
InternalErrorCode["REALITY_CHECK_IN_PROGRESS"] = "REALITY_CHECK_IN_PROGRESS";
|
|
27
|
-
InternalErrorCode["SESSION_TERMINATED"] = "SESSION_TERMINATED";
|
|
28
|
-
InternalErrorCode["SESSION_CANNOT_BE_TERMINATED"] = "SESSION_CANNOT_BE_TERMINATED";
|
|
29
|
-
InternalErrorCode["SESSION_AUTO_RESOLVE_FAILED"] = "SESSION_AUTO_RESOLVE_FAILED";
|
|
30
|
-
InternalErrorCode["SESSION_ALREADY_EXISTS"] = "SESSION_ALREADY_EXISTS";
|
|
31
|
-
InternalErrorCode["INCOMPATIBLE_GAMEPLAY_CONFIG"] = "INCOMPATIBLE_GAMEPLAY_CONFIG";
|
|
32
13
|
InternalErrorCode["UNKNOWN_COMMAND"] = "UNKNOWN_COMMAND";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
InternalErrorCode["
|
|
36
|
-
|
|
37
|
-
InternalErrorCode["
|
|
38
|
-
InternalErrorCode["
|
|
14
|
+
InternalErrorCode["INVALID_COMMAND"] = "INVALID_COMMAND";
|
|
15
|
+
// RNG integrity (GLI-19)
|
|
16
|
+
InternalErrorCode["INVALID_RNG_SEED"] = "INVALID_RNG_SEED";
|
|
17
|
+
// Infrastructure errors
|
|
18
|
+
InternalErrorCode["INTERNAL_SERVER_ERROR"] = "INTERNAL_SERVER_ERROR";
|
|
19
|
+
InternalErrorCode["FORBIDDEN"] = "FORBIDDEN";
|
|
39
20
|
InternalErrorCode["UNAUTHORIZED"] = "UNAUTHORIZED";
|
|
40
|
-
InternalErrorCode["AUTH_VALIDATION_FAILED"] = "AUTH_VALIDATION_FAILED";
|
|
41
|
-
InternalErrorCode["BALANCE_NOT_FOUND"] = "BALANCE_NOT_FOUND";
|
|
42
|
-
InternalErrorCode["DEBIT_FAILED"] = "DEBIT_FAILED";
|
|
43
|
-
InternalErrorCode["CREDIT_FAILED"] = "CREDIT_FAILED";
|
|
44
|
-
InternalErrorCode["INVALID_AUTH_DATA"] = "INVALID_AUTH_DATA";
|
|
45
21
|
InternalErrorCode["VALIDATION_ERROR"] = "VALIDATION_ERROR";
|
|
46
|
-
InternalErrorCode["JURISDICTION_CONFIG_ALREADY_EXISTS"] = "JURISDICTION_CONFIG_ALREADY_EXISTS";
|
|
47
|
-
InternalErrorCode["JURISDICTION_CONFIG_NOT_FOUND"] = "JURISDICTION_CONFIG_NOT_FOUND";
|
|
48
|
-
InternalErrorCode["OPERATOR_JURISDICTION_CONFIG_NOT_FOUND"] = "OPERATOR_JURISDICTION_CONFIG_NOT_FOUND";
|
|
49
|
-
// Game round log errors
|
|
50
|
-
InternalErrorCode["GAME_ROUND_LOG_NOT_FOUND"] = "GAME_ROUND_LOG_NOT_FOUND";
|
|
51
|
-
// Geo Validation errors
|
|
52
|
-
InternalErrorCode["COUNTRY_NOT_PERMITTED"] = "COUNTRY_NOT_PERMITTED";
|
|
53
|
-
InternalErrorCode["GEO_VALIDATION_SERVICE_UNAVAILABLE"] = "GEO_VALIDATION_SERVICE_UNAVAILABLE";
|
|
54
|
-
InternalErrorCode["RESOURCE_NOT_FOUND"] = "RESOURCE_NOT_FOUND";
|
|
55
|
-
// Financial transaction errors
|
|
56
|
-
InternalErrorCode["FINANCIAL_TRANSACTION_NOT_FOUND"] = "FINANCIAL_TRANSACTION_NOT_FOUND";
|
|
57
|
-
//Health check errors
|
|
58
|
-
InternalErrorCode["HEALTH_CHECK_FAILED"] = "HEALTH_CHECK_FAILED";
|
|
59
|
-
//Jackpot errors
|
|
60
|
-
InternalErrorCode["JACKPOT_TYPE_NOT_FOUND"] = "JACKPOT_TYPE_NOT_FOUND";
|
|
61
|
-
InternalErrorCode["JACKPOT_TIER_NOT_FOUND"] = "JACKPOT_TIER_NOT_FOUND";
|
|
62
|
-
InternalErrorCode["JACKPOT_CONFIGURATION_NOT_FOUND"] = "JACKPOT_CONFIGURATION_NOT_FOUND";
|
|
63
|
-
InternalErrorCode["JACKPOT_CONFIGURATION_IS_ACTIVE"] = "JACKPOT_CONFIGURATION_IS_ACTIVE";
|
|
64
|
-
InternalErrorCode["JACKPOT_POOL_CONTRIBUTION_ALREADY_PROCESSED"] = "JACKPOT_POOL_CONTRIBUTION_ALREADY_PROCESSED";
|
|
65
|
-
InternalErrorCode["JACKPOT_TYPE_DOES_NOT_SUPPORT_TIERS"] = "JACKPOT_TYPE_DOES_NOT_SUPPORT_TIERS";
|
|
66
|
-
// RNG and Replay errors
|
|
67
|
-
InternalErrorCode["RNG_SEED_NOT_FOUND"] = "RNG_SEED_NOT_FOUND";
|
|
68
|
-
InternalErrorCode["RNG_SEED_MISMATCH"] = "RNG_SEED_MISMATCH";
|
|
69
|
-
InternalErrorCode["MASTER_HASH_INVALID"] = "MASTER_HASH_INVALID";
|
|
70
|
-
InternalErrorCode["REPLAY_OUTCOME_MISMATCH"] = "REPLAY_OUTCOME_MISMATCH";
|
|
71
|
-
// Concurrency
|
|
72
|
-
InternalErrorCode["CONCURRENT_MODIFICATION"] = "CONCURRENT_MODIFICATION";
|
|
73
|
-
InternalErrorCode["ACCOUNT_LOCKED"] = "ACCOUNT_LOCKED";
|
|
74
|
-
InternalErrorCode["DAILY_LIMIT_EXCEEDED"] = "DAILY_LIMIT_EXCEEDED";
|
|
75
|
-
InternalErrorCode["INVALID_AMOUNT"] = "INVALID_AMOUNT";
|
|
76
22
|
InternalErrorCode["SERVICE_UNAVAILABLE"] = "SERVICE_UNAVAILABLE";
|
|
23
|
+
// Health check
|
|
24
|
+
InternalErrorCode["HEALTH_CHECK_FAILED"] = "HEALTH_CHECK_FAILED";
|
|
77
25
|
})(InternalErrorCode || (InternalErrorCode = {}));
|
|
@@ -66,25 +66,12 @@ export class Logger {
|
|
|
66
66
|
return output;
|
|
67
67
|
}));
|
|
68
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
69
|
getTransports() {
|
|
83
|
-
const
|
|
70
|
+
const consoleTransport = new transports.Console();
|
|
84
71
|
if (process.env.LOG_TO_FILE === 'true') {
|
|
85
|
-
|
|
72
|
+
return [consoleTransport, new transports.File({ filename: 'logs/app.log' })];
|
|
86
73
|
}
|
|
87
|
-
return
|
|
74
|
+
return [consoleTransport];
|
|
88
75
|
}
|
|
89
76
|
log(message, { level = 'info', ...rest } = {}) {
|
|
90
77
|
switch (level) {
|
|
@@ -10,11 +10,23 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
10
10
|
var LoggingMiddleware_1;
|
|
11
11
|
import { Injectable } from '@nestjs/common';
|
|
12
12
|
import { Logger } from './logger';
|
|
13
|
-
|
|
13
|
+
/** Endpoints to suppress from logging on success. Configurable via LOG_BLOCKED_ENDPOINTS env var (comma-separated). */
|
|
14
|
+
const BLOCKED_ENDPOINTS = process.env.LOG_BLOCKED_ENDPOINTS
|
|
15
|
+
? process.env.LOG_BLOCKED_ENDPOINTS.split(',').map(e => e.trim())
|
|
16
|
+
: [];
|
|
14
17
|
const SENSITIVE_FIELDS = new Set([
|
|
15
|
-
'password',
|
|
16
|
-
'
|
|
17
|
-
'
|
|
18
|
+
'password',
|
|
19
|
+
'token',
|
|
20
|
+
'secret',
|
|
21
|
+
'authorization',
|
|
22
|
+
'apikey',
|
|
23
|
+
'api_key',
|
|
24
|
+
'accesstoken',
|
|
25
|
+
'refreshtoken',
|
|
26
|
+
'creditcard',
|
|
27
|
+
'ssn',
|
|
28
|
+
'private_key',
|
|
29
|
+
'privatekey',
|
|
18
30
|
]);
|
|
19
31
|
function sanitize(obj) {
|
|
20
32
|
if (obj === null || obj === undefined || typeof obj !== 'object')
|
|
@@ -30,8 +30,9 @@ let PrometheusService = class PrometheusService {
|
|
|
30
30
|
this.metricsRegistry = new Map();
|
|
31
31
|
this.initializeRegistry();
|
|
32
32
|
}
|
|
33
|
-
initializeMetricsFromDatabase() {
|
|
34
|
-
|
|
33
|
+
async initializeMetricsFromDatabase() {
|
|
34
|
+
// No-op: Game engine metrics are initialized from Prometheus registry, not database.
|
|
35
|
+
// Override in subclass if database-backed metric initialization is needed.
|
|
35
36
|
}
|
|
36
37
|
initializeRegistry() {
|
|
37
38
|
this.metricsRegistry.set('game_engine_commands_total', this.engineCommandsTotal);
|
|
@@ -68,8 +69,14 @@ let PrometheusService = class PrometheusService {
|
|
|
68
69
|
}
|
|
69
70
|
return metric;
|
|
70
71
|
}
|
|
72
|
+
/**
|
|
73
|
+
* Returns Prometheus text format metrics from the default prom-client registry.
|
|
74
|
+
* The @willsoto/nestjs-prometheus module also exposes a /metrics HTTP endpoint
|
|
75
|
+
* automatically — this method is for programmatic access via the MetricsPort.
|
|
76
|
+
*/
|
|
71
77
|
async getMetrics() {
|
|
72
|
-
|
|
78
|
+
const { register } = await import('prom-client');
|
|
79
|
+
return register.metrics();
|
|
73
80
|
}
|
|
74
81
|
};
|
|
75
82
|
PrometheusService = __decorate([
|
|
@@ -21,7 +21,7 @@ export class RetryPolicy {
|
|
|
21
21
|
return result;
|
|
22
22
|
}
|
|
23
23
|
catch (error) {
|
|
24
|
-
const err = error;
|
|
24
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
25
25
|
lastError = err;
|
|
26
26
|
if (!this.isRetryable(err)) {
|
|
27
27
|
throw err;
|
|
@@ -36,7 +36,9 @@ export class RetryPolicy {
|
|
|
36
36
|
try {
|
|
37
37
|
this.onRetry(attempt, err);
|
|
38
38
|
}
|
|
39
|
-
catch {
|
|
39
|
+
catch (callbackError) {
|
|
40
|
+
this.logger.debug(`onRetry callback threw: ${callbackError instanceof Error ? callbackError.message : String(callbackError)}`);
|
|
41
|
+
}
|
|
40
42
|
}
|
|
41
43
|
await this.sleep(delay);
|
|
42
44
|
}
|
|
@@ -46,8 +48,11 @@ export class RetryPolicy {
|
|
|
46
48
|
isRetryable(error) {
|
|
47
49
|
if (!this.retryableErrors || this.retryableErrors.length === 0)
|
|
48
50
|
return true;
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
+
const errorRecord = error;
|
|
52
|
+
const cause = errorRecord.cause;
|
|
53
|
+
const causeCode = typeof cause?.code === 'string' ? cause.code : '';
|
|
54
|
+
const errorCode = typeof errorRecord.code === 'string' ? errorRecord.code : '';
|
|
55
|
+
const text = `${errorCode} ${error.name} ${error.message} ${causeCode}`;
|
|
51
56
|
return this.retryableErrors.some(pattern => text.includes(pattern));
|
|
52
57
|
}
|
|
53
58
|
calculateDelay(attempt) {
|
|
@@ -50,7 +50,8 @@ let AwsSecretsProvider = AwsSecretsProvider_1 = class AwsSecretsProvider {
|
|
|
50
50
|
this.logger.log(`Successfully loaded secrets from AWS Secrets Manager.`);
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
53
|
-
|
|
53
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
54
|
+
this.logger.error(`Failed to retrieve secrets from AWS: ${errorMessage}`);
|
|
54
55
|
throw error;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
// @generated by protoc-gen-es v2.
|
|
1
|
+
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
|
|
2
2
|
// @generated from file game-engine-registry.proto (package game_engine_registry, syntax proto3)
|
|
3
3
|
/* eslint-disable */
|
|
4
|
-
import { fileDesc, messageDesc, serviceDesc } from
|
|
4
|
+
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
|
|
5
5
|
/**
|
|
6
6
|
* Describes the file game-engine-registry.proto.
|
|
7
7
|
*/
|
|
8
|
-
export const file_game_engine_registry =
|
|
9
|
-
/*@__PURE__*/
|
|
10
|
-
fileDesc('ChpnYW1lLWVuZ2luZS1yZWdpc3RyeS5wcm90bxIUZ2FtZV9lbmdpbmVfcmVnaXN0cnkilgEKGVJlZ2lzdGVyR2FtZUVuZ2luZVJlcXVlc3QSEQoJZ2FtZV9jb2RlGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSCwoDcnRwGAMgASgBEhEKCWdhbWVfdHlwZRgEIAEoCRIQCghncnBjX3VybBgFIAEoCRIRCglnYW1lX25hbWUYBiABKAkSEAoIcHJvdmlkZXIYByABKAkiTwoaUmVnaXN0ZXJHYW1lRW5naW5lUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIUCgdtZXNzYWdlGAIgASgJSACIAQFCCgoIX21lc3NhZ2UylAEKGUdhbWVFbmdpbmVSZWdpc3RyeVNlcnZpY2USdwoSUmVnaXN0ZXJHYW1lRW5naW5lEi8uZ2FtZV9lbmdpbmVfcmVnaXN0cnkuUmVnaXN0ZXJHYW1lRW5naW5lUmVxdWVzdBowLmdhbWVfZW5naW5lX3JlZ2lzdHJ5LlJlZ2lzdGVyR2FtZUVuZ2luZVJlc3BvbnNlYgZwcm90bzM');
|
|
8
|
+
export const file_game_engine_registry = /*@__PURE__*/ fileDesc("ChpnYW1lLWVuZ2luZS1yZWdpc3RyeS5wcm90bxIUZ2FtZV9lbmdpbmVfcmVnaXN0cnkilgEKGVJlZ2lzdGVyR2FtZUVuZ2luZVJlcXVlc3QSEQoJZ2FtZV9jb2RlGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSCwoDcnRwGAMgASgBEhEKCWdhbWVfdHlwZRgEIAEoCRIQCghncnBjX3VybBgFIAEoCRIRCglnYW1lX25hbWUYBiABKAkSEAoIcHJvdmlkZXIYByABKAkiTwoaUmVnaXN0ZXJHYW1lRW5naW5lUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIUCgdtZXNzYWdlGAIgASgJSACIAQFCCgoIX21lc3NhZ2UylAEKGUdhbWVFbmdpbmVSZWdpc3RyeVNlcnZpY2USdwoSUmVnaXN0ZXJHYW1lRW5naW5lEi8uZ2FtZV9lbmdpbmVfcmVnaXN0cnkuUmVnaXN0ZXJHYW1lRW5naW5lUmVxdWVzdBowLmdhbWVfZW5naW5lX3JlZ2lzdHJ5LlJlZ2lzdGVyR2FtZUVuZ2luZVJlc3BvbnNlYgZwcm90bzM");
|
|
11
9
|
/**
|
|
12
10
|
* Describes the message game_engine_registry.RegisterGameEngineRequest.
|
|
13
11
|
* Use `create(RegisterGameEngineRequestSchema)` to create a new message.
|
|
14
12
|
*/
|
|
15
|
-
export const RegisterGameEngineRequestSchema =
|
|
16
|
-
/*@__PURE__*/
|
|
17
|
-
messageDesc(file_game_engine_registry, 0);
|
|
13
|
+
export const RegisterGameEngineRequestSchema = /*@__PURE__*/ messageDesc(file_game_engine_registry, 0);
|
|
18
14
|
/**
|
|
19
15
|
* Describes the message game_engine_registry.RegisterGameEngineResponse.
|
|
20
16
|
* Use `create(RegisterGameEngineResponseSchema)` to create a new message.
|
|
21
17
|
*/
|
|
22
|
-
export const RegisterGameEngineResponseSchema =
|
|
23
|
-
/*@__PURE__*/
|
|
24
|
-
messageDesc(file_game_engine_registry, 1);
|
|
18
|
+
export const RegisterGameEngineResponseSchema = /*@__PURE__*/ messageDesc(file_game_engine_registry, 1);
|
|
25
19
|
/**
|
|
26
20
|
* @generated from service game_engine_registry.GameEngineRegistryService
|
|
27
21
|
*/
|
|
@@ -1,56 +1,42 @@
|
|
|
1
|
-
// @generated by protoc-gen-es v2.
|
|
1
|
+
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
|
|
2
2
|
// @generated from file game-engine.proto (package game_engine, syntax proto3)
|
|
3
3
|
/* eslint-disable */
|
|
4
|
-
import { fileDesc, messageDesc, serviceDesc } from
|
|
5
|
-
import { file_google_protobuf_struct } from
|
|
4
|
+
import { fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
|
|
5
|
+
import { file_google_protobuf_struct } from "@bufbuild/protobuf/wkt";
|
|
6
6
|
/**
|
|
7
7
|
* Describes the file game-engine.proto.
|
|
8
8
|
*/
|
|
9
|
-
export const file_game_engine =
|
|
10
|
-
/*@__PURE__*/
|
|
11
|
-
fileDesc('ChFnYW1lLWVuZ2luZS5wcm90bxILZ2FtZV9lbmdpbmUi5QEKFVByb2Nlc3NDb21tYW5kUmVxdWVzdBIyCgxwdWJsaWNfc3RhdGUYASABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgCIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARI0Cgdjb21tYW5kGAMgASgLMh4uZ2FtZV9lbmdpbmUuR2FtZUFjdGlvbkNvbW1hbmRIAogBAUIPCg1fcHVibGljX3N0YXRlQhAKDl9wcml2YXRlX3N0YXRlQgoKCF9jb21tYW5kImgKEUdhbWVBY3Rpb25Db21tYW5kEgoKAmlkGAEgASgJEgwKBHR5cGUYAiABKAkSLQoHcGF5bG9hZBgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAIgBAUIKCghfcGF5bG9hZCJKChBSbmdPdXRjb21lUmVjb3JkEg4KBnJlc3VsdBgBIAEoARIMCgRzZWVkGAIgASgJEgsKA21pbhgDIAEoARILCgNtYXgYBCABKAEirgMKFlByb2Nlc3NDb21tYW5kUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIyCgxwdWJsaWNfc3RhdGUYAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARItCgdvdXRjb21lGAQgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEgCiAEBEhQKB21lc3NhZ2UYBSABKAlIA4gBARJICgtybmdfb3V0Y29tZRgGIAMoCzIzLmdhbWVfZW5naW5lLlByb2Nlc3NDb21tYW5kUmVzcG9uc2UuUm5nT3V0Y29tZUVudHJ5GlAKD1JuZ091dGNvbWVFbnRyeRILCgNrZXkYASABKAkSLAoFdmFsdWUYAiABKAsyHS5nYW1lX2VuZ2luZS5SbmdPdXRjb21lUmVjb3JkOgI4AUIPCg1fcHVibGljX3N0YXRlQhAKDl9wcml2YXRlX3N0YXRlQgoKCF9vdXRjb21lQgoKCF9tZXNzYWdlIhoKGEdldEdhbWVFbmdpbmVJbmZvUmVxdWVzdCJfChlHZXRHYW1lRW5naW5lSW5mb1Jlc3BvbnNlEhEKCWdhbWVfY29kZRgBIAEoCRIPCgd2ZXJzaW9uGAIgASgJEgsKA3J0cBgDIAEoARIRCglnYW1lX3R5cGUYBCABKAky0gEKEUdhbWVFbmdpbmVTZXJ2aWNlElkKDlByb2Nlc3NDb21tYW5kEiIuZ2FtZV9lbmdpbmUuUHJvY2Vzc0NvbW1hbmRSZXF1ZXN0GiMuZ2FtZV9lbmdpbmUuUHJvY2Vzc0NvbW1hbmRSZXNwb25zZRJiChFHZXRHYW1lRW5naW5lSW5mbxIlLmdhbWVfZW5naW5lLkdldEdhbWVFbmdpbmVJbmZvUmVxdWVzdBomLmdhbWVfZW5naW5lLkdldEdhbWVFbmdpbmVJbmZvUmVzcG9uc2ViBnByb3RvMw', [file_google_protobuf_struct]);
|
|
9
|
+
export const file_game_engine = /*@__PURE__*/ fileDesc("ChFnYW1lLWVuZ2luZS5wcm90bxILZ2FtZV9lbmdpbmUisAIKFVByb2Nlc3NDb21tYW5kUmVxdWVzdBIyCgxwdWJsaWNfc3RhdGUYASABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgCIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARI0Cgdjb21tYW5kGAMgASgLMh4uZ2FtZV9lbmdpbmUuR2FtZUFjdGlvbkNvbW1hbmRIAogBARI1Cg9hZGRpdGlvbmFsX2RhdGEYBCABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SAOIAQFCDwoNX3B1YmxpY19zdGF0ZUIQCg5fcHJpdmF0ZV9zdGF0ZUIKCghfY29tbWFuZEISChBfYWRkaXRpb25hbF9kYXRhImgKEUdhbWVBY3Rpb25Db21tYW5kEgoKAmlkGAEgASgJEgwKBHR5cGUYAiABKAkSLQoHcGF5bG9hZBgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAIgBAUIKCghfcGF5bG9hZCJKChBSbmdPdXRjb21lUmVjb3JkEg4KBnJlc3VsdBgBIAEoARIMCgRzZWVkGAIgASgJEgsKA21pbhgDIAEoARILCgNtYXgYBCABKAEi+QMKFlByb2Nlc3NDb21tYW5kUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIyCgxwdWJsaWNfc3RhdGUYAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARItCgdvdXRjb21lGAQgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEgCiAEBEhQKB21lc3NhZ2UYBSABKAlIA4gBARJICgtybmdfb3V0Y29tZRgGIAMoCzIzLmdhbWVfZW5naW5lLlByb2Nlc3NDb21tYW5kUmVzcG9uc2UuUm5nT3V0Y29tZUVudHJ5EjUKD2FkZGl0aW9uYWxfZGF0YRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIBIgBARpQCg9SbmdPdXRjb21lRW50cnkSCwoDa2V5GAEgASgJEiwKBXZhbHVlGAIgASgLMh0uZ2FtZV9lbmdpbmUuUm5nT3V0Y29tZVJlY29yZDoCOAFCDwoNX3B1YmxpY19zdGF0ZUIQCg5fcHJpdmF0ZV9zdGF0ZUIKCghfb3V0Y29tZUIKCghfbWVzc2FnZUISChBfYWRkaXRpb25hbF9kYXRhIhoKGEdldEdhbWVFbmdpbmVJbmZvUmVxdWVzdCKEAQoZR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZRIRCglnYW1lX2NvZGUYASABKAkSDwoHdmVyc2lvbhgCIAEoCRILCgNydHAYAyABKAESEQoJZ2FtZV90eXBlGAQgASgJEhEKCWdhbWVfbmFtZRgFIAEoCRIQCghwcm92aWRlchgGIAEoCTLSAQoRR2FtZUVuZ2luZVNlcnZpY2USWQoOUHJvY2Vzc0NvbW1hbmQSIi5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlcXVlc3QaIy5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlc3BvbnNlEmIKEUdldEdhbWVFbmdpbmVJbmZvEiUuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXF1ZXN0GiYuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZWIGcHJvdG8z", [file_google_protobuf_struct]);
|
|
12
10
|
/**
|
|
13
11
|
* Describes the message game_engine.ProcessCommandRequest.
|
|
14
12
|
* Use `create(ProcessCommandRequestSchema)` to create a new message.
|
|
15
13
|
*/
|
|
16
|
-
export const ProcessCommandRequestSchema =
|
|
17
|
-
/*@__PURE__*/
|
|
18
|
-
messageDesc(file_game_engine, 0);
|
|
14
|
+
export const ProcessCommandRequestSchema = /*@__PURE__*/ messageDesc(file_game_engine, 0);
|
|
19
15
|
/**
|
|
20
16
|
* Describes the message game_engine.GameActionCommand.
|
|
21
17
|
* Use `create(GameActionCommandSchema)` to create a new message.
|
|
22
18
|
*/
|
|
23
|
-
export const GameActionCommandSchema =
|
|
24
|
-
/*@__PURE__*/
|
|
25
|
-
messageDesc(file_game_engine, 1);
|
|
19
|
+
export const GameActionCommandSchema = /*@__PURE__*/ messageDesc(file_game_engine, 1);
|
|
26
20
|
/**
|
|
27
21
|
* Describes the message game_engine.RngOutcomeRecord.
|
|
28
22
|
* Use `create(RngOutcomeRecordSchema)` to create a new message.
|
|
29
23
|
*/
|
|
30
|
-
export const RngOutcomeRecordSchema =
|
|
31
|
-
/*@__PURE__*/
|
|
32
|
-
messageDesc(file_game_engine, 2);
|
|
24
|
+
export const RngOutcomeRecordSchema = /*@__PURE__*/ messageDesc(file_game_engine, 2);
|
|
33
25
|
/**
|
|
34
26
|
* Describes the message game_engine.ProcessCommandResponse.
|
|
35
27
|
* Use `create(ProcessCommandResponseSchema)` to create a new message.
|
|
36
28
|
*/
|
|
37
|
-
export const ProcessCommandResponseSchema =
|
|
38
|
-
/*@__PURE__*/
|
|
39
|
-
messageDesc(file_game_engine, 3);
|
|
29
|
+
export const ProcessCommandResponseSchema = /*@__PURE__*/ messageDesc(file_game_engine, 3);
|
|
40
30
|
/**
|
|
41
31
|
* Describes the message game_engine.GetGameEngineInfoRequest.
|
|
42
32
|
* Use `create(GetGameEngineInfoRequestSchema)` to create a new message.
|
|
43
33
|
*/
|
|
44
|
-
export const GetGameEngineInfoRequestSchema =
|
|
45
|
-
/*@__PURE__*/
|
|
46
|
-
messageDesc(file_game_engine, 4);
|
|
34
|
+
export const GetGameEngineInfoRequestSchema = /*@__PURE__*/ messageDesc(file_game_engine, 4);
|
|
47
35
|
/**
|
|
48
36
|
* Describes the message game_engine.GetGameEngineInfoResponse.
|
|
49
37
|
* Use `create(GetGameEngineInfoResponseSchema)` to create a new message.
|
|
50
38
|
*/
|
|
51
|
-
export const GetGameEngineInfoResponseSchema =
|
|
52
|
-
/*@__PURE__*/
|
|
53
|
-
messageDesc(file_game_engine, 5);
|
|
39
|
+
export const GetGameEngineInfoResponseSchema = /*@__PURE__*/ messageDesc(file_game_engine, 5);
|
|
54
40
|
/**
|
|
55
41
|
* @generated from service game_engine.GameEngineService
|
|
56
42
|
*/
|
|
@@ -3,14 +3,20 @@ import { GameEngineService } from '../generated/game-engine_pb';
|
|
|
3
3
|
/**
|
|
4
4
|
* Creates Connect router middleware for GameEngineService.
|
|
5
5
|
* This replaces NestJS built-in gRPC transport with Connect-compatible server.
|
|
6
|
+
*
|
|
7
|
+
* @param gameEngineAdapter - The gRPC adapter handling game engine requests
|
|
8
|
+
* @param options - Optional configuration including additional route registration
|
|
6
9
|
*/
|
|
7
|
-
export function createConnectRouter(gameEngineAdapter) {
|
|
10
|
+
export function createConnectRouter(gameEngineAdapter, options) {
|
|
8
11
|
return connectNodeAdapter({
|
|
9
12
|
routes: router => {
|
|
10
13
|
router.service(GameEngineService, {
|
|
11
14
|
processCommand: gameEngineAdapter.processCommand.bind(gameEngineAdapter),
|
|
12
15
|
getGameEngineInfo: gameEngineAdapter.getGameEngineInfo.bind(gameEngineAdapter),
|
|
13
16
|
});
|
|
17
|
+
if (options?.additionalRoutes) {
|
|
18
|
+
options.additionalRoutes(router);
|
|
19
|
+
}
|
|
14
20
|
},
|
|
15
21
|
});
|
|
16
22
|
}
|