@takaro/module-test 0.0.0-stage → 0.7.5

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 (67) hide show
  1. package/README.md +259 -2
  2. package/dist/.source-hash +1 -0
  3. package/dist/config.d.ts +49 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +54 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/currencyLedger.d.ts +13 -0
  8. package/dist/currencyLedger.d.ts.map +1 -0
  9. package/dist/currencyLedger.js +39 -0
  10. package/dist/currencyLedger.js.map +1 -0
  11. package/dist/fakeClient.d.ts +48 -0
  12. package/dist/fakeClient.d.ts.map +1 -0
  13. package/dist/fakeClient.js +335 -0
  14. package/dist/fakeClient.js.map +1 -0
  15. package/dist/fixtureQuery.d.ts +33 -0
  16. package/dist/fixtureQuery.d.ts.map +1 -0
  17. package/dist/fixtureQuery.js +120 -0
  18. package/dist/fixtureQuery.js.map +1 -0
  19. package/dist/fixtures.d.ts +49 -0
  20. package/dist/fixtures.d.ts.map +1 -0
  21. package/dist/fixtures.js +152 -0
  22. package/dist/fixtures.js.map +1 -0
  23. package/dist/installation.d.ts +23 -0
  24. package/dist/installation.d.ts.map +1 -0
  25. package/dist/installation.js +170 -0
  26. package/dist/installation.js.map +1 -0
  27. package/dist/intrinsics.d.ts +9 -0
  28. package/dist/intrinsics.d.ts.map +1 -0
  29. package/dist/intrinsics.js +33 -0
  30. package/dist/intrinsics.js.map +1 -0
  31. package/dist/loadModule.d.ts +11 -0
  32. package/dist/loadModule.d.ts.map +1 -0
  33. package/dist/loadModule.js +173 -0
  34. package/dist/loadModule.js.map +1 -0
  35. package/dist/main.d.ts +22 -0
  36. package/dist/main.d.ts.map +1 -0
  37. package/dist/main.js +12 -0
  38. package/dist/main.js.map +1 -0
  39. package/dist/moduleExport.d.ts +74 -0
  40. package/dist/moduleExport.d.ts.map +1 -0
  41. package/dist/moduleExport.js +2 -0
  42. package/dist/moduleExport.js.map +1 -0
  43. package/dist/moduleTest.d.ts +100 -0
  44. package/dist/moduleTest.d.ts.map +1 -0
  45. package/dist/moduleTest.js +195 -0
  46. package/dist/moduleTest.js.map +1 -0
  47. package/dist/query.d.ts +8 -0
  48. package/dist/query.d.ts.map +1 -0
  49. package/dist/query.js +51 -0
  50. package/dist/query.js.map +1 -0
  51. package/dist/stubbedClient.d.ts +20 -0
  52. package/dist/stubbedClient.d.ts.map +1 -0
  53. package/dist/stubbedClient.js +44 -0
  54. package/dist/stubbedClient.js.map +1 -0
  55. package/dist/systemConfig.d.ts +19 -0
  56. package/dist/systemConfig.d.ts.map +1 -0
  57. package/dist/systemConfig.js +199 -0
  58. package/dist/systemConfig.js.map +1 -0
  59. package/dist/triggers.d.ts +53 -0
  60. package/dist/triggers.d.ts.map +1 -0
  61. package/dist/triggers.js +116 -0
  62. package/dist/triggers.js.map +1 -0
  63. package/dist/variableStore.d.ts +51 -0
  64. package/dist/variableStore.d.ts.map +1 -0
  65. package/dist/variableStore.js +201 -0
  66. package/dist/variableStore.js.map +1 -0
  67. package/package.json +42 -3
