@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/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +178 -0
- package/dist/index.d.cts +1749 -0
- package/dist/index.d.ts +1749 -0
- package/dist/index.js +2418 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2385 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +84 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1749 @@
|
|
|
1
|
+
export { Collection as CollectJsCollection } from 'collect.js';
|
|
2
|
+
import { Newable, ModuleContainer, ServiceIdentifier } from '@abdokouta/react-di';
|
|
3
|
+
export { ModuleContainer, Newable, ServiceIdentifier } from '@abdokouta/react-di';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Laravel-style string manipulation class
|
|
7
|
+
* Provides static methods for common string operations
|
|
8
|
+
*/
|
|
9
|
+
declare class Str {
|
|
10
|
+
/**
|
|
11
|
+
* Return the remainder of a string after the first occurrence of a given value
|
|
12
|
+
*/
|
|
13
|
+
static after(subject: string, search: string): string;
|
|
14
|
+
/**
|
|
15
|
+
* Return the remainder of a string after the last occurrence of a given value
|
|
16
|
+
*/
|
|
17
|
+
static afterLast(subject: string, search: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Convert a string to title case following APA guidelines
|
|
20
|
+
*/
|
|
21
|
+
static apa(value: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Transliterate a UTF-8 value to ASCII
|
|
24
|
+
*/
|
|
25
|
+
static ascii(value: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Get the portion of a string before the first occurrence of a given value
|
|
28
|
+
*/
|
|
29
|
+
static before(subject: string, search: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Get the portion of a string before the last occurrence of a given value
|
|
32
|
+
*/
|
|
33
|
+
static beforeLast(subject: string, search: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Get the portion of a string between two values
|
|
36
|
+
*/
|
|
37
|
+
static between(subject: string, from: string, to: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Get the smallest possible portion of a string between two values
|
|
40
|
+
*/
|
|
41
|
+
static betweenFirst(subject: string, from: string, to: string): string;
|
|
42
|
+
/**
|
|
43
|
+
* Convert a string to camelCase
|
|
44
|
+
*/
|
|
45
|
+
static camel(value: string): string;
|
|
46
|
+
/**
|
|
47
|
+
* Get the character at the specified index
|
|
48
|
+
*/
|
|
49
|
+
static charAt(subject: string, index: number): string | false;
|
|
50
|
+
/**
|
|
51
|
+
* Remove the first occurrence of the given value from the start of the string
|
|
52
|
+
*/
|
|
53
|
+
static chopStart(subject: string, search: string | string[]): string;
|
|
54
|
+
/**
|
|
55
|
+
* Remove the last occurrence of the given value from the end of the string
|
|
56
|
+
*/
|
|
57
|
+
static chopEnd(subject: string, search: string | string[]): string;
|
|
58
|
+
/**
|
|
59
|
+
* Determine if a given string contains a given substring
|
|
60
|
+
*/
|
|
61
|
+
static contains(haystack: string, needles: string | string[], ignoreCase?: boolean): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Determine if a given string contains all array values
|
|
64
|
+
*/
|
|
65
|
+
static containsAll(haystack: string, needles: string[], ignoreCase?: boolean): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Determine if a given string doesn't contain a given substring
|
|
68
|
+
*/
|
|
69
|
+
static doesntContain(haystack: string, needles: string | string[], ignoreCase?: boolean): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Replace consecutive instances of a character with a single instance
|
|
72
|
+
*/
|
|
73
|
+
static deduplicate(value: string, character?: string): string;
|
|
74
|
+
/**
|
|
75
|
+
* Determine if a given string ends with a given substring
|
|
76
|
+
*/
|
|
77
|
+
static endsWith(haystack: string, needles: string | string[]): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Extract an excerpt from text that matches the first instance of a phrase
|
|
80
|
+
*/
|
|
81
|
+
static excerpt(text: string, phrase: string, options?: {
|
|
82
|
+
radius?: number;
|
|
83
|
+
omission?: string;
|
|
84
|
+
}): string;
|
|
85
|
+
/**
|
|
86
|
+
* Cap a string with a single instance of a given value
|
|
87
|
+
*/
|
|
88
|
+
static finish(value: string, cap: string): string;
|
|
89
|
+
/**
|
|
90
|
+
* Convert a string to headline case
|
|
91
|
+
*/
|
|
92
|
+
static headline(value: string): string;
|
|
93
|
+
/**
|
|
94
|
+
* Determine if a given string matches a given pattern
|
|
95
|
+
*/
|
|
96
|
+
static is(pattern: string, value: string, ignoreCase?: boolean): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Determine if a given string is 7-bit ASCII
|
|
99
|
+
*/
|
|
100
|
+
static isAscii(value: string): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Determine if a given string is valid JSON
|
|
103
|
+
*/
|
|
104
|
+
static isJson(value: string): boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Determine if a given string is a valid URL
|
|
107
|
+
*/
|
|
108
|
+
static isUrl(value: string, protocols?: string[]): boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Determine if a given string is a valid ULID
|
|
111
|
+
*/
|
|
112
|
+
static isUlid(value: string): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Determine if a given string is a valid UUID
|
|
115
|
+
*/
|
|
116
|
+
static isUuid(value: string): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Convert a string to kebab-case
|
|
119
|
+
*/
|
|
120
|
+
static kebab(value: string): string;
|
|
121
|
+
/**
|
|
122
|
+
* Return the given string with the first character lowercased
|
|
123
|
+
*/
|
|
124
|
+
static lcfirst(value: string): string;
|
|
125
|
+
/**
|
|
126
|
+
* Return the length of the given string
|
|
127
|
+
*/
|
|
128
|
+
static len(value: string): number;
|
|
129
|
+
/**
|
|
130
|
+
* Limit the number of characters in a string
|
|
131
|
+
*/
|
|
132
|
+
static limit(value: string, limit?: number, end?: string, preserveWords?: boolean): string;
|
|
133
|
+
/**
|
|
134
|
+
* Convert the given string to lowercase
|
|
135
|
+
*/
|
|
136
|
+
static lower(value: string): string;
|
|
137
|
+
/**
|
|
138
|
+
* Masks a portion of a string with a repeated character
|
|
139
|
+
*/
|
|
140
|
+
static mask(value: string, character: string, index: number, length?: number): string;
|
|
141
|
+
/**
|
|
142
|
+
* Pad both sides of a string with another
|
|
143
|
+
*/
|
|
144
|
+
static padBoth(value: string, length: number, pad?: string): string;
|
|
145
|
+
/**
|
|
146
|
+
* Pad the left side of a string with another
|
|
147
|
+
*/
|
|
148
|
+
static padLeft(value: string, length: number, pad?: string): string;
|
|
149
|
+
/**
|
|
150
|
+
* Pad the right side of a string with another
|
|
151
|
+
*/
|
|
152
|
+
static padRight(value: string, length: number, pad?: string): string;
|
|
153
|
+
/**
|
|
154
|
+
* Get the plural form of an English word
|
|
155
|
+
*/
|
|
156
|
+
static plural(value: string, count?: number): string;
|
|
157
|
+
/**
|
|
158
|
+
* Pluralize the last word of an English, studly caps case string
|
|
159
|
+
*/
|
|
160
|
+
static pluralStudly(value: string, count?: number): string;
|
|
161
|
+
/**
|
|
162
|
+
* Find the position of the first occurrence of a substring
|
|
163
|
+
*/
|
|
164
|
+
static position(haystack: string, needle: string): number | false;
|
|
165
|
+
/**
|
|
166
|
+
* Generate a random string
|
|
167
|
+
*/
|
|
168
|
+
static random(length?: number): string;
|
|
169
|
+
/**
|
|
170
|
+
* Remove the given value from the string
|
|
171
|
+
*/
|
|
172
|
+
static remove(search: string | string[], subject: string, caseSensitive?: boolean): string;
|
|
173
|
+
/**
|
|
174
|
+
* Repeat the given string
|
|
175
|
+
*/
|
|
176
|
+
static repeat(value: string, times: number): string;
|
|
177
|
+
/**
|
|
178
|
+
* Replace the given value in the given string
|
|
179
|
+
*/
|
|
180
|
+
static replace(search: string, replace: string, subject: string, caseSensitive?: boolean): string;
|
|
181
|
+
/**
|
|
182
|
+
* Replace a given value in the string sequentially with an array
|
|
183
|
+
*/
|
|
184
|
+
static replaceArray(search: string, replacements: string[], subject: string): string;
|
|
185
|
+
/**
|
|
186
|
+
* Replace the first occurrence of a given value in the string
|
|
187
|
+
*/
|
|
188
|
+
static replaceFirst(search: string, replace: string, subject: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* Replace the last occurrence of a given value in the string
|
|
191
|
+
*/
|
|
192
|
+
static replaceLast(search: string, replace: string, subject: string): string;
|
|
193
|
+
/**
|
|
194
|
+
* Replace the first occurrence only if it appears at the start
|
|
195
|
+
*/
|
|
196
|
+
static replaceStart(search: string, replace: string, subject: string): string;
|
|
197
|
+
/**
|
|
198
|
+
* Replace the last occurrence only if it appears at the end
|
|
199
|
+
*/
|
|
200
|
+
static replaceEnd(search: string, replace: string, subject: string): string;
|
|
201
|
+
/**
|
|
202
|
+
* Reverse the given string
|
|
203
|
+
*/
|
|
204
|
+
static reverse(value: string): string;
|
|
205
|
+
/**
|
|
206
|
+
* Get the singular form of an English word
|
|
207
|
+
*/
|
|
208
|
+
static singular(value: string): string;
|
|
209
|
+
/**
|
|
210
|
+
* Generate a URL friendly slug
|
|
211
|
+
*/
|
|
212
|
+
static slug(value: string, separator?: string): string;
|
|
213
|
+
/**
|
|
214
|
+
* Convert a string to snake_case
|
|
215
|
+
*/
|
|
216
|
+
static snake(value: string, delimiter?: string): string;
|
|
217
|
+
/**
|
|
218
|
+
* Remove all extraneous whitespace
|
|
219
|
+
*/
|
|
220
|
+
static squish(value: string): string;
|
|
221
|
+
/**
|
|
222
|
+
* Begin a string with a single instance of a given value
|
|
223
|
+
*/
|
|
224
|
+
static start(value: string, prefix: string): string;
|
|
225
|
+
/**
|
|
226
|
+
* Determine if a given string starts with a given substring
|
|
227
|
+
*/
|
|
228
|
+
static startsWith(haystack: string, needles: string | string[]): boolean;
|
|
229
|
+
/**
|
|
230
|
+
* Convert a value to studly caps case
|
|
231
|
+
*/
|
|
232
|
+
static studly(value: string): string;
|
|
233
|
+
/**
|
|
234
|
+
* Returns the portion of string specified by the start and length parameters
|
|
235
|
+
*/
|
|
236
|
+
static substr(value: string, start: number, length?: number): string;
|
|
237
|
+
/**
|
|
238
|
+
* Returns the number of substring occurrences
|
|
239
|
+
*/
|
|
240
|
+
static substrCount(haystack: string, needle: string): number;
|
|
241
|
+
/**
|
|
242
|
+
* Replace text within a portion of a string
|
|
243
|
+
*/
|
|
244
|
+
static substrReplace(value: string, replace: string, start: number, length?: number): string;
|
|
245
|
+
/**
|
|
246
|
+
* Swap multiple keywords in a string with other keywords
|
|
247
|
+
*/
|
|
248
|
+
static swap(map: Record<string, string>, subject: string): string;
|
|
249
|
+
/**
|
|
250
|
+
* Take the first or last {limit} characters
|
|
251
|
+
*/
|
|
252
|
+
static take(value: string, limit: number): string;
|
|
253
|
+
/**
|
|
254
|
+
* Convert the given string to title case
|
|
255
|
+
*/
|
|
256
|
+
static title(value: string): string;
|
|
257
|
+
/**
|
|
258
|
+
* Convert the given string to Base64
|
|
259
|
+
*/
|
|
260
|
+
static toBase64(value: string): string;
|
|
261
|
+
/**
|
|
262
|
+
* Transliterate a string to its closest ASCII representation
|
|
263
|
+
*/
|
|
264
|
+
static transliterate(value: string): string;
|
|
265
|
+
/**
|
|
266
|
+
* Trim whitespace from both ends of the string
|
|
267
|
+
*/
|
|
268
|
+
static trim(value: string, characters?: string): string;
|
|
269
|
+
/**
|
|
270
|
+
* Trim whitespace from the beginning of the string
|
|
271
|
+
*/
|
|
272
|
+
static ltrim(value: string, characters?: string): string;
|
|
273
|
+
/**
|
|
274
|
+
* Trim whitespace from the end of the string
|
|
275
|
+
*/
|
|
276
|
+
static rtrim(value: string, characters?: string): string;
|
|
277
|
+
/**
|
|
278
|
+
* Make a string's first character uppercase
|
|
279
|
+
*/
|
|
280
|
+
static ucfirst(value: string): string;
|
|
281
|
+
/**
|
|
282
|
+
* Split a string by uppercase characters
|
|
283
|
+
*/
|
|
284
|
+
static ucsplit(value: string): string[];
|
|
285
|
+
/**
|
|
286
|
+
* Convert the given string to uppercase
|
|
287
|
+
*/
|
|
288
|
+
static upper(value: string): string;
|
|
289
|
+
/**
|
|
290
|
+
* Remove the specified strings from the beginning and end
|
|
291
|
+
*/
|
|
292
|
+
static unwrap(value: string, before: string, after?: string): string;
|
|
293
|
+
/**
|
|
294
|
+
* Get the number of words a string contains
|
|
295
|
+
*/
|
|
296
|
+
static wordCount(value: string): number;
|
|
297
|
+
/**
|
|
298
|
+
* Wrap a string to a given number of characters
|
|
299
|
+
*/
|
|
300
|
+
static wordWrap(value: string, characters?: number, breakStr?: string): string;
|
|
301
|
+
/**
|
|
302
|
+
* Limit the number of words in a string
|
|
303
|
+
*/
|
|
304
|
+
static words(value: string, words?: number, end?: string): string;
|
|
305
|
+
/**
|
|
306
|
+
* Wrap the string with the given strings
|
|
307
|
+
*/
|
|
308
|
+
static wrap(value: string, before: string, after?: string): string;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
declare class Collection$1<T = any> {
|
|
312
|
+
private collection;
|
|
313
|
+
constructor(items?: T[]);
|
|
314
|
+
/**
|
|
315
|
+
* Create a new collection instance
|
|
316
|
+
*/
|
|
317
|
+
static make<T>(items?: T[]): Collection$1<T>;
|
|
318
|
+
/**
|
|
319
|
+
* Get all items in the collection
|
|
320
|
+
*/
|
|
321
|
+
all(): T[];
|
|
322
|
+
/**
|
|
323
|
+
* Get the average value of a given key
|
|
324
|
+
*/
|
|
325
|
+
avg(key?: keyof T | ((item: T) => number)): number;
|
|
326
|
+
/**
|
|
327
|
+
* Chunk the collection into chunks of the given size
|
|
328
|
+
*/
|
|
329
|
+
chunk(size: number): Collection$1<T[]>;
|
|
330
|
+
/**
|
|
331
|
+
* Collapse a collection of arrays into a single, flat collection
|
|
332
|
+
*/
|
|
333
|
+
collapse(): Collection$1<any>;
|
|
334
|
+
/**
|
|
335
|
+
* Determine if an item exists in the collection
|
|
336
|
+
*/
|
|
337
|
+
contains(key: keyof T | ((item: T) => boolean), value?: any): boolean;
|
|
338
|
+
/**
|
|
339
|
+
* Get the total number of items in the collection
|
|
340
|
+
*/
|
|
341
|
+
count(): number;
|
|
342
|
+
/**
|
|
343
|
+
* Get the items in the collection that are not present in the given items
|
|
344
|
+
*/
|
|
345
|
+
diff(items: T[]): Collection$1<T>;
|
|
346
|
+
/**
|
|
347
|
+
* Execute a callback over each item
|
|
348
|
+
*/
|
|
349
|
+
each(callback: (item: T, key: number) => void | false): this;
|
|
350
|
+
/**
|
|
351
|
+
* Determine if all items pass the given test
|
|
352
|
+
*/
|
|
353
|
+
every(callback: (item: T, key: number) => boolean): boolean;
|
|
354
|
+
/**
|
|
355
|
+
* Get all items except for those with the specified keys
|
|
356
|
+
*/
|
|
357
|
+
except(keys: (keyof T)[]): Collection$1<T>;
|
|
358
|
+
/**
|
|
359
|
+
* Run a filter over each of the items
|
|
360
|
+
*/
|
|
361
|
+
filter(callback?: (item: T, key: number) => boolean): Collection$1<T>;
|
|
362
|
+
/**
|
|
363
|
+
* Get the first item from the collection
|
|
364
|
+
*/
|
|
365
|
+
first(callback?: (item: T, key: number) => boolean): T | undefined;
|
|
366
|
+
/**
|
|
367
|
+
* Get a flattened array of the items in the collection
|
|
368
|
+
*/
|
|
369
|
+
flatten(depth?: number): Collection$1<any>;
|
|
370
|
+
/**
|
|
371
|
+
* Flip the items in the collection
|
|
372
|
+
*/
|
|
373
|
+
flip(): Collection$1<any>;
|
|
374
|
+
/**
|
|
375
|
+
* Remove an item from the collection by key
|
|
376
|
+
*/
|
|
377
|
+
forget(key: number): this;
|
|
378
|
+
/**
|
|
379
|
+
* Get an item from the collection by key
|
|
380
|
+
*/
|
|
381
|
+
get(key: number, defaultValue?: T): T | undefined;
|
|
382
|
+
/**
|
|
383
|
+
* Group the collection's items by a given key
|
|
384
|
+
*/
|
|
385
|
+
groupBy(key: keyof T | ((item: T) => any)): Collection$1<Collection$1<T>>;
|
|
386
|
+
/**
|
|
387
|
+
* Determine if a given key exists in the collection
|
|
388
|
+
*/
|
|
389
|
+
has(key: number): boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Concatenate values of a given key as a string
|
|
392
|
+
*/
|
|
393
|
+
implode(key: keyof T | string, glue?: string): string;
|
|
394
|
+
/**
|
|
395
|
+
* Intersect the collection with the given items
|
|
396
|
+
*/
|
|
397
|
+
intersect(items: T[]): Collection$1<T>;
|
|
398
|
+
/**
|
|
399
|
+
* Determine if the collection is empty
|
|
400
|
+
*/
|
|
401
|
+
isEmpty(): boolean;
|
|
402
|
+
/**
|
|
403
|
+
* Determine if the collection is not empty
|
|
404
|
+
*/
|
|
405
|
+
isNotEmpty(): boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Join all items from the collection using a string
|
|
408
|
+
*/
|
|
409
|
+
join(glue: string, finalGlue?: string): string;
|
|
410
|
+
/**
|
|
411
|
+
* Key the collection by the given key
|
|
412
|
+
*/
|
|
413
|
+
keyBy(key: keyof T | ((item: T) => any)): Collection$1<T>;
|
|
414
|
+
/**
|
|
415
|
+
* Get the keys of the collection items
|
|
416
|
+
*/
|
|
417
|
+
keys(): Collection$1<string | number>;
|
|
418
|
+
/**
|
|
419
|
+
* Get the last item from the collection
|
|
420
|
+
*/
|
|
421
|
+
last(callback?: (item: T, key: number) => boolean): T | undefined;
|
|
422
|
+
/**
|
|
423
|
+
* Run a map over each of the items
|
|
424
|
+
*/
|
|
425
|
+
map<U>(callback: (item: T, key: number) => U): Collection$1<U>;
|
|
426
|
+
/**
|
|
427
|
+
* Get the max value of a given key
|
|
428
|
+
*/
|
|
429
|
+
max(key?: keyof T): number;
|
|
430
|
+
/**
|
|
431
|
+
* Merge the collection with the given items
|
|
432
|
+
*/
|
|
433
|
+
merge(items: T[]): Collection$1<T>;
|
|
434
|
+
/**
|
|
435
|
+
* Get the min value of a given key
|
|
436
|
+
*/
|
|
437
|
+
min(key?: keyof T): number;
|
|
438
|
+
/**
|
|
439
|
+
* Get the items with the specified keys
|
|
440
|
+
*/
|
|
441
|
+
only(keys: (keyof T)[]): Collection$1<T>;
|
|
442
|
+
/**
|
|
443
|
+
* Get and remove the last item from the collection
|
|
444
|
+
*/
|
|
445
|
+
pop(): T | undefined;
|
|
446
|
+
/**
|
|
447
|
+
* Push an item onto the beginning of the collection
|
|
448
|
+
*/
|
|
449
|
+
prepend(value: T): this;
|
|
450
|
+
/**
|
|
451
|
+
* Get and remove an item from the collection
|
|
452
|
+
*/
|
|
453
|
+
pull(key: number): T | undefined;
|
|
454
|
+
/**
|
|
455
|
+
* Push an item onto the end of the collection
|
|
456
|
+
*/
|
|
457
|
+
push(value: T): this;
|
|
458
|
+
/**
|
|
459
|
+
* Put an item in the collection by key
|
|
460
|
+
*/
|
|
461
|
+
put(key: number, value: T): this;
|
|
462
|
+
/**
|
|
463
|
+
* Get one or a specified number of items randomly from the collection
|
|
464
|
+
*/
|
|
465
|
+
random(count?: number): T | Collection$1<T>;
|
|
466
|
+
/**
|
|
467
|
+
* Reduce the collection to a single value
|
|
468
|
+
*/
|
|
469
|
+
reduce<U>(callback: (carry: U, item: T) => U, initial: U): U;
|
|
470
|
+
/**
|
|
471
|
+
* Filter items by the given key value pair
|
|
472
|
+
*/
|
|
473
|
+
reject(callback: (item: T, key: number) => boolean): Collection$1<T>;
|
|
474
|
+
/**
|
|
475
|
+
* Reverse items order
|
|
476
|
+
*/
|
|
477
|
+
reverse(): Collection$1<T>;
|
|
478
|
+
/**
|
|
479
|
+
* Search the collection for a given value
|
|
480
|
+
*/
|
|
481
|
+
search(value: T | ((item: T) => boolean)): number | false;
|
|
482
|
+
/**
|
|
483
|
+
* Get and remove the first item from the collection
|
|
484
|
+
*/
|
|
485
|
+
shift(): T | undefined;
|
|
486
|
+
/**
|
|
487
|
+
* Shuffle the items in the collection
|
|
488
|
+
*/
|
|
489
|
+
shuffle(): Collection$1<T>;
|
|
490
|
+
/**
|
|
491
|
+
* Slice the underlying collection array
|
|
492
|
+
*/
|
|
493
|
+
slice(start: number, length?: number): Collection$1<T>;
|
|
494
|
+
/**
|
|
495
|
+
* Sort through each item with a callback
|
|
496
|
+
*/
|
|
497
|
+
sort(callback?: (a: T, b: T) => number): Collection$1<T>;
|
|
498
|
+
/**
|
|
499
|
+
* Sort the collection by the given key
|
|
500
|
+
*/
|
|
501
|
+
sortBy(key: keyof T | ((item: T) => any)): Collection$1<T>;
|
|
502
|
+
/**
|
|
503
|
+
* Sort the collection in descending order by the given key
|
|
504
|
+
*/
|
|
505
|
+
sortByDesc(key: keyof T | ((item: T) => any)): Collection$1<T>;
|
|
506
|
+
/**
|
|
507
|
+
* Splice a portion of the underlying collection array
|
|
508
|
+
*/
|
|
509
|
+
splice(start: number, length?: number, ...items: T[]): Collection$1<T>;
|
|
510
|
+
/**
|
|
511
|
+
* Get the sum of the given values
|
|
512
|
+
*/
|
|
513
|
+
sum(key?: keyof T | ((item: T) => number)): number;
|
|
514
|
+
/**
|
|
515
|
+
* Take the first or last {limit} items
|
|
516
|
+
*/
|
|
517
|
+
take(limit: number): Collection$1<T>;
|
|
518
|
+
/**
|
|
519
|
+
* Pass the collection to the given callback and return the result
|
|
520
|
+
*/
|
|
521
|
+
pipe<U>(callback: (collection: Collection$1<T>) => U): U;
|
|
522
|
+
/**
|
|
523
|
+
* Pass the collection to the given callback and then return it
|
|
524
|
+
*/
|
|
525
|
+
tap(callback: (collection: Collection$1<T>) => void): this;
|
|
526
|
+
/**
|
|
527
|
+
* Transform each item in the collection using a callback
|
|
528
|
+
*/
|
|
529
|
+
transform(callback: (item: T, key: number) => T): this;
|
|
530
|
+
/**
|
|
531
|
+
* Return only unique items from the collection array
|
|
532
|
+
*/
|
|
533
|
+
unique(key?: keyof T): Collection$1<T>;
|
|
534
|
+
/**
|
|
535
|
+
* Reset the keys on the underlying array
|
|
536
|
+
*/
|
|
537
|
+
values(): Collection$1<T>;
|
|
538
|
+
/**
|
|
539
|
+
* Filter items by the given key value pair
|
|
540
|
+
*/
|
|
541
|
+
where(key: keyof T, value: any): Collection$1<T>;
|
|
542
|
+
where(key: keyof T, operator: string, value: any): Collection$1<T>;
|
|
543
|
+
/**
|
|
544
|
+
* Filter items by the given key value pair using loose comparison
|
|
545
|
+
*/
|
|
546
|
+
whereIn(key: keyof T, values: any[]): Collection$1<T>;
|
|
547
|
+
/**
|
|
548
|
+
* Filter items by the given key value pair using loose comparison
|
|
549
|
+
*/
|
|
550
|
+
whereNotIn(key: keyof T, values: any[]): Collection$1<T>;
|
|
551
|
+
/**
|
|
552
|
+
* Zip the collection together with one or more arrays
|
|
553
|
+
*/
|
|
554
|
+
zip<U>(...arrays: U[][]): Collection$1<any[]>;
|
|
555
|
+
/**
|
|
556
|
+
* Convert the collection to a plain array
|
|
557
|
+
*/
|
|
558
|
+
toArray(): T[];
|
|
559
|
+
/**
|
|
560
|
+
* Convert the collection to JSON
|
|
561
|
+
*/
|
|
562
|
+
toJson(): string;
|
|
563
|
+
/**
|
|
564
|
+
* Get the collection as a string
|
|
565
|
+
*/
|
|
566
|
+
toString(): string;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Helper function to create a new collection
|
|
570
|
+
*/
|
|
571
|
+
declare function collect<T>(items?: T[]): Collection$1<T>;
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Laravel-style Map Collection class
|
|
575
|
+
* Provides collection methods for Map data structures
|
|
576
|
+
*/
|
|
577
|
+
declare class MapCollection<K = any, V = any> {
|
|
578
|
+
private internalMap;
|
|
579
|
+
constructor(entries?: Iterable<[K, V]> | Record<string, V>);
|
|
580
|
+
/**
|
|
581
|
+
* Create a new map collection instance
|
|
582
|
+
*/
|
|
583
|
+
static make<K, V>(entries?: Iterable<[K, V]> | Record<string, V>): MapCollection<K, V>;
|
|
584
|
+
/**
|
|
585
|
+
* Get all entries as an array of [key, value] pairs
|
|
586
|
+
*/
|
|
587
|
+
all(): [K, V][];
|
|
588
|
+
/**
|
|
589
|
+
* Get the number of items in the map
|
|
590
|
+
*/
|
|
591
|
+
count(): number;
|
|
592
|
+
/**
|
|
593
|
+
* Get the number of items in the map (alias for count)
|
|
594
|
+
*/
|
|
595
|
+
size(): number;
|
|
596
|
+
/**
|
|
597
|
+
* Determine if the map is empty
|
|
598
|
+
*/
|
|
599
|
+
isEmpty(): boolean;
|
|
600
|
+
/**
|
|
601
|
+
* Determine if the map is not empty
|
|
602
|
+
*/
|
|
603
|
+
isNotEmpty(): boolean;
|
|
604
|
+
/**
|
|
605
|
+
* Determine if a key exists in the map
|
|
606
|
+
*/
|
|
607
|
+
has(key: K): boolean;
|
|
608
|
+
/**
|
|
609
|
+
* Get a value from the map by key
|
|
610
|
+
*/
|
|
611
|
+
get(key: K, defaultValue?: V): V | undefined;
|
|
612
|
+
/**
|
|
613
|
+
* Set a value in the map
|
|
614
|
+
*/
|
|
615
|
+
set(key: K, value: V): this;
|
|
616
|
+
/**
|
|
617
|
+
* Put a value in the map (alias for set)
|
|
618
|
+
*/
|
|
619
|
+
put(key: K, value: V): this;
|
|
620
|
+
/**
|
|
621
|
+
* Remove a key from the map
|
|
622
|
+
*/
|
|
623
|
+
delete(key: K): boolean;
|
|
624
|
+
/**
|
|
625
|
+
* Remove a key from the map (alias for delete)
|
|
626
|
+
*/
|
|
627
|
+
forget(key: K): boolean;
|
|
628
|
+
/**
|
|
629
|
+
* Remove all items from the map
|
|
630
|
+
*/
|
|
631
|
+
clear(): this;
|
|
632
|
+
/**
|
|
633
|
+
* Get all keys from the map
|
|
634
|
+
*/
|
|
635
|
+
keys(): K[];
|
|
636
|
+
/**
|
|
637
|
+
* Get all values from the map
|
|
638
|
+
*/
|
|
639
|
+
values(): V[];
|
|
640
|
+
/**
|
|
641
|
+
* Execute a callback over each item
|
|
642
|
+
*/
|
|
643
|
+
each(callback: (value: V, key: K) => void | false): this;
|
|
644
|
+
/**
|
|
645
|
+
* Run a map over each of the items
|
|
646
|
+
*/
|
|
647
|
+
mapValues<U>(callback: (value: V, key: K) => U): MapCollection<K, U>;
|
|
648
|
+
/**
|
|
649
|
+
* Run a filter over each of the items
|
|
650
|
+
*/
|
|
651
|
+
filter(callback: (value: V, key: K) => boolean): MapCollection<K, V>;
|
|
652
|
+
/**
|
|
653
|
+
* Determine if all items pass the given test
|
|
654
|
+
*/
|
|
655
|
+
every(callback: (value: V, key: K) => boolean): boolean;
|
|
656
|
+
/**
|
|
657
|
+
* Determine if any item passes the given test
|
|
658
|
+
*/
|
|
659
|
+
some(callback: (value: V, key: K) => boolean): boolean;
|
|
660
|
+
/**
|
|
661
|
+
* Get the first value that passes the given test
|
|
662
|
+
*/
|
|
663
|
+
first(callback?: (value: V, key: K) => boolean): V | undefined;
|
|
664
|
+
/**
|
|
665
|
+
* Get the last value that passes the given test
|
|
666
|
+
*/
|
|
667
|
+
last(callback?: (value: V, key: K) => boolean): V | undefined;
|
|
668
|
+
/**
|
|
669
|
+
* Reduce the map to a single value
|
|
670
|
+
*/
|
|
671
|
+
reduce<U>(callback: (carry: U, value: V, key: K) => U, initial: U): U;
|
|
672
|
+
/**
|
|
673
|
+
* Merge another map into this one
|
|
674
|
+
*/
|
|
675
|
+
merge(other: MapCollection<K, V> | Map<K, V> | Record<string, V>): this;
|
|
676
|
+
/**
|
|
677
|
+
* Get only the specified keys
|
|
678
|
+
*/
|
|
679
|
+
only(keys: K[]): MapCollection<K, V>;
|
|
680
|
+
/**
|
|
681
|
+
* Get all items except the specified keys
|
|
682
|
+
*/
|
|
683
|
+
except(keys: K[]): MapCollection<K, V>;
|
|
684
|
+
/**
|
|
685
|
+
* Flip the keys and values
|
|
686
|
+
*/
|
|
687
|
+
flip(): MapCollection<V, K>;
|
|
688
|
+
/**
|
|
689
|
+
* Pass the map to the given callback and return the result
|
|
690
|
+
*/
|
|
691
|
+
pipe<U>(callback: (map: MapCollection<K, V>) => U): U;
|
|
692
|
+
/**
|
|
693
|
+
* Pass the map to the given callback and then return it
|
|
694
|
+
*/
|
|
695
|
+
tap(callback: (map: MapCollection<K, V>) => void): this;
|
|
696
|
+
/**
|
|
697
|
+
* Convert the map to a plain object
|
|
698
|
+
*/
|
|
699
|
+
toObject(): Record<string, V>;
|
|
700
|
+
/**
|
|
701
|
+
* Convert the map to an array of [key, value] pairs
|
|
702
|
+
*/
|
|
703
|
+
toArray(): [K, V][];
|
|
704
|
+
/**
|
|
705
|
+
* Convert the map to JSON
|
|
706
|
+
*/
|
|
707
|
+
toJson(): string;
|
|
708
|
+
/**
|
|
709
|
+
* Get the map as a string
|
|
710
|
+
*/
|
|
711
|
+
toString(): string;
|
|
712
|
+
/**
|
|
713
|
+
* Get the underlying Map instance
|
|
714
|
+
*/
|
|
715
|
+
toMap(): Map<K, V>;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Helper function to create a new map collection
|
|
719
|
+
*/
|
|
720
|
+
declare function collectMap<K, V>(entries?: Iterable<[K, V]> | Record<string, V>): MapCollection<K, V>;
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* Laravel-style Set Collection class
|
|
724
|
+
* Provides collection methods for Set data structures
|
|
725
|
+
*/
|
|
726
|
+
declare class SetCollection<T = any> {
|
|
727
|
+
private set;
|
|
728
|
+
constructor(items?: Iterable<T>);
|
|
729
|
+
/**
|
|
730
|
+
* Create a new set collection instance
|
|
731
|
+
*/
|
|
732
|
+
static make<T>(items?: Iterable<T>): SetCollection<T>;
|
|
733
|
+
/**
|
|
734
|
+
* Get all items as an array
|
|
735
|
+
*/
|
|
736
|
+
all(): T[];
|
|
737
|
+
/**
|
|
738
|
+
* Get the number of items in the set
|
|
739
|
+
*/
|
|
740
|
+
count(): number;
|
|
741
|
+
/**
|
|
742
|
+
* Get the number of items in the set (alias for count)
|
|
743
|
+
*/
|
|
744
|
+
size(): number;
|
|
745
|
+
/**
|
|
746
|
+
* Determine if the set is empty
|
|
747
|
+
*/
|
|
748
|
+
isEmpty(): boolean;
|
|
749
|
+
/**
|
|
750
|
+
* Determine if the set is not empty
|
|
751
|
+
*/
|
|
752
|
+
isNotEmpty(): boolean;
|
|
753
|
+
/**
|
|
754
|
+
* Determine if an item exists in the set
|
|
755
|
+
*/
|
|
756
|
+
has(item: T): boolean;
|
|
757
|
+
/**
|
|
758
|
+
* Determine if an item exists in the set (alias for has)
|
|
759
|
+
*/
|
|
760
|
+
contains(item: T): boolean;
|
|
761
|
+
/**
|
|
762
|
+
* Add an item to the set
|
|
763
|
+
*/
|
|
764
|
+
add(item: T): this;
|
|
765
|
+
/**
|
|
766
|
+
* Add an item to the set (alias for add)
|
|
767
|
+
*/
|
|
768
|
+
push(item: T): this;
|
|
769
|
+
/**
|
|
770
|
+
* Remove an item from the set
|
|
771
|
+
*/
|
|
772
|
+
delete(item: T): boolean;
|
|
773
|
+
/**
|
|
774
|
+
* Remove an item from the set (alias for delete)
|
|
775
|
+
*/
|
|
776
|
+
forget(item: T): boolean;
|
|
777
|
+
/**
|
|
778
|
+
* Remove all items from the set
|
|
779
|
+
*/
|
|
780
|
+
clear(): this;
|
|
781
|
+
/**
|
|
782
|
+
* Execute a callback over each item
|
|
783
|
+
*/
|
|
784
|
+
each(callback: (item: T, index: number) => void | false): this;
|
|
785
|
+
/**
|
|
786
|
+
* Run a map over each of the items
|
|
787
|
+
*/
|
|
788
|
+
map<U>(callback: (item: T, index: number) => U): SetCollection<U>;
|
|
789
|
+
/**
|
|
790
|
+
* Run a filter over each of the items
|
|
791
|
+
*/
|
|
792
|
+
filter(callback: (item: T, index: number) => boolean): SetCollection<T>;
|
|
793
|
+
/**
|
|
794
|
+
* Determine if all items pass the given test
|
|
795
|
+
*/
|
|
796
|
+
every(callback: (item: T, index: number) => boolean): boolean;
|
|
797
|
+
/**
|
|
798
|
+
* Determine if any item passes the given test
|
|
799
|
+
*/
|
|
800
|
+
some(callback: (item: T, index: number) => boolean): boolean;
|
|
801
|
+
/**
|
|
802
|
+
* Get the first item that passes the given test
|
|
803
|
+
*/
|
|
804
|
+
first(callback?: (item: T, index: number) => boolean): T | undefined;
|
|
805
|
+
/**
|
|
806
|
+
* Get the last item that passes the given test
|
|
807
|
+
*/
|
|
808
|
+
last(callback?: (item: T, index: number) => boolean): T | undefined;
|
|
809
|
+
/**
|
|
810
|
+
* Reduce the set to a single value
|
|
811
|
+
*/
|
|
812
|
+
reduce<U>(callback: (carry: U, item: T, index: number) => U, initial: U): U;
|
|
813
|
+
/**
|
|
814
|
+
* Merge another set into this one
|
|
815
|
+
*/
|
|
816
|
+
merge(other: SetCollection<T> | Set<T> | T[]): this;
|
|
817
|
+
/**
|
|
818
|
+
* Get the union of this set and another
|
|
819
|
+
*/
|
|
820
|
+
union(other: SetCollection<T> | Set<T> | T[]): SetCollection<T>;
|
|
821
|
+
/**
|
|
822
|
+
* Get the intersection of this set and another
|
|
823
|
+
*/
|
|
824
|
+
intersect(other: SetCollection<T> | Set<T> | T[]): SetCollection<T>;
|
|
825
|
+
/**
|
|
826
|
+
* Get the difference between this set and another
|
|
827
|
+
*/
|
|
828
|
+
diff(other: SetCollection<T> | Set<T> | T[]): SetCollection<T>;
|
|
829
|
+
/**
|
|
830
|
+
* Get items that are in either set but not in both
|
|
831
|
+
*/
|
|
832
|
+
symmetricDiff(other: SetCollection<T> | Set<T> | T[]): SetCollection<T>;
|
|
833
|
+
/**
|
|
834
|
+
* Determine if this set is a subset of another
|
|
835
|
+
*/
|
|
836
|
+
isSubsetOf(other: SetCollection<T> | Set<T> | T[]): boolean;
|
|
837
|
+
/**
|
|
838
|
+
* Determine if this set is a superset of another
|
|
839
|
+
*/
|
|
840
|
+
isSupersetOf(other: SetCollection<T> | Set<T> | T[]): boolean;
|
|
841
|
+
/**
|
|
842
|
+
* Pass the set to the given callback and return the result
|
|
843
|
+
*/
|
|
844
|
+
pipe<U>(callback: (set: SetCollection<T>) => U): U;
|
|
845
|
+
/**
|
|
846
|
+
* Pass the set to the given callback and then return it
|
|
847
|
+
*/
|
|
848
|
+
tap(callback: (set: SetCollection<T>) => void): this;
|
|
849
|
+
/**
|
|
850
|
+
* Convert the set to an array
|
|
851
|
+
*/
|
|
852
|
+
toArray(): T[];
|
|
853
|
+
/**
|
|
854
|
+
* Convert the set to JSON
|
|
855
|
+
*/
|
|
856
|
+
toJson(): string;
|
|
857
|
+
/**
|
|
858
|
+
* Get the set as a string
|
|
859
|
+
*/
|
|
860
|
+
toString(): string;
|
|
861
|
+
/**
|
|
862
|
+
* Get the underlying Set instance
|
|
863
|
+
*/
|
|
864
|
+
toSet(): Set<T>;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Helper function to create a new set collection
|
|
868
|
+
*/
|
|
869
|
+
declare function collectSet<T>(items?: Iterable<T>): SetCollection<T>;
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* @fileoverview Base registry implementation
|
|
873
|
+
*
|
|
874
|
+
* This file provides a generic base registry class that uses the Collection
|
|
875
|
+
* interface for storage. It provides a consistent API for all registry
|
|
876
|
+
* implementations across the application.
|
|
877
|
+
*
|
|
878
|
+
* Key Features:
|
|
879
|
+
* - Generic type support for any item type
|
|
880
|
+
* - Default item support (fallback when item not found)
|
|
881
|
+
* - Validation hooks (before add, after add)
|
|
882
|
+
* - Collection-based storage (efficient O(1) operations)
|
|
883
|
+
* - Type-safe API
|
|
884
|
+
* - Consistent interface across all registries
|
|
885
|
+
*
|
|
886
|
+
* Use Cases:
|
|
887
|
+
* - Theme registry (storing and retrieving themes)
|
|
888
|
+
* - Token registry (managing design tokens)
|
|
889
|
+
* - Plugin registry (managing plugins)
|
|
890
|
+
* - Configuration registry (storing configs)
|
|
891
|
+
* - Any key-value registry needs
|
|
892
|
+
*
|
|
893
|
+
* @module @pixielity/support
|
|
894
|
+
* @category Registries
|
|
895
|
+
*/
|
|
896
|
+
/**
|
|
897
|
+
* Collection interface for registry storage
|
|
898
|
+
*/
|
|
899
|
+
interface Collection<T> {
|
|
900
|
+
add(key: string, value: T): void;
|
|
901
|
+
get(key: string): T | undefined;
|
|
902
|
+
getAll(): T[];
|
|
903
|
+
getKeys(): string[];
|
|
904
|
+
getAsRecord(): Record<string, T>;
|
|
905
|
+
has(key: string): boolean;
|
|
906
|
+
remove(key: string): boolean;
|
|
907
|
+
clear(): void;
|
|
908
|
+
size(): number;
|
|
909
|
+
isEmpty(): boolean;
|
|
910
|
+
forEach(callback: (value: T, key: string) => void): void;
|
|
911
|
+
map<U>(callback: (value: T, key: string) => U): U[];
|
|
912
|
+
filter(predicate: (value: T, key: string) => boolean): T[];
|
|
913
|
+
find(predicate: (value: T, key: string) => boolean): T | undefined;
|
|
914
|
+
}
|
|
915
|
+
/**
|
|
916
|
+
* Validation result for registry operations
|
|
917
|
+
*
|
|
918
|
+
* Used by validation hooks to indicate whether an operation
|
|
919
|
+
* should proceed or be rejected.
|
|
920
|
+
*
|
|
921
|
+
* @example
|
|
922
|
+
* ```typescript
|
|
923
|
+
* const result: ValidationResult = {
|
|
924
|
+
* valid: false,
|
|
925
|
+
* error: 'Item name cannot be empty'
|
|
926
|
+
* };
|
|
927
|
+
* ```
|
|
928
|
+
*/
|
|
929
|
+
interface ValidationResult {
|
|
930
|
+
/**
|
|
931
|
+
* Whether the validation passed
|
|
932
|
+
*/
|
|
933
|
+
valid: boolean;
|
|
934
|
+
/**
|
|
935
|
+
* Error message if validation failed
|
|
936
|
+
*/
|
|
937
|
+
error?: string;
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Base registry options
|
|
941
|
+
*
|
|
942
|
+
* Configuration options for creating a registry instance.
|
|
943
|
+
* Allows customization of default item behavior and validation.
|
|
944
|
+
*
|
|
945
|
+
* @template T - The type of items stored in the registry
|
|
946
|
+
*/
|
|
947
|
+
interface BaseRegistryOptions<T> {
|
|
948
|
+
/**
|
|
949
|
+
* Default item to return when requested item is not found
|
|
950
|
+
*
|
|
951
|
+
* If not provided, get() will return undefined for missing items.
|
|
952
|
+
* If provided, get() will return this default item instead.
|
|
953
|
+
*/
|
|
954
|
+
defaultItem?: T;
|
|
955
|
+
/**
|
|
956
|
+
* Validation hook called before adding an item
|
|
957
|
+
*
|
|
958
|
+
* Allows custom validation logic before items are added to the registry.
|
|
959
|
+
* If validation fails, the item will not be added and an error will be thrown.
|
|
960
|
+
*
|
|
961
|
+
* @param key - Item key
|
|
962
|
+
* @param item - Item to validate
|
|
963
|
+
* @returns Validation result
|
|
964
|
+
*/
|
|
965
|
+
validateBeforeAdd?: (key: string, item: T) => ValidationResult;
|
|
966
|
+
/**
|
|
967
|
+
* Hook called after an item is successfully added
|
|
968
|
+
*
|
|
969
|
+
* Useful for side effects like logging, notifications, or triggering
|
|
970
|
+
* dependent updates after an item is registered.
|
|
971
|
+
*
|
|
972
|
+
* @param key - Item key
|
|
973
|
+
* @param item - Item that was added
|
|
974
|
+
*/
|
|
975
|
+
afterAdd?: (key: string, item: T) => void;
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Base registry class
|
|
979
|
+
*
|
|
980
|
+
* A generic registry implementation that provides a consistent API for
|
|
981
|
+
* storing and retrieving items by key. Uses the Collection interface
|
|
982
|
+
* for efficient storage with O(1) operations.
|
|
983
|
+
*
|
|
984
|
+
* This class extends Collection functionality by adding:
|
|
985
|
+
* - Default item support
|
|
986
|
+
* - Validation hooks
|
|
987
|
+
* - Consistent registry API
|
|
988
|
+
*
|
|
989
|
+
* All Collection methods are directly accessible on the registry instance.
|
|
990
|
+
*
|
|
991
|
+
* Performance Characteristics:
|
|
992
|
+
* - register(): O(1) + validation time
|
|
993
|
+
* - get(): O(1)
|
|
994
|
+
* - has(): O(1)
|
|
995
|
+
* - remove(): O(1)
|
|
996
|
+
* - getAll(): O(n)
|
|
997
|
+
* - clear(): O(1)
|
|
998
|
+
*
|
|
999
|
+
* @template T - The type of items stored in the registry
|
|
1000
|
+
*
|
|
1001
|
+
* @example
|
|
1002
|
+
* ```typescript
|
|
1003
|
+
* // Create a theme registry
|
|
1004
|
+
* const themeRegistry = new BaseRegistry<Theme>({
|
|
1005
|
+
* defaultItem: defaultTheme,
|
|
1006
|
+
* validateBeforeAdd: (key, theme) => {
|
|
1007
|
+
* if (!theme.name) {
|
|
1008
|
+
* return { valid: false, error: 'Theme must have a name' };
|
|
1009
|
+
* }
|
|
1010
|
+
* return { valid: true };
|
|
1011
|
+
* }
|
|
1012
|
+
* });
|
|
1013
|
+
*
|
|
1014
|
+
* // Register themes
|
|
1015
|
+
* themeRegistry.register('blue', blueTheme);
|
|
1016
|
+
* themeRegistry.register('red', redTheme);
|
|
1017
|
+
*
|
|
1018
|
+
* // Get a theme
|
|
1019
|
+
* const theme = themeRegistry.get('blue');
|
|
1020
|
+
*
|
|
1021
|
+
* // Get all themes
|
|
1022
|
+
* const allThemes = themeRegistry.getAll();
|
|
1023
|
+
*
|
|
1024
|
+
* // Check if theme exists
|
|
1025
|
+
* if (themeRegistry.has('blue')) {
|
|
1026
|
+
* console.log('Blue theme exists');
|
|
1027
|
+
* }
|
|
1028
|
+
* ```
|
|
1029
|
+
*
|
|
1030
|
+
* @example
|
|
1031
|
+
* ```typescript
|
|
1032
|
+
* // Create a simple token registry
|
|
1033
|
+
* const tokenRegistry = new BaseRegistry<Token>();
|
|
1034
|
+
*
|
|
1035
|
+
* tokenRegistry.register('primary', { value: '#0000FF' });
|
|
1036
|
+
* tokenRegistry.register('secondary', { value: '#FF0000' });
|
|
1037
|
+
*
|
|
1038
|
+
* const allTokens = tokenRegistry.getAll();
|
|
1039
|
+
* console.log(allTokens.length); // 2
|
|
1040
|
+
* ```
|
|
1041
|
+
*/
|
|
1042
|
+
declare class BaseRegistry<T> implements Collection<T> {
|
|
1043
|
+
/**
|
|
1044
|
+
* Internal collection for storing registry items
|
|
1045
|
+
*
|
|
1046
|
+
* Uses Collection interface for flexible storage implementation.
|
|
1047
|
+
* By default, uses MapCollection for O(1) operations.
|
|
1048
|
+
*/
|
|
1049
|
+
protected collection: Collection<T>;
|
|
1050
|
+
/**
|
|
1051
|
+
* Default item to return when requested item is not found
|
|
1052
|
+
*
|
|
1053
|
+
* If set, get() will return this item instead of undefined
|
|
1054
|
+
* when the requested key doesn't exist in the registry.
|
|
1055
|
+
*/
|
|
1056
|
+
protected defaultItem?: T;
|
|
1057
|
+
/**
|
|
1058
|
+
* Validation hook called before adding an item
|
|
1059
|
+
*
|
|
1060
|
+
* If provided, this function is called before every register()
|
|
1061
|
+
* operation to validate the item. If validation fails, the
|
|
1062
|
+
* item is not added and an error is thrown.
|
|
1063
|
+
*/
|
|
1064
|
+
protected validateBeforeAdd?: (key: string, item: T) => ValidationResult;
|
|
1065
|
+
/**
|
|
1066
|
+
* Hook called after an item is successfully added
|
|
1067
|
+
*
|
|
1068
|
+
* If provided, this function is called after every successful
|
|
1069
|
+
* register() operation. Useful for side effects like logging
|
|
1070
|
+
* or triggering dependent updates.
|
|
1071
|
+
*/
|
|
1072
|
+
protected afterAdd?: (key: string, item: T) => void;
|
|
1073
|
+
/**
|
|
1074
|
+
* Creates a new BaseRegistry instance
|
|
1075
|
+
*
|
|
1076
|
+
* Initializes the registry with optional configuration for default
|
|
1077
|
+
* item and validation hooks. By default, uses MapCollection for storage.
|
|
1078
|
+
*
|
|
1079
|
+
* @param options - Registry configuration options
|
|
1080
|
+
*
|
|
1081
|
+
* @example
|
|
1082
|
+
* ```typescript
|
|
1083
|
+
* // Simple registry without options
|
|
1084
|
+
* const registry = new BaseRegistry<Theme>();
|
|
1085
|
+
* ```
|
|
1086
|
+
*
|
|
1087
|
+
* @example
|
|
1088
|
+
* ```typescript
|
|
1089
|
+
* // Registry with default item
|
|
1090
|
+
* const registry = new BaseRegistry<Theme>({
|
|
1091
|
+
* defaultItem: defaultTheme
|
|
1092
|
+
* });
|
|
1093
|
+
* ```
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```typescript
|
|
1097
|
+
* // Registry with validation
|
|
1098
|
+
* const registry = new BaseRegistry<Theme>({
|
|
1099
|
+
* validateBeforeAdd: (key, theme) => {
|
|
1100
|
+
* if (!theme.name) {
|
|
1101
|
+
* return { valid: false, error: 'Theme must have a name' };
|
|
1102
|
+
* }
|
|
1103
|
+
* return { valid: true };
|
|
1104
|
+
* },
|
|
1105
|
+
* afterAdd: (key, theme) => {
|
|
1106
|
+
* console.log(`Registered theme: ${theme.name}`);
|
|
1107
|
+
* }
|
|
1108
|
+
* });
|
|
1109
|
+
* ```
|
|
1110
|
+
*/
|
|
1111
|
+
constructor(options?: BaseRegistryOptions<T>);
|
|
1112
|
+
/**
|
|
1113
|
+
* Register an item in the registry
|
|
1114
|
+
*
|
|
1115
|
+
* Adds or updates an item in the registry with the specified key.
|
|
1116
|
+
* If an item with the same key already exists, it will be replaced.
|
|
1117
|
+
*
|
|
1118
|
+
* If a validation hook is configured, it will be called before adding
|
|
1119
|
+
* the item. If validation fails, an error is thrown and the item is
|
|
1120
|
+
* not added.
|
|
1121
|
+
*
|
|
1122
|
+
* If an afterAdd hook is configured, it will be called after the item
|
|
1123
|
+
* is successfully added.
|
|
1124
|
+
*
|
|
1125
|
+
* Time Complexity: O(1) + validation time
|
|
1126
|
+
*
|
|
1127
|
+
* @param key - Unique identifier for the item
|
|
1128
|
+
* @param item - Item to register
|
|
1129
|
+
* @throws Error if validation fails
|
|
1130
|
+
*
|
|
1131
|
+
* @example
|
|
1132
|
+
* ```typescript
|
|
1133
|
+
* const registry = new BaseRegistry<Theme>();
|
|
1134
|
+
*
|
|
1135
|
+
* // Register a theme
|
|
1136
|
+
* registry.register('blue', {
|
|
1137
|
+
* name: 'Blue',
|
|
1138
|
+
* colors: { accent: '#0000FF' }
|
|
1139
|
+
* });
|
|
1140
|
+
*
|
|
1141
|
+
* // Update existing theme
|
|
1142
|
+
* registry.register('blue', {
|
|
1143
|
+
* name: 'Blue',
|
|
1144
|
+
* colors: { accent: '#0066FF' }
|
|
1145
|
+
* });
|
|
1146
|
+
* ```
|
|
1147
|
+
*/
|
|
1148
|
+
register(key: string, item: T): void;
|
|
1149
|
+
/**
|
|
1150
|
+
* Add an item to the collection (alias for register)
|
|
1151
|
+
*
|
|
1152
|
+
* This method is part of the Collection interface.
|
|
1153
|
+
* It delegates to register() to ensure validation hooks are called.
|
|
1154
|
+
*
|
|
1155
|
+
* Time Complexity: O(1) + validation time
|
|
1156
|
+
*
|
|
1157
|
+
* @param key - Unique identifier for the item
|
|
1158
|
+
* @param value - Item to add
|
|
1159
|
+
*/
|
|
1160
|
+
add(key: string, value: T): void;
|
|
1161
|
+
/**
|
|
1162
|
+
* Get an item from the registry
|
|
1163
|
+
*
|
|
1164
|
+
* Retrieves an item by its key. If the item doesn't exist:
|
|
1165
|
+
* - Returns the default item if one was configured
|
|
1166
|
+
* - Returns undefined if no default item was configured
|
|
1167
|
+
*
|
|
1168
|
+
* Time Complexity: O(1)
|
|
1169
|
+
*
|
|
1170
|
+
* @param key - Item identifier
|
|
1171
|
+
* @returns Item if found, default item if configured, or undefined
|
|
1172
|
+
*
|
|
1173
|
+
* @example
|
|
1174
|
+
* ```typescript
|
|
1175
|
+
* const theme = registry.get('blue');
|
|
1176
|
+
* ```
|
|
1177
|
+
*/
|
|
1178
|
+
get(key: string): T | undefined;
|
|
1179
|
+
/**
|
|
1180
|
+
* Get all items in the registry
|
|
1181
|
+
*
|
|
1182
|
+
* Returns an array containing all items in the registry.
|
|
1183
|
+
* The order of items depends on the collection implementation
|
|
1184
|
+
* (MapCollection maintains insertion order).
|
|
1185
|
+
*
|
|
1186
|
+
* Time Complexity: O(n) where n is the number of items
|
|
1187
|
+
*
|
|
1188
|
+
* @returns Array of all items in the registry
|
|
1189
|
+
*
|
|
1190
|
+
* @example
|
|
1191
|
+
* ```typescript
|
|
1192
|
+
* const allThemes = registry.getAll();
|
|
1193
|
+
* ```
|
|
1194
|
+
*/
|
|
1195
|
+
getAll(): T[];
|
|
1196
|
+
/**
|
|
1197
|
+
* Get all keys in the registry
|
|
1198
|
+
*
|
|
1199
|
+
* Returns an array containing all keys in the registry.
|
|
1200
|
+
* Useful for iteration or checking what items are registered.
|
|
1201
|
+
*
|
|
1202
|
+
* Time Complexity: O(n) where n is the number of items
|
|
1203
|
+
*
|
|
1204
|
+
* @returns Array of all keys in the registry
|
|
1205
|
+
*
|
|
1206
|
+
* @example
|
|
1207
|
+
* ```typescript
|
|
1208
|
+
* const keys = registry.getKeys();
|
|
1209
|
+
* ```
|
|
1210
|
+
*/
|
|
1211
|
+
getKeys(): string[];
|
|
1212
|
+
/**
|
|
1213
|
+
* Get registry as a record object
|
|
1214
|
+
*
|
|
1215
|
+
* Converts the registry to a plain JavaScript object (record)
|
|
1216
|
+
* with keys mapping to values. Useful for serialization.
|
|
1217
|
+
*
|
|
1218
|
+
* Time Complexity: O(n) where n is the number of items
|
|
1219
|
+
*
|
|
1220
|
+
* @returns Record object with keys mapping to values
|
|
1221
|
+
*
|
|
1222
|
+
* @example
|
|
1223
|
+
* ```typescript
|
|
1224
|
+
* const record = registry.getAsRecord();
|
|
1225
|
+
* ```
|
|
1226
|
+
*/
|
|
1227
|
+
getAsRecord(): Record<string, T>;
|
|
1228
|
+
/**
|
|
1229
|
+
* Check if an item is registered
|
|
1230
|
+
*
|
|
1231
|
+
* Checks whether an item with the specified key exists in the registry.
|
|
1232
|
+
* Does not check the value, only the presence of the key.
|
|
1233
|
+
*
|
|
1234
|
+
* Time Complexity: O(1)
|
|
1235
|
+
*
|
|
1236
|
+
* @param key - Item identifier to check
|
|
1237
|
+
* @returns True if item is registered, false otherwise
|
|
1238
|
+
*
|
|
1239
|
+
* @example
|
|
1240
|
+
* ```typescript
|
|
1241
|
+
* if (registry.has('blue')) {
|
|
1242
|
+
* console.log('Blue theme exists');
|
|
1243
|
+
* }
|
|
1244
|
+
* ```
|
|
1245
|
+
*/
|
|
1246
|
+
has(key: string): boolean;
|
|
1247
|
+
/**
|
|
1248
|
+
* Remove an item from the registry
|
|
1249
|
+
*
|
|
1250
|
+
* Removes an item with the specified key from the registry.
|
|
1251
|
+
* Returns true if the item was removed, false if it didn't exist.
|
|
1252
|
+
*
|
|
1253
|
+
* Time Complexity: O(1)
|
|
1254
|
+
*
|
|
1255
|
+
* @param key - Item identifier to remove
|
|
1256
|
+
* @returns True if item was removed, false if it didn't exist
|
|
1257
|
+
*
|
|
1258
|
+
* @example
|
|
1259
|
+
* ```typescript
|
|
1260
|
+
* const removed = registry.remove('blue');
|
|
1261
|
+
* ```
|
|
1262
|
+
*/
|
|
1263
|
+
remove(key: string): boolean;
|
|
1264
|
+
/**
|
|
1265
|
+
* Clear all items from the registry
|
|
1266
|
+
*
|
|
1267
|
+
* Removes all items from the registry, leaving it empty.
|
|
1268
|
+
* This operation is irreversible.
|
|
1269
|
+
*
|
|
1270
|
+
* Time Complexity: O(1)
|
|
1271
|
+
*
|
|
1272
|
+
* @example
|
|
1273
|
+
* ```typescript
|
|
1274
|
+
* registry.clear();
|
|
1275
|
+
* ```
|
|
1276
|
+
*/
|
|
1277
|
+
clear(): void;
|
|
1278
|
+
/**
|
|
1279
|
+
* Get the number of items in the registry
|
|
1280
|
+
*
|
|
1281
|
+
* Returns the total count of items currently registered.
|
|
1282
|
+
*
|
|
1283
|
+
* Time Complexity: O(1)
|
|
1284
|
+
*
|
|
1285
|
+
* @returns Number of items in the registry
|
|
1286
|
+
*
|
|
1287
|
+
* @example
|
|
1288
|
+
* ```typescript
|
|
1289
|
+
* console.log(registry.size()); // 2
|
|
1290
|
+
* ```
|
|
1291
|
+
*/
|
|
1292
|
+
size(): number;
|
|
1293
|
+
/**
|
|
1294
|
+
* Check if the registry is empty
|
|
1295
|
+
*
|
|
1296
|
+
* Returns true if the registry contains no items, false otherwise.
|
|
1297
|
+
* This is a convenience method equivalent to checking if size() === 0.
|
|
1298
|
+
*
|
|
1299
|
+
* Time Complexity: O(1)
|
|
1300
|
+
*
|
|
1301
|
+
* @returns True if registry has no items, false otherwise
|
|
1302
|
+
*
|
|
1303
|
+
* @example
|
|
1304
|
+
* ```typescript
|
|
1305
|
+
* console.log(registry.isEmpty()); // true
|
|
1306
|
+
* ```
|
|
1307
|
+
*/
|
|
1308
|
+
isEmpty(): boolean;
|
|
1309
|
+
/**
|
|
1310
|
+
* Iterate over all items in the registry
|
|
1311
|
+
*
|
|
1312
|
+
* Executes a callback function for each item in the registry.
|
|
1313
|
+
* Items are iterated in insertion order (for MapCollection).
|
|
1314
|
+
*
|
|
1315
|
+
* Time Complexity: O(n) where n is the number of items
|
|
1316
|
+
*
|
|
1317
|
+
* @param callback - Function to call for each item (value, key)
|
|
1318
|
+
*
|
|
1319
|
+
* @example
|
|
1320
|
+
* ```typescript
|
|
1321
|
+
* registry.forEach((theme, key) => {
|
|
1322
|
+
* console.log(`${key}: ${theme.name}`);
|
|
1323
|
+
* });
|
|
1324
|
+
* ```
|
|
1325
|
+
*/
|
|
1326
|
+
forEach(callback: (value: T, key: string) => void): void;
|
|
1327
|
+
/**
|
|
1328
|
+
* Map over all items in the registry
|
|
1329
|
+
*
|
|
1330
|
+
* Transforms each item in the registry using a callback function
|
|
1331
|
+
* and returns an array of the transformed values.
|
|
1332
|
+
*
|
|
1333
|
+
* Time Complexity: O(n) where n is the number of items
|
|
1334
|
+
*
|
|
1335
|
+
* @template U - The type of the transformed items
|
|
1336
|
+
* @param callback - Function to transform each item (value, key) => U
|
|
1337
|
+
* @returns Array of transformed items
|
|
1338
|
+
*
|
|
1339
|
+
* @example
|
|
1340
|
+
* ```typescript
|
|
1341
|
+
* const names = registry.map(theme => theme.name);
|
|
1342
|
+
* ```
|
|
1343
|
+
*/
|
|
1344
|
+
map<U>(callback: (value: T, key: string) => U): U[];
|
|
1345
|
+
/**
|
|
1346
|
+
* Filter items in the registry
|
|
1347
|
+
*
|
|
1348
|
+
* Returns an array of items that pass the test implemented by the
|
|
1349
|
+
* provided predicate function.
|
|
1350
|
+
*
|
|
1351
|
+
* Time Complexity: O(n) where n is the number of items
|
|
1352
|
+
*
|
|
1353
|
+
* @param predicate - Function to test each item (value, key) => boolean
|
|
1354
|
+
* @returns Array of items that pass the test
|
|
1355
|
+
*
|
|
1356
|
+
* @example
|
|
1357
|
+
* ```typescript
|
|
1358
|
+
* const darkThemes = registry.filter(theme => theme.isDark);
|
|
1359
|
+
* ```
|
|
1360
|
+
*/
|
|
1361
|
+
filter(predicate: (value: T, key: string) => boolean): T[];
|
|
1362
|
+
/**
|
|
1363
|
+
* Find an item in the registry
|
|
1364
|
+
*
|
|
1365
|
+
* Returns the first item that satisfies the provided predicate function.
|
|
1366
|
+
* Returns undefined if no item passes the test.
|
|
1367
|
+
*
|
|
1368
|
+
* Time Complexity: O(n) worst case, O(1) best case
|
|
1369
|
+
*
|
|
1370
|
+
* @param predicate - Function to test each item (value, key) => boolean
|
|
1371
|
+
* @returns First item that passes the test, or undefined
|
|
1372
|
+
*
|
|
1373
|
+
* @example
|
|
1374
|
+
* ```typescript
|
|
1375
|
+
* const defaultTheme = registry.find(theme => theme.isDefault);
|
|
1376
|
+
* ```
|
|
1377
|
+
*/
|
|
1378
|
+
find(predicate: (value: T, key: string) => boolean): T | undefined;
|
|
1379
|
+
}
|
|
1380
|
+
|
|
1381
|
+
/**
|
|
1382
|
+
* @fileoverview Facade interfaces
|
|
1383
|
+
*
|
|
1384
|
+
* Defines the interfaces for the Facade pattern implementation.
|
|
1385
|
+
* Facades provide a static interface to services resolved from the DI container.
|
|
1386
|
+
*
|
|
1387
|
+
* @module @abdokouta/react-support
|
|
1388
|
+
* @category Facades
|
|
1389
|
+
*/
|
|
1390
|
+
/**
|
|
1391
|
+
* Application interface for facade resolution
|
|
1392
|
+
*
|
|
1393
|
+
* This interface represents the minimal contract that an application/container
|
|
1394
|
+
* must implement to work with facades. It mirrors the Laravel Application contract.
|
|
1395
|
+
*/
|
|
1396
|
+
interface FacadeApplication {
|
|
1397
|
+
/**
|
|
1398
|
+
* Resolve a service from the container
|
|
1399
|
+
*
|
|
1400
|
+
* @param abstract - Service identifier (string, symbol, or class)
|
|
1401
|
+
* @returns The resolved service instance
|
|
1402
|
+
*/
|
|
1403
|
+
get<T>(abstract: string | symbol | (new (...args: unknown[]) => T)): T;
|
|
1404
|
+
/**
|
|
1405
|
+
* Check if a service has been resolved
|
|
1406
|
+
*
|
|
1407
|
+
* @param abstract - Service identifier
|
|
1408
|
+
* @returns True if the service has been resolved
|
|
1409
|
+
*/
|
|
1410
|
+
resolved?(abstract: string | symbol): boolean;
|
|
1411
|
+
/**
|
|
1412
|
+
* Register a callback to run after a service is resolved
|
|
1413
|
+
*
|
|
1414
|
+
* @param abstract - Service identifier
|
|
1415
|
+
* @param callback - Callback to run after resolution
|
|
1416
|
+
*/
|
|
1417
|
+
afterResolving?(abstract: string | symbol, callback: (service: unknown, app: FacadeApplication) => void): void;
|
|
1418
|
+
/**
|
|
1419
|
+
* Bind an instance to the container
|
|
1420
|
+
*
|
|
1421
|
+
* @param abstract - Service identifier
|
|
1422
|
+
* @param instance - Instance to bind
|
|
1423
|
+
*/
|
|
1424
|
+
instance?(abstract: string | symbol, instance: unknown): void;
|
|
1425
|
+
}
|
|
1426
|
+
/**
|
|
1427
|
+
* Fake interface for testing
|
|
1428
|
+
*
|
|
1429
|
+
* Facades can be swapped with fakes for testing purposes.
|
|
1430
|
+
* Any object implementing this interface is considered a fake.
|
|
1431
|
+
*/
|
|
1432
|
+
interface Fake {
|
|
1433
|
+
/**
|
|
1434
|
+
* Marker to identify fake instances
|
|
1435
|
+
*/
|
|
1436
|
+
readonly __isFake: true;
|
|
1437
|
+
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Check if an object is a Fake
|
|
1440
|
+
*
|
|
1441
|
+
* @param obj - Object to check
|
|
1442
|
+
* @returns True if the object is a Fake
|
|
1443
|
+
*/
|
|
1444
|
+
declare function isFake(obj: unknown): obj is Fake;
|
|
1445
|
+
|
|
1446
|
+
/**
|
|
1447
|
+
* @fileoverview Base Facade implementation
|
|
1448
|
+
*
|
|
1449
|
+
* This file provides the base Facade class that enables static access to
|
|
1450
|
+
* services resolved from the DI container. Inspired by Laravel's Facade pattern.
|
|
1451
|
+
*
|
|
1452
|
+
* Uses @abdokouta/react-di's getModuleContainer to resolve services,
|
|
1453
|
+
* enabling facades to work outside of React components.
|
|
1454
|
+
*
|
|
1455
|
+
* Key Features:
|
|
1456
|
+
* - Static interface to container-resolved services
|
|
1457
|
+
* - Instance caching for performance
|
|
1458
|
+
* - Hot-swapping for testing
|
|
1459
|
+
* - Fake detection for test assertions
|
|
1460
|
+
* - Works outside React components
|
|
1461
|
+
*
|
|
1462
|
+
* @module @abdokouta/react-support
|
|
1463
|
+
* @category Facades
|
|
1464
|
+
*/
|
|
1465
|
+
|
|
1466
|
+
/**
|
|
1467
|
+
* Base Facade class
|
|
1468
|
+
*
|
|
1469
|
+
* Provides a static interface to services resolved from the DI container.
|
|
1470
|
+
* Subclasses must implement `getFacadeAccessor()` to specify which service
|
|
1471
|
+
* the facade represents.
|
|
1472
|
+
*
|
|
1473
|
+
* @example
|
|
1474
|
+
* ```typescript
|
|
1475
|
+
* import { Facade } from '@abdokouta/react-support';
|
|
1476
|
+
* import { LoggerService } from './logger.service';
|
|
1477
|
+
* import { AppModule } from './app.module';
|
|
1478
|
+
*
|
|
1479
|
+
* class Log extends Facade {
|
|
1480
|
+
* protected static getFacadeAccessor(): ServiceIdentifier {
|
|
1481
|
+
* return LoggerService;
|
|
1482
|
+
* }
|
|
1483
|
+
* }
|
|
1484
|
+
*
|
|
1485
|
+
* // Set the module once at app bootstrap
|
|
1486
|
+
* Facade.setFacadeModule(AppModule);
|
|
1487
|
+
*
|
|
1488
|
+
* // Use the facade statically anywhere
|
|
1489
|
+
* Log.info('Hello, world!');
|
|
1490
|
+
* Log.error('Something went wrong');
|
|
1491
|
+
* ```
|
|
1492
|
+
*
|
|
1493
|
+
* @example
|
|
1494
|
+
* ```typescript
|
|
1495
|
+
* // Swap with a fake for testing
|
|
1496
|
+
* const fakeLogs: string[] = [];
|
|
1497
|
+
* const fakeLogger = {
|
|
1498
|
+
* __isFake: true as const,
|
|
1499
|
+
* info: (msg: string) => fakeLogs.push(msg),
|
|
1500
|
+
* error: (msg: string) => fakeLogs.push(msg),
|
|
1501
|
+
* };
|
|
1502
|
+
*
|
|
1503
|
+
* Log.swap(fakeLogger);
|
|
1504
|
+
* Log.info('Test message');
|
|
1505
|
+
* expect(fakeLogs).toContain('Test message');
|
|
1506
|
+
* ```
|
|
1507
|
+
*/
|
|
1508
|
+
declare abstract class Facade {
|
|
1509
|
+
/**
|
|
1510
|
+
* The root module class for resolving services
|
|
1511
|
+
*/
|
|
1512
|
+
protected static moduleClass: Newable | null;
|
|
1513
|
+
/**
|
|
1514
|
+
* The module container instance (cached)
|
|
1515
|
+
*/
|
|
1516
|
+
protected static container: ModuleContainer | null;
|
|
1517
|
+
/**
|
|
1518
|
+
* The resolved object instances
|
|
1519
|
+
*
|
|
1520
|
+
* Caches resolved instances by their accessor key for performance.
|
|
1521
|
+
*/
|
|
1522
|
+
protected static resolvedInstance: Map<string | symbol, unknown>;
|
|
1523
|
+
/**
|
|
1524
|
+
* Indicates if the resolved instance should be cached
|
|
1525
|
+
*
|
|
1526
|
+
* Set to false in subclasses to always resolve fresh instances.
|
|
1527
|
+
*/
|
|
1528
|
+
protected static cached: boolean;
|
|
1529
|
+
/**
|
|
1530
|
+
* Hotswap the underlying instance behind the facade
|
|
1531
|
+
*
|
|
1532
|
+
* Useful for testing - swap the real service with a mock or fake.
|
|
1533
|
+
*
|
|
1534
|
+
* @param instance - Instance to swap in
|
|
1535
|
+
*
|
|
1536
|
+
* @example
|
|
1537
|
+
* ```typescript
|
|
1538
|
+
* // In tests
|
|
1539
|
+
* const mockLogger = { info: vi.fn(), error: vi.fn() };
|
|
1540
|
+
* Log.swap(mockLogger);
|
|
1541
|
+
*
|
|
1542
|
+
* // Now Log.info() calls mockLogger.info()
|
|
1543
|
+
* Log.info('test');
|
|
1544
|
+
* expect(mockLogger.info).toHaveBeenCalledWith('test');
|
|
1545
|
+
* ```
|
|
1546
|
+
*/
|
|
1547
|
+
static swap(instance: unknown): void;
|
|
1548
|
+
/**
|
|
1549
|
+
* Determines whether a "fake" has been set as the facade instance
|
|
1550
|
+
*
|
|
1551
|
+
* @returns True if the current instance is a Fake
|
|
1552
|
+
*
|
|
1553
|
+
* @example
|
|
1554
|
+
* ```typescript
|
|
1555
|
+
* if (Log.isFake()) {
|
|
1556
|
+
* console.log('Using fake logger');
|
|
1557
|
+
* }
|
|
1558
|
+
* ```
|
|
1559
|
+
*/
|
|
1560
|
+
static isFake(): boolean;
|
|
1561
|
+
/**
|
|
1562
|
+
* Get the root object behind the facade
|
|
1563
|
+
*
|
|
1564
|
+
* Resolves and returns the actual service instance.
|
|
1565
|
+
*
|
|
1566
|
+
* @returns The resolved service instance
|
|
1567
|
+
*/
|
|
1568
|
+
static getFacadeRoot<T = unknown>(): T;
|
|
1569
|
+
/**
|
|
1570
|
+
* Get the registered name of the component
|
|
1571
|
+
*
|
|
1572
|
+
* Subclasses MUST override this method to specify which service
|
|
1573
|
+
* the facade represents.
|
|
1574
|
+
*
|
|
1575
|
+
* @returns Service identifier (string, symbol, or class)
|
|
1576
|
+
* @throws Error if not implemented
|
|
1577
|
+
*
|
|
1578
|
+
* @example
|
|
1579
|
+
* ```typescript
|
|
1580
|
+
* class Log extends Facade {
|
|
1581
|
+
* protected static getFacadeAccessor(): ServiceIdentifier {
|
|
1582
|
+
* return LoggerService; // or 'logger' string token
|
|
1583
|
+
* }
|
|
1584
|
+
* }
|
|
1585
|
+
* ```
|
|
1586
|
+
*/
|
|
1587
|
+
protected static getFacadeAccessor(): ServiceIdentifier;
|
|
1588
|
+
/**
|
|
1589
|
+
* Get a consistent key for the accessor
|
|
1590
|
+
*/
|
|
1591
|
+
protected static getAccessorKey(accessor: ServiceIdentifier): string | symbol;
|
|
1592
|
+
/**
|
|
1593
|
+
* Resolve the facade root instance from the container
|
|
1594
|
+
*
|
|
1595
|
+
* @param identifier - Service identifier
|
|
1596
|
+
* @returns Resolved service instance
|
|
1597
|
+
*/
|
|
1598
|
+
protected static resolveFacadeInstance<T>(identifier: ServiceIdentifier<T>): T;
|
|
1599
|
+
/**
|
|
1600
|
+
* Get the module container
|
|
1601
|
+
*
|
|
1602
|
+
* @returns The module container instance
|
|
1603
|
+
*/
|
|
1604
|
+
protected static getContainer(): ModuleContainer | null;
|
|
1605
|
+
/**
|
|
1606
|
+
* Clear a resolved facade instance
|
|
1607
|
+
*
|
|
1608
|
+
* @param name - Service identifier to clear (defaults to this facade's accessor)
|
|
1609
|
+
*/
|
|
1610
|
+
static clearResolvedInstance(name?: string | symbol): void;
|
|
1611
|
+
/**
|
|
1612
|
+
* Clear all resolved instances
|
|
1613
|
+
*
|
|
1614
|
+
* Useful for test cleanup.
|
|
1615
|
+
*/
|
|
1616
|
+
static clearResolvedInstances(): void;
|
|
1617
|
+
/**
|
|
1618
|
+
* Get the module class
|
|
1619
|
+
*
|
|
1620
|
+
* @returns The module class
|
|
1621
|
+
*/
|
|
1622
|
+
static getFacadeModule(): Newable | null;
|
|
1623
|
+
/**
|
|
1624
|
+
* Set the module class for facade resolution
|
|
1625
|
+
*
|
|
1626
|
+
* Must be called during application bootstrap to enable facades.
|
|
1627
|
+
* Call this AFTER Inversiland.run() or Container.configure().build().
|
|
1628
|
+
*
|
|
1629
|
+
* @param module - The root module class
|
|
1630
|
+
*
|
|
1631
|
+
* @example
|
|
1632
|
+
* ```typescript
|
|
1633
|
+
* // In your app bootstrap (main.tsx)
|
|
1634
|
+
* import { Facade } from '@abdokouta/react-support';
|
|
1635
|
+
* import { Container, ContainerProvider } from '@abdokouta/react-di';
|
|
1636
|
+
* import { AppModule } from './app.module';
|
|
1637
|
+
*
|
|
1638
|
+
* // Initialize container
|
|
1639
|
+
* Container.configure().withModule(AppModule).withDefaults().build();
|
|
1640
|
+
*
|
|
1641
|
+
* // Set facade module
|
|
1642
|
+
* Facade.setFacadeModule(AppModule);
|
|
1643
|
+
*
|
|
1644
|
+
* // Now facades work anywhere
|
|
1645
|
+
* ReactDOM.createRoot(document.getElementById("root")!).render(
|
|
1646
|
+
* <ContainerProvider module={AppModule}>
|
|
1647
|
+
* <App />
|
|
1648
|
+
* </ContainerProvider>
|
|
1649
|
+
* );
|
|
1650
|
+
* ```
|
|
1651
|
+
*/
|
|
1652
|
+
static setFacadeModule(module: Newable | null): void;
|
|
1653
|
+
/**
|
|
1654
|
+
* Set the container directly (alternative to setFacadeModule)
|
|
1655
|
+
*
|
|
1656
|
+
* @param container - The module container instance
|
|
1657
|
+
*/
|
|
1658
|
+
static setFacadeContainer(container: ModuleContainer | null): void;
|
|
1659
|
+
/**
|
|
1660
|
+
* @deprecated Use setFacadeModule instead
|
|
1661
|
+
*/
|
|
1662
|
+
static setFacadeApplication(app: FacadeApplication | null): void;
|
|
1663
|
+
/**
|
|
1664
|
+
* @deprecated Use getFacadeModule instead
|
|
1665
|
+
*/
|
|
1666
|
+
static getFacadeApplication(): FacadeApplication | null;
|
|
1667
|
+
}
|
|
1668
|
+
|
|
1669
|
+
/**
|
|
1670
|
+
* @fileoverview Facade factory with Proxy support
|
|
1671
|
+
*
|
|
1672
|
+
* Creates facades with automatic method forwarding using JavaScript Proxy.
|
|
1673
|
+
* This enables the Laravel-style `Facade::method()` pattern in TypeScript.
|
|
1674
|
+
*
|
|
1675
|
+
* @module @abdokouta/react-support
|
|
1676
|
+
* @category Facades
|
|
1677
|
+
*/
|
|
1678
|
+
|
|
1679
|
+
/**
|
|
1680
|
+
* Facade class type with static methods and proxied service methods
|
|
1681
|
+
*/
|
|
1682
|
+
type FacadeClass<T> = typeof Facade & {
|
|
1683
|
+
getFacadeRoot<R = T>(): R;
|
|
1684
|
+
} & {
|
|
1685
|
+
[K in keyof T]: T[K];
|
|
1686
|
+
};
|
|
1687
|
+
/**
|
|
1688
|
+
* Options for creating a facade
|
|
1689
|
+
*/
|
|
1690
|
+
interface CreateFacadeOptions<T> {
|
|
1691
|
+
/**
|
|
1692
|
+
* Service identifier (string token, symbol, or class)
|
|
1693
|
+
*/
|
|
1694
|
+
accessor: ServiceIdentifier<T>;
|
|
1695
|
+
/**
|
|
1696
|
+
* Whether to cache the resolved instance
|
|
1697
|
+
* @default true
|
|
1698
|
+
*/
|
|
1699
|
+
cached?: boolean;
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Create a facade for a service
|
|
1703
|
+
*
|
|
1704
|
+
* Creates a Proxy-based facade that forwards all method calls to the
|
|
1705
|
+
* resolved service instance. This enables the Laravel-style pattern
|
|
1706
|
+
* where you can call methods directly on the facade class.
|
|
1707
|
+
*
|
|
1708
|
+
* @param options - Facade configuration
|
|
1709
|
+
* @returns Proxied facade class
|
|
1710
|
+
*
|
|
1711
|
+
* @example
|
|
1712
|
+
* ```typescript
|
|
1713
|
+
* // Define your service interface
|
|
1714
|
+
* interface ILogger {
|
|
1715
|
+
* info(message: string): void;
|
|
1716
|
+
* error(message: string): void;
|
|
1717
|
+
* debug(message: string): void;
|
|
1718
|
+
* }
|
|
1719
|
+
*
|
|
1720
|
+
* // Create the facade
|
|
1721
|
+
* const Log = createFacade<ILogger>({
|
|
1722
|
+
* accessor: 'logger', // or LoggerService class
|
|
1723
|
+
* });
|
|
1724
|
+
*
|
|
1725
|
+
* // Set module at bootstrap
|
|
1726
|
+
* Facade.setFacadeModule(AppModule);
|
|
1727
|
+
*
|
|
1728
|
+
* // Use it statically
|
|
1729
|
+
* Log.info('Hello!');
|
|
1730
|
+
* Log.error('Oops!');
|
|
1731
|
+
* ```
|
|
1732
|
+
*/
|
|
1733
|
+
declare function createFacade<T extends object>(options: CreateFacadeOptions<T>): FacadeClass<T>;
|
|
1734
|
+
/**
|
|
1735
|
+
* Create a typed facade class (without proxy)
|
|
1736
|
+
*
|
|
1737
|
+
* @param accessor - Service identifier
|
|
1738
|
+
* @returns Facade class constructor
|
|
1739
|
+
*/
|
|
1740
|
+
declare function createFacadeClass<T>(accessor: ServiceIdentifier<T>): typeof Facade;
|
|
1741
|
+
/**
|
|
1742
|
+
* Get container from a module class
|
|
1743
|
+
*
|
|
1744
|
+
* @param moduleClass - The module class
|
|
1745
|
+
* @returns ModuleContainer instance
|
|
1746
|
+
*/
|
|
1747
|
+
declare function getContainerFromModule(moduleClass: Newable): ModuleContainer;
|
|
1748
|
+
|
|
1749
|
+
export { BaseRegistry, type BaseRegistryOptions, Collection$1 as Collection, type CreateFacadeOptions, Facade, type FacadeApplication, type FacadeClass, type Fake, MapCollection, SetCollection, Str, type ValidationResult, collect, collectMap, collectSet, createFacade, createFacadeClass, getContainerFromModule, isFake };
|