@molecule/app-solid 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,15 +3,11 @@ 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-08-04T01:52:41.099Z
6
+ Generated: 2026-10-21T09:43:19.112Z
7
7
  -->
8
8
 
9
9
  # @molecule/app-solid
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
  Solid.js framework bindings for molecule.dev.
16
12
 
17
13
  Provides Solid-specific implementations of molecule.dev core interfaces
@@ -20,6 +16,10 @@ app in `MoleculeProvider` with a `config` of providers, then consume them
20
16
  through `createAuth`, `createTheme`, `createRouter`, `createI18n`, and the
21
17
  other primitives.
22
18
 
19
+ > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
20
+ > It is written to be read by coding agents as much as by people, and is generated from this
21
+ > package's source — edit `src/index.ts` JSDoc, not this file.
22
+
23
23
  ## Quick Start
24
24
 
25
25
  ```tsx
@@ -69,893 +69,1179 @@ npm install @molecule/app-solid @molecule/app-auth @molecule/app-device @molecul
69
69
 
70
70
  ### Interfaces
71
71
 
72
- #### `AuthClient`
72
+ #### `AuthState`
73
73
 
74
- Auth client interface that all auth bond packages must implement.
75
- Provides login/logout/register flows, token management, profile
76
- updates, and auth state subscription.
74
+ Reactive authentication state snapshot (initialized, authenticated, user, loading, and error).
77
75
 
78
76
  ```typescript
