@nebulr-group/bridge-svelte 0.9.1-beta.0 → 0.9.1-beta.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.
@@ -199,6 +199,39 @@ async function waitForConfigured() {
199
199
  clearTimeout(timer);
200
200
  }
201
201
  }
202
+ /** Longest the first render waits for the plan's features before showing anyway. */
203
+ const ENTITLEMENTS_FIRST_RENDER_WAIT_MS = 1500;
204
+ // TBP-810 — flag rules on `bridge:billing.entitlement.*` read auth-core's
205
+ // entitlements store. Nothing ever configured it, so it could not load itself
206
+ // and only filled from `/session/init` on the first realtime connect, about a
207
+ // second after the page rendered. Until then an entitled user saw every
208
+ // plan-gated feature locked (and a click offered an upgrade). Configure it,
209
+ // then load it before the first render — bounded, so a slow or failing read
210
+ // shows the page anyway and the store fills in when it can, as before.
211
+ async function loadEntitlementsBeforeFirstRender(bridge) {
212
+ try {
213
+ const store = useBridge().entitlementsStore;
214
+ store.configure({
215
+ apiBaseUrl: bridge.getApiContext().apiBaseUrl,
216
+ getAccessToken: () => bridge.getApiContext().accessToken ?? null,
217
+ }, logger);
218
+ if (store.isHydrated())
219
+ return;
220
+ let timer;
221
+ const timeout = new Promise((resolve) => {
222
+ timer = setTimeout(resolve, ENTITLEMENTS_FIRST_RENDER_WAIT_MS);
223
+ });
224
+ try {
225
+ await Promise.race([store.hydrate(), timeout]);
226
+ }
227
+ finally {
228
+ clearTimeout(timer);
229
+ }
230
+ }
231
+ catch (err) {
232
+ logger.debug('[bridgeBootstrap] entitlements not loaded before first render:', err);
233
+ }
234
+ }
202
235
  // Once per page load. Concurrent callers share the same promise, so a first
203
236
  // navigation that redirects mid-bootstrap does not start a second refresh or
204
237
  // flag load. Never rejects: every step is best-effort by design — none of them
@@ -219,17 +252,22 @@ function ensureInitialised() {
219
252
  }
220
253
  // Auto-manage billing state so the notice/gate render without the
221
254
  // integrator wiring a mount, and `hard` billing route rules can decide.
255
+ // The plan's features load alongside it (same round-trip time, so the
256
+ // page waits no longer).
222
257
  try {
223
258
  const bridge = getBridgeAuth();
224
259
  const ctx = bridge.getApiContext();
225
260
  if (ctx.accessToken) {
226
- await useBridge().subscription.mount({
227
- apiBaseUrl: ctx.apiBaseUrl,
228
- accessToken: ctx.accessToken,
229
- appId: ctx.appId,
230
- // TBP-762 — renew an out-of-date sign-in and retry instead of failing.
231
- onTokenStale: tokenStaleHandlerOf(bridge),
232
- });
261
+ await Promise.all([
262
+ useBridge().subscription.mount({
263
+ apiBaseUrl: ctx.apiBaseUrl,
264
+ accessToken: ctx.accessToken,
265
+ appId: ctx.appId,
266
+ // TBP-762 — renew an out-of-date sign-in and retry instead of failing.
267
+ onTokenStale: tokenStaleHandlerOf(bridge),
268
+ }),
269
+ loadEntitlementsBeforeFirstRender(bridge),
270
+ ]);
233
271
  }
234
272
  }
235
273
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nebulr-group/bridge-svelte",
3
- "version": "0.9.1-beta.0",
3
+ "version": "0.9.1-beta.1",
4
4
  "description": "The Bridge for SvelteKit: sign-in, workspaces and roles, feature flags, Stripe subscriptions and plan limits in one .env line and three files.",
5
5
  "author": "Iman Pouya",
6
6
  "license": "MIT",