@@ -0,0 +1,152 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ const EPOCH = '2024-01-01T00:00:00.000Z';
3
+ /** @internal Exported for tests only. */
4
+ export function createPlayerFixture(options, resolveModule) {
5
+ const playerId = options.playerId ?? randomUUID();
6
+ const gameId = options.gameId ?? randomUUID();
7
+ const name = options.name ?? 'Test player';
8
+ const roles = buildRoles(playerId, options.gameServerId, options.permissions ?? 'ROOT', resolveModule);
9
+ const position = options.position ?? { x: 1, y: 2, z: 3, dimension: 'overworld' };
10
+ const pog = {
11
+ id: randomUUID(),
12
+ playerId,
13
+ gameServerId: options.gameServerId,
14
+ gameId,
15
+ roles,
16
+ currency: options.currency ?? 0,
17
+ online: options.online ?? true,
18
+ inventory: [],
19
+ lastSeen: EPOCH,
20
+ playtimeSeconds: 0,
21
+ positionX: position.x,
22
+ positionY: position.y,
23
+ positionZ: position.z,
24
+ dimension: position.dimension ?? 'overworld',
25
+ ...(options.ping === undefined ? {} : { ping: options.ping }),
26
+ ...(options.ip === undefined ? {} : { ip: options.ip }),
27
+ createdAt: EPOCH,
28
+ updatedAt: EPOCH,
29
+ };
30
+ // `roleAssignments`, not `roles`: the two DTOs spell the same thing differently, and it is the
31
+ // POG's `roles` that `checkPermission` walks.
32
+ const player = {
33
+ id: playerId,
34
+ name,
35
+ roleAssignments: roles,
36
+ ...(options.steamId === undefined ? {} : { steamId: options.steamId }),
37
+ ...(options.epicOnlineServicesId === undefined ? {} : { epicOnlineServicesId: options.epicOnlineServicesId }),
38
+ ...(options.xboxLiveId === undefined ? {} : { xboxLiveId: options.xboxLiveId }),
39
+ ...(options.platformId === undefined ? {} : { platformId: options.platformId }),
40
+ playtimeSeconds: 0,
41
+ ipHistory: [],
42
+ nameHistory: [],
43
+ createdAt: EPOCH,
44
+ updatedAt: EPOCH,
45
+ };
46
+ return { player, pog };
47
+ }
48
+ // Absent by default: an unlinked player is the real default, so a module's "must link your
49
+ // account" branch stays reachable. Only `id` is load-bearing today.
50
+ /** @internal Exported for tests only. */
51
+ export function createUserFixture(player, options = {}) {
52
+ const id = options.userId ?? randomUUID();
53
+ return {
54
+ id,
55
+ // Never empty: `UserService.extend` always pushes the system `User` role; `roles: []` is a
56
+ // shape production cannot produce.
57
+ roles: buildUserRoles(id),
58
+ name: `${player.name} (user)`,
59
+ email: `${id}@module-test.invalid`,
60
+ idpId: id,
61
+ lastSeen: EPOCH,
62
+ playerId: player.id,
63
+ player,
64
+ isDashboardUser: false,
65
+ isSupportAccount: false,
66
+ // A module's caller is always a real, player-linked human — never the Service Account behind
67
+ // a Domain Key, which has no player and cannot run a command.
68
+ isServiceAccount: false,
69
+ createdAt: EPOCH,
70
+ updatedAt: EPOCH,
71
+ };
72
+ }
73
+ // The system `User` role every user carries, matching `UserService.extend`. Holds no permissions:
74
+ // the command gate walks `pog.roles`, not this, so only the shape matters.
75
+ function buildUserRoles(userId) {
76
+ const roleId = randomUUID();
77
+ return [
78
+ {
79
+ // `id`/`createdAt`/`updatedAt` are noise `UserService.extend` never sets, but the generated
80
+ // DTO declares them required.
81
+ id: randomUUID(),
82
+ userId,
83
+ roleId,
84
+ createdAt: EPOCH,
85
+ updatedAt: EPOCH,
86
+ role: {
87
+ id: roleId,
88
+ name: 'User',
89
+ system: true,
90
+ createdAt: EPOCH,
91
+ updatedAt: EPOCH,
92
+ permissions: [],
93
+ },
94
+ },
95
+ ];
96
+ }
97
+ // One Role matching the shape `checkPermission` walks (`pog.roles[].role.permissions[].permission`),
98
+ // with the count on the assignment record. ROOT is a system permission, so it carries no `module`.
99
+ function buildRoles(playerId, gameServerId, fixture, resolveModule) {
100
+ const moduleOf = (entry) => {
101
+ if (entry.permission === 'ROOT') {
102
+ return {};
103
+ }
104
+ if (!resolveModule) {
105
+ if (entry.module) {
106
+ throw new Error(`Fixture grant '${entry.permission}' names module '${entry.module}' but no resolver was given`);
107
+ }
108
+ return {};
109
+ }
110
+ return { module: resolveModule(entry.module) };
111
+ };
112
+ const permissions = fixture === 'ROOT' ? [{ permission: 'ROOT' }] : fixture;
113
+ const roleId = randomUUID();
114
+ return [
115
+ {
116
+ id: randomUUID(),
117
+ playerId,
118
+ roleId,
119
+ gameServerId,
120
+ createdAt: EPOCH,
121
+ updatedAt: EPOCH,
122
+ role: {
123
+ id: roleId,
124
+ name: 'Test role',
125
+ system: false,
126
+ createdAt: EPOCH,
127
+ updatedAt: EPOCH,
128
+ permissions: permissions.map((entry) => {
129
+ const permissionId = randomUUID();
130
+ return {
131
+ id: randomUUID(),
132
+ permissionId,
133
+ count: entry.count ?? 0,
134
+ createdAt: EPOCH,
135
+ updatedAt: EPOCH,
136
+ permission: {
137
+ id: permissionId,
138
+ permission: entry.permission,
139
+ friendlyName: entry.permission,
140
+ description: entry.permission,
141
+ canHaveCount: entry.count !== undefined,
142
+ ...moduleOf(entry),
143
+ createdAt: EPOCH,
144
+ updatedAt: EPOCH,
145
+ },
146
+ };
147
+ }),
148
+ },
149
+ },
150
+ ];
151
+ }
152
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../src/fixtures.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ModuleInstallationOutputDTO } from '@takaro/apiclient';
2
+ import type { ModuleExport, ModuleExportVersion, ModuleSource } from './moduleExport.js';
3
+ import type { SystemConfig, SystemConfigOverrides } from './config.js';
4
+ /** The newest version of a module, which is what `latestVersion` resolves to in production. */
5
+ export declare function latestVersionOf<M extends ModuleExport>(mod: M): M['versions'][number];
6
+ export interface InstallationOptions {
7
+ gameServerId: string;
8
+ userConfig?: Record<string, unknown>;
9
+ systemConfig?: SystemConfigOverrides;
10
+ versionTag?: string;
11
+ }
12
+ export interface ModuleInstallation {
13
+ installation: ModuleInstallationOutputDTO;
14
+ /** The `{ name, code }` pairs `executeLocal` derives from `module.version.functions`. */
15
+ userModules: Array<{
16
+ name: string;
17
+ code: string;
18
+ }>;
19
+ transferVersion: ModuleExportVersion;
20
+ }
21
+ export declare function installModule(source: ModuleSource, options: InstallationOptions): ModuleInstallation;
22
+ export declare function systemConfigOf(installation: ModuleInstallationOutputDTO): SystemConfig;
23
+ //# sourceMappingURL=installation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installation.d.ts","sourceRoot":"","sources":["../src/installation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAMV,2BAA2B,EAK5B,MAAM,mBAAmB,CAAC;AAE3B,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGzF,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAIvE,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,CAAC,SAAS,YAAY,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAMrF;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,2BAA2B,CAAC;IAC1C,yFAAyF;IACzF,WAAW,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,eAAe,EAAE,mBAAmB,CAAC;CACtC;AA2BD,wBAAgB,aAAa,CAAC,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,GAAG,kBAAkB,CAsCpG;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,2BAA2B,GAAG,YAAY,CAEtF"}
@@ -0,0 +1,170 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { loadModuleDirectory } from './loadModule.js';
3
+ import { getSystemConfigSchema } from './systemConfig.js';
4
+ import { resolveSystemConfig, resolveUserConfig } from './config.js';
5
+ const EPOCH = '2024-01-01T00:00:00.000Z';
6
+ /** The newest version of a module, which is what `latestVersion` resolves to in production. */
7
+ export function latestVersionOf(mod) {
8
+ const version = mod.versions.at(-1);
9
+ if (!version) {
10
+ throw new Error(`Module '${mod.name}' declares no versions`);
11
+ }
12
+ return version;
13
+ }
14
+ function resolveModuleSource(source) {
15
+ const mod = typeof source === 'string' || source instanceof URL ? loadModuleDirectory(source) : source;
16
+ if (typeof mod.name !== 'string' || mod.name === '') {
17
+ throw new Error('A module needs a non-empty string `name`');
18
+ }
19
+ if (!Array.isArray(mod.versions) || mod.versions.length === 0) {
20
+ throw new Error(`Module '${mod.name}' needs a non-empty \`versions\` array`);
21
+ }
22
+ return mod;
23
+ }
24
+ function selectVersion(mod, versionTag) {
25
+ if (!versionTag) {
26
+ return latestVersionOf(mod);
27
+ }
28
+ const found = mod.versions.find((candidate) => candidate.tag === versionTag);
29
+ if (!found) {
30
+ const tags = mod.versions.map((candidate) => candidate.tag).join(', ');
31
+ throw new Error(`Module '${mod.name}' has no version tagged '${versionTag}'. Available: ${tags}`);
32
+ }
33
+ return found;
34
+ }
35
+ // Ids are synthetic but stable within one installation, so an assertion on `moduleId` matches
36
+ // what module code actually read.
37
+ export function installModule(source, options) {
38
+ const mod = resolveModuleSource(source);
39
+ const transferVersion = selectVersion(mod, options.versionTag);
40
+ const moduleId = randomUUID();
41
+ const versionId = randomUUID();
42
+ const version = toVersionOutput(transferVersion, moduleId, versionId);
43
+ const module = {
44
+ id: moduleId,
45
+ name: mod.name,
46
+ author: mod.author,
47
+ supportedGames: mod.supportedGames ?? [],
48
+ latestVersion: version,
49
+ createdAt: EPOCH,
50
+ updatedAt: EPOCH,
51
+ };
52
+ const installation = {
53
+ id: randomUUID(),
54
+ gameserverId: options.gameServerId,
55
+ versionId,
56
+ moduleId,
57
+ version,
58
+ module,
59
+ userConfig: resolveUserConfig(transferVersion, options.userConfig),
60
+ systemConfig: resolveSystemConfig(transferVersion, options.systemConfig),
61
+ createdAt: EPOCH,
62
+ updatedAt: EPOCH,
63
+ };
64
+ return {
65
+ installation,
66
+ userModules: version.functions
67
+ .filter((fn) => Boolean(fn.name))
68
+ .map((fn) => ({ name: fn.name, code: fn.code })),
69
+ transferVersion,
70
+ };
71
+ }
72
+ export function systemConfigOf(installation) {
73
+ return installation.systemConfig;
74
+ }
75
+ function toFunction(code, versionId, name) {
76
+ return { id: randomUUID(), code, versionId, createdAt: EPOCH, updatedAt: EPOCH, ...(name ? { name } : {}) };
77
+ }
78
+ function toVersionOutput(version, moduleId, versionId) {
79
+ const commands = (version.commands ?? []).map((command) => {
80
+ const fn = toFunction(command.function, versionId);
81
+ return {
82
+ id: randomUUID(),
83
+ name: command.name,
84
+ trigger: command.trigger,
85
+ helpText: command.helpText ?? '',
86
+ description: command.description,
87
+ function: fn,
88
+ functionId: fn.id,
89
+ versionId,
90
+ requiredPermissions: command.requiredPermissions ?? [],
91
+ arguments: (command.arguments ?? []).map((argument, index) => ({
92
+ id: randomUUID(),
93
+ name: argument.name,
94
+ type: argument.type,
95
+ helpText: argument.helpText ?? '',
96
+ position: argument.position ?? index,
97
+ createdAt: EPOCH,
98
+ updatedAt: EPOCH,
99
+ // `defaultValue` is nullable in the export format and optional in the API DTO; a null
100
+ // default means "required", which is not the same as "defaults to the string 'null'".
101
+ ...(argument.defaultValue !== null && argument.defaultValue !== undefined
102
+ ? { defaultValue: argument.defaultValue }
103
+ : {}),
104
+ })),
105
+ createdAt: EPOCH,
106
+ updatedAt: EPOCH,
107
+ };
108
+ });
109
+ const hooks = (version.hooks ?? []).map((hook) => ({
110
+ id: randomUUID(),
111
+ name: hook.name,
112
+ description: hook.description,
113
+ regex: hook.regex ?? '',
114
+ eventType: hook.eventType,
115
+ function: toFunction(hook.function, versionId),
116
+ versionId,
117
+ createdAt: EPOCH,
118
+ updatedAt: EPOCH,
119
+ }));
120
+ const cronJobs = (version.cronJobs ?? []).map((cronJob) => ({
121
+ id: randomUUID(),
122
+ name: cronJob.name,
123
+ description: cronJob.description,
124
+ temporalValue: cronJob.temporalValue,
125
+ function: toFunction(cronJob.function, versionId),
126
+ versionId,
127
+ createdAt: EPOCH,
128
+ updatedAt: EPOCH,
129
+ }));
130
+ const shopActions = (version.shopActions ?? []).map((shopAction) => ({
131
+ id: randomUUID(),
132
+ name: shopAction.name,
133
+ description: shopAction.description,
134
+ function: toFunction(shopAction.function, versionId),
135
+ versionId,
136
+ createdAt: EPOCH,
137
+ updatedAt: EPOCH,
138
+ }));
139
+ const permissions = (version.permissions ?? []).map((permission) => ({
140
+ id: randomUUID(),
141
+ permission: permission.permission,
142
+ friendlyName: permission.friendlyName,
143
+ description: permission.description,
144
+ canHaveCount: permission.canHaveCount,
145
+ createdAt: EPOCH,
146
+ updatedAt: EPOCH,
147
+ }));
148
+ return {
149
+ id: versionId,
150
+ moduleId,
151
+ tag: version.tag,
152
+ description: version.description,
153
+ configSchema: version.configSchema,
154
+ uiSchema: version.uiSchema ?? '{}',
155
+ systemConfigSchema: getSystemConfigSchema(version),
156
+ defaultSystemConfig: version.defaultSystemConfig,
157
+ commands,
158
+ hooks,
159
+ cronJobs,
160
+ // Named functions are the linkable `./x.js` user-modules; commands and hooks carry their
161
+ // own code inline and are not importable.
162
+ functions: (version.functions ?? []).map((fn) => toFunction(fn.function, versionId, fn.name)),
163
+ permissions,
164
+ shopActions,
165
+ commandsWithUndeclaredPermissions: [],
166
+ createdAt: EPOCH,
167
+ updatedAt: EPOCH,
168
+ };
169
+ }
170
+ //# sourceMappingURL=installation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"installation.js","sourceRoot":"","sources":["../src/installation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface IntrinsicsOptions {
2
+ /** Freeze the VM's clock here. `Date.now()` and `new Date()` both report it. */
3
+ now?: Date;
4
+ /** What `Math.random()` returns, in order; the last value repeats once the list is exhausted. */
5
+ random?: number | number[];
6
+ }
7
+ /** @internal Exported for tests only. */
8
+ export declare function buildContextOverride(options: IntrinsicsOptions): Record<string, unknown>;
9
+ //# sourceMappingURL=intrinsics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intrinsics.d.ts","sourceRoot":"","sources":["../src/intrinsics.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,iGAAiG;IACjG,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC5B;AAED,yCAAyC;AACzC,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAgCxF"}
@@ -0,0 +1,33 @@
1
+ /** @internal Exported for tests only. */
2
+ export function buildContextOverride(options) {
3
+ const context = {};
4
+ if (options.now) {
5
+ const fixed = options.now.getTime();
6
+ context.Date = class FrozenDate extends Date {
7
+ constructor(...args) {
8
+ // Only the zero-argument form is the clock; `new Date(iso)` must keep parsing.
9
+ if (args.length === 0) {
10
+ super(fixed);
11
+ }
12
+ else {
13
+ super(...args);
14
+ }
15
+ }
16
+ static now() {
17
+ return fixed;
18
+ }
19
+ };
20
+ }
21
+ if (options.random !== undefined) {
22
+ const sequence = Array.isArray(options.random) ? options.random : [options.random];
23
+ if (sequence.length === 0) {
24
+ throw new Error('random must not be an empty sequence');
25
+ }
26
+ let index = 0;
27
+ const draw = () => sequence[Math.min(index++, sequence.length - 1)];
28
+ // A copy, not a mutation: `Math` here is the HOST's, and stubbing it would leak into later tests.
29
+ context.Math = Object.create(Math, { random: { value: draw, enumerable: true } });
30
+ }
31
+ return context;
32
+ }
33
+ //# sourceMappingURL=intrinsics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intrinsics.js","sourceRoot":"","sources":["../src/intrinsics.ts"],"names":[],"mappings":"AAQA,yCAAyC;AACzC,MAAM,UAAU,oBAAoB,CAAC,OAA0B;IAC7D,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QACpC,OAAO,CAAC,IAAI,GAAG,MAAM,UAAW,SAAQ,IAAI;YAC1C,YAAY,GAAG,IAAe;gBAC5B,+EAA+E;gBAC/E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACtB,KAAK,CAAC,KAAK,CAAC,CAAC;gBACf,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,GAAI,IAA2C,CAAC,CAAC;gBACzD,CAAC;YACH,CAAC;YACD,MAAM,CAAU,GAAG;gBACjB,OAAO,KAAK,CAAC;YACf,CAAC;SACF,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnF,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACpE,kGAAkG;QAClG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,CAAC;IACpF,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ModuleExport } from './moduleExport.js';
2
+ export declare class ModuleLoadError extends Error {
3
+ constructor(moduleJsonPath: string, problem: string);
4
+ }
5
+ /**
6
+ * Reads a module directory in the registry source layout: a `module.json` whose components point
7
+ * at JS files by relative path. Returns the single-version export Takaro would import.
8
+ * Unknown `module.json` keys are ignored.
9
+ */
10
+ export declare function loadModuleDirectory(dir: string | URL): ModuleExport;
11
+ //# sourceMappingURL=loadModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadModule.d.ts","sourceRoot":"","sources":["../src/loadModule.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EAQb,MAAM,mBAAmB,CAAC;AA2C3B,qBAAa,eAAgB,SAAQ,KAAK;IACxC,YAAY,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAGlD;CACF;AAsFD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,YAAY,CA0FnE"}
@@ -0,0 +1,173 @@
1
+ import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ const EMPTY_CONFIG_SCHEMA = '{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{},"required":[],"additionalProperties":false}';
5
+ export class ModuleLoadError extends Error {
6
+ constructor(moduleJsonPath, problem) {
7
+ super(`${moduleJsonPath}: ${problem}`);
8
+ this.name = 'ModuleLoadError';
9
+ }
10
+ }
11
+ function isPlainObject(value) {
12
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
13
+ }
14
+ function isInside(parent, candidate) {
15
+ return candidate === parent || candidate.startsWith(parent + path.sep);
16
+ }
17
+ class ModuleDirectory {
18
+ constructor(dir) {
19
+ this.root = path.resolve(dir instanceof URL ? fileURLToPath(dir) : dir);
20
+ this.moduleJsonPath = path.join(this.root, 'module.json');
21
+ }
22
+ fail(problem) {
23
+ throw new ModuleLoadError(this.moduleJsonPath, problem);
24
+ }
25
+ readModuleJson() {
26
+ if (!existsSync(this.root) || !statSync(this.root).isDirectory()) {
27
+ this.fail(`${this.root} is not a directory`);
28
+ }
29
+ if (!existsSync(this.moduleJsonPath)) {
30
+ this.fail('module.json not found');
31
+ }
32
+ let parsed;
33
+ try {
34
+ parsed = JSON.parse(readFileSync(this.moduleJsonPath, 'utf-8'));
35
+ }
36
+ catch (error) {
37
+ return this.fail(`not valid JSON: ${error.message}`);
38
+ }
39
+ if (!isPlainObject(parsed)) {
40
+ this.fail('must contain a JSON object');
41
+ }
42
+ return parsed;
43
+ }
44
+ readCode(relativePath, label) {
45
+ const absolute = path.resolve(this.root, relativePath);
46
+ if (!isInside(this.root, absolute)) {
47
+ this.fail(`path '${relativePath}' escapes the module directory (for ${label})`);
48
+ }
49
+ if (!existsSync(absolute)) {
50
+ this.fail(`file '${relativePath}' not found (for ${label}); expected at ${absolute}`);
51
+ }
52
+ const real = realpathSync(absolute);
53
+ if (!isInside(realpathSync(this.root), real)) {
54
+ this.fail(`path '${relativePath}' escapes the module directory via a symlink (for ${label})`);
55
+ }
56
+ return readFileSync(real, 'utf-8');
57
+ }
58
+ requireObjectField(mod, field) {
59
+ const value = mod[field];
60
+ if (value === undefined) {
61
+ return [];
62
+ }
63
+ if (!isPlainObject(value)) {
64
+ this.fail(`field '${field}' must be a plain object keyed by name`);
65
+ }
66
+ return Object.entries(value);
67
+ }
68
+ requireFunctionPath(def, label) {
69
+ if (!def.function) {
70
+ this.fail(`${label} is missing required field 'function' (path to a JS file)`);
71
+ }
72
+ return def.function;
73
+ }
74
+ }
75
+ function serialiseSchema(directory, value, field, fallback) {
76
+ if (value === undefined) {
77
+ return fallback;
78
+ }
79
+ if (!isPlainObject(value)) {
80
+ directory.fail(`field '${field}' must be a plain object`);
81
+ }
82
+ return Object.keys(value).length > 0 ? JSON.stringify(value) : fallback;
83
+ }
84
+ /**
85
+ * Reads a module directory in the registry source layout: a `module.json` whose components point
86
+ * at JS files by relative path. Returns the single-version export Takaro would import.
87
+ * Unknown `module.json` keys are ignored.
88
+ */
89
+ export function loadModuleDirectory(dir) {
90
+ const directory = new ModuleDirectory(dir);
91
+ const mod = directory.readModuleJson();
92
+ if (typeof mod.name !== 'string' || mod.name === '') {
93
+ directory.fail("field 'name' is required");
94
+ }
95
+ const commands = directory.requireObjectField(mod, 'commands').map(([name, def]) => {
96
+ const label = `command '${name}'`;
97
+ return {
98
+ name,
99
+ trigger: def.trigger ?? name,
100
+ description: def.description ?? undefined,
101
+ helpText: def.helpText ?? 'No help text available',
102
+ function: directory.readCode(directory.requireFunctionPath(def, label), label),
103
+ arguments: def.arguments ?? [],
104
+ ...(def.requiredPermissions ? { requiredPermissions: def.requiredPermissions } : {}),
105
+ };
106
+ });
107
+ const hooks = directory.requireObjectField(mod, 'hooks').map(([name, def]) => {
108
+ const label = `hook '${name}'`;
109
+ if (!def.eventType) {
110
+ directory.fail(`${label} is missing required field 'eventType'`);
111
+ }
112
+ return {
113
+ name,
114
+ eventType: def.eventType,
115
+ description: def.description ?? undefined,
116
+ regex: def.regex ?? undefined,
117
+ function: directory.readCode(directory.requireFunctionPath(def, label), label),
118
+ };
119
+ });
120
+ const cronJobs = directory.requireObjectField(mod, 'cronJobs').map(([name, def]) => {
121
+ const label = `cronJob '${name}'`;
122
+ if (!def.temporalValue) {
123
+ directory.fail(`${label} is missing required field 'temporalValue'`);
124
+ }
125
+ return {
126
+ name,
127
+ temporalValue: def.temporalValue,
128
+ description: def.description ?? undefined,
129
+ function: directory.readCode(directory.requireFunctionPath(def, label), label),
130
+ };
131
+ });
132
+ const functions = directory
133
+ .requireObjectField(mod, 'functions')
134
+ .map(([name, def]) => {
135
+ const label = `function '${name}'`;
136
+ return { name, function: directory.readCode(directory.requireFunctionPath(def, label), label) };
137
+ });
138
+ const shopActions = directory
139
+ .requireObjectField(mod, 'shopActions')
140
+ .map(([name, def]) => {
141
+ const label = `shopAction '${name}'`;
142
+ return {
143
+ name,
144
+ description: def.description ?? undefined,
145
+ function: directory.readCode(directory.requireFunctionPath(def, label), label),
146
+ };
147
+ });
148
+ const defaultSystemConfig = mod.defaultSystemConfig;
149
+ if (defaultSystemConfig !== undefined && !isPlainObject(defaultSystemConfig)) {
150
+ directory.fail("field 'defaultSystemConfig' must be a plain object");
151
+ }
152
+ return {
153
+ name: mod.name,
154
+ author: mod.author ?? 'Unknown',
155
+ supportedGames: mod.supportedGames ?? ['all'],
156
+ versions: [
157
+ {
158
+ tag: mod.version ?? 'latest',
159
+ description: mod.description ?? 'No description',
160
+ configSchema: serialiseSchema(directory, mod.config, 'config', EMPTY_CONFIG_SCHEMA),
161
+ uiSchema: serialiseSchema(directory, mod.uiSchema, 'uiSchema', '{}'),
162
+ ...(defaultSystemConfig ? { defaultSystemConfig: JSON.stringify(defaultSystemConfig) } : {}),
163
+ commands,
164
+ hooks,
165
+ cronJobs,
166
+ functions,
167
+ permissions: mod.permissions ?? [],
168
+ shopActions,
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ //# sourceMappingURL=loadModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadModule.js","sourceRoot":"","sources":["../src/loadModule.ts"],"names":[],"mappings":"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"}
package/dist/main.d.ts ADDED
@@ -0,0 +1,22 @@
1
+ export { createModuleTest, ModuleTest } from './moduleTest.js';
2
+ export type { IModuleTest, ModuleInstallSpec, CommandRunOptions, HookRunOptions, PlayerSpec } from './moduleTest.js';
3
+ export { createFakeClient, ok, paginated, single, MissingFixtureError, UnsupportedQueryError } from './fakeClient.js';
4
+ export { UnstubbedMethodError } from './stubbedClient.js';
5
+ export type { ClientStubs, ControllerKey } from './stubbedClient.js';
6
+ export type { FakeClient, FakeClientOptions, PageMeta, RecordedMessage } from './fakeClient.js';
7
+ export { VariableStore, VariableConflictError, VariableNotFoundError } from './variableStore.js';
8
+ export type { VariableSeed } from './variableStore.js';
9
+ export { CurrencyLedger, InsufficientFundsError } from './currencyLedger.js';
10
+ export { createPlayerFixture, createUserFixture } from './fixtures.js';
11
+ export type { PermissionFixture, PlatformIds, PlayerFixture, PlayerFixtureOptions, PlayerPermission, UserFixtureOptions, } from './fixtures.js';
12
+ export { installModule, latestVersionOf, systemConfigOf } from './installation.js';
13
+ export type { InstallationOptions, ModuleInstallation } from './installation.js';
14
+ export { loadModuleDirectory, ModuleLoadError } from './loadModule.js';
15
+ export type { ModuleExport, ModuleExportCommand, ModuleExportCommandArgument, ModuleExportCronJob, ModuleExportFunction, ModuleExportHook, ModuleExportPermission, ModuleExportShopAction, ModuleExportVersion, ModuleSource, } from './moduleExport.js';
16
+ export { InvalidSystemConfigError, InvalidUserConfigError, resolveSystemConfig, resolveUserConfig } from './config.js';
17
+ export type { SystemConfig, SystemConfigOverrides } from './config.js';
18
+ export { applyArgumentDefaults, buildCommandData, buildCronJobData, buildHookData, buildShopActionData, classifyTriggerData, matchingTriggerKinds, toJobPayload, } from './triggers.js';
19
+ export type { CommandArguments, TriggerContext, TriggerData, TriggerKind } from './triggers.js';
20
+ export { buildContextOverride } from './intrinsics.js';
21
+ export type { IntrinsicsOptions } from './intrinsics.js';
22
+ //# sourceMappingURL=main.d.ts.map