@molecule/app-solid 1.0.2 → 1.0.3

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