@molecule/app-bonds-default-react 2.0.0 → 3.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@ 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-10-24T08:39:00.105Z
6
+ Generated: 2026-10-31T10:35:03.226Z
7
7
  -->
8
8
 
9
9
  # @molecule/app-bonds-default-react
@@ -39,6 +39,17 @@ React fleet stack, replacing the byte-identical per-app files:
39
39
  argument is given. The profile is never inferred from `authConfig`, so an
40
40
  untyped call keeps the default contract.
41
41
 
42
+ **What this client already handles**
43
+
44
+ - `getAccessToken()` returns a stored token during restore; only 401/403 ends
45
+ the session, while network/5xx failures retain it.
46
+ - `tokenKey`/`storagePrefix`, `authScheme`, `mapAuthResponse`,
47
+ `currentUserEndpoint`, and `profileEndpoint`/`profileUpdateMethod` adapt the API.
48
+ - `logout()` settles local sign-out; `refresh()` uses a stored refresh token.
49
+
50
+ This factory adds no render gate: `AuthProvider` renders children immediately.
51
+ The HTTP-sync variants gate requests during restore, not rendering.
52
+
42
53
  > **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
43
54
  > It is written to be read by coding agents as much as by people, and is generated from this
44
55
  > package's source — edit `src/index.ts` JSDoc, not this file.
@@ -72,6 +83,24 @@ bootstrapApp({
72
83
  })
73
84
  ```
74
85
 
86
+ Adapt a nested token and `Token` header without another session store.
87
+
88
+ ```ts
89
+ import { createDefaultAuthClient } from '@molecule/app-bonds-default-react'
90
+
91
+ const { authClient, setupAuthDefault } = createDefaultAuthClient({
92
+ tokenKey: 'app.jwt',
93
+ authScheme: 'Token',
94
+ currentUserEndpoint: '/user',
95
+ profileEndpoint: '/user',
96
+ profileUpdateMethod: 'PUT',
97
+ mapAuthResponse: (data) => {
98
+ const { token, ...user } = (data as { user: { token: string; id: string } }).user
99
+ return { accessToken: token, user }
100
+ },
101
+ })
102
+ ```
103
+
75
104
  ## Type
76
105
 
77
106
  `feature`
@@ -113,7 +142,9 @@ this same wiring. Pass `stripApiPrefix: true` when the app uses
113
142
  when the API reads another scheme than `Bearer`: it is an option of THIS
114
143
  constructor (`createDefaultHttpClientWithAuthBearer({ authScheme: 'Token', … })`,
115
144
  or `createFetchClient({ baseURL, authScheme: 'Token' })` directly), never a
116
- property of the client it returns.
145
+ property of the client it returns. The client is built with the same scheme, so
146
+ a token the client also holds — the one a default auth bond's token sync gives
147
+ it — is sent with that scheme too, not as `Bearer`.
117
148
 
118
149
  ```typescript
119
150
  function createDefaultHttpClientWithAuthBearer(opts: {
@@ -121,26 +152,33 @@ function createDefaultHttpClientWithAuthBearer(opts: {
121
152
  withCredentials?: boolean
122
153
  stripApiPrefix?: boolean
123
154
  getToken: () => string | null | undefined
155
+ /**
156
+ * The scheme of the `Authorization` header the token from `getToken()` is sent
157
+ * with: `Bearer` (default), or what the API expects, e.g. `Token` for an API
158
+ * that reads `Authorization: Token <jwt>`. Pass it to this constructor — the
159
+ * same option `@molecule/app-http`'s client config calls `authScheme`, and not
160
+ * a property of the client that comes back.
161
+ */
124
162
  authScheme?: string
125
- }): { httpClient: HttpClient; setupHttpDefault: () => void }
163
+ }): {
164
+ httpClient: HttpClient
165
+ setupHttpDefault: () => void
166
+ }
126
167
  ```
127
168
 
128
169
  #### `createDefaultAuthClient(authConfig)`
129
170
 
130
171
  Builds the default JWT auth client + wires it into `@molecule/app-auth`.
131
-
132
- Replaces the 16-line per-app `bonds/auth-default.ts` that 93 fleet
133
- apps shipped byte-identically. Apps pass their own `authConfig`
134
- (which lives in `src/config.ts`).
172
+ Apps pass their own `authConfig` (which lives in `src/config.ts`).
135
173
 
136
174
  `TUser` is the profile the app's pages read, and may be any JSON object type —
137
- including a profile with NO `id` (`{ username, email, bio, image }`), exactly
138
- like the factory beneath this wrapper. Never add a synthetic `id` to satisfy a
139
- type: nothing in the client reads it, and the fabricated value then travels into
140
- storage, `getUser()` and every page. Omit the type parameter and the default is
141
- `UserProfile`, whose `id: string` stays required — the profile is never inferred
142
- from `authConfig` (no member of it, and not from an annotated config variable),
143
- so an untyped wrapper call keeps the default contract.
175
+ including a profile with NO `id` (`{ username, email, bio, image }`), as in the
176
+ factory it wraps. Never add a synthetic `id` to satisfy a type: nothing in the
177
+ client reads it, and the fabricated value then travels into storage, `getUser()`
178
+ and every page. Omit the type parameter and the default is `UserProfile`, whose
179
+ `id: string` stays required — the profile is never inferred from `authConfig`
180
+ (not even from an annotated config variable), so an untyped wrapper call keeps
181
+ the default contract.
144
182
 
145
183
  Type the config with the SAME type (`const authConfig: AuthClientConfig<MyUser> = { … }`)
146
184
  so its `mapAuthResponse` is checked against `MyUser`, and name that type at the
@@ -150,12 +188,19 @@ page that reads `undefined`. An annotated config alone does not supply the type
150
188
  argument — that is a 1.8 caller shape this major changes (see
151
189
  `AuthClientConfig`'s migration note in `@molecule/app-auth`).
152
190
 
153
- `TRegister` is the app's own registration fields (`{ username: string }` for a
191
+ `TRegister` is the app's own extra registration fields (for example
192
+ `{ username: string }`), passed on to `@molecule/app-auth`'s factory so
193
+ `authClient.register({ username, email, password })` type-checks with no cast.
154
194
 
155
195
  _(description truncated — read the full text in `node_modules/@molecule/app-bonds-default-react/dist/auth.d.ts`.)_
156
196
 
157
197
  ```typescript
