@svintsow/discord-components 1.0.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 +8 -0
- package/dist/index.d.mts +289 -0
- package/dist/index.d.ts +289 -0
- package/dist/index.js +923 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +868 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +64 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,868 @@
|
|
|
1
|
+
// src/enums/ComponentType.ts
|
|
2
|
+
var ComponentType = /* @__PURE__ */ ((ComponentType2) => {
|
|
3
|
+
ComponentType2[ComponentType2["Container"] = 1] = "Container";
|
|
4
|
+
ComponentType2[ComponentType2["Section"] = 2] = "Section";
|
|
5
|
+
ComponentType2[ComponentType2["TextDisplay"] = 3] = "TextDisplay";
|
|
6
|
+
ComponentType2[ComponentType2["Thumbnail"] = 4] = "Thumbnail";
|
|
7
|
+
ComponentType2[ComponentType2["MediaGallery"] = 5] = "MediaGallery";
|
|
8
|
+
ComponentType2[ComponentType2["MediaGalleryItem"] = 6] = "MediaGalleryItem";
|
|
9
|
+
ComponentType2[ComponentType2["Separator"] = 7] = "Separator";
|
|
10
|
+
ComponentType2[ComponentType2["File"] = 8] = "File";
|
|
11
|
+
ComponentType2[ComponentType2["Label"] = 9] = "Label";
|
|
12
|
+
return ComponentType2;
|
|
13
|
+
})(ComponentType || {});
|
|
14
|
+
|
|
15
|
+
// src/constants/limits.ts
|
|
16
|
+
var Limits = {
|
|
17
|
+
MAX_COMPONENTS_PER_CONTAINER: 5,
|
|
18
|
+
MAX_TEXT_LENGTH: 2e3,
|
|
19
|
+
MAX_DESCRIPTION_LENGTH: 2e3,
|
|
20
|
+
MAX_LABEL_LENGTH: 80,
|
|
21
|
+
MAX_FILENAME_LENGTH: 255,
|
|
22
|
+
MAX_GALLERY_ITEMS: 10,
|
|
23
|
+
MAX_URL_LENGTH: 2048
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// src/errors/ValidationError.ts
|
|
27
|
+
var ValidationError = class extends Error {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "ValidationError";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// src/errors/InvalidComponentError.ts
|
|
35
|
+
var InvalidComponentError = class extends Error {
|
|
36
|
+
constructor(message) {
|
|
37
|
+
super(message);
|
|
38
|
+
this.name = "InvalidComponentError";
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// src/errors/InvalidURLException.ts
|
|
43
|
+
var InvalidURLException = class extends Error {
|
|
44
|
+
constructor(message) {
|
|
45
|
+
super(message);
|
|
46
|
+
this.name = "InvalidURLException";
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// src/errors/ComponentLimitError.ts
|
|
51
|
+
var ComponentLimitError = class extends Error {
|
|
52
|
+
constructor(message) {
|
|
53
|
+
super(message);
|
|
54
|
+
this.name = "ComponentLimitError";
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/builders/base/ComponentBuilder.ts
|
|
59
|
+
var ComponentBuilder = class {
|
|
60
|
+
clone() {
|
|
61
|
+
const data = this.toJSON();
|
|
62
|
+
const Constructor = this.constructor;
|
|
63
|
+
const instance = new Constructor();
|
|
64
|
+
return instance.fromJSON(data);
|
|
65
|
+
}
|
|
66
|
+
static from(data) {
|
|
67
|
+
const instance = new this();
|
|
68
|
+
return instance.fromJSON(data);
|
|
69
|
+
}
|
|
70
|
+
fromJSON(data) {
|
|
71
|
+
return this;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// src/builders/base/AccessoryBuilder.ts
|
|
76
|
+
var AccessoryBuilder = class extends ComponentBuilder {
|
|
77
|
+
setStyle(style) {
|
|
78
|
+
this.style = style;
|
|
79
|
+
return this;
|
|
80
|
+
}
|
|
81
|
+
toJSON() {
|
|
82
|
+
const data = {
|
|
83
|
+
type: this.type
|
|
84
|
+
};
|
|
85
|
+
if (this.style) {
|
|
86
|
+
data.style = this.style;
|
|
87
|
+
}
|
|
88
|
+
return data;
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// src/validation/validators/URLValidator.ts
|
|
93
|
+
var URLValidator = class {
|
|
94
|
+
static validate(url) {
|
|
95
|
+
try {
|
|
96
|
+
new URL(url);
|
|
97
|
+
} catch {
|
|
98
|
+
throw new InvalidURLException(`Invalid URL: ${url}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
static validateOptional(url) {
|
|
102
|
+
if (url) {
|
|
103
|
+
this.validate(url);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
// src/utils/urlUtils.ts
|
|
109
|
+
var UrlUtils = class {
|
|
110
|
+
static isValidUrl(url) {
|
|
111
|
+
try {
|
|
112
|
+
new URL(url);
|
|
113
|
+
return true;
|
|
114
|
+
} catch {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
static normalizeUrl(url) {
|
|
119
|
+
if (!this.isValidUrl(url)) {
|
|
120
|
+
throw new Error("Invalid URL");
|
|
121
|
+
}
|
|
122
|
+
return url.trim();
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// src/utils/stringUtils.ts
|
|
127
|
+
var StringUtils = class {
|
|
128
|
+
static isString(value) {
|
|
129
|
+
return typeof value === "string";
|
|
130
|
+
}
|
|
131
|
+
static truncate(text, maxLength) {
|
|
132
|
+
if (text.length <= maxLength)
|
|
133
|
+
return text;
|
|
134
|
+
return text.slice(0, maxLength - 3) + "...";
|
|
135
|
+
}
|
|
136
|
+
static validateLength(text, maxLength, field) {
|
|
137
|
+
if (text && text.length > maxLength) {
|
|
138
|
+
throw new Error(`${field} exceeds maximum length of ${maxLength}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
// src/utils/arrayUtils.ts
|
|
144
|
+
var ArrayUtils = class {
|
|
145
|
+
static isValidArray(arr) {
|
|
146
|
+
return Array.isArray(arr);
|
|
147
|
+
}
|
|
148
|
+
static ensureArray(items) {
|
|
149
|
+
return Array.isArray(items) ? items : [items];
|
|
150
|
+
}
|
|
151
|
+
static splice(arr, index, deleteCount, ...items) {
|
|
152
|
+
const result = [...arr];
|
|
153
|
+
result.splice(index, deleteCount, ...items);
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// src/utils/objectUtils.ts
|
|
159
|
+
var ObjectUtils = class {
|
|
160
|
+
static deepClone(obj) {
|
|
161
|
+
return JSON.parse(JSON.stringify(obj));
|
|
162
|
+
}
|
|
163
|
+
static hasOwnProperty(obj, prop) {
|
|
164
|
+
return Object.prototype.hasOwnProperty.call(obj, prop);
|
|
165
|
+
}
|
|
166
|
+
static mergeDeep(target, source) {
|
|
167
|
+
const result = { ...target };
|
|
168
|
+
for (const key in source) {
|
|
169
|
+
if (this.hasOwnProperty(source, key)) {
|
|
170
|
+
result[key] = source[key];
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// src/validation/validators/StringValidator.ts
|
|
178
|
+
var StringValidator = class {
|
|
179
|
+
static validate(value, field) {
|
|
180
|
+
if (!StringUtils.isString(value)) {
|
|
181
|
+
throw new ValidationError(`${field} must be a string`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
static validateLength(value, maxLength, field) {
|
|
185
|
+
if (value && value.length > maxLength) {
|
|
186
|
+
throw new ValidationError(
|
|
187
|
+
`${field} must be at most ${maxLength} characters, got ${value.length}`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
static validateOptional(value, field) {
|
|
192
|
+
if (value !== void 0 && value !== null) {
|
|
193
|
+
this.validate(value, field || "Value");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
// src/validation/validators/ComponentValidator.ts
|
|
199
|
+
var ComponentValidator = class {
|
|
200
|
+
static validateType(type) {
|
|
201
|
+
if (!Object.values(ComponentType).includes(type)) {
|
|
202
|
+
throw new ValidationError(`Invalid component type: ${type}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
static validateComponentStructure(obj) {
|
|
206
|
+
if (!obj || typeof obj !== "object") {
|
|
207
|
+
throw new ValidationError("Component must be an object");
|
|
208
|
+
}
|
|
209
|
+
if (!obj.type) {
|
|
210
|
+
throw new ValidationError("Component must have a type");
|
|
211
|
+
}
|
|
212
|
+
this.validateType(obj.type);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// src/validation/rules/limitRules.ts
|
|
217
|
+
var LimitRules = class {
|
|
218
|
+
static validateComponentCount(count) {
|
|
219
|
+
if (count > Limits.MAX_COMPONENTS_PER_CONTAINER) {
|
|
220
|
+
throw new ComponentLimitError(
|
|
221
|
+
`Maximum ${Limits.MAX_COMPONENTS_PER_CONTAINER} components allowed, got ${count}`
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
static validateGalleryItems(count) {
|
|
226
|
+
if (count > Limits.MAX_GALLERY_ITEMS) {
|
|
227
|
+
throw new ComponentLimitError(
|
|
228
|
+
`Maximum ${Limits.MAX_GALLERY_ITEMS} gallery items allowed, got ${count}`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// src/validation/rules/nestingRules.ts
|
|
235
|
+
var NestingRules = class {
|
|
236
|
+
static validateContainerNesting(componentType) {
|
|
237
|
+
const allowedTypes = [
|
|
238
|
+
1 /* Container */,
|
|
239
|
+
2 /* Section */,
|
|
240
|
+
3 /* TextDisplay */,
|
|
241
|
+
4 /* Thumbnail */,
|
|
242
|
+
5 /* MediaGallery */,
|
|
243
|
+
7 /* Separator */,
|
|
244
|
+
8 /* File */,
|
|
245
|
+
9 /* Label */
|
|
246
|
+
];
|
|
247
|
+
if (!allowedTypes.includes(componentType)) {
|
|
248
|
+
throw new InvalidComponentError(
|
|
249
|
+
`Component type ${componentType} cannot be nested in Container`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
static validateSectionNesting(componentType) {
|
|
254
|
+
const allowedTypes = [
|
|
255
|
+
3 /* TextDisplay */,
|
|
256
|
+
4 /* Thumbnail */,
|
|
257
|
+
5 /* MediaGallery */,
|
|
258
|
+
8 /* File */,
|
|
259
|
+
9 /* Label */,
|
|
260
|
+
7 /* Separator */
|
|
261
|
+
];
|
|
262
|
+
if (!allowedTypes.includes(componentType)) {
|
|
263
|
+
throw new InvalidComponentError(
|
|
264
|
+
`Component type ${componentType} cannot be nested in Section`
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
// src/components/parser/ComponentParser.ts
|
|
271
|
+
var ComponentParser = class {
|
|
272
|
+
static parse(data) {
|
|
273
|
+
if (!data || typeof data !== "object") {
|
|
274
|
+
throw new ValidationError("Invalid component data");
|
|
275
|
+
}
|
|
276
|
+
if (!data.type) {
|
|
277
|
+
throw new ValidationError("Component data must have type");
|
|
278
|
+
}
|
|
279
|
+
switch (data.type) {
|
|
280
|
+
case 1 /* Container */:
|
|
281
|
+
return ContainerBuilder.from(data);
|
|
282
|
+
case 2 /* Section */:
|
|
283
|
+
return SectionBuilder.from(data);
|
|
284
|
+
case 3 /* TextDisplay */:
|
|
285
|
+
return TextDisplayBuilder.from(data);
|
|
286
|
+
case 4 /* Thumbnail */:
|
|
287
|
+
return ThumbnailBuilder.from(data);
|
|
288
|
+
case 5 /* MediaGallery */:
|
|
289
|
+
return MediaGalleryBuilder.from(data);
|
|
290
|
+
case 6 /* MediaGalleryItem */:
|
|
291
|
+
return MediaGalleryItemBuilder.from(data);
|
|
292
|
+
case 7 /* Separator */:
|
|
293
|
+
return SeparatorBuilder.from(data);
|
|
294
|
+
case 8 /* File */:
|
|
295
|
+
return FileBuilder.from(data);
|
|
296
|
+
case 9 /* Label */:
|
|
297
|
+
return LabelBuilder.from(data);
|
|
298
|
+
default:
|
|
299
|
+
throw new ValidationError(`Unknown component type: ${data.type}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
static parseMany(dataArray) {
|
|
303
|
+
return dataArray.map((data) => this.parse(data));
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
// src/builders/container/ContainerBuilder.ts
|
|
308
|
+
var ContainerBuilder = class _ContainerBuilder extends ComponentBuilder {
|
|
309
|
+
constructor() {
|
|
310
|
+
super();
|
|
311
|
+
this.components = [];
|
|
312
|
+
this.type = 1 /* Container */;
|
|
313
|
+
}
|
|
314
|
+
addComponents(...components) {
|
|
315
|
+
for (const component of components) {
|
|
316
|
+
const componentType = component.type || component.constructor.type;
|
|
317
|
+
if (componentType !== 1 /* Container */) {
|
|
318
|
+
NestingRules.validateContainerNesting(componentType);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const newCount = this.components.length + components.length;
|
|
322
|
+
LimitRules.validateComponentCount(newCount);
|
|
323
|
+
this.components.push(...components);
|
|
324
|
+
return this;
|
|
325
|
+
}
|
|
326
|
+
spliceComponents(index, deleteCount, ...components) {
|
|
327
|
+
if (index < 0 || index > this.components.length) {
|
|
328
|
+
throw new ValidationError(`Invalid index: ${index}`);
|
|
329
|
+
}
|
|
330
|
+
for (const component of components) {
|
|
331
|
+
const componentType = component.type || component.constructor.type;
|
|
332
|
+
if (componentType !== 1 /* Container */) {
|
|
333
|
+
NestingRules.validateContainerNesting(componentType);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
const newCount = this.components.length - deleteCount + components.length;
|
|
337
|
+
LimitRules.validateComponentCount(newCount);
|
|
338
|
+
this.components = ArrayUtils.splice(
|
|
339
|
+
this.components,
|
|
340
|
+
index,
|
|
341
|
+
deleteCount,
|
|
342
|
+
...components
|
|
343
|
+
);
|
|
344
|
+
return this;
|
|
345
|
+
}
|
|
346
|
+
clearComponents() {
|
|
347
|
+
this.components = [];
|
|
348
|
+
return this;
|
|
349
|
+
}
|
|
350
|
+
toJSON() {
|
|
351
|
+
return {
|
|
352
|
+
type: this.type,
|
|
353
|
+
components: this.components.map((comp) => comp.toJSON())
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
fromJSON(data) {
|
|
357
|
+
if (!data.components || !Array.isArray(data.components)) {
|
|
358
|
+
throw new ValidationError("Container data must have components array");
|
|
359
|
+
}
|
|
360
|
+
this.components = data.components.map((compData) => {
|
|
361
|
+
return ComponentParser.parse(compData);
|
|
362
|
+
});
|
|
363
|
+
return this;
|
|
364
|
+
}
|
|
365
|
+
clone() {
|
|
366
|
+
const cloned = new _ContainerBuilder();
|
|
367
|
+
cloned.components = this.components.map((comp) => comp.clone());
|
|
368
|
+
return cloned;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
// src/builders/section/SectionBuilder.ts
|
|
373
|
+
var SectionBuilder = class _SectionBuilder extends ComponentBuilder {
|
|
374
|
+
constructor() {
|
|
375
|
+
super();
|
|
376
|
+
this.texts = [];
|
|
377
|
+
this.accessory = null;
|
|
378
|
+
this.type = 2 /* Section */;
|
|
379
|
+
}
|
|
380
|
+
addText(...textComponents) {
|
|
381
|
+
for (const component of textComponents) {
|
|
382
|
+
NestingRules.validateSectionNesting(component.type);
|
|
383
|
+
}
|
|
384
|
+
this.texts.push(...textComponents);
|
|
385
|
+
return this;
|
|
386
|
+
}
|
|
387
|
+
setAccessory(accessory) {
|
|
388
|
+
this.accessory = accessory;
|
|
389
|
+
return this;
|
|
390
|
+
}
|
|
391
|
+
clearAccessory() {
|
|
392
|
+
this.accessory = null;
|
|
393
|
+
return this;
|
|
394
|
+
}
|
|
395
|
+
toJSON() {
|
|
396
|
+
const data = {
|
|
397
|
+
type: this.type,
|
|
398
|
+
texts: this.texts.map((text) => text.toJSON())
|
|
399
|
+
};
|
|
400
|
+
if (this.accessory) {
|
|
401
|
+
data.accessory = this.accessory.toJSON();
|
|
402
|
+
}
|
|
403
|
+
return data;
|
|
404
|
+
}
|
|
405
|
+
fromJSON(data) {
|
|
406
|
+
if (!data.texts || !Array.isArray(data.texts)) {
|
|
407
|
+
throw new ValidationError("Section data must have texts array");
|
|
408
|
+
}
|
|
409
|
+
this.texts = data.texts.map((textData) => {
|
|
410
|
+
return ComponentParser.parse(textData);
|
|
411
|
+
});
|
|
412
|
+
if (data.accessory) {
|
|
413
|
+
const parsed = ComponentParser.parse(data.accessory);
|
|
414
|
+
this.accessory = parsed;
|
|
415
|
+
}
|
|
416
|
+
return this;
|
|
417
|
+
}
|
|
418
|
+
clone() {
|
|
419
|
+
const cloned = new _SectionBuilder();
|
|
420
|
+
cloned.texts = this.texts.map((text) => text.clone());
|
|
421
|
+
if (this.accessory) {
|
|
422
|
+
cloned.accessory = this.accessory.clone();
|
|
423
|
+
}
|
|
424
|
+
return cloned;
|
|
425
|
+
}
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
// src/builders/textDisplay/TextDisplayBuilder.ts
|
|
429
|
+
var TextDisplayBuilder = class _TextDisplayBuilder extends ComponentBuilder {
|
|
430
|
+
constructor() {
|
|
431
|
+
super();
|
|
432
|
+
this.content = "";
|
|
433
|
+
this.type = 3 /* TextDisplay */;
|
|
434
|
+
}
|
|
435
|
+
setContent(text) {
|
|
436
|
+
StringValidator.validate(text, "Content");
|
|
437
|
+
StringValidator.validateLength(text, Limits.MAX_TEXT_LENGTH, "Content");
|
|
438
|
+
this.content = text;
|
|
439
|
+
return this;
|
|
440
|
+
}
|
|
441
|
+
toJSON() {
|
|
442
|
+
if (!this.content) {
|
|
443
|
+
throw new ValidationError("TextDisplay must have content");
|
|
444
|
+
}
|
|
445
|
+
return {
|
|
446
|
+
type: this.type,
|
|
447
|
+
content: this.content
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
fromJSON(data) {
|
|
451
|
+
if (!data.content) {
|
|
452
|
+
throw new ValidationError("TextDisplay data must have content");
|
|
453
|
+
}
|
|
454
|
+
return this.setContent(data.content);
|
|
455
|
+
}
|
|
456
|
+
clone() {
|
|
457
|
+
const cloned = new _TextDisplayBuilder();
|
|
458
|
+
cloned.content = this.content;
|
|
459
|
+
return cloned;
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
// src/builders/thumbnail/ThumbnailBuilder.ts
|
|
464
|
+
var ThumbnailBuilder = class _ThumbnailBuilder extends ComponentBuilder {
|
|
465
|
+
constructor() {
|
|
466
|
+
super();
|
|
467
|
+
// Не extends AccessoryBuilder
|
|
468
|
+
this.url = "";
|
|
469
|
+
this.description = "";
|
|
470
|
+
this.spoiler = false;
|
|
471
|
+
this.type = 4 /* Thumbnail */;
|
|
472
|
+
}
|
|
473
|
+
setURL(url) {
|
|
474
|
+
URLValidator.validate(url);
|
|
475
|
+
this.url = url;
|
|
476
|
+
return this;
|
|
477
|
+
}
|
|
478
|
+
setDescription(text) {
|
|
479
|
+
StringValidator.validate(text, "Description");
|
|
480
|
+
StringValidator.validateLength(
|
|
481
|
+
text,
|
|
482
|
+
Limits.MAX_DESCRIPTION_LENGTH,
|
|
483
|
+
"Description"
|
|
484
|
+
);
|
|
485
|
+
this.description = text;
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
setSpoiler(spoiler) {
|
|
489
|
+
this.spoiler = spoiler;
|
|
490
|
+
return this;
|
|
491
|
+
}
|
|
492
|
+
toJSON() {
|
|
493
|
+
if (!this.url) {
|
|
494
|
+
throw new ValidationError("Thumbnail must have URL");
|
|
495
|
+
}
|
|
496
|
+
const data = {
|
|
497
|
+
type: this.type,
|
|
498
|
+
url: this.url
|
|
499
|
+
};
|
|
500
|
+
if (this.description) {
|
|
501
|
+
data.description = this.description;
|
|
502
|
+
}
|
|
503
|
+
if (this.spoiler) {
|
|
504
|
+
data.spoiler = this.spoiler;
|
|
505
|
+
}
|
|
506
|
+
return data;
|
|
507
|
+
}
|
|
508
|
+
fromJSON(data) {
|
|
509
|
+
if (!data.url) {
|
|
510
|
+
throw new ValidationError("Thumbnail data must have URL");
|
|
511
|
+
}
|
|
512
|
+
this.setURL(data.url);
|
|
513
|
+
if (data.description) {
|
|
514
|
+
this.setDescription(data.description);
|
|
515
|
+
}
|
|
516
|
+
if (data.spoiler !== void 0) {
|
|
517
|
+
this.setSpoiler(data.spoiler);
|
|
518
|
+
}
|
|
519
|
+
return this;
|
|
520
|
+
}
|
|
521
|
+
clone() {
|
|
522
|
+
const cloned = new _ThumbnailBuilder();
|
|
523
|
+
cloned.url = this.url;
|
|
524
|
+
cloned.description = this.description;
|
|
525
|
+
cloned.spoiler = this.spoiler;
|
|
526
|
+
return cloned;
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// src/builders/mediaGallery/MediaGalleryItemBuilder.ts
|
|
531
|
+
var MediaGalleryItemBuilder = class _MediaGalleryItemBuilder extends ComponentBuilder {
|
|
532
|
+
constructor() {
|
|
533
|
+
super();
|
|
534
|
+
this.url = "";
|
|
535
|
+
this.description = "";
|
|
536
|
+
this.spoiler = false;
|
|
537
|
+
this.type = 6 /* MediaGalleryItem */;
|
|
538
|
+
}
|
|
539
|
+
setURL(url) {
|
|
540
|
+
URLValidator.validate(url);
|
|
541
|
+
this.url = url;
|
|
542
|
+
return this;
|
|
543
|
+
}
|
|
544
|
+
setDescription(text) {
|
|
545
|
+
StringValidator.validate(text, "Description");
|
|
546
|
+
StringValidator.validateLength(
|
|
547
|
+
text,
|
|
548
|
+
Limits.MAX_DESCRIPTION_LENGTH,
|
|
549
|
+
"Description"
|
|
550
|
+
);
|
|
551
|
+
this.description = text;
|
|
552
|
+
return this;
|
|
553
|
+
}
|
|
554
|
+
setSpoiler(spoiler) {
|
|
555
|
+
this.spoiler = spoiler;
|
|
556
|
+
return this;
|
|
557
|
+
}
|
|
558
|
+
toJSON() {
|
|
559
|
+
if (!this.url) {
|
|
560
|
+
throw new ValidationError("MediaGalleryItem must have URL");
|
|
561
|
+
}
|
|
562
|
+
const data = {
|
|
563
|
+
type: this.type,
|
|
564
|
+
url: this.url
|
|
565
|
+
};
|
|
566
|
+
if (this.description) {
|
|
567
|
+
data.description = this.description;
|
|
568
|
+
}
|
|
569
|
+
if (this.spoiler) {
|
|
570
|
+
data.spoiler = this.spoiler;
|
|
571
|
+
}
|
|
572
|
+
return data;
|
|
573
|
+
}
|
|
574
|
+
fromJSON(data) {
|
|
575
|
+
if (!data.url) {
|
|
576
|
+
throw new ValidationError("MediaGalleryItem data must have URL");
|
|
577
|
+
}
|
|
578
|
+
this.setURL(data.url);
|
|
579
|
+
if (data.description) {
|
|
580
|
+
this.setDescription(data.description);
|
|
581
|
+
}
|
|
582
|
+
if (data.spoiler !== void 0) {
|
|
583
|
+
this.setSpoiler(data.spoiler);
|
|
584
|
+
}
|
|
585
|
+
return this;
|
|
586
|
+
}
|
|
587
|
+
clone() {
|
|
588
|
+
const cloned = new _MediaGalleryItemBuilder();
|
|
589
|
+
cloned.url = this.url;
|
|
590
|
+
cloned.description = this.description;
|
|
591
|
+
cloned.spoiler = this.spoiler;
|
|
592
|
+
return cloned;
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
// src/builders/mediaGallery/MediaGalleryBuilder.ts
|
|
597
|
+
var MediaGalleryBuilder = class _MediaGalleryBuilder extends ComponentBuilder {
|
|
598
|
+
constructor() {
|
|
599
|
+
super();
|
|
600
|
+
this.items = [];
|
|
601
|
+
this.type = 5 /* MediaGallery */;
|
|
602
|
+
}
|
|
603
|
+
addItems(...items) {
|
|
604
|
+
const newCount = this.items.length + items.length;
|
|
605
|
+
LimitRules.validateGalleryItems(newCount);
|
|
606
|
+
this.items.push(...items);
|
|
607
|
+
return this;
|
|
608
|
+
}
|
|
609
|
+
spliceItems(index, deleteCount, ...items) {
|
|
610
|
+
if (index < 0 || index > this.items.length) {
|
|
611
|
+
throw new ValidationError(`Invalid index: ${index}`);
|
|
612
|
+
}
|
|
613
|
+
const newCount = this.items.length - deleteCount + items.length;
|
|
614
|
+
LimitRules.validateGalleryItems(newCount);
|
|
615
|
+
this.items = ArrayUtils.splice(this.items, index, deleteCount, ...items);
|
|
616
|
+
return this;
|
|
617
|
+
}
|
|
618
|
+
clearItems() {
|
|
619
|
+
this.items = [];
|
|
620
|
+
return this;
|
|
621
|
+
}
|
|
622
|
+
toJSON() {
|
|
623
|
+
return {
|
|
624
|
+
type: this.type,
|
|
625
|
+
items: this.items.map((item) => item.toJSON())
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
fromJSON(data) {
|
|
629
|
+
if (!data.items || !Array.isArray(data.items)) {
|
|
630
|
+
throw new ValidationError("MediaGallery data must have items array");
|
|
631
|
+
}
|
|
632
|
+
this.items = data.items.map((itemData) => {
|
|
633
|
+
return MediaGalleryItemBuilder.from(itemData);
|
|
634
|
+
});
|
|
635
|
+
return this;
|
|
636
|
+
}
|
|
637
|
+
clone() {
|
|
638
|
+
const cloned = new _MediaGalleryBuilder();
|
|
639
|
+
cloned.items = this.items.map((item) => item.clone());
|
|
640
|
+
return cloned;
|
|
641
|
+
}
|
|
642
|
+
};
|
|
643
|
+
|
|
644
|
+
// src/builders/separator/SeparatorBuilder.ts
|
|
645
|
+
var SeparatorBuilder = class _SeparatorBuilder extends ComponentBuilder {
|
|
646
|
+
constructor() {
|
|
647
|
+
super();
|
|
648
|
+
this.spacing = 8;
|
|
649
|
+
this.divider = true;
|
|
650
|
+
this.type = 7 /* Separator */;
|
|
651
|
+
}
|
|
652
|
+
setSpacing(spacing) {
|
|
653
|
+
if (spacing < 0 || spacing > 32) {
|
|
654
|
+
throw new ValidationError("Spacing must be between 0 and 32");
|
|
655
|
+
}
|
|
656
|
+
this.spacing = spacing;
|
|
657
|
+
return this;
|
|
658
|
+
}
|
|
659
|
+
setDivider(divider) {
|
|
660
|
+
this.divider = divider;
|
|
661
|
+
return this;
|
|
662
|
+
}
|
|
663
|
+
toJSON() {
|
|
664
|
+
const data = {
|
|
665
|
+
type: this.type,
|
|
666
|
+
spacing: this.spacing
|
|
667
|
+
};
|
|
668
|
+
if (!this.divider) {
|
|
669
|
+
data.divider = this.divider;
|
|
670
|
+
}
|
|
671
|
+
return data;
|
|
672
|
+
}
|
|
673
|
+
fromJSON(data) {
|
|
674
|
+
if (data.spacing !== void 0) {
|
|
675
|
+
this.setSpacing(data.spacing);
|
|
676
|
+
}
|
|
677
|
+
if (data.divider !== void 0) {
|
|
678
|
+
this.setDivider(data.divider);
|
|
679
|
+
}
|
|
680
|
+
return this;
|
|
681
|
+
}
|
|
682
|
+
clone() {
|
|
683
|
+
const cloned = new _SeparatorBuilder();
|
|
684
|
+
cloned.spacing = this.spacing;
|
|
685
|
+
cloned.divider = this.divider;
|
|
686
|
+
return cloned;
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
|
|
690
|
+
// src/builders/file/FileBuilder.ts
|
|
691
|
+
var FileBuilder = class _FileBuilder extends ComponentBuilder {
|
|
692
|
+
constructor() {
|
|
693
|
+
super();
|
|
694
|
+
this.url = "";
|
|
695
|
+
this.filename = "";
|
|
696
|
+
this.description = "";
|
|
697
|
+
this.type = 8 /* File */;
|
|
698
|
+
}
|
|
699
|
+
setURL(url) {
|
|
700
|
+
URLValidator.validate(url);
|
|
701
|
+
this.url = url;
|
|
702
|
+
return this;
|
|
703
|
+
}
|
|
704
|
+
setFilename(name) {
|
|
705
|
+
StringValidator.validate(name, "Filename");
|
|
706
|
+
StringValidator.validateLength(name, Limits.MAX_FILENAME_LENGTH, "Filename");
|
|
707
|
+
this.filename = name;
|
|
708
|
+
return this;
|
|
709
|
+
}
|
|
710
|
+
setDescription(text) {
|
|
711
|
+
StringValidator.validate(text, "Description");
|
|
712
|
+
StringValidator.validateLength(
|
|
713
|
+
text,
|
|
714
|
+
Limits.MAX_DESCRIPTION_LENGTH,
|
|
715
|
+
"Description"
|
|
716
|
+
);
|
|
717
|
+
this.description = text;
|
|
718
|
+
return this;
|
|
719
|
+
}
|
|
720
|
+
toJSON() {
|
|
721
|
+
if (!this.url) {
|
|
722
|
+
throw new ValidationError("File must have URL");
|
|
723
|
+
}
|
|
724
|
+
if (!this.filename) {
|
|
725
|
+
throw new ValidationError("File must have filename");
|
|
726
|
+
}
|
|
727
|
+
const data = {
|
|
728
|
+
type: this.type,
|
|
729
|
+
url: this.url,
|
|
730
|
+
filename: this.filename
|
|
731
|
+
};
|
|
732
|
+
if (this.description) {
|
|
733
|
+
data.description = this.description;
|
|
734
|
+
}
|
|
735
|
+
return data;
|
|
736
|
+
}
|
|
737
|
+
fromJSON(data) {
|
|
738
|
+
if (!data.url || !data.filename) {
|
|
739
|
+
throw new ValidationError("File data must have URL and filename");
|
|
740
|
+
}
|
|
741
|
+
this.setURL(data.url);
|
|
742
|
+
this.setFilename(data.filename);
|
|
743
|
+
if (data.description) {
|
|
744
|
+
this.setDescription(data.description);
|
|
745
|
+
}
|
|
746
|
+
return this;
|
|
747
|
+
}
|
|
748
|
+
clone() {
|
|
749
|
+
const cloned = new _FileBuilder();
|
|
750
|
+
cloned.url = this.url;
|
|
751
|
+
cloned.filename = this.filename;
|
|
752
|
+
cloned.description = this.description;
|
|
753
|
+
return cloned;
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
|
|
757
|
+
// src/builders/label/LabelBuilder.ts
|
|
758
|
+
var LabelBuilder = class _LabelBuilder extends ComponentBuilder {
|
|
759
|
+
constructor() {
|
|
760
|
+
super();
|
|
761
|
+
this.label = "";
|
|
762
|
+
this.description = "";
|
|
763
|
+
this.type = 9 /* Label */;
|
|
764
|
+
}
|
|
765
|
+
setLabel(text) {
|
|
766
|
+
StringValidator.validate(text, "Label");
|
|
767
|
+
StringValidator.validateLength(text, Limits.MAX_LABEL_LENGTH, "Label");
|
|
768
|
+
this.label = text;
|
|
769
|
+
return this;
|
|
770
|
+
}
|
|
771
|
+
setDescription(text) {
|
|
772
|
+
StringValidator.validate(text, "Description");
|
|
773
|
+
StringValidator.validateLength(
|
|
774
|
+
text,
|
|
775
|
+
Limits.MAX_DESCRIPTION_LENGTH,
|
|
776
|
+
"Description"
|
|
777
|
+
);
|
|
778
|
+
this.description = text;
|
|
779
|
+
return this;
|
|
780
|
+
}
|
|
781
|
+
toJSON() {
|
|
782
|
+
if (!this.label) {
|
|
783
|
+
throw new ValidationError("Label must have label text");
|
|
784
|
+
}
|
|
785
|
+
const data = {
|
|
786
|
+
type: this.type,
|
|
787
|
+
label: this.label
|
|
788
|
+
};
|
|
789
|
+
if (this.description) {
|
|
790
|
+
data.description = this.description;
|
|
791
|
+
}
|
|
792
|
+
return data;
|
|
793
|
+
}
|
|
794
|
+
fromJSON(data) {
|
|
795
|
+
if (!data.label) {
|
|
796
|
+
throw new ValidationError("Label data must have label");
|
|
797
|
+
}
|
|
798
|
+
this.setLabel(data.label);
|
|
799
|
+
if (data.description) {
|
|
800
|
+
this.setDescription(data.description);
|
|
801
|
+
}
|
|
802
|
+
return this;
|
|
803
|
+
}
|
|
804
|
+
clone() {
|
|
805
|
+
const cloned = new _LabelBuilder();
|
|
806
|
+
cloned.label = this.label;
|
|
807
|
+
cloned.description = this.description;
|
|
808
|
+
return cloned;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
// src/helpers/componentHelper.ts
|
|
813
|
+
var ComponentHelper = class {
|
|
814
|
+
static createTextSection(text) {
|
|
815
|
+
return new SectionBuilder().addText(
|
|
816
|
+
new TextDisplayBuilder().setContent(text)
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
static createContainerFrom(...components) {
|
|
820
|
+
return new ContainerBuilder().addComponents(...components);
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
|
|
824
|
+
// src/internal/registry.ts
|
|
825
|
+
var ComponentRegistry = class {
|
|
826
|
+
static register(name, builder) {
|
|
827
|
+
this.builders.set(name, builder);
|
|
828
|
+
}
|
|
829
|
+
static get(name) {
|
|
830
|
+
return this.builders.get(name);
|
|
831
|
+
}
|
|
832
|
+
static has(name) {
|
|
833
|
+
return this.builders.has(name);
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
ComponentRegistry.builders = /* @__PURE__ */ new Map();
|
|
837
|
+
export {
|
|
838
|
+
AccessoryBuilder,
|
|
839
|
+
ArrayUtils,
|
|
840
|
+
ComponentBuilder,
|
|
841
|
+
ComponentHelper,
|
|
842
|
+
ComponentLimitError,
|
|
843
|
+
ComponentParser,
|
|
844
|
+
ComponentRegistry,
|
|
845
|
+
ComponentType,
|
|
846
|
+
ComponentValidator,
|
|
847
|
+
ContainerBuilder,
|
|
848
|
+
FileBuilder,
|
|
849
|
+
InvalidComponentError,
|
|
850
|
+
InvalidURLException,
|
|
851
|
+
LabelBuilder,
|
|
852
|
+
LimitRules,
|
|
853
|
+
Limits,
|
|
854
|
+
MediaGalleryBuilder,
|
|
855
|
+
MediaGalleryItemBuilder,
|
|
856
|
+
NestingRules,
|
|
857
|
+
ObjectUtils,
|
|
858
|
+
SectionBuilder,
|
|
859
|
+
SeparatorBuilder,
|
|
860
|
+
StringUtils,
|
|
861
|
+
StringValidator,
|
|
862
|
+
TextDisplayBuilder,
|
|
863
|
+
ThumbnailBuilder,
|
|
864
|
+
URLValidator,
|
|
865
|
+
UrlUtils,
|
|
866
|
+
ValidationError
|
|
867
|
+
};
|
|
868
|
+
//# sourceMappingURL=index.mjs.map
|