@molecule/app-solid 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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-09-15T19:11:42.735Z
6
+ Generated: 2026-10-21T17:02:42.221Z
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 RegisterExtraShape<TRegister> = 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
789
+ /**
790
+ * Gets the current route params.
791
+ */
792
+ getParams<T extends RouteParams = RouteParams>(): T
793
+ /**
794
+ * Gets the current query params.
795
+ */
796
+ getQuery(): QueryParams
797
+ /**
798
+ * Gets a specific query parameter.
799
+ */
800
+ getQueryParam(key: string): string | undefined
801
+ /**
802
+ * Gets the current hash.
803
+ */
804
+ getHash(): string
667
805
  /**
668
- * Gets the current locale.
806
+ * Navigates to a path.
669
807
  */
670
- getLocale(): string
808
+ navigate(path: string, options?: NavigateOptions): void
671
809
  /**
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.
810
+ * Navigates to a named route.
683
811
  */
684
- setLocale(locale: string): Promise<void>
812
+ navigateTo(
813
+ name: string,
814
+ params?: RouteParams,
815
+ query?: QueryParams,
816
+ options?: NavigateOptions,
817
+ ): void
685
818
  /**
686
- * Gets all available locales.
819
+ * Goes back in history.
687
820
  */
688
- getLocales(): LocaleConfig[]
821
+ back(): void
689
822
  /**
690
- * Adds a locale.
823
+ * Goes forward in history.
691
824
  */
692
- addLocale(config: LocaleConfig): void
825
+ forward(): void
693
826
  /**
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.
827
+ * Goes to a specific point in history.
702
828
  */
703
- removeLocale(code: string): boolean
829
+ go(delta: number): void
704
830
  /**
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.
831
+ * Updates the current query params.
712
832
  */
713
- addTranslations(locale: string, translations: Translations, namespace?: string): void
833
+ setQuery(params: QueryParams, options?: NavigateOptions): void
714
834
  /**
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.
835
+ * Updates a specific query parameter.
727
836
  */
728
- t(
729
- key: string,
730
- values?: InterpolationValues,
731
- options?: {
732
- defaultValue?: string
733
- count?: number
734
- },
735
- ): string
837
+ setQueryParam(key: string, value: string | undefined, options?: NavigateOptions): void
736
838
  /**
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.
839
+ * Updates the current hash.
748
840
  */
749
- exists(key: string): boolean
841
+ setHash(hash: string, options?: NavigateOptions): void
750
842
  /**
751
- * Formats a number according to the current locale.
843
+ * Checks if a path matches the current location.
752
844
  *
753
- * @returns The locale-formatted number string.
845
+ * @returns `true` if the path matches the current route.
754
846
  */
755
- formatNumber(value: number, options?: NumberFormatOptions): string
847
+ isActive(path: string, exact?: boolean): boolean
756
848
  /**
757
- * Formats a date according to the current locale.
758
- *
759
- * @returns The locale-formatted date string.
849
+ * Matches a path pattern against a pathname.
760
850
  */
761
- formatDate(value: Date | number | string, options?: DateFormatOptions): string
851
+ matchPath<Params extends RouteParams = RouteParams>(
852
+ pattern: string,
853
+ pathname: string,
854
+ ): RouteMatch<Params> | null
762
855
  /**
763
- * Formats a relative time (e.g. "2 hours ago").
764
- *
765
- * @returns The locale-formatted relative time string.
856
+ * Generates a URL from a named route.
766
857
  */
767
- formatRelativeTime(
768
- value: Date | number,
769
- options?: {
770
- unit?: Intl.RelativeTimeFormatUnit
771
- },
772
- ): string
858
+ generatePath(name: string, params?: RouteParams, query?: QueryParams): string
773
859
  /**
774
- * Formats a list (e.g. "A, B, and C").
775
- *
776
- * @returns The locale-formatted list string.
860
+ * Subscribes to route changes.
777
861
  */
778
- formatList(
779
- values: string[],
780
- options?: {
781
- type?: 'conjunction' | 'disjunction' | 'unit'
782
- },
783
- ): string
862
+ subscribe(listener: RouteChangeListener): () => void
784
863
  /**
785
- * Subscribes to locale changes.
786
- *
787
- * @returns An unsubscribe function.
864
+ * Adds a navigation guard.
788
865
  */
789
- onLocaleChange(listener: (locale: string) => void): () => void
866
+ addGuard(guard: NavigationGuard): () => void
790
867
  /**
791
- * Gets the text direction for the current locale.
792
- *
793
- * @returns `'ltr'` or `'rtl'`.
868
+ * Registers route definitions.
794
869
  */
795
- getDirection(): 'ltr' | 'rtl'
870
+ registerRoutes(routes: RouteDefinition[]): void
796
871
  /**
797
- * Checks if a translation key exists (alias for exists).
872
+ * Gets all registered routes.
798
873
  */
799
- hasKey?(key: string): boolean
874
+ getRoutes(): RouteDefinition[]
800
875
  /**
801
- * Checks if the provider is ready.
876
+ * Destroys the router.
802
877
  */
803
- isReady?(): boolean
878
+ destroy(): void
879
+ }
880
+ ```
881
+
882
+ #### `StoreConfig`
883
+
884
+ Configuration for creating a store (initial state, optional name, and middleware chain).
885
+
886
+ ```typescript
887
+ interface StoreConfig<T> {
804
888
  /**
805
- * Registers a callback for when the provider is ready.
889
+ * Initial state value.
806
890
  */
807
- onReady?(callback: () => void): () => void
891
+ initialState: T
808
892
  /**
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.
893
+ * Optional name for debugging.
814
894
  */
815
- registerContent?(module: string, loader: (locale: string) => Promise<void>): void
895
+ name?: string
896
+ /**
897
+ * Optional middleware functions.
898
+ */
899
+ middleware?: StoreMiddleware<T>[]
816
900
  }
817
901
  ```
818
902
 
819
- #### `Logger`
903
+ #### `MoleculeStore`
820
904
 
821
- Logger instance with leveled logging methods, child logger creation,
822
- and transport management.
905
+ Reactive state container with getState, setState, subscribe, and destroy.
906
+
907
+ All state management providers must implement this interface.
823
908
 
824
909
  ```typescript
