@molecule/app-angular 1.0.2 → 1.0.4
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/LICENSE +111 -24
- package/README.md +1940 -706
- package/dist/services/auth.service.d.ts +5 -5
- package/dist/services/auth.service.d.ts.map +1 -1
- package/dist/services/auth.service.js.map +1 -1
- package/dist/tokens.d.ts +1 -1
- package/dist/tokens.d.ts.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -3,21 +3,21 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-
|
|
6
|
+
Generated: 2026-10-23T15:23:09.411Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/app-angular
|
|
10
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
11
|
Angular framework bindings for molecule.dev.
|
|
16
12
|
|
|
17
13
|
Provides Angular-specific services and providers for all molecule
|
|
18
14
|
core interfaces. This package enables the use of molecule's framework-agnostic
|
|
19
15
|
interfaces with Angular's idioms (services, DI, RxJS observables, etc.).
|
|
20
16
|
|
|
17
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
18
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
19
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
20
|
+
|
|
21
21
|
## Quick Start
|
|
22
22
|
|
|
23
23
|
```typescript
|
|
@@ -86,131 +86,17 @@ npm install @molecule/app-angular @angular/core @molecule/app-auth @molecule/app
|
|
|
86
86
|
|
|
87
87
|
### Interfaces
|
|
88
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
89
|
#### `AuthState`
|
|
209
90
|
|
|
210
91
|
Reactive authentication state snapshot (initialized, authenticated, user, loading, and error).
|
|
211
92
|
|
|
212
93
|
```typescript
|
|
213
94
|
interface AuthState<T = UserProfile> {
|
|
95
|
+
/**
|
|
96
|
+
* The session's state as one value — render from this instead of combining
|
|
97
|
+
* `initialized`/`authenticated`/`loading`. See {@link AuthStatus}.
|
|
98
|
+
*/
|
|
99
|
+
status: AuthStatus
|
|
214
100
|
/**
|
|
215
101
|
* Whether auth state has been initialized.
|
|
216
102
|
*/
|
|
@@ -234,49 +120,178 @@ interface AuthState<T = UserProfile> {
|
|
|
234
120
|
}
|
|
235
121
|
```
|
|
236
122
|
|
|
237
|
-
#### `
|
|
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`
|
|
123
|
+
#### `AuthClient`
|
|
265
124
|
|
|
266
|
-
|
|
125
|
+
Auth client interface that all auth bond packages must implement.
|
|
126
|
+
Provides login/logout/register flows, token management, profile
|
|
127
|
+
updates, and auth state subscription.
|
|
267
128
|
|
|
268
129
|
```typescript
|
|
269
|
-
interface
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
130
|
+
interface AuthClient<T = UserProfile, TRegister extends RegisterExtraShape<TRegister> = Record<never, never>> {
|
|
131
|
+
/**
|
|
132
|
+
* Returns the current authentication state snapshot.
|
|
133
|
+
*
|
|
134
|
+
* READING the state starts the client's one session restore when nobody has called
|
|
135
|
+
* {@link initialize} yet — lazily and exactly once, sharing the promise an explicit
|
|
136
|
+
* `initialize()` returns. A hook (`useAuth()`), a subscriber, `isAuthenticated()` and
|
|
137
|
+
* `getUser()` are reads too, so a client whose entry file dropped the template's
|
|
138
|
+
* `authClient.initialize()` line still restores instead of reporting `'loading'`
|
|
139
|
+
* forever.
|
|
140
|
+
*/
|
|
141
|
+
getState(): AuthState<T>;
|
|
142
|
+
/**
|
|
143
|
+
* Returns whether the user is currently authenticated.
|
|
144
|
+
*/
|
|
145
|
+
isAuthenticated(): boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Gets the current user.
|
|
148
|
+
*/
|
|
149
|
+
getUser(): T | null;
|
|
150
|
+
/**
|
|
151
|
+
* Optional ownership marker for the current session. Compare values only within
|
|
152
|
+
* this client: replacing or ending a session changes it, including re-adopting
|
|
153
|
+
* the same token and user. Profile updates and same-session refreshes keep it.
|
|
154
|
+
* Consumers can use it to discard stale async work without treating editable
|
|
155
|
+
* user fields as an immutable account identifier. Providers without this
|
|
156
|
+
* capability require the consumer's own stable identity check.
|
|
157
|
+
*/
|
|
158
|
+
getSessionRevision?(): number;
|
|
159
|
+
/**
|
|
160
|
+
* Updates the cached user object (state + persistent storage) without
|
|
161
|
+
* hitting the network. Intended for local refreshes after a per-app
|
|
162
|
+
* mutation (e.g., the user just PATCHed their own profile and the
|
|
163
|
+
* server returned the canonical row). Does NOT change tokens.
|
|
164
|
+
*
|
|
165
|
+
* This does not sign the client in: `authenticated` and `status` are
|
|
166
|
+
* unchanged, so an anonymous client stays anonymous. Use
|
|
167
|
+
* {@link login} / {@link register} for a credential exchange, or
|
|
168
|
+
* {@link setSession} when the token was issued outside the client.
|
|
169
|
+
*/
|
|
170
|
+
setUser(user: T | null): void;
|
|
171
|
+
/**
|
|
172
|
+
* Gets the current access token.
|
|
173
|
+
*/
|
|
174
|
+
getAccessToken(): string | null;
|
|
175
|
+
/**
|
|
176
|
+
* Stores the access token in the configured token storage adapter (in a
|
|
177
|
+
* browser, Web Storage; `'memory'` where no browser store exists). Use this
|
|
178
|
+
* to seed the token after an out-of-band exchange (e.g. the OAuth
|
|
179
|
+
* code→token redirect) instead of writing to `localStorage` directly,
|
|
180
|
+
* which would violate the storage contract and make a stored bearer token
|
|
181
|
+
* JS-readable (XSS-exfiltratable). Pass `null` to clear it.
|
|
182
|
+
*
|
|
183
|
+
* This changes token storage only; it does not sign the client in
|
|
184
|
+
* (`authenticated` and `status` are unchanged). Use {@link login} /
|
|
185
|
+
* {@link register} for a credential exchange, or call {@link setSession}
|
|
186
|
+
* with the token and the user to establish an already-issued session.
|
|
187
|
+
*/
|
|
188
|
+
setAccessToken(token: string | null): void;
|
|
189
|
+
/**
|
|
190
|
+
* Adopts a session an out-of-band exchange already established: stores the
|
|
191
|
+
* access token (and the refresh token when given), caches the user, and
|
|
192
|
+
* sets the COMPLETE state — `initialized`, `authenticated`, `status:
|
|
193
|
+
* 'authenticated'`, no error — in one update, with one subscriber
|
|
194
|
+
* notification. Every hook reading the shared client sees the user as
|
|
195
|
+
* signed in immediately.
|
|
196
|
+
*
|
|
197
|
+
* This is the way to seed an OAuth/custom sign-in. Calling
|
|
198
|
+
* {@link setAccessToken} and {@link setUser} instead does NOT sign the
|
|
199
|
+
* client in.
|
|
200
|
+
*/
|
|
201
|
+
setSession(session: AuthSessionSeed<T>): void;
|
|
202
|
+
/**
|
|
203
|
+
* Gets the refresh token.
|
|
204
|
+
*/
|
|
205
|
+
getRefreshToken(): string | null;
|
|
206
|
+
/**
|
|
207
|
+
* Logs in with credentials.
|
|
208
|
+
*/
|
|
209
|
+
login(credentials: LoginCredentials): Promise<AuthResult<T>>;
|
|
210
|
+
/**
|
|
211
|
+
* Logs out the current user.
|
|
212
|
+
*/
|
|
213
|
+
logout(): Promise<void>;
|
|
214
|
+
/**
|
|
215
|
+
* Registers a new user. Accepts the base fields plus the app's own fields
|
|
216
|
+
* (`TRegister`) at the top level — see {@link RegisterData}.
|
|
217
|
+
*/
|
|
218
|
+
register(data: RegisterData<TRegister>): Promise<AuthResult<T>>;
|
|
219
|
+
/**
|
|
220
|
+
* Refreshes the access token.
|
|
221
|
+
*/
|
|
222
|
+
refresh(): Promise<AuthResult<T>>;
|
|
223
|
+
/**
|
|
224
|
+
* Requests a password reset.
|
|
225
|
+
*/
|
|
226
|
+
requestPasswordReset(data: PasswordResetRequest): Promise<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Confirms a password reset.
|
|
229
|
+
*/
|
|
230
|
+
confirmPasswordReset(data: PasswordResetConfirm): Promise<void>;
|
|
231
|
+
/**
|
|
232
|
+
* Updates the current user's profile.
|
|
233
|
+
* Returns the saved response. If the session is explicitly replaced or ended
|
|
234
|
+
* while the request is pending, that response does not replace the current
|
|
235
|
+
* session's user or persisted cache.
|
|
236
|
+
*/
|
|
237
|
+
updateProfile(data: Partial<T>): Promise<T>;
|
|
238
|
+
/**
|
|
239
|
+
* Changes the current user's password.
|
|
240
|
+
*/
|
|
241
|
+
changePassword(oldPassword: string, newPassword: string): Promise<void>;
|
|
242
|
+
/**
|
|
243
|
+
* Initializes auth state (e.g., from stored tokens).
|
|
244
|
+
*
|
|
245
|
+
* LAZY and IDEMPOTENT: the first read of the state ({@link getState},
|
|
246
|
+
* {@link subscribe}, `useAuth()`) starts this same restore when nobody has called
|
|
247
|
+
* `initialize()`, and every later call shares the one promise instead of sending a
|
|
248
|
+
* second request. An app that keeps the template's explicit call behaves exactly as
|
|
249
|
+
* before; an app that loses that line still restores its session.
|
|
250
|
+
*
|
|
251
|
+
* With a stored token AND a stored user it marks the session `'authenticated'`
|
|
252
|
+
* SYNCHRONOUSLY — before its first `await` — so the first render is the
|
|
253
|
+
* signed-in UI and no page waits on a verification round trip. Any check
|
|
254
|
+
* (a refresh, the cookie-restore probe) settles behind that render, and only an
|
|
255
|
+
* explicit 401/403 ends the session; a network/5xx/404 failure keeps it and
|
|
256
|
+
* reports `'unavailable'`. With no stored user the client stays `'loading'`
|
|
257
|
+
* until the cookie restore decides.
|
|
258
|
+
*
|
|
259
|
+
* Do not put this call (or a `/me` request of your own) in front of the first
|
|
260
|
+
* render, and do not render a loading screen over a session it just restored:
|
|
261
|
+
* `whenRestored()` already resolves as soon as the restore has settled, and the
|
|
262
|
+
* HTTP gate built on it holds requests for exactly that window.
|
|
263
|
+
*/
|
|
264
|
+
initialize(): Promise<void>;
|
|
265
|
+
/**
|
|
266
|
+
* Re-checks a restored session against the server, in the background — the
|
|
267
|
+
* boot-time validation an app with a stored token needs when a revoked or
|
|
268
|
+
* expired token must sign the user out. Call it AFTER the first render
|
|
269
|
+
* (`initialize()` restores synchronously from storage; this costs one request).
|
|
270
|
+
*
|
|
271
|
+
* - The server confirms the user: the session is refreshed and {@link AuthState.status}
|
|
272
|
+
* stays `'authenticated'`.
|
|
273
|
+
* - The server answers 401 or 403: the token is dead — the stored session is
|
|
274
|
+
* cleared and the status becomes `'unauthenticated'`.
|
|
275
|
+
* - The server cannot confirm the session — a network failure, a 5xx, or a 404
|
|
276
|
+
* from a misconfigured {@link AuthClientConfig.currentUserEndpoint}: the
|
|
277
|
+
* session (token AND user) is KEPT and the status becomes `'unavailable'`, so
|
|
278
|
+
* the app can retry instead of signing the user out over a bad connection or a
|
|
279
|
+
* route that does not exist. The 404 error names `currentUserEndpoint`.
|
|
280
|
+
*
|
|
281
|
+
* Do not hand-write this beside the client: a parallel token/user store for a
|
|
282
|
+
* "validating"/"unavailable" flag is the race this method removes.
|
|
283
|
+
*
|
|
284
|
+
* Optional: a provider with no restorable session has nothing to validate.
|
|
285
|
+
*/
|
|
286
|
+
validateSession?(): Promise<void>;
|
|
287
|
+
/**
|
|
288
|
+
* Resolves when the session restore started by `initialize()` has settled — the point
|
|
289
|
+
* after which the client knows whether this visitor is signed in.
|
|
290
|
+
*
|
|
291
|
+
* Resolves IMMEDIATELY when no restore is in flight: before `initialize()` is ever
|
|
292
|
+
* called, and after it has finished. A restore that failed resolves too (it settled the
|
|
293
|
+
* question), so an HTTP client can await this before every request without risking one
|
|
294
|
+
// … truncated — the full declaration is in node_modules/@molecule/app-angular/dist
|
|
280
295
|
```
|
|
281
296
|
|
|
282
297
|
#### `FormController`
|
|
@@ -358,7 +373,13 @@ interface FormController<T extends Record<string, unknown> = Record<string, unkn
|
|
|
358
373
|
*/
|
|
359
374
|
validate(): Promise<boolean>
|
|
360
375
|
/**
|
|
361
|
-
* Resets the form
|
|
376
|
+
* Resets the form and clears errors, touched fields and submission state.
|
|
377
|
+
*
|
|
378
|
+
* With no argument it restores the current baseline — the initial
|
|
379
|
+
* `defaultValues`, or the values a previous `reset(values)` established.
|
|
380
|
+
* Passing `values` merges them over the current baseline and makes the
|
|
381
|
+
* result the new baseline, so a form reset to freshly loaded or saved data
|
|
382
|
+
* reads clean (`isDirty === false`).
|
|
362
383
|
*/
|
|
363
384
|
reset(values?: Partial<T>): void
|
|
364
385
|
/**
|
|
@@ -390,7 +411,8 @@ Form creation options.
|
|
|
390
411
|
```typescript
|
|
391
412
|
interface FormOptions<T extends Record<string, unknown>> {
|
|
392
413
|
/**
|
|
393
|
-
* Default values
|
|
414
|
+
* Default values, captured as the form's clean baseline when the controller
|
|
415
|
+
* is created. Mutating this object afterwards does not change the baseline.
|
|
394
416
|
*/
|
|
395
417
|
defaultValues?: Partial<T>
|
|
396
418
|
/**
|
|
@@ -431,7 +453,8 @@ interface HttpClient {
|
|
|
431
453
|
*/
|
|
432
454
|
defaultHeaders: Record<string, string>
|
|
433
455
|
/**
|
|
434
|
-
* Makes a generic HTTP request.
|
|
456
|
+
* Makes a generic HTTP request. `data` is a field of THIS config object — the same body
|
|
457
|
+
* `post(url, data, config)` takes as its second argument.
|
|
435
458
|
*/
|
|
436
459
|
request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
|
|
437
460
|
/**
|
|
@@ -439,15 +462,19 @@ interface HttpClient {
|
|
|
439
462
|
*/
|
|
440
463
|
get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
441
464
|
/**
|
|
442
|
-
* Makes a POST request.
|
|
465
|
+
* Makes a POST request. `data` is the request BODY, not a config object: the wire body is
|
|
466
|
+
* `data` itself, so `post(url, { data: body })` sends `{"data":body}` — pass `body` directly.
|
|
467
|
+
* A config (headers, params) is the THIRD argument.
|
|
443
468
|
*/
|
|
444
469
|
post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
445
470
|
/**
|
|
446
|
-
* Makes a PUT request.
|
|
471
|
+
* Makes a PUT request. `data` is the request BODY (second argument) — never `{ data: body }`,
|
|
472
|
+
* which sends `{"data":body}`; a config is the THIRD argument.
|
|
447
473
|
*/
|
|
448
474
|
put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
449
475
|
/**
|
|
450
|
-
* Makes a PATCH request.
|
|
476
|
+
* Makes a PATCH request. `data` is the request BODY (second argument) — never `{ data: body }`,
|
|
477
|
+
* which sends `{"data":body}`; a config is the THIRD argument.
|
|
451
478
|
*/
|
|
452
479
|
patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
|
|
453
480
|
/**
|
|
@@ -486,18 +513,6 @@ interface HttpClient {
|
|
|
486
513
|
}
|
|
487
514
|
```
|
|
488
515
|
|
|
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
516
|
#### `I18nProvider`
|
|
502
517
|
|
|
503
518
|
i18n provider interface.
|
|
@@ -756,244 +771,55 @@ interface LoggerProvider {
|
|
|
756
771
|
}
|
|
757
772
|
```
|
|
758
773
|
|
|
759
|
-
#### `
|
|
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
|
+
#### `RouteLocation`
|
|
774
775
|
|
|
775
|
-
|
|
776
|
+
Current URL decomposed into pathname, search string, hash, navigation state, and unique key.
|
|
776
777
|
|
|
777
778
|
```typescript
|
|
778
|
-
interface
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
779
|
+
interface RouteLocation {
|
|
780
|
+
/**
|
|
781
|
+
* Current pathname.
|
|
782
|
+
*/
|
|
783
|
+
pathname: string
|
|
784
|
+
/**
|
|
785
|
+
* Query string (including leading ?).
|
|
786
|
+
*/
|
|
787
|
+
search: string
|
|
788
|
+
/**
|
|
789
|
+
* Hash (including leading #).
|
|
790
|
+
*/
|
|
791
|
+
hash: string
|
|
792
|
+
/**
|
|
793
|
+
* State data passed with navigation.
|
|
794
|
+
*/
|
|
795
|
+
state?: unknown
|
|
796
|
+
/**
|
|
797
|
+
* Unique key for this location.
|
|
798
|
+
*/
|
|
799
|
+
key?: string
|
|
787
800
|
}
|
|
788
801
|
```
|
|
789
802
|
|
|
790
|
-
#### `
|
|
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
|
-
```
|
|
803
|
+
#### `Router`
|
|
806
804
|
|
|
807
|
-
|
|
805
|
+
Client-side router providing navigation, guards, route matching, and history control.
|
|
808
806
|
|
|
809
|
-
|
|
807
|
+
All routing providers must implement this interface.
|
|
810
808
|
|
|
811
809
|
```typescript
|
|
812
|
-
interface
|
|
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
|
|
810
|
+
interface Router {
|
|
823
811
|
/**
|
|
824
|
-
*
|
|
825
|
-
* also emitted on {@link OAuthStateManager.error$}.
|
|
812
|
+
* Returns the current route location (pathname, search, hash, state).
|
|
826
813
|
*/
|
|
827
|
-
|
|
814
|
+
getLocation(): RouteLocation
|
|
828
815
|
/**
|
|
829
|
-
*
|
|
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}).
|
|
816
|
+
* Gets the current route params.
|
|
834
817
|
*/
|
|
835
|
-
|
|
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[]>
|
|
818
|
+
getParams<T extends RouteParams = RouteParams>(): T
|
|
847
819
|
/**
|
|
848
|
-
*
|
|
849
|
-
* Completed by {@link OAuthStateManager.destroy}.
|
|
820
|
+
* Gets the current query params.
|
|
850
821
|
*/
|
|
851
|
-
|
|
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
|
|
822
|
+
getQuery(): QueryParams
|
|
997
823
|
/**
|
|
998
824
|
* Gets a specific query parameter.
|
|
999
825
|
*/
|
|
@@ -1079,17 +905,52 @@ interface Router {
|
|
|
1079
905
|
}
|
|
1080
906
|
```
|
|
1081
907
|
|
|
1082
|
-
#### `
|
|
908
|
+
#### `StoreConfig`
|
|
1083
909
|
|
|
1084
|
-
|
|
910
|
+
Configuration for creating a store (initial state, optional name, and middleware chain).
|
|
1085
911
|
|
|
1086
912
|
```typescript
|
|
1087
|
-
interface
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
913
|
+
interface StoreConfig<T> {
|
|
914
|
+
/**
|
|
915
|
+
* Initial state value.
|
|
916
|
+
*/
|
|
917
|
+
initialState: T
|
|
918
|
+
/**
|
|
919
|
+
* Optional name for debugging.
|
|
920
|
+
*/
|
|
921
|
+
name?: string
|
|
922
|
+
/**
|
|
923
|
+
* Optional middleware functions.
|
|
924
|
+
*/
|
|
925
|
+
middleware?: StoreMiddleware<T>[]
|
|
926
|
+
}
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
#### `Store`
|
|
930
|
+
|
|
931
|
+
Reactive state container with getState, setState, subscribe, and destroy.
|
|
932
|
+
|
|
933
|
+
All state management providers must implement this interface.
|
|
934
|
+
|
|
935
|
+
```typescript
|
|
936
|
+
interface Store<T> {
|
|
937
|
+
/**
|
|
938
|
+
* Gets the current state.
|
|
939
|
+
*/
|
|
940
|
+
getState(): T
|
|
941
|
+
/**
|
|
942
|
+
* Sets the state (partial or via updater function).
|
|
943
|
+
*/
|
|
944
|
+
setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
|
|
945
|
+
/**
|
|
946
|
+
* Subscribes to state changes.
|
|
947
|
+
* Returns an unsubscribe function.
|
|
948
|
+
*/
|
|
949
|
+
subscribe(listener: StateListener<T>): () => void
|
|
950
|
+
/**
|
|
951
|
+
* Destroys the store and cleans up subscriptions.
|
|
952
|
+
*/
|
|
953
|
+
destroy(): void
|
|
1093
954
|
}
|
|
1094
955
|
```
|
|
1095
956
|
|
|
@@ -1150,246 +1011,1748 @@ interface StorageProvider {
|
|
|
1150
1011
|
}
|
|
1151
1012
|
```
|
|
1152
1013
|
|
|
1153
|
-
#### `
|
|
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.
|
|
1014
|
+
#### `ThemeProvider`
|
|
1168
1015
|
|
|
1169
|
-
|
|
1016
|
+
Manages theme state including the active theme, mode toggling,
|
|
1017
|
+
and change subscriptions.
|
|
1170
1018
|
|
|
1171
1019
|
```typescript
|
|
1172
|
-
interface
|
|
1020
|
+
interface ThemeProvider {
|
|
1173
1021
|
/**
|
|
1174
|
-
*
|
|
1022
|
+
* Returns the currently active theme.
|
|
1175
1023
|
*/
|
|
1176
|
-
|
|
1024
|
+
getTheme(): Theme
|
|
1177
1025
|
/**
|
|
1178
|
-
* Sets the
|
|
1026
|
+
* Sets the active theme by reference or by name.
|
|
1027
|
+
*
|
|
1028
|
+
* @param theme - A `Theme` object or a theme name string to activate.
|
|
1179
1029
|
*/
|
|
1180
|
-
|
|
1030
|
+
setTheme(theme: Theme | string): void
|
|
1181
1031
|
/**
|
|
1182
|
-
*
|
|
1183
|
-
* Returns an unsubscribe function.
|
|
1032
|
+
* Toggles between light and dark mode for the active theme.
|
|
1184
1033
|
*/
|
|
1185
|
-
|
|
1034
|
+
toggleMode(): void
|
|
1186
1035
|
/**
|
|
1187
|
-
*
|
|
1036
|
+
* Subscribes to theme changes. The callback fires whenever
|
|
1037
|
+
* `setTheme()` or `toggleMode()` is called.
|
|
1038
|
+
*
|
|
1039
|
+
* @param callback - Invoked with the new theme after each change.
|
|
1040
|
+
* @returns An unsubscribe function.
|
|
1188
1041
|
*/
|
|
1189
|
-
|
|
1042
|
+
subscribe(callback: (theme: Theme) => void): () => void
|
|
1043
|
+
/**
|
|
1044
|
+
* Returns all registered themes. Optional — not all providers
|
|
1045
|
+
* support multiple themes.
|
|
1046
|
+
*/
|
|
1047
|
+
getThemes?(): Theme[]
|
|
1048
|
+
/**
|
|
1049
|
+
* Returns the theme a render WITHOUT a browser produces — a server or
|
|
1050
|
+
* build-time render, which has no storage and no `prefers-color-scheme`
|
|
1051
|
+
* to read. A hydrating client renders this theme first, so its markup
|
|
1052
|
+
* matches what the server sent, and switches to `getTheme()` right
|
|
1053
|
+
* after. Optional — a provider whose theme cannot differ between the two
|
|
1054
|
+
* need not implement it.
|
|
1055
|
+
*/
|
|
1056
|
+
getServerTheme?(): Theme
|
|
1190
1057
|
}
|
|
1191
1058
|
```
|
|
1192
1059
|
|
|
1193
|
-
#### `
|
|
1060
|
+
#### `Theme`
|
|
1194
1061
|
|
|
1195
|
-
|
|
1062
|
+
Complete theme definition.
|
|
1196
1063
|
|
|
1197
1064
|
```typescript
|
|
1198
|
-
interface
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1065
|
+
interface Theme {
|
|
1066
|
+
name: string
|
|
1067
|
+
mode: 'light' | 'dark'
|
|
1068
|
+
colors: ThemeColors
|
|
1069
|
+
breakpoints: ThemeBreakpoints
|
|
1070
|
+
spacing: ThemeSpacing
|
|
1071
|
+
typography: ThemeTypography
|
|
1072
|
+
borderRadius: ThemeBorderRadius
|
|
1073
|
+
shadows: ThemeShadows
|
|
1074
|
+
transitions: ThemeTransitions
|
|
1075
|
+
zIndex: ThemeZIndex
|
|
1076
|
+
}
|
|
1077
|
+
```
|
|
1078
|
+
|
|
1079
|
+
#### `AsyncStateManager`
|
|
1080
|
+
|
|
1081
|
+
Async state manager.
|
|
1082
|
+
|
|
1083
|
+
```typescript
|
|
1084
|
+
interface AsyncStateManager<T> {
|
|
1085
|
+
state$: Observable<T>
|
|
1086
|
+
getState: () => T
|
|
1087
|
+
setState: (value: T | ((prev: T) => T) | Promise<T | ((prev: T) => T)>) => void
|
|
1088
|
+
extendState: (
|
|
1089
|
+
partial:
|
|
1090
|
+
Partial<T> | ((prev: T) => Partial<T>) | Promise<Partial<T> | ((prev: T) => Partial<T>)>,
|
|
1091
|
+
) => void
|
|
1092
|
+
destroy: () => void
|
|
1093
|
+
}
|
|
1094
|
+
```
|
|
1095
|
+
|
|
1096
|
+
#### `CapacitorAppManager`
|
|
1097
|
+
|
|
1098
|
+
Capacitor app manager interface.
|
|
1099
|
+
|
|
1100
|
+
```typescript
|
|
1101
|
+
interface CapacitorAppManager {
|
|
1102
|
+
state$: Observable<CapacitorAppState>
|
|
1103
|
+
ready$: Observable<boolean>
|
|
1104
|
+
initialize: () => Promise<void>
|
|
1105
|
+
destroy: () => void
|
|
1106
|
+
}
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
#### `ChangePasswordStateManager`
|
|
1110
|
+
|
|
1111
|
+
Change password state manager.
|
|
1112
|
+
|
|
1113
|
+
```typescript
|
|
1114
|
+
interface ChangePasswordStateManager {
|
|
1115
|
+
state$: Observable<PromiseState<void>>
|
|
1116
|
+
getState: () => PromiseState<void>
|
|
1117
|
+
changePassword: (oldPassword: string, newPassword: string) => Promise<void>
|
|
1118
|
+
reset: () => void
|
|
1119
|
+
destroy: () => void
|
|
1120
|
+
}
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
#### `DeviceService`
|
|
1124
|
+
|
|
1125
|
+
Device service interface.
|
|
1126
|
+
|
|
1127
|
+
```typescript
|
|
1128
|
+
interface DeviceService {
|
|
1129
|
+
deviceInfo: DeviceInfo
|
|
1130
|
+
screenInfo: ScreenInfo
|
|
1131
|
+
hardwareInfo: HardwareInfo
|
|
1132
|
+
featureSupport: FeatureSupport
|
|
1133
|
+
supports: (feature: keyof FeatureSupport) => boolean
|
|
1134
|
+
isOnline: () => boolean
|
|
1135
|
+
isStandalone: () => boolean
|
|
1136
|
+
language: string
|
|
1137
|
+
languages: string[]
|
|
1138
|
+
}
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
#### `HttpState`
|
|
1142
|
+
|
|
1143
|
+
State for HTTP requests.
|
|
1144
|
+
|
|
1145
|
+
```typescript
|
|
1146
|
+
interface HttpState<T> {
|
|
1147
|
+
data: T | null
|
|
1148
|
+
loading: boolean
|
|
1149
|
+
error: Error | null
|
|
1150
|
+
}
|
|
1151
|
+
```
|
|
1152
|
+
|
|
1153
|
+
#### `LoginStateManager`
|
|
1154
|
+
|
|
1155
|
+
Login state manager.
|
|
1156
|
+
|
|
1157
|
+
```typescript
|
|
1158
|
+
interface LoginStateManager<T = unknown> {
|
|
1159
|
+
state$: Observable<PromiseState<AuthResult<T>>>
|
|
1160
|
+
getState: () => PromiseState<AuthResult<T>>
|
|
1161
|
+
login: (credentials: LoginCredentials) => Promise<AuthResult<T>>
|
|
1162
|
+
reset: () => void
|
|
1163
|
+
destroy: () => void
|
|
1164
|
+
}
|
|
1165
|
+
```
|
|
1166
|
+
|
|
1167
|
+
#### `OAuthOptions`
|
|
1168
|
+
|
|
1169
|
+
OAuth configuration options.
|
|
1170
|
+
|
|
1171
|
+
```typescript
|
|
1172
|
+
interface OAuthOptions {
|
|
1173
|
+
/** Base URL for the API server (e.g. `https://api.example.com`). */
|
|
1174
|
+
baseURL?: string
|
|
1175
|
+
/** List of supported OAuth provider names (e.g. `['github', 'google']`). */
|
|
1176
|
+
oauthProviders?: string[]
|
|
1177
|
+
/** Path prefix for OAuth initiation routes. Defaults to `/oauth`. */
|
|
1178
|
+
oauthEndpoint?: string
|
|
1179
|
+
/** Path for the OAuth login POST endpoint. Defaults to `/users/log-in/oauth`. */
|
|
1180
|
+
loginEndpoint?: string
|
|
1181
|
+
/** Called after a successful OAuth login (session established). */
|
|
1182
|
+
onSuccess?: () => void
|
|
1183
|
+
/**
|
|
1184
|
+
* Called with a failure message when the OAuth login fails. Failures are
|
|
1185
|
+
* also emitted on {@link OAuthStateManager.error$}.
|
|
1186
|
+
*/
|
|
1187
|
+
onError?: (error: string) => void
|
|
1188
|
+
/**
|
|
1189
|
+
* Auth client used to establish the session after the code exchange. This
|
|
1190
|
+
* is THE way to wire session establishment in Angular: inject the
|
|
1191
|
+
* `AUTH_CLIENT` token and pass the client here. When omitted, the helper
|
|
1192
|
+
* falls back to the server-established httpOnly-cookie session (see
|
|
1193
|
+
* {@link OAuthStateManager.handleCallback}).
|
|
1194
|
+
*/
|
|
1195
|
+
authClient?: AuthClient<unknown>
|
|
1196
|
+
}
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
#### `OAuthStateManager`
|
|
1200
|
+
|
|
1201
|
+
OAuth state manager.
|
|
1202
|
+
|
|
1203
|
+
```typescript
|
|
1204
|
+
interface OAuthStateManager {
|
|
1205
|
+
/** Observable of the configured OAuth provider names. */
|
|
1206
|
+
providers$: Observable<string[]>
|
|
1207
|
+
/**
|
|
1208
|
+
* Observable of OAuth failure messages (from the callback code exchange).
|
|
1209
|
+
* Completed by {@link OAuthStateManager.destroy}.
|
|
1210
|
+
*/
|
|
1211
|
+
error$: Observable<string>
|
|
1212
|
+
/** Returns the configured OAuth provider names. */
|
|
1213
|
+
getProviders: () => string[]
|
|
1214
|
+
/** Builds the OAuth initiation URL for a provider. */
|
|
1215
|
+
getOAuthUrl: (provider: string) => string
|
|
1216
|
+
/** Starts the full-page redirect flow for a provider. */
|
|
1217
|
+
redirect: (provider: string) => void
|
|
1218
|
+
/**
|
|
1219
|
+
* Handles the OAuth callback: exchanges the `code` URL parameter for a
|
|
1220
|
+
* session. Invoked automatically at creation (see {@link createOAuthState});
|
|
1221
|
+
* exposed for callers that need to re-run it manually. No-ops unless
|
|
1222
|
+
* running in a browser with a `code` URL parameter and a stashed provider.
|
|
1223
|
+
*
|
|
1224
|
+
* When an auth client was provided, the session is established locally
|
|
1225
|
+
* (`setAccessToken` + `setUser` + `initialize`). When no client is
|
|
1226
|
+
* available, the server has already established the httpOnly-cookie
|
|
1227
|
+
* session during the exchange, so a user-carrying response still counts
|
|
1228
|
+
* as success.
|
|
1229
|
+
*/
|
|
1230
|
+
handleCallback: () => Promise<void>
|
|
1231
|
+
/** Completes the `providers$` and `error$` observables. */
|
|
1232
|
+
destroy: () => void
|
|
1233
|
+
}
|
|
1234
|
+
```
|
|
1235
|
+
|
|
1236
|
+
#### `PasswordResetStateManager`
|
|
1237
|
+
|
|
1238
|
+
Password reset state manager.
|
|
1239
|
+
|
|
1240
|
+
```typescript
|
|
1241
|
+
interface PasswordResetStateManager {
|
|
1242
|
+
requestState$: Observable<PromiseState<void>>
|
|
1243
|
+
confirmState$: Observable<PromiseState<void>>
|
|
1244
|
+
getRequestState: () => PromiseState<void>
|
|
1245
|
+
getConfirmState: () => PromiseState<void>
|
|
1246
|
+
requestReset: (data: PasswordResetRequest) => Promise<void>
|
|
1247
|
+
confirmReset: (data: PasswordResetConfirm) => Promise<void>
|
|
1248
|
+
reset: () => void
|
|
1249
|
+
destroy: () => void
|
|
1250
|
+
}
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
#### `PlatformService`
|
|
1254
|
+
|
|
1255
|
+
Platform service interface.
|
|
1256
|
+
|
|
1257
|
+
```typescript
|
|
1258
|
+
interface PlatformService {
|
|
1259
|
+
platform: Platform
|
|
1260
|
+
isNative: boolean
|
|
1261
|
+
isMobile: boolean
|
|
1262
|
+
isDesktop: boolean
|
|
1263
|
+
isWeb: boolean
|
|
1264
|
+
isDevelopment: boolean
|
|
1265
|
+
isProduction: boolean
|
|
1266
|
+
isPlatform: (...platforms: Platform[]) => boolean
|
|
1267
|
+
}
|
|
1268
|
+
```
|
|
1269
|
+
|
|
1270
|
+
#### `PromiseStateManager`
|
|
1271
|
+
|
|
1272
|
+
Promise state manager.
|
|
1273
|
+
|
|
1274
|
+
```typescript
|
|
1275
|
+
interface PromiseStateManager<T> {
|
|
1276
|
+
state$: Observable<PromiseState<T>>
|
|
1277
|
+
getState: () => PromiseState<T>
|
|
1278
|
+
call: (...args: any[]) => Promise<T>
|
|
1279
|
+
cancel: (message?: string) => void
|
|
1280
|
+
reset: () => void
|
|
1281
|
+
destroy: () => void
|
|
1282
|
+
}
|
|
1283
|
+
```
|
|
1284
|
+
|
|
1285
|
+
**Returns:** The result.
|
|
1286
|
+
|
|
1287
|
+
#### `PushService`
|
|
1288
|
+
|
|
1289
|
+
Push service interface.
|
|
1290
|
+
|
|
1291
|
+
```typescript
|
|
1292
|
+
interface PushService {
|
|
1293
|
+
permission$: Observable<PermissionStatus | null>
|
|
1294
|
+
token$: Observable<PushToken | null>
|
|
1295
|
+
getPermission: () => PermissionStatus | null
|
|
1296
|
+
getToken: () => PushToken | null
|
|
1297
|
+
checkPermission: () => Promise<PermissionStatus>
|
|
1298
|
+
requestPermission: () => Promise<PermissionStatus>
|
|
1299
|
+
register: (options?: PushRegisterOptions) => Promise<PushToken>
|
|
1300
|
+
unregister: () => Promise<void>
|
|
1301
|
+
onNotificationReceived: (listener: NotificationReceivedListener) => () => void
|
|
1302
|
+
onNotificationAction: (listener: NotificationActionListener) => () => void
|
|
1303
|
+
onTokenChange: (listener: TokenChangeListener) => () => void
|
|
1304
|
+
setBadge: (count: number) => Promise<void>
|
|
1305
|
+
clearBadge: () => Promise<void>
|
|
1306
|
+
destroy: () => void
|
|
1307
|
+
}
|
|
1308
|
+
```
|
|
1309
|
+
|
|
1310
|
+
#### `SignupStateManager`
|
|
1311
|
+
|
|
1312
|
+
Signup state manager.
|
|
1313
|
+
|
|
1314
|
+
```typescript
|
|
1315
|
+
interface SignupStateManager<T = unknown> {
|
|
1316
|
+
state$: Observable<PromiseState<AuthResult<T>>>
|
|
1317
|
+
getState: () => PromiseState<AuthResult<T>>
|
|
1318
|
+
signup: (data: RegisterData) => Promise<AuthResult<T>>
|
|
1319
|
+
reset: () => void
|
|
1320
|
+
destroy: () => void
|
|
1321
|
+
}
|
|
1322
|
+
```
|
|
1323
|
+
|
|
1324
|
+
#### `StorageValueState`
|
|
1325
|
+
|
|
1326
|
+
State for a storage value.
|
|
1327
|
+
|
|
1328
|
+
```typescript
|
|
1329
|
+
interface StorageValueState<T> {
|
|
1330
|
+
value: T | undefined
|
|
1331
|
+
loading: boolean
|
|
1332
|
+
error: Error | null
|
|
1333
|
+
}
|
|
1334
|
+
```
|
|
1335
|
+
|
|
1336
|
+
#### `VersionService`
|
|
1337
|
+
|
|
1338
|
+
Version service interface.
|
|
1339
|
+
|
|
1340
|
+
```typescript
|
|
1341
|
+
interface VersionService {
|
|
1342
|
+
state$: Observable<VersionState>
|
|
1343
|
+
isUpdateAvailable$: Observable<boolean>
|
|
1344
|
+
isChecking$: Observable<boolean>
|
|
1345
|
+
isServiceWorkerWaiting$: Observable<boolean>
|
|
1346
|
+
newVersion$: Observable<string | undefined>
|
|
1347
|
+
getState: () => VersionState
|
|
1348
|
+
checkForUpdates: () => Promise<boolean>
|
|
1349
|
+
applyUpdate: (options?: { force?: boolean }) => void
|
|
1350
|
+
dismissUpdate: () => void
|
|
1351
|
+
startPeriodicChecks: (options?: UpdateCheckOptions) => void
|
|
1352
|
+
stopPeriodicChecks: () => void
|
|
1353
|
+
destroy: () => void
|
|
1354
|
+
}
|
|
1355
|
+
```
|
|
1356
|
+
|
|
1357
|
+
#### `MoleculeModuleConfig`
|
|
1358
|
+
|
|
1359
|
+
Configuration for molecule Angular module.
|
|
1360
|
+
|
|
1361
|
+
```typescript
|
|
1362
|
+
interface MoleculeModuleConfig {
|
|
1363
|
+
state?: StateProvider
|
|
1364
|
+
auth?: AuthClient<unknown>
|
|
1365
|
+
theme?: ThemeProvider
|
|
1366
|
+
router?: Router
|
|
1367
|
+
i18n?: I18nProvider
|
|
1368
|
+
http?: HttpClient
|
|
1369
|
+
storage?: StorageProvider
|
|
1370
|
+
logger?: LoggerProvider
|
|
1371
|
+
}
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
#### `MoleculeTokens`
|
|
1375
|
+
|
|
1376
|
+
Injection tokens for molecule services.
|
|
1377
|
+
|
|
1378
|
+
```typescript
|
|
1379
|
+
interface MoleculeTokens {
|
|
1380
|
+
STATE_PROVIDER: symbol
|
|
1381
|
+
AUTH_CLIENT: symbol
|
|
1382
|
+
THEME_PROVIDER: symbol
|
|
1383
|
+
ROUTER: symbol
|
|
1384
|
+
I18N_PROVIDER: symbol
|
|
1385
|
+
HTTP_CLIENT: symbol
|
|
1386
|
+
STORAGE_PROVIDER: symbol
|
|
1387
|
+
LOGGER_PROVIDER: symbol
|
|
1388
|
+
}
|
|
1389
|
+
```
|
|
1390
|
+
|
|
1391
|
+
### Types
|
|
1392
|
+
|
|
1393
|
+
#### `RouteParams`
|
|
1394
|
+
|
|
1395
|
+
URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
|
|
1396
|
+
|
|
1397
|
+
```typescript
|
|
1398
|
+
type RouteParams = Record<string, string>
|
|
1399
|
+
```
|
|
1400
|
+
|
|
1401
|
+
#### `QueryParams`
|
|
1402
|
+
|
|
1403
|
+
URL query string parameter map (single values or arrays for repeated keys).
|
|
1404
|
+
|
|
1405
|
+
```typescript
|
|
1406
|
+
type QueryParams = Record<string, string | string[] | undefined>
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
### Classes
|
|
1410
|
+
|
|
1411
|
+
#### `MoleculeAuthService`
|
|
1412
|
+
|
|
1413
|
+
Angular service for authentication.
|
|
1414
|
+
|
|
1415
|
+
Wraps molecule auth client and exposes state as RxJS observables.
|
|
1416
|
+
|
|
1417
|
+
```typescript
|
|
1418
|
+
@Injectable({
|
|
1419
|
+
providedIn: 'root',
|
|
1420
|
+
})
|
|
1421
|
+
export class MoleculeAuthService<
|
|
1422
|
+
T = unknown,
|
|
1423
|
+
TRegister extends RegisterExtraShape<TRegister> = Record<never, never>,
|
|
1424
|
+
> implements OnDestroy {
|
|
1425
|
+
private stateSubject: BehaviorSubject<AuthState<T>>
|
|
1426
|
+
private unsubscribe: (() => void) | null = null
|
|
1427
|
+
|
|
1428
|
+
/**
|
|
1429
|
+
* Observable of the full auth state.
|
|
1430
|
+
*/
|
|
1431
|
+
state$: Observable<AuthState<T>>
|
|
1432
|
+
|
|
1433
|
+
/**
|
|
1434
|
+
* Observable of the authenticated user.
|
|
1435
|
+
*/
|
|
1436
|
+
user$: Observable<T | null>
|
|
1437
|
+
|
|
1438
|
+
/**
|
|
1439
|
+
* Observable of authentication status.
|
|
1440
|
+
*/
|
|
1441
|
+
isAuthenticated$: Observable<boolean>
|
|
1442
|
+
|
|
1443
|
+
/**
|
|
1444
|
+
* Observable of loading status.
|
|
1445
|
+
*/
|
|
1446
|
+
isLoading$: Observable<boolean>
|
|
1447
|
+
|
|
1448
|
+
constructor(@Inject(AUTH_CLIENT) private client: AuthClient<T, TRegister>) {
|
|
1449
|
+
this.stateSubject = new BehaviorSubject<AuthState<T>>(client.getState())
|
|
1450
|
+
|
|
1451
|
+
this.unsubscribe = client.onAuthChange(() => {
|
|
1452
|
+
this.stateSubject.next(client.getState())
|
|
1453
|
+
})
|
|
1454
|
+
|
|
1455
|
+
this.state$ = this.stateSubject.asObservable()
|
|
1456
|
+
|
|
1457
|
+
this.user$ = this.state$.pipe(
|
|
1458
|
+
map((state) => state.user),
|
|
1459
|
+
distinctUntilChanged(),
|
|
1460
|
+
)
|
|
1461
|
+
|
|
1462
|
+
this.isAuthenticated$ = this.state$.pipe(
|
|
1463
|
+
map((state) => state.authenticated),
|
|
1464
|
+
distinctUntilChanged(),
|
|
1465
|
+
)
|
|
1466
|
+
|
|
1467
|
+
this.isLoading$ = this.state$.pipe(
|
|
1468
|
+
map((state) => state.loading),
|
|
1469
|
+
distinctUntilChanged(),
|
|
1470
|
+
)
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
/**
|
|
1474
|
+
* Get the current auth state snapshot.
|
|
1475
|
+
* @returns The current authentication state including user, loading, and authenticated flags.
|
|
1476
|
+
*/
|
|
1477
|
+
get state(): AuthState<T> {
|
|
1478
|
+
return this.client.getState()
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
/**
|
|
1482
|
+
* Get the current user snapshot.
|
|
1483
|
+
* @returns The authenticated user object, or `null` if not authenticated.
|
|
1484
|
+
*/
|
|
1485
|
+
get user(): T | null {
|
|
1486
|
+
return this.state.user
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* Check if user is currently authenticated.
|
|
1491
|
+
* @returns `true` if the user is authenticated, `false` otherwise.
|
|
1492
|
+
*/
|
|
1493
|
+
get isAuthenticated(): boolean {
|
|
1494
|
+
return this.state.authenticated
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
/**
|
|
1498
|
+
* Login with credentials.
|
|
1499
|
+
*
|
|
1500
|
+
* @param credentials - The email/password or provider-specific login credentials.
|
|
1501
|
+
* @returns A promise that resolves to the authentication result with user data and tokens.
|
|
1502
|
+
*/
|
|
1503
|
+
login(credentials: LoginCredentials): Promise<AuthResult<T>> {
|
|
1504
|
+
return this.client.login(credentials)
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
/**
|
|
1508
|
+
* Logout the current user.
|
|
1509
|
+
* @returns A promise that resolves when the user has been logged out.
|
|
1510
|
+
*/
|
|
1511
|
+
logout(): Promise<void> {
|
|
1512
|
+
return this.client.logout()
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/**
|
|
1516
|
+
* Register a new user.
|
|
1517
|
+
*
|
|
1518
|
+
* @param data - The registration payload including email, password, and profile fields.
|
|
1519
|
+
* @returns A promise that resolves to the authentication result for the newly registered user.
|
|
1520
|
+
*/
|
|
1521
|
+
register(data: RegisterData<TRegister>): Promise<AuthResult<T>> {
|
|
1522
|
+
return this.client.register(data)
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
* Refresh the authentication token.
|
|
1527
|
+
* @returns A promise that resolves to the authentication result with refreshed tokens.
|
|
1528
|
+
*/
|
|
1529
|
+
refresh(): Promise<AuthResult<T>> {
|
|
1530
|
+
return this.client.refresh()
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1533
|
+
/**
|
|
1534
|
+
* Clean up auth state subscription on service destruction.
|
|
1535
|
+
*/
|
|
1536
|
+
ngOnDestroy(): void {
|
|
1537
|
+
this.unsubscribe?.()
|
|
1538
|
+
this.stateSubject.complete()
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
```
|
|
1542
|
+
|
|
1543
|
+
#### `MoleculeFormInstance`
|
|
1544
|
+
|
|
1545
|
+
Wrapper around a FormController that provides RxJS observables and
|
|
1546
|
+
synchronous accessors for use in Angular components.
|
|
1547
|
+
|
|
1548
|
+
```typescript
|
|
1549
|
+
class MoleculeFormInstance<T extends Record<string, unknown>> {
|
|
1550
|
+
private stateSubject: BehaviorSubject<FormState<T>>
|
|
1551
|
+
private unsubscribe: (() => void) | null = null
|
|
1552
|
+
|
|
1553
|
+
/**
|
|
1554
|
+
* Observable of the full form state.
|
|
1555
|
+
*/
|
|
1556
|
+
state$: Observable<FormState<T>>
|
|
1557
|
+
|
|
1558
|
+
/**
|
|
1559
|
+
* Observable of form validity.
|
|
1560
|
+
*/
|
|
1561
|
+
isValid$: Observable<boolean>
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Observable of form dirty state.
|
|
1565
|
+
*/
|
|
1566
|
+
isDirty$: Observable<boolean>
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
* Observable of form submitting state.
|
|
1570
|
+
*/
|
|
1571
|
+
isSubmitting$: Observable<boolean>
|
|
1572
|
+
|
|
1573
|
+
/**
|
|
1574
|
+
* Observable of field errors.
|
|
1575
|
+
*/
|
|
1576
|
+
errors$: Observable<Partial<Record<keyof T, string>>>
|
|
1577
|
+
|
|
1578
|
+
constructor(private controller: FormController<T>) {
|
|
1579
|
+
this.stateSubject = new BehaviorSubject<FormState<T>>(controller.getState())
|
|
1580
|
+
|
|
1581
|
+
this.unsubscribe = controller.subscribe((state: FormState<T>) => {
|
|
1582
|
+
this.stateSubject.next(state)
|
|
1583
|
+
})
|
|
1584
|
+
|
|
1585
|
+
this.state$ = this.stateSubject.asObservable()
|
|
1586
|
+
|
|
1587
|
+
this.isValid$ = this.state$.pipe(
|
|
1588
|
+
map((state) => state.isValid),
|
|
1589
|
+
distinctUntilChanged(),
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
this.isDirty$ = this.state$.pipe(
|
|
1593
|
+
map((state) => state.isDirty),
|
|
1594
|
+
distinctUntilChanged(),
|
|
1595
|
+
)
|
|
1596
|
+
|
|
1597
|
+
this.isSubmitting$ = this.state$.pipe(
|
|
1598
|
+
map((state) => state.isSubmitting),
|
|
1599
|
+
distinctUntilChanged(),
|
|
1600
|
+
)
|
|
1601
|
+
|
|
1602
|
+
this.errors$ = this.state$.pipe(
|
|
1603
|
+
map((state) => state.errors),
|
|
1604
|
+
distinctUntilChanged(),
|
|
1605
|
+
)
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
/**
|
|
1609
|
+
* Get the current form state snapshot.
|
|
1610
|
+
* @returns The current form state including values, errors, validity, and submission status.
|
|
1611
|
+
*/
|
|
1612
|
+
get state(): FormState<T> {
|
|
1613
|
+
return this.controller.getState()
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
/**
|
|
1617
|
+
* Get the current form validity snapshot.
|
|
1618
|
+
* @returns `true` if all fields pass validation, `false` otherwise.
|
|
1619
|
+
*/
|
|
1620
|
+
get isValid(): boolean {
|
|
1621
|
+
return this.controller.getState().isValid
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
/**
|
|
1625
|
+
* Get the current form dirty state snapshot.
|
|
1626
|
+
* @returns `true` if any field has been modified from its default value, `false` otherwise.
|
|
1627
|
+
*/
|
|
1628
|
+
get isDirty(): boolean {
|
|
1629
|
+
return this.controller.getState().isDirty
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
/**
|
|
1633
|
+
* Get the current form submitting state snapshot.
|
|
1634
|
+
* @returns `true` if the form is currently being submitted, `false` otherwise.
|
|
1635
|
+
*/
|
|
1636
|
+
get isSubmitting(): boolean {
|
|
1637
|
+
return this.controller.getState().isSubmitting
|
|
1638
|
+
}
|
|
1639
|
+
|
|
1640
|
+
/**
|
|
1641
|
+
* Register a field for form management.
|
|
1642
|
+
*
|
|
1643
|
+
* @param name - The field name corresponding to a key in the form values type.
|
|
1644
|
+
* @param options - Registration options including validation rules and default value.
|
|
1645
|
+
* @returns The field registration with value, onChange, onBlur, and ref bindings.
|
|
1646
|
+
*/
|
|
1647
|
+
register(name: keyof T, options?: Omit<RegisterOptions, 'name'>): FieldRegistration {
|
|
1648
|
+
return this.controller.register({ ...options, name: name as string } as RegisterOptions)
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
/**
|
|
1652
|
+
* Get the value of a specific field.
|
|
1653
|
+
*
|
|
1654
|
+
* @param name - The field name corresponding to a key in the form values type.
|
|
1655
|
+
* @returns The current value of the specified field.
|
|
1656
|
+
*/
|
|
1657
|
+
getValue<K extends keyof T>(name: K): T[K] {
|
|
1658
|
+
return this.controller.getValue(name)
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
/**
|
|
1662
|
+
* Set the value of a specific field.
|
|
1663
|
+
*
|
|
1664
|
+
* @param name - The field name corresponding to a key in the form values type.
|
|
1665
|
+
* @param value - The new value to set for the field.
|
|
1666
|
+
*/
|
|
1667
|
+
setValue<K extends keyof T>(name: K, value: T[K]): void {
|
|
1668
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1669
|
+
this.controller.setValue(name as any, value as any)
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
/**
|
|
1673
|
+
* Get the error for a specific field.
|
|
1674
|
+
*
|
|
1675
|
+
* @param name - The field name to retrieve the error for.
|
|
1676
|
+
* @returns The error message for the field, or `undefined` if the field has no error.
|
|
1677
|
+
*/
|
|
1678
|
+
getError(name: keyof T): string | undefined {
|
|
1679
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1680
|
+
return this.controller.getError(name as any)
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
/**
|
|
1684
|
+
* Set the error for a specific field.
|
|
1685
|
+
*
|
|
1686
|
+
* @param name - The field name to set or clear the error for.
|
|
1687
|
+
* @param error - The error message to set, or `undefined` to clear the error.
|
|
1688
|
+
*/
|
|
1689
|
+
setError(name: keyof T, error: string | undefined): void {
|
|
1690
|
+
if (error !== undefined) {
|
|
1691
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1692
|
+
this.controller.setError(name as any, error)
|
|
1693
|
+
} else {
|
|
1694
|
+
this.controller.clearError(name)
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
/**
|
|
1699
|
+
* Clear all field errors.
|
|
1700
|
+
*/
|
|
1701
|
+
clearErrors(): void {
|
|
1702
|
+
this.controller.clearErrors()
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
/**
|
|
1706
|
+
* Create a submit handler function.
|
|
1707
|
+
*
|
|
1708
|
+
* @param onSubmit - Callback invoked with validated form values on successful submission.
|
|
1709
|
+
* @param onError - Optional callback invoked with field errors when validation fails.
|
|
1710
|
+
* @returns A submit handler function that can be called from form submit events.
|
|
1711
|
+
*/
|
|
1712
|
+
handleSubmit(
|
|
1713
|
+
onSubmit: (values: T) => void | Promise<void>,
|
|
1714
|
+
onError?: (errors: Partial<Record<keyof T, string>>) => void,
|
|
1715
|
+
): (event?: { preventDefault?: () => void }) => Promise<void> {
|
|
1716
|
+
return this.controller.handleSubmit(onSubmit, onError)
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
/**
|
|
1720
|
+
* Reset the form to initial values.
|
|
1721
|
+
*
|
|
1722
|
+
* @param values - Optional partial values to use as the new initial state.
|
|
1723
|
+
*/
|
|
1724
|
+
reset(values?: Partial<T>): void {
|
|
1725
|
+
this.controller.reset(values)
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/**
|
|
1729
|
+
* Validate all fields.
|
|
1730
|
+
*
|
|
1731
|
+
* @returns A promise that resolves to `true` if all fields are valid, `false` otherwise.
|
|
1732
|
+
*/
|
|
1733
|
+
validate(): Promise<boolean> {
|
|
1734
|
+
return this.controller.validate()
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
/**
|
|
1738
|
+
* Destroy the form instance and clean up subscriptions.
|
|
1739
|
+
*/
|
|
1740
|
+
destroy(): void {
|
|
1741
|
+
this.unsubscribe?.()
|
|
1742
|
+
this.unsubscribe = null
|
|
1743
|
+
this.stateSubject.complete()
|
|
1744
|
+
this.controller.destroy()
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
```
|
|
1748
|
+
|
|
1749
|
+
#### `MoleculeFormsService`
|
|
1750
|
+
|
|
1751
|
+
Angular service for form handling.
|
|
1752
|
+
|
|
1753
|
+
Wraps molecule form providers and creates form instances that expose
|
|
1754
|
+
state as RxJS observables.
|
|
1755
|
+
|
|
1756
|
+
```typescript
|
|
1757
|
+
@Injectable({
|
|
1758
|
+
providedIn: 'root',
|
|
1759
|
+
})
|
|
1760
|
+
export class MoleculeFormsService implements OnDestroy {
|
|
1761
|
+
private instances: MoleculeFormInstance<Record<string, unknown>>[] = []
|
|
1762
|
+
|
|
1763
|
+
/**
|
|
1764
|
+
* Create a form instance from a provider.
|
|
1765
|
+
*
|
|
1766
|
+
* @param provider - The form provider that creates form controllers.
|
|
1767
|
+
* @param options - Form configuration including default values and validation mode.
|
|
1768
|
+
* @returns A new form instance with RxJS observables for reactive state tracking.
|
|
1769
|
+
*/
|
|
1770
|
+
createForm<T extends Record<string, unknown>>(
|
|
1771
|
+
provider: FormProvider,
|
|
1772
|
+
options: FormOptions<T>,
|
|
1773
|
+
): MoleculeFormInstance<T> {
|
|
1774
|
+
const controller = provider.createForm(options)
|
|
1775
|
+
const instance = new MoleculeFormInstance<T>(controller)
|
|
1776
|
+
this.instances.push(instance as MoleculeFormInstance<Record<string, unknown>>)
|
|
1777
|
+
return instance
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
/**
|
|
1781
|
+
* Destroy all managed form instances on service destruction.
|
|
1782
|
+
*/
|
|
1783
|
+
ngOnDestroy(): void {
|
|
1784
|
+
for (const instance of this.instances) {
|
|
1785
|
+
instance.destroy()
|
|
1786
|
+
}
|
|
1787
|
+
this.instances = []
|
|
1788
|
+
}
|
|
1789
|
+
}
|
|
1790
|
+
```
|
|
1791
|
+
|
|
1792
|
+
#### `MoleculeHttpService`
|
|
1793
|
+
|
|
1794
|
+
Angular service for HTTP requests.
|
|
1795
|
+
|
|
1796
|
+
Wraps molecule HTTP client and returns RxJS observables.
|
|
1797
|
+
|
|
1798
|
+
```typescript
|
|
1799
|
+
@Injectable({
|
|
1800
|
+
providedIn: 'root',
|
|
1801
|
+
})
|
|
1802
|
+
/**
|
|
1803
|
+
* Molecule Http Service class.
|
|
1804
|
+
*/
|
|
1805
|
+
export class MoleculeHttpService {
|
|
1806
|
+
constructor(@Inject(HTTP_CLIENT) private client: HttpClient) {}
|
|
1807
|
+
|
|
1808
|
+
/**
|
|
1809
|
+
* Make a GET request.
|
|
1810
|
+
*
|
|
1811
|
+
* @param url - Request URL
|
|
1812
|
+
* @param config - Request configuration
|
|
1813
|
+
* @returns Observable of response data
|
|
1814
|
+
*/
|
|
1815
|
+
get<T>(url: string, config?: RequestConfig): Observable<T> {
|
|
1816
|
+
return from(this.client.get<T>(url, config)).pipe(map((res) => res.data))
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
/**
|
|
1820
|
+
* Make a POST request.
|
|
1821
|
+
*
|
|
1822
|
+
* @param url - Request URL
|
|
1823
|
+
* @param data - Request body
|
|
1824
|
+
* @param config - Request configuration
|
|
1825
|
+
* @returns Observable of response data
|
|
1826
|
+
*/
|
|
1827
|
+
post<T>(url: string, data?: unknown, config?: RequestConfig): Observable<T> {
|
|
1828
|
+
return from(this.client.post<T>(url, data, config)).pipe(map((res) => res.data))
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
/**
|
|
1832
|
+
* Make a PUT request.
|
|
1833
|
+
*
|
|
1834
|
+
* @param url - Request URL
|
|
1835
|
+
* @param data - Request body
|
|
1836
|
+
* @param config - Request configuration
|
|
1837
|
+
* @returns Observable of response data
|
|
1838
|
+
*/
|
|
1839
|
+
put<T>(url: string, data?: unknown, config?: RequestConfig): Observable<T> {
|
|
1840
|
+
return from(this.client.put<T>(url, data, config)).pipe(map((res) => res.data))
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
/**
|
|
1844
|
+
* Make a PATCH request.
|
|
1845
|
+
*
|
|
1846
|
+
* @param url - Request URL
|
|
1847
|
+
* @param data - Request body
|
|
1848
|
+
* @param config - Request configuration
|
|
1849
|
+
* @returns Observable of response data
|
|
1850
|
+
*/
|
|
1851
|
+
patch<T>(url: string, data?: unknown, config?: RequestConfig): Observable<T> {
|
|
1852
|
+
return from(this.client.patch<T>(url, data, config)).pipe(map((res) => res.data))
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
/**
|
|
1856
|
+
* Make a DELETE request.
|
|
1857
|
+
*
|
|
1858
|
+
* @param url - Request URL
|
|
1859
|
+
* @param config - Request configuration
|
|
1860
|
+
* @returns Observable of response data
|
|
1861
|
+
*/
|
|
1862
|
+
delete<T>(url: string, config?: RequestConfig): Observable<T> {
|
|
1863
|
+
return from(this.client.delete<T>(url, config)).pipe(map((res) => res.data))
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
/**
|
|
1867
|
+
* Get the full response (including headers, status, etc.).
|
|
1868
|
+
*
|
|
1869
|
+
* @param method - HTTP method
|
|
1870
|
+
* @param url - Request URL
|
|
1871
|
+
* @param config - Request configuration
|
|
1872
|
+
* @returns Observable of full response
|
|
1873
|
+
*/
|
|
1874
|
+
request<T>(
|
|
1875
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE',
|
|
1876
|
+
url: string,
|
|
1877
|
+
config?: RequestConfig,
|
|
1878
|
+
): Observable<HttpResponse<T>> {
|
|
1879
|
+
const promise = (async () => {
|
|
1880
|
+
switch (method) {
|
|
1881
|
+
case 'GET':
|
|
1882
|
+
return this.client.get<T>(url, config)
|
|
1883
|
+
case 'POST':
|
|
1884
|
+
return this.client.post<T>(
|
|
1885
|
+
url,
|
|
1886
|
+
(config as RequestConfig & { data?: unknown })?.data,
|
|
1887
|
+
config,
|
|
1888
|
+
)
|
|
1889
|
+
case 'PUT':
|
|
1890
|
+
return this.client.put<T>(
|
|
1891
|
+
url,
|
|
1892
|
+
(config as RequestConfig & { data?: unknown })?.data,
|
|
1893
|
+
config,
|
|
1894
|
+
)
|
|
1895
|
+
case 'PATCH':
|
|
1896
|
+
return this.client.patch<T>(
|
|
1897
|
+
url,
|
|
1898
|
+
(config as RequestConfig & { data?: unknown })?.data,
|
|
1899
|
+
config,
|
|
1900
|
+
)
|
|
1901
|
+
case 'DELETE':
|
|
1902
|
+
return this.client.delete<T>(url, config)
|
|
1903
|
+
}
|
|
1904
|
+
})()
|
|
1905
|
+
|
|
1906
|
+
return from(promise)
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
/**
|
|
1910
|
+
* Create a state subject for managing request state.
|
|
1911
|
+
*
|
|
1912
|
+
* @returns The created instance.
|
|
1913
|
+
*/
|
|
1914
|
+
createState<T>(): BehaviorSubject<HttpState<T>> {
|
|
1915
|
+
return new BehaviorSubject<HttpState<T>>({
|
|
1916
|
+
data: null,
|
|
1917
|
+
loading: false,
|
|
1918
|
+
error: null,
|
|
1919
|
+
})
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
/**
|
|
1923
|
+
* Make a GET request with state management.
|
|
1924
|
+
*
|
|
1925
|
+
* @param url - Request URL
|
|
1926
|
+
* @param state - State subject to update
|
|
1927
|
+
* @param config - Request configuration
|
|
1928
|
+
*/
|
|
1929
|
+
getWithState<T>(url: string, state: BehaviorSubject<HttpState<T>>, config?: RequestConfig): void {
|
|
1930
|
+
state.next({ ...state.value, loading: true, error: null })
|
|
1931
|
+
|
|
1932
|
+
this.get<T>(url, config)
|
|
1933
|
+
.pipe(
|
|
1934
|
+
tap((data) => state.next({ data, loading: false, error: null })),
|
|
1935
|
+
catchError((error) => {
|
|
1936
|
+
state.next({ data: null, loading: false, error })
|
|
1937
|
+
throw error
|
|
1938
|
+
}),
|
|
1939
|
+
)
|
|
1940
|
+
.subscribe()
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
```
|
|
1944
|
+
|
|
1945
|
+
#### `MoleculeI18nService`
|
|
1946
|
+
|
|
1947
|
+
Angular service for internationalization.
|
|
1948
|
+
|
|
1949
|
+
Wraps molecule i18n provider and exposes state as RxJS observables.
|
|
1950
|
+
|
|
1951
|
+
```typescript
|
|
1952
|
+
@Injectable({
|
|
1953
|
+
providedIn: 'root',
|
|
1954
|
+
})
|
|
1955
|
+
export class MoleculeI18nService implements OnDestroy {
|
|
1956
|
+
private localeSubject: BehaviorSubject<string>
|
|
1957
|
+
private directionSubject: BehaviorSubject<'ltr' | 'rtl'>
|
|
1958
|
+
private localesSubject: BehaviorSubject<LocaleConfig[]>
|
|
1959
|
+
private unsubscribe: (() => void) | null = null
|
|
1960
|
+
|
|
1961
|
+
/**
|
|
1962
|
+
* Observable of the current locale code.
|
|
1963
|
+
*/
|
|
1964
|
+
locale$: Observable<string>
|
|
1965
|
+
|
|
1966
|
+
/**
|
|
1967
|
+
* Observable of the text direction.
|
|
1968
|
+
*/
|
|
1969
|
+
direction$: Observable<'ltr' | 'rtl'>
|
|
1970
|
+
|
|
1971
|
+
/**
|
|
1972
|
+
* Observable of available locales.
|
|
1973
|
+
*/
|
|
1974
|
+
locales$: Observable<LocaleConfig[]>
|
|
1975
|
+
|
|
1976
|
+
constructor(@Inject(I18N_PROVIDER) private provider: I18nProvider) {
|
|
1977
|
+
this.localeSubject = new BehaviorSubject<string>(provider.getLocale())
|
|
1978
|
+
this.directionSubject = new BehaviorSubject<'ltr' | 'rtl'>(provider.getDirection())
|
|
1979
|
+
this.localesSubject = new BehaviorSubject<LocaleConfig[]>(provider.getLocales())
|
|
1980
|
+
|
|
1981
|
+
this.unsubscribe = provider.onLocaleChange(() => {
|
|
1982
|
+
this.localeSubject.next(provider.getLocale())
|
|
1983
|
+
this.directionSubject.next(provider.getDirection())
|
|
1984
|
+
this.localesSubject.next(provider.getLocales())
|
|
1985
|
+
})
|
|
1986
|
+
|
|
1987
|
+
this.locale$ = this.localeSubject.asObservable()
|
|
1988
|
+
this.direction$ = this.directionSubject.asObservable()
|
|
1989
|
+
this.locales$ = this.localesSubject.asObservable()
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
/**
|
|
1993
|
+
* Get the current locale code snapshot.
|
|
1994
|
+
* @returns The active locale code (e.g. `'en'`, `'fr'`).
|
|
1995
|
+
*/
|
|
1996
|
+
get locale(): string {
|
|
1997
|
+
return this.provider.getLocale()
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
/**
|
|
2001
|
+
* Get the current text direction snapshot.
|
|
2002
|
+
* @returns The text direction for the active locale, either `'ltr'` or `'rtl'`.
|
|
2003
|
+
*/
|
|
2004
|
+
get direction(): 'ltr' | 'rtl' {
|
|
2005
|
+
return this.provider.getDirection()
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
/**
|
|
2009
|
+
* Translate a key.
|
|
2010
|
+
*
|
|
2011
|
+
* @param key - The dot-notation translation key to look up.
|
|
2012
|
+
* @param values - Optional interpolation values to substitute into the translated string.
|
|
2013
|
+
* @returns The translated and interpolated string for the current locale.
|
|
2014
|
+
*/
|
|
2015
|
+
t(key: string, values?: InterpolationValues): string {
|
|
2016
|
+
return this.provider.t(key, values)
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
/**
|
|
2020
|
+
* Set the current locale.
|
|
2021
|
+
*
|
|
2022
|
+
* @param code - The locale code to switch to (e.g. `'en'`, `'fr'`).
|
|
2023
|
+
*/
|
|
2024
|
+
setLocale(code: string): void {
|
|
2025
|
+
this.provider.setLocale(code)
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
/**
|
|
2029
|
+
* Format a number.
|
|
2030
|
+
*
|
|
2031
|
+
* @param value - The number to format.
|
|
2032
|
+
* @param options - Locale-aware formatting options such as style, currency, and precision.
|
|
2033
|
+
* @returns The locale-formatted number string.
|
|
2034
|
+
*/
|
|
2035
|
+
formatNumber(value: number, options?: NumberFormatOptions): string {
|
|
2036
|
+
return this.provider.formatNumber(value, options)
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
/**
|
|
2040
|
+
* Format a date.
|
|
2041
|
+
*
|
|
2042
|
+
* @param value - The date to format, as a Date object, timestamp, or ISO string.
|
|
2043
|
+
* @param options - Locale-aware formatting options such as date style and time zone.
|
|
2044
|
+
* @returns The locale-formatted date string.
|
|
2045
|
+
*/
|
|
2046
|
+
formatDate(value: Date | number | string, options?: DateFormatOptions): string {
|
|
2047
|
+
return this.provider.formatDate(value, options)
|
|
2048
|
+
}
|
|
2049
|
+
|
|
2050
|
+
/**
|
|
2051
|
+
* Clean up locale change subscription and complete all subjects on service destruction.
|
|
2052
|
+
*/
|
|
2053
|
+
ngOnDestroy(): void {
|
|
2054
|
+
this.unsubscribe?.()
|
|
2055
|
+
this.localeSubject.complete()
|
|
2056
|
+
this.directionSubject.complete()
|
|
2057
|
+
this.localesSubject.complete()
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
```
|
|
2061
|
+
|
|
2062
|
+
#### `MoleculeLoggerService`
|
|
2063
|
+
|
|
2064
|
+
Angular service for logging.
|
|
2065
|
+
|
|
2066
|
+
Wraps molecule logger provider.
|
|
2067
|
+
|
|
2068
|
+
```typescript
|
|
2069
|
+
@Injectable({
|
|
2070
|
+
providedIn: 'root',
|
|
2071
|
+
})
|
|
2072
|
+
export class MoleculeLoggerService {
|
|
2073
|
+
constructor(@Inject(LOGGER_PROVIDER) private provider: LoggerProvider) {}
|
|
2074
|
+
|
|
2075
|
+
/**
|
|
2076
|
+
* Get a logger instance.
|
|
2077
|
+
*
|
|
2078
|
+
* @param name - Logger name (usually component/service name)
|
|
2079
|
+
* @returns The result.
|
|
2080
|
+
*/
|
|
2081
|
+
getLogger(name?: string): Logger {
|
|
2082
|
+
return this.provider.getLogger(name)
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
/**
|
|
2086
|
+
* Create a logger with custom configuration.
|
|
2087
|
+
*
|
|
2088
|
+
* @param config - Logger configuration
|
|
2089
|
+
* @returns The created instance.
|
|
2090
|
+
*/
|
|
2091
|
+
createLogger(config: LoggerConfig): Logger {
|
|
2092
|
+
return this.provider.createLogger(config)
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
/**
|
|
2096
|
+
* Set the global log level.
|
|
2097
|
+
*
|
|
2098
|
+
* @param level - Log level
|
|
2099
|
+
*/
|
|
2100
|
+
setLevel(level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent'): void {
|
|
2101
|
+
this.provider.setLevel(level)
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
/**
|
|
2105
|
+
* Get the current global log level.
|
|
2106
|
+
*
|
|
2107
|
+
* @returns The result.
|
|
2108
|
+
*/
|
|
2109
|
+
getLevel(): string {
|
|
2110
|
+
return this.provider.getLevel()
|
|
2111
|
+
}
|
|
2112
|
+
|
|
2113
|
+
/**
|
|
2114
|
+
* Enable logging.
|
|
2115
|
+
*/
|
|
2116
|
+
enable(): void {
|
|
2117
|
+
this.provider.enable()
|
|
2118
|
+
}
|
|
2119
|
+
|
|
2120
|
+
/**
|
|
2121
|
+
* Disable logging.
|
|
2122
|
+
*/
|
|
2123
|
+
disable(): void {
|
|
2124
|
+
this.provider.disable()
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
/**
|
|
2128
|
+
* Check if logging is enabled.
|
|
2129
|
+
*
|
|
2130
|
+
* @returns Whether logging is enabled
|
|
2131
|
+
*/
|
|
2132
|
+
isEnabled(): boolean {
|
|
2133
|
+
return this.provider.isEnabled()
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
```
|
|
2137
|
+
|
|
2138
|
+
#### `MoleculeRouterService`
|
|
2139
|
+
|
|
2140
|
+
Angular service for routing.
|
|
2141
|
+
|
|
2142
|
+
Wraps molecule router and exposes state as RxJS observables.
|
|
2143
|
+
|
|
2144
|
+
```typescript
|
|
2145
|
+
@Injectable({
|
|
2146
|
+
providedIn: 'root',
|
|
2147
|
+
})
|
|
2148
|
+
/**
|
|
2149
|
+
* Molecule Router Service class.
|
|
2150
|
+
*/
|
|
2151
|
+
export class MoleculeRouterService implements OnDestroy {
|
|
2152
|
+
private locationSubject: BehaviorSubject<RouteLocation>
|
|
2153
|
+
private paramsSubject: BehaviorSubject<RouteParams>
|
|
2154
|
+
private querySubject: BehaviorSubject<QueryParams>
|
|
2155
|
+
private unsubscribe: (() => void) | null = null
|
|
2156
|
+
|
|
2157
|
+
/**
|
|
2158
|
+
* Observable of the current location.
|
|
2159
|
+
*/
|
|
2160
|
+
location$: Observable<RouteLocation>
|
|
2161
|
+
|
|
2162
|
+
/**
|
|
2163
|
+
* Observable of route parameters.
|
|
2164
|
+
*/
|
|
2165
|
+
params$: Observable<RouteParams>
|
|
2166
|
+
|
|
2167
|
+
/**
|
|
2168
|
+
* Observable of query parameters.
|
|
2169
|
+
*/
|
|
2170
|
+
query$: Observable<QueryParams>
|
|
2171
|
+
|
|
2172
|
+
/**
|
|
2173
|
+
* Observable of the current pathname.
|
|
2174
|
+
*/
|
|
2175
|
+
pathname$: Observable<string>
|
|
2176
|
+
|
|
2177
|
+
constructor(@Inject(ROUTER) private router: Router) {
|
|
2178
|
+
this.locationSubject = new BehaviorSubject<RouteLocation>(router.getLocation())
|
|
2179
|
+
this.paramsSubject = new BehaviorSubject<RouteParams>(router.getParams())
|
|
2180
|
+
this.querySubject = new BehaviorSubject<QueryParams>(router.getQuery())
|
|
2181
|
+
|
|
2182
|
+
this.unsubscribe = router.subscribe(() => {
|
|
2183
|
+
this.locationSubject.next(router.getLocation())
|
|
2184
|
+
this.paramsSubject.next(router.getParams())
|
|
2185
|
+
this.querySubject.next(router.getQuery())
|
|
2186
|
+
})
|
|
2187
|
+
|
|
2188
|
+
this.location$ = this.locationSubject.asObservable()
|
|
2189
|
+
this.params$ = this.paramsSubject.asObservable()
|
|
2190
|
+
this.query$ = this.querySubject.asObservable()
|
|
2191
|
+
|
|
2192
|
+
this.pathname$ = this.location$.pipe(
|
|
2193
|
+
map((loc) => loc.pathname),
|
|
2194
|
+
distinctUntilChanged(),
|
|
2195
|
+
)
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2198
|
+
/**
|
|
2199
|
+
* Get the current location snapshot.
|
|
2200
|
+
* @returns The result.
|
|
2201
|
+
*/
|
|
2202
|
+
get location(): RouteLocation {
|
|
2203
|
+
return this.router.getLocation()
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
/**
|
|
2207
|
+
* Get the current params snapshot.
|
|
2208
|
+
* @returns The result.
|
|
1205
2209
|
*/
|
|
1206
|
-
|
|
2210
|
+
get params(): RouteParams {
|
|
2211
|
+
return this.router.getParams()
|
|
2212
|
+
}
|
|
2213
|
+
|
|
1207
2214
|
/**
|
|
1208
|
-
*
|
|
2215
|
+
* Get the current query snapshot.
|
|
2216
|
+
* @returns The result.
|
|
1209
2217
|
*/
|
|
1210
|
-
|
|
2218
|
+
get query(): QueryParams {
|
|
2219
|
+
return this.router.getQuery()
|
|
2220
|
+
}
|
|
2221
|
+
|
|
2222
|
+
/**
|
|
2223
|
+
* Navigate to a path.
|
|
2224
|
+
*
|
|
2225
|
+
* @param path - Target path
|
|
2226
|
+
* @param options - Navigation options
|
|
2227
|
+
*/
|
|
2228
|
+
navigate(path: string, options?: NavigateOptions): void {
|
|
2229
|
+
this.router.navigate(path, options)
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
/**
|
|
2233
|
+
* Navigate to a named route.
|
|
2234
|
+
*
|
|
2235
|
+
* @param name - Route name
|
|
2236
|
+
* @param params - Route parameters
|
|
2237
|
+
* @param query - Query parameters
|
|
2238
|
+
* @param options - Navigation options
|
|
2239
|
+
*/
|
|
2240
|
+
navigateTo(
|
|
2241
|
+
name: string,
|
|
2242
|
+
params?: RouteParams,
|
|
2243
|
+
query?: QueryParams,
|
|
2244
|
+
options?: NavigateOptions,
|
|
2245
|
+
): void {
|
|
2246
|
+
this.router.navigateTo(name, params, query, options)
|
|
2247
|
+
}
|
|
2248
|
+
|
|
2249
|
+
/**
|
|
2250
|
+
* Go back in history.
|
|
2251
|
+
*/
|
|
2252
|
+
back(): void {
|
|
2253
|
+
this.router.back()
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
/**
|
|
2257
|
+
* Go forward in history.
|
|
2258
|
+
*/
|
|
2259
|
+
forward(): void {
|
|
2260
|
+
this.router.forward()
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
/**
|
|
2264
|
+
* Check if a path is currently active.
|
|
2265
|
+
*
|
|
2266
|
+
* @param path - Path to check
|
|
2267
|
+
* @param exact - Whether to match exactly
|
|
2268
|
+
* @returns The result.
|
|
2269
|
+
*/
|
|
2270
|
+
isActive(path: string, exact = false): boolean {
|
|
2271
|
+
return this.router.isActive(path, exact)
|
|
2272
|
+
}
|
|
2273
|
+
|
|
2274
|
+
/**
|
|
2275
|
+
* Cleans up subscriptions and completes subjects on service destruction.
|
|
2276
|
+
*/
|
|
2277
|
+
ngOnDestroy(): void {
|
|
2278
|
+
this.unsubscribe?.()
|
|
2279
|
+
this.locationSubject.complete()
|
|
2280
|
+
this.paramsSubject.complete()
|
|
2281
|
+
this.querySubject.complete()
|
|
2282
|
+
}
|
|
1211
2283
|
}
|
|
1212
2284
|
```
|
|
1213
2285
|
|
|
1214
|
-
#### `
|
|
2286
|
+
#### `MoleculeStateService`
|
|
1215
2287
|
|
|
1216
|
-
|
|
2288
|
+
Angular service for state management.
|
|
2289
|
+
|
|
2290
|
+
Wraps molecule state stores and exposes them as RxJS observables.
|
|
1217
2291
|
|
|
1218
2292
|
```typescript
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
2293
|
+
@Injectable({
|
|
2294
|
+
providedIn: 'root',
|
|
2295
|
+
})
|
|
2296
|
+
/**
|
|
2297
|
+
* Molecule State Service class.
|
|
2298
|
+
*/
|
|
2299
|
+
export class MoleculeStateService implements OnDestroy {
|
|
2300
|
+
private subscriptions = new Map<Store<unknown>, () => void>()
|
|
2301
|
+
private subjects = new Map<Store<unknown>, BehaviorSubject<unknown>>()
|
|
2302
|
+
|
|
2303
|
+
constructor(@Inject(STATE_PROVIDER) private provider: StateProvider) {}
|
|
2304
|
+
|
|
2305
|
+
/**
|
|
2306
|
+
* Get an observable of the full store state.
|
|
2307
|
+
*
|
|
2308
|
+
* @param store - The store to observe
|
|
2309
|
+
* @returns Observable of the store state
|
|
2310
|
+
*/
|
|
2311
|
+
observe<T>(store: Store<T>): Observable<T> {
|
|
2312
|
+
return this.getOrCreateSubject(store).asObservable() as Observable<T>
|
|
2313
|
+
}
|
|
2314
|
+
|
|
2315
|
+
/**
|
|
2316
|
+
* Select a piece of state from a store.
|
|
2317
|
+
*
|
|
2318
|
+
* @param store - The store to select from
|
|
2319
|
+
* @param selector - Selector function
|
|
2320
|
+
* @returns Observable of the selected state
|
|
2321
|
+
*/
|
|
2322
|
+
select<T, S>(store: Store<T>, selector: (state: T) => S): Observable<S> {
|
|
2323
|
+
return this.observe(store).pipe(map(selector), distinctUntilChanged())
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
/**
|
|
2327
|
+
* Get the current snapshot of a store's state.
|
|
2328
|
+
*
|
|
2329
|
+
* @param store - The store
|
|
2330
|
+
* @returns The result.
|
|
2331
|
+
*/
|
|
2332
|
+
snapshot<T>(store: Store<T>): T {
|
|
2333
|
+
return store.getState()
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
/**
|
|
2337
|
+
* Update a store's state.
|
|
2338
|
+
*
|
|
2339
|
+
* @param store - The store to update
|
|
2340
|
+
* @param partial - Partial state or updater function
|
|
2341
|
+
*/
|
|
2342
|
+
update<T>(store: Store<T>, partial: Partial<T> | ((state: T) => Partial<T>)): void {
|
|
2343
|
+
store.setState(partial)
|
|
2344
|
+
}
|
|
2345
|
+
|
|
2346
|
+
/**
|
|
2347
|
+
* Gets or creates a BehaviorSubject for the given store.
|
|
2348
|
+
* @param store - The data store to observe.
|
|
2349
|
+
* @returns The BehaviorSubject tracking the store state.
|
|
2350
|
+
*/
|
|
2351
|
+
private getOrCreateSubject<T>(store: Store<T>): BehaviorSubject<T> {
|
|
2352
|
+
let subject = this.subjects.get(store as Store<unknown>) as BehaviorSubject<T> | undefined
|
|
2353
|
+
|
|
2354
|
+
if (!subject) {
|
|
2355
|
+
subject = new BehaviorSubject<T>(store.getState())
|
|
2356
|
+
this.subjects.set(store as Store<unknown>, subject as BehaviorSubject<unknown>)
|
|
2357
|
+
|
|
2358
|
+
const unsubscribe = store.subscribe(() => {
|
|
2359
|
+
subject!.next(store.getState())
|
|
2360
|
+
})
|
|
2361
|
+
this.subscriptions.set(store as Store<unknown>, unsubscribe)
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
return subject
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
/**
|
|
2368
|
+
* Cleans up all store subscriptions and completes subjects on service destruction.
|
|
2369
|
+
*/
|
|
2370
|
+
ngOnDestroy(): void {
|
|
2371
|
+
// Clean up all subscriptions
|
|
2372
|
+
this.subscriptions.forEach((unsubscribe) => unsubscribe())
|
|
2373
|
+
this.subscriptions.clear()
|
|
2374
|
+
|
|
2375
|
+
// Complete all subjects
|
|
2376
|
+
this.subjects.forEach((subject) => subject.complete())
|
|
2377
|
+
this.subjects.clear()
|
|
2378
|
+
}
|
|
1230
2379
|
}
|
|
1231
2380
|
```
|
|
1232
2381
|
|
|
1233
|
-
#### `
|
|
2382
|
+
#### `MoleculeStorageService`
|
|
1234
2383
|
|
|
1235
|
-
|
|
1236
|
-
|
|
2384
|
+
Angular service for storage.
|
|
2385
|
+
|
|
2386
|
+
Wraps molecule storage provider and returns RxJS observables.
|
|
1237
2387
|
|
|
1238
2388
|
```typescript
|
|
1239
|
-
|
|
2389
|
+
@Injectable({
|
|
2390
|
+
providedIn: 'root',
|
|
2391
|
+
})
|
|
2392
|
+
/**
|
|
2393
|
+
* Molecule Storage Service class.
|
|
2394
|
+
*/
|
|
2395
|
+
export class MoleculeStorageService {
|
|
2396
|
+
constructor(@Inject(STORAGE_PROVIDER) private provider: StorageProvider) {}
|
|
2397
|
+
|
|
1240
2398
|
/**
|
|
1241
|
-
*
|
|
2399
|
+
* Get a value from storage.
|
|
2400
|
+
*
|
|
2401
|
+
* @param key - Storage key
|
|
2402
|
+
* @returns Observable of the value
|
|
1242
2403
|
*/
|
|
1243
|
-
|
|
2404
|
+
get<T>(key: string): Observable<T | null> {
|
|
2405
|
+
return from(this.provider.get<T>(key))
|
|
2406
|
+
}
|
|
2407
|
+
|
|
1244
2408
|
/**
|
|
1245
|
-
*
|
|
2409
|
+
* Set a value in storage.
|
|
1246
2410
|
*
|
|
1247
|
-
* @param
|
|
2411
|
+
* @param key - Storage key
|
|
2412
|
+
* @param value - Value to store
|
|
2413
|
+
* @returns Observable that completes when done
|
|
1248
2414
|
*/
|
|
1249
|
-
|
|
2415
|
+
set<T>(key: string, value: T): Observable<void> {
|
|
2416
|
+
return from(this.provider.set(key, value))
|
|
2417
|
+
}
|
|
2418
|
+
|
|
1250
2419
|
/**
|
|
1251
|
-
*
|
|
2420
|
+
* Remove a value from storage.
|
|
2421
|
+
*
|
|
2422
|
+
* @param key - Storage key
|
|
2423
|
+
* @returns Observable that completes when done
|
|
1252
2424
|
*/
|
|
1253
|
-
|
|
2425
|
+
remove(key: string): Observable<void> {
|
|
2426
|
+
return from(this.provider.remove(key))
|
|
2427
|
+
}
|
|
2428
|
+
|
|
1254
2429
|
/**
|
|
1255
|
-
*
|
|
1256
|
-
* `setTheme()` or `toggleMode()` is called.
|
|
2430
|
+
* Clear all values from storage.
|
|
1257
2431
|
*
|
|
1258
|
-
* @
|
|
1259
|
-
* @returns An unsubscribe function.
|
|
2432
|
+
* @returns Observable that completes when done
|
|
1260
2433
|
*/
|
|
1261
|
-
|
|
2434
|
+
clear(): Observable<void> {
|
|
2435
|
+
return from(this.provider.clear())
|
|
2436
|
+
}
|
|
2437
|
+
|
|
1262
2438
|
/**
|
|
1263
|
-
*
|
|
1264
|
-
*
|
|
2439
|
+
* Get all keys in storage.
|
|
2440
|
+
*
|
|
2441
|
+
* @returns Observable of key array
|
|
1265
2442
|
*/
|
|
1266
|
-
|
|
2443
|
+
keys(): Observable<string[]> {
|
|
2444
|
+
return from(this.provider.keys())
|
|
2445
|
+
}
|
|
2446
|
+
|
|
1267
2447
|
/**
|
|
1268
|
-
*
|
|
1269
|
-
*
|
|
1270
|
-
*
|
|
1271
|
-
*
|
|
1272
|
-
*
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
2448
|
+
* Create a reactive storage value with auto-loading.
|
|
2449
|
+
*
|
|
2450
|
+
* @param key - Storage key
|
|
2451
|
+
* @param defaultValue - Default value if not found
|
|
2452
|
+
* @returns BehaviorSubject that syncs with storage
|
|
2453
|
+
*/
|
|
2454
|
+
createValue<T>(key: string, defaultValue: T): BehaviorSubject<StorageValueState<T>> {
|
|
2455
|
+
const state = new BehaviorSubject<StorageValueState<T>>({
|
|
2456
|
+
value: defaultValue,
|
|
2457
|
+
loading: true,
|
|
2458
|
+
error: null,
|
|
2459
|
+
})
|
|
2460
|
+
|
|
2461
|
+
// Load initial value
|
|
2462
|
+
this.get<T>(key).subscribe({
|
|
2463
|
+
next: (value) => {
|
|
2464
|
+
state.next({
|
|
2465
|
+
value: value ?? defaultValue,
|
|
2466
|
+
loading: false,
|
|
2467
|
+
error: null,
|
|
2468
|
+
})
|
|
2469
|
+
},
|
|
2470
|
+
error: (error) => {
|
|
2471
|
+
state.next({
|
|
2472
|
+
value: defaultValue,
|
|
2473
|
+
loading: false,
|
|
2474
|
+
error,
|
|
2475
|
+
})
|
|
2476
|
+
},
|
|
2477
|
+
})
|
|
2478
|
+
|
|
2479
|
+
return state
|
|
2480
|
+
}
|
|
2481
|
+
|
|
2482
|
+
/**
|
|
2483
|
+
* Update a reactive storage value.
|
|
2484
|
+
*
|
|
2485
|
+
* @param key - Storage key
|
|
2486
|
+
* @param value - New value
|
|
2487
|
+
* @param state - State subject to update
|
|
2488
|
+
*/
|
|
2489
|
+
updateValue<T>(key: string, value: T, state: BehaviorSubject<StorageValueState<T>>): void {
|
|
2490
|
+
state.next({ ...state.value, loading: true })
|
|
2491
|
+
|
|
2492
|
+
this.set(key, value).subscribe({
|
|
2493
|
+
next: () => {
|
|
2494
|
+
state.next({ value, loading: false, error: null })
|
|
2495
|
+
},
|
|
2496
|
+
error: (error) => {
|
|
2497
|
+
state.next({ ...state.value, loading: false, error })
|
|
2498
|
+
},
|
|
2499
|
+
})
|
|
2500
|
+
}
|
|
1276
2501
|
}
|
|
1277
2502
|
```
|
|
1278
2503
|
|
|
1279
|
-
#### `
|
|
2504
|
+
#### `MoleculeThemeService`
|
|
1280
2505
|
|
|
1281
|
-
|
|
2506
|
+
Angular service for theming.
|
|
2507
|
+
|
|
2508
|
+
Wraps molecule theme provider and exposes state as RxJS observables.
|
|
1282
2509
|
|
|
1283
2510
|
```typescript
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
2511
|
+
@Injectable({
|
|
2512
|
+
providedIn: 'root',
|
|
2513
|
+
})
|
|
2514
|
+
/**
|
|
2515
|
+
* Molecule Theme Service class.
|
|
2516
|
+
*/
|
|
2517
|
+
export class MoleculeThemeService implements OnDestroy {
|
|
2518
|
+
private themeSubject: BehaviorSubject<Theme>
|
|
2519
|
+
private themeNameSubject: BehaviorSubject<string>
|
|
2520
|
+
private unsubscribe: (() => void) | null = null
|
|
2521
|
+
|
|
2522
|
+
/**
|
|
2523
|
+
* Observable of the current theme.
|
|
2524
|
+
*/
|
|
2525
|
+
theme$: Observable<Theme>
|
|
2526
|
+
|
|
2527
|
+
/**
|
|
2528
|
+
* Observable of the current theme name.
|
|
2529
|
+
*/
|
|
2530
|
+
themeName$: Observable<string>
|
|
2531
|
+
|
|
2532
|
+
/**
|
|
2533
|
+
* Observable of the theme mode (light/dark).
|
|
2534
|
+
*/
|
|
2535
|
+
mode$: Observable<'light' | 'dark'>
|
|
2536
|
+
|
|
2537
|
+
constructor(@Inject(THEME_PROVIDER) private provider: ThemeProvider) {
|
|
2538
|
+
this.themeSubject = new BehaviorSubject<Theme>(provider.getTheme())
|
|
2539
|
+
this.themeNameSubject = new BehaviorSubject<string>(provider.getTheme().name)
|
|
2540
|
+
|
|
2541
|
+
this.unsubscribe = provider.subscribe(() => {
|
|
2542
|
+
this.themeSubject.next(provider.getTheme())
|
|
2543
|
+
this.themeNameSubject.next(provider.getTheme().name)
|
|
2544
|
+
})
|
|
2545
|
+
|
|
2546
|
+
this.theme$ = this.themeSubject.asObservable()
|
|
2547
|
+
this.themeName$ = this.themeNameSubject.asObservable()
|
|
2548
|
+
|
|
2549
|
+
this.mode$ = this.theme$.pipe(
|
|
2550
|
+
map((theme: Theme) => theme.mode),
|
|
2551
|
+
distinctUntilChanged(),
|
|
2552
|
+
)
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
/**
|
|
2556
|
+
* Get the current theme snapshot.
|
|
2557
|
+
* @returns The result.
|
|
2558
|
+
*/
|
|
2559
|
+
get theme(): Theme {
|
|
2560
|
+
return this.provider.getTheme()
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
/**
|
|
2564
|
+
* Get the current theme name snapshot.
|
|
2565
|
+
* @returns The result.
|
|
2566
|
+
*/
|
|
2567
|
+
get themeName(): string {
|
|
2568
|
+
return this.provider.getTheme().name
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2571
|
+
/**
|
|
2572
|
+
* Get available themes.
|
|
2573
|
+
* @returns The result.
|
|
2574
|
+
*/
|
|
2575
|
+
get themes(): Theme[] {
|
|
2576
|
+
return this.provider.getThemes?.() ?? []
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
/**
|
|
2580
|
+
* Set the current theme.
|
|
2581
|
+
*
|
|
2582
|
+
* @param name - Theme name
|
|
2583
|
+
*/
|
|
2584
|
+
setTheme(name: string): void {
|
|
2585
|
+
this.provider.setTheme(name)
|
|
2586
|
+
}
|
|
2587
|
+
|
|
2588
|
+
/**
|
|
2589
|
+
* Toggle to the next theme.
|
|
2590
|
+
*/
|
|
2591
|
+
toggleTheme(): void {
|
|
2592
|
+
const themes = this.themes
|
|
2593
|
+
const currentName = this.themeName
|
|
2594
|
+
const currentIndex = themes.findIndex((t: Theme) => t.name === currentName)
|
|
2595
|
+
const nextIndex = (currentIndex + 1) % themes.length
|
|
2596
|
+
this.provider.setTheme(themes[nextIndex])
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
/**
|
|
2600
|
+
* Cleans up subscriptions and completes subjects on service destruction.
|
|
2601
|
+
*/
|
|
2602
|
+
ngOnDestroy(): void {
|
|
2603
|
+
this.unsubscribe?.()
|
|
2604
|
+
this.themeSubject.complete()
|
|
2605
|
+
this.themeNameSubject.complete()
|
|
2606
|
+
}
|
|
1297
2607
|
}
|
|
1298
2608
|
```
|
|
1299
2609
|
|
|
1300
|
-
###
|
|
2610
|
+
### Functions
|
|
1301
2611
|
|
|
1302
|
-
#### `
|
|
2612
|
+
#### `bumpLocaleVersion()`
|
|
1303
2613
|
|
|
1304
|
-
|
|
2614
|
+
Bump the locale version signal, causing all template bindings that use
|
|
2615
|
+
the reactive `t()` to re-evaluate on the next change detection cycle.
|
|
2616
|
+
|
|
2617
|
+
Called automatically by the `ENVIRONMENT_INITIALIZER` in `provideMolecule`.
|
|
1305
2618
|
|
|
1306
2619
|
```typescript
|
|
1307
|
-
|
|
2620
|
+
function bumpLocaleVersion(): void
|
|
1308
2621
|
```
|
|
1309
2622
|
|
|
1310
|
-
#### `
|
|
2623
|
+
#### `t(key, values, options)`
|
|
1311
2624
|
|
|
1312
|
-
|
|
2625
|
+
Translate a key using the current locale.
|
|
2626
|
+
|
|
2627
|
+
This is a signal-aware wrapper around `@molecule/app-i18n`'s `t()`.
|
|
2628
|
+
Reading the internal locale signal establishes an Angular reactivity
|
|
2629
|
+
dependency, so template bindings that call this function will be
|
|
2630
|
+
re-evaluated when the locale changes.
|
|
1313
2631
|
|
|
1314
2632
|
```typescript
|
|
1315
|
-
|
|
2633
|
+
function t(
|
|
2634
|
+
key: string,
|
|
2635
|
+
values?: InterpolationValues,
|
|
2636
|
+
options?: { defaultValue?: string; count?: number },
|
|
2637
|
+
): string
|
|
1316
2638
|
```
|
|
1317
2639
|
|
|
1318
|
-
|
|
2640
|
+
- `key` — Translation key
|
|
2641
|
+
- `values` — Interpolation values
|
|
2642
|
+
- `options` — Options (defaultValue, count).
|
|
2643
|
+
- `options.defaultValue` — Fallback string when no translation is found.
|
|
2644
|
+
- `options.count` — Pluralization count.
|
|
2645
|
+
|
|
2646
|
+
**Returns:** Translated string
|
|
2647
|
+
|
|
2648
|
+
#### `provideState(provider)`
|
|
2649
|
+
|
|
2650
|
+
Provide state management.
|
|
2651
|
+
|
|
2652
|
+
```typescript
|
|
2653
|
+
function provideState(provider: StateProvider): EnvironmentProviders
|
|
2654
|
+
```
|
|
2655
|
+
|
|
2656
|
+
- `provider` — State provider
|
|
2657
|
+
|
|
2658
|
+
**Returns:** Environment providers
|
|
2659
|
+
|
|
2660
|
+
#### `provideAuth(client)`
|
|
2661
|
+
|
|
2662
|
+
Registers an AuthClient as an Angular environment provider for dependency injection.
|
|
2663
|
+
|
|
2664
|
+
```typescript
|
|
2665
|
+
function provideAuth(client: AuthClient<T, Record<never, never>>): EnvironmentProviders
|
|
2666
|
+
```
|
|
2667
|
+
|
|
2668
|
+
- `client` — Auth client
|
|
1319
2669
|
|
|
1320
|
-
|
|
2670
|
+
**Returns:** Environment providers
|
|
1321
2671
|
|
|
1322
|
-
|
|
2672
|
+
#### `provideTheme(provider)`
|
|
1323
2673
|
|
|
1324
|
-
|
|
2674
|
+
Registers a ThemeProvider as an Angular environment provider for dependency injection.
|
|
1325
2675
|
|
|
1326
|
-
|
|
2676
|
+
```typescript
|
|
2677
|
+
function provideTheme(provider: ThemeProvider): EnvironmentProviders
|
|
2678
|
+
```
|
|
1327
2679
|
|
|
1328
|
-
|
|
1329
|
-
synchronous accessors for use in Angular components.
|
|
2680
|
+
- `provider` — Theme provider
|
|
1330
2681
|
|
|
1331
|
-
|
|
2682
|
+
**Returns:** Environment providers
|
|
1332
2683
|
|
|
1333
|
-
|
|
2684
|
+
#### `provideRouter(router)`
|
|
1334
2685
|
|
|
1335
|
-
|
|
1336
|
-
state as RxJS observables.
|
|
2686
|
+
Registers a Router as an Angular environment provider for dependency injection.
|
|
1337
2687
|
|
|
1338
|
-
|
|
2688
|
+
```typescript
|
|
2689
|
+
function provideRouter(router: Router): EnvironmentProviders
|
|
2690
|
+
```
|
|
1339
2691
|
|
|
1340
|
-
|
|
2692
|
+
- `router` — Router instance
|
|
1341
2693
|
|
|
1342
|
-
|
|
2694
|
+
**Returns:** Environment providers
|
|
1343
2695
|
|
|
1344
|
-
#### `
|
|
2696
|
+
#### `provideI18n(provider)`
|
|
1345
2697
|
|
|
1346
|
-
Angular
|
|
2698
|
+
Registers an I18nProvider as an Angular environment provider for dependency injection.
|
|
1347
2699
|
|
|
1348
|
-
|
|
2700
|
+
```typescript
|
|
2701
|
+
function provideI18n(provider: I18nProvider): EnvironmentProviders
|
|
2702
|
+
```
|
|
1349
2703
|
|
|
1350
|
-
|
|
2704
|
+
- `provider` — I18n provider
|
|
1351
2705
|
|
|
1352
|
-
|
|
2706
|
+
**Returns:** Environment providers
|
|
1353
2707
|
|
|
1354
|
-
|
|
2708
|
+
#### `provideHttp(client)`
|
|
1355
2709
|
|
|
1356
|
-
|
|
2710
|
+
Provide HTTP client.
|
|
1357
2711
|
|
|
1358
|
-
|
|
2712
|
+
```typescript
|
|
2713
|
+
function provideHttp(client: HttpClient): EnvironmentProviders
|
|
2714
|
+
```
|
|
1359
2715
|
|
|
1360
|
-
|
|
2716
|
+
- `client` — HTTP client
|
|
1361
2717
|
|
|
1362
|
-
|
|
2718
|
+
**Returns:** Environment providers
|
|
1363
2719
|
|
|
1364
|
-
|
|
2720
|
+
#### `provideStorage(provider)`
|
|
1365
2721
|
|
|
1366
|
-
|
|
2722
|
+
Registers a StorageProvider as an Angular environment provider for dependency injection.
|
|
1367
2723
|
|
|
1368
|
-
|
|
2724
|
+
```typescript
|
|
2725
|
+
function provideStorage(provider: StorageProvider): EnvironmentProviders
|
|
2726
|
+
```
|
|
1369
2727
|
|
|
1370
|
-
|
|
2728
|
+
- `provider` — Storage provider
|
|
1371
2729
|
|
|
1372
|
-
|
|
2730
|
+
**Returns:** Environment providers
|
|
1373
2731
|
|
|
1374
|
-
#### `
|
|
2732
|
+
#### `provideLogger(provider)`
|
|
1375
2733
|
|
|
1376
|
-
Angular
|
|
2734
|
+
Registers a LoggerProvider as an Angular environment provider for dependency injection.
|
|
1377
2735
|
|
|
1378
|
-
|
|
2736
|
+
```typescript
|
|
2737
|
+
function provideLogger(provider: LoggerProvider): EnvironmentProviders
|
|
2738
|
+
```
|
|
1379
2739
|
|
|
1380
|
-
|
|
2740
|
+
- `provider` — Logger provider
|
|
1381
2741
|
|
|
1382
|
-
|
|
2742
|
+
**Returns:** Environment providers
|
|
1383
2743
|
|
|
1384
|
-
|
|
1385
|
-
the reactive `t()` to re-evaluate on the next change detection cycle.
|
|
2744
|
+
#### `provideMolecule(config)`
|
|
1386
2745
|
|
|
1387
|
-
|
|
2746
|
+
Provide all molecule services at once.
|
|
1388
2747
|
|
|
1389
2748
|
```typescript
|
|
1390
|
-
function
|
|
2749
|
+
function provideMolecule(config: MoleculeModuleConfig): EnvironmentProviders
|
|
1391
2750
|
```
|
|
1392
2751
|
|
|
2752
|
+
- `config` — Configuration with all providers
|
|
2753
|
+
|
|
2754
|
+
**Returns:** Environment providers
|
|
2755
|
+
|
|
1393
2756
|
#### `createAsyncState(initialState)`
|
|
1394
2757
|
|
|
1395
2758
|
Creates an async-capable state manager.
|
|
@@ -1422,7 +2785,9 @@ function createCapacitorAppState(options?: CapacitorAppOptions): CapacitorAppMan
|
|
|
1422
2785
|
Creates a change password state manager with async state tracking.
|
|
1423
2786
|
|
|
1424
2787
|
```typescript
|
|
1425
|
-
function createChangePasswordState(
|
|
2788
|
+
function createChangePasswordState(
|
|
2789
|
+
client: AuthClient<UserProfile, Record<never, never>>,
|
|
2790
|
+
): ChangePasswordStateManager
|
|
1426
2791
|
```
|
|
1427
2792
|
|
|
1428
2793
|
- `client` — Auth client
|
|
@@ -1444,7 +2809,7 @@ function createDeviceService(): DeviceService
|
|
|
1444
2809
|
Creates a login state manager with async state tracking.
|
|
1445
2810
|
|
|
1446
2811
|
```typescript
|
|
1447
|
-
function createLoginState(client: AuthClient<T
|
|
2812
|
+
function createLoginState(client: AuthClient<T, Record<never, never>>): LoginStateManager<T>
|
|
1448
2813
|
```
|
|
1449
2814
|
|
|
1450
2815
|
- `client` — Auth client
|
|
@@ -1472,7 +2837,9 @@ function createOAuthState(options?: OAuthOptions): OAuthStateManager
|
|
|
1472
2837
|
Creates a password reset state manager with async state tracking.
|
|
1473
2838
|
|
|
1474
2839
|
```typescript
|
|
1475
|
-
function createPasswordResetState(
|
|
2840
|
+
function createPasswordResetState(
|
|
2841
|
+
client: AuthClient<UserProfile, Record<never, never>>,
|
|
2842
|
+
): PasswordResetStateManager
|
|
1476
2843
|
```
|
|
1477
2844
|
|
|
1478
2845
|
- `client` — Auth client
|
|
@@ -1516,7 +2883,7 @@ function createPushService(): PushService
|
|
|
1516
2883
|
Creates a signup state manager with async state tracking.
|
|
1517
2884
|
|
|
1518
2885
|
```typescript
|
|
1519
|
-
function createSignupState(client: AuthClient<T
|
|
2886
|
+
function createSignupState(client: AuthClient<T, Record<never, never>>): SignupStateManager<T>
|
|
1520
2887
|
```
|
|
1521
2888
|
|
|
1522
2889
|
- `client` — Auth client
|
|
@@ -1533,155 +2900,38 @@ function createVersionService(): VersionService
|
|
|
1533
2900
|
|
|
1534
2901
|
**Returns:** The created instance.
|
|
1535
2902
|
|
|
1536
|
-
|
|
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
|
|
2903
|
+
### Constants
|
|
1631
2904
|
|
|
1632
|
-
#### `
|
|
2905
|
+
#### `STATE_PROVIDER`
|
|
1633
2906
|
|
|
1634
|
-
|
|
2907
|
+
Injection token for state provider.
|
|
1635
2908
|
|
|
1636
2909
|
```typescript
|
|
1637
|
-
|
|
2910
|
+
const STATE_PROVIDER: InjectionToken<StateProvider>
|
|
1638
2911
|
```
|
|
1639
2912
|
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
**Returns:** Environment providers
|
|
1643
|
-
|
|
1644
|
-
#### `t(key, values, options)`
|
|
1645
|
-
|
|
1646
|
-
Translate a key using the current locale.
|
|
2913
|
+
#### `AUTH_CLIENT`
|
|
1647
2914
|
|
|
1648
|
-
|
|
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.
|
|
2915
|
+
Injection token for auth client.
|
|
1652
2916
|
|
|
1653
2917
|
```typescript
|
|
1654
|
-
|
|
1655
|
-
key: string,
|
|
1656
|
-
values?: InterpolationValues,
|
|
1657
|
-
options?: { defaultValue?: string; count?: number },
|
|
1658
|
-
): string
|
|
2918
|
+
const AUTH_CLIENT: InjectionToken<AuthClient<unknown, Record<never, never>>>
|
|
1659
2919
|
```
|
|
1660
2920
|
|
|
1661
|
-
|
|
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`
|
|
2921
|
+
#### `THEME_PROVIDER`
|
|
1672
2922
|
|
|
1673
|
-
Injection token for
|
|
2923
|
+
Injection token for theme provider.
|
|
1674
2924
|
|
|
1675
2925
|
```typescript
|
|
1676
|
-
const
|
|
2926
|
+
const THEME_PROVIDER: InjectionToken<ThemeProvider>
|
|
1677
2927
|
```
|
|
1678
2928
|
|
|
1679
|
-
#### `
|
|
2929
|
+
#### `ROUTER`
|
|
1680
2930
|
|
|
1681
|
-
Injection token for
|
|
2931
|
+
Injection token for router.
|
|
1682
2932
|
|
|
1683
2933
|
```typescript
|
|
1684
|
-
const
|
|
2934
|
+
const ROUTER: InjectionToken<Router>
|
|
1685
2935
|
```
|
|
1686
2936
|
|
|
1687
2937
|
#### `I18N_PROVIDER`
|
|
@@ -1692,28 +2942,12 @@ Injection token for i18n provider.
|
|
|
1692
2942
|
const I18N_PROVIDER: InjectionToken<I18nProvider>
|
|
1693
2943
|
```
|
|
1694
2944
|
|
|
1695
|
-
#### `
|
|
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`
|
|
2945
|
+
#### `HTTP_CLIENT`
|
|
1712
2946
|
|
|
1713
|
-
Injection token for
|
|
2947
|
+
Injection token for HTTP client.
|
|
1714
2948
|
|
|
1715
2949
|
```typescript
|
|
1716
|
-
const
|
|
2950
|
+
const HTTP_CLIENT: InjectionToken<HttpClient>
|
|
1717
2951
|
```
|
|
1718
2952
|
|
|
1719
2953
|
#### `STORAGE_PROVIDER`
|
|
@@ -1724,12 +2958,12 @@ Injection token for storage provider.
|
|
|
1724
2958
|
const STORAGE_PROVIDER: InjectionToken<StorageProvider>
|
|
1725
2959
|
```
|
|
1726
2960
|
|
|
1727
|
-
#### `
|
|
2961
|
+
#### `LOGGER_PROVIDER`
|
|
1728
2962
|
|
|
1729
|
-
Injection token for
|
|
2963
|
+
Injection token for logger provider.
|
|
1730
2964
|
|
|
1731
2965
|
```typescript
|
|
1732
|
-
const
|
|
2966
|
+
const LOGGER_PROVIDER: InjectionToken<LoggerProvider>
|
|
1733
2967
|
```
|
|
1734
2968
|
|
|
1735
2969
|
## Injection Notes
|