@takaro/modules 0.0.14 → 0.0.18

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 (244) hide show
  1. package/dist/BuiltinModule.d.ts +13 -8
  2. package/dist/BuiltinModule.d.ts.map +1 -0
  3. package/dist/BuiltinModule.js +48 -31
  4. package/dist/BuiltinModule.js.map +1 -1
  5. package/dist/dto/base.d.ts +1 -0
  6. package/dist/dto/base.d.ts.map +1 -0
  7. package/dist/dto/discordEvents.d.ts +1 -0
  8. package/dist/dto/discordEvents.d.ts.map +1 -0
  9. package/dist/dto/gameEvents.d.ts +1 -0
  10. package/dist/dto/gameEvents.d.ts.map +1 -0
  11. package/dist/dto/index.d.ts +4 -0
  12. package/dist/dto/index.d.ts.map +1 -0
  13. package/dist/dto/takaroEvents.d.ts +16 -0
  14. package/dist/dto/takaroEvents.d.ts.map +1 -0
  15. package/dist/dto/takaroEvents.js +36 -0
  16. package/dist/dto/takaroEvents.js.map +1 -1
  17. package/dist/main.d.ts +4 -3
  18. package/dist/main.d.ts.map +1 -0
  19. package/dist/main.js +3 -1
  20. package/dist/main.js.map +1 -1
  21. package/dist/modules/chatBridge/hooks/DiscordToGame.d.ts +1 -0
  22. package/dist/modules/chatBridge/hooks/DiscordToGame.d.ts.map +1 -0
  23. package/dist/modules/chatBridge/hooks/GameToDiscord.d.ts +1 -0
  24. package/dist/modules/chatBridge/hooks/GameToDiscord.d.ts.map +1 -0
  25. package/dist/modules/chatBridge/hooks/PlayerConnected.d.ts +1 -0
  26. package/dist/modules/chatBridge/hooks/PlayerConnected.d.ts.map +1 -0
  27. package/dist/modules/chatBridge/hooks/PlayerDisconnected.d.ts +1 -0
  28. package/dist/modules/chatBridge/hooks/PlayerDisconnected.d.ts.map +1 -0
  29. package/dist/modules/chatBridge/index.d.ts +3 -2
  30. package/dist/modules/chatBridge/index.d.ts.map +1 -0
  31. package/dist/modules/chatBridge/index.js +55 -47
  32. package/dist/modules/chatBridge/index.js.map +1 -1
  33. package/dist/modules/dailyRewards/commands/daily.d.ts +2 -0
  34. package/dist/modules/dailyRewards/commands/daily.d.ts.map +1 -0
  35. package/dist/modules/dailyRewards/commands/daily.js +106 -0
  36. package/dist/modules/dailyRewards/commands/daily.js.map +1 -0
  37. package/dist/modules/dailyRewards/commands/streak.d.ts +2 -0
  38. package/dist/modules/dailyRewards/commands/streak.d.ts.map +1 -0
  39. package/dist/modules/dailyRewards/commands/streak.js +34 -0
  40. package/dist/modules/dailyRewards/commands/streak.js.map +1 -0
  41. package/dist/modules/dailyRewards/commands/topstreak.d.ts +2 -0
  42. package/dist/modules/dailyRewards/commands/topstreak.d.ts.map +1 -0
  43. package/dist/modules/dailyRewards/commands/topstreak.js +44 -0
  44. package/dist/modules/dailyRewards/commands/topstreak.js.map +1 -0
  45. package/dist/modules/dailyRewards/functions/utils.d.ts +6 -0
  46. package/dist/modules/dailyRewards/functions/utils.d.ts.map +1 -0
  47. package/dist/modules/dailyRewards/functions/utils.js +32 -0
  48. package/dist/modules/dailyRewards/functions/utils.js.map +1 -0
  49. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.d.ts +2 -0
  50. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.d.ts.map +1 -0
  51. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.js +19 -0
  52. package/dist/modules/dailyRewards/hooks/dailyLoginCheck.js.map +1 -0
  53. package/dist/modules/dailyRewards/index.d.ts +5 -0
  54. package/dist/modules/dailyRewards/index.d.ts.map +1 -0
  55. package/dist/modules/dailyRewards/index.js +125 -0
  56. package/dist/modules/dailyRewards/index.js.map +1 -0
  57. package/dist/modules/economyUtils/commands/balance.d.ts +1 -0
  58. package/dist/modules/economyUtils/commands/balance.d.ts.map +1 -0
  59. package/dist/modules/economyUtils/commands/claim.d.ts +1 -0
  60. package/dist/modules/economyUtils/commands/claim.d.ts.map +1 -0
  61. package/dist/modules/economyUtils/commands/confirmTransfer.d.ts +1 -0
  62. package/dist/modules/economyUtils/commands/confirmTransfer.d.ts.map +1 -0
  63. package/dist/modules/economyUtils/commands/grantCurrency.d.ts +1 -0
  64. package/dist/modules/economyUtils/commands/grantCurrency.d.ts.map +1 -0
  65. package/dist/modules/economyUtils/commands/revokeCurrency.d.ts +1 -0
  66. package/dist/modules/economyUtils/commands/revokeCurrency.d.ts.map +1 -0
  67. package/dist/modules/economyUtils/commands/shop.d.ts +1 -0
  68. package/dist/modules/economyUtils/commands/shop.d.ts.map +1 -0
  69. package/dist/modules/economyUtils/commands/topCurrency.d.ts +1 -0
  70. package/dist/modules/economyUtils/commands/topCurrency.d.ts.map +1 -0
  71. package/dist/modules/economyUtils/commands/transfer.d.ts +1 -0
  72. package/dist/modules/economyUtils/commands/transfer.d.ts.map +1 -0
  73. package/dist/modules/economyUtils/cronJobs/zombieKillReward.d.ts +1 -0
  74. package/dist/modules/economyUtils/cronJobs/zombieKillReward.d.ts.map +1 -0
  75. package/dist/modules/economyUtils/index.d.ts +3 -2
  76. package/dist/modules/economyUtils/index.d.ts.map +1 -0
  77. package/dist/modules/economyUtils/index.js +178 -170
  78. package/dist/modules/economyUtils/index.js.map +1 -1
  79. package/dist/modules/geoBlock/hooks/IPDetected.d.ts +1 -0
  80. package/dist/modules/geoBlock/hooks/IPDetected.d.ts.map +1 -0
  81. package/dist/modules/geoBlock/hooks/IPDetected.js +4 -2
  82. package/dist/modules/geoBlock/hooks/IPDetected.js.map +1 -1
  83. package/dist/modules/geoBlock/index.d.ts +3 -2
  84. package/dist/modules/geoBlock/index.d.ts.map +1 -0
  85. package/dist/modules/geoBlock/index.js +71 -63
  86. package/dist/modules/geoBlock/index.js.map +1 -1
  87. package/dist/modules/gimme/commands/gimme.d.ts +1 -0
  88. package/dist/modules/gimme/commands/gimme.d.ts.map +1 -0
  89. package/dist/modules/gimme/commands/gimme.js +17 -6
  90. package/dist/modules/gimme/commands/gimme.js.map +1 -1
  91. package/dist/modules/gimme/index.d.ts +3 -2
  92. package/dist/modules/gimme/index.d.ts.map +1 -0
  93. package/dist/modules/gimme/index.js +64 -34
  94. package/dist/modules/gimme/index.js.map +1 -1
  95. package/dist/modules/highPingKicker/cronJobs/Ping check.d.ts +1 -0
  96. package/dist/modules/highPingKicker/cronJobs/Ping check.d.ts.map +1 -0
  97. package/dist/modules/highPingKicker/index.d.ts +3 -2
  98. package/dist/modules/highPingKicker/index.d.ts.map +1 -0
  99. package/dist/modules/highPingKicker/index.js +36 -28
  100. package/dist/modules/highPingKicker/index.js.map +1 -1
  101. package/dist/modules/lottery/commands/buyTicket.d.ts +1 -0
  102. package/dist/modules/lottery/commands/buyTicket.d.ts.map +1 -0
  103. package/dist/modules/lottery/commands/nextDraw.d.ts +1 -0
  104. package/dist/modules/lottery/commands/nextDraw.d.ts.map +1 -0
  105. package/dist/modules/lottery/commands/viewTickets.d.ts +1 -0
  106. package/dist/modules/lottery/commands/viewTickets.d.ts.map +1 -0
  107. package/dist/modules/lottery/cronJobs/drawLottery.d.ts +1 -0
  108. package/dist/modules/lottery/cronJobs/drawLottery.d.ts.map +1 -0
  109. package/dist/modules/lottery/index.d.ts +3 -2
  110. package/dist/modules/lottery/index.d.ts.map +1 -0
  111. package/dist/modules/lottery/index.js +73 -65
  112. package/dist/modules/lottery/index.js.map +1 -1
  113. package/dist/modules/playerOnboarding/commands/starterkit.d.ts +1 -0
  114. package/dist/modules/playerOnboarding/commands/starterkit.d.ts.map +1 -0
  115. package/dist/modules/playerOnboarding/commands/starterkit.js +16 -3
  116. package/dist/modules/playerOnboarding/commands/starterkit.js.map +1 -1
  117. package/dist/modules/playerOnboarding/hooks/playerConnected.d.ts +1 -0
  118. package/dist/modules/playerOnboarding/hooks/playerConnected.d.ts.map +1 -0
  119. package/dist/modules/playerOnboarding/index.d.ts +3 -2
  120. package/dist/modules/playerOnboarding/index.d.ts.map +1 -0
  121. package/dist/modules/playerOnboarding/index.js +73 -43
  122. package/dist/modules/playerOnboarding/index.js.map +1 -1
  123. package/dist/modules/serverMessages/cronJobs/Automated message.d.ts +1 -0
  124. package/dist/modules/serverMessages/cronJobs/Automated message.d.ts.map +1 -0
  125. package/dist/modules/serverMessages/index.d.ts +3 -2
  126. package/dist/modules/serverMessages/index.d.ts.map +1 -0
  127. package/dist/modules/serverMessages/index.js +36 -28
  128. package/dist/modules/serverMessages/index.js.map +1 -1
  129. package/dist/modules/teleports/commands/deletetp.d.ts +1 -0
  130. package/dist/modules/teleports/commands/deletetp.d.ts.map +1 -0
  131. package/dist/modules/teleports/commands/deletewaypoint.d.ts +1 -0
  132. package/dist/modules/teleports/commands/deletewaypoint.d.ts.map +1 -0
  133. package/dist/modules/teleports/commands/deletewaypoint.js +4 -35
  134. package/dist/modules/teleports/commands/deletewaypoint.js.map +1 -1
  135. package/dist/modules/teleports/commands/listwaypoints.d.ts +1 -0
  136. package/dist/modules/teleports/commands/listwaypoints.d.ts.map +1 -0
  137. package/dist/modules/teleports/commands/listwaypoints.js +3 -22
  138. package/dist/modules/teleports/commands/listwaypoints.js.map +1 -1
  139. package/dist/modules/teleports/commands/setprivate.d.ts +1 -0
  140. package/dist/modules/teleports/commands/setprivate.d.ts.map +1 -0
  141. package/dist/modules/teleports/commands/setpublic.d.ts +1 -0
  142. package/dist/modules/teleports/commands/setpublic.d.ts.map +1 -0
  143. package/dist/modules/teleports/commands/settp.d.ts +1 -0
  144. package/dist/modules/teleports/commands/settp.d.ts.map +1 -0
  145. package/dist/modules/teleports/commands/setwaypoint.d.ts +1 -0
  146. package/dist/modules/teleports/commands/setwaypoint.d.ts.map +1 -0
  147. package/dist/modules/teleports/commands/setwaypoint.js +5 -63
  148. package/dist/modules/teleports/commands/setwaypoint.js.map +1 -1
  149. package/dist/modules/teleports/commands/teleport.d.ts +1 -0
  150. package/dist/modules/teleports/commands/teleport.d.ts.map +1 -0
  151. package/dist/modules/teleports/commands/teleportwaypoint.d.ts +1 -0
  152. package/dist/modules/teleports/commands/teleportwaypoint.d.ts.map +1 -0
  153. package/dist/modules/teleports/commands/teleportwaypoint.js +7 -23
  154. package/dist/modules/teleports/commands/teleportwaypoint.js.map +1 -1
  155. package/dist/modules/teleports/commands/tplist.d.ts +1 -0
  156. package/dist/modules/teleports/commands/tplist.d.ts.map +1 -0
  157. package/dist/modules/teleports/cronJobs/Waypoint reconciler.d.ts +2 -0
  158. package/dist/modules/teleports/cronJobs/Waypoint reconciler.d.ts.map +1 -0
  159. package/dist/modules/teleports/cronJobs/Waypoint reconciler.js +6 -0
  160. package/dist/modules/teleports/cronJobs/Waypoint reconciler.js.map +1 -0
  161. package/dist/modules/teleports/functions/utils.d.ts +12 -0
  162. package/dist/modules/teleports/functions/utils.d.ts.map +1 -0
  163. package/dist/modules/teleports/functions/utils.js +117 -0
  164. package/dist/modules/teleports/functions/utils.js.map +1 -1
  165. package/dist/modules/teleports/index.d.ts +3 -2
  166. package/dist/modules/teleports/index.d.ts.map +1 -0
  167. package/dist/modules/teleports/index.js +188 -172
  168. package/dist/modules/teleports/index.js.map +1 -1
  169. package/dist/modules/timedShutdown/cronJobs/Shutdown.d.ts +1 -0
  170. package/dist/modules/timedShutdown/cronJobs/Shutdown.d.ts.map +1 -0
  171. package/dist/modules/timedShutdown/cronJobs/warning.d.ts +1 -0
  172. package/dist/modules/timedShutdown/cronJobs/warning.d.ts.map +1 -0
  173. package/dist/modules/timedShutdown/index.d.ts +3 -2
  174. package/dist/modules/timedShutdown/index.d.ts.map +1 -0
  175. package/dist/modules/timedShutdown/index.js +35 -27
  176. package/dist/modules/timedShutdown/index.js.map +1 -1
  177. package/dist/modules/utils/commands/help.d.ts +1 -0
  178. package/dist/modules/utils/commands/help.d.ts.map +1 -0
  179. package/dist/modules/utils/commands/help.js +10 -9
  180. package/dist/modules/utils/commands/help.js.map +1 -1
  181. package/dist/modules/utils/commands/ping.d.ts +1 -0
  182. package/dist/modules/utils/commands/ping.d.ts.map +1 -0
  183. package/dist/modules/utils/index.d.ts +3 -2
  184. package/dist/modules/utils/index.d.ts.map +1 -0
  185. package/dist/modules/utils/index.js +36 -28
  186. package/dist/modules/utils/index.js.map +1 -1
  187. package/dist/modules.json +601 -506
  188. package/package.json +2 -5
  189. package/scripts/buildBuiltinJson.ts +50 -2
  190. package/src/BuiltinModule.ts +25 -17
  191. package/src/__tests__/aliases.integration.test.ts +23 -26
  192. package/src/__tests__/bugRepros.integration.test.ts +261 -10
  193. package/src/__tests__/builtinmodule.unit.test.ts +3 -1
  194. package/src/__tests__/commandArgs.integration.test.ts +13 -6
  195. package/src/__tests__/economy/claim.integration.test.ts +1 -0
  196. package/src/__tests__/economy/economyUtils.integration.test.ts +43 -46
  197. package/src/__tests__/economy/shop.integration.test.ts +28 -4
  198. package/src/__tests__/economy/zombieKillReward.integration.test.ts +28 -31
  199. package/src/__tests__/geoblock.integration.test.ts +76 -91
  200. package/src/__tests__/gimme.integration.test.ts +25 -22
  201. package/src/__tests__/help.integration.test.ts +21 -20
  202. package/src/__tests__/lottery.integration.test.ts +15 -11
  203. package/src/__tests__/modulePermission.integration.test.ts +17 -13
  204. package/src/__tests__/onboarding.integration.test.ts +43 -43
  205. package/src/__tests__/ping.integration.test.ts +5 -4
  206. package/src/__tests__/roleExpiry.integration.test.ts +5 -4
  207. package/src/__tests__/serverMessages.integration.test.ts +24 -27
  208. package/src/__tests__/systemConfigCooldown.integration.test.ts +5 -1
  209. package/src/__tests__/systemConfigCost.integration.test.ts +16 -17
  210. package/src/__tests__/teleports/listtp.integration.test.ts +20 -21
  211. package/src/__tests__/teleports/publicteleports.integration.test.ts +58 -70
  212. package/src/__tests__/teleports/teleport.integration.test.ts +16 -17
  213. package/src/__tests__/teleports/tpManagement.integration.test.ts +21 -20
  214. package/src/__tests__/teleports/waypoints.integration.test.ts +52 -6
  215. package/src/dto/takaroEvents.ts +21 -0
  216. package/src/main.ts +14 -4
  217. package/src/modules/chatBridge/index.ts +54 -51
  218. package/src/modules/dailyRewards/commands/daily.js +118 -0
  219. package/src/modules/dailyRewards/commands/streak.js +42 -0
  220. package/src/modules/dailyRewards/commands/topstreak.js +54 -0
  221. package/src/modules/dailyRewards/functions/utils.js +36 -0
  222. package/src/modules/dailyRewards/hooks/dailyLoginCheck.js +24 -0
  223. package/src/modules/dailyRewards/index.ts +136 -0
  224. package/src/modules/economyUtils/index.ts +182 -179
  225. package/src/modules/geoBlock/hooks/IPDetected.js +4 -2
  226. package/src/modules/geoBlock/index.ts +72 -70
  227. package/src/modules/gimme/commands/gimme.js +16 -6
  228. package/src/modules/gimme/index.ts +62 -37
  229. package/src/modules/highPingKicker/index.ts +35 -32
  230. package/src/modules/lottery/index.ts +73 -71
  231. package/src/modules/playerOnboarding/commands/starterkit.js +19 -5
  232. package/src/modules/playerOnboarding/index.ts +72 -47
  233. package/src/modules/serverMessages/index.ts +36 -32
  234. package/src/modules/teleports/commands/deletewaypoint.js +4 -53
  235. package/src/modules/teleports/commands/listwaypoints.js +3 -35
  236. package/src/modules/teleports/commands/setwaypoint.js +5 -83
  237. package/src/modules/teleports/commands/teleportwaypoint.js +9 -36
  238. package/src/modules/teleports/cronJobs/Waypoint reconciler.js +7 -0
  239. package/src/modules/teleports/functions/utils.js +150 -0
  240. package/src/modules/teleports/index.ts +196 -180
  241. package/src/modules/timedShutdown/index.ts +35 -30
  242. package/src/modules/utils/commands/help.js +14 -14
  243. package/src/modules/utils/index.ts +36 -32
  244. package/tsconfig.json +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takaro/modules",
