@omnitronix/game-engine-sdk 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/debug/debug-command-registry.d.ts +186 -0
- package/dist/debug/debug-command-registry.d.ts.map +1 -0
- package/dist/debug/debug-command-registry.js +163 -0
- package/dist/debug/index.d.ts +26 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +34 -0
- package/dist/esm/debug/debug-command-registry.js +156 -0
- package/dist/esm/debug/index.js +29 -0
- package/dist/esm/generated/game-engine-registry_pb.js +4 -10
- package/dist/esm/generated/game-engine_pb.js +9 -23
- package/dist/esm/grpc/game-engine.grpc.in-adapter.js +19 -4
- package/dist/esm/index.js +2 -0
- 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 +3 -9
- package/dist/generated/game-engine_pb.d.ts +18 -10
- package/dist/generated/game-engine_pb.d.ts.map +1 -1
- package/dist/generated/game-engine_pb.js +7 -21
- package/dist/grpc/game-engine.grpc.in-adapter.d.ts +4 -0
- package/dist/grpc/game-engine.grpc.in-adapter.d.ts.map +1 -1
- package/dist/grpc/game-engine.grpc.in-adapter.js +19 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +12 -2
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Command Registry
|
|
3
|
+
*
|
|
4
|
+
* A registry pattern implementation for debug commands that provides
|
|
5
|
+
* a single source of truth for both definitions and execution.
|
|
6
|
+
*
|
|
7
|
+
* This eliminates the risk of definition/implementation drift by
|
|
8
|
+
* co-locating the command metadata with its handler.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const debugCommands = createDebugCommandRegistry({
|
|
13
|
+
* TRIGGER_BONUS: {
|
|
14
|
+
* displayName: 'Trigger Bonus',
|
|
15
|
+
* description: 'Force-trigger a specific bonus type',
|
|
16
|
+
* category: 'bonus',
|
|
17
|
+
* parameters: [
|
|
18
|
+
* {
|
|
19
|
+
* name: 'bonusType',
|
|
20
|
+
* displayName: 'Bonus Type',
|
|
21
|
+
* type: 'enum',
|
|
22
|
+
* enumValues: ['BONUS_GAME', 'FREE_SPIN_AIR', 'FREE_SPIN_WATER'],
|
|
23
|
+
* },
|
|
24
|
+
* ],
|
|
25
|
+
* execute: async (engine, params) => {
|
|
26
|
+
* return engine.triggerBonus(params.bonusType);
|
|
27
|
+
* },
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Get definitions for dev-tools
|
|
32
|
+
* const definitions = debugCommands.getDefinitions();
|
|
33
|
+
*
|
|
34
|
+
* // Execute a command
|
|
35
|
+
* const result = await debugCommands.execute('TRIGGER_BONUS', engine, { bonusType: 'BONUS_GAME' });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
import { DebugCommandDefinition, DebugParameterDefinition } from '@omnitronix/game-engine-contract';
|
|
39
|
+
/**
|
|
40
|
+
* Handler function type for debug commands.
|
|
41
|
+
* Receives the game engine instance and validated parameters.
|
|
42
|
+
*/
|
|
43
|
+
export type DebugCommandHandler<TEngine, TParams, TResult> = (engine: TEngine, params: TParams) => Promise<TResult> | TResult;
|
|
44
|
+
/**
|
|
45
|
+
* Configuration for a single debug command in the registry.
|
|
46
|
+
*/
|
|
47
|
+
export interface DebugCommandConfig<TEngine, TParams = Record<string, unknown>, TResult = unknown> {
|
|
48
|
+
/**
|
|
49
|
+
* Human-readable display name
|
|
50
|
+
*/
|
|
51
|
+
displayName: string;
|
|
52
|
+
/**
|
|
53
|
+
* Detailed description of what this command does
|
|
54
|
+
*/
|
|
55
|
+
description?: string;
|
|
56
|
+
/**
|
|
57
|
+
* Grouping category for UI organization
|
|
58
|
+
*/
|
|
59
|
+
category?: string;
|
|
60
|
+
/**
|
|
61
|
+
* Parameter definitions
|
|
62
|
+
*/
|
|
63
|
+
parameters?: DebugParameterDefinition[];
|
|
64
|
+
/**
|
|
65
|
+
* Whether this command can cause issues (shows warning in UI)
|
|
66
|
+
*/
|
|
67
|
+
dangerous?: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Warning message to display
|
|
70
|
+
*/
|
|
71
|
+
warningMessage?: string;
|
|
72
|
+
/**
|
|
73
|
+
* The command execution handler
|
|
74
|
+
*/
|
|
75
|
+
execute: DebugCommandHandler<TEngine, TParams, TResult>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Registry configuration type.
|
|
79
|
+
* Maps command codes to their configurations.
|
|
80
|
+
*/
|
|
81
|
+
export type DebugCommandRegistryConfig<TEngine> = {
|
|
82
|
+
[code: string]: DebugCommandConfig<TEngine, any, any>;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The debug command registry interface.
|
|
86
|
+
*/
|
|
87
|
+
export interface DebugCommandRegistry<TEngine> {
|
|
88
|
+
/**
|
|
89
|
+
* Get all command definitions (for dev-tools).
|
|
90
|
+
* Safe to call - strips execute handlers before returning.
|
|
91
|
+
*/
|
|
92
|
+
getDefinitions(): DebugCommandDefinition[];
|
|
93
|
+
/**
|
|
94
|
+
* Execute a debug command by code.
|
|
95
|
+
*
|
|
96
|
+
* @param code - The command code to execute
|
|
97
|
+
* @param engine - The game engine instance
|
|
98
|
+
* @param params - The command parameters
|
|
99
|
+
* @throws Error if command code is not found
|
|
100
|
+
*/
|
|
101
|
+
execute<TResult = unknown>(code: string, engine: TEngine, params: Record<string, unknown>): Promise<TResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Check if a command code exists in the registry.
|
|
104
|
+
*/
|
|
105
|
+
hasCommand(code: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Get list of all registered command codes.
|
|
108
|
+
*/
|
|
109
|
+
getCommandCodes(): string[];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates a debug command registry with type-safe definitions and handlers.
|
|
113
|
+
*
|
|
114
|
+
* The registry pattern ensures that:
|
|
115
|
+
* 1. Definitions and handlers are always in sync (single source of truth)
|
|
116
|
+
* 2. Type safety is maintained for parameters
|
|
117
|
+
* 3. Unknown commands throw clear errors
|
|
118
|
+
*
|
|
119
|
+
* @param config - Map of command codes to their configurations
|
|
120
|
+
* @returns A registry object with getDefinitions() and execute() methods
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* ```typescript
|
|
124
|
+
* const registry = createDebugCommandRegistry({
|
|
125
|
+
* FORCE_WIN: {
|
|
126
|
+
* displayName: 'Force Win',
|
|
127
|
+
* description: 'Force the next spin to be a winning spin',
|
|
128
|
+
* category: 'testing',
|
|
129
|
+
* parameters: [
|
|
130
|
+
* { name: 'multiplier', displayName: 'Win Multiplier', type: 'number', min: 1, max: 100 },
|
|
131
|
+
* ],
|
|
132
|
+
* execute: async (engine, { multiplier }) => {
|
|
133
|
+
* return engine.setNextWinMultiplier(multiplier);
|
|
134
|
+
* },
|
|
135
|
+
* },
|
|
136
|
+
* });
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
export declare function createDebugCommandRegistry<TEngine>(config: DebugCommandRegistryConfig<TEngine>): DebugCommandRegistry<TEngine>;
|
|
140
|
+
/**
|
|
141
|
+
* Security error thrown when debug features are accessed in production.
|
|
142
|
+
*/
|
|
143
|
+
export declare class DebugSecurityError extends Error {
|
|
144
|
+
constructor(message?: string);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Production guard wrapper for debug definitions.
|
|
148
|
+
*
|
|
149
|
+
* Throws DebugSecurityError in production environments as defense-in-depth.
|
|
150
|
+
* This should be called at the start of getDebugCommandDefinitions().
|
|
151
|
+
*
|
|
152
|
+
* @param logger - Optional logger for audit logging
|
|
153
|
+
* @throws DebugSecurityError if NODE_ENV is 'production'
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* getDebugCommandDefinitions(): DebugCommandDefinition[] {
|
|
158
|
+
* assertNotProduction(this.logger);
|
|
159
|
+
* return this.debugRegistry.getDefinitions();
|
|
160
|
+
* }
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
export declare function assertNotProduction(logger?: {
|
|
164
|
+
warn: (msg: string, ctx?: object) => void;
|
|
165
|
+
}): void;
|
|
166
|
+
/**
|
|
167
|
+
* Wraps a getDebugCommandDefinitions implementation with production guard.
|
|
168
|
+
*
|
|
169
|
+
* @param getDefinitions - The function that returns definitions
|
|
170
|
+
* @param logger - Optional logger for audit logging
|
|
171
|
+
* @returns A wrapped function that throws in production
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```typescript
|
|
175
|
+
* class MyEngine implements DebugIntrospectable {
|
|
176
|
+
* getDebugCommandDefinitions = withProductionGuard(
|
|
177
|
+
* () => this.debugRegistry.getDefinitions(),
|
|
178
|
+
* this.logger,
|
|
179
|
+
* );
|
|
180
|
+
* }
|
|
181
|
+
* ```
|
|
182
|
+
*/
|
|
183
|
+
export declare function withProductionGuard(getDefinitions: () => DebugCommandDefinition[], logger?: {
|
|
184
|
+
warn: (msg: string, ctx?: object) => void;
|
|
185
|
+
}): () => DebugCommandDefinition[];
|
|
186
|
+
//# sourceMappingURL=debug-command-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug-command-registry.d.ts","sourceRoot":"","sources":["../../src/debug/debug-command-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EACL,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,kCAAkC,CAAC;AAE1C;;;GAGG;AACH,MAAM,MAAM,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,CAC3D,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,OAAO,KACZ,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAEhC;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO;IAC/F;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,UAAU,CAAC,EAAE,wBAAwB,EAAE,CAAC;IAExC;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,OAAO,EAAE,mBAAmB,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;CACzD;AAED;;;GAGG;AACH,MAAM,MAAM,0BAA0B,CAAC,OAAO,IAAI;IAChD,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;CACvD,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,oBAAoB,CAAC,OAAO;IAC3C;;;OAGG;IACH,cAAc,IAAI,sBAAsB,EAAE,CAAC;IAE3C;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO,GAAG,OAAO,EACvB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,OAAO,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;IAElC;;OAEG;IACH,eAAe,IAAI,MAAM,EAAE,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAChD,MAAM,EAAE,0BAA0B,CAAC,OAAO,CAAC,GAC1C,oBAAoB,CAAC,OAAO,CAAC,CA6C/B;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,GAAE,MAAyD;CAI/E;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GAAG,IAAI,CAQhG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,cAAc,EAAE,MAAM,sBAAsB,EAAE,EAC9C,MAAM,CAAC,EAAE;IAAE,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,GACrD,MAAM,sBAAsB,EAAE,CAKhC"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Debug Command Registry
|
|
4
|
+
*
|
|
5
|
+
* A registry pattern implementation for debug commands that provides
|
|
6
|
+
* a single source of truth for both definitions and execution.
|
|
7
|
+
*
|
|
8
|
+
* This eliminates the risk of definition/implementation drift by
|
|
9
|
+
* co-locating the command metadata with its handler.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const debugCommands = createDebugCommandRegistry({
|
|
14
|
+
* TRIGGER_BONUS: {
|
|
15
|
+
* displayName: 'Trigger Bonus',
|
|
16
|
+
* description: 'Force-trigger a specific bonus type',
|
|
17
|
+
* category: 'bonus',
|
|
18
|
+
* parameters: [
|
|
19
|
+
* {
|
|
20
|
+
* name: 'bonusType',
|
|
21
|
+
* displayName: 'Bonus Type',
|
|
22
|
+
* type: 'enum',
|
|
23
|
+
* enumValues: ['BONUS_GAME', 'FREE_SPIN_AIR', 'FREE_SPIN_WATER'],
|
|
24
|
+
* },
|
|
25
|
+
* ],
|
|
26
|
+
* execute: async (engine, params) => {
|
|
27
|
+
* return engine.triggerBonus(params.bonusType);
|
|
28
|
+
* },
|
|
29
|
+
* },
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // Get definitions for dev-tools
|
|
33
|
+
* const definitions = debugCommands.getDefinitions();
|
|
34
|
+
*
|
|
35
|
+
* // Execute a command
|
|
36
|
+
* const result = await debugCommands.execute('TRIGGER_BONUS', engine, { bonusType: 'BONUS_GAME' });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.DebugSecurityError = void 0;
|
|
41
|
+
exports.createDebugCommandRegistry = createDebugCommandRegistry;
|
|
42
|
+
exports.assertNotProduction = assertNotProduction;
|
|
43
|
+
exports.withProductionGuard = withProductionGuard;
|
|
44
|
+
/**
|
|
45
|
+
* Creates a debug command registry with type-safe definitions and handlers.
|
|
46
|
+
*
|
|
47
|
+
* The registry pattern ensures that:
|
|
48
|
+
* 1. Definitions and handlers are always in sync (single source of truth)
|
|
49
|
+
* 2. Type safety is maintained for parameters
|
|
50
|
+
* 3. Unknown commands throw clear errors
|
|
51
|
+
*
|
|
52
|
+
* @param config - Map of command codes to their configurations
|
|
53
|
+
* @returns A registry object with getDefinitions() and execute() methods
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const registry = createDebugCommandRegistry({
|
|
58
|
+
* FORCE_WIN: {
|
|
59
|
+
* displayName: 'Force Win',
|
|
60
|
+
* description: 'Force the next spin to be a winning spin',
|
|
61
|
+
* category: 'testing',
|
|
62
|
+
* parameters: [
|
|
63
|
+
* { name: 'multiplier', displayName: 'Win Multiplier', type: 'number', min: 1, max: 100 },
|
|
64
|
+
* ],
|
|
65
|
+
* execute: async (engine, { multiplier }) => {
|
|
66
|
+
* return engine.setNextWinMultiplier(multiplier);
|
|
67
|
+
* },
|
|
68
|
+
* },
|
|
69
|
+
* });
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
function createDebugCommandRegistry(config) {
|
|
73
|
+
// Pre-compute definitions at creation time (immutable)
|
|
74
|
+
const definitions = Object.entries(config).map(([code, cmdConfig]) => ({
|
|
75
|
+
code,
|
|
76
|
+
commandType: `DEBUG_${code}`,
|
|
77
|
+
displayName: cmdConfig.displayName,
|
|
78
|
+
description: cmdConfig.description,
|
|
79
|
+
category: cmdConfig.category,
|
|
80
|
+
parameters: cmdConfig.parameters,
|
|
81
|
+
dangerous: cmdConfig.dangerous,
|
|
82
|
+
warningMessage: cmdConfig.warningMessage,
|
|
83
|
+
}));
|
|
84
|
+
return {
|
|
85
|
+
getDefinitions() {
|
|
86
|
+
// Return a copy to prevent external mutation
|
|
87
|
+
return [...definitions];
|
|
88
|
+
},
|
|
89
|
+
async execute(code, engine, params) {
|
|
90
|
+
const cmdConfig = config[code];
|
|
91
|
+
if (!cmdConfig) {
|
|
92
|
+
const available = Object.keys(config).join(', ');
|
|
93
|
+
throw new Error(`Unknown debug command: '${code}'. Available commands: ${available}`);
|
|
94
|
+
}
|
|
95
|
+
return cmdConfig.execute(engine, params);
|
|
96
|
+
},
|
|
97
|
+
hasCommand(code) {
|
|
98
|
+
return code in config;
|
|
99
|
+
},
|
|
100
|
+
getCommandCodes() {
|
|
101
|
+
return Object.keys(config);
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Security error thrown when debug features are accessed in production.
|
|
107
|
+
*/
|
|
108
|
+
class DebugSecurityError extends Error {
|
|
109
|
+
constructor(message = 'Debug features are not available in production') {
|
|
110
|
+
super(message);
|
|
111
|
+
this.name = 'DebugSecurityError';
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
exports.DebugSecurityError = DebugSecurityError;
|
|
115
|
+
/**
|
|
116
|
+
* Production guard wrapper for debug definitions.
|
|
117
|
+
*
|
|
118
|
+
* Throws DebugSecurityError in production environments as defense-in-depth.
|
|
119
|
+
* This should be called at the start of getDebugCommandDefinitions().
|
|
120
|
+
*
|
|
121
|
+
* @param logger - Optional logger for audit logging
|
|
122
|
+
* @throws DebugSecurityError if NODE_ENV is 'production'
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* getDebugCommandDefinitions(): DebugCommandDefinition[] {
|
|
127
|
+
* assertNotProduction(this.logger);
|
|
128
|
+
* return this.debugRegistry.getDefinitions();
|
|
129
|
+
* }
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
function assertNotProduction(logger) {
|
|
133
|
+
if (process.env.NODE_ENV === 'production') {
|
|
134
|
+
logger?.warn('Attempted to access debug definitions in production', {
|
|
135
|
+
timestamp: new Date().toISOString(),
|
|
136
|
+
nodeEnv: process.env.NODE_ENV,
|
|
137
|
+
});
|
|
138
|
+
throw new DebugSecurityError();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Wraps a getDebugCommandDefinitions implementation with production guard.
|
|
143
|
+
*
|
|
144
|
+
* @param getDefinitions - The function that returns definitions
|
|
145
|
+
* @param logger - Optional logger for audit logging
|
|
146
|
+
* @returns A wrapped function that throws in production
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```typescript
|
|
150
|
+
* class MyEngine implements DebugIntrospectable {
|
|
151
|
+
* getDebugCommandDefinitions = withProductionGuard(
|
|
152
|
+
* () => this.debugRegistry.getDefinitions(),
|
|
153
|
+
* this.logger,
|
|
154
|
+
* );
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
function withProductionGuard(getDefinitions, logger) {
|
|
159
|
+
return () => {
|
|
160
|
+
assertNotProduction(logger);
|
|
161
|
+
return getDefinitions();
|
|
162
|
+
};
|
|
163
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Command Infrastructure
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for game engines to implement DebugIntrospectable interface
|
|
5
|
+
* with the registry pattern for type-safe, single-source-of-truth debug commands.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import {
|
|
10
|
+
* createDebugCommandRegistry,
|
|
11
|
+
* withProductionGuard,
|
|
12
|
+
* DebugCommandRegistry,
|
|
13
|
+
* } from '@omnitronix/game-engine-sdk/debug';
|
|
14
|
+
*
|
|
15
|
+
* const debugRegistry = createDebugCommandRegistry({
|
|
16
|
+
* TRIGGER_BONUS: {
|
|
17
|
+
* displayName: 'Trigger Bonus',
|
|
18
|
+
* description: 'Force trigger a bonus round',
|
|
19
|
+
* category: 'bonus',
|
|
20
|
+
* execute: async (engine, params) => engine.triggerBonus(params.bonusType),
|
|
21
|
+
* },
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export { createDebugCommandRegistry, assertNotProduction, withProductionGuard, DebugSecurityError, DebugCommandHandler, DebugCommandConfig, DebugCommandRegistryConfig, DebugCommandRegistry, } from './debug-command-registry';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/debug/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAEL,0BAA0B,EAE1B,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAElB,mBAAmB,EACnB,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,GACrB,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Debug Command Infrastructure
|
|
4
|
+
*
|
|
5
|
+
* Provides utilities for game engines to implement DebugIntrospectable interface
|
|
6
|
+
* with the registry pattern for type-safe, single-source-of-truth debug commands.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import {
|
|
11
|
+
* createDebugCommandRegistry,
|
|
12
|
+
* withProductionGuard,
|
|
13
|
+
* DebugCommandRegistry,
|
|
14
|
+
* } from '@omnitronix/game-engine-sdk/debug';
|
|
15
|
+
*
|
|
16
|
+
* const debugRegistry = createDebugCommandRegistry({
|
|
17
|
+
* TRIGGER_BONUS: {
|
|
18
|
+
* displayName: 'Trigger Bonus',
|
|
19
|
+
* description: 'Force trigger a bonus round',
|
|
20
|
+
* category: 'bonus',
|
|
21
|
+
* execute: async (engine, params) => engine.triggerBonus(params.bonusType),
|
|
22
|
+
* },
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.DebugSecurityError = exports.withProductionGuard = exports.assertNotProduction = exports.createDebugCommandRegistry = void 0;
|
|
28
|
+
var debug_command_registry_1 = require("./debug-command-registry");
|
|
29
|
+
// Registry factory
|
|
30
|
+
Object.defineProperty(exports, "createDebugCommandRegistry", { enumerable: true, get: function () { return debug_command_registry_1.createDebugCommandRegistry; } });
|
|
31
|
+
// Production guards
|
|
32
|
+
Object.defineProperty(exports, "assertNotProduction", { enumerable: true, get: function () { return debug_command_registry_1.assertNotProduction; } });
|
|
33
|
+
Object.defineProperty(exports, "withProductionGuard", { enumerable: true, get: function () { return debug_command_registry_1.withProductionGuard; } });
|
|
34
|
+
Object.defineProperty(exports, "DebugSecurityError", { enumerable: true, get: function () { return debug_command_registry_1.DebugSecurityError; } });
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Command Registry
|
|
3
|
+
*
|
|
4
|
+
* A registry pattern implementation for debug commands that provides
|
|
5
|
+
* a single source of truth for both definitions and execution.
|
|
6
|
+
*
|
|
7
|
+
* This eliminates the risk of definition/implementation drift by
|
|
8
|
+
* co-locating the command metadata with its handler.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* const debugCommands = createDebugCommandRegistry({
|
|
13
|
+
* TRIGGER_BONUS: {
|
|
14
|
+
* displayName: 'Trigger Bonus',
|
|
15
|
+
* description: 'Force-trigger a specific bonus type',
|
|
16
|
+
* category: 'bonus',
|
|
17
|
+
* parameters: [
|
|
18
|
+
* {
|
|
19
|
+
* name: 'bonusType',
|
|
20
|
+
* displayName: 'Bonus Type',
|
|
21
|
+
* type: 'enum',
|
|
22
|
+
* enumValues: ['BONUS_GAME', 'FREE_SPIN_AIR', 'FREE_SPIN_WATER'],
|
|
23
|
+
* },
|
|
24
|
+
* ],
|
|
25
|
+
* execute: async (engine, params) => {
|
|
26
|
+
* return engine.triggerBonus(params.bonusType);
|
|
27
|
+
* },
|
|
28
|
+
* },
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Get definitions for dev-tools
|
|
32
|
+
* const definitions = debugCommands.getDefinitions();
|
|
33
|
+
*
|
|
34
|
+
* // Execute a command
|
|
35
|
+
* const result = await debugCommands.execute('TRIGGER_BONUS', engine, { bonusType: 'BONUS_GAME' });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
/**
|
|
39
|
+
* Creates a debug command registry with type-safe definitions and handlers.
|
|
40
|
+
*
|
|
41
|
+
* The registry pattern ensures that:
|
|
42
|
+
* 1. Definitions and handlers are always in sync (single source of truth)
|
|
43
|
+
* 2. Type safety is maintained for parameters
|
|
44
|
+
* 3. Unknown commands throw clear errors
|
|
45
|
+
*
|
|
46
|
+
* @param config - Map of command codes to their configurations
|
|
47
|
+
* @returns A registry object with getDefinitions() and execute() methods
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```typescript
|
|
51
|
+
* const registry = createDebugCommandRegistry({
|
|
52
|
+
* FORCE_WIN: {
|
|
53
|
+
* displayName: 'Force Win',
|
|
54
|
+
* description: 'Force the next spin to be a winning spin',
|
|
55
|
+
* category: 'testing',
|
|
56
|
+
* parameters: [
|
|
57
|
+
* { name: 'multiplier', displayName: 'Win Multiplier', type: 'number', min: 1, max: 100 },
|
|
58
|
+
* ],
|
|
59
|
+
* execute: async (engine, { multiplier }) => {
|
|
60
|
+
* return engine.setNextWinMultiplier(multiplier);
|
|
61
|
+
* },
|
|
62
|
+
* },
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export function createDebugCommandRegistry(config) {
|
|
67
|
+
// Pre-compute definitions at creation time (immutable)
|
|
68
|
+
const definitions = Object.entries(config).map(([code, cmdConfig]) => ({
|
|
69
|
+
code,
|
|
70
|
+
commandType: `DEBUG_${code}`,
|
|
71
|
+
displayName: cmdConfig.displayName,
|
|
72
|
+
description: cmdConfig.description,
|
|
73
|
+
category: cmdConfig.category,
|
|
74
|
+
parameters: cmdConfig.parameters,
|
|
75
|
+
dangerous: cmdConfig.dangerous,
|
|
76
|
+
warningMessage: cmdConfig.warningMessage,
|
|
77
|
+
}));
|
|
78
|
+
return {
|
|
79
|
+
getDefinitions() {
|
|
80
|
+
// Return a copy to prevent external mutation
|
|
81
|
+
return [...definitions];
|
|
82
|
+
},
|
|
83
|
+
async execute(code, engine, params) {
|
|
84
|
+
const cmdConfig = config[code];
|
|
85
|
+
if (!cmdConfig) {
|
|
86
|
+
const available = Object.keys(config).join(', ');
|
|
87
|
+
throw new Error(`Unknown debug command: '${code}'. Available commands: ${available}`);
|
|
88
|
+
}
|
|
89
|
+
return cmdConfig.execute(engine, params);
|
|
90
|
+
},
|
|
91
|
+
hasCommand(code) {
|
|
92
|
+
return code in config;
|
|
93
|
+
},
|
|
94
|
+
getCommandCodes() {
|
|
95
|
+
return Object.keys(config);
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Security error thrown when debug features are accessed in production.
|
|
101
|
+
*/
|
|
102
|
+
export class DebugSecurityError extends Error {
|
|
103
|
+
constructor(message = 'Debug features are not available in production') {
|
|
104
|
+
super(message);
|
|
105
|
+
this.name = 'DebugSecurityError';
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Production guard wrapper for debug definitions.
|
|
110
|
+
*
|
|
111
|
+
* Throws DebugSecurityError in production environments as defense-in-depth.
|
|
112
|
+
* This should be called at the start of getDebugCommandDefinitions().
|
|
113
|
+
*
|
|
114
|
+
* @param logger - Optional logger for audit logging
|
|
115
|
+
* @throws DebugSecurityError if NODE_ENV is 'production'
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```typescript
|
|
119
|
+
* getDebugCommandDefinitions(): DebugCommandDefinition[] {
|
|
120
|
+
* assertNotProduction(this.logger);
|
|
121
|
+
* return this.debugRegistry.getDefinitions();
|
|
122
|
+
* }
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export function assertNotProduction(logger) {
|
|
126
|
+
if (process.env.NODE_ENV === 'production') {
|
|
127
|
+
logger?.warn('Attempted to access debug definitions in production', {
|
|
128
|
+
timestamp: new Date().toISOString(),
|
|
129
|
+
nodeEnv: process.env.NODE_ENV,
|
|
130
|
+
});
|
|
131
|
+
throw new DebugSecurityError();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Wraps a getDebugCommandDefinitions implementation with production guard.
|
|
136
|
+
*
|
|
137
|
+
* @param getDefinitions - The function that returns definitions
|
|
138
|
+
* @param logger - Optional logger for audit logging
|
|
139
|
+
* @returns A wrapped function that throws in production
|
|
140
|
+
*
|
|
141
|
+
* @example
|
|
142
|
+
* ```typescript
|
|
143
|
+
* class MyEngine implements DebugIntrospectable {
|
|
144
|
+
* getDebugCommandDefinitions = withProductionGuard(
|
|
145
|
+
* () => this.debugRegistry.getDefinitions(),
|
|
146
|
+
* this.logger,
|
|
147
|
+
* );
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
export function withProductionGuard(getDefinitions, logger) {
|
|
152
|
+
return () => {
|
|
153
|
+
assertNotProduction(logger);
|
|
154
|
+
return getDefinitions();
|
|
155
|
+
};
|
|
156
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Debug Command Infrastructure
|
|
3
|
+
*
|
|
4
|
+
* Provides utilities for game engines to implement DebugIntrospectable interface
|
|
5
|
+
* with the registry pattern for type-safe, single-source-of-truth debug commands.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import {
|
|
10
|
+
* createDebugCommandRegistry,
|
|
11
|
+
* withProductionGuard,
|
|
12
|
+
* DebugCommandRegistry,
|
|
13
|
+
* } from '@omnitronix/game-engine-sdk/debug';
|
|
14
|
+
*
|
|
15
|
+
* const debugRegistry = createDebugCommandRegistry({
|
|
16
|
+
* TRIGGER_BONUS: {
|
|
17
|
+
* displayName: 'Trigger Bonus',
|
|
18
|
+
* description: 'Force trigger a bonus round',
|
|
19
|
+
* category: 'bonus',
|
|
20
|
+
* execute: async (engine, params) => engine.triggerBonus(params.bonusType),
|
|
21
|
+
* },
|
|
22
|
+
* });
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export {
|
|
26
|
+
// Registry factory
|
|
27
|
+
createDebugCommandRegistry,
|
|
28
|
+
// Production guards
|
|
29
|
+
assertNotProduction, withProductionGuard, DebugSecurityError, } from './debug-command-registry';
|
|
@@ -1,27 +1,21 @@
|
|
|
1
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
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('ChFnYW1lLWVuZ2luZS5wcm90bxILZ2FtZV9lbmdpbmUi5QEKFVByb2Nlc3NDb21tYW5kUmVxdWVzdBIyCgxwdWJsaWNfc3RhdGUYASABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgCIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARI0Cgdjb21tYW5kGAMgASgLMh4uZ2FtZV9lbmdpbmUuR2FtZUFjdGlvbkNvbW1hbmRIAogBAUIPCg1fcHVibGljX3N0YXRlQhAKDl9wcml2YXRlX3N0YXRlQgoKCF9jb21tYW5kImgKEUdhbWVBY3Rpb25Db21tYW5kEgoKAmlkGAEgASgJEgwKBHR5cGUYAiABKAkSLQoHcGF5bG9hZBgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAIgBAUIKCghfcGF5bG9hZCJKChBSbmdPdXRjb21lUmVjb3JkEg4KBnJlc3VsdBgBIAEoARIMCgRzZWVkGAIgASgJEgsKA21pbhgDIAEoARILCgNtYXgYBCABKAEirgMKFlByb2Nlc3NDb21tYW5kUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIyCgxwdWJsaWNfc3RhdGUYAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARItCgdvdXRjb21lGAQgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEgCiAEBEhQKB21lc3NhZ2UYBSABKAlIA4gBARJICgtybmdfb3V0Y29tZRgGIAMoCzIzLmdhbWVfZW5naW5lLlByb2Nlc3NDb21tYW5kUmVzcG9uc2UuUm5nT3V0Y29tZUVudHJ5GlAKD1JuZ091dGNvbWVFbnRyeRILCgNrZXkYASABKAkSLAoFdmFsdWUYAiABKAsyHS5nYW1lX2VuZ2luZS5SbmdPdXRjb21lUmVjb3JkOgI4AUIPCg1fcHVibGljX3N0YXRlQhAKDl9wcml2YXRlX3N0YXRlQgoKCF9vdXRjb21lQgoKCF9tZXNzYWdlIhoKGEdldEdhbWVFbmdpbmVJbmZvUmVxdWVzdCKEAQoZR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZRIRCglnYW1lX2NvZGUYASABKAkSDwoHdmVyc2lvbhgCIAEoCRILCgNydHAYAyABKAESEQoJZ2FtZV90eXBlGAQgASgJEhEKCWdhbWVfbmFtZRgFIAEoCRIQCghwcm92aWRlchgGIAEoCTLSAQoRR2FtZUVuZ2luZVNlcnZpY2USWQoOUHJvY2Vzc0NvbW1hbmQSIi5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlcXVlc3QaIy5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlc3BvbnNlEmIKEUdldEdhbWVFbmdpbmVJbmZvEiUuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXF1ZXN0GiYuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZWIGcHJvdG8z', [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
|
*/
|
|
@@ -28,8 +28,9 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
28
28
|
const command = this.extractCommandFromRequest(request);
|
|
29
29
|
const publicState = request.publicState ?? {};
|
|
30
30
|
const privateState = request.privateState ?? {};
|
|
31
|
+
const additionalData = request.additionalData;
|
|
31
32
|
const result = await this.gameEngineInPort.processCommand(publicState, privateState, command);
|
|
32
|
-
return this.createSuccessResponse(result);
|
|
33
|
+
return this.createSuccessResponse(result, additionalData);
|
|
33
34
|
}
|
|
34
35
|
catch (error) {
|
|
35
36
|
this.logger.error('Error in processCommand', error);
|
|
@@ -49,8 +50,10 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
49
50
|
}
|
|
50
51
|
return { id, type, payload };
|
|
51
52
|
}
|
|
52
|
-
createSuccessResponse(result) {
|
|
53
|
+
createSuccessResponse(result, requestAdditionalData) {
|
|
53
54
|
const rngOutcome = this.convertRngOutcome(result.rngOutcome);
|
|
55
|
+
// additionalData passthrough: game engine result takes precedence, falls back to request
|
|
56
|
+
const additionalData = result.additionalData ?? requestAdditionalData;
|
|
54
57
|
return create(ProcessCommandResponseSchema, {
|
|
55
58
|
success: result.success ?? true,
|
|
56
59
|
// Cast at gRPC boundary: game engine state objects are serialized as protobuf Struct
|
|
@@ -59,6 +62,7 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
59
62
|
outcome: result.outcome,
|
|
60
63
|
message: result.message,
|
|
61
64
|
rngOutcome: rngOutcome,
|
|
65
|
+
additionalData: additionalData,
|
|
62
66
|
});
|
|
63
67
|
}
|
|
64
68
|
/**
|
|
@@ -105,15 +109,26 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
105
109
|
* Validate a single RNG outcome record for GLI-19 compliance.
|
|
106
110
|
* Throws INVALID_RNG_SEED on any invalid numeric field to prevent
|
|
107
111
|
* silent data corruption in the audit trail.
|
|
112
|
+
*
|
|
113
|
+
* Note: seed field may come as string from RNG service (JSON parsing).
|
|
114
|
+
* We accept both number and numeric string for seed since it's converted
|
|
115
|
+
* to string for wire format anyway.
|
|
108
116
|
*/
|
|
109
117
|
validateRngRecord(key, record) {
|
|
110
|
-
|
|
111
|
-
|
|
118
|
+
// Validate result, min, max as strict numbers
|
|
119
|
+
const strictFields = ['result', 'min', 'max'];
|
|
120
|
+
for (const field of strictFields) {
|
|
112
121
|
const val = record[field];
|
|
113
122
|
if (typeof val !== 'number' || !isFinite(val)) {
|
|
114
123
|
throw new DomainException(InternalErrorCode.INVALID_RNG_SEED, `Invalid RNG ${field} for action '${key}': expected finite number, got ${String(val)}`);
|
|
115
124
|
}
|
|
116
125
|
}
|
|
126
|
+
// Validate seed - allow string or number (RNG service may return string)
|
|
127
|
+
const seed = record.seed;
|
|
128
|
+
const seedNum = typeof seed === 'string' ? Number(seed) : seed;
|
|
129
|
+
if (typeof seedNum !== 'number' || !isFinite(seedNum)) {
|
|
130
|
+
throw new DomainException(InternalErrorCode.INVALID_RNG_SEED, `Invalid RNG seed for action '${key}': expected finite number, got ${String(seed)}`);
|
|
131
|
+
}
|
|
117
132
|
if (record.min > record.max) {
|
|
118
133
|
throw new DomainException(InternalErrorCode.INVALID_RNG_SEED, `Invalid RNG range for action '${key}': min (${record.min}) > max (${record.max})`);
|
|
119
134
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -10,6 +10,8 @@ export * from './registration';
|
|
|
10
10
|
export * from './grpc';
|
|
11
11
|
// Bootstrap
|
|
12
12
|
export { createGameEngineApp } from './bootstrap';
|
|
13
|
+
// Debug command infrastructure
|
|
14
|
+
export * from './debug';
|
|
13
15
|
// Generated proto types (re-exported for convenience)
|
|
14
16
|
export { GameEngineService, ProcessCommandRequestSchema, ProcessCommandResponseSchema, GetGameEngineInfoRequestSchema, GetGameEngineInfoResponseSchema, } from './generated/game-engine_pb';
|
|
15
17
|
export { GameEngineRegistryService, RegisterGameEngineRequestSchema, RegisterGameEngineResponseSchema, } from './generated/game-engine-registry_pb';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { GenFile, GenMessage, GenService } from
|
|
2
|
-
import type { Message } from
|
|
1
|
+
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
|
|
2
|
+
import type { Message } from "@bufbuild/protobuf";
|
|
3
3
|
/**
|
|
4
4
|
* Describes the file game-engine-registry.proto.
|
|
5
5
|
*/
|
|
@@ -7,7 +7,7 @@ export declare const file_game_engine_registry: GenFile;
|
|
|
7
7
|
/**
|
|
8
8
|
* @generated from message game_engine_registry.RegisterGameEngineRequest
|
|
9
9
|
*/
|
|
10
|
-
export type RegisterGameEngineRequest = Message<
|
|
10
|
+
export type RegisterGameEngineRequest = Message<"game_engine_registry.RegisterGameEngineRequest"> & {
|
|
11
11
|
/**
|
|
12
12
|
* @generated from field: string game_code = 1;
|
|
13
13
|
*/
|
|
@@ -45,7 +45,7 @@ export declare const RegisterGameEngineRequestSchema: GenMessage<RegisterGameEng
|
|
|
45
45
|
/**
|
|
46
46
|
* @generated from message game_engine_registry.RegisterGameEngineResponse
|
|
47
47
|
*/
|
|
48
|
-
export type RegisterGameEngineResponse = Message<
|
|
48
|
+
export type RegisterGameEngineResponse = Message<"game_engine_registry.RegisterGameEngineResponse"> & {
|
|
49
49
|
/**
|
|
50
50
|
* @generated from field: bool success = 1;
|
|
51
51
|
*/
|
|
@@ -68,7 +68,7 @@ export declare const GameEngineRegistryService: GenService<{
|
|
|
68
68
|
* @generated from rpc game_engine_registry.GameEngineRegistryService.RegisterGameEngine
|
|
69
69
|
*/
|
|
70
70
|
registerGameEngine: {
|
|
71
|
-
methodKind:
|
|
71
|
+
methodKind: "unary";
|
|
72
72
|
input: typeof RegisterGameEngineRequestSchema;
|
|
73
73
|
output: typeof RegisterGameEngineResponseSchema;
|
|
74
74
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-engine-registry_pb.d.ts","sourceRoot":"","sources":["../../src/generated/game-engine-registry_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,
|
|
1
|
+
{"version":3,"file":"game-engine-registry_pb.d.ts","sourceRoot":"","sources":["../../src/generated/game-engine-registry_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAEpF,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,OACqjB,CAAC;AAE9lB;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,gDAAgD,CAAC,GAAG;IAClG;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,+BAA+B,EAAE,UAAU,CAAC,yBAAyB,CACvC,CAAC;AAE5C;;GAEG;AACH,MAAM,MAAM,0BAA0B,GAAG,OAAO,CAAC,iDAAiD,CAAC,GAAG;IACpG;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gCAAgC,EAAE,UAAU,CAAC,0BAA0B,CACzC,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,UAAU,CAAC;IACjD;;OAEG;IACH,kBAAkB,EAAE;QAClB,UAAU,EAAE,OAAO,CAAC;QACpB,KAAK,EAAE,OAAO,+BAA+B,CAAC;QAC9C,MAAM,EAAE,OAAO,gCAAgC,CAAC;KACjD,CAAC;CACH,CAC0C,CAAC"}
|
|
@@ -8,23 +8,17 @@ const codegenv2_1 = require("@bufbuild/protobuf/codegenv2");
|
|
|
8
8
|
/**
|
|
9
9
|
* Describes the file game-engine-registry.proto.
|
|
10
10
|
*/
|
|
11
|
-
exports.file_game_engine_registry =
|
|
12
|
-
/*@__PURE__*/
|
|
13
|
-
(0, codegenv2_1.fileDesc)('ChpnYW1lLWVuZ2luZS1yZWdpc3RyeS5wcm90bxIUZ2FtZV9lbmdpbmVfcmVnaXN0cnkilgEKGVJlZ2lzdGVyR2FtZUVuZ2luZVJlcXVlc3QSEQoJZ2FtZV9jb2RlGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSCwoDcnRwGAMgASgBEhEKCWdhbWVfdHlwZRgEIAEoCRIQCghncnBjX3VybBgFIAEoCRIRCglnYW1lX25hbWUYBiABKAkSEAoIcHJvdmlkZXIYByABKAkiTwoaUmVnaXN0ZXJHYW1lRW5naW5lUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIUCgdtZXNzYWdlGAIgASgJSACIAQFCCgoIX21lc3NhZ2UylAEKGUdhbWVFbmdpbmVSZWdpc3RyeVNlcnZpY2USdwoSUmVnaXN0ZXJHYW1lRW5naW5lEi8uZ2FtZV9lbmdpbmVfcmVnaXN0cnkuUmVnaXN0ZXJHYW1lRW5naW5lUmVxdWVzdBowLmdhbWVfZW5naW5lX3JlZ2lzdHJ5LlJlZ2lzdGVyR2FtZUVuZ2luZVJlc3BvbnNlYgZwcm90bzM');
|
|
11
|
+
exports.file_game_engine_registry = (0, codegenv2_1.fileDesc)("ChpnYW1lLWVuZ2luZS1yZWdpc3RyeS5wcm90bxIUZ2FtZV9lbmdpbmVfcmVnaXN0cnkilgEKGVJlZ2lzdGVyR2FtZUVuZ2luZVJlcXVlc3QSEQoJZ2FtZV9jb2RlGAEgASgJEg8KB3ZlcnNpb24YAiABKAkSCwoDcnRwGAMgASgBEhEKCWdhbWVfdHlwZRgEIAEoCRIQCghncnBjX3VybBgFIAEoCRIRCglnYW1lX25hbWUYBiABKAkSEAoIcHJvdmlkZXIYByABKAkiTwoaUmVnaXN0ZXJHYW1lRW5naW5lUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIUCgdtZXNzYWdlGAIgASgJSACIAQFCCgoIX21lc3NhZ2UylAEKGUdhbWVFbmdpbmVSZWdpc3RyeVNlcnZpY2USdwoSUmVnaXN0ZXJHYW1lRW5naW5lEi8uZ2FtZV9lbmdpbmVfcmVnaXN0cnkuUmVnaXN0ZXJHYW1lRW5naW5lUmVxdWVzdBowLmdhbWVfZW5naW5lX3JlZ2lzdHJ5LlJlZ2lzdGVyR2FtZUVuZ2luZVJlc3BvbnNlYgZwcm90bzM");
|
|
14
12
|
/**
|
|
15
13
|
* Describes the message game_engine_registry.RegisterGameEngineRequest.
|
|
16
14
|
* Use `create(RegisterGameEngineRequestSchema)` to create a new message.
|
|
17
15
|
*/
|
|
18
|
-
exports.RegisterGameEngineRequestSchema =
|
|
19
|
-
/*@__PURE__*/
|
|
20
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine_registry, 0);
|
|
16
|
+
exports.RegisterGameEngineRequestSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine_registry, 0);
|
|
21
17
|
/**
|
|
22
18
|
* Describes the message game_engine_registry.RegisterGameEngineResponse.
|
|
23
19
|
* Use `create(RegisterGameEngineResponseSchema)` to create a new message.
|
|
24
20
|
*/
|
|
25
|
-
exports.RegisterGameEngineResponseSchema =
|
|
26
|
-
/*@__PURE__*/
|
|
27
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine_registry, 1);
|
|
21
|
+
exports.RegisterGameEngineResponseSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine_registry, 1);
|
|
28
22
|
/**
|
|
29
23
|
* @generated from service game_engine_registry.GameEngineRegistryService
|
|
30
24
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { GenFile, GenMessage, GenService } from
|
|
2
|
-
import type { JsonObject, Message } from
|
|
1
|
+
import type { GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
|
|
2
|
+
import type { JsonObject, Message } from "@bufbuild/protobuf";
|
|
3
3
|
/**
|
|
4
4
|
* Describes the file game-engine.proto.
|
|
5
5
|
*/
|
|
@@ -7,7 +7,7 @@ export declare const file_game_engine: GenFile;
|
|
|
7
7
|
/**
|
|
8
8
|
* @generated from message game_engine.ProcessCommandRequest
|
|
9
9
|
*/
|
|
10
|
-
export type ProcessCommandRequest = Message<
|
|
10
|
+
export type ProcessCommandRequest = Message<"game_engine.ProcessCommandRequest"> & {
|
|
11
11
|
/**
|
|
12
12
|
* @generated from field: optional google.protobuf.Struct public_state = 1;
|
|
13
13
|
*/
|
|
@@ -20,6 +20,10 @@ export type ProcessCommandRequest = Message<'game_engine.ProcessCommandRequest'>
|
|
|
20
20
|
* @generated from field: optional game_engine.GameActionCommand command = 3;
|
|
21
21
|
*/
|
|
22
22
|
command?: GameActionCommand;
|
|
23
|
+
/**
|
|
24
|
+
* @generated from field: optional google.protobuf.Struct additional_data = 4;
|
|
25
|
+
*/
|
|
26
|
+
additionalData?: JsonObject;
|
|
23
27
|
};
|
|
24
28
|
/**
|
|
25
29
|
* Describes the message game_engine.ProcessCommandRequest.
|
|
@@ -29,7 +33,7 @@ export declare const ProcessCommandRequestSchema: GenMessage<ProcessCommandReque
|
|
|
29
33
|
/**
|
|
30
34
|
* @generated from message game_engine.GameActionCommand
|
|
31
35
|
*/
|
|
32
|
-
export type GameActionCommand = Message<
|
|
36
|
+
export type GameActionCommand = Message<"game_engine.GameActionCommand"> & {
|
|
33
37
|
/**
|
|
34
38
|
* @generated from field: string id = 1;
|
|
35
39
|
*/
|
|
@@ -51,7 +55,7 @@ export declare const GameActionCommandSchema: GenMessage<GameActionCommand>;
|
|
|
51
55
|
/**
|
|
52
56
|
* @generated from message game_engine.RngOutcomeRecord
|
|
53
57
|
*/
|
|
54
|
-
export type RngOutcomeRecord = Message<
|
|
58
|
+
export type RngOutcomeRecord = Message<"game_engine.RngOutcomeRecord"> & {
|
|
55
59
|
/**
|
|
56
60
|
* @generated from field: double result = 1;
|
|
57
61
|
*/
|
|
@@ -77,7 +81,7 @@ export declare const RngOutcomeRecordSchema: GenMessage<RngOutcomeRecord>;
|
|
|
77
81
|
/**
|
|
78
82
|
* @generated from message game_engine.ProcessCommandResponse
|
|
79
83
|
*/
|
|
80
|
-
export type ProcessCommandResponse = Message<
|
|
84
|
+
export type ProcessCommandResponse = Message<"game_engine.ProcessCommandResponse"> & {
|
|
81
85
|
/**
|
|
82
86
|
* @generated from field: bool success = 1;
|
|
83
87
|
*/
|
|
@@ -106,6 +110,10 @@ export type ProcessCommandResponse = Message<'game_engine.ProcessCommandResponse
|
|
|
106
110
|
rngOutcome: {
|
|
107
111
|
[key: string]: RngOutcomeRecord;
|
|
108
112
|
};
|
|
113
|
+
/**
|
|
114
|
+
* @generated from field: optional google.protobuf.Struct additional_data = 7;
|
|
115
|
+
*/
|
|
116
|
+
additionalData?: JsonObject;
|
|
109
117
|
};
|
|
110
118
|
/**
|
|
111
119
|
* Describes the message game_engine.ProcessCommandResponse.
|
|
@@ -115,7 +123,7 @@ export declare const ProcessCommandResponseSchema: GenMessage<ProcessCommandResp
|
|
|
115
123
|
/**
|
|
116
124
|
* @generated from message game_engine.GetGameEngineInfoRequest
|
|
117
125
|
*/
|
|
118
|
-
export type GetGameEngineInfoRequest = Message<
|
|
126
|
+
export type GetGameEngineInfoRequest = Message<"game_engine.GetGameEngineInfoRequest"> & {};
|
|
119
127
|
/**
|
|
120
128
|
* Describes the message game_engine.GetGameEngineInfoRequest.
|
|
121
129
|
* Use `create(GetGameEngineInfoRequestSchema)` to create a new message.
|
|
@@ -124,7 +132,7 @@ export declare const GetGameEngineInfoRequestSchema: GenMessage<GetGameEngineInf
|
|
|
124
132
|
/**
|
|
125
133
|
* @generated from message game_engine.GetGameEngineInfoResponse
|
|
126
134
|
*/
|
|
127
|
-
export type GetGameEngineInfoResponse = Message<
|
|
135
|
+
export type GetGameEngineInfoResponse = Message<"game_engine.GetGameEngineInfoResponse"> & {
|
|
128
136
|
/**
|
|
129
137
|
* @generated from field: string game_code = 1;
|
|
130
138
|
*/
|
|
@@ -163,7 +171,7 @@ export declare const GameEngineService: GenService<{
|
|
|
163
171
|
* @generated from rpc game_engine.GameEngineService.ProcessCommand
|
|
164
172
|
*/
|
|
165
173
|
processCommand: {
|
|
166
|
-
methodKind:
|
|
174
|
+
methodKind: "unary";
|
|
167
175
|
input: typeof ProcessCommandRequestSchema;
|
|
168
176
|
output: typeof ProcessCommandResponseSchema;
|
|
169
177
|
};
|
|
@@ -171,7 +179,7 @@ export declare const GameEngineService: GenService<{
|
|
|
171
179
|
* @generated from rpc game_engine.GameEngineService.GetGameEngineInfo
|
|
172
180
|
*/
|
|
173
181
|
getGameEngineInfo: {
|
|
174
|
-
methodKind:
|
|
182
|
+
methodKind: "unary";
|
|
175
183
|
input: typeof GetGameEngineInfoRequestSchema;
|
|
176
184
|
output: typeof GetGameEngineInfoResponseSchema;
|
|
177
185
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-engine_pb.d.ts","sourceRoot":"","sources":["../../src/generated/game-engine_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAGpF,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,
|
|
1
|
+
{"version":3,"file":"game-engine_pb.d.ts","sourceRoot":"","sources":["../../src/generated/game-engine_pb.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAGpF,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAE9D;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,OAC02D,CAAC;AAE14D;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG,OAAO,CAAC,mCAAmC,CAAC,GAAG;IACjF;;OAEG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IAEzB;;OAEG;IACH,YAAY,CAAC,EAAE,UAAU,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAE5B;;OAEG;IACH,cAAc,CAAC,EAAE,UAAU,CAAC;CAC7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,UAAU,CAAC,qBAAqB,CACxC,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC,+BAA+B,CAAC,GAAG;IACzE;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,EAAE,UAAU,CAAC,iBAAiB,CAChC,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,OAAO,CAAC,8BAA8B,CAAC,GAAG;IACvE;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,EAAE,UAAU,CAAC,gBAAgB,CAC9B,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,oCAAoC,CAAC,GAAG;IACnF;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IAEjB;;OAEG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IAEzB;;OAEG;IACH,YAAY,CAAC,EAAE,UAAU,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;;;OAIG;IACH,UAAU,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CAAA;KAAE,CAAC;IAEhD;;OAEG;IACH,cAAc,CAAC,EAAE,UAAU,CAAC;CAC7B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,UAAU,CAAC,sBAAsB,CAC1C,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,OAAO,CAAC,sCAAsC,CAAC,GAAG,EACxF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,UAAU,CAAC,wBAAwB,CAC9C,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,yBAAyB,GAAG,OAAO,CAAC,uCAAuC,CAAC,GAAG;IACzF;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,GAAG,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,+BAA+B,EAAE,UAAU,CAAC,yBAAyB,CAChD,CAAC;AAEnC;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAAU,CAAC;IACzC;;OAEG;IACH,cAAc,EAAE;QACd,UAAU,EAAE,OAAO,CAAC;QACpB,KAAK,EAAE,OAAO,2BAA2B,CAAC;QAC1C,MAAM,EAAE,OAAO,4BAA4B,CAAC;KAC7C,CAAC;IACF;;OAEG;IACH,iBAAiB,EAAE;QACjB,UAAU,EAAE,OAAO,CAAC;QACpB,KAAK,EAAE,OAAO,8BAA8B,CAAC;QAC7C,MAAM,EAAE,OAAO,+BAA+B,CAAC;KAChD,CAAC;CACH,CACiC,CAAC"}
|
|
@@ -9,51 +9,37 @@ const wkt_1 = require("@bufbuild/protobuf/wkt");
|
|
|
9
9
|
/**
|
|
10
10
|
* Describes the file game-engine.proto.
|
|
11
11
|
*/
|
|
12
|
-
exports.file_game_engine =
|
|
13
|
-
/*@__PURE__*/
|
|
14
|
-
(0, codegenv2_1.fileDesc)('ChFnYW1lLWVuZ2luZS5wcm90bxILZ2FtZV9lbmdpbmUi5QEKFVByb2Nlc3NDb21tYW5kUmVxdWVzdBIyCgxwdWJsaWNfc3RhdGUYASABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgCIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARI0Cgdjb21tYW5kGAMgASgLMh4uZ2FtZV9lbmdpbmUuR2FtZUFjdGlvbkNvbW1hbmRIAogBAUIPCg1fcHVibGljX3N0YXRlQhAKDl9wcml2YXRlX3N0YXRlQgoKCF9jb21tYW5kImgKEUdhbWVBY3Rpb25Db21tYW5kEgoKAmlkGAEgASgJEgwKBHR5cGUYAiABKAkSLQoHcGF5bG9hZBgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAIgBAUIKCghfcGF5bG9hZCJKChBSbmdPdXRjb21lUmVjb3JkEg4KBnJlc3VsdBgBIAEoARIMCgRzZWVkGAIgASgJEgsKA21pbhgDIAEoARILCgNtYXgYBCABKAEirgMKFlByb2Nlc3NDb21tYW5kUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIyCgxwdWJsaWNfc3RhdGUYAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARItCgdvdXRjb21lGAQgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEgCiAEBEhQKB21lc3NhZ2UYBSABKAlIA4gBARJICgtybmdfb3V0Y29tZRgGIAMoCzIzLmdhbWVfZW5naW5lLlByb2Nlc3NDb21tYW5kUmVzcG9uc2UuUm5nT3V0Y29tZUVudHJ5GlAKD1JuZ091dGNvbWVFbnRyeRILCgNrZXkYASABKAkSLAoFdmFsdWUYAiABKAsyHS5nYW1lX2VuZ2luZS5SbmdPdXRjb21lUmVjb3JkOgI4AUIPCg1fcHVibGljX3N0YXRlQhAKDl9wcml2YXRlX3N0YXRlQgoKCF9vdXRjb21lQgoKCF9tZXNzYWdlIhoKGEdldEdhbWVFbmdpbmVJbmZvUmVxdWVzdCKEAQoZR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZRIRCglnYW1lX2NvZGUYASABKAkSDwoHdmVyc2lvbhgCIAEoCRILCgNydHAYAyABKAESEQoJZ2FtZV90eXBlGAQgASgJEhEKCWdhbWVfbmFtZRgFIAEoCRIQCghwcm92aWRlchgGIAEoCTLSAQoRR2FtZUVuZ2luZVNlcnZpY2USWQoOUHJvY2Vzc0NvbW1hbmQSIi5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlcXVlc3QaIy5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlc3BvbnNlEmIKEUdldEdhbWVFbmdpbmVJbmZvEiUuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXF1ZXN0GiYuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZWIGcHJvdG8z', [wkt_1.file_google_protobuf_struct]);
|
|
12
|
+
exports.file_game_engine = (0, codegenv2_1.fileDesc)("ChFnYW1lLWVuZ2luZS5wcm90bxILZ2FtZV9lbmdpbmUisAIKFVByb2Nlc3NDb21tYW5kUmVxdWVzdBIyCgxwdWJsaWNfc3RhdGUYASABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgCIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARI0Cgdjb21tYW5kGAMgASgLMh4uZ2FtZV9lbmdpbmUuR2FtZUFjdGlvbkNvbW1hbmRIAogBARI1Cg9hZGRpdGlvbmFsX2RhdGEYBCABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SAOIAQFCDwoNX3B1YmxpY19zdGF0ZUIQCg5fcHJpdmF0ZV9zdGF0ZUIKCghfY29tbWFuZEISChBfYWRkaXRpb25hbF9kYXRhImgKEUdhbWVBY3Rpb25Db21tYW5kEgoKAmlkGAEgASgJEgwKBHR5cGUYAiABKAkSLQoHcGF5bG9hZBgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAIgBAUIKCghfcGF5bG9hZCJKChBSbmdPdXRjb21lUmVjb3JkEg4KBnJlc3VsdBgBIAEoARIMCgRzZWVkGAIgASgJEgsKA21pbhgDIAEoARILCgNtYXgYBCABKAEi+QMKFlByb2Nlc3NDb21tYW5kUmVzcG9uc2USDwoHc3VjY2VzcxgBIAEoCBIyCgxwdWJsaWNfc3RhdGUYAiABKAsyFy5nb29nbGUucHJvdG9idWYuU3RydWN0SACIAQESMwoNcHJpdmF0ZV9zdGF0ZRgDIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIAYgBARItCgdvdXRjb21lGAQgASgLMhcuZ29vZ2xlLnByb3RvYnVmLlN0cnVjdEgCiAEBEhQKB21lc3NhZ2UYBSABKAlIA4gBARJICgtybmdfb3V0Y29tZRgGIAMoCzIzLmdhbWVfZW5naW5lLlByb2Nlc3NDb21tYW5kUmVzcG9uc2UuUm5nT3V0Y29tZUVudHJ5EjUKD2FkZGl0aW9uYWxfZGF0YRgHIAEoCzIXLmdvb2dsZS5wcm90b2J1Zi5TdHJ1Y3RIBIgBARpQCg9SbmdPdXRjb21lRW50cnkSCwoDa2V5GAEgASgJEiwKBXZhbHVlGAIgASgLMh0uZ2FtZV9lbmdpbmUuUm5nT3V0Y29tZVJlY29yZDoCOAFCDwoNX3B1YmxpY19zdGF0ZUIQCg5fcHJpdmF0ZV9zdGF0ZUIKCghfb3V0Y29tZUIKCghfbWVzc2FnZUISChBfYWRkaXRpb25hbF9kYXRhIhoKGEdldEdhbWVFbmdpbmVJbmZvUmVxdWVzdCKEAQoZR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZRIRCglnYW1lX2NvZGUYASABKAkSDwoHdmVyc2lvbhgCIAEoCRILCgNydHAYAyABKAESEQoJZ2FtZV90eXBlGAQgASgJEhEKCWdhbWVfbmFtZRgFIAEoCRIQCghwcm92aWRlchgGIAEoCTLSAQoRR2FtZUVuZ2luZVNlcnZpY2USWQoOUHJvY2Vzc0NvbW1hbmQSIi5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlcXVlc3QaIy5nYW1lX2VuZ2luZS5Qcm9jZXNzQ29tbWFuZFJlc3BvbnNlEmIKEUdldEdhbWVFbmdpbmVJbmZvEiUuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXF1ZXN0GiYuZ2FtZV9lbmdpbmUuR2V0R2FtZUVuZ2luZUluZm9SZXNwb25zZWIGcHJvdG8z", [wkt_1.file_google_protobuf_struct]);
|
|
15
13
|
/**
|
|
16
14
|
* Describes the message game_engine.ProcessCommandRequest.
|
|
17
15
|
* Use `create(ProcessCommandRequestSchema)` to create a new message.
|
|
18
16
|
*/
|
|
19
|
-
exports.ProcessCommandRequestSchema =
|
|
20
|
-
/*@__PURE__*/
|
|
21
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine, 0);
|
|
17
|
+
exports.ProcessCommandRequestSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine, 0);
|
|
22
18
|
/**
|
|
23
19
|
* Describes the message game_engine.GameActionCommand.
|
|
24
20
|
* Use `create(GameActionCommandSchema)` to create a new message.
|
|
25
21
|
*/
|
|
26
|
-
exports.GameActionCommandSchema =
|
|
27
|
-
/*@__PURE__*/
|
|
28
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine, 1);
|
|
22
|
+
exports.GameActionCommandSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine, 1);
|
|
29
23
|
/**
|
|
30
24
|
* Describes the message game_engine.RngOutcomeRecord.
|
|
31
25
|
* Use `create(RngOutcomeRecordSchema)` to create a new message.
|
|
32
26
|
*/
|
|
33
|
-
exports.RngOutcomeRecordSchema =
|
|
34
|
-
/*@__PURE__*/
|
|
35
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine, 2);
|
|
27
|
+
exports.RngOutcomeRecordSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine, 2);
|
|
36
28
|
/**
|
|
37
29
|
* Describes the message game_engine.ProcessCommandResponse.
|
|
38
30
|
* Use `create(ProcessCommandResponseSchema)` to create a new message.
|
|
39
31
|
*/
|
|
40
|
-
exports.ProcessCommandResponseSchema =
|
|
41
|
-
/*@__PURE__*/
|
|
42
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine, 3);
|
|
32
|
+
exports.ProcessCommandResponseSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine, 3);
|
|
43
33
|
/**
|
|
44
34
|
* Describes the message game_engine.GetGameEngineInfoRequest.
|
|
45
35
|
* Use `create(GetGameEngineInfoRequestSchema)` to create a new message.
|
|
46
36
|
*/
|
|
47
|
-
exports.GetGameEngineInfoRequestSchema =
|
|
48
|
-
/*@__PURE__*/
|
|
49
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine, 4);
|
|
37
|
+
exports.GetGameEngineInfoRequestSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine, 4);
|
|
50
38
|
/**
|
|
51
39
|
* Describes the message game_engine.GetGameEngineInfoResponse.
|
|
52
40
|
* Use `create(GetGameEngineInfoResponseSchema)` to create a new message.
|
|
53
41
|
*/
|
|
54
|
-
exports.GetGameEngineInfoResponseSchema =
|
|
55
|
-
/*@__PURE__*/
|
|
56
|
-
(0, codegenv2_1.messageDesc)(exports.file_game_engine, 5);
|
|
42
|
+
exports.GetGameEngineInfoResponseSchema = (0, codegenv2_1.messageDesc)(exports.file_game_engine, 5);
|
|
57
43
|
/**
|
|
58
44
|
* @generated from service game_engine.GameEngineService
|
|
59
45
|
*/
|
|
@@ -25,6 +25,10 @@ export declare class GameEngineGrpcInAdapter {
|
|
|
25
25
|
* Validate a single RNG outcome record for GLI-19 compliance.
|
|
26
26
|
* Throws INVALID_RNG_SEED on any invalid numeric field to prevent
|
|
27
27
|
* silent data corruption in the audit trail.
|
|
28
|
+
*
|
|
29
|
+
* Note: seed field may come as string from RNG service (JSON parsing).
|
|
30
|
+
* We accept both number and numeric string for seed since it's converted
|
|
31
|
+
* to string for wire format anyway.
|
|
28
32
|
*/
|
|
29
33
|
private validateRngRecord;
|
|
30
34
|
getGameEngineInfo(_request: GetGameEngineInfoRequest): Promise<GetGameEngineInfoResponse>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"game-engine.grpc.in-adapter.d.ts","sourceRoot":"","sources":["../../src/grpc/game-engine.grpc.in-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EAEzB,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,gBAAgB,EAMjB,MAAM,UAAU,CAAC;AAGlB,qBACa,uBAAuB;IAIhC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAHnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,gBAAgB,EAAE,gBAAgB;IAK/C,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"game-engine.grpc.in-adapter.d.ts","sourceRoot":"","sources":["../../src/grpc/game-engine.grpc.in-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EAEzB,qBAAqB,EACrB,sBAAsB,EAEvB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,gBAAgB,EAMjB,MAAM,UAAU,CAAC;AAGlB,qBACa,uBAAuB;IAIhC,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAHnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAGb,gBAAgB,EAAE,gBAAgB;IAK/C,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,sBAAsB,CAAC;IAgBrF,OAAO,CAAC,yBAAyB;IA2BjC,OAAO,CAAC,qBAAqB;IAsB7B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;;;;;;;OAQG;IACH,OAAO,CAAC,iBAAiB;IA+BnB,iBAAiB,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;CAYhG"}
|
|
@@ -31,8 +31,9 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
31
31
|
const command = this.extractCommandFromRequest(request);
|
|
32
32
|
const publicState = request.publicState ?? {};
|
|
33
33
|
const privateState = request.privateState ?? {};
|
|
34
|
+
const additionalData = request.additionalData;
|
|
34
35
|
const result = await this.gameEngineInPort.processCommand(publicState, privateState, command);
|
|
35
|
-
return this.createSuccessResponse(result);
|
|
36
|
+
return this.createSuccessResponse(result, additionalData);
|
|
36
37
|
}
|
|
37
38
|
catch (error) {
|
|
38
39
|
this.logger.error('Error in processCommand', error);
|
|
@@ -52,8 +53,10 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
52
53
|
}
|
|
53
54
|
return { id, type, payload };
|
|
54
55
|
}
|
|
55
|
-
createSuccessResponse(result) {
|
|
56
|
+
createSuccessResponse(result, requestAdditionalData) {
|
|
56
57
|
const rngOutcome = this.convertRngOutcome(result.rngOutcome);
|
|
58
|
+
// additionalData passthrough: game engine result takes precedence, falls back to request
|
|
59
|
+
const additionalData = result.additionalData ?? requestAdditionalData;
|
|
57
60
|
return (0, protobuf_1.create)(game_engine_pb_1.ProcessCommandResponseSchema, {
|
|
58
61
|
success: result.success ?? true,
|
|
59
62
|
// Cast at gRPC boundary: game engine state objects are serialized as protobuf Struct
|
|
@@ -62,6 +65,7 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
62
65
|
outcome: result.outcome,
|
|
63
66
|
message: result.message,
|
|
64
67
|
rngOutcome: rngOutcome,
|
|
68
|
+
additionalData: additionalData,
|
|
65
69
|
});
|
|
66
70
|
}
|
|
67
71
|
/**
|
|
@@ -108,15 +112,26 @@ let GameEngineGrpcInAdapter = GameEngineGrpcInAdapter_1 = class GameEngineGrpcIn
|
|
|
108
112
|
* Validate a single RNG outcome record for GLI-19 compliance.
|
|
109
113
|
* Throws INVALID_RNG_SEED on any invalid numeric field to prevent
|
|
110
114
|
* silent data corruption in the audit trail.
|
|
115
|
+
*
|
|
116
|
+
* Note: seed field may come as string from RNG service (JSON parsing).
|
|
117
|
+
* We accept both number and numeric string for seed since it's converted
|
|
118
|
+
* to string for wire format anyway.
|
|
111
119
|
*/
|
|
112
120
|
validateRngRecord(key, record) {
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
// Validate result, min, max as strict numbers
|
|
122
|
+
const strictFields = ['result', 'min', 'max'];
|
|
123
|
+
for (const field of strictFields) {
|
|
115
124
|
const val = record[field];
|
|
116
125
|
if (typeof val !== 'number' || !isFinite(val)) {
|
|
117
126
|
throw new domain_exception_1.DomainException(internal_error_code_1.InternalErrorCode.INVALID_RNG_SEED, `Invalid RNG ${field} for action '${key}': expected finite number, got ${String(val)}`);
|
|
118
127
|
}
|
|
119
128
|
}
|
|
129
|
+
// Validate seed - allow string or number (RNG service may return string)
|
|
130
|
+
const seed = record.seed;
|
|
131
|
+
const seedNum = typeof seed === 'string' ? Number(seed) : seed;
|
|
132
|
+
if (typeof seedNum !== 'number' || !isFinite(seedNum)) {
|
|
133
|
+
throw new domain_exception_1.DomainException(internal_error_code_1.InternalErrorCode.INVALID_RNG_SEED, `Invalid RNG seed for action '${key}': expected finite number, got ${String(seed)}`);
|
|
134
|
+
}
|
|
120
135
|
if (record.min > record.max) {
|
|
121
136
|
throw new domain_exception_1.DomainException(internal_error_code_1.InternalErrorCode.INVALID_RNG_SEED, `Invalid RNG range for action '${key}': min (${record.min}) > max (${record.max})`);
|
|
122
137
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './health';
|
|
|
4
4
|
export * from './registration';
|
|
5
5
|
export * from './grpc';
|
|
6
6
|
export { createGameEngineApp, GameEngineAppOptions } from './bootstrap';
|
|
7
|
+
export * from './debug';
|
|
7
8
|
export { GameEngineService, ProcessCommandRequest, ProcessCommandRequestSchema, ProcessCommandResponse, ProcessCommandResponseSchema, GetGameEngineInfoRequest, GetGameEngineInfoRequestSchema, GetGameEngineInfoResponse, GetGameEngineInfoResponseSchema, } from './generated/game-engine_pb';
|
|
8
9
|
export { GameEngineRegistryService, RegisterGameEngineRequest, RegisterGameEngineRequestSchema, RegisterGameEngineResponse, RegisterGameEngineResponseSchema, } from './generated/game-engine-registry_pb';
|
|
9
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,QAAQ,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxE,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,4BAA4B,EAC5B,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,+BAA+B,EAC/B,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,qCAAqC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,WAAW,EACX,UAAU,EACV,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,UAAU,EACV,gBAAgB,EAChB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,SAAS,CAAC;AAGjB,cAAc,UAAU,CAAC;AAGzB,cAAc,UAAU,CAAC;AAGzB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,QAAQ,CAAC;AAGvB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGxE,cAAc,SAAS,CAAC;AAGxB,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,4BAA4B,EAC5B,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACL,yBAAyB,EACzB,yBAAyB,EACzB,+BAA+B,EAC/B,0BAA0B,EAC1B,gCAAgC,GACjC,MAAM,qCAAqC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,8 @@ __exportStar(require("./grpc"), exports);
|
|
|
30
30
|
// Bootstrap
|
|
31
31
|
var bootstrap_1 = require("./bootstrap");
|
|
32
32
|
Object.defineProperty(exports, "createGameEngineApp", { enumerable: true, get: function () { return bootstrap_1.createGameEngineApp; } });
|
|
33
|
+
// Debug command infrastructure
|
|
34
|
+
__exportStar(require("./debug"), exports);
|
|
33
35
|
// Generated proto types (re-exported for convenience)
|
|
34
36
|
var game_engine_pb_1 = require("./generated/game-engine_pb");
|
|
35
37
|
Object.defineProperty(exports, "GameEngineService", { enumerable: true, get: function () { return game_engine_pb_1.GameEngineService; } });
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,WAAW,eAAwB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,UAAU,GAAG;IAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAAA;CAAE,CAAC;AAElE,MAAM,WAAW,uBAAuB,CACtC,YAAY,GAAG,OAAO,EACtB,aAAa,GAAG,OAAO,EACvB,QAAQ,GAAG,OAAO;IAElB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,YAAY,CAAC;IAC1B,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,WAAW,eAAwB,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,UAAU,GAAG;IAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAAA;CAAE,CAAC;AAElE,MAAM,WAAW,uBAAuB,CACtC,YAAY,GAAG,OAAO,EACtB,aAAa,GAAG,OAAO,EACvB,QAAQ,GAAG,OAAO;IAElB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,YAAY,CAAC;IAC1B,YAAY,EAAE,aAAa,CAAC;IAC5B,OAAO,CAAC,EAAE,QAAQ,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB,CAAC,QAAQ,GAAG,OAAO;IACnD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,UAAU,CAAC,YAAY,GAAG,OAAO,EAAE,aAAa,GAAG,OAAO,EAAE,QAAQ,GAAG,OAAO;IAC7F,cAAc,CACZ,WAAW,EAAE,YAAY,GAAG,IAAI,EAChC,YAAY,EAAE,aAAa,GAAG,IAAI,EAClC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,uBAAuB,CAAC,YAAY,EAAE,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC;IAE3E,iBAAiB,IAAI,cAAc,CAAC;CACrC;AAED,eAAO,MAAM,mBAAmB,eAAgC,CAAC;AAEjE,MAAM,WAAW,gBAAgB;IAC/B,cAAc,CACZ,WAAW,EAAE,OAAO,EACpB,YAAY,EAAE,OAAO,EACrB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,uBAAuB,CAAC,CAAC;IACpC,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;CAC9C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omnitronix/game-engine-sdk",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Shared NestJS infrastructure SDK for Omnitronix game engine services",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -65,6 +65,16 @@
|
|
|
65
65
|
"types": "./dist/bootstrap/index.d.ts",
|
|
66
66
|
"default": "./dist/bootstrap/index.js"
|
|
67
67
|
}
|
|
68
|
+
},
|
|
69
|
+
"./debug": {
|
|
70
|
+
"import": {
|
|
71
|
+
"types": "./dist/debug/index.d.ts",
|
|
72
|
+
"default": "./dist/esm/debug/index.js"
|
|
73
|
+
},
|
|
74
|
+
"require": {
|
|
75
|
+
"types": "./dist/debug/index.d.ts",
|
|
76
|
+
"default": "./dist/debug/index.js"
|
|
77
|
+
}
|
|
68
78
|
}
|
|
69
79
|
},
|
|
70
80
|
"scripts": {
|
|
@@ -143,7 +153,7 @@
|
|
|
143
153
|
"@nestjs/platform-express": "^11.0.0",
|
|
144
154
|
"@nestjs/swagger": "^11.0.6",
|
|
145
155
|
"@nestjs/testing": "^11.0.9",
|
|
146
|
-
"@omnitronix/game-engine-contract": "^1.
|
|
156
|
+
"@omnitronix/game-engine-contract": "^1.2.0",
|
|
147
157
|
"@types/express": "^5.0.0",
|
|
148
158
|
"@types/jest": "^29.5.14",
|
|
149
159
|
"@types/node": "^20.17.10",
|