@molecule/app-angular 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,1792 @@
1
+ <!--
2
+ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
+ Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
+ Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
+ To change this document, edit the module-level JSDoc in src/index.ts.
6
+ Generated: 2026-09-15T19:11:41.538Z
7
+ -->
8
+
9
+ # @molecule/app-angular
10
+
11
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
12
+ > It is written to be read by coding agents as much as by people, and is generated from this
13
+ > package's source — edit `src/index.ts` JSDoc, not this file.
14
+
15
+ Angular framework bindings for molecule.dev.
16
+
17
+ Provides Angular-specific services and providers for all molecule
18
+ core interfaces. This package enables the use of molecule's framework-agnostic
19
+ interfaces with Angular's idioms (services, DI, RxJS observables, etc.).
20
+
21
+ ## Quick Start
22
+
23
+ ```typescript
24
+ // main.ts — wire concrete providers into Angular DI:
25
+ import { bootstrapApplication } from '@angular/platform-browser'
26
+ import { provideMolecule } from '@molecule/app-angular'
27
+ import { createJWTAuthClient } from '@molecule/app-auth'
28
+ import { provider as stateProvider } from '@molecule/app-state-zustand'
29
+ import { provider as themeProvider } from '@molecule/app-theme-css-variables'
30
+
31
+ const authClient = createJWTAuthClient({ baseURL: '/api' })
32
+
33
+ bootstrapApplication(AppComponent, {
34
+ providers: [
35
+ provideMolecule({
36
+ state: stateProvider,
37
+ auth: authClient,
38
+ theme: themeProvider,
39
+ }),
40
+ ],
41
+ })
42
+
43
+ // dashboard.component.ts — inject the Molecule services:
44
+ import { Component, inject } from '@angular/core'
45
+ import { MoleculeAuthService, MoleculeThemeService, t } from '@molecule/app-angular'
46
+
47
+ @Component({
48
+ selector: 'app-dashboard',
49
+ template: `
50
+ <div [style.background]="(theme$ | async)?.colors.background">
51
+ <h1>{{ t('dashboard.welcome', {}, { defaultValue: 'Welcome!' }) }}</h1>
52
+ <p>{{ (user$ | async)?.name }}</p>
53
+ <button (click)="logout()">
54
+ {{ t('auth.logout', {}, { defaultValue: 'Log out' }) }}
55
+ </button>
56
+ </div>
57
+ `,
58
+ })
59
+ class DashboardComponent {
60
+ // Expose the reactive t() so template bindings re-evaluate on locale change.
61
+ protected readonly t = t
62
+
63
+ private authService = inject(MoleculeAuthService)
64
+ private themeService = inject(MoleculeThemeService)
65
+
66
+ user$ = this.authService.user$ // Observable<UserProfile | null>
67
+ theme$ = this.themeService.theme$ // Observable<Theme>
68
+
69
+ logout(): void {
70
+ void this.authService.logout()
71
+ }
72
+ }
73
+ ```
74
+
75
+ ## Type
76
+
77
+ `framework`
78
+
79
+ ## Installation
80
+
81
+ ```bash
82
+ npm install @molecule/app-angular @angular/core @molecule/app-auth @molecule/app-device @molecule/app-forms @molecule/app-http @molecule/app-i18n @molecule/app-logger @molecule/app-platform @molecule/app-push @molecule/app-routing @molecule/app-state @molecule/app-storage @molecule/app-theme @molecule/app-ui @molecule/app-utilities @molecule/app-version rxjs
83
+ ```
84
+
85
+ ## API
86
+
87
+ ### Interfaces
88
+
89
+ #### `AsyncStateManager`
90
+
91
+ Async state manager.
92
+
93
+ ```typescript
94
+ interface AsyncStateManager<T> {
95
+ state$: Observable<T>
96
+ getState: () => T
97
+ setState: (value: T | ((prev: T) => T) | Promise<T | ((prev: T) => T)>) => void
98
+ extendState: (
99
+ partial:
100
+ Partial<T> | ((prev: T) => Partial<T>) | Promise<Partial<T> | ((prev: T) => Partial<T>)>,
101
+ ) => void
102
+ destroy: () => void
103
+ }
104
+ ```
105
+
106
+ #### `AuthClient`
107
+
108
+ Auth client interface that all auth bond packages must implement.
109
+ Provides login/logout/register flows, token management, profile
110
+ updates, and auth state subscription.
111
+
112
+ ```typescript
113
+ interface AuthClient<T = UserProfile> {
114
+ /**
115
+ * Returns the current authentication state snapshot.
116
+ */
117
+ getState(): AuthState<T>
118
+ /**
119
+ * Returns whether the user is currently authenticated.
120
+ */
121
+ isAuthenticated(): boolean
122
+ /**
123
+ * Gets the current user.
124
+ */
125
+ getUser(): T | null
126
+ /**
127
+ * Updates the cached user object (state + persistent storage) without
128
+ * hitting the network. Intended for local refreshes after a per-app
129
+ * mutation (e.g., the user just PATCHed their own profile and the
130
+ * server returned the canonical row). Does NOT change tokens.
131
+ */
132
+ setUser(user: T | null): void
133
+ /**
134
+ * Gets the current access token.
135
+ */
136
+ getAccessToken(): string | null
137
+ /**
138
+ * Stores the access token in the configured token storage adapter (in-memory
139
+ * by default). Use this to seed the token after an out-of-band exchange (e.g.
140
+ * the OAuth code→token redirect) instead of writing to `localStorage` directly,
141
+ * which would violate the in-memory-default storage contract and make the bearer
142
+ * token JS-readable (XSS-exfiltratable). Pass `null` to clear it.
143
+ */
144
+ setAccessToken(token: string | null): void
145
+ /**
146
+ * Gets the refresh token.
147
+ */
148
+ getRefreshToken(): string | null
149
+ /**
150
+ * Logs in with credentials.
151
+ */
152
+ login(credentials: LoginCredentials): Promise<AuthResult<T>>
153
+ /**
154
+ * Logs out the current user.
155
+ */
156
+ logout(): Promise<void>
157
+ /**
158
+ * Registers a new user.
159
+ */
160
+ register(data: RegisterData): Promise<AuthResult<T>>
161
+ /**
162
+ * Refreshes the access token.
163
+ */
164
+ refresh(): Promise<AuthResult<T>>
165
+ /**
166
+ * Requests a password reset.
167
+ */
168
+ requestPasswordReset(data: PasswordResetRequest): Promise<void>
169
+ /**
170
+ * Confirms a password reset.
171
+ */
172
+ confirmPasswordReset(data: PasswordResetConfirm): Promise<void>
173
+ /**
174
+ * Updates the current user's profile.
175
+ */
176
+ updateProfile(data: Partial<T>): Promise<T>
177
+ /**
178
+ * Changes the current user's password.
179
+ */
180
+ changePassword(oldPassword: string, newPassword: string): Promise<void>
181
+ /**
182
+ * Initializes auth state (e.g., from stored tokens).
183
+ */
184
+ initialize(): Promise<void>
185
+ /**
186
+ * Subscribes to auth state changes.
187
+ */
188
+ subscribe(callback: (state: AuthState<T>) => void): () => void
189
+ /**
190
+ * Subscribes to auth state changes (alias for subscribe).
191
+ */
192
+ onAuthChange(callback: (state: AuthState<T>) => void): () => void
193
+ /**
194
+ * Gets the current access token (alias for getAccessToken).
195
+ */
196
+ getToken?(): string | null
197
+ /**
198
+ * Adds an auth event listener.
199
+ */
200
+ addEventListener(listener: AuthEventListener): () => void
201
+ /**
202
+ * Destroys the auth client.
203
+ */
204
+ destroy(): void
205
+ }
206
+ ```
207
+
208
+ #### `AuthState`
209
+
210
+ Reactive authentication state snapshot (initialized, authenticated, user, loading, and error).
211
+
212
+ ```typescript
213
+ interface AuthState<T = UserProfile> {
214
+ /**
215
+ * Whether auth state has been initialized.
216
+ */
217
+ initialized: boolean
218
+ /**
219
+ * Whether the user is authenticated.
220
+ */
221
+ authenticated: boolean
222
+ /**
223
+ * Current user (if authenticated).
224
+ */
225
+ user: T | null
226
+ /**
227
+ * Whether an auth operation is in progress.
228
+ */
229
+ loading: boolean
230
+ /**
231
+ * Last auth error (if any).
232
+ */
233
+ error: string | null
234
+ }
235
+ ```
236
+
237
+ #### `CapacitorAppManager`
238
+
239
+ Capacitor app manager interface.
240
+
241
+ ```typescript
242
+ interface CapacitorAppManager {
243
+ state$: Observable<CapacitorAppState>
244
+ ready$: Observable<boolean>
245
+ initialize: () => Promise<void>
246
+ destroy: () => void
247
+ }
248
+ ```
249
+
250
+ #### `ChangePasswordStateManager`
251
+
252
+ Change password state manager.
253
+
254
+ ```typescript
255
+ interface ChangePasswordStateManager {
256
+ state$: Observable<PromiseState<void>>
257
+ getState: () => PromiseState<void>
258
+ changePassword: (oldPassword: string, newPassword: string) => Promise<void>
259
+ reset: () => void
260
+ destroy: () => void
261
+ }
262
+ ```
263
+
264
+ #### `DeviceService`
265
+
266
+ Device service interface.
267
+
268
+ ```typescript
269
+ interface DeviceService {
270
+ deviceInfo: DeviceInfo
271
+ screenInfo: ScreenInfo
272
+ hardwareInfo: HardwareInfo
273
+ featureSupport: FeatureSupport
274
+ supports: (feature: keyof FeatureSupport) => boolean
275
+ isOnline: () => boolean
276
+ isStandalone: () => boolean
277
+ language: string
278
+ languages: string[]
279
+ }
280
+ ```
281
+
282
+ #### `FormController`
283
+
284
+ Form controller interface.
285
+
286
+ All form providers must implement this interface.
287
+
288
+ ```typescript
289
+ interface FormController<T extends Record<string, unknown> = Record<string, unknown>> {
290
+ /**
291
+ * Gets the current form state.
292
+ */
293
+ getState(): FormState<T>
294
+ /**
295
+ * Gets the value of a specific field.
296
+ */
297
+ getValue(name: string): unknown
298
+ getValue<K extends keyof T>(name: K): T[K]
299
+ /**
300
+ * Gets all form values.
301
+ */
302
+ getValues(): T
303
+ /**
304
+ * Sets the value of a specific field.
305
+ */
306
+ setValue(
307
+ name: string,
308
+ value: unknown,
309
+ options?: {
310
+ shouldValidate?: boolean
311
+ shouldDirty?: boolean
312
+ shouldTouch?: boolean
313
+ },
314
+ ): void
315
+ /**
316
+ * Sets multiple values at once.
317
+ */
318
+ setValues(
319
+ values: Partial<T>,
320
+ options?: {
321
+ shouldValidate?: boolean
322
+ },
323
+ ): void
324
+ /**
325
+ * Gets the error for a specific field.
326
+ */
327
+ getError(name: string): string | undefined
328
+ /**
329
+ * Sets the error for a specific field.
330
+ */
331
+ setError(name: string, error: string | undefined): void
332
+ /**
333
+ * Clears the error for a specific field.
334
+ */
335
+ clearError<K extends keyof T>(name: K): void
336
+ /**
337
+ * Clears all errors.
338
+ */
339
+ clearErrors(): void
340
+ /**
341
+ * Gets the field state for a specific field.
342
+ */
343
+ getFieldState<K extends keyof T>(name: K): FieldState<T[K]>
344
+ /**
345
+ * Registers a field for form management.
346
+ */
347
+ register(nameOrOptions: string | RegisterOptions, options?: RegisterOptions): FieldRegistration
348
+ /**
349
+ * Unregisters a field.
350
+ */
351
+ unregister(name: string): void
352
+ /**
353
+ * Validates a specific field.
354
+ */
355
+ validateField<K extends keyof T>(name: K): Promise<boolean>
356
+ /**
357
+ * Validates all fields.
358
+ */
359
+ validate(): Promise<boolean>
360
+ /**
361
+ * Resets the form to initial values.
362
+ */
363
+ reset(values?: Partial<T>): void
364
+ /**
365
+ * Handles form submission.
366
+ */
367
+ handleSubmit(
368
+ onSubmit: (values: T) => void | Promise<void>,
369
+ onError?: (errors: Partial<Record<keyof T, string>>) => void,
370
+ ): (event?: { preventDefault?: () => void }) => Promise<void>
371
+ /**
372
+ * Sets focus to a field.
373
+ */
374
+ setFocus(name: keyof T): void
375
+ /**
376
+ * Subscribes to form state changes.
377
+ */
378
+ subscribe(callback: (state: FormState<T>) => void): () => void
379
+ /**
380
+ * Destroys the form controller.
381
+ */
382
+ destroy(): void
383
+ }
384
+ ```
385
+
386
+ #### `FormOptions`
387
+
388
+ Form creation options.
389
+
390
+ ```typescript
391
+ interface FormOptions<T extends Record<string, unknown>> {
392
+ /**
393
+ * Default values.
394
+ */
395
+ defaultValues?: Partial<T>
396
+ /**
397
+ * Validation mode.
398
+ */
399
+ mode?: 'onSubmit' | 'onChange' | 'onBlur' | 'all'
400
+ /**
401
+ * Revalidation mode.
402
+ */
403
+ reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit'
404
+ /**
405
+ * Whether to focus the first error field on submit.
406
+ */
407
+ shouldFocusError?: boolean
408
+ /**
409
+ * Form-level validation function.
410
+ */
411
+ validate?: (
412
+ values: T,
413
+ ) => Partial<Record<keyof T, string>> | Promise<Partial<Record<keyof T, string>>>
414
+ }
415
+ ```
416
+
417
+ #### `HttpClient`
418
+
419
+ HTTP client interface.
420
+
421
+ All HTTP providers must implement this interface.
422
+
423
+ ```typescript
424
+ interface HttpClient {
425
+ /**
426
+ * Base URL for all requests.
427
+ */
428
+ baseURL: string
429
+ /**
430
+ * Default headers for all requests.
431
+ */
432
+ defaultHeaders: Record<string, string>
433
+ /**
434
+ * Makes a generic HTTP request.
435
+ */
436
+ request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
437
+ /**
438
+ * Makes a GET request.
439
+ */
440
+ get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
441
+ /**
442
+ * Makes a POST request.
443
+ */
444
+ post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
445
+ /**
446
+ * Makes a PUT request.
447
+ */
448
+ put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
449
+ /**
450
+ * Makes a PATCH request.
451
+ */
452
+ patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
453
+ /**
454
+ * Makes a DELETE request.
455
+ */
456
+ delete<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
457
+ /**
458
+ * Adds a request interceptor.
459
+ * Returns a function to remove the interceptor.
460
+ */
461
+ addRequestInterceptor(interceptor: RequestInterceptor): () => void
462
+ /**
463
+ * Adds a response interceptor.
464
+ * Returns a function to remove the interceptor.
465
+ */
466
+ addResponseInterceptor(interceptor: ResponseInterceptor): () => void
467
+ /**
468
+ * Adds an error interceptor.
469
+ * Returns a function to remove the interceptor.
470
+ */
471
+ addErrorInterceptor(interceptor: ErrorInterceptor): () => void
472
+ /**
473
+ * Sets the authorization token.
474
+ */
475
+ setAuthToken(token: string | null): void
476
+ /**
477
+ * Returns the current authorization token, or `null` if not set.
478
+ */
479
+ getAuthToken(): string | null
480
+ /**
481
+ * Registers a handler for authentication errors (401).
482
+ *
483
+ * @returns An unsubscribe function.
484
+ */
485
+ onAuthError(handler: () => void): () => void
486
+ }
487
+ ```
488
+
489
+ #### `HttpState`
490
+
491
+ State for HTTP requests.
492
+
493
+ ```typescript
494
+ interface HttpState<T> {
495
+ data: T | null
496
+ loading: boolean
497
+ error: Error | null
498
+ }
499
+ ```
500
+
501
+ #### `I18nProvider`
502
+
503
+ i18n provider interface.
504
+
505
+ All i18n providers must implement this interface.
506
+
507
+ ```typescript
508
+ interface I18nProvider {
509
+ /**
510
+ * Gets the current locale.
511
+ */
512
+ getLocale(): string
513
+ /**
514
+ * Sets the current locale.
515
+ *
516
+ * **Fleet contract:** every conformant provider (the core simple provider,
517
+ * `@molecule/api-i18n-simple`, `@molecule/app-i18n-i18next`, and
518
+ * `@molecule/app-i18n-react-i18next`) MUST throw `Error('Locale "<code>"
519
+ * not found')` when `locale` is not registered — via the constructor's
520
+ * `initialLocales`/`locales` config, `addLocale()`, or `addTranslations()`
521
+ * (all three register a locale). It must NOT silently degrade to
522
+ * fallback-locale text while `getLocale()` reports the unregistered code —
523
+ * that divergence makes a misconfigured locale switch indistinguishable
524
+ * from a working one until a user notices the wrong language on screen.
525
+ */
526
+ setLocale(locale: string): Promise<void>
527
+ /**
528
+ * Gets all available locales.
529
+ */
530
+ getLocales(): LocaleConfig[]
531
+ /**
532
+ * Adds a locale.
533
+ */
534
+ addLocale(config: LocaleConfig): void
535
+ /**
536
+ * Removes a locale by code, notifying subscribers so language pickers
537
+ * built on `onLocaleChange` re-render their list. If the removed locale
538
+ * is currently active, the caller is responsible for switching to a
539
+ * fallback (e.g. `'en'`) BEFORE calling this — the provider will not
540
+ * auto-fall-back on its own.
541
+ *
542
+ * Returns `true` if the locale was registered and removed, `false`
543
+ * otherwise.
544
+ */
545
+ removeLocale(code: string): boolean
546
+ /**
547
+ * Adds translations to a locale. Auto-creates the locale if it doesn't exist.
548
+ *
549
+ * **Fleet contract:** merges are DEEP, not a shallow spread — registering
550
+ * two calls (e.g. two modules) that share a top-level namespace key merges
551
+ * their subtrees instead of the second call clobbering the first's nested
552
+ * translations wholesale. `@molecule/api-i18n-simple` implements the same
553
+ * contract on the API side.
554
+ */
555
+ addTranslations(locale: string, translations: Translations, namespace?: string): void
556
+ /**
557
+ * Translates a key with optional interpolation values and pluralization.
558
+ *
559
+ * **Fleet plural contract (matches i18next's own key resolution order):**
560
+ * when `options.count` is provided, the plural-suffixed key
561
+ * (`` `${key}_${pluralForm}` ``, e.g. `item_one`/`item_few`/…, falling back
562
+ * to `` `${key}_other` ``) is looked up FIRST and wins over the base `key`
563
+ * if BOTH are registered. Only when no plural-suffixed key exists at all
564
+ * does resolution fall back to the base key. A catalog that ships both
565
+ * `item` and `item_one`/`item_other` therefore pluralizes identically
566
+ * whichever provider is bonded.
567
+ *
568
+ * @returns The translated string, or the default value / key if not found.
569
+ */
570
+ t(
571
+ key: string,
572
+ values?: InterpolationValues,
573
+ options?: {
574
+ defaultValue?: string
575
+ count?: number
576
+ },
577
+ ): string
578
+ /**
579
+ * Checks if a translation key exists.
580
+ *
581
+ * **Fleet contract:** follows the SAME locale-resolution chain as `t()` —
582
+ * the active locale, then the English fallback — so `exists(key) === true`
583
+ * whenever `t(key)` would render real translated text (not the raw key or
584
+ * an inline `defaultValue`). Do not narrow this to "only the active
585
+ * locale's own catalog"; that made `exists()` return `false` for keys `t()`
586
+ * happily rendered via the English fallback, and the answer differed by
587
+ * provider.
588
+ *
589
+ * @returns `true` if the key has a translation.
590
+ */
591
+ exists(key: string): boolean
592
+ /**
593
+ * Formats a number according to the current locale.
594
+ *
595
+ * @returns The locale-formatted number string.
596
+ */
597
+ formatNumber(value: number, options?: NumberFormatOptions): string
598
+ /**
599
+ * Formats a date according to the current locale.
600
+ *
601
+ * @returns The locale-formatted date string.
602
+ */
603
+ formatDate(value: Date | number | string, options?: DateFormatOptions): string
604
+ /**
605
+ * Formats a relative time (e.g. "2 hours ago").
606
+ *
607
+ * @returns The locale-formatted relative time string.
608
+ */
609
+ formatRelativeTime(
610
+ value: Date | number,
611
+ options?: {
612
+ unit?: Intl.RelativeTimeFormatUnit
613
+ },
614
+ ): string
615
+ /**
616
+ * Formats a list (e.g. "A, B, and C").
617
+ *
618
+ * @returns The locale-formatted list string.
619
+ */
620
+ formatList(
621
+ values: string[],
622
+ options?: {
623
+ type?: 'conjunction' | 'disjunction' | 'unit'
624
+ },
625
+ ): string
626
+ /**
627
+ * Subscribes to locale changes.
628
+ *
629
+ * @returns An unsubscribe function.
630
+ */
631
+ onLocaleChange(listener: (locale: string) => void): () => void
632
+ /**
633
+ * Gets the text direction for the current locale.
634
+ *
635
+ * @returns `'ltr'` or `'rtl'`.
636
+ */
637
+ getDirection(): 'ltr' | 'rtl'
638
+ /**
639
+ * Checks if a translation key exists (alias for exists).
640
+ */
641
+ hasKey?(key: string): boolean
642
+ /**
643
+ * Checks if the provider is ready.
644
+ */
645
+ isReady?(): boolean
646
+ /**
647
+ * Registers a callback for when the provider is ready.
648
+ */
649
+ onReady?(callback: () => void): () => void
650
+ /**
651
+ * Registers a lazily-loaded content module for automatic reload on locale changes.
652
+ * All registered content is reloaded during `setLocale()` before listeners fire,
653
+ * ensuring content is available on the first re-render with no flash.
654
+ *
655
+ * Idempotent: registering the same module name twice is a no-op.
656
+ */
657
+ registerContent?(module: string, loader: (locale: string) => Promise<void>): void
658
+ }
659
+ ```
660
+
661
+ #### `Logger`
662
+
663
+ Logger instance with leveled logging methods, child logger creation,
664
+ and transport management.
665
+
666
+ ```typescript
667
+ interface Logger {
668
+ /**
669
+ * Logs a trace message.
670
+ */
671
+ trace(message: string, ...args: unknown[]): void
672
+ /**
673
+ * Logs a debug message.
674
+ */
675
+ debug(message: string, ...args: unknown[]): void
676
+ /**
677
+ * Logs an info message.
678
+ */
679
+ info(message: string, ...args: unknown[]): void
680
+ /**
681
+ * Logs a warning message.
682
+ */
683
+ warn(message: string, ...args: unknown[]): void
684
+ /**
685
+ * Logs an error message.
686
+ */
687
+ error(message: string | Error, ...args: unknown[]): void
688
+ /**
689
+ * Sets the log level.
690
+ */
691
+ setLevel(level: LogLevel): void
692
+ /**
693
+ * Gets the current log level.
694
+ */
695
+ getLevel(): LogLevel
696
+ /**
697
+ * Creates a child logger with a namespace.
698
+ */
699
+ child(name: string, context?: Record<string, unknown>): Logger
700
+ /**
701
+ * Adds additional context to the logger.
702
+ */
703
+ withContext(context: Record<string, unknown>): Logger
704
+ /**
705
+ * Adds a transport.
706
+ */
707
+ addTransport(transport: LogTransport): () => void
708
+ /**
709
+ * Removes a transport.
710
+ */
711
+ removeTransport(transport: LogTransport): void
712
+ }
713
+ ```
714
+
715
+ #### `LoggerProvider`
716
+
717
+ Logger provider interface that all logger bond packages must implement.
718
+ Creates and manages logger instances and global log configuration.
719
+
720
+ ```typescript
721
+ interface LoggerProvider {
722
+ /**
723
+ * Gets a logger by name, or the root logger if no name given.
724
+ */
725
+ getLogger(name?: string): Logger
726
+ /**
727
+ * Creates a named logger.
728
+ */
729
+ createLogger(nameOrConfig: string | LoggerConfig, config?: LoggerConfig): Logger
730
+ /**
731
+ * Sets the global log level.
732
+ */
733
+ setLevel(level: LogLevel): void
734
+ /**
735
+ * Gets the global log level.
736
+ */
737
+ getLevel(): LogLevel
738
+ /**
739
+ * Adds a global transport.
740
+ */
741
+ addTransport(transport: LogTransport): () => void
742
+ /**
743
+ * Enables logging.
744
+ */
745
+ enable(): void
746
+ /**
747
+ * Disables logging.
748
+ */
749
+ disable(): void
750
+ /**
751
+ * Checks if logging is enabled.
752
+ *
753
+ * @returns `true` if logging is currently enabled.
754
+ */
755
+ isEnabled(): boolean
756
+ }
757
+ ```
758
+
759
+ #### `LoginStateManager`
760
+
761
+ Login state manager.
762
+
763
+ ```typescript
764
+ interface LoginStateManager<T = unknown> {
765
+ state$: Observable<PromiseState<AuthResult<T>>>
766
+ getState: () => PromiseState<AuthResult<T>>
767
+ login: (credentials: LoginCredentials) => Promise<AuthResult<T>>
768
+ reset: () => void
769
+ destroy: () => void
770
+ }
771
+ ```
772
+
773
+ #### `MoleculeModuleConfig`
774
+
775
+ Configuration for molecule Angular module.
776
+
777
+ ```typescript
778
+ interface MoleculeModuleConfig {
779
+ state?: StateProvider
780
+ auth?: AuthClient<unknown>
781
+ theme?: ThemeProvider
782
+ router?: Router
783
+ i18n?: I18nProvider
784
+ http?: HttpClient
785
+ storage?: StorageProvider
786
+ logger?: LoggerProvider
787
+ }
788
+ ```
789
+
790
+ #### `MoleculeTokens`
791
+
792
+ Injection tokens for molecule services.
793
+
794
+ ```typescript
795
+ interface MoleculeTokens {
796
+ STATE_PROVIDER: symbol
797
+ AUTH_CLIENT: symbol
798
+ THEME_PROVIDER: symbol
799
+ ROUTER: symbol
800
+ I18N_PROVIDER: symbol
801
+ HTTP_CLIENT: symbol
802
+ STORAGE_PROVIDER: symbol
803
+ LOGGER_PROVIDER: symbol
804
+ }
805
+ ```
806
+
807
+ #### `OAuthOptions`
808
+
809
+ OAuth configuration options.
810
+
811
+ ```typescript
812
+ interface OAuthOptions {
813
+ /** Base URL for the API server (e.g. `https://api.example.com`). */
814
+ baseURL?: string
815
+ /** List of supported OAuth provider names (e.g. `['github', 'google']`). */
816
+ oauthProviders?: string[]
817
+ /** Path prefix for OAuth initiation routes. Defaults to `/oauth`. */
818
+ oauthEndpoint?: string
819
+ /** Path for the OAuth login POST endpoint. Defaults to `/users/log-in/oauth`. */
820
+ loginEndpoint?: string
821
+ /** Called after a successful OAuth login (session established). */
822
+ onSuccess?: () => void
823
+ /**
824
+ * Called with a failure message when the OAuth login fails. Failures are
825
+ * also emitted on {@link OAuthStateManager.error$}.
826
+ */
827
+ onError?: (error: string) => void
828
+ /**
829
+ * Auth client used to establish the session after the code exchange. This
830
+ * is THE way to wire session establishment in Angular: inject the
831
+ * `AUTH_CLIENT` token and pass the client here. When omitted, the helper
832
+ * falls back to the server-established httpOnly-cookie session (see
833
+ * {@link OAuthStateManager.handleCallback}).
834
+ */
835
+ authClient?: AuthClient<unknown>
836
+ }
837
+ ```
838
+
839
+ #### `OAuthStateManager`
840
+
841
+ OAuth state manager.
842
+
843
+ ```typescript
844
+ interface OAuthStateManager {
845
+ /** Observable of the configured OAuth provider names. */
846
+ providers$: Observable<string[]>
847
+ /**
848
+ * Observable of OAuth failure messages (from the callback code exchange).
849
+ * Completed by {@link OAuthStateManager.destroy}.
850
+ */
851
+ error$: Observable<string>
852
+ /** Returns the configured OAuth provider names. */
853
+ getProviders: () => string[]
854
+ /** Builds the OAuth initiation URL for a provider. */
855
+ getOAuthUrl: (provider: string) => string
856
+ /** Starts the full-page redirect flow for a provider. */
857
+ redirect: (provider: string) => void
858
+ /**
859
+ * Handles the OAuth callback: exchanges the `code` URL parameter for a
860
+ * session. Invoked automatically at creation (see {@link createOAuthState});
861
+ * exposed for callers that need to re-run it manually. No-ops unless
862
+ * running in a browser with a `code` URL parameter and a stashed provider.
863
+ *
864
+ * When an auth client was provided, the session is established locally
865
+ * (`setAccessToken` + `setUser` + `initialize`). When no client is
866
+ * available, the server has already established the httpOnly-cookie
867
+ * session during the exchange, so a user-carrying response still counts
868
+ * as success.
869
+ */
870
+ handleCallback: () => Promise<void>
871
+ /** Completes the `providers$` and `error$` observables. */
872
+ destroy: () => void
873
+ }
874
+ ```
875
+
876
+ #### `PasswordResetStateManager`
877
+
878
+ Password reset state manager.
879
+
880
+ ```typescript
881
+ interface PasswordResetStateManager {
882
+ requestState$: Observable<PromiseState<void>>
883
+ confirmState$: Observable<PromiseState<void>>
884
+ getRequestState: () => PromiseState<void>
885
+ getConfirmState: () => PromiseState<void>
886
+ requestReset: (data: PasswordResetRequest) => Promise<void>
887
+ confirmReset: (data: PasswordResetConfirm) => Promise<void>
888
+ reset: () => void
889
+ destroy: () => void
890
+ }
891
+ ```
892
+
893
+ #### `PlatformService`
894
+
895
+ Platform service interface.
896
+
897
+ ```typescript
898
+ interface PlatformService {
899
+ platform: Platform
900
+ isNative: boolean
901
+ isMobile: boolean
902
+ isDesktop: boolean
903
+ isWeb: boolean
904
+ isDevelopment: boolean
905
+ isProduction: boolean
906
+ isPlatform: (...platforms: Platform[]) => boolean
907
+ }
908
+ ```
909
+
910
+ #### `PromiseStateManager`
911
+
912
+ Promise state manager.
913
+
914
+ ```typescript
915
+ interface PromiseStateManager<T> {
916
+ state$: Observable<PromiseState<T>>
917
+ getState: () => PromiseState<T>
918
+ call: (...args: any[]) => Promise<T>
919
+ cancel: (message?: string) => void
920
+ reset: () => void
921
+ destroy: () => void
922
+ }
923
+ ```
924
+
925
+ #### `PushService`
926
+
927
+ Push service interface.
928
+
929
+ ```typescript
930
+ interface PushService {
931
+ permission$: Observable<PermissionStatus | null>
932
+ token$: Observable<PushToken | null>
933
+ getPermission: () => PermissionStatus | null
934
+ getToken: () => PushToken | null
935
+ checkPermission: () => Promise<PermissionStatus>
936
+ requestPermission: () => Promise<PermissionStatus>
937
+ register: (options?: PushRegisterOptions) => Promise<PushToken>
938
+ unregister: () => Promise<void>
939
+ onNotificationReceived: (listener: NotificationReceivedListener) => () => void
940
+ onNotificationAction: (listener: NotificationActionListener) => () => void
941
+ onTokenChange: (listener: TokenChangeListener) => () => void
942
+ setBadge: (count: number) => Promise<void>
943
+ clearBadge: () => Promise<void>
944
+ destroy: () => void
945
+ }
946
+ ```
947
+
948
+ #### `RouteLocation`
949
+
950
+ Current URL decomposed into pathname, search string, hash, navigation state, and unique key.
951
+
952
+ ```typescript
953
+ interface RouteLocation {
954
+ /**
955
+ * Current pathname.
956
+ */
957
+ pathname: string
958
+ /**
959
+ * Query string (including leading ?).
960
+ */
961
+ search: string
962
+ /**
963
+ * Hash (including leading #).
964
+ */
965
+ hash: string
966
+ /**
967
+ * State data passed with navigation.
968
+ */
969
+ state?: unknown
970
+ /**
971
+ * Unique key for this location.
972
+ */
973
+ key?: string
974
+ }
975
+ ```
976
+
977
+ #### `Router`
978
+
979
+ Client-side router providing navigation, guards, route matching, and history control.
980
+
981
+ All routing providers must implement this interface.
982
+
983
+ ```typescript
984
+ interface Router {
985
+ /**
986
+ * Returns the current route location (pathname, search, hash, state).
987
+ */
988
+ getLocation(): RouteLocation
989
+ /**
990
+ * Gets the current route params.
991
+ */
992
+ getParams<T extends RouteParams = RouteParams>(): T
993
+ /**
994
+ * Gets the current query params.
995
+ */
996
+ getQuery(): QueryParams
997
+ /**
998
+ * Gets a specific query parameter.
999
+ */
1000
+ getQueryParam(key: string): string | undefined
1001
+ /**
1002
+ * Gets the current hash.
1003
+ */
1004
+ getHash(): string
1005
+ /**
1006
+ * Navigates to a path.
1007
+ */
1008
+ navigate(path: string, options?: NavigateOptions): void
1009
+ /**
1010
+ * Navigates to a named route.
1011
+ */
1012
+ navigateTo(
1013
+ name: string,
1014
+ params?: RouteParams,
1015
+ query?: QueryParams,
1016
+ options?: NavigateOptions,
1017
+ ): void
1018
+ /**
1019
+ * Goes back in history.
1020
+ */
1021
+ back(): void
1022
+ /**
1023
+ * Goes forward in history.
1024
+ */
1025
+ forward(): void
1026
+ /**
1027
+ * Goes to a specific point in history.
1028
+ */
1029
+ go(delta: number): void
1030
+ /**
1031
+ * Updates the current query params.
1032
+ */
1033
+ setQuery(params: QueryParams, options?: NavigateOptions): void
1034
+ /**
1035
+ * Updates a specific query parameter.
1036
+ */
1037
+ setQueryParam(key: string, value: string | undefined, options?: NavigateOptions): void
1038
+ /**
1039
+ * Updates the current hash.
1040
+ */
1041
+ setHash(hash: string, options?: NavigateOptions): void
1042
+ /**
1043
+ * Checks if a path matches the current location.
1044
+ *
1045
+ * @returns `true` if the path matches the current route.
1046
+ */
1047
+ isActive(path: string, exact?: boolean): boolean
1048
+ /**
1049
+ * Matches a path pattern against a pathname.
1050
+ */
1051
+ matchPath<Params extends RouteParams = RouteParams>(
1052
+ pattern: string,
1053
+ pathname: string,
1054
+ ): RouteMatch<Params> | null
1055
+ /**
1056
+ * Generates a URL from a named route.
1057
+ */
1058
+ generatePath(name: string, params?: RouteParams, query?: QueryParams): string
1059
+ /**
1060
+ * Subscribes to route changes.
1061
+ */
1062
+ subscribe(listener: RouteChangeListener): () => void
1063
+ /**
1064
+ * Adds a navigation guard.
1065
+ */
1066
+ addGuard(guard: NavigationGuard): () => void
1067
+ /**
1068
+ * Registers route definitions.
1069
+ */
1070
+ registerRoutes(routes: RouteDefinition[]): void
1071
+ /**
1072
+ * Gets all registered routes.
1073
+ */
1074
+ getRoutes(): RouteDefinition[]
1075
+ /**
1076
+ * Destroys the router.
1077
+ */
1078
+ destroy(): void
1079
+ }
1080
+ ```
1081
+
1082
+ #### `SignupStateManager`
1083
+
1084
+ Signup state manager.
1085
+
1086
+ ```typescript
1087
+ interface SignupStateManager<T = unknown> {
1088
+ state$: Observable<PromiseState<AuthResult<T>>>
1089
+ getState: () => PromiseState<AuthResult<T>>
1090
+ signup: (data: RegisterData) => Promise<AuthResult<T>>
1091
+ reset: () => void
1092
+ destroy: () => void
1093
+ }
1094
+ ```
1095
+
1096
+ #### `StateProvider`
1097
+
1098
+ State provider interface that all state management bond packages
1099
+ must implement. Provides the store creation factory.
1100
+
1101
+ ```typescript
1102
+ interface StateProvider {
1103
+ /**
1104
+ * Creates a new store.
1105
+ */
1106
+ createStore<T>(config: StoreConfig<T>): Store<T>
1107
+ }
1108
+ ```
1109
+
1110
+ #### `StorageProvider`
1111
+
1112
+ Storage provider interface.
1113
+
1114
+ All storage providers must implement this interface.
1115
+
1116
+ ```typescript
1117
+ interface StorageProvider {
1118
+ /**
1119
+ * Gets a value from storage.
1120
+ */
1121
+ get<T = unknown>(key: string): Promise<T | null>
1122
+ /**
1123
+ * Sets a value in storage.
1124
+ */
1125
+ set<T = unknown>(key: string, value: T): Promise<void>
1126
+ /**
1127
+ * Removes a value from storage.
1128
+ */
1129
+ remove(key: string): Promise<void>
1130
+ /**
1131
+ * Clears all values from storage.
1132
+ */
1133
+ clear(): Promise<void>
1134
+ /**
1135
+ * Gets all keys in storage.
1136
+ */
1137
+ keys(): Promise<string[]>
1138
+ /**
1139
+ * Gets multiple values from storage.
1140
+ */
1141
+ getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>
1142
+ /**
1143
+ * Sets multiple values in storage.
1144
+ */
1145
+ setMany?<T = unknown>(entries: Array<[string, T]>): Promise<void>
1146
+ /**
1147
+ * Removes multiple values from storage.
1148
+ */
1149
+ removeMany?(keys: string[]): Promise<void>
1150
+ }
1151
+ ```
1152
+
1153
+ #### `StorageValueState`
1154
+
1155
+ State for a storage value.
1156
+
1157
+ ```typescript
1158
+ interface StorageValueState<T> {
1159
+ value: T | undefined
1160
+ loading: boolean
1161
+ error: Error | null
1162
+ }
1163
+ ```
1164
+
1165
+ #### `Store`
1166
+
1167
+ Reactive state container with getState, setState, subscribe, and destroy.
1168
+
1169
+ All state management providers must implement this interface.
1170
+
1171
+ ```typescript
1172
+ interface Store<T> {
1173
+ /**
1174
+ * Gets the current state.
1175
+ */
1176
+ getState(): T
1177
+ /**
1178
+ * Sets the state (partial or via updater function).
1179
+ */
1180
+ setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
1181
+ /**
1182
+ * Subscribes to state changes.
1183
+ * Returns an unsubscribe function.
1184
+ */
1185
+ subscribe(listener: StateListener<T>): () => void
1186
+ /**
1187
+ * Destroys the store and cleans up subscriptions.
1188
+ */
1189
+ destroy(): void
1190
+ }
1191
+ ```
1192
+
1193
+ #### `StoreConfig`
1194
+
1195
+ Configuration for creating a store (initial state, optional name, and middleware chain).
1196
+
1197
+ ```typescript
1198
+ interface StoreConfig<T> {
1199
+ /**
1200
+ * Initial state value.
1201
+ */
1202
+ initialState: T
1203
+ /**
1204
+ * Optional name for debugging.
1205
+ */
1206
+ name?: string
1207
+ /**
1208
+ * Optional middleware functions.
1209
+ */
1210
+ middleware?: StoreMiddleware<T>[]
1211
+ }
1212
+ ```
1213
+
1214
+ #### `Theme`
1215
+
1216
+ Complete theme definition.
1217
+
1218
+ ```typescript
1219
+ interface Theme {
1220
+ name: string
1221
+ mode: 'light' | 'dark'
1222
+ colors: ThemeColors
1223
+ breakpoints: ThemeBreakpoints
1224
+ spacing: ThemeSpacing
1225
+ typography: ThemeTypography
1226
+ borderRadius: ThemeBorderRadius
1227
+ shadows: ThemeShadows
1228
+ transitions: ThemeTransitions
1229
+ zIndex: ThemeZIndex
1230
+ }
1231
+ ```
1232
+
1233
+ #### `ThemeProvider`
1234
+
1235
+ Manages theme state including the active theme, mode toggling,
1236
+ and change subscriptions.
1237
+
1238
+ ```typescript
1239
+ interface ThemeProvider {
1240
+ /**
1241
+ * Returns the currently active theme.
1242
+ */
1243
+ getTheme(): Theme
1244
+ /**
1245
+ * Sets the active theme by reference or by name.
1246
+ *
1247
+ * @param theme - A `Theme` object or a theme name string to activate.
1248
+ */
1249
+ setTheme(theme: Theme | string): void
1250
+ /**
1251
+ * Toggles between light and dark mode for the active theme.
1252
+ */
1253
+ toggleMode(): void
1254
+ /**
1255
+ * Subscribes to theme changes. The callback fires whenever
1256
+ * `setTheme()` or `toggleMode()` is called.
1257
+ *
1258
+ * @param callback - Invoked with the new theme after each change.
1259
+ * @returns An unsubscribe function.
1260
+ */
1261
+ subscribe(callback: (theme: Theme) => void): () => void
1262
+ /**
1263
+ * Returns all registered themes. Optional — not all providers
1264
+ * support multiple themes.
1265
+ */
1266
+ getThemes?(): Theme[]
1267
+ /**
1268
+ * Returns the theme a render WITHOUT a browser produces — a server or
1269
+ * build-time render, which has no storage and no `prefers-color-scheme`
1270
+ * to read. A hydrating client renders this theme first, so its markup
1271
+ * matches what the server sent, and switches to `getTheme()` right
1272
+ * after. Optional — a provider whose theme cannot differ between the two
1273
+ * need not implement it.
1274
+ */
1275
+ getServerTheme?(): Theme
1276
+ }
1277
+ ```
1278
+
1279
+ #### `VersionService`
1280
+
1281
+ Version service interface.
1282
+
1283
+ ```typescript
1284
+ interface VersionService {
1285
+ state$: Observable<VersionState>
1286
+ isUpdateAvailable$: Observable<boolean>
1287
+ isChecking$: Observable<boolean>
1288
+ isServiceWorkerWaiting$: Observable<boolean>
1289
+ newVersion$: Observable<string | undefined>
1290
+ getState: () => VersionState
1291
+ checkForUpdates: () => Promise<boolean>
1292
+ applyUpdate: (options?: { force?: boolean }) => void
1293
+ dismissUpdate: () => void
1294
+ startPeriodicChecks: (options?: UpdateCheckOptions) => void
1295
+ stopPeriodicChecks: () => void
1296
+ destroy: () => void
1297
+ }
1298
+ ```
1299
+
1300
+ ### Types
1301
+
1302
+ #### `QueryParams`
1303
+
1304
+ URL query string parameter map (single values or arrays for repeated keys).
1305
+
1306
+ ```typescript
1307
+ type QueryParams = Record<string, string | string[] | undefined>
1308
+ ```
1309
+
1310
+ #### `RouteParams`
1311
+
1312
+ URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
1313
+
1314
+ ```typescript
1315
+ type RouteParams = Record<string, string>
1316
+ ```
1317
+
1318
+ ### Classes
1319
+
1320
+ #### `MoleculeAuthService`
1321
+
1322
+ Angular service for authentication.
1323
+
1324
+ Wraps molecule auth client and exposes state as RxJS observables.
1325
+
1326
+ #### `MoleculeFormInstance`
1327
+
1328
+ Wrapper around a FormController that provides RxJS observables and
1329
+ synchronous accessors for use in Angular components.
1330
+
1331
+ #### `MoleculeFormsService`
1332
+
1333
+ Angular service for form handling.
1334
+
1335
+ Wraps molecule form providers and creates form instances that expose
1336
+ state as RxJS observables.
1337
+
1338
+ #### `MoleculeHttpService`
1339
+
1340
+ Angular service for HTTP requests.
1341
+
1342
+ Wraps molecule HTTP client and returns RxJS observables.
1343
+
1344
+ #### `MoleculeI18nService`
1345
+
1346
+ Angular service for internationalization.
1347
+
1348
+ Wraps molecule i18n provider and exposes state as RxJS observables.
1349
+
1350
+ #### `MoleculeLoggerService`
1351
+
1352
+ Angular service for logging.
1353
+
1354
+ Wraps molecule logger provider.
1355
+
1356
+ #### `MoleculeRouterService`
1357
+
1358
+ Angular service for routing.
1359
+
1360
+ Wraps molecule router and exposes state as RxJS observables.
1361
+
1362
+ #### `MoleculeStateService`
1363
+
1364
+ Angular service for state management.
1365
+
1366
+ Wraps molecule state stores and exposes them as RxJS observables.
1367
+
1368
+ #### `MoleculeStorageService`
1369
+
1370
+ Angular service for storage.
1371
+
1372
+ Wraps molecule storage provider and returns RxJS observables.
1373
+
1374
+ #### `MoleculeThemeService`
1375
+
1376
+ Angular service for theming.
1377
+
1378
+ Wraps molecule theme provider and exposes state as RxJS observables.
1379
+
1380
+ ### Functions
1381
+
1382
+ #### `bumpLocaleVersion()`
1383
+
1384
+ Bump the locale version signal, causing all template bindings that use
1385
+ the reactive `t()` to re-evaluate on the next change detection cycle.
1386
+
1387
+ Called automatically by the `ENVIRONMENT_INITIALIZER` in `provideMolecule`.
1388
+
1389
+ ```typescript
1390
+ function bumpLocaleVersion(): void
1391
+ ```
1392
+
1393
+ #### `createAsyncState(initialState)`
1394
+
1395
+ Creates an async-capable state manager.
1396
+
1397
+ ```typescript
1398
+ function createAsyncState(initialState: T): AsyncStateManager<T>
1399
+ ```
1400
+
1401
+ - `initialState` — Initial state value
1402
+
1403
+ **Returns:** The created instance.
1404
+
1405
+ #### `createCapacitorAppState(options)`
1406
+
1407
+ Creates an Angular Capacitor app service with reactive state.
1408
+
1409
+ Wraps `createCapacitorApp` from `@molecule/app-platform` and exposes
1410
+ state changes as RxJS observables.
1411
+
1412
+ ```typescript
1413
+ function createCapacitorAppState(options?: CapacitorAppOptions): CapacitorAppManager
1414
+ ```
1415
+
1416
+ - `options` — Capacitor app configuration options
1417
+
1418
+ **Returns:** Capacitor app manager with observables and action methods
1419
+
1420
+ #### `createChangePasswordState(client)`
1421
+
1422
+ Creates a change password state manager with async state tracking.
1423
+
1424
+ ```typescript
1425
+ function createChangePasswordState(client: AuthClient<UserProfile>): ChangePasswordStateManager
1426
+ ```
1427
+
1428
+ - `client` — Auth client
1429
+
1430
+ **Returns:** Change password state manager
1431
+
1432
+ #### `createDeviceService()`
1433
+
1434
+ Creates an Angular device service with static device information.
1435
+
1436
+ ```typescript
1437
+ function createDeviceService(): DeviceService
1438
+ ```
1439
+
1440
+ **Returns:** Device service with device, screen, hardware, and feature info
1441
+
1442
+ #### `createLoginState(client)`
1443
+
1444
+ Creates a login state manager with async state tracking.
1445
+
1446
+ ```typescript
1447
+ function createLoginState(client: AuthClient<T>): LoginStateManager<T>
1448
+ ```
1449
+
1450
+ - `client` — Auth client
1451
+
1452
+ **Returns:** Login state manager
1453
+
1454
+ #### `createOAuthState(options)`
1455
+
1456
+ Creates an OAuth state manager.
1457
+
1458
+ Automatically handles OAuth callbacks: when created in a browser, it
1459
+ invokes {@link OAuthStateManager.handleCallback} immediately (a guarded
1460
+ no-op when the URL carries no `code` parameter).
1461
+
1462
+ ```typescript
1463
+ function createOAuthState(options?: OAuthOptions): OAuthStateManager
1464
+ ```
1465
+
1466
+ - `options` — OAuth configuration
1467
+
1468
+ **Returns:** The created instance.
1469
+
1470
+ #### `createPasswordResetState(client)`
1471
+
1472
+ Creates a password reset state manager with async state tracking.
1473
+
1474
+ ```typescript
1475
+ function createPasswordResetState(client: AuthClient<UserProfile>): PasswordResetStateManager
1476
+ ```
1477
+
1478
+ - `client` — Auth client
1479
+
1480
+ **Returns:** Password reset state manager
1481
+
1482
+ #### `createPlatformService()`
1483
+
1484
+ Creates an Angular platform service with static platform information.
1485
+
1486
+ ```typescript
1487
+ function createPlatformService(): PlatformService
1488
+ ```
1489
+
1490
+ **Returns:** Platform service with platform flags and isPlatform check
1491
+
1492
+ #### `createPromiseState(asyncFn)`
1493
+
1494
+ Creates a promise state manager for tracking async function state.
1495
+
1496
+ ```typescript
1497
+ function createPromiseState(asyncFn: T): PromiseStateManager<Awaited<ReturnType<T>>>
1498
+ ```
1499
+
1500
+ - `asyncFn` — The async function to track
1501
+
1502
+ **Returns:** Promise state manager with observable state
1503
+
1504
+ #### `createPushService()`
1505
+
1506
+ Creates an Angular push notifications service with reactive state.
1507
+
1508
+ ```typescript
1509
+ function createPushService(): PushService
1510
+ ```
1511
+
1512
+ **Returns:** Push service with observables and action methods
1513
+
1514
+ #### `createSignupState(client)`
1515
+
1516
+ Creates a signup state manager with async state tracking.
1517
+
1518
+ ```typescript
1519
+ function createSignupState(client: AuthClient<T>): SignupStateManager<T>
1520
+ ```
1521
+
1522
+ - `client` — Auth client
1523
+
1524
+ **Returns:** Signup state manager
1525
+
1526
+ #### `createVersionService()`
1527
+
1528
+ Creates an Angular version service with reactive state.
1529
+
1530
+ ```typescript
1531
+ function createVersionService(): VersionService
1532
+ ```
1533
+
1534
+ **Returns:** The created instance.
1535
+
1536
+ #### `provideAuth(client)`
1537
+
1538
+ Registers an AuthClient as an Angular environment provider for dependency injection.
1539
+
1540
+ ```typescript
1541
+ function provideAuth(client: AuthClient<T>): EnvironmentProviders
1542
+ ```
1543
+
1544
+ - `client` — Auth client
1545
+
1546
+ **Returns:** Environment providers
1547
+
1548
+ #### `provideHttp(client)`
1549
+
1550
+ Provide HTTP client.
1551
+
1552
+ ```typescript
1553
+ function provideHttp(client: HttpClient): EnvironmentProviders
1554
+ ```
1555
+
1556
+ - `client` — HTTP client
1557
+
1558
+ **Returns:** Environment providers
1559
+
1560
+ #### `provideI18n(provider)`
1561
+
1562
+ Registers an I18nProvider as an Angular environment provider for dependency injection.
1563
+
1564
+ ```typescript
1565
+ function provideI18n(provider: I18nProvider): EnvironmentProviders
1566
+ ```
1567
+
1568
+ - `provider` — I18n provider
1569
+
1570
+ **Returns:** Environment providers
1571
+
1572
+ #### `provideLogger(provider)`
1573
+
1574
+ Registers a LoggerProvider as an Angular environment provider for dependency injection.
1575
+
1576
+ ```typescript
1577
+ function provideLogger(provider: LoggerProvider): EnvironmentProviders
1578
+ ```
1579
+
1580
+ - `provider` — Logger provider
1581
+
1582
+ **Returns:** Environment providers
1583
+
1584
+ #### `provideMolecule(config)`
1585
+
1586
+ Provide all molecule services at once.
1587
+
1588
+ ```typescript
1589
+ function provideMolecule(config: MoleculeModuleConfig): EnvironmentProviders
1590
+ ```
1591
+
1592
+ - `config` — Configuration with all providers
1593
+
1594
+ **Returns:** Environment providers
1595
+
1596
+ #### `provideRouter(router)`
1597
+
1598
+ Registers a Router as an Angular environment provider for dependency injection.
1599
+
1600
+ ```typescript
1601
+ function provideRouter(router: Router): EnvironmentProviders
1602
+ ```
1603
+
1604
+ - `router` — Router instance
1605
+
1606
+ **Returns:** Environment providers
1607
+
1608
+ #### `provideState(provider)`
1609
+
1610
+ Provide state management.
1611
+
1612
+ ```typescript
1613
+ function provideState(provider: StateProvider): EnvironmentProviders
1614
+ ```
1615
+
1616
+ - `provider` — State provider
1617
+
1618
+ **Returns:** Environment providers
1619
+
1620
+ #### `provideStorage(provider)`
1621
+
1622
+ Registers a StorageProvider as an Angular environment provider for dependency injection.
1623
+
1624
+ ```typescript
1625
+ function provideStorage(provider: StorageProvider): EnvironmentProviders
1626
+ ```
1627
+
1628
+ - `provider` — Storage provider
1629
+
1630
+ **Returns:** Environment providers
1631
+
1632
+ #### `provideTheme(provider)`
1633
+
1634
+ Registers a ThemeProvider as an Angular environment provider for dependency injection.
1635
+
1636
+ ```typescript
1637
+ function provideTheme(provider: ThemeProvider): EnvironmentProviders
1638
+ ```
1639
+
1640
+ - `provider` — Theme provider
1641
+
1642
+ **Returns:** Environment providers
1643
+
1644
+ #### `t(key, values, options)`
1645
+
1646
+ Translate a key using the current locale.
1647
+
1648
+ This is a signal-aware wrapper around `@molecule/app-i18n`'s `t()`.
1649
+ Reading the internal locale signal establishes an Angular reactivity
1650
+ dependency, so template bindings that call this function will be
1651
+ re-evaluated when the locale changes.
1652
+
1653
+ ```typescript
1654
+ function t(
1655
+ key: string,
1656
+ values?: InterpolationValues,
1657
+ options?: { defaultValue?: string; count?: number },
1658
+ ): string
1659
+ ```
1660
+
1661
+ - `key` — Translation key
1662
+ - `values` — Interpolation values
1663
+ - `options` — Options (defaultValue, count).
1664
+ - `options.defaultValue` — Fallback string when no translation is found.
1665
+ - `options.count` — Pluralization count.
1666
+
1667
+ **Returns:** Translated string
1668
+
1669
+ ### Constants
1670
+
1671
+ #### `AUTH_CLIENT`
1672
+
1673
+ Injection token for auth client.
1674
+
1675
+ ```typescript
1676
+ const AUTH_CLIENT: InjectionToken<AuthClient<unknown>>
1677
+ ```
1678
+
1679
+ #### `HTTP_CLIENT`
1680
+
1681
+ Injection token for HTTP client.
1682
+
1683
+ ```typescript
1684
+ const HTTP_CLIENT: InjectionToken<HttpClient>
1685
+ ```
1686
+
1687
+ #### `I18N_PROVIDER`
1688
+
1689
+ Injection token for i18n provider.
1690
+
1691
+ ```typescript
1692
+ const I18N_PROVIDER: InjectionToken<I18nProvider>
1693
+ ```
1694
+
1695
+ #### `LOGGER_PROVIDER`
1696
+
1697
+ Injection token for logger provider.
1698
+
1699
+ ```typescript
1700
+ const LOGGER_PROVIDER: InjectionToken<LoggerProvider>
1701
+ ```
1702
+
1703
+ #### `ROUTER`
1704
+
1705
+ Injection token for router.
1706
+
1707
+ ```typescript
1708
+ const ROUTER: InjectionToken<Router>
1709
+ ```
1710
+
1711
+ #### `STATE_PROVIDER`
1712
+
1713
+ Injection token for state provider.
1714
+
1715
+ ```typescript
1716
+ const STATE_PROVIDER: InjectionToken<StateProvider>
1717
+ ```
1718
+
1719
+ #### `STORAGE_PROVIDER`
1720
+
1721
+ Injection token for storage provider.
1722
+
1723
+ ```typescript
1724
+ const STORAGE_PROVIDER: InjectionToken<StorageProvider>
1725
+ ```
1726
+
1727
+ #### `THEME_PROVIDER`
1728
+
1729
+ Injection token for theme provider.
1730
+
1731
+ ```typescript
1732
+ const THEME_PROVIDER: InjectionToken<ThemeProvider>
1733
+ ```
1734
+
1735
+ ## Injection Notes
1736
+
1737
+ ### Requirements
1738
+
1739
+ Peer dependencies:
1740
+
1741
+ - `@angular/core` 22.0.0
1742
+ - `@molecule/app-auth` ^1.0.1
1743
+ - `@molecule/app-device` ^1.0.1
1744
+ - `@molecule/app-forms` ^1.0.1
1745
+ - `@molecule/app-http` ^1.0.1
1746
+ - `@molecule/app-i18n` ^1.0.1
1747
+ - `@molecule/app-logger` ^1.0.1
1748
+ - `@molecule/app-platform` ^1.0.1
1749
+ - `@molecule/app-push` ^1.0.1
1750
+ - `@molecule/app-routing` ^1.0.1
1751
+ - `@molecule/app-state` ^1.0.1
1752
+ - `@molecule/app-storage` ^1.0.1
1753
+ - `@molecule/app-theme` ^1.0.1
1754
+ - `@molecule/app-ui` ^1.0.1
1755
+ - `@molecule/app-utilities` ^1.0.1
1756
+ - `@molecule/app-version` ^1.0.1
1757
+ - `rxjs` ^7.8.0
1758
+
1759
+ ### Runtime Dependencies
1760
+
1761
+ - `@angular/core`
1762
+ - `@molecule/app-auth`
1763
+ - `@molecule/app-device`
1764
+ - `@molecule/app-forms`
1765
+ - `@molecule/app-http`
1766
+ - `@molecule/app-i18n`
1767
+ - `@molecule/app-logger`
1768
+ - `@molecule/app-platform`
1769
+ - `@molecule/app-push`
1770
+ - `@molecule/app-routing`
1771
+ - `@molecule/app-state`
1772
+ - `@molecule/app-storage`
1773
+ - `@molecule/app-theme`
1774
+ - `@molecule/app-ui`
1775
+ - `@molecule/app-utilities`
1776
+ - `@molecule/app-version`
1777
+ - `rxjs`
1778
+
1779
+ - Peer requirements: Angular 22 (`@angular/core` is pinned to 22.0.0) and
1780
+ rxjs 7.8+.
1781
+ - Translations: import `t` from THIS package, not from
1782
+ `@molecule/app-i18n`. The re-exported `t` reads an internal Angular
1783
+ signal, so template bindings that CALL it (expose it on the component as
1784
+ above) re-evaluate automatically when the locale changes; the plain
1785
+ app-i18n `t` — or a one-time field assignment like `title = t(...)` —
1786
+ renders once and goes stale. The signal is bumped by `provideMolecule` —
1787
+ pass your `i18n` provider there (or call `bumpLocaleVersion()` from your
1788
+ own locale-change hook) for the reactivity to fire.
1789
+ - `provideMolecule` only registers the providers you pass; injecting a
1790
+ Molecule service whose token was never provided fails at DI time.
1791
+ Per-concern helpers (`provideAuth`, `provideTheme`, ...) exist for
1792
+ piecemeal setup.