@truelab/trueserver 0.0.4 → 0.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.
Files changed (137) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/MIGRATION.md +508 -0
  3. package/README.md +114 -94
  4. package/dist/application.d.ts.map +1 -1
  5. package/dist/application.js +9 -5
  6. package/dist/application.js.map +1 -1
  7. package/dist/examples.d.ts +1 -0
  8. package/dist/examples.d.ts.map +1 -1
  9. package/dist/examples.js +3 -1
  10. package/dist/examples.js.map +1 -1
  11. package/dist/helpers/config.helper.d.ts +9 -1
  12. package/dist/helpers/config.helper.d.ts.map +1 -1
  13. package/dist/helpers/config.helper.js +29 -0
  14. package/dist/helpers/config.helper.js.map +1 -1
  15. package/dist/helpers/errors.helper.d.ts +19 -0
  16. package/dist/helpers/errors.helper.d.ts.map +1 -0
  17. package/dist/helpers/errors.helper.js +21 -0
  18. package/dist/helpers/errors.helper.js.map +1 -0
  19. package/dist/helpers/fastify.helper.d.ts +5 -1
  20. package/dist/helpers/fastify.helper.d.ts.map +1 -1
  21. package/dist/helpers/fastify.helper.js +3 -1
  22. package/dist/helpers/fastify.helper.js.map +1 -1
  23. package/dist/helpers/handlers.helper.d.ts +10 -1
  24. package/dist/helpers/handlers.helper.d.ts.map +1 -1
  25. package/dist/helpers/handlers.helper.js +2 -1
  26. package/dist/helpers/handlers.helper.js.map +1 -1
  27. package/dist/helpers/money.helper.d.ts +13 -0
  28. package/dist/helpers/money.helper.d.ts.map +1 -0
  29. package/dist/helpers/money.helper.js +29 -0
  30. package/dist/helpers/money.helper.js.map +1 -0
  31. package/dist/index.d.ts +7 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +11 -4
  34. package/dist/index.js.map +1 -1
  35. package/dist/plugins/404.plugin.d.ts.map +1 -1
  36. package/dist/plugins/404.plugin.js +2 -1
  37. package/dist/plugins/404.plugin.js.map +1 -1
  38. package/dist/plugins/apikey.plugin.d.ts.map +1 -1
  39. package/dist/plugins/apikey.plugin.js +6 -7
  40. package/dist/plugins/apikey.plugin.js.map +1 -1
  41. package/dist/plugins/error.plugin.d.ts.map +1 -1
  42. package/dist/plugins/error.plugin.js +6 -2
  43. package/dist/plugins/error.plugin.js.map +1 -1
  44. package/dist/plugins/sentry.plugin.d.ts.map +1 -1
  45. package/dist/plugins/sentry.plugin.js +1 -2
  46. package/dist/plugins/sentry.plugin.js.map +1 -1
  47. package/dist/plugins/swagger.plugin.d.ts.map +1 -1
  48. package/dist/plugins/swagger.plugin.js +5 -1
  49. package/dist/plugins/swagger.plugin.js.map +1 -1
  50. package/dist/routes/checksum/checksum.route.d.ts +3 -0
  51. package/dist/routes/checksum/checksum.route.d.ts.map +1 -0
  52. package/dist/routes/checksum/checksum.route.js +21 -0
  53. package/dist/routes/checksum/checksum.route.js.map +1 -0
  54. package/dist/routes/checksum/index.d.ts +3 -0
  55. package/dist/routes/checksum/index.d.ts.map +1 -0
  56. package/dist/routes/checksum/index.js +12 -0
  57. package/dist/routes/checksum/index.js.map +1 -0
  58. package/dist/routes/client/client.route.d.ts +3 -0
  59. package/dist/routes/client/client.route.d.ts.map +1 -0
  60. package/dist/routes/{client.route.js → client/client.route.js} +5 -5
  61. package/dist/routes/client/client.route.js.map +1 -0
  62. package/dist/routes/client/index.d.ts +3 -0
  63. package/dist/routes/client/index.d.ts.map +1 -0
  64. package/dist/routes/client/index.js +12 -0
  65. package/dist/routes/client/index.js.map +1 -0
  66. package/dist/routes/config/config.route.js +1 -1
  67. package/dist/routes/config/config.route.js.map +1 -1
  68. package/dist/routes/config/config.route.validate.plugin.d.ts.map +1 -1
  69. package/dist/routes/config/config.route.validate.plugin.js +48 -17
  70. package/dist/routes/config/config.route.validate.plugin.js.map +1 -1
  71. package/dist/routes/play/play.route.validate.plugin.d.ts +10 -9
  72. package/dist/routes/play/play.route.validate.plugin.d.ts.map +1 -1
  73. package/dist/routes/play/play.route.validate.plugin.js +90 -39
  74. package/dist/routes/play/play.route.validate.plugin.js.map +1 -1
  75. package/dist/routes/validate/validate.route.validate.plugin.d.ts.map +1 -1
  76. package/dist/routes/validate/validate.route.validate.plugin.js +5 -4
  77. package/dist/routes/validate/validate.route.validate.plugin.js.map +1 -1
  78. package/dist/routes-public/healthcheck.route.d.ts.map +1 -0
  79. package/dist/{routes → routes-public}/healthcheck.route.js +4 -10
  80. package/dist/routes-public/healthcheck.route.js.map +1 -0
  81. package/dist/schemas/checksum.schema.d.ts +11 -0
  82. package/dist/schemas/checksum.schema.d.ts.map +1 -0
  83. package/dist/schemas/checksum.schema.js +26 -0
  84. package/dist/schemas/checksum.schema.js.map +1 -0
  85. package/dist/schemas/client.schema.d.ts +1 -1
  86. package/dist/schemas/client.schema.js +4 -4
  87. package/dist/schemas/client.schema.js.map +1 -1
  88. package/dist/schemas/config.schema.d.ts +17 -20
  89. package/dist/schemas/config.schema.d.ts.map +1 -1
  90. package/dist/schemas/config.schema.js +42 -43
  91. package/dist/schemas/config.schema.js.map +1 -1
  92. package/dist/schemas/examples/checksum.schema.examples.d.ts +3 -0
  93. package/dist/schemas/examples/checksum.schema.examples.d.ts.map +1 -0
  94. package/dist/schemas/examples/checksum.schema.examples.js +26 -0
  95. package/dist/schemas/examples/checksum.schema.examples.js.map +1 -0
  96. package/dist/schemas/examples/client.schema.examples.d.ts.map +1 -1
  97. package/dist/schemas/examples/client.schema.examples.js +15 -18
  98. package/dist/schemas/examples/client.schema.examples.js.map +1 -1
  99. package/dist/schemas/examples/config.schema.examples.d.ts.map +1 -1
  100. package/dist/schemas/examples/config.schema.examples.js +65 -33
  101. package/dist/schemas/examples/config.schema.examples.js.map +1 -1
  102. package/dist/schemas/examples/healthcheck.schema.examples.d.ts.map +1 -1
  103. package/dist/schemas/examples/healthcheck.schema.examples.js +3 -14
  104. package/dist/schemas/examples/healthcheck.schema.examples.js.map +1 -1
  105. package/dist/schemas/examples/play.schema.examples.d.ts.map +1 -1
  106. package/dist/schemas/examples/play.schema.examples.js +94 -130
  107. package/dist/schemas/examples/play.schema.examples.js.map +1 -1
  108. package/dist/schemas/examples/validate.schema.examples.d.ts.map +1 -1
  109. package/dist/schemas/examples/validate.schema.examples.js +51 -41
  110. package/dist/schemas/examples/validate.schema.examples.js.map +1 -1
  111. package/dist/schemas/healthcheck.schema.d.ts +2 -20
  112. package/dist/schemas/healthcheck.schema.d.ts.map +1 -1
  113. package/dist/schemas/healthcheck.schema.js +10 -41
  114. package/dist/schemas/healthcheck.schema.js.map +1 -1
  115. package/dist/schemas/play.schema.d.ts +22 -17
  116. package/dist/schemas/play.schema.d.ts.map +1 -1
  117. package/dist/schemas/play.schema.js +37 -45
  118. package/dist/schemas/play.schema.js.map +1 -1
  119. package/dist/schemas/shared.d.ts +13 -21
  120. package/dist/schemas/shared.d.ts.map +1 -1
  121. package/dist/schemas/shared.js +56 -72
  122. package/dist/schemas/shared.js.map +1 -1
  123. package/dist/schemas/validate.schema.d.ts +11 -7
  124. package/dist/schemas/validate.schema.d.ts.map +1 -1
  125. package/dist/schemas/validate.schema.js +14 -16
  126. package/dist/schemas/validate.schema.js.map +1 -1
  127. package/package.json +5 -2
  128. package/dist/plugins/metrics.plugin.d.ts +0 -9
  129. package/dist/plugins/metrics.plugin.d.ts.map +0 -1
  130. package/dist/plugins/metrics.plugin.js +0 -24
  131. package/dist/plugins/metrics.plugin.js.map +0 -1
  132. package/dist/routes/client.route.d.ts +0 -3
  133. package/dist/routes/client.route.d.ts.map +0 -1
  134. package/dist/routes/client.route.js.map +0 -1
  135. package/dist/routes/healthcheck.route.d.ts.map +0 -1
  136. package/dist/routes/healthcheck.route.js.map +0 -1
  137. /package/dist/{routes → routes-public}/healthcheck.route.d.ts +0 -0