825
- interface Logger {
910
+ interface Store<T> {
826
911
  /**
827
- * Logs a trace message.
912
+ * Gets the current state.
828
913
  */
829
- trace(message: string, ...args: unknown[]): void
914
+ getState(): T
830
915
  /**
831
- * Logs a debug message.
916
+ * Sets the state (partial or via updater function).
832
917
  */
833
- debug(message: string, ...args: unknown[]): void
918
+ setState(partial: Partial<T> | ((state: T) => Partial<T>)): void
834
919
  /**
835
- * Logs an info message.
920
+ * Subscribes to state changes.
921
+ * Returns an unsubscribe function.
836
922
  */
837
- info(message: string, ...args: unknown[]): void
923
+ subscribe(listener: StateListener<T>): () => void
838
924
  /**
839
- * Logs a warning message.
925
+ * Destroys the store and cleans up subscriptions.
840
926
  */
841
- warn(message: string, ...args: unknown[]): void
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 {
842
938
  /**
843
- * Logs an error message.
939
+ * Creates a new store.
844
940
  */
845
- error(message: string | Error, ...args: unknown[]): void
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 {
846
953
  /**
847
- * Sets the log level.
954
+ * Gets a value from storage.
848
955
  */
849
- setLevel(level: LogLevel): void
956
+ get<T = unknown>(key: string): Promise<T | null>
850
957
  /**
851
- * Gets the current log level.
958
+ * Sets a value in storage.
852
959
  */
853
- getLevel(): LogLevel
960
+ set<T = unknown>(key: string, value: T): Promise<void>
854
961
  /**
855
- * Creates a child logger with a namespace.
962
+ * Removes a value from storage.
856
963
  */
857
- child(name: string, context?: Record<string, unknown>): Logger
964
+ remove(key: string): Promise<void>
858
965
  /**
859
- * Adds additional context to the logger.
966
+ * Clears all values from storage.
860
967
  */
861
- withContext(context: Record<string, unknown>): Logger
968
+ clear(): Promise<void>
862
969
  /**
863
- * Adds a transport.
970
+ * Gets all keys in storage.
864
971
  */
865
- addTransport(transport: LogTransport): () => void
972
+ keys(): Promise<string[]>
866
973
  /**
867
- * Removes a transport.
974
+ * Gets multiple values from storage.
868
975
  */
869
- removeTransport(transport: LogTransport): void
976
+ getMany?<T = unknown>(keys: string[]): Promise<Map<string, T | null>>
977
+ /**
978
+ * Sets multiple values in storage.
979
+ */
980
+ setMany?<T = unknown>(entries: Array<[string, T]>): Promise<void>
981
+ /**
982
+ * Removes multiple values from storage.
983
+ */
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,263 +1295,95 @@ interface PushPrimitives {
996
1295
  }
997
1296
  ```
998
1297
 
999
- #### `RouteLocation`
1000
-
1001
- Current URL decomposed into pathname, search string, hash, navigation state, and unique key.
1002
-
1003
- ```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
1025
- }
1026
- ```
1027
-
1028
- #### `Router`
1029
-
1030
- Client-side router providing navigation, guards, route matching, and history control.
1031
-
1032
- All routing providers must implement this interface.
1033
-
1034
- ```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
1130
- }
1131
- ```
1132
-
1133
- #### `RouterPrimitives`
1298
+ #### `CreateSignupReturn`
1134
1299
 
1135
- Router primitives return type.
1300
+ Return type for createSignup primitive.
1136
1301
 
1137
1302
  ```typescript
1138
- interface RouterPrimitives {
1139
- location: Accessor<RouteLocation>
1140
- params: Accessor<RouteParams>
1141
- query: Accessor<QueryParams>
1142
- navigate: Router['navigate']
1143
- navigateTo: Router['navigateTo']
1144
- back: Router['back']
1145
- forward: Router['forward']
1146
- isActive: Router['isActive']
1303
+ interface CreateSignupReturn<T = unknown> {
1304
+ state: Accessor<PromiseState<AuthResult<T>>>
1305
+ signup: (data: RegisterData) => Promise<AuthResult<T>>
1306
+ reset: () => void
1147
1307
  }
1148
1308
  ```
1149
1309
 
1150
- #### `StateProvider`
1310
+ #### `VersionPrimitives`
1151
1311
 
1152
- State provider interface that all state management bond packages
1153
- must implement. Provides the store creation factory.
1312
+ Version primitives return type.
1154
1313
 
1155
1314
  ```typescript
1156
- interface StateProvider {
1157
- /**
1158
- * Creates a new store.
1159
- */
1160
- createStore<T>(config: StoreConfig<T>): Store<T>
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
1161
1326
  }
1162
1327
  ```
1163
1328
 
1164
- #### `StorageProvider`
1165
-
1166
- Storage provider interface.
1329
+ #### `MoleculeConfig`
1167
1330
 
1168
- All storage providers must implement this interface.
1331
+ Configuration for molecule Solid context.
1169
1332
 
1170
1333
  ```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>
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
1204
1343
  }
1205
1344
  ```
1206
1345
 
1207
- #### `StorageValueState`
1346
+ #### `HttpState`
1208
1347
 
1209
- State for async storage values.
1348
+ State for async HTTP operations.
1210
1349
 
1211
1350
  ```typescript
1212
- interface StorageValueState<T> {
1213
- value: T | undefined
1351
+ interface HttpState<T> {
1352
+ data: T | null
1214
1353
  loading: boolean
1215
1354
  error: Error | null
1216
1355
  }
1217
1356
  ```
1218
1357
 
1219
- #### `StoreConfig`
1358
+ #### `StorageValueState`
1220
1359
 
1221
- Configuration for creating a store (initial state, optional name, and middleware chain).
1360
+ State for async storage values.
1222
1361
 
1223
1362
  ```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>[]
1363
+ interface StorageValueState<T> {
1364
+ value: T | undefined
1365
+ loading: boolean
1366
+ error: Error | null
1237
1367
  }
1238
1368
  ```
1239
1369
 
1240
- #### `Theme`
1370
+ #### `AuthPrimitives`
1241
1371
 
1242
- Complete theme definition.
1372
+ Auth primitives return type.
1243
1373
 
1244
1374
  ```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
1375
+ interface AuthPrimitives<
1376
+ T = unknown,
1377
+ TRegister extends RegisterExtraShape<TRegister> = Record<never, never>,
1378
+ > {
1379
+ state: Accessor<AuthState<T>>
1380
+ user: Accessor<T | null>
1381
+ isAuthenticated: Accessor<boolean>
1382
+ isLoading: Accessor<boolean>
1383
+ login: AuthClient<T>['login']
1384
+ logout: AuthClient<T>['logout']
1385
+ register: AuthClient<T, TRegister>['register']
1386
+ refresh: AuthClient<T>['refresh']
1256
1387
  }
1257
1388
  ```
1258
1389
 
@@ -1270,77 +1401,50 @@ interface ThemePrimitives {
1270
1401
  }
1271
1402
  ```
1272
1403
 
1273
- #### `ThemeProvider`
1404
+ #### `RouterPrimitives`
1274
1405
 
1275
- Manages theme state including the active theme, mode toggling,
1276
- and change subscriptions.
1406
+ Router primitives return type.
1277
1407
 
1278
1408
  ```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
- /**
1308
- * Returns the theme a render WITHOUT a browser produces — a server or
1309
- * build-time render, which has no storage and no `prefers-color-scheme`
1310
- * to read. A hydrating client renders this theme first, so its markup
1311
- * matches what the server sent, and switches to `getTheme()` right
1312
- * after. Optional — a provider whose theme cannot differ between the two
1313
- * need not implement it.
1314
- */
1315
- getServerTheme?(): Theme
1409
+ interface RouterPrimitives {
1410
+ location: Accessor<RouteLocation>
1411
+ params: Accessor<RouteParams>
1412
+ query: Accessor<QueryParams>
1413
+ navigate: Router['navigate']
1414
+ navigateTo: Router['navigateTo']
1415
+ back: Router['back']
1416
+ forward: Router['forward']
1417
+ isActive: Router['isActive']
1316
1418
  }
1317
1419
  ```
1318
1420
 
1319
- #### `VersionPrimitives`
1421
+ ### Types
1320
1422
 
1321
- Version primitives return type.
1423
+ #### `Accessor`
1322
1424
 
1323
1425
  ```typescript
1324
- interface VersionPrimitives {
1325
- state: Accessor<VersionState>
1326
- isUpdateAvailable: Accessor<boolean>
1327
- isChecking: Accessor<boolean>
1328
- isServiceWorkerWaiting: Accessor<boolean>
1329
- newVersion: Accessor<string | undefined>
1330
- checkForUpdates: () => Promise<boolean>
1331
- applyUpdate: (options?: { force?: boolean }) => void
1332
- dismissUpdate: () => void
1333
- startPeriodicChecks: (options?: UpdateCheckOptions) => void
1334
- stopPeriodicChecks: () => void
1426
+ type Accessor<T> = () => T
1427
+ ```
1428
+
1429
+ #### `Setter`
1430
+
1431
+ ```typescript
1432
+ type Setter<in out T> = {
1433
+ <U extends T>(
1434
+ ...args: undefined extends T ? [] : [value: Exclude<U, Function> | ((prev: T) => U)]
1435
+ ): undefined extends T ? undefined : U
1436
+ <U extends T>(value: (prev: T) => U): U
1437
+ <U extends T>(value: Exclude<U, Function>): U
1438
+ <U extends T>(value: Exclude<U, Function> | ((prev: T) => U)): U
1335
1439
  }
1336
1440
  ```
1337
1441
 
1338
- ### Types
1442
+ #### `RouteParams`
1339
1443
 
1340
- #### `Accessor`
1444
+ URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
1341
1445
 
1342
1446
  ```typescript
1343
- type Accessor<T> = () => T
1447
+ type RouteParams = Record<string, string>
1344
1448
  ```
1345
1449
 
1346
1450
  #### `QueryParams`
@@ -1351,37 +1455,92 @@ URL query string parameter map (single values or arrays for repeated keys).
1351
1455
  type QueryParams = Record<string, string | string[] | undefined>
1352
1456
  ```
1353
1457
 
1354
- #### `RouteParams`
1458
+ ### Functions
1355
1459
 
1356
- URL path parameter key-value map extracted from dynamic route segments (e.g. `{ id: '123' }`).
1460
+ #### `getStateProvider()`
1461
+
1462
+ Get the state provider from context.
1357
1463
 
1358
1464
  ```typescript
1359
- type RouteParams = Record<string, string>
1465
+ function getStateProvider(): StateProvider
1360
1466
  ```
1361
1467
 
1362
- #### `Setter`
1468
+ **Returns:** The state provider instance.
1469
+
1470
+ #### `getAuthClient()`
1471
+
1472
+ Get the auth client from context.
1473
+
1474
+ Pass the same generics the client was created with —
1475
+ `getAuthClient<MyUser, { username: string }>()` — so `register()` accepts
1476
+ the app's own fields.
1363
1477
 
1364
1478
  ```typescript
1365
- type Setter<in out T> = {
1366
- <U extends T>(
1367
- ...args: undefined extends T ? [] : [value: Exclude<U, Function> | ((prev: T) => U)]
1368
- ): undefined extends T ? undefined : U
1369
- <U extends T>(value: (prev: T) => U): U
1370
- <U extends T>(value: Exclude<U, Function>): U
1371
- <U extends T>(value: Exclude<U, Function> | ((prev: T) => U)): U
1372
- }
1479
+ function getAuthClient(): AuthClient<T, TRegister>
1373
1480
  ```
1374
1481
 
1375
- ### Functions
1482
+ **Returns:** The auth client instance.
1376
1483
 
1377
- #### `applyThemeToDocument()`
1484
+ #### `getThemeProvider()`
1378
1485
 
1379
- Apply theme CSS variables to document.
1486
+ Get the theme provider from context.
1380
1487
 
1381
1488
  ```typescript
1382
- function applyThemeToDocument(): void
1489
+ function getThemeProvider(): ThemeProvider
1490
+ ```
1491
+
1492
+ **Returns:** The theme provider instance.
1493
+
1494
+ #### `getRouter()`
1495
+
1496
+ Get the router from context.
1497
+
1498
+ ```typescript
1499
+ function getRouter(): Router
1500
+ ```
1501
+
1502
+ **Returns:** The router instance.
1503
+
1504
+ #### `getI18nProvider()`
1505
+
1506
+ Get the i18n provider from context.
1507
+
1508
+ ```typescript
1509
+ function getI18nProvider(): I18nProvider
1510
+ ```
1511
+
1512
+ **Returns:** The i18n provider instance.
1513
+
1514
+ #### `getHttpClient()`
1515
+
1516
+ Get the HTTP client from context.
1517
+
1518
+ ```typescript
1519
+ function getHttpClient(): HttpClient
1520
+ ```
1521
+
1522
+ **Returns:** The HTTP client instance.
1523
+
1524
+ #### `getStorageProvider()`
1525
+
1526
+ Get the storage provider from context.
1527
+
1528
+ ```typescript
1529
+ function getStorageProvider(): StorageProvider
1530
+ ```
1531
+
1532
+ **Returns:** The storage provider instance.
1533
+
1534
+ #### `getLoggerProvider()`
1535
+
1536
+ Get the logger provider from context.
1537
+
1538
+ ```typescript
1539
+ function getLoggerProvider(): LoggerProvider
1383
1540
  ```
1384
1541
 
1542
+ **Returns:** The logger provider instance.
1543
+
1385
1544
  #### `createAsyncState(initialState)`
1386
1545
 
1387
1546
  Primitive like createSignal but accepts Promises and supports partial state extension.
@@ -1399,23 +1558,11 @@ function createAsyncState(initialState: T): CreateAsyncStateReturn<T>
1399
1558
  Create auth primitives for authentication state and actions.
1400
1559
 
1401
1560
  ```typescript
1402
- function createAuth(): AuthPrimitives<T>
1561
+ function createAuth(): AuthPrimitives<T, TRegister>
1403
1562
  ```
1404
1563
 
1405
1564
  **Returns:** Auth primitives object
1406
1565
 
1407
- #### `createAuthFromClient(client)`
1408
-
1409
- Create auth primitives from a specific client.
1410
-
1411
- ```typescript
1412
- function createAuthFromClient(client: AuthClient<T>): AuthPrimitives<T>
1413
- ```
1414
-
1415
- - `client` — Auth client
1416
-
1417
- **Returns:** Auth primitives
1418
-
1419
1566
  #### `createAuthGuard(redirectTo)`
1420
1567
 
1421
1568
  Create a guard primitive that redirects unauthenticated users.
@@ -1436,7 +1583,7 @@ Creates a auth helpers.
1436
1583
  function createAuthHelpers(): {
1437
1584
  login: (credentials: LoginCredentials) => Promise<AuthResult<T>>
1438
1585
  logout: () => Promise<void>
1439
- register: (data: RegisterData) => Promise<AuthResult<T>>
1586
+ register: (data: RegisterData<TRegister>) => Promise<AuthResult<T>>
1440
1587
  refresh: () => Promise<AuthResult<T>>
1441
1588
  getUser: () => T | null
1442
1589
  getToken: () => string | null
@@ -1446,6 +1593,18 @@ function createAuthHelpers(): {
1446
1593
 
1447
1594
  **Returns:** The created result.
1448
1595
 
1596
+ #### `createAuthFromClient(client)`
1597
+
1598
+ Create auth primitives from a specific client.
1599
+
1600
+ ```typescript
1601
+ function createAuthFromClient(client: AuthClient<T, TRegister>): AuthPrimitives<T, TRegister>
1602
+ ```
1603
+
1604
+ - `client` — Auth client
1605
+
1606
+ **Returns:** Auth primitives
1607
+
1449
1608
  #### `createCapacitorApp(options)`
1450
1609
 
1451
1610
  Create Capacitor app primitives for native app initialization.
@@ -1473,16 +1632,29 @@ function createChangePassword(): CreateChangePasswordReturn
1473
1632
 
1474
1633
  #### `createDevice()`
1475
1634
 
1476
- Create device primitives for accessing device information.
1635
+ Create device primitives for accessing device information.
1636
+
1637
+ This is a static primitive (no reactive signals) since device info
1638
+ does not change during the lifecycle of the app.
1639
+
1640
+ ```typescript
1641
+ function createDevice(): DevicePrimitives
1642
+ ```
1643
+
1644
+ **Returns:** Device primitives object
1645
+
1646
+ #### `createForm(provider, options)`
1477
1647
 
1478
- This is a static primitive (no reactive signals) since device info
1479
- does not change during the lifecycle of the app.
1648
+ Create form primitives for form state management and validation.
1480
1649
 
1481
1650
  ```typescript
1482
- function createDevice(): DevicePrimitives
1651
+ function createForm(provider: FormProvider, options: FormOptions<T>): CreateFormResult<T>
1483
1652
  ```
1484
1653
 
1485
- **Returns:** Device primitives object
1654
+ - `provider` — Form provider that creates controllers
1655
+ - `options` — Form configuration options
1656
+
1657
+ **Returns:** Form primitives object
1486
1658
 
1487
1659
  #### `createFieldSignal(controller, name)`
1488
1660
 
@@ -1500,33 +1672,18 @@ function createFieldSignal(
1500
1672
 
1501
1673
  **Returns:** Accessor for the field state
1502
1674
 
1503
- #### `createForm(provider, options)`
1504
-
1505
- Create form primitives for form state management and validation.
1506
-
1507
- ```typescript
1508
- function createForm(provider: FormProvider, options: FormOptions<T>): CreateFormResult<T>
1509
- ```
1510
-
1511
- - `provider` — Form provider that creates controllers
1512
- - `options` — Form configuration options
1513
-
1514
- **Returns:** Form primitives object
1515
-
1516
- #### `createFormFromController(controller)`
1517
-
1518
- Create form primitives from an existing controller.
1675
+ #### `createWatchSignal(controller, name)`
1519
1676
 
1520
- Useful when you have a controller created externally and want to
1521
- wrap it with Solid reactivity.
1677
+ Create a reactive accessor that tracks a single field's value.
1522
1678
 
1523
1679
  ```typescript
1524
- function createFormFromController(controller: FormController<T>): CreateFormResult<T>
1680
+ function createWatchSignal(controller: FormController<T>, name: K): Accessor<T[K]>
1525
1681
  ```
1526
1682
 
1527
- - `controller` — An existing FormController
1683
+ - `controller` — Form controller
1684
+ - `name` — Field name to watch
1528
1685
 
1529
- **Returns:** Form primitives object
1686
+ **Returns:** Accessor for the field value
1530
1687
 
1531
1688
  #### `createFormHelpers(provider)`
1532
1689
 
@@ -1542,931 +1699,857 @@ function createFormHelpers(provider: FormProvider): {
1542
1699
 
1543
1700
  **Returns:** The created result.
1544
1701
 
1545
- #### `createHttp()`
1546
-
1547
- Creates a http.
1548
-
1549
- ```typescript
1550
- function createHttp(): {
1551
- get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1552
- post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1553
- put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1554
- patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1555
- delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1556
- request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1557
- }
1558
- ```
1559
-
1560
- **Returns:** The created result.
1702
+ #### `createFormFromController(controller)`
1561
1703
 
1562
- #### `createHttpFromClient(client)`
1704
+ Create form primitives from an existing controller.
1563
1705
 
1564
- Creates a http from client.
1706
+ Useful when you have a controller created externally and want to
1707
+ wrap it with Solid reactivity.
1565
1708
 
1566
1709
  ```typescript
1567
- function createHttpFromClient(client: HttpClient): {
1568
- get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1569
- post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1570
- put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1571
- patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1572
- delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1573
- request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1574
- }
1710
+ function createFormFromController(controller: FormController<T>): CreateFormResult<T>
1575
1711
  ```
1576
1712
 
1577
- - `client` — The client instance.
1713
+ - `controller` — An existing FormController
1578
1714
 
1579
- **Returns:** The created result.
1715
+ **Returns:** Form primitives object
1580
1716
 
1581
- #### `createHttpHelpers()`
1717
+ #### `createHttp()`
1582
1718
 
1583
- Creates a http helpers.
1719
+ Creates a http.
1584
1720
 
1585
1721
  ```typescript
1586
- function createHttpHelpers(): {
1722
+ function createHttp(): {
1587
1723
  get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1588
1724
  post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1589
1725
  put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1590
1726
  patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1591
1727
  delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1592
- setAuthToken: (token: string | null) => void
1593
- getAuthToken: () => string | null
1594
- }
1595
- ```
1596
-
1597
- **Returns:** The created result.
1598
-
1599
- #### `createI18n()`
1600
-
1601
- Creates a i18n.
1602
-
1603
- ```typescript
1604
- function createI18n(): {
1605
- t: TranslateFunction
1606
- locale: Accessor<string>
1607
- setLocale: (newLocale: string) => Promise<void>
1608
- isReady: Accessor<boolean>
1609
- getLocales: () => LocaleConfig[]
1610
- hasKey: (key: string) => boolean
1728
+ request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1611
1729
  }
1612
1730
  ```
1613
1731
 
1614
1732
  **Returns:** The created result.
1615
1733
 
1616
- #### `createI18nFromProvider(provider)`
1734
+ #### `useFetch(url, config)`
1617
1735
 
1618
- Creates a i18n from provider.
1736
+ Create a resource for fetching data.
1619
1737
 
1620
1738
  ```typescript
1621
- function createI18nFromProvider(provider: I18nProvider): {
1622
- t: TranslateFunction
1623
- locale: Accessor<string>
1624
- setLocale: (newLocale: string) => Promise<void>
1625
- isReady: Accessor<boolean>
1626
- getLocales: () => LocaleConfig[]
1627
- hasKey: (key: string) => boolean
1628
- }
1739
+ function useFetch(url: string | Accessor<string>, config?: RequestConfig): Resource<T | undefined>
1629
1740
  ```
1630
1741
 
1631
- - `provider` — The provider implementation.
1742
+ - `url` — URL string or accessor returning a URL string.
1743
+ - `config` — Optional request configuration.
1632
1744
 
1633
- **Returns:** The created result.
1745
+ **Returns:** Solid resource
1634
1746
 
1635
- #### `createI18nHelpers()`
1747
+ #### `useMutation()`
1636
1748
 
1637
- Creates a i18n helpers.
1749
+ Hook for mutation.
1638
1750
 
1639
1751
  ```typescript
1640
- function createI18nHelpers(): {
1641
- t: TranslateFunction
1642
- getLocale: () => string
1643
- setLocale: (locale: string) => Promise<void>
1644
- getLocales: () => LocaleConfig[]
1645
- hasKey: (key: string) => boolean
1646
- isReady: () => boolean
1752
+ function useMutation(): {
1753
+ mutate: (
1754
+ url: string,
1755
+ payload?: unknown,
1756
+ method?: 'POST' | 'PUT' | 'PATCH' | 'DELETE',
1757
+ ) => Promise<T>
1758
+ isLoading: Accessor<boolean>
1759
+ error: Accessor<Error | null>
1760
+ data: Accessor<T | null>
1761
+ reset: () => void
1647
1762
  }
1648
1763
  ```
1649
1764
 
1650
- **Returns:** The created result.
1651
-
1652
- #### `createIsActive(path, exact)`
1653
-
1654
- Create a reactive boolean accessor that tracks whether a given path is active.
1655
-
1656
- Unlike `useMatch` which only accepts a static pattern, this factory returns
1657
- a signal that re-evaluates on every route change and supports the `exact`
1658
- parameter from the router's `isActive` method.
1659
-
1660
- ```typescript
1661
- function createIsActive(path: string, exact?: boolean): Accessor<boolean>
1662
- ```
1663
-
1664
- - `path` — Path to check against the current location
1665
- - `exact` — Whether to require an exact match (default: false)
1666
-
1667
- **Returns:** Accessor<boolean> that is true when the path is active
1668
-
1669
- #### `createLogger(config)`
1670
-
1671
- Create a logger with custom configuration.
1672
-
1673
- ```typescript
1674
- function createLogger(config: LoggerConfig): Logger
1675
- ```
1676
-
1677
- - `config` — Logger configuration
1678
-
1679
- **Returns:** Logger instance
1680
-
1681
- #### `createLoggerFromProvider(provider, name)`
1682
-
1683
- Create logger from a specific provider.
1684
-
1685
- ```typescript
1686
- function createLoggerFromProvider(provider: LoggerProvider, name?: string): Logger
1687
- ```
1688
-
1689
- - `provider` — Logger provider
1690
- - `name` — Logger name
1691
-
1692
- **Returns:** Logger instance
1765
+ **Returns:** The result.
1693
1766
 
1694
- #### `createLoggerHelpers()`
1767
+ #### `useLazyQuery()`
1695
1768
 
1696
- Creates a logger helpers.
1769
+ Hook for lazy query.
1697
1770
 
1698
1771
  ```typescript
1699
- function createLoggerHelpers(): {
1700
- getLogger: (name?: string) => Logger
1701
- createLogger: (config: LoggerConfig) => Logger
1702
- setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
1703
- getLevel: () => string
1704
- enable: () => void
1705
- disable: () => void
1706
- isEnabled: () => boolean
1772
+ function useLazyQuery(): {
1773
+ execute: (url: string, config?: RequestConfig) => Promise<T>
1774
+ data: () => T | null
1775
+ isLoading: () => boolean
1776
+ error: () => Error | null
1777
+ reset: () => void
1707
1778
  }
1708
1779
  ```
1709
1780
 
1710
- **Returns:** The created result.
1781
+ **Returns:** The result.
1711
1782
 
1712
- #### `createLoggerHelpersFromProvider(provider)`
1783
+ #### `createHttpHelpers()`
1713
1784
 
1714
- Creates a logger helpers from provider.
1785
+ Creates a http helpers.
1715
1786
 
1716
1787
  ```typescript
1717
- function createLoggerHelpersFromProvider(provider: LoggerProvider): {
1718
- getLogger: (name?: string) => Logger
1719
- createLogger: (config: LoggerConfig) => Logger
1720
- setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
1721
- getLevel: () => string
1722
- enable: () => void
1723
- disable: () => void
1724
- isEnabled: () => boolean
1788
+ function createHttpHelpers(): {
1789
+ get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1790
+ post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1791
+ put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1792
+ patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1793
+ delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1794
+ setAuthToken: (token: string | null) => void
1795
+ getAuthToken: () => string | null
1725
1796
  }
1726
1797
  ```
1727
1798
 
1728
- - `provider` — The provider implementation.
1729
-
1730
1799
  **Returns:** The created result.
1731
1800
 
1732
- #### `createLogin()`
1733
-
1734
- Creates a login primitive with async state tracking.
1735
-
1736
- ```typescript
1737
- function createLogin(): CreateLoginReturn<T>
1738
- ```
1739
-
1740
- **Returns:** Login state and action
1741
-
1742
- #### `createOAuth(options)`
1743
-
1744
- Creates OAuth helpers.
1745
-
1746
- Automatically handles OAuth callbacks by detecting `code` and `state` URL
1747
- parameters and exchanging them for a session:
1801
+ #### `createHttpFromClient(client)`
1748
1802
 
1749
- - Inside a Solid owner (component setup / `createRoot`), the callback
1750
- handling is deferred to `onMount` so it runs client-side after mount.
1751
- - Outside an owner (a plain function call, e.g. bootstrap code), it runs
1752
- immediately at creation, browser-guarded.
1803
+ Creates a http from client.
1753
1804
 
1754
1805
  ```typescript
1755
- function createOAuth(options?: CreateOAuthOptions): CreateOAuthReturn
1806
+ function createHttpFromClient(client: HttpClient): {
1807
+ get: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1808
+ post: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1809
+ put: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1810
+ patch: <T>(url: string, data?: unknown, config?: RequestConfig) => Promise<HttpResponse<T>>
1811
+ delete: <T>(url: string, config?: RequestConfig) => Promise<HttpResponse<T>>
1812
+ request: <T>(config: FullRequestConfig) => Promise<HttpResponse<T>>
1813
+ }
1756
1814
  ```
1757
1815
 
1758
- - `options` — OAuth configuration
1816
+ - `client` — The client instance.
1759
1817
 
1760
- **Returns:** The created instance.
1818
+ **Returns:** The created result.
1761
1819
 
1762
- #### `createPasswordReset()`
1820
+ #### `createI18n()`
1763
1821
 
1764
- Creates a password reset primitive with async state tracking.
1822
+ Creates a i18n.
1765
1823
 
1766
1824
  ```typescript
1767
- function createPasswordReset(): CreatePasswordResetReturn
1825
+ function createI18n(): {
1826
+ t: TranslateFunction
1827
+ locale: Accessor<string>
1828
+ setLocale: (newLocale: string) => Promise<void>
1829
+ isReady: Accessor<boolean>
1830
+ getLocales: () => LocaleConfig[]
1831
+ hasKey: (key: string) => boolean
1832
+ }
1768
1833
  ```
1769
1834
 
1770
- **Returns:** Password reset state and actions
1835
+ **Returns:** The created result.
1771
1836
 
1772
- #### `createPersistedStore(key, initial, storage)`
1837
+ #### `useTranslate()`
1773
1838
 
1774
- Create a persisted signal store.
1839
+ Get translate function.
1775
1840
 
1776
1841
  ```typescript
1777
- function createPersistedStore(
1778
- key: string,
1779
- initial: T,
1780
- storage: StorageAdapter,
1781
- ): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
1842
+ function useTranslate(): TranslateFunction
1782
1843
  ```
1783
1844
 
1784
- - `key` — Storage key
1785
- - `initial` — Initial value
1786
- - `storage` — Storage adapter (required - use localStorage, sessionStorage, or `@molecule/app-storage`)
1787
-
1788
- **Returns:** Tuple of accessor and setter
1789
-
1790
- #### `createPlatform()`
1845
+ **Returns:** Translate function
1791
1846
 
1792
- Create platform primitives for detecting the current platform.
1847
+ #### `useLocale()`
1793
1848
 
1794
- This is a static primitive (no reactive signals) since the platform
1795
- does not change during the lifecycle of the app.
1849
+ Get current locale as accessor.
1796
1850
 
1797
1851
  ```typescript
1798
- function createPlatform(): PlatformPrimitives
1852
+ function useLocale(): Accessor<string>
1799
1853
  ```
1800
1854
 
1801
- **Returns:** Platform primitives object
1855
+ **Returns:** Accessor for current locale
1802
1856
 
1803
- #### `createPromise(asyncFn)`
1857
+ #### `useTranslation(key, values, options)`
1804
1858
 
1805
- Primitive that wraps an async function with reactive state tracking.
1859
+ Create a reactive translation.
1806
1860
 
1807
1861
  ```typescript
1808
- function createPromise(asyncFn: T): CreatePromiseReturn<Awaited<ReturnType<T>>>
1862
+ function useTranslation(
1863
+ key: string,
1864
+ values?: InterpolationValues,
1865
+ options?: TranslateOptions,
1866
+ ): Accessor<string>
1809
1867
  ```
1810
1868
 
1811
- - `asyncFn` — The async function to wrap
1869
+ - `key` — Translation key
1870
+ - `values` — Interpolation values for the translation.
1871
+ - `options` — Translation options
1812
1872
 
1813
- **Returns:** Object with state accessor, call, cancel, and reset functions
1873
+ **Returns:** Accessor for translated string
1814
1874
 
1815
- #### `createPush()`
1875
+ #### `usePlural(key, count, values)`
1816
1876
 
1817
- Create push notification primitives.
1877
+ Create a reactive plural translation.
1818
1878
 
1819
1879
  ```typescript
1820
- function createPush(): PushPrimitives
1880
+ function usePlural(
1881
+ key: string,
1882
+ count: Accessor<number>,
1883
+ values?: InterpolationValues,
1884
+ ): Accessor<string>
1821
1885
  ```
1822
1886
 
1823
- **Returns:** Push primitives object
1824
-
1825
- #### `createRouter()`
1826
-
1827
- Create router primitives for navigation state and actions.
1828
-
1829
- ```typescript
1830
- function createRouter(): RouterPrimitives
1831
- ```
1887
+ - `key` — Translation key
1888
+ - `count` — Count accessor for pluralization
1889
+ - `values` — Interpolation values for the translation.
1832
1890
 
1833
- **Returns:** Router primitives object
1891
+ **Returns:** Accessor for translated string
1834
1892
 
1835
- #### `createRouterFromInstance(router)`
1893
+ #### `createI18nHelpers()`
1836
1894
 
1837
- Create router primitives from a specific router.
1895
+ Creates a i18n helpers.
1838
1896
 
1839
1897
  ```typescript
1840
- function createRouterFromInstance(router: Router): RouterPrimitives
1898
+ function createI18nHelpers(): {
1899
+ t: TranslateFunction
1900
+ getLocale: () => string
1901
+ setLocale: (locale: string) => Promise<void>
1902
+ getLocales: () => LocaleConfig[]
1903
+ hasKey: (key: string) => boolean
1904
+ isReady: () => boolean
1905
+ }
1841
1906
  ```
1842
1907
 
1843
- - `router` — Router instance
1844
-
1845
- **Returns:** Router primitives
1908
+ **Returns:** The created result.
1846
1909
 
1847
- #### `createRouterHelpers()`
1910
+ #### `createI18nFromProvider(provider)`
1848
1911
 
1849
- Creates a router helpers.
1912
+ Creates a i18n from provider.
1850
1913
 
1851
1914
  ```typescript
1852
- function createRouterHelpers(): {
1853
- navigate: (path: string, options?: NavigateOptions) => void
1854
- navigateTo: (
1855
- name: string,
1856
- params?: RouteParams,
1857
- query?: QueryParams,
1858
- options?: NavigateOptions,
1859
- ) => void
1860
- back: () => void
1861
- forward: () => void
1862
- getLocation: () => RouteLocation
1863
- getParams: () => RouteParams
1864
- getQuery: () => QueryParams
1865
- isActive: (path: string) => boolean
1915
+ function createI18nFromProvider(provider: I18nProvider): {
1916
+ t: TranslateFunction
1917
+ locale: Accessor<string>
1918
+ setLocale: (newLocale: string) => Promise<void>
1919
+ isReady: Accessor<boolean>
1920
+ getLocales: () => LocaleConfig[]
1921
+ hasKey: (key: string) => boolean
1866
1922
  }
1867
1923
  ```
1868
1924
 
1925
+ - `provider` — The provider implementation.
1926
+
1869
1927
  **Returns:** The created result.
1870
1928
 
1871
- #### `createSignalStore(initial)`
1929
+ #### `getLogger(name)`
1872
1930
 
1873
- Create a simple signal-based store without provider.
1931
+ Get a logger instance.
1874
1932
 
1875
1933
  ```typescript
1876
- function createSignalStore(initial: T): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
1934
+ function getLogger(name?: string): Logger
1877
1935
  ```
1878
1936
 
1879
- - `initial` — Initial state
1937
+ - `name` — Logger name
1880
1938
 
1881
- **Returns:** The created instance.
1939
+ **Returns:** Logger instance
1882
1940
 
1883
- #### `createSignup()`
1941
+ #### `createLogger(config)`
1884
1942
 
1885
- Creates a signup primitive with async state tracking.
1943
+ Create a logger with custom configuration.
1886
1944
 
1887
1945
  ```typescript
1888
- function createSignup(): CreateSignupReturn<T>
1946
+ function createLogger(config: LoggerConfig): Logger
1889
1947
  ```
1890
1948
 
1891
- **Returns:** Signup state and action
1949
+ - `config` — Logger configuration
1892
1950
 
1893
- #### `createStateHelpers()`
1951
+ **Returns:** Logger instance
1894
1952
 
1895
- Creates a state helpers.
1953
+ #### `getRootLogger()`
1954
+
1955
+ Get the root logger.
1896
1956
 
1897
1957
  ```typescript
1898
- function createStateHelpers(): {
1899
- createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
1900
- }
1958
+ function getRootLogger(): Logger
1901
1959
  ```
1902
1960
 
1903
- **Returns:** The created result.
1961
+ **Returns:** Root logger instance
1904
1962
 
1905
- #### `createStateHelpersFromProvider(provider)`
1963
+ #### `getChildLogger(name, context)`
1906
1964
 
1907
- Creates a state helpers from provider.
1965
+ Create a child logger with additional context.
1908
1966
 
1909
1967
  ```typescript
1910
- function createStateHelpersFromProvider(provider: StateProvider): {
1911
- createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
1912
- }
1968
+ function getChildLogger(name: string, context: Record<string, unknown>): Logger
1913
1969
  ```
1914
1970
 
1915
- - `provider` — The provider implementation.
1971
+ - `name` — Parent logger name
1972
+ - `context` — Additional context
1916
1973
 
1917
- **Returns:** The created result.
1974
+ **Returns:** Child logger instance
1918
1975
 
1919
- #### `createStorage()`
1976
+ #### `useComponentLogger(componentName)`
1920
1977
 
1921
- Create storage primitives.
1978
+ Create a component logger that includes component name in context.
1922
1979
 
1923
1980
  ```typescript
1924
- function createStorage(): {
1925
- get: <T>(key: string) => Promise<T | null>
1926
- set: <T>(key: string, value: T) => Promise<void>
1927
- remove: (key: string) => Promise<void>
1928
- clear: () => Promise<void>
1929
- keys: () => Promise<string[]>
1930
- }
1981
+ function useComponentLogger(componentName: string): Logger
1931
1982
  ```
1932
1983
 
1933
- **Returns:** Storage methods
1984
+ - `componentName` — Name of the component
1934
1985
 
1935
- #### `createStorageFromProvider(storage)`
1986
+ **Returns:** Logger configured for the component
1936
1987
 
1937
- Create storage primitives from a specific provider.
1988
+ #### `createLoggerHelpers()`
1989
+
1990
+ Creates a logger helpers.
1938
1991
 
1939
1992
  ```typescript
1940
- function createStorageFromProvider(storage: StorageProvider): {
1941
- get: <T>(key: string) => Promise<T | null>
1942
- set: <T>(key: string, value: T) => Promise<void>
1943
- remove: (key: string) => Promise<void>
1944
- clear: () => Promise<void>
1945
- keys: () => Promise<string[]>
1993
+ function createLoggerHelpers(): {
1994
+ getLogger: (name?: string) => Logger
1995
+ createLogger: (config: LoggerConfig) => Logger
1996
+ setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
1997
+ getLevel: () => string
1998
+ enable: () => void
1999
+ disable: () => void
2000
+ isEnabled: () => boolean
1946
2001
  }
1947
2002
  ```
1948
2003
 
1949
- - `storage` — Storage provider
1950
-
1951
- **Returns:** Storage methods
2004
+ **Returns:** The created result.
1952
2005
 
1953
- #### `createStorageHelpers()`
2006
+ #### `createLoggerHelpersFromProvider(provider)`
1954
2007
 
1955
- Create storage helpers from context.
2008
+ Creates a logger helpers from provider.
1956
2009
 
1957
2010
  ```typescript
1958
- function createStorageHelpers(): {
1959
- get: <T>(key: string) => Promise<T | null>
1960
- set: <T>(key: string, value: T) => Promise<void>
1961
- remove: (key: string) => Promise<void>
1962
- clear: () => Promise<void>
1963
- keys: () => Promise<string[]>
2011
+ function createLoggerHelpersFromProvider(provider: LoggerProvider): {
2012
+ getLogger: (name?: string) => Logger
2013
+ createLogger: (config: LoggerConfig) => Logger
2014
+ setLevel: (level: 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent') => void
2015
+ getLevel: () => string
2016
+ enable: () => void
2017
+ disable: () => void
2018
+ isEnabled: () => boolean
1964
2019
  }
1965
2020
  ```
1966
2021
 
1967
- **Returns:** Storage helper functions
2022
+ - `provider` — The provider implementation.
1968
2023
 
1969
- #### `createStorageValue(key, defaultValue)`
2024
+ **Returns:** The created result.
1970
2025
 
1971
- Create a storage value primitive.
2026
+ #### `createLoggerFromProvider(provider, name)`
2027
+
2028
+ Create logger from a specific provider.
1972
2029
 
1973
2030
  ```typescript
1974
- function createStorageValue(
1975
- key: string,
1976
- defaultValue?: T,
1977
- ): {
1978
- value: () => T | undefined
1979
- loading: () => boolean
1980
- error: () => Error | null
1981
- set: (value: T) => Promise<void>
1982
- remove: () => Promise<void>
1983
- refresh: () => Promise<T | undefined>
1984
- }
2031
+ function createLoggerFromProvider(provider: LoggerProvider, name?: string): Logger
1985
2032
  ```
1986
2033
 
1987
- - `key` — Storage key
1988
- - `defaultValue` — Default value if not found
2034
+ - `provider` — Logger provider
2035
+ - `name` — Logger name
1989
2036
 
1990
- **Returns:** Storage value accessor and actions
2037
+ **Returns:** Logger instance
1991
2038
 
1992
- #### `createStorageValueFromProvider(storage, key, defaultValue)`
2039
+ #### `createLogin()`
1993
2040
 
1994
- Create storage value primitive from a specific provider.
2041
+ Creates a login primitive with async state tracking.
1995
2042
 
1996
2043
  ```typescript
1997
- function createStorageValueFromProvider(
1998
- storage: StorageProvider,
1999
- key: string,
2000
- defaultValue?: T,
2001
- ): {
2002
- value: () => T | undefined
2003
- loading: () => boolean
2004
- error: () => Error | null
2005
- set: (value: T) => Promise<void>
2006
- remove: () => Promise<void>
2007
- }
2044
+ function createLogin(): CreateLoginReturn<T>
2008
2045
  ```
2009
2046
 
2010
- - `storage` — Storage provider
2011
- - `key` — Storage key
2012
- - `defaultValue` — Default value
2047
+ **Returns:** Login state and action
2013
2048
 
2014
- **Returns:** Storage value accessor and actions
2049
+ #### `createOAuth(options)`
2015
2050
 
2016
- #### `createStore(config)`
2051
+ Creates OAuth helpers.
2017
2052
 
2018
- Create a reactive store using Solid signals.
2053
+ Automatically handles OAuth callbacks by detecting `code` and `state` URL
2054
+ parameters and exchanging them for a session:
2055
+
2056
+ - Inside a Solid owner (component setup / `createRoot`), the callback
2057
+ handling is deferred to `onMount` so it runs client-side after mount.
2058
+ - Outside an owner (a plain function call, e.g. bootstrap code), it runs
2059
+ immediately at creation, browser-guarded.
2019
2060
 
2020
2061
  ```typescript
2021
- function createStore(config: StoreConfig<T>): Store<T>
2062
+ function createOAuth(options?: CreateOAuthOptions): CreateOAuthReturn
2022
2063
  ```
2023
2064
 
2024
- - `config` — Store configuration
2065
+ - `options` — OAuth configuration
2025
2066
 
2026
- **Returns:** Store instance
2067
+ **Returns:** The created instance.
2027
2068
 
2028
- #### `createTheme()`
2069
+ #### `createPasswordReset()`
2029
2070
 
2030
- Create theme primitives for theme state and actions.
2071
+ Creates a password reset primitive with async state tracking.
2031
2072
 
2032
2073
  ```typescript
2033
- function createTheme(): ThemePrimitives
2074
+ function createPasswordReset(): CreatePasswordResetReturn
2034
2075
  ```
2035
2076
 
2036
- **Returns:** The created instance.
2077
+ **Returns:** Password reset state and actions
2037
2078
 
2038
- #### `createThemeColors(theme)`
2079
+ #### `createPlatform()`
2039
2080
 
2040
- Create a colors accessor derived from a theme accessor.
2081
+ Create platform primitives for detecting the current platform.
2082
+
2083
+ This is a static primitive (no reactive signals) since the platform
2084
+ does not change during the lifecycle of the app.
2041
2085
 
2042
2086
  ```typescript
2043
- function createThemeColors(theme: Accessor<Theme>): Accessor<ThemeColors>
2087
+ function createPlatform(): PlatformPrimitives
2044
2088
  ```
2045
2089
 
2046
- - `theme` — Theme accessor (e.g. from createTheme().theme)
2047
-
2048
- **Returns:** Accessor for the current theme colors
2090
+ **Returns:** Platform primitives object
2049
2091
 
2050
- #### `createThemeFromProvider(provider)`
2092
+ #### `createPromise(asyncFn)`
2051
2093
 
2052
- Create theme primitives from a specific provider.
2094
+ Primitive that wraps an async function with reactive state tracking.
2053
2095
 
2054
2096
  ```typescript
2055
- function createThemeFromProvider(provider: ThemeProvider): ThemePrimitives
2097
+ function createPromise(asyncFn: T): CreatePromiseReturn<Awaited<ReturnType<T>>>
2056
2098
  ```
2057
2099
 
2058
- - `provider` — Theme provider
2100
+ - `asyncFn` — The async function to wrap
2059
2101
 
2060
- **Returns:** Theme primitives
2102
+ **Returns:** Object with state accessor, call, cancel, and reset functions
2061
2103
 
2062
- #### `createThemeHelpers()`
2104
+ #### `createPush()`
2063
2105
 
2064
- Creates a theme helpers.
2106
+ Create push notification primitives.
2065
2107
 
2066
2108
  ```typescript
2067
- function createThemeHelpers(): {
2068
- getTheme: () => Theme
2069
- setTheme: (name: string) => void
2070
- getMode: () => 'light' | 'dark'
2071
- toggleMode: () => void
2072
- getAvailableThemes: () => Theme[]
2073
- }
2109
+ function createPush(): PushPrimitives
2074
2110
  ```
2075
2111
 
2076
- **Returns:** The created result.
2112
+ **Returns:** Push primitives object
2077
2113
 
2078
- #### `createVersion()`
2114
+ #### `createRouter()`
2079
2115
 
2080
- Create version primitives for tracking app updates.
2116
+ Create router primitives for navigation state and actions.
2081
2117
 
2082
2118
  ```typescript
2083
- function createVersion(): VersionPrimitives
2119
+ function createRouter(): RouterPrimitives
2084
2120
  ```
2085
2121
 
2086
- **Returns:** Version primitives object
2122
+ **Returns:** Router primitives object
2087
2123
 
2088
- #### `createWatchSignal(controller, name)`
2124
+ #### `useLocation()`
2089
2125
 
2090
- Create a reactive accessor that tracks a single field's value.
2126
+ Get current route location as accessor.
2091
2127
 
2092
2128
  ```typescript
2093
- function createWatchSignal(controller: FormController<T>, name: K): Accessor<T[K]>
2129
+ function useLocation(): Accessor<RouteLocation>
2094
2130
  ```
2095
2131
 
2096
- - `controller` — Form controller
2097
- - `name` — Field name to watch
2098
-
2099
- **Returns:** Accessor for the field value
2132
+ **Returns:** Accessor for current location
2100
2133
 
2101
- #### `getAuthClient()`
2134
+ #### `useParams()`
2102
2135
 
2103
- Get the auth client from context.
2136
+ Get current route params as accessor.
2104
2137
 
2105
2138
  ```typescript
2106
- function getAuthClient(): AuthClient<T>
2139
+ function useParams(): Accessor<RouteParams>
2107
2140
  ```
2108
2141
 
2109
- **Returns:** The auth client instance.
2142
+ **Returns:** Accessor for route params
2110
2143
 
2111
- #### `getChildLogger(name, context)`
2144
+ #### `useQuery()`
2112
2145
 
2113
- Create a child logger with additional context.
2146
+ Get current query params as accessor.
2114
2147
 
2115
2148
  ```typescript
2116
- function getChildLogger(name: string, context: Record<string, unknown>): Logger
2149
+ function useQuery(): Accessor<QueryParams>
2117
2150
  ```
2118
2151
 
2119
- - `name` — Parent logger name
2120
- - `context` — Additional context
2121
-
2122
- **Returns:** Child logger instance
2152
+ **Returns:** Accessor for query params
2123
2153
 
2124
- #### `getHttpClient()`
2154
+ #### `useNavigate()`
2125
2155
 
2126
- Get the HTTP client from context.
2156
+ Get navigate function.
2127
2157
 
2128
2158
  ```typescript
2129
- function getHttpClient(): HttpClient
2159
+ function useNavigate(): (path: string, options?: NavigateOptions) => void
2130
2160
  ```
2131
2161
 
2132
- **Returns:** The HTTP client instance.
2162
+ **Returns:** Navigate function
2133
2163
 
2134
- #### `getI18nProvider()`
2164
+ #### `useMatch(pattern)`
2135
2165
 
2136
- Get the i18n provider from context.
2166
+ Create a match accessor for a path pattern.
2137
2167
 
2138
2168
  ```typescript
2139
- function getI18nProvider(): I18nProvider
2169
+ function useMatch(pattern: string): Accessor<boolean>
2140
2170
  ```
2141
2171
 
2142
- **Returns:** The i18n provider instance.
2172
+ - `pattern` — Path pattern to match
2143
2173
 
2144
- #### `getLogger(name)`
2174
+ **Returns:** Accessor indicating if current path matches
2145
2175
 
2146
- Get a logger instance.
2176
+ #### `createIsActive(path, exact)`
2177
+
2178
+ Create a reactive boolean accessor that tracks whether a given path is active.
2179
+
2180
+ Unlike `useMatch` which only accepts a static pattern, this factory returns
2181
+ a signal that re-evaluates on every route change and supports the `exact`
2182
+ parameter from the router's `isActive` method.
2147
2183
 
2148
2184
  ```typescript
2149
- function getLogger(name?: string): Logger
2185
+ function createIsActive(path: string, exact?: boolean): Accessor<boolean>
2150
2186
  ```
2151
2187
 
2152
- - `name` — Logger name
2188
+ - `path` — Path to check against the current location
2189
+ - `exact` — Whether to require an exact match (default: false)
2153
2190
 
2154
- **Returns:** Logger instance
2191
+ **Returns:** Accessor<boolean> that is true when the path is active
2155
2192
 
2156
- #### `getLoggerProvider()`
2193
+ #### `createRouterHelpers()`
2157
2194
 
2158
- Get the logger provider from context.
2195
+ Creates a router helpers.
2159
2196
 
2160
2197
  ```typescript
2161
- function getLoggerProvider(): LoggerProvider
2198
+ function createRouterHelpers(): {
2199
+ navigate: (path: string, options?: NavigateOptions) => void
2200
+ navigateTo: (
2201
+ name: string,
2202
+ params?: RouteParams,
2203
+ query?: QueryParams,
2204
+ options?: NavigateOptions,
2205
+ ) => void
2206
+ back: () => void
2207
+ forward: () => void
2208
+ getLocation: () => RouteLocation
2209
+ getParams: () => RouteParams
2210
+ getQuery: () => QueryParams
2211
+ isActive: (path: string) => boolean
2212
+ }
2162
2213
  ```
2163
2214
 
2164
- **Returns:** The logger provider instance.
2215
+ **Returns:** The created result.
2165
2216
 
2166
- #### `getRootLogger()`
2217
+ #### `createRouterFromInstance(router)`
2167
2218
 
2168
- Get the root logger.
2219
+ Create router primitives from a specific router.
2169
2220
 
2170
2221
  ```typescript
2171
- function getRootLogger(): Logger
2222
+ function createRouterFromInstance(router: Router): RouterPrimitives
2172
2223
  ```
2173
2224
 
2174
- **Returns:** Root logger instance
2225
+ - `router` — Router instance
2175
2226
 
2176
- #### `getRouter()`
2227
+ **Returns:** Router primitives
2177
2228
 
2178
- Get the router from context.
2229
+ #### `createSignup()`
2230
+
2231
+ Creates a signup primitive with async state tracking.
2179
2232
 
2180
2233
  ```typescript
2181
- function getRouter(): Router
2234
+ function createSignup(): CreateSignupReturn<T>
2182
2235
  ```
2183
2236
 
2184
- **Returns:** The router instance.
2237
+ **Returns:** Signup state and action
2185
2238
 
2186
- #### `getStateProvider()`
2239
+ #### `createStore(config)`
2187
2240
 
2188
- Get the state provider from context.
2241
+ Create a reactive store using Solid signals.
2189
2242
 
2190
2243
  ```typescript
2191
- function getStateProvider(): StateProvider
2244
+ function createStore(config: StoreConfig<T>): Store<T>
2192
2245
  ```
2193
2246
 
2194
- **Returns:** The state provider instance.
2247
+ - `config` — Store configuration
2195
2248
 
2196
- #### `getStorageProvider()`
2249
+ **Returns:** Store instance
2197
2250
 
2198
- Get the storage provider from context.
2251
+ #### `useStore(store, selector)`
2252
+
2253
+ Use a store with optional selector, returning an accessor.
2199
2254
 
2200
2255
  ```typescript
2201
- function getStorageProvider(): StorageProvider
2256
+ function useStore(store: Store<T>, selector?: (state: T) => S): Accessor<S>
2202
2257
  ```
2203
2258
 
2204
- **Returns:** The storage provider instance.
2259
+ - `store` — Store to subscribe to
2260
+ - `selector` — Optional selector function
2205
2261
 
2206
- #### `getThemeProvider()`
2262
+ **Returns:** Accessor for selected state
2207
2263
 
2208
- Get the theme provider from context.
2264
+ #### `createSignalStore(initial)`
2265
+
2266
+ Create a simple signal-based store without provider.
2209
2267
 
2210
2268
  ```typescript
2211
- function getThemeProvider(): ThemeProvider
2269
+ function createSignalStore(initial: T): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
2212
2270
  ```
2213
2271
 
2214
- **Returns:** The theme provider instance.
2272
+ - `initial` — Initial state
2215
2273
 
2216
- #### `MoleculeProvider(props)`
2274
+ **Returns:** The created instance.
2217
2275
 
2218
- MoleculeProvider component that provides all molecule services to the component tree.
2276
+ #### `createPersistedStore(key, initial, storage)`
2277
+
2278
+ Create a persisted signal store.
2219
2279
 
2220
2280
  ```typescript
2221
- function MoleculeProvider(props: ParentProps<{ config: MoleculeConfig }>): JSX.Element
2281
+ function createPersistedStore(
2282
+ key: string,
2283
+ initial: T,
2284
+ storage: StorageAdapter,
2285
+ ): [Accessor<T>, (value: T | ((prev: T) => T)) => void]
2222
2286
  ```
2223
2287
 
2224
- - `props` — Component props containing the molecule config.
2288
+ - `key` — Storage key
2289
+ - `initial` — Initial value
2290
+ - `storage` — Storage adapter (required - use localStorage, sessionStorage, or `@molecule/app-storage`)
2225
2291
 
2226
- **Returns:** The nested provider tree wrapping children.
2292
+ **Returns:** Tuple of accessor and setter
2227
2293
 
2228
- #### `useComponentLogger(componentName)`
2294
+ #### `createStateHelpers()`
2229
2295
 
2230
- Create a component logger that includes component name in context.
2296
+ Creates a state helpers.
2231
2297
 
2232
2298
  ```typescript
2233
- function useComponentLogger(componentName: string): Logger
2299
+ function createStateHelpers(): {
2300
+ createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
2301
+ }
2234
2302
  ```
2235
2303
 
2236
- - `componentName` — Name of the component
2237
-
2238
- **Returns:** Logger configured for the component
2304
+ **Returns:** The created result.
2239
2305
 
2240
- #### `useFetch(url, config)`
2306
+ #### `createStateHelpersFromProvider(provider)`
2241
2307
 
2242
- Create a resource for fetching data.
2308
+ Creates a state helpers from provider.
2243
2309
 
2244
2310
  ```typescript
2245
- function useFetch(url: string | Accessor<string>, config?: RequestConfig): Resource<T | undefined>
2311
+ function createStateHelpersFromProvider(provider: StateProvider): {
2312
+ createStore: <T extends object>(config: StoreConfig<T>) => Store<T>
2313
+ }
2246
2314
  ```
2247
2315
 
2248
- - `url` — URL string or accessor returning a URL string.
2249
- - `config` — Optional request configuration.
2316
+ - `provider` — The provider implementation.
2250
2317
 
2251
- **Returns:** Solid resource
2318
+ **Returns:** The created result.
2252
2319
 
2253
- #### `useLazyQuery()`
2320
+ #### `createStorageValue(key, defaultValue)`
2254
2321
 
2255
- Hook for lazy query.
2322
+ Create a storage value primitive.
2256
2323
 
2257
2324
  ```typescript
2258
- function useLazyQuery(): {
2259
- execute: (url: string, config?: RequestConfig) => Promise<T>
2260
- data: () => T | null
2261
- isLoading: () => boolean
2325
+ function createStorageValue(
2326
+ key: string,
2327
+ defaultValue?: T,
2328
+ ): {
2329
+ value: () => T | undefined
2330
+ loading: () => boolean
2262
2331
  error: () => Error | null
2263
- reset: () => void
2332
+ set: (value: T) => Promise<void>
2333
+ remove: () => Promise<void>
2334
+ refresh: () => Promise<T | undefined>
2264
2335
  }
2265
2336
  ```
2266
2337
 
2267
- **Returns:** The result.
2338
+ - `key` — Storage key
2339
+ - `defaultValue` — Default value if not found
2268
2340
 
2269
- #### `useLocale()`
2341
+ **Returns:** Storage value accessor and actions
2270
2342
 
2271
- Get current locale as accessor.
2343
+ #### `createStorage()`
2344
+
2345
+ Create storage primitives.
2272
2346
 
2273
2347
  ```typescript
2274
- function useLocale(): Accessor<string>
2348
+ function createStorage(): {
2349
+ get: <T>(key: string) => Promise<T | null>
2350
+ set: <T>(key: string, value: T) => Promise<void>
2351
+ remove: (key: string) => Promise<void>
2352
+ clear: () => Promise<void>
2353
+ keys: () => Promise<string[]>
2354
+ }
2275
2355
  ```
2276
2356
 
2277
- **Returns:** Accessor for current locale
2357
+ **Returns:** Storage methods
2278
2358
 
2279
- #### `useLocation()`
2359
+ #### `usePersistedSignal(key, defaultValue)`
2280
2360
 
2281
- Get current route location as accessor.
2361
+ Create a persisted signal that syncs with storage.
2282
2362
 
2283
2363
  ```typescript
2284
- function useLocation(): Accessor<RouteLocation>
2364
+ function usePersistedSignal(
2365
+ key: string,
2366
+ defaultValue: T,
2367
+ ): [Accessor<T | undefined>, (value: T | ((prev: T | undefined) => T)) => void]
2285
2368
  ```
2286
2369
 
2287
- **Returns:** Accessor for current location
2370
+ - `key` — Storage key
2371
+ - `defaultValue` — Default value
2288
2372
 
2289
- #### `useMatch(pattern)`
2373
+ **Returns:** Tuple of accessor and setter
2290
2374
 
2291
- Create a match accessor for a path pattern.
2375
+ #### `createStorageHelpers()`
2376
+
2377
+ Create storage helpers from context.
2292
2378
 
2293
2379
  ```typescript
2294
- function useMatch(pattern: string): Accessor<boolean>
2380
+ function createStorageHelpers(): {
2381
+ get: <T>(key: string) => Promise<T | null>
2382
+ set: <T>(key: string, value: T) => Promise<void>
2383
+ remove: (key: string) => Promise<void>
2384
+ clear: () => Promise<void>
2385
+ keys: () => Promise<string[]>
2386
+ }
2295
2387
  ```
2296
2388
 
2297
- - `pattern` — Path pattern to match
2298
-
2299
- **Returns:** Accessor indicating if current path matches
2389
+ **Returns:** Storage helper functions
2300
2390
 
2301
- #### `useMode()`
2391
+ #### `createStorageFromProvider(storage)`
2302
2392
 
2303
- Create a mode accessor.
2393
+ Create storage primitives from a specific provider.
2304
2394
 
2305
2395
  ```typescript
2306
- function useMode(): Accessor<'light' | 'dark'>
2396
+ function createStorageFromProvider(storage: StorageProvider): {
2397
+ get: <T>(key: string) => Promise<T | null>
2398
+ set: <T>(key: string, value: T) => Promise<void>
2399
+ remove: (key: string) => Promise<void>
2400
+ clear: () => Promise<void>
2401
+ keys: () => Promise<string[]>
2402
+ }
2307
2403
  ```
2308
2404
 
2309
- **Returns:** Accessor for current mode
2405
+ - `storage` — Storage provider
2310
2406
 
2311
- #### `useMutation()`
2407
+ **Returns:** Storage methods
2312
2408
 
2313
- Hook for mutation.
2409
+ #### `createStorageValueFromProvider(storage, key, defaultValue)`
2410
+
2411
+ Create storage value primitive from a specific provider.
2314
2412
 
2315
2413
  ```typescript
2316
- function useMutation(): {
2317
- mutate: (
2318
- url: string,
2319
- payload?: unknown,
2320
- method?: 'POST' | 'PUT' | 'PATCH' | 'DELETE',
2321
- ) => Promise<T>
2322
- isLoading: Accessor<boolean>
2323
- error: Accessor<Error | null>
2324
- data: Accessor<T | null>
2325
- reset: () => void
2414
+ function createStorageValueFromProvider(
2415
+ storage: StorageProvider,
2416
+ key: string,
2417
+ defaultValue?: T,
2418
+ ): {
2419
+ value: () => T | undefined
2420
+ loading: () => boolean
2421
+ error: () => Error | null
2422
+ set: (value: T) => Promise<void>
2423
+ remove: () => Promise<void>
2326
2424
  }
2327
2425
  ```
2328
2426
 
2329
- **Returns:** The result.
2427
+ - `storage` — Storage provider
2428
+ - `key` — Storage key
2429
+ - `defaultValue` — Default value
2330
2430
 
2331
- #### `useNavigate()`
2431
+ **Returns:** Storage value accessor and actions
2332
2432
 
2333
- Get navigate function.
2433
+ #### `createTheme()`
2434
+
2435
+ Create theme primitives for theme state and actions.
2334
2436
 
2335
2437
  ```typescript
2336
- function useNavigate(): (path: string, options?: NavigateOptions) => void
2438
+ function createTheme(): ThemePrimitives
2337
2439
  ```
2338
2440
 
2339
- **Returns:** Navigate function
2441
+ **Returns:** The created instance.
2340
2442
 
2341
- #### `useParams()`
2443
+ #### `useMode()`
2342
2444
 
2343
- Get current route params as accessor.
2445
+ Create a mode accessor.
2344
2446
 
2345
2447
  ```typescript
2346
- function useParams(): Accessor<RouteParams>
2448
+ function useMode(): Accessor<'light' | 'dark'>
2347
2449
  ```
2348
2450
 
2349
- **Returns:** Accessor for route params
2451
+ **Returns:** Accessor for current mode
2350
2452
 
2351
- #### `usePersistedSignal(key, defaultValue)`
2453
+ #### `useThemeName()`
2352
2454
 
2353
- Create a persisted signal that syncs with storage.
2455
+ Create a theme name accessor.
2354
2456
 
2355
2457
  ```typescript
2356
- function usePersistedSignal(
2357
- key: string,
2358
- defaultValue: T,
2359
- ): [Accessor<T | undefined>, (value: T | ((prev: T | undefined) => T)) => void]
2458
+ function useThemeName(): Accessor<string>
2360
2459
  ```
2361
2460
 
2362
- - `key` — Storage key
2363
- - `defaultValue` — Default value
2364
-
2365
- **Returns:** Tuple of accessor and setter
2461
+ **Returns:** Accessor for current theme name
2366
2462
 
2367
- #### `usePlural(key, count, values)`
2463
+ #### `createThemeHelpers()`
2368
2464
 
2369
- Create a reactive plural translation.
2465
+ Creates a theme helpers.
2370
2466
 
2371
2467
  ```typescript
2372
- function usePlural(
2373
- key: string,
2374
- count: Accessor<number>,
2375
- values?: InterpolationValues,
2376
- ): Accessor<string>
2468
+ function createThemeHelpers(): {
2469
+ getTheme: () => Theme
2470
+ setTheme: (name: string) => void
2471
+ getMode: () => 'light' | 'dark'
2472
+ toggleMode: () => void
2473
+ getAvailableThemes: () => Theme[]
2474
+ }
2377
2475
  ```
2378
2476
 
2379
- - `key` — Translation key
2380
- - `count` — Count accessor for pluralization
2381
- - `values` — Interpolation values for the translation.
2382
-
2383
- **Returns:** Accessor for translated string
2477
+ **Returns:** The created result.
2384
2478
 
2385
- #### `useQuery()`
2479
+ #### `createThemeFromProvider(provider)`
2386
2480
 
2387
- Get current query params as accessor.
2481
+ Create theme primitives from a specific provider.
2388
2482
 
2389
2483
  ```typescript
2390
- function useQuery(): Accessor<QueryParams>
2484
+ function createThemeFromProvider(provider: ThemeProvider): ThemePrimitives
2391
2485
  ```
2392
2486
 
2393
- **Returns:** Accessor for query params
2487
+ - `provider` — Theme provider
2394
2488
 
2395
- #### `useStore(store, selector)`
2489
+ **Returns:** Theme primitives
2396
2490
 
2397
- Use a store with optional selector, returning an accessor.
2491
+ #### `createThemeColors(theme)`
2492
+
2493
+ Create a colors accessor derived from a theme accessor.
2398
2494
 
2399
2495
  ```typescript
2400
- function useStore(store: Store<T>, selector?: (state: T) => S): Accessor<S>
2496
+ function createThemeColors(theme: Accessor<Theme>): Accessor<ThemeColors>
2401
2497
  ```
2402
2498
 
2403
- - `store` — Store to subscribe to
2404
- - `selector` — Optional selector function
2499
+ - `theme` — Theme accessor (e.g. from createTheme().theme)
2405
2500
 
2406
- **Returns:** Accessor for selected state
2501
+ **Returns:** Accessor for the current theme colors
2407
2502
 
2408
- #### `useThemeName()`
2503
+ #### `applyThemeToDocument()`
2409
2504
 
2410
- Create a theme name accessor.
2505
+ Apply theme CSS variables to document.
2411
2506
 
2412
2507
  ```typescript
2413
- function useThemeName(): Accessor<string>
2508
+ function applyThemeToDocument(): void
2414
2509
  ```
2415
2510
 
2416
- **Returns:** Accessor for current theme name
2417
-
2418
- #### `useTranslate()`
2511
+ #### `createVersion()`
2419
2512
 
2420
- Get translate function.
2513
+ Create version primitives for tracking app updates.
2421
2514
 
2422
2515
  ```typescript
2423
- function useTranslate(): TranslateFunction
2516
+ function createVersion(): VersionPrimitives
2424
2517
  ```
2425
2518
 
2426
- **Returns:** Translate function
2519
+ **Returns:** Version primitives object
2427
2520
 
2428
- #### `useTranslation(key, values, options)`
2521
+ #### `MoleculeProvider(props)`
2429
2522
 
2430
- Create a reactive translation.
2523
+ MoleculeProvider component that provides all molecule services to the component tree.
2431
2524
 
2432
2525
  ```typescript
2433
- function useTranslation(
2434
- key: string,
2435
- values?: InterpolationValues,
2436
- options?: TranslateOptions,
2437
- ): Accessor<string>
2526
+ function MoleculeProvider(props: ParentProps<{ config: MoleculeConfig }>): JSX.Element
2438
2527
  ```
2439
2528
 
2440
- - `key` — Translation key
2441
- - `values` — Interpolation values for the translation.
2442
- - `options` — Translation options
2529
+ - `props` — Component props containing the molecule config.
2443
2530
 
2444
- **Returns:** Accessor for translated string
2531
+ **Returns:** The nested provider tree wrapping children.
2445
2532
 
2446
2533
  ### Constants
2447
2534
 
2448
- #### `AuthContext`
2449
-
2450
- ```typescript
2451
- const AuthContext: Context<AuthClient<unknown> | undefined>
2452
- ```
2535
+ #### `StateContext`
2453
2536
 
2454
- #### `HttpContext`
2537
+ Internal contexts for molecule providers.
2455
2538
 
2456
2539
  ```typescript
2457
- const HttpContext: Context<HttpClient | undefined>
2540
+ const StateContext: Context<StateProvider | undefined>
2458
2541
  ```
2459
2542
 
2460
- #### `I18nContext`
2543
+ #### `AuthContext`
2461
2544
 
2462
2545
  ```typescript
2463
- const I18nContext: Context<I18nProvider | undefined>
2546
+ const AuthContext: Context<AuthClient<unknown, Record<never, never>> | undefined>
2464
2547
  ```
2465
2548
 
2466
- #### `LoggerContext`
2549
+ #### `ThemeContext`
2467
2550
 
2468
2551
  ```typescript
2469
- const LoggerContext: Context<LoggerProvider | undefined>
2552
+ const ThemeContext: Context<ThemeProvider | undefined>
2470
2553
  ```
2471
2554
 
2472
2555
  #### `RouterContext`
@@ -2475,12 +2558,16 @@ const LoggerContext: Context<LoggerProvider | undefined>
2475
2558
  const RouterContext: Context<Router | undefined>
2476
2559
  ```
2477
2560
 
2478
- #### `StateContext`
2561
+ #### `I18nContext`
2479
2562
 
2480
- Internal contexts for molecule providers.
2563
+ ```typescript
2564
+ const I18nContext: Context<I18nProvider | undefined>
2565
+ ```
2566
+
2567
+ #### `HttpContext`
2481
2568
 
2482
2569
  ```typescript
2483
- const StateContext: Context<StateProvider | undefined>
2570
+ const HttpContext: Context<HttpClient | undefined>
2484
2571
  ```
2485
2572
 
2486
2573
  #### `StorageContext`
@@ -2489,10 +2576,10 @@ const StateContext: Context<StateProvider | undefined>
2489
2576
  const StorageContext: Context<StorageProvider | undefined>
2490
2577
  ```
2491
2578
 
2492
- #### `ThemeContext`
2579
+ #### `LoggerContext`
2493
2580
 
2494
2581
  ```typescript
2495
- const ThemeContext: Context<ThemeProvider | undefined>
2582
+ const LoggerContext: Context<LoggerProvider | undefined>
2496
2583
  ```
2497
2584
 
2498
2585
  ## Injection Notes