3
- "version": "0.0.14",
3
+ "version": "0.0.18",
4
4
  "description": "Built-in modules for Takaro",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
@@ -9,10 +9,7 @@
9
9
  "start:dev": "tsc --watch --preserveWatchOutput -p ./tsconfig.build.json",
10
10
  "build": "tsc -p ./tsconfig.build.json",
11
11
  "postbuild": "npm run build:builtin-json",
12
- "test": "npm run test:unit --if-present && npm run test:integration --if-present",
13
- "test:unit": "mocha --config ../../.mocharc.js src/**/*.unit.test.ts",
14
- "test:integration": "mocha --file ../test/dist/waitUntilReady.js --config ../../.mocharc.js 'src/**/*.integration.test.ts' --exit",
15
- "build:builtin-json": "node --loader ts-node/esm ./scripts/buildBuiltinJson.ts"
12
+ "build:builtin-json": "node --import=ts-node-maintained/register/esm ./scripts/buildBuiltinJson.ts"
16
13
  },
17
14
  "keywords": [],
18
15
  "author": "",
@@ -1,7 +1,7 @@
1
1
  import 'reflect-metadata';
2
2
  import { getModules } from '@takaro/modules';
3
3
  import { writeFile } from 'fs/promises';
4
- import { readdir, readFile } from 'node:fs/promises';
4
+ import { readdir, readFile, stat } from 'node:fs/promises';
5
5
  import path from 'path';
