@avsbhq/vue 1.0.2 → 1.1.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/dist/index.cjs CHANGED
@@ -18,227 +18,243 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
 
20
20
  // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
23
  AvsbInjectionKey: () => AvsbInjectionKey,
24
24
  AvsbPlugin: () => AvsbPlugin,
25
25
  AvsbProvider: () => AvsbProvider,
26
+ DecideOption: () => import_core2.DecideOption,
26
27
  useAlias: () => useAlias,
27
28
  useAllFlags: () => useAllFlags,
28
29
  useAvsbClient: () => useAvsbClient,
29
- useAvsbStore: () => useAvsbStore,
30
+ useAvsbStatus: () => useAvsbStatus,
30
31
  useBoolFlag: () => useBoolFlag,
32
+ useExposure: () => useExposure,
31
33
  useFlag: () => useFlag,
32
34
  useFlagReady: () => useFlagReady,
35
+ useFlagSubscription: () => useFlagSubscription,
33
36
  useFlagValue: () => useFlagValue,
34
37
  useIdentify: () => useIdentify,
35
38
  useJsonFlag: () => useJsonFlag,
36
39
  useNumberFlag: () => useNumberFlag,
40
+ useReset: () => useReset,
37
41
  useStringFlag: () => useStringFlag,
38
42
  useTrack: () => useTrack
39
43
  });
40
- module.exports = __toCommonJS(index_exports);
44
+ module.exports = __toCommonJS(src_exports);
41
45
 
42
46
  // src/AvsbProvider.ts
43
- var import_vue2 = require("vue");
44
- var import_browser = require("@avsbhq/browser");
47
+ var import_vue3 = require("vue");
48
+ var import_browser2 = require("@avsbhq/browser");
49
+ var import_core = require("@avsbhq/core");
45
50
 
46
51
  // src/context.ts
47
52
  var import_vue = require("vue");
48
53
  var AvsbInjectionKey = /* @__PURE__ */ Symbol("avsb-injection-key");