@@ -1,13 +1,14 @@
1
1
  import { TGameConfig } from '../../helpers/config.helper';
2
- import { TStake, TStakeMode } from '../../schemas/shared';
3
- export declare function validateStakes(stakes: TStake[], gameConfig: TGameConfig, stakesMap: Map<string, TStakeMode>): void;
4
- export declare function validateTestData(testData: string): void;
5
- export declare function validateChoice(choice: number, gameConfig: TGameConfig): void;
6
- export declare function validateMeta(metaPrivate: string, metaPublic: string, gameConfig: TGameConfig): void;
7
- export declare function validateGamble(isGambleAllowed: boolean, gameConfig: TGameConfig): void;
8
- export declare function validateFinishedInReply(finished: boolean, gameConfig: TGameConfig): void;
9
- export declare function validateChoicesInReply(choices: number[], gameConfig: TGameConfig): void;
10
- export declare function validateMetaInReply(metaPrivate: string, metaPublic: string, gameConfig: TGameConfig): void;
2
+ import { TMeta, TStake, TStakeMode } from '../../schemas/shared';
3
+ export declare function validateStakes(stakes: TStake[] | undefined, gameConfig: TGameConfig, stakesMap: Map<string, TStakeMode>): void;
4
+ export declare function validateTestData(testData: string | undefined): void;
5
+ export declare function validateStepIndexConsistency(stepIndex: number, stakes: TStake[] | undefined, choice: number | string | undefined, gameConfig: TGameConfig): void;
6
+ export declare function validateChoice(choice: number | string | undefined, gameConfig: TGameConfig): void;
7
+ export declare function validateMeta(meta: TMeta | undefined, gameConfig: TGameConfig): void;
8
+ export declare function validateFinishedInReply(finished: boolean, choices: (number | string)[] | undefined, gameConfig: TGameConfig): void;
9
+ export declare function validateChoicesInReply(choices: (number | string)[] | undefined, gameConfig: TGameConfig): void;
10
+ export declare function validateMetaInReply(meta: TMeta | undefined, gameConfig: TGameConfig): void;
11
+ export declare function validateMaxWinInReply(hasMaxWin: boolean, finished: boolean): void;
11
12
  declare const playRouteValidatePlugin: (fastify: import("../../helpers/fastify.helper").FastifyTypebox) => Promise<void>;
12
13
  export default playRouteValidatePlugin;
13
14
  //# sourceMappingURL=play.route.validate.plugin.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"play.route.validate.plugin.d.ts","sourceRoot":"","sources":["../../../routes/play/play.route.validate.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAIxE,OAAO,EAAiB,MAAM,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAExE,wBAAgB,cAAc,CAC1B,MAAM,EAAE,MAAM,EAAE,EAChB,UAAU,EAAE,WAAW,EACvB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,QAiCrC;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,QAIhD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,QAIrE;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,WAAW,QAI5F;AAED,wBAAgB,cAAc,CAAC,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,QAI/E;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,QAIjF;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,WAAW,QAIhF;AAED,wBAAgB,mBAAmB,CAC/B,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,WAAW,QAK1B;AAED,QAAA,MAAM,uBAAuB,mFAkC3B,CAAA;AAEF,eAAe,uBAAuB,CAAA"}
