@plyaz/types 1.6.0 → 1.7.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.
@@ -12,11 +12,1573 @@
12
12
  * // getUser("abc") // ❌ Type error
13
13
  * ```
14
14
  */
15
- export type Brand<T, B> = T & {
16
- readonly _brand: B;
17
- };
15
+ import type { Arrayable, SetOptional, Tagged, UnknownRecord } from 'type-fest';
16
+ export type Brand<T, B extends PropertyKey> = Tagged<T, B>;
18
17
  /**
19
18
  * Branded `string` type representing a unique identifier.
20
19
  * @description This is used to avoid mixing generic strings with semantically significant IDs in function arguments and data structures.
21
20
  */
22
21
  export type ID = Brand<string, 'ID'>;
22
+ /**
23
+ * Base interface for entities with timestamps.
24
+ * Provides common timestamp fields for tracking creation and modification times.
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * interface User extends Timestamped {
29
+ * id: string;
30
+ * name: string;
31
+ * }
32
+ * ```
33
+ */
34
+ export interface Timestamped<CreatedAt = Date, UpdatedAt = Date> {
35
+ /** When the entity was created */
36
+ createdAt: CreatedAt;
37
+ /** When the entity was last updated */
38
+ updatedAt: UpdatedAt;
39
+ }
40
+ /**
41
+ * Base interface for entities with an identifier.
42
+ * Provides a common id field for uniquely identifying entities.
43
+ *
44
+ * @typeParam T - Type of the identifier (string or number)
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * interface Product extends Identifiable {
49
+ * name: string;
50
+ * price: number;
51
+ * }
52
+ *
53
+ * interface LegacyProduct extends Identifiable<number> {
54
+ * name: string;
55
+ * }
56
+ * ```
57
+ */
58
+ export interface Identifiable<T = string> {
59
+ /** Unique identifier for the entity */
60
+ id: T;
61
+ }
62
+ /**
63
+ * Base interface for entities with both identifier and timestamps.
64
+ * Combines Identifiable and Timestamped for complete entity tracking.
65
+ *
66
+ * @example
67
+ * ```typescript
68
+ * interface Order extends Entity {
69
+ * total: number;
70
+ * status: OrderStatus;
71
+ * }
72
+ * ```
73
+ */
74
+ export interface Entity extends Identifiable, Timestamped {
75
+ }
76
+ /**
77
+ * Base interface for loading states.
78
+ * Provides common fields for tracking async operation states.
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * interface DataState<T> extends Loadable {
83
+ * data?: T;
84
+ * }
85
+ * ```
86
+ */
87
+ export interface Loadable {
88
+ /** Whether the operation is currently loading */
89
+ isLoading: boolean;
90
+ /** Error that occurred during the operation, if any */
91
+ error: Error | null;
92
+ }
93
+ /**
94
+ * Base interface for async data states.
95
+ * Combines loading state with data result.
96
+ *
97
+ * @template T - The type of data being loaded
98
+ *
99
+ * @example
100
+ * ```typescript
101
+ * const userState: AsyncState<User> = {
102
+ * data: user,
103
+ * isLoading: false,
104
+ * error: null
105
+ * };
106
+ * ```
107
+ */
108
+ export interface AsyncState<T> extends Loadable {
109
+ /** The loaded data, if available */
110
+ data: T | undefined;
111
+ }
112
+ /**
113
+ * Base interface for collections with items.
114
+ * Provides items array wrapper for collections.
115
+ *
116
+ * @typeParam T - Type of items in the collection
117
+ * @example
118
+ * ```typescript
119
+ * interface SearchResults<T> extends WithItems<T> {
120
+ * query: string;
121
+ * }
122
+ * ```
123
+ */
124
+ export interface WithItems<T> {
125
+ /** Array of items in the collection */
126
+ items: T[];
127
+ }
128
+ /**
129
+ * Base interface for pagination metadata.
130
+ * Provides core pagination information without items.
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * interface ApiPaginationInfo extends PaginationMetadata {
135
+ * // Additional API-specific fields
136
+ * }
137
+ * ```
138
+ */
139
+ export interface PaginationMetadata {
140
+ /** Total number of items across all pages */
141
+ total: number;
142
+ /** Current page number (1-based) */
143
+ page: number;
144
+ /** Number of items per page */
145
+ pageSize: number;
146
+ /** Total number of pages */
147
+ totalPages: number;
148
+ }
149
+ /**
150
+ * Base interface for paginated collection results.
151
+ * Combines pagination metadata with items array.
152
+ * Note: This is different from API's Paginated interface which only contains items.
153
+ *
154
+ * @example
155
+ * ```typescript
156
+ * interface UserList extends PaginatedCollection<User> {
157
+ * filters?: UserFilters;
158
+ * }
159
+ * ```
160
+ */
161
+ export interface PaginatedCollection<T> extends PaginationMetadata, WithItems<T> {
162
+ }
163
+ /**
164
+ * Extended pagination metadata with navigation helpers.
165
+ * Adds navigation flags to the base pagination metadata.
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * interface ApiPaginationInfo extends NavigablePaginationMetadata {
170
+ * // Maps hasNext to hasNextPage for API conventions
171
+ * }
172
+ * ```
173
+ */
174
+ export interface NavigablePaginationMetadata extends PaginationMetadata {
175
+ /** Whether there's a next page */
176
+ hasNext: boolean;
177
+ /** Whether there's a previous page */
178
+ hasPrevious: boolean;
179
+ }
180
+ /**
181
+ * Extended paginated collection with navigation helpers.
182
+ * Combines navigation metadata with items array.
183
+ *
184
+ * @example
185
+ * ```typescript
186
+ * interface SearchResults extends NavigablePaginatedCollection<Result> {
187
+ * query: string;
188
+ * }
189
+ * ```
190
+ */
191
+ export interface NavigablePaginatedCollection<T> extends PaginatedCollection<T>, NavigablePaginationMetadata {
192
+ }
193
+ /**
194
+ * Base interface for soft-deletable entities.
195
+ * Adds deletion timestamp for soft delete functionality.
196
+ *
197
+ * @example
198
+ * ```typescript
199
+ * interface Document extends Entity, SoftDeletable {
200
+ * content: string;
201
+ * }
202
+ * ```
203
+ */
204
+ export interface SoftDeletable {
205
+ /** When the entity was soft deleted */
206
+ deletedAt: Date | null;
207
+ }
208
+ /**
209
+ * Base interface for named entities.
210
+ * Provides a common name field.
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * interface Category extends Named {
215
+ * parentId?: string;
216
+ * }
217
+ * ```
218
+ */
219
+ export interface Named {
220
+ /** Name of the entity */
221
+ name: string;
222
+ }
223
+ /**
224
+ * Base interface for describable entities.
225
+ * Provides name and description fields.
226
+ *
227
+ * @example
228
+ * ```typescript
229
+ * interface Project extends Describable {
230
+ * status: ProjectStatus;
231
+ * }
232
+ * ```
233
+ */
234
+ export interface Describable extends Named {
235
+ /** Description of the entity */
236
+ description: string;
237
+ }
238
+ /**
239
+ * Base interface for entities with metadata.
240
+ * Provides metadata field for extensibility.
241
+ *
242
+ * @typeParam T - Type of the metadata object, defaults to UnknownRecord
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * interface Event extends WithMetadata {
247
+ * type: EventType;
248
+ * payload: unknown;
249
+ * }
250
+ *
251
+ * interface CustomEvent extends WithMetadata<{ userId: string; sessionId: string }> {
252
+ * type: EventType;
253
+ * }
254
+ * ```
255
+ */
256
+ export interface WithMetadata<T = UnknownRecord> {
257
+ /** Metadata for additional information */
258
+ metadata: T;
259
+ }
260
+ /**
261
+ * Base interface for configuration objects.
262
+ * Provides common configuration fields.
263
+ *
264
+ * @example
265
+ * ```typescript
266
+ * interface CacheConfig extends Configurable {
267
+ * ttl: number;
268
+ * strategy: 'memory' | 'redis';
269
+ * }
270
+ * ```
271
+ */
272
+ export interface Configurable {
273
+ /** Whether this configuration is enabled */
274
+ isEnabled: boolean;
275
+ }
276
+ /**
277
+ * Base interface for entities that can be enabled/disabled.
278
+ * Provides a flag for controlling feature availability.
279
+ *
280
+ * @example
281
+ * ```typescript
282
+ * interface Feature extends Enabled {
283
+ * name: string;
284
+ * config: FeatureConfig;
285
+ * }
286
+ * ```
287
+ */
288
+ export interface Enabled {
289
+ /** Whether this entity is enabled */
290
+ isEnabled: boolean;
291
+ }
292
+ /**
293
+ * Base interface for pageable collections.
294
+ * Provides pagination parameters for list operations.
295
+ *
296
+ * @example
297
+ * ```typescript
298
+ * interface UserListRequest extends Pageable {
299
+ * filters?: UserFilters;
300
+ * }
301
+ * ```
302
+ */
303
+ export interface Pageable {
304
+ /** Page number to retrieve (starting from 1) */
305
+ page: number;
306
+ /** Maximum number of items per page */
307
+ limit: number;
308
+ }
309
+ /**
310
+ * Base interface for entities with expiration.
311
+ * Provides expiration tracking for temporary entities.
312
+ *
313
+ * @example
314
+ * ```typescript
315
+ * interface Token extends WithExpiration {
316
+ * value: string;
317
+ * scope: string[];
318
+ * }
319
+ * ```
320
+ */
321
+ export interface WithExpiration<T = Date | string> {
322
+ /** When the entity expires */
323
+ expiresAt: T;
324
+ }
325
+ /**
326
+ * Base interface for resettable entities.
327
+ * Provides reset functionality.
328
+ *
329
+ * @example
330
+ * ```typescript
331
+ * interface Counter extends Resettable {
332
+ * value: number;
333
+ * increment: () => void;
334
+ * }
335
+ * ```
336
+ */
337
+ export interface Resettable {
338
+ /** Reset to initial state */
339
+ reset: () => void;
340
+ }
341
+ /**
342
+ * Base interface for clearable entities.
343
+ * Provides clear functionality.
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * interface Cache extends Clearable {
348
+ * size: number;
349
+ * get: (key: string) => unknown;
350
+ * }
351
+ * ```
352
+ */
353
+ export interface Clearable {
354
+ /** Clear all data */
355
+ clear: () => void;
356
+ }
357
+ /**
358
+ * Base interface for entities with lifecycle methods.
359
+ * Provides start, stop, and optional pause/resume functionality.
360
+ *
361
+ * @example
362
+ * ```typescript
363
+ * interface Service extends WithLifecycle {
364
+ * isRunning: boolean;
365
+ * }
366
+ * ```
367
+ */
368
+ export interface WithLifecycle {
369
+ /** Start the entity */
370
+ start: () => void | Promise<void>;
371
+ /** Stop the entity */
372
+ stop: () => void | Promise<void>;
373
+ /** Pause the entity (optional) */
374
+ pause?: () => void | Promise<void>;
375
+ /** Resume the entity (optional) */
376
+ resume?: () => void | Promise<void>;
377
+ }
378
+ /**
379
+ * Base interface for entities with payload.
380
+ * Provides payload field for events, messages, and requests.
381
+ *
382
+ * @typeParam T - Type of the payload data
383
+ *
384
+ * @example
385
+ * ```typescript
386
+ * interface Message<T> extends WithPayload<T> {
387
+ * id: string;
388
+ * timestamp: Date;
389
+ * }
390
+ * ```
391
+ */
392
+ export interface WithPayload<T = unknown> {
393
+ /** Payload data */
394
+ payload: T;
395
+ }
396
+ /**
397
+ * Base interface for entities with a value.
398
+ * Provides value field for settings, flags, and state containers.
399
+ *
400
+ * @typeParam T - Type of the value
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * interface Setting<T> extends WithValue<T> {
405
+ * key: string;
406
+ * updatedAt: Date;
407
+ * }
408
+ * ```
409
+ */
410
+ export interface WithValue<T = unknown> {
411
+ /** The value */
412
+ value: T;
413
+ }
414
+ /**
415
+ * Base interface for entities with impact level.
416
+ * Provides impact field for violations, issues, and assessments.
417
+ *
418
+ * @example
419
+ * ```typescript
420
+ * interface SecurityIssue extends WithImpact {
421
+ * vulnerability: string;
422
+ * affectedFiles: string[];
423
+ * }
424
+ * ```
425
+ */
426
+ export interface WithImpact<T = 'minor' | 'moderate' | 'serious' | 'critical'> {
427
+ /** Impact level or severity */
428
+ impact: T;
429
+ }
430
+ /**
431
+ * Base interface for entities with an element reference.
432
+ * Provides element field for UI interactions and DOM manipulation.
433
+ *
434
+ * @typeParam T - Type of the element, defaults to HTMLElement
435
+ *
436
+ * @example
437
+ * ```typescript
438
+ * interface DragOperation extends WithElement {
439
+ * startPosition: { x: number; y: number };
440
+ * }
441
+ * ```
442
+ */
443
+ export interface WithElement<T = HTMLElement> {
444
+ /** The element reference */
445
+ element: T;
446
+ }
447
+ /**
448
+ * Base interface for interval/timer controls.
449
+ * Provides common methods for managing timed operations.
450
+ *
451
+ * @example
452
+ * ```typescript
453
+ * interface AnimationLoop extends IntervalControl {
454
+ * frameRate: number;
455
+ * }
456
+ * ```
457
+ */
458
+ export interface IntervalControl {
459
+ /** Start the interval */
460
+ start: () => void;
461
+ /** Stop the interval */
462
+ stop: () => void;
463
+ /** Check if currently running */
464
+ isRunning: () => boolean;
465
+ /** Pause the interval (optional) */
466
+ pause?: () => void;
467
+ /** Resume from pause (optional) */
468
+ resume?: () => void;
469
+ /** Check if currently paused (optional) */
470
+ isPaused?: () => boolean;
471
+ }
472
+ /**
473
+ * Base interface for error handlers.
474
+ * Standardizes error callback signatures.
475
+ *
476
+ * @example
477
+ * ```typescript
478
+ * interface ComponentProps extends WithErrorHandler {
479
+ * onSuccess?: () => void;
480
+ * }
481
+ * ```
482
+ */
483
+ export interface WithErrorHandler {
484
+ /** Callback when an error occurs */
485
+ onError: (error: Error) => void;
486
+ }
487
+ /**
488
+ * Base interface for success/error callbacks.
489
+ * Provides standard async operation callbacks.
490
+ *
491
+ * @template T - The type of the success data
492
+ *
493
+ * @example
494
+ * ```typescript
495
+ * interface UploadOptions extends WithCallbacks<File> {
496
+ * maxSize: number;
497
+ * }
498
+ * ```
499
+ */
500
+ export interface WithCallbacks<T = void> extends WithErrorHandler {
501
+ /** Callback when operation succeeds */
502
+ onSuccess: (data: T) => void;
503
+ }
504
+ /**
505
+ * Base interface for timeout configuration.
506
+ * Provides timeout setting.
507
+ *
508
+ * @example
509
+ * ```typescript
510
+ * interface RequestOptions extends WithTimeout {
511
+ * retries?: number;
512
+ * }
513
+ * ```
514
+ */
515
+ export interface WithTimeout {
516
+ /** Operation timeout in milliseconds */
517
+ timeout: number;
518
+ }
519
+ /**
520
+ * Base interface for retry configuration.
521
+ * Provides retry-related settings.
522
+ *
523
+ * @example
524
+ * ```typescript
525
+ * interface ApiClientOptions extends WithRetry {
526
+ * baseURL: string;
527
+ * }
528
+ * ```
529
+ */
530
+ export interface WithRetry extends WithTimeout {
531
+ /** Number of retry attempts */
532
+ retries: number;
533
+ /** Delay between retries in milliseconds */
534
+ retryDelay: number;
535
+ }
536
+ /**
537
+ * Base interface for authored entities.
538
+ * Tracks who created and last updated an entity.
539
+ *
540
+ * @example
541
+ * ```typescript
542
+ * interface Document extends Authored {
543
+ * content: string;
544
+ * }
545
+ * ```
546
+ */
547
+ export interface Authored {
548
+ /** User who created this entity */
549
+ createdBy: string;
550
+ /** User who last updated this entity */
551
+ updatedBy: string;
552
+ }
553
+ /**
554
+ * Base interface for entities with tags.
555
+ * Provides tagging functionality for categorization.
556
+ *
557
+ * @example
558
+ * ```typescript
559
+ * interface Article extends WithTags {
560
+ * title: string;
561
+ * content: string;
562
+ * }
563
+ * ```
564
+ */
565
+ export interface WithTags {
566
+ /** Tags for categorization */
567
+ tags: string[];
568
+ }
569
+ /**
570
+ * Base interface for environment-specific entities.
571
+ * Specifies which environment(s) an entity applies to.
572
+ *
573
+ * @example
574
+ * ```typescript
575
+ * interface Config extends WithEnvironment {
576
+ * apiUrl: string;
577
+ * }
578
+ * ```
579
+ */
580
+ export interface WithEnvironment {
581
+ /** Environment(s) this entity applies to */
582
+ environment: 'development' | 'staging' | 'production' | 'all' | string;
583
+ }
584
+ /**
585
+ * Base interface for platform-specific entities.
586
+ * Specifies which platform(s) an entity supports.
587
+ *
588
+ * @example
589
+ * ```typescript
590
+ * interface AppConfig extends WithPlatform {
591
+ * appId: string;
592
+ * }
593
+ * ```
594
+ */
595
+ export interface WithPlatform {
596
+ /** Platform(s) this entity supports */
597
+ platform: 'web' | 'ios' | 'android' | 'desktop' | string | string[];
598
+ }
599
+ /**
600
+ * Base interface for entities with API key.
601
+ * Provides API key field for authentication.
602
+ *
603
+ * @example
604
+ * ```typescript
605
+ * interface ServiceConfig extends WithApiKey {
606
+ * endpoint: string;
607
+ * }
608
+ * ```
609
+ */
610
+ export interface WithApiKey {
611
+ /** API key for authentication */
612
+ apiKey: string;
613
+ }
614
+ /**
615
+ * Base interface for entities with URL.
616
+ * Provides URL field for network resources.
617
+ *
618
+ * @example
619
+ * ```typescript
620
+ * interface WebhookConfig extends WithUrl {
621
+ * method: 'POST';
622
+ * }
623
+ * ```
624
+ */
625
+ export interface WithUrl {
626
+ /** URL of the resource */
627
+ url: string;
628
+ }
629
+ /**
630
+ * Base interface for entities with endpoint.
631
+ * Provides endpoint field for API routes.
632
+ *
633
+ * @example
634
+ * ```typescript
635
+ * interface ApiRoute extends WithEndpoint {
636
+ * method: HttpMethod;
637
+ * }
638
+ * ```
639
+ */
640
+ export interface WithEndpoint {
641
+ /** API endpoint path */
642
+ endpoint: string;
643
+ }
644
+ /**
645
+ * Base interface for entities with base URL.
646
+ * Provides base URL for API clients.
647
+ *
648
+ * @example
649
+ * ```typescript
650
+ * interface ApiClient extends WithBaseUrl {
651
+ * timeout: number;
652
+ * }
653
+ * ```
654
+ */
655
+ export interface WithBaseUrl {
656
+ /** Base URL for API requests */
657
+ baseUrl: string;
658
+ }
659
+ /**
660
+ * Base interface for key-value pair operations.
661
+ * Provides generic key-value storage and retrieval.
662
+ *
663
+ * @template K - The type of keys
664
+ * @template V - The type of values
665
+ * @example
666
+ * ```typescript
667
+ * interface Cache extends KeyValueStore<string, unknown> {}
668
+ * ```
669
+ */
670
+ export interface KeyValueStore<K = string, V = unknown> {
671
+ /** Get a value by key */
672
+ get: (key: K) => V | undefined | Promise<V | undefined>;
673
+ /** Set a key-value pair */
674
+ set: (key: K, value: V) => void | Promise<void>;
675
+ /** Delete a key-value pair */
676
+ delete: (key: K) => void | Promise<void>;
677
+ /** Check if a key exists */
678
+ has: (key: K) => boolean | Promise<boolean>;
679
+ /** Clear all key-value pairs */
680
+ clear: () => void | Promise<void>;
681
+ }
682
+ /**
683
+ * Base interface for a single key-value pair.
684
+ *
685
+ * @template K - The type of the key
686
+ * @template V - The type of the value
687
+ * @example
688
+ * ```typescript
689
+ * interface ConfigEntry extends KeyValuePair<string, string> {}
690
+ * ```
691
+ */
692
+ export interface KeyValuePair<K = string, V = unknown> {
693
+ /** The key */
694
+ key: K;
695
+ /** The value */
696
+ value: V;
697
+ }
698
+ /**
699
+ * Base interface for entities with key-value pairs.
700
+ *
701
+ * @template K - The type of keys
702
+ * @template V - The type of values
703
+ * @example
704
+ * ```typescript
705
+ * interface Settings extends WithKeyValues<string, boolean> {}
706
+ * ```
707
+ */
708
+ export interface WithKeyValues<K = string, V = unknown> {
709
+ /** Collection of key-value pairs */
710
+ values: KeyValuePair<K, V>[];
711
+ }
712
+ /**
713
+ * Base interface for subscription management.
714
+ * Represents a single subscription with an unsubscribe capability.
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * const subscription: Subscription = {
719
+ * unsubscribe: () => console.log('Unsubscribed')
720
+ * };
721
+ * ```
722
+ */
723
+ export interface BaseSubscription {
724
+ /** Function to cancel the subscription */
725
+ unsubscribe: () => void | Promise<void>;
726
+ }
727
+ /**
728
+ * Extended subscription with additional metadata.
729
+ *
730
+ * @template T - The type of data being subscribed to
731
+ * @example
732
+ * ```typescript
733
+ * const subscription: SubscriptionWithHandler<UserEvent> = {
734
+ * id: 'sub-123',
735
+ * topic: 'user.created',
736
+ * handler: (event) => console.log(event),
737
+ * unsubscribe: () => eventBus.off('user.created', handler)
738
+ * };
739
+ * ```
740
+ */
741
+ export interface SubscriptionWithHandler<T = unknown> extends BaseSubscription, Identifiable {
742
+ /** Topic the handler is subscribed to */
743
+ topic: string;
744
+ /** Handler function to invoke when data is published */
745
+ handler: (data: T) => void | Promise<void>;
746
+ }
747
+ /**
748
+ * Base interface for entities that support subscribing to events/data.
749
+ * Provides subscribe capability that returns a Subscription.
750
+ *
751
+ * @template T - The type of data being subscribed to
752
+ * @example
753
+ * ```typescript
754
+ * interface Observable<T> extends WithSubscribe<T> {}
755
+ * ```
756
+ */
757
+ export interface WithSubscribe<T = unknown> {
758
+ /** Subscribe to receive data, returns a Subscription for cleanup */
759
+ subscribe: (callback: (data: T) => void | Promise<void>) => BaseSubscription | Promise<BaseSubscription>;
760
+ }
761
+ /**
762
+ * Base interface for entities that support publishing events/data.
763
+ *
764
+ * @template T - The type of data being published
765
+ * @example
766
+ * ```typescript
767
+ * interface EventEmitter<T> extends WithPublish<T> {}
768
+ * ```
769
+ */
770
+ export interface WithPublish<T = unknown> {
771
+ /** Publish data to subscribers */
772
+ publish: (data: T) => void | Promise<void>;
773
+ }
774
+ /**
775
+ * Base interface for subscribable entities with pub/sub pattern.
776
+ * Combines publish and subscribe capabilities.
777
+ *
778
+ * @template T - The type of data being published/subscribed
779
+ * @example
780
+ * ```typescript
781
+ * interface EventBus extends WithSubscribable<Event> {
782
+ * // EventBus specific methods
783
+ * }
784
+ * ```
785
+ */
786
+ export interface WithSubscribable<T = unknown> extends WithPublish<T>, WithSubscribe<T> {
787
+ }
788
+ /**
789
+ * Base interface for topic-based subscription.
790
+ * Allows subscribing to specific topics/channels.
791
+ *
792
+ * @template T - The type of data being subscribed to
793
+ * @example
794
+ * ```typescript
795
+ * interface EventBus extends WithTopicSubscribe<Event> {}
796
+ * ```
797
+ */
798
+ export interface WithTopicSubscribe<T = unknown> {
799
+ /** Subscribe to a specific topic, returns a Subscription for cleanup */
800
+ subscribe: (topic: string, callback: (data: T) => void | Promise<void>) => BaseSubscription | Promise<BaseSubscription>;
801
+ /** Unsubscribe from a specific subscription */
802
+ unsubscribe: (subscriptionId: string) => void | Promise<void>;
803
+ }
804
+ /**
805
+ * Base interface for topic-based pub/sub pattern.
806
+ * Combines topic-based publish and subscribe capabilities.
807
+ *
808
+ * @template T - The type of data being published/subscribed
809
+ * @example
810
+ * ```typescript
811
+ * interface MessageBus extends WithTopicPubSub<Message> {}
812
+ * ```
813
+ */
814
+ export interface WithTopicPubSub<T = unknown> extends WithPublish<T>, WithTopicSubscribe<T> {
815
+ }
816
+ /**
817
+ * Operation types that can be performed.
818
+ * Can be combined for specific use cases.
819
+ */
820
+ export type BaseOperationType = 'create' | 'read' | 'update' | 'delete' | 'evaluate' | 'validate' | 'execute' | 'list' | 'search' | 'filter' | 'sort' | 'paginate' | 'aggregate' | 'transform' | 'subscribe' | 'publish' | 'refresh' | string;
821
+ /**
822
+ * Base interface for operations with configurable types.
823
+ * Allows specifying which operations are supported.
824
+ *
825
+ * @template T - The allowed operation types
826
+ * @example
827
+ * ```typescript
828
+ * // Read-only operations
829
+ * interface ReadOnlyOperation extends Operation<'read' | 'list' | 'search'> {
830
+ * query: string;
831
+ * }
832
+ *
833
+ * // CRUD operations
834
+ * interface CrudOperation extends Operation<'create' | 'read' | 'update' | 'delete'> {
835
+ * table: string;
836
+ * }
837
+ * ```
838
+ */
839
+ export interface WithOperation<T extends BaseOperationType = BaseOperationType> {
840
+ /** Type of operation being performed */
841
+ operation: T;
842
+ }
843
+ /**
844
+ * Base interface for entities with logging control.
845
+ * Provides logging configuration.
846
+ *
847
+ * @example
848
+ * ```typescript
849
+ * interface ServiceOptions extends WithLogging {
850
+ * timeout: number;
851
+ * }
852
+ * ```
853
+ */
854
+ export interface WithLogging {
855
+ /** Whether logging is enabled */
856
+ isLoggingEnabled: boolean;
857
+ }
858
+ /**
859
+ * Base interface for refreshable entities.
860
+ * Provides refresh capability and tracking.
861
+ *
862
+ * @example
863
+ * ```typescript
864
+ * interface TokenManager extends Refreshable {
865
+ * token: string;
866
+ * }
867
+ * ```
868
+ */
869
+ export interface Refreshable {
870
+ /** When the entity was last updated/refreshed */
871
+ lastUpdated: Date | string | null;
872
+ /** Function to refresh the entity */
873
+ refresh: () => void | Promise<void>;
874
+ }
875
+ /**
876
+ * Base interface for initializable entities.
877
+ * Tracks initialization state and readiness.
878
+ *
879
+ * @example
880
+ * ```typescript
881
+ * interface Service extends Initializable {
882
+ * start(): void;
883
+ * }
884
+ * ```
885
+ */
886
+ export interface Initializable {
887
+ /** Whether the entity has been initialized */
888
+ isInitialized: boolean;
889
+ /** Callback when entity is ready */
890
+ onReady: () => void;
891
+ }
892
+ /**
893
+ * Base interface for entities with a single timestamp.
894
+ * Provides basic timestamp tracking.
895
+ *
896
+ * @example
897
+ * ```typescript
898
+ * interface Event extends WithTimestamp {
899
+ * type: string;
900
+ * payload: unknown;
901
+ * }
902
+ * ```
903
+ */
904
+ export interface WithTimestamp<T = Date | string> {
905
+ /** When the event/operation occurred */
906
+ timestamp: T;
907
+ }
908
+ /**
909
+ * Base interface for tracked operations.
910
+ * Provides timestamp and error tracking.
911
+ *
912
+ * @typeParam T - Type of the result
913
+ *
914
+ * @example
915
+ * ```typescript
916
+ * interface ApiCall extends Tracked<Response> {
917
+ * endpoint: string;
918
+ * }
919
+ * ```
920
+ */
921
+ export interface Tracked<T = unknown> extends WithTimestamp {
922
+ /** Result of the operation */
923
+ result: T | null;
924
+ /** Error if the operation failed */
925
+ error: Error | null;
926
+ }
927
+ /**
928
+ * Base interface for entities with duration tracking.
929
+ * Provides timing measurement.
930
+ *
931
+ * @example
932
+ * ```typescript
933
+ * interface PerformanceMetric extends WithDuration {
934
+ * name: string;
935
+ * }
936
+ * ```
937
+ */
938
+ export interface WithDuration {
939
+ /** Duration in milliseconds */
940
+ duration: number;
941
+ }
942
+ /**
943
+ * Base interface for entities with last accessed tracking.
944
+ * Provides access timestamp.
945
+ *
946
+ * @example
947
+ * ```typescript
948
+ * interface CacheEntry extends WithLastAccessed {
949
+ * data: unknown;
950
+ * }
951
+ * ```
952
+ */
953
+ export interface WithLastAccessed {
954
+ /** When the entity was last accessed */
955
+ lastAccessedAt: Date | string | null;
956
+ }
957
+ /**
958
+ * Base interface for versioned entities.
959
+ * Provides version tracking.
960
+ *
961
+ * @example
962
+ * ```typescript
963
+ * interface Config extends Versioned {
964
+ * settings: unknown;
965
+ * }
966
+ * ```
967
+ */
968
+ export interface Versioned {
969
+ /** Version identifier */
970
+ version: string | number;
971
+ }
972
+ /**
973
+ * Base interface for entities with source tracking.
974
+ * Identifies where the entity originated.
975
+ *
976
+ * @example
977
+ * ```typescript
978
+ * interface ImportedData extends WithSource {
979
+ * data: unknown;
980
+ * }
981
+ * ```
982
+ */
983
+ export interface WithSource {
984
+ /** Source identifier */
985
+ source: string;
986
+ }
987
+ /**
988
+ * Base interface for entities with status.
989
+ * Provides status field for state tracking.
990
+ *
991
+ * @template T - The type of status values (typically an enum or union type)
992
+ * @example
993
+ * ```typescript
994
+ * interface Task extends WithStatus<'pending' | 'running' | 'completed'> {
995
+ * name: string;
996
+ * }
997
+ * ```
998
+ */
999
+ export interface WithStatus<T = string> {
1000
+ /** Current status */
1001
+ status: T;
1002
+ }
1003
+ /**
1004
+ * Base interface for entities with priority.
1005
+ * Provides priority field for ordering/importance.
1006
+ *
1007
+ * @template T - The type of priority values (typically an enum or union type)
1008
+ * @example
1009
+ * ```typescript
1010
+ * interface Alert extends WithPriority<'low' | 'medium' | 'high' | 'critical'> {
1011
+ * message: string;
1012
+ * }
1013
+ * ```
1014
+ */
1015
+ export interface WithPriority<T = string | number> {
1016
+ /** Priority level */
1017
+ priority: T;
1018
+ }
1019
+ /**
1020
+ * Base interface for entities with labels.
1021
+ * Provides key-value labeling.
1022
+ *
1023
+ * @example
1024
+ * ```typescript
1025
+ * interface Resource extends WithLabels {
1026
+ * name: string;
1027
+ * }
1028
+ * ```
1029
+ */
1030
+ export interface WithLabels {
1031
+ /** Key-value labels */
1032
+ labels: Record<string, string>;
1033
+ }
1034
+ /**
1035
+ * Base interface for entities with annotations.
1036
+ * Provides flexible metadata attachment.
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * interface Document extends WithAnnotations {
1041
+ * content: string;
1042
+ * }
1043
+ * ```
1044
+ */
1045
+ export interface WithAnnotations {
1046
+ /** Additional annotations */
1047
+ annotations: UnknownRecord;
1048
+ }
1049
+ /**
1050
+ * Base interface for entities with email.
1051
+ * Provides email field.
1052
+ *
1053
+ * @example
1054
+ * ```typescript
1055
+ * interface UserProfile extends WithEmail {
1056
+ * name: string;
1057
+ * }
1058
+ * ```
1059
+ */
1060
+ export interface WithEmail {
1061
+ /** Email address */
1062
+ email: string;
1063
+ }
1064
+ /**
1065
+ * Base interface for entities with UUID.
1066
+ * Provides UUID field.
1067
+ *
1068
+ * @example
1069
+ * ```typescript
1070
+ * interface Session extends WithUuid {
1071
+ * data: unknown;
1072
+ * }
1073
+ * ```
1074
+ */
1075
+ export interface WithUuid {
1076
+ /** Universally unique identifier */
1077
+ uuid: string;
1078
+ }
1079
+ /**
1080
+ * Base interface for entities with user context.
1081
+ * Provides user identification.
1082
+ *
1083
+ * @example
1084
+ * ```typescript
1085
+ * interface Request extends WithUserId {
1086
+ * action: string;
1087
+ * }
1088
+ * ```
1089
+ */
1090
+ export interface WithUserId {
1091
+ /** User identifier */
1092
+ userId: string;
1093
+ }
1094
+ /**
1095
+ * Base interface for entities with session context.
1096
+ * Provides session identification.
1097
+ *
1098
+ * @example
1099
+ * ```typescript
1100
+ * interface Activity extends WithSessionId {
1101
+ * action: string;
1102
+ * }
1103
+ * ```
1104
+ */
1105
+ export interface WithSessionId {
1106
+ /** Session identifier */
1107
+ sessionId: string;
1108
+ }
1109
+ /**
1110
+ * Base interface for entities with retry configuration.
1111
+ * Provides retry tracking fields.
1112
+ *
1113
+ * @example
1114
+ * ```typescript
1115
+ * interface RetryableOperation extends WithRetryTracking {
1116
+ * operation: string;
1117
+ * }
1118
+ * ```
1119
+ */
1120
+ export interface WithRetryTracking {
1121
+ /** Current retry attempt count */
1122
+ retryCount: number;
1123
+ /** Maximum allowed retries */
1124
+ maxRetries: number;
1125
+ }
1126
+ /**
1127
+ * Base interface for entities with roles.
1128
+ * Provides role-based access control.
1129
+ *
1130
+ * @example
1131
+ * ```typescript
1132
+ * interface Account extends WithRoles {
1133
+ * username: string;
1134
+ * }
1135
+ * ```
1136
+ */
1137
+ export interface WithRoles {
1138
+ /** User roles */
1139
+ roles: string[];
1140
+ }
1141
+ /**
1142
+ * Base interface for entities with permissions.
1143
+ * Provides permission management.
1144
+ *
1145
+ * @example
1146
+ * ```typescript
1147
+ * interface Principal extends WithPermissions {
1148
+ * id: string;
1149
+ * }
1150
+ * ```
1151
+ */
1152
+ export interface WithPermissions {
1153
+ /** User permissions */
1154
+ permissions: string[];
1155
+ }
1156
+ /**
1157
+ * Base interface for entities with locale.
1158
+ * Provides localization support.
1159
+ *
1160
+ * @example
1161
+ * ```typescript
1162
+ * interface UserSettings extends WithLocale {
1163
+ * theme: string;
1164
+ * }
1165
+ * ```
1166
+ */
1167
+ export interface WithLocale {
1168
+ /** Locale identifier (e.g., 'en-US') */
1169
+ locale: string;
1170
+ }
1171
+ /**
1172
+ * Base interface for entities with IP address.
1173
+ * Provides IP tracking.
1174
+ *
1175
+ * @example
1176
+ * ```typescript
1177
+ * interface AuditLog extends WithIpAddress {
1178
+ * action: string;
1179
+ * }
1180
+ * ```
1181
+ */
1182
+ export interface WithIpAddress {
1183
+ /** IP address */
1184
+ ip: string;
1185
+ }
1186
+ /**
1187
+ * Base interface for entities with user agent.
1188
+ * Provides client identification.
1189
+ *
1190
+ * @example
1191
+ * ```typescript
1192
+ * interface Session extends WithUserAgent {
1193
+ * id: string;
1194
+ * }
1195
+ * ```
1196
+ */
1197
+ export interface WithUserAgent {
1198
+ /** User agent string */
1199
+ userAgent: string;
1200
+ }
1201
+ /**
1202
+ * Base interface for entities with timezone.
1203
+ * Provides timezone information.
1204
+ *
1205
+ * @example
1206
+ * ```typescript
1207
+ * interface UserPreferences extends WithTimezone {
1208
+ * dateFormat: string;
1209
+ * }
1210
+ * ```
1211
+ */
1212
+ export interface WithTimezone {
1213
+ /** Timezone identifier (e.g., 'UTC', 'America/New_York') */
1214
+ timezone: string;
1215
+ }
1216
+ /**
1217
+ * Base interface for entities with country.
1218
+ * Provides geographical context.
1219
+ *
1220
+ * @example
1221
+ * ```typescript
1222
+ * interface GeoData extends WithCountry {
1223
+ * city: string;
1224
+ * }
1225
+ * ```
1226
+ */
1227
+ export interface WithCountry {
1228
+ /** Country code or name */
1229
+ country: string;
1230
+ }
1231
+ /**
1232
+ * Base interface for entities with status code.
1233
+ * Provides HTTP/error status.
1234
+ *
1235
+ * @example
1236
+ * ```typescript
1237
+ * interface Response extends WithStatusCode {
1238
+ * message: string;
1239
+ * }
1240
+ * ```
1241
+ */
1242
+ export interface WithStatusCode {
1243
+ /** Status code (HTTP or custom) */
1244
+ statusCode: number;
1245
+ }
1246
+ /**
1247
+ * Base interface for entities with HTTP status.
1248
+ * Provides HTTP status code and text.
1249
+ *
1250
+ * @example
1251
+ * ```typescript
1252
+ * interface HttpResponse extends WithHttpStatus {
1253
+ * body: unknown;
1254
+ * }
1255
+ * ```
1256
+ */
1257
+ export interface WithHttpStatus {
1258
+ /** HTTP status code */
1259
+ status: number;
1260
+ /** HTTP status text */
1261
+ statusText: string;
1262
+ }
1263
+ /**
1264
+ * Base interface for entities with request ID.
1265
+ * Provides request tracking.
1266
+ *
1267
+ * @example
1268
+ * ```typescript
1269
+ * interface ApiResponse extends WithRequestId {
1270
+ * data: unknown;
1271
+ * }
1272
+ * ```
1273
+ */
1274
+ export interface WithRequestId {
1275
+ /** Unique request identifier */
1276
+ requestId: string;
1277
+ }
1278
+ /**
1279
+ * Base interface for entities with correlation ID.
1280
+ * Provides distributed tracing.
1281
+ *
1282
+ * @example
1283
+ * ```typescript
1284
+ * interface Event extends WithCorrelationId {
1285
+ * type: string;
1286
+ * }
1287
+ * ```
1288
+ */
1289
+ export interface WithCorrelationId {
1290
+ /** Correlation ID for tracing */
1291
+ correlationId: string;
1292
+ }
1293
+ /**
1294
+ * Base interface for entities with path.
1295
+ * Provides path/route information.
1296
+ *
1297
+ * @example
1298
+ * ```typescript
1299
+ * interface RouteError extends WithPath {
1300
+ * error: Error;
1301
+ * }
1302
+ * ```
1303
+ */
1304
+ export interface WithPath {
1305
+ /** Path or route */
1306
+ path: string;
1307
+ }
1308
+ /**
1309
+ * Base interface for validation results.
1310
+ * Standardizes validation response structure.
1311
+ *
1312
+ * @example
1313
+ * ```typescript
1314
+ * const result: ValidationResult = {
1315
+ * isValid: false,
1316
+ * errors: ['Email is required', 'Password too short']
1317
+ * };
1318
+ * ```
1319
+ */
1320
+ export interface ValidationResult {
1321
+ /** Whether validation passed */
1322
+ isValid: boolean;
1323
+ /** Validation error messages */
1324
+ errors: string[];
1325
+ }
1326
+ /**
1327
+ * Base interface for validation errors with field-level details.
1328
+ * Provides comprehensive validation error information.
1329
+ *
1330
+ * @template Context - Type of additional context information
1331
+ * @example
1332
+ * ```typescript
1333
+ * interface FieldValidationError extends WithValidationError<{ min: number; max: number }> {
1334
+ * severity: 'error' | 'warning';
1335
+ * }
1336
+ * ```
1337
+ */
1338
+ export interface WithValidationError<Context = unknown> extends WithErrorCode, WithMessage {
1339
+ /** The field that caused the validation error */
1340
+ field?: string;
1341
+ /** Additional context about the validation error */
1342
+ context?: Context;
1343
+ }
1344
+ /**
1345
+ * Base interface for HTTP methods.
1346
+ */
1347
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
1348
+ /**
1349
+ * Base interface for entities with HTTP method.
1350
+ *
1351
+ * @example
1352
+ * ```typescript
1353
+ * interface ApiRoute extends WithHttpMethod {
1354
+ * path: string;
1355
+ * }
1356
+ * ```
1357
+ */
1358
+ export interface WithHttpMethod {
1359
+ /** HTTP method for the request */
1360
+ method: HttpMethod;
1361
+ }
1362
+ /**
1363
+ * Base interface for entities with headers.
1364
+ *
1365
+ * @example
1366
+ * ```typescript
1367
+ * interface Request extends WithHeaders {
1368
+ * body: unknown;
1369
+ * }
1370
+ * ```
1371
+ */
1372
+ export interface WithHeaders {
1373
+ /** HTTP headers */
1374
+ headers: Record<string, string | string[]>;
1375
+ }
1376
+ /**
1377
+ * Base interface for entities with cookies.
1378
+ * Provides cookie storage.
1379
+ *
1380
+ * @example
1381
+ * ```typescript
1382
+ * interface HttpRequest extends WithCookies {
1383
+ * url: string;
1384
+ * }
1385
+ * ```
1386
+ */
1387
+ export interface WithCookies {
1388
+ /** Cookie key-value pairs */
1389
+ cookies: Record<string, string>;
1390
+ }
1391
+ /**
1392
+ * Base interface for entities with query parameters.
1393
+ *
1394
+ * @example
1395
+ * ```typescript
1396
+ * interface SearchRequest extends WithQueryParams {
1397
+ * path: string;
1398
+ * }
1399
+ * ```
1400
+ */
1401
+ export interface WithQueryParams {
1402
+ /** Query parameters */
1403
+ query?: Record<string, string | string[] | undefined>;
1404
+ }
1405
+ /**
1406
+ * Base interface for entities with route parameters.
1407
+ * Provides route/path parameters support.
1408
+ *
1409
+ * @example
1410
+ * ```typescript
1411
+ * interface RouteRequest extends WithParams {
1412
+ * method: 'GET';
1413
+ * }
1414
+ * ```
1415
+ */
1416
+ export interface WithParams {
1417
+ /** Route/path parameters */
1418
+ params: Record<string, Arrayable<string>>;
1419
+ }
1420
+ /**
1421
+ * Base interface for entities with request body.
1422
+ *
1423
+ * @template T - Type of the body
1424
+ * @example
1425
+ * ```typescript
1426
+ * interface CreateRequest extends WithBody<UserData> {
1427
+ * method: 'POST';
1428
+ * }
1429
+ * ```
1430
+ */
1431
+ export interface WithBody<T = unknown> {
1432
+ /** Request body */
1433
+ body: T;
1434
+ }
1435
+ /**
1436
+ * Base interface for entities with error information.
1437
+ * Provides standard error fields.
1438
+ *
1439
+ * @example
1440
+ * ```typescript
1441
+ * interface ApiError extends WithError {
1442
+ * statusCode: number;
1443
+ * }
1444
+ * ```
1445
+ */
1446
+ export interface WithError extends WithMessage {
1447
+ /** Error code for programmatic handling */
1448
+ code?: string;
1449
+ }
1450
+ /**
1451
+ * Base interface for entities with error code.
1452
+ * Provides error code field for programmatic error handling.
1453
+ *
1454
+ * @example
1455
+ * ```typescript
1456
+ * interface BusinessError extends WithErrorCode {
1457
+ * details: unknown;
1458
+ * }
1459
+ * ```
1460
+ */
1461
+ export interface WithErrorCode {
1462
+ /** Application-specific error code */
1463
+ errorCode: string;
1464
+ }
1465
+ /**
1466
+ * Base interface for detailed error information.
1467
+ * Provides comprehensive error fields for debugging.
1468
+ *
1469
+ * @example
1470
+ * ```typescript
1471
+ * import type { SetOptional } from 'type-fest';
1472
+ * interface ApiErrorResponse extends WithErrorDetailed {
1473
+ * requestId: string;
1474
+ * }
1475
+ * // Or with optional path:
1476
+ * interface TestError extends SetOptional<WithErrorDetailed, 'path'> {
1477
+ * testName: string;
1478
+ * }
1479
+ * ```
1480
+ */
1481
+ export interface WithErrorDetailed<T = UnknownRecord> extends WithTimestamp, SetOptional<WithPath, 'path'>, WithMessage, WithStatusCode {
1482
+ /** Error type/name */
1483
+ error: string;
1484
+ /** Additional error details */
1485
+ details?: T;
1486
+ }
1487
+ /**
1488
+ * Base interface for token-based authentication.
1489
+ * Provides access and refresh token fields.
1490
+ *
1491
+ * @example
1492
+ * ```typescript
1493
+ * interface AuthResponse extends WithTokens {
1494
+ * user: User;
1495
+ * }
1496
+ * ```
1497
+ */
1498
+ export interface WithAuthTokens {
1499
+ /** JWT or opaque access token for API authentication */
1500
+ accessToken: string;
1501
+ /** Token used to obtain new access token when current expires */
1502
+ refreshToken: string;
1503
+ }
1504
+ /**
1505
+ * Base interface for single token authentication.
1506
+ * Provides a single token field.
1507
+ *
1508
+ * @example
1509
+ * ```typescript
1510
+ * interface ApiKeyAuth extends WithToken {
1511
+ * expiresAt: Date;
1512
+ * }
1513
+ * ```
1514
+ */
1515
+ export interface WithToken {
1516
+ /** Authentication token */
1517
+ token: string;
1518
+ }
1519
+ /**
1520
+ * Base interface for entities with message.
1521
+ * Provides message field for user-facing information.
1522
+ *
1523
+ * @example
1524
+ * ```typescript
1525
+ * interface Notification extends WithMessage {
1526
+ * type: 'info' | 'warning' | 'error';
1527
+ * }
1528
+ * ```
1529
+ */
1530
+ export interface WithMessage {
1531
+ /** Human-readable message */
1532
+ message: string;
1533
+ }
1534
+ /**
1535
+ * Base interface for operation results.
1536
+ * Provides success/failure pattern.
1537
+ *
1538
+ * @template T - The type of the result data
1539
+ * @template E - The type of the error data
1540
+ *
1541
+ * @example
1542
+ * ```typescript
1543
+ * const result: Result<User> = {
1544
+ * success: true,
1545
+ * data: user,
1546
+ * error: null,
1547
+ * message: 'Success'
1548
+ * };
1549
+ * ```
1550
+ */
1551
+ export interface Result<T = unknown, E = Error> {
1552
+ /** Whether the operation succeeded */
1553
+ success: boolean;
1554
+ /** Result data */
1555
+ data: T | null;
1556
+ /** Error if operation failed */
1557
+ error: E | null;
1558
+ /** Status message */
1559
+ message: string;
1560
+ }
1561
+ /**
1562
+ * Base interface for entities with a slug.
1563
+ * Provides URL-friendly identifier.
1564
+ */
1565
+ export interface Sluggable {
1566
+ /** URL-friendly identifier */
1567
+ slug: string;
1568
+ }
1569
+ /**
1570
+ * Base interface for entities with categories.
1571
+ * Provides categorization support.
1572
+ */
1573
+ export interface WithCategories {
1574
+ /** Array of category names or identifiers */
1575
+ categories: string[];
1576
+ }
1577
+ /**
1578
+ * Base interface for HTTP response status.
1579
+ * Provides status code and message.
1580
+ */
1581
+ export interface WithStatusMessage {
1582
+ /** HTTP status message */
1583
+ statusMessage: string;
1584
+ }