@nebulr-group/bridge-svelte 0.4.0-beta.2 → 0.4.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/BridgeBootstrap.js +11 -6
- package/dist/core/bridge-instance.d.ts +0 -3
- package/dist/core/bridge-instance.js +4 -10
- package/dist/core/bridge-runtime.js +20 -1
- package/dist/core/bridge.d.ts +3 -4
- package/dist/core/bridge.js +3 -4
- package/dist/core/bridge.test.js +2 -2
- package/dist/flags/bootstrap.js +2 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -3
- package/package.json +2 -2
- package/dist/client/components/FeatureFlag.svelte +0 -37
- package/dist/client/components/FeatureFlag.svelte.d.ts +0 -15
- package/dist/shared/feature-flag.d.ts +0 -6
- package/dist/shared/feature-flag.js +0 -13
|
@@ -5,7 +5,6 @@ import { createRouteGuard } from '../auth/route-guard.js';
|
|
|
5
5
|
import { getBridgeAuth, bridgeReadyStore, markReady, waitForBridge as _waitForBridge, } from '../core/bridge-instance.js';
|
|
6
6
|
import { installBridgeAuthFetch } from '../core/bridge-runtime.js';
|
|
7
7
|
import { useBridge } from '@nebulr-group/bridge-auth-core';
|
|
8
|
-
import { featureFlags } from '../shared/feature-flag.js';
|
|
9
8
|
import { logger } from '../shared/logger.js';
|
|
10
9
|
import { bridgeConfig, getConfig } from './stores/config.store.js';
|
|
11
10
|
export async function bridgeBootstrap(url, config, routeConfig = { rules: [], defaultAccess: 'protected' }, kitFetch) {
|
|
@@ -158,11 +157,17 @@ export async function bridgeBootstrap(url, config, routeConfig = { rules: [], de
|
|
|
158
157
|
catch {
|
|
159
158
|
// Non-fatal — gate fails open; the notice hydrates lazily on first render.
|
|
160
159
|
}
|
|
161
|
-
// 3.
|
|
162
|
-
//
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
|
|
160
|
+
// 3. Warm the route-guard's flag cache without awaiting so GQL queries can
|
|
161
|
+
// start in parallel. `loadFeatureFlags()` populates the same auth-core
|
|
162
|
+
// FeatureFlagService the route guard evaluates `featureFlag` rules
|
|
163
|
+
// against; the flagsReady promise is passed to the guard and returned to
|
|
164
|
+
// callers so routes that gate on flags can await before rendering.
|
|
165
|
+
// (Component/programmatic flag reads use FF 2.0 `useFlag` / <FeatureFlag>.)
|
|
166
|
+
// Errors are logged, never thrown — flag failures must not crash bootstrap.
|
|
167
|
+
const flagsReady = getBridgeAuth()
|
|
168
|
+
.loadFeatureFlags()
|
|
169
|
+
.then(() => { })
|
|
170
|
+
.catch((err) => {
|
|
166
171
|
logger.warn('[bridgeBootstrap] Feature flags failed to load:', err);
|
|
167
172
|
});
|
|
168
173
|
// 4. Handle route guarding and redirects
|
|
@@ -39,8 +39,6 @@ export declare const isOnboarded: Readable<boolean>;
|
|
|
39
39
|
export declare const hasMultiTenantAccess: Readable<boolean>;
|
|
40
40
|
/** Tenant users for multi-tenant selection */
|
|
41
41
|
export declare const tenantUsersStore: Readable<TenantUser[]>;
|
|
42
|
-
/** Feature flags map */
|
|
43
|
-
export declare const flagsStore: Readable<Record<string, boolean>>;
|
|
44
42
|
/** Bridge ready state */
|
|
45
43
|
export declare const bridgeReadyStore: Readable<boolean>;
|
|
46
44
|
/** App-level config (SSO providers, feature flags, etc.) — loaded anonymously on init */
|
|
@@ -56,6 +54,5 @@ export declare const subscriptionStore: Readable<SubscriptionState>;
|
|
|
56
54
|
export declare function loadSubscription(): Promise<void>;
|
|
57
55
|
/** Lazy proxy to the BridgeAuth singleton — call methods directly: `auth.getToken()`, `auth.logout()`, etc. */
|
|
58
56
|
export declare const auth: BridgeAuth;
|
|
59
|
-
export declare const _flagsWritable: Writable<Record<string, boolean>>;
|
|
60
57
|
export declare const _profileWritable: Writable<Profile | null | undefined>;
|
|
61
58
|
export declare const _errorWritable: Writable<string | null>;
|
|
@@ -14,7 +14,6 @@ let _instance = null;
|
|
|
14
14
|
const _tokens = writable(null);
|
|
15
15
|
const _appConfig = writable(null);
|
|
16
16
|
const _profile = writable(undefined);
|
|
17
|
-
const _flags = writable({});
|
|
18
17
|
const _authState = writable('unauthenticated');
|
|
19
18
|
const _isLoading = writable(true);
|
|
20
19
|
const _error = writable(null);
|
|
@@ -46,19 +45,18 @@ export function initBridge(config) {
|
|
|
46
45
|
if (existingTokens) {
|
|
47
46
|
_tokens.set(existingTokens);
|
|
48
47
|
// Fetch profile for existing tokens
|
|
49
|
-
_instance.getProfile().then((p) => _profile.set(p ?? null)).catch(() =>
|
|
48
|
+
_instance.getProfile().then((p) => _profile.set(p ?? null)).catch((err) => logger.warn('[bridge-instance] profile fetch failed:', err));
|
|
50
49
|
}
|
|
51
50
|
_authState.set(_instance.getAuthState());
|
|
52
51
|
_isLoading.set(false);
|
|
53
52
|
// Wire auth-core events → Svelte stores
|
|
54
53
|
_instance.on('auth:login', (tokens) => {
|
|
55
54
|
_tokens.set(tokens);
|
|
56
|
-
_instance.getProfile().then((p) => _profile.set(p ?? null)).catch(() =>
|
|
55
|
+
_instance.getProfile().then((p) => _profile.set(p ?? null)).catch((err) => logger.warn('[bridge-instance] profile fetch failed:', err));
|
|
57
56
|
});
|
|
58
57
|
_instance.on('auth:logout', () => {
|
|
59
58
|
_tokens.set(null);
|
|
60
59
|
_profile.set(null);
|
|
61
|
-
_flags.set({});
|
|
62
60
|
});
|
|
63
61
|
_instance.on('auth:token-refreshed', (tokens) => {
|
|
64
62
|
_tokens.set(tokens);
|
|
@@ -77,9 +75,8 @@ export function initBridge(config) {
|
|
|
77
75
|
});
|
|
78
76
|
_instance.on('auth:workspace-changed', (tokens) => {
|
|
79
77
|
_tokens.set(tokens);
|
|
80
|
-
_flags.set({});
|
|
81
78
|
_subscriptionWritable.set({ status: null, plans: null, loading: false, error: null });
|
|
82
|
-
_instance.getProfile().then((p) => _profile.set(p ?? null)).catch(() =>
|
|
79
|
+
_instance.getProfile().then((p) => _profile.set(p ?? null)).catch((err) => logger.warn('[bridge-instance] profile fetch failed:', err));
|
|
83
80
|
});
|
|
84
81
|
_instance.on('auth:error', (err) => {
|
|
85
82
|
_error.set(err.message);
|
|
@@ -150,8 +147,6 @@ export const isOnboarded = _isOnboarded;
|
|
|
150
147
|
export const hasMultiTenantAccess = _hasMultiTenantAccess;
|
|
151
148
|
/** Tenant users for multi-tenant selection */
|
|
152
149
|
export const tenantUsersStore = _tenantUsers;
|
|
153
|
-
/** Feature flags map */
|
|
154
|
-
export const flagsStore = _flags;
|
|
155
150
|
/** Bridge ready state */
|
|
156
151
|
export const bridgeReadyStore = _ready;
|
|
157
152
|
/** App-level config (SSO providers, feature flags, etc.) — loaded anonymously on init */
|
|
@@ -183,11 +178,10 @@ export async function loadSubscription() {
|
|
|
183
178
|
export const auth = new Proxy({}, {
|
|
184
179
|
get(_, prop) {
|
|
185
180
|
const instance = getBridgeAuth();
|
|
186
|
-
const value = instance
|
|
181
|
+
const value = Reflect.get(instance, prop);
|
|
187
182
|
return typeof value === 'function' ? value.bind(instance) : value;
|
|
188
183
|
},
|
|
189
184
|
});
|
|
190
185
|
// ── Internal-only store writers (for use by wrapper modules) ───────────────────
|
|
191
|
-
export const _flagsWritable = _flags;
|
|
192
186
|
export const _profileWritable = _profile;
|
|
193
187
|
export const _errorWritable = _error;
|
|
@@ -104,6 +104,10 @@ export function startBridgeRuntime(options = {}) {
|
|
|
104
104
|
getAuthToken: () => _currentAuthToken,
|
|
105
105
|
});
|
|
106
106
|
let _connectedOnce = false;
|
|
107
|
+
// Set just before we call _realtime.reauthorize() so the resulting
|
|
108
|
+
// reconnect's setOnOpen handler knows the token is already fresh and skips
|
|
109
|
+
// its proactive refresh — see the loop note in setOnOpen below.
|
|
110
|
+
let _reauthInFlight = false;
|
|
107
111
|
_realtime.setOnOpen(() => {
|
|
108
112
|
_setRealtimeStatus('open');
|
|
109
113
|
// On reconnect (not initial connect), proactively refresh tokens.
|
|
@@ -111,7 +115,18 @@ export function startBridgeRuntime(options = {}) {
|
|
|
111
115
|
// client missed the user.state_changed broadcast. Refreshing here
|
|
112
116
|
// syncs tokens before the first post-reconnect request can fail with
|
|
113
117
|
// TOKEN_VERSION_STALE.
|
|
114
|
-
|
|
118
|
+
//
|
|
119
|
+
// EXCEPT when this reconnect was caused by our OWN reauthorize() below
|
|
120
|
+
// (a token-only refresh). In that case the token is already current, so
|
|
121
|
+
// refreshing again would mint yet another JWT, which the tokenStore
|
|
122
|
+
// subscription would see as a change and reauthorize() again → reconnect
|
|
123
|
+
// → setOnOpen → refresh → … an unbounded loop that hammers /auth/token
|
|
124
|
+
// (observed ~32 cycles/sec, jamming the page's main thread and stalling
|
|
125
|
+
// every downstream wait). Only genuine, externally-triggered reconnects
|
|
126
|
+
// (network blips, server restarts) should trigger the catch-up refresh.
|
|
127
|
+
const causedByReauthorize = _reauthInFlight;
|
|
128
|
+
_reauthInFlight = false;
|
|
129
|
+
if (_connectedOnce && !causedByReauthorize) {
|
|
115
130
|
getBridgeAuth().refreshTokens().catch(() => { });
|
|
116
131
|
}
|
|
117
132
|
_connectedOnce = true;
|
|
@@ -224,6 +239,10 @@ export function startBridgeRuntime(options = {}) {
|
|
|
224
239
|
// Centrifugo's connection-token TTL drops it. Force a reauthorize so the
|
|
225
240
|
// server re-validates against the new token immediately.
|
|
226
241
|
if (prevAuthToken && _currentAuthToken && prevAuthToken !== _currentAuthToken) {
|
|
242
|
+
// Flag this as a self-induced reconnect so setOnOpen does NOT fire its
|
|
243
|
+
// proactive refresh (which would mint a new token → land back here →
|
|
244
|
+
// loop forever). The token we're reauthorizing with is already current.
|
|
245
|
+
_reauthInFlight = true;
|
|
227
246
|
void _realtime.reauthorize();
|
|
228
247
|
}
|
|
229
248
|
});
|
package/dist/core/bridge.d.ts
CHANGED
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
* follow-up sub-tickets (TBP-322 `.load()` semantics + TBP-323 reactive
|
|
9
9
|
* binding for loaded slices).
|
|
10
10
|
*
|
|
11
|
-
* Backward compat: this is purely additive. The
|
|
12
|
-
* (`subscriptionStore`, `
|
|
13
|
-
*
|
|
14
|
-
* in deprecation warnings; for now both surfaces coexist.
|
|
11
|
+
* Backward compat: this is purely additive. The module-level stores
|
|
12
|
+
* (`subscriptionStore`, `appConfigStore`, etc.) continue to exist and are
|
|
13
|
+
* populated by the same internal state; both surfaces coexist.
|
|
15
14
|
*
|
|
16
15
|
* Note: `useBridge()` (Svelte context hook) lands in TBP-320. This module
|
|
17
16
|
* only exposes the singleton aggregate `bridge`; consumers can import it
|
package/dist/core/bridge.js
CHANGED
|
@@ -8,10 +8,9 @@
|
|
|
8
8
|
* follow-up sub-tickets (TBP-322 `.load()` semantics + TBP-323 reactive
|
|
9
9
|
* binding for loaded slices).
|
|
10
10
|
*
|
|
11
|
-
* Backward compat: this is purely additive. The
|
|
12
|
-
* (`subscriptionStore`, `
|
|
13
|
-
*
|
|
14
|
-
* in deprecation warnings; for now both surfaces coexist.
|
|
11
|
+
* Backward compat: this is purely additive. The module-level stores
|
|
12
|
+
* (`subscriptionStore`, `appConfigStore`, etc.) continue to exist and are
|
|
13
|
+
* populated by the same internal state; both surfaces coexist.
|
|
15
14
|
*
|
|
16
15
|
* Note: `useBridge()` (Svelte context hook) lands in TBP-320. This module
|
|
17
16
|
* only exposes the singleton aggregate `bridge`; consumers can import it
|
package/dist/core/bridge.test.js
CHANGED
|
@@ -218,7 +218,7 @@ describe('bridge.app.plans lazy slice (Phase 4, TBP-321/322)', () => {
|
|
|
218
218
|
});
|
|
219
219
|
it('apply() updates a loaded slice (TBP-323 reactive binding primitive)', async () => {
|
|
220
220
|
await bridge.app.plans.load();
|
|
221
|
-
bridge.app.plans.apply([{ key: 'enterprise', name: 'Enterprise' }]);
|
|
222
|
-
expect(get(bridge.app.plans)).toEqual([{ key: 'enterprise', name: 'Enterprise' }]);
|
|
221
|
+
bridge.app.plans.apply([{ key: 'enterprise', name: 'Enterprise', prices: [] }]);
|
|
222
|
+
expect(get(bridge.app.plans)).toEqual([{ key: 'enterprise', name: 'Enterprise', prices: [] }]);
|
|
223
223
|
});
|
|
224
224
|
});
|
package/dist/flags/bootstrap.js
CHANGED
|
@@ -27,11 +27,10 @@ export class BrowserIdentityStorage {
|
|
|
27
27
|
constructor(mode, key = 'bridge.anon_id') {
|
|
28
28
|
this.mode = mode;
|
|
29
29
|
this.key = key;
|
|
30
|
-
if (typeof
|
|
30
|
+
if (typeof window === 'undefined') {
|
|
31
31
|
throw new Error('BrowserIdentityStorage requires a window — use MemoryIdentityStorage on the server');
|
|
32
32
|
}
|
|
33
|
-
|
|
34
|
-
this.storage = mode === 'persistent' ? w.localStorage : w.sessionStorage;
|
|
33
|
+
this.storage = mode === 'persistent' ? window.localStorage : window.sessionStorage;
|
|
35
34
|
}
|
|
36
35
|
read() {
|
|
37
36
|
try {
|
package/dist/index.d.ts
CHANGED
|
@@ -5,10 +5,10 @@ export type { SubscriptionState } from './core/bridge-instance.js';
|
|
|
5
5
|
export { bridge } from './core/bridge.js';
|
|
6
6
|
export type { BridgeSurface, BridgeAppSurface, BridgeTenantSurface, } from './core/bridge.js';
|
|
7
7
|
export type { BrandingSnapshot, SubscriptionSnapshot, UserSnapshot, SessionSnapshotData, } from './core/snapshot-stores.js';
|
|
8
|
-
export type { BridgeEventHandlers } from './core/events.js';
|
|
8
|
+
export type { BridgeEventHandlers, BridgeEventsDispatcher } from './core/events.js';
|
|
9
9
|
export { default as BridgeBootstrap, default as BridgeProvider } from './client/BridgeBootstrap.svelte';
|
|
10
10
|
export { default as ApiTokenManagement } from './client/components/developer/ApiTokenManagement.svelte';
|
|
11
|
-
export { default as FeatureFlag } from './
|
|
11
|
+
export { default as FeatureFlag } from './flags/FeatureFlag.svelte';
|
|
12
12
|
export { default as ProfileName } from './client/components/ProfileName.svelte';
|
|
13
13
|
export { default as TeamManagementPanel } from './client/components/team/TeamManagementPanel.svelte';
|
|
14
14
|
export { default as TeamUserList } from './client/components/team/TeamUserList.svelte';
|
|
@@ -31,7 +31,6 @@ export { default as BridgeSubscriptionStatus } from './client/components/subscri
|
|
|
31
31
|
export { default as BridgeBillingNotice } from './client/components/subscription/BridgeBillingNotice.svelte';
|
|
32
32
|
export { default as BridgePaywall } from './client/components/subscription/BridgePaywall.svelte';
|
|
33
33
|
export { default as BridgeQuotaBanner } from './client/components/subscription/BridgeQuotaBanner.svelte';
|
|
34
|
-
export * from './shared/feature-flag.js';
|
|
35
34
|
export * from './auth/route-guard.js';
|
|
36
35
|
export * from './shared/profile.js';
|
|
37
36
|
export * from './shared/types/config.js';
|
|
@@ -41,6 +40,7 @@ export type { RedditConversionEvent, RedditEcommerce, RedditEcommerceItem, Reddi
|
|
|
41
40
|
export { sha256Email } from './client/tracking/pii-hashing.js';
|
|
42
41
|
export type { AuthConfigResponse, AuthResult, AuthState, BridgeAuthConfig, BridgeAuthEventName, BridgeAuthEvents, FederationConnection, MagicLinkResult, MfaResult, PasskeyAuthOptions, PasskeyRegistrationOptions, PasskeyVerificationResult, SignupResult, SsoOptions, SsoResult, TenantUser, } from '@nebulr-group/bridge-auth-core';
|
|
43
42
|
export { BridgeAuth, BridgeAuthError, HttpError, TeamService, ApiTokenService } from '@nebulr-group/bridge-auth-core';
|
|
43
|
+
export type { SessionStalePayload } from '@nebulr-group/bridge-auth-core';
|
|
44
44
|
export type { ApiToken, CreateApiTokenInput, CreateApiTokenResponse, } from '@nebulr-group/bridge-auth-core';
|
|
45
45
|
export type { TeamProfile, TeamProfileUpdateInput, TeamUser, TeamUserListResult, TeamUserUpdateInput, TeamWorkspace, TeamWorkspaceUpdateInput, } from '@nebulr-group/bridge-auth-core';
|
|
46
46
|
export type { Plan, PriceOfferSdk, SubscriptionStatus, CheckoutSession, Workspace, } from '@nebulr-group/bridge-auth-core';
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ export { bridge } from './core/bridge.js';
|
|
|
16
16
|
// Components (Svelte components must have `export default`)
|
|
17
17
|
export { default as BridgeBootstrap, default as BridgeProvider } from './client/BridgeBootstrap.svelte';
|
|
18
18
|
export { default as ApiTokenManagement } from './client/components/developer/ApiTokenManagement.svelte';
|
|
19
|
-
export { default as FeatureFlag } from './
|
|
19
|
+
export { default as FeatureFlag } from './flags/FeatureFlag.svelte';
|
|
20
20
|
export { default as ProfileName } from './client/components/ProfileName.svelte';
|
|
21
21
|
export { default as TeamManagementPanel } from './client/components/team/TeamManagementPanel.svelte';
|
|
22
22
|
export { default as TeamUserList } from './client/components/team/TeamUserList.svelte';
|
|
@@ -49,8 +49,6 @@ export { default as BridgeBillingNotice } from './client/components/subscription
|
|
|
49
49
|
export { default as BridgePaywall } from './client/components/subscription/BridgePaywall.svelte';
|
|
50
50
|
// Billing 2.0 (Phase C / US-11) — live quota counter banner.
|
|
51
51
|
export { default as BridgeQuotaBanner } from './client/components/subscription/BridgeQuotaBanner.svelte';
|
|
52
|
-
// Feature flags
|
|
53
|
-
export * from './shared/feature-flag.js';
|
|
54
52
|
// Auth route guards
|
|
55
53
|
export * from './auth/route-guard.js';
|
|
56
54
|
// Types
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebulr-group/bridge-svelte",
|
|
3
|
-
"version": "0.4.0-beta.
|
|
3
|
+
"version": "0.4.0-beta.4",
|
|
4
4
|
"description": "Bridge Svelte library, This library helps you to add bridge authentication and feature flags, and payments to your svelte application.",
|
|
5
5
|
"author": "Iman Pouya",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
}
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
-
"@nebulr-group/bridge-auth-core": "0.4.0-beta.
|
|
70
|
+
"@nebulr-group/bridge-auth-core": "0.4.0-beta.5"
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
73
|
"@sveltejs/kit": "^2.16.0",
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { Snippet } from 'svelte';
|
|
3
|
-
import { onMount } from 'svelte';
|
|
4
|
-
import { isFeatureEnabled } from '../../shared/feature-flag.js';
|
|
5
|
-
|
|
6
|
-
type FlagRenderArgs = { enabled: boolean; rawEnabled: boolean };
|
|
7
|
-
|
|
8
|
-
let {
|
|
9
|
-
flagName,
|
|
10
|
-
forceLive = false,
|
|
11
|
-
negate = false,
|
|
12
|
-
renderWhenDisabled = false,
|
|
13
|
-
children
|
|
14
|
-
}: {
|
|
15
|
-
flagName: string;
|
|
16
|
-
forceLive?: boolean;
|
|
17
|
-
negate?: boolean;
|
|
18
|
-
renderWhenDisabled?: boolean;
|
|
19
|
-
children?: Snippet<[FlagRenderArgs]>;
|
|
20
|
-
} = $props();
|
|
21
|
-
|
|
22
|
-
let enabled = $state(false);
|
|
23
|
-
let rawEnabled = $derived(enabled);
|
|
24
|
-
let effectiveEnabled = $derived(negate ? !enabled : enabled);
|
|
25
|
-
|
|
26
|
-
onMount(async () => {
|
|
27
|
-
enabled = await isFeatureEnabled(flagName, forceLive);
|
|
28
|
-
});
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
{#if children}
|
|
32
|
-
{#if renderWhenDisabled}
|
|
33
|
-
{@render children({ enabled: effectiveEnabled, rawEnabled })}
|
|
34
|
-
{:else if effectiveEnabled}
|
|
35
|
-
{@render children({ enabled: true, rawEnabled })}
|
|
36
|
-
{/if}
|
|
37
|
-
{/if}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { Snippet } from 'svelte';
|
|
2
|
-
type FlagRenderArgs = {
|
|
3
|
-
enabled: boolean;
|
|
4
|
-
rawEnabled: boolean;
|
|
5
|
-
};
|
|
6
|
-
type $$ComponentProps = {
|
|
7
|
-
flagName: string;
|
|
8
|
-
forceLive?: boolean;
|
|
9
|
-
negate?: boolean;
|
|
10
|
-
renderWhenDisabled?: boolean;
|
|
11
|
-
children?: Snippet<[FlagRenderArgs]>;
|
|
12
|
-
};
|
|
13
|
-
declare const FeatureFlag: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
14
|
-
type FeatureFlag = ReturnType<typeof FeatureFlag>;
|
|
15
|
-
export default FeatureFlag;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
export declare function loadFeatureFlags(): Promise<void>;
|
|
2
|
-
export declare function isFeatureEnabled(flag: string, forceLive?: boolean): Promise<boolean>;
|
|
3
|
-
export declare const featureFlags: {
|
|
4
|
-
flags: import("svelte/store").Writable<Record<string, boolean>>;
|
|
5
|
-
refresh: typeof loadFeatureFlags;
|
|
6
|
-
};
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
// src/lib/shared/feature-flag.ts — thin wrapper delegating to bridge-instance
|
|
2
|
-
import { getBridgeAuth, _flagsWritable, flagsStore } from '../core/bridge-instance.js';
|
|
3
|
-
export async function loadFeatureFlags() {
|
|
4
|
-
const flags = await getBridgeAuth().loadFeatureFlags();
|
|
5
|
-
_flagsWritable.set(flags);
|
|
6
|
-
}
|
|
7
|
-
export async function isFeatureEnabled(flag, forceLive = false) {
|
|
8
|
-
return getBridgeAuth().isFeatureEnabled(flag, { forceLive });
|
|
9
|
-
}
|
|
10
|
-
export const featureFlags = {
|
|
11
|
-
flags: flagsStore,
|
|
12
|
-
refresh: loadFeatureFlags
|
|
13
|
-
};
|