meocord 4.2.1 → 4.2.3
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/CHANGELOG.md +188 -0
- package/dist/cjs/_shared/{controller.decorator-XKMlcUZz.cjs → controller.decorator-hp5xdJU4.cjs} +550 -189
- package/dist/cjs/_shared/{startup-roots-CgfPQrNl.cjs → event-sources-DzqTODXg.cjs} +274 -88
- package/dist/cjs/_shared/{providers-BZgJyfZS.cjs → providers-BBvbnmLP.cjs} +837 -295
- package/dist/cjs/_shared/{sharded-cooldown-store-CsJJyCZd.cjs → sharded-cooldown-store-B62g5O88.cjs} +11 -9
- package/dist/cjs/_shared/{translate-error-BUAR1WYG.cjs → translate-error-wsgfsUET.cjs} +1 -1
- package/dist/cjs/common/index.cjs +4 -104
- package/dist/cjs/core/index.cjs +435 -182
- package/dist/cjs/decorator/index.cjs +116 -121
- package/dist/cjs/testing/index.cjs +1923 -808
- package/dist/cli.json +1 -1
- package/dist/esm/bin/app-template/package.json.template +9 -9
- package/dist/esm/bin/app-template/src/main.ts.template +3 -2
- package/dist/esm/bin/generator.js +6 -4
- package/dist/esm/bin/helper/filter-generator.helper.js +6 -4
- package/dist/esm/bin/helper/guard-generator.helper.js +6 -4
- package/dist/esm/bin/helper/interceptor-generator.helper.js +6 -4
- package/dist/esm/bin/helper/observer-generator.helper.js +6 -4
- package/dist/esm/bin/helper/pipe-generator.helper.js +6 -4
- package/dist/esm/bin/helper/service-generator.helper.js +6 -4
- package/dist/esm/bin/meocord.js +106 -48
- package/dist/esm/build/native-addons.js +75 -19
- package/dist/esm/build/rsbuild-config.js +11 -3
- package/dist/esm/build/typed-externals.js +15 -2
- package/dist/esm/common/cooldown-store.js +38 -14
- package/dist/esm/common/deprecation.js +4 -1
- package/dist/esm/common/execution-context.js +3 -1
- package/dist/esm/common/explained-error.js +7 -3
- package/dist/esm/common/log-level.js +13 -9
- package/dist/esm/common/logger.js +4 -2
- package/dist/esm/common/meocord-text.js +11 -6
- package/dist/esm/common/redis-cooldown-store.js +3 -7
- package/dist/esm/common/response/flags.js +17 -1
- package/dist/esm/common/response/install-context.js +27 -16
- package/dist/esm/common/response/presenter.js +7 -3
- package/dist/esm/common/response/response-state.js +32 -10
- package/dist/esm/common/sharded-cooldown-store.js +11 -9
- package/dist/esm/common/theme.js +3 -1
- package/dist/esm/common/translator.js +27 -8
- package/dist/esm/core/autocomplete-routes.js +26 -0
- package/dist/esm/core/command-conflicts.js +15 -7
- package/dist/esm/core/command-registration.js +15 -1
- package/dist/esm/core/cooldown-runner.js +7 -9
- package/dist/esm/core/defer.js +2 -5
- package/dist/esm/core/dispatcher.js +92 -66
- package/dist/esm/core/event-requirements.js +67 -19
- package/dist/esm/core/event-sources.js +100 -0
- package/dist/esm/core/fallback.js +3 -1
- package/dist/esm/core/filter-runner.js +6 -6
- package/dist/esm/core/guard-runner.js +173 -52
- package/dist/esm/core/handler-input.js +24 -3
- package/dist/esm/core/handler-pipeline.js +54 -32
- package/dist/esm/core/handler-registry.js +51 -21
- package/dist/esm/core/input-runner.js +7 -8
- package/dist/esm/core/interceptor-runner.js +4 -5
- package/dist/esm/core/lifecycle-hooks.js +3 -8
- package/dist/esm/core/lifecycle-order.js +1 -15
- package/dist/esm/core/meocord-classes.js +14 -1
- package/dist/esm/core/meocord-factory.js +83 -54
- package/dist/esm/core/meocord.app.js +174 -89
- package/dist/esm/core/message-help.js +37 -15
- package/dist/esm/core/message-params.js +126 -46
- package/dist/esm/core/message-routes.js +225 -45
- package/dist/esm/core/message-words.js +30 -2
- package/dist/esm/core/observer-runner.js +4 -2
- package/dist/esm/core/process-state.js +19 -0
- package/dist/esm/core/providers.js +39 -4
- package/dist/esm/core/scalar-types.js +57 -16
- package/dist/esm/core/shard-context.js +11 -10
- package/dist/esm/core/shard-exit.js +3 -3
- package/dist/esm/core/shard-manager.js +16 -6
- package/dist/esm/core/stage-scope.js +2 -1
- package/dist/esm/core/startup-roots.js +28 -8
- package/dist/esm/core/theme-resolvers.js +26 -11
- package/dist/esm/core/theme-runtime.js +23 -13
- package/dist/esm/core/theme-scope.js +31 -30
- package/dist/esm/core/theme-validation.js +1 -1
- package/dist/esm/decorator/app.decorator.js +37 -1
- package/dist/esm/decorator/command-builder.decorator.js +14 -0
- package/dist/esm/decorator/controller-class.decorator.js +1 -1
- package/dist/esm/decorator/controller.decorator.js +48 -19
- package/dist/esm/decorator/defer.decorator.js +2 -2
- package/dist/esm/decorator/event.decorator.js +4 -5
- package/dist/esm/decorator/filter.decorator.js +4 -4
- package/dist/esm/decorator/guard.decorator.js +4 -61
- package/dist/esm/decorator/inject.decorator.js +4 -1
- package/dist/esm/decorator/interceptor.decorator.js +2 -2
- package/dist/esm/decorator/theme.decorator.js +4 -3
- package/dist/esm/decorator/validation.decorator.js +5 -5
- package/dist/esm/package.json.js +1 -1
- package/dist/esm/testing/catalog.js +32 -25
- package/dist/esm/testing/cooldown-store-suite.js +3 -3
- package/dist/esm/testing/discord-defaults.js +449 -335
- package/dist/esm/testing/inspect-handler.js +91 -10
- package/dist/esm/testing/meocord-testing-module.js +217 -91
- package/dist/esm/testing/mock-fn.js +8 -2
- package/dist/esm/testing/mock-interaction.js +864 -124
- package/dist/esm/testing/response-log.js +8 -0
- package/dist/esm/testing/response.js +7 -5
- package/dist/esm/testing/routing.js +48 -6
- package/dist/esm/testing/strict-mocks.js +8 -4
- package/dist/esm/testing/theme.js +3 -2
- package/dist/esm/util/common.util.js +30 -9
- package/dist/esm/util/generator-cli.util.js +6 -4
- package/dist/esm/util/inherited-env.util.js +72 -13
- package/dist/esm/util/json.util.js +10 -3
- package/dist/esm/util/meocord-cli.util.js +3 -2
- package/dist/esm/util/meocord-config-loader.util.js +14 -1
- package/dist/esm/util/meocord-config-validation.util.js +13 -3
- package/dist/esm/util/meocord-source-config.util.js +13 -3
- package/dist/esm/util/platform.util.js +3 -2
- package/dist/esm/util/refusal.util.js +29 -11
- package/dist/esm/util/registration-mode.util.js +14 -1
- package/dist/esm/util/timer-limit.util.js +4 -1
- package/dist/esm/util/tsconfig-paths.util.js +38 -7
- package/dist/esm/util/tsconfig.util.js +16 -58
- package/dist/esm/util/user-text.util.js +8 -4
- package/dist/esm/util/value.util.js +33 -5
- package/dist/types/common/index.d.cts +17 -10
- package/dist/types/common/index.d.ts +17 -10
- package/dist/types/core/index.d.cts +21 -11
- package/dist/types/core/index.d.ts +21 -11
- package/dist/types/decorator/index.d.cts +63 -63
- package/dist/types/decorator/index.d.ts +63 -63
- package/dist/types/{index-DKJclIi-.d.ts → index-Brkd6QGL.d.ts} +81 -35
- package/dist/types/{index-Dlf0ZZtS.d.cts → index-CqXImwF_.d.cts} +81 -35
- package/dist/types/interface/index.d.cts +1 -1
- package/dist/types/interface/index.d.ts +1 -1
- package/dist/types/{route-Bh1U13yy.d.ts → route-IQrK-MN2.d.cts} +11 -3
- package/dist/types/{route-Bh1U13yy.d.cts → route-bI-okq7g.d.ts} +11 -3
- package/dist/types/testing/index.d.cts +158 -61
- package/dist/types/testing/index.d.ts +158 -61
- package/dist/types/{theme-resolvers-CyEz9pnv.d.cts → theme-resolvers-AtgeaYqF.d.cts} +1 -1
- package/dist/types/{theme-resolvers-DA204O-q.d.ts → theme-resolvers-BgqysV8d.d.ts} +1 -1
- package/dist/types/{translator-Bg7hwxDF.d.cts → translator-D8aydlCE.d.ts} +12 -11
- package/dist/types/{translator-CeP4bCzp.d.ts → translator-iJhDlgwL.d.cts} +12 -11
- package/package.json +5 -2
|
@@ -2,15 +2,22 @@ import 'reflect-metadata';
|
|
|
2
2
|
import { HandlerExecutionContext } from '../common/execution-context.js';
|
|
3
3
|
import { appStages, handlerStages } from '../core/handler-pipeline.js';
|
|
4
4
|
import { handlerCooldowns } from '../core/cooldown-runner.js';
|
|
5
|
-
import { getMessageHandlers, getHandlerRoutes, getDeclaredRoutes } from '../decorator/controller.decorator.js';
|
|
5
|
+
import { getMessageHandlers, getHandlerRoutes, eventRoute, getDeclaredRoutes, ownEventHandlers, getCommandMap, getAutocompleteHandlers, getReactionHandlers } from '../decorator/controller.decorator.js';
|
|
6
|
+
import { getEventHandlers } from '../decorator/event.decorator.js';
|
|
7
|
+
import { appliesTo } from '../core/stage-scope.js';
|
|
8
|
+
import { Logger } from '../common/logger.js';
|
|
9
|
+
import { warnOnce } from '../common/deprecation.js';
|
|
10
|
+
import { strictMocks } from './strict-mocks.js';
|
|
6
11
|
import { appObservers } from '../core/observer-runner.js';
|
|
7
12
|
|
|
8
13
|
/**
|
|
9
14
|
* Reports what runs when a handler is dispatched, and the metadata declared on it, without running anything.
|
|
10
15
|
*
|
|
11
16
|
* Use it to check that decorators set a handler up as intended: its guards with their params, its interceptors,
|
|
12
|
-
* filters and cooldowns, in the order dispatch applies them.
|
|
13
|
-
*
|
|
17
|
+
* filters and cooldowns, in the order dispatch applies them. Under `useStrictMocks()`, the guards, interceptors and
|
|
18
|
+
* observers are those dispatch runs for the handler's context types: a stage declared with `types` is listed only for
|
|
19
|
+
* a handler of one of them, and an autocomplete lists no interceptors. Default mode lists every one, with a warning
|
|
20
|
+
* once where dispatch runs fewer. To check what a handler does, run it with {@link TestingModule.invoke}.
|
|
14
21
|
*
|
|
15
22
|
* @param controller - The controller class declaring the handler.
|
|
16
23
|
* @param methodName - The handler method's name.
|
|
@@ -46,14 +53,20 @@ import { appObservers } from '../core/observer-runner.js';
|
|
|
46
53
|
});
|
|
47
54
|
const globals = options.app ? appStages(options.app) : undefined;
|
|
48
55
|
const { guards, interceptors, filters } = handlerStages(controller.prototype, methodName, globals);
|
|
56
|
+
const observers = options.app ? appObservers(options.app) : [];
|
|
57
|
+
const stages = runStages(controller.prototype, methodName, {
|
|
58
|
+
guards,
|
|
59
|
+
interceptors,
|
|
60
|
+
observers
|
|
61
|
+
});
|
|
49
62
|
const inspection = {
|
|
50
63
|
controller,
|
|
51
64
|
methodName,
|
|
52
65
|
guards: Object.freeze([
|
|
53
|
-
...guards
|
|
66
|
+
...stages.guards
|
|
54
67
|
]),
|
|
55
68
|
interceptors: Object.freeze([
|
|
56
|
-
...interceptors
|
|
69
|
+
...stages.interceptors
|
|
57
70
|
]),
|
|
58
71
|
filters: Object.freeze(filters.flat()),
|
|
59
72
|
cooldowns: Object.freeze(handlerCooldowns(controller.prototype, methodName).map(({ seconds, uses, per, bypass, by })=>Object.freeze({
|
|
@@ -64,24 +77,92 @@ import { appObservers } from '../core/observer-runner.js';
|
|
|
64
77
|
by: by !== undefined
|
|
65
78
|
}))),
|
|
66
79
|
pattern: getMessageHandlers(controller.prototype).find((handler)=>handler.method === methodName)?.pattern,
|
|
67
|
-
observers: Object.freeze(
|
|
80
|
+
observers: Object.freeze([
|
|
81
|
+
...stages.observers
|
|
82
|
+
]),
|
|
68
83
|
get: (metadata)=>context.get(metadata),
|
|
69
84
|
getAll: (metadata)=>context.getAll(metadata)
|
|
70
85
|
};
|
|
71
86
|
// Read by a test but not compared by toEqual, so an assertion on the result's other fields holds
|
|
87
|
+
const routes = Object.freeze(inheritedRoutesOf(controller.prototype, methodName, false));
|
|
88
|
+
const withEvents = Object.freeze(inheritedRoutesOf(controller.prototype, methodName, true));
|
|
72
89
|
Object.defineProperty(inspection, 'inheritedRoutes', {
|
|
73
|
-
|
|
90
|
+
get: ()=>{
|
|
91
|
+
if (strictMocks()) return withEvents;
|
|
92
|
+
if (withEvents.length > routes.length) {
|
|
93
|
+
warnOnce(new Logger('inspectHandler'), `inspectHandler() here leaves the @On and @Once events ${controller.name}.${methodName} inherits out of ` + 'inheritedRoutes, though the bot answers them; under useStrictMocks() it lists them.');
|
|
94
|
+
}
|
|
95
|
+
return routes;
|
|
96
|
+
},
|
|
74
97
|
enumerable: false
|
|
75
98
|
});
|
|
76
99
|
return inspection;
|
|
77
100
|
}
|
|
78
|
-
/** The
|
|
101
|
+
/** The context types dispatch calls `methodName` with: one for each kind of route it answers. */ function handlerContextTypes(prototype, methodName) {
|
|
102
|
+
const answers = [
|
|
103
|
+
[
|
|
104
|
+
'interaction',
|
|
105
|
+
Object.values(getCommandMap(prototype) ?? {}).some((metas)=>metas.some((meta)=>meta.methodName === methodName))
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
'autocomplete',
|
|
109
|
+
getAutocompleteHandlers(prototype).some((handler)=>handler.methodName === methodName)
|
|
110
|
+
],
|
|
111
|
+
[
|
|
112
|
+
'message',
|
|
113
|
+
getMessageHandlers(prototype).some((handler)=>handler.method === methodName)
|
|
114
|
+
],
|
|
115
|
+
[
|
|
116
|
+
'reaction',
|
|
117
|
+
getReactionHandlers(prototype).some((handler)=>handler.method === methodName)
|
|
118
|
+
],
|
|
119
|
+
[
|
|
120
|
+
'event',
|
|
121
|
+
getEventHandlers(prototype).some((handler)=>handler.method === methodName)
|
|
122
|
+
]
|
|
123
|
+
];
|
|
124
|
+
return answers.filter(([, answered])=>answered).map(([type])=>type);
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The guards, interceptors and observers dispatch runs for the handler, by the same `appliesTo` it uses: those for one
|
|
128
|
+
* of its context types, and no interceptors for an autocomplete. Default mode lists every one, and warns once where
|
|
129
|
+
* that lists more; a method no route reaches lists every one in both modes.
|
|
130
|
+
*/ function runStages(prototype, methodName, all) {
|
|
131
|
+
const types = handlerContextTypes(prototype, methodName);
|
|
132
|
+
if (types.length === 0) return all;
|
|
133
|
+
const forTypes = (entries, among)=>entries.filter((entry)=>among.some((type)=>appliesTo(entry, type)));
|
|
134
|
+
const run = {
|
|
135
|
+
...all,
|
|
136
|
+
guards: forTypes(all.guards, types),
|
|
137
|
+
// Autocomplete answers within three seconds and has no reply to shape, so it runs no interceptors
|
|
138
|
+
interceptors: forTypes(all.interceptors, types.filter((type)=>type !== 'autocomplete')),
|
|
139
|
+
observers: forTypes(all.observers, types)
|
|
140
|
+
};
|
|
141
|
+
if (strictMocks()) return run;
|
|
142
|
+
const handlerName = `${prototype.constructor.name}.${methodName}`;
|
|
143
|
+
const count = (stages)=>stages.guards.length + stages.interceptors.length + stages.observers.length;
|
|
144
|
+
if (count(run) < count(all)) {
|
|
145
|
+
warnOnce(new Logger('inspectHandler'), `inspectHandler() here lists the guards, interceptors and observers of every context type for ${handlerName}, ` + "where dispatch runs only those of its own; under useStrictMocks() it lists the ones dispatch runs.");
|
|
146
|
+
}
|
|
147
|
+
return all;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* The routes `methodName` answers that the class declaring it last doesn't declare for it: those it inherits, its
|
|
151
|
+
* `@On` and `@Once` events among them when `events` is set.
|
|
152
|
+
*/ function inheritedRoutesOf(prototype, methodName, events) {
|
|
153
|
+
const labels = (routes)=>routes.filter((route)=>route.method === methodName).map((route)=>route.label);
|
|
79
154
|
const answered = [
|
|
80
|
-
...new Set(
|
|
155
|
+
...new Set(labels([
|
|
156
|
+
...getHandlerRoutes(prototype),
|
|
157
|
+
...events ? getEventHandlers(prototype).map(eventRoute) : []
|
|
158
|
+
]))
|
|
81
159
|
];
|
|
82
160
|
// The nearest class with its own decorators on the method; a class that only overrides it declares none
|
|
83
161
|
for(let at = prototype; at && at !== Object.prototype; at = Object.getPrototypeOf(at)){
|
|
84
|
-
const own =
|
|
162
|
+
const own = labels([
|
|
163
|
+
...getDeclaredRoutes(at),
|
|
164
|
+
...events ? ownEventHandlers(at).map(eventRoute) : []
|
|
165
|
+
]);
|
|
85
166
|
if (own.length > 0) return at === prototype ? answered.filter((label)=>!own.includes(label)) : answered;
|
|
86
167
|
}
|
|
87
168
|
return [];
|