@nexussdk/sdk 0.0.3 → 0.0.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/README.md CHANGED
@@ -106,6 +106,44 @@ function CheckoutPage() {
106
106
 
107
107
  ---
108
108
 
109
+ ## Vue 3 & Nuxt 4 Integration
110
+
111
+ Install `NexusPlugin` and use the `<NexusGuard>` error boundary component:
112
+
113
+ ```typescript
114
+ // main.ts
115
+ import { createApp } from 'vue';
116
+ import { NexusPlugin } from '@nexussdk/sdk/vue';
117
+ import App from './App.vue';
118
+
119
+ const app = createApp(App);
120
+ app.use(NexusPlugin, {
121
+ apiKey: 'pk_live_your_client_key',
122
+ environment: 'production',
123
+ autoCapture: true,
124
+ realtime: true,
125
+ });
126
+ app.mount('#app');
127
+ ```
128
+
129
+ ```vue
130
+ <!-- App.vue -->
131
+ <script setup lang="ts">
132
+ import { useFeatureFlag, NexusGuard } from '@nexussdk/sdk/vue';
133
+
134
+ const { isEnabled } = useFeatureFlag('new-checkout-flow', false);
135
+ </script>
136
+
137
+ <template>
138
+ <NexusGuard>
139
+ <button v-if="isEnabled">1-Click Express Checkout</button>
140
+ <button v-else>Standard Checkout</button>
141
+ </NexusGuard>
142
+ </template>
143
+ ```
144
+
145
+ ---
146
+
109
147
  ## Architecture & Subpackages
110
148
 
111
149
  `@nexussdk/sdk` bundles the following specialized modules for maximum modularity:
@@ -114,8 +152,8 @@ function CheckoutPage() {
114
152
  |---|---|
115
153
  | [`@nexussdk/contracts`](https://www.npmjs.com/package/@nexussdk/contracts) | SSOT TypeScript types and RFC 7807 error models |
116
154
  | [`@nexussdk/core`](https://www.npmjs.com/package/@nexussdk/core) | Ring buffer transport kernel and environment resolvers |
117
- | [`@nexussdk/flags`](https://www.npmjs.com/package/@nexussdk/flags) | Standalone feature flag evaluator and SSE manager |
118
- | [`@nexussdk/tracker`](https://www.npmjs.com/package/@nexussdk/tracker) | Standalone error tracker and PII sanitizer |
155
+ | [`@nexussdk/flags`](https://www.npmjs.com/package/@nexussdk/flags) | Standalone feature flag evaluator, local dev server (`nexus-flags-dev`) & SSE manager |
156
+ | [`@nexussdk/tracker`](https://www.npmjs.com/package/@nexussdk/tracker) | Standalone error tracker, local dev server (`nexus-dev`) & PII sanitizer |
119
157
 
120
158
  ---
121
159
 
package/dist/index.cjs CHANGED
@@ -1 +1,2 @@
1
- 'use strict';var flags=require('@nexussdk/flags'),tracker=require('@nexussdk/tracker');var n=class t{static instance=null;flags;tracker;constructor(e={}){let{apiKey:s,baseUrl:r,user:a,environment:i,tags:o,autoCapture:c,flags:l,tracker:u}=e;this.flags=new flags.NexusFlagsClient({apiKey:s,baseUrl:r,user:a,...l}),this.tracker=new tracker.NexusTrackerClient({apiKey:s,baseUrl:r,environment:i,tags:o,autoCapture:c,...u});}static init(e={}){return t.instance||(t.instance=new t(e)),t.instance}static getInstance(){if(!t.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return t.instance}static isEnabled(e,s=false){return t.getInstance().flags.isEnabled(e,s)}static getVariant(e,s,r){return t.getInstance().flags.getVariant(e,s,r)}static captureError(e,s){t.getInstance().tracker.captureError(e,s);}static async identify(e){let s=t.getInstance();s.tracker.setUser(e),await s.flags.identify(e);}static reset(){let e=t.getInstance();e.tracker.setUser(null),e.flags.reset();}static async destroy(){t.instance&&(await t.instance.tracker.flush(),t.instance.tracker.destroy(),t.instance.flags.destroy(),t.instance=null);}};Object.defineProperty(exports,"NexusFlagsClient",{enumerable:true,get:function(){return flags.NexusFlagsClient}});Object.defineProperty(exports,"NexusTrackerClient",{enumerable:true,get:function(){return tracker.NexusTrackerClient}});exports.Nexus=n;
1
+ 'use strict';var flags=require('@nexussdk/flags'),tracker=require('@nexussdk/tracker');var o=class t{static instance=null;static vitalsCleanup=null;flags;tracker;constructor(e={}){let{apiKey:r,baseUrl:s,user:u,environment:p,tags:g,autoCapture:x,sampling:d,transport:f,vitals:n,devServer:a,flags:v,tracker:m}=e;this.flags=new flags.NexusFlagsClient({apiKey:r,baseUrl:s,user:u,...v});let l=s,b=f;if(a?.enabled){let i=a.port??4567;l=`http://${a.host??"localhost"}:${i}`;}if(this.tracker=new tracker.NexusTrackerClient({apiKey:r,baseUrl:l,environment:p,tags:g,autoCapture:x,sampling:d,transport:b,...m}),n){let i=typeof n=="object"?n:{};t.vitalsCleanup=tracker.attachWebVitals(this.tracker,i);}}static init(e={}){return t.instance||(t.instance=new t(e)),t.instance}static getInstance(){if(!t.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return t.instance}static isEnabled(e,r=false){return t.getInstance().flags.isEnabled(e,r)}static getVariant(e,r,s){return t.getInstance().flags.getVariant(e,r,s)}static captureError(e,r){t.getInstance().tracker.captureError(e,r);}static captureMessage(e,r="info",s){t.getInstance().tracker.captureMessage(e,r,s);}static addBreadcrumb(e){t.getInstance().tracker.addBreadcrumb(e);}static setExtra(e,r){t.getInstance().tracker.setExtra(e,r);}static attachWebVitals(e){return tracker.attachWebVitals(t.getInstance().tracker,e)}static async identify(e){let r=t.getInstance();r.tracker.setUser(e),await r.flags.identify(e);}static reset(){let e=t.getInstance();e.tracker.setUser(null),e.flags.reset();}static async destroy(){t.vitalsCleanup&&(t.vitalsCleanup(),t.vitalsCleanup=null),t.instance&&(await t.instance.tracker.flush(),t.instance.tracker.destroy(),t.instance.flags.destroy(),t.instance=null);}};
2
+ Object.defineProperty(exports,"NexusFlagsClient",{enumerable:true,get:function(){return flags.NexusFlagsClient}});Object.defineProperty(exports,"NexusGuardCore",{enumerable:true,get:function(){return tracker.NexusGuardCore}});Object.defineProperty(exports,"NexusTrackerClient",{enumerable:true,get:function(){return tracker.NexusTrackerClient}});Object.defineProperty(exports,"attachWebVitals",{enumerable:true,get:function(){return tracker.attachWebVitals}});exports.Nexus=o;
package/dist/index.d.mts CHANGED
@@ -1,25 +1,36 @@
1
1
  import { NexusFlagsClient, NexusFlagsOptions } from '@nexussdk/flags';
2
2
  export { INexusFlagsClient, NexusFlagsClient, NexusFlagsOptions } from '@nexussdk/flags';
3
3
  import { NexusTrackerClient, NexusTrackerOptions } from '@nexussdk/tracker';
4
- export { INexusTrackerClient, NexusTrackerClient, NexusTrackerOptions } from '@nexussdk/tracker';
5
- import { UserContext } from '@nexussdk/contracts';
6
- export { ErrorEventPayload, FeatureFlag, FlagEvaluationResult, ProblemDetails, UserContext } from '@nexussdk/contracts';
4
+ export { INexusTrackerClient, NexusGuardCore, NexusGuardCoreOptions, NexusTrackerClient, NexusTrackerOptions, attachWebVitals } from '@nexussdk/tracker';
5
+ import { UserContext, SamplingConfig, TransportPlugin, PerformanceVitalsOptions, SeverityLevel, Breadcrumb } from '@nexussdk/contracts';
6
+ export { Breadcrumb, ErrorEventPayload, FeatureFlag, FlagEvaluationResult, NexusErrorInfo, PerformanceVitalEntry, PerformanceVitalsOptions, ProblemDetails, SamplingConfig, SeverityLevel, TransportPlugin, UserContext } from '@nexussdk/contracts';
7
7
 
8
8
  /**
9
9
  * @fileoverview Unified Nexus singleton facade wrapping Flags and Tracker clients.
10
10
  * @module @nexus/sdk/nexus
11
11
  */
12
12
 
13
+ /**
14
+ * Dev server routing configuration.
15
+ */
16
+ interface NexusDevServerOptions {
17
+ /** Enable local dev server ingestion mode. Auto-enabled in development if true. */
18
+ enabled?: boolean;
19
+ /** Port the dev server is listening on. Defaults to 4567. */
20
+ port?: number;
21
+ /** Host the dev server is bound to. Defaults to 'localhost'. */
22
+ host?: string;
23
+ }
13
24
  /**
14
25
  * Unified initialization options for the Nexus SDK umbrella.
15
26
  *
16
27
  * @example
17
28
  * Nexus.init({
18
29
  * apiKey: 'pk_live_...',
19
- * baseUrl: 'http://localhost:8080',
20
30
  * user: { id: 'usr_12345', country: 'VN' },
21
31
  * environment: 'production',
22
32
  * autoCapture: true,
33
+ * devServer: { enabled: process.env.NODE_ENV === 'development' },
23
34
  * });
24
35
  */
25
36
  interface NexusInitOptions {
@@ -35,6 +46,14 @@ interface NexusInitOptions {
35
46
  tags?: Record<string, string>;
36
47
  /** Toggle automated global error capture. Defaults to true. */
37
48
  autoCapture?: boolean;
49
+ /** Client-side rate limiting and deduplication sampling options. */
50
+ sampling?: SamplingConfig;
51
+ /** Pluggable transport adapter ('fetch', 'console', 'localStorage', custom fn). */
52
+ transport?: TransportPlugin;
53
+ /** Web Vitals performance observer options, or true for default observation. */
54
+ vitals?: boolean | PerformanceVitalsOptions;
55
+ /** Local dev server auto-routing configuration. */
56
+ devServer?: NexusDevServerOptions;
38
57
  /** Additional flags-specific options. */
39
58
  flags?: Partial<NexusFlagsOptions>;
40
59
  /** Additional tracker-specific options. */
@@ -61,6 +80,7 @@ interface NexusInitOptions {
61
80
  */
62
81
  declare class Nexus {
63
82
  private static instance;
83
+ private static vitalsCleanup;
64
84
  /** The underlying feature flags client instance. */
65
85
  readonly flags: NexusFlagsClient;
66
86
  /** The underlying error tracker client instance. */
@@ -73,9 +93,6 @@ declare class Nexus {
73
93
  *
74
94
  * @param options - SDK configuration options.
75
95
  * @returns The initialized Nexus singleton instance.
76
- *
77
- * @example
78
- * const nexus = Nexus.init({ apiKey: 'pk_live_...' });
79
96
  */
80
97
  static init(options?: NexusInitOptions): Nexus;
81
98
  /**
@@ -83,69 +100,48 @@ declare class Nexus {
83
100
  *
84
101
  * @returns The active Nexus instance.
85
102
  * @throws {Error} If `Nexus.init()` has not been called yet.
86
- *
87
- * @example
88
- * const nexus = Nexus.getInstance();
89
- * nexus.flags.isEnabled('checkout_v2');
90
103
  */
91
104
  static getInstance(): Nexus;
92
105
  /**
93
106
  * Convenience method: Check if a feature flag is enabled.
94
- *
95
- * @param key - Flag identifier.
96
- * @param defaultValue - Fallback if flag is missing.
97
- * @returns Boolean enabled state.
98
- *
99
- * @example
100
- * if (Nexus.isEnabled('checkout_redesign')) { ... }
101
107
  */
102
108
  static isEnabled(key: string, defaultValue?: boolean): boolean;
103
109
  /**
104
110
  * Convenience method: Get a flag variant value.
105
- *
106
- * @param key - Flag identifier.
107
- * @param variantKey - Variant property name.
108
- * @param defaultValue - Fallback value.
109
- * @returns Variant value cast to type T.
110
- *
111
- * @example
112
- * const rate = Nexus.getVariant<number>('promo_banner_v2', 'discount_rate', 10);
113
111
  */
114
112
  static getVariant<T = unknown>(key: string, variantKey: string, defaultValue?: T): T;
115
113
  /**
116
114
  * Convenience method: Capture an error manually.
117
- *
118
- * @param error - Error instance, string, or unknown value.
119
- * @param extra - Optional metadata tags.
120
- *
121
- * @example
122
- * Nexus.captureError(new TypeError('Cannot read properties of null'));
123
115
  */
124
116
  static captureError(error: unknown, extra?: Record<string, unknown>): void;
117
+ /**
118
+ * Convenience method: Capture an informational or warning message event.
119
+ */
120
+ static captureMessage(message: string, level?: SeverityLevel, extra?: Record<string, unknown>): void;
121
+ /**
122
+ * Convenience method: Add a breadcrumb manually.
123
+ */
124
+ static addBreadcrumb(breadcrumb: Breadcrumb): void;
125
+ /**
126
+ * Convenience method: Set extra contextual metadata.
127
+ */
128
+ static setExtra(key: string, value: unknown): void;
129
+ /**
130
+ * Convenience method: Attach Web Vitals observer to tracker.
131
+ */
132
+ static attachWebVitals(options?: PerformanceVitalsOptions): () => void;
125
133
  /**
126
134
  * Convenience method: Update user context for both flags and tracker.
127
- *
128
- * @param user - New user context (merged with existing).
129
- * @returns Promise resolving after flags refresh.
130
- *
131
- * @example
132
- * await Nexus.identify({ id: 'usr_12345', country: 'VN' });
133
135
  */
134
136
  static identify(user: UserContext): Promise<void>;
135
137
  /**
136
138
  * Resets user context to anonymous state (e.g. on logout).
137
- *
138
- * @example
139
- * Nexus.reset(); // called on user logout
140
139
  */
141
140
  static reset(): void;
142
141
  /**
143
142
  * Gracefully tears down both clients, closing SSE connections and flushing pending events.
144
- *
145
- * @example
146
- * await Nexus.destroy();
147
143
  */
148
144
  static destroy(): Promise<void>;
149
145
  }
150
146
 
151
- export { Nexus, type NexusInitOptions };
147
+ export { Nexus, type NexusDevServerOptions, type NexusInitOptions };
package/dist/index.d.ts CHANGED
@@ -1,25 +1,36 @@
1
1
  import { NexusFlagsClient, NexusFlagsOptions } from '@nexussdk/flags';
2
2
  export { INexusFlagsClient, NexusFlagsClient, NexusFlagsOptions } from '@nexussdk/flags';
3
3
  import { NexusTrackerClient, NexusTrackerOptions } from '@nexussdk/tracker';
4
- export { INexusTrackerClient, NexusTrackerClient, NexusTrackerOptions } from '@nexussdk/tracker';
5
- import { UserContext } from '@nexussdk/contracts';
6
- export { ErrorEventPayload, FeatureFlag, FlagEvaluationResult, ProblemDetails, UserContext } from '@nexussdk/contracts';
4
+ export { INexusTrackerClient, NexusGuardCore, NexusGuardCoreOptions, NexusTrackerClient, NexusTrackerOptions, attachWebVitals } from '@nexussdk/tracker';
5
+ import { UserContext, SamplingConfig, TransportPlugin, PerformanceVitalsOptions, SeverityLevel, Breadcrumb } from '@nexussdk/contracts';
6
+ export { Breadcrumb, ErrorEventPayload, FeatureFlag, FlagEvaluationResult, NexusErrorInfo, PerformanceVitalEntry, PerformanceVitalsOptions, ProblemDetails, SamplingConfig, SeverityLevel, TransportPlugin, UserContext } from '@nexussdk/contracts';
7
7
 
8
8
  /**
9
9
  * @fileoverview Unified Nexus singleton facade wrapping Flags and Tracker clients.
10
10
  * @module @nexus/sdk/nexus
11
11
  */
12
12
 
13
+ /**
14
+ * Dev server routing configuration.
15
+ */
16
+ interface NexusDevServerOptions {
17
+ /** Enable local dev server ingestion mode. Auto-enabled in development if true. */
18
+ enabled?: boolean;
19
+ /** Port the dev server is listening on. Defaults to 4567. */
20
+ port?: number;
21
+ /** Host the dev server is bound to. Defaults to 'localhost'. */
22
+ host?: string;
23
+ }
13
24
  /**
14
25
  * Unified initialization options for the Nexus SDK umbrella.
15
26
  *
16
27
  * @example
17
28
  * Nexus.init({
18
29
  * apiKey: 'pk_live_...',
19
- * baseUrl: 'http://localhost:8080',
20
30
  * user: { id: 'usr_12345', country: 'VN' },
21
31
  * environment: 'production',
22
32
  * autoCapture: true,
33
+ * devServer: { enabled: process.env.NODE_ENV === 'development' },
23
34
  * });
24
35
  */
25
36
  interface NexusInitOptions {
@@ -35,6 +46,14 @@ interface NexusInitOptions {
35
46
  tags?: Record<string, string>;
36
47
  /** Toggle automated global error capture. Defaults to true. */
37
48
  autoCapture?: boolean;
49
+ /** Client-side rate limiting and deduplication sampling options. */
50
+ sampling?: SamplingConfig;
51
+ /** Pluggable transport adapter ('fetch', 'console', 'localStorage', custom fn). */
52
+ transport?: TransportPlugin;
53
+ /** Web Vitals performance observer options, or true for default observation. */
54
+ vitals?: boolean | PerformanceVitalsOptions;
55
+ /** Local dev server auto-routing configuration. */
56
+ devServer?: NexusDevServerOptions;
38
57
  /** Additional flags-specific options. */
39
58
  flags?: Partial<NexusFlagsOptions>;
40
59
  /** Additional tracker-specific options. */
@@ -61,6 +80,7 @@ interface NexusInitOptions {
61
80
  */
62
81
  declare class Nexus {
63
82
  private static instance;
83
+ private static vitalsCleanup;
64
84
  /** The underlying feature flags client instance. */
65
85
  readonly flags: NexusFlagsClient;
66
86
  /** The underlying error tracker client instance. */
@@ -73,9 +93,6 @@ declare class Nexus {
73
93
  *
74
94
  * @param options - SDK configuration options.
75
95
  * @returns The initialized Nexus singleton instance.
76
- *
77
- * @example
78
- * const nexus = Nexus.init({ apiKey: 'pk_live_...' });
79
96
  */
80
97
  static init(options?: NexusInitOptions): Nexus;
81
98
  /**
@@ -83,69 +100,48 @@ declare class Nexus {
83
100
  *
84
101
  * @returns The active Nexus instance.
85
102
  * @throws {Error} If `Nexus.init()` has not been called yet.
86
- *
87
- * @example
88
- * const nexus = Nexus.getInstance();
89
- * nexus.flags.isEnabled('checkout_v2');
90
103
  */
91
104
  static getInstance(): Nexus;
92
105
  /**
93
106
  * Convenience method: Check if a feature flag is enabled.
94
- *
95
- * @param key - Flag identifier.
96
- * @param defaultValue - Fallback if flag is missing.
97
- * @returns Boolean enabled state.
98
- *
99
- * @example
100
- * if (Nexus.isEnabled('checkout_redesign')) { ... }
101
107
  */
102
108
  static isEnabled(key: string, defaultValue?: boolean): boolean;
103
109
  /**
104
110
  * Convenience method: Get a flag variant value.
105
- *
106
- * @param key - Flag identifier.
107
- * @param variantKey - Variant property name.
108
- * @param defaultValue - Fallback value.
109
- * @returns Variant value cast to type T.
110
- *
111
- * @example
112
- * const rate = Nexus.getVariant<number>('promo_banner_v2', 'discount_rate', 10);
113
111
  */
114
112
  static getVariant<T = unknown>(key: string, variantKey: string, defaultValue?: T): T;
115
113
  /**
116
114
  * Convenience method: Capture an error manually.
117
- *
118
- * @param error - Error instance, string, or unknown value.
119
- * @param extra - Optional metadata tags.
120
- *
121
- * @example
122
- * Nexus.captureError(new TypeError('Cannot read properties of null'));
123
115
  */
124
116
  static captureError(error: unknown, extra?: Record<string, unknown>): void;
117
+ /**
118
+ * Convenience method: Capture an informational or warning message event.
119
+ */
120
+ static captureMessage(message: string, level?: SeverityLevel, extra?: Record<string, unknown>): void;
121
+ /**
122
+ * Convenience method: Add a breadcrumb manually.
123
+ */
124
+ static addBreadcrumb(breadcrumb: Breadcrumb): void;
125
+ /**
126
+ * Convenience method: Set extra contextual metadata.
127
+ */
128
+ static setExtra(key: string, value: unknown): void;
129
+ /**
130
+ * Convenience method: Attach Web Vitals observer to tracker.
131
+ */
132
+ static attachWebVitals(options?: PerformanceVitalsOptions): () => void;
125
133
  /**
126
134
  * Convenience method: Update user context for both flags and tracker.
127
- *
128
- * @param user - New user context (merged with existing).
129
- * @returns Promise resolving after flags refresh.
130
- *
131
- * @example
132
- * await Nexus.identify({ id: 'usr_12345', country: 'VN' });
133
135
  */
134
136
  static identify(user: UserContext): Promise<void>;
135
137
  /**
136
138
  * Resets user context to anonymous state (e.g. on logout).
137
- *
138
- * @example
139
- * Nexus.reset(); // called on user logout
140
139
  */
141
140
  static reset(): void;
142
141
  /**
143
142
  * Gracefully tears down both clients, closing SSE connections and flushing pending events.
144
- *
145
- * @example
146
- * await Nexus.destroy();
147
143
  */
148
144
  static destroy(): Promise<void>;
149
145
  }
150
146
 
151
- export { Nexus, type NexusInitOptions };
147
+ export { Nexus, type NexusDevServerOptions, type NexusInitOptions };
@@ -1,8 +1,9 @@
1
- var Nexus=(function(exports){'use strict';function f(e,t=1e3,r=3e4){let n=t*Math.pow(2,e),s=Math.min(r,n);return Math.random()*s}function T(e,t){return new Promise((r,n)=>{if(t?.aborted){n(new DOMException("Aborted","AbortError"));return}let s=setTimeout(r,e);t?.addEventListener("abort",()=>{clearTimeout(s),n(new DOMException("Aborted","AbortError"));});})}function O(e){return e>=500||e===429}async function x(e){let{url:t,method:r="GET",headers:n={},body:s,timeoutMs:a=5e3,maxRetries:i=3,retryBaseMs:o=1e3,retryMaxMs:l=3e4,signal:c}=e,d=new Error("Request failed");for(let p=0;p<=i;p++){if(c?.aborted)throw new DOMException("Request aborted by caller.","AbortError");let b=new AbortController,k=setTimeout(()=>b.abort(),a);c?.addEventListener("abort",()=>b.abort());try{let h={method:r,headers:{"Content-Type":"application/json",...n},signal:b.signal};s!==void 0&&(h.body=typeof s=="string"?s:JSON.stringify(s));let u=await fetch(t,h);if(clearTimeout(k),u.ok)return {data:await u.json(),status:u.status,headers:u.headers};if(O(u.status)&&p<i){d=new Error(`HTTP ${u.status}: ${u.statusText}`);let P=f(p,o,l);await T(P,c);continue}let K=await u.text().catch(()=>"");throw new Error(`HTTP ${u.status}: ${K}`)}catch(h){if(clearTimeout(k),h instanceof DOMException&&h.name==="AbortError")throw h;if(d=h instanceof Error?h:new Error(String(h)),p<i){let u=f(p,o,l);await T(u,c);}}}throw d}var C=class{capacity;buffer;head=0;count=0;constructor(e){if(e<1)throw new RangeError(`RingBuffer capacity must be >= 1, got ${e}`);this.capacity=e,this.buffer=new Array(e).fill(void 0);}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this.count<this.capacity&&this.count++;}toArray(){if(this.count===0)return [];let e=[];if(this.count<this.capacity)for(let t=0;t<this.count;t++)e.push(this.buffer[t]);else for(let t=0;t<this.capacity;t++)e.push(this.buffer[(this.head+t)%this.capacity]);return e}get size(){return this.count}get maxCapacity(){return this.capacity}get isFull(){return this.count===this.capacity}clear(){this.buffer.fill(void 0),this.head=0,this.count=0;}peek(){if(this.count===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}};function g(e){try{let t=globalThis.process;if(typeof t<"u"&&t&&t.env)return t.env[e]??void 0}catch{}}function _(e){try{let t=typeof globalThis<"u"&&globalThis.__import_meta__;if(t&&t.env)return t.env[e]??void 0;let r=new Function("try { return import.meta; } catch(e) { return undefined; }")();if(r&&r.env)return r.env[e]??void 0}catch{}}function $(){try{if(typeof window<"u"&&window.__NEXUS_API_KEY__)return window.__NEXUS_API_KEY__}catch{}}function m(e){let t=e||$()||g("NEXUS_API_KEY")||g("NEXT_PUBLIC_NEXUS_API_KEY")||_("VITE_NEXUS_API_KEY")||g("NUXT_PUBLIC_NEXUS_API_KEY");if(!t||t.trim()==="")throw new Error(`[Nexus SDK] No API key found. Please provide one via:
1
+ var Nexus=(function(exports){'use strict';function f(e,t=1e3,r=3e4){let n=t*Math.pow(2,e),s=Math.min(r,n);return Math.random()*s}function L(e,t){return new Promise((r,n)=>{if(t?.aborted){n(new DOMException("Aborted","AbortError"));return}let s=setTimeout(r,e);t?.addEventListener("abort",()=>{clearTimeout(s),n(new DOMException("Aborted","AbortError"));});})}function W(e){return e>=500||e===429}async function M(e){let{url:t,method:r="GET",headers:n={},body:s,timeoutMs:a=5e3,maxRetries:o=3,retryBaseMs:c=1e3,retryMaxMs:u=3e4,signal:i}=e,l=new Error("Request failed");for(let h=0;h<=o;h++){if(i?.aborted)throw new DOMException("Request aborted by caller.","AbortError");let m=new AbortController,b=setTimeout(()=>m.abort(),a);i?.addEventListener("abort",()=>m.abort());try{let p={method:r,headers:{"Content-Type":"application/json",...n},signal:m.signal};s!==void 0&&(p.body=typeof s=="string"?s:JSON.stringify(s));let d=await fetch(t,p);if(clearTimeout(b),d.ok)return {data:await d.json(),status:d.status,headers:d.headers};if(W(d.status)&&h<o){l=new Error(`HTTP ${d.status}: ${d.statusText}`);let I=f(h,c,u);await L(I,i);continue}let y=await d.text().catch(()=>"");throw new Error(`HTTP ${d.status}: ${y}`)}catch(p){if(clearTimeout(b),p instanceof DOMException&&p.name==="AbortError")throw p;if(l=p instanceof Error?p:new Error(String(p)),h<o){let d=f(h,c,u);await L(d,i);}}}throw l}var P=class{capacity;buffer;head=0;count=0;constructor(e){if(e<1)throw new RangeError(`RingBuffer capacity must be >= 1, got ${e}`);this.capacity=e,this.buffer=new Array(e).fill(void 0);}push(e){this.buffer[this.head]=e,this.head=(this.head+1)%this.capacity,this.count<this.capacity&&this.count++;}toArray(){if(this.count===0)return [];let e=[];if(this.count<this.capacity)for(let t=0;t<this.count;t++)e.push(this.buffer[t]);else for(let t=0;t<this.capacity;t++)e.push(this.buffer[(this.head+t)%this.capacity]);return e}get size(){return this.count}get maxCapacity(){return this.capacity}get isFull(){return this.count===this.capacity}clear(){this.buffer.fill(void 0),this.head=0,this.count=0;}peek(){if(this.count===0)return;let e=(this.head-1+this.capacity)%this.capacity;return this.buffer[e]}};function E(e){try{let t=globalThis.process;if(typeof t<"u"&&t&&t.env)return t.env[e]??void 0}catch{}}function O(e){try{let t=typeof globalThis<"u"&&globalThis.__import_meta__;if(t&&t.env)return t.env[e]??void 0;let r=new Function("try { return import.meta; } catch(e) { return undefined; }")();if(r&&r.env)return r.env[e]??void 0}catch{}}function X(){try{if(typeof window<"u"&&window.__NEXUS_API_KEY__)return window.__NEXUS_API_KEY__}catch{}}function w(e){let t=e||X()||E("NEXUS_API_KEY")||E("NEXT_PUBLIC_NEXUS_API_KEY")||O("VITE_NEXUS_API_KEY")||E("NUXT_PUBLIC_NEXUS_API_KEY");if(!t||t.trim()==="")throw new Error(`[Nexus SDK] No API key found. Please provide one via:
2
2
  1. Nexus.init({ apiKey: "pk_live_..." })
3
3
  2. window.__NEXUS_API_KEY__ = "pk_live_..."
4
4
  3. NEXUS_API_KEY env var
5
5
  4. NEXT_PUBLIC_NEXUS_API_KEY (Next.js)
6
6
  5. VITE_NEXUS_API_KEY (Vite)
7
- 6. NUXT_PUBLIC_NEXUS_API_KEY (Nuxt)`);return t.trim()}function y(e,t="https://api.nexus.dev"){return (e||g("NEXT_PUBLIC_NEXUS_URL")||_("VITE_NEXUS_URL")||t).replace(/\/$/,"")}function w(e,t,r,n){if(r>n)return "[MaxDepthExceeded]";if(e==null)return e;if(typeof e!="object"&&typeof e!="function")return typeof e=="bigint"||typeof e=="symbol"?e.toString():typeof e=="function"?"[Function]":e;if(e instanceof Error)return {name:e.name,message:e.message,stack:e.stack};if(t.has(e))return "[Circular]";if(t.add(e),Array.isArray(e)){let a=e.map(i=>w(i,t,r+1,n));return t.delete(e),a}let s={};for(let a of Object.keys(e)){let i=e[a];s[a]=w(i,t,r+1,n);}return t.delete(e),s}function E(e,t=8){let r=w(e,new WeakSet,0,t);try{return JSON.stringify(r)}catch{return JSON.stringify({error:"[SerializationFailed]"})}}function D(e,t=0){let r=t>>>0,n=3432918353,s=461845907,a=0,i=Math.floor(e.length/4)*4;for(;a<i;){let c=e.charCodeAt(a)&255|(e.charCodeAt(a+1)&255)<<8|(e.charCodeAt(a+2)&255)<<16|(e.charCodeAt(a+3)&255)<<24;c=Math.imul(c,n),c=c<<15|c>>>17,c=Math.imul(c,s),r^=c,r=r<<13|r>>>19,r=Math.imul(r,5)+3864292196>>>0,a+=4;}let o=0,l=e.length&3;return l>=3&&(o^=(e.charCodeAt(a+2)&255)<<16),l>=2&&(o^=(e.charCodeAt(a+1)&255)<<8),l>=1&&(o^=e.charCodeAt(a)&255,o=Math.imul(o,n),o=o<<15|o>>>17,o=Math.imul(o,s),r^=o),r^=e.length,r^=r>>>16,r=Math.imul(r,2246822507),r^=r>>>13,r=Math.imul(r,3266489909),r^=r>>>16,r>>>0}function B(e,t){let r=`${e}:${t}`;return D(r)%100}function M(e,t){let r=e.replace(/^v/,"").split(".").map(Number),n=t.replace(/^v/,"").split(".").map(Number);for(let s=0;s<3;s++){let a=(r[s]??0)-(n[s]??0);if(a!==0)return a}return 0}function F(e,t){let r=t.split("."),n=e;for(let s of r){if(n==null||typeof n!="object")return;n=n[s];}return n}function H(e,t){let r=F(t,e.attribute),n=e.values;switch(e.operator){case "EQUALS":return r===n[0];case "NOT_EQUALS":return r!==n[0];case "IN":return n.includes(r);case "NOT_IN":return !n.includes(r);case "CONTAINS":return typeof r=="string"&&r.includes(String(n[0]));case "NOT_CONTAINS":return typeof r=="string"&&!r.includes(String(n[0]));case "STARTS_WITH":return typeof r=="string"&&r.startsWith(String(n[0]));case "ENDS_WITH":return typeof r=="string"&&r.endsWith(String(n[0]));case "GREATER_THAN":return typeof r=="number"&&r>Number(n[0]);case "LESS_THAN":return typeof r=="number"&&r<Number(n[0]);case "SEMVER_GTE":return typeof r=="string"&&typeof n[0]=="string"&&M(r,String(n[0]))>=0;case "SEMVER_LTE":return typeof r=="string"&&typeof n[0]=="string"&&M(r,String(n[0]))<=0;default:return false}}function I(e,t){if(!e.isEnabled)return {key:e.key,enabled:false,variants:{},reason:"KILL_SWITCH",version:e.version};if(e.targetingRules.length>0){if(!e.targetingRules.every(r=>H(r,t)))return {key:e.key,enabled:false,variants:{},reason:"FALLBACK",version:e.version};if(e.rolloutPercentage>=100)return {key:e.key,enabled:true,variants:e.variants,reason:"TARGETING_MATCH",version:e.version}}if(e.rolloutPercentage>0){let r=t.id??"anon";return B(r,e.key)<e.rolloutPercentage?{key:e.key,enabled:true,variants:e.variants,reason:e.targetingRules.length>0?"TARGETING_MATCH":"ROLLOUT_MATCH",version:e.version}:{key:e.key,enabled:false,variants:{},reason:"FALLBACK",version:e.version}}return {key:e.key,enabled:false,variants:{},reason:"KILL_SWITCH",version:e.version}}var j=class{options;eventSource=null;connected=false;destroyed=false;reconnectAttempt=0;reconnectTimer=null;maxReconnects;constructor(e){this.options=e,this.maxReconnects=e.maxReconnects??1/0;}get isConnected(){return this.connected}connect(){this.destroyed||this.connected||this.eventSource||this.openConnection();}disconnect(){this.destroyed=true,this.cleanup();}openConnection(){if(!this.destroyed)try{let e=new URL(this.options.url);e.searchParams.set("apiKey",this.options.apiKey),this.eventSource=new EventSource(e.toString()),this.eventSource.addEventListener("open",()=>{this.connected=!0,this.reconnectAttempt=0,this.options.onStateChange?.(!0);}),this.eventSource.addEventListener("message",t=>{this.handleMessage(t.data);}),this.eventSource.addEventListener("flag_update",t=>{this.handleMessage(t.data);}),this.eventSource.addEventListener("error",()=>{this.connected=!1,this.options.onStateChange?.(!1),this.cleanup(),this.scheduleReconnect();});}catch{this.scheduleReconnect();}}handleMessage(e){try{let t=JSON.parse(e);this.options.onEvent(t);}catch{}}cleanup(){this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.reconnectTimer!==null&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null);}scheduleReconnect(){if(this.destroyed||this.reconnectAttempt>=this.maxReconnects)return;let e=f(this.reconnectAttempt,1e3,3e4);this.reconnectAttempt++,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.destroyed||this.openConnection();},e);}},X="nexus_flags_",R="nexus_anon_id",W=class{memory=new Map;storageKey;localStorageAvailable;broadcastChannel=null;constructor(e){this.storageKey=`${X}${e}`,this.localStorageAvailable=this.testLocalStorage(),this.hydrate(),this.setupBroadcastChannel();}set(e,t){this.memory.set(e,t),this.persist(),this.broadcastUpdate(e,t);}get(e){return this.memory.get(e)}setAll(e){for(let[t,r]of Object.entries(e))this.memory.set(t,r);this.persist();}delete(e){this.memory.delete(e),this.persist();}getAll(){return Object.fromEntries(this.memory.entries())}clear(){if(this.memory.clear(),this.localStorageAvailable)try{window.localStorage.removeItem(this.storageKey);}catch{}this.broadcastChannel?.close();}getOrCreateAnonymousId(){if(typeof window>"u")return "anon-ssr-node";if(this.localStorageAvailable)try{let e=window.localStorage.getItem(R);return e||(e=`anon_${Math.random().toString(36).substring(2,11)}`,window.localStorage.setItem(R,e)),e}catch{}return `anon_${Math.random().toString(36).substring(2,11)}`}testLocalStorage(){try{if(typeof window>"u")return !1;let e="__nexus_test__";return window.localStorage.setItem(e,"1"),window.localStorage.removeItem(e),!0}catch{return false}}hydrate(){if(this.localStorageAvailable)try{let e=window.localStorage.getItem(this.storageKey);if(e){let t=JSON.parse(e);for(let[r,n]of Object.entries(t))this.memory.set(r,n);}}catch{}}persist(){if(this.localStorageAvailable)try{window.localStorage.setItem(this.storageKey,JSON.stringify(Object.fromEntries(this.memory.entries())));}catch{}}setupBroadcastChannel(){try{typeof BroadcastChannel<"u"&&(this.broadcastChannel=new BroadcastChannel(`nexus_flags_${this.storageKey}`),this.broadcastChannel.onmessage=e=>{e.data?.key&&e.data?.result&&this.memory.set(e.data.key,e.data.result);});}catch{}}broadcastUpdate(e,t){try{this.broadcastChannel?.postMessage({key:e,result:t});}catch{}}},S=class{apiKey;baseUrl;timeoutMs;user;storage;listeners=new Map;sseManager;flagDefinitions=new Map;constructor(e={}){this.apiKey=m(e.apiKey),this.baseUrl=y(e.baseUrl),this.timeoutMs=e.timeoutMs??3e3,this.storage=new W(this.apiKey.substring(0,16)),this.user=e.user??{id:this.storage.getOrCreateAnonymousId()},e.bootstrap&&this.storage.setAll(e.bootstrap),e.realtime!==false&&this.initRealtimeSync(),this.refreshFlags();}isEnabled(e,t=false){let r=this.storage.get(e);return r!==void 0?r.enabled:t}getVariant(e,t,r){let n=this.storage.get(e);if(!n?.enabled||!n.variants)return r;let s=n.variants[t];return s!==void 0?s:r}async identify(e){this.user={...this.user,...e},await this.refreshFlags();}reset(){this.user={id:this.storage.getOrCreateAnonymousId()},this.refreshFlags();}onFlagChange(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.listeners.get(e)?.delete(t)}destroy(){this.sseManager?.disconnect(),this.listeners.clear(),this.storage.clear();}initRealtimeSync(){this.sseManager=new j({url:`${this.baseUrl}/api/v1/flags/stream`,apiKey:this.apiKey,onEvent:e=>{if(e.type==="FLAG_UPDATE"&&e.data){let t=this.flagDefinitions.get(e.key),r=t?I(t,this.user):e.data;this.storage.set(e.key,r),this.listeners.get(e.key)?.forEach(n=>n(r));}else e.type==="FLAG_DELETE"&&(this.storage.delete(e.key),this.flagDefinitions.delete(e.key));}}),this.sseManager.connect();}async refreshFlags(){try{let e=await x({url:`${this.baseUrl}/api/v1/flags/eval`,method:"GET",headers:{Authorization:`Bearer ${this.apiKey}`,"X-Nexus-User-Id":this.user.id??"anon","X-Nexus-Country":this.user.country??""},timeoutMs:this.timeoutMs,maxRetries:2});for(let[t,r]of Object.entries(e.data)){this.flagDefinitions.set(t,r);let n=I(r,this.user);this.storage.set(t,n),this.listeners.get(t)?.forEach(s=>s(n));}}catch{}}};var z=/^(password|passwd|token|secret|authorization|bearer|auth|credit_?card|cvv|cvc|ssn|api_?key|access_?token|refresh_?token)$/i,Y=/\b(?:\d[ -]*?){13,16}\b/g,G=/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,U=/([?&](token|auth|key|secret|password|api_key|access_token|refresh_token)=)[^&]*/gi;function V(e){return e.replace(Y,"[CARD_REDACTED]").replace(G,"[EMAIL_REDACTED]").replace(U,"$1[REDACTED]")}function v(e,t=0){if(t>5)return "[MaxDepthExceeded]";if(e==null)return e;if(typeof e=="string")return V(e);if(typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>v(n,t+1));let r={};for(let[n,s]of Object.entries(e))z.test(n)?r[n]="[REDACTED]":r[n]=v(s,t+1);return r}function L(e){return e.replace(U,"$1[REDACTED]")}function J(e){if(!e)return [];let t=[],r=e.split(`
8
- `);for(let n of r){let s=n.trim(),a=s.match(/^at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)$/)||s.match(/^at\s+(.+?):(\d+):(\d+)$/)||s.match(/^at\s+\((.+?):(\d+):(\d+)\)$/);if(a){a.length===5?t.push({functionName:a[1]??"<anonymous>",fileName:a[2]??"<unknown>",lineNumber:parseInt(a[3]??"0",10),columnNumber:parseInt(a[4]??"0",10)}):a.length===4&&t.push({functionName:"<anonymous>",fileName:a[1]??"<unknown>",lineNumber:parseInt(a[2]??"0",10),columnNumber:parseInt(a[3]??"0",10)});continue}let i=s.match(/^(.+?)@(.+?):(\d+):(\d+)$/);i&&t.push({functionName:i[1]??"<anonymous>",fileName:i[2]??"<unknown>",lineNumber:parseInt(i[3]??"0",10),columnNumber:parseInt(i[4]??"0",10)});}return t}function Z(e,t,r){let n=r?.fileName??"unknown",s=r?.lineNumber??0,a=`${e}:${t}:${n}:${s}`,i=5381;for(let o=0;o<a.length;o++)i=(i<<5)+i+a.charCodeAt(o)>>>0;return `fp_${i.toString(16).padStart(8,"0")}`}var q=class{buffer;listenersAttached=false;clickHandler;popStateHandler;constructor(e){this.buffer=new C(e),this.clickHandler=this.handleClick.bind(this),this.popStateHandler=this.handleNavigation.bind(this);}push(e){let t=e.data?v(e.data):void 0;this.buffer.push({...e,data:t,timestamp:Date.now()});}getAll(){return this.buffer.toArray()}clear(){this.buffer.clear();}attachListeners(){this.listenersAttached||typeof window>"u"||(this.listenersAttached=true,document.addEventListener("click",this.clickHandler,{capture:true,passive:true}),window.addEventListener("popstate",this.popStateHandler,{passive:true}),this.interceptConsoleError());}detachListeners(){!this.listenersAttached||typeof window>"u"||(document.removeEventListener("click",this.clickHandler,{capture:true}),window.removeEventListener("popstate",this.popStateHandler),this.listenersAttached=false);}handleClick(e){let t=e.target;if(!t||t instanceof HTMLInputElement&&(t.type==="password"||t.hasAttribute("data-nexus-mask")))return;let r=this.describeElement(t);this.push({category:"ui.click",message:`Clicked ${r}`,level:"info",data:{elementTag:t.tagName.toLowerCase(),elementId:t.id||void 0,elementClass:t.className||void 0}});}handleNavigation(){this.push({category:"navigation",message:`Navigated to ${L(window.location.href)}`,level:"info",data:{url:L(window.location.href)}});}describeElement(e){let t=[e.tagName.toLowerCase()];return e.id&&t.push(`#${e.id}`),e.getAttribute("aria-label")&&t.push(`[aria-label="${e.getAttribute("aria-label")}"]`),t.join("")}interceptConsoleError(){let e=console.error.bind(console);console.error=(...t)=>{this.push({category:"console",message:t.map(String).join(" ").substring(0,500),level:"error"}),e(...t);};}},Q=class{options;maxRetries;isPageHiding=false;constructor(e){this.options=e,this.maxRetries=e.maxRetries??2,typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&(this.isPageHiding=true);}),typeof window<"u"&&window.addEventListener("pagehide",()=>{this.isPageHiding=true;});}send(e){let t=E(e);if(this.isPageHiding&&typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){let r=new Blob([t],{type:"application/json"});navigator.sendBeacon(this.options.endpoint,r);return}this.sendWithRetry(t,0);}async flush(e){let t=E(e);if(typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){let r=new Blob([t],{type:"application/json"});navigator.sendBeacon(this.options.endpoint,r);return}await this.sendWithRetry(t,0);}async sendWithRetry(e,t){try{let r=await fetch(this.options.endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:e,keepalive:!0});if(r.ok)return;if(r.status>=500&&t<this.maxRetries){let n=f(t,1e3,3e4);await new Promise(s=>setTimeout(s,n)),await this.sendWithRetry(e,t+1);}}catch{if(t<this.maxRetries){let r=f(t,1e3,3e4);await new Promise(n=>setTimeout(n,r)),await this.sendWithRetry(e,t+1);}}}};function ee(e){if(typeof window>"u")return ()=>{};let t=n=>{let s=n.error instanceof Error?n.error:new Error(n.message);e.captureError(s);},r=n=>{e.captureError(n.reason);};return window.addEventListener("error",t),window.addEventListener("unhandledrejection",r),()=>{window.removeEventListener("error",t),window.removeEventListener("unhandledrejection",r);}}var A=class{apiKey;environment;tags;beforeSend;breadcrumbManager;transport;userContext;dedupeMap=new Map;cleanupListeners;constructor(e={}){this.apiKey=m(e.apiKey);let t=y(e.baseUrl);this.environment=e.environment??"production",this.tags={...e.tags},this.beforeSend=e.beforeSend,this.breadcrumbManager=new q(Math.min(e.maxBreadcrumbs??20,50)),this.transport=new Q({endpoint:`${t}/api/v1/telemetry/errors`,apiKey:this.apiKey}),e.autoCapture!==false&&typeof window<"u"&&(this.breadcrumbManager.attachListeners(),this.cleanupListeners=ee(this));}captureError(e,t){let r=this.normalizeError(e),n=J(r.stack),s=Z(r.type,r.message,n[0]),a=this.dedupeMap.get(s);if(a){a.count+=1;return}let i={fingerprint:s,errorType:r.type,errorMessage:r.message,stackTrace:n,breadcrumbs:this.breadcrumbManager.getAll(),userContext:this.userContext,deviceContext:this.getDeviceContext(),tags:{environment:this.environment,...this.tags,...t},occurrenceCount:1,clientTimestamp:Date.now()},o=v(i),l=this.beforeSend?this.beforeSend(o):o;if(!l)return;this.transport.send(l);let c=setTimeout(()=>{let d=this.dedupeMap.get(s);if(d&&d.count>1){let p={...d.lastPayload,occurrenceCount:d.count,clientTimestamp:Date.now()};this.transport.send(p);}this.dedupeMap.delete(s);},1e4);this.dedupeMap.set(s,{timer:c,count:1,lastPayload:l});}addBreadcrumb(e){this.breadcrumbManager.push(e);}setUser(e){this.userContext=e??void 0;}setTag(e,t){this.tags[e]=t;}async flush(){for(let[e,t]of this.dedupeMap.entries()){if(clearTimeout(t.timer),t.count>0){let r={...t.lastPayload,occurrenceCount:t.count,clientTimestamp:Date.now()};await this.transport.flush(r);}this.dedupeMap.delete(e);}}destroy(){this.cleanupListeners?.(),this.breadcrumbManager.detachListeners(),this.breadcrumbManager.clear(),this.dedupeMap.forEach(e=>clearTimeout(e.timer)),this.dedupeMap.clear();}normalizeError(e){return e instanceof Error?{type:e.name||"Error",message:e.message,stack:e.stack}:typeof e=="string"?{type:"UnhandledException",message:e}:{type:"NonErrorRejection",message:String(e)}}getDeviceContext(){let e=typeof window<"u"&&typeof navigator<"u";return {userAgent:e?navigator.userAgent:"Node/SSR",currentUrl:e?window.location.href:"",viewport:e?`${window.innerWidth}x${window.innerHeight}`:void 0,timezone:Intl?.DateTimeFormat()?.resolvedOptions()?.timeZone,networkStatus:e&&"connection"in navigator?navigator.connection?.effectiveType??"unknown":void 0}}};var N=class e{static instance=null;flags;tracker;constructor(t={}){let{apiKey:r,baseUrl:n,user:s,environment:a,tags:i,autoCapture:o,flags:l,tracker:c}=t;this.flags=new S({apiKey:r,baseUrl:n,user:s,...l}),this.tracker=new A({apiKey:r,baseUrl:n,environment:a,tags:i,autoCapture:o,...c});}static init(t={}){return e.instance||(e.instance=new e(t)),e.instance}static getInstance(){if(!e.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return e.instance}static isEnabled(t,r=false){return e.getInstance().flags.isEnabled(t,r)}static getVariant(t,r,n){return e.getInstance().flags.getVariant(t,r,n)}static captureError(t,r){e.getInstance().tracker.captureError(t,r);}static async identify(t){let r=e.getInstance();r.tracker.setUser(t),await r.flags.identify(t);}static reset(){let t=e.getInstance();t.tracker.setUser(null),t.flags.reset();}static async destroy(){e.instance&&(await e.instance.tracker.flush(),e.instance.tracker.destroy(),e.instance.flags.destroy(),e.instance=null);}};exports.Nexus=N;exports.NexusFlagsClient=S;exports.NexusTrackerClient=A;return exports;})({});
7
+ 6. NUXT_PUBLIC_NEXUS_API_KEY (Nuxt)`);return t.trim()}function S(e,t="https://api.nexus.dev"){return (e||E("NEXT_PUBLIC_NEXUS_URL")||O("VITE_NEXUS_URL")||t).replace(/\/$/,"")}function x(e,t,r,n){if(r>n)return "[MaxDepthExceeded]";if(e==null)return e;if(typeof e!="object"&&typeof e!="function")return typeof e=="bigint"||typeof e=="symbol"?e.toString():typeof e=="function"?"[Function]":e;if(e instanceof Error)return {name:e.name,message:e.message,stack:e.stack};if(t.has(e))return "[Circular]";if(t.add(e),Array.isArray(e)){let a=e.map(o=>x(o,t,r+1,n));return t.delete(e),a}let s={};for(let a of Object.keys(e)){let o=e[a];s[a]=x(o,t,r+1,n);}return t.delete(e),s}function T(e,t=8){let r=x(e,new WeakSet,0,t);try{return JSON.stringify(r)}catch{return JSON.stringify({error:"[SerializationFailed]"})}}function V(e,t=0){let r=t>>>0,n=3432918353,s=461845907,a=0,o=Math.floor(e.length/4)*4;for(;a<o;){let i=e.charCodeAt(a)&255|(e.charCodeAt(a+1)&255)<<8|(e.charCodeAt(a+2)&255)<<16|(e.charCodeAt(a+3)&255)<<24;i=Math.imul(i,n),i=i<<15|i>>>17,i=Math.imul(i,s),r^=i,r=r<<13|r>>>19,r=Math.imul(r,5)+3864292196>>>0,a+=4;}let c=0,u=e.length&3;return u>=3&&(c^=(e.charCodeAt(a+2)&255)<<16),u>=2&&(c^=(e.charCodeAt(a+1)&255)<<8),u>=1&&(c^=e.charCodeAt(a)&255,c=Math.imul(c,n),c=c<<15|c>>>17,c=Math.imul(c,s),r^=c),r^=e.length,r^=r>>>16,r=Math.imul(r,2246822507),r^=r>>>13,r=Math.imul(r,3266489909),r^=r>>>16,r>>>0}function G(e,t){let r=`${e}:${t}`;return V(r)%100}function R(e,t){let r=e.replace(/^v/,"").split(".").map(Number),n=t.replace(/^v/,"").split(".").map(Number);for(let s=0;s<3;s++){let a=(r[s]??0)-(n[s]??0);if(a!==0)return a}return 0}function z(e,t){let r=t.split("."),n=e;for(let s of r){if(n==null||typeof n!="object")return;n=n[s];}return n}function Y(e,t){let r=z(t,e.attribute),n=e.values;switch(e.operator){case "EQUALS":return r===n[0];case "NOT_EQUALS":return r!==n[0];case "IN":return n.includes(r);case "NOT_IN":return !n.includes(r);case "CONTAINS":return typeof r=="string"&&r.includes(String(n[0]));case "NOT_CONTAINS":return typeof r=="string"&&!r.includes(String(n[0]));case "STARTS_WITH":return typeof r=="string"&&r.startsWith(String(n[0]));case "ENDS_WITH":return typeof r=="string"&&r.endsWith(String(n[0]));case "GREATER_THAN":return typeof r=="number"&&r>Number(n[0]);case "LESS_THAN":return typeof r=="number"&&r<Number(n[0]);case "SEMVER_GTE":return typeof r=="string"&&typeof n[0]=="string"&&R(r,String(n[0]))>=0;case "SEMVER_LTE":return typeof r=="string"&&typeof n[0]=="string"&&R(r,String(n[0]))<=0;default:return false}}function U(e,t){if(!e.isEnabled)return {key:e.key,enabled:false,variants:{},reason:"KILL_SWITCH",version:e.version};if(e.targetingRules.length>0){if(!e.targetingRules.every(r=>Y(r,t)))return {key:e.key,enabled:false,variants:{},reason:"FALLBACK",version:e.version};if(e.rolloutPercentage>=100)return {key:e.key,enabled:true,variants:e.variants,reason:"TARGETING_MATCH",version:e.version}}if(e.rolloutPercentage>0){let r=t.id??"anon";return G(r,e.key)<e.rolloutPercentage?{key:e.key,enabled:true,variants:e.variants,reason:e.targetingRules.length>0?"TARGETING_MATCH":"ROLLOUT_MATCH",version:e.version}:{key:e.key,enabled:false,variants:{},reason:"FALLBACK",version:e.version}}return {key:e.key,enabled:false,variants:{},reason:"KILL_SWITCH",version:e.version}}var J=class{options;eventSource=null;connected=false;destroyed=false;reconnectAttempt=0;reconnectTimer=null;maxReconnects;constructor(e){this.options=e,this.maxReconnects=e.maxReconnects??1/0;}get isConnected(){return this.connected}connect(){this.destroyed||this.connected||this.eventSource||this.openConnection();}disconnect(){this.destroyed=true,this.cleanup();}openConnection(){if(!this.destroyed)try{let e=new URL(this.options.url);e.searchParams.set("apiKey",this.options.apiKey),this.eventSource=new EventSource(e.toString()),this.eventSource.addEventListener("open",()=>{this.connected=!0,this.reconnectAttempt=0,this.options.onStateChange?.(!0);}),this.eventSource.addEventListener("message",t=>{this.handleMessage(t.data);}),this.eventSource.addEventListener("flag_update",t=>{this.handleMessage(t.data);}),this.eventSource.addEventListener("FLAG_UPDATE",t=>{this.handleMessage(t.data);}),this.eventSource.addEventListener("FLAG_DELETE",t=>{this.handleMessage(t.data);}),this.eventSource.addEventListener("error",()=>{this.connected=!1,this.options.onStateChange?.(!1),this.cleanup(),this.scheduleReconnect();});}catch{this.scheduleReconnect();}}handleMessage(e){try{let t=JSON.parse(e);this.options.onEvent(t);}catch{}}cleanup(){this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.reconnectTimer!==null&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null);}scheduleReconnect(){if(this.destroyed||this.reconnectAttempt>=this.maxReconnects)return;let e=f(this.reconnectAttempt,1e3,3e4);this.reconnectAttempt++,this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,this.destroyed||this.openConnection();},e);}},Z="nexus_flags_",F="nexus_anon_id",q=class{memory=new Map;storageKey;localStorageAvailable;broadcastChannel=null;constructor(e){this.storageKey=`${Z}${e}`,this.localStorageAvailable=this.testLocalStorage(),this.hydrate(),this.setupBroadcastChannel();}set(e,t){this.memory.set(e,t),this.persist(),this.broadcastUpdate(e,t);}get(e){return this.memory.get(e)}setAll(e){for(let[t,r]of Object.entries(e))this.memory.set(t,r);this.persist();}delete(e){this.memory.delete(e),this.persist();}getAll(){return Object.fromEntries(this.memory.entries())}clear(){if(this.memory.clear(),this.localStorageAvailable)try{window.localStorage.removeItem(this.storageKey);}catch{}this.broadcastChannel?.close();}getOrCreateAnonymousId(){if(typeof window>"u")return "anon-ssr-node";if(this.localStorageAvailable)try{let e=window.localStorage.getItem(F);return e||(e=`anon_${Math.random().toString(36).substring(2,11)}`,window.localStorage.setItem(F,e)),e}catch{}return `anon_${Math.random().toString(36).substring(2,11)}`}testLocalStorage(){try{if(typeof window>"u")return !1;let e="__nexus_test__";return window.localStorage.setItem(e,"1"),window.localStorage.removeItem(e),!0}catch{return false}}hydrate(){if(this.localStorageAvailable)try{let e=window.localStorage.getItem(this.storageKey);if(e){let t=JSON.parse(e);for(let[r,n]of Object.entries(t))this.memory.set(r,n);}}catch{}}persist(){if(this.localStorageAvailable)try{window.localStorage.setItem(this.storageKey,JSON.stringify(Object.fromEntries(this.memory.entries())));}catch{}}setupBroadcastChannel(){try{typeof BroadcastChannel<"u"&&(this.broadcastChannel=new BroadcastChannel(`nexus_flags_${this.storageKey}`),this.broadcastChannel.onmessage=e=>{e.data?.key&&e.data?.result&&this.memory.set(e.data.key,e.data.result);});}catch{}}broadcastUpdate(e,t){try{this.broadcastChannel?.postMessage({key:e,result:t});}catch{}}},N=class{apiKey;baseUrl;timeoutMs;user;storage;listeners=new Map;sseManager;flagDefinitions=new Map;constructor(e={}){if(this.apiKey=w(e.apiKey),this.baseUrl=S(e.baseUrl),this.timeoutMs=e.timeoutMs??3e3,this.storage=new q(this.apiKey.substring(0,16)),this.user=e.user??{id:this.storage.getOrCreateAnonymousId()},e.bootstrap){let t={};for(let[r,n]of Object.entries(e.bootstrap))if(typeof n=="boolean")t[r]={key:r,enabled:n,variants:{},reason:n?"DEFAULT_ENABLED":"KILL_SWITCH",version:1};else if(n&&typeof n=="object"){let s=n,a=typeof s.enabled=="boolean"?s.enabled:typeof s.isEnabled=="boolean"?s.isEnabled:true;t[r]={key:s.key??r,enabled:a,variants:s.variants??{},reason:a?"DEFAULT_ENABLED":"KILL_SWITCH",version:typeof s.version=="number"?s.version:1};}this.storage.setAll(t);}e.realtime!==false&&this.initRealtimeSync(),this.refreshFlags();}isEnabled(e,t=false){let r=this.storage.get(e);return r!==void 0?r.enabled:t}getVariant(e,t,r){let n=this.storage.get(e);if(!n?.enabled||!n.variants)return r;let s=n.variants[t];return s!==void 0?s:r}async identify(e){this.user={...this.user,...e},await this.refreshFlags();}reset(){this.user={id:this.storage.getOrCreateAnonymousId()},this.refreshFlags();}onFlagChange(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>this.listeners.get(e)?.delete(t)}destroy(){this.sseManager?.disconnect(),this.listeners.clear(),this.storage.clear();}initRealtimeSync(){this.sseManager=new J({url:`${this.baseUrl}/api/v1/flags/stream`,apiKey:this.apiKey,onEvent:e=>{if(e.type==="FLAG_UPDATE"&&e.data){let t=this.flagDefinitions.get(e.key),r=t?U(t,this.user):e.data;this.storage.set(e.key,r),this.listeners.get(e.key)?.forEach(n=>n(r));}else e.type==="FLAG_DELETE"&&(this.storage.delete(e.key),this.flagDefinitions.delete(e.key));}}),this.sseManager.connect();}async refreshFlags(){try{let e=await M({url:`${this.baseUrl}/api/v1/flags/eval`,method:"GET",headers:{Authorization:`Bearer ${this.apiKey}`,"X-Nexus-User-Id":this.user.id??"anon","X-Nexus-Country":this.user.country??""},timeoutMs:this.timeoutMs,maxRetries:2}),t=e.data,r=t&&typeof t=="object"&&"data"in t?t.data:e.data;if(r&&typeof r=="object")for(let[n,s]of Object.entries(r)){this.flagDefinitions.set(n,s);let a=U(s,this.user);this.storage.set(n,a),this.listeners.get(n)?.forEach(o=>o(a));}}catch{}}};var Q=/^(password|passwd|token|secret|authorization|bearer|auth|credit_?card|cvv|cvc|ssn|api_?key|access_?token|refresh_?token)$/i,ee=/\b(?:\d[ -]*?){13,16}\b/g,te=/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,K=/([?&](token|auth|key|secret|password|api_key|access_token|refresh_token)=)[^&]*/gi;function re(e){return e.replace(ee,"[CARD_REDACTED]").replace(te,"[EMAIL_REDACTED]").replace(K,"$1[REDACTED]")}function C(e,t=0){if(t>5)return "[MaxDepthExceeded]";if(e==null)return e;if(typeof e=="string")return re(e);if(typeof e!="object")return e;if(Array.isArray(e))return e.map(n=>C(n,t+1));let r={};for(let[n,s]of Object.entries(e))Q.test(n)?r[n]="[REDACTED]":r[n]=C(s,t+1);return r}function B(e){return e.replace(K,"$1[REDACTED]")}function H(e){if(!e)return [];let t=[],r=e.split(`
8
+ `);for(let n of r){let s=n.trim(),a=s.match(/^at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)$/)||s.match(/^at\s+(.+?):(\d+):(\d+)$/)||s.match(/^at\s+\((.+?):(\d+):(\d+)\)$/);if(a){a.length===5?t.push({functionName:a[1]??"<anonymous>",fileName:a[2]??"<unknown>",lineNumber:parseInt(a[3]??"0",10),columnNumber:parseInt(a[4]??"0",10)}):a.length===4&&t.push({functionName:"<anonymous>",fileName:a[1]??"<unknown>",lineNumber:parseInt(a[2]??"0",10),columnNumber:parseInt(a[3]??"0",10)});continue}let o=s.match(/^(.+?)@(.+?):(\d+):(\d+)$/);o&&t.push({functionName:o[1]??"<anonymous>",fileName:o[2]??"<unknown>",lineNumber:parseInt(o[3]??"0",10),columnNumber:parseInt(o[4]??"0",10)});}return t}function j(e,t,r){let n=r?.fileName??"unknown",s=r?.lineNumber??0,a=`${e}:${t}:${n}:${s}`,o=5381;for(let c=0;c<a.length;c++)o=(o<<5)+o+a.charCodeAt(c)>>>0;return `fp_${o.toString(16).padStart(8,"0")}`}var ne=class{buffer;listenersAttached=false;clickHandler;popStateHandler;constructor(e){this.buffer=new P(e),this.clickHandler=this.handleClick.bind(this),this.popStateHandler=this.handleNavigation.bind(this);}push(e){let t=e.data?C(e.data):void 0;this.buffer.push({...e,data:t,timestamp:Date.now()});}getAll(){return this.buffer.toArray()}clear(){this.buffer.clear();}attachListeners(){this.listenersAttached||typeof window>"u"||(this.listenersAttached=true,document.addEventListener("click",this.clickHandler,{capture:true,passive:true}),window.addEventListener("popstate",this.popStateHandler,{passive:true}),this.interceptConsoleError());}detachListeners(){!this.listenersAttached||typeof window>"u"||(document.removeEventListener("click",this.clickHandler,{capture:true}),window.removeEventListener("popstate",this.popStateHandler),this.listenersAttached=false);}handleClick(e){let t=e.target;if(!t||t instanceof HTMLInputElement&&(t.type==="password"||t.hasAttribute("data-nexus-mask")))return;let r=this.describeElement(t);this.push({category:"ui.click",message:`Clicked ${r}`,level:"info",data:{elementTag:t.tagName.toLowerCase(),elementId:t.id||void 0,elementClass:t.className||void 0}});}handleNavigation(){this.push({category:"navigation",message:`Navigated to ${B(window.location.href)}`,level:"info",data:{url:B(window.location.href)}});}describeElement(e){let t=[e.tagName.toLowerCase()];return e.id&&t.push(`#${e.id}`),e.getAttribute("aria-label")&&t.push(`[aria-label="${e.getAttribute("aria-label")}"]`),t.join("")}interceptConsoleError(){let e=console.error.bind(console);console.error=(...t)=>{this.push({category:"console",message:t.map(String).join(" ").substring(0,500),level:"error"}),e(...t);};}},$="nexus_events",D=200,se=class{options;maxRetries;plugin;isPageHiding=false;constructor(e){this.options=e,this.maxRetries=e.maxRetries??2,this.plugin=e.plugin??"fetch",this.plugin==="fetch"&&(typeof document<"u"&&document.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&(this.isPageHiding=true);}),typeof window<"u"&&window.addEventListener("pagehide",()=>{this.isPageHiding=true;}));}send(e){if(typeof this.plugin=="function"){this.plugin(e);return}switch(this.plugin){case "console":this.sendConsole(e);return;case "localStorage":this.sendLocalStorage(e);return;default:this.sendFetch(e);}}async flush(e){if(typeof this.plugin=="function"){await this.plugin(e);return}switch(this.plugin){case "console":this.sendConsole(e);return;case "localStorage":this.sendLocalStorage(e);return;default:{let t=T(e);if(typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){let r=new Blob([t],{type:"application/json"});navigator.sendBeacon(this.options.endpoint,r);return}await this.sendWithRetry(t,0);}}}sendFetch(e){let t=T(e);if(this.isPageHiding&&typeof navigator<"u"&&typeof navigator.sendBeacon=="function"){let r=new Blob([t],{type:"application/json"});navigator.sendBeacon(this.options.endpoint,r);return}this.sendWithRetry(t,0);}sendConsole(e){let t=`[Nexus|${e.errorType}]`;console.group(t,e.errorMessage),console.warn("Fingerprint:",e.fingerprint),console.warn("Stack frames:",e.stackTrace.slice(0,3)),e.breadcrumbs.length>0&&console.warn("Last breadcrumbs:",e.breadcrumbs.slice(-5)),e.userContext&&console.warn("User:",e.userContext),console.groupEnd();}sendLocalStorage(e){if(!(typeof localStorage>"u"))try{let t=localStorage.getItem($),r=t?JSON.parse(t):[];r.push(e),r.length>D&&r.splice(0,r.length-D),localStorage.setItem($,T(r));}catch{}}async sendWithRetry(e,t){try{let r=await fetch(this.options.endpoint,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.options.apiKey}`},body:e,keepalive:!0});if(r.ok)return;if(r.status>=500&&t<this.maxRetries){let n=f(t,1e3,3e4);await new Promise(s=>setTimeout(s,n)),await this.sendWithRetry(e,t+1);}}catch{if(t<this.maxRetries){let r=f(t,1e3,3e4);await new Promise(n=>setTimeout(n,r)),await this.sendWithRetry(e,t+1);}}}};function ae(e){if(typeof window>"u")return ()=>{};let t=n=>{let s=n.error instanceof Error?n.error:new Error(n.message);e.captureError(s);},r=n=>{e.captureError(n.reason);};return window.addEventListener("error",t),window.addEventListener("unhandledrejection",r),()=>{window.removeEventListener("error",t),window.removeEventListener("unhandledrejection",r);}}var _=class{apiKey;environment;tags;extras;beforeSend;breadcrumbManager;transport;samplingRate;dedupeWindowMs;maxPerSession;sessionCaptureCount=0;userContext;dedupeMap=new Map;cleanupListeners;constructor(e={}){this.apiKey=w(e.apiKey);let t=S(e.baseUrl);this.environment=e.environment??"production",this.tags={...e.tags},this.extras={},this.beforeSend=e.beforeSend,this.samplingRate=Math.max(0,Math.min(1,e.sampling?.rate??1)),this.dedupeWindowMs=e.sampling?.dedupeWindow??1e4,this.maxPerSession=e.sampling?.maxPerSession??100,this.breadcrumbManager=new ne(Math.min(e.maxBreadcrumbs??20,50)),this.transport=new se({endpoint:`${t}/api/v1/telemetry/errors`,apiKey:this.apiKey,plugin:e.transport}),e.autoCapture!==false&&typeof window<"u"&&(this.breadcrumbManager.attachListeners(),this.cleanupListeners=ae(this));}captureError(e,t){if(this.sessionCaptureCount>=this.maxPerSession||this.samplingRate<1&&Math.random()>this.samplingRate)return;let r=this.normalizeError(e),n=H(r.stack),s=j(r.type,r.message,n[0]),a=this.dedupeMap.get(s);if(a){a.count+=1;return}let o={fingerprint:s,errorType:r.type,errorMessage:r.message,stackTrace:n,breadcrumbs:this.breadcrumbManager.getAll(),userContext:this.userContext,deviceContext:this.getDeviceContext(),tags:{environment:this.environment,...this.tags,...t},occurrenceCount:1,clientTimestamp:Date.now()},c=C(o),u=this.beforeSend?this.beforeSend(c):c;if(!u)return;this.transport.send(u),this.sessionCaptureCount++;let i=setTimeout(()=>{let l=this.dedupeMap.get(s);if(l&&l.count>1){let h={...l.lastPayload,occurrenceCount:l.count,clientTimestamp:Date.now()};this.transport.send(h);}this.dedupeMap.delete(s);},this.dedupeWindowMs);this.dedupeMap.set(s,{timer:i,count:1,lastPayload:u});}captureMessage(e,t="info",r){let n=new Error(e);n.name="NexusMessage",this.captureError(n,{_level:t,...r});}addBreadcrumb(e){this.breadcrumbManager.push(e);}setUser(e){this.userContext=e??void 0;}setTag(e,t){this.tags[e]=t;}setExtra(e,t){this.extras[e]=t;}async flush(){for(let[e,t]of this.dedupeMap.entries()){if(clearTimeout(t.timer),t.count>0){let r={...t.lastPayload,occurrenceCount:t.count,clientTimestamp:Date.now()};await this.transport.flush(r);}this.dedupeMap.delete(e);}}destroy(){this.cleanupListeners?.(),this.breadcrumbManager.detachListeners(),this.breadcrumbManager.clear(),this.dedupeMap.forEach(e=>clearTimeout(e.timer)),this.dedupeMap.clear();}normalizeError(e){return e instanceof Error?{type:e.name||"Error",message:e.message,stack:e.stack}:typeof e=="string"?{type:"UnhandledException",message:e}:{type:"NonErrorRejection",message:String(e)}}getDeviceContext(){let e=typeof window<"u"&&typeof navigator<"u";return {userAgent:e?navigator.userAgent:"Node/SSR",currentUrl:e?window.location.href:"",viewport:e?`${window.innerWidth}x${window.innerHeight}`:void 0,timezone:Intl?.DateTimeFormat()?.resolvedOptions()?.timeZone,networkStatus:e&&"connection"in navigator?navigator.connection?.effectiveType??"unknown":void 0}}},ie=class{_error=null;_errorInfo=null;_listeners=new Set;_tracker;_onError;_tags;_generateErrorId;constructor(e={}){this._tracker=e.tracker,this._onError=e.onError,this._tags=e.tags,this._generateErrorId=e.generateErrorId??(t=>{let r=H(t.stack);return `NX-${j(t.name,t.message,r[0]).replace(/^fp_/,"").slice(0,8).toUpperCase()}`});}get hasError(){return this._error!==null}get currentError(){return this._error}get errorInfo(){return this._errorInfo}capture(e,t){let r=e instanceof Error?e:new Error(String(e));this._error=r;let n=this._generateErrorId(r),s={error:r,errorId:n,reset:()=>this.recover(),componentStack:t?.componentStack};if(this._errorInfo=s,this._tracker)try{this._tracker.captureError(r,{tags:{...this._tags,...t?.tags,guardErrorId:n},componentStack:t?.componentStack});}catch(a){typeof console<"u"&&console.warn("[NexusGuardCore] Failed to forward error to tracker:",a);}if(this._onError)try{this._onError(r,s);}catch(a){typeof console<"u"&&console.warn("[NexusGuardCore] onError callback threw:",a);}return this._notify(),s}recover(){this._error!==null&&(this._error=null,this._errorInfo=null,this._notify());}reset(){this.recover();}subscribe(e){return this._listeners.add(e),e(this._errorInfo),()=>{this._listeners.delete(e);}}_notify(){for(let e of this._listeners)try{e(this._errorInfo);}catch(t){typeof console<"u"&&console.error("[NexusGuardCore] Subscriber threw error:",t);}}},oe={LCP:[2500,4e3],CLS:[.1,.25],FID:[100,300],TTFB:[800,1800],INP:[200,500],FCP:[1800,3e3]};function g(e,t){let[r,n]=oe[e]??[1/0,1/0];return t<=r?"good":t<=n?"needs-improvement":"poor"}function v(){return typeof performance>"u"?"navigate":performance.getEntriesByType("navigation")[0]?.type??"navigate"}function ce(e){if(typeof PerformanceObserver>"u")return ()=>{};let t=0,r=null;try{r=new PerformanceObserver(a=>{let o=a.getEntries(),c=o[o.length-1];c&&(t=c.startTime??0);}),r.observe({type:"largest-contentful-paint",buffered:!0});}catch{return ()=>{}}let n=()=>{t!==0&&e({name:"LCP",value:t,rating:g("LCP",t),delta:t,navigationType:v()});},s=()=>n();return document.addEventListener("visibilitychange",s,{once:true}),()=>{r?.disconnect(),document.removeEventListener("visibilitychange",s);}}function le(e){if(typeof PerformanceObserver>"u")return ()=>{};let t=0,r=null;try{r=new PerformanceObserver(a=>{for(let o of a.getEntries()){let c=o;c.hadRecentInput||(t+=c.value??0);}}),r.observe({type:"layout-shift",buffered:!0});}catch{return ()=>{}}let n=()=>{t!==0&&e({name:"CLS",value:t,rating:g("CLS",t),delta:t,navigationType:v()});},s=()=>n();return document.addEventListener("visibilitychange",s,{once:true}),()=>{r?.disconnect(),document.removeEventListener("visibilitychange",s);}}function ue(e){if(typeof PerformanceObserver>"u")return ()=>{};let t=null;try{t=new PerformanceObserver(r=>{let n=r.getEntries()[0];if(!n)return;let s=n.processingStart-n.startTime;e({name:"FID",value:s,rating:g("FID",s),delta:s,navigationType:v()}),t?.disconnect();}),t.observe({type:"first-input",buffered:!0});}catch{return ()=>{}}return ()=>t?.disconnect()}function de(e){if(typeof PerformanceObserver>"u")return ()=>{};try{let t=performance.getEntriesByType("navigation")[0];if(t){let r=t.responseStart-t.requestStart;e({name:"TTFB",value:r,rating:g("TTFB",r),delta:r,navigationType:t.type??"navigate"});}}catch{}return ()=>{}}function he(e){if(typeof PerformanceObserver>"u")return ()=>{};let t=0,r=null;try{r=new PerformanceObserver(a=>{for(let o of a.getEntries()){let c=o;c.duration>t&&(t=c.duration);}}),r.observe({type:"event",buffered:!0,durationThreshold:16});}catch{return ()=>{}}let n=()=>{t!==0&&e({name:"INP",value:t,rating:g("INP",t),delta:t,navigationType:v()});},s=()=>n();return document.addEventListener("visibilitychange",s,{once:true}),()=>{r?.disconnect(),document.removeEventListener("visibilitychange",s);}}function pe(e){if(typeof PerformanceObserver>"u")return ()=>{};let t=null;try{t=new PerformanceObserver(r=>{let n=r.getEntries().find(a=>a.name==="first-contentful-paint");if(!n)return;let s=n.startTime;e({name:"FCP",value:s,rating:g("FCP",s),delta:s,navigationType:v()}),t?.disconnect();}),t.observe({type:"paint",buffered:!0});}catch{return ()=>{}}return ()=>t?.disconnect()}function fe(e,t){if(typeof PerformanceObserver>"u")return ()=>{};let r=null;try{r=new PerformanceObserver(n=>{for(let s of n.getEntries())s.duration>=t&&e.addBreadcrumb({category:"custom",message:`Long task detected: ${Math.round(s.duration)}ms`,level:s.duration>=t*3?"error":"warning",data:{durationMs:Math.round(s.duration),startTime:Math.round(s.startTime)}});}),r.observe({type:"longtask",buffered:!0});}catch{return ()=>{}}return ()=>r?.disconnect()}var ge={LCP:ce,CLS:le,FID:ue,TTFB:de,INP:he,FCP:pe};function k(e,t={}){if(typeof window>"u")return ()=>{};let{captureAsEvents:r=false,poorRatingOnly:n=false,vitals:s=["LCP","CLS","FID","TTFB","INP","FCP"],longTaskThresholdMs:a=50}=t,o=i=>{n&&i.rating==="good"||(e.addBreadcrumb({category:"custom",message:`Web Vital ${i.name}: ${i.rating.toUpperCase()} (${Math.round(i.value)}${i.name==="CLS"?"":"ms"})`,level:i.rating==="poor"?"error":i.rating==="needs-improvement"?"warning":"info",data:{metric:i.name,value:i.value,rating:i.rating,navigationType:i.navigationType}}),r&&i.rating!=="good"&&e.captureMessage(`Performance degradation: ${i.name} is ${i.rating} (${Math.round(i.value)}${i.name==="CLS"?"":"ms"})`,i.rating==="poor"?"error":"warning",{metric:i.name,value:i.value,rating:i.rating,navigationType:i.navigationType}));},c=s.map(i=>{let l=ge[i];return l?l(o):()=>{}}),u=fe(e,a);return ()=>{c.forEach(i=>i()),u();}}var A=class e{static instance=null;static vitalsCleanup=null;flags;tracker;constructor(t={}){let{apiKey:r,baseUrl:n,user:s,environment:a,tags:o,autoCapture:c,sampling:u,transport:i,vitals:l,devServer:h,flags:m,tracker:b}=t;this.flags=new N({apiKey:r,baseUrl:n,user:s,...m});let p=n,d=i;if(h?.enabled){let y=h.port??4567;p=`http://${h.host??"localhost"}:${y}`;}if(this.tracker=new _({apiKey:r,baseUrl:p,environment:a,tags:o,autoCapture:c,sampling:u,transport:d,...b}),l){let y=typeof l=="object"?l:{};e.vitalsCleanup=k(this.tracker,y);}}static init(t={}){return e.instance||(e.instance=new e(t)),e.instance}static getInstance(){if(!e.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return e.instance}static isEnabled(t,r=false){return e.getInstance().flags.isEnabled(t,r)}static getVariant(t,r,n){return e.getInstance().flags.getVariant(t,r,n)}static captureError(t,r){e.getInstance().tracker.captureError(t,r);}static captureMessage(t,r="info",n){e.getInstance().tracker.captureMessage(t,r,n);}static addBreadcrumb(t){e.getInstance().tracker.addBreadcrumb(t);}static setExtra(t,r){e.getInstance().tracker.setExtra(t,r);}static attachWebVitals(t){return k(e.getInstance().tracker,t)}static async identify(t){let r=e.getInstance();r.tracker.setUser(t),await r.flags.identify(t);}static reset(){let t=e.getInstance();t.tracker.setUser(null),t.flags.reset();}static async destroy(){e.vitalsCleanup&&(e.vitalsCleanup(),e.vitalsCleanup=null),e.instance&&(await e.instance.tracker.flush(),e.instance.tracker.destroy(),e.instance.flags.destroy(),e.instance=null);}};
9
+ exports.Nexus=A;exports.NexusFlagsClient=N;exports.NexusGuardCore=ie;exports.NexusTrackerClient=_;exports.attachWebVitals=k;return exports;})({});
package/dist/index.mjs CHANGED
@@ -1 +1,2 @@
1
- import {NexusFlagsClient}from'@nexussdk/flags';export{NexusFlagsClient}from'@nexussdk/flags';import {NexusTrackerClient}from'@nexussdk/tracker';export{NexusTrackerClient}from'@nexussdk/tracker';var n=class t{static instance=null;flags;tracker;constructor(e={}){let{apiKey:s,baseUrl:r,user:a,environment:i,tags:o,autoCapture:c,flags:l,tracker:u}=e;this.flags=new NexusFlagsClient({apiKey:s,baseUrl:r,user:a,...l}),this.tracker=new NexusTrackerClient({apiKey:s,baseUrl:r,environment:i,tags:o,autoCapture:c,...u});}static init(e={}){return t.instance||(t.instance=new t(e)),t.instance}static getInstance(){if(!t.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return t.instance}static isEnabled(e,s=false){return t.getInstance().flags.isEnabled(e,s)}static getVariant(e,s,r){return t.getInstance().flags.getVariant(e,s,r)}static captureError(e,s){t.getInstance().tracker.captureError(e,s);}static async identify(e){let s=t.getInstance();s.tracker.setUser(e),await s.flags.identify(e);}static reset(){let e=t.getInstance();e.tracker.setUser(null),e.flags.reset();}static async destroy(){t.instance&&(await t.instance.tracker.flush(),t.instance.tracker.destroy(),t.instance.flags.destroy(),t.instance=null);}};export{n as Nexus};
1
+ import {NexusFlagsClient}from'@nexussdk/flags';export{NexusFlagsClient}from'@nexussdk/flags';import {NexusTrackerClient,attachWebVitals}from'@nexussdk/tracker';export{NexusGuardCore,NexusTrackerClient,attachWebVitals}from'@nexussdk/tracker';var o=class t{static instance=null;static vitalsCleanup=null;flags;tracker;constructor(e={}){let{apiKey:r,baseUrl:s,user:u,environment:p,tags:g,autoCapture:x,sampling:d,transport:f,vitals:n,devServer:a,flags:v,tracker:m}=e;this.flags=new NexusFlagsClient({apiKey:r,baseUrl:s,user:u,...v});let l=s,b=f;if(a?.enabled){let i=a.port??4567;l=`http://${a.host??"localhost"}:${i}`;}if(this.tracker=new NexusTrackerClient({apiKey:r,baseUrl:l,environment:p,tags:g,autoCapture:x,sampling:d,transport:b,...m}),n){let i=typeof n=="object"?n:{};t.vitalsCleanup=attachWebVitals(this.tracker,i);}}static init(e={}){return t.instance||(t.instance=new t(e)),t.instance}static getInstance(){if(!t.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return t.instance}static isEnabled(e,r=false){return t.getInstance().flags.isEnabled(e,r)}static getVariant(e,r,s){return t.getInstance().flags.getVariant(e,r,s)}static captureError(e,r){t.getInstance().tracker.captureError(e,r);}static captureMessage(e,r="info",s){t.getInstance().tracker.captureMessage(e,r,s);}static addBreadcrumb(e){t.getInstance().tracker.addBreadcrumb(e);}static setExtra(e,r){t.getInstance().tracker.setExtra(e,r);}static attachWebVitals(e){return attachWebVitals(t.getInstance().tracker,e)}static async identify(e){let r=t.getInstance();r.tracker.setUser(e),await r.flags.identify(e);}static reset(){let e=t.getInstance();e.tracker.setUser(null),e.flags.reset();}static async destroy(){t.vitalsCleanup&&(t.vitalsCleanup(),t.vitalsCleanup=null),t.instance&&(await t.instance.tracker.flush(),t.instance.tracker.destroy(),t.instance.flags.destroy(),t.instance=null);}};
2
+ export{o as Nexus};
package/dist/react.cjs CHANGED
@@ -1 +1,2 @@
1
- 'use strict';var N=require('react'),flags=require('@nexussdk/flags'),tracker=require('@nexussdk/tracker');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var N__default=/*#__PURE__*/_interopDefault(N);var a=class e{static instance=null;flags;tracker;constructor(n={}){let{apiKey:t,baseUrl:s,user:i,environment:r,tags:u,autoCapture:o,flags:p,tracker:g}=n;this.flags=new flags.NexusFlagsClient({apiKey:t,baseUrl:s,user:i,...p}),this.tracker=new tracker.NexusTrackerClient({apiKey:t,baseUrl:s,environment:r,tags:u,autoCapture:o,...g});}static init(n={}){return e.instance||(e.instance=new e(n)),e.instance}static getInstance(){if(!e.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return e.instance}static isEnabled(n,t=false){return e.getInstance().flags.isEnabled(n,t)}static getVariant(n,t,s){return e.getInstance().flags.getVariant(n,t,s)}static captureError(n,t){e.getInstance().tracker.captureError(n,t);}static async identify(n){let t=e.getInstance();t.tracker.setUser(n),await t.flags.identify(n);}static reset(){let n=e.getInstance();n.tracker.setUser(null),n.flags.reset();}static async destroy(){e.instance&&(await e.instance.tracker.flush(),e.instance.tracker.destroy(),e.instance.flags.destroy(),e.instance=null);}};var x=N.createContext(null);function y({children:e,...n}){let t=N.useRef(null);t.current||(t.current=a.init(n));let s=N.useMemo(()=>({flags:t.current.flags,tracker:t.current.tracker,nexus:t.current}),[]);return N.useEffect(()=>()=>{a.destroy();},[]),N__default.default.createElement(x.Provider,{value:s},e)}function C(){let e=N.useContext(x);if(!e)throw new Error("[Nexus SDK] useNexus() must be called inside a <NexusProvider>.");return e}function I(e,n=false){let{flags:t}=C(),[s,i]=N.useState(()=>t.isEnabled(e)!==n?{key:e,enabled:t.isEnabled(e),variants:{},reason:"DEFAULT_ENABLED",version:0}:null);return N.useEffect(()=>{let r=t.isEnabled(e,n);return r!==(s?.enabled??n)&&i({key:e,enabled:r,variants:{},reason:"DEFAULT_ENABLED",version:0}),t.onFlagChange(e,o=>{i(o);})},[e]),N.useMemo(()=>({enabled:s?.enabled??t.isEnabled(e,n),getVariant:(r,u)=>t.getVariant(e,r,u),result:s}),[s,e,t,n])}exports.NexusProvider=y;exports.useFlag=I;exports.useNexus=C;
1
+ 'use strict';var i=require('react'),flags=require('@nexussdk/flags'),tracker=require('@nexussdk/tracker');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var i__default=/*#__PURE__*/_interopDefault(i);var l=class t{static instance=null;static vitalsCleanup=null;flags;tracker;constructor(e={}){let{apiKey:r,baseUrl:n,user:s,environment:a,tags:o,autoCapture:u,sampling:m,transport:d,vitals:c,devServer:p,flags:y,tracker:C}=e;this.flags=new flags.NexusFlagsClient({apiKey:r,baseUrl:n,user:s,...y});let N=n,R=d;if(p?.enabled){let f=p.port??4567;N=`http://${p.host??"localhost"}:${f}`;}if(this.tracker=new tracker.NexusTrackerClient({apiKey:r,baseUrl:N,environment:a,tags:o,autoCapture:u,sampling:m,transport:R,...C}),c){let f=typeof c=="object"?c:{};t.vitalsCleanup=tracker.attachWebVitals(this.tracker,f);}}static init(e={}){return t.instance||(t.instance=new t(e)),t.instance}static getInstance(){if(!t.instance)throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: "..." }) first.');return t.instance}static isEnabled(e,r=false){return t.getInstance().flags.isEnabled(e,r)}static getVariant(e,r,n){return t.getInstance().flags.getVariant(e,r,n)}static captureError(e,r){t.getInstance().tracker.captureError(e,r);}static captureMessage(e,r="info",n){t.getInstance().tracker.captureMessage(e,r,n);}static addBreadcrumb(e){t.getInstance().tracker.addBreadcrumb(e);}static setExtra(e,r){t.getInstance().tracker.setExtra(e,r);}static attachWebVitals(e){return tracker.attachWebVitals(t.getInstance().tracker,e)}static async identify(e){let r=t.getInstance();r.tracker.setUser(e),await r.flags.identify(e);}static reset(){let e=t.getInstance();e.tracker.setUser(null),e.flags.reset();}static async destroy(){t.vitalsCleanup&&(t.vitalsCleanup(),t.vitalsCleanup=null),t.instance&&(await t.instance.tracker.flush(),t.instance.tracker.destroy(),t.instance.flags.destroy(),t.instance=null);}};var g=i.createContext(null);function M({children:t,...e}){let r=i.useRef(null);r.current||(r.current=l.init(e));let n=i.useMemo(()=>({flags:r.current.flags,tracker:r.current.tracker,nexus:r.current}),[]);return i.useEffect(()=>()=>{l.destroy();},[]),i__default.default.createElement(g.Provider,{value:n},t)}function O(){let t=i.useContext(g);if(!t)throw new Error("[Nexus SDK] useNexus() must be called inside a <NexusProvider>.");return t}function W(t,e=false){let{flags:r}=O(),[n,s]=i.useState(()=>r.isEnabled(t)!==e?{key:t,enabled:r.isEnabled(t),variants:{},reason:"DEFAULT_ENABLED",version:0}:null);return i.useEffect(()=>{let a=r.isEnabled(t,e);return a!==(n?.enabled??e)&&s({key:t,enabled:a,variants:{},reason:"DEFAULT_ENABLED",version:0}),r.onFlagChange(t,u=>{s(u);})},[t]),i.useMemo(()=>({enabled:n?.enabled??r.isEnabled(t,e),getVariant:(a,o)=>r.getVariant(t,a,o),result:n}),[n,t,r,e])}var x=class extends i__default.default.Component{static contextType=g;constructor(e){super(e),this.state={hasError:false,errorInfo:null};}static getDerivedStateFromError(e){let r=tracker.parseStackTrace(e.stack),s=`NX-${tracker.computeFingerprint(e.name,e.message,r[0]).replace(/^fp_/,"").slice(0,8).toUpperCase()}`;return {hasError:true,errorInfo:{error:e,errorId:s,reset:()=>{}}}}componentDidCatch(e,r){let{onError:n,tags:s,tracker:a}=this.props,o=a;if(!o&&this.context?.tracker&&(o=this.context.tracker),!o)try{o=l.getInstance().tracker;}catch{}let u=tracker.parseStackTrace(e.stack),d=`NX-${tracker.computeFingerprint(e.name,e.message,u[0]).replace(/^fp_/,"").slice(0,8).toUpperCase()}`,c={error:e,errorId:d,componentStack:r.componentStack??void 0,reset:()=>this.reset()};if(this.setState({errorInfo:c}),o&&o.captureError(e,{tags:{...s,guardErrorId:d},componentStack:r.componentStack??void 0}),n)try{n(e,c);}catch(p){typeof console<"u"&&console.warn("[NexusGuard] onError handler threw:",p);}}componentDidMount(){this.props.resetOnNavigation&&typeof window<"u"&&window.addEventListener("popstate",this.handleNavigation);}componentDidUpdate(e){let{resetKeys:r}=this.props;this.state.hasError&&r&&e.resetKeys&&r.some((s,a)=>s!==e.resetKeys[a])&&this.reset();}componentWillUnmount(){this.props.resetOnNavigation&&typeof window<"u"&&window.removeEventListener("popstate",this.handleNavigation);}handleNavigation=()=>{this.state.hasError&&this.reset();};reset=()=>{this.setState({hasError:false,errorInfo:null});};render(){let{hasError:e,errorInfo:r}=this.state,{fallback:n,children:s}=this.props;return e&&r?typeof n=="function"?n(r):n||i__default.default.createElement("div",{role:"alert",style:{padding:"16px 20px",margin:"12px 0",borderRadius:"8px",backgroundColor:"#1f1315",border:"1px solid #7f1d1d",color:"#fca5a5",fontFamily:"-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, sans-serif",fontSize:"14px",lineHeight:1.5}},i__default.default.createElement("div",{style:{display:"flex",alignItems:"center",justifyContent:"space-between",marginBottom:"8px"}},i__default.default.createElement("strong",{style:{color:"#ef4444"}},"Application Error Encountered"),i__default.default.createElement("span",{style:{fontSize:"12px",fontFamily:"monospace",background:"#450a0a",padding:"2px 8px",borderRadius:"4px"}},r.errorId)),i__default.default.createElement("p",{style:{margin:"0 0 12px 0",color:"#fecaca"}},r.error.message),i__default.default.createElement("button",{type:"button",onClick:()=>this.reset(),style:{background:"#b91c1c",border:"none",color:"#fff",padding:"6px 14px",borderRadius:"6px",fontSize:"13px",cursor:"pointer",fontWeight:500}},"Retry")):s}};function $(t,e={}){let r=s=>i__default.default.createElement(x,e,i__default.default.createElement(t,s)),n=t.displayName||t.name||"Component";return r.displayName=`withNexusGuard(${n})`,r}
2
+ exports.NexusContext=g;exports.NexusGuard=x;exports.NexusProvider=M;exports.useFlag=W;exports.useNexus=O;exports.withNexusGuard=$;