@abdokouta/react-support 1.1.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/dist/index.js ADDED
@@ -0,0 +1,2418 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ BaseRegistry: () => BaseRegistry,
34
+ Collection: () => Collection,
35
+ Facade: () => Facade,
36
+ MapCollection: () => MapCollection,
37
+ SetCollection: () => SetCollection,
38
+ Str: () => Str,
39
+ collect: () => collect,
40
+ collectMap: () => collectMap,
41
+ collectSet: () => collectSet,
42
+ createFacade: () => createFacade,
43
+ createFacadeClass: () => createFacadeClass,
44
+ getContainerFromModule: () => getContainerFromModule,
45
+ isFake: () => isFake
46
+ });
47
+ module.exports = __toCommonJS(index_exports);
48
+
49
+ // src/str/str.ts
50
+ var Str = class _Str {
51
+ /**
52
+ * Return the remainder of a string after the first occurrence of a given value
53
+ */
54
+ static after(subject, search) {
55
+ if (search === "") return subject;
56
+ const index = subject.indexOf(search);
57
+ return index === -1 ? subject : subject.substring(index + search.length);
58
+ }
59
+ /**
60
+ * Return the remainder of a string after the last occurrence of a given value
61
+ */
62
+ static afterLast(subject, search) {
63
+ if (search === "") return subject;
64
+ const index = subject.lastIndexOf(search);
65
+ return index === -1 ? subject : subject.substring(index + search.length);
66
+ }
67
+ /**
68
+ * Convert a string to title case following APA guidelines
69
+ */
70
+ static apa(value) {
71
+ const minorWords = ["a", "an", "and", "as", "at", "but", "by", "for", "in", "of", "on", "or", "the", "to", "up"];
72
+ const words = value.split(" ");
73
+ return words.map((word, index) => {
74
+ if (index === 0 || !minorWords.includes(word.toLowerCase())) {
75
+ return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
76
+ }
77
+ return word.toLowerCase();
78
+ }).join(" ");
79
+ }
80
+ /**
81
+ * Transliterate a UTF-8 value to ASCII
82
+ */
83
+ static ascii(value) {
84
+ return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
85
+ }
86
+ /**
87
+ * Get the portion of a string before the first occurrence of a given value
88
+ */
89
+ static before(subject, search) {
90
+ if (search === "") return subject;
91
+ const index = subject.indexOf(search);
92
+ return index === -1 ? subject : subject.substring(0, index);
93
+ }
94
+ /**
95
+ * Get the portion of a string before the last occurrence of a given value
96
+ */
97
+ static beforeLast(subject, search) {
98
+ if (search === "") return subject;
99
+ const index = subject.lastIndexOf(search);
100
+ return index === -1 ? subject : subject.substring(0, index);
101
+ }
102
+ /**
103
+ * Get the portion of a string between two values
104
+ */
105
+ static between(subject, from, to) {
106
+ if (from === "" || to === "") return subject;
107
+ const startIndex = subject.indexOf(from);
108
+ if (startIndex === -1) return "";
109
+ const start = startIndex + from.length;
110
+ const endIndex = subject.indexOf(to, start);
111
+ return endIndex === -1 ? "" : subject.substring(start, endIndex);
112
+ }
113
+ /**
114
+ * Get the smallest possible portion of a string between two values
115
+ */
116
+ static betweenFirst(subject, from, to) {
117
+ return _Str.between(subject, from, to);
118
+ }
119
+ /**
120
+ * Convert a string to camelCase
121
+ */
122
+ static camel(value) {
123
+ return value.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
124
+ }
125
+ /**
126
+ * Get the character at the specified index
127
+ */
128
+ static charAt(subject, index) {
129
+ if (index < 0 || index >= subject.length) return false;
130
+ return subject.charAt(index);
131
+ }
132
+ /**
133
+ * Remove the first occurrence of the given value from the start of the string
134
+ */
135
+ static chopStart(subject, search) {
136
+ const searches = Array.isArray(search) ? search : [search];
137
+ for (const s of searches) {
138
+ if (subject.startsWith(s)) {
139
+ return subject.substring(s.length);
140
+ }
141
+ }
142
+ return subject;
143
+ }
144
+ /**
145
+ * Remove the last occurrence of the given value from the end of the string
146
+ */
147
+ static chopEnd(subject, search) {
148
+ const searches = Array.isArray(search) ? search : [search];
149
+ for (const s of searches) {
150
+ if (subject.endsWith(s)) {
151
+ return subject.substring(0, subject.length - s.length);
152
+ }
153
+ }
154
+ return subject;
155
+ }
156
+ /**
157
+ * Determine if a given string contains a given substring
158
+ */
159
+ static contains(haystack, needles, ignoreCase = false) {
160
+ const needleArray = Array.isArray(needles) ? needles : [needles];
161
+ const subject = ignoreCase ? haystack.toLowerCase() : haystack;
162
+ return needleArray.some((needle) => {
163
+ const search = ignoreCase ? needle.toLowerCase() : needle;
164
+ return subject.includes(search);
165
+ });
166
+ }
167
+ /**
168
+ * Determine if a given string contains all array values
169
+ */
170
+ static containsAll(haystack, needles, ignoreCase = false) {
171
+ const subject = ignoreCase ? haystack.toLowerCase() : haystack;
172
+ return needles.every((needle) => {
173
+ const search = ignoreCase ? needle.toLowerCase() : needle;
174
+ return subject.includes(search);
175
+ });
176
+ }
177
+ /**
178
+ * Determine if a given string doesn't contain a given substring
179
+ */
180
+ static doesntContain(haystack, needles, ignoreCase = false) {
181
+ return !_Str.contains(haystack, needles, ignoreCase);
182
+ }
183
+ /**
184
+ * Replace consecutive instances of a character with a single instance
185
+ */
186
+ static deduplicate(value, character = " ") {
187
+ const escaped = character.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
188
+ const regex = new RegExp(`${escaped}+`, "g");
189
+ return value.replace(regex, character);
190
+ }
191
+ /**
192
+ * Determine if a given string ends with a given substring
193
+ */
194
+ static endsWith(haystack, needles) {
195
+ const needleArray = Array.isArray(needles) ? needles : [needles];
196
+ return needleArray.some((needle) => haystack.endsWith(needle));
197
+ }
198
+ /**
199
+ * Extract an excerpt from text that matches the first instance of a phrase
200
+ */
201
+ static excerpt(text, phrase, options = {}) {
202
+ const radius = options.radius ?? 100;
203
+ const omission = options.omission ?? "...";
204
+ const index = text.indexOf(phrase);
205
+ if (index === -1) return "";
206
+ const start = Math.max(0, index - radius);
207
+ const end = Math.min(text.length, index + phrase.length + radius);
208
+ let excerpt = text.substring(start, end);
209
+ if (start > 0) excerpt = omission + excerpt;
210
+ if (end < text.length) excerpt = excerpt + omission;
211
+ return excerpt;
212
+ }
213
+ /**
214
+ * Cap a string with a single instance of a given value
215
+ */
216
+ static finish(value, cap) {
217
+ return value.endsWith(cap) ? value : value + cap;
218
+ }
219
+ /**
220
+ * Convert a string to headline case
221
+ */
222
+ static headline(value) {
223
+ return value.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[-_]/g, " ").split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
224
+ }
225
+ /**
226
+ * Determine if a given string matches a given pattern
227
+ */
228
+ static is(pattern, value, ignoreCase = false) {
229
+ const regexPattern = pattern.replace(/\*/g, ".*");
230
+ const flags = ignoreCase ? "i" : "";
231
+ const regex = new RegExp(`^${regexPattern}$`, flags);
232
+ return regex.test(value);
233
+ }
234
+ /**
235
+ * Determine if a given string is 7-bit ASCII
236
+ */
237
+ static isAscii(value) {
238
+ return /^[\x00-\x7F]*$/.test(value);
239
+ }
240
+ /**
241
+ * Determine if a given string is valid JSON
242
+ */
243
+ static isJson(value) {
244
+ try {
245
+ JSON.parse(value);
246
+ return true;
247
+ } catch {
248
+ return false;
249
+ }
250
+ }
251
+ /**
252
+ * Determine if a given string is a valid URL
253
+ */
254
+ static isUrl(value, protocols) {
255
+ try {
256
+ if (typeof URL === "undefined") {
257
+ const urlPattern = /^https?:\/\/.+/i;
258
+ return urlPattern.test(value);
259
+ }
260
+ const urlObj = new URL(value);
261
+ if (protocols) {
262
+ return protocols.includes(urlObj.protocol.replace(":", ""));
263
+ }
264
+ return true;
265
+ } catch {
266
+ return false;
267
+ }
268
+ }
269
+ /**
270
+ * Determine if a given string is a valid ULID
271
+ */
272
+ static isUlid(value) {
273
+ return /^[0-9A-HJKMNP-TV-Z]{26}$/i.test(value);
274
+ }
275
+ /**
276
+ * Determine if a given string is a valid UUID
277
+ */
278
+ static isUuid(value) {
279
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
280
+ }
281
+ /**
282
+ * Convert a string to kebab-case
283
+ */
284
+ static kebab(value) {
285
+ return value.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
286
+ }
287
+ /**
288
+ * Return the given string with the first character lowercased
289
+ */
290
+ static lcfirst(value) {
291
+ return value.charAt(0).toLowerCase() + value.slice(1);
292
+ }
293
+ /**
294
+ * Return the length of the given string
295
+ */
296
+ static len(value) {
297
+ return value.length;
298
+ }
299
+ /**
300
+ * Limit the number of characters in a string
301
+ */
302
+ static limit(value, limit = 100, end = "...", preserveWords = false) {
303
+ if (value.length <= limit) return value;
304
+ let truncated = value.substring(0, limit);
305
+ if (preserveWords) {
306
+ const lastSpace = truncated.lastIndexOf(" ");
307
+ if (lastSpace > 0) {
308
+ truncated = truncated.substring(0, lastSpace);
309
+ }
310
+ }
311
+ return truncated + end;
312
+ }
313
+ /**
314
+ * Convert the given string to lowercase
315
+ */
316
+ static lower(value) {
317
+ return value.toLowerCase();
318
+ }
319
+ /**
320
+ * Masks a portion of a string with a repeated character
321
+ */
322
+ static mask(value, character, index, length) {
323
+ if (index < 0) {
324
+ index = value.length + index;
325
+ }
326
+ const maskLength = length ?? value.length - index;
327
+ const mask = character.repeat(Math.abs(maskLength));
328
+ return value.substring(0, index) + mask + value.substring(index + Math.abs(maskLength));
329
+ }
330
+ /**
331
+ * Pad both sides of a string with another
332
+ */
333
+ static padBoth(value, length, pad = " ") {
334
+ const totalPadding = length - value.length;
335
+ if (totalPadding <= 0) return value;
336
+ const leftPadding = Math.floor(totalPadding / 2);
337
+ const rightPadding = totalPadding - leftPadding;
338
+ return pad.repeat(leftPadding) + value + pad.repeat(rightPadding);
339
+ }
340
+ /**
341
+ * Pad the left side of a string with another
342
+ */
343
+ static padLeft(value, length, pad = " ") {
344
+ return value.padStart(length, pad);
345
+ }
346
+ /**
347
+ * Pad the right side of a string with another
348
+ */
349
+ static padRight(value, length, pad = " ") {
350
+ return value.padEnd(length, pad);
351
+ }
352
+ /**
353
+ * Get the plural form of an English word
354
+ */
355
+ static plural(value, count = 2) {
356
+ if (count === 1) return value;
357
+ if (value.endsWith("y") && !/[aeiou]y$/i.test(value)) {
358
+ return value.slice(0, -1) + "ies";
359
+ }
360
+ if (value.endsWith("s") || value.endsWith("x") || value.endsWith("z") || value.endsWith("ch") || value.endsWith("sh")) {
361
+ return value + "es";
362
+ }
363
+ return value + "s";
364
+ }
365
+ /**
366
+ * Pluralize the last word of an English, studly caps case string
367
+ */
368
+ static pluralStudly(value, count = 2) {
369
+ const parts = value.match(/[A-Z][a-z]*/g) || [value];
370
+ const lastWord = parts[parts.length - 1];
371
+ const pluralized = _Str.plural(lastWord, count);
372
+ parts[parts.length - 1] = pluralized;
373
+ return parts.join("");
374
+ }
375
+ /**
376
+ * Find the position of the first occurrence of a substring
377
+ */
378
+ static position(haystack, needle) {
379
+ const pos = haystack.indexOf(needle);
380
+ return pos === -1 ? false : pos;
381
+ }
382
+ /**
383
+ * Generate a random string
384
+ */
385
+ static random(length = 16) {
386
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
387
+ let result = "";
388
+ for (let i = 0; i < length; i++) {
389
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
390
+ }
391
+ return result;
392
+ }
393
+ /**
394
+ * Remove the given value from the string
395
+ */
396
+ static remove(search, subject, caseSensitive = true) {
397
+ const searches = Array.isArray(search) ? search : [search];
398
+ let result = subject;
399
+ searches.forEach((s) => {
400
+ const flags = caseSensitive ? "g" : "gi";
401
+ const escaped = s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
402
+ result = result.replace(new RegExp(escaped, flags), "");
403
+ });
404
+ return result;
405
+ }
406
+ /**
407
+ * Repeat the given string
408
+ */
409
+ static repeat(value, times) {
410
+ return value.repeat(times);
411
+ }
412
+ /**
413
+ * Replace the given value in the given string
414
+ */
415
+ static replace(search, replace, subject, caseSensitive = true) {
416
+ const flags = caseSensitive ? "g" : "gi";
417
+ const escaped = search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
418
+ return subject.replace(new RegExp(escaped, flags), replace);
419
+ }
420
+ /**
421
+ * Replace a given value in the string sequentially with an array
422
+ */
423
+ static replaceArray(search, replacements, subject) {
424
+ let result = subject;
425
+ let index = 0;
426
+ while (result.includes(search) && index < replacements.length) {
427
+ result = result.replace(search, replacements[index]);
428
+ index++;
429
+ }
430
+ return result;
431
+ }
432
+ /**
433
+ * Replace the first occurrence of a given value in the string
434
+ */
435
+ static replaceFirst(search, replace, subject) {
436
+ return subject.replace(search, replace);
437
+ }
438
+ /**
439
+ * Replace the last occurrence of a given value in the string
440
+ */
441
+ static replaceLast(search, replace, subject) {
442
+ const index = subject.lastIndexOf(search);
443
+ if (index === -1) return subject;
444
+ return subject.substring(0, index) + replace + subject.substring(index + search.length);
445
+ }
446
+ /**
447
+ * Replace the first occurrence only if it appears at the start
448
+ */
449
+ static replaceStart(search, replace, subject) {
450
+ return subject.startsWith(search) ? replace + subject.substring(search.length) : subject;
451
+ }
452
+ /**
453
+ * Replace the last occurrence only if it appears at the end
454
+ */
455
+ static replaceEnd(search, replace, subject) {
456
+ return subject.endsWith(search) ? subject.substring(0, subject.length - search.length) + replace : subject;
457
+ }
458
+ /**
459
+ * Reverse the given string
460
+ */
461
+ static reverse(value) {
462
+ return value.split("").reverse().join("");
463
+ }
464
+ /**
465
+ * Get the singular form of an English word
466
+ */
467
+ static singular(value) {
468
+ if (value.endsWith("ies")) {
469
+ return value.slice(0, -3) + "y";
470
+ }
471
+ if (value.endsWith("es")) {
472
+ return value.slice(0, -2);
473
+ }
474
+ if (value.endsWith("s") && !value.endsWith("ss")) {
475
+ return value.slice(0, -1);
476
+ }
477
+ return value;
478
+ }
479
+ /**
480
+ * Generate a URL friendly slug
481
+ */
482
+ static slug(value, separator = "-") {
483
+ return value.toLowerCase().replace(/[^\w\s-]/g, "").replace(/[\s_]+/g, separator).replace(new RegExp(`${separator}+`, "g"), separator).replace(new RegExp(`^${separator}|${separator}$`, "g"), "");
484
+ }
485
+ /**
486
+ * Convert a string to snake_case
487
+ */
488
+ static snake(value, delimiter = "_") {
489
+ return value.replace(/([a-z])([A-Z])/g, `$1${delimiter}$2`).replace(/[\s-]+/g, delimiter).toLowerCase();
490
+ }
491
+ /**
492
+ * Remove all extraneous whitespace
493
+ */
494
+ static squish(value) {
495
+ return value.trim().replace(/\s+/g, " ");
496
+ }
497
+ /**
498
+ * Begin a string with a single instance of a given value
499
+ */
500
+ static start(value, prefix) {
501
+ return value.startsWith(prefix) ? value : prefix + value;
502
+ }
503
+ /**
504
+ * Determine if a given string starts with a given substring
505
+ */
506
+ static startsWith(haystack, needles) {
507
+ const needleArray = Array.isArray(needles) ? needles : [needles];
508
+ return needleArray.some((needle) => haystack.startsWith(needle));
509
+ }
510
+ /**
511
+ * Convert a value to studly caps case
512
+ */
513
+ static studly(value) {
514
+ return value.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toUpperCase());
515
+ }
516
+ /**
517
+ * Returns the portion of string specified by the start and length parameters
518
+ */
519
+ static substr(value, start, length) {
520
+ return value.substr(start, length);
521
+ }
522
+ /**
523
+ * Returns the number of substring occurrences
524
+ */
525
+ static substrCount(haystack, needle) {
526
+ return (haystack.match(new RegExp(needle, "g")) || []).length;
527
+ }
528
+ /**
529
+ * Replace text within a portion of a string
530
+ */
531
+ static substrReplace(value, replace, start, length) {
532
+ const actualLength = length ?? value.length - start;
533
+ return value.substring(0, start) + replace + value.substring(start + actualLength);
534
+ }
535
+ /**
536
+ * Swap multiple keywords in a string with other keywords
537
+ */
538
+ static swap(map, subject) {
539
+ let result = subject;
540
+ Object.entries(map).forEach(([search, replace]) => {
541
+ result = _Str.replace(search, replace, result);
542
+ });
543
+ return result;
544
+ }
545
+ /**
546
+ * Take the first or last {limit} characters
547
+ */
548
+ static take(value, limit) {
549
+ if (limit < 0) {
550
+ return value.slice(limit);
551
+ }
552
+ return value.slice(0, limit);
553
+ }
554
+ /**
555
+ * Convert the given string to title case
556
+ */
557
+ static title(value) {
558
+ return value.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
559
+ }
560
+ /**
561
+ * Convert the given string to Base64
562
+ */
563
+ static toBase64(value) {
564
+ if (typeof Buffer !== "undefined") {
565
+ return Buffer.from(value).toString("base64");
566
+ }
567
+ if (typeof btoa !== "undefined") {
568
+ return btoa(value);
569
+ }
570
+ throw new Error("Base64 encoding not supported in this environment");
571
+ }
572
+ /**
573
+ * Transliterate a string to its closest ASCII representation
574
+ */
575
+ static transliterate(value) {
576
+ return _Str.ascii(value);
577
+ }
578
+ /**
579
+ * Trim whitespace from both ends of the string
580
+ */
581
+ static trim(value, characters) {
582
+ if (!characters) return value.trim();
583
+ const escaped = characters.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
584
+ return value.replace(new RegExp(`^[${escaped}]+|[${escaped}]+$`, "g"), "");
585
+ }
586
+ /**
587
+ * Trim whitespace from the beginning of the string
588
+ */
589
+ static ltrim(value, characters) {
590
+ if (!characters) return value.trimStart();
591
+ const escaped = characters.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
592
+ return value.replace(new RegExp(`^[${escaped}]+`, "g"), "");
593
+ }
594
+ /**
595
+ * Trim whitespace from the end of the string
596
+ */
597
+ static rtrim(value, characters) {
598
+ if (!characters) return value.trimEnd();
599
+ const escaped = characters.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
600
+ return value.replace(new RegExp(`[${escaped}]+$`, "g"), "");
601
+ }
602
+ /**
603
+ * Make a string's first character uppercase
604
+ */
605
+ static ucfirst(value) {
606
+ return value.charAt(0).toUpperCase() + value.slice(1);
607
+ }
608
+ /**
609
+ * Split a string by uppercase characters
610
+ */
611
+ static ucsplit(value) {
612
+ return value.match(/[A-Z][a-z]*/g) || [value];
613
+ }
614
+ /**
615
+ * Convert the given string to uppercase
616
+ */
617
+ static upper(value) {
618
+ return value.toUpperCase();
619
+ }
620
+ /**
621
+ * Remove the specified strings from the beginning and end
622
+ */
623
+ static unwrap(value, before, after) {
624
+ const actualAfter = after ?? before;
625
+ let result = value;
626
+ if (result.startsWith(before)) {
627
+ result = result.substring(before.length);
628
+ }
629
+ if (result.endsWith(actualAfter)) {
630
+ result = result.substring(0, result.length - actualAfter.length);
631
+ }
632
+ return result;
633
+ }
634
+ /**
635
+ * Get the number of words a string contains
636
+ */
637
+ static wordCount(value) {
638
+ return value.trim().split(/\s+/).filter((word) => word.length > 0).length;
639
+ }
640
+ /**
641
+ * Wrap a string to a given number of characters
642
+ */
643
+ static wordWrap(value, characters = 75, breakStr = "\n") {
644
+ const words = value.split(" ");
645
+ let line = "";
646
+ const lines = [];
647
+ words.forEach((word) => {
648
+ if ((line + word).length > characters) {
649
+ if (line) lines.push(line.trim());
650
+ line = word + " ";
651
+ } else {
652
+ line += word + " ";
653
+ }
654
+ });
655
+ if (line) lines.push(line.trim());
656
+ return lines.join(breakStr);
657
+ }
658
+ /**
659
+ * Limit the number of words in a string
660
+ */
661
+ static words(value, words = 100, end = "...") {
662
+ const wordArray = value.split(/\s+/);
663
+ if (wordArray.length <= words) return value;
664
+ return wordArray.slice(0, words).join(" ") + end;
665
+ }
666
+ /**
667
+ * Wrap the string with the given strings
668
+ */
669
+ static wrap(value, before, after) {
670
+ const actualAfter = after ?? before;
671
+ return before + value + actualAfter;
672
+ }
673
+ };
674
+
675
+ // src/collections/collection.ts
676
+ var import_collect = __toESM(require("collect.js"), 1);
677
+ var Collection = class _Collection {
678
+ constructor(items = []) {
679
+ this.collection = (0, import_collect.default)(items);
680
+ }
681
+ /**
682
+ * Create a new collection instance
683
+ */
684
+ static make(items = []) {
685
+ return new _Collection(items);
686
+ }
687
+ /**
688
+ * Get all items in the collection
689
+ */
690
+ all() {
691
+ return this.collection.all();
692
+ }
693
+ /**
694
+ * Get the average value of a given key
695
+ */
696
+ avg(key) {
697
+ return this.collection.avg(key);
698
+ }
699
+ /**
700
+ * Chunk the collection into chunks of the given size
701
+ */
702
+ chunk(size) {
703
+ return new _Collection(this.collection.chunk(size).all());
704
+ }
705
+ /**
706
+ * Collapse a collection of arrays into a single, flat collection
707
+ */
708
+ collapse() {
709
+ return new _Collection(this.collection.collapse().all());
710
+ }
711
+ /**
712
+ * Determine if an item exists in the collection
713
+ */
714
+ contains(key, value) {
715
+ return this.collection.contains(key, value);
716
+ }
717
+ /**
718
+ * Get the total number of items in the collection
719
+ */
720
+ count() {
721
+ return this.collection.count();
722
+ }
723
+ /**
724
+ * Get the items in the collection that are not present in the given items
725
+ */
726
+ diff(items) {
727
+ return new _Collection(this.collection.diff(items).all());
728
+ }
729
+ /**
730
+ * Execute a callback over each item
731
+ */
732
+ each(callback) {
733
+ this.collection.each(callback);
734
+ return this;
735
+ }
736
+ /**
737
+ * Determine if all items pass the given test
738
+ */
739
+ every(callback) {
740
+ return this.collection.every(callback);
741
+ }
742
+ /**
743
+ * Get all items except for those with the specified keys
744
+ */
745
+ except(keys) {
746
+ return new _Collection(this.collection.except(keys).all());
747
+ }
748
+ /**
749
+ * Run a filter over each of the items
750
+ */
751
+ filter(callback) {
752
+ return new _Collection(this.collection.filter(callback).all());
753
+ }
754
+ /**
755
+ * Get the first item from the collection
756
+ */
757
+ first(callback) {
758
+ return this.collection.first(callback);
759
+ }
760
+ /**
761
+ * Get a flattened array of the items in the collection
762
+ */
763
+ flatten(depth) {
764
+ return new _Collection(this.collection.flatten(depth).all());
765
+ }
766
+ /**
767
+ * Flip the items in the collection
768
+ */
769
+ flip() {
770
+ return new _Collection(this.collection.flip().all());
771
+ }
772
+ /**
773
+ * Remove an item from the collection by key
774
+ */
775
+ forget(key) {
776
+ this.collection.forget(key);
777
+ return this;
778
+ }
779
+ /**
780
+ * Get an item from the collection by key
781
+ */
782
+ get(key, defaultValue) {
783
+ const result = this.collection.get(key, defaultValue);
784
+ return result === null ? void 0 : result;
785
+ }
786
+ /**
787
+ * Group the collection's items by a given key
788
+ */
789
+ groupBy(key) {
790
+ const grouped = this.collection.groupBy(key);
791
+ const result = {};
792
+ grouped.each((items, groupKey) => {
793
+ result[groupKey] = new _Collection(items.all());
794
+ });
795
+ return new _Collection(Object.values(result));
796
+ }
797
+ /**
798
+ * Determine if a given key exists in the collection
799
+ */
800
+ has(key) {
801
+ return this.collection.has(key);
802
+ }
803
+ /**
804
+ * Concatenate values of a given key as a string
805
+ */
806
+ implode(key, glue) {
807
+ return this.collection.implode(key, glue);
808
+ }
809
+ /**
810
+ * Intersect the collection with the given items
811
+ */
812
+ intersect(items) {
813
+ return new _Collection(this.collection.intersect(items).all());
814
+ }
815
+ /**
816
+ * Determine if the collection is empty
817
+ */
818
+ isEmpty() {
819
+ return this.collection.isEmpty();
820
+ }
821
+ /**
822
+ * Determine if the collection is not empty
823
+ */
824
+ isNotEmpty() {
825
+ return this.collection.isNotEmpty();
826
+ }
827
+ /**
828
+ * Join all items from the collection using a string
829
+ */
830
+ join(glue, finalGlue) {
831
+ return this.collection.join(glue, finalGlue);
832
+ }
833
+ /**
834
+ * Key the collection by the given key
835
+ */
836
+ keyBy(key) {
837
+ return new _Collection(this.collection.keyBy(key).all());
838
+ }
839
+ /**
840
+ * Get the keys of the collection items
841
+ */
842
+ keys() {
843
+ return new _Collection(this.collection.keys().all());
844
+ }
845
+ /**
846
+ * Get the last item from the collection
847
+ */
848
+ last(callback) {
849
+ return this.collection.last(callback);
850
+ }
851
+ /**
852
+ * Run a map over each of the items
853
+ */
854
+ map(callback) {
855
+ return new _Collection(this.collection.map(callback).all());
856
+ }
857
+ /**
858
+ * Get the max value of a given key
859
+ */
860
+ max(key) {
861
+ return this.collection.max(key);
862
+ }
863
+ /**
864
+ * Merge the collection with the given items
865
+ */
866
+ merge(items) {
867
+ return new _Collection(this.collection.merge(items).all());
868
+ }
869
+ /**
870
+ * Get the min value of a given key
871
+ */
872
+ min(key) {
873
+ return this.collection.min(key);
874
+ }
875
+ /**
876
+ * Get the items with the specified keys
877
+ */
878
+ only(keys) {
879
+ return new _Collection(this.collection.only(keys).all());
880
+ }
881
+ /**
882
+ * Get and remove the last item from the collection
883
+ */
884
+ pop() {
885
+ return this.collection.pop();
886
+ }
887
+ /**
888
+ * Push an item onto the beginning of the collection
889
+ */
890
+ prepend(value) {
891
+ this.collection.prepend(value);
892
+ return this;
893
+ }
894
+ /**
895
+ * Get and remove an item from the collection
896
+ */
897
+ pull(key) {
898
+ const result = this.collection.pull(key);
899
+ return result === null ? void 0 : result;
900
+ }
901
+ /**
902
+ * Push an item onto the end of the collection
903
+ */
904
+ push(value) {
905
+ this.collection.push(value);
906
+ return this;
907
+ }
908
+ /**
909
+ * Put an item in the collection by key
910
+ */
911
+ put(key, value) {
912
+ this.collection.put(key, value);
913
+ return this;
914
+ }
915
+ /**
916
+ * Get one or a specified number of items randomly from the collection
917
+ */
918
+ random(count) {
919
+ if (count) {
920
+ const result = this.collection.random(count);
921
+ return new _Collection(result.all());
922
+ }
923
+ return this.collection.random();
924
+ }
925
+ /**
926
+ * Reduce the collection to a single value
927
+ */
928
+ reduce(callback, initial) {
929
+ return this.collection.reduce(callback, initial);
930
+ }
931
+ /**
932
+ * Filter items by the given key value pair
933
+ */
934
+ reject(callback) {
935
+ return new _Collection(this.collection.reject(callback).all());
936
+ }
937
+ /**
938
+ * Reverse items order
939
+ */
940
+ reverse() {
941
+ return new _Collection(this.collection.reverse().all());
942
+ }
943
+ /**
944
+ * Search the collection for a given value
945
+ */
946
+ search(value) {
947
+ const result = this.collection.search(value);
948
+ return result === false ? false : result;
949
+ }
950
+ /**
951
+ * Get and remove the first item from the collection
952
+ */
953
+ shift() {
954
+ return this.collection.shift();
955
+ }
956
+ /**
957
+ * Shuffle the items in the collection
958
+ */
959
+ shuffle() {
960
+ return new _Collection(this.collection.shuffle().all());
961
+ }
962
+ /**
963
+ * Slice the underlying collection array
964
+ */
965
+ slice(start, length) {
966
+ return new _Collection(this.collection.slice(start, length).all());
967
+ }
968
+ /**
969
+ * Sort through each item with a callback
970
+ */
971
+ sort(callback) {
972
+ return new _Collection(this.collection.sort(callback).all());
973
+ }
974
+ /**
975
+ * Sort the collection by the given key
976
+ */
977
+ sortBy(key) {
978
+ return new _Collection(this.collection.sortBy(key).all());
979
+ }
980
+ /**
981
+ * Sort the collection in descending order by the given key
982
+ */
983
+ sortByDesc(key) {
984
+ return new _Collection(this.collection.sortByDesc(key).all());
985
+ }
986
+ /**
987
+ * Splice a portion of the underlying collection array
988
+ */
989
+ splice(start, length, ...items) {
990
+ const actualLength = length ?? 0;
991
+ const itemsArray = items;
992
+ return new _Collection(this.collection.splice(start, actualLength, ...itemsArray).all());
993
+ }
994
+ /**
995
+ * Get the sum of the given values
996
+ */
997
+ sum(key) {
998
+ const result = this.collection.sum(key);
999
+ return typeof result === "number" ? result : 0;
1000
+ }
1001
+ /**
1002
+ * Take the first or last {limit} items
1003
+ */
1004
+ take(limit) {
1005
+ return new _Collection(this.collection.take(limit).all());
1006
+ }
1007
+ /**
1008
+ * Pass the collection to the given callback and return the result
1009
+ */
1010
+ pipe(callback) {
1011
+ return callback(this);
1012
+ }
1013
+ /**
1014
+ * Pass the collection to the given callback and then return it
1015
+ */
1016
+ tap(callback) {
1017
+ callback(this);
1018
+ return this;
1019
+ }
1020
+ /**
1021
+ * Transform each item in the collection using a callback
1022
+ */
1023
+ transform(callback) {
1024
+ this.collection = this.collection.map(callback);
1025
+ return this;
1026
+ }
1027
+ /**
1028
+ * Return only unique items from the collection array
1029
+ */
1030
+ unique(key) {
1031
+ return new _Collection(this.collection.unique(key).all());
1032
+ }
1033
+ /**
1034
+ * Reset the keys on the underlying array
1035
+ */
1036
+ values() {
1037
+ return new _Collection(this.collection.values().all());
1038
+ }
1039
+ where(key, operatorOrValue, value) {
1040
+ if (value === void 0) {
1041
+ return new _Collection(this.collection.where(key, operatorOrValue).all());
1042
+ }
1043
+ return new _Collection(this.collection.where(key, operatorOrValue, value).all());
1044
+ }
1045
+ /**
1046
+ * Filter items by the given key value pair using loose comparison
1047
+ */
1048
+ whereIn(key, values) {
1049
+ return new _Collection(this.collection.whereIn(key, values).all());
1050
+ }
1051
+ /**
1052
+ * Filter items by the given key value pair using loose comparison
1053
+ */
1054
+ whereNotIn(key, values) {
1055
+ return new _Collection(this.collection.whereNotIn(key, values).all());
1056
+ }
1057
+ /**
1058
+ * Zip the collection together with one or more arrays
1059
+ */
1060
+ zip(...arrays) {
1061
+ const zipArgs = arrays;
1062
+ return new _Collection(this.collection.zip(...zipArgs).all());
1063
+ }
1064
+ /**
1065
+ * Convert the collection to a plain array
1066
+ */
1067
+ toArray() {
1068
+ return this.all();
1069
+ }
1070
+ /**
1071
+ * Convert the collection to JSON
1072
+ */
1073
+ toJson() {
1074
+ return JSON.stringify(this.all());
1075
+ }
1076
+ /**
1077
+ * Get the collection as a string
1078
+ */
1079
+ toString() {
1080
+ return this.toJson();
1081
+ }
1082
+ };
1083
+ function collect(items = []) {
1084
+ return new Collection(items);
1085
+ }
1086
+
1087
+ // src/collections/map.collection.ts
1088
+ var MapCollection = class _MapCollection {
1089
+ constructor(entries) {
1090
+ if (entries && typeof entries === "object" && !(Symbol.iterator in entries)) {
1091
+ this.internalMap = new Map(Object.entries(entries));
1092
+ } else {
1093
+ this.internalMap = new Map(entries);
1094
+ }
1095
+ }
1096
+ /**
1097
+ * Create a new map collection instance
1098
+ */
1099
+ static make(entries) {
1100
+ return new _MapCollection(entries);
1101
+ }
1102
+ /**
1103
+ * Get all entries as an array of [key, value] pairs
1104
+ */
1105
+ all() {
1106
+ return Array.from(this.internalMap.entries());
1107
+ }
1108
+ /**
1109
+ * Get the number of items in the map
1110
+ */
1111
+ count() {
1112
+ return this.internalMap.size;
1113
+ }
1114
+ /**
1115
+ * Get the number of items in the map (alias for count)
1116
+ */
1117
+ size() {
1118
+ return this.internalMap.size;
1119
+ }
1120
+ /**
1121
+ * Determine if the map is empty
1122
+ */
1123
+ isEmpty() {
1124
+ return this.internalMap.size === 0;
1125
+ }
1126
+ /**
1127
+ * Determine if the map is not empty
1128
+ */
1129
+ isNotEmpty() {
1130
+ return this.internalMap.size > 0;
1131
+ }
1132
+ /**
1133
+ * Determine if a key exists in the map
1134
+ */
1135
+ has(key) {
1136
+ return this.internalMap.has(key);
1137
+ }
1138
+ /**
1139
+ * Get a value from the map by key
1140
+ */
1141
+ get(key, defaultValue) {
1142
+ return this.internalMap.has(key) ? this.internalMap.get(key) : defaultValue;
1143
+ }
1144
+ /**
1145
+ * Set a value in the map
1146
+ */
1147
+ set(key, value) {
1148
+ this.internalMap.set(key, value);
1149
+ return this;
1150
+ }
1151
+ /**
1152
+ * Put a value in the map (alias for set)
1153
+ */
1154
+ put(key, value) {
1155
+ return this.set(key, value);
1156
+ }
1157
+ /**
1158
+ * Remove a key from the map
1159
+ */
1160
+ delete(key) {
1161
+ return this.internalMap.delete(key);
1162
+ }
1163
+ /**
1164
+ * Remove a key from the map (alias for delete)
1165
+ */
1166
+ forget(key) {
1167
+ return this.delete(key);
1168
+ }
1169
+ /**
1170
+ * Remove all items from the map
1171
+ */
1172
+ clear() {
1173
+ this.internalMap.clear();
1174
+ return this;
1175
+ }
1176
+ /**
1177
+ * Get all keys from the map
1178
+ */
1179
+ keys() {
1180
+ return Array.from(this.internalMap.keys());
1181
+ }
1182
+ /**
1183
+ * Get all values from the map
1184
+ */
1185
+ values() {
1186
+ return Array.from(this.internalMap.values());
1187
+ }
1188
+ /**
1189
+ * Execute a callback over each item
1190
+ */
1191
+ each(callback) {
1192
+ for (const [key, value] of this.internalMap) {
1193
+ if (callback(value, key) === false) {
1194
+ break;
1195
+ }
1196
+ }
1197
+ return this;
1198
+ }
1199
+ /**
1200
+ * Run a map over each of the items
1201
+ */
1202
+ mapValues(callback) {
1203
+ const result = /* @__PURE__ */ new Map();
1204
+ this.internalMap.forEach((value, key) => {
1205
+ result.set(key, callback(value, key));
1206
+ });
1207
+ return new _MapCollection(result);
1208
+ }
1209
+ /**
1210
+ * Run a filter over each of the items
1211
+ */
1212
+ filter(callback) {
1213
+ const result = /* @__PURE__ */ new Map();
1214
+ this.internalMap.forEach((value, key) => {
1215
+ if (callback(value, key)) {
1216
+ result.set(key, value);
1217
+ }
1218
+ });
1219
+ return new _MapCollection(result);
1220
+ }
1221
+ /**
1222
+ * Determine if all items pass the given test
1223
+ */
1224
+ every(callback) {
1225
+ for (const [key, value] of this.internalMap) {
1226
+ if (!callback(value, key)) {
1227
+ return false;
1228
+ }
1229
+ }
1230
+ return true;
1231
+ }
1232
+ /**
1233
+ * Determine if any item passes the given test
1234
+ */
1235
+ some(callback) {
1236
+ for (const [key, value] of this.internalMap) {
1237
+ if (callback(value, key)) {
1238
+ return true;
1239
+ }
1240
+ }
1241
+ return false;
1242
+ }
1243
+ /**
1244
+ * Get the first value that passes the given test
1245
+ */
1246
+ first(callback) {
1247
+ if (!callback) {
1248
+ return this.internalMap.values().next().value;
1249
+ }
1250
+ for (const [key, value] of this.internalMap) {
1251
+ if (callback(value, key)) {
1252
+ return value;
1253
+ }
1254
+ }
1255
+ return void 0;
1256
+ }
1257
+ /**
1258
+ * Get the last value that passes the given test
1259
+ */
1260
+ last(callback) {
1261
+ const entries = Array.from(this.internalMap.entries()).reverse();
1262
+ if (!callback) {
1263
+ return entries[0]?.[1];
1264
+ }
1265
+ for (const [key, value] of entries) {
1266
+ if (callback(value, key)) {
1267
+ return value;
1268
+ }
1269
+ }
1270
+ return void 0;
1271
+ }
1272
+ /**
1273
+ * Reduce the map to a single value
1274
+ */
1275
+ reduce(callback, initial) {
1276
+ let carry = initial;
1277
+ this.internalMap.forEach((value, key) => {
1278
+ carry = callback(carry, value, key);
1279
+ });
1280
+ return carry;
1281
+ }
1282
+ /**
1283
+ * Merge another map into this one
1284
+ */
1285
+ merge(other) {
1286
+ if (other instanceof _MapCollection) {
1287
+ other.each((value, key) => {
1288
+ this.set(key, value);
1289
+ return void 0;
1290
+ });
1291
+ } else if (other instanceof Map) {
1292
+ other.forEach((value, key) => this.set(key, value));
1293
+ } else {
1294
+ Object.entries(other).forEach(([key, value]) => {
1295
+ this.set(key, value);
1296
+ });
1297
+ }
1298
+ return this;
1299
+ }
1300
+ /**
1301
+ * Get only the specified keys
1302
+ */
1303
+ only(keys) {
1304
+ const result = /* @__PURE__ */ new Map();
1305
+ keys.forEach((key) => {
1306
+ if (this.internalMap.has(key)) {
1307
+ result.set(key, this.internalMap.get(key));
1308
+ }
1309
+ });
1310
+ return new _MapCollection(result);
1311
+ }
1312
+ /**
1313
+ * Get all items except the specified keys
1314
+ */
1315
+ except(keys) {
1316
+ const result = /* @__PURE__ */ new Map();
1317
+ this.internalMap.forEach((value, key) => {
1318
+ if (!keys.includes(key)) {
1319
+ result.set(key, value);
1320
+ }
1321
+ });
1322
+ return new _MapCollection(result);
1323
+ }
1324
+ /**
1325
+ * Flip the keys and values
1326
+ */
1327
+ flip() {
1328
+ const result = /* @__PURE__ */ new Map();
1329
+ this.internalMap.forEach((value, key) => {
1330
+ result.set(value, key);
1331
+ });
1332
+ return new _MapCollection(result);
1333
+ }
1334
+ /**
1335
+ * Pass the map to the given callback and return the result
1336
+ */
1337
+ pipe(callback) {
1338
+ return callback(this);
1339
+ }
1340
+ /**
1341
+ * Pass the map to the given callback and then return it
1342
+ */
1343
+ tap(callback) {
1344
+ callback(this);
1345
+ return this;
1346
+ }
1347
+ /**
1348
+ * Convert the map to a plain object
1349
+ */
1350
+ toObject() {
1351
+ const obj = {};
1352
+ this.internalMap.forEach((value, key) => {
1353
+ obj[String(key)] = value;
1354
+ });
1355
+ return obj;
1356
+ }
1357
+ /**
1358
+ * Convert the map to an array of [key, value] pairs
1359
+ */
1360
+ toArray() {
1361
+ return this.all();
1362
+ }
1363
+ /**
1364
+ * Convert the map to JSON
1365
+ */
1366
+ toJson() {
1367
+ return JSON.stringify(this.toObject());
1368
+ }
1369
+ /**
1370
+ * Get the map as a string
1371
+ */
1372
+ toString() {
1373
+ return this.toJson();
1374
+ }
1375
+ /**
1376
+ * Get the underlying Map instance
1377
+ */
1378
+ toMap() {
1379
+ return new Map(this.internalMap);
1380
+ }
1381
+ };
1382
+ function collectMap(entries) {
1383
+ return new MapCollection(entries);
1384
+ }
1385
+
1386
+ // src/collections/set.collection.ts
1387
+ var SetCollection = class _SetCollection {
1388
+ constructor(items) {
1389
+ this.set = new Set(items);
1390
+ }
1391
+ /**
1392
+ * Create a new set collection instance
1393
+ */
1394
+ static make(items) {
1395
+ return new _SetCollection(items);
1396
+ }
1397
+ /**
1398
+ * Get all items as an array
1399
+ */
1400
+ all() {
1401
+ return Array.from(this.set);
1402
+ }
1403
+ /**
1404
+ * Get the number of items in the set
1405
+ */
1406
+ count() {
1407
+ return this.set.size;
1408
+ }
1409
+ /**
1410
+ * Get the number of items in the set (alias for count)
1411
+ */
1412
+ size() {
1413
+ return this.set.size;
1414
+ }
1415
+ /**
1416
+ * Determine if the set is empty
1417
+ */
1418
+ isEmpty() {
1419
+ return this.set.size === 0;
1420
+ }
1421
+ /**
1422
+ * Determine if the set is not empty
1423
+ */
1424
+ isNotEmpty() {
1425
+ return this.set.size > 0;
1426
+ }
1427
+ /**
1428
+ * Determine if an item exists in the set
1429
+ */
1430
+ has(item) {
1431
+ return this.set.has(item);
1432
+ }
1433
+ /**
1434
+ * Determine if an item exists in the set (alias for has)
1435
+ */
1436
+ contains(item) {
1437
+ return this.has(item);
1438
+ }
1439
+ /**
1440
+ * Add an item to the set
1441
+ */
1442
+ add(item) {
1443
+ this.set.add(item);
1444
+ return this;
1445
+ }
1446
+ /**
1447
+ * Add an item to the set (alias for add)
1448
+ */
1449
+ push(item) {
1450
+ return this.add(item);
1451
+ }
1452
+ /**
1453
+ * Remove an item from the set
1454
+ */
1455
+ delete(item) {
1456
+ return this.set.delete(item);
1457
+ }
1458
+ /**
1459
+ * Remove an item from the set (alias for delete)
1460
+ */
1461
+ forget(item) {
1462
+ return this.delete(item);
1463
+ }
1464
+ /**
1465
+ * Remove all items from the set
1466
+ */
1467
+ clear() {
1468
+ this.set.clear();
1469
+ return this;
1470
+ }
1471
+ /**
1472
+ * Execute a callback over each item
1473
+ */
1474
+ each(callback) {
1475
+ let index = 0;
1476
+ for (const item of this.set) {
1477
+ if (callback(item, index++) === false) {
1478
+ break;
1479
+ }
1480
+ }
1481
+ return this;
1482
+ }
1483
+ /**
1484
+ * Run a map over each of the items
1485
+ */
1486
+ map(callback) {
1487
+ const result = /* @__PURE__ */ new Set();
1488
+ let index = 0;
1489
+ this.set.forEach((item) => {
1490
+ result.add(callback(item, index++));
1491
+ });
1492
+ return new _SetCollection(result);
1493
+ }
1494
+ /**
1495
+ * Run a filter over each of the items
1496
+ */
1497
+ filter(callback) {
1498
+ const result = /* @__PURE__ */ new Set();
1499
+ let index = 0;
1500
+ this.set.forEach((item) => {
1501
+ if (callback(item, index++)) {
1502
+ result.add(item);
1503
+ }
1504
+ });
1505
+ return new _SetCollection(result);
1506
+ }
1507
+ /**
1508
+ * Determine if all items pass the given test
1509
+ */
1510
+ every(callback) {
1511
+ let index = 0;
1512
+ for (const item of this.set) {
1513
+ if (!callback(item, index++)) {
1514
+ return false;
1515
+ }
1516
+ }
1517
+ return true;
1518
+ }
1519
+ /**
1520
+ * Determine if any item passes the given test
1521
+ */
1522
+ some(callback) {
1523
+ let index = 0;
1524
+ for (const item of this.set) {
1525
+ if (callback(item, index++)) {
1526
+ return true;
1527
+ }
1528
+ }
1529
+ return false;
1530
+ }
1531
+ /**
1532
+ * Get the first item that passes the given test
1533
+ */
1534
+ first(callback) {
1535
+ if (!callback) {
1536
+ return this.set.values().next().value;
1537
+ }
1538
+ let index = 0;
1539
+ for (const item of this.set) {
1540
+ if (callback(item, index++)) {
1541
+ return item;
1542
+ }
1543
+ }
1544
+ return void 0;
1545
+ }
1546
+ /**
1547
+ * Get the last item that passes the given test
1548
+ */
1549
+ last(callback) {
1550
+ const items = Array.from(this.set).reverse();
1551
+ if (!callback) {
1552
+ return items[0];
1553
+ }
1554
+ for (let i = 0; i < items.length; i++) {
1555
+ if (callback(items[i], i)) {
1556
+ return items[i];
1557
+ }
1558
+ }
1559
+ return void 0;
1560
+ }
1561
+ /**
1562
+ * Reduce the set to a single value
1563
+ */
1564
+ reduce(callback, initial) {
1565
+ let carry = initial;
1566
+ let index = 0;
1567
+ this.set.forEach((item) => {
1568
+ carry = callback(carry, item, index++);
1569
+ });
1570
+ return carry;
1571
+ }
1572
+ /**
1573
+ * Merge another set into this one
1574
+ */
1575
+ merge(other) {
1576
+ if (other instanceof _SetCollection) {
1577
+ other.each((item) => {
1578
+ this.add(item);
1579
+ return void 0;
1580
+ });
1581
+ } else if (other instanceof Set) {
1582
+ other.forEach((item) => this.add(item));
1583
+ } else {
1584
+ other.forEach((item) => this.add(item));
1585
+ }
1586
+ return this;
1587
+ }
1588
+ /**
1589
+ * Get the union of this set and another
1590
+ */
1591
+ union(other) {
1592
+ const result = new _SetCollection(this.set);
1593
+ return result.merge(other);
1594
+ }
1595
+ /**
1596
+ * Get the intersection of this set and another
1597
+ */
1598
+ intersect(other) {
1599
+ const otherSet = other instanceof _SetCollection ? other.toSet() : other instanceof Set ? other : new Set(other);
1600
+ const result = /* @__PURE__ */ new Set();
1601
+ this.set.forEach((item) => {
1602
+ if (otherSet.has(item)) {
1603
+ result.add(item);
1604
+ }
1605
+ });
1606
+ return new _SetCollection(result);
1607
+ }
1608
+ /**
1609
+ * Get the difference between this set and another
1610
+ */
1611
+ diff(other) {
1612
+ const otherSet = other instanceof _SetCollection ? other.toSet() : other instanceof Set ? other : new Set(other);
1613
+ const result = /* @__PURE__ */ new Set();
1614
+ this.set.forEach((item) => {
1615
+ if (!otherSet.has(item)) {
1616
+ result.add(item);
1617
+ }
1618
+ });
1619
+ return new _SetCollection(result);
1620
+ }
1621
+ /**
1622
+ * Get items that are in either set but not in both
1623
+ */
1624
+ symmetricDiff(other) {
1625
+ const otherSet = other instanceof _SetCollection ? other.toSet() : other instanceof Set ? other : new Set(other);
1626
+ const result = /* @__PURE__ */ new Set();
1627
+ this.set.forEach((item) => {
1628
+ if (!otherSet.has(item)) {
1629
+ result.add(item);
1630
+ }
1631
+ });
1632
+ otherSet.forEach((item) => {
1633
+ if (!this.set.has(item)) {
1634
+ result.add(item);
1635
+ }
1636
+ });
1637
+ return new _SetCollection(result);
1638
+ }
1639
+ /**
1640
+ * Determine if this set is a subset of another
1641
+ */
1642
+ isSubsetOf(other) {
1643
+ const otherSet = other instanceof _SetCollection ? other.toSet() : other instanceof Set ? other : new Set(other);
1644
+ for (const item of this.set) {
1645
+ if (!otherSet.has(item)) {
1646
+ return false;
1647
+ }
1648
+ }
1649
+ return true;
1650
+ }
1651
+ /**
1652
+ * Determine if this set is a superset of another
1653
+ */
1654
+ isSupersetOf(other) {
1655
+ const otherSet = other instanceof _SetCollection ? other.toSet() : other instanceof Set ? other : new Set(other);
1656
+ for (const item of otherSet) {
1657
+ if (!this.set.has(item)) {
1658
+ return false;
1659
+ }
1660
+ }
1661
+ return true;
1662
+ }
1663
+ /**
1664
+ * Pass the set to the given callback and return the result
1665
+ */
1666
+ pipe(callback) {
1667
+ return callback(this);
1668
+ }
1669
+ /**
1670
+ * Pass the set to the given callback and then return it
1671
+ */
1672
+ tap(callback) {
1673
+ callback(this);
1674
+ return this;
1675
+ }
1676
+ /**
1677
+ * Convert the set to an array
1678
+ */
1679
+ toArray() {
1680
+ return this.all();
1681
+ }
1682
+ /**
1683
+ * Convert the set to JSON
1684
+ */
1685
+ toJson() {
1686
+ return JSON.stringify(this.all());
1687
+ }
1688
+ /**
1689
+ * Get the set as a string
1690
+ */
1691
+ toString() {
1692
+ return this.toJson();
1693
+ }
1694
+ /**
1695
+ * Get the underlying Set instance
1696
+ */
1697
+ toSet() {
1698
+ return new Set(this.set);
1699
+ }
1700
+ };
1701
+ function collectSet(items) {
1702
+ return new SetCollection(items);
1703
+ }
1704
+
1705
+ // src/registry/base-registry.ts
1706
+ var RegistryCollection = class {
1707
+ constructor() {
1708
+ this._storage = new MapCollection();
1709
+ }
1710
+ add(key, value) {
1711
+ this._storage.set(key, value);
1712
+ }
1713
+ get(key) {
1714
+ return this._storage.get(key);
1715
+ }
1716
+ getAll() {
1717
+ return this._storage.values();
1718
+ }
1719
+ getKeys() {
1720
+ return this._storage.keys();
1721
+ }
1722
+ getAsRecord() {
1723
+ return this._storage.toObject();
1724
+ }
1725
+ has(key) {
1726
+ return this._storage.has(key);
1727
+ }
1728
+ remove(key) {
1729
+ return this._storage.delete(key);
1730
+ }
1731
+ clear() {
1732
+ this._storage.clear();
1733
+ }
1734
+ size() {
1735
+ return this._storage.size();
1736
+ }
1737
+ isEmpty() {
1738
+ return this._storage.isEmpty();
1739
+ }
1740
+ forEach(callback) {
1741
+ this._storage.each((value, key) => {
1742
+ callback(value, key);
1743
+ });
1744
+ }
1745
+ map(callback) {
1746
+ const result = [];
1747
+ this._storage.each((value, key) => {
1748
+ result.push(callback(value, key));
1749
+ });
1750
+ return result;
1751
+ }
1752
+ filter(predicate) {
1753
+ const result = [];
1754
+ this._storage.each((value, key) => {
1755
+ if (predicate(value, key)) {
1756
+ result.push(value);
1757
+ }
1758
+ });
1759
+ return result;
1760
+ }
1761
+ find(predicate) {
1762
+ return this._storage.first(predicate);
1763
+ }
1764
+ };
1765
+ var BaseRegistry = class {
1766
+ /**
1767
+ * Creates a new BaseRegistry instance
1768
+ *
1769
+ * Initializes the registry with optional configuration for default
1770
+ * item and validation hooks. By default, uses MapCollection for storage.
1771
+ *
1772
+ * @param options - Registry configuration options
1773
+ *
1774
+ * @example
1775
+ * ```typescript
1776
+ * // Simple registry without options
1777
+ * const registry = new BaseRegistry<Theme>();
1778
+ * ```
1779
+ *
1780
+ * @example
1781
+ * ```typescript
1782
+ * // Registry with default item
1783
+ * const registry = new BaseRegistry<Theme>({
1784
+ * defaultItem: defaultTheme
1785
+ * });
1786
+ * ```
1787
+ *
1788
+ * @example
1789
+ * ```typescript
1790
+ * // Registry with validation
1791
+ * const registry = new BaseRegistry<Theme>({
1792
+ * validateBeforeAdd: (key, theme) => {
1793
+ * if (!theme.name) {
1794
+ * return { valid: false, error: 'Theme must have a name' };
1795
+ * }
1796
+ * return { valid: true };
1797
+ * },
1798
+ * afterAdd: (key, theme) => {
1799
+ * console.log(`Registered theme: ${theme.name}`);
1800
+ * }
1801
+ * });
1802
+ * ```
1803
+ */
1804
+ constructor(options = {}) {
1805
+ this.collection = new RegistryCollection();
1806
+ this.defaultItem = options.defaultItem;
1807
+ this.validateBeforeAdd = options.validateBeforeAdd;
1808
+ this.afterAdd = options.afterAdd;
1809
+ }
1810
+ /**
1811
+ * Register an item in the registry
1812
+ *
1813
+ * Adds or updates an item in the registry with the specified key.
1814
+ * If an item with the same key already exists, it will be replaced.
1815
+ *
1816
+ * If a validation hook is configured, it will be called before adding
1817
+ * the item. If validation fails, an error is thrown and the item is
1818
+ * not added.
1819
+ *
1820
+ * If an afterAdd hook is configured, it will be called after the item
1821
+ * is successfully added.
1822
+ *
1823
+ * Time Complexity: O(1) + validation time
1824
+ *
1825
+ * @param key - Unique identifier for the item
1826
+ * @param item - Item to register
1827
+ * @throws Error if validation fails
1828
+ *
1829
+ * @example
1830
+ * ```typescript
1831
+ * const registry = new BaseRegistry<Theme>();
1832
+ *
1833
+ * // Register a theme
1834
+ * registry.register('blue', {
1835
+ * name: 'Blue',
1836
+ * colors: { accent: '#0000FF' }
1837
+ * });
1838
+ *
1839
+ * // Update existing theme
1840
+ * registry.register('blue', {
1841
+ * name: 'Blue',
1842
+ * colors: { accent: '#0066FF' }
1843
+ * });
1844
+ * ```
1845
+ */
1846
+ register(key, item) {
1847
+ if (this.validateBeforeAdd) {
1848
+ const result = this.validateBeforeAdd(key, item);
1849
+ if (!result.valid) {
1850
+ throw new Error(
1851
+ `Validation failed for key "${key}": ${result.error || "Unknown error"}`
1852
+ );
1853
+ }
1854
+ }
1855
+ this.collection.add(key, item);
1856
+ if (this.afterAdd) {
1857
+ this.afterAdd(key, item);
1858
+ }
1859
+ }
1860
+ // ============================================================================
1861
+ // Collection Interface Implementation
1862
+ // All methods below delegate directly to the internal collection
1863
+ // ============================================================================
1864
+ /**
1865
+ * Add an item to the collection (alias for register)
1866
+ *
1867
+ * This method is part of the Collection interface.
1868
+ * It delegates to register() to ensure validation hooks are called.
1869
+ *
1870
+ * Time Complexity: O(1) + validation time
1871
+ *
1872
+ * @param key - Unique identifier for the item
1873
+ * @param value - Item to add
1874
+ */
1875
+ add(key, value) {
1876
+ this.register(key, value);
1877
+ }
1878
+ /**
1879
+ * Get an item from the registry
1880
+ *
1881
+ * Retrieves an item by its key. If the item doesn't exist:
1882
+ * - Returns the default item if one was configured
1883
+ * - Returns undefined if no default item was configured
1884
+ *
1885
+ * Time Complexity: O(1)
1886
+ *
1887
+ * @param key - Item identifier
1888
+ * @returns Item if found, default item if configured, or undefined
1889
+ *
1890
+ * @example
1891
+ * ```typescript
1892
+ * const theme = registry.get('blue');
1893
+ * ```
1894
+ */
1895
+ get(key) {
1896
+ const item = this.collection.get(key);
1897
+ if (item !== void 0) {
1898
+ return item;
1899
+ }
1900
+ return this.defaultItem;
1901
+ }
1902
+ /**
1903
+ * Get all items in the registry
1904
+ *
1905
+ * Returns an array containing all items in the registry.
1906
+ * The order of items depends on the collection implementation
1907
+ * (MapCollection maintains insertion order).
1908
+ *
1909
+ * Time Complexity: O(n) where n is the number of items
1910
+ *
1911
+ * @returns Array of all items in the registry
1912
+ *
1913
+ * @example
1914
+ * ```typescript
1915
+ * const allThemes = registry.getAll();
1916
+ * ```
1917
+ */
1918
+ getAll() {
1919
+ return this.collection.getAll();
1920
+ }
1921
+ /**
1922
+ * Get all keys in the registry
1923
+ *
1924
+ * Returns an array containing all keys in the registry.
1925
+ * Useful for iteration or checking what items are registered.
1926
+ *
1927
+ * Time Complexity: O(n) where n is the number of items
1928
+ *
1929
+ * @returns Array of all keys in the registry
1930
+ *
1931
+ * @example
1932
+ * ```typescript
1933
+ * const keys = registry.getKeys();
1934
+ * ```
1935
+ */
1936
+ getKeys() {
1937
+ return this.collection.getKeys();
1938
+ }
1939
+ /**
1940
+ * Get registry as a record object
1941
+ *
1942
+ * Converts the registry to a plain JavaScript object (record)
1943
+ * with keys mapping to values. Useful for serialization.
1944
+ *
1945
+ * Time Complexity: O(n) where n is the number of items
1946
+ *
1947
+ * @returns Record object with keys mapping to values
1948
+ *
1949
+ * @example
1950
+ * ```typescript
1951
+ * const record = registry.getAsRecord();
1952
+ * ```
1953
+ */
1954
+ getAsRecord() {
1955
+ return this.collection.getAsRecord();
1956
+ }
1957
+ /**
1958
+ * Check if an item is registered
1959
+ *
1960
+ * Checks whether an item with the specified key exists in the registry.
1961
+ * Does not check the value, only the presence of the key.
1962
+ *
1963
+ * Time Complexity: O(1)
1964
+ *
1965
+ * @param key - Item identifier to check
1966
+ * @returns True if item is registered, false otherwise
1967
+ *
1968
+ * @example
1969
+ * ```typescript
1970
+ * if (registry.has('blue')) {
1971
+ * console.log('Blue theme exists');
1972
+ * }
1973
+ * ```
1974
+ */
1975
+ has(key) {
1976
+ return this.collection.has(key);
1977
+ }
1978
+ /**
1979
+ * Remove an item from the registry
1980
+ *
1981
+ * Removes an item with the specified key from the registry.
1982
+ * Returns true if the item was removed, false if it didn't exist.
1983
+ *
1984
+ * Time Complexity: O(1)
1985
+ *
1986
+ * @param key - Item identifier to remove
1987
+ * @returns True if item was removed, false if it didn't exist
1988
+ *
1989
+ * @example
1990
+ * ```typescript
1991
+ * const removed = registry.remove('blue');
1992
+ * ```
1993
+ */
1994
+ remove(key) {
1995
+ return this.collection.remove(key);
1996
+ }
1997
+ /**
1998
+ * Clear all items from the registry
1999
+ *
2000
+ * Removes all items from the registry, leaving it empty.
2001
+ * This operation is irreversible.
2002
+ *
2003
+ * Time Complexity: O(1)
2004
+ *
2005
+ * @example
2006
+ * ```typescript
2007
+ * registry.clear();
2008
+ * ```
2009
+ */
2010
+ clear() {
2011
+ this.collection.clear();
2012
+ }
2013
+ /**
2014
+ * Get the number of items in the registry
2015
+ *
2016
+ * Returns the total count of items currently registered.
2017
+ *
2018
+ * Time Complexity: O(1)
2019
+ *
2020
+ * @returns Number of items in the registry
2021
+ *
2022
+ * @example
2023
+ * ```typescript
2024
+ * console.log(registry.size()); // 2
2025
+ * ```
2026
+ */
2027
+ size() {
2028
+ return this.collection.size();
2029
+ }
2030
+ /**
2031
+ * Check if the registry is empty
2032
+ *
2033
+ * Returns true if the registry contains no items, false otherwise.
2034
+ * This is a convenience method equivalent to checking if size() === 0.
2035
+ *
2036
+ * Time Complexity: O(1)
2037
+ *
2038
+ * @returns True if registry has no items, false otherwise
2039
+ *
2040
+ * @example
2041
+ * ```typescript
2042
+ * console.log(registry.isEmpty()); // true
2043
+ * ```
2044
+ */
2045
+ isEmpty() {
2046
+ return this.collection.isEmpty();
2047
+ }
2048
+ /**
2049
+ * Iterate over all items in the registry
2050
+ *
2051
+ * Executes a callback function for each item in the registry.
2052
+ * Items are iterated in insertion order (for MapCollection).
2053
+ *
2054
+ * Time Complexity: O(n) where n is the number of items
2055
+ *
2056
+ * @param callback - Function to call for each item (value, key)
2057
+ *
2058
+ * @example
2059
+ * ```typescript
2060
+ * registry.forEach((theme, key) => {
2061
+ * console.log(`${key}: ${theme.name}`);
2062
+ * });
2063
+ * ```
2064
+ */
2065
+ forEach(callback) {
2066
+ this.collection.forEach(callback);
2067
+ }
2068
+ /**
2069
+ * Map over all items in the registry
2070
+ *
2071
+ * Transforms each item in the registry using a callback function
2072
+ * and returns an array of the transformed values.
2073
+ *
2074
+ * Time Complexity: O(n) where n is the number of items
2075
+ *
2076
+ * @template U - The type of the transformed items
2077
+ * @param callback - Function to transform each item (value, key) => U
2078
+ * @returns Array of transformed items
2079
+ *
2080
+ * @example
2081
+ * ```typescript
2082
+ * const names = registry.map(theme => theme.name);
2083
+ * ```
2084
+ */
2085
+ map(callback) {
2086
+ return this.collection.map(callback);
2087
+ }
2088
+ /**
2089
+ * Filter items in the registry
2090
+ *
2091
+ * Returns an array of items that pass the test implemented by the
2092
+ * provided predicate function.
2093
+ *
2094
+ * Time Complexity: O(n) where n is the number of items
2095
+ *
2096
+ * @param predicate - Function to test each item (value, key) => boolean
2097
+ * @returns Array of items that pass the test
2098
+ *
2099
+ * @example
2100
+ * ```typescript
2101
+ * const darkThemes = registry.filter(theme => theme.isDark);
2102
+ * ```
2103
+ */
2104
+ filter(predicate) {
2105
+ return this.collection.filter(predicate);
2106
+ }
2107
+ /**
2108
+ * Find an item in the registry
2109
+ *
2110
+ * Returns the first item that satisfies the provided predicate function.
2111
+ * Returns undefined if no item passes the test.
2112
+ *
2113
+ * Time Complexity: O(n) worst case, O(1) best case
2114
+ *
2115
+ * @param predicate - Function to test each item (value, key) => boolean
2116
+ * @returns First item that passes the test, or undefined
2117
+ *
2118
+ * @example
2119
+ * ```typescript
2120
+ * const defaultTheme = registry.find(theme => theme.isDefault);
2121
+ * ```
2122
+ */
2123
+ find(predicate) {
2124
+ return this.collection.find(predicate);
2125
+ }
2126
+ };
2127
+
2128
+ // src/facades/facade.ts
2129
+ var import_react_di = require("@abdokouta/react-di");
2130
+
2131
+ // src/facades/facade.interface.ts
2132
+ function isFake(obj) {
2133
+ return typeof obj === "object" && obj !== null && "__isFake" in obj && obj.__isFake === true;
2134
+ }
2135
+
2136
+ // src/facades/facade.ts
2137
+ var Facade = class {
2138
+ /**
2139
+ * Hotswap the underlying instance behind the facade
2140
+ *
2141
+ * Useful for testing - swap the real service with a mock or fake.
2142
+ *
2143
+ * @param instance - Instance to swap in
2144
+ *
2145
+ * @example
2146
+ * ```typescript
2147
+ * // In tests
2148
+ * const mockLogger = { info: vi.fn(), error: vi.fn() };
2149
+ * Log.swap(mockLogger);
2150
+ *
2151
+ * // Now Log.info() calls mockLogger.info()
2152
+ * Log.info('test');
2153
+ * expect(mockLogger.info).toHaveBeenCalledWith('test');
2154
+ * ```
2155
+ */
2156
+ static swap(instance) {
2157
+ const accessor = this.getFacadeAccessor();
2158
+ const key = this.getAccessorKey(accessor);
2159
+ this.resolvedInstance.set(key, instance);
2160
+ }
2161
+ /**
2162
+ * Determines whether a "fake" has been set as the facade instance
2163
+ *
2164
+ * @returns True if the current instance is a Fake
2165
+ *
2166
+ * @example
2167
+ * ```typescript
2168
+ * if (Log.isFake()) {
2169
+ * console.log('Using fake logger');
2170
+ * }
2171
+ * ```
2172
+ */
2173
+ static isFake() {
2174
+ const accessor = this.getFacadeAccessor();
2175
+ const key = this.getAccessorKey(accessor);
2176
+ const instance = this.resolvedInstance.get(key);
2177
+ return instance !== void 0 && isFake(instance);
2178
+ }
2179
+ /**
2180
+ * Get the root object behind the facade
2181
+ *
2182
+ * Resolves and returns the actual service instance.
2183
+ *
2184
+ * @returns The resolved service instance
2185
+ */
2186
+ static getFacadeRoot() {
2187
+ return this.resolveFacadeInstance(this.getFacadeAccessor());
2188
+ }
2189
+ /**
2190
+ * Get the registered name of the component
2191
+ *
2192
+ * Subclasses MUST override this method to specify which service
2193
+ * the facade represents.
2194
+ *
2195
+ * @returns Service identifier (string, symbol, or class)
2196
+ * @throws Error if not implemented
2197
+ *
2198
+ * @example
2199
+ * ```typescript
2200
+ * class Log extends Facade {
2201
+ * protected static getFacadeAccessor(): ServiceIdentifier {
2202
+ * return LoggerService; // or 'logger' string token
2203
+ * }
2204
+ * }
2205
+ * ```
2206
+ */
2207
+ static getFacadeAccessor() {
2208
+ throw new Error("Facade does not implement getFacadeAccessor method.");
2209
+ }
2210
+ /**
2211
+ * Get a consistent key for the accessor
2212
+ */
2213
+ static getAccessorKey(accessor) {
2214
+ if (typeof accessor === "function") {
2215
+ return accessor.name || accessor.toString();
2216
+ }
2217
+ return accessor;
2218
+ }
2219
+ /**
2220
+ * Resolve the facade root instance from the container
2221
+ *
2222
+ * @param identifier - Service identifier
2223
+ * @returns Resolved service instance
2224
+ */
2225
+ static resolveFacadeInstance(identifier) {
2226
+ const key = this.getAccessorKey(identifier);
2227
+ if (this.resolvedInstance.has(key)) {
2228
+ return this.resolvedInstance.get(key);
2229
+ }
2230
+ const container = this.getContainer();
2231
+ if (!container) {
2232
+ throw new Error(
2233
+ `Unable to resolve facade instance. Module not set. Call Facade.setFacadeModule(YourModule) first.`
2234
+ );
2235
+ }
2236
+ const instance = container.get(identifier);
2237
+ if (this.cached) {
2238
+ this.resolvedInstance.set(key, instance);
2239
+ }
2240
+ return instance;
2241
+ }
2242
+ /**
2243
+ * Get the module container
2244
+ *
2245
+ * @returns The module container instance
2246
+ */
2247
+ static getContainer() {
2248
+ if (this.container) {
2249
+ return this.container;
2250
+ }
2251
+ if (this.moduleClass) {
2252
+ this.container = (0, import_react_di.getModuleContainer)(this.moduleClass);
2253
+ return this.container;
2254
+ }
2255
+ return null;
2256
+ }
2257
+ /**
2258
+ * Clear a resolved facade instance
2259
+ *
2260
+ * @param name - Service identifier to clear (defaults to this facade's accessor)
2261
+ */
2262
+ static clearResolvedInstance(name) {
2263
+ const key = name ?? this.getAccessorKey(this.getFacadeAccessor());
2264
+ this.resolvedInstance.delete(key);
2265
+ }
2266
+ /**
2267
+ * Clear all resolved instances
2268
+ *
2269
+ * Useful for test cleanup.
2270
+ */
2271
+ static clearResolvedInstances() {
2272
+ this.resolvedInstance.clear();
2273
+ }
2274
+ /**
2275
+ * Get the module class
2276
+ *
2277
+ * @returns The module class
2278
+ */
2279
+ static getFacadeModule() {
2280
+ return this.moduleClass;
2281
+ }
2282
+ /**
2283
+ * Set the module class for facade resolution
2284
+ *
2285
+ * Must be called during application bootstrap to enable facades.
2286
+ * Call this AFTER Inversiland.run() or Container.configure().build().
2287
+ *
2288
+ * @param module - The root module class
2289
+ *
2290
+ * @example
2291
+ * ```typescript
2292
+ * // In your app bootstrap (main.tsx)
2293
+ * import { Facade } from '@abdokouta/react-support';
2294
+ * import { Container, ContainerProvider } from '@abdokouta/react-di';
2295
+ * import { AppModule } from './app.module';
2296
+ *
2297
+ * // Initialize container
2298
+ * Container.configure().withModule(AppModule).withDefaults().build();
2299
+ *
2300
+ * // Set facade module
2301
+ * Facade.setFacadeModule(AppModule);
2302
+ *
2303
+ * // Now facades work anywhere
2304
+ * ReactDOM.createRoot(document.getElementById("root")!).render(
2305
+ * <ContainerProvider module={AppModule}>
2306
+ * <App />
2307
+ * </ContainerProvider>
2308
+ * );
2309
+ * ```
2310
+ */
2311
+ static setFacadeModule(module2) {
2312
+ this.moduleClass = module2;
2313
+ this.container = null;
2314
+ }
2315
+ /**
2316
+ * Set the container directly (alternative to setFacadeModule)
2317
+ *
2318
+ * @param container - The module container instance
2319
+ */
2320
+ static setFacadeContainer(container) {
2321
+ this.container = container;
2322
+ }
2323
+ // ============================================================================
2324
+ // Legacy API (for compatibility with FacadeApplication interface)
2325
+ // ============================================================================
2326
+ /**
2327
+ * @deprecated Use setFacadeModule instead
2328
+ */
2329
+ static setFacadeApplication(app) {
2330
+ if (app) {
2331
+ this.container = {
2332
+ get: (id) => app.get(id)
2333
+ };
2334
+ } else {
2335
+ this.container = null;
2336
+ }
2337
+ }
2338
+ /**
2339
+ * @deprecated Use getFacadeModule instead
2340
+ */
2341
+ static getFacadeApplication() {
2342
+ const container = this.getContainer();
2343
+ if (!container) return null;
2344
+ return {
2345
+ get: (abstract) => container.get(abstract)
2346
+ };
2347
+ }
2348
+ };
2349
+ /**
2350
+ * The root module class for resolving services
2351
+ */
2352
+ Facade.moduleClass = null;
2353
+ /**
2354
+ * The module container instance (cached)
2355
+ */
2356
+ Facade.container = null;
2357
+ /**
2358
+ * The resolved object instances
2359
+ *
2360
+ * Caches resolved instances by their accessor key for performance.
2361
+ */
2362
+ Facade.resolvedInstance = /* @__PURE__ */ new Map();
2363
+ /**
2364
+ * Indicates if the resolved instance should be cached
2365
+ *
2366
+ * Set to false in subclasses to always resolve fresh instances.
2367
+ */
2368
+ Facade.cached = true;
2369
+
2370
+ // src/facades/create-facade.ts
2371
+ var import_react_di2 = require("@abdokouta/react-di");
2372
+ function createFacade(options) {
2373
+ const { accessor, cached = true } = options;
2374
+ class ConcreteFacade extends Facade {
2375
+ static getFacadeAccessor() {
2376
+ return accessor;
2377
+ }
2378
+ }
2379
+ ConcreteFacade.cached = cached;
2380
+ const proxy = new Proxy(ConcreteFacade, {
2381
+ get(target, prop, receiver) {
2382
+ if (prop in target) {
2383
+ const value = Reflect.get(target, prop, receiver);
2384
+ if (typeof value === "function") {
2385
+ return value.bind(target);
2386
+ }
2387
+ return value;
2388
+ }
2389
+ return (...args) => {
2390
+ const instance = target.getFacadeRoot();
2391
+ if (!instance) {
2392
+ throw new Error(
2393
+ `A facade root has not been set. Call Facade.setFacadeModule() first.`
2394
+ );
2395
+ }
2396
+ const method = instance[prop];
2397
+ if (typeof method !== "function") {
2398
+ throw new Error(
2399
+ `Method "${String(prop)}" does not exist on the facade root.`
2400
+ );
2401
+ }
2402
+ return method.apply(instance, args);
2403
+ };
2404
+ }
2405
+ });
2406
+ return proxy;
2407
+ }
2408
+ function createFacadeClass(accessor) {
2409
+ return class extends Facade {
2410
+ static getFacadeAccessor() {
2411
+ return accessor;
2412
+ }
2413
+ };
2414
+ }
2415
+ function getContainerFromModule(moduleClass) {
2416
+ return (0, import_react_di2.getModuleContainer)(moduleClass);
2417
+ }
2418
+ //# sourceMappingURL=index.js.map