6
6
 
7
7
  const __dirname = path.dirname(new URL(import.meta.url).pathname);
@@ -12,7 +12,7 @@ async function main() {
12
12
  const modules = getModules();
13
13
  const modulesJson = JSON.stringify(modules, null, 2);
14
14
  await writeFile('dist/modules.json', modulesJson);
15
- await writeFile('../web-docs/docs/modules.json', modulesJson);
15
+ await writeFile('../web-docs/docs/modules/modules.json', modulesJson);
16
16
  await writeFile('../e2e/src/web-main/fixtures/modules.json', modulesJson);
17
17
 
18
18
  // Community modules
@@ -28,6 +28,54 @@ async function main() {
28
28
  await writeFile('dist/community-modules.json', communityModulesJson);
29
29
  await writeFile('../web-docs/docs/community-modules.json', communityModulesJson);
30
30
  await writeFile('../e2e/src/web-main/fixtures/community-modules.json', communityModulesJson);
31
+
32
+ const startMarker = '{/* AUTO-GENERATED CONTENT () */}';
33
+ const endMarker = '{/* END AUTO-GENERATED CONTENT */}';
34
+
35
+ // Generate docs pages for each builtin module
36
+ for (const mod of modules) {
37
+ const fileExists = await stat(`../web-docs/docs/modules/${mod.name}.mdx`).catch(() => null);
38
+ // This is also generated, but docusaurus takes the first content of the page as the title, so we cannot put the auto-generated content at the top
39
+ const autoGeneratedContent = `---
40
+ description: ${mod.versions.find((v) => v.tag === 'latest')?.description}
41
+ ---
42
+
43
+ ${startMarker}
44
+
45
+ import { Commands, Config, CronJobs, Hooks } from './helpers';
46
+
47
+ # ${mod.name}
48
+
49
+ export function Module() {
50
+ const mod = ${JSON.stringify(mod, null, 2)};
51
+
52
+ return (
53
+ <div>
54
+ <p>{mod.versions[0].description}</p>
55
+ <Commands commands={mod.versions[0].commands} />
56
+ <CronJobs cronJobs={mod.versions[0].cronJobs} />
57
+ <Hooks hooks={mod.versions[0].hooks} />
58
+ <Config configSchema={mod.versions[0].configSchema} />
59
+ </div>
60
+ )
61
+ }
62
+
63
+ <Module />
64
+
65
+ ${endMarker}`;
66
+
67
+ // If file doesnt exist yet, create it
68
+ if (!fileExists) {
69
+ await writeFile(`../web-docs/docs/modules/${mod.name}.mdx`, autoGeneratedContent);
70
+ } else {
71
+ const existingFile = await readFile(`../web-docs/docs/modules/${mod.name}.mdx`, 'utf-8');
72
+ // Otherwise, fine the auto generated content markers and replace it
73
+ const end = existingFile.indexOf(endMarker) + endMarker.length;
74
+
75
+ const newFile = autoGeneratedContent + existingFile.slice(end);
76
+ await writeFile(`../web-docs/docs/modules/${mod.name}.mdx`, newFile);
77
+ }
78
+ }
31
79
  }
32
80
 
33
81
  main().catch(console.error);
@@ -77,40 +77,48 @@ export class IPermission extends TakaroDTO<IPermission> {
77
77
  canHaveCount?: boolean;
78
78
  }
79
79
 
80
- export class BuiltinModule<T> extends TakaroDTO<T> {
81
- constructor(name: string, description: string, configSchema: string, uiSchema: string = JSON.stringify({})) {
82
- super();
83
- this.name = name;
84
- this.description = description;
85
- this.configSchema = configSchema;
86
- this.uiSchema = uiSchema;
87
- }
88
-
80
+ export class ModuleTransferVersionDTO<T> extends TakaroDTO<T> {
89
81
  @IsString()
90
- public name: string;
82
+ public tag: string;
91
83
  @IsString()
92
84
  public description: string;
93
85
  @IsString()
94
86
  public configSchema: string;
95
87
  @IsString()
96
- public uiSchema: string;
97
-
88
+ public uiSchema = '{}';
98
89
  @ValidateNested({ each: true })
99
90
  @Type(() => ICommand)
100
- public commands: Array<ICommand> = [];
91
+ @IsOptional()
92
+ public commands?: Array<ICommand>;
101
93
  @ValidateNested({ each: true })
102
94
  @Type(() => IHook)
103
- public hooks: Array<IHook> = [];
95
+ @IsOptional()
96
+ public hooks?: Array<IHook>;
104
97
  @ValidateNested({ each: true })
105
98
  @Type(() => ICronJob)
106
- public cronJobs: Array<ICronJob> = [];
99
+ @IsOptional()
100
+ public cronJobs?: Array<ICronJob>;
107
101
  @ValidateNested({ each: true })
108
102
  @Type(() => IFunction)
109
- public functions: Array<IFunction> = [];
103
+ @IsOptional()
104
+ public functions?: Array<IFunction>;
110
105
  @IsArray()
111
106
  @Type(() => IPermission)
112
107
  @ValidateNested({ each: true })
113
- public permissions: IPermission[] = [];
108
+ @IsOptional()
109
+ public permissions?: IPermission[];
110
+ }
111
+
112
+ export class ModuleTransferDTO<T> extends TakaroDTO<T> {
113
+ @IsString()
114
+ public name: string;
115
+ @IsString()
116
+ @IsOptional()
117
+ takaroVersion = process.env.TAKARO_VERSION;
118
+
119
+ @ValidateNested({ each: true })
120
+ @Type(() => ModuleTransferVersionDTO)
121
+ versions: ModuleTransferVersionDTO<T>[];
114
122
 
115
123
  protected loadFn(type: 'commands' | 'hooks' | 'cronJobs' | 'functions', name: string) {
116
124
  const folderPath = path.join(__dirname, 'modules', this.name, type);
@@ -1,5 +1,6 @@
1
1
  import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
2
2
  import { GameEvents } from '../dto/index.js';
3
+ import { describe } from 'node:test';
3
4
 
4
5
  const group = 'Aliases';
5
6
 
@@ -10,20 +11,18 @@ const tests = [
10
11
  setup: modulesTestSetup,
11
12
  name: 'Can install and use aliases',
12
13
  test: async function () {
13
- await this.client.gameserver.gameServerControllerInstallModule(
14
- this.setupData.gameserver.id,
15
- this.setupData.teleportsModule.id,
16
- {
17
- systemConfig: JSON.stringify({
18
- commands: {
19
- teleport: {
20
- delay: 0,
21
- aliases: ['tp', 'tellyport'],
22
- },
14
+ await this.client.module.moduleInstallationsControllerInstallModule({
15
+ gameServerId: this.setupData.gameserver.id,
16
+ versionId: this.setupData.teleportsModule.latestVersion.id,
17
+ systemConfig: JSON.stringify({
18
+ commands: {
19
+ teleport: {
20
+ delay: 0,
21
+ aliases: ['tp', 'tellyport'],
23
22
  },
24
- }),
25
- },
26
- );
23
+ },
24
+ }),
25
+ });
27
26
 
28
27
  const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
29
28
  await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
@@ -50,20 +49,18 @@ const tests = [
50
49
  setup: modulesTestSetup,
51
50
  name: 'Aliases are case insensitive',
52
51
  test: async function () {
53
- await this.client.gameserver.gameServerControllerInstallModule(
54
- this.setupData.gameserver.id,
55
- this.setupData.teleportsModule.id,
56
- {
57
- systemConfig: JSON.stringify({
58
- commands: {
59
- teleport: {
60
- delay: 0,
61
- aliases: ['tp', 'tellyport'],
62
- },
52
+ await this.client.module.moduleInstallationsControllerInstallModule({
53
+ gameServerId: this.setupData.gameserver.id,
54
+ versionId: this.setupData.teleportsModule.latestVersion.id,
55
+ systemConfig: JSON.stringify({
56
+ commands: {
57
+ teleport: {
58
+ delay: 0,
59
+ aliases: ['tp', 'tellyport'],
63
60
  },
64
- }),
65
- },
66
- );
61
+ },
62
+ }),
63
+ });
67
64
 
68
65
  const setEvents = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
69
66
  await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
@@ -1,6 +1,8 @@
1
1
  import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
2
2
  import { GameEvents, HookEvents } from '../dto/index.js';
3
3
  import { EventChatMessageChannelEnum } from '@takaro/apiclient';
4
+ import { randomUUID } from 'crypto';
5
+ import { describe } from 'node:test';
4
6
 
5
7
  const group = 'Bug repros';
6
8
 
@@ -30,7 +32,7 @@ const tests = [
30
32
  // Add the buggy hooks
31
33
  await this.client.hook.hookControllerCreate({
32
34
  name: 'Test hook 1',
33
- moduleId: mod.id,
35
+ versionId: mod.latestVersion.id,
34
36
  regex: 'test msg',
35
37
  eventType: 'chat-message',
36
38
  function: genFn('First'),
@@ -38,13 +40,16 @@ const tests = [
38
40
 
39
41
  await this.client.hook.hookControllerCreate({
40
42
  name: 'Test hook 2',
41
- moduleId: mod.id,
43
+ versionId: mod.latestVersion.id,
42
44
  regex: 'test msg',
43
45
  eventType: 'chat-message',
44
46
  function: genFn('Second'),
45
47
  });
46
48
 
47
- await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id);
49
+ await this.client.module.moduleInstallationsControllerInstallModule({
50
+ gameServerId: this.setupData.gameserver.id,
51
+ versionId: mod.latestVersion.id,
52
+ });
48
53
 
49
54
  const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
50
55
 
@@ -79,7 +84,7 @@ const tests = [
79
84
  ).data.data;
80
85
  await this.client.hook.hookControllerCreate({
81
86
  name: 'Test hook 1',
82
- moduleId: mod.id,
87
+ versionId: mod.latestVersion.id,
83
88
  regex: 'test msg',
84
89
  eventType: 'chat-message',
85
90
  function: `import { data, takaro } from '@takaro/helpers';
@@ -91,7 +96,10 @@ const tests = [
91
96
  await main();`,
92
97
  });
93
98
 
94
- await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id);
99
+ await this.client.module.moduleInstallationsControllerInstallModule({
100
+ gameServerId: this.setupData.gameserver.id,
101
+ versionId: mod.latestVersion.id,
102
+ });
95
103
 
96
104
  const listener = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.HOOK_EXECUTED, 1);
97
105
 
@@ -113,6 +121,59 @@ const tests = [
113
121
  expect(msgs).to.include.members(['foo', JSON.stringify({ foo: 'bar' }), JSON.stringify(['baz', 1])]);
114
122
  },
115
123
  }),
124
+ /**
125
+ * Repro for `console.log`ging `undefined`
126
+ */
127
+ new IntegrationTest<IModuleTestsSetupData>({
128
+ group,
129
+ snapshot: false,
130
+ name: 'Bug repro: console.log in a function works with undefined and null objects',
131
+ setup: modulesTestSetup,
132
+ test: async function () {
133
+ const mod = (
134
+ await this.client.module.moduleControllerCreate({
135
+ name: 'Test module',
136
+ })
137
+ ).data.data;
138
+ await this.client.hook.hookControllerCreate({
139
+ name: 'Test hook 1',
140
+ versionId: mod.latestVersion.id,
141
+ regex: 'test msg',
142
+ eventType: 'chat-message',
143
+ function: `import { data, takaro } from '@takaro/helpers';
144
+ async function main() {
145
+ console.log(undefined);
146
+ console.log(null);
147
+ }
148
+ await main();`,
149
+ });
150
+
151
+ await this.client.module.moduleInstallationsControllerInstallModule({
152
+ gameServerId: this.setupData.gameserver.id,
153
+ versionId: mod.latestVersion.id,
154
+ });
155
+
156
+ const listener = (await new EventsAwaiter().connect(this.client)).waitForEvents(HookEvents.HOOK_EXECUTED, 1);
157
+
158
+ await this.client.hook.hookControllerTrigger({
159
+ eventType: 'chat-message',
160
+ gameServerId: this.setupData.gameserver.id,
161
+ moduleId: mod.id,
162
+ playerId: this.setupData.players[0].id,
163
+ eventMeta: {
164
+ msg: 'test msg',
165
+ channel: EventChatMessageChannelEnum.Global,
166
+ },
167
+ });
168
+
169
+ const result = (await listener)[0].data.meta.result;
170
+ expect(result.success).to.be.true;
171
+ const logs = result.logs;
172
+ const msgs = logs.map((l: any) => l.msg);
173
+ expect(msgs[0]).to.be.eq('undefined');
174
+ expect(msgs[1]).to.be.eq('null');
175
+ },
176
+ }),
116
177
  /**
117
178
  * Repro for https://github.com/gettakaro/takaro/issues/1047
118
179
  * System config uses the names of functions to create structure
@@ -131,7 +192,7 @@ const tests = [
131
192
  ).data.data;
132
193
  const createdCommand = await this.client.command.commandControllerCreate({
133
194
  name: 'testcmd',
134
- moduleId: mod.id,
195
+ versionId: mod.latestVersion.id,
135
196
  trigger: 'testpong',
136
197
  function: `import { data, takaro } from '@takaro/helpers';
137
198
  async function main() {
@@ -143,7 +204,9 @@ const tests = [
143
204
  await main();`,
144
205
  });
145
206
 
146
- await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id, {
207
+ await this.client.module.moduleInstallationsControllerInstallModule({
208
+ gameServerId: this.setupData.gameserver.id,
209
+ versionId: mod.latestVersion.id,
147
210
  userConfig: JSON.stringify({}),
148
211
  systemConfig: JSON.stringify({ commands: { testcmd: { aliases: ['foobar'] } } }),
149
212
  });
@@ -190,7 +253,7 @@ const tests = [
190
253
  ).data.data;
191
254
  await this.client.command.commandControllerCreate({
192
255
  name: 'testcmd',
193
- moduleId: mod.id,
256
+ versionId: mod.latestVersion.id,
194
257
  trigger: 'test',
195
258
  // Yes, very bad code! This is what a user might accidentally do
196
259
  function: `import { data, takaro } from '@takaro/helpers';
@@ -207,7 +270,9 @@ const tests = [
207
270
  `,
208
271
  });
209
272
 
210
- await this.client.gameserver.gameServerControllerInstallModule(this.setupData.gameserver.id, mod.id, {
273
+ await this.client.module.moduleInstallationsControllerInstallModule({
274
+ gameServerId: this.setupData.gameserver.id,
275
+ versionId: mod.latestVersion.id,
211
276
  userConfig: JSON.stringify({}),
212
277
  systemConfig: JSON.stringify({}),
213
278
  });
@@ -219,12 +284,198 @@ const tests = [
219
284
  playerId: this.setupData.players[0].id,
220
285
  });
221
286
 
222
- console.log(JSON.stringify((await events)[0].data.meta.result, null, 2));
223
287
  const result = (await events)[0].data.meta.result;
224
288
  expect(result.success).to.be.false;
225
289
  expect(result.reason).to.include('SyntaxError: Unexpected end of input.');
226
290
  },
227
291
  }),
292
+ /**
293
+ * Create a module with a version and command that returns a 'hello world' message and tag it
294
+ * Install the module and trigger the command
295
+ * Then, edit the command so it returns a 'goodbye world' message and tag the module again
296
+ * Trigger the command again and check if the message is 'goodbye world' *
297
+ */
298
+ new IntegrationTest<IModuleTestsSetupData>({
299
+ group,
300
+ snapshot: false,
301
+ name: 'Bug repro: command code not updated after tag change',
302
+ setup: modulesTestSetup,
303
+ test: async function () {
304
+ const mod = (
305
+ await this.client.module.moduleControllerCreate({
306
+ name: 'Test module',
307
+ })
308
+ ).data.data;
309
+ const createdCommand = await this.client.command.commandControllerCreate({
310
+ name: 'testcmd',
311
+ versionId: mod.latestVersion.id,
312
+ trigger: 'test',
313
+ function: `import { data, takaro } from '@takaro/helpers';
314
+ async function main() {
315
+ const { player } = data;
316
+ await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {
317
+ message: 'hello world',
318
+ });
319
+ }
320
+ await main();`,
321
+ });
322
+
323
+ const tagRes1 = await this.client.module.moduleVersionControllerTagVersion({
324
+ moduleId: mod.id,
325
+ tag: '0.0.1',
326
+ });
327
+
328
+ await this.client.module.moduleInstallationsControllerInstallModule({
329
+ gameServerId: this.setupData.gameserver.id,
330
+ versionId: tagRes1.data.data.id,
331
+ userConfig: JSON.stringify({}),
332
+ systemConfig: JSON.stringify({}),
333
+ });
334
+
335
+ const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
336
+
337
+ await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
338
+ msg: '/test',
339
+ playerId: this.setupData.players[0].id,
340
+ });
341
+
342
+ expect((await events).length).to.be.eq(1);
343
+ expect((await events)[0].data.meta.msg).to.be.eq('hello world');
344
+
345
+ // Update the command
346
+ await this.client.command.commandControllerUpdate(createdCommand.data.data.id, {
347
+ function: `import { data, takaro } from '@takaro/helpers';
348
+ async function main() {
349
+ const { player } = data;
350
+ await takaro.gameserver.gameServerControllerSendMessage(data.gameServerId, {
351
+ message: 'goodbye world',
352
+ });
353
+ }
354
+ await main();`,
355
+ });
356
+
357
+ const tagRes2 = await this.client.module.moduleVersionControllerTagVersion({
358
+ moduleId: mod.id,
359
+ tag: '0.0.2',
360
+ });
361
+
362
+ await this.client.module.moduleInstallationsControllerInstallModule({
363
+ gameServerId: this.setupData.gameserver.id,
364
+ versionId: tagRes2.data.data.id,
365
+ userConfig: JSON.stringify({}),
366
+ systemConfig: JSON.stringify({}),
367
+ });
368
+
369
+ const eventsAfter = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
370
+
371
+ await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
372
+ msg: '/test',
373
+ playerId: this.setupData.players[0].id,
374
+ });
375
+
376
+ expect((await eventsAfter).length).to.be.eq(1);
377
+ expect((await eventsAfter)[0].data.meta.msg).to.be.eq('goodbye world');
378
+ },
379
+ }),
380
+ new IntegrationTest<IModuleTestsSetupData>({
381
+ group,
382
+ snapshot: false,
383
+ name: 'Bug repro: permissions from old module versions cleanly transfer when upgrading',
384
+ setup: modulesTestSetup,
385
+ /**
386
+ * Scenario:
387
+ * Module with PermA, v0.0.1 is installed
388
+ * User then tags v0.0.2 and installs this
389
+ * Players with permA can still use the module function that requires that permission
390
+ */
391
+ test: async function () {
392
+ const permission = 'USE_TEST_PERMISSION';
393
+ const module = (
394
+ await this.client.module.moduleControllerCreate({
395
+ name: randomUUID(),
396
+ latestVersion: {
397
+ permissions: [{ permission, canHaveCount: false, friendlyName: 'test', description: 'blabla test' }],
398
+ },
399
+ })
400
+ ).data.data;
401
+
402
+ await this.client.command.commandControllerCreate({
403
+ name: 'test',
404
+ versionId: module.latestVersion.id,
405
+ trigger: 'test',
406
+ function: `import { data, takaro, checkPermission } from '@takaro/helpers';
407
+ async function main() {
408
+ const { player, pog } = data;
409
+
410
+ if (!checkPermission(pog, '${permission}')) {
411
+ await takaro.gameserver.gameServerControllerSendMessage('${this.setupData.gameserver.id}', {
412
+ message: 'no permission',
413
+ });
414
+ } else {
415
+ await takaro.gameserver.gameServerControllerSendMessage('${this.setupData.gameserver.id}', {
416
+ message: 'yes permission',
417
+ });
418
+ }
419
+
420
+ }
421
+ await main();`,
422
+ });
423
+
424
+ // Create version 0.0.1
425
+ const v1 = (
426
+ await this.client.module.moduleVersionControllerTagVersion({
427
+ moduleId: module.id,
428
+ tag: '0.0.1',
429
+ })
430
+ ).data.data;
431
+
432
+ // Install this version
433
+ await this.client.module.moduleInstallationsControllerInstallModule({
434
+ gameServerId: this.setupData.gameserver.id,
435
+ versionId: v1.id,
436
+ });
437
+
438
+ // Create a role with the permission
439
+ const permissionCode = await this.client.permissionCodesToInputs([permission]);
440
+ const role = (await this.client.role.roleControllerCreate({ name: 'testing role', permissions: permissionCode }))
441
+ .data.data;
442
+
443
+ // Assign the role to a player
444
+ await this.client.player.playerControllerAssignRole(this.setupData.players[0].id, role.id);
445
+
446
+ // Firing the command should return 'yes permission'
447
+ const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
448
+ await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
449
+ msg: '/test',
450
+ playerId: this.setupData.players[0].id,
451
+ });
452
+
453
+ expect((await events)[0].data.meta.msg).to.be.eq('yes permission');
454
+
455
+ // Tag a new version
456
+ const v2 = (
457
+ await this.client.module.moduleVersionControllerTagVersion({
458
+ moduleId: module.id,
459
+ tag: '0.0.2',
460
+ })
461
+ ).data.data;
462
+
463
+ // Install this version
464
+ await this.client.module.moduleInstallationsControllerInstallModule({
465
+ gameServerId: this.setupData.gameserver.id,
466
+ versionId: v2.id,
467
+ });
468
+
469
+ // Firing the command should return 'yes permission'
470
+ const eventsAfter = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 1);
471
+ await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
472
+ msg: '/test',
473
+ playerId: this.setupData.players[0].id,
474
+ });
475
+
476
+ expect((await eventsAfter)[0].data.meta.msg).to.be.eq('yes permission');
477
+ },
478
+ }),
228
479
  ];
