@zssz-soft/core-api 0.2.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.
@@ -0,0 +1,1633 @@
1
+ import { Identifiable, Meta, EntityTypeEnum, User, QueryOptions, CursorPaginatedResult, PaginatedResult, SearchParam, Message } from '@zssz-soft/common-api';
2
+ import { Observable } from 'rxjs';
3
+ import * as _angular_core from '@angular/core';
4
+ import { Signal, InjectionToken, Provider, PipeTransform } from '@angular/core';
5
+ import { FormGroup } from '@angular/forms';
6
+ import { KeyValue } from '@angular/common';
7
+ import { SelectEntityId, EntityId } from '@ngrx/signals/entities';
8
+ import { HttpClient } from '@angular/common/http';
9
+ import { Translation } from '@jsverse/transloco';
10
+ import { DateFormatOptions } from '@jsverse/transloco-locale';
11
+
12
+ interface EntityHelper {
13
+ meta: Meta;
14
+ }
15
+ type Entity = Identifiable & EntityHelper;
16
+ type EntityAdd = Omit<Entity, 'uid'>;
17
+ type EntityUpdate = Partial<Entity> & Identifiable & EntityHelper;
18
+ type EntityModel = Entity;
19
+ type EntityModelAdd = Omit<EntityModel, 'uid'>;
20
+ type EntityModelUpdate = Partial<EntityModel> & Identifiable & EntityHelper;
21
+ type EntityType = EntityTypeEnum.Entity;
22
+ type CustomEntityState = {
23
+ isLoading: boolean;
24
+ isNewEntityButtonEnabled: boolean;
25
+ };
26
+
27
+ interface EntityCollectionStoreView<E extends Entity> {
28
+ editEntity(entity: E): void;
29
+ deleteEntity(entity: E): void;
30
+ setSearchTerm(searchTerm: string): void;
31
+ setSorting(field: string, order: 'asc' | 'desc'): void;
32
+ setViewMode(viewMode: 'table' | 'dataview' | 'cards'): void;
33
+ toggleSortOrder(): void;
34
+ entities: Signal<E[]>;
35
+ isLoading: Signal<boolean>;
36
+ }
37
+
38
+ declare abstract class EntityFormLogic<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
39
+ abstract cancel(): void;
40
+ abstract createEntity(formValue: any): void;
41
+ abstract createFormGroup(entity?: E): FormGroup;
42
+ abstract getEntityById(entityId: string): E | undefined;
43
+ abstract updateEntity(entityId: string, formValue: any): void;
44
+ abstract validateAndProcessForm(form: FormGroup | null, entityId: string | null): {
45
+ isValid: boolean;
46
+ formValue?: any;
47
+ entityId?: string | null;
48
+ };
49
+ }
50
+
51
+ interface EntityFormStoreView<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
52
+ cancel(): void;
53
+ createEntity(formValue: any): void;
54
+ createFormGroup(entity: E | undefined): FormGroup;
55
+ updateEntity(entityId: string, formValue: any): void;
56
+ formGroup(): FormGroup | undefined;
57
+ }
58
+
59
+ /**
60
+ * Interface defining the contract for entity table stores.
61
+ * Provides standard methods for table operations like editing, deleting, and navigation.
62
+ */
63
+ interface EntityTableStoreView<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
64
+ editEntity(entity: E): void;
65
+ deleteEntity(entity: E): void;
66
+ navigateToCreate(): void;
67
+ navigateToEdit(entityId: string): void;
68
+ setViewMode(viewMode: 'table' | 'dataview' | 'cards'): void;
69
+ setSearchTerm(searchTerm: string): void;
70
+ setSorting(field: string, order: 'asc' | 'desc'): void;
71
+ clearFilters(): void;
72
+ setCurrentPage(page: number): void;
73
+ setPageSize(size: number): void;
74
+ refresh(): void;
75
+ }
76
+
77
+ /**
78
+ * Interface defining the contract for resource-based entity table stores.
79
+ * Uses cursor-based pagination for Firestore cost optimization.
80
+ */
81
+ interface EntityTableResourceStoreView<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
82
+ editEntity(entity: E): void;
83
+ deleteEntity(entity: E): void;
84
+ navigateToCreate(): void;
85
+ navigateToEdit(entityId: string): void;
86
+ setViewMode(viewMode: 'table' | 'dataview' | 'cards'): void;
87
+ setSearchTerm(searchTerm: string): void;
88
+ setSorting(field: string, order: 'asc' | 'desc'): void;
89
+ clearFilters(): void;
90
+ loadNextPage(): void;
91
+ resetPagination(): void;
92
+ setPageSize(size: number): void;
93
+ refresh(): void;
94
+ }
95
+
96
+ declare abstract class EntityAdapter<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate, EM extends EntityModel, EMA extends EntityModelAdd, EMU extends EntityModelUpdate> {
97
+ user: Signal<User | undefined>;
98
+ abstract _sort(a: E, b: E): number;
99
+ abstract convertEntityAddToModelAdd(entityAdd: EA): EMA;
100
+ abstract convertEntityToModel(entity: E): EM;
101
+ abstract convertEntityUpdateToModelUpdate(entity: EU): EMU;
102
+ abstract convertModelToEntity(model: EM): E;
103
+ abstract convertModelUpdateToEntityUpdate(model: EMU): EU;
104
+ }
105
+
106
+ /**
107
+ * Abstract base class for entity effects
108
+ *
109
+ * Design Pattern: Template Method Pattern
110
+ * - Definiálja az entity műveletek absztrakt szerződését
111
+ * - A konkrét implementációk a domain-specifikus logikát adják
112
+ *
113
+ * Effects felelősségei:
114
+ * - Adapter hívások koordinálása (Entity <-> Model konverzió)
115
+ * - Error handling és logging
116
+ * - Repository művelet delegálás
117
+ */
118
+ declare abstract class EntityEffect<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
119
+ abstract createEntity$(entityAdd: EA): Observable<E>;
120
+ abstract deleteEntity$(entity: E): Observable<E>;
121
+ abstract listEntities$(pathParams: string[], queryParams: KeyValue<string, string>[]): Observable<E[]>;
122
+ abstract loadEntity$(entityId: string): Observable<E>;
123
+ abstract updateEntity$(entityUpdate: EU): Observable<EU>;
124
+ /**
125
+ * Query entities with cursor-based pagination
126
+ * Optional method - can be overridden by domain effects for optimized queries
127
+ *
128
+ * @param options Query options including filters, sorting, and pagination
129
+ * @returns Observable of cursor-paginated result
130
+ */
131
+ queryCursorPaginated$(_options: QueryOptions): Observable<CursorPaginatedResult<E>>;
132
+ /**
133
+ * Query entities by parent ID (for subcollections)
134
+ * Optional method - can be overridden by effects that handle subcollections
135
+ *
136
+ * @param parentId The ID of the parent entity
137
+ * @param options Optional query options
138
+ * @returns Observable of entities belonging to parent
139
+ */
140
+ queryByParentId$(_parentId: string, _options?: QueryOptions): Observable<E[]>;
141
+ }
142
+
143
+ /**
144
+ * Batch operation interface
145
+ */
146
+ interface BatchOperation<T> {
147
+ type: 'create' | 'update' | 'delete';
148
+ uid?: string;
149
+ data?: Partial<T>;
150
+ }
151
+ /**
152
+ * Context for resolving subcollection paths in Firestore
153
+ * Enables repositories to work with nested collections (e.g., apartments/{id}/rules)
154
+ */
155
+ interface SubcollectionContext {
156
+ /**
157
+ * Name of parent collection (e.g., 'apartments')
158
+ */
159
+ parentCollection: string;
160
+ /**
161
+ * Field name on the entity that contains parent ID (e.g., 'entityId', 'apartmentId')
162
+ */
163
+ parentIdField: string;
164
+ /**
165
+ * Name of subcollection (e.g., 'rules')
166
+ */
167
+ subcollection: string;
168
+ }
169
+ /**
170
+ * Builder function type for dynamic collection paths
171
+ * Takes optional entity data and returns the resolved collection path
172
+ */
173
+ type CollectionPathBuilder = (entityData?: Partial<EntityModel>) => string;
174
+ /**
175
+ * Abstract base repository interface for database operations
176
+ * This interface defines the contract that all data repositories must implement
177
+ */
178
+ declare abstract class Repository<EM extends EntityModel, EMA extends EntityModelAdd, EMU extends EntityModelUpdate> {
179
+ abstract create$(modelAdd: EMA): Observable<EM>;
180
+ abstract list$(pathParams: string[], queryParams: KeyValue<string, string>[]): Observable<EM[]>;
181
+ abstract listByIds$(ids: string[]): Observable<EM[]>;
182
+ abstract load$(uid: string): Observable<EM | undefined>;
183
+ abstract update$(modelUpdate: EMU): Observable<EMU>;
184
+ abstract delete$(model: EM): Observable<EM>;
185
+ abstract query(options: QueryOptions): Observable<EM[]>;
186
+ abstract queryPaginated(options: QueryOptions, pageSize: number, lastDocument?: EM): Observable<PaginatedResult<EM>>;
187
+ abstract count(options?: QueryOptions): Observable<number>;
188
+ abstract exists(uid: string): Observable<boolean>;
189
+ abstract batch(operations: BatchOperation<EM>[]): Observable<void>;
190
+ abstract search$(params: SearchParam[]): Observable<EM[]>;
191
+ /**
192
+ * Query entities by parent ID (for subcollections)
193
+ * Optional - only implemented for repositories with subcollection context
194
+ * @param parentId The ID of the parent entity
195
+ * @param options Optional query options for filtering/sorting
196
+ */
197
+ queryByParentId?(parentId: string, options?: QueryOptions): Observable<EM[]>;
198
+ }
199
+
200
+ declare abstract class RepositoryEngine<E extends EntityModel, EA extends EntityModelAdd, EU extends EntityModelUpdate> extends Repository<E, EA, EU> {
201
+ }
202
+
203
+ /**
204
+ * Type for a factory function that creates a repository engine
205
+ */
206
+ type RepositoryEngineCreator = <R extends EntityModel, S extends EntityModelAdd, T extends EntityModelUpdate>(featureKey: string, subcollectionContext?: SubcollectionContext) => RepositoryEngine<R, S, T>;
207
+ /**
208
+ * Injection token for the Firestore engine creator function
209
+ * This allows the actual Firebase implementation to be provided at the app level
210
+ * while keeping the factory testable
211
+ */
212
+ declare const FIRESTORE_ENGINE_CREATOR: InjectionToken<RepositoryEngineCreator>;
213
+
214
+ declare abstract class EntityRepository<EM extends EntityModel, EMA extends EntityModelAdd, EU extends EntityModelUpdate> extends Repository<EM, EMA, EU> {
215
+ }
216
+
217
+ interface EntityActions<E extends Entity> {
218
+ setLoading(isLoading: boolean): void;
219
+ setNewEntityButtonEnabled(enabled: boolean): void;
220
+ setSearchResult(searchResult: E[]): void;
221
+ setSelectedEntityId(selectedEntityId: string | undefined): void;
222
+ }
223
+ interface EntityConfig<E extends Entity> {
224
+ collection: string;
225
+ entity: E;
226
+ selectId: SelectEntityId<NoInfer<E>>;
227
+ }
228
+ interface EntitySignals<A extends string, E extends Entity> {
229
+ all: Signal<E[]>;
230
+ count: Signal<number>;
231
+ entities: Signal<Record<A, E>>;
232
+ error: Signal<string | null>;
233
+ ids: Signal<A[]>;
234
+ isLoading: Signal<boolean>;
235
+ selected: Signal<E | undefined>;
236
+ selectedId: Signal<A | null>;
237
+ selectEntityById(): Signal<E | undefined>;
238
+ }
239
+ interface EntityStore<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate, V extends string> extends EntitySignals<V, E>, RxEntityActions<E, EA, EU>, EntityActions<E> {
240
+ }
241
+ interface RxEntityActions<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
242
+ createEntity$(entityAdd: EA): void;
243
+ deleteEntity$(entity: E): void;
244
+ listEntities$(): void;
245
+ updateEntity$(entityUpdate: EU): void;
246
+ }
247
+ interface EntityStoreView<E extends Entity, EA extends EntityAdd, EU extends EntityUpdate> {
248
+ entityMap: Signal<Record<string, E>>;
249
+ ids: Signal<EntityId[]>;
250
+ entities: Signal<E[]>;
251
+ selectedEntityId: Signal<string | undefined>;
252
+ isLoading: Signal<boolean>;
253
+ isNewEntityButtonEnabled: Signal<boolean>;
254
+ searchResult: Signal<E[]>;
255
+ error: Signal<string | null>;
256
+ getEntityBySelectedId: Signal<E | undefined>;
257
+ resourceEntities?: Signal<E[]>;
258
+ hasNextPage?: Signal<boolean>;
259
+ hasPreviousPage?: Signal<boolean>;
260
+ isLoaded?: Signal<boolean>;
261
+ getEntityById(entityId: string): E | undefined;
262
+ setSelectedEntityId(id?: string): void;
263
+ setNewEntityButtonEnabled(enabled: boolean): void;
264
+ setSearchResult(results: E[]): void;
265
+ setLoading(loading: boolean): void;
266
+ setQueryOptions?(options: QueryOptions): void;
267
+ updateQueryOptions?(options: Partial<QueryOptions>): void;
268
+ loadNextPage?(): void;
269
+ resetPagination?(): void;
270
+ reload?(): void;
271
+ parentId?: Signal<string | null>;
272
+ subcollectionOptions?: Signal<QueryOptions | null>;
273
+ loadEntitiesByParentId?(parentId: string, options?: QueryOptions): Promise<E[]>;
274
+ listEntities(params: {
275
+ pathParams: string[];
276
+ queryParams: KeyValue<string, string>[];
277
+ }): Promise<E[]>;
278
+ createEntity(entity: EA): Promise<E>;
279
+ updateEntity(entity: EU): Promise<EU>;
280
+ deleteEntity(entity: E): Promise<E>;
281
+ loadEntity(id: string): Promise<E>;
282
+ }
283
+
284
+ declare const AUDIT_FEATURE_KEY = "audit_logs";
285
+ /**
286
+ * Audit log entry for tracking user actions
287
+ */
288
+ interface AuditLog {
289
+ /** Unique audit log ID */
290
+ id?: string;
291
+ /** User who performed the action */
292
+ user: User | string;
293
+ /** Action performed */
294
+ action: AuditAction;
295
+ /** Resource affected by the action */
296
+ resource: AuditResource;
297
+ /** Timestamp when action occurred */
298
+ timestamp: Date;
299
+ /** Session information */
300
+ sessionId?: string;
301
+ /** Request metadata */
302
+ metadata: AuditMetadata;
303
+ /** Action result */
304
+ result: AuditResult;
305
+ /** Additional context data */
306
+ context?: Record<string, any>;
307
+ }
308
+ /**
309
+ * Types of actions that can be audited
310
+ */
311
+ type AuditAction = 'auth.login' | 'auth.logout' | 'auth.register' | 'auth.password_reset' | 'auth.email_verification' | 'user.create' | 'user.update' | 'user.delete' | 'user.role_change' | 'user.status_change' | 'data.create' | 'data.read' | 'data.update' | 'data.delete' | 'data.export' | 'data.import' | 'system.configuration_change' | 'system.backup' | 'system.restore' | 'ui.page_view' | 'ui.button_click' | 'ui.form_submit' | 'ui.theme_change' | 'ui.search' | 'ui.filter' | 'ui.download' | 'ui.upload' | 'security.unauthorized_access' | 'security.permission_denied' | 'security.suspicious_activity' | string;
312
+ /**
313
+ * Resource types that can be audited
314
+ */
315
+ interface AuditResource {
316
+ /** Type of resource */
317
+ type: string;
318
+ /** Resource identifier */
319
+ id?: string;
320
+ /** Resource name or description */
321
+ name?: string;
322
+ /** Parent resource if applicable */
323
+ parent?: AuditResource;
324
+ /** Additional resource metadata */
325
+ metadata?: Record<string, any>;
326
+ }
327
+ /**
328
+ * Metadata associated with an audit action
329
+ */
330
+ interface AuditMetadata {
331
+ /** IP address of the request */
332
+ ipAddress?: string;
333
+ /** User agent string */
334
+ userAgent?: string;
335
+ /** Geographic location */
336
+ location?: {
337
+ country?: string;
338
+ region?: string;
339
+ city?: string;
340
+ coordinates?: {
341
+ latitude: number;
342
+ longitude: number;
343
+ };
344
+ };
345
+ /** Request information */
346
+ request?: {
347
+ method?: string;
348
+ url?: string;
349
+ headers?: Record<string, string>;
350
+ body?: any;
351
+ };
352
+ /** Response information */
353
+ response?: {
354
+ statusCode?: number;
355
+ headers?: Record<string, string>;
356
+ body?: any;
357
+ };
358
+ /** Performance metrics */
359
+ performance?: {
360
+ duration?: number;
361
+ memoryUsage?: number;
362
+ cpuUsage?: number;
363
+ };
364
+ /** Additional custom metadata */
365
+ [key: string]: any;
366
+ }
367
+ /**
368
+ * Result of an audited action
369
+ */
370
+ interface AuditResult {
371
+ /** Whether the action was successful */
372
+ success: boolean;
373
+ /** Status code or error code */
374
+ code?: string | number;
375
+ /** Human-readable message */
376
+ message?: string;
377
+ /** Error details if action failed */
378
+ error?: {
379
+ type: string;
380
+ message: string;
381
+ stack?: string;
382
+ };
383
+ /** Changes made (for update actions) */
384
+ changes?: {
385
+ before?: any;
386
+ after?: any;
387
+ fields?: string[];
388
+ };
389
+ /** Additional result data */
390
+ data?: any;
391
+ }
392
+ /**
393
+ * Audit log query filters
394
+ */
395
+ interface AuditLogQuery {
396
+ /** Filter by user */
397
+ userId?: string;
398
+ /** Filter by action */
399
+ action?: AuditAction | AuditAction[];
400
+ /** Filter by resource type */
401
+ resourceType?: string;
402
+ /** Filter by date range */
403
+ dateRange?: {
404
+ start: Date;
405
+ end: Date;
406
+ };
407
+ /** Filter by success/failure */
408
+ success?: boolean;
409
+ /** Filter by session ID */
410
+ sessionId?: string;
411
+ /** Filter by IP address */
412
+ ipAddress?: string;
413
+ /** Pagination */
414
+ limit?: number;
415
+ offset?: number;
416
+ /** Sorting */
417
+ sortBy?: 'timestamp' | 'action' | 'user';
418
+ sortOrder?: 'asc' | 'desc';
419
+ }
420
+ /**
421
+ * Audit log summary statistics
422
+ */
423
+ interface AuditLogStats {
424
+ /** Total number of logs */
425
+ totalLogs: number;
426
+ /** Actions by type */
427
+ actionCounts: Record<string, number>;
428
+ /** Success rate */
429
+ successRate: number;
430
+ /** Most active users */
431
+ topUsers: Array<{
432
+ userId: string;
433
+ actionCount: number;
434
+ }>;
435
+ /** Most common actions */
436
+ topActions: Array<{
437
+ action: string;
438
+ count: number;
439
+ }>;
440
+ /** Date range covered */
441
+ dateRange: {
442
+ start: Date;
443
+ end: Date;
444
+ };
445
+ }
446
+ interface Audit {
447
+ /** User who performed the action */
448
+ user: User | string;
449
+ /** Action performed */
450
+ action: AuditAction;
451
+ /** Resource affected by the action */
452
+ resource: AuditResource;
453
+ /** Timestamp when action occurred */
454
+ timestamp: Date;
455
+ /** Session information */
456
+ sessionId?: string;
457
+ /** Request metadata */
458
+ metadata: AuditMetadata;
459
+ /** Action result */
460
+ result: AuditResult;
461
+ /** Additional context data */
462
+ context?: Record<string, any>;
463
+ }
464
+ type AuditEntity = Audit & Entity;
465
+ type AuditEntityAdd = Omit<AuditEntity, 'uid'>;
466
+ type AuditEntityUpdate = Partial<AuditEntity> & Entity;
467
+ type AuditModel = Audit & EntityModel;
468
+ type AuditModelAdd = Omit<AuditModel, 'uid'>;
469
+ type AuditModelUpdate = Partial<AuditModel> & EntityModel;
470
+
471
+ /**
472
+ * Abstract interface for audit logging operations
473
+ * This defines the contract for audit logging without implementation details
474
+ */
475
+ declare abstract class AuditService {
476
+ /**
477
+ * Log a user action with result
478
+ * @param user User performing the action
479
+ * @param action Action being performed
480
+ * @param resource Resource being acted upon
481
+ * @param result Action result (success/failure)
482
+ * @param context Additional context data
483
+ * @returns Observable with the audit log ID
484
+ */
485
+ abstract logAction(user: User, action: AuditAction, resource: AuditResource, result: 'success' | 'failure', context?: Record<string, any>): Observable<string>;
486
+ /**
487
+ * Log a successful action
488
+ * @param user User performing the action
489
+ * @param action Action being performed
490
+ * @param resource Resource being acted upon
491
+ * @param data Additional data about the action
492
+ * @param context Additional context data
493
+ * @returns Observable with the audit log ID
494
+ */
495
+ abstract logSuccess(user: User, action: AuditAction, resource: AuditResource, data?: any, context?: Record<string, any>): Observable<string>;
496
+ /**
497
+ * Log a failed action
498
+ * @param user User performing the action
499
+ * @param action Action being performed
500
+ * @param resource Resource being acted upon
501
+ * @param error Error that occurred
502
+ * @param context Additional context data
503
+ * @returns Observable with the audit log ID
504
+ */
505
+ abstract logFailure(user: User, action: AuditAction, resource: AuditResource, error: Error, context?: Record<string, any>): Observable<string>;
506
+ /**
507
+ * Log authentication events
508
+ * @param user User involved in auth event
509
+ * @param action Auth action performed
510
+ * @param success Whether the auth action was successful
511
+ * @param additionalData Additional auth-related data
512
+ * @returns Observable with the audit log ID
513
+ */
514
+ abstract logAuthEvent(user: User, action: AuditAction, success: boolean, additionalData?: Record<string, any>): Observable<string>;
515
+ /**
516
+ * Query audit logs with filters
517
+ * @param query Query filters
518
+ * @returns Observable with array of audit logs
519
+ */
520
+ abstract queryLogs(query: AuditLogQuery): Observable<AuditLog[]>;
521
+ /**
522
+ * Get audit log statistics
523
+ * @param timeRange Optional time range for statistics
524
+ * @returns Observable with audit statistics
525
+ */
526
+ abstract getStats(timeRange?: {
527
+ start: Date;
528
+ end: Date;
529
+ }): Observable<AuditLogStats>;
530
+ /**
531
+ * Get audit logs for a specific user
532
+ * @param userId User ID
533
+ * @param limit Optional limit on number of logs
534
+ * @returns Observable with array of user's audit logs
535
+ */
536
+ abstract getUserLogs(userId: string, limit?: number): Observable<AuditLog[]>;
537
+ /**
538
+ * Get recent audit logs
539
+ * @param limit Number of recent logs to retrieve
540
+ * @returns Observable with array of recent audit logs
541
+ */
542
+ abstract getRecentLogs(limit?: number): Observable<AuditLog[]>;
543
+ }
544
+
545
+ interface AuthResult<T = any> {
546
+ data?: T;
547
+ error?: {
548
+ code: AuthErrorCode;
549
+ message: string;
550
+ };
551
+ success: boolean;
552
+ }
553
+ interface AuthState {
554
+ error: string | null;
555
+ isAuthenticated: boolean;
556
+ loading: boolean;
557
+ user: AuthUser | null;
558
+ }
559
+ interface AuthUser {
560
+ createdAt?: string;
561
+ customClaims?: Record<string, any>;
562
+ displayName: string | null;
563
+ email: string | null;
564
+ emailVerified: boolean;
565
+ lastSignInAt?: string;
566
+ phoneNumber: string | null;
567
+ photoURL: string | null;
568
+ uid: string;
569
+ }
570
+ interface EmailPasswordCredentials {
571
+ email: string;
572
+ password: string;
573
+ }
574
+ interface UserRegistrationData extends EmailPasswordCredentials {
575
+ displayName?: string;
576
+ phoneNumber?: string;
577
+ }
578
+ type AuthCredentials = EmailPasswordCredentials;
579
+ type AuthErrorCode = 'auth/user-not-found' | 'auth/wrong-password' | 'auth/email-already-in-use' | 'auth/weak-password' | 'auth/invalid-email' | 'auth/user-disabled' | 'auth/too-many-requests' | 'auth/network-request-failed' | 'auth/popup-closed-by-user' | 'auth/popup-blocked' | 'auth/cancelled-popup-request' | 'auth/account-exists-with-different-credential' | 'unknown-error';
580
+ type AuthMethod = 'signIn' | 'signUp' | 'signOut' | 'resetPassword' | 'verifyEmail';
581
+ type AuthProvider = 'email' | 'google' | 'facebook';
582
+ declare const initialAuthState: AuthState;
583
+
584
+ declare abstract class AuthenticationStoreService {
585
+ abstract signOut(): Promise<AuthResult<void>>;
586
+ abstract signInWithEmailAndPassword(email: string, password: string): Promise<void>;
587
+ abstract signInWithGoogle(): Promise<AuthResult<AuthUser>>;
588
+ abstract createUserWithEmailAndPassword(userData: UserRegistrationData): Promise<AuthResult<AuthUser>>;
589
+ abstract sendPasswordResetEmail(email: string): Promise<void>;
590
+ abstract updatePassword(newPassword: string): Promise<AuthResult<void>>;
591
+ abstract updateEmail(newEmail: string): Promise<AuthResult<void>>;
592
+ abstract getIdToken(forceRefresh: boolean): Promise<string | null>;
593
+ abstract getStore(): AuthenticationStoreView;
594
+ }
595
+ interface AuthenticationStoreView {
596
+ user: Signal<AuthUser | null>;
597
+ isAuthenticated: Signal<boolean>;
598
+ isLoading: Signal<boolean>;
599
+ error: Signal<string | null>;
600
+ isLoggedIn: Signal<boolean>;
601
+ userDisplayName: Signal<string>;
602
+ userInitials: Signal<string>;
603
+ setUser(user: AuthUser | null): void;
604
+ setLoading(isLoading: boolean): void;
605
+ setError(error: string | null): void;
606
+ clearError(): void;
607
+ clearUser(): void;
608
+ setInitialized(): void;
609
+ }
610
+ declare const AUTHENTICATION_STORE_SERVICE_TOKEN: InjectionToken<AuthenticationStoreService>;
611
+ declare const AUTHENTICATION_STORE_VIEW_TOKEN: InjectionToken<AuthenticationStoreView>;
612
+
613
+ declare abstract class AuthenticationService {
614
+ private readonly _authState;
615
+ readonly authState: _angular_core.Signal<AuthState>;
616
+ readonly currentUser: _angular_core.Signal<AuthState>;
617
+ readonly isAuthenticated: _angular_core.Signal<AuthState>;
618
+ abstract createUserWithEmailAndPassword(userData: UserRegistrationData): Promise<AuthResult<AuthUser>>;
619
+ abstract generateUserWithUID(email: string, displayName?: string): Promise<AuthResult<AuthUser>>;
620
+ abstract generateUserWithUIDAndSendReset(email: string, displayName?: string): Promise<AuthResult<AuthUser>>;
621
+ abstract getIdToken(forceRefresh: boolean): Promise<string | null>;
622
+ abstract getIdTokenResult(forceRefresh: boolean): Promise<any>;
623
+ abstract sendEmailVerification(): Promise<AuthResult<void>>;
624
+ abstract sendPasswordResetEmail(email: string): Promise<void>;
625
+ abstract signInWithEmailAndPassword(credentials: EmailPasswordCredentials): Promise<void>;
626
+ abstract signInWithGoogle(): Promise<AuthResult<AuthUser>>;
627
+ abstract signOut(): Promise<AuthResult<void>>;
628
+ abstract updateEmail(newEmail: string): Promise<AuthResult<void>>;
629
+ abstract updatePassword(newPassword: string): Promise<AuthResult<void>>;
630
+ abstract updateProfile(profile: Partial<Pick<AuthUser, 'displayName' | 'photoURL'>>): Promise<AuthResult<void>>;
631
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<AuthenticationService, never>;
632
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<AuthenticationService>;
633
+ }
634
+
635
+ declare const DEFAULT_FIREBASE_CONFIG: FirebaseConfig;
636
+ declare const DEFAULT_FIREBASE_AUTH_CONFIG: FirebaseAuthConfig;
637
+ interface FirebaseConfig {
638
+ apiKey: string;
639
+ authDomain: string;
640
+ projectId: string;
641
+ storageBucket: string;
642
+ messagingSenderId: string;
643
+ appId: string;
644
+ measurementId?: string;
645
+ }
646
+ interface SessionConfig {
647
+ /** Inactivity timeout in milliseconds (default: 30 minutes) */
648
+ inactivityTimeout: number;
649
+ /** Warning before timeout in milliseconds (default: 5 minutes before timeout) */
650
+ warningBeforeTimeout?: number;
651
+ /** Events to track for activity (default: ['click', 'keypress', 'mousemove', 'touchstart']) */
652
+ events?: string[];
653
+ /** Whether to show warning dialog before logout */
654
+ showWarningDialog?: boolean;
655
+ }
656
+ interface UserConfig {
657
+ /** Firestore collection name for user documents (default: 'user') */
658
+ collection?: string;
659
+ /** Default role ID to assign to new OAuth users */
660
+ defaultRoleId: string;
661
+ /** Whether to automatically create user document on OAuth login (default: true) */
662
+ autoCreate?: boolean;
663
+ }
664
+ interface FirebaseAuthConfig {
665
+ firebase: FirebaseConfig;
666
+ enableRegistration?: boolean;
667
+ enableSocialLogin?: boolean;
668
+ enabledProviders?: ('email' | 'google' | 'facebook')[];
669
+ session?: SessionConfig;
670
+ /** Configuration for automatic user document creation on OAuth login */
671
+ userDocument?: UserConfig;
672
+ }
673
+ declare const FIREBASE_CONFIG: InjectionToken<FirebaseConfig>;
674
+ declare const FIREBASE_AUTH_CONFIG: InjectionToken<FirebaseAuthConfig>;
675
+ declare function provideFirebaseAuthConfig(config: FirebaseAuthConfig): Provider;
676
+
677
+ /**
678
+ * Represents a permission in the authorization system
679
+ */
680
+ interface Permission {
681
+ /**
682
+ * Unique identifier for the permission
683
+ */
684
+ id: string;
685
+ /**
686
+ * Human-readable name of the permission
687
+ */
688
+ name: string;
689
+ /**
690
+ * Optional description of what this permission allows
691
+ */
692
+ description?: string;
693
+ /**
694
+ * Optional category to group related permissions
695
+ */
696
+ category?: string;
697
+ }
698
+ /**
699
+ * Represents a role that can be assigned to users
700
+ */
701
+ interface Role {
702
+ /**
703
+ * Unique identifier for the role
704
+ */
705
+ id: string;
706
+ /**
707
+ * Human-readable name of the role
708
+ */
709
+ name: string;
710
+ /**
711
+ * Optional description of the role's purpose
712
+ */
713
+ description?: string;
714
+ /**
715
+ * List of permission IDs granted to this role
716
+ */
717
+ permissions: string[];
718
+ }
719
+ /**
720
+ * Represents authorization context for a user
721
+ */
722
+ interface AuthorizationContext {
723
+ /**
724
+ * User's assigned roles
725
+ */
726
+ roles: Role[];
727
+ /**
728
+ * Direct permissions assigned to the user (not through roles)
729
+ */
730
+ directPermissions: Permission[];
731
+ /**
732
+ * Additional context data that might affect authorization decisions
733
+ */
734
+ context?: Record<string, any>;
735
+ }
736
+ /**
737
+ * Configuration options for authorization checks
738
+ */
739
+ interface AuthorizationOptions {
740
+ /**
741
+ * Whether to require ALL permissions (AND logic) or ANY permission (OR logic)
742
+ * @default 'any'
743
+ */
744
+ mode?: 'all' | 'any';
745
+ /**
746
+ * Whether to include permissions from roles
747
+ * @default true
748
+ */
749
+ includeRolePermissions?: boolean;
750
+ /**
751
+ * Whether to include direct permissions
752
+ * @default true
753
+ */
754
+ includeDirectPermissions?: boolean;
755
+ }
756
+
757
+ interface CloudFunctionResult<T = any> {
758
+ success: boolean;
759
+ message?: string;
760
+ data?: T;
761
+ userId?: string;
762
+ uid?: string;
763
+ userCreated?: boolean;
764
+ }
765
+ interface CreateUserAndSendPasswordResetResult extends CloudFunctionResult {
766
+ uid: string;
767
+ userId: string;
768
+ }
769
+ type BootstrapStatusResult = CloudFunctionResult<{
770
+ isBootstrapped: boolean;
771
+ userCount?: number;
772
+ }>;
773
+ interface CreateUserRequest {
774
+ email: string;
775
+ password?: string;
776
+ firstName: string;
777
+ lastName: string;
778
+ displayName?: string;
779
+ phoneNumber?: string;
780
+ photoURL?: string;
781
+ disabled?: boolean;
782
+ sendWelcomeEmail?: boolean;
783
+ loginUrl?: string;
784
+ }
785
+ interface CreateUserResponse {
786
+ success: boolean;
787
+ uid: string;
788
+ email: string;
789
+ emailSent?: boolean;
790
+ error?: string;
791
+ }
792
+
793
+ declare abstract class CloudService {
794
+ abstract checkBootstrapStatus(): Promise<BootstrapStatusResult>;
795
+ abstract createUserAndSendPasswordReset(email: string, displayName: string, sendEmail: boolean): Promise<CreateUserAndSendPasswordResetResult>;
796
+ abstract sendPasswordResetEmail(email: string): Promise<CloudFunctionResult>;
797
+ abstract sendWelcomeEmail(email: string, displayName: string, firstName?: string, lastName?: string, roles?: string[]): Promise<CloudFunctionResult>;
798
+ abstract systemBootstrap(adminEmail: string, adminDisplayName?: string, adminPassword?: string): Promise<CloudFunctionResult>;
799
+ abstract registerUserWithWelcomeEmail(email: string, password: string, firstName: string, lastName: string, options?: {
800
+ displayName?: string;
801
+ phoneNumber?: string;
802
+ photoURL?: string;
803
+ disabled?: boolean;
804
+ loginUrl?: string;
805
+ }): Promise<CreateUserResponse>;
806
+ abstract registerUserWithoutEmail(email: string, password: string, firstName: string, lastName: string, options?: {
807
+ displayName?: string;
808
+ phoneNumber?: string;
809
+ photoURL?: string;
810
+ disabled?: boolean;
811
+ }): Promise<CreateUserResponse>;
812
+ abstract generateThumbnail(params: {
813
+ path: string;
814
+ documentId?: string;
815
+ maxWidth?: number;
816
+ maxHeight?: number;
817
+ force?: boolean;
818
+ }): Promise<CloudFunctionResult & {
819
+ thumbPath?: string;
820
+ documentUpdated?: boolean;
821
+ originalFilePath?: string;
822
+ }>;
823
+ }
824
+ declare const CLOUD_SERVICE_TOKEN: InjectionToken<CloudService>;
825
+
826
+ type AppBootstrapConfig = {
827
+ bootstrapAdmin: {
828
+ email: string;
829
+ displayName: string;
830
+ firstName: string;
831
+ lastName: string;
832
+ language: string;
833
+ roles: string[];
834
+ };
835
+ };
836
+ declare const APP_BOOTSTRAP_CONFIG: InjectionToken<AppBootstrapConfig>;
837
+ declare function provideAppBootstrapConfig(config: AppBootstrapConfig): Provider;
838
+ declare const DEFAULT_APP_BOOTSTRAP_CONFIG: AppBootstrapConfig;
839
+
840
+ declare const DOCUMENTS_KEYS: {
841
+ ház: string;
842
+ hálószoba: string;
843
+ földszint: string;
844
+ emelet: string;
845
+ nappali: string;
846
+ étkező: string;
847
+ konyha: string;
848
+ fürdőszoba: string;
849
+ kültér: string;
850
+ stég: string;
851
+ parkoló: string;
852
+ bográcsozó: string;
853
+ terasz: string;
854
+ wc: string;
855
+ };
856
+
857
+ interface NotificationConfig {
858
+ closable?: boolean;
859
+ life?: number;
860
+ sticky?: boolean;
861
+ }
862
+ declare const NOTIFICATION_CONFIG_TOKEN: InjectionToken<NotificationConfig>;
863
+ declare function provideNotificationConfig(config?: NotificationConfig): {
864
+ provide: InjectionToken<NotificationConfig>;
865
+ useValue: NotificationConfig;
866
+ };
867
+ declare const DEFAULT_NOTIFICATION_CONFIG: NotificationConfig;
868
+
869
+ interface EmailConfig {
870
+ fromEmail: string;
871
+ fromName: string;
872
+ mailersendApiKey: string;
873
+ }
874
+ interface SendPasswordResetEmailData {
875
+ customMessage?: string;
876
+ email: string;
877
+ }
878
+ type CreateUserData = Omit<WelcomeEmailData, 'firstName' | 'lastName'> & {
879
+ sendEmail?: boolean;
880
+ };
881
+ type WelcomeEmailData = Omit<User, 'language' | 'phone' | 'photoUrl' | 'uid'> & {
882
+ roles?: string[];
883
+ temporaryPassword?: string;
884
+ };
885
+ type WelcomeEmailDataWithConfig = WelcomeEmailData & Omit<EmailConfig, 'mailersendApiKey'>;
886
+ declare const EMAIL_CONFIG: InjectionToken<EmailConfig>;
887
+
888
+ /**
889
+ * Email service for sending welcome and notification emails
890
+ * This can be implemented with different providers
891
+ */
892
+ declare abstract class EmailService {
893
+ /**
894
+ * Send custom notification email
895
+ * @param to Recipient email
896
+ * @param subject Email subject
897
+ * @param body Email body (HTML or text)
898
+ * @param data Optional template data
899
+ * @returns Promise that resolves when email is sent
900
+ */
901
+ abstract sendNotificationEmail(to: string, subject: string, body: string, data?: Record<string, any>): Promise<void>;
902
+ /**
903
+ * Send welcome email to newly created user
904
+ * @param userData User data for the email
905
+ * @returns Promise that resolves when email is sent
906
+ */
907
+ abstract sendWelcomeEmail(userData: WelcomeEmailData): Promise<void>;
908
+ }
909
+
910
+ declare enum ErrorType {
911
+ HttpError = "http-error"
912
+ }
913
+ interface ErrorOptions {
914
+ type: ErrorType;
915
+ viewable?: boolean;
916
+ }
917
+ declare class KError extends Error {
918
+ options: ErrorOptions;
919
+ constructor(message: string, error: Error, options: ErrorOptions);
920
+ }
921
+
922
+ declare abstract class ErrorUtilService {
923
+ abstract createErrorMessage(error: KError): Message;
924
+ abstract throwEffectError(message: string, error: unknown, viewable?: boolean): KError;
925
+ }
926
+
927
+ declare abstract class DateTimePipeBase implements PipeTransform {
928
+ abstract transform(value: any, ...args: unknown[]): string;
929
+ }
930
+
931
+ declare abstract class DateUtil {
932
+ abstract createActionTime(minute: number, second: number): number;
933
+ abstract createFullTime(startTime: number, minute: number, second: number): number;
934
+ abstract getDateRange(firstDate: Date, lastDate: Date): Date[];
935
+ abstract getDateRangeWithoutBorder(firstDate: Date, lastDate: Date): Date[];
936
+ abstract getDateRangeAsString(dates: Date[], format: string): string[];
937
+ abstract getDateRangeLength(firstDate: Date, lastDate: Date): number;
938
+ abstract getFormattedDate(date: Date, format: string): string;
939
+ abstract getNextDay(baseDate: Date): Date;
940
+ abstract getNow(): number;
941
+ abstract getPreviousDay(baseDate: Date): Date;
942
+ abstract getToday(): Date;
943
+ abstract getTomorrow(): Date;
944
+ }
945
+
946
+ declare interface HashMapModel<T = unknown> {
947
+ [key: string]: T;
948
+ }
949
+
950
+ declare enum LanguagesEnum {
951
+ de = "de",
952
+ en = "en",
953
+ hu = "hu",
954
+ hr = "hr",
955
+ ro = "ro",
956
+ sk = "sk",
957
+ sl = "sl",
958
+ sr = "sr",
959
+ uk = "uk"
960
+ }
961
+ declare const LANGUAGES_TOKEN: InjectionToken<string[]>;
962
+ declare const DEFAULT_LANGUAGE_TOKEN: InjectionToken<string>;
963
+
964
+ type LoaderData = {
965
+ scope: string;
966
+ };
967
+ type I18nText = {
968
+ [key in string]: string;
969
+ };
970
+ interface I18nConfig {
971
+ availableLangs: LanguagesEnum[];
972
+ defaultLang: LanguagesEnum;
973
+ prodMode: boolean;
974
+ reRenderOnLangChange: boolean;
975
+ }
976
+
977
+ declare abstract class I18nService {
978
+ protected httpClient: HttpClient;
979
+ protected defaultPath: string;
980
+ constructor(httpClient: HttpClient);
981
+ abstract activeLanguageChanges$(): Observable<string>;
982
+ abstract getActiveLang(): LanguagesEnum;
983
+ abstract getActiveLangAsString(): string;
984
+ abstract getAvailableLanguages(): string[];
985
+ abstract getActiveLocale(): string;
986
+ abstract getDefaultI18nText(): I18nText;
987
+ abstract getValue(property: any, locale?: string): string;
988
+ abstract getValueByLanguage(i18nText: I18nText, language?: string): string;
989
+ abstract init(language: string): void;
990
+ abstract load(): Observable<Translation>;
991
+ abstract localizeDate(date: string | Date, locale: string, format: DateFormatOptions): string;
992
+ abstract nameComponentShorter(firstName: string, lastName: string): string[];
993
+ abstract translate<T>(key: string | string[], params?: HashMapModel<unknown>, lang?: string): string;
994
+ abstract selectTranslate$(key: string, params?: HashMapModel<unknown>, lang?: string): Observable<string>;
995
+ }
996
+
997
+ declare abstract class I18nUtil {
998
+ abstract getActiveLang(): LanguagesEnum;
999
+ abstract getDefaultI18nText(): I18nText;
1000
+ abstract updateLanguage(language: string): void;
1001
+ abstract getValueByLanguage(i18nText: I18nText, language?: string): string;
1002
+ abstract getCurrentLocale(): string;
1003
+ }
1004
+
1005
+ interface Localizable {
1006
+ currentLanguage: string;
1007
+ }
1008
+
1009
+ type IconType = 'material' | 'svg' | 'primeicons';
1010
+ type Icon = {
1011
+ name: string;
1012
+ class: string;
1013
+ type?: IconType;
1014
+ svgContent?: string;
1015
+ };
1016
+ /**
1017
+ * Helper function to create a PrimeIcons icon
1018
+ * @param name - PrimeIcons icon name without 'pi-' prefix (e.g., 'search', 'user', 'home')
1019
+ */
1020
+ declare function primeIcon(name: string): Icon;
1021
+ declare const materialIcons: Icon[];
1022
+ /**
1023
+ * Custom SVG icons for items not available in Material Symbols
1024
+ */
1025
+ declare const customSvgIcons: Icon[];
1026
+ /**
1027
+ * All available icons (Material + Custom SVG)
1028
+ */
1029
+ declare const allIcons: Icon[];
1030
+
1031
+ /**
1032
+ * Abstract interface for logging operations
1033
+ * This defines the contract for logging without implementation details
1034
+ */
1035
+ declare abstract class Logger {
1036
+ /**
1037
+ * Set the current user for audit logging
1038
+ * @param user Current authenticated user
1039
+ */
1040
+ abstract setCurrentUser(user: User | null): void;
1041
+ /**
1042
+ * Get the current user
1043
+ * @returns Current user or null
1044
+ */
1045
+ abstract getCurrentUser(): User | null;
1046
+ /**
1047
+ * Log trace level message
1048
+ * @param message Log message
1049
+ * @param data Additional data
1050
+ * @param context Context information
1051
+ */
1052
+ abstract trace(message: string, data?: any, context?: Record<string, any>): void;
1053
+ /**
1054
+ * Log debug level message
1055
+ * @param message Log message
1056
+ * @param data Additional data
1057
+ * @param context Context information
1058
+ */
1059
+ abstract debug(message: string, data?: any, context?: Record<string, any>): void;
1060
+ /**
1061
+ * Log info level message
1062
+ * @param message Log message
1063
+ * @param data Additional data
1064
+ * @param context Context information
1065
+ */
1066
+ abstract info(message: string, data?: any, context?: Record<string, any>): void;
1067
+ /**
1068
+ * Log warning level message
1069
+ * @param message Log message
1070
+ * @param data Additional data
1071
+ * @param context Context information
1072
+ */
1073
+ abstract warn(message: string, data?: any, context?: Record<string, any>): void;
1074
+ /**
1075
+ * Log error level message
1076
+ * @param message Log message
1077
+ * @param data Additional data
1078
+ * @param context Context information
1079
+ */
1080
+ abstract error(message: string, data?: any, context?: Record<string, any>): void;
1081
+ /**
1082
+ * Log fatal level message
1083
+ * @param message Log message
1084
+ * @param data Additional data
1085
+ * @param context Context information
1086
+ */
1087
+ abstract fatal(message: string, data?: any, context?: Record<string, any>): void;
1088
+ /**
1089
+ * Audit user actions with automatic success/failure logging
1090
+ * @param action Action being performed
1091
+ * @param resource Resource being acted upon
1092
+ * @param success Whether the action was successful
1093
+ * @param data Additional action data
1094
+ * @param context Additional context
1095
+ */
1096
+ abstract auditUserAction(action: AuditAction, resource: AuditResource, success: boolean, data?: any, context?: Record<string, any>): void;
1097
+ /**
1098
+ * Audit authentication events
1099
+ * @param user User involved in auth event
1100
+ * @param action Auth action performed
1101
+ * @param success Whether the auth action was successful
1102
+ * @param additionalData Additional auth-related data
1103
+ */
1104
+ abstract auditAuthEvent(user: User, action: AuditAction, success: boolean, additionalData?: Record<string, any>): void;
1105
+ /**
1106
+ * Audit UI interactions
1107
+ * @param action UI action performed
1108
+ * @param component Component where action occurred
1109
+ * @param data Additional UI data
1110
+ * @param context Additional context
1111
+ */
1112
+ abstract auditUIAction(action: string, component: string, data?: any, context?: Record<string, any>): void;
1113
+ /**
1114
+ * Audit data operations
1115
+ * @param operation Type of data operation
1116
+ * @param resourceType Type of resource
1117
+ * @param resourceId Resource identifier
1118
+ * @param success Whether operation was successful
1119
+ * @param data Additional operation data
1120
+ * @param context Additional context
1121
+ */
1122
+ abstract auditDataOperation(operation: 'create' | 'read' | 'update' | 'delete', resourceType: string, resourceId?: string, success?: boolean, data?: any, context?: Record<string, any>): void;
1123
+ /**
1124
+ * Log user action for tracking
1125
+ * @param component Component where action occurred
1126
+ * @param action Action performed
1127
+ * @param data Additional action data
1128
+ */
1129
+ abstract logUserAction(component: string, action: string, data?: any): void;
1130
+ /**
1131
+ * Log performance metrics
1132
+ * @param operation Operation being measured
1133
+ * @param duration Duration in milliseconds
1134
+ * @param component Component where operation occurred
1135
+ */
1136
+ abstract logPerformance(operation: string, duration: number, component?: string): void;
1137
+ /**
1138
+ * Log HTTP requests
1139
+ * @param method HTTP method
1140
+ * @param url Request URL
1141
+ * @param status Response status code
1142
+ * @param duration Request duration in milliseconds
1143
+ */
1144
+ abstract logHttpRequest(method: string, url: string, status: number, duration: number): void;
1145
+ abstract logComponentLifecycle(component: string, lifecycle: string): void;
1146
+ abstract logThemeChangeAudit(from: string, to: string): void;
1147
+ }
1148
+
1149
+ interface LoggerEnvironmentConfig {
1150
+ production: boolean;
1151
+ logLevel?: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
1152
+ enableConsoleLogging?: boolean;
1153
+ enableStorageLogging?: boolean;
1154
+ maxStoredLogs?: number;
1155
+ }
1156
+ /**
1157
+ * Log levels for the logger
1158
+ */
1159
+ type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
1160
+ interface LoggerConfig {
1161
+ level: LogLevel;
1162
+ environment: 'development' | 'production' | 'test';
1163
+ enableConsole: boolean;
1164
+ }
1165
+ interface LogEntry {
1166
+ timestamp: string;
1167
+ level: string;
1168
+ message: string;
1169
+ data?: any;
1170
+ component?: string;
1171
+ action?: string;
1172
+ }
1173
+ declare const LOGGER_ENVIRONMENT = "LOGGER_ENVIRONMENT";
1174
+ /**
1175
+ * Decorator options for method logging
1176
+ */
1177
+ interface LogMethodOptions {
1178
+ /** Component name for logging context */
1179
+ component?: string;
1180
+ /** Log level to use */
1181
+ level?: 'trace' | 'debug' | 'info' | 'warn' | 'error';
1182
+ /** Whether to log method entry */
1183
+ logEntry?: boolean;
1184
+ /** Whether to log method exit */
1185
+ logExit?: boolean;
1186
+ /** Whether to log method duration */
1187
+ logDuration?: boolean;
1188
+ /** Additional context data */
1189
+ context?: Record<string, any>;
1190
+ }
1191
+ /**
1192
+ * Decorator options for user action logging
1193
+ */
1194
+ interface LogUserActionOptions {
1195
+ /** Component name */
1196
+ component: string;
1197
+ /** Action name - if not provided, method name will be used */
1198
+ action?: string;
1199
+ /** Additional data extractor function */
1200
+ dataExtractor?: (args: any[]) => any;
1201
+ }
1202
+ /**
1203
+ * Decorator options for data operation auditing
1204
+ */
1205
+ interface LogDataOperationOptions {
1206
+ /** Operation type */
1207
+ operation: 'create' | 'read' | 'update' | 'delete';
1208
+ /** Resource type */
1209
+ resourceType: string;
1210
+ /** Function to extract resource ID from method arguments */
1211
+ resourceIdExtractor?: (args: any[]) => string | undefined;
1212
+ /** Function to extract operation data from method arguments */
1213
+ dataExtractor?: (args: any[]) => any;
1214
+ /** Component name for context */
1215
+ component?: string;
1216
+ }
1217
+ /**
1218
+ * Decorator options for UI action auditing
1219
+ */
1220
+ interface LogUIActionOptions {
1221
+ /** Component name */
1222
+ component: string;
1223
+ /** Action name - if not provided, method name will be used */
1224
+ action?: string;
1225
+ /** Function to extract UI data from method arguments */
1226
+ dataExtractor?: (args: any[]) => any;
1227
+ }
1228
+
1229
+ interface StorageFile {
1230
+ name: string;
1231
+ path: string;
1232
+ size: number;
1233
+ contentType: string;
1234
+ lastModified: Date;
1235
+ downloadUrl?: string;
1236
+ }
1237
+ interface StorageUploadProgress {
1238
+ bytesTransferred: number;
1239
+ totalBytes: number;
1240
+ progress: number;
1241
+ state: 'running' | 'paused' | 'success' | 'canceled' | 'error';
1242
+ }
1243
+ interface StorageUploadOptions {
1244
+ contentType?: string;
1245
+ metadata?: Record<string, string>;
1246
+ onProgress?: (progress: StorageUploadProgress) => void;
1247
+ }
1248
+ interface StorageListOptions {
1249
+ maxResults?: number;
1250
+ pageToken?: string;
1251
+ prefix?: string;
1252
+ }
1253
+ interface StorageListResult {
1254
+ items: StorageFile[];
1255
+ nextPageToken?: string;
1256
+ prefixes: string[];
1257
+ }
1258
+ interface StorageDeleteOptions {
1259
+ recursive?: boolean;
1260
+ }
1261
+ type StorageError = {
1262
+ code: string;
1263
+ message: string;
1264
+ serverResponse?: unknown;
1265
+ };
1266
+
1267
+ declare abstract class StorageEngine {
1268
+ /**
1269
+ * Upload a file to storage
1270
+ */
1271
+ abstract upload(path: string, file: File | Blob, options?: StorageUploadOptions): Observable<StorageFile>;
1272
+ /**
1273
+ * Download a file as blob
1274
+ */
1275
+ abstract download(path: string): Observable<Blob>;
1276
+ /**
1277
+ * Get download URL for a file
1278
+ */
1279
+ abstract getDownloadUrl(path: string): Observable<string>;
1280
+ /**
1281
+ * Get file metadata
1282
+ */
1283
+ abstract getMetadata(path: string): Observable<StorageFile>;
1284
+ /**
1285
+ * List files in a directory
1286
+ */
1287
+ abstract list(path: string, options?: StorageListOptions): Observable<StorageListResult>;
1288
+ /**
1289
+ * Delete a file or directory
1290
+ */
1291
+ abstract delete(path: string, options?: StorageDeleteOptions): Observable<void>;
1292
+ /**
1293
+ * Check if file exists
1294
+ */
1295
+ abstract exists(path: string): Observable<boolean>;
1296
+ /**
1297
+ * Copy a file
1298
+ */
1299
+ abstract copy(sourcePath: string, destinationPath: string): Observable<StorageFile>;
1300
+ /**
1301
+ * Move a file
1302
+ */
1303
+ abstract move(sourcePath: string, destinationPath: string): Observable<StorageFile>;
1304
+ }
1305
+
1306
+ type RuleTarget = {
1307
+ kind: 'DocRef';
1308
+ path: string;
1309
+ } | {
1310
+ kind: 'TypedId';
1311
+ type: string;
1312
+ id: string;
1313
+ } | {
1314
+ kind: 'Composite';
1315
+ parts: Array<RuleTarget>;
1316
+ };
1317
+ interface RuleEffectBase {
1318
+ type: string;
1319
+ payload?: unknown;
1320
+ }
1321
+ interface TimeAsDateRange {
1322
+ from: Date;
1323
+ to: Date;
1324
+ }
1325
+ interface TimeAsString {
1326
+ from: string;
1327
+ to: string;
1328
+ }
1329
+ interface RuleWhen {
1330
+ time?: TimeAsString | TimeAsDateRange;
1331
+ conditions?: RuleCondition[];
1332
+ }
1333
+ interface Rule<RT extends RuleTarget = RuleTarget, W extends RuleWhen = RuleWhen, E extends RuleEffectBase = RuleEffectBase> {
1334
+ description: I18nText;
1335
+ enabled: boolean;
1336
+ entityId: string;
1337
+ name: I18nText;
1338
+ priority: number;
1339
+ tags?: string[];
1340
+ target: RT;
1341
+ when: W;
1342
+ effect: E;
1343
+ }
1344
+ /**
1345
+ * Condition for when a rule should be evaluated
1346
+ */
1347
+ interface RuleCondition {
1348
+ field: string;
1349
+ operator: 'eq' | 'neq' | 'in' | 'gte' | 'lte' | 'gt' | 'lt';
1350
+ value: unknown;
1351
+ }
1352
+ /**
1353
+ * Context for rule evaluation
1354
+ * Contains all information needed to evaluate rules
1355
+ */
1356
+ interface RuleEvaluationContext<T = unknown> {
1357
+ startDate?: Date;
1358
+ endDate?: Date;
1359
+ entityId: string;
1360
+ entityType: string;
1361
+ additionalContext?: T;
1362
+ }
1363
+ /**
1364
+ * Result of rule evaluation
1365
+ */
1366
+ interface RuleEvaluationResult<TResult = unknown> {
1367
+ appliedRules: Rule[];
1368
+ result: TResult;
1369
+ conflicts: RuleConflict[];
1370
+ }
1371
+ /**
1372
+ * Conflict between rules
1373
+ */
1374
+ interface RuleConflict {
1375
+ rule1: Rule;
1376
+ rule2: Rule;
1377
+ conflictType: string;
1378
+ message: string;
1379
+ }
1380
+ /**
1381
+ * Validation error for rules
1382
+ */
1383
+ interface RuleValidationError {
1384
+ ruleId: string;
1385
+ field: string;
1386
+ message: string;
1387
+ conflictingRuleId?: string;
1388
+ }
1389
+ /**
1390
+ * Validation result
1391
+ */
1392
+ interface RuleValidationResult {
1393
+ valid: boolean;
1394
+ errors: RuleValidationError[];
1395
+ }
1396
+
1397
+ /**
1398
+ * Workflow Type Definitions
1399
+ *
1400
+ * These are the core workflow types used by entities that participate in workflows.
1401
+ * The actual workflow engine and services are in the 'workflow' library.
1402
+ */
1403
+
1404
+ type WorkflowId = string;
1405
+ type StateId = string;
1406
+ type TransitionId = string;
1407
+ /**
1408
+ * Workflow summary stored in the parent entity (e.g., BookingEntity).
1409
+ * Contains only the current state and metadata for efficient queries.
1410
+ * The full history is stored in the workflow_history subcollection.
1411
+ */
1412
+ interface WorkflowSummary {
1413
+ workflowDefinitionId: WorkflowId;
1414
+ currentState: StateId;
1415
+ initialState: StateId;
1416
+ stateCount: number;
1417
+ lastTransitionAt: string;
1418
+ lastTransitionBy: string;
1419
+ }
1420
+ /**
1421
+ * Interface for entities that can participate in workflows.
1422
+ * Extend your entity with this interface to make it workflowable.
1423
+ *
1424
+ * @example
1425
+ * ```typescript
1426
+ * interface BookingEntity extends Entity, Workflowable {
1427
+ * // ... booking fields
1428
+ * }
1429
+ * ```
1430
+ */
1431
+ interface Workflowable {
1432
+ workflow?: WorkflowSummary;
1433
+ }
1434
+ /**
1435
+ * Type helper for entities that require workflow to be present.
1436
+ */
1437
+ type WithWorkflow<T extends Workflowable> = T & {
1438
+ workflow: WorkflowSummary;
1439
+ };
1440
+ /**
1441
+ * Core data fields for a workflow history entry (without Entity base fields).
1442
+ */
1443
+ interface WorkflowHistoryEntryData {
1444
+ bookingId: string;
1445
+ sequence: number;
1446
+ from: StateId;
1447
+ to: StateId;
1448
+ transitionId: TransitionId;
1449
+ changedBy: string;
1450
+ changedAt: string;
1451
+ comment?: string;
1452
+ payload?: unknown;
1453
+ }
1454
+ declare const WORKFLOW_HISTORY_FEATURE_KEY = "workflow_history";
1455
+ /**
1456
+ * Workflow history entry entity stored in the subcollection.
1457
+ * Extends Entity to include uid and meta for Firestore compatibility.
1458
+ */
1459
+ interface WorkflowHistoryEntry extends Entity, WorkflowHistoryEntryData {
1460
+ }
1461
+ /**
1462
+ * Type for adding a new workflow history entry.
1463
+ * uid is auto-generated, meta is provided by the caller.
1464
+ */
1465
+ type WorkflowHistoryEntryAdd = EntityAdd & WorkflowHistoryEntryData;
1466
+ /**
1467
+ * Type for updating workflow history entries.
1468
+ * NOTE: Updates are NOT allowed - this type exists only for type system compatibility.
1469
+ */
1470
+ type WorkflowHistoryEntryUpdate = EntityUpdate & Partial<WorkflowHistoryEntryData>;
1471
+ /**
1472
+ * Model types for Firestore storage.
1473
+ */
1474
+ type WorkflowHistoryModel = WorkflowHistoryEntry;
1475
+ type WorkflowHistoryModelAdd = WorkflowHistoryEntryAdd;
1476
+
1477
+ /**
1478
+ * Abstract WorkflowEngine - defines the contract for workflow operations
1479
+ *
1480
+ * Implementations should handle:
1481
+ * - Transition execution with guards and actions
1482
+ * - Permission and role checking
1483
+ * - Workflow history management
1484
+ */
1485
+
1486
+ /**
1487
+ * Current user context for workflow operations
1488
+ */
1489
+ interface WorkflowCurrentUser {
1490
+ id: string;
1491
+ roles: string[];
1492
+ permissions: string[];
1493
+ }
1494
+ /**
1495
+ * Result of checking if a transition can be executed
1496
+ */
1497
+ interface CanExecuteTransitionResult {
1498
+ allowed: boolean;
1499
+ reason?: string;
1500
+ failedCheck?: 'state' | 'permission' | 'role' | 'guard';
1501
+ }
1502
+ /**
1503
+ * Result of bulk transition execution
1504
+ */
1505
+ interface BulkTransitionResult<T extends Workflowable> {
1506
+ succeeded: WithWorkflow<T>[];
1507
+ failed: Array<{
1508
+ entity: WithWorkflow<T>;
1509
+ error: string;
1510
+ }>;
1511
+ stats: {
1512
+ total: number;
1513
+ succeeded: number;
1514
+ failed: number;
1515
+ };
1516
+ }
1517
+ /**
1518
+ * Workflow state definition
1519
+ */
1520
+ interface WorkflowState {
1521
+ id: string;
1522
+ label: string;
1523
+ description?: string;
1524
+ isInitial?: boolean;
1525
+ isFinal?: boolean;
1526
+ color?: string;
1527
+ icon?: string;
1528
+ requiredFields?: string[];
1529
+ editableFields?: string[];
1530
+ readonlyFields?: string[];
1531
+ }
1532
+ /**
1533
+ * Workflow transition context passed to guards and actions
1534
+ */
1535
+ interface WorkflowTransitionContext<T = unknown> {
1536
+ entity: T;
1537
+ currentUserId: string;
1538
+ currentUserRoles: string[];
1539
+ currentUserPermissions: string[];
1540
+ payload?: unknown;
1541
+ }
1542
+ /**
1543
+ * Guard function type - returns true if transition is allowed
1544
+ */
1545
+ type WorkflowGuardFn<T = unknown> = (ctx: WorkflowTransitionContext<T>) => boolean | Promise<boolean>;
1546
+ /**
1547
+ * Action function type - executed after successful transition
1548
+ */
1549
+ type WorkflowActionFn<T = unknown> = (ctx: WorkflowTransitionContext<T>) => void | Promise<void>;
1550
+ /**
1551
+ * Workflow transition definition
1552
+ */
1553
+ interface WorkflowTransition<T = unknown> {
1554
+ id: string;
1555
+ from: string;
1556
+ to: string;
1557
+ label: string;
1558
+ description?: string;
1559
+ requiredPermissions?: string[];
1560
+ requiredRoles?: string[];
1561
+ guards?: WorkflowGuardFn<T>[];
1562
+ actions?: WorkflowActionFn<T>[];
1563
+ icon?: string;
1564
+ severity?: 'primary' | 'secondary' | 'success' | 'info' | 'warn' | 'danger' | 'help';
1565
+ }
1566
+ /**
1567
+ * Complete workflow definition
1568
+ */
1569
+ interface WorkflowDefinition<T = unknown> {
1570
+ id: string;
1571
+ entityType: string;
1572
+ label: string;
1573
+ description?: string;
1574
+ states: WorkflowState[];
1575
+ transitions: WorkflowTransition<T>[];
1576
+ }
1577
+ /**
1578
+ * Result of executing a transition - contains updated entity and history entry
1579
+ */
1580
+ interface TransitionExecutionResult<T extends Workflowable> {
1581
+ entity: WithWorkflow<T>;
1582
+ historyEntry: WorkflowHistoryEntryData;
1583
+ }
1584
+ /**
1585
+ * Abstract WorkflowEngine class
1586
+ *
1587
+ * Defines the contract for workflow operations.
1588
+ * Implementations should be provided via dependency injection.
1589
+ *
1590
+ * @typeParam T - The entity type that extends Workflowable
1591
+ */
1592
+ declare abstract class WorkflowEngine<T extends Workflowable> {
1593
+ /**
1594
+ * Check if a transition can be executed
1595
+ */
1596
+ abstract canExecuteTransition(definition: WorkflowDefinition<T>, transitionId: TransitionId, entity: WithWorkflow<T>, currentUser: WorkflowCurrentUser): CanExecuteTransitionResult;
1597
+ /**
1598
+ * Execute a workflow transition
1599
+ * Returns both the updated entity and the history entry to be persisted
1600
+ */
1601
+ abstract executeTransition(definition: WorkflowDefinition<T>, transitionId: TransitionId, entity: WithWorkflow<T>, currentUser: WorkflowCurrentUser, payload?: unknown, comment?: string): Promise<TransitionExecutionResult<T>>;
1602
+ /**
1603
+ * Execute transition on multiple entities
1604
+ */
1605
+ abstract executeBulkTransition(definition: WorkflowDefinition<T>, transitionId: TransitionId, entities: WithWorkflow<T>[], currentUser: WorkflowCurrentUser, payload?: unknown): Promise<BulkTransitionResult<T>>;
1606
+ /**
1607
+ * Get available transitions from the current state
1608
+ */
1609
+ abstract getAvailableTransitions(definition: WorkflowDefinition<T>, entity: WithWorkflow<T>, currentUser: WorkflowCurrentUser): WorkflowTransition<T>[];
1610
+ /**
1611
+ * Get the current state definition for an entity
1612
+ */
1613
+ abstract getCurrentState(definition: WorkflowDefinition<T>, entity: WithWorkflow<T>): WorkflowState | undefined;
1614
+ /**
1615
+ * Get a state definition by ID
1616
+ */
1617
+ abstract getState(definition: WorkflowDefinition<T>, stateId: StateId): WorkflowState | undefined;
1618
+ /**
1619
+ * Get the initial state for a workflow
1620
+ */
1621
+ abstract getInitialState(definition: WorkflowDefinition<T>): WorkflowState | undefined;
1622
+ /**
1623
+ * Create initial workflow summary for a new entity
1624
+ */
1625
+ abstract createInitialSummary(definition: WorkflowDefinition<T>, userId: string): WorkflowSummary;
1626
+ /**
1627
+ * Check if entity is in a final state
1628
+ */
1629
+ abstract isFinalState(definition: WorkflowDefinition<T>, entity: WithWorkflow<T>): boolean;
1630
+ }
1631
+
1632
+ export { APP_BOOTSTRAP_CONFIG, AUDIT_FEATURE_KEY, AUTHENTICATION_STORE_SERVICE_TOKEN, AUTHENTICATION_STORE_VIEW_TOKEN, AuditService, AuthenticationService, AuthenticationStoreService, CLOUD_SERVICE_TOKEN, CloudService, DEFAULT_APP_BOOTSTRAP_CONFIG, DEFAULT_FIREBASE_AUTH_CONFIG, DEFAULT_FIREBASE_CONFIG, DEFAULT_LANGUAGE_TOKEN, DEFAULT_NOTIFICATION_CONFIG, DOCUMENTS_KEYS, DateTimePipeBase, DateUtil, EMAIL_CONFIG, EmailService, EntityAdapter, EntityEffect, EntityFormLogic, EntityRepository, ErrorType, ErrorUtilService, FIREBASE_AUTH_CONFIG, FIREBASE_CONFIG, FIRESTORE_ENGINE_CREATOR, I18nService, I18nUtil, KError, LANGUAGES_TOKEN, LOGGER_ENVIRONMENT, LanguagesEnum, Logger, NOTIFICATION_CONFIG_TOKEN, Repository, RepositoryEngine, StorageEngine, WORKFLOW_HISTORY_FEATURE_KEY, WorkflowEngine, allIcons, customSvgIcons, initialAuthState, materialIcons, primeIcon, provideAppBootstrapConfig, provideFirebaseAuthConfig, provideNotificationConfig };
1633
+ export type { AppBootstrapConfig, Audit, AuditAction, AuditEntity, AuditEntityAdd, AuditEntityUpdate, AuditLog, AuditLogQuery, AuditLogStats, AuditMetadata, AuditModel, AuditModelAdd, AuditModelUpdate, AuditResource, AuditResult, AuthCredentials, AuthErrorCode, AuthMethod, AuthProvider, AuthResult, AuthState, AuthUser, AuthenticationStoreView, AuthorizationContext, AuthorizationOptions, BatchOperation, BootstrapStatusResult, BulkTransitionResult, CanExecuteTransitionResult, CloudFunctionResult, CollectionPathBuilder, CreateUserAndSendPasswordResetResult, CreateUserData, CreateUserRequest, CreateUserResponse, CustomEntityState, EmailConfig, EmailPasswordCredentials, Entity, EntityActions, EntityAdd, EntityCollectionStoreView, EntityConfig, EntityFormStoreView, EntityHelper, EntityModel, EntityModelAdd, EntityModelUpdate, EntitySignals, EntityStore, EntityStoreView, EntityTableResourceStoreView, EntityTableStoreView, EntityType, EntityUpdate, ErrorOptions, FirebaseAuthConfig, FirebaseConfig, HashMapModel, I18nConfig, I18nText, Icon, IconType, LoaderData, Localizable, LogDataOperationOptions, LogEntry, LogLevel, LogMethodOptions, LogUIActionOptions, LogUserActionOptions, LoggerConfig, LoggerEnvironmentConfig, NotificationConfig, Permission, RepositoryEngineCreator, Role, Rule, RuleCondition, RuleConflict, RuleEffectBase, RuleEvaluationContext, RuleEvaluationResult, RuleTarget, RuleValidationError, RuleValidationResult, RuleWhen, RxEntityActions, SendPasswordResetEmailData, SessionConfig, StateId, StorageDeleteOptions, StorageError, StorageFile, StorageListOptions, StorageListResult, StorageUploadOptions, StorageUploadProgress, SubcollectionContext, TimeAsDateRange, TimeAsString, TransitionExecutionResult, TransitionId, UserConfig, UserRegistrationData, WelcomeEmailData, WelcomeEmailDataWithConfig, WithWorkflow, WorkflowActionFn, WorkflowCurrentUser, WorkflowDefinition, WorkflowGuardFn, WorkflowHistoryEntry, WorkflowHistoryEntryAdd, WorkflowHistoryEntryData, WorkflowHistoryEntryUpdate, WorkflowHistoryModel, WorkflowHistoryModelAdd, WorkflowId, WorkflowState, WorkflowSummary, WorkflowTransition, WorkflowTransitionContext, Workflowable };