@takaro/module-test 0.0.0-dev.4dbe15b → 0.0.0-stage
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.
- package/README.md +2 -259
- package/package.json +3 -42
- package/dist/.source-hash +0 -1
- package/dist/config.d.ts +0 -49
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -54
- package/dist/config.js.map +0 -1
- package/dist/currencyLedger.d.ts +0 -13
- package/dist/currencyLedger.d.ts.map +0 -1
- package/dist/currencyLedger.js +0 -39
- package/dist/currencyLedger.js.map +0 -1
- package/dist/fakeClient.d.ts +0 -48
- package/dist/fakeClient.d.ts.map +0 -1
- package/dist/fakeClient.js +0 -335
- package/dist/fakeClient.js.map +0 -1
- package/dist/fixtureQuery.d.ts +0 -33
- package/dist/fixtureQuery.d.ts.map +0 -1
- package/dist/fixtureQuery.js +0 -120
- package/dist/fixtureQuery.js.map +0 -1
- package/dist/fixtures.d.ts +0 -49
- package/dist/fixtures.d.ts.map +0 -1
- package/dist/fixtures.js +0 -152
- package/dist/fixtures.js.map +0 -1
- package/dist/installation.d.ts +0 -23
- package/dist/installation.d.ts.map +0 -1
- package/dist/installation.js +0 -170
- package/dist/installation.js.map +0 -1
- package/dist/intrinsics.d.ts +0 -9
- package/dist/intrinsics.d.ts.map +0 -1
- package/dist/intrinsics.js +0 -33
- package/dist/intrinsics.js.map +0 -1
- package/dist/loadModule.d.ts +0 -11
- package/dist/loadModule.d.ts.map +0 -1
- package/dist/loadModule.js +0 -173
- package/dist/loadModule.js.map +0 -1
- package/dist/main.d.ts +0 -22
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js +0 -12
- package/dist/main.js.map +0 -1
- package/dist/moduleExport.d.ts +0 -74
- package/dist/moduleExport.d.ts.map +0 -1
- package/dist/moduleExport.js +0 -2
- package/dist/moduleExport.js.map +0 -1
- package/dist/moduleTest.d.ts +0 -100
- package/dist/moduleTest.d.ts.map +0 -1
- package/dist/moduleTest.js +0 -195
- package/dist/moduleTest.js.map +0 -1
- package/dist/query.d.ts +0 -8
- package/dist/query.d.ts.map +0 -1
- package/dist/query.js +0 -51
- package/dist/query.js.map +0 -1
- package/dist/stubbedClient.d.ts +0 -20
- package/dist/stubbedClient.d.ts.map +0 -1
- package/dist/stubbedClient.js +0 -44
- package/dist/stubbedClient.js.map +0 -1
- package/dist/systemConfig.d.ts +0 -19
- package/dist/systemConfig.d.ts.map +0 -1
- package/dist/systemConfig.js +0 -199
- package/dist/systemConfig.js.map +0 -1
- package/dist/triggers.d.ts +0 -53
- package/dist/triggers.d.ts.map +0 -1
- package/dist/triggers.js +0 -116
- package/dist/triggers.js.map +0 -1
- package/dist/variableStore.d.ts +0 -51
- package/dist/variableStore.d.ts.map +0 -1
- package/dist/variableStore.js +0 -201
- package/dist/variableStore.js.map +0 -1
package/dist/systemConfig.js
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { HookOutputDTOEventTypeEnum } from '@takaro/apiclient';
|
|
2
|
-
const ONE_DAY_SECONDS = 86_400;
|
|
3
|
-
const SEVEN_DAYS_SECONDS = 604_800;
|
|
4
|
-
function getEmptyConfigSchema() {
|
|
5
|
-
return {
|
|
6
|
-
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
7
|
-
type: 'object',
|
|
8
|
-
properties: {},
|
|
9
|
-
required: [],
|
|
10
|
-
additionalProperties: false,
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
const COOLDOWN_TYPE_DESCRIPTION = `When a cooldown time is set, this determines the scope of the cooldown.
|
|
14
|
-
If set to 'player', the target player will have to wait before triggering the hook again.
|
|
15
|
-
If set to 'server', the cooldown will apply to all players on the server.
|
|
16
|
-
If set to 'global', the cooldown will apply to the entire domain.
|
|
17
|
-
|
|
18
|
-
Note that if you select 'player' but the hook fires for an event that has no player attached (e.g. a server goes on/offline), the cooldown will be treated as a server cooldown instead.`;
|
|
19
|
-
// A copy of `getSystemConfigSchema` in the private `@takaro/modules`; its lib-modules
|
|
20
|
-
// `systemConfigParity` test pins the two together.
|
|
21
|
-
// oxlint-disable-next-line sonarjs/cognitive-complexity -- GH #4103
|
|
22
|
-
export function getSystemConfigSchema(mod) {
|
|
23
|
-
const systemConfigSchema = getEmptyConfigSchema();
|
|
24
|
-
systemConfigSchema.properties.enabled = {
|
|
25
|
-
type: 'boolean',
|
|
26
|
-
default: true,
|
|
27
|
-
description: 'Enable/disable the module without having to uninstall it.',
|
|
28
|
-
};
|
|
29
|
-
const cronJobs = mod.cronJobs ?? [];
|
|
30
|
-
const hooks = mod.hooks ?? [];
|
|
31
|
-
const commands = mod.commands ?? [];
|
|
32
|
-
const shopActions = mod.shopActions ?? [];
|
|
33
|
-
if (cronJobs.length) {
|
|
34
|
-
systemConfigSchema.properties.cronJobs = {
|
|
35
|
-
type: 'object',
|
|
36
|
-
properties: {},
|
|
37
|
-
required: [],
|
|
38
|
-
default: {},
|
|
39
|
-
};
|
|
40
|
-
systemConfigSchema.required.push('cronJobs');
|
|
41
|
-
for (const cronJob of cronJobs) {
|
|
42
|
-
systemConfigSchema.properties.cronJobs.properties[cronJob.name] = {
|
|
43
|
-
type: 'object',
|
|
44
|
-
required: [],
|
|
45
|
-
default: {},
|
|
46
|
-
properties: {
|
|
47
|
-
enabled: {
|
|
48
|
-
type: 'boolean',
|
|
49
|
-
default: true,
|
|
50
|
-
description: `Enable the ${cronJob.name} cron job.`,
|
|
51
|
-
},
|
|
52
|
-
temporalValue: {
|
|
53
|
-
type: 'string',
|
|
54
|
-
description: 'Temporal value for the cron job. Controls when it runs',
|
|
55
|
-
default: cronJob.temporalValue,
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (hooks.length) {
|
|
62
|
-
systemConfigSchema.properties.hooks = {
|
|
63
|
-
type: 'object',
|
|
64
|
-
properties: {},
|
|
65
|
-
required: [],
|
|
66
|
-
default: {},
|
|
67
|
-
};
|
|
68
|
-
for (const hook of hooks) {
|
|
69
|
-
systemConfigSchema.properties.hooks.properties[hook.name] = {
|
|
70
|
-
type: 'object',
|
|
71
|
-
properties: {
|
|
72
|
-
enabled: {
|
|
73
|
-
type: 'boolean',
|
|
74
|
-
default: true,
|
|
75
|
-
description: `Enable the ${hook.name} hook.`,
|
|
76
|
-
},
|
|
77
|
-
delay: {
|
|
78
|
-
type: 'number',
|
|
79
|
-
default: 0,
|
|
80
|
-
minimum: 0,
|
|
81
|
-
maximum: ONE_DAY_SECONDS,
|
|
82
|
-
description: 'How many seconds to wait before executing the hook.',
|
|
83
|
-
},
|
|
84
|
-
cooldown: {
|
|
85
|
-
type: 'number',
|
|
86
|
-
default: 0,
|
|
87
|
-
minimum: 0,
|
|
88
|
-
maximum: ONE_DAY_SECONDS,
|
|
89
|
-
description: 'How many seconds before this hook can be triggered again.',
|
|
90
|
-
},
|
|
91
|
-
cooldownType: {
|
|
92
|
-
type: 'string',
|
|
93
|
-
enum: ['player', 'server', 'global'],
|
|
94
|
-
default: 'player',
|
|
95
|
-
description: COOLDOWN_TYPE_DESCRIPTION,
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
required: [],
|
|
99
|
-
default: {},
|
|
100
|
-
};
|
|
101
|
-
if (hook.eventType === HookOutputDTOEventTypeEnum.DiscordMessage) {
|
|
102
|
-
if (!systemConfigSchema.required.includes('hooks')) {
|
|
103
|
-
systemConfigSchema.required.push('hooks');
|
|
104
|
-
}
|
|
105
|
-
systemConfigSchema.properties.hooks.properties[hook.name].required.push('discordChannelId');
|
|
106
|
-
systemConfigSchema.properties.hooks.properties[hook.name].properties.discordChannelId = {
|
|
107
|
-
type: 'string',
|
|
108
|
-
description: 'Discord channel ID where Takaro will listen for messages.',
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
if (shopActions.length) {
|
|
114
|
-
systemConfigSchema.properties.shopActions = {
|
|
115
|
-
type: 'object',
|
|
116
|
-
properties: {},
|
|
117
|
-
required: [],
|
|
118
|
-
default: {},
|
|
119
|
-
};
|
|
120
|
-
for (const shopAction of shopActions) {
|
|
121
|
-
systemConfigSchema.properties.shopActions.properties[shopAction.name] = {
|
|
122
|
-
type: 'object',
|
|
123
|
-
required: [],
|
|
124
|
-
default: {},
|
|
125
|
-
properties: {
|
|
126
|
-
enabled: {
|
|
127
|
-
type: 'boolean',
|
|
128
|
-
default: true,
|
|
129
|
-
description: `Enable the ${shopAction.name} shop action.`,
|
|
130
|
-
},
|
|
131
|
-
triggerOn: {
|
|
132
|
-
type: 'string',
|
|
133
|
-
enum: ['orderCreated', 'orderClaimed', 'both'],
|
|
134
|
-
default: 'orderClaimed',
|
|
135
|
-
description: 'When to execute: orderCreated (payment deducted), orderClaimed (items delivered), both.',
|
|
136
|
-
},
|
|
137
|
-
},
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
if (commands.length) {
|
|
142
|
-
systemConfigSchema.properties.commands = {
|
|
143
|
-
type: 'object',
|
|
144
|
-
properties: {},
|
|
145
|
-
required: [],
|
|
146
|
-
default: {},
|
|
147
|
-
};
|
|
148
|
-
systemConfigSchema.required.push('commands');
|
|
149
|
-
for (const command of commands) {
|
|
150
|
-
const configKey = command.name;
|
|
151
|
-
systemConfigSchema.properties.commands.properties[configKey] = {
|
|
152
|
-
type: 'object',
|
|
153
|
-
properties: {
|
|
154
|
-
enabled: {
|
|
155
|
-
type: 'boolean',
|
|
156
|
-
default: true,
|
|
157
|
-
description: `Enable the ${configKey} command.`,
|
|
158
|
-
},
|
|
159
|
-
delay: {
|
|
160
|
-
type: 'number',
|
|
161
|
-
default: 0,
|
|
162
|
-
minimum: 0,
|
|
163
|
-
maximum: ONE_DAY_SECONDS,
|
|
164
|
-
description: 'How many seconds to wait before executing the command.',
|
|
165
|
-
},
|
|
166
|
-
announceDelay: {
|
|
167
|
-
type: 'boolean',
|
|
168
|
-
default: true,
|
|
169
|
-
description: 'Whether to announce the delay to the user.',
|
|
170
|
-
},
|
|
171
|
-
cooldown: {
|
|
172
|
-
type: 'number',
|
|
173
|
-
default: 0,
|
|
174
|
-
minimum: 0,
|
|
175
|
-
maximum: SEVEN_DAYS_SECONDS,
|
|
176
|
-
description: 'How many seconds a player has to wait before executing the command again.',
|
|
177
|
-
},
|
|
178
|
-
cost: {
|
|
179
|
-
type: 'number',
|
|
180
|
-
default: 0,
|
|
181
|
-
minimum: 0,
|
|
182
|
-
description: 'How much currency to deduct from the player before executing the command.',
|
|
183
|
-
},
|
|
184
|
-
aliases: {
|
|
185
|
-
type: 'array',
|
|
186
|
-
items: {
|
|
187
|
-
type: 'string',
|
|
188
|
-
},
|
|
189
|
-
description: 'Trigger the command with other names than the default',
|
|
190
|
-
},
|
|
191
|
-
},
|
|
192
|
-
required: [],
|
|
193
|
-
default: {},
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return JSON.stringify(systemConfigSchema);
|
|
198
|
-
}
|
|
199
|
-
//# sourceMappingURL=systemConfig.js.map
|
package/dist/systemConfig.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"systemConfig.js","sourceRoot":"","sources":["../src/systemConfig.ts"],"names":[],"mappings":"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"}
|
package/dist/triggers.d.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import type { CommandOutputDTO, ModuleInstallationOutputDTO, PlayerOnGameserverOutputWithRolesDTO, PlayerOutputWithRolesDTO, UserOutputWithRolesDTO } from '@takaro/apiclient';
|
|
2
|
-
import { HookOutputDTOEventTypeEnum } from '@takaro/apiclient';
|
|
3
|
-
export type CommandArguments = Record<string, string | number | boolean | PlayerOnGameserverOutputWithRolesDTO>;
|
|
4
|
-
export type TriggerKind = 'command' | 'hook' | 'cronjob' | 'shopAction';
|
|
5
|
-
export interface TriggerContext {
|
|
6
|
-
domainId: string;
|
|
7
|
-
gameServerId: string;
|
|
8
|
-
installation: ModuleInstallationOutputDTO;
|
|
9
|
-
player: PlayerOutputWithRolesDTO;
|
|
10
|
-
pog: PlayerOnGameserverOutputWithRolesDTO;
|
|
11
|
-
/** The linked Takaro user, when the test declared one. Absent for an unlinked player. */
|
|
12
|
-
user?: UserOutputWithRolesDTO;
|
|
13
|
-
}
|
|
14
|
-
/** The shape `executeVM` is handed — `IJobData` plus the two fields the executors add. */
|
|
15
|
-
export type TriggerData = Record<string, unknown>;
|
|
16
|
-
/** @internal Exported for tests only. */
|
|
17
|
-
export declare function matchingTriggerKinds(data: TriggerData): TriggerKind[];
|
|
18
|
-
/**
|
|
19
|
-
* The single kind a payload classifies as. Throws when the payload is ambiguous.
|
|
20
|
-
* @internal Exported for tests only.
|
|
21
|
-
*/
|
|
22
|
-
export declare function classifyTriggerData(data: TriggerData): TriggerKind;
|
|
23
|
-
/** @internal Exported for tests only. */
|
|
24
|
-
export declare function applyArgumentDefaults(command: CommandOutputDTO, provided?: CommandArguments): CommandArguments;
|
|
25
|
-
/** @internal Exported for tests only. */
|
|
26
|
-
export declare function toJobPayload(data: TriggerData): TriggerData;
|
|
27
|
-
export interface CommandTriggerOptions {
|
|
28
|
-
command: CommandOutputDTO;
|
|
29
|
-
arguments?: CommandArguments;
|
|
30
|
-
/** The raw chat line, when a test wants module code to see it. Defaults to `/<trigger>`. */
|
|
31
|
-
chatMessage?: string;
|
|
32
|
-
}
|
|
33
|
-
/** @internal Exported for tests only. */
|
|
34
|
-
export declare function buildCommandData(context: TriggerContext, options: CommandTriggerOptions): TriggerData;
|
|
35
|
-
export interface HookTriggerOptions {
|
|
36
|
-
eventType: HookOutputDTOEventTypeEnum;
|
|
37
|
-
eventData: Record<string, unknown>;
|
|
38
|
-
/** Hooks fire for server-level events too, where there is no player. */
|
|
39
|
-
withPlayer?: boolean;
|
|
40
|
-
}
|
|
41
|
-
/** @internal Exported for tests only. */
|
|
42
|
-
export declare function buildHookData(context: TriggerContext, options: HookTriggerOptions): TriggerData;
|
|
43
|
-
/** @internal Exported for tests only. */
|
|
44
|
-
export declare function buildCronJobData(context: TriggerContext): TriggerData;
|
|
45
|
-
export interface ShopActionTriggerOptions {
|
|
46
|
-
orderId?: string;
|
|
47
|
-
listingId?: string;
|
|
48
|
-
triggerEvent: 'orderCreated' | 'orderClaimed';
|
|
49
|
-
withPlayer?: boolean;
|
|
50
|
-
}
|
|
51
|
-
/** @internal Exported for tests only. */
|
|
52
|
-
export declare function buildShopActionData(context: TriggerContext, options: ShopActionTriggerOptions): TriggerData;
|
|
53
|
-
//# sourceMappingURL=triggers.d.ts.map
|
package/dist/triggers.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"triggers.d.ts","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,2BAA2B,EAC3B,oCAAoC,EACpC,wBAAwB,EACxB,sBAAsB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAE/D,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,oCAAoC,CAAC,CAAC;AAEhH,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;AAExE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,2BAA2B,CAAC;IAC1C,MAAM,EAAE,wBAAwB,CAAC;IACjC,GAAG,EAAE,oCAAoC,CAAC;IAC1C,yFAAyF;IACzF,IAAI,CAAC,EAAE,sBAAsB,CAAC;CAC/B;AAED,0FAA0F;AAC1F,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAYlD,yCAAyC;AACzC,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,EAAE,CAKrE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CASlE;AA4BD,yCAAyC;AACzC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,gBAAgB,EAAE,QAAQ,GAAE,gBAAqB,GAAG,gBAAgB,CAYlH;AAID,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAE3D;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,yCAAyC;AACzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,qBAAqB,GAAG,WAAW,CAqBrG;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,0BAA0B,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,wEAAwE;IACxE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,yCAAyC;AACzC,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,kBAAkB,GAAG,WAAW,CAU/F;AAED,yCAAyC;AACzC,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAGrE;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,cAAc,GAAG,cAAc,CAAC;IAC9C,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,yCAAyC;AACzC,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,wBAAwB,GAAG,WAAW,CAY3G"}
|
package/dist/triggers.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { HookOutputDTOEventTypeEnum } from '@takaro/apiclient';
|
|
3
|
-
// A copy of Takaro's job-payload classifiers; lib-modules' `triggers.unit.test.ts` pins it
|
|
4
|
-
// against the original.
|
|
5
|
-
const TRIGGER_PREDICATES = [
|
|
6
|
-
{ kind: 'command', matches: (data) => 'arguments' in data },
|
|
7
|
-
{ kind: 'hook', matches: (data) => 'eventData' in data },
|
|
8
|
-
{ kind: 'shopAction', matches: (data) => 'orderId' in data && 'triggerEvent' in data },
|
|
9
|
-
];
|
|
10
|
-
// Every kind whose predicate the payload satisfies, since Takaro evaluates them
|
|
11
|
-
// independently — a malformed shop action would otherwise become a cron job in silence.
|
|
12
|
-
/** @internal Exported for tests only. */
|
|
13
|
-
export function matchingTriggerKinds(data) {
|
|
14
|
-
const matched = TRIGGER_PREDICATES.filter((predicate) => predicate.matches(data)).map((predicate) => predicate.kind);
|
|
15
|
-
return matched.length > 0 ? matched : ['cronjob'];
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* The single kind a payload classifies as. Throws when the payload is ambiguous.
|
|
19
|
-
* @internal Exported for tests only.
|
|
20
|
-
*/
|
|
21
|
-
export function classifyTriggerData(data) {
|
|
22
|
-
const kinds = matchingTriggerKinds(data);
|
|
23
|
-
if (kinds.length > 1) {
|
|
24
|
-
throw new Error(`Payload matches more than one trigger kind (${kinds.join(', ')}); Takaro would run ` +
|
|
25
|
-
'both branches. See matchingTriggerKinds.');
|
|
26
|
-
}
|
|
27
|
-
return kinds[0];
|
|
28
|
-
}
|
|
29
|
-
function assertKind(data, expected) {
|
|
30
|
-
const kinds = matchingTriggerKinds(data);
|
|
31
|
-
if (kinds.length !== 1 || kinds[0] !== expected) {
|
|
32
|
-
throw new Error(`Built a ${expected} payload that Takaro would classify as ${kinds.join(' and ')}. ` +
|
|
33
|
-
'See matchingTriggerKinds.');
|
|
34
|
-
}
|
|
35
|
-
return data;
|
|
36
|
-
}
|
|
37
|
-
function baseData(context) {
|
|
38
|
-
return {
|
|
39
|
-
domainId: context.domainId,
|
|
40
|
-
functionId: randomUUID(),
|
|
41
|
-
itemId: randomUUID(),
|
|
42
|
-
gameServerId: context.gameServerId,
|
|
43
|
-
module: context.installation,
|
|
44
|
-
// Read by `getTakaro` when it builds a real Client. A module test always overrides the
|
|
45
|
-
// client, so these are only present because the production path reads them.
|
|
46
|
-
url: 'http://module-test.invalid',
|
|
47
|
-
token: 'module-test-token',
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
// Only fills `defaultValue`; tokenising the chat line is Takaro's command parser's job, not modelled here.
|
|
51
|
-
/** @internal Exported for tests only. */
|
|
52
|
-
export function applyArgumentDefaults(command, provided = {}) {
|
|
53
|
-
const args = { ...provided };
|
|
54
|
-
for (const argument of command.arguments) {
|
|
55
|
-
if (argument.name in args) {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (argument.defaultValue === undefined) {
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
args[argument.name] = argument.defaultValue;
|
|
62
|
-
}
|
|
63
|
-
return args;
|
|
64
|
-
}
|
|
65
|
-
// The JSON round-trip BullMQ actually performs: a deep copy (stale `pog.currency`, must refetch),
|
|
66
|
-
// `Date` arrives as a string, and `undefined`-valued properties vanish.
|
|
67
|
-
/** @internal Exported for tests only. */
|
|
68
|
-
export function toJobPayload(data) {
|
|
69
|
-
return JSON.parse(JSON.stringify(data));
|
|
70
|
-
}
|
|
71
|
-
/** @internal Exported for tests only. */
|
|
72
|
-
export function buildCommandData(context, options) {
|
|
73
|
-
const msg = options.chatMessage ?? `/${options.command.trigger}`;
|
|
74
|
-
return assertKind({
|
|
75
|
-
...baseData(context),
|
|
76
|
-
player: context.player,
|
|
77
|
-
pog: context.pog,
|
|
78
|
-
// Unlinked player: `toJobPayload`'s round-trip drops the `undefined` `user` key, matching
|
|
79
|
-
// what `claim.js` tests for.
|
|
80
|
-
...(context.user ? { user: context.user } : {}),
|
|
81
|
-
arguments: applyArgumentDefaults(options.command, options.arguments),
|
|
82
|
-
trigger: options.command.trigger,
|
|
83
|
-
chatMessage: {
|
|
84
|
-
type: HookOutputDTOEventTypeEnum.ChatMessage,
|
|
85
|
-
timestamp: new Date().toISOString(),
|
|
86
|
-
msg,
|
|
87
|
-
channel: 'global',
|
|
88
|
-
},
|
|
89
|
-
}, 'command');
|
|
90
|
-
}
|
|
91
|
-
/** @internal Exported for tests only. */
|
|
92
|
-
export function buildHookData(context, options) {
|
|
93
|
-
const withPlayer = options.withPlayer ?? true;
|
|
94
|
-
return assertKind({
|
|
95
|
-
...baseData(context),
|
|
96
|
-
eventData: { type: options.eventType, timestamp: new Date().toISOString(), ...options.eventData },
|
|
97
|
-
...(withPlayer ? { player: context.player, pog: context.pog } : {}),
|
|
98
|
-
}, 'hook');
|
|
99
|
-
}
|
|
100
|
-
/** @internal Exported for tests only. */
|
|
101
|
-
export function buildCronJobData(context) {
|
|
102
|
-
// No player, no arguments, no order: a cron payload is defined by what it does NOT carry.
|
|
103
|
-
return assertKind(baseData(context), 'cronjob');
|
|
104
|
-
}
|
|
105
|
-
/** @internal Exported for tests only. */
|
|
106
|
-
export function buildShopActionData(context, options) {
|
|
107
|
-
const withPlayer = options.withPlayer ?? true;
|
|
108
|
-
return assertKind({
|
|
109
|
-
...baseData(context),
|
|
110
|
-
orderId: options.orderId ?? randomUUID(),
|
|
111
|
-
listingId: options.listingId ?? randomUUID(),
|
|
112
|
-
triggerEvent: options.triggerEvent,
|
|
113
|
-
...(withPlayer ? { player: context.player, pog: context.pog } : {}),
|
|
114
|
-
}, 'shopAction');
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=triggers.js.map
|
package/dist/triggers.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"triggers.js","sourceRoot":"","sources":["../src/triggers.ts"],"names":[],"mappings":"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"}
|
package/dist/variableStore.d.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import type { VariableCreateDTO, VariableOutputDTO, VariableSearchInputDTO, VariableUpdateDTO } from '@takaro/apiclient';
|
|
2
|
-
/** Message axios produces for a 409, which module code string-matches. */
|
|
3
|
-
export declare const CONFLICT_MESSAGE = "Request failed with status code 409";
|
|
4
|
-
export declare class VariableConflictError extends Error {
|
|
5
|
-
readonly status = 409;
|
|
6
|
-
constructor();
|
|
7
|
-
}
|
|
8
|
-
export declare class VariableNotFoundError extends Error {
|
|
9
|
-
readonly status = 404;
|
|
10
|
-
constructor(id: string);
|
|
11
|
-
}
|
|
12
|
-
export interface VariableSeed {
|
|
13
|
-
key: string;
|
|
14
|
-
value: string;
|
|
15
|
-
expiresAt?: string;
|
|
16
|
-
gameServerId?: string;
|
|
17
|
-
playerId?: string;
|
|
18
|
-
moduleId?: string;
|
|
19
|
-
}
|
|
20
|
-
export declare class VariableStore {
|
|
21
|
-
private rows;
|
|
22
|
-
constructor(seeds?: VariableSeed[]);
|
|
23
|
-
/** Every row, unfiltered and unpaginated — for assertions, not for module code. */
|
|
24
|
-
get all(): VariableOutputDTO[];
|
|
25
|
-
/**
|
|
26
|
-
* Insert without the create-path checks. Seeding a fixture is not the operation under test.
|
|
27
|
-
*/
|
|
28
|
-
insert(seed: VariableSeed): VariableOutputDTO;
|
|
29
|
-
create(input: VariableCreateDTO, now?: Date): VariableOutputDTO;
|
|
30
|
-
update(id: string, input: VariableUpdateDTO, now?: Date): VariableOutputDTO;
|
|
31
|
-
delete(id: string, now?: Date): void;
|
|
32
|
-
findOne(id: string, now?: Date): VariableOutputDTO;
|
|
33
|
-
/** @returns the page of results, total BEFORE pagination (matches `PaginatedOutput`), page, limit. */
|
|
34
|
-
search(query?: VariableSearchInputDTO, now?: Date): {
|
|
35
|
-
results: VariableOutputDTO[];
|
|
36
|
-
total: number;
|
|
37
|
-
page: number;
|
|
38
|
-
limit: number;
|
|
39
|
-
};
|
|
40
|
-
/** Only the scope columns the source actually sets — an omitted column leaves the row's own. */
|
|
41
|
-
private scopeOf;
|
|
42
|
-
private requireColumn;
|
|
43
|
-
private column;
|
|
44
|
-
private isExpired;
|
|
45
|
-
/**
|
|
46
|
-
* `NULLS NOT DISTINCT`: two rows collide when every scope column is equal, and two NULLs count
|
|
47
|
-
* as equal. `undefined` and an absent property are both the API's way of saying NULL.
|
|
48
|
-
*/
|
|
49
|
-
private sameScope;
|
|
50
|
-
}
|
|
51
|
-
//# sourceMappingURL=variableStore.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"variableStore.d.ts","sourceRoot":"","sources":["../src/variableStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,iBAAiB,EAClB,MAAM,mBAAmB,CAAC;AAU3B,0EAA0E;AAC1E,eAAO,MAAM,gBAAgB,wCAAwC,CAAC;AAItE,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,OAAO;IACtB,cAGC;CACF;AAED,qBAAa,qBAAsB,SAAQ,KAAK;IAC9C,QAAQ,CAAC,MAAM,OAAO;IACtB,YAAY,EAAE,EAAE,MAAM,EAGrB;CACF;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAA2B;IAEvC,YAAY,KAAK,GAAE,YAAY,EAAO,EAIrC;IAED,mFAAmF;IACnF,IAAI,GAAG,IAAI,iBAAiB,EAAE,CAE7B;IAED;;OAEG;IACH,MAAM,CAAC,IAAI,EAAE,YAAY,GAAG,iBAAiB,CAe5C;IAED,MAAM,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,GAAE,IAAiB,GAAG,iBAAiB,CAU1E;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,GAAG,GAAE,IAAiB,GAAG,iBAAiB,CA4BtF;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,IAAI,CAG/C;IAED,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,iBAAiB,CAM7D;IAED,sGAAsG;IACtG,MAAM,CACJ,KAAK,GAAE,sBAA2B,EAClC,GAAG,GAAE,IAAiB,GACrB;QAAE,OAAO,EAAE,iBAAiB,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAiE9E;IAED,gGAAgG;IAChG,OAAO,CAAC,OAAO;IAaf,OAAO,CAAC,aAAa;IAMrB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,SAAS;IAIjB;;;OAGG;IACH,OAAO,CAAC,SAAS;CAMlB"}
|
package/dist/variableStore.js
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { compareForSort, nonArrayFilter, toDisplayString, unimplementedKey, UnsupportedQueryError } from './query.js';
|
|
3
|
-
// The unique constraint's scope columns: `UNIQUE NULLS NOT DISTINCT (key, domain, "gameServerId",
|
|
4
|
-
// "playerId", "moduleId")` (`20230713184927-variables-modulescoped.ts`); domain is implicit.
|
|
5
|
-
const SCOPE_COLUMNS = ['gameServerId', 'playerId', 'moduleId'];
|
|
6
|
-
/** Every column of the variables table, and therefore everything a query may name. */
|
|
7
|
-
const VARIABLE_COLUMNS = ['id', 'key', 'value', 'expiresAt', 'createdAt', 'updatedAt', ...SCOPE_COLUMNS];
|
|
8
|
-
/** Message axios produces for a 409, which module code string-matches. */
|
|
9
|
-
export const CONFLICT_MESSAGE = 'Request failed with status code 409';
|
|
10
|
-
// `teleports/commands/setwaypoint.js` branches on the literal axios message string, not a status
|
|
11
|
-
// field, so `CONFLICT_MESSAGE` is the contract module code depends on.
|
|
12
|
-
export class VariableConflictError extends Error {
|
|
13
|
-
constructor() {
|
|
14
|
-
super(CONFLICT_MESSAGE);
|
|
15
|
-
this.status = 409;
|
|
16
|
-
this.name = 'VariableConflictError';
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
export class VariableNotFoundError extends Error {
|
|
20
|
-
constructor(id) {
|
|
21
|
-
super(`Request failed with status code 404 (variable ${id})`);
|
|
22
|
-
this.status = 404;
|
|
23
|
-
this.name = 'VariableNotFoundError';
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
// An in-memory `variables` table with `QueryBuilder`'s actual semantics: an empty filter array
|
|
27
|
-
// means NO filter (`teleports/functions/utils.js` relies on this to find public teleports).
|
|
28
|
-
export class VariableStore {
|
|
29
|
-
constructor(seeds = []) {
|
|
30
|
-
this.rows = [];
|
|
31
|
-
for (const seed of seeds) {
|
|
32
|
-
this.insert(seed);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
/** Every row, unfiltered and unpaginated — for assertions, not for module code. */
|
|
36
|
-
get all() {
|
|
37
|
-
return [...this.rows];
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Insert without the create-path checks. Seeding a fixture is not the operation under test.
|
|
41
|
-
*/
|
|
42
|
-
insert(seed) {
|
|
43
|
-
const now = new Date().toISOString();
|
|
44
|
-
const row = {
|
|
45
|
-
id: randomUUID(),
|
|
46
|
-
key: seed.key,
|
|
47
|
-
value: seed.value,
|
|
48
|
-
createdAt: now,
|
|
49
|
-
updatedAt: now,
|
|
50
|
-
...(seed.expiresAt === undefined ? {} : { expiresAt: seed.expiresAt }),
|
|
51
|
-
...(seed.gameServerId === undefined ? {} : { gameServerId: seed.gameServerId }),
|
|
52
|
-
...(seed.playerId === undefined ? {} : { playerId: seed.playerId }),
|
|
53
|
-
...(seed.moduleId === undefined ? {} : { moduleId: seed.moduleId }),
|
|
54
|
-
};
|
|
55
|
-
this.rows.push(row);
|
|
56
|
-
return row;
|
|
57
|
-
}
|
|
58
|
-
create(input, now = new Date()) {
|
|
59
|
-
// Expired-but-uncleaned rows are deleted before the constraint is considered, exactly as
|
|
60
|
-
// `VariableRepo.create` does — otherwise a TTL that has passed still blocks the new value.
|
|
61
|
-
this.rows = this.rows.filter((row) => !(this.sameScope(row, input) && this.isExpired(row, now)));
|
|
62
|
-
if (this.rows.some((row) => this.sameScope(row, input))) {
|
|
63
|
-
throw new VariableConflictError();
|
|
64
|
-
}
|
|
65
|
-
return this.insert(input);
|
|
66
|
-
}
|
|
67
|
-
update(id, input, now = new Date()) {
|
|
68
|
-
const row = this.findOne(id, now);
|
|
69
|
-
// The unique index applies to an UPDATE too, since `setpublic`/`setprivate` rename keys.
|
|
70
|
-
const scope = this.scopeOf(input);
|
|
71
|
-
const moved = { key: input.key ?? row.key, ...this.scopeOf(row), ...scope };
|
|
72
|
-
// Expired candidates still count: `VariableRepo.update` (unlike `create`) never deletes them
|
|
73
|
-
// first, and the Postgres unique index keeps counting a row until the TTL cleanup job runs.
|
|
74
|
-
const collision = this.rows.some((candidate) => candidate.id !== id && this.sameScope(candidate, moved));
|
|
75
|
-
if (collision) {
|
|
76
|
-
throw new VariableConflictError();
|
|
77
|
-
}
|
|
78
|
-
// `VariableRepo.update` writes `data.toJSON()`, which drops `undefined` properties, so an
|
|
79
|
-
// undefined scope field leaves the row's own value rather than blanking it.
|
|
80
|
-
const { expiresAt, ...rest } = input;
|
|
81
|
-
for (const [column, value] of Object.entries(rest)) {
|
|
82
|
-
// oxlint-disable-next-line typescript/no-unnecessary-condition -- VariableUpdateDTO (apiclient-generated, app-api-owned) declares every field required, but this is a partial update payload where a field can genuinely arrive undefined
|
|
83
|
-
if (value !== undefined) {
|
|
84
|
-
row[column] = value;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
if (expiresAt) {
|
|
88
|
-
row.expiresAt = expiresAt;
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
delete row.expiresAt;
|
|
92
|
-
}
|
|
93
|
-
row.updatedAt = now.toISOString();
|
|
94
|
-
return row;
|
|
95
|
-
}
|
|
96
|
-
delete(id, now = new Date()) {
|
|
97
|
-
this.findOne(id, now);
|
|
98
|
-
this.rows = this.rows.filter((row) => row.id !== id);
|
|
99
|
-
}
|
|
100
|
-
findOne(id, now = new Date()) {
|
|
101
|
-
const row = this.rows.find((candidate) => candidate.id === id && !this.isExpired(candidate, now));
|
|
102
|
-
if (!row) {
|
|
103
|
-
throw new VariableNotFoundError(id);
|
|
104
|
-
}
|
|
105
|
-
return row;
|
|
106
|
-
}
|
|
107
|
-
/** @returns the page of results, total BEFORE pagination (matches `PaginatedOutput`), page, limit. */
|
|
108
|
-
search(query = {}, now = new Date()) {
|
|
109
|
-
let matched = this.rows.filter((row) => !this.isExpired(row, now));
|
|
110
|
-
for (const [column, values] of Object.entries(query.filters ?? {})) {
|
|
111
|
-
if (values === null || values === undefined) {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
this.requireColumn('variableControllerSearch', 'filter', column);
|
|
115
|
-
// A bare boolean is the one non-array value `QueryBuilder` honours; kept in sync with the
|
|
116
|
-
// fake client's collections even though no variables column is boolean today.
|
|
117
|
-
if (typeof values === 'boolean') {
|
|
118
|
-
matched = matched.filter((row) => this.column(row, column) === values);
|
|
119
|
-
continue;
|
|
120
|
-
}
|
|
121
|
-
if (!Array.isArray(values)) {
|
|
122
|
-
throw new UnsupportedQueryError('variableControllerSearch', nonArrayFilter(column, values));
|
|
123
|
-
}
|
|
124
|
-
if (values.length === 0) {
|
|
125
|
-
continue;
|
|
126
|
-
}
|
|
127
|
-
// The literal string 'null' means `whereNull` — the only way to ask for a domain-global
|
|
128
|
-
// variable, which `highPingKicker`'s warning counter is.
|
|
129
|
-
if (values.includes('null')) {
|
|
130
|
-
matched = matched.filter((row) => {
|
|
131
|
-
const value = this.column(row, column);
|
|
132
|
-
return value === null || value === undefined;
|
|
133
|
-
});
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
const wanted = values.filter((value) => value !== null && value !== undefined);
|
|
137
|
-
matched = matched.filter((row) => wanted.includes(this.column(row, column)));
|
|
138
|
-
}
|
|
139
|
-
// Search is a single OR group across every key and every value — partial, case-insensitive,
|
|
140
|
-
// `ilike '%value%'`.
|
|
141
|
-
const searchTerms = Object.entries(query.search ?? {}).flatMap(([column, values]) => {
|
|
142
|
-
if (values === null || values === undefined) {
|
|
143
|
-
return [];
|
|
144
|
-
}
|
|
145
|
-
this.requireColumn('variableControllerSearch', 'search', column);
|
|
146
|
-
if (!Array.isArray(values)) {
|
|
147
|
-
throw new UnsupportedQueryError('variableControllerSearch', nonArrayFilter(column, values));
|
|
148
|
-
}
|
|
149
|
-
return values.filter(Boolean).map((value) => ({ column, value: String(value) }));
|
|
150
|
-
});
|
|
151
|
-
if (searchTerms.length > 0) {
|
|
152
|
-
matched = matched.filter((row) => searchTerms.some(({ column, value }) => toDisplayString(this.column(row, column) ?? '')
|
|
153
|
-
.toLowerCase()
|
|
154
|
-
.includes(value.toLowerCase())));
|
|
155
|
-
}
|
|
156
|
-
const sortBy = query.sortBy ?? 'id';
|
|
157
|
-
this.requireColumn('variableControllerSearch', 'sortBy', sortBy);
|
|
158
|
-
const direction = query.sortDirection === 'desc' ? -1 : 1;
|
|
159
|
-
matched.sort((a, b) => compareForSort(this.column(a, sortBy), this.column(b, sortBy), direction));
|
|
160
|
-
const total = matched.length;
|
|
161
|
-
// 100, matching Takaro's default page size, not "everything".
|
|
162
|
-
const limit = query.limit ?? 100;
|
|
163
|
-
const page = query.page ?? 0;
|
|
164
|
-
return { results: matched.slice(page * limit, page * limit + limit), total, page, limit };
|
|
165
|
-
}
|
|
166
|
-
/** Only the scope columns the source actually sets — an omitted column leaves the row's own. */
|
|
167
|
-
scopeOf(source) {
|
|
168
|
-
const scope = {};
|
|
169
|
-
for (const column of SCOPE_COLUMNS) {
|
|
170
|
-
const value = source[column];
|
|
171
|
-
if (value !== undefined) {
|
|
172
|
-
scope[column] = value;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return scope;
|
|
176
|
-
}
|
|
177
|
-
// Deliberately louder than production: `cleanQueryObject` silently drops an unknown-column
|
|
178
|
-
// filter (returning everything), which would hide the bug rather than test around it.
|
|
179
|
-
requireColumn(method, kind, name) {
|
|
180
|
-
if (!VARIABLE_COLUMNS.includes(name)) {
|
|
181
|
-
throw new UnsupportedQueryError(method, unimplementedKey(kind, name, VARIABLE_COLUMNS));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
column(row, name) {
|
|
185
|
-
return row[name];
|
|
186
|
-
}
|
|
187
|
-
isExpired(row, now) {
|
|
188
|
-
return row.expiresAt !== undefined && new Date(row.expiresAt).getTime() < now.getTime();
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* `NULLS NOT DISTINCT`: two rows collide when every scope column is equal, and two NULLs count
|
|
192
|
-
* as equal. `undefined` and an absent property are both the API's way of saying NULL.
|
|
193
|
-
*/
|
|
194
|
-
sameScope(row, input) {
|
|
195
|
-
if (row.key !== input.key) {
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
return SCOPE_COLUMNS.every((column) => (row[column] ?? null) === (input[column] ?? null));
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
//# sourceMappingURL=variableStore.js.map
|