1
+ {"version":3,"file":"play.route.validate.plugin.d.ts","sourceRoot":"","sources":["../../../routes/play/play.route.validate.plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAKxE,OAAO,EACH,KAAK,EAAiB,MAAM,EAAE,UAAU,EAC3C,MAAM,sBAAsB,CAAA;AAW7B,wBAAgB,cAAc,CAC1B,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAC5B,UAAU,EAAE,WAAW,EACvB,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,QAkDrC;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,QAI5D;AAED,wBAAgB,4BAA4B,CACxC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,EAC5B,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EACnC,UAAU,EAAE,WAAW,QAiB1B;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,UAAU,EAAE,WAAW,QAI1F;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,EAAE,UAAU,EAAE,WAAW,QAI5E;AAED,wBAAgB,uBAAuB,CACnC,QAAQ,EAAE,OAAO,EACjB,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,SAAS,EACxC,UAAU,EAAE,WAAW,QAW1B;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,SAAS,EAAE,UAAU,EAAE,WAAW,QAOvG;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,EAAE,UAAU,EAAE,WAAW,QAInF;AAED,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,QAI1E;AAED,QAAA,MAAM,uBAAuB,mFAqC3B,CAAA;AAEF,eAAe,uBAAuB,CAAA"}
@@ -2,103 +2,154 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateStakes = validateStakes;
4
4
  exports.validateTestData = validateTestData;
5
+ exports.validateStepIndexConsistency = validateStepIndexConsistency;
5
6
  exports.validateChoice = validateChoice;
6
7
  exports.validateMeta = validateMeta;
7
- exports.validateGamble = validateGamble;
8
8
  exports.validateFinishedInReply = validateFinishedInReply;
9
9
  exports.validateChoicesInReply = validateChoicesInReply;
10
10
  exports.validateMetaInReply = validateMetaInReply;
11
+ exports.validateMaxWinInReply = validateMaxWinInReply;
11
12
  const config_helper_1 = require("../../helpers/config.helper");
12
13
  const env_helper_1 = require("../../helpers/env.helper");
14
+ const errors_helper_1 = require("../../helpers/errors.helper");
13
15
  const fastify_helper_1 = require("../../helpers/fastify.helper");
16
+ class CodedError extends Error {
17
+ code;
18
+ constructor(message, code) {
19
+ super(message);
20
+ this.code = code;
21
+ }
22
+ }
14
23
  function validateStakes(stakes, gameConfig, stakesMap) {
15
24
  if (stakes === undefined)
16
25
  return;
17
26
  if (gameConfig.hasMultiStake === false && stakes.length > 1) {
18
- throw new Error('Multiple stakes are not allowed');
27
+ throw new CodedError('Multiple stakes are not allowed', errors_helper_1.EErrorCode.ValidationStakes);
19
28
  }
29
+ const seenNames = new Set();
20
30
  stakes.forEach((stake) => {
21
- if (!stakesMap.has(stake.name)) {
22
- throw new Error(`Unknown stake name "${stake.name}"`);
31
+ if (seenNames.has(stake.name)) {
32
+ throw new CodedError(`Duplicate stake name "${stake.name}" — each stake must have a unique name`, errors_helper_1.EErrorCode.ValidationStakes);
33
+ }
34
+ seenNames.add(stake.name);
35
+ const stakeMode = stakesMap.get(stake.name);
36
+ if (!stakeMode) {
37
+ throw new CodedError(`Unknown stake name "${stake.name}"`, errors_helper_1.EErrorCode.ValidationStakes);
38
+ }
39
+ if (!stakeMode.multiple && stake.qty !== undefined) {
40
+ throw new CodedError(`Stake "${stake.name}" is not multiple. "qty" property is not allowed`, errors_helper_1.EErrorCode.ValidationStakes);
41
+ }
42
+ if (stakeMode.multiple && stakeMode.maxQty !== undefined && stake.qty !== undefined && stake.qty > stakeMode.maxQty) {
43
+ throw new CodedError(`Stake "${stake.name}" exceeds maxQty=${stakeMode.maxQty}`, errors_helper_1.EErrorCode.ValidationStakes);
23
44
  }
24
- if (!stakesMap.get(stake.name).multiple && stake.qty !== undefined) {
25
- throw new Error(`Stake "${stake.name}" is not multiple. "qty" property is not allowed`);
45
+ if (!gameConfig.hasVariableLevels && stake.level !== undefined) {
46
+ throw new CodedError('Variable levels are not allowed when hasVariableLevels=false', errors_helper_1.EErrorCode.ValidationStakes);
26
47
  }
27
- if (gameConfig.variableLevels === undefined && stake.level !== undefined) {
28
- throw new Error('Variable levels are not allowed');
48
+ if (gameConfig.hasVariableLevels && stake.level === undefined) {
49
+ throw new CodedError('"level" is required in stakes when hasVariableLevels=true', errors_helper_1.EErrorCode.ValidationStakes);
29
50
  }
30
- if (gameConfig.variableLevels !== undefined && stake.level === undefined) {
31
- throw new Error('Variable levels are required in stakes');
51
+ if (gameConfig.hasVariableLevels && !gameConfig.variableLevels.includes(stake.level)) {
52
+ throw new CodedError(`Stake "${stake.name}" level=${stake.level} is not in variableLevels`, errors_helper_1.EErrorCode.ValidationStakes);
32
53
  }
33
- if (!stakesMap.get(stake.name).parametric && stake.params !== undefined) {
34
- throw new Error(`Stake "${stake.name}" is not parametric. "params" property is not allowed`);
54
+ if (!stakeMode.parametric && stake.params !== undefined) {
55
+ throw new CodedError(`Stake "${stake.name}" is not parametric. "params" property is not allowed`, errors_helper_1.EErrorCode.ValidationStakes);
35
56
  }
36
- if (stakesMap.get(stake.name).parametric && stake.params === undefined) {
37
- throw new Error(`Stake "${stake.name}" is parametric. "params" property is required`);
57
+ if (stakeMode.parametric && stake.params === undefined) {
58
+ throw new CodedError(`Stake "${stake.name}" is parametric. "params" property is required`, errors_helper_1.EErrorCode.ValidationStakes);
38
59
  }
39
60
  });
40
61
  }
41
62
  function validateTestData(testData) {
42
63
  if ((0, env_helper_1.variation)(false, false, true) && testData !== undefined) {
43
- throw new Error('Test data is not allowed on production environment');
64
+ throw new CodedError('Test data is not allowed on production environment', errors_helper_1.EErrorCode.ValidationTest);
44
65
  }
45
66
  }
46
- function validateChoice(choice, gameConfig) {
47
- if (!gameConfig.hasChoice && choice !== undefined) {
48
- throw new Error('The game is not stepped. Choice is not allowed');
67
+ function validateStepIndexConsistency(stepIndex, stakes, choice, gameConfig) {
68
+ if (stepIndex === 0) {
69
+ if (stakes === undefined) {
70
+ throw new CodedError('"stakes" is required on the opening step (stepIndex=0)', errors_helper_1.EErrorCode.ValidationStakes);
71
+ }
72
+ if (choice !== undefined) {
73
+ throw new CodedError('"choice" is not allowed on the opening step (stepIndex=0)', errors_helper_1.EErrorCode.ValidationChoice);
74
+ }
75
+ }
76
+ else {
77
+ if (stakes !== undefined) {
78
+ throw new CodedError('"stakes" is allowed only on the opening step (stepIndex=0)', errors_helper_1.EErrorCode.ValidationStakes);
79
+ }
80
+ if (gameConfig.hasChoice && choice === undefined) {
81
+ throw new CodedError('"choice" is required on continuation steps (stepIndex > 0)', errors_helper_1.EErrorCode.ValidationChoice);
82
+ }
49
83
  }
50
84
  }
51
- function validateMeta(metaPrivate, metaPublic, gameConfig) {
52
- if (!gameConfig.hasMeta && (metaPrivate !== undefined || metaPublic !== undefined)) {
53
- throw new Error('The game is not supported meta data. metaPrivate and metaPublic are not allowed');
85
+ function validateChoice(choice, gameConfig) {
86
+ if (!gameConfig.hasChoice && choice !== undefined) {
87
+ throw new CodedError('The game is not stepped. "choice" is not allowed', errors_helper_1.EErrorCode.ValidationChoice);
54
88
  }
55
89
  }
56
- function validateGamble(isGambleAllowed, gameConfig) {
57
- if (!gameConfig.hasGamble && isGambleAllowed) {
58
- throw new Error('The game is not supported gamble feature');
90
+ function validateMeta(meta, gameConfig) {
91
+ if (!gameConfig.hasMeta && meta !== undefined) {
92
+ throw new CodedError('The game does not support meta data. "meta" is not allowed', errors_helper_1.EErrorCode.ValidationMeta);
59
93
  }
60
94
  }
61
- function validateFinishedInReply(finished, gameConfig) {
95
+ function validateFinishedInReply(finished, choices, gameConfig) {
62
96
  if (!gameConfig.hasChoice && !finished) {
63
- throw new Error('The game is not stepped. Round should be finished');
97
+ throw new CodedError('The game is not stepped. Round should be finished', errors_helper_1.EErrorCode.BusinessFinishedMismatch);
98
+ }
99
+ if (finished && choices !== undefined) {
100
+ throw new CodedError('"choices" must be absent when finished=true', errors_helper_1.EErrorCode.BusinessChoicesMismatch);
101
+ }
102
+ if (!finished && gameConfig.hasChoice && (choices === undefined || choices.length === 0)) {
103
+ throw new CodedError('"choices" must be a non-empty array when finished=false', errors_helper_1.EErrorCode.BusinessChoicesMismatch);
64
104
  }
65
105
  }
66
106
  function validateChoicesInReply(choices, gameConfig) {
67
107
  if (!gameConfig.hasChoice && choices !== undefined) {
68
- throw new Error('The game is not stepped. No choices!');
108
+ throw new CodedError('The game is not stepped. choices must be absent', errors_helper_1.EErrorCode.BusinessChoicesMismatch);
109
+ }
110
+ if (choices !== undefined && choices.length === 0) {
111
+ throw new CodedError('choices must be a non-empty array (never [] or null)', errors_helper_1.EErrorCode.BusinessChoicesMismatch);
112
+ }
113
+ }
114
+ function validateMetaInReply(meta, gameConfig) {
115
+ if (!gameConfig.hasMeta && meta !== undefined) {
116
+ throw new CodedError('The game does not have meta data. meta is not allowed', errors_helper_1.EErrorCode.ValidationMeta);
69
117
  }
70
118
  }
71
- function validateMetaInReply(metaPrivate, metaPublic, gameConfig) {
72
- if (!gameConfig.hasMeta && (metaPrivate !== undefined || metaPublic !== undefined)) {
73
- throw new Error('The game doesn\'t have meta data. metaPrivate and metaPublic are not allowed');
119
+ function validateMaxWinInReply(hasMaxWin, finished) {
120
+ if (hasMaxWin && !finished) {
121
+ throw new CodedError('"finished" must be true when hasMaxWin=true (max-win closes the round)', errors_helper_1.EErrorCode.BusinessMaxWinMismatch);
74
122
  }
75
123
  }
76
124
  const playRouteValidatePlugin = (0, fastify_helper_1.registerPlugin)(async (fastify) => {
77
125
  const gameConfig = (0, config_helper_1.getGameConfig)();
78
126
  const stakesMap = new Map(gameConfig.stakeModes.map((stakeMode) => [stakeMode.name, stakeMode]));
79
- fastify.addHook('preHandler', (request, reply, done) => {
127
+ fastify.addHook('preHandler', (request, _reply, done) => {
80
128
  const { body } = request;
81
129
  try {
82
130
  validateStakes(body.stakes, gameConfig, stakesMap);
83
131
  validateTestData(body.test);
84
132
  validateChoice(body.choice, gameConfig);
85
- validateMeta(body.metaPrivate, body.metaPublic, gameConfig);
86
- validateGamble(body.isGambleAllowed, gameConfig);
133
+ validateMeta(body.meta, gameConfig);
134
+ validateStepIndexConsistency(body.stepIndex, body.stakes, body.choice, gameConfig);
87
135
  done();
88
136
  }
89
137
  catch (error) {
90
- throw (0, fastify_helper_1.httpError)(`Advanced validation failed: ${error.message}`, 400);
138
+ const code = error instanceof CodedError ? error.code : errors_helper_1.EErrorCode.ValidationBody;
139
+ throw (0, fastify_helper_1.httpError)(`Advanced validation failed: ${error.message}`, 400, code);
91
140
  }
92
141
  });
93
- fastify.addHook('preSerialization', (_request, reply, payload, done) => {
94
- if (payload?.ok) {
142
+ fastify.addHook('preSerialization', (_request, _reply, payload, done) => {
143
+ if (payload) {
95
144
  try {
96
- validateFinishedInReply(payload.finished, gameConfig);
145
+ validateFinishedInReply(payload.finished, payload.choices, gameConfig);
97
146
  validateChoicesInReply(payload.choices, gameConfig);
98
- validateMetaInReply(payload.metaPrivate, payload.metaPublic, gameConfig);
147
+ validateMetaInReply(payload.meta, gameConfig);
148
+ validateMaxWinInReply(payload.hasMaxWin, payload.finished);
99
149
  }
100
150
  catch (error) {
101
- throw (0, fastify_helper_1.httpError)(`Advanced validation failed: ${error.message}`, 500);
151
+ const code = error instanceof CodedError ? error.code : errors_helper_1.EErrorCode.Unhandled;
152
+ throw (0, fastify_helper_1.httpError)(`Advanced validation failed: ${error.message}`, 500, code);
102
153
  }
103
154
  }
104
155
  done(null, payload);
@@ -1 +1 @@
1
- {"version":3,"file":"play.route.validate.plugin.js","sourceRoot":"","sources":["../../../routes/play/play.route.validate.plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"play.route.validate.plugin.js","sourceRoot":"","sources":["../../../routes/play/play.route.validate.plugin.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"validate.route.validate.plugin.d.ts","sourceRoot":"","sources":["../../../routes/validate/validate.route.validate.plugin.ts"],"names":[],"mappings":"AAWA,QAAA,MAAM,2BAA2B,mFAkB/B,CAAA;AAEF,eAAe,2BAA2B,CAAA"}
1
+ {"version":3,"file":"validate.route.validate.plugin.d.ts","sourceRoot":"","sources":["../../../routes/validate/validate.route.validate.plugin.ts"],"names":[],"mappings":"AAYA,QAAA,MAAM,2BAA2B,mFAkB/B,CAAA;AAEF,eAAe,2BAA2B,CAAA"}
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const config_helper_1 = require("../../helpers/config.helper");
4
+ const errors_helper_1 = require("../../helpers/errors.helper");
4
5
  const fastify_helper_1 = require("../../helpers/fastify.helper");
5
6
  const play_route_validate_plugin_1 = require("../play/play.route.validate.plugin");
6
7
  function validateAccessibility(gameConfig) {
7
- if (!gameConfig.hasValidation) {
8
- throw new Error('The game doesn\'t support validation');
8
+ if (!gameConfig.hasValidate) {
9
+ throw new Error("The game doesn't support validation");
9
10
  }
10
11
  }
11
12
  const validateRouteValidatePlugin = (0, fastify_helper_1.registerPlugin)(async (fastify) => {
@@ -16,11 +17,11 @@ const validateRouteValidatePlugin = (0, fastify_helper_1.registerPlugin)(async (
16
17
  try {
17
18
  validateAccessibility(gameConfig);
18
19
  (0, play_route_validate_plugin_1.validateStakes)(body.stakes, gameConfig, stakesMap);
19
- (0, play_route_validate_plugin_1.validateMeta)(body.metaPrivate, body.metaPublic, gameConfig);
20
+ (0, play_route_validate_plugin_1.validateMeta)(body.meta, gameConfig);
20
21
  done();
21
22
  }
22
23
  catch (error) {
23
- throw (0, fastify_helper_1.httpError)(`Advanced validation failed: ${error.message}`, 400);
24
+ throw (0, fastify_helper_1.httpError)(`Advanced validation failed: ${error.message}`, 400, errors_helper_1.EErrorCode.ValidationBody);
24
25
  }
25
26
  });
26
27
  });
@@ -1 +1 @@
1
- {"version":3,"file":"validate.route.validate.plugin.js","sourceRoot":"","sources":["../../../routes/validate/validate.route.validate.plugin.ts"],"names":[],"mappings":";;AAAA,+DAAwE;AACxE,iEAAwE;AAExE,mFAAiF;AAEjF,SAAS,qBAAqB,CAAC,UAAuB;IAClD,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAA;IAC3D,CAAC;AACL,CAAC;AAED,MAAM,2BAA2B,GAAG,IAAA,+BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACjE,MAAM,UAAU,GAAG,IAAA,6BAAa,GAAE,CAAA;IAElC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IAEhG,OAAO,CAAC,OAAO,CAA4D,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC/G,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QAExB,IAAI,CAAC;YACD,qBAAqB,CAAC,UAAU,CAAC,CAAA;YACjC,IAAA,2CAAc,EAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;YAClD,IAAA,yCAAY,EAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAA;YAE3D,IAAI,EAAE,CAAA;QACV,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAA,0BAAS,EAAC,+BAA+B,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAA;QACxE,CAAC;IACL,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA;AAEF,kBAAe,2BAA2B,CAAA"}
1
+ {"version":3,"file":"validate.route.validate.plugin.js","sourceRoot":"","sources":["../../../routes/validate/validate.route.validate.plugin.ts"],"names":[],"mappings":";;AAAA,+DAAwE;AACxE,+DAAwD;AACxD,iEAAwE;AAExE,mFAAiF;AAEjF,SAAS,qBAAqB,CAAC,UAAuB;IAClD,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAA;IAC1D,CAAC;AACL,CAAC;AAED,MAAM,2BAA2B,GAAG,IAAA,+BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACjE,MAAM,UAAU,GAAG,IAAA,6BAAa,GAAE,CAAA;IAElC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;IAEhG,OAAO,CAAC,OAAO,CAA4D,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QAC/G,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAA;QAExB,IAAI,CAAC;YACD,qBAAqB,CAAC,UAAU,CAAC,CAAA;YACjC,IAAA,2CAAc,EAAC,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,CAAC,CAAA;YAClD,IAAA,yCAAY,EAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;YAEnC,IAAI,EAAE,CAAA;QACV,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,IAAA,0BAAS,EAAC,+BAA+B,KAAK,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,0BAAU,CAAC,cAAc,CAAC,CAAA;QACnG,CAAC;IACL,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA;AAEF,kBAAe,2BAA2B,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"healthcheck.route.d.ts","sourceRoot":"","sources":["../../routes-public/healthcheck.route.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,gBAAgB,gFAsBpB,CAAA;AAEF,eAAe,gBAAgB,CAAA"}
@@ -6,7 +6,7 @@ const fastify_helper_1 = require("../helpers/fastify.helper");
6
6
  const healthcheck_schema_1 = require("../schemas/healthcheck.schema");
7
7
  const shared_1 = require("../schemas/shared");
8
8
  const healthcheckRoute = (0, fastify_helper_1.registerRoute)(async (fastify) => {
9
- fastify.post('/healthcheck', {
9
+ fastify.get('/healthcheck', {
10
10
  schema: {
11
11
  response: {
12
12
  200: healthcheck_schema_1.HealthcheckReplySchema,
@@ -17,17 +17,11 @@ const healthcheckRoute = (0, fastify_helper_1.registerRoute)(async (fastify) =>
17
17
  headers: shared_1.HeadersSchema,
18
18
  },
19
19
  }, () => ({
20
- code: 200,
21
- status: true,
22
- service: (0, config_helper_1.getGameConfig)().name,
20
+ ok: true,
21
+ gameId: (0, config_helper_1.getGameConfig)().gameId,
23
22
  environment: (0, env_helper_1.variation)(shared_1.EEnvironment.development, shared_1.EEnvironment.staging, shared_1.EEnvironment.production),
24
23
  uptime: process.uptime(),
25
- message: 'OK',
26
- timestamp: new Date().getTime(),
27
- metrics: fastify.metrics,
28
- services: {
29
- sentry: !!fastify.Sentry,
30
- },
24
+ timestamp: Date.now(),
31
25
  }));
32
26
  });
33
27
  exports.default = healthcheckRoute;
@@ -0,0 +1 @@
1
+ {"version":3,"file":"healthcheck.route.js","sourceRoot":"","sources":["../../routes-public/healthcheck.route.ts"],"names":[],"mappings":";;AAAA,4DAAwD;AACxD,sDAAiD;AACjD,8DAAyD;AACzD,sEAAsE;AACtE,8CAE0B;AAE1B,MAAM,gBAAgB,GAAG,IAAA,8BAAa,EAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACrD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE;QACxB,MAAM,EAAE;YACJ,QAAQ,EAAE;gBACN,GAAG,EAAE,2CAAsB;gBAC3B,GAAG,EAAE,2BAAkB;gBACvB,GAAG,EAAE,0BAAiB;gBACtB,GAAG,EAAE,4BAAmB;aAC3B;YACD,OAAO,EAAE,sBAAa;SACzB;KACJ,EAAE,GAAG,EAAE,CAAC,CAAC;QACN,EAAE,EAAE,IAAa;QACjB,MAAM,EAAE,IAAA,6BAAa,GAAE,CAAC,MAAM;QAC9B,WAAW,EAAE,IAAA,sBAAS,EAClB,qBAAY,CAAC,WAAW,EACxB,qBAAY,CAAC,OAAO,EACpB,qBAAY,CAAC,UAAU,CAC1B;QACD,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;QACxB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC,CAAA;AACP,CAAC,CAAC,CAAA;AAEF,kBAAe,gBAAgB,CAAA"}
@@ -0,0 +1,11 @@
1
+ import { Static, Type } from 'typebox';
2
+ export declare const ChecksumRequestSchema: Type.TObject<{}>;
3
+ export declare const ChecksumReplySchema: Type.TObject<{
4
+ files: Type.TArray<Type.TObject<{
5
+ path: Type.TString;
6
+ hash: Type.TString;
7
+ }>>;
8
+ }>;
9
+ export type TChecksumRequest = Static<typeof ChecksumRequestSchema>;
10
+ export type TChecksumReply = Static<typeof ChecksumReplySchema>;
11
+ //# sourceMappingURL=checksum.schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.schema.d.ts","sourceRoot":"","sources":["../../schemas/checksum.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAItC,eAAO,MAAM,qBAAqB,kBAGhC,CAAA;AAEF,eAAO,MAAM,mBAAmB;;;;;EAe9B,CAAA;AAEF,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAA;AACnE,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAA"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChecksumReplySchema = exports.ChecksumRequestSchema = void 0;
4
+ const typebox_1 = require("typebox");
5
+ const checksum_schema_examples_1 = require("./examples/checksum.schema.examples");
6
+ exports.ChecksumRequestSchema = typebox_1.Type.Object({}, {
7
+ $id: 'ChecksumRequest',
8
+ additionalProperties: false,
9
+ });
10
+ exports.ChecksumReplySchema = typebox_1.Type.Object({
11
+ files: typebox_1.Type.Array(typebox_1.Type.Object({
12
+ path: typebox_1.Type.String({
13
+ description: 'Path of the file, relative to the Game Server source root',
14
+ }),
15
+ hash: typebox_1.Type.String({
16
+ description: 'Hash of the file content. Algorithm and case (hex/base64) agreed with the RGS team',
17
+ }),
18
+ }, { additionalProperties: false }), {
19
+ description: 'List of files included in the integrity check',
20
+ }),
21
+ }, {
22
+ $id: 'ChecksumReply',
23
+ additionalProperties: false,
24
+ 'x-examples': checksum_schema_examples_1.checksumReplyExamples,
25
+ });
26
+ //# sourceMappingURL=checksum.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checksum.schema.js","sourceRoot":"","sources":["../../schemas/checksum.schema.ts"],"names":[],"mappings":";;;AAAA,qCAAsC;AAEtC,kFAA2E;AAE9D,QAAA,qBAAqB,GAAG,cAAI,CAAC,MAAM,CAAC,EAAE,EAAE;IACjD,GAAG,EAAE,iBAAiB;IACtB,oBAAoB,EAAE,KAAK;CAC9B,CAAC,CAAA;AAEW,QAAA,mBAAmB,GAAG,cAAI,CAAC,MAAM,CAAC;IAC3C,KAAK,EAAE,cAAI,CAAC,KAAK,CAAC,cAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,EAAE,cAAI,CAAC,MAAM,CAAC;YACd,WAAW,EAAE,2DAA2D;SAC3E,CAAC;QACF,IAAI,EAAE,cAAI,CAAC,MAAM,CAAC;YACd,WAAW,EAAE,oFAAoF;SACpG,CAAC;KACL,EAAE,EAAE,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE;QACjC,WAAW,EAAE,+CAA+C;KAC/D,CAAC;CACL,EAAE;IACC,GAAG,EAAE,eAAe;IACpB,oBAAoB,EAAE,KAAK;IAC3B,YAAY,EAAE,gDAAqB;CACtC,CAAC,CAAA"}
@@ -1,8 +1,8 @@
1
1
  import { Static, Type } from 'typebox';
2
2
  export declare const ClientRequestSchema: Type.TObject<{}>;
3
3
  export declare const ClientReplySchema: Type.TObject<{
4
- ok: Type.TBoolean;
5
4
  data: Type.TAny;
5
+ test: Type.TOptional<Type.TAny>;
6
6
  }>;
7
7
  export type TClientRequest = Static<typeof ClientRequestSchema>;
8
8
  export type TClientReply = Static<typeof ClientReplySchema>;
@@ -8,12 +8,12 @@ exports.ClientRequestSchema = typebox_1.Type.Object({}, {
8
8
  additionalProperties: false,
9
9
  });
10
10
  exports.ClientReplySchema = typebox_1.Type.Object({
11
- ok: typebox_1.Type.Boolean({
12
- description: 'Always true for success responses',
13
- }),
14
11
  data: typebox_1.Type.Any({
15
- description: 'JSON object with all game client settings',
12
+ description: 'Any client-side data (paytables, RNG params, limits, etc.). RGS forwards it to the client as-is, for every session, without filtering',
16
13
  }),
14
+ test: typebox_1.Type.Optional(typebox_1.Type.Any({
15
+ description: 'Any data the front-end needs to render the cheat tool. RGS forwards it only to sessions that are allowed to use the cheat tool',
16
+ })),
17
17
  }, {
18
18
  $id: 'ClientReply',
19
19
  additionalProperties: false,
@@ -1 +1 @@
1
- {"version":3,"file":"client.schema.js","sourceRoot":"","sources":["../../schemas/client.schema.ts"],"names":[],"mappings":";;;AAAA,qCAAsC;AAEtC,8EAAuE;AAE1D,QAAA,mBAAmB,GAAG,cAAI,CAAC,MAAM,CAAC,EAAE,EAAE;IAC/C,GAAG,EAAE,eAAe;IACpB,oBAAoB,EAAE,KAAK;CAC9B,CAAC,CAAA;AAEW,QAAA,iBAAiB,GAAG,cAAI,CAAC,MAAM,CAAC;IACzC,EAAE,EAAE,cAAI,CAAC,OAAO,CAAC;QACb,WAAW,EAAE,mCAAmC;KACnD,CAAC;IACF,IAAI,EAAE,cAAI,CAAC,GAAG,CAAC;QACX,WAAW,EAAE,2CAA2C;KAC3D,CAAC;CACL,EAAE;IACC,GAAG,EAAE,aAAa;IAClB,oBAAoB,EAAE,KAAK;IAC3B,YAAY,EAAE,4CAAmB;CACpC,CAAC,CAAA"}
1
+ {"version":3,"file":"client.schema.js","sourceRoot":"","sources":["../../schemas/client.schema.ts"],"names":[],"mappings":";;;AAAA,qCAAsC;AAEtC,8EAAuE;AAE1D,QAAA,mBAAmB,GAAG,cAAI,CAAC,MAAM,CAAC,EAAE,EAAE;IAC/C,GAAG,EAAE,eAAe;IACpB,oBAAoB,EAAE,KAAK;CAC9B,CAAC,CAAA;AAEW,QAAA,iBAAiB,GAAG,cAAI,CAAC,MAAM,CAAC;IACzC,IAAI,EAAE,cAAI,CAAC,GAAG,CAAC;QACX,WAAW,EAAE,uIAAuI;KACvJ,CAAC;IACF,IAAI,EAAE,cAAI,CAAC,QAAQ,CAAC,cAAI,CAAC,GAAG,CAAC;QACzB,WAAW,EAAE,gIAAgI;KAChJ,CAAC,CAAC;CACN,EAAE;IACC,GAAG,EAAE,aAAa;IAClB,oBAAoB,EAAE,KAAK;IAC3B,YAAY,EAAE,4CAAmB;CACpC,CAAC,CAAA"}
@@ -1,33 +1,30 @@
1
1
  import { Static, Type } from 'typebox';
2
- import { ECategory, EVolatility } from './shared';
3
2
  export declare const ConfigRequestSchema: Type.TObject<{}>;
4
3
  export declare const ConfigReplySchema: Type.TObject<{
5
- ok: Type.TBoolean;
6
- name: Type.TString;
7
- category: Type.TEnum<[ECategory.slots, ECategory.cluster, ECategory.table]>;
4
+ gameId: Type.TString;
5
+ volatility: Type.TNumber;
6
+ rtp: Type.TString;
7
+ rtpVersion: Type.TString;
8
+ hasMeta: Type.TBoolean;
9
+ hasChoice: Type.TBoolean;
10
+ hasRestore: Type.TBoolean;
11
+ hasMultiStake: Type.TBoolean;
12
+ hasVariableLevels: Type.TBoolean;
13
+ variableLevels: Type.TOptional<Type.TArray<Type.TNumber>>;
14
+ defaultLevel: Type.TOptional<Type.TNumber>;
15
+ coinRatio: Type.TOptional<Type.TNumber>;
16
+ minWin: Type.TNumber;
17
+ maxWin: Type.TNumber;
18
+ freeroundsAllowed: Type.TBoolean;
19
+ hasValidate: Type.TBoolean;
8
20
  stakeModes: Type.TArray<Type.TObject<{
9
21
  name: Type.TString;
10
22
  type: Type.TEnum<[import("./shared").EStakeType.default, import("./shared").EStakeType.buy, import("./shared").EStakeType.bonusBet]>;
11
23
  bets: Type.TNumber;
12
24
  multiple: Type.TOptional<Type.TBoolean>;
13
- parametric: Type.TBoolean;
14
25
  maxQty: Type.TOptional<Type.TInteger>;
26
+ parametric: Type.TOptional<Type.TBoolean>;
15
27
  }>>;
16
- rtp: Type.TNumber;
17
- hitrate: Type.TOptional<Type.TNumber>;
18
- volatility: Type.TOptional<Type.TEnum<[EVolatility.variable, EVolatility.low, EVolatility.medLow, EVolatility.med, EVolatility.medHigh, EVolatility.high, EVolatility.veryHigh]>>;
19
- hasMeta: Type.TBoolean;
20
- hasChoice: Type.TBoolean;
21
- hasBuy: Type.TBoolean;
22
- hasMultiStake: Type.TBoolean;
23
- hasValidation: Type.TBoolean;
24
- hasGamble: Type.TBoolean;
25
- freeroundsAllowed: Type.TBoolean;
26
- minWin: Type.TOptional<Type.TNumber>;
27
- maxWin: Type.TNumber;
28
- apiVersion: Type.TNumber;
29
- variableLevels: Type.TOptional<Type.TInteger>;
30
- coinRatio: Type.TOptional<Type.TNumber>;
31
28
  }>;
32
29
  export type TConfigRequest = Static<typeof ConfigRequestSchema>;
33
30
  export type TConfigReply = Static<typeof ConfigReplySchema>;
@@ -1 +1 @@
1
- {"version":3,"file":"config.schema.d.ts","sourceRoot":"","sources":["../../schemas/config.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAGtC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAmB,MAAM,UAAU,CAAA;AAElE,eAAO,MAAM,mBAAmB,kBAG9B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkE5B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
1
+ {"version":3,"file":"config.schema.d.ts","sourceRoot":"","sources":["../../schemas/config.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAKtC,eAAO,MAAM,mBAAmB,kBAG9B,CAAA;AAEF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;EAiE5B,CAAA;AAEF,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAA;AAC/D,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAA"}
@@ -9,67 +9,66 @@ exports.ConfigRequestSchema = typebox_1.Type.Object({}, {
9
9
  additionalProperties: false,
10
10
  });
11
11
  exports.ConfigReplySchema = typebox_1.Type.Object({
12
- ok: typebox_1.Type.Boolean({
13
- description: 'Always true for success responses',
12
+ gameId: typebox_1.Type.String({
13
+ description: 'Unique game identifier, shared across all RTP versions of this game (e.g. "book-of-odin")',
14
14
  }),
15
- name: typebox_1.Type.String({
16
- description: 'Full game name',
15
+ volatility: typebox_1.Type.Number({
16
+ description: 'Game volatility. One of 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5',
17
+ enum: [0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5],
17
18
  }),
18
- category: typebox_1.Type.Enum(shared_1.ECategory, {
19
- description: 'Game category: "slots", "cluster", "table", etc.',
19
+ rtp: typebox_1.Type.String({
20
+ description: 'Exact RTP value of the deployed version as a decimal string (e.g. "96.17")',
21
+ pattern: '^\\d+(\\.\\d+)?$',
20
22
  }),
21
- stakeModes: typebox_1.Type.Array(shared_1.StakeModeSchema, {
22
- description: 'Array of available stake modes',
23
- minItems: 1,
24
- }),
25
- rtp: typebox_1.Type.Number({
26
- description: 'Full RTP "xx.xx"',
23
+ rtpVersion: typebox_1.Type.String({
24
+ description: 'RTP version label (the bucket, e.g. "96") — matches the {rtpVersion} path segment under which this endpoint is mounted. Connected to rtp 1:1',
25
+ minLength: 1,
27
26
  }),
28
- hitrate: typebox_1.Type.Optional(typebox_1.Type.Number({
29
- description: 'Game hitrate "x.xx". Optional if the game does not have static hitrate',
30
- })),
31
- volatility: typebox_1.Type.Optional(typebox_1.Type.Enum(shared_1.EVolatility, {
32
- description: 'Game volatility level. Optional if the game does not have static volatility',
33
- })),
34
27
  hasMeta: typebox_1.Type.Boolean({
35
- description: 'true if the game uses meta data or has choice mechanics',
28
+ description: 'true if the game uses meta state. Must be true whenever hasChoice is true',
36
29
  }),
37
30
  hasChoice: typebox_1.Type.Boolean({
38
- description: 'true if the game has user choice or double up mechanics',
31
+ description: 'true if rounds may include in-round player choices. Requires hasMeta=true',
39
32
  }),
40
- hasBuy: typebox_1.Type.Boolean({
41
- description: 'true if the game has any buy features',
33
+ hasRestore: typebox_1.Type.Boolean({
34
+ description: 'true if a round stays open across requests until the client explicitly sends /round/close',
42
35
  }),
43
36
  hasMultiStake: typebox_1.Type.Boolean({
44
- description: 'true if the game is able to make multiple bets',
45
- }),
46
- hasValidation: typebox_1.Type.Boolean({
47
- description: 'true if Business Logic should use validation endpoint for checking meta and stakes. Needed for games with complex mechanics, that can exceed max exposure',
37
+ description: 'true if the game accepts more than one stake at once',
48
38
  }),
49
- hasGamble: typebox_1.Type.Boolean({
50
- description: 'true if the game has “double up” mechanics',
39
+ hasVariableLevels: typebox_1.Type.Boolean({
40
+ description: 'true if the game has selectable bet levels — e.g. paylines for slots, table id for roulette',
51
41
  }),
52
- freeroundsAllowed: typebox_1.Type.Boolean({
53
- description: 'true if freerounds for the game are allowed',
54
- }),
55
- minWin: typebox_1.Type.Optional(typebox_1.Type.Number({
56
- description: 'Minimum available win in x bets. Optional if the game does not have static minWin',
42
+ variableLevels: typebox_1.Type.Optional(typebox_1.Type.Array(typebox_1.Type.Number({ exclusiveMinimum: 0 }), {
43
+ description: 'Required when hasVariableLevels=true; omit otherwise. Available bet levels the player can choose between (literal values, e.g. [10, 20, 30, 40, 50])',
44
+ minItems: 1,
45
+ })),
46
+ defaultLevel: typebox_1.Type.Optional(typebox_1.Type.Number({
47
+ description: 'Required when hasVariableLevels=true; omit otherwise. Default selected bet level (must be one of variableLevels)',
48
+ exclusiveMinimum: 0,
49
+ })),
50
+ coinRatio: typebox_1.Type.Optional(typebox_1.Type.Number({
51
+ description: 'Required when hasVariableLevels=false; omit otherwise. Ratio converting coins to currency units',
57
52
  exclusiveMinimum: 0,
58
53
  })),
54
+ minWin: typebox_1.Type.Number({
55
+ description: 'Minimum available win, expressed as a multiplier of the bet (×bet)',
56
+ minimum: 0,
57
+ }),
59
58
  maxWin: typebox_1.Type.Number({
60
- description: 'Maximum available win in x bets',
59
+ description: 'Maximum available win, expressed as a multiplier of the bet (×bet)',
61
60
  exclusiveMinimum: 0,
62
61
  }),
63
- apiVersion: typebox_1.Type.Number({
64
- description: 'Major version of the TrueLab server API',
62
+ freeroundsAllowed: typebox_1.Type.Boolean({
63
+ description: 'true if the game supports free-rounds bonuses',
64
+ }),
65
+ hasValidate: typebox_1.Type.Boolean({
66
+ description: 'true if RGS must call /validate before opening a round. Must be true when hasMultiStake=true',
67
+ }),
68
+ stakeModes: typebox_1.Type.Array(shared_1.StakeModeSchema, {
69
+ description: 'List of stake modes the game accepts in /play',
70
+ minItems: 1,
65
71
  }),
66
- variableLevels: typebox_1.Type.Optional(typebox_1.Type.Integer({
67
- minimum: 2,
68
- description: 'true if the game has variable number of lines, tables etc.',
69
- })),
70
- coinRatio: typebox_1.Type.Optional(typebox_1.Type.Number({
71
- description: 'Game coin ratio',
72
- })),
73
72
  }, {
74
73
  $id: 'ConfigReply',
75
74
  additionalProperties: false,