@omnitronix/game-engine-sdk 2.0.2 → 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.
@@ -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';
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';
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
@@ -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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitronix/game-engine-sdk",
3
- "version": "2.0.2",
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.0.0",
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",