229
480
 
230
481
  describe(group, function () {
@@ -1,5 +1,6 @@
1
1
  import { expect } from '@takaro/test';
2
2
  import { getModules } from '../main.js';
3
+ import { describe, it } from 'node:test';
3
4
 
4
5
  describe('BuiltInModule', () => {
5
6
  it('Can load module items', async () => {
@@ -8,6 +9,7 @@ describe('BuiltInModule', () => {
8
9
  const utilsModule = mods.find((mod) => mod.name === 'utils');
9
10
 
10
11
  expect(utilsModule).to.not.be.undefined;
11
- expect(utilsModule?.commands).to.have.length(2);
12
+ expect(utilsModule?.versions).to.have.length(1);
13
+ expect(utilsModule?.versions[0].commands).to.have.length(2);
12
14
  });
13
15
  });
@@ -1,6 +1,7 @@
1
1
  import { IntegrationTest, expect, IModuleTestsSetupData, modulesTestSetup, EventsAwaiter } from '@takaro/test';
2
2
  import { GameEvents } from '../dto/gameEvents.js';
3
3
  import { CommandArgumentCreateDTO } from '@takaro/apiclient';
4
+ import { describe } from 'node:test';
4
5
 
5
6
  const group = 'Command args';
6
7
 
@@ -14,7 +15,7 @@ const createSetup = (commandArgs: CommandArgumentCreateDTO[]) => {
14
15
  await this.client.command.commandControllerCreate({
15
16
  name: 'test',
16
17
  trigger: 'test',
17
- moduleId: moduleRes.data.data.id,
18
+ versionId: moduleRes.data.data.latestVersion.id,
18
19
  arguments: commandArgs,
19
20
  function: `import { getTakaro, getData } from '@takaro/helpers';
20
21
 
@@ -28,7 +29,10 @@ const createSetup = (commandArgs: CommandArgumentCreateDTO[]) => {
28
29
  await main();`,
29
30
  });
30
31
 
31
- await this.client.gameserver.gameServerControllerInstallModule(setupRes.gameserver.id, moduleRes.data.data.id);
32
+ await this.client.module.moduleInstallationsControllerInstallModule({
33
+ gameServerId: setupRes.gameserver.id,
34
+ versionId: moduleRes.data.data.latestVersion.id,
35
+ });
32
36
 
33
37
  return setupRes;
34
38
  };
@@ -43,7 +47,7 @@ const playerArgSetup = async function (this: IntegrationTest<IModuleTestsSetupDa
43
47
  await this.client.command.commandControllerCreate({
44
48
  name: 'test',
45
49
  trigger: 'test',
46
- moduleId: moduleRes.data.data.id,
50
+ versionId: moduleRes.data.data.latestVersion.id,
47
51
  arguments: [{ name: 'name', type: 'player', position: 0 }],
48
52
  function: `import { getTakaro, getData } from '@takaro/helpers';
49
53
 
@@ -58,7 +62,10 @@ const playerArgSetup = async function (this: IntegrationTest<IModuleTestsSetupDa
58
62
  await main();`,
59
63
  });
60
64
 
61
- await this.client.gameserver.gameServerControllerInstallModule(setupRes.gameserver.id, moduleRes.data.data.id);
65
+ await this.client.module.moduleInstallationsControllerInstallModule({
66
+ gameServerId: setupRes.gameserver.id,
67
+ versionId: moduleRes.data.data.latestVersion.id,
68
+ });
62
69
 
63
70
  return setupRes;
64
71
  };
@@ -162,8 +169,6 @@ const tests = [
162
169
  snapshot: false,
163
170
  setup: playerArgSetup,
164
171
  test: async function () {
165
- const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
166
-
167
172
  const pogRes = await this.client.playerOnGameserver.playerOnGameServerControllerSearch({
168
173
  filters: {
169
174
  playerId: [this.setupData.players[0].id],
@@ -172,6 +177,8 @@ const tests = [
172
177
  });
173
178
  const pog = pogRes.data.data[0];
174
179
 
180
+ const events = (await new EventsAwaiter().connect(this.client)).waitForEvents(GameEvents.CHAT_MESSAGE, 2);
181
+
175
182
  await this.client.command.commandControllerTrigger(this.setupData.gameserver.id, {
176
183
  msg: `/test ${this.setupData.players[0].name.substring(0, 3)}`,
177
184
  playerId: this.setupData.players[0].id,
@@ -1,5 +1,6 @@
1
1
  import { EventsAwaiter, expect, IntegrationTest, IShopSetup, shopSetup } from '@takaro/test';
2
2
  import { HookEvents } from '../../dto/index.js';
3
+ import { describe } from 'node:test';
3
4
 
4
5
  const group = 'EconomyUtils:Shop:Claim';
5
6