158
- function createDefaultAuthClient(authConfig: NoInfer<AuthClientConfigOptions<TUser>>): {
198
+ function createDefaultAuthClient<
199
+ TUser extends AuthProfileConstraint<TUser> = UserProfile,
200
+ TRegister extends RegisterExtraShape<TRegister> = Record<never, never>,
201
+ >(
202
+ authConfig: NoInfer<AuthClientConfigOptions<TUser>>,
203
+ ): {
159
204
  authClient: AuthClient<TUser, TRegister>
160
205
  setupAuthDefault: () => void
161
206
  }
@@ -164,28 +209,35 @@ function createDefaultAuthClient(authConfig: NoInfer<AuthClientConfigOptions<TUs
164
209
  #### `createDefaultAuthClientWithHttpSync(authConfig)`
165
210
 
166
211
  Variant of `createDefaultAuthClient` that also keeps the bonded
167
- `@molecule/app-http` client's bearer token in sync with auth events
168
- (login / register / refresh / logout). Required by apps whose http
169
- client must carry the JWT on every request — without this wiring,
170
- authed endpoints return 401 after page reloads or token refresh.
212
+ `@molecule/app-http` client's bearer token in sync with the auth client's session.
213
+ Required by apps whose http client must carry the JWT on every request — without
214
+ this wiring, authed endpoints return 401 after page reloads or token refresh.
215
+
216
+ The sync is a LIVE read: `@molecule/app-http`'s `setAuthTokenSource` registers the auth
217
+ client's token, and every client the app bonds — one bonded after this setup too (the
218
+ scaffold wires auth BEFORE http, so a token copied into the client present at setup was
219
+ never sent) — reads it on each request. A session adopted with no
220
+ auth event (`useAuth().setSession()`, an OAuth callback's `setAccessToken()`, the same
221
+ profile under a new token) is therefore sent by the next request, not the previous
222
+ account's bearer. A transport without `setAuthTokenResolver` is followed through a request
223
+ interceptor (see `setAuthTokenSource` for which request first carries the change), and
224
+ auth events still push the token to it.
225
+
226
+ A cookie session (no body token) resolves to `null`, so the request carries NO
227
+ `Authorization` header — a kept bearer would answer as the PRIOR session.
228
+ Requests also wait for the session restore, so a page that fetches viewer data on mount
229
+ cannot race it (see {@link registerAuthGate}).
171
230
 
172
231
  The profile type is `createDefaultAuthClient`'s: a JSON object type of named
173
232
  fields (see `AuthProfileShape`), including an app profile with no `id`.
174
233
 
175
- Hydrates the HTTP client's token from the persisted auth state
176
- on setup, then listens for auth events to keep them aligned, and holds
177
- requests until the session restore settles so a page effect that fetches
178
- viewer-dependent data on mount cannot race it (see {@link registerAuthGate}).
179
-
180
- The hydrated token is delivered through `@molecule/app-http`'s token source, not
181
- through a client read at setup: the scaffold wires auth BEFORE http, so a client
182
- read here is the unbonded fallback and the restored session's token would land on a
183
- client nothing sends through (xr-molecule-flash-m156 — a reload sent every request
184
- with no `Authorization` header). The source is applied to the client WHENEVER it is
185
- bonded, so setup order no longer decides whether the first request is authorized.
186
-
187
234
  ```typescript
188
- function createDefaultAuthClientWithHttpSync(authConfig: NoInfer<AuthClientConfigOptions<TUser>>): {
235
+ function createDefaultAuthClientWithHttpSync<
236
+ TUser extends AuthProfileConstraint<TUser> = UserProfile,
237
+ TRegister extends RegisterExtraShape<TRegister> = Record<never, never>,
238
+ >(
239
+ authConfig: NoInfer<AuthClientConfigOptions<TUser>>,
240
+ ): {
189
241
  authClient: AuthClient<TUser, TRegister>
190
242
  setupAuthDefault: () => void
191
243
  }
@@ -196,15 +248,18 @@ function createDefaultAuthClientWithHttpSync(authConfig: NoInfer<AuthClientConfi
196
248
  Most aggressive variant — bonds a fetch-based HTTP client with the
197
249
  given `baseURL` (so molecule pkg `useGet('/path')` calls hit
198
250
  `${baseURL}/path` instead of the SPA's catch-all route), AND keeps
199
- its bearer token in sync with auth events.
251
+ its bearer token in sync with the auth client's session, read on every
252
+ request: a session adopted with no auth event (`setSession()`,
253
+ `setAccessToken()`) is sent by the next request. The token uses the auth
254
+ config's `authScheme` (default `Bearer`); a client bonded after this setup
255
+ gets the same source and auth events.
200
256
 
201
257
  The auth client restores a stored token AND user SYNCHRONOUSLY, so the first
202
258
  render is the signed-in UI — do not gate a protected page (or a provider of
203
259
  yours) on a current-user request. This bond registers `whenRestored()` as the
204
260
  HTTP gate, so requests still wait for the background restore/verification to
205
261
  settle; only `useAuth().status === 'loading'` means "no decision yet"
206
- (xr-molecule-flash-m177: a page that waited on its own `/me` paid a round trip
207
- on every navigation).
262
+ (a page that waits on its own `/me` pays a round trip on every navigation).
208
263
 
209
264
  Used by apps where molecule packages render pricing / billing /
210
265
  other authed JSON-fetching screens that need both behaviors.
@@ -217,10 +272,16 @@ The profile type is `createDefaultAuthClient`'s: a JSON object type of named
217
272
  fields (see `AuthProfileShape`), including an app profile with no `id`.
218
273
 
219
274
  ```typescript
220
- function createDefaultAuthClientWithFetchClient(
275
+ function createDefaultAuthClientWithFetchClient<
276
+ TUser extends AuthProfileConstraint<TUser> = UserProfile,
277
+ TRegister extends RegisterExtraShape<TRegister> = Record<never, never>,
278
+ >(
221
279
  authConfig: NoInfer<AuthClientConfigOptions<TUser>>,
222
280
  fetchClientOptions: { baseURL: string; withCredentials?: boolean },
223
- ): { authClient: AuthClient<TUser, TRegister>; setupAuthDefault: () => void }
281
+ ): {
282
+ authClient: AuthClient<TUser, TRegister>
283
+ setupAuthDefault: () => void
284
+ }
224
285
  ```
225
286
 
226
287
  #### `bootstrapApp(opts)`
@@ -246,7 +307,7 @@ function bootstrapApp(opts: {
246
307
  Returns (and lazily constructs) the shared default CSS-variables theme provider.
247
308
 
248
309
  ```typescript
249
- function getDefaultThemeProvider(): ThemeProvider
310
+ function getDefaultThemeProvider(): ReturnType<typeof createCSSVariablesThemeProvider>
250
311
  ```
251
312
 
252
313
  #### `setupAppFontsArimo()`
@@ -282,7 +343,7 @@ WITHOUT this, `createStore()` throws
282
343
  `@molecule/app-state: No provider set. Call setProvider() first` — nothing
283
344
  else in a scaffolded app wires the `state` bond, so the documented
284
345
  `createStore()` + `useStore()` pattern failed at the first render and every
285
- page came up blank while `tsc` passed (X1 flash-m65).
346
+ page came up blank while `tsc` passed.
286
347
 
287
348
  ```typescript
288
349
  function setupAppStateSimple(): void
@@ -343,7 +404,7 @@ function setupAllDefaultBonds(): void
343
404
 
344
405
  Peer dependencies:
345
406
 
346
- - `@molecule/app-auth` ^2.0.0
407
+ - `@molecule/app-auth` ^3.0.0
347
408
  - `@molecule/app-charts` ^1.0.1
348
409
  - `@molecule/app-charts-chartjs` ^1.0.1
349
410
  - `@molecule/app-client-search` ^1.0.0
@@ -356,7 +417,7 @@ Peer dependencies:
356
417
  - `@molecule/app-drag-drop-dndkit` ^1.0.1
357
418
  - `@molecule/app-fonts` ^1.0.1
358
419
  - `@molecule/app-fonts-arimo` ^1.0.1
359
- - `@molecule/app-http` ^1.0.1
420
+ - `@molecule/app-http` ^1.5.0
360
421
  - `@molecule/app-icons` ^1.0.1
361
422
  - `@molecule/app-icons-molecule` ^1.0.1
362
423
  - `@molecule/app-keyboard-shortcuts` ^1.0.1
package/dist/auth.d.ts CHANGED
@@ -30,7 +30,9 @@ export declare function createDefaultHttpClient(baseURL: string): {
30
30
  * when the API reads another scheme than `Bearer`: it is an option of THIS
31
31
  * constructor (`createDefaultHttpClientWithAuthBearer({ authScheme: 'Token', … })`,
32
32
  * or `createFetchClient({ baseURL, authScheme: 'Token' })` directly), never a
33
- * property of the client it returns.
33
+ * property of the client it returns. The client is built with the same scheme, so
34
+ * a token the client also holds — the one a default auth bond's token sync gives
35
+ * it — is sent with that scheme too, not as `Bearer`.
34
36
  */
35
37
  export declare function createDefaultHttpClientWithAuthBearer(opts: {
36
38
  baseURL: string;
@@ -51,19 +53,16 @@ export declare function createDefaultHttpClientWithAuthBearer(opts: {
51
53
  };
52
54
  /**
53
55
  * Builds the default JWT auth client + wires it into `@molecule/app-auth`.
54
- *
55
- * Replaces the 16-line per-app `bonds/auth-default.ts` that 93 fleet
56
- * apps shipped byte-identically. Apps pass their own `authConfig`
57
- * (which lives in `src/config.ts`).
56
+ * Apps pass their own `authConfig` (which lives in `src/config.ts`).
58
57
  *
59
58
  * `TUser` is the profile the app's pages read, and may be any JSON object type —
60
- * including a profile with NO `id` (`{ username, email, bio, image }`), exactly
61
- * like the factory beneath this wrapper. Never add a synthetic `id` to satisfy a
62
- * type: nothing in the client reads it, and the fabricated value then travels into
63
- * storage, `getUser()` and every page. Omit the type parameter and the default is
64
- * `UserProfile`, whose `id: string` stays required — the profile is never inferred
65
- * from `authConfig` (no member of it, and not from an annotated config variable),
66
- * so an untyped wrapper call keeps the default contract.
59
+ * including a profile with NO `id` (`{ username, email, bio, image }`), as in the
60
+ * factory it wraps. Never add a synthetic `id` to satisfy a type: nothing in the
61
+ * client reads it, and the fabricated value then travels into storage, `getUser()`
62
+ * and every page. Omit the type parameter and the default is `UserProfile`, whose
63
+ * `id: string` stays required — the profile is never inferred from `authConfig`
64
+ * (not even from an annotated config variable), so an untyped wrapper call keeps
65
+ * the default contract.
67
66
  *
68
67
  * Type the config with the SAME type (`const authConfig: AuthClientConfig<MyUser> = { … }`)
69
68
  * so its `mapAuthResponse` is checked against `MyUser`, and name that type at the
@@ -73,9 +72,10 @@ export declare function createDefaultHttpClientWithAuthBearer(opts: {
73
72
  * argument — that is a 1.8 caller shape this major changes (see
74
73
  * `AuthClientConfig`'s migration note in `@molecule/app-auth`).
75
74
  *
76
- * `TRegister` is the app's own registration fields (`{ username: string }` for a
77
- * RealWorld-shaped API), passed on to `@molecule/app-auth`'s factory so
75
+ * `TRegister` is the app's own extra registration fields (for example
76
+ * `{ username: string }`), passed on to `@molecule/app-auth`'s factory so
78
77
  * `authClient.register({ username, email, password })` type-checks with no cast.
78
+ * See the module guidance for the lifecycle and API adaptations already included.
79
79
  *
80
80
  * @example
81
81
  * ```ts
@@ -93,25 +93,27 @@ export declare function createDefaultAuthClient<TUser extends AuthProfileConstra
93
93
  };
94
94
  /**
95
95
  * Variant of `createDefaultAuthClient` that also keeps the bonded
96
- * `@molecule/app-http` client's bearer token in sync with auth events
97
- * (login / register / refresh / logout). Required by apps whose http
98
- * client must carry the JWT on every request — without this wiring,
99
- * authed endpoints return 401 after page reloads or token refresh.
96
+ * `@molecule/app-http` client's bearer token in sync with the auth client's session.
97
+ * Required by apps whose http client must carry the JWT on every request — without
98
+ * this wiring, authed endpoints return 401 after page reloads or token refresh.
99
+ *
100
+ * The sync is a LIVE read: `@molecule/app-http`'s `setAuthTokenSource` registers the auth
101
+ * client's token, and every client the app bonds — one bonded after this setup too (the
102
+ * scaffold wires auth BEFORE http, so a token copied into the client present at setup was
103
+ * never sent) — reads it on each request. A session adopted with no
104
+ * auth event (`useAuth().setSession()`, an OAuth callback's `setAccessToken()`, the same
105
+ * profile under a new token) is therefore sent by the next request, not the previous
106
+ * account's bearer. A transport without `setAuthTokenResolver` is followed through a request
107
+ * interceptor (see `setAuthTokenSource` for which request first carries the change), and
108
+ * auth events still push the token to it.
109
+ *
110
+ * A cookie session (no body token) resolves to `null`, so the request carries NO
111
+ * `Authorization` header — a kept bearer would answer as the PRIOR session.
112
+ * Requests also wait for the session restore, so a page that fetches viewer data on mount
113
+ * cannot race it (see {@link registerAuthGate}).
100
114
  *
101
115
  * The profile type is `createDefaultAuthClient`'s: a JSON object type of named
102
116
  * fields (see `AuthProfileShape`), including an app profile with no `id`.
103
- *
104
- * Hydrates the HTTP client's token from the persisted auth state
105
- * on setup, then listens for auth events to keep them aligned, and holds
106
- * requests until the session restore settles so a page effect that fetches
107
- * viewer-dependent data on mount cannot race it (see {@link registerAuthGate}).
108
- *
109
- * The hydrated token is delivered through `@molecule/app-http`'s token source, not
110
- * through a client read at setup: the scaffold wires auth BEFORE http, so a client
111
- * read here is the unbonded fallback and the restored session's token would land on a
112
- * client nothing sends through (xr-molecule-flash-m156 — a reload sent every request
113
- * with no `Authorization` header). The source is applied to the client WHENEVER it is
114
- * bonded, so setup order no longer decides whether the first request is authorized.
115
117
  */
116
118
  export declare function createDefaultAuthClientWithHttpSync<TUser extends AuthProfileConstraint<TUser> = UserProfile, TRegister extends RegisterExtraShape<TRegister> = Record<never, never>>(authConfig: NoInfer<AuthClientConfigOptions<TUser>>): {
117
119
  authClient: AuthClient<TUser, TRegister>;
@@ -121,15 +123,18 @@ export declare function createDefaultAuthClientWithHttpSync<TUser extends AuthPr
121
123
  * Most aggressive variant — bonds a fetch-based HTTP client with the
122
124
  * given `baseURL` (so molecule pkg `useGet('/path')` calls hit
123
125
  * `${baseURL}/path` instead of the SPA's catch-all route), AND keeps
124
- * its bearer token in sync with auth events.
126
+ * its bearer token in sync with the auth client's session, read on every
127
+ * request: a session adopted with no auth event (`setSession()`,
128
+ * `setAccessToken()`) is sent by the next request. The token uses the auth
129
+ * config's `authScheme` (default `Bearer`); a client bonded after this setup
130
+ * gets the same source and auth events.
125
131
  *
126
132
  * The auth client restores a stored token AND user SYNCHRONOUSLY, so the first
127
133
  * render is the signed-in UI — do not gate a protected page (or a provider of
128
134
  * yours) on a current-user request. This bond registers `whenRestored()` as the
129
135
  * HTTP gate, so requests still wait for the background restore/verification to
130
136
  * settle; only `useAuth().status === 'loading'` means "no decision yet"
131
- * (xr-molecule-flash-m177: a page that waited on its own `/me` paid a round trip
132
- * on every navigation).
137
+ * (a page that waits on its own `/me` pays a round trip on every navigation).
133
138
  *
134
139
  * Used by apps where molecule packages render pricing / billing /
135
140
  * other authed JSON-fetching screens that need both behaviors.
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,uBAAuB,EAEvB,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACZ,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAuCpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACxD,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAMA;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qCAAqC,CAAC,IAAI,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACzC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG;IACF,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAoBA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,SAAS,qBAAqB,CAAC,KAAK,CAAC,GAAG,WAAW,EACxD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,GAClD;IACD,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAMA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,SAAS,qBAAqB,CAAC,KAAK,CAAC,GAAG,WAAW,EACxD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,GAClD;IACD,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CA4BA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sCAAsC,CACpD,KAAK,SAAS,qBAAqB,CAAC,KAAK,CAAC,GAAG,WAAW,EACxD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,EACnD,kBAAkB,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACjE;IACD,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CA2BA"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,uBAAuB,EAEvB,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,EACZ,MAAM,oBAAoB,CAAA;AAE3B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAsCpD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG;IACxD,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAMA;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qCAAqC,CAAC,IAAI,EAAE;IAC1D,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,EAAE,MAAM,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IACzC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,GAAG;IACF,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAuBA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,SAAS,qBAAqB,CAAC,KAAK,CAAC,GAAG,WAAW,EACxD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,GAClD;IACD,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAMA;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mCAAmC,CACjD,KAAK,SAAS,qBAAqB,CAAC,KAAK,CAAC,GAAG,WAAW,EACxD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,GAClD;IACD,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAkCA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,sCAAsC,CACpD,KAAK,SAAS,qBAAqB,CAAC,KAAK,CAAC,GAAG,WAAW,EACxD,SAAS,SAAS,kBAAkB,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAEtE,UAAU,EAAE,OAAO,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,EACnD,kBAAkB,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACjE;IACD,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IACxC,gBAAgB,EAAE,MAAM,IAAI,CAAA;CAC7B,CAmCA"}
package/dist/auth.js CHANGED
@@ -3,13 +3,12 @@ import { createFetchClient, getClient as getHttpClient, setAuthGate, setAuthToke
3
3
  /**
4
4
  * Holds every HTTP request until this auth client's session restore has settled.
5
5
  *
6
- * Without it a page effect that fires on mount (fetching a profile's `following`
7
- * flag, a feed, a `favorited` state) sends its request before `initialize()` has
6
+ * Without it a page effect that fires on mount (fetching account settings, a
7
+ * dashboard, or a saved-item state) sends its request before `initialize()` has
8
8
  * restored the session, so it leaves with no `Authorization` header and the server
9
9
  * answers for an anonymous viewer. Localhost usually hides it — the restore wins
10
- * the race against the first effect there — and the deployed URL exposes it, which
11
- * is how X1 xr-molecule-flash-m95 spent ~25 min treating a "Follow" button on a
12
- * followed user as database leftovers.
10
+ * the race against the first effect there — and the deployed URL exposes it, where a
11
+ * saved item reads as unsaved because the request lacked its session.
13
12
  *
14
13
  * `whenRestored()` resolves immediately when no restore is in flight, so a request
15
14
  * made after boot never waits at all; it holds only while the restore is actually
@@ -62,13 +61,18 @@ export function createDefaultHttpClient(baseURL) {
62
61
  * when the API reads another scheme than `Bearer`: it is an option of THIS
63
62
  * constructor (`createDefaultHttpClientWithAuthBearer({ authScheme: 'Token', … })`,
64
63
  * or `createFetchClient({ baseURL, authScheme: 'Token' })` directly), never a
65
- * property of the client it returns.
64
+ * property of the client it returns. The client is built with the same scheme, so
65
+ * a token the client also holds — the one a default auth bond's token sync gives
66
+ * it — is sent with that scheme too, not as `Bearer`.
66
67
  */
67
68
  export function createDefaultHttpClientWithAuthBearer(opts) {
68
69
  const authScheme = opts.authScheme ?? 'Bearer';
69
70
  const httpClient = createFetchClient({
70
71
  baseURL: opts.baseURL,
71
72
  withCredentials: opts.withCredentials,
73
+ // The client's own token (a default auth bond's token sync) overrides the interceptor's
74
+ // header, so it must carry the same scheme.
75
+ authScheme,
72
76
  });
73
77
  httpClient.addRequestInterceptor((config) => {
74
78
  if (opts.stripApiPrefix && typeof config.url === 'string' && config.url.startsWith('/api/')) {
@@ -87,19 +91,16 @@ export function createDefaultHttpClientWithAuthBearer(opts) {
87
91
  }
88
92
  /**
89
93
  * Builds the default JWT auth client + wires it into `@molecule/app-auth`.
90
- *
91
- * Replaces the 16-line per-app `bonds/auth-default.ts` that 93 fleet
92
- * apps shipped byte-identically. Apps pass their own `authConfig`
93
- * (which lives in `src/config.ts`).
94
+ * Apps pass their own `authConfig` (which lives in `src/config.ts`).
94
95
  *
95
96
  * `TUser` is the profile the app's pages read, and may be any JSON object type —
96
- * including a profile with NO `id` (`{ username, email, bio, image }`), exactly
97
- * like the factory beneath this wrapper. Never add a synthetic `id` to satisfy a
98
- * type: nothing in the client reads it, and the fabricated value then travels into
99
- * storage, `getUser()` and every page. Omit the type parameter and the default is
100
- * `UserProfile`, whose `id: string` stays required — the profile is never inferred
101
- * from `authConfig` (no member of it, and not from an annotated config variable),
102
- * so an untyped wrapper call keeps the default contract.
97
+ * including a profile with NO `id` (`{ username, email, bio, image }`), as in the
98
+ * factory it wraps. Never add a synthetic `id` to satisfy a type: nothing in the
99
+ * client reads it, and the fabricated value then travels into storage, `getUser()`
100
+ * and every page. Omit the type parameter and the default is `UserProfile`, whose
101
+ * `id: string` stays required — the profile is never inferred from `authConfig`
102
+ * (not even from an annotated config variable), so an untyped wrapper call keeps
103
+ * the default contract.
103
104
  *
104
105
  * Type the config with the SAME type (`const authConfig: AuthClientConfig<MyUser> = { … }`)
105
106
  * so its `mapAuthResponse` is checked against `MyUser`, and name that type at the
@@ -109,9 +110,10 @@ export function createDefaultHttpClientWithAuthBearer(opts) {
109
110
  * argument — that is a 1.8 caller shape this major changes (see
110
111
  * `AuthClientConfig`'s migration note in `@molecule/app-auth`).
111
112
  *
112
- * `TRegister` is the app's own registration fields (`{ username: string }` for a
113
- * RealWorld-shaped API), passed on to `@molecule/app-auth`'s factory so
113
+ * `TRegister` is the app's own extra registration fields (for example
114
+ * `{ username: string }`), passed on to `@molecule/app-auth`'s factory so
114
115
  * `authClient.register({ username, email, password })` type-checks with no cast.
116
+ * See the module guidance for the lifecycle and API adaptations already included.
115
117
  *
116
118
  * @example
117
119
  * ```ts
@@ -132,25 +134,27 @@ export function createDefaultAuthClient(authConfig) {
132
134
  }
133
135
  /**
134
136
  * Variant of `createDefaultAuthClient` that also keeps the bonded
135
- * `@molecule/app-http` client's bearer token in sync with auth events
136
- * (login / register / refresh / logout). Required by apps whose http
137
- * client must carry the JWT on every request — without this wiring,
138
- * authed endpoints return 401 after page reloads or token refresh.
137
+ * `@molecule/app-http` client's bearer token in sync with the auth client's session.
138
+ * Required by apps whose http client must carry the JWT on every request — without
139
+ * this wiring, authed endpoints return 401 after page reloads or token refresh.
140
+ *
141
+ * The sync is a LIVE read: `@molecule/app-http`'s `setAuthTokenSource` registers the auth
142
+ * client's token, and every client the app bonds — one bonded after this setup too (the
143
+ * scaffold wires auth BEFORE http, so a token copied into the client present at setup was
144
+ * never sent) — reads it on each request. A session adopted with no
145
+ * auth event (`useAuth().setSession()`, an OAuth callback's `setAccessToken()`, the same
146
+ * profile under a new token) is therefore sent by the next request, not the previous
147
+ * account's bearer. A transport without `setAuthTokenResolver` is followed through a request
148
+ * interceptor (see `setAuthTokenSource` for which request first carries the change), and
149
+ * auth events still push the token to it.
150
+ *
151
+ * A cookie session (no body token) resolves to `null`, so the request carries NO
152
+ * `Authorization` header — a kept bearer would answer as the PRIOR session.
153
+ * Requests also wait for the session restore, so a page that fetches viewer data on mount
154
+ * cannot race it (see {@link registerAuthGate}).
139
155
  *
140
156
  * The profile type is `createDefaultAuthClient`'s: a JSON object type of named
141
157
  * fields (see `AuthProfileShape`), including an app profile with no `id`.
142
- *
143
- * Hydrates the HTTP client's token from the persisted auth state
144
- * on setup, then listens for auth events to keep them aligned, and holds
145
- * requests until the session restore settles so a page effect that fetches
146
- * viewer-dependent data on mount cannot race it (see {@link registerAuthGate}).
147
- *
148
- * The hydrated token is delivered through `@molecule/app-http`'s token source, not
149
- * through a client read at setup: the scaffold wires auth BEFORE http, so a client
150
- * read here is the unbonded fallback and the restored session's token would land on a
151
- * client nothing sends through (xr-molecule-flash-m156 — a reload sent every request
152
- * with no `Authorization` header). The source is applied to the client WHENEVER it is
153
- * bonded, so setup order no longer decides whether the first request is authorized.
154
158
  */
155
159
  export function createDefaultAuthClientWithHttpSync(authConfig) {
156
160
  const authClient = createJWTAuthClient(authConfig);
@@ -164,7 +168,9 @@ export function createDefaultAuthClientWithHttpSync(authConfig) {
164
168
  // Resolve the HTTP client per sync, never once here. `setClient` runs this
165
169
  // source, so the token reaches the client the scaffold bonds later as well as
166
170
  // one already bonded; a client kept from this moment would be the throwaway
167
- // fallback the later `setHttpDefault()` replaces.
171
+ // fallback the later `setHttpDefault()` replaces. The client reads the source
172
+ // itself on every request, so a session adopted by `setSession()` (no auth
173
+ // event) or re-adopted for the same profile (no state change) is sent at once.
168
174
  setHttpAuthTokenSource(() => authClient.getAccessToken());
169
175
  authClient.addEventListener((event) => {
170
176
  if (event.type === 'login' || event.type === 'register' || event.type === 'refresh') {
@@ -173,6 +179,10 @@ export function createDefaultAuthClientWithHttpSync(authConfig) {
173
179
  // keeping a previously-set bearer here would pin the http client to the
174
180
  // PRIOR session (e.g. a guest's) — the server prefers the Authorization
175
181
  // header over the fresh cookie, so every request 401s as the old user.
182
+ //
183
+ // A client that implements `setAuthTokenResolver` already resolves the source
184
+ // per request; this push is what carries the same change to a transport that
185
+ // does not (and keeps `getAuthToken()` current there).
176
186
  getHttpClient().setAuthToken(authClient.getAccessToken());
177
187
  }
178
188
  else if (event.type === 'logout') {
@@ -186,15 +196,18 @@ export function createDefaultAuthClientWithHttpSync(authConfig) {
186
196
  * Most aggressive variant — bonds a fetch-based HTTP client with the
187
197
  * given `baseURL` (so molecule pkg `useGet('/path')` calls hit
188
198
  * `${baseURL}/path` instead of the SPA's catch-all route), AND keeps
189
- * its bearer token in sync with auth events.
199
+ * its bearer token in sync with the auth client's session, read on every
200
+ * request: a session adopted with no auth event (`setSession()`,
201
+ * `setAccessToken()`) is sent by the next request. The token uses the auth
202
+ * config's `authScheme` (default `Bearer`); a client bonded after this setup
203
+ * gets the same source and auth events.
190
204
  *
191
205
  * The auth client restores a stored token AND user SYNCHRONOUSLY, so the first
192
206
  * render is the signed-in UI — do not gate a protected page (or a provider of
193
207
  * yours) on a current-user request. This bond registers `whenRestored()` as the
194
208
  * HTTP gate, so requests still wait for the background restore/verification to
195
209
  * settle; only `useAuth().status === 'loading'` means "no decision yet"
196
- * (xr-molecule-flash-m177: a page that waited on its own `/me` paid a round trip
197
- * on every navigation).
210
+ * (a page that waits on its own `/me` pays a round trip on every navigation).
198
211
  *
199
212
  * Used by apps where molecule packages render pricing / billing /
200
213
  * other authed JSON-fetching screens that need both behaviors.
@@ -214,22 +227,30 @@ export function createDefaultAuthClientWithFetchClient(authConfig, fetchClientOp
214
227
  const httpClient = createFetchClient({
215
228
  baseURL: fetchClientOptions.baseURL,
216
229
  withCredentials: fetchClientOptions.withCredentials ?? true,
230
+ // The scheme the auth config names for this token (`Authorization: Token <jwt>`).
231
+ authScheme: authConfig.authScheme,
217
232
  });
218
233
  // Registered BEFORE the bond: `setHttpClient` applies the restored session's
219
234
  // token, and the same source reaches any client an app bonds later instead of
220
- // this one (xr-molecule-flash-m156 — a client captured at setup cannot).
235
+ // this one. A client captured at setup cannot track later replacements. The
236
+ // client resolves the source on every request, so a session adopted by
237
+ // `setSession()` or `setAccessToken()` after this point is sent immediately.
221
238
  setHttpAuthTokenSource(() => authClient.getAccessToken());
222
239
  setHttpClient(httpClient);
223
240
  setClient(authClient);
224
241
  registerAuthGate(authClient);
225
242
  authClient.addEventListener((event) => {
243
+ // The client bonded NOW, resolved per event: an app that bonds its own client after
244
+ // this setup sends through that one, never through the client created above.
226
245
  if (event.type === 'login' || event.type === 'register' || event.type === 'refresh') {
227
246
  // Mirror the token exactly, including null — see the identical note in
228
247
  // createDefaultAuthClientWithHttpSync (stale bearer = stuck prior session).
229
- httpClient.setAuthToken(authClient.getAccessToken());
248
+ // The per-request read of the source above is the guarantee; this push keeps
249
+ // `getAuthToken()` current on a transport without `setAuthTokenResolver`.
250
+ getHttpClient().setAuthToken(authClient.getAccessToken());
230
251
  }
231
252
  else if (event.type === 'logout') {
232
- httpClient.setAuthToken(null);
253
+ getHttpClient().setAuthToken(null);
233
254
  }
234
255
  });
235
256
  },
package/dist/index.d.ts CHANGED
@@ -30,6 +30,16 @@
30
30
  * argument is given. The profile is never inferred from `authConfig`, so an
31
31
  * untyped call keeps the default contract.
32
32
  *
33
+ * **What this client already handles**
34
+ * - `getAccessToken()` returns a stored token during restore; only 401/403 ends
35
+ * the session, while network/5xx failures retain it.
36
+ * - `tokenKey`/`storagePrefix`, `authScheme`, `mapAuthResponse`,
37
+ * `currentUserEndpoint`, and `profileEndpoint`/`profileUpdateMethod` adapt the API.
38
+ * - `logout()` settles local sign-out; `refresh()` uses a stored refresh token.
39
+ *
40
+ * This factory adds no render gate: `AuthProvider` renders children immediately.
41
+ * The HTTP-sync variants gate requests during restore, not rendering.
42
+ *
33
43
  * @example
34
44
  * ```tsx
35
45
  * // src/main.tsx
@@ -59,6 +69,23 @@
59
69
  * })
60
70
  * ```
61
71
  *
72
+ * @example Adapt a nested token and `Token` header without another session store.
73
+ * ```ts
74
+ * import { createDefaultAuthClient } from '@molecule/app-bonds-default-react'
75
+ *
76
+ * const { authClient, setupAuthDefault } = createDefaultAuthClient({
77
+ * tokenKey: 'app.jwt',
78
+ * authScheme: 'Token',
79
+ * currentUserEndpoint: '/user',
80
+ * profileEndpoint: '/user',
81
+ * profileUpdateMethod: 'PUT',
82
+ * mapAuthResponse: (data) => {
83
+ * const { token, ...user } = (data as { user: { token: string; id: string } }).user
84
+ * return { accessToken: token, user }
85
+ * },
86
+ * })
87
+ * ```
88
+ *
62
89
  * @remarks
63
90
  * - **Optional setups are NOT exported from the package root.** Import each from
64
91
  * its own subpath — `@molecule/app-bonds-default-react/optional/maps-leaflet.js`,
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2FG;AAEH,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsHG;AAEH,cAAc,WAAW,CAAA;AACzB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,YAAY,CAAA"}
package/dist/index.js CHANGED
@@ -30,6 +30,16 @@
30
30
  * argument is given. The profile is never inferred from `authConfig`, so an
31
31
  * untyped call keeps the default contract.
32
32
  *
33
+ * **What this client already handles**
34
+ * - `getAccessToken()` returns a stored token during restore; only 401/403 ends
35
+ * the session, while network/5xx failures retain it.
36
+ * - `tokenKey`/`storagePrefix`, `authScheme`, `mapAuthResponse`,
37
+ * `currentUserEndpoint`, and `profileEndpoint`/`profileUpdateMethod` adapt the API.
38
+ * - `logout()` settles local sign-out; `refresh()` uses a stored refresh token.
39
+ *
40
+ * This factory adds no render gate: `AuthProvider` renders children immediately.
41
+ * The HTTP-sync variants gate requests during restore, not rendering.
42
+ *
33
43
  * @example
34
44
  * ```tsx
35
45
  * // src/main.tsx
@@ -59,6 +69,23 @@
59
69
  * })
60
70
  * ```
61
71
  *
72
+ * @example Adapt a nested token and `Token` header without another session store.
73
+ * ```ts
74
+ * import { createDefaultAuthClient } from '@molecule/app-bonds-default-react'
75
+ *
76
+ * const { authClient, setupAuthDefault } = createDefaultAuthClient({
77
+ * tokenKey: 'app.jwt',
78
+ * authScheme: 'Token',
79
+ * currentUserEndpoint: '/user',
80
+ * profileEndpoint: '/user',
81
+ * profileUpdateMethod: 'PUT',
82
+ * mapAuthResponse: (data) => {
83
+ * const { token, ...user } = (data as { user: { token: string; id: string } }).user
84
+ * return { accessToken: token, user }
85
+ * },
86
+ * })
87
+ * ```
88
+ *
62
89
  * @remarks
63
90
  * - **Optional setups are NOT exported from the package root.** Import each from
64
91
  * its own subpath — `@molecule/app-bonds-default-react/optional/maps-leaflet.js`,
package/dist/setup.d.ts CHANGED
@@ -29,7 +29,7 @@ export declare function setupAppRoutingReactRouter(): void;
29
29
  * `@molecule/app-state: No provider set. Call setProvider() first` — nothing
30
30
  * else in a scaffolded app wires the `state` bond, so the documented
31
31
  * `createStore()` + `useStore()` pattern failed at the first render and every
32
- * page came up blank while `tsc` passed (X1 flash-m65).
32
+ * page came up blank while `tsc` passed.
33
33
  */
34
34
  export declare function setupAppStateSimple(): void;
35
35
  /** Wires `@molecule/app-storage-localstorage` to `@molecule/app-storage`. */
package/dist/setup.js CHANGED
@@ -68,7 +68,7 @@ export function setupAppRoutingReactRouter() {
68
68
  * `@molecule/app-state: No provider set. Call setProvider() first` — nothing
69
69
  * else in a scaffolded app wires the `state` bond, so the documented
70
70
  * `createStore()` + `useStore()` pattern failed at the first render and every
71
- * page came up blank while `tsc` passed (X1 flash-m65).
71
+ * page came up blank while `tsc` passed.
72
72
  */
73
73
  export function setupAppStateSimple() {
74
74
  setState(defaultStateProvider);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/app-bonds-default-react",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
4
4
  "description": "Default app-side bond wirings for React+Tailwind+react-router+localStorage+Arimo font+molecule icons. 5 setup functions consolidating 665 byte-identical per-app bond wiring files across the fleet.",
5
5
  "homepage": "https://www.molecule.dev/packages/app-bonds-default-react",
6
6
  "type": "module",
@@ -9,7 +9,8 @@
9
9
  "scripts": {
10
10
  "build": "tsc",
11
11
  "test": "vitest run",
12
- "test:watch": "vitest"
12
+ "test:watch": "vitest",
13
+ "typecheck:tests": "tsc -p tsconfig.tests.json"
13
14
  },
14
15
  "exports": {
15
16
  ".": {
@@ -38,37 +39,37 @@
38
39
  "directory": "packages/app/infrastructure/bonds-default-react"
39
40
  },
40
41
  "devDependencies": {
41
- "@molecule/app-auth": "2.0.0",
42
+ "@molecule/app-auth": "3.2.0",
42
43
  "@molecule/app-charts-chartjs": "1.0.3",
43
- "@molecule/app-client-search": "1.0.3",
44
+ "@molecule/app-client-search": "1.0.4",
44
45
  "@molecule/app-client-search-minisearch": "1.0.4",
45
46
  "@molecule/app-code-editor": "1.0.3",
46
47
  "@molecule/app-code-editor-monaco": "1.0.4",
47
48
  "@molecule/app-command-palette": "1.0.3",
48
49
  "@molecule/app-command-palette-cmdk": "1.0.3",
49
- "@molecule/app-drag-drop": "1.0.3",
50
- "@molecule/app-drag-drop-dndkit": "1.0.3",
50
+ "@molecule/app-drag-drop": "1.0.4",
51
+ "@molecule/app-drag-drop-dndkit": "1.0.4",
51
52
  "@molecule/app-fonts": "1.2.2",
52
53
  "@molecule/app-fonts-arimo": "1.0.5",
53
- "@molecule/app-http": "1.4.1",
54
+ "@molecule/app-http": "1.5.3",
54
55
  "@molecule/app-icons": "1.0.3",
55
56
  "@molecule/app-icons-molecule": "1.0.3",
56
57
  "@molecule/app-keyboard-shortcuts": "1.0.3",
57
58
  "@molecule/app-keyboard-shortcuts-hotkeys": "1.0.3",
58
59
  "@molecule/app-maps-leaflet": "1.0.3",
59
60
  "@molecule/app-realtime": "1.0.4",
60
- "@molecule/app-realtime-socketio": "1.1.1",
61
- "@molecule/app-routing": "1.0.4",
62
- "@molecule/app-routing-react-router": "1.1.1",
63
- "@molecule/app-state": "1.0.4",
64
- "@molecule/app-storage": "1.0.4",
65
- "@molecule/app-storage-localstorage": "1.0.3",
61
+ "@molecule/app-realtime-socketio": "1.1.2",
62
+ "@molecule/app-routing": "1.0.5",
63
+ "@molecule/app-routing-react-router": "1.2.1",
64
+ "@molecule/app-state": "1.0.5",
65
+ "@molecule/app-storage": "1.1.0",
66
+ "@molecule/app-storage-localstorage": "1.1.0",
66
67
  "@molecule/app-theme": "1.0.4",
67
68
  "@molecule/app-theme-css-variables": "1.0.4",
68
69
  "@molecule/app-ui": "1.3.8",
69
- "@molecule/app-ui-tailwind": "1.2.7",
70
+ "@molecule/app-ui-tailwind": "1.2.8",
70
71
  "@molecule/app-video-hls": "1.0.3",
71
- "@molecule/app-virtual-scroll": "1.0.3",
72
+ "@molecule/app-virtual-scroll": "1.0.4",
72
73
  "@molecule/app-virtual-scroll-tanstack": "1.0.3",
73
74
  "@types/node": "26.6.5",
74
75
  "@types/react": "19.3.0",
@@ -80,7 +81,7 @@
80
81
  "vitest": "4.1.12"
81
82
  },
82
83
  "peerDependencies": {
83
- "@molecule/app-auth": "^2.0.0",
84
+ "@molecule/app-auth": "^3.0.0",
84
85
  "@molecule/app-charts": "^1.0.1",
85
86
  "@molecule/app-charts-chartjs": "^1.0.1",
86
87
  "@molecule/app-client-search": "^1.0.0",
@@ -93,7 +94,7 @@
93
94
  "@molecule/app-drag-drop-dndkit": "^1.0.1",
94
95
  "@molecule/app-fonts": "^1.0.1",
95
96
  "@molecule/app-fonts-arimo": "^1.0.1",
96
- "@molecule/app-http": "^1.0.1",
97
+ "@molecule/app-http": "^1.5.0",
97
98
  "@molecule/app-icons": "^1.0.1",
98
99
  "@molecule/app-icons-molecule": "^1.0.1",
99
100
  "@molecule/app-keyboard-shortcuts": "^1.0.1",