49
54
  function useAvsbContext() {
50
- const v = (0, import_vue.inject)(AvsbInjectionKey);
51
- if (v === void 0) {
55
+ const value = (0, import_vue.inject)(AvsbInjectionKey);
56
+ if (value === void 0) {
52
57
  throw new Error(
53
- '[avsb] composables must be used inside <AvsbProvider> or app.use(AvsbPlugin). Wrap your component tree with <AvsbProvider sdkKey="..." context={...}> or install the plugin.'
58
+ `[avsb] composables must be used inside <AvsbProvider> or app.use(AvsbPlugin). Wrap your component tree with <AvsbProvider sdk-key="sdk_production_..." :context="{ kind: 'user', key: userId }">, or install the plugin with app.use(AvsbPlugin, { sdkKey: 'sdk_production_...' }).`
54
59
  );
55
60
  }
56
- return v;
61
+ return value;
62
+ }
63
+ function hasAvsbContext() {
64
+ return (0, import_vue.inject)(AvsbInjectionKey, null) !== null;
65
+ }
66
+
67
+ // src/internal/providerState.ts
68
+ var import_vue2 = require("vue");
69
+ var UNEXPLAINED_FAILURE = "[avsb] the SDK could not load a datafile and nothing was cached or bootstrapped, so every flag is returning the default you passed. Check the SDK key on app.avsb.cloud under Environments in the project sidebar.";
70
+ function createProviderState(client) {
71
+ const status = (0, import_vue2.ref)(client.isReady() ? "ready" : "loading");
72
+ const error = (0, import_vue2.shallowRef)(void 0);
73
+ const degraded = (0, import_vue2.ref)(false);
74
+ let stopped = false;
75
+ const applyInitResult = (result) => {
76
+ if (stopped) return;
77
+ if (result.success) {
78
+ status.value = "ready";
79
+ degraded.value = result.degraded === true;
80
+ error.value = result.error;
81
+ return;
82
+ }
83
+ status.value = "error";
84
+ error.value = result.error ?? new Error(UNEXPLAINED_FAILURE);
85
+ };
86
+ const settled = client.getInitResult();
87
+ if (settled) {
88
+ applyInitResult(settled);
89
+ } else {
90
+ void client.onReady().then(applyInitResult);
91
+ }
92
+ const offError = client.on("error", (e) => {
93
+ if (stopped) return;
94
+ error.value = e;
95
+ if (client.isReady()) {
96
+ degraded.value = true;
97
+ return;
98
+ }
99
+ status.value = "error";
100
+ });
101
+ const offReady = client.on("ready", applyInitResult);
102
+ return {
103
+ status,
104
+ error,
105
+ degraded,
106
+ stop: () => {
107
+ stopped = true;
108
+ offError();
109
+ offReady();
110
+ }
111
+ };
112
+ }
113
+
114
+ // src/internal/resolveClient.ts
115
+ var import_browser = require("@avsbhq/browser");
116
+ var MISUSE_MESSAGE = `[avsb] <AvsbProvider> needs either an sdk-key (Mode A) or a client (Mode B). Mode A: <AvsbProvider sdk-key="sdk_production_..." :context="{ kind: 'user', key: userId }">. Mode B: <AvsbProvider :client="myClient">. The key for each environment is on app.avsb.cloud under Environments in the project sidebar.`;
117
+ function resolveClient(props) {
118
+ const injected = props.client;
119
+ if (injected !== void 0 && injected !== null) {
120
+ return { client: injected, owned: false };
121
+ }
122
+ const { sdkKey, context, bootstrap, options } = props;
123
+ if (typeof sdkKey !== "string" || sdkKey.length === 0) {
124
+ throw new Error(MISUSE_MESSAGE);
125
+ }
126
+ const clientOptions = {
127
+ ...options ?? {},
128
+ sdkKey,
129
+ ...context !== void 0 ? { context } : {},
130
+ ...bootstrap !== void 0 ? { bootstrap } : {}
131
+ };
132
+ return { client: new import_browser.AvsbClient(clientOptions), owned: true };
57
133
  }
58
134
 
59
135
  // src/AvsbProvider.ts
60
- var AvsbProvider = (0, import_vue2.defineComponent)({
136
+ var NESTED_PROVIDER_WARNING = "[avsb] <AvsbProvider> is nested inside another <AvsbProvider>. The inner one shadows the outer for everything below it, so two clients are now running, each with its own visitor id and its own event queue. Mount one provider at the root of the app unless you meant to isolate a subtree.";
137
+ var AvsbProvider = (0, import_vue3.defineComponent)({
61
138
  name: "AvsbProvider",
62
139
  props: {
63
- // Mode B — caller passes a pre-built client
140
+ /** Mode B: a client you built and own. */
64
141
  client: {
65
142
  type: Object,
66
143
  default: void 0
67
144
  },
68
- // Mode A — sdkKey is the minimum required field from AvsbClientOptions
145
+ /** Mode A: the environment's SDK key. */
69
146
  sdkKey: {
70
147
  type: String,
71
148
  default: void 0
149
+ },
150
+ /** Mode A: evaluation context. Omit for an anonymous visitor. */
151
+ context: {
152
+ type: Object,
153
+ default: void 0
154
+ },
155
+ /** Mode A: a datafile fetched on the server, for a real first paint. */
156
+ bootstrap: {
157
+ type: Object,
158
+ default: void 0
159
+ },
160
+ /** Mode A: everything else AvsbClient accepts. */
161
+ options: {
162
+ type: Object,
163
+ default: void 0
72
164
  }
73
165
  },
74
- // Accept any additional option props (pollingInterval, bootstrap, etc.)
75
- // via inheritAttrs + $attrs so callers can pass the full AvsbClientOptions
76
- // surface without enumerating every field as a prop.
77
- inheritAttrs: false,
78
- setup(props, { slots, attrs }) {
79
- const injectedClient = props.client ?? null;
80
- const isInjectionMode = injectedClient !== null;
81
- let ownedClient = null;
82
- if (!isInjectionMode) {
83
- if (!props.sdkKey) {
84
- throw new Error(
85
- "[avsb] <AvsbProvider> requires either a `client` prop (Mode B) or a `sdkKey` prop (Mode A)."
86
- );
87
- }
88
- const opts = {
89
- sdkKey: props.sdkKey,
90
- ...attrs
91
- };
92
- ownedClient = new import_browser.AvsbClient(opts);
166
+ setup(props, { slots }) {
167
+ if (hasAvsbContext() && (0, import_browser2.isDevEnvironment)()) {
168
+ (0, import_core.consoleLogger)("warn").warn(NESTED_PROVIDER_WARNING);
93
169
  }
94
- const activeClient = isInjectionMode ? injectedClient : ownedClient;
95
- const status = (0, import_vue2.ref)("loading");
96
- const error = (0, import_vue2.ref)(void 0);
97
- (0, import_vue2.provide)(AvsbInjectionKey, {
98
- get client() {
99
- return activeClient;
100
- },
170
+ const { client, owned } = resolveClient(props);
171
+ const state = createProviderState(client);
172
+ (0, import_vue3.provide)(AvsbInjectionKey, {
173
+ client,
101
174
  get status() {
102
- return status.value;
175
+ return state.status.value;
103
176
  },
104
177
  get error() {
105
- return error.value;
106
- }
107
- });
108
- let cancelled = false;
109
- let unsubscribeError;
110
- (0, import_vue2.onMounted)(() => {
111
- if (!activeClient) return;
112
- activeClient.onReady().then(() => {
113
- if (!cancelled) status.value = "ready";
114
- }).catch((err) => {
115
- if (!cancelled) {
116
- status.value = "error";
117
- error.value = err instanceof Error ? err : new Error(String(err));
118
- }
119
- });
120
- if (typeof activeClient.on === "function") {
121
- unsubscribeError = activeClient.on("error", (e) => {
122
- if (!cancelled) {
123
- status.value = "error";
124
- error.value = e;
125
- }
126
- });
178
+ return state.error.value;
179
+ },
180
+ get degraded() {
181
+ return state.degraded.value;
127
182
  }
128
183
  });
129
- (0, import_vue2.onUnmounted)(() => {
130
- cancelled = true;
131
- unsubscribeError?.();
132
- if (!isInjectionMode && ownedClient) {
133
- ownedClient.close().catch(() => {
134
- });
135
- ownedClient = null;
136
- }
184
+ (0, import_vue3.onUnmounted)(() => {
185
+ state.stop();
186
+ if (owned) void client.close();
137
187
  });
138
188
  return () => slots.default?.();
139
- },
140
- render() {
141
- return (0, import_vue2.h)("div");
142
189
  }
143
190
  });
144
191
 
145
192
  // src/plugin.ts
146
- var import_vue3 = require("vue");
147
- var import_browser2 = require("@avsbhq/browser");
148
193
  var AvsbPlugin = {
149
194
  install(app, options) {
150
- const injectedClient = "client" in options && options.client ? options.client : null;
151
- const isInjectionMode = injectedClient !== null;
152
- let activeClient;
153
- if (isInjectionMode) {
154
- activeClient = injectedClient;
155
- } else {
156
- const opts = options;
157
- activeClient = new import_browser2.AvsbClient(opts);
158
- }
159
- const status = (0, import_vue3.ref)("loading");
160
- const error = (0, import_vue3.ref)(void 0);
195
+ const { sdkKey, context, bootstrap, client: injected, ...rest } = options;
196
+ const { client, owned } = resolveClient({
197
+ ...injected ? { client: injected } : { sdkKey },
198
+ ...context !== void 0 ? { context } : {},
199
+ ...bootstrap !== void 0 ? { bootstrap } : {},
200
+ options: rest
201
+ });
202
+ const state = createProviderState(client);
161
203
  app.provide(AvsbInjectionKey, {
162
- get client() {
163
- return activeClient;
164
- },
204
+ client,
165
205
  get status() {
166
- return status.value;
206
+ return state.status.value;
167
207
  },
168
208
  get error() {
169
- return error.value;
209
+ return state.error.value;
210
+ },
211
+ get degraded() {
212
+ return state.degraded.value;
170
213
  }
171
214
  });
172
- activeClient.onReady().then(() => {
173
- status.value = "ready";
174
- }).catch((err) => {
175
- status.value = "error";
176
- error.value = err instanceof Error ? err : new Error(String(err));
177
- });
178
- if (typeof activeClient.on === "function") {
179
- activeClient.on("error", (e) => {
180
- status.value = "error";
181
- error.value = e;
182
- });
183
- }
184
- if (!isInjectionMode) {
185
- app.unmount = new Proxy(app.unmount, {
186
- apply(target, thisArg, args) {
187
- activeClient.close().catch(() => {
188
- });
189
- return Reflect.apply(target, thisArg, args);
190
- }
191
- });
192
- }
215
+ const unmount = app.unmount.bind(app);
216
+ app.unmount = () => {
217
+ state.stop();
218
+ if (owned) void client.close();
219
+ unmount();
220
+ };
193
221
  }
194
222
  };
195
223
 
196
- // src/composables/useFlag.ts
224
+ // src/internal/bindFlagRef.ts
197
225
  var import_vue4 = require("vue");
198
- var import_core = require("@avsbhq/core");
199
- function useFlag(flagKey, defaultValue) {
200
- const { client } = useAvsbContext();
201
- const noClientSentinel = (0, import_core.notFoundFlag)(defaultValue, "no client");
202
- const flagRef = (0, import_vue4.ref)(
203
- client !== null && typeof client.getSnapshot === "function" ? client.getSnapshot(
204
- (0, import_vue4.isRef)(flagKey) ? flagKey.value : flagKey,
205
- defaultValue
206
- ) : noClientSentinel
207
- );
208
- let unsub;
209
- function resubscribe() {
210
- unsub?.();
211
- unsub = void 0;
212
- if (!client || typeof client.subscribe !== "function") return;
213
- const key = (0, import_vue4.isRef)(flagKey) ? flagKey.value : flagKey;
214
- if (typeof client.getSnapshot === "function") {
215
- flagRef.value = client.getSnapshot(key, defaultValue);
216
- }
217
- unsub = client.subscribe(key, () => {
218
- if (typeof client.getSnapshot === "function") {
219
- flagRef.value = client.getSnapshot(
220
- (0, import_vue4.isRef)(flagKey) ? flagKey.value : flagKey,
221
- defaultValue
222
- );
223
- }
226
+ var RENDER_SAFE = { readOnly: true };
227
+ function resolveFlagKey(flagKey) {
228
+ return (0, import_vue4.isRef)(flagKey) ? flagKey.value : flagKey;
229
+ }
230
+ function bindFlagRef(client, flagKey, read) {
231
+ const current = (0, import_vue4.shallowRef)(read(client, resolveFlagKey(flagKey)));
232
+ let unsubscribe;
233
+ const subscribe = (key) => {
234
+ unsubscribe?.();
235
+ current.value = read(client, key);
236
+ unsubscribe = client.subscribe(key, () => {
237
+ current.value = read(client, key);
224
238
  });
225
- }
226
- let stopWatcher;
227
- (0, import_vue4.onMounted)(() => {
228
- if ((0, import_vue4.isRef)(flagKey)) {
229
- stopWatcher = (0, import_vue4.watchEffect)(() => {
230
- void flagKey.value;
231
- resubscribe();
232
- });
233
- } else {
234
- resubscribe();
235
- }
236
- });
237
- (0, import_vue4.onUnmounted)(() => {
239
+ };
240
+ subscribe(resolveFlagKey(flagKey));
241
+ const stopWatcher = (0, import_vue4.isRef)(flagKey) ? (0, import_vue4.watch)(flagKey, (next) => subscribe(next), { flush: "sync" }) : void 0;
242
+ (0, import_vue4.onScopeDispose)(() => {
238
243
  stopWatcher?.();
239
- unsub?.();
244
+ unsubscribe?.();
245
+ unsubscribe = void 0;
240
246
  });
241
- return (0, import_vue4.computed)(() => flagRef.value);
247
+ return (0, import_vue4.computed)(() => current.value);
248
+ }
249
+
250
+ // src/composables/useFlag.ts
251
+ function useFlag(flagKey, defaultValue) {
252
+ const { client } = useAvsbContext();
253
+ return bindFlagRef(
254
+ client,
255
+ flagKey,
256
+ (c, key) => c.getSnapshot(key, defaultValue)
257
+ );
242
258
  }
243
259
 
244
260
  // src/composables/useFlagValue.ts
@@ -249,274 +265,191 @@ function useFlagValue(flagKey, defaultValue) {
249
265
  }
250
266
 
251
267
  // src/composables/useBoolFlag.ts
252
- var import_vue6 = require("vue");
253
- var import_core2 = require("@avsbhq/core");
254
268
  function useBoolFlag(flagKey, defaultValue) {
255
269
  const { client } = useAvsbContext();
256
- const noClientSentinel = (0, import_core2.notFoundFlag)(defaultValue, "no client");
257
- const flagRef = (0, import_vue6.ref)(
258
- client !== null && typeof client.getBoolFlag === "function" ? client.getBoolFlag(flagKey, defaultValue) : noClientSentinel
270
+ return bindFlagRef(
271
+ client,
272
+ flagKey,
273
+ (c, key) => c.getBoolFlag(key, defaultValue, RENDER_SAFE)
259
274
  );
260
- let unsub;
261
- (0, import_vue6.onMounted)(() => {
262
- if (!client || typeof client.subscribe !== "function") return;
263
- if (typeof client.getBoolFlag === "function") {
264
- flagRef.value = client.getBoolFlag(flagKey, defaultValue);
265
- }
266
- unsub = client.subscribe(flagKey, () => {
267
- if (typeof client.getBoolFlag === "function") {
268
- flagRef.value = client.getBoolFlag(flagKey, defaultValue);
269
- }
270
- });
271
- });
272
- (0, import_vue6.onUnmounted)(() => {
273
- unsub?.();
274
- });
275
- return (0, import_vue6.computed)(() => flagRef.value);
276
275
  }
277
276
 
278
277
  // src/composables/useStringFlag.ts
279
- var import_vue7 = require("vue");
280
- var import_core3 = require("@avsbhq/core");
281
278
  function useStringFlag(flagKey, defaultValue) {
282
279
  const { client } = useAvsbContext();
283
- const noClientSentinel = (0, import_core3.notFoundFlag)(defaultValue, "no client");
284
- const flagRef = (0, import_vue7.ref)(
285
- client !== null && typeof client.getStringFlag === "function" ? client.getStringFlag(flagKey, defaultValue) : noClientSentinel
280
+ return bindFlagRef(
281
+ client,
282
+ flagKey,
283
+ (c, key) => c.getStringFlag(key, defaultValue, RENDER_SAFE)
286
284
  );
287
- let unsub;
288
- (0, import_vue7.onMounted)(() => {
289
- if (!client || typeof client.subscribe !== "function") return;
290
- if (typeof client.getStringFlag === "function") {
291
- flagRef.value = client.getStringFlag(flagKey, defaultValue);
292
- }
293
- unsub = client.subscribe(flagKey, () => {
294
- if (typeof client.getStringFlag === "function") {
295
- flagRef.value = client.getStringFlag(flagKey, defaultValue);
296
- }
297
- });
298
- });
299
- (0, import_vue7.onUnmounted)(() => {
300
- unsub?.();
301
- });
302
- return (0, import_vue7.computed)(() => flagRef.value);
303
285
  }
304
286
 
305
287
  // src/composables/useNumberFlag.ts
306
- var import_vue8 = require("vue");
307
- var import_core4 = require("@avsbhq/core");
308
288
  function useNumberFlag(flagKey, defaultValue) {
309
289
  const { client } = useAvsbContext();
310
- const noClientSentinel = (0, import_core4.notFoundFlag)(defaultValue, "no client");
311
- const flagRef = (0, import_vue8.ref)(
312
- client !== null && typeof client.getNumberFlag === "function" ? client.getNumberFlag(flagKey, defaultValue) : noClientSentinel
290
+ return bindFlagRef(
291
+ client,
292
+ flagKey,
293
+ (c, key) => c.getNumberFlag(key, defaultValue, RENDER_SAFE)
313
294
  );
314
- let unsub;
315
- (0, import_vue8.onMounted)(() => {
316
- if (!client || typeof client.subscribe !== "function") return;
317
- if (typeof client.getNumberFlag === "function") {
318
- flagRef.value = client.getNumberFlag(flagKey, defaultValue);
319
- }
320
- unsub = client.subscribe(flagKey, () => {
321
- if (typeof client.getNumberFlag === "function") {
322
- flagRef.value = client.getNumberFlag(flagKey, defaultValue);
323
- }
324
- });
325
- });
326
- (0, import_vue8.onUnmounted)(() => {
327
- unsub?.();
328
- });
329
- return (0, import_vue8.computed)(() => flagRef.value);
330
295
  }
331
296
 
332
297
  // src/composables/useJsonFlag.ts
333
- var import_vue9 = require("vue");
334
- var import_core5 = require("@avsbhq/core");
335
298
  function useJsonFlag(flagKey, defaultValue) {
336
299
  const { client } = useAvsbContext();
337
- const noClientSentinel = (0, import_core5.notFoundFlag)(defaultValue, "no client");
338
- const flagRef = (0, import_vue9.ref)(
339
- client !== null && typeof client.getJsonFlag === "function" ? client.getJsonFlag(flagKey, defaultValue) : noClientSentinel
300
+ return bindFlagRef(
301
+ client,
302
+ flagKey,
303
+ (c, key) => c.getJsonFlag(key, defaultValue, RENDER_SAFE)
340
304
  );
341
- let unsub;
342
- (0, import_vue9.onMounted)(() => {
343
- if (!client || typeof client.subscribe !== "function") return;
344
- if (typeof client.getJsonFlag === "function") {
345
- flagRef.value = client.getJsonFlag(flagKey, defaultValue);
346
- }
347
- unsub = client.subscribe(flagKey, () => {
348
- if (typeof client.getJsonFlag === "function") {
349
- flagRef.value = client.getJsonFlag(flagKey, defaultValue);
350
- }
351
- });
352
- });
353
- (0, import_vue9.onUnmounted)(() => {
354
- unsub?.();
355
- });
356
- return (0, import_vue9.computed)(() => flagRef.value);
357
305
  }
358
306
 
359
307
  // src/composables/useAllFlags.ts
360
- var import_vue10 = require("vue");
308
+ var import_vue6 = require("vue");
361
309
  function useAllFlags() {
362
310
  const { client } = useAvsbContext();
363
- const snapshotRef = (0, import_vue10.ref)(
364
- client !== null && typeof client.getAllFlags === "function" ? client.getAllFlags() : {}
365
- );
366
- let unsub;
367
- (0, import_vue10.onMounted)(() => {
368
- if (!client || typeof client.on !== "function") return;
369
- if (typeof client.getAllFlags === "function") {
370
- snapshotRef.value = client.getAllFlags();
371
- }
372
- unsub = client.on("flagChange", () => {
373
- if (typeof client.getAllFlags === "function") {
374
- snapshotRef.value = client.getAllFlags();
375
- }
376
- });
377
- });
378
- (0, import_vue10.onUnmounted)(() => {
379
- unsub?.();
311
+ const current = (0, import_vue6.shallowRef)(client.getAllFlags());
312
+ const unsubscribe = client.on("flagChange", () => {
313
+ current.value = client.getAllFlags();
380
314
  });
381
- return (0, import_vue10.computed)(() => snapshotRef.value);
315
+ (0, import_vue6.onScopeDispose)(unsubscribe);
316
+ return (0, import_vue6.computed)(() => current.value);
382
317
  }
383
318
 
384
319
  // src/composables/useFlagReady.ts
385
- var import_vue11 = require("vue");
320
+ var import_vue7 = require("vue");
386
321
  function useFlagReady() {
387
322
  const context = useAvsbContext();
388
- return (0, import_vue11.computed)(() => context.status === "ready");
323
+ return (0, import_vue7.computed)(() => context.status === "ready");
324
+ }
325
+
326
+ // src/composables/useAvsbStatus.ts
327
+ var import_vue8 = require("vue");
328
+ function useAvsbStatus() {
329
+ const context = useAvsbContext();
330
+ return {
331
+ status: (0, import_vue8.computed)(() => context.status),
332
+ error: (0, import_vue8.computed)(() => context.error),
333
+ degraded: (0, import_vue8.computed)(() => context.degraded)
334
+ };
389
335
  }
390
336
 
391
337
  // src/composables/useAvsbClient.ts
392
338
  function useAvsbClient() {
393
- const { client } = useAvsbContext();
394
- return client;
339
+ return useAvsbContext().client;
395
340
  }
396
341
 
397
342
  // src/composables/useIdentify.ts
398
- var import_vue12 = require("vue");
399
343
  function useIdentify() {
400
344
  const { client } = useAvsbContext();
401
- const clientRef = (0, import_vue12.ref)(client);
402
- clientRef.value = client;
403
- function identify(ctx) {
404
- const c = clientRef.value;
405
- if (!c || typeof c.identify !== "function") return;
406
- c.identify(ctx);
407
- }
408
- return identify;
345
+ return (context) => {
346
+ client.identify(context);
347
+ };
409
348
  }
410
349
 
411
350
  // src/composables/useAlias.ts
412
- var import_vue13 = require("vue");
413
351
  function useAlias() {
414
352
  const { client } = useAvsbContext();
415
- const clientRef = (0, import_vue13.ref)(client);
416
- clientRef.value = client;
417
- async function alias(prev, next) {
418
- const c = clientRef.value;
419
- if (!c || typeof c.alias !== "function") return;
420
- await c.alias(prev, next);
421
- }
422
- return alias;
353
+ return (previousContext, newContext) => {
354
+ client.alias(previousContext, newContext);
355
+ };
356
+ }
357
+
358
+ // src/composables/useReset.ts
359
+ function useReset() {
360
+ const { client } = useAvsbContext();
361
+ return () => {
362
+ client.reset();
363
+ };
423
364
  }
424
365
 
425
366
  // src/composables/useTrack.ts
426
- var import_vue14 = require("vue");
427
367
  function useTrack() {
428
368
  const { client } = useAvsbContext();
429
- const clientRef = (0, import_vue14.ref)(client);
430
- clientRef.value = client;
431
- function track(eventKey, payload) {
432
- const c = clientRef.value;
433
- if (!c || typeof c.track !== "function") return;
434
- c.track(eventKey, payload);
369
+ return (eventKey, payload) => {
370
+ client.track(eventKey, payload);
371
+ };
372
+ }
373
+
374
+ // src/composables/useExposure.ts
375
+ var import_vue9 = require("vue");
376
+
377
+ // src/internal/fireExposure.ts
378
+ function fireExposureWhenReady(client, flagKey) {
379
+ if (client.isReady()) {
380
+ client.getFlag(flagKey, null);
381
+ return () => {
382
+ };
435
383
  }
436
- return track;
384
+ const off = client.on("ready", () => {
385
+ client.getFlag(flagKey, null);
386
+ off();
387
+ });
388
+ return off;
437
389
  }
438
390
 
439
- // src/pinia.ts
440
- var import_pinia = require("pinia");
441
- var import_vue15 = require("vue");
442
- var import_vue16 = require("vue");
443
- var useAvsbStore = (0, import_pinia.defineStore)("avsb", () => {
444
- const injectedContext = (0, import_vue16.inject)(AvsbInjectionKey);
445
- const _client = (0, import_vue15.ref)(injectedContext?.client ?? null);
446
- const _status = (0, import_vue15.ref)(
447
- injectedContext?.status ?? "loading"
448
- );
449
- const _error = (0, import_vue15.ref)(injectedContext?.error);
450
- if (injectedContext) {
391
+ // src/composables/useExposure.ts
392
+ function useExposure(flagKey) {
393
+ const { client } = useAvsbContext();
394
+ let cancel;
395
+ const fire = (key) => {
396
+ cancel?.();
397
+ cancel = fireExposureWhenReady(client, key);
398
+ };
399
+ (0, import_vue9.onMounted)(() => {
400
+ fire(resolveFlagKey(flagKey));
401
+ });
402
+ if (typeof flagKey !== "string") {
403
+ (0, import_vue9.watch)(flagKey, (next) => fire(next));
451
404
  }
452
- const client = (0, import_vue15.computed)(
453
- () => injectedContext ? injectedContext.client : _client.value
454
- );
455
- const status = (0, import_vue15.computed)(
456
- () => injectedContext ? injectedContext.status : _status.value
457
- );
458
- const error = (0, import_vue15.computed)(
459
- () => injectedContext ? injectedContext.error : _error.value
460
- );
461
- function setClient(c) {
462
- _client.value = c;
463
- _status.value = "loading";
464
- _error.value = void 0;
465
- if (!c) return;
466
- c.onReady().then(() => {
467
- _status.value = "ready";
468
- }).catch((err) => {
469
- _status.value = "error";
470
- _error.value = err instanceof Error ? err : new Error(String(err));
405
+ (0, import_vue9.onUnmounted)(() => {
406
+ cancel?.();
407
+ cancel = void 0;
408
+ });
409
+ }
410
+
411
+ // src/composables/useFlagSubscription.ts
412
+ var import_vue10 = require("vue");
413
+ function useFlagSubscription(flagKey, callback) {
414
+ const { client } = useAvsbContext();
415
+ let unsubscribe;
416
+ const subscribe = (key) => {
417
+ unsubscribe?.();
418
+ unsubscribe = client.subscribe(key, () => {
419
+ callback(client.getSnapshot(key, void 0));
471
420
  });
472
- }
473
- function identify(ctx) {
474
- const c = client.value;
475
- if (!c || typeof c.identify !== "function") return;
476
- c.identify(ctx);
477
- }
478
- function track(eventKey, payload) {
479
- const c = client.value;
480
- if (!c || typeof c.track !== "function") return;
481
- c.track(eventKey, payload);
482
- }
483
- async function alias(prev, next) {
484
- const c = client.value;
485
- if (!c || typeof c.alias !== "function") return;
486
- await c.alias(prev, next);
487
- }
488
- function reset() {
489
- const c = client.value;
490
- if (!c || typeof c.reset !== "function") return;
491
- c.reset();
492
- }
493
- return {
494
- client,
495
- status,
496
- error,
497
- setClient,
498
- identify,
499
- track,
500
- alias,
501
- reset
502
421
  };
503
- });
422
+ subscribe(resolveFlagKey(flagKey));
423
+ const stopWatcher = typeof flagKey === "string" ? void 0 : (0, import_vue10.watch)(flagKey, (next) => subscribe(next), { flush: "sync" });
424
+ (0, import_vue10.onScopeDispose)(() => {
425
+ stopWatcher?.();
426
+ unsubscribe?.();
427
+ unsubscribe = void 0;
428
+ });
429
+ }
430
+
431
+ // src/index.ts
432
+ var import_core2 = require("@avsbhq/core");
504
433
  // Annotate the CommonJS export names for ESM import in node:
505
434
  0 && (module.exports = {
506
435
  AvsbInjectionKey,
507
436
  AvsbPlugin,
508
437
  AvsbProvider,
438
+ DecideOption,
509
439
  useAlias,
510
440
  useAllFlags,
511
441
  useAvsbClient,
512
- useAvsbStore,
442
+ useAvsbStatus,
513
443
  useBoolFlag,
444
+ useExposure,
514
445
  useFlag,
515
446
  useFlagReady,
447
+ useFlagSubscription,
516
448
  useFlagValue,
517
449
  useIdentify,
518
450
  useJsonFlag,
519
451
  useNumberFlag,
452
+ useReset,
520
453
  useStringFlag,
521
454
  useTrack
522
455
  });