seyfert 4.2.1 → 4.2.2-dev-22071590650.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/lib/api/api.d.ts +4 -2
- package/lib/api/api.js +57 -11
- package/lib/builders/Attachment.d.ts +1 -1
- package/lib/builders/Attachment.js +40 -6
- package/lib/builders/Button.js +6 -1
- package/lib/builders/CheckboxGroup.d.ts +1 -1
- package/lib/builders/CheckboxGroup.js +9 -1
- package/lib/builders/Label.js +9 -1
- package/lib/builders/Poll.js +6 -1
- package/lib/builders/RadioGroup.d.ts +1 -1
- package/lib/builders/RadioGroup.js +9 -1
- package/lib/builders/Section.d.ts +1 -1
- package/lib/builders/Section.js +9 -1
- package/lib/builders/SelectMenu.d.ts +1 -1
- package/lib/builders/SelectMenu.js +7 -1
- package/lib/cache/adapters/workeradapter.js +1 -1
- package/lib/cache/index.js +144 -42
- package/lib/client/base.js +4 -2
- package/lib/client/workerclient.js +4 -2
- package/lib/commands/applications/chat.js +1 -1
- package/lib/commands/handler.js +3 -1
- package/lib/commands/optionresolver.d.ts +1 -1
- package/lib/commands/optionresolver.js +3 -2
- package/lib/common/index.d.ts +1 -0
- package/lib/common/index.js +1 -0
- package/lib/common/it/error.d.ts +115 -0
- package/lib/common/it/error.js +138 -0
- package/lib/common/it/utils.js +5 -3
- package/lib/common/shorters/reactions.js +5 -4
- package/lib/components/handler.js +3 -1
- package/lib/events/handler.js +3 -1
- package/lib/langs/handler.js +3 -1
- package/lib/langs/router.js +3 -2
- package/lib/structures/Interaction.js +32 -12
- package/lib/structures/Poll.js +1 -1
- package/lib/websocket/discord/sharder.js +3 -1
- package/lib/websocket/discord/socket/custom.js +4 -1
- package/lib/websocket/discord/workermanager.js +35 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,19 @@ npm i seyfert
|
|
|
49
49
|
## Contributing
|
|
50
50
|
We are open to contributions, fork the repo and make your changes!
|
|
51
51
|
|
|
52
|
+
## Typed errors
|
|
53
|
+
|
|
54
|
+
Seyfert throws `SeyfertError` in validation/runtime checks and can include:
|
|
55
|
+
|
|
56
|
+
- `code`: machine-readable identifier (`INVALID_EMOJI`, `INVALID_OPTIONS_LENGTH`, `MISSING_COMPONENT`, etc.)
|
|
57
|
+
- `metadata`: structured context for diagnostics
|
|
58
|
+
|
|
59
|
+
For validation errors, metadata follows this convention:
|
|
60
|
+
|
|
61
|
+
- `expected`: expected value/shape
|
|
62
|
+
- `received`: value actually received
|
|
63
|
+
- `receivedType`: optional primitive/runtime type
|
|
64
|
+
|
|
52
65
|
## Useful links
|
|
53
66
|
|
|
54
67
|
- [GitHub Repository](https://github.com/tiramisulabs/seyfert)
|
package/lib/api/api.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type UUID } from 'node:crypto';
|
|
2
|
-
import { type Awaitable, Logger } from '../common';
|
|
2
|
+
import { type Awaitable, Logger, SeyfertError } from '../common';
|
|
3
3
|
import type { WorkerSendApiRequest } from '../websocket/discord/worker';
|
|
4
4
|
import { Bucket } from './bucket';
|
|
5
5
|
import type { APIRoutes } from './Routes';
|
|
@@ -27,7 +27,9 @@ export declare class ApiHandler {
|
|
|
27
27
|
protected sendMessage(_body: WorkerSendApiRequest): void;
|
|
28
28
|
protected postMessage<T = unknown>(body: WorkerSendApiRequest): Promise<T>;
|
|
29
29
|
request<T = unknown>(method: HttpMethods, url: `/${string}`, { auth, ...request }?: ApiRequestOptions): Promise<T>;
|
|
30
|
-
parseError(method: HttpMethods, route: `/${string}`, response: Response, result: string | Record<string, any
|
|
30
|
+
parseError(method: HttpMethods, route: `/${string}`, response: Response, result: string | Record<string, any>, originTrace?: {
|
|
31
|
+
stack?: string;
|
|
32
|
+
}): SeyfertError;
|
|
31
33
|
parseValidationError(data: Record<string, any>, path?: string, errors?: string[]): string[];
|
|
32
34
|
handle50X(method: HttpMethods, url: `/${string}`, request: ApiRequestOptions, next: () => void): Promise<unknown>;
|
|
33
35
|
handle429(route: string, method: HttpMethods, url: `/${string}`, request: ApiRequestOptions, response: Response, result: string, next: () => void, reject: (err: unknown) => void, now: number): Promise<unknown>;
|
package/lib/api/api.js
CHANGED
|
@@ -28,7 +28,9 @@ class ApiHandler {
|
|
|
28
28
|
this.debug = true;
|
|
29
29
|
const worker_threads = (0, common_1.lazyLoadPackage)('node:worker_threads');
|
|
30
30
|
if (options.workerProxy && !worker_threads?.parentPort && !process.send)
|
|
31
|
-
throw new
|
|
31
|
+
throw new common_1.SeyfertError('API_WORKER_PROXY_PARENT_REQUIRED', {
|
|
32
|
+
metadata: { detail: 'Cannot use workerProxy without a parent.' },
|
|
33
|
+
});
|
|
32
34
|
if (options.workerProxy)
|
|
33
35
|
this.workerPromises = new Map();
|
|
34
36
|
if (worker_threads?.parentPort) {
|
|
@@ -79,7 +81,7 @@ class ApiHandler {
|
|
|
79
81
|
return uuid;
|
|
80
82
|
}
|
|
81
83
|
sendMessage(_body) {
|
|
82
|
-
throw new
|
|
84
|
+
throw new common_1.SeyfertError('FUNCTION_NOT_IMPLEMENTED', { metadata: { detail: 'Function not implemented' } });
|
|
83
85
|
}
|
|
84
86
|
postMessage(body) {
|
|
85
87
|
this.sendMessage(body);
|
|
@@ -88,6 +90,8 @@ class ApiHandler {
|
|
|
88
90
|
});
|
|
89
91
|
}
|
|
90
92
|
async request(method, url, { auth = true, ...request } = {}) {
|
|
93
|
+
const originTrace = {};
|
|
94
|
+
Error.captureStackTrace(originTrace, this.request);
|
|
91
95
|
if (this.options.workerProxy) {
|
|
92
96
|
const nonce = this.randomUUID();
|
|
93
97
|
return this.postMessage({
|
|
@@ -151,14 +155,14 @@ class ApiHandler {
|
|
|
151
155
|
result = JSON.parse(result);
|
|
152
156
|
}
|
|
153
157
|
catch (err) {
|
|
154
|
-
this.debugger?.warn('
|
|
158
|
+
this.debugger?.warn('SeyfertError parsing result error (', result, ')', err);
|
|
155
159
|
reject(err);
|
|
156
160
|
return;
|
|
157
161
|
}
|
|
158
162
|
}
|
|
159
163
|
}
|
|
160
|
-
const parsedError = this.parseError(method, route, response, result);
|
|
161
|
-
this.debugger?.warn(parsedError);
|
|
164
|
+
const parsedError = this.parseError(method, route, response, result, originTrace);
|
|
165
|
+
this.debugger?.warn(parsedError.message);
|
|
162
166
|
reject(parsedError);
|
|
163
167
|
return;
|
|
164
168
|
}
|
|
@@ -168,7 +172,7 @@ class ApiHandler {
|
|
|
168
172
|
result = JSON.parse(result);
|
|
169
173
|
}
|
|
170
174
|
catch (err) {
|
|
171
|
-
this.debugger?.warn('
|
|
175
|
+
this.debugger?.warn('Failed parsing result (', result, ')', err);
|
|
172
176
|
next();
|
|
173
177
|
reject(err);
|
|
174
178
|
return;
|
|
@@ -195,9 +199,20 @@ class ApiHandler {
|
|
|
195
199
|
}
|
|
196
200
|
});
|
|
197
201
|
}
|
|
198
|
-
parseError(method, route, response, result) {
|
|
202
|
+
parseError(method, route, response, result, originTrace) {
|
|
199
203
|
let errMessage = '';
|
|
204
|
+
let code;
|
|
205
|
+
const metadata = {
|
|
206
|
+
method,
|
|
207
|
+
route,
|
|
208
|
+
status: response.status,
|
|
209
|
+
statusText: response.statusText,
|
|
210
|
+
};
|
|
200
211
|
if (typeof result === 'object') {
|
|
212
|
+
if (typeof result.code !== 'undefined') {
|
|
213
|
+
code = String(result.code);
|
|
214
|
+
}
|
|
215
|
+
metadata.response = result;
|
|
201
216
|
errMessage += `${result.message ?? 'Unknown'} ${result.code ?? ''}\n[${response.status} ${response.statusText}] ${method} ${route}`;
|
|
202
217
|
if ('errors' in result) {
|
|
203
218
|
const errors = this.parseValidationError(result.errors);
|
|
@@ -207,7 +222,25 @@ class ApiHandler {
|
|
|
207
222
|
else {
|
|
208
223
|
errMessage = `[${response.status} ${response.statusText}] ${method} ${route}`;
|
|
209
224
|
}
|
|
210
|
-
|
|
225
|
+
const error = new common_1.SeyfertError(`API_${response.statusText}_${code}`, {
|
|
226
|
+
metadata: {
|
|
227
|
+
...metadata,
|
|
228
|
+
detail: errMessage,
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
const originStack = originTrace?.stack;
|
|
232
|
+
if (originStack) {
|
|
233
|
+
const originLines = originStack
|
|
234
|
+
.split('\n')
|
|
235
|
+
.slice(1)
|
|
236
|
+
.filter(line => !line.includes('node:internal') &&
|
|
237
|
+
!line.includes('/src/api/api.ts') &&
|
|
238
|
+
!line.includes('\\src\\api\\api.ts'));
|
|
239
|
+
if (originLines.length) {
|
|
240
|
+
error.stack = `${error.name}: ${error.message}\n${originLines.join('\n')}`;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return error;
|
|
211
244
|
}
|
|
212
245
|
parseValidationError(data, path = '', errors = []) {
|
|
213
246
|
for (const key in data) {
|
|
@@ -237,7 +270,7 @@ class ApiHandler {
|
|
|
237
270
|
}
|
|
238
271
|
async handle429(route, method, url, request, response, result, next, reject, now) {
|
|
239
272
|
await this.onRatelimit?.(response, request);
|
|
240
|
-
const
|
|
273
|
+
const bucket = this.ratelimits.get(route);
|
|
241
274
|
let retryAfter;
|
|
242
275
|
const data = JSON.parse(result);
|
|
243
276
|
if (data.retry_after)
|
|
@@ -247,10 +280,23 @@ class ApiHandler {
|
|
|
247
280
|
if (Number.isNaN(retryAfter)) {
|
|
248
281
|
this.debugger?.warn(`${route} Could not extract retry_after from 429 response. ${result}`);
|
|
249
282
|
next();
|
|
250
|
-
reject(new
|
|
283
|
+
reject(new common_1.SeyfertError('INVALID_RETRY_AFTER', {
|
|
284
|
+
metadata: {
|
|
285
|
+
...{
|
|
286
|
+
route,
|
|
287
|
+
method,
|
|
288
|
+
status: response.status,
|
|
289
|
+
result,
|
|
290
|
+
},
|
|
291
|
+
detail: 'Could not extract retry_after from 429 response.',
|
|
292
|
+
},
|
|
293
|
+
}));
|
|
251
294
|
return false;
|
|
252
295
|
}
|
|
253
|
-
|
|
296
|
+
if (this.debugger) {
|
|
297
|
+
const content = `${JSON.stringify(request)} `;
|
|
298
|
+
this.debugger.info(`${response.headers.get('x-ratelimit-global') ? 'Global' : 'Unexpected'} 429: ${result.slice(0, 256)}\n${content} ${now} ${route} ${response.status}: ${bucket.remaining}/${bucket.limit} left | Reset ${retryAfter} (${bucket.reset - now}ms left) | Scope ${response.headers.get('x-ratelimit-scope')}`);
|
|
299
|
+
}
|
|
254
300
|
if (retryAfter) {
|
|
255
301
|
await (0, common_1.delay)(retryAfter);
|
|
256
302
|
next();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RawFile, UsingClient } from '..';
|
|
2
|
-
import type
|
|
2
|
+
import { type ImageResolvable, type ObjectToLower } from '../common';
|
|
3
3
|
import { Base } from '../structures/extra/Base';
|
|
4
4
|
import type { APIAttachment, RESTAPIAttachment } from '../types';
|
|
5
5
|
export interface AttachmentResolvableMap {
|
|
@@ -13,6 +13,7 @@ const node_crypto_1 = require("node:crypto");
|
|
|
13
13
|
const node_fs_1 = require("node:fs");
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
15
|
const utils_1 = require("../api/utils/utils");
|
|
16
|
+
const common_1 = require("../common");
|
|
16
17
|
const Base_1 = require("../structures/extra/Base");
|
|
17
18
|
class Attachment extends Base_1.Base {
|
|
18
19
|
data;
|
|
@@ -159,13 +160,23 @@ async function resolveFiles(resources) {
|
|
|
159
160
|
async function resolveAttachmentData(data, type) {
|
|
160
161
|
if (data instanceof AttachmentBuilder) {
|
|
161
162
|
if (!data.data.resolvable)
|
|
162
|
-
throw new
|
|
163
|
+
throw new common_1.SeyfertError('INVALID_ATTACHMENT_TYPE', {
|
|
164
|
+
metadata: {
|
|
165
|
+
...(0, common_1.createValidationMetadata)('AttachmentBuilder with resolvable data', data.data.resolvable),
|
|
166
|
+
detail: 'The attachment type has been expressed as attachment but cannot be resolved as one.',
|
|
167
|
+
},
|
|
168
|
+
});
|
|
163
169
|
return { data: data.data.resolvable };
|
|
164
170
|
}
|
|
165
171
|
switch (type) {
|
|
166
172
|
case 'url': {
|
|
167
173
|
if (!/^https?:\/\//.test(data))
|
|
168
|
-
throw new
|
|
174
|
+
throw new common_1.SeyfertError('INVALID_ATTACHMENT_TYPE', {
|
|
175
|
+
metadata: {
|
|
176
|
+
...(0, common_1.createValidationMetadata)('string URL starting with http:// or https://', data),
|
|
177
|
+
detail: `The attachment type has been expressed as ${type.toUpperCase()} but cannot be resolved as one.`,
|
|
178
|
+
},
|
|
179
|
+
});
|
|
169
180
|
const res = await fetch(data);
|
|
170
181
|
return {
|
|
171
182
|
data: Buffer.from(await res.arrayBuffer()),
|
|
@@ -176,7 +187,12 @@ async function resolveAttachmentData(data, type) {
|
|
|
176
187
|
const file = node_path_1.default.resolve(data);
|
|
177
188
|
const stats = await node_fs_1.promises.stat(file);
|
|
178
189
|
if (!stats.isFile())
|
|
179
|
-
throw new
|
|
190
|
+
throw new common_1.SeyfertError('INVALID_ATTACHMENT_TYPE', {
|
|
191
|
+
metadata: {
|
|
192
|
+
...(0, common_1.createValidationMetadata)('path to an existing file', file),
|
|
193
|
+
detail: `The attachment type has been expressed as ${type.toUpperCase()} but cannot be resolved as one.`,
|
|
194
|
+
},
|
|
195
|
+
});
|
|
180
196
|
return { data: await node_fs_1.promises.readFile(file) };
|
|
181
197
|
}
|
|
182
198
|
case 'buffer': {
|
|
@@ -188,10 +204,20 @@ async function resolveAttachmentData(data, type) {
|
|
|
188
204
|
buffers.push(Buffer.from(resource));
|
|
189
205
|
return { data: Buffer.concat(buffers) };
|
|
190
206
|
}
|
|
191
|
-
throw new
|
|
207
|
+
throw new common_1.SeyfertError('INVALID_ATTACHMENT_TYPE', {
|
|
208
|
+
metadata: {
|
|
209
|
+
...(0, common_1.createValidationMetadata)('Buffer | ArrayBuffer | AsyncIterable<ArrayBuffer>', data),
|
|
210
|
+
detail: `The attachment type has been expressed as ${type.toUpperCase()} but cannot be resolved as one.`,
|
|
211
|
+
},
|
|
212
|
+
});
|
|
192
213
|
}
|
|
193
214
|
default: {
|
|
194
|
-
throw new
|
|
215
|
+
throw new common_1.SeyfertError('INVALID_ATTACHMENT_TYPE', {
|
|
216
|
+
metadata: {
|
|
217
|
+
...(0, common_1.createValidationMetadata)('url | path | buffer', type),
|
|
218
|
+
detail: `The attachment type has been expressed as ${type} but cannot be resolved as one.`,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
195
221
|
}
|
|
196
222
|
}
|
|
197
223
|
}
|
|
@@ -215,7 +241,15 @@ async function resolveImage(image) {
|
|
|
215
241
|
const { data: { type, resolvable }, } = image;
|
|
216
242
|
if (type && resolvable)
|
|
217
243
|
return resolveBase64((await resolveAttachmentData(resolvable, type)).data);
|
|
218
|
-
throw new
|
|
244
|
+
throw new common_1.SeyfertError('INVALID_ATTACHMENT_TYPE', {
|
|
245
|
+
metadata: {
|
|
246
|
+
...(0, common_1.createValidationMetadata)('AttachmentBuilder with type and resolvable data', {
|
|
247
|
+
type,
|
|
248
|
+
resolvable,
|
|
249
|
+
}),
|
|
250
|
+
detail: `The attachment type has been expressed as ${(type ?? 'Attachment').toUpperCase()} but cannot be resolved as one.`,
|
|
251
|
+
},
|
|
252
|
+
});
|
|
219
253
|
}
|
|
220
254
|
if (image instanceof Attachment) {
|
|
221
255
|
const response = await fetch(image.url);
|
package/lib/builders/Button.js
CHANGED
|
@@ -47,7 +47,12 @@ class Button extends Base_1.BaseComponentBuilder {
|
|
|
47
47
|
setEmoji(emoji) {
|
|
48
48
|
const resolve = (0, common_1.resolvePartialEmoji)(emoji);
|
|
49
49
|
if (!resolve)
|
|
50
|
-
throw new
|
|
50
|
+
throw new common_1.SeyfertError('INVALID_EMOJI', {
|
|
51
|
+
metadata: {
|
|
52
|
+
...(0, common_1.createValidationMetadata)('EmojiResolvable', emoji, { component: 'Button' }),
|
|
53
|
+
detail: 'Invalid Emoji',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
51
56
|
this.data.emoji =
|
|
52
57
|
resolve;
|
|
53
58
|
return this;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type RestOrArray } from '../common';
|
|
2
2
|
import { type APICheckboxGroupComponent, type APICheckboxGroupOption } from '../types';
|
|
3
3
|
import { BaseComponentBuilder, type OptionValuesLength } from './Base';
|
|
4
4
|
export declare class CheckboxGroup extends BaseComponentBuilder<APICheckboxGroupComponent> {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CheckboxGroupOption = exports.CheckboxGroup = void 0;
|
|
4
|
+
const common_1 = require("../common");
|
|
4
5
|
const types_1 = require("../types");
|
|
5
6
|
const Base_1 = require("./Base");
|
|
6
7
|
class CheckboxGroup extends Base_1.BaseComponentBuilder {
|
|
@@ -59,7 +60,14 @@ class CheckboxGroup extends Base_1.BaseComponentBuilder {
|
|
|
59
60
|
const options = [...this.#options.map(option => option.toJSON()), ...(this.data.options ?? [])];
|
|
60
61
|
const optionCount = options.length;
|
|
61
62
|
if (optionCount < 2 || optionCount > 10) {
|
|
62
|
-
throw new
|
|
63
|
+
throw new common_1.SeyfertError('INVALID_OPTIONS_LENGTH', {
|
|
64
|
+
metadata: {
|
|
65
|
+
...(0, common_1.createValidationMetadata)('number of options between 2 and 10', optionCount, {
|
|
66
|
+
component: 'CheckboxGroup',
|
|
67
|
+
}),
|
|
68
|
+
detail: 'CheckboxGroup must have between 2 and 10 options.',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
63
71
|
}
|
|
64
72
|
return {
|
|
65
73
|
...this.data,
|
package/lib/builders/Label.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Label = void 0;
|
|
4
|
+
const common_1 = require("../common");
|
|
4
5
|
const types_1 = require("../types");
|
|
5
6
|
const _1 = require(".");
|
|
6
7
|
const Base_1 = require("./Base");
|
|
@@ -25,7 +26,14 @@ class Label extends Base_1.BaseComponentBuilder {
|
|
|
25
26
|
}
|
|
26
27
|
toJSON() {
|
|
27
28
|
if (!this.component)
|
|
28
|
-
throw new
|
|
29
|
+
throw new common_1.SeyfertError('MISSING_COMPONENT', {
|
|
30
|
+
metadata: {
|
|
31
|
+
...(0, common_1.createValidationMetadata)('component to be set before calling toJSON()', this.component, {
|
|
32
|
+
component: 'Label',
|
|
33
|
+
}),
|
|
34
|
+
detail: 'Cannot convert to JSON without a component.',
|
|
35
|
+
},
|
|
36
|
+
});
|
|
29
37
|
return {
|
|
30
38
|
...this.data,
|
|
31
39
|
component: this.component.toJSON(),
|
package/lib/builders/Poll.js
CHANGED
|
@@ -40,7 +40,12 @@ class PollBuilder {
|
|
|
40
40
|
return { text: data.text };
|
|
41
41
|
const resolve = (0, common_1.resolvePartialEmoji)(data.emoji);
|
|
42
42
|
if (!resolve)
|
|
43
|
-
throw new
|
|
43
|
+
throw new common_1.SeyfertError('INVALID_EMOJI', {
|
|
44
|
+
metadata: {
|
|
45
|
+
...(0, common_1.createValidationMetadata)('EmojiResolvable', data.emoji, { component: 'PollBuilder' }),
|
|
46
|
+
detail: 'Invalid Emoji',
|
|
47
|
+
},
|
|
48
|
+
});
|
|
44
49
|
return { text: data.text, emoji: resolve };
|
|
45
50
|
}
|
|
46
51
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type RestOrArray } from '../common';
|
|
2
2
|
import { type APIRadioGroupComponent, type APIRadioGroupOption } from '../types';
|
|
3
3
|
import { BaseComponentBuilder } from './Base';
|
|
4
4
|
export declare class RadioGroup extends BaseComponentBuilder<APIRadioGroupComponent> {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RadioGroupOption = exports.RadioGroup = void 0;
|
|
4
|
+
const common_1 = require("../common");
|
|
4
5
|
const types_1 = require("../types");
|
|
5
6
|
const Base_1 = require("./Base");
|
|
6
7
|
class RadioGroup extends Base_1.BaseComponentBuilder {
|
|
@@ -47,7 +48,14 @@ class RadioGroup extends Base_1.BaseComponentBuilder {
|
|
|
47
48
|
const options = [...this.#options.map(option => option.data), ...(this.data.options ?? [])];
|
|
48
49
|
const optionCount = options.length;
|
|
49
50
|
if (optionCount < 2 || optionCount > 10) {
|
|
50
|
-
throw new
|
|
51
|
+
throw new common_1.SeyfertError('INVALID_OPTIONS_LENGTH', {
|
|
52
|
+
metadata: {
|
|
53
|
+
...(0, common_1.createValidationMetadata)('number of options between 2 and 10', optionCount, {
|
|
54
|
+
component: 'RadioGroup',
|
|
55
|
+
}),
|
|
56
|
+
detail: 'RadioGroup must have between 2 and 10 options.',
|
|
57
|
+
},
|
|
58
|
+
});
|
|
51
59
|
}
|
|
52
60
|
return {
|
|
53
61
|
...this.data,
|
package/lib/builders/Section.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Section = void 0;
|
|
4
|
+
const common_1 = require("../common");
|
|
4
5
|
const types_1 = require("../types");
|
|
5
6
|
const _1 = require(".");
|
|
6
7
|
const Base_1 = require("./Base");
|
|
@@ -41,7 +42,14 @@ class Section extends Base_1.BaseComponentBuilder {
|
|
|
41
42
|
*/
|
|
42
43
|
toJSON() {
|
|
43
44
|
if (!this.accessory)
|
|
44
|
-
throw new
|
|
45
|
+
throw new common_1.SeyfertError('MISSING_ACCESSORY', {
|
|
46
|
+
metadata: {
|
|
47
|
+
...(0, common_1.createValidationMetadata)('accessory to be set before calling toJSON()', this.accessory, {
|
|
48
|
+
component: 'Section',
|
|
49
|
+
}),
|
|
50
|
+
detail: 'Cannot convert to JSON without an accessory.',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
45
53
|
return {
|
|
46
54
|
...this.data,
|
|
47
55
|
components: this.components.map(component => component.toJSON()),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type EmojiResolvable, type RestOrArray } from '../common';
|
|
2
2
|
import { type APIChannelSelectComponent, type APIMentionableSelectComponent, type APIRoleSelectComponent, type APISelectMenuComponent, type APISelectMenuOption, type APIStringSelectComponent, type APIUserSelectComponent, type ChannelType, SelectMenuDefaultValueType } from '../types';
|
|
3
3
|
import { BaseComponentBuilder, type OptionValuesLength } from './Base';
|
|
4
4
|
export type BuilderSelectMenus = RoleSelectMenu | UserSelectMenu | MentionableSelectMenu | ChannelSelectMenu | StringSelectMenu;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StringSelectOption = exports.StringSelectMenu = exports.ChannelSelectMenu = exports.MentionableSelectMenu = exports.RoleSelectMenu = exports.UserSelectMenu = exports.SelectMenu = void 0;
|
|
4
|
+
const common_1 = require("../common");
|
|
4
5
|
const utils_1 = require("../common/it/utils");
|
|
5
6
|
const types_1 = require("../types");
|
|
6
7
|
const Base_1 = require("./Base");
|
|
@@ -318,7 +319,12 @@ class StringSelectOption {
|
|
|
318
319
|
setEmoji(emoji) {
|
|
319
320
|
const resolve = (0, utils_1.resolvePartialEmoji)(emoji);
|
|
320
321
|
if (!resolve)
|
|
321
|
-
throw new
|
|
322
|
+
throw new common_1.SeyfertError('INVALID_EMOJI', {
|
|
323
|
+
metadata: {
|
|
324
|
+
...(0, common_1.createValidationMetadata)('EmojiResolvable', emoji, { component: 'StringSelectOption' }),
|
|
325
|
+
detail: 'Invalid Emoji',
|
|
326
|
+
},
|
|
327
|
+
});
|
|
322
328
|
this.data.emoji = resolve;
|
|
323
329
|
return this;
|
|
324
330
|
}
|
|
@@ -36,7 +36,7 @@ class WorkerAdapter {
|
|
|
36
36
|
return new Promise((res, rej) => {
|
|
37
37
|
const timeout = setTimeout(() => {
|
|
38
38
|
this.promises.delete(nonce);
|
|
39
|
-
rej(new
|
|
39
|
+
rej(new common_1.SeyfertError('CACHE_TIMEOUT', { metadata: { ...{ nonce, method }, detail: 'Timeout cache request' } }));
|
|
40
40
|
}, 60e3);
|
|
41
41
|
this.promises.set(nonce, { resolve: res, timeout });
|
|
42
42
|
});
|