@omnitronix/game-engine-sdk 1.0.2 → 1.0.4

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.
@@ -5,6 +5,8 @@ export interface GameEngineAppOptions {
5
5
  bootstrapOptions?: {
6
6
  driver: 'database' | 'in-memory';
7
7
  };
8
+ /** Allowed CORS origins. Defaults to false (CORS disabled). */
9
+ corsOrigins?: string[] | boolean;
8
10
  }
9
11
  /**
10
12
  * Creates and bootstraps a game engine NestJS application with
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAsD,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAK1F,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,gBAAgB,CAAC,EAAE;QAAE,MAAM,EAAE,UAAU,GAAG,WAAW,CAAA;KAAE,CAAC;CACzD;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,2DAwHtE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bootstrap/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAsD,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAK1F,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACrB,gBAAgB,CAAC,EAAE;QAAE,MAAM,EAAE,UAAU,GAAG,WAAW,CAAA;KAAE,CAAC;IACxD,+DAA+D;IAC/D,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,2DA0HtE"}
@@ -51,7 +51,7 @@ const http2 = __importStar(require("http2"));
51
51
  * Swagger docs, Connect RPC gRPC server, and graceful shutdown.
52
52
  */
53
53
  async function createGameEngineApp(options) {
54
- const { serviceName, appModule, bootstrapOptions } = options;
54
+ const { serviceName, appModule, bootstrapOptions, corsOrigins = false } = options;
55
55
  const logger = new logger_1.Logger(serviceName);
56
56
  const moduleArg = bootstrapOptions
57
57
  ? appModule.register
@@ -61,7 +61,9 @@ async function createGameEngineApp(options) {
61
61
  const app = await core_1.NestFactory.create(moduleArg, {
62
62
  logger: logger,
63
63
  });
64
- app.enableCors({ origin: true });
64
+ if (corsOrigins) {
65
+ app.enableCors({ origin: corsOrigins });
66
+ }
65
67
  const configService = app.get(config_1.ConfigService);
66
68
  const shutdownService = app.get(shutdown_out_port_1.SHUTDOWN_OUT_PORT);
67
69
  let isShuttingDown = false;
@@ -1 +1 @@
1
- {"version":3,"file":"setup-documentation.d.ts","sourceRoot":"","sources":["../../../src/common/api-docs/setup-documentation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAMlD,eAAO,MAAM,kBAAkB,GAC7B,KAAK,gBAAgB,CAAC,GAAG,CAAC,EAC1B,MAAM,MAAM,EACZ,cAAc,MAAM,kBAqBrB,CAAC"}
1
+ {"version":3,"file":"setup-documentation.d.ts","sourceRoot":"","sources":["../../../src/common/api-docs/setup-documentation.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAMlD,eAAO,MAAM,kBAAkB,GAC7B,KAAK,gBAAgB,CAAC,GAAG,CAAC,EAC1B,MAAM,MAAM,EACZ,cAAc,MAAM,kBA0BrB,CAAC"}
@@ -5,6 +5,10 @@ const swagger_1 = require("@nestjs/swagger");
5
5
  const logger_1 = require("../logger/logger");
6
6
  const logger = new logger_1.Logger('ApiDocs');
7
7
  const setupDocumentation = async (app, port, serviceName) => {
8
+ if (process.env.NODE_ENV === 'production' && process.env.ENABLE_SWAGGER !== 'true') {
9
+ logger.log('Swagger docs disabled in production (set ENABLE_SWAGGER=true to override)');
10
+ return;
11
+ }
8
12
  const config = new swagger_1.DocumentBuilder()
9
13
  .setTitle(serviceName ? `${serviceName} API` : 'Game Engine API')
10
14
  .setDescription('API documentation')
@@ -100,7 +100,7 @@ let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
100
100
  return this.buildResponsePayload({
101
101
  status: common_1.HttpStatus.INTERNAL_SERVER_ERROR,
102
102
  internalCode: internal_error_code_1.InternalErrorCode.INTERNAL_SERVER_ERROR,
103
- message: exception.message,
103
+ message: 'Internal server error',
104
104
  path: request.url,
105
105
  });
106
106
  }
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/common/logger/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,KAAK,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnC,qBAAa,MAAO,YAAW,iBAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS;IAMlD,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,aAAa;IAIrB,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,KAAc,EAAE,GAAG,IAAI,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM;IAoB5F,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAsB5C,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAI3C,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAI5C,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;CAG/C"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/common/logger/logger.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGpE,KAAK,SAAS,GAAG,MAAM,GAAG,QAAQ,CAAC;AAEnC,qBAAa,MAAO,YAAW,iBAAiB;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,OAAO,CAAS;gBAEZ,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,SAAS;IAMlD,OAAO,CAAC,eAAe;IAavB,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,aAAa;IAYrB,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,aAAa;IAUrB,GAAG,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,KAAc,EAAE,GAAG,IAAI,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM;IAoB5F,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAsB5C,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAI3C,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;IAI5C,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,EAAE;CAG/C"}
@@ -83,7 +83,11 @@ class Logger {
83
83
  }
84
84
  }
85
85
  getTransports() {
86
- return [new winston_1.transports.Console(), new winston_1.transports.File({ filename: 'logs/app.log' })];
86
+ const logTransports = [new winston_1.transports.Console()];
87
+ if (process.env.LOG_TO_FILE === 'true') {
88
+ logTransports.push(new winston_1.transports.File({ filename: 'logs/app.log' }));
89
+ }
90
+ return logTransports;
87
91
  }
88
92
  log(message, { level = 'info', ...rest } = {}) {
89
93
  switch (level) {
@@ -1 +1 @@
1
- {"version":3,"file":"logging.middleware.d.ts","sourceRoot":"","sources":["../../../src/common/logger/logging.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAM1D,qBACa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAMhC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;CAwBpD"}
1
+ {"version":3,"file":"logging.middleware.d.ts","sourceRoot":"","sources":["../../../src/common/logger/logging.middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AA4B1D,qBACa,iBAAkB,YAAW,cAAc;IACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;;IAMhC,GAAG,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY;CAkBpD"}
@@ -14,19 +14,37 @@ exports.LoggingMiddleware = void 0;
14
14
  const common_1 = require("@nestjs/common");
15
15
  const logger_1 = require("./logger");
16
16
  const BLOCKED_ENDPOINTS = ['/api/races/active'];
17
+ const SENSITIVE_FIELDS = new Set([
18
+ 'password', 'token', 'secret', 'authorization',
19
+ 'apikey', 'api_key', 'accesstoken', 'refreshtoken',
20
+ 'creditcard', 'ssn', 'private_key', 'privatekey',
21
+ ]);
22
+ function sanitize(obj) {
23
+ if (obj === null || obj === undefined || typeof obj !== 'object')
24
+ return obj;
25
+ if (Array.isArray(obj))
26
+ return obj.map(sanitize);
27
+ const result = {};
28
+ for (const [key, value] of Object.entries(obj)) {
29
+ if (SENSITIVE_FIELDS.has(key.toLowerCase())) {
30
+ result[key] = '***';
31
+ }
32
+ else if (typeof value === 'object' && value !== null) {
33
+ result[key] = sanitize(value);
34
+ }
35
+ else {
36
+ result[key] = value;
37
+ }
38
+ }
39
+ return result;
40
+ }
17
41
  let LoggingMiddleware = LoggingMiddleware_1 = class LoggingMiddleware {
18
42
  constructor() {
19
43
  this.logger = new logger_1.Logger(LoggingMiddleware_1.name);
20
44
  }
21
45
  use(req, res, next) {
22
46
  const { method, originalUrl, body } = req;
23
- const sanitizedBody = { ...body };
24
- if (sanitizedBody.password) {
25
- sanitizedBody.password = '***';
26
- }
27
- if (sanitizedBody.token) {
28
- sanitizedBody.token = '***';
29
- }
47
+ const sanitizedBody = sanitize(body);
30
48
  res.on('finish', () => {
31
49
  const isBlockedEndpoint = BLOCKED_ENDPOINTS.some(endpoint => originalUrl.includes(endpoint));
32
50
  const isSuccessfulRequest = res.statusCode < 400;
@@ -15,7 +15,7 @@ import * as http2 from 'http2';
15
15
  * Swagger docs, Connect RPC gRPC server, and graceful shutdown.
16
16
  */
17
17
  export async function createGameEngineApp(options) {
18
- const { serviceName, appModule, bootstrapOptions } = options;
18
+ const { serviceName, appModule, bootstrapOptions, corsOrigins = false } = options;
19
19
  const logger = new Logger(serviceName);
20
20
  const moduleArg = bootstrapOptions
21
21
  ? appModule.register
@@ -25,7 +25,9 @@ export async function createGameEngineApp(options) {
25
25
  const app = await NestFactory.create(moduleArg, {
26
26
  logger: logger,
27
27
  });
28
- app.enableCors({ origin: true });
28
+ if (corsOrigins) {
29
+ app.enableCors({ origin: corsOrigins });
30
+ }
29
31
  const configService = app.get(ConfigService);
30
32
  const shutdownService = app.get(SHUTDOWN_OUT_PORT);
31
33
  let isShuttingDown = false;
@@ -2,6 +2,10 @@ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
2
2
  import { Logger } from '../logger/logger';
3
3
  const logger = new Logger('ApiDocs');
4
4
  export const setupDocumentation = async (app, port, serviceName) => {
5
+ if (process.env.NODE_ENV === 'production' && process.env.ENABLE_SWAGGER !== 'true') {
6
+ logger.log('Swagger docs disabled in production (set ENABLE_SWAGGER=true to override)');
7
+ return;
8
+ }
5
9
  const config = new DocumentBuilder()
6
10
  .setTitle(serviceName ? `${serviceName} API` : 'Game Engine API')
7
11
  .setDescription('API documentation')
@@ -97,7 +97,7 @@ let ExceptionsFilter = ExceptionsFilter_1 = class ExceptionsFilter {
97
97
  return this.buildResponsePayload({
98
98
  status: HttpStatus.INTERNAL_SERVER_ERROR,
99
99
  internalCode: InternalErrorCode.INTERNAL_SERVER_ERROR,
100
- message: exception.message,
100
+ message: 'Internal server error',
101
101
  path: request.url,
102
102
  });
103
103
  }
@@ -80,7 +80,11 @@ export class Logger {
80
80
  }
81
81
  }
82
82
  getTransports() {
83
- return [new transports.Console(), new transports.File({ filename: 'logs/app.log' })];
83
+ const logTransports = [new transports.Console()];
84
+ if (process.env.LOG_TO_FILE === 'true') {
85
+ logTransports.push(new transports.File({ filename: 'logs/app.log' }));
86
+ }
87
+ return logTransports;
84
88
  }
85
89
  log(message, { level = 'info', ...rest } = {}) {
86
90
  switch (level) {
@@ -11,19 +11,37 @@ var LoggingMiddleware_1;
11
11
  import { Injectable } from '@nestjs/common';
12
12
  import { Logger } from './logger';
13
13
  const BLOCKED_ENDPOINTS = ['/api/races/active'];
14
+ const SENSITIVE_FIELDS = new Set([
15
+ 'password', 'token', 'secret', 'authorization',
16
+ 'apikey', 'api_key', 'accesstoken', 'refreshtoken',
17
+ 'creditcard', 'ssn', 'private_key', 'privatekey',
18
+ ]);
19
+ function sanitize(obj) {
20
+ if (obj === null || obj === undefined || typeof obj !== 'object')
21
+ return obj;
22
+ if (Array.isArray(obj))
23
+ return obj.map(sanitize);
24
+ const result = {};
25
+ for (const [key, value] of Object.entries(obj)) {
26
+ if (SENSITIVE_FIELDS.has(key.toLowerCase())) {
27
+ result[key] = '***';
28
+ }
29
+ else if (typeof value === 'object' && value !== null) {
30
+ result[key] = sanitize(value);
31
+ }
32
+ else {
33
+ result[key] = value;
34
+ }
35
+ }
36
+ return result;
37
+ }
14
38
  let LoggingMiddleware = LoggingMiddleware_1 = class LoggingMiddleware {
15
39
  constructor() {
16
40
  this.logger = new Logger(LoggingMiddleware_1.name);
17
41
  }
18
42
  use(req, res, next) {
19
43
  const { method, originalUrl, body } = req;
20
- const sanitizedBody = { ...body };
21
- if (sanitizedBody.password) {
22
- sanitizedBody.password = '***';
23
- }
24
- if (sanitizedBody.token) {
25
- sanitizedBody.token = '***';
26
- }
44
+ const sanitizedBody = sanitize(body);
27
45
  res.on('finish', () => {
28
46
  const isBlockedEndpoint = BLOCKED_ENDPOINTS.some(endpoint => originalUrl.includes(endpoint));
29
47
  const isSuccessfulRequest = res.statusCode < 400;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitronix/game-engine-sdk",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
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",