@molecule/app-angular 1.0.0 → 1.0.1

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.
Files changed (2) hide show
  1. package/README.md +1783 -0
  2. package/package.json +19 -18
package/README.md ADDED
@@ -0,0 +1,1783 @@
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-08-04T01:50:02.002Z
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
+ ```
1269
+
1270
+ #### `VersionService`
1271
+
1272
+ Version service interface.
1273
+
1274
+ ```typescript
1275
+ interface VersionService {
1276
+ state$: Observable<VersionState>
1277
+ isUpdateAvailable$: Observable<boolean>
1278
+ isChecking$: Observable<boolean>
1279
+ isServiceWorkerWaiting$: Observable<boolean>
1280
+ newVersion$: Observable<string | undefined>
1281
+ getState: () => VersionState
1282
+ checkForUpdates: () => Promise<boolean>
1283
+ applyUpdate: (options?: { force?: boolean }) => void
1284
+ dismissUpdate: () => void
1285
+ startPeriodicChecks: (options?: UpdateCheckOptions) => void
1286
+ stopPeriodicChecks: () => void
1287
+ destroy: () => void
1288
+ }
1289
+ ```
1290
+
1291
+ ### Types
1292
+
1293
+ #### `QueryParams`
1294
+
1295
+ URL query string parameter map (single values or arrays for repeated keys).
1296
+
1297
+ ```typescript
1298
+ type QueryParams = Record<string, string | string[] | undefined>
1299
+ ```
1300
+
1301
+ #### `RouteParams`
1302
+
1303
+ URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
1304
+
1305
+ ```typescript
1306
+ type RouteParams = Record<string, string>
1307
+ ```
1308
+
1309
+ ### Classes
1310
+
1311
+ #### `MoleculeAuthService`
1312
+
1313
+ Angular service for authentication.
1314
+
1315
+ Wraps molecule auth client and exposes state as RxJS observables.
1316
+
1317
+ #### `MoleculeFormInstance`
1318
+
1319
+ Wrapper around a FormController that provides RxJS observables and
1320
+ synchronous accessors for use in Angular components.
1321
+
1322
+ #### `MoleculeFormsService`
1323
+
1324
+ Angular service for form handling.
1325
+
1326
+ Wraps molecule form providers and creates form instances that expose
1327
+ state as RxJS observables.
1328
+
1329
+ #### `MoleculeHttpService`
1330
+
1331
+ Angular service for HTTP requests.
1332
+
1333
+ Wraps molecule HTTP client and returns RxJS observables.
1334
+
1335
+ #### `MoleculeI18nService`
1336
+
1337
+ Angular service for internationalization.
1338
+
1339
+ Wraps molecule i18n provider and exposes state as RxJS observables.
1340
+
1341
+ #### `MoleculeLoggerService`
1342
+
1343
+ Angular service for logging.
1344
+
1345
+ Wraps molecule logger provider.
1346
+
1347
+ #### `MoleculeRouterService`
1348
+
1349
+ Angular service for routing.
1350
+
1351
+ Wraps molecule router and exposes state as RxJS observables.
1352
+
1353
+ #### `MoleculeStateService`
1354
+
1355
+ Angular service for state management.
1356
+
1357
+ Wraps molecule state stores and exposes them as RxJS observables.
1358
+
1359
+ #### `MoleculeStorageService`
1360
+
1361
+ Angular service for storage.
1362
+
1363
+ Wraps molecule storage provider and returns RxJS observables.
1364
+
1365
+ #### `MoleculeThemeService`
1366
+
1367
+ Angular service for theming.
1368
+
1369
+ Wraps molecule theme provider and exposes state as RxJS observables.
1370
+
1371
+ ### Functions
1372
+
1373
+ #### `bumpLocaleVersion()`
1374
+
1375
+ Bump the locale version signal, causing all template bindings that use
1376
+ the reactive `t()` to re-evaluate on the next change detection cycle.
1377
+
1378
+ Called automatically by the `ENVIRONMENT_INITIALIZER` in `provideMolecule`.
1379
+
1380
+ ```typescript
1381
+ function bumpLocaleVersion(): void
1382
+ ```
1383
+
1384
+ #### `createAsyncState(initialState)`
1385
+
1386
+ Creates an async-capable state manager.
1387
+
1388
+ ```typescript
1389
+ function createAsyncState(initialState: T): AsyncStateManager<T>
1390
+ ```
1391
+
1392
+ - `initialState` — Initial state value
1393
+
1394
+ **Returns:** The created instance.
1395
+
1396
+ #### `createCapacitorAppState(options)`
1397
+
1398
+ Creates an Angular Capacitor app service with reactive state.
1399
+
1400
+ Wraps `createCapacitorApp` from `@molecule/app-platform` and exposes
1401
+ state changes as RxJS observables.
1402
+
1403
+ ```typescript
1404
+ function createCapacitorAppState(options?: CapacitorAppOptions): CapacitorAppManager
1405
+ ```
1406
+
1407
+ - `options` — Capacitor app configuration options
1408
+
1409
+ **Returns:** Capacitor app manager with observables and action methods
1410
+
1411
+ #### `createChangePasswordState(client)`
1412
+
1413
+ Creates a change password state manager with async state tracking.
1414
+
1415
+ ```typescript
1416
+ function createChangePasswordState(client: AuthClient<UserProfile>): ChangePasswordStateManager
1417
+ ```
1418
+
1419
+ - `client` — Auth client
1420
+
1421
+ **Returns:** Change password state manager
1422
+
1423
+ #### `createDeviceService()`
1424
+
1425
+ Creates an Angular device service with static device information.
1426
+
1427
+ ```typescript
1428
+ function createDeviceService(): DeviceService
1429
+ ```
1430
+
1431
+ **Returns:** Device service with device, screen, hardware, and feature info
1432
+
1433
+ #### `createLoginState(client)`
1434
+
1435
+ Creates a login state manager with async state tracking.
1436
+
1437
+ ```typescript
1438
+ function createLoginState(client: AuthClient<T>): LoginStateManager<T>
1439
+ ```
1440
+
1441
+ - `client` — Auth client
1442
+
1443
+ **Returns:** Login state manager
1444
+
1445
+ #### `createOAuthState(options)`
1446
+
1447
+ Creates an OAuth state manager.
1448
+
1449
+ Automatically handles OAuth callbacks: when created in a browser, it
1450
+ invokes {@link OAuthStateManager.handleCallback} immediately (a guarded
1451
+ no-op when the URL carries no `code` parameter).
1452
+
1453
+ ```typescript
1454
+ function createOAuthState(options?: OAuthOptions): OAuthStateManager
1455
+ ```
1456
+
1457
+ - `options` — OAuth configuration
1458
+
1459
+ **Returns:** The created instance.
1460
+
1461
+ #### `createPasswordResetState(client)`
1462
+
1463
+ Creates a password reset state manager with async state tracking.
1464
+
1465
+ ```typescript
1466
+ function createPasswordResetState(client: AuthClient<UserProfile>): PasswordResetStateManager
1467
+ ```
1468
+
1469
+ - `client` — Auth client
1470
+
1471
+ **Returns:** Password reset state manager
1472
+
1473
+ #### `createPlatformService()`
1474
+
1475
+ Creates an Angular platform service with static platform information.
1476
+
1477
+ ```typescript
1478
+ function createPlatformService(): PlatformService
1479
+ ```
1480
+
1481
+ **Returns:** Platform service with platform flags and isPlatform check
1482
+
1483
+ #### `createPromiseState(asyncFn)`
1484
+
1485
+ Creates a promise state manager for tracking async function state.
1486
+
1487
+ ```typescript
1488
+ function createPromiseState(asyncFn: T): PromiseStateManager<Awaited<ReturnType<T>>>
1489
+ ```
1490
+
1491
+ - `asyncFn` — The async function to track
1492
+
1493
+ **Returns:** Promise state manager with observable state
1494
+
1495
+ #### `createPushService()`
1496
+
1497
+ Creates an Angular push notifications service with reactive state.
1498
+
1499
+ ```typescript
1500
+ function createPushService(): PushService
1501
+ ```
1502
+
1503
+ **Returns:** Push service with observables and action methods
1504
+
1505
+ #### `createSignupState(client)`
1506
+
1507
+ Creates a signup state manager with async state tracking.
1508
+
1509
+ ```typescript
1510
+ function createSignupState(client: AuthClient<T>): SignupStateManager<T>
1511
+ ```
1512
+
1513
+ - `client` — Auth client
1514
+
1515
+ **Returns:** Signup state manager
1516
+
1517
+ #### `createVersionService()`
1518
+
1519
+ Creates an Angular version service with reactive state.
1520
+
1521
+ ```typescript
1522
+ function createVersionService(): VersionService
1523
+ ```
1524
+
1525
+ **Returns:** The created instance.
1526
+
1527
+ #### `provideAuth(client)`
1528
+
1529
+ Registers an AuthClient as an Angular environment provider for dependency injection.
1530
+
1531
+ ```typescript
1532
+ function provideAuth(client: AuthClient<T>): EnvironmentProviders
1533
+ ```
1534
+
1535
+ - `client` — Auth client
1536
+
1537
+ **Returns:** Environment providers
1538
+
1539
+ #### `provideHttp(client)`
1540
+
1541
+ Provide HTTP client.
1542
+
1543
+ ```typescript
1544
+ function provideHttp(client: HttpClient): EnvironmentProviders
1545
+ ```
1546
+
1547
+ - `client` — HTTP client
1548
+
1549
+ **Returns:** Environment providers
1550
+
1551
+ #### `provideI18n(provider)`
1552
+
1553
+ Registers an I18nProvider as an Angular environment provider for dependency injection.
1554
+
1555
+ ```typescript
1556
+ function provideI18n(provider: I18nProvider): EnvironmentProviders
1557
+ ```
1558
+
1559
+ - `provider` — I18n provider
1560
+
1561
+ **Returns:** Environment providers
1562
+
1563
+ #### `provideLogger(provider)`
1564
+
1565
+ Registers a LoggerProvider as an Angular environment provider for dependency injection.
1566
+
1567
+ ```typescript
1568
+ function provideLogger(provider: LoggerProvider): EnvironmentProviders
1569
+ ```
1570
+
1571
+ - `provider` — Logger provider
1572
+
1573
+ **Returns:** Environment providers
1574
+
1575
+ #### `provideMolecule(config)`
1576
+
1577
+ Provide all molecule services at once.
1578
+
1579
+ ```typescript
1580
+ function provideMolecule(config: MoleculeModuleConfig): EnvironmentProviders
1581
+ ```
1582
+
1583
+ - `config` — Configuration with all providers
1584
+
1585
+ **Returns:** Environment providers
1586
+
1587
+ #### `provideRouter(router)`
1588
+
1589
+ Registers a Router as an Angular environment provider for dependency injection.
1590
+
1591
+ ```typescript
1592
+ function provideRouter(router: Router): EnvironmentProviders
1593
+ ```
1594
+
1595
+ - `router` — Router instance
1596
+
1597
+ **Returns:** Environment providers
1598
+
1599
+ #### `provideState(provider)`
1600
+
1601
+ Provide state management.
1602
+
1603
+ ```typescript
1604
+ function provideState(provider: StateProvider): EnvironmentProviders
1605
+ ```
1606
+
1607
+ - `provider` — State provider
1608
+
1609
+ **Returns:** Environment providers
1610
+
1611
+ #### `provideStorage(provider)`
1612
+
1613
+ Registers a StorageProvider as an Angular environment provider for dependency injection.
1614
+
1615
+ ```typescript
1616
+ function provideStorage(provider: StorageProvider): EnvironmentProviders
1617
+ ```
1618
+
1619
+ - `provider` — Storage provider
1620
+
1621
+ **Returns:** Environment providers
1622
+
1623
+ #### `provideTheme(provider)`
1624
+
1625
+ Registers a ThemeProvider as an Angular environment provider for dependency injection.
1626
+
1627
+ ```typescript
1628
+ function provideTheme(provider: ThemeProvider): EnvironmentProviders
1629
+ ```
1630
+
1631
+ - `provider` — Theme provider
1632
+
1633
+ **Returns:** Environment providers
1634
+
1635
+ #### `t(key, values, options)`
1636
+
1637
+ Translate a key using the current locale.
1638
+
1639
+ This is a signal-aware wrapper around `@molecule/app-i18n`'s `t()`.
1640
+ Reading the internal locale signal establishes an Angular reactivity
1641
+ dependency, so template bindings that call this function will be
1642
+ re-evaluated when the locale changes.
1643
+
1644
+ ```typescript
1645
+ function t(
1646
+ key: string,
1647
+ values?: InterpolationValues,
1648
+ options?: { defaultValue?: string; count?: number },
1649
+ ): string
1650
+ ```
1651
+
1652
+ - `key` — Translation key
1653
+ - `values` — Interpolation values
1654
+ - `options` — Options (defaultValue, count).
1655
+ - `options.defaultValue` — Fallback string when no translation is found.
1656
+ - `options.count` — Pluralization count.
1657
+
1658
+ **Returns:** Translated string
1659
+
1660
+ ### Constants
1661
+
1662
+ #### `AUTH_CLIENT`
1663
+
1664
+ Injection token for auth client.
1665
+
1666
+ ```typescript
1667
+ const AUTH_CLIENT: InjectionToken<AuthClient<unknown>>
1668
+ ```
1669
+
1670
+ #### `HTTP_CLIENT`
1671
+
1672
+ Injection token for HTTP client.
1673
+
1674
+ ```typescript
1675
+ const HTTP_CLIENT: InjectionToken<HttpClient>
1676
+ ```
1677
+
1678
+ #### `I18N_PROVIDER`
1679
+
1680
+ Injection token for i18n provider.
1681
+
1682
+ ```typescript
1683
+ const I18N_PROVIDER: InjectionToken<I18nProvider>
1684
+ ```
1685
+
1686
+ #### `LOGGER_PROVIDER`
1687
+
1688
+ Injection token for logger provider.
1689
+
1690
+ ```typescript
1691
+ const LOGGER_PROVIDER: InjectionToken<LoggerProvider>
1692
+ ```
1693
+
1694
+ #### `ROUTER`
1695
+
1696
+ Injection token for router.
1697
+
1698
+ ```typescript
1699
+ const ROUTER: InjectionToken<Router>
1700
+ ```
1701
+
1702
+ #### `STATE_PROVIDER`
1703
+
1704
+ Injection token for state provider.
1705
+
1706
+ ```typescript
1707
+ const STATE_PROVIDER: InjectionToken<StateProvider>
1708
+ ```
1709
+
1710
+ #### `STORAGE_PROVIDER`
1711
+
1712
+ Injection token for storage provider.
1713
+
1714
+ ```typescript
1715
+ const STORAGE_PROVIDER: InjectionToken<StorageProvider>
1716
+ ```
1717
+
1718
+ #### `THEME_PROVIDER`
1719
+
1720
+ Injection token for theme provider.
1721
+
1722
+ ```typescript
1723
+ const THEME_PROVIDER: InjectionToken<ThemeProvider>
1724
+ ```
1725
+
1726
+ ## Injection Notes
1727
+
1728
+ ### Requirements
1729
+
1730
+ Peer dependencies:
1731
+
1732
+ - `@angular/core` 22.0.0
1733
+ - `@molecule/app-auth` ^1.0.1
1734
+ - `@molecule/app-device` ^1.0.1
1735
+ - `@molecule/app-forms` ^1.0.1
1736
+ - `@molecule/app-http` ^1.0.1
1737
+ - `@molecule/app-i18n` ^1.0.1
1738
+ - `@molecule/app-logger` ^1.0.1
1739
+ - `@molecule/app-platform` ^1.0.1
1740
+ - `@molecule/app-push` ^1.0.1
1741
+ - `@molecule/app-routing` ^1.0.1
1742
+ - `@molecule/app-state` ^1.0.1
1743
+ - `@molecule/app-storage` ^1.0.1
1744
+ - `@molecule/app-theme` ^1.0.1
1745
+ - `@molecule/app-ui` ^1.0.1
1746
+ - `@molecule/app-utilities` ^1.0.1
1747
+ - `@molecule/app-version` ^1.0.1
1748
+ - `rxjs` ^7.8.0
1749
+
1750
+ ### Runtime Dependencies
1751
+
1752
+ - `@angular/core`
1753
+ - `@molecule/app-auth`
1754
+ - `@molecule/app-device`
1755
+ - `@molecule/app-forms`
1756
+ - `@molecule/app-http`
1757
+ - `@molecule/app-i18n`
1758
+ - `@molecule/app-logger`
1759
+ - `@molecule/app-platform`
1760
+ - `@molecule/app-push`
1761
+ - `@molecule/app-routing`
1762
+ - `@molecule/app-state`
1763
+ - `@molecule/app-storage`
1764
+ - `@molecule/app-theme`
1765
+ - `@molecule/app-ui`
1766
+ - `@molecule/app-utilities`
1767
+ - `@molecule/app-version`
1768
+ - `rxjs`
1769
+
1770
+ - Peer requirements: Angular 22 (`@angular/core` is pinned to 22.0.0) and
1771
+ rxjs 7.8+.
1772
+ - Translations: import `t` from THIS package, not from
1773
+ `@molecule/app-i18n`. The re-exported `t` reads an internal Angular
1774
+ signal, so template bindings that CALL it (expose it on the component as
1775
+ above) re-evaluate automatically when the locale changes; the plain
1776
+ app-i18n `t` — or a one-time field assignment like `title = t(...)` —
1777
+ renders once and goes stale. The signal is bumped by `provideMolecule` —
1778
+ pass your `i18n` provider there (or call `bumpLocaleVersion()` from your
1779
+ own locale-change hook) for the reactivity to fire.
1780
+ - `provideMolecule` only registers the providers you pass; injecting a
1781
+ Molecule service whose token was never provided fails at DI time.
1782
+ Per-concern helpers (`provideAuth`, `provideTheme`, ...) exist for
1783
+ piecemeal setup.