79
- interface AuthClient<T = UserProfile> {
77
+ interface AuthState<T = UserProfile> {
78
+ /**
79
+ * The session's state as one value — render from this instead of combining
80
+ * `initialized`/`authenticated`/`loading`. See {@link AuthStatus}.
81
+ */
82
+ status: AuthStatus
83
+ /**
84
+ * Whether auth state has been initialized.
85
+ */
86
+ initialized: boolean
87
+ /**
88
+ * Whether the user is authenticated.
89
+ */
90
+ authenticated: boolean
91
+ /**
92
+ * Current user (if authenticated).
93
+ */
94
+ user: T | null
80
95
  /**
81
- * Returns the current authentication state snapshot.
96
+ * Whether an auth operation is in progress.
82
97
  */
83
- getState(): AuthState<T>
98
+ loading: boolean
84
99
  /**
85
- * Returns whether the user is currently authenticated.
100
+ * Last auth error (if any).
86
101
  */
87
- isAuthenticated(): boolean
102
+ error: string | null
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, TRegister extends Record<string, unknown> = Record<never, never>> {
114
+ /**
115
+ * Returns the current authentication state snapshot.
116
+ *
117
+ * READING the state starts the client's one session restore when nobody has called
118
+ * {@link initialize} yet — lazily and exactly once, sharing the promise an explicit
119
+ * `initialize()` returns. A hook (`useAuth()`), a subscriber, `isAuthenticated()` and
120
+ * `getUser()` are reads too, so a client whose entry file dropped the template's
121
+ * `authClient.initialize()` line still restores instead of reporting `'loading'`
122
+ * forever.
123
+ */
124
+ getState(): AuthState<T>;
125
+ /**
126
+ * Returns whether the user is currently authenticated.
127
+ */
128
+ isAuthenticated(): boolean;
129
+ /**
130
+ * Gets the current user.
131
+ */
132
+ getUser(): T | null;
133
+ /**
134
+ * Updates the cached user object (state + persistent storage) without
135
+ * hitting the network. Intended for local refreshes after a per-app
136
+ * mutation (e.g., the user just PATCHed their own profile and the
137
+ * server returned the canonical row). Does NOT change tokens.
138
+ *
139
+ * This does not sign the client in: `authenticated` and `status` are
140
+ * unchanged, so an anonymous client stays anonymous. Use
141
+ * {@link login} / {@link register} for a credential exchange, or
142
+ * {@link setSession} when the token was issued outside the client.
143
+ */
144
+ setUser(user: T | null): void;
145
+ /**
146
+ * Gets the current access token.
147
+ */
148
+ getAccessToken(): string | null;
149
+ /**
150
+ * Stores the access token in the configured token storage adapter (in a
151
+ * browser, Web Storage; `'memory'` where no browser store exists). Use this
152
+ * to seed the token after an out-of-band exchange (e.g. the OAuth
153
+ * code→token redirect) instead of writing to `localStorage` directly,
154
+ * which would violate the storage contract and make a stored bearer token
155
+ * JS-readable (XSS-exfiltratable). Pass `null` to clear it.
156
+ *
157
+ * This changes token storage only; it does not sign the client in
158
+ * (`authenticated` and `status` are unchanged). Use {@link login} /
159
+ * {@link register} for a credential exchange, or call {@link setSession}
160
+ * with the token and the user to establish an already-issued session.
161
+ */
162
+ setAccessToken(token: string | null): void;
163
+ /**
164
+ * Adopts a session an out-of-band exchange already established: stores the
165
+ * access token (and the refresh token when given), caches the user, and
166
+ * sets the COMPLETE state — `initialized`, `authenticated`, `status:
167
+ * 'authenticated'`, no error — in one update, with one subscriber
168
+ * notification. Every hook reading the shared client sees the user as
169
+ * signed in immediately.
170
+ *
171
+ * This is the way to seed an OAuth/custom sign-in. Calling
172
+ * {@link setAccessToken} and {@link setUser} instead does NOT sign the
173
+ * client in.
174
+ */
175
+ setSession(session: AuthSessionSeed<T>): void;
176
+ /**
177
+ * Gets the refresh token.
178
+ */
179
+ getRefreshToken(): string | null;
180
+ /**
181
+ * Logs in with credentials.
182
+ */
183
+ login(credentials: LoginCredentials): Promise<AuthResult<T>>;
184
+ /**
185
+ * Logs out the current user.
186
+ */
187
+ logout(): Promise<void>;
188
+ /**
189
+ * Registers a new user. Accepts the base fields plus the app's own fields
190
+ * (`TRegister`) at the top level — see {@link RegisterData}.
191
+ */
192
+ register(data: RegisterData<TRegister>): Promise<AuthResult<T>>;
193
+ /**
194
+ * Refreshes the access token.
195
+ */
196
+ refresh(): Promise<AuthResult<T>>;
197
+ /**
198
+ * Requests a password reset.
199
+ */
200
+ requestPasswordReset(data: PasswordResetRequest): Promise<void>;
201
+ /**
202
+ * Confirms a password reset.
203
+ */
204
+ confirmPasswordReset(data: PasswordResetConfirm): Promise<void>;
205
+ /**
206
+ * Updates the current user's profile.
207
+ */
208
+ updateProfile(data: Partial<T>): Promise<T>;
209
+ /**
210
+ * Changes the current user's password.
211
+ */
212
+ changePassword(oldPassword: string, newPassword: string): Promise<void>;
213
+ /**
214
+ * Initializes auth state (e.g., from stored tokens).
215
+ *
216
+ * LAZY and IDEMPOTENT: the first read of the state ({@link getState},
217
+ * {@link subscribe}, `useAuth()`) starts this same restore when nobody has called
218
+ * `initialize()`, and every later call shares the one promise instead of sending a
219
+ * second request. An app that keeps the template's explicit call behaves exactly as
220
+ * before; an app that loses that line still restores its session.
221
+ *
222
+ * With a stored token AND a stored user it marks the session `'authenticated'`
223
+ * SYNCHRONOUSLY — before its first `await` — so the first render is the
224
+ * signed-in UI and no page waits on a verification round trip. Any check
225
+ * (a refresh, the cookie-restore probe) settles behind that render, and only an
226
+ * explicit 401/403 ends the session; a network/5xx/404 failure keeps it and
227
+ * reports `'unavailable'`. With no stored user the client stays `'loading'`
228
+ * until the cookie restore decides.
229
+ *
230
+ * Do not put this call (or a `/me` request of your own) in front of the first
231
+ * render, and do not render a loading screen over a session it just restored:
232
+ * `whenRestored()` already resolves as soon as the restore has settled, and the
233
+ * HTTP gate built on it holds requests for exactly that window.
234
+ */
235
+ initialize(): Promise<void>;
236
+ /**
237
+ * Re-checks a restored session against the server, in the background — the
238
+ * boot-time validation an app with a stored token needs when a revoked or
239
+ * expired token must sign the user out. Call it AFTER the first render
240
+ * (`initialize()` restores synchronously from storage; this costs one request).
241
+ *
242
+ * - The server confirms the user: the session is refreshed and {@link AuthState.status}
243
+ * stays `'authenticated'`.
244
+ * - The server answers 401 or 403: the token is dead — the stored session is
245
+ * cleared and the status becomes `'unauthenticated'`.
246
+ * - The server cannot confirm the session — a network failure, a 5xx, or a 404
247
+ * from a misconfigured {@link AuthClientConfig.currentUserEndpoint}: the
248
+ * session (token AND user) is KEPT and the status becomes `'unavailable'`, so
249
+ * the app can retry instead of signing the user out over a bad connection or a
250
+ * route that does not exist. The 404 error names `currentUserEndpoint`.
251
+ *
252
+ * Do not hand-write this beside the client: a parallel token/user store for a
253
+ * "validating"/"unavailable" flag is the race this method removes.
254
+ *
255
+ * Optional: a provider with no restorable session has nothing to validate.
256
+ */
257
+ validateSession?(): Promise<void>;
258
+ /**
259
+ * Resolves when the session restore started by `initialize()` has settled — the point
260
+ * after which the client knows whether this visitor is signed in.
261
+ *
262
+ * Resolves IMMEDIATELY when no restore is in flight: before `initialize()` is ever
263
+ * called, and after it has finished. A restore that failed resolves too (it settled the
264
+ * question), so an HTTP client can await this before every request without risking one
265
+ * held forever. That is what makes the fetch-before-restore race impossible: a page that
266
+ * fetches viewer-dependent data on mount waits here instead of going out anonymously
267
+ * (see `setAuthGate` in `@molecule/app-http`).
268
+ *
269
+ * Optional: a provider that restores no session has nothing to wait for. Without it, an
270
+ * HTTP client bonded to that provider sends first-paint requests unauthenticated.
271
+ *
272
+ * A provider whose restore sends a request THROUGH the gated HTTP client must send that
273
+ * request with `skipAuthGate: true` (`RequestConfig` in `@molecule/app-http`): the gate
274
+ * waits on this promise, so holding the restore's own request makes the gate wait on
275
+ // … truncated — the full declaration is in node_modules/@molecule/app-solid/dist
276
+ ```
277
+
278
+ #### `FormController`
279
+
280
+ Form controller interface.
281
+
282
+ All form providers must implement this interface.
283
+
284
+ ```typescript
285
+ interface FormController<T extends Record<string, unknown> = Record<string, unknown>> {
88
286
  /**
89
- * Gets the current user.
287
+ * Gets the current form state.
90
288
  */
91
- getUser(): T | null
289
+ getState(): FormState<T>
92
290
  /**
93
- * Updates the cached user object (state + persistent storage) without
94
- * hitting the network. Intended for local refreshes after a per-app
95
- * mutation (e.g., the user just PATCHed their own profile and the
96
- * server returned the canonical row). Does NOT change tokens.
291
+ * Gets the value of a specific field.
97
292
  */
98
- setUser(user: T | null): void
293
+ getValue(name: string): unknown
294
+ getValue<K extends keyof T>(name: K): T[K]
99
295
  /**
100
- * Gets the current access token.
296
+ * Gets all form values.
101
297
  */
102
- getAccessToken(): string | null
298
+ getValues(): T
103
299
  /**
104
- * Stores the access token in the configured token storage adapter (in-memory
105
- * by default). Use this to seed the token after an out-of-band exchange (e.g.
106
- * the OAuth code→token redirect) instead of writing to `localStorage` directly,
107
- * which would violate the in-memory-default storage contract and make the bearer
108
- * token JS-readable (XSS-exfiltratable). Pass `null` to clear it.
300
+ * Sets the value of a specific field.
109
301
  */
110
- setAccessToken(token: string | null): void
302
+ setValue(
303
+ name: string,
304
+ value: unknown,
305
+ options?: {
306
+ shouldValidate?: boolean
307
+ shouldDirty?: boolean
308
+ shouldTouch?: boolean
309
+ },
310
+ ): void
111
311
  /**
112
- * Gets the refresh token.
312
+ * Sets multiple values at once.
113
313
  */
114
- getRefreshToken(): string | null
314
+ setValues(
315
+ values: Partial<T>,
316
+ options?: {
317
+ shouldValidate?: boolean
318
+ },
319
+ ): void
115
320
  /**
116
- * Logs in with credentials.
321
+ * Gets the error for a specific field.
117
322
  */
118
- login(credentials: LoginCredentials): Promise<AuthResult<T>>
323
+ getError(name: string): string | undefined
119
324
  /**
120
- * Logs out the current user.
325
+ * Sets the error for a specific field.
121
326
  */
122
- logout(): Promise<void>
327
+ setError(name: string, error: string | undefined): void
123
328
  /**
124
- * Registers a new user.
329
+ * Clears the error for a specific field.
125
330
  */
126
- register(data: RegisterData): Promise<AuthResult<T>>
331
+ clearError<K extends keyof T>(name: K): void
127
332
  /**
128
- * Refreshes the access token.
333
+ * Clears all errors.
129
334
  */
130
- refresh(): Promise<AuthResult<T>>
335
+ clearErrors(): void
131
336
  /**
132
- * Requests a password reset.
337
+ * Gets the field state for a specific field.
133
338
  */
134
- requestPasswordReset(data: PasswordResetRequest): Promise<void>
339
+ getFieldState<K extends keyof T>(name: K): FieldState<T[K]>
135
340
  /**
136
- * Confirms a password reset.
341
+ * Registers a field for form management.
137
342
  */
138
- confirmPasswordReset(data: PasswordResetConfirm): Promise<void>
343
+ register(nameOrOptions: string | RegisterOptions, options?: RegisterOptions): FieldRegistration
139
344
  /**
140
- * Updates the current user's profile.
345
+ * Unregisters a field.
141
346
  */
142
- updateProfile(data: Partial<T>): Promise<T>
347
+ unregister(name: string): void
143
348
  /**
144
- * Changes the current user's password.
349
+ * Validates a specific field.
145
350
  */
146
- changePassword(oldPassword: string, newPassword: string): Promise<void>
351
+ validateField<K extends keyof T>(name: K): Promise<boolean>
147
352
  /**
148
- * Initializes auth state (e.g., from stored tokens).
353
+ * Validates all fields.
149
354
  */
150
- initialize(): Promise<void>
355
+ validate(): Promise<boolean>
151
356
  /**
152
- * Subscribes to auth state changes.
357
+ * Resets the form to initial values.
153
358
  */
154
- subscribe(callback: (state: AuthState<T>) => void): () => void
359
+ reset(values?: Partial<T>): void
155
360
  /**
156
- * Subscribes to auth state changes (alias for subscribe).
361
+ * Handles form submission.
157
362
  */
158
- onAuthChange(callback: (state: AuthState<T>) => void): () => void
363
+ handleSubmit(
364
+ onSubmit: (values: T) => void | Promise<void>,
365
+ onError?: (errors: Partial<Record<keyof T, string>>) => void,
366
+ ): (event?: { preventDefault?: () => void }) => Promise<void>
159
367
  /**
160
- * Gets the current access token (alias for getAccessToken).
368
+ * Sets focus to a field.
161
369
  */
162
- getToken?(): string | null
370
+ setFocus(name: keyof T): void
163
371
  /**
164
- * Adds an auth event listener.
372
+ * Subscribes to form state changes.
165
373
  */
166
- addEventListener(listener: AuthEventListener): () => void
374
+ subscribe(callback: (state: FormState<T>) => void): () => void
167
375
  /**
168
- * Destroys the auth client.
376
+ * Destroys the form controller.
169
377
  */
170
378
  destroy(): void
171
379
  }
172
380
  ```
173
381
 
174
- #### `AuthPrimitives`
175
-
176
- Auth primitives return type.
177
-
178
- ```typescript
179
- interface AuthPrimitives<T = unknown> {
180
- state: Accessor<AuthState<T>>
181
- user: Accessor<T | null>
182
- isAuthenticated: Accessor<boolean>
183
- isLoading: Accessor<boolean>
184
- login: AuthClient<T>['login']
185
- logout: AuthClient<T>['logout']
186
- register: AuthClient<T>['register']
187
- refresh: AuthClient<T>['refresh']
188
- }
189
- ```
190
-
191
- #### `AuthState`
382
+ #### `FormOptions`
192
383
 
193
- Reactive authentication state snapshot (initialized, authenticated, user, loading, and error).
384
+ Form creation options.
194
385
 
195
386
  ```typescript
196
- interface AuthState<T = UserProfile> {
387
+ interface FormOptions<T extends Record<string, unknown>> {
197
388
  /**
198
- * Whether auth state has been initialized.
389
+ * Default values.
199
390
  */
200
- initialized: boolean
391
+ defaultValues?: Partial<T>
201
392
  /**
202
- * Whether the user is authenticated.
393
+ * Validation mode.
203
394
  */
204
- authenticated: boolean
395
+ mode?: 'onSubmit' | 'onChange' | 'onBlur' | 'all'
205
396
  /**
206
- * Current user (if authenticated).
397
+ * Revalidation mode.
207
398
  */
208
- user: T | null
399
+ reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit'
209
400
  /**
210
- * Whether an auth operation is in progress.
401
+ * Whether to focus the first error field on submit.
211
402
  */
212
- loading: boolean
403
+ shouldFocusError?: boolean
213
404
  /**
214
- * Last auth error (if any).
405
+ * Form-level validation function.
215
406
  */
216
- error: string | null
407
+ validate?: (
408
+ values: T,
409
+ ) => Partial<Record<keyof T, string>> | Promise<Partial<Record<keyof T, string>>>
217
410
  }
218
411
  ```
219
412
 
220
- #### `CapacitorAppPrimitives`
221
-
222
- Capacitor app primitives return type.
223
-
224
- ```typescript
225
- interface CapacitorAppPrimitives {
226
- state: Accessor<CapacitorAppState>
227
- ready: Accessor<boolean>
228
- initialize: () => Promise<void>
229
- }
230
- ```
413
+ #### `HttpClient`
231
414
 
232
- #### `CreateAsyncStateReturn`
415
+ HTTP client interface.
233
416
 
234
- Return type for createAsyncState.
417
+ All HTTP providers must implement this interface.
235
418
 
236
419
  ```typescript
237
- interface CreateAsyncStateReturn<T> {
238
- state: () => T
239
- setState: (value: T | ((prev: T) => T) | Promise<T | ((prev: T) => T)>) => void
240
- extendState: (
241
- partial:
242
- Partial<T> | ((prev: T) => Partial<T>) | Promise<Partial<T> | ((prev: T) => Partial<T>)>,
243
- ) => void
420
+ interface HttpClient {
421
+ /**
422
+ * Base URL for all requests.
423
+ */
424
+ baseURL: string
425
+ /**
426
+ * Default headers for all requests.
427
+ */
428
+ defaultHeaders: Record<string, string>
429
+ /**
430
+ * Makes a generic HTTP request. `data` is a field of THIS config object — the same body
431
+ * `post(url, data, config)` takes as its second argument.
432
+ */
433
+ request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
434
+ /**
435
+ * Makes a GET request.
436
+ */
437
+ get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
438
+ /**
439
+ * Makes a POST request. `data` is the request BODY, not a config object: the wire body is
440
+ * `data` itself, so `post(url, { data: body })` sends `{"data":body}` — pass `body` directly.
441
+ * A config (headers, params) is the THIRD argument.
442
+ */
443
+ post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
444
+ /**
445
+ * Makes a PUT request. `data` is the request BODY (second argument) — never `{ data: body }`,
446
+ * which sends `{"data":body}`; a config is the THIRD argument.
447
+ */
448
+ put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
449
+ /**
450
+ * Makes a PATCH request. `data` is the request BODY (second argument) — never `{ data: body }`,
451
+ * which sends `{"data":body}`; a config is the THIRD argument.
452
+ */
453
+ patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
454
+ /**
455
+ * Makes a DELETE request.
456
+ */
457
+ delete<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
458
+ /**
459
+ * Adds a request interceptor.
460
+ * Returns a function to remove the interceptor.
461
+ */
462
+ addRequestInterceptor(interceptor: RequestInterceptor): () => void
463
+ /**
464
+ * Adds a response interceptor.
465
+ * Returns a function to remove the interceptor.
466
+ */
467
+ addResponseInterceptor(interceptor: ResponseInterceptor): () => void
468
+ /**
469
+ * Adds an error interceptor.
470
+ * Returns a function to remove the interceptor.
471
+ */
472
+ addErrorInterceptor(interceptor: ErrorInterceptor): () => void
473
+ /**
474
+ * Sets the authorization token.
475
+ */
476
+ setAuthToken(token: string | null): void
477
+ /**
478
+ * Returns the current authorization token, or `null` if not set.
479
+ */
480
+ getAuthToken(): string | null
481
+ /**
482
+ * Registers a handler for authentication errors (401).
483
+ *
484
+ * @returns An unsubscribe function.
485
+ */
486
+ onAuthError(handler: () => void): () => void
244
487
  }
245
488
  ```
246
489
 
247
- #### `CreateChangePasswordReturn`
248
-
249
- Return type for createChangePassword primitive.
250
-
251
- ```typescript
252
- interface CreateChangePasswordReturn {
253
- state: Accessor<PromiseState<void>>
254
- changePassword: (oldPassword: string, newPassword: string) => Promise<void>
255
- reset: () => void
256
- }
257
- ```
490
+ #### `I18nProvider`
258
491
 
259
- #### `CreateFormResult`
492
+ i18n provider interface.
260
493
 
261
- Result of createForm primitive.
494
+ All i18n providers must implement this interface.
262
495
 
263
496
  ```typescript
264
- interface CreateFormResult<T extends Record<string, unknown>> {
265
- /** Reactive form state accessor. */
266
- formState: Accessor<FormState<T>>
267
-
268
- /** Whether the form is currently valid. */
269
- isValid: Accessor<boolean>
270
-
271
- /** Whether any field has been modified. */
272
- isDirty: Accessor<boolean>
273
-
274
- /** Whether the form is currently submitting. */
275
- isSubmitting: Accessor<boolean>
276
-
277
- /** Current field errors. */
278
- errors: Accessor<Partial<Record<keyof T, string>>>
279
-
280
- /** Register a field for form management. */
281
- register: (name: keyof T, options?: RegisterOptions) => FieldRegistration
282
-
283
- /** Get the current value of a field. */
284
- getValue: <K extends keyof T>(name: K) => T[K]
285
-
286
- /** Set the value of a field. */
287
- setValue: <K extends keyof T>(name: K, value: T[K]) => void
288
-
289
- /** Get the error message for a field. */
290
- getError: (name: keyof T) => string | undefined
291
-
292
- /** Set an error message for a field. */
293
- setError: (name: keyof T, error: string | undefined) => void
294
-
295
- /** Clear all field errors. */
296
- clearErrors: () => void
297
-
298
- /** Create a submit handler function. */
299
- handleSubmit: (
300
- onSubmit: (values: T) => void | Promise<void>,
301
- ) => (event?: { preventDefault?: () => void }) => Promise<void>
302
-
303
- /** Reset the form to initial or provided values. */
304
- reset: (values?: Partial<T>) => void
305
-
306
- /** Validate all fields. */
307
- validate: () => Promise<boolean>
308
-
309
- /** The raw FormController instance for advanced use. */
310
- controller: FormController<T>
311
- }
312
- ```
313
-
314
- #### `CreateLoginReturn`
315
-
316
- Return type for createLogin primitive.
317
-
318
- ```typescript
319
- interface CreateLoginReturn<T = unknown> {
320
- state: Accessor<PromiseState<AuthResult<T>>>
321
- login: (credentials: LoginCredentials) => Promise<AuthResult<T>>
322
- reset: () => void
323
- }
324
- ```
325
-
326
- #### `CreateOAuthOptions`
327
-
328
- OAuth configuration options.
329
-
330
- ```typescript
331
- interface CreateOAuthOptions {
332
- /** Base URL for the API server (e.g. `https://api.example.com`). */
333
- baseURL?: string
334
- /** List of supported OAuth provider names (e.g. `['github', 'google']`). */
335
- oauthProviders?: string[]
336
- /** Path prefix for OAuth initiation routes. Defaults to `/oauth`. */
337
- oauthEndpoint?: string
338
- /** Path for the OAuth login POST endpoint. Defaults to `/users/log-in/oauth`. */
339
- loginEndpoint?: string
340
- /** Called after a successful OAuth login (session established). */
341
- onSuccess?: () => void
342
- /** Called with a failure message when the OAuth login fails. */
343
- onError?: (error: string) => void
497
+ interface I18nProvider {
344
498
  /**
345
- * Auth client used to establish the session after the code exchange.
346
- * Overrides context resolution — when omitted, the client is resolved from
347
- * the surrounding `MoleculeProvider` (tolerated when absent; see the
348
- * cookie-session fallback documented on
349
- * {@link CreateOAuthReturn.handleCallback}).
499
+ * Gets the current locale.
350
500
  */
351
- authClient?: AuthClient<unknown>
352
- }
353
- ```
354
-
355
- #### `CreateOAuthReturn`
356
-
357
- Return type for createOAuth primitive.
358
-
359
- ```typescript
360
- interface CreateOAuthReturn {
361
- /** Accessor for the configured OAuth provider names. */
362
- providers: Accessor<string[]>
363
- /** Builds the OAuth initiation URL for a provider. */
364
- getOAuthUrl: (provider: string) => string
365
- /** Starts the full-page redirect flow for a provider. */
366
- redirect: (provider: string) => void
501
+ getLocale(): string
367
502
  /**
368
- * Handles the OAuth callback: exchanges the `code` URL parameter for a
369
- * session. Invoked automatically at creation (see {@link createOAuth});
370
- * exposed for callers that need to re-run it manually. No-ops unless
371
- * running in a browser with a `code` URL parameter and a stashed provider.
503
+ * Sets the current locale.
372
504
  *
373
- * When an auth client is available (explicit option or context), the
374
- * session is established locally (`setAccessToken` + `setUser` +
375
- * `initialize`). When no client is available, the server has already
376
- * established the httpOnly-cookie session during the exchange, so a
377
- * user-carrying response still counts as success.
505
+ * **Fleet contract:** every conformant provider (the core simple provider,
506
+ * `@molecule/api-i18n-simple`, `@molecule/app-i18n-i18next`, and
507
+ * `@molecule/app-i18n-react-i18next`) MUST throw `Error('Locale "<code>"
508
+ * not found')` when `locale` is not registered — via the constructor's
509
+ * `initialLocales`/`locales` config, `addLocale()`, or `addTranslations()`
510
+ * (all three register a locale). It must NOT silently degrade to
511
+ * fallback-locale text while `getLocale()` reports the unregistered code —
512
+ * that divergence makes a misconfigured locale switch indistinguishable
513
+ * from a working one until a user notices the wrong language on screen.
378
514
  */
379
- handleCallback: () => Promise<void>
380
- }
381
- ```
382
-
383
- #### `CreatePasswordResetReturn`
384
-
385
- Return type for createPasswordReset primitive.
386
-
387
- ```typescript
388
- interface CreatePasswordResetReturn {
389
- requestState: Accessor<PromiseState<void>>
390
- confirmState: Accessor<PromiseState<void>>
391
- requestReset: (data: PasswordResetRequest) => Promise<void>
392
- confirmReset: (data: PasswordResetConfirm) => Promise<void>
393
- reset: () => void
394
- }
395
- ```
396
-
397
- #### `CreatePromiseReturn`
398
-
399
- Promise state accessor with actions.
400
-
401
- ```typescript
402
- interface CreatePromiseReturn<T> {
403
- state: () => PromiseState<T>
404
- call: (...args: any[]) => Promise<T>
405
- cancel: (message?: string) => void
406
- reset: () => void
407
- }
408
- ```
409
-
410
- #### `CreateSignupReturn`
411
-
412
- Return type for createSignup primitive.
413
-
414
- ```typescript
415
- interface CreateSignupReturn<T = unknown> {
416
- state: Accessor<PromiseState<AuthResult<T>>>
417
- signup: (data: RegisterData) => Promise<AuthResult<T>>
418
- reset: () => void
419
- }
420
- ```
421
-
422
- #### `DevicePrimitives`
423
-
424
- Device primitives return type.
425
-
426
- ```typescript
427
- interface DevicePrimitives {
428
- deviceInfo: DeviceInfo
429
- screenInfo: ScreenInfo
430
- hardwareInfo: HardwareInfo
431
- featureSupport: FeatureSupport
432
- supports: (feature: keyof FeatureSupport) => boolean
433
- isOnline: () => boolean
434
- isStandalone: () => boolean
435
- language: string
436
- languages: string[]
437
- }
438
- ```
439
-
440
- #### `FormController`
441
-
442
- Form controller interface.
443
-
444
- All form providers must implement this interface.
445
-
446
- ```typescript
447
- interface FormController<T extends Record<string, unknown> = Record<string, unknown>> {
515
+ setLocale(locale: string): Promise<void>
448
516
  /**
449
- * Gets the current form state.
517
+ * Gets all available locales.
450
518
  */
451
- getState(): FormState<T>
519
+ getLocales(): LocaleConfig[]
452
520
  /**
453
- * Gets the value of a specific field.
521
+ * Adds a locale.
454
522
  */
455
- getValue(name: string): unknown
456
- getValue<K extends keyof T>(name: K): T[K]
523
+ addLocale(config: LocaleConfig): void
457
524
  /**
458
- * Gets all form values.
525
+ * Removes a locale by code, notifying subscribers so language pickers
526
+ * built on `onLocaleChange` re-render their list. If the removed locale
527
+ * is currently active, the caller is responsible for switching to a
528
+ * fallback (e.g. `'en'`) BEFORE calling this — the provider will not
529
+ * auto-fall-back on its own.
530
+ *
531
+ * Returns `true` if the locale was registered and removed, `false`
532
+ * otherwise.
459
533
  */
460
- getValues(): T
534
+ removeLocale(code: string): boolean
461
535
  /**
462
- * Sets the value of a specific field.
536
+ * Adds translations to a locale. Auto-creates the locale if it doesn't exist.
537
+ *
538
+ * **Fleet contract:** merges are DEEP, not a shallow spread — registering
539
+ * two calls (e.g. two modules) that share a top-level namespace key merges
540
+ * their subtrees instead of the second call clobbering the first's nested
541
+ * translations wholesale. `@molecule/api-i18n-simple` implements the same
542
+ * contract on the API side.
463
543
  */
464
- setValue(
465
- name: string,
466
- value: unknown,
467
- options?: {
468
- shouldValidate?: boolean
469
- shouldDirty?: boolean
470
- shouldTouch?: boolean
471
- },
472
- ): void
544
+ addTranslations(locale: string, translations: Translations, namespace?: string): void
473
545
  /**
474
- * Sets multiple values at once.
546
+ * Translates a key with optional interpolation values and pluralization.
547
+ *
548
+ * **Fleet plural contract (matches i18next's own key resolution order):**
549
+ * when `options.count` is provided, the plural-suffixed key
550
+ * (`` `${key}_${pluralForm}` ``, e.g. `item_one`/`item_few`/…, falling back
551
+ * to `` `${key}_other` ``) is looked up FIRST and wins over the base `key`
552
+ * if BOTH are registered. Only when no plural-suffixed key exists at all
553
+ * does resolution fall back to the base key. A catalog that ships both
554
+ * `item` and `item_one`/`item_other` therefore pluralizes identically
555
+ * whichever provider is bonded.
556
+ *
557
+ * @returns The translated string, or the default value / key if not found.
475
558
  */
476
- setValues(
477
- values: Partial<T>,
559
+ t(
560
+ key: string,
561
+ values?: InterpolationValues,
478
562
  options?: {
479
- shouldValidate?: boolean
563
+ defaultValue?: string
564
+ count?: number
480
565
  },
481
- ): void
482
- /**
483
- * Gets the error for a specific field.
484
- */
485
- getError(name: string): string | undefined
486
- /**
487
- * Sets the error for a specific field.
488
- */
489
- setError(name: string, error: string | undefined): void
490
- /**
491
- * Clears the error for a specific field.
492
- */
493
- clearError<K extends keyof T>(name: K): void
566
+ ): string
494
567
  /**
495
- * Clears all errors.
568
+ * Checks if a translation key exists.
569
+ *
570
+ * **Fleet contract:** follows the SAME locale-resolution chain as `t()` —
571
+ * the active locale, then the English fallback — so `exists(key) === true`
572
+ * whenever `t(key)` would render real translated text (not the raw key or
573
+ * an inline `defaultValue`). Do not narrow this to "only the active
574
+ * locale's own catalog"; that made `exists()` return `false` for keys `t()`
575
+ * happily rendered via the English fallback, and the answer differed by
576
+ * provider.
577
+ *
578
+ * @returns `true` if the key has a translation.
496
579
  */
497
- clearErrors(): void
580
+ exists(key: string): boolean
498
581
  /**
499
- * Gets the field state for a specific field.
582
+ * Formats a number according to the current locale.
583
+ *
584
+ * @returns The locale-formatted number string.
500
585
  */
501
- getFieldState<K extends keyof T>(name: K): FieldState<T[K]>
586
+ formatNumber(value: number, options?: NumberFormatOptions): string
502
587
  /**
503
- * Registers a field for form management.
588
+ * Formats a date according to the current locale.
589
+ *
590
+ * @returns The locale-formatted date string.
504
591
  */
505
- register(nameOrOptions: string | RegisterOptions, options?: RegisterOptions): FieldRegistration
592
+ formatDate(value: Date | number | string, options?: DateFormatOptions): string
506
593
  /**
507
- * Unregisters a field.
594
+ * Formats a relative time (e.g. "2 hours ago").
595
+ *
596
+ * @returns The locale-formatted relative time string.
508
597
  */
509
- unregister(name: string): void
598
+ formatRelativeTime(
599
+ value: Date | number,
600
+ options?: {
601
+ unit?: Intl.RelativeTimeFormatUnit
602
+ },
603
+ ): string
510
604
  /**
511
- * Validates a specific field.
605
+ * Formats a list (e.g. "A, B, and C").
606
+ *
607
+ * @returns The locale-formatted list string.
512
608
  */
513
- validateField<K extends keyof T>(name: K): Promise<boolean>
609
+ formatList(
610
+ values: string[],
611
+ options?: {
612
+ type?: 'conjunction' | 'disjunction' | 'unit'
613
+ },
614
+ ): string
514
615
  /**
515
- * Validates all fields.
616
+ * Subscribes to locale changes.
617
+ *
618
+ * @returns An unsubscribe function.
516
619
  */
517
- validate(): Promise<boolean>
620
+ onLocaleChange(listener: (locale: string) => void): () => void
518
621
  /**
519
- * Resets the form to initial values.
622
+ * Gets the text direction for the current locale.
623
+ *
624
+ * @returns `'ltr'` or `'rtl'`.
520
625
  */
521
- reset(values?: Partial<T>): void
626
+ getDirection(): 'ltr' | 'rtl'
522
627
  /**
523
- * Handles form submission.
628
+ * Checks if a translation key exists (alias for exists).
524
629
  */
525
- handleSubmit(
526
- onSubmit: (values: T) => void | Promise<void>,
527
- onError?: (errors: Partial<Record<keyof T, string>>) => void,
528
- ): (event?: { preventDefault?: () => void }) => Promise<void>
630
+ hasKey?(key: string): boolean
529
631
  /**
530
- * Sets focus to a field.
632
+ * Checks if the provider is ready.
531
633
  */
532
- setFocus(name: keyof T): void
634
+ isReady?(): boolean
533
635
  /**
534
- * Subscribes to form state changes.
636
+ * Registers a callback for when the provider is ready.
535
637
  */
536
- subscribe(callback: (state: FormState<T>) => void): () => void
638
+ onReady?(callback: () => void): () => void
537
639
  /**
538
- * Destroys the form controller.
640
+ * Registers a lazily-loaded content module for automatic reload on locale changes.
641
+ * All registered content is reloaded during `setLocale()` before listeners fire,
642
+ * ensuring content is available on the first re-render with no flash.
643
+ *
644
+ * Idempotent: registering the same module name twice is a no-op.
539
645
  */
540
- destroy(): void
646
+ registerContent?(module: string, loader: (locale: string) => Promise<void>): void
541
647
  }
542
648
  ```
543
649
 
544
- #### `FormOptions`
650
+ #### `Logger`
545
651
 
546
- Form creation options.
652
+ Logger instance with leveled logging methods, child logger creation,
653
+ and transport management.
547
654
 
548
655
  ```typescript
549
- interface FormOptions<T extends Record<string, unknown>> {
656
+ interface Logger {
550
657
  /**
551
- * Default values.
658
+ * Logs a trace message.
552
659
  */
553
- defaultValues?: Partial<T>
660
+ trace(message: string, ...args: unknown[]): void
554
661
  /**
555
- * Validation mode.
662
+ * Logs a debug message.
556
663
  */
557
- mode?: 'onSubmit' | 'onChange' | 'onBlur' | 'all'
664
+ debug(message: string, ...args: unknown[]): void
558
665
  /**
559
- * Revalidation mode.
666
+ * Logs an info message.
560
667
  */
561
- reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit'
668
+ info(message: string, ...args: unknown[]): void
562
669
  /**
563
- * Whether to focus the first error field on submit.
670
+ * Logs a warning message.
564
671
  */
565
- shouldFocusError?: boolean
672
+ warn(message: string, ...args: unknown[]): void
566
673
  /**
567
- * Form-level validation function.
674
+ * Logs an error message.
568
675
  */
569
- validate?: (
570
- values: T,
571
- ) => Partial<Record<keyof T, string>> | Promise<Partial<Record<keyof T, string>>>
572
- }
573
- ```
574
-
575
- #### `HttpClient`
576
-
577
- HTTP client interface.
578
-
579
- All HTTP providers must implement this interface.
580
-
581
- ```typescript
582
- interface HttpClient {
676
+ error(message: string | Error, ...args: unknown[]): void
583
677
  /**
584
- * Base URL for all requests.
678
+ * Sets the log level.
585
679
  */
586
- baseURL: string
680
+ setLevel(level: LogLevel): void
587
681
  /**
588
- * Default headers for all requests.
682
+ * Gets the current log level.
589
683
  */
590
- defaultHeaders: Record<string, string>
684
+ getLevel(): LogLevel
591
685
  /**
592
- * Makes a generic HTTP request.
686
+ * Creates a child logger with a namespace.
593
687
  */
594
- request<T = unknown>(config: FullRequestConfig): Promise<HttpResponse<T>>
688
+ child(name: string, context?: Record<string, unknown>): Logger
595
689
  /**
596
- * Makes a GET request.
690
+ * Adds additional context to the logger.
597
691
  */
598
- get<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
692
+ withContext(context: Record<string, unknown>): Logger
599
693
  /**
600
- * Makes a POST request.
694
+ * Adds a transport.
601
695
  */
602
- post<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
696
+ addTransport(transport: LogTransport): () => void
603
697
  /**
604
- * Makes a PUT request.
698
+ * Removes a transport.
605
699
  */
606
- put<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
700
+ removeTransport(transport: LogTransport): void
701
+ }
702
+ ```
703
+
704
+ #### `LoggerProvider`
705
+
706
+ Logger provider interface that all logger bond packages must implement.
707
+ Creates and manages logger instances and global log configuration.
708
+
709
+ ```typescript
710
+ interface LoggerProvider {
607
711
  /**
608
- * Makes a PATCH request.
712
+ * Gets a logger by name, or the root logger if no name given.
609
713
  */
610
- patch<T = unknown>(url: string, data?: unknown, config?: RequestConfig): Promise<HttpResponse<T>>
714
+ getLogger(name?: string): Logger
611
715
  /**
612
- * Makes a DELETE request.
716
+ * Creates a named logger.
613
717
  */
614
- delete<T = unknown>(url: string, config?: RequestConfig): Promise<HttpResponse<T>>
718
+ createLogger(nameOrConfig: string | LoggerConfig, config?: LoggerConfig): Logger
615
719
  /**
616
- * Adds a request interceptor.
617
- * Returns a function to remove the interceptor.
720
+ * Sets the global log level.
618
721
  */
619
- addRequestInterceptor(interceptor: RequestInterceptor): () => void
722
+ setLevel(level: LogLevel): void
620
723
  /**
621
- * Adds a response interceptor.
622
- * Returns a function to remove the interceptor.
724
+ * Gets the global log level.
623
725
  */
624
- addResponseInterceptor(interceptor: ResponseInterceptor): () => void
726
+ getLevel(): LogLevel
625
727
  /**
626
- * Adds an error interceptor.
627
- * Returns a function to remove the interceptor.
728
+ * Adds a global transport.
628
729
  */
629
- addErrorInterceptor(interceptor: ErrorInterceptor): () => void
730
+ addTransport(transport: LogTransport): () => void
630
731
  /**
631
- * Sets the authorization token.
732
+ * Enables logging.
632
733
  */
633
- setAuthToken(token: string | null): void
734
+ enable(): void
634
735
  /**
635
- * Returns the current authorization token, or `null` if not set.
736
+ * Disables logging.
636
737
  */
637
- getAuthToken(): string | null
738
+ disable(): void
638
739
  /**
639
- * Registers a handler for authentication errors (401).
740
+ * Checks if logging is enabled.
640
741
  *
641
- * @returns An unsubscribe function.
742
+ * @returns `true` if logging is currently enabled.
642
743
  */
643
- onAuthError(handler: () => void): () => void
744
+ isEnabled(): boolean
644
745
  }
645
746
  ```
646
747
 
647
- #### `HttpState`
748
+ #### `RouteLocation`
648
749
 
649
- State for async HTTP operations.
750
+ Current URL decomposed into pathname, search string, hash, navigation state, and unique key.
650
751
 
651
752
  ```typescript
652
- interface HttpState<T> {
653
- data: T | null
654
- loading: boolean
655
- error: Error | null
753
+ interface RouteLocation {
754
+ /**
755
+ * Current pathname.
756
+ */
757
+ pathname: string
758
+ /**
759
+ * Query string (including leading ?).
760
+ */
761
+ search: string
762
+ /**
763
+ * Hash (including leading #).
764
+ */
765
+ hash: string
766
+ /**
767
+ * State data passed with navigation.
768
+ */
769
+ state?: unknown
770
+ /**
771
+ * Unique key for this location.
772
+ */
773
+ key?: string
656
774
  }
657
775
  ```
658
776
 
659
- #### `I18nProvider`
777
+ #### `Router`
660
778
 
661
- i18n provider interface.
779
+ Client-side router providing navigation, guards, route matching, and history control.
662
780
 
663
- All i18n providers must implement this interface.
781
+ All routing providers must implement this interface.
664
782
 
665
783
  ```typescript
666
- interface I18nProvider {
784
+ interface Router {
785
+ /**
786
+ * Returns the current route location (pathname, search, hash, state).
787
+ */
788
+ getLocation(): RouteLocation
667
789
  /**
668
- * Gets the current locale.
790
+ * Gets the current route params.
669
791
  */
670
- getLocale(): string
792
+ getParams<T extends RouteParams = RouteParams>(): T
671
793
  /**
672
- * Sets the current locale.
673
- *
674
- * **Fleet contract:** every conformant provider (the core simple provider,
675
- * `@molecule/api-i18n-simple`, `@molecule/app-i18n-i18next`, and
676
- * `@molecule/app-i18n-react-i18next`) MUST throw `Error('Locale "<code>"
677
- * not found')` when `locale` is not registered — via the constructor's
678
- * `initialLocales`/`locales` config, `addLocale()`, or `addTranslations()`
679
- * (all three register a locale). It must NOT silently degrade to
680
- * fallback-locale text while `getLocale()` reports the unregistered code —
681
- * that divergence makes a misconfigured locale switch indistinguishable
682
- * from a working one until a user notices the wrong language on screen.
794
+ * Gets the current query params.
683
795
  */
684
- setLocale(locale: string): Promise<void>
796
+ getQuery(): QueryParams
685
797
  /**
686
- * Gets all available locales.
798
+ * Gets a specific query parameter.
687
799
  */
688
- getLocales(): LocaleConfig[]
800
+ getQueryParam(key: string): string | undefined
689
801
  /**
690
- * Adds a locale.
802
+ * Gets the current hash.
691
803
  */
692
- addLocale(config: LocaleConfig): void
804
+ getHash(): string
693
805
  /**
694
- * Removes a locale by code, notifying subscribers so language pickers
695
- * built on `onLocaleChange` re-render their list. If the removed locale
696
- * is currently active, the caller is responsible for switching to a
697
- * fallback (e.g. `'en'`) BEFORE calling this — the provider will not
698
- * auto-fall-back on its own.
699
- *
700
- * Returns `true` if the locale was registered and removed, `false`
701
- * otherwise.
806
+ * Navigates to a path.
702
807
  */
703
- removeLocale(code: string): boolean
808
+ navigate(path: string, options?: NavigateOptions): void
704
809
  /**
705
- * Adds translations to a locale. Auto-creates the locale if it doesn't exist.
706
- *
707
- * **Fleet contract:** merges are DEEP, not a shallow spread — registering
708
- * two calls (e.g. two modules) that share a top-level namespace key merges
709
- * their subtrees instead of the second call clobbering the first's nested
710
- * translations wholesale. `@molecule/api-i18n-simple` implements the same
711
- * contract on the API side.
810
+ * Navigates to a named route.
712
811
  */
713
- addTranslations(locale: string, translations: Translations, namespace?: string): void
812
+ navigateTo(
813
+ name: string,
814
+ params?: RouteParams,
815
+ query?: QueryParams,
816
+ options?: NavigateOptions,
817
+ ): void
714
818
  /**
715
- * Translates a key with optional interpolation values and pluralization.
716
- *
717
- * **Fleet plural contract (matches i18next's own key resolution order):**
718
- * when `options.count` is provided, the plural-suffixed key
719
- * (`` `${key}_${pluralForm}` ``, e.g. `item_one`/`item_few`/…, falling back
720
- * to `` `${key}_other` ``) is looked up FIRST and wins over the base `key`
721
- * if BOTH are registered. Only when no plural-suffixed key exists at all
722
- * does resolution fall back to the base key. A catalog that ships both
723
- * `item` and `item_one`/`item_other` therefore pluralizes identically
724
- * whichever provider is bonded.
725
- *
726
- * @returns The translated string, or the default value / key if not found.
819
+ * Goes back in history.
727
820
  */
728
- t(
729
- key: string,
730
- values?: InterpolationValues,
731
- options?: {
732
- defaultValue?: string
733
- count?: number
734
- },
735
- ): string
821
+ back(): void
736
822
  /**
737
- * Checks if a translation key exists.
738
- *
739
- * **Fleet contract:** follows the SAME locale-resolution chain as `t()` —
740
- * the active locale, then the English fallback — so `exists(key) === true`
741
- * whenever `t(key)` would render real translated text (not the raw key or
742
- * an inline `defaultValue`). Do not narrow this to "only the active
743
- * locale's own catalog"; that made `exists()` return `false` for keys `t()`
744
- * happily rendered via the English fallback, and the answer differed by
745
- * provider.
746
- *
747
- * @returns `true` if the key has a translation.
823
+ * Goes forward in history.
748
824
  */
749
- exists(key: string): boolean
825
+ forward(): void
750
826
  /**
751
- * Formats a number according to the current locale.
752
- *
753
- * @returns The locale-formatted number string.
827
+ * Goes to a specific point in history.
754
828
  */
755
- formatNumber(value: number, options?: NumberFormatOptions): string
829
+ go(delta: number): void
756
830
  /**
757
- * Formats a date according to the current locale.
758
- *
759
- * @returns The locale-formatted date string.
831
+ * Updates the current query params.
760
832
  */
761
- formatDate(value: Date | number | string, options?: DateFormatOptions): string
833
+ setQuery(params: QueryParams, options?: NavigateOptions): void
762
834
  /**
763
- * Formats a relative time (e.g. "2 hours ago").
764
- *
765
- * @returns The locale-formatted relative time string.
835
+ * Updates a specific query parameter.
766
836
  */
767
- formatRelativeTime(
768
- value: Date | number,
769
- options?: {
770
- unit?: Intl.RelativeTimeFormatUnit
771
- },
772
- ): string
837
+ setQueryParam(key: string, value: string | undefined, options?: NavigateOptions): void
773
838
  /**
774
- * Formats a list (e.g. "A, B, and C").
775
- *
776
- * @returns The locale-formatted list string.
839
+ * Updates the current hash.
777
840
  */
778
- formatList(
779
- values: string[],
780
- options?: {
781
- type?: 'conjunction' | 'disjunction' | 'unit'
782
- },
783
- ): string
841
+ setHash(hash: string, options?: NavigateOptions): void
784
842
  /**
785
- * Subscribes to locale changes.
843
+ * Checks if a path matches the current location.
786
844
  *
787
- * @returns An unsubscribe function.
845
+ * @returns `true` if the path matches the current route.
788
846
  */
789
- onLocaleChange(listener: (locale: string) => void): () => void
847
+ isActive(path: string, exact?: boolean): boolean
790
848
  /**
791
- * Gets the text direction for the current locale.
792
- *
793
- * @returns `'ltr'` or `'rtl'`.
849
+ * Matches a path pattern against a pathname.
794
850
  */
795
- getDirection(): 'ltr' | 'rtl'
851
+ matchPath<Params extends RouteParams = RouteParams>(
852
+ pattern: string,
853
+ pathname: string,
854
+ ): RouteMatch<Params> | null
796
855
  /**
797
- * Checks if a translation key exists (alias for exists).
856
+ * Generates a URL from a named route.
798
857
  */
799
- hasKey?(key: string): boolean
858
+ generatePath(name: string, params?: RouteParams, query?: QueryParams): string
800
859
  /**
801
- * Checks if the provider is ready.
860
+ * Subscribes to route changes.
802
861
  */
803
- isReady?(): boolean
862
+ subscribe(listener: RouteChangeListener): () => void
804
863
  /**
805
- * Registers a callback for when the provider is ready.
864
+ * Adds a navigation guard.
806
865
  */
807
- onReady?(callback: () => void): () => void
866
+ addGuard(guard: NavigationGuard): () => void
808
867
  /**
809
- * Registers a lazily-loaded content module for automatic reload on locale changes.
810
- * All registered content is reloaded during `setLocale()` before listeners fire,
811
- * ensuring content is available on the first re-render with no flash.
812
- *
813
- * Idempotent: registering the same module name twice is a no-op.
868
+ * Registers route definitions.
814
869
  */
815
- registerContent?(module: string, loader: (locale: string) => Promise<void>): void
870
+ registerRoutes(routes: RouteDefinition[]): void
871
+ /**
872
+ * Gets all registered routes.
873
+ */
874
+ getRoutes(): RouteDefinition[]
875
+ /**
876
+ * Destroys the router.
877
+ */
878
+ destroy(): void
816
879
  }
817
880
  ```
818
881
 
819
- #### `Logger`
882
+ #### `StoreConfig`
820
883
 
821
- Logger instance with leveled logging methods, child logger creation,
822
- and transport management.
884
+ Configuration for creating a store (initial state, optional name, and middleware chain).
823
885
 
824
886
  ```typescript
825
- interface Logger {
887
+ interface StoreConfig<T> {
826
888
  /**
827
- * Logs a trace message.
889
+ * Initial state value.
828
890
  */
829
- trace(message: string, ...args: unknown[]): void
891
+ initialState: T
830
892
  /**
831
- * Logs a debug message.
893
+ * Optional name for debugging.
832
894
  */
833
- debug(message: string, ...args: unknown[]): void
895
+ name?: string
834
896
  /**
835
- * Logs an info message.
897
+ * Optional middleware functions.
836
898
  */
837
- info(message: string, ...args: unknown[]): void
899
+ middleware?: StoreMiddleware<T>[]
900
+ }
901
+ ```
902
+
903
+ #### `MoleculeStore`
904
+
905
+ Reactive state container with getState, setState, subscribe, and destroy.
906
+
907
+ All state management providers must implement this interface.
908
+
909
+ ```typescript
910
+ interface Store<T> {
838
911
  /**
839
- * Logs a warning message.
912
+ * Gets the current state.
840
913
  */
841
- warn(message: string, ...args: unknown[]): void
914
+ getState(): T
842
915
  /**
843
- * Logs an error message.
916
+ * Sets the state (partial or via updater function).
844
917
  */
845
- error(message: string | Error, ...args: unknown[]): void
918
+ setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
846
919
  /**
847
- * Sets the log level.
920
+ * Subscribes to state changes.
921
+ * Returns an unsubscribe function.
848
922
  */
849
- setLevel(level: LogLevel): void
923
+ subscribe(listener: StateListener<T>): () => void
850
924
  /**
851
- * Gets the current log level.
925
+ * Destroys the store and cleans up subscriptions.
852
926
  */
853
- getLevel(): LogLevel
927
+ destroy(): void
928
+ }
929
+ ```
930
+
931
+ #### `StateProvider`
932
+
933
+ State provider interface that all state management bond packages
934
+ must implement. Provides the store creation factory.
935
+
936
+ ```typescript
937
+ interface StateProvider {
854
938
  /**
855
- * Creates a child logger with a namespace.
939
+ * Creates a new store.
856
940
  */
857
- child(name: string, context?: Record<string, unknown>): Logger
941
+ createStore<T>(config: StoreConfig<T>): Store<T>
942
+ }
943
+ ```
944
+
945
+ #### `StorageProvider`
946
+
947
+ Storage provider interface.
948
+
949
+ All storage providers must implement this interface.
950
+
951
+ ```typescript
952
+ interface StorageProvider {
953
+ /**
954
+ * Gets a value from storage.
955
+ */
956
+ get<T = unknown>(key: string): Promise<T | null>
957
+ /**
958
+ * Sets a value in storage.
959
+ */
960
+ set<T = unknown>(key: string, value: T): Promise<void>
961
+ /**
962
+ * Removes a value from storage.
963
+ */
964
+ remove(key: string): Promise<void>
965
+ /**
966
+ * Clears all values from storage.
967
+ */
968
+ clear(): Promise<void>
969
+ /**
970
+ * Gets all keys in storage.
971
+ */
972
+ keys(): Promise<string[]>
858
973
  /**
859
- * Adds additional context to the logger.
974
+ * Gets multiple values from storage.
860
975
  */
861
- withContext(context: Record<string, unknown>): Logger
976
+ getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>
862
977
  /**
863
- * Adds a transport.
978
+ * Sets multiple values in storage.
864
979
  */
865
- addTransport(transport: LogTransport): () => void
980
+ setMany?<T = unknown>(entries: Array<[string, T]>): Promise<void>
866
981
  /**
867
- * Removes a transport.
982
+ * Removes multiple values from storage.
868
983
  */
869
- removeTransport(transport: LogTransport): void
984
+ removeMany?(keys: string[]): Promise<void>
870
985
  }
871
986
  ```
872
987
 
873
- #### `LoggerProvider`
988
+ #### `ThemeProvider`
874
989
 
875
- Logger provider interface that all logger bond packages must implement.
876
- Creates and manages logger instances and global log configuration.
990
+ Manages theme state including the active theme, mode toggling,
991
+ and change subscriptions.
877
992
 
878
993
  ```typescript
879
- interface LoggerProvider {
880
- /**
881
- * Gets a logger by name, or the root logger if no name given.
882
- */
883
- getLogger(name?: string): Logger
994
+ interface ThemeProvider {
884
995
  /**
885
- * Creates a named logger.
996
+ * Returns the currently active theme.
886
997
  */
887
- createLogger(nameOrConfig: string | LoggerConfig, config?: LoggerConfig): Logger
998
+ getTheme(): Theme
888
999
  /**
889
- * Sets the global log level.
1000
+ * Sets the active theme by reference or by name.
1001
+ *
1002
+ * @param theme - A `Theme` object or a theme name string to activate.
890
1003
  */
891
- setLevel(level: LogLevel): void
1004
+ setTheme(theme: Theme | string): void
892
1005
  /**
893
- * Gets the global log level.
1006
+ * Toggles between light and dark mode for the active theme.
894
1007
  */
895
- getLevel(): LogLevel
1008
+ toggleMode(): void
896
1009
  /**
897
- * Adds a global transport.
1010
+ * Subscribes to theme changes. The callback fires whenever
1011
+ * `setTheme()` or `toggleMode()` is called.
1012
+ *
1013
+ * @param callback - Invoked with the new theme after each change.
1014
+ * @returns An unsubscribe function.
898
1015
  */
899
- addTransport(transport: LogTransport): () => void
1016
+ subscribe(callback: (theme: Theme) => void): () => void
900
1017
  /**
901
- * Enables logging.
1018
+ * Returns all registered themes. Optional — not all providers
1019
+ * support multiple themes.
902
1020
  */
903
- enable(): void
1021
+ getThemes?(): Theme[]
904
1022
  /**
905
- * Disables logging.
1023
+ * Returns the theme a render WITHOUT a browser produces — a server or
1024
+ * build-time render, which has no storage and no `prefers-color-scheme`
1025
+ * to read. A hydrating client renders this theme first, so its markup
1026
+ * matches what the server sent, and switches to `getTheme()` right
1027
+ * after. Optional — a provider whose theme cannot differ between the two
1028
+ * need not implement it.
906
1029
  */
907
- disable(): void
1030
+ getServerTheme?(): Theme
1031
+ }
1032
+ ```
1033
+
1034
+ #### `Theme`
1035
+
1036
+ Complete theme definition.
1037
+
1038
+ ```typescript
1039
+ interface Theme {
1040
+ name: string
1041
+ mode: 'light' | 'dark'
1042
+ colors: ThemeColors
1043
+ breakpoints: ThemeBreakpoints
1044
+ spacing: ThemeSpacing
1045
+ typography: ThemeTypography
1046
+ borderRadius: ThemeBorderRadius
1047
+ shadows: ThemeShadows
1048
+ transitions: ThemeTransitions
1049
+ zIndex: ThemeZIndex
1050
+ }
1051
+ ```
1052
+
1053
+ #### `CreateAsyncStateReturn`
1054
+
1055
+ Return type for createAsyncState.
1056
+
1057
+ ```typescript
1058
+ interface CreateAsyncStateReturn<T> {
1059
+ state: () => T
1060
+ setState: (value: T | ((prev: T) => T) | Promise<T | ((prev: T) => T)>) => void
1061
+ extendState: (
1062
+ partial:
1063
+ Partial<T> | ((prev: T) => Partial<T>) | Promise<Partial<T> | ((prev: T) => Partial<T>)>,
1064
+ ) => void
1065
+ }
1066
+ ```
1067
+
1068
+ #### `CapacitorAppPrimitives`
1069
+
1070
+ Capacitor app primitives return type.
1071
+
1072
+ ```typescript
1073
+ interface CapacitorAppPrimitives {
1074
+ state: Accessor<CapacitorAppState>
1075
+ ready: Accessor<boolean>
1076
+ initialize: () => Promise<void>
1077
+ }
1078
+ ```
1079
+
1080
+ #### `CreateChangePasswordReturn`
1081
+
1082
+ Return type for createChangePassword primitive.
1083
+
1084
+ ```typescript
1085
+ interface CreateChangePasswordReturn {
1086
+ state: Accessor<PromiseState<void>>
1087
+ changePassword: (oldPassword: string, newPassword: string) => Promise<void>
1088
+ reset: () => void
1089
+ }
1090
+ ```
1091
+
1092
+ #### `DevicePrimitives`
1093
+
1094
+ Device primitives return type.
1095
+
1096
+ ```typescript
1097
+ interface DevicePrimitives {
1098
+ deviceInfo: DeviceInfo
1099
+ screenInfo: ScreenInfo
1100
+ hardwareInfo: HardwareInfo
1101
+ featureSupport: FeatureSupport
1102
+ supports: (feature: keyof FeatureSupport) => boolean
1103
+ isOnline: () => boolean
1104
+ isStandalone: () => boolean
1105
+ language: string
1106
+ languages: string[]
1107
+ }
1108
+ ```
1109
+
1110
+ #### `CreateFormResult`
1111
+
1112
+ Result of createForm primitive.
1113
+
1114
+ ```typescript
1115
+ interface CreateFormResult<T extends Record<string, unknown>> {
1116
+ /** Reactive form state accessor. */
1117
+ formState: Accessor<FormState<T>>
1118
+
1119
+ /** Whether the form is currently valid. */
1120
+ isValid: Accessor<boolean>
1121
+
1122
+ /** Whether any field has been modified. */
1123
+ isDirty: Accessor<boolean>
1124
+
1125
+ /** Whether the form is currently submitting. */
1126
+ isSubmitting: Accessor<boolean>
1127
+
1128
+ /** Current field errors. */
1129
+ errors: Accessor<Partial<Record<keyof T, string>>>
1130
+
1131
+ /** Register a field for form management. */
1132
+ register: (name: keyof T, options?: RegisterOptions) => FieldRegistration
1133
+
1134
+ /** Get the current value of a field. */
1135
+ getValue: <K extends keyof T>(name: K) => T[K]
1136
+
1137
+ /** Set the value of a field. */
1138
+ setValue: <K extends keyof T>(name: K, value: T[K]) => void
1139
+
1140
+ /** Get the error message for a field. */
1141
+ getError: (name: keyof T) => string | undefined
1142
+
1143
+ /** Set an error message for a field. */
1144
+ setError: (name: keyof T, error: string | undefined) => void
1145
+
1146
+ /** Clear all field errors. */
1147
+ clearErrors: () => void
1148
+
1149
+ /** Create a submit handler function. */
1150
+ handleSubmit: (
1151
+ onSubmit: (values: T) => void | Promise<void>,
1152
+ ) => (event?: { preventDefault?: () => void }) => Promise<void>
1153
+
1154
+ /** Reset the form to initial or provided values. */
1155
+ reset: (values?: Partial<T>) => void
1156
+
1157
+ /** Validate all fields. */
1158
+ validate: () => Promise<boolean>
1159
+
1160
+ /** The raw FormController instance for advanced use. */
1161
+ controller: FormController<T>
1162
+ }
1163
+ ```
1164
+
1165
+ #### `CreateLoginReturn`
1166
+
1167
+ Return type for createLogin primitive.
1168
+
1169
+ ```typescript
1170
+ interface CreateLoginReturn<T = unknown> {
1171
+ state: Accessor<PromiseState<AuthResult<T>>>
1172
+ login: (credentials: LoginCredentials) => Promise<AuthResult<T>>
1173
+ reset: () => void
1174
+ }
1175
+ ```
1176
+
1177
+ #### `CreateOAuthOptions`
1178
+
1179
+ OAuth configuration options.
1180
+
1181
+ ```typescript
1182
+ interface CreateOAuthOptions {
1183
+ /** Base URL for the API server (e.g. `https://api.example.com`). */
1184
+ baseURL?: string
1185
+ /** List of supported OAuth provider names (e.g. `['github', 'google']`). */
1186
+ oauthProviders?: string[]
1187
+ /** Path prefix for OAuth initiation routes. Defaults to `/oauth`. */
1188
+ oauthEndpoint?: string
1189
+ /** Path for the OAuth login POST endpoint. Defaults to `/users/log-in/oauth`. */
1190
+ loginEndpoint?: string
1191
+ /** Called after a successful OAuth login (session established). */
1192
+ onSuccess?: () => void
1193
+ /** Called with a failure message when the OAuth login fails. */
1194
+ onError?: (error: string) => void
908
1195
  /**
909
- * Checks if logging is enabled.
910
- *
911
- * @returns `true` if logging is currently enabled.
1196
+ * Auth client used to establish the session after the code exchange.
1197
+ * Overrides context resolution — when omitted, the client is resolved from
1198
+ * the surrounding `MoleculeProvider` (tolerated when absent; see the
1199
+ * cookie-session fallback documented on
1200
+ * {@link CreateOAuthReturn.handleCallback}).
912
1201
  */
913
- isEnabled(): boolean
1202
+ authClient?: AuthClient<unknown>
914
1203
  }
915
1204
  ```
916
1205
 
917
- #### `MoleculeConfig`
1206
+ #### `CreateOAuthReturn`
918
1207
 
919
- Configuration for molecule Solid context.
1208
+ Return type for createOAuth primitive.
920
1209
 
921
1210
  ```typescript
922
- interface MoleculeConfig {
923
- state?: StateProvider
924
- auth?: AuthClient<unknown>
925
- theme?: ThemeProvider
926
- router?: Router
927
- i18n?: I18nProvider
928
- http?: HttpClient
929
- storage?: StorageProvider
930
- logger?: LoggerProvider
1211
+ interface CreateOAuthReturn {
1212
+ /** Accessor for the configured OAuth provider names. */
1213
+ providers: Accessor<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 createOAuth});
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 is available (explicit option or context), the
1225
+ * session is established locally (`setAccessToken` + `setUser` +
1226
+ * `initialize`). When no client is available, the server has already
1227
+ * established the httpOnly-cookie session during the exchange, so a
1228
+ * user-carrying response still counts as success.
1229
+ */
1230
+ handleCallback: () => Promise<void>
931
1231
  }
932
1232
  ```
933
1233
 
934
- #### `MoleculeStore`
935
-
936
- Reactive state container with getState, setState, subscribe, and destroy.
1234
+ #### `CreatePasswordResetReturn`
937
1235
 
938
- All state management providers must implement this interface.
1236
+ Return type for createPasswordReset primitive.
939
1237
 
940
1238
  ```typescript
941
- interface Store<T> {
942
- /**
943
- * Gets the current state.
944
- */
945
- getState(): T
946
- /**
947
- * Sets the state (partial or via updater function).
948
- */
949
- setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
950
- /**
951
- * Subscribes to state changes.
952
- * Returns an unsubscribe function.
953
- */
954
- subscribe(listener: StateListener<T>): () => void
955
- /**
956
- * Destroys the store and cleans up subscriptions.
957
- */
958
- destroy(): void
1239
+ interface CreatePasswordResetReturn {
1240
+ requestState: Accessor<PromiseState<void>>
1241
+ confirmState: Accessor<PromiseState<void>>
1242
+ requestReset: (data: PasswordResetRequest) => Promise<void>
1243
+ confirmReset: (data: PasswordResetConfirm) => Promise<void>
1244
+ reset: () => void
959
1245
  }
960
1246
  ```
961
1247
 
@@ -976,6 +1262,19 @@ interface PlatformPrimitives {
976
1262
  }
977
1263
  ```
978
1264
 
1265
+ #### `CreatePromiseReturn`
1266
+
1267
+ Promise state accessor with actions.
1268
+
1269
+ ```typescript
1270
+ interface CreatePromiseReturn<T> {
1271
+ state: () => PromiseState<T>
1272
+ call: (...args: any[]) => Promise<T>
1273
+ cancel: (message?: string) => void
1274
+ reset: () => void
1275
+ }
1276
+ ```
1277
+
979
1278
  #### `PushPrimitives`
980
1279
 
981
1280
  Push primitives return type.
@@ -996,137 +1295,106 @@ interface PushPrimitives {
996
1295
  }
997
1296
  ```
998
1297
 
999
- #### `RouteLocation`
1298
+ #### `CreateSignupReturn`
1000
1299
 
1001
- Current URL decomposed into pathname, search string, hash, navigation state, and unique key.
1300
+ Return type for createSignup primitive.
1002
1301
 
1003
1302
  ```typescript
1004
- interface RouteLocation {
1005
- /**
1006
- * Current pathname.
1007
- */
1008
- pathname: string
1009
- /**
1010
- * Query string (including leading ?).
1011
- */
1012
- search: string
1013
- /**
1014
- * Hash (including leading #).
1015
- */
1016
- hash: string
1017
- /**
1018
- * State data passed with navigation.
1019
- */
1020
- state?: unknown
1021
- /**
1022
- * Unique key for this location.
1023
- */
1024
- key?: string
1303
+ interface CreateSignupReturn<T = unknown> {
1304
+ state: Accessor<PromiseState<AuthResult<T>>>
1305
+ signup: (data: RegisterData) => Promise<AuthResult<T>>
1306
+ reset: () => void
1025
1307
  }
1026
1308
  ```
1027
1309
 
1028
- #### `Router`
1310
+ #### `VersionPrimitives`
1029
1311
 
1030
- Client-side router providing navigation, guards, route matching, and history control.
1312
+ Version primitives return type.
1031
1313
 
1032
- All routing providers must implement this interface.
1314
+ ```typescript
1315
+ interface VersionPrimitives {
1316
+ state: Accessor<VersionState>
1317
+ isUpdateAvailable: Accessor<boolean>
1318
+ isChecking: Accessor<boolean>
1319
+ isServiceWorkerWaiting: Accessor<boolean>
1320
+ newVersion: Accessor<string | undefined>
1321
+ checkForUpdates: () => Promise<boolean>
1322
+ applyUpdate: (options?: { force?: boolean }) => void
1323
+ dismissUpdate: () => void
1324
+ startPeriodicChecks: (options?: UpdateCheckOptions) => void
1325
+ stopPeriodicChecks: () => void
1326
+ }
1327
+ ```
1328
+
1329
+ #### `MoleculeConfig`
1330
+
1331
+ Configuration for molecule Solid context.
1033
1332
 
1034
1333
  ```typescript
1035
- interface Router {
1036
- /**
1037
- * Returns the current route location (pathname, search, hash, state).
1038
- */
1039
- getLocation(): RouteLocation
1040
- /**
1041
- * Gets the current route params.
1042
- */
1043
- getParams<T extends RouteParams = RouteParams>(): T
1044
- /**
1045
- * Gets the current query params.
1046
- */
1047
- getQuery(): QueryParams
1048
- /**
1049
- * Gets a specific query parameter.
1050
- */
1051
- getQueryParam(key: string): string | undefined
1052
- /**
1053
- * Gets the current hash.
1054
- */
1055
- getHash(): string
1056
- /**
1057
- * Navigates to a path.
1058
- */
1059
- navigate(path: string, options?: NavigateOptions): void
1060
- /**
1061
- * Navigates to a named route.
1062
- */
1063
- navigateTo(
1064
- name: string,
1065
- params?: RouteParams,
1066
- query?: QueryParams,
1067
- options?: NavigateOptions,
1068
- ): void
1069
- /**
1070
- * Goes back in history.
1071
- */
1072
- back(): void
1073
- /**
1074
- * Goes forward in history.
1075
- */
1076
- forward(): void
1077
- /**
1078
- * Goes to a specific point in history.
1079
- */
1080
- go(delta: number): void
1081
- /**
1082
- * Updates the current query params.
1083
- */
1084
- setQuery(params: QueryParams, options?: NavigateOptions): void
1085
- /**
1086
- * Updates a specific query parameter.
1087
- */
1088
- setQueryParam(key: string, value: string | undefined, options?: NavigateOptions): void
1089
- /**
1090
- * Updates the current hash.
1091
- */
1092
- setHash(hash: string, options?: NavigateOptions): void
1093
- /**
1094
- * Checks if a path matches the current location.
1095
- *
1096
- * @returns `true` if the path matches the current route.
1097
- */
1098
- isActive(path: string, exact?: boolean): boolean
1099
- /**
1100
- * Matches a path pattern against a pathname.
1101
- */
1102
- matchPath<Params extends RouteParams = RouteParams>(
1103
- pattern: string,
1104
- pathname: string,
1105
- ): RouteMatch<Params> | null
1106
- /**
1107
- * Generates a URL from a named route.
1108
- */
1109
- generatePath(name: string, params?: RouteParams, query?: QueryParams): string
1110
- /**
1111
- * Subscribes to route changes.
1112
- */
1113
- subscribe(listener: RouteChangeListener): () => void
1114
- /**
1115
- * Adds a navigation guard.
1116
- */
1117
- addGuard(guard: NavigationGuard): () => void
1118
- /**
1119
- * Registers route definitions.
1120
- */
1121
- registerRoutes(routes: RouteDefinition[]): void
1122
- /**
1123
- * Gets all registered routes.
1124
- */
1125
- getRoutes(): RouteDefinition[]
1126
- /**
1127
- * Destroys the router.
1128
- */
1129
- destroy(): void
1334
+ interface MoleculeConfig {
1335
+ state?: StateProvider
1336
+ auth?: AuthClient<unknown>
1337
+ theme?: ThemeProvider
1338
+ router?: Router
1339
+ i18n?: I18nProvider
1340
+ http?: HttpClient
1341
+ storage?: StorageProvider
1342
+ logger?: LoggerProvider
1343
+ }
1344
+ ```
1345
+
1346
+ #### `HttpState`
1347
+
1348
+ State for async HTTP operations.
1349
+
1350
+ ```typescript
1351
+ interface HttpState<T> {
1352
+ data: T | null
1353
+ loading: boolean
1354
+ error: Error | null
1355
+ }
1356
+ ```
1357
+
1358
+ #### `StorageValueState`
1359
+
1360
+ State for async storage values.
1361
+
1362
+ ```typescript
1363
+ interface StorageValueState<T> {
1364
+ value: T | undefined
1365
+ loading: boolean
1366
+ error: Error | null
1367
+ }
1368
+ ```
1369
+
1370
+ #### `AuthPrimitives`
1371
+
1372
+ Auth primitives return type.
1373
+
1374
+ ```typescript
1375
+ interface AuthPrimitives<T = unknown> {
1376
+ state: Accessor<AuthState<T>>
1377
+ user: Accessor<T | null>
1378
+ isAuthenticated: Accessor<boolean>
1379
+ isLoading: Accessor<boolean>
1380
+ login: AuthClient<T>['login']
1381
+ logout: AuthClient<T>['logout']
1382
+ register: AuthClient<T>['register']
1383
+ refresh: AuthClient<T>['refresh']
1384
+ }
1385
+ ```
1386
+
1387
+ #### `ThemePrimitives`
1388
+
1389
+ Theme primitives return type.
1390
+
1391
+ ```typescript
1392
+ interface ThemePrimitives {
1393
+ theme: Accessor<Theme>
1394
+ themeName: Accessor<string>
1395
+ mode: Accessor<'light' | 'dark'>
1396
+ setTheme: (name: string) => void
1397
+ toggleTheme: () => void
1130
1398
  }
1131
1399
  ```
1132
1400
 
@@ -1147,232 +1415,125 @@ interface RouterPrimitives {
1147
1415
  }
1148
1416
  ```
1149
1417
 
1150
- #### `StateProvider`
1418
+ ### Types
1151
1419
 
1152
- State provider interface that all state management bond packages
1153
- must implement. Provides the store creation factory.
1420
+ #### `Accessor`
1154
1421
 
1155
1422
  ```typescript
1156
- interface StateProvider {
1157
- /**
1158
- * Creates a new store.
1159
- */
1160
- createStore<T>(config: StoreConfig<T>): Store<T>
1161
- }
1423
+ type Accessor<T> = () => T
1162
1424
  ```
1163
1425
 
1164
- #### `StorageProvider`
1165
-
1166
- Storage provider interface.
1167
-
1168
- All storage providers must implement this interface.
1426
+ #### `Setter`
1169
1427
 
1170
1428
  ```typescript
1171
- interface StorageProvider {
1172
- /**
1173
- * Gets a value from storage.
1174
- */
1175
- get<T = unknown>(key: string): Promise<T | null>
1176
- /**
1177
- * Sets a value in storage.
1178
- */
1179
- set<T = unknown>(key: string, value: T): Promise<void>
1180
- /**
1181
- * Removes a value from storage.
1182
- */
1183
- remove(key: string): Promise<void>
1184
- /**
1185
- * Clears all values from storage.
1186
- */
1187
- clear(): Promise<void>
1188
- /**
1189
- * Gets all keys in storage.
1190
- */
1191
- keys(): Promise<string[]>
1192
- /**
1193
- * Gets multiple values from storage.
1194
- */
1195
- getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>
1196
- /**
1197
- * Sets multiple values in storage.
1198
- */
1199
- setMany?<T = unknown>(entries: Array<[string, T]>): Promise<void>
1200
- /**
1201
- * Removes multiple values from storage.
1202
- */
1203
- removeMany?(keys: string[]): Promise<void>
1429
+ type Setter<in out T> = {
1430
+ <U extends T>(
1431
+ ...args: undefined extends T ? [] : [value: Exclude<U, Function> | ((prev: T) => U)]
1432
+ ): undefined extends T ? undefined : U
1433
+ <U extends T>(value: (prev: T) => U): U
1434
+ <U extends T>(value: Exclude<U, Function>): U
1435
+ <U extends T>(value: Exclude<U, Function> | ((prev: T) => U)): U
1204
1436
  }
1205
1437
  ```
1206
1438
 
1207
- #### `StorageValueState`
1439
+ #### `RouteParams`
1208
1440
 
1209
- State for async storage values.
1441
+ URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
1210
1442
 
1211
1443
  ```typescript
1212
- interface StorageValueState<T> {
1213
- value: T | undefined
1214
- loading: boolean
1215
- error: Error | null
1216
- }
1444
+ type RouteParams = Record<string, string>
1217
1445
  ```
1218
1446
 
1219
- #### `StoreConfig`
1447
+ #### `QueryParams`
1220
1448
 
1221
- Configuration for creating a store (initial state, optional name, and middleware chain).
1449
+ URL query string parameter map (single values or arrays for repeated keys).
1222
1450
 
1223
1451
  ```typescript
1224
- interface StoreConfig<T> {
1225
- /**
1226
- * Initial state value.
1227
- */
1228
- initialState: T
1229
- /**
1230
- * Optional name for debugging.
1231
- */
1232
- name?: string
1233
- /**
1234
- * Optional middleware functions.
1235
- */
1236
- middleware?: StoreMiddleware<T>[]
1237
- }
1452
+ type QueryParams = Record<string, string | string[] | undefined>
1238
1453
  ```
1239
1454
 
1240
- #### `Theme`
1455
+ ### Functions
1241
1456
 
1242
- Complete theme definition.
1457
+ #### `getStateProvider()`
1458
+
1459
+ Get the state provider from context.
1243
1460
 
1244
1461
  ```typescript
1245
- interface Theme {
1246
- name: string
1247
- mode: 'light' | 'dark'
1248
- colors: ThemeColors
1249
- breakpoints: ThemeBreakpoints
1250
- spacing: ThemeSpacing
1251
- typography: ThemeTypography
1252
- borderRadius: ThemeBorderRadius
1253
- shadows: ThemeShadows
1254
- transitions: ThemeTransitions
1255
- zIndex: ThemeZIndex
1256
- }
1462
+ function getStateProvider(): StateProvider
1257
1463
  ```
1258
1464
 
1259
- #### `ThemePrimitives`
1465
+ **Returns:** The state provider instance.
1260
1466
 
1261
- Theme primitives return type.
1467
+ #### `getAuthClient()`
1468
+
1469
+ Get the auth client from context.
1262
1470
 
1263
1471
  ```typescript
1264
- interface ThemePrimitives {
1265
- theme: Accessor<Theme>
1266
- themeName: Accessor<string>
1267
- mode: Accessor<'light' | 'dark'>
1268
- setTheme: (name: string) => void
1269
- toggleTheme: () => void
1270
- }
1472
+ function getAuthClient(): AuthClient<T, Record<never, never>>
1271
1473
  ```
1272
1474
 
1273
- #### `ThemeProvider`
1475
+ **Returns:** The auth client instance.
1274
1476
 
1275
- Manages theme state including the active theme, mode toggling,
1276
- and change subscriptions.
1477
+ #### `getThemeProvider()`
1478
+
1479
+ Get the theme provider from context.
1277
1480
 
1278
1481
  ```typescript
1279
- interface ThemeProvider {
1280
- /**
1281
- * Returns the currently active theme.
1282
- */
1283
- getTheme(): Theme
1284
- /**
1285
- * Sets the active theme by reference or by name.
1286
- *
1287
- * @param theme - A `Theme` object or a theme name string to activate.
1288
- */
1289
- setTheme(theme: Theme | string): void
1290
- /**
1291
- * Toggles between light and dark mode for the active theme.
1292
- */
1293
- toggleMode(): void
1294
- /**
1295
- * Subscribes to theme changes. The callback fires whenever
1296
- * `setTheme()` or `toggleMode()` is called.
1297
- *
1298
- * @param callback - Invoked with the new theme after each change.
1299
- * @returns An unsubscribe function.
1300
- */
1301
- subscribe(callback: (theme: Theme) => void): () => void
1302
- /**
1303
- * Returns all registered themes. Optional — not all providers
1304
- * support multiple themes.
1305
- */
1306
- getThemes?(): Theme[]
1307
- }
1482
+ function getThemeProvider(): ThemeProvider
1308
1483
  ```
1309
1484
 
1310
- #### `VersionPrimitives`
1485
+ **Returns:** The theme provider instance.
1311
1486
 
1312
- Version primitives return type.
1487
+ #### `getRouter()`
1488
+
1489
+ Get the router from context.
1313
1490
 
1314
1491
  ```typescript
1315
- interface VersionPrimitives {
1316
- state: Accessor<VersionState>
1317
- isUpdateAvailable: Accessor<boolean>
1318
- isChecking: Accessor<boolean>
1319
- isServiceWorkerWaiting: Accessor<boolean>
1320
- newVersion: Accessor<string | undefined>
1321
- checkForUpdates: () => Promise<boolean>
1322
- applyUpdate: (options?: { force?: boolean }) => void
1323
- dismissUpdate: () => void
1324
- startPeriodicChecks: (options?: UpdateCheckOptions) => void
1325
- stopPeriodicChecks: () => void
1326
- }
1492
+ function getRouter(): Router
1327
1493
  ```
1328
1494
 
1329
- ### Types
1495
+ **Returns:** The router instance.
1330
1496
 
1331
- #### `Accessor`
1497
+ #### `getI18nProvider()`
1498
+
1499
+ Get the i18n provider from context.
1332
1500
 
1333
1501
  ```typescript
1334
- type Accessor<T> = () => T
1502
+ function getI18nProvider(): I18nProvider
1335
1503
  ```
1336
1504
 
1337
- #### `QueryParams`
1505
+ **Returns:** The i18n provider instance.
1338
1506
 
1339
- URL query string parameter map (single values or arrays for repeated keys).
1507
+ #### `getHttpClient()`
1508
+
1509
+ Get the HTTP client from context.
1340
1510
 
1341
1511
  ```typescript
1342
- type QueryParams = Record<string, string | string[] | undefined>
1512
+ function getHttpClient(): HttpClient
1343
1513
  ```
1344
1514
 
1345
- #### `RouteParams`
1346
-
1347
- URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
1515
+ **Returns:** The HTTP client instance.
1348
1516
 
1349
- ```typescript
1350
- type RouteParams = Record<string, string>
1351
- ```
1517
+ #### `getStorageProvider()`
1352
1518
 
1353
- #### `Setter`
1519
+ Get the storage provider from context.
1354
1520
 
1355
1521
  ```typescript
1356
- type Setter<in out T> = {
1357
- <U extends T>(
1358
- ...args: undefined extends T ? [] : [value: Exclude<U, Function> | ((prev: T) => U)]
1359
- ): undefined extends T ? undefined : U
1360
- <U extends T>(value: (prev: T) => U): U
1361
- <U extends T>(value: Exclude<U, Function>): U
1362
- <U extends T>(value: Exclude<U, Function> | ((prev: T) => U)): U
1363
- }
1522
+ function getStorageProvider(): StorageProvider
1364
1523
  ```
1365
1524
 
1366
- ### Functions
1525
+ **Returns:** The storage provider instance.
1367
1526
 
1368
- #### `applyThemeToDocument()`
1527
+ #### `getLoggerProvider()`
1369
1528
 
1370
- Apply theme CSS variables to document.
1529
+ Get the logger provider from context.
1371
1530
 
1372
1531
  ```typescript
1373
- function applyThemeToDocument(): void
1532
+ function getLoggerProvider(): LoggerProvider
1374
1533
  ```
1375
1534
 
1535
+ **Returns:** The logger provider instance.
1536
+
1376
1537
  #### `createAsyncState(initialState)`
1377
1538
 
1378
1539
  Primitive like createSignal but accepts Promises and supports partial state extension.
@@ -1395,18 +1556,6 @@ function createAuth(): AuthPrimitives<T>
1395
1556
 
1396
1557
  **Returns:** Auth primitives object
1397
1558
 
1398
- #### `createAuthFromClient(client)`
1399
-
1400
- Create auth primitives from a specific client.
1401
-
1402
- ```typescript
1403
- function createAuthFromClient(client: AuthClient<T>): AuthPrimitives<T>
1404
- ```
1405
-
1406
- - `client` — Auth client
1407
-
1408
- **Returns:** Auth primitives
1409
-
1410
1559
  #### `createAuthGuard(redirectTo)`
1411
1560
 
1412
1561
  Create a guard primitive that redirects unauthenticated users.
@@ -1437,6 +1586,18 @@ function createAuthHelpers(): {
1437
1586
 
1438
1587
  **Returns:** The created result.
1439
1588
 
1589
+ #### `createAuthFromClient(client)`
1590
+
1591
+ Create auth primitives from a specific client.
1592
+
1593
+ ```typescript
1594
+ function createAuthFromClient(client: AuthClient<T, Record<never, never>>): AuthPrimitives<T>
1595
+ ```
1596
+
1597
+ - `client` — Auth client
1598
+
1599
+ **Returns:** Auth primitives
1600
+
1440
1601
  #### `createCapacitorApp(options)`
1441
1602
 
1442
1603
  Create Capacitor app primitives for native app initialization.
@@ -1464,16 +1625,29 @@ function createChangePassword(): CreateChangePasswordReturn
1464
1625
 
1465
1626
  #### `createDevice()`
1466
1627
 
1467
- Create device primitives for accessing device information.
1628
+ Create device primitives for accessing device information.
1629
+
1630
+ This is a static primitive (no reactive signals) since device info
1631
+ does not change during the lifecycle of the app.
1632
+
1633
+ ```typescript
1634
+ function createDevice(): DevicePrimitives
1635
+ ```
1636
+
1637
+ **Returns:** Device primitives object
1638
+
1639
+ #### `createForm(provider, options)`
1468
1640
 
1469
- This is a static primitive (no reactive signals) since device info
1470
- does not change during the lifecycle of the app.
1641
+ Create form primitives for form state management and validation.
1471
1642
 
1472
1643
  ```typescript
1473
- function createDevice(): DevicePrimitives
1644
+ function createForm(provider: FormProvider, options: FormOptions<T>): CreateFormResult<T>
1474
1645
  ```
1475
1646
 
1476
- **Returns:** Device primitives object
1647
+ - `provider` — Form provider that creates controllers
1648
+ - `options` — Form configuration options
1649
+
1650
+ **Returns:** Form primitives object
1477
1651
 
1478
1652
  #### `createFieldSignal(controller, name)`
1479
1653
 
@@ -1491,33 +1665,18 @@ function createFieldSignal(
1491
1665
 
1492
1666
  **Returns:** Accessor for the field state
1493
1667
 
1494
- #### `createForm(provider, options)`
1495
-
1496
- Create form primitives for form state management and validation.
1497
-
1498
- ```typescript
1499
- function createForm(provider: FormProvider, options: FormOptions<T>): CreateFormResult<T>
1500
- ```
1501
-
1502
- - `provider` — Form provider that creates controllers
1503
- - `options` — Form configuration options
1504
-
1505
- **Returns:** Form primitives object
1506
-
1507
- #### `createFormFromController(controller)`
1508
-
1509
- Create form primitives from an existing controller.
1668
+ #### `createWatchSignal(controller, name)`
1510
1669
 
1511
- Useful when you have a controller created externally and want to
1512
- wrap it with Solid reactivity.
1670
+ Create a reactive accessor that tracks a single field's value.
1513
1671
 
1514
1672
  ```typescript
1515
- function createFormFromController(controller: FormController<T>): CreateFormResult<T>
1673
+ function createWatchSignal(controller: FormController<T>, name: K): Accessor<T[K]>
1516
1674
  ```
1517
1675
 
1518
- - `controller` — An existing FormController
1676
+ - `controller` — Form controller
1677
+ - `name` — Field name to watch
1519
1678
 
1520
- **Returns:** Form primitives object
1679
+ **Returns:** Accessor for the field value
1521
1680
 
1522
1681
  #### `createFormHelpers(provider)`
1523
1682
 
@@ -1533,931 +1692,857 @@ function createFormHelpers(provider: FormProvider): {
1533
1692
 
1534
1693
  **Returns:** The created result.
1535
1694
 
1536
- #### `createHttp()`
1537
-
1538
- Creates a http.
1539
-
1540
- ```typescript
1541
- function createHttp(): {
1542
- get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1543
- post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1544
- put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1545
- patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1546
- delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1547
- request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1548
- }
1549
- ```
1550
-
1551
- **Returns:** The created result.
1695
+ #### `createFormFromController(controller)`
1552
1696
 
1553
- #### `createHttpFromClient(client)`
1697
+ Create form primitives from an existing controller.
1554
1698
 
1555
- Creates a http from client.
1699
+ Useful when you have a controller created externally and want to
1700
+ wrap it with Solid reactivity.
1556
1701
 
1557
1702
  ```typescript
1558
- function createHttpFromClient(client: HttpClient): {
1559
- get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1560
- post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1561
- put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1562
- patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1563
- delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1564
- request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1565
- }
1703
+ function createFormFromController(controller: FormController<T>): CreateFormResult<T>
1566
1704
  ```
1567
1705
 
1568
- - `client` — The client instance.
1706
+ - `controller` — An existing FormController
1569
1707
 
1570
- **Returns:** The created result.
1708
+ **Returns:** Form primitives object
1571
1709
 
1572
- #### `createHttpHelpers()`
1710
+ #### `createHttp()`
1573
1711
 
1574
- Creates a http helpers.
1712
+ Creates a http.
1575
1713
 
1576
1714
  ```typescript
1577
- function createHttpHelpers(): {
1715
+ function createHttp(): {
1578
1716
  get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1579
1717
  post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1580
1718
  put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1581
1719
  patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1582
1720
  delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1583
- setAuthToken: (token: string | null) => void
1584
- getAuthToken: () => string | null
1585
- }
1586
- ```
1587
-
1588
- **Returns:** The created result.
1589
-
1590
- #### `createI18n()`
1591
-
1592
- Creates a i18n.
1593
-
1594
- ```typescript
1595
- function createI18n(): {
1596
- t: TranslateFunction
1597
- locale: Accessor<string>
1598
- setLocale: (newLocale: string) => Promise<void>
1599
- isReady: Accessor<boolean>
1600
- getLocales: () => LocaleConfig[]
1601
- hasKey: (key: string) => boolean
1721
+ request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1602
1722
  }
1603
1723
  ```
1604
1724
 
1605
1725
  **Returns:** The created result.
1606
1726
 
1607
- #### `createI18nFromProvider(provider)`
1727
+ #### `useFetch(url, config)`
1608
1728
 
1609
- Creates a i18n from provider.
1729
+ Create a resource for fetching data.
1610
1730
 
1611
1731
  ```typescript
1612
- function createI18nFromProvider(provider: I18nProvider): {
1613
- t: TranslateFunction
1614
- locale: Accessor<string>
1615
- setLocale: (newLocale: string) => Promise<void>
1616
- isReady: Accessor<boolean>
1617
- getLocales: () => LocaleConfig[]
1618
- hasKey: (key: string) => boolean
1619
- }
1732
+ function useFetch(url: string | Accessor<string>, config?: RequestConfig): Resource<T | undefined>
1620
1733
  ```
1621
1734
 
1622
- - `provider` — The provider implementation.
1735
+ - `url` — URL string or accessor returning a URL string.
1736
+ - `config` — Optional request configuration.
1623
1737
 
1624
- **Returns:** The created result.
1738
+ **Returns:** Solid resource
1625
1739
 
1626
- #### `createI18nHelpers()`
1740
+ #### `useMutation()`
1627
1741
 
1628
- Creates a i18n helpers.
1742
+ Hook for mutation.
1629
1743
 
1630
1744
  ```typescript
1631
- function createI18nHelpers(): {
1632
- t: TranslateFunction
1633
- getLocale: () => string
1634
- setLocale: (locale: string) => Promise<void>
1635
- getLocales: () => LocaleConfig[]
1636
- hasKey: (key: string) => boolean
1637
- isReady: () => boolean
1745
+ function useMutation(): {
1746
+ mutate: (
1747
+ url: string,
1748
+ payload?: unknown,
1749
+ method?: 'POST' | 'PUT' | 'PATCH' | 'DELETE',
1750
+ ) => Promise<T>
1751
+ isLoading: Accessor<boolean>
1752
+ error: Accessor<Error | null>
1753
+ data: Accessor<T | null>
1754
+ reset: () => void
1638
1755
  }
1639
1756
  ```
1640
1757
 
1641
- **Returns:** The created result.
1642
-
1643
- #### `createIsActive(path, exact)`
1644
-
1645
- Create a reactive boolean accessor that tracks whether a given path is active.
1646
-
1647
- Unlike `useMatch` which only accepts a static pattern, this factory returns
1648
- a signal that re-evaluates on every route change and supports the `exact`
1649
- parameter from the router's `isActive` method.
1650
-
1651
- ```typescript
1652
- function createIsActive(path: string, exact?: boolean): Accessor<boolean>
1653
- ```
1654
-
1655
- - `path` — Path to check against the current location
1656
- - `exact` — Whether to require an exact match (default: false)
1657
-
1658
- **Returns:** Accessor<boolean> that is true when the path is active
1659
-
1660
- #### `createLogger(config)`
1661
-
1662
- Create a logger with custom configuration.
1663
-
1664
- ```typescript
1665
- function createLogger(config: LoggerConfig): Logger
1666
- ```
1667
-
1668
- - `config` — Logger configuration
1669
-
1670
- **Returns:** Logger instance
1671
-
1672
- #### `createLoggerFromProvider(provider, name)`
1673
-
1674
- Create logger from a specific provider.
1675
-
1676
- ```typescript
1677
- function createLoggerFromProvider(provider: LoggerProvider, name?: string): Logger
1678
- ```
1679
-
1680
- - `provider` — Logger provider
1681
- - `name` — Logger name
1682
-
1683
- **Returns:** Logger instance
1758
+ **Returns:** The result.
1684
1759
 
1685
- #### `createLoggerHelpers()`
1760
+ #### `useLazyQuery()`
1686
1761
 
1687
- Creates a logger helpers.
1762
+ Hook for lazy query.
1688
1763
 
1689
1764
  ```typescript
1690
- function createLoggerHelpers(): {
1691
- getLogger: (name?: string) => Logger
1692
- createLogger: (config: LoggerConfig) => Logger
1693
- setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
1694
- getLevel: () => string
1695
- enable: () => void
1696
- disable: () => void
1697
- isEnabled: () => boolean
1765
+ function useLazyQuery(): {
1766
+ execute: (url: string, config?: RequestConfig) => Promise<T>
1767
+ data: () => T | null
1768
+ isLoading: () => boolean
1769
+ error: () => Error | null
1770
+ reset: () => void
1698
1771
  }
1699
1772
  ```
1700
1773
 
1701
- **Returns:** The created result.
1774
+ **Returns:** The result.
1702
1775
 
1703
- #### `createLoggerHelpersFromProvider(provider)`
1776
+ #### `createHttpHelpers()`
1704
1777
 
1705
- Creates a logger helpers from provider.
1778
+ Creates a http helpers.
1706
1779
 
1707
1780
  ```typescript
1708
- function createLoggerHelpersFromProvider(provider: LoggerProvider): {
1709
- getLogger: (name?: string) => Logger
1710
- createLogger: (config: LoggerConfig) => Logger
1711
- setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
1712
- getLevel: () => string
1713
- enable: () => void
1714
- disable: () => void
1715
- isEnabled: () => boolean
1781
+ function createHttpHelpers(): {
1782
+ get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1783
+ post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1784
+ put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1785
+ patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1786
+ delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1787
+ setAuthToken: (token: string | null) => void
1788
+ getAuthToken: () => string | null
1716
1789
  }
1717
1790
  ```
1718
1791
 
1719
- - `provider` — The provider implementation.
1720
-
1721
1792
  **Returns:** The created result.
1722
1793
 
1723
- #### `createLogin()`
1724
-
1725
- Creates a login primitive with async state tracking.
1726
-
1727
- ```typescript
1728
- function createLogin(): CreateLoginReturn<T>
1729
- ```
1730
-
1731
- **Returns:** Login state and action
1732
-
1733
- #### `createOAuth(options)`
1734
-
1735
- Creates OAuth helpers.
1736
-
1737
- Automatically handles OAuth callbacks by detecting `code` and `state` URL
1738
- parameters and exchanging them for a session:
1794
+ #### `createHttpFromClient(client)`
1739
1795
 
1740
- - Inside a Solid owner (component setup / `createRoot`), the callback
1741
- handling is deferred to `onMount` so it runs client-side after mount.
1742
- - Outside an owner (a plain function call, e.g. bootstrap code), it runs
1743
- immediately at creation, browser-guarded.
1796
+ Creates a http from client.
1744
1797
 
1745
1798
  ```typescript
1746
- function createOAuth(options?: CreateOAuthOptions): CreateOAuthReturn
1799
+ function createHttpFromClient(client: HttpClient): {
1800
+ get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1801
+ post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1802
+ put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1803
+ patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1804
+ delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1805
+ request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1806
+ }
1747
1807
  ```
1748
1808
 
1749
- - `options` — OAuth configuration
1809
+ - `client` — The client instance.
1750
1810
 
1751
- **Returns:** The created instance.
1811
+ **Returns:** The created result.
1752
1812
 
1753
- #### `createPasswordReset()`
1813
+ #### `createI18n()`
1754
1814
 
1755
- Creates a password reset primitive with async state tracking.
1815
+ Creates a i18n.
1756
1816
 
1757
1817
  ```typescript
1758
- function createPasswordReset(): CreatePasswordResetReturn
1818
+ function createI18n(): {
1819
+ t: TranslateFunction
1820
+ locale: Accessor<string>
1821
+ setLocale: (newLocale: string) => Promise<void>
1822
+ isReady: Accessor<boolean>
1823
+ getLocales: () => LocaleConfig[]
1824
+ hasKey: (key: string) => boolean
1825
+ }
1759
1826
  ```
1760
1827
 
1761
- **Returns:** Password reset state and actions
1828
+ **Returns:** The created result.
1762
1829
 
1763
- #### `createPersistedStore(key, initial, storage)`
1830
+ #### `useTranslate()`
1764
1831
 
1765
- Create a persisted signal store.
1832
+ Get translate function.
1766
1833
 
1767
1834
  ```typescript
1768
- function createPersistedStore(
1769
- key: string,
1770
- initial: T,
1771
- storage: StorageAdapter,
1772
- ): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
1835
+ function useTranslate(): TranslateFunction
1773
1836
  ```
1774
1837
 
1775
- - `key` — Storage key
1776
- - `initial` — Initial value
1777
- - `storage` — Storage adapter (required - use localStorage, sessionStorage, or `@molecule/app-storage`)
1778
-
1779
- **Returns:** Tuple of accessor and setter
1780
-
1781
- #### `createPlatform()`
1838
+ **Returns:** Translate function
1782
1839
 
1783
- Create platform primitives for detecting the current platform.
1840
+ #### `useLocale()`
1784
1841
 
1785
- This is a static primitive (no reactive signals) since the platform
1786
- does not change during the lifecycle of the app.
1842
+ Get current locale as accessor.
1787
1843
 
1788
1844
  ```typescript
1789
- function createPlatform(): PlatformPrimitives
1845
+ function useLocale(): Accessor<string>
1790
1846
  ```
1791
1847
 
1792
- **Returns:** Platform primitives object
1848
+ **Returns:** Accessor for current locale
1793
1849
 
1794
- #### `createPromise(asyncFn)`
1850
+ #### `useTranslation(key, values, options)`
1795
1851
 
1796
- Primitive that wraps an async function with reactive state tracking.
1852
+ Create a reactive translation.
1797
1853
 
1798
1854
  ```typescript
1799
- function createPromise(asyncFn: T): CreatePromiseReturn<Awaited<ReturnType<T>>>
1855
+ function useTranslation(
1856
+ key: string,
1857
+ values?: InterpolationValues,
1858
+ options?: TranslateOptions,
1859
+ ): Accessor<string>
1800
1860
  ```
1801
1861
 
1802
- - `asyncFn` — The async function to wrap
1862
+ - `key` — Translation key
1863
+ - `values` — Interpolation values for the translation.
1864
+ - `options` — Translation options
1803
1865
 
1804
- **Returns:** Object with state accessor, call, cancel, and reset functions
1866
+ **Returns:** Accessor for translated string
1805
1867
 
1806
- #### `createPush()`
1868
+ #### `usePlural(key, count, values)`
1807
1869
 
1808
- Create push notification primitives.
1870
+ Create a reactive plural translation.
1809
1871
 
1810
1872
  ```typescript
1811
- function createPush(): PushPrimitives
1873
+ function usePlural(
1874
+ key: string,
1875
+ count: Accessor<number>,
1876
+ values?: InterpolationValues,
1877
+ ): Accessor<string>
1812
1878
  ```
1813
1879
 
1814
- **Returns:** Push primitives object
1815
-
1816
- #### `createRouter()`
1817
-
1818
- Create router primitives for navigation state and actions.
1819
-
1820
- ```typescript
1821
- function createRouter(): RouterPrimitives
1822
- ```
1880
+ - `key` — Translation key
1881
+ - `count` — Count accessor for pluralization
1882
+ - `values` — Interpolation values for the translation.
1823
1883
 
1824
- **Returns:** Router primitives object
1884
+ **Returns:** Accessor for translated string
1825
1885
 
1826
- #### `createRouterFromInstance(router)`
1886
+ #### `createI18nHelpers()`
1827
1887
 
1828
- Create router primitives from a specific router.
1888
+ Creates a i18n helpers.
1829
1889
 
1830
1890
  ```typescript
1831
- function createRouterFromInstance(router: Router): RouterPrimitives
1891
+ function createI18nHelpers(): {
1892
+ t: TranslateFunction
1893
+ getLocale: () => string
1894
+ setLocale: (locale: string) => Promise<void>
1895
+ getLocales: () => LocaleConfig[]
1896
+ hasKey: (key: string) => boolean
1897
+ isReady: () => boolean
1898
+ }
1832
1899
  ```
1833
1900
 
1834
- - `router` — Router instance
1835
-
1836
- **Returns:** Router primitives
1901
+ **Returns:** The created result.
1837
1902
 
1838
- #### `createRouterHelpers()`
1903
+ #### `createI18nFromProvider(provider)`
1839
1904
 
1840
- Creates a router helpers.
1905
+ Creates a i18n from provider.
1841
1906
 
1842
1907
  ```typescript
1843
- function createRouterHelpers(): {
1844
- navigate: (path: string, options?: NavigateOptions) => void
1845
- navigateTo: (
1846
- name: string,
1847
- params?: RouteParams,
1848
- query?: QueryParams,
1849
- options?: NavigateOptions,
1850
- ) => void
1851
- back: () => void
1852
- forward: () => void
1853
- getLocation: () => RouteLocation
1854
- getParams: () => RouteParams
1855
- getQuery: () => QueryParams
1856
- isActive: (path: string) => boolean
1908
+ function createI18nFromProvider(provider: I18nProvider): {
1909
+ t: TranslateFunction
1910
+ locale: Accessor<string>
1911
+ setLocale: (newLocale: string) => Promise<void>
1912
+ isReady: Accessor<boolean>
1913
+ getLocales: () => LocaleConfig[]
1914
+ hasKey: (key: string) => boolean
1857
1915
  }
1858
1916
  ```
1859
1917
 
1918
+ - `provider` — The provider implementation.
1919
+
1860
1920
  **Returns:** The created result.
1861
1921
 
1862
- #### `createSignalStore(initial)`
1922
+ #### `getLogger(name)`
1863
1923
 
1864
- Create a simple signal-based store without provider.
1924
+ Get a logger instance.
1865
1925
 
1866
1926
  ```typescript
1867
- function createSignalStore(initial: T): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
1927
+ function getLogger(name?: string): Logger
1868
1928
  ```
1869
1929
 
1870
- - `initial` — Initial state
1930
+ - `name` — Logger name
1871
1931
 
1872
- **Returns:** The created instance.
1932
+ **Returns:** Logger instance
1873
1933
 
1874
- #### `createSignup()`
1934
+ #### `createLogger(config)`
1875
1935
 
1876
- Creates a signup primitive with async state tracking.
1936
+ Create a logger with custom configuration.
1877
1937
 
1878
1938
  ```typescript
1879
- function createSignup(): CreateSignupReturn<T>
1939
+ function createLogger(config: LoggerConfig): Logger
1880
1940
  ```
1881
1941
 
1882
- **Returns:** Signup state and action
1942
+ - `config` — Logger configuration
1883
1943
 
1884
- #### `createStateHelpers()`
1944
+ **Returns:** Logger instance
1885
1945
 
1886
- Creates a state helpers.
1946
+ #### `getRootLogger()`
1947
+
1948
+ Get the root logger.
1887
1949
 
1888
1950
  ```typescript
1889
- function createStateHelpers(): {
1890
- createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
1891
- }
1951
+ function getRootLogger(): Logger
1892
1952
  ```
1893
1953
 
1894
- **Returns:** The created result.
1954
+ **Returns:** Root logger instance
1895
1955
 
1896
- #### `createStateHelpersFromProvider(provider)`
1956
+ #### `getChildLogger(name, context)`
1897
1957
 
1898
- Creates a state helpers from provider.
1958
+ Create a child logger with additional context.
1899
1959
 
1900
1960
  ```typescript
1901
- function createStateHelpersFromProvider(provider: StateProvider): {
1902
- createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
1903
- }
1961
+ function getChildLogger(name: string, context: Record<string, unknown>): Logger
1904
1962
  ```
1905
1963
 
1906
- - `provider` — The provider implementation.
1964
+ - `name` — Parent logger name
1965
+ - `context` — Additional context
1907
1966
 
1908
- **Returns:** The created result.
1967
+ **Returns:** Child logger instance
1909
1968
 
1910
- #### `createStorage()`
1969
+ #### `useComponentLogger(componentName)`
1911
1970
 
1912
- Create storage primitives.
1971
+ Create a component logger that includes component name in context.
1913
1972
 
1914
1973
  ```typescript
1915
- function createStorage(): {
1916
- get: <T>(key: string) => Promise<T | null>
1917
- set: <T>(key: string, value: T) => Promise<void>
1918
- remove: (key: string) => Promise<void>
1919
- clear: () => Promise<void>
1920
- keys: () => Promise<string[]>
1921
- }
1974
+ function useComponentLogger(componentName: string): Logger
1922
1975
  ```
1923
1976
 
1924
- **Returns:** Storage methods
1977
+ - `componentName` — Name of the component
1925
1978
 
1926
- #### `createStorageFromProvider(storage)`
1979
+ **Returns:** Logger configured for the component
1927
1980
 
1928
- Create storage primitives from a specific provider.
1981
+ #### `createLoggerHelpers()`
1982
+
1983
+ Creates a logger helpers.
1929
1984
 
1930
1985
  ```typescript
1931
- function createStorageFromProvider(storage: StorageProvider): {
1932
- get: <T>(key: string) => Promise<T | null>
1933
- set: <T>(key: string, value: T) => Promise<void>
1934
- remove: (key: string) => Promise<void>
1935
- clear: () => Promise<void>
1936
- keys: () => Promise<string[]>
1986
+ function createLoggerHelpers(): {
1987
+ getLogger: (name?: string) => Logger
1988
+ createLogger: (config: LoggerConfig) => Logger
1989
+ setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
1990
+ getLevel: () => string
1991
+ enable: () => void
1992
+ disable: () => void
1993
+ isEnabled: () => boolean
1937
1994
  }
1938
1995
  ```
1939
1996
 
1940
- - `storage` — Storage provider
1941
-
1942
- **Returns:** Storage methods
1997
+ **Returns:** The created result.
1943
1998
 
1944
- #### `createStorageHelpers()`
1999
+ #### `createLoggerHelpersFromProvider(provider)`
1945
2000
 
1946
- Create storage helpers from context.
2001
+ Creates a logger helpers from provider.
1947
2002
 
1948
2003
  ```typescript
1949
- function createStorageHelpers(): {
1950
- get: <T>(key: string) => Promise<T | null>
1951
- set: <T>(key: string, value: T) => Promise<void>
1952
- remove: (key: string) => Promise<void>
1953
- clear: () => Promise<void>
1954
- keys: () => Promise<string[]>
2004
+ function createLoggerHelpersFromProvider(provider: LoggerProvider): {
2005
+ getLogger: (name?: string) => Logger
2006
+ createLogger: (config: LoggerConfig) => Logger
2007
+ setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
2008
+ getLevel: () => string
2009
+ enable: () => void
2010
+ disable: () => void
2011
+ isEnabled: () => boolean
1955
2012
  }
1956
2013
  ```
1957
2014
 
1958
- **Returns:** Storage helper functions
2015
+ - `provider` — The provider implementation.
1959
2016
 
1960
- #### `createStorageValue(key, defaultValue)`
2017
+ **Returns:** The created result.
1961
2018
 
1962
- Create a storage value primitive.
2019
+ #### `createLoggerFromProvider(provider, name)`
2020
+
2021
+ Create logger from a specific provider.
1963
2022
 
1964
2023
  ```typescript
1965
- function createStorageValue(
1966
- key: string,
1967
- defaultValue?: T,
1968
- ): {
1969
- value: () => T | undefined
1970
- loading: () => boolean
1971
- error: () => Error | null
1972
- set: (value: T) => Promise<void>
1973
- remove: () => Promise<void>
1974
- refresh: () => Promise<T | undefined>
1975
- }
2024
+ function createLoggerFromProvider(provider: LoggerProvider, name?: string): Logger
1976
2025
  ```
1977
2026
 
1978
- - `key` — Storage key
1979
- - `defaultValue` — Default value if not found
2027
+ - `provider` — Logger provider
2028
+ - `name` — Logger name
1980
2029
 
1981
- **Returns:** Storage value accessor and actions
2030
+ **Returns:** Logger instance
1982
2031
 
1983
- #### `createStorageValueFromProvider(storage, key, defaultValue)`
2032
+ #### `createLogin()`
1984
2033
 
1985
- Create storage value primitive from a specific provider.
2034
+ Creates a login primitive with async state tracking.
1986
2035
 
1987
2036
  ```typescript
1988
- function createStorageValueFromProvider(
1989
- storage: StorageProvider,
1990
- key: string,
1991
- defaultValue?: T,
1992
- ): {
1993
- value: () => T | undefined
1994
- loading: () => boolean
1995
- error: () => Error | null
1996
- set: (value: T) => Promise<void>
1997
- remove: () => Promise<void>
1998
- }
2037
+ function createLogin(): CreateLoginReturn<T>
1999
2038
  ```
2000
2039
 
2001
- - `storage` — Storage provider
2002
- - `key` — Storage key
2003
- - `defaultValue` — Default value
2040
+ **Returns:** Login state and action
2004
2041
 
2005
- **Returns:** Storage value accessor and actions
2042
+ #### `createOAuth(options)`
2006
2043
 
2007
- #### `createStore(config)`
2044
+ Creates OAuth helpers.
2008
2045
 
2009
- Create a reactive store using Solid signals.
2046
+ Automatically handles OAuth callbacks by detecting `code` and `state` URL
2047
+ parameters and exchanging them for a session:
2048
+
2049
+ - Inside a Solid owner (component setup / `createRoot`), the callback
2050
+ handling is deferred to `onMount` so it runs client-side after mount.
2051
+ - Outside an owner (a plain function call, e.g. bootstrap code), it runs
2052
+ immediately at creation, browser-guarded.
2010
2053
 
2011
2054
  ```typescript
2012
- function createStore(config: StoreConfig<T>): Store<T>
2055
+ function createOAuth(options?: CreateOAuthOptions): CreateOAuthReturn
2013
2056
  ```
2014
2057
 
2015
- - `config` — Store configuration
2058
+ - `options` — OAuth configuration
2016
2059
 
2017
- **Returns:** Store instance
2060
+ **Returns:** The created instance.
2018
2061
 
2019
- #### `createTheme()`
2062
+ #### `createPasswordReset()`
2020
2063
 
2021
- Create theme primitives for theme state and actions.
2064
+ Creates a password reset primitive with async state tracking.
2022
2065
 
2023
2066
  ```typescript
2024
- function createTheme(): ThemePrimitives
2067
+ function createPasswordReset(): CreatePasswordResetReturn
2025
2068
  ```
2026
2069
 
2027
- **Returns:** The created instance.
2070
+ **Returns:** Password reset state and actions
2028
2071
 
2029
- #### `createThemeColors(theme)`
2072
+ #### `createPlatform()`
2030
2073
 
2031
- Create a colors accessor derived from a theme accessor.
2074
+ Create platform primitives for detecting the current platform.
2075
+
2076
+ This is a static primitive (no reactive signals) since the platform
2077
+ does not change during the lifecycle of the app.
2032
2078
 
2033
2079
  ```typescript
2034
- function createThemeColors(theme: Accessor<Theme>): Accessor<ThemeColors>
2080
+ function createPlatform(): PlatformPrimitives
2035
2081
  ```
2036
2082
 
2037
- - `theme` — Theme accessor (e.g. from createTheme().theme)
2038
-
2039
- **Returns:** Accessor for the current theme colors
2083
+ **Returns:** Platform primitives object
2040
2084
 
2041
- #### `createThemeFromProvider(provider)`
2085
+ #### `createPromise(asyncFn)`
2042
2086
 
2043
- Create theme primitives from a specific provider.
2087
+ Primitive that wraps an async function with reactive state tracking.
2044
2088
 
2045
2089
  ```typescript
2046
- function createThemeFromProvider(provider: ThemeProvider): ThemePrimitives
2090
+ function createPromise(asyncFn: T): CreatePromiseReturn<Awaited<ReturnType<T>>>
2047
2091
  ```
2048
2092
 
2049
- - `provider` — Theme provider
2093
+ - `asyncFn` — The async function to wrap
2050
2094
 
2051
- **Returns:** Theme primitives
2095
+ **Returns:** Object with state accessor, call, cancel, and reset functions
2052
2096
 
2053
- #### `createThemeHelpers()`
2097
+ #### `createPush()`
2054
2098
 
2055
- Creates a theme helpers.
2099
+ Create push notification primitives.
2056
2100
 
2057
2101
  ```typescript
2058
- function createThemeHelpers(): {
2059
- getTheme: () => Theme
2060
- setTheme: (name: string) => void
2061
- getMode: () => 'light' | 'dark'
2062
- toggleMode: () => void
2063
- getAvailableThemes: () => Theme[]
2064
- }
2102
+ function createPush(): PushPrimitives
2065
2103
  ```
2066
2104
 
2067
- **Returns:** The created result.
2105
+ **Returns:** Push primitives object
2068
2106
 
2069
- #### `createVersion()`
2107
+ #### `createRouter()`
2070
2108
 
2071
- Create version primitives for tracking app updates.
2109
+ Create router primitives for navigation state and actions.
2072
2110
 
2073
2111
  ```typescript
2074
- function createVersion(): VersionPrimitives
2112
+ function createRouter(): RouterPrimitives
2075
2113
  ```
2076
2114
 
2077
- **Returns:** Version primitives object
2115
+ **Returns:** Router primitives object
2078
2116
 
2079
- #### `createWatchSignal(controller, name)`
2117
+ #### `useLocation()`
2080
2118
 
2081
- Create a reactive accessor that tracks a single field's value.
2119
+ Get current route location as accessor.
2082
2120
 
2083
2121
  ```typescript
2084
- function createWatchSignal(controller: FormController<T>, name: K): Accessor<T[K]>
2122
+ function useLocation(): Accessor<RouteLocation>
2085
2123
  ```
2086
2124
 
2087
- - `controller` — Form controller
2088
- - `name` — Field name to watch
2089
-
2090
- **Returns:** Accessor for the field value
2125
+ **Returns:** Accessor for current location
2091
2126
 
2092
- #### `getAuthClient()`
2127
+ #### `useParams()`
2093
2128
 
2094
- Get the auth client from context.
2129
+ Get current route params as accessor.
2095
2130
 
2096
2131
  ```typescript
2097
- function getAuthClient(): AuthClient<T>
2132
+ function useParams(): Accessor<RouteParams>
2098
2133
  ```
2099
2134
 
2100
- **Returns:** The auth client instance.
2135
+ **Returns:** Accessor for route params
2101
2136
 
2102
- #### `getChildLogger(name, context)`
2137
+ #### `useQuery()`
2103
2138
 
2104
- Create a child logger with additional context.
2139
+ Get current query params as accessor.
2105
2140
 
2106
2141
  ```typescript
2107
- function getChildLogger(name: string, context: Record<string, unknown>): Logger
2142
+ function useQuery(): Accessor<QueryParams>
2108
2143
  ```
2109
2144
 
2110
- - `name` — Parent logger name
2111
- - `context` — Additional context
2112
-
2113
- **Returns:** Child logger instance
2145
+ **Returns:** Accessor for query params
2114
2146
 
2115
- #### `getHttpClient()`
2147
+ #### `useNavigate()`
2116
2148
 
2117
- Get the HTTP client from context.
2149
+ Get navigate function.
2118
2150
 
2119
2151
  ```typescript
2120
- function getHttpClient(): HttpClient
2152
+ function useNavigate(): (path: string, options?: NavigateOptions) => void
2121
2153
  ```
2122
2154
 
2123
- **Returns:** The HTTP client instance.
2155
+ **Returns:** Navigate function
2124
2156
 
2125
- #### `getI18nProvider()`
2157
+ #### `useMatch(pattern)`
2126
2158
 
2127
- Get the i18n provider from context.
2159
+ Create a match accessor for a path pattern.
2128
2160
 
2129
2161
  ```typescript
2130
- function getI18nProvider(): I18nProvider
2162
+ function useMatch(pattern: string): Accessor<boolean>
2131
2163
  ```
2132
2164
 
2133
- **Returns:** The i18n provider instance.
2165
+ - `pattern` — Path pattern to match
2134
2166
 
2135
- #### `getLogger(name)`
2167
+ **Returns:** Accessor indicating if current path matches
2136
2168
 
2137
- Get a logger instance.
2169
+ #### `createIsActive(path, exact)`
2170
+
2171
+ Create a reactive boolean accessor that tracks whether a given path is active.
2172
+
2173
+ Unlike `useMatch` which only accepts a static pattern, this factory returns
2174
+ a signal that re-evaluates on every route change and supports the `exact`
2175
+ parameter from the router's `isActive` method.
2138
2176
 
2139
2177
  ```typescript
2140
- function getLogger(name?: string): Logger
2178
+ function createIsActive(path: string, exact?: boolean): Accessor<boolean>
2141
2179
  ```
2142
2180
 
2143
- - `name` — Logger name
2181
+ - `path` — Path to check against the current location
2182
+ - `exact` — Whether to require an exact match (default: false)
2144
2183
 
2145
- **Returns:** Logger instance
2184
+ **Returns:** Accessor<boolean> that is true when the path is active
2146
2185
 
2147
- #### `getLoggerProvider()`
2186
+ #### `createRouterHelpers()`
2148
2187
 
2149
- Get the logger provider from context.
2188
+ Creates a router helpers.
2150
2189
 
2151
2190
  ```typescript
2152
- function getLoggerProvider(): LoggerProvider
2191
+ function createRouterHelpers(): {
2192
+ navigate: (path: string, options?: NavigateOptions) => void
2193
+ navigateTo: (
2194
+ name: string,
2195
+ params?: RouteParams,
2196
+ query?: QueryParams,
2197
+ options?: NavigateOptions,
2198
+ ) => void
2199
+ back: () => void
2200
+ forward: () => void
2201
+ getLocation: () => RouteLocation
2202
+ getParams: () => RouteParams
2203
+ getQuery: () => QueryParams
2204
+ isActive: (path: string) => boolean
2205
+ }
2153
2206
  ```
2154
2207
 
2155
- **Returns:** The logger provider instance.
2208
+ **Returns:** The created result.
2156
2209
 
2157
- #### `getRootLogger()`
2210
+ #### `createRouterFromInstance(router)`
2158
2211
 
2159
- Get the root logger.
2212
+ Create router primitives from a specific router.
2160
2213
 
2161
2214
  ```typescript
2162
- function getRootLogger(): Logger
2215
+ function createRouterFromInstance(router: Router): RouterPrimitives
2163
2216
  ```
2164
2217
 
2165
- **Returns:** Root logger instance
2218
+ - `router` — Router instance
2166
2219
 
2167
- #### `getRouter()`
2220
+ **Returns:** Router primitives
2168
2221
 
2169
- Get the router from context.
2222
+ #### `createSignup()`
2223
+
2224
+ Creates a signup primitive with async state tracking.
2170
2225
 
2171
2226
  ```typescript
2172
- function getRouter(): Router
2227
+ function createSignup(): CreateSignupReturn<T>
2173
2228
  ```
2174
2229
 
2175
- **Returns:** The router instance.
2230
+ **Returns:** Signup state and action
2176
2231
 
2177
- #### `getStateProvider()`
2232
+ #### `createStore(config)`
2178
2233
 
2179
- Get the state provider from context.
2234
+ Create a reactive store using Solid signals.
2180
2235
 
2181
2236
  ```typescript
2182
- function getStateProvider(): StateProvider
2237
+ function createStore(config: StoreConfig<T>): Store<T>
2183
2238
  ```
2184
2239
 
2185
- **Returns:** The state provider instance.
2240
+ - `config` — Store configuration
2186
2241
 
2187
- #### `getStorageProvider()`
2242
+ **Returns:** Store instance
2188
2243
 
2189
- Get the storage provider from context.
2244
+ #### `useStore(store, selector)`
2245
+
2246
+ Use a store with optional selector, returning an accessor.
2190
2247
 
2191
2248
  ```typescript
2192
- function getStorageProvider(): StorageProvider
2249
+ function useStore(store: Store<T>, selector?: (state: T) => S): Accessor<S>
2193
2250
  ```
2194
2251
 
2195
- **Returns:** The storage provider instance.
2252
+ - `store` — Store to subscribe to
2253
+ - `selector` — Optional selector function
2196
2254
 
2197
- #### `getThemeProvider()`
2255
+ **Returns:** Accessor for selected state
2198
2256
 
2199
- Get the theme provider from context.
2257
+ #### `createSignalStore(initial)`
2258
+
2259
+ Create a simple signal-based store without provider.
2200
2260
 
2201
2261
  ```typescript
2202
- function getThemeProvider(): ThemeProvider
2262
+ function createSignalStore(initial: T): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
2203
2263
  ```
2204
2264
 
2205
- **Returns:** The theme provider instance.
2265
+ - `initial` — Initial state
2206
2266
 
2207
- #### `MoleculeProvider(props)`
2267
+ **Returns:** The created instance.
2208
2268
 
2209
- MoleculeProvider component that provides all molecule services to the component tree.
2269
+ #### `createPersistedStore(key, initial, storage)`
2270
+
2271
+ Create a persisted signal store.
2210
2272
 
2211
2273
  ```typescript
2212
- function MoleculeProvider(props: ParentProps<{ config: MoleculeConfig }>): JSX.Element
2274
+ function createPersistedStore(
2275
+ key: string,
2276
+ initial: T,
2277
+ storage: StorageAdapter,
2278
+ ): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
2213
2279
  ```
2214
2280
 
2215
- - `props` — Component props containing the molecule config.
2281
+ - `key` — Storage key
2282
+ - `initial` — Initial value
2283
+ - `storage` — Storage adapter (required - use localStorage, sessionStorage, or `@molecule/app-storage`)
2216
2284
 
2217
- **Returns:** The nested provider tree wrapping children.
2285
+ **Returns:** Tuple of accessor and setter
2218
2286
 
2219
- #### `useComponentLogger(componentName)`
2287
+ #### `createStateHelpers()`
2220
2288
 
2221
- Create a component logger that includes component name in context.
2289
+ Creates a state helpers.
2222
2290
 
2223
2291
  ```typescript
2224
- function useComponentLogger(componentName: string): Logger
2292
+ function createStateHelpers(): {
2293
+ createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
2294
+ }
2225
2295
  ```
2226
2296
 
2227
- - `componentName` — Name of the component
2228
-
2229
- **Returns:** Logger configured for the component
2297
+ **Returns:** The created result.
2230
2298
 
2231
- #### `useFetch(url, config)`
2299
+ #### `createStateHelpersFromProvider(provider)`
2232
2300
 
2233
- Create a resource for fetching data.
2301
+ Creates a state helpers from provider.
2234
2302
 
2235
2303
  ```typescript
2236
- function useFetch(url: string | Accessor<string>, config?: RequestConfig): Resource<T | undefined>
2304
+ function createStateHelpersFromProvider(provider: StateProvider): {
2305
+ createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
2306
+ }
2237
2307
  ```
2238
2308
 
2239
- - `url` — URL string or accessor returning a URL string.
2240
- - `config` — Optional request configuration.
2309
+ - `provider` — The provider implementation.
2241
2310
 
2242
- **Returns:** Solid resource
2311
+ **Returns:** The created result.
2243
2312
 
2244
- #### `useLazyQuery()`
2313
+ #### `createStorageValue(key, defaultValue)`
2245
2314
 
2246
- Hook for lazy query.
2315
+ Create a storage value primitive.
2247
2316
 
2248
2317
  ```typescript
2249
- function useLazyQuery(): {
2250
- execute: (url: string, config?: RequestConfig) => Promise<T>
2251
- data: () => T | null
2252
- isLoading: () => boolean
2318
+ function createStorageValue(
2319
+ key: string,
2320
+ defaultValue?: T,
2321
+ ): {
2322
+ value: () => T | undefined
2323
+ loading: () => boolean
2253
2324
  error: () => Error | null
2254
- reset: () => void
2325
+ set: (value: T) => Promise<void>
2326
+ remove: () => Promise<void>
2327
+ refresh: () => Promise<T | undefined>
2255
2328
  }
2256
2329
  ```
2257
2330
 
2258
- **Returns:** The result.
2331
+ - `key` — Storage key
2332
+ - `defaultValue` — Default value if not found
2259
2333
 
2260
- #### `useLocale()`
2334
+ **Returns:** Storage value accessor and actions
2261
2335
 
2262
- Get current locale as accessor.
2336
+ #### `createStorage()`
2337
+
2338
+ Create storage primitives.
2263
2339
 
2264
2340
  ```typescript
2265
- function useLocale(): Accessor<string>
2341
+ function createStorage(): {
2342
+ get: <T>(key: string) => Promise<T | null>
2343
+ set: <T>(key: string, value: T) => Promise<void>
2344
+ remove: (key: string) => Promise<void>
2345
+ clear: () => Promise<void>
2346
+ keys: () => Promise<string[]>
2347
+ }
2266
2348
  ```
2267
2349
 
2268
- **Returns:** Accessor for current locale
2350
+ **Returns:** Storage methods
2269
2351
 
2270
- #### `useLocation()`
2352
+ #### `usePersistedSignal(key, defaultValue)`
2271
2353
 
2272
- Get current route location as accessor.
2354
+ Create a persisted signal that syncs with storage.
2273
2355
 
2274
2356
  ```typescript
2275
- function useLocation(): Accessor<RouteLocation>
2357
+ function usePersistedSignal(
2358
+ key: string,
2359
+ defaultValue: T,
2360
+ ): [Accessor<T | undefined>, (value: T | ((prev: T | undefined) => T)) => void]
2276
2361
  ```
2277
2362
 
2278
- **Returns:** Accessor for current location
2363
+ - `key` — Storage key
2364
+ - `defaultValue` — Default value
2279
2365
 
2280
- #### `useMatch(pattern)`
2366
+ **Returns:** Tuple of accessor and setter
2281
2367
 
2282
- Create a match accessor for a path pattern.
2368
+ #### `createStorageHelpers()`
2369
+
2370
+ Create storage helpers from context.
2283
2371
 
2284
2372
  ```typescript
2285
- function useMatch(pattern: string): Accessor<boolean>
2373
+ function createStorageHelpers(): {
2374
+ get: <T>(key: string) => Promise<T | null>
2375
+ set: <T>(key: string, value: T) => Promise<void>
2376
+ remove: (key: string) => Promise<void>
2377
+ clear: () => Promise<void>
2378
+ keys: () => Promise<string[]>
2379
+ }
2286
2380
  ```
2287
2381
 
2288
- - `pattern` — Path pattern to match
2289
-
2290
- **Returns:** Accessor indicating if current path matches
2382
+ **Returns:** Storage helper functions
2291
2383
 
2292
- #### `useMode()`
2384
+ #### `createStorageFromProvider(storage)`
2293
2385
 
2294
- Create a mode accessor.
2386
+ Create storage primitives from a specific provider.
2295
2387
 
2296
2388
  ```typescript
2297
- function useMode(): Accessor<'light' | 'dark'>
2389
+ function createStorageFromProvider(storage: StorageProvider): {
2390
+ get: <T>(key: string) => Promise<T | null>
2391
+ set: <T>(key: string, value: T) => Promise<void>
2392
+ remove: (key: string) => Promise<void>
2393
+ clear: () => Promise<void>
2394
+ keys: () => Promise<string[]>
2395
+ }
2298
2396
  ```
2299
2397
 
2300
- **Returns:** Accessor for current mode
2398
+ - `storage` — Storage provider
2301
2399
 
2302
- #### `useMutation()`
2400
+ **Returns:** Storage methods
2303
2401
 
2304
- Hook for mutation.
2402
+ #### `createStorageValueFromProvider(storage, key, defaultValue)`
2403
+
2404
+ Create storage value primitive from a specific provider.
2305
2405
 
2306
2406
  ```typescript
2307
- function useMutation(): {
2308
- mutate: (
2309
- url: string,
2310
- payload?: unknown,
2311
- method?: 'POST' | 'PUT' | 'PATCH' | 'DELETE',
2312
- ) => Promise<T>
2313
- isLoading: Accessor<boolean>
2314
- error: Accessor<Error | null>
2315
- data: Accessor<T | null>
2316
- reset: () => void
2407
+ function createStorageValueFromProvider(
2408
+ storage: StorageProvider,
2409
+ key: string,
2410
+ defaultValue?: T,
2411
+ ): {
2412
+ value: () => T | undefined
2413
+ loading: () => boolean
2414
+ error: () => Error | null
2415
+ set: (value: T) => Promise<void>
2416
+ remove: () => Promise<void>
2317
2417
  }
2318
2418
  ```
2319
2419
 
2320
- **Returns:** The result.
2420
+ - `storage` — Storage provider
2421
+ - `key` — Storage key
2422
+ - `defaultValue` — Default value
2321
2423
 
2322
- #### `useNavigate()`
2424
+ **Returns:** Storage value accessor and actions
2323
2425
 
2324
- Get navigate function.
2426
+ #### `createTheme()`
2427
+
2428
+ Create theme primitives for theme state and actions.
2325
2429
 
2326
2430
  ```typescript
2327
- function useNavigate(): (path: string, options?: NavigateOptions) => void
2431
+ function createTheme(): ThemePrimitives
2328
2432
  ```
2329
2433
 
2330
- **Returns:** Navigate function
2434
+ **Returns:** The created instance.
2331
2435
 
2332
- #### `useParams()`
2436
+ #### `useMode()`
2333
2437
 
2334
- Get current route params as accessor.
2438
+ Create a mode accessor.
2335
2439
 
2336
2440
  ```typescript
2337
- function useParams(): Accessor<RouteParams>
2441
+ function useMode(): Accessor<'light' | 'dark'>
2338
2442
  ```
2339
2443
 
2340
- **Returns:** Accessor for route params
2444
+ **Returns:** Accessor for current mode
2341
2445
 
2342
- #### `usePersistedSignal(key, defaultValue)`
2446
+ #### `useThemeName()`
2343
2447
 
2344
- Create a persisted signal that syncs with storage.
2448
+ Create a theme name accessor.
2345
2449
 
2346
2450
  ```typescript
2347
- function usePersistedSignal(
2348
- key: string,
2349
- defaultValue: T,
2350
- ): [Accessor<T | undefined>, (value: T | ((prev: T | undefined) => T)) => void]
2451
+ function useThemeName(): Accessor<string>
2351
2452
  ```
2352
2453
 
2353
- - `key` — Storage key
2354
- - `defaultValue` — Default value
2355
-
2356
- **Returns:** Tuple of accessor and setter
2454
+ **Returns:** Accessor for current theme name
2357
2455
 
2358
- #### `usePlural(key, count, values)`
2456
+ #### `createThemeHelpers()`
2359
2457
 
2360
- Create a reactive plural translation.
2458
+ Creates a theme helpers.
2361
2459
 
2362
2460
  ```typescript
2363
- function usePlural(
2364
- key: string,
2365
- count: Accessor<number>,
2366
- values?: InterpolationValues,
2367
- ): Accessor<string>
2461
+ function createThemeHelpers(): {
2462
+ getTheme: () => Theme
2463
+ setTheme: (name: string) => void
2464
+ getMode: () => 'light' | 'dark'
2465
+ toggleMode: () => void
2466
+ getAvailableThemes: () => Theme[]
2467
+ }
2368
2468
  ```
2369
2469
 
2370
- - `key` — Translation key
2371
- - `count` — Count accessor for pluralization
2372
- - `values` — Interpolation values for the translation.
2373
-
2374
- **Returns:** Accessor for translated string
2470
+ **Returns:** The created result.
2375
2471
 
2376
- #### `useQuery()`
2472
+ #### `createThemeFromProvider(provider)`
2377
2473
 
2378
- Get current query params as accessor.
2474
+ Create theme primitives from a specific provider.
2379
2475
 
2380
2476
  ```typescript
2381
- function useQuery(): Accessor<QueryParams>
2477
+ function createThemeFromProvider(provider: ThemeProvider): ThemePrimitives
2382
2478
  ```
2383
2479
 
2384
- **Returns:** Accessor for query params
2480
+ - `provider` — Theme provider
2385
2481
 
2386
- #### `useStore(store, selector)`
2482
+ **Returns:** Theme primitives
2387
2483
 
2388
- Use a store with optional selector, returning an accessor.
2484
+ #### `createThemeColors(theme)`
2485
+
2486
+ Create a colors accessor derived from a theme accessor.
2389
2487
 
2390
2488
  ```typescript
2391
- function useStore(store: Store<T>, selector?: (state: T) => S): Accessor<S>
2489
+ function createThemeColors(theme: Accessor<Theme>): Accessor<ThemeColors>
2392
2490
  ```
2393
2491
 
2394
- - `store` — Store to subscribe to
2395
- - `selector` — Optional selector function
2492
+ - `theme` — Theme accessor (e.g. from createTheme().theme)
2396
2493
 
2397
- **Returns:** Accessor for selected state
2494
+ **Returns:** Accessor for the current theme colors
2398
2495
 
2399
- #### `useThemeName()`
2496
+ #### `applyThemeToDocument()`
2400
2497
 
2401
- Create a theme name accessor.
2498
+ Apply theme CSS variables to document.
2402
2499
 
2403
2500
  ```typescript
2404
- function useThemeName(): Accessor<string>
2501
+ function applyThemeToDocument(): void
2405
2502
  ```
2406
2503
 
2407
- **Returns:** Accessor for current theme name
2408
-
2409
- #### `useTranslate()`
2504
+ #### `createVersion()`
2410
2505
 
2411
- Get translate function.
2506
+ Create version primitives for tracking app updates.
2412
2507
 
2413
2508
  ```typescript
2414
- function useTranslate(): TranslateFunction
2509
+ function createVersion(): VersionPrimitives
2415
2510
  ```
2416
2511
 
2417
- **Returns:** Translate function
2512
+ **Returns:** Version primitives object
2418
2513
 
2419
- #### `useTranslation(key, values, options)`
2514
+ #### `MoleculeProvider(props)`
2420
2515
 
2421
- Create a reactive translation.
2516
+ MoleculeProvider component that provides all molecule services to the component tree.
2422
2517
 
2423
2518
  ```typescript
2424
- function useTranslation(
2425
- key: string,
2426
- values?: InterpolationValues,
2427
- options?: TranslateOptions,
2428
- ): Accessor<string>
2519
+ function MoleculeProvider(props: ParentProps<{ config: MoleculeConfig }>): JSX.Element
2429
2520
  ```
2430
2521
 
2431
- - `key` — Translation key
2432
- - `values` — Interpolation values for the translation.
2433
- - `options` — Translation options
2522
+ - `props` — Component props containing the molecule config.
2434
2523
 
2435
- **Returns:** Accessor for translated string
2524
+ **Returns:** The nested provider tree wrapping children.
2436
2525
 
2437
2526
  ### Constants
2438
2527
 
2439
- #### `AuthContext`
2440
-
2441
- ```typescript
2442
- const AuthContext: Context<AuthClient<unknown> | undefined>
2443
- ```
2528
+ #### `StateContext`
2444
2529
 
2445
- #### `HttpContext`
2530
+ Internal contexts for molecule providers.
2446
2531
 
2447
2532
  ```typescript
2448
- const HttpContext: Context<HttpClient | undefined>
2533
+ const StateContext: Context<StateProvider | undefined>
2449
2534
  ```
2450
2535
 
2451
- #### `I18nContext`
2536
+ #### `AuthContext`
2452
2537
 
2453
2538
  ```typescript
2454
- const I18nContext: Context<I18nProvider | undefined>
2539
+ const AuthContext: Context<AuthClient<unknown, Record<never, never>> | undefined>
2455
2540
  ```
2456
2541
 
2457
- #### `LoggerContext`
2542
+ #### `ThemeContext`
2458
2543
 
2459
2544
  ```typescript
2460
- const LoggerContext: Context<LoggerProvider | undefined>
2545
+ const ThemeContext: Context<ThemeProvider | undefined>
2461
2546
  ```
2462
2547
 
2463
2548
  #### `RouterContext`
@@ -2466,12 +2551,16 @@ const LoggerContext: Context<LoggerProvider | undefined>
2466
2551
  const RouterContext: Context<Router | undefined>
2467
2552
  ```
2468
2553
 
2469
- #### `StateContext`
2554
+ #### `I18nContext`
2470
2555
 
2471
- Internal contexts for molecule providers.
2556
+ ```typescript
2557
+ const I18nContext: Context<I18nProvider | undefined>
2558
+ ```
2559
+
2560
+ #### `HttpContext`
2472
2561
 
2473
2562
  ```typescript
2474
- const StateContext: Context<StateProvider | undefined>
2563
+ const HttpContext: Context<HttpClient | undefined>
2475
2564
  ```
2476
2565
 
2477
2566
  #### `StorageContext`
@@ -2480,10 +2569,10 @@ const StateContext: Context<StateProvider | undefined>
2480
2569
  const StorageContext: Context<StorageProvider | undefined>
2481
2570
  ```
2482
2571
 
2483
- #### `ThemeContext`
2572
+ #### `LoggerContext`
2484
2573
 
2485
2574
  ```typescript
2486
- const ThemeContext: Context<ThemeProvider | undefined>
2575
+ const LoggerContext: Context<LoggerProvider | undefined>
2487
2576
  ```
2488
2577
 
2489
2578
  ## Injection Notes