@nexussdk/sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,249 @@
1
+ import React from 'react';
2
+ import { NexusFlagsOptions, NexusFlagsClient } from '@nexussdk/flags';
3
+ import { NexusTrackerOptions, NexusTrackerClient } from '@nexussdk/tracker';
4
+ import { UserContext, FlagEvaluationResult } from '@nexussdk/contracts';
5
+
6
+ /**
7
+ * @fileoverview Unified Nexus singleton facade wrapping Flags and Tracker clients.
8
+ * @module @nexus/sdk/nexus
9
+ */
10
+
11
+ /**
12
+ * Unified initialization options for the Nexus SDK umbrella.
13
+ *
14
+ * @example
15
+ * Nexus.init({
16
+ * apiKey: 'pk_live_...',
17
+ * baseUrl: 'http://localhost:8080',
18
+ * user: { id: 'usr_12345', country: 'VN' },
19
+ * environment: 'production',
20
+ * autoCapture: true,
21
+ * });
22
+ */
23
+ interface NexusInitOptions {
24
+ /** Public API key. Resolved from env if omitted. */
25
+ apiKey?: string;
26
+ /** Base URL for all API calls. */
27
+ baseUrl?: string;
28
+ /** Initial user context for flag targeting and error attribution. */
29
+ user?: UserContext;
30
+ /** Target environment for telemetry routing. Defaults to 'production'. */
31
+ environment?: string;
32
+ /** Global tags attached to all telemetry events. */
33
+ tags?: Record<string, string>;
34
+ /** Toggle automated global error capture. Defaults to true. */
35
+ autoCapture?: boolean;
36
+ /** Additional flags-specific options. */
37
+ flags?: Partial<NexusFlagsOptions>;
38
+ /** Additional tracker-specific options. */
39
+ tracker?: Partial<NexusTrackerOptions>;
40
+ }
41
+ /**
42
+ * The Nexus singleton class — the primary unified entry point for the SDK.
43
+ *
44
+ * Provides access to both the feature flags client and the error tracker client.
45
+ * Initialize once, then use throughout your application.
46
+ *
47
+ * @example
48
+ * // Initialize (call once at app startup)
49
+ * Nexus.init({ apiKey: 'pk_live_...' });
50
+ *
51
+ * // Feature flags
52
+ * const showBanner = Nexus.isEnabled('promo_banner_v2', false);
53
+ *
54
+ * // Error tracking
55
+ * Nexus.captureError(new Error('Something went wrong'));
56
+ *
57
+ * // Update user context
58
+ * await Nexus.identify({ id: 'usr_12345', country: 'VN' });
59
+ */
60
+ declare class Nexus {
61
+ private static instance;
62
+ /** The underlying feature flags client instance. */
63
+ readonly flags: NexusFlagsClient;
64
+ /** The underlying error tracker client instance. */
65
+ readonly tracker: NexusTrackerClient;
66
+ private constructor();
67
+ /**
68
+ * Initializes the Nexus SDK singleton.
69
+ * Must be called before any other SDK methods.
70
+ * Safe to call multiple times — returns existing instance after first init.
71
+ *
72
+ * @param options - SDK configuration options.
73
+ * @returns The initialized Nexus singleton instance.
74
+ *
75
+ * @example
76
+ * const nexus = Nexus.init({ apiKey: 'pk_live_...' });
77
+ */
78
+ static init(options?: NexusInitOptions): Nexus;
79
+ /**
80
+ * Returns the current Nexus singleton instance.
81
+ *
82
+ * @returns The active Nexus instance.
83
+ * @throws {Error} If `Nexus.init()` has not been called yet.
84
+ *
85
+ * @example
86
+ * const nexus = Nexus.getInstance();
87
+ * nexus.flags.isEnabled('checkout_v2');
88
+ */
89
+ static getInstance(): Nexus;
90
+ /**
91
+ * Convenience method: Check if a feature flag is enabled.
92
+ *
93
+ * @param key - Flag identifier.
94
+ * @param defaultValue - Fallback if flag is missing.
95
+ * @returns Boolean enabled state.
96
+ *
97
+ * @example
98
+ * if (Nexus.isEnabled('checkout_redesign')) { ... }
99
+ */
100
+ static isEnabled(key: string, defaultValue?: boolean): boolean;
101
+ /**
102
+ * Convenience method: Get a flag variant value.
103
+ *
104
+ * @param key - Flag identifier.
105
+ * @param variantKey - Variant property name.
106
+ * @param defaultValue - Fallback value.
107
+ * @returns Variant value cast to type T.
108
+ *
109
+ * @example
110
+ * const rate = Nexus.getVariant<number>('promo_banner_v2', 'discount_rate', 10);
111
+ */
112
+ static getVariant<T = unknown>(key: string, variantKey: string, defaultValue?: T): T;
113
+ /**
114
+ * Convenience method: Capture an error manually.
115
+ *
116
+ * @param error - Error instance, string, or unknown value.
117
+ * @param extra - Optional metadata tags.
118
+ *
119
+ * @example
120
+ * Nexus.captureError(new TypeError('Cannot read properties of null'));
121
+ */
122
+ static captureError(error: unknown, extra?: Record<string, unknown>): void;
123
+ /**
124
+ * Convenience method: Update user context for both flags and tracker.
125
+ *
126
+ * @param user - New user context (merged with existing).
127
+ * @returns Promise resolving after flags refresh.
128
+ *
129
+ * @example
130
+ * await Nexus.identify({ id: 'usr_12345', country: 'VN' });
131
+ */
132
+ static identify(user: UserContext): Promise<void>;
133
+ /**
134
+ * Resets user context to anonymous state (e.g. on logout).
135
+ *
136
+ * @example
137
+ * Nexus.reset(); // called on user logout
138
+ */
139
+ static reset(): void;
140
+ /**
141
+ * Gracefully tears down both clients, closing SSE connections and flushing pending events.
142
+ *
143
+ * @example
144
+ * await Nexus.destroy();
145
+ */
146
+ static destroy(): Promise<void>;
147
+ }
148
+
149
+ /**
150
+ * @fileoverview React Context Provider and hooks for the Nexus SDK umbrella.
151
+ * @module @nexus/sdk/react
152
+ */
153
+
154
+ interface NexusContextValue {
155
+ flags: NexusFlagsClient;
156
+ tracker: NexusTrackerClient;
157
+ nexus: Nexus;
158
+ }
159
+ /**
160
+ * Props for the NexusProvider component.
161
+ */
162
+ interface NexusProviderProps extends NexusInitOptions {
163
+ /** Child components that will have access to Nexus context. */
164
+ children?: React.ReactNode | any;
165
+ }
166
+ /**
167
+ * React Context Provider that initializes the Nexus SDK and makes it available
168
+ * to all descendant components via `useFlag` and `useNexus` hooks.
169
+ *
170
+ * Mount once at the root of your application (e.g. in `layout.tsx`).
171
+ *
172
+ * @param props - Provider configuration options (see {@link NexusProviderProps}).
173
+ * @returns Provider-wrapped children.
174
+ *
175
+ * @example
176
+ * // app/layout.tsx
177
+ * import { NexusProvider } from '@nexussdk/sdk/react';
178
+ *
179
+ * export default function RootLayout({ children }) {
180
+ * return (
181
+ * <html>
182
+ * <body>
183
+ * <NexusProvider apiKey={process.env.NEXT_PUBLIC_NEXUS_API_KEY}>
184
+ * {children}
185
+ * </NexusProvider>
186
+ * </body>
187
+ * </html>
188
+ * );
189
+ * }
190
+ */
191
+ declare function NexusProvider({ children, ...initOptions }: NexusProviderProps): React.ReactElement;
192
+ /**
193
+ * Returns the full Nexus SDK instance from context.
194
+ *
195
+ * @returns Object with `flags`, `tracker`, and `nexus` properties.
196
+ * @throws {Error} If called outside of a `NexusProvider`.
197
+ *
198
+ * @example
199
+ * const { flags, tracker } = useNexus();
200
+ * const enabled = flags.isEnabled('checkout_v2');
201
+ * tracker.captureError(new Error('something failed'));
202
+ */
203
+ declare function useNexus(): NexusContextValue;
204
+ /**
205
+ * Return value of the `useFlag` hook.
206
+ */
207
+ interface UseFlagResult {
208
+ /** Whether the flag is currently enabled for the current user. */
209
+ enabled: boolean;
210
+ /**
211
+ * Retrieves a specific variant value from this flag.
212
+ *
213
+ * @param variantKey - Property name inside the variants object.
214
+ * @param defaultValue - Fallback if variant is not found.
215
+ * @returns Typed variant value.
216
+ *
217
+ * @example
218
+ * const { enabled, getVariant } = useFlag('promo_banner_v2');
219
+ * const rate = getVariant<number>('discount_rate', 10);
220
+ */
221
+ getVariant: <T = unknown>(variantKey: string, defaultValue?: T) => T;
222
+ /** Full evaluation result including reason and version. */
223
+ result: FlagEvaluationResult | null;
224
+ }
225
+ /**
226
+ * React hook for subscribing to a feature flag's real-time state.
227
+ *
228
+ * Automatically re-renders when the flag changes via SSE updates.
229
+ * Returns a stable result without triggering additional re-renders if unchanged.
230
+ *
231
+ * @param key - Flag programmatic identifier.
232
+ * @param defaultEnabled - Fallback boolean if flag is not yet evaluated. Defaults to false.
233
+ * @returns {@link UseFlagResult} with `enabled`, `getVariant`, and `result`.
234
+ *
235
+ * @example
236
+ * function CheckoutButton() {
237
+ * const { enabled, getVariant } = useFlag('checkout_redesign');
238
+ * const theme = getVariant<string>('theme', 'default');
239
+ *
240
+ * return (
241
+ * <button className={enabled ? `btn-${theme}` : 'btn-default'}>
242
+ * {enabled ? 'New Checkout' : 'Checkout'}
243
+ * </button>
244
+ * );
245
+ * }
246
+ */
247
+ declare function useFlag(key: string, defaultEnabled?: boolean): UseFlagResult;
248
+
249
+ export { NexusProvider, type NexusProviderProps, type UseFlagResult, useFlag, useNexus };
@@ -0,0 +1,249 @@
1
+ import React from 'react';
2
+ import { NexusFlagsOptions, NexusFlagsClient } from '@nexussdk/flags';
3
+ import { NexusTrackerOptions, NexusTrackerClient } from '@nexussdk/tracker';
4
+ import { UserContext, FlagEvaluationResult } from '@nexussdk/contracts';
5
+
6
+ /**
7
+ * @fileoverview Unified Nexus singleton facade wrapping Flags and Tracker clients.
8
+ * @module @nexus/sdk/nexus
9
+ */
10
+
11
+ /**
12
+ * Unified initialization options for the Nexus SDK umbrella.
13
+ *
14
+ * @example
15
+ * Nexus.init({
16
+ * apiKey: 'pk_live_...',
17
+ * baseUrl: 'http://localhost:8080',
18
+ * user: { id: 'usr_12345', country: 'VN' },
19
+ * environment: 'production',
20
+ * autoCapture: true,
21
+ * });
22
+ */
23
+ interface NexusInitOptions {
24
+ /** Public API key. Resolved from env if omitted. */
25
+ apiKey?: string;
26
+ /** Base URL for all API calls. */
27
+ baseUrl?: string;
28
+ /** Initial user context for flag targeting and error attribution. */
29
+ user?: UserContext;
30
+ /** Target environment for telemetry routing. Defaults to 'production'. */
31
+ environment?: string;
32
+ /** Global tags attached to all telemetry events. */
33
+ tags?: Record<string, string>;
34
+ /** Toggle automated global error capture. Defaults to true. */
35
+ autoCapture?: boolean;
36
+ /** Additional flags-specific options. */
37
+ flags?: Partial<NexusFlagsOptions>;
38
+ /** Additional tracker-specific options. */
39
+ tracker?: Partial<NexusTrackerOptions>;
40
+ }
41
+ /**
42
+ * The Nexus singleton class — the primary unified entry point for the SDK.
43
+ *
44
+ * Provides access to both the feature flags client and the error tracker client.
45
+ * Initialize once, then use throughout your application.
46
+ *
47
+ * @example
48
+ * // Initialize (call once at app startup)
49
+ * Nexus.init({ apiKey: 'pk_live_...' });
50
+ *
51
+ * // Feature flags
52
+ * const showBanner = Nexus.isEnabled('promo_banner_v2', false);
53
+ *
54
+ * // Error tracking
55
+ * Nexus.captureError(new Error('Something went wrong'));
56
+ *
57
+ * // Update user context
58
+ * await Nexus.identify({ id: 'usr_12345', country: 'VN' });
59
+ */
60
+ declare class Nexus {
61
+ private static instance;
62
+ /** The underlying feature flags client instance. */
63
+ readonly flags: NexusFlagsClient;
64
+ /** The underlying error tracker client instance. */
65
+ readonly tracker: NexusTrackerClient;
66
+ private constructor();
67
+ /**
68
+ * Initializes the Nexus SDK singleton.
69
+ * Must be called before any other SDK methods.
70
+ * Safe to call multiple times — returns existing instance after first init.
71
+ *
72
+ * @param options - SDK configuration options.
73
+ * @returns The initialized Nexus singleton instance.
74
+ *
75
+ * @example
76
+ * const nexus = Nexus.init({ apiKey: 'pk_live_...' });
77
+ */
78
+ static init(options?: NexusInitOptions): Nexus;
79
+ /**
80
+ * Returns the current Nexus singleton instance.
81
+ *
82
+ * @returns The active Nexus instance.
83
+ * @throws {Error} If `Nexus.init()` has not been called yet.
84
+ *
85
+ * @example
86
+ * const nexus = Nexus.getInstance();
87
+ * nexus.flags.isEnabled('checkout_v2');
88
+ */
89
+ static getInstance(): Nexus;
90
+ /**
91
+ * Convenience method: Check if a feature flag is enabled.
92
+ *
93
+ * @param key - Flag identifier.
94
+ * @param defaultValue - Fallback if flag is missing.
95
+ * @returns Boolean enabled state.
96
+ *
97
+ * @example
98
+ * if (Nexus.isEnabled('checkout_redesign')) { ... }
99
+ */
100
+ static isEnabled(key: string, defaultValue?: boolean): boolean;
101
+ /**
102
+ * Convenience method: Get a flag variant value.
103
+ *
104
+ * @param key - Flag identifier.
105
+ * @param variantKey - Variant property name.
106
+ * @param defaultValue - Fallback value.
107
+ * @returns Variant value cast to type T.
108
+ *
109
+ * @example
110
+ * const rate = Nexus.getVariant<number>('promo_banner_v2', 'discount_rate', 10);
111
+ */
112
+ static getVariant<T = unknown>(key: string, variantKey: string, defaultValue?: T): T;
113
+ /**
114
+ * Convenience method: Capture an error manually.
115
+ *
116
+ * @param error - Error instance, string, or unknown value.
117
+ * @param extra - Optional metadata tags.
118
+ *
119
+ * @example
120
+ * Nexus.captureError(new TypeError('Cannot read properties of null'));
121
+ */
122
+ static captureError(error: unknown, extra?: Record<string, unknown>): void;
123
+ /**
124
+ * Convenience method: Update user context for both flags and tracker.
125
+ *
126
+ * @param user - New user context (merged with existing).
127
+ * @returns Promise resolving after flags refresh.
128
+ *
129
+ * @example
130
+ * await Nexus.identify({ id: 'usr_12345', country: 'VN' });
131
+ */
132
+ static identify(user: UserContext): Promise<void>;
133
+ /**
134
+ * Resets user context to anonymous state (e.g. on logout).
135
+ *
136
+ * @example
137
+ * Nexus.reset(); // called on user logout
138
+ */
139
+ static reset(): void;
140
+ /**
141
+ * Gracefully tears down both clients, closing SSE connections and flushing pending events.
142
+ *
143
+ * @example
144
+ * await Nexus.destroy();
145
+ */
146
+ static destroy(): Promise<void>;
147
+ }
148
+
149
+ /**
150
+ * @fileoverview React Context Provider and hooks for the Nexus SDK umbrella.
151
+ * @module @nexus/sdk/react
152
+ */
153
+
154
+ interface NexusContextValue {
155
+ flags: NexusFlagsClient;
156
+ tracker: NexusTrackerClient;
157
+ nexus: Nexus;
158
+ }
159
+ /**
160
+ * Props for the NexusProvider component.
161
+ */
162
+ interface NexusProviderProps extends NexusInitOptions {
163
+ /** Child components that will have access to Nexus context. */
164
+ children?: React.ReactNode | any;
165
+ }
166
+ /**
167
+ * React Context Provider that initializes the Nexus SDK and makes it available
168
+ * to all descendant components via `useFlag` and `useNexus` hooks.
169
+ *
170
+ * Mount once at the root of your application (e.g. in `layout.tsx`).
171
+ *
172
+ * @param props - Provider configuration options (see {@link NexusProviderProps}).
173
+ * @returns Provider-wrapped children.
174
+ *
175
+ * @example
176
+ * // app/layout.tsx
177
+ * import { NexusProvider } from '@nexussdk/sdk/react';
178
+ *
179
+ * export default function RootLayout({ children }) {
180
+ * return (
181
+ * <html>
182
+ * <body>
183
+ * <NexusProvider apiKey={process.env.NEXT_PUBLIC_NEXUS_API_KEY}>
184
+ * {children}
185
+ * </NexusProvider>
186
+ * </body>
187
+ * </html>
188
+ * );
189
+ * }
190
+ */
191
+ declare function NexusProvider({ children, ...initOptions }: NexusProviderProps): React.ReactElement;
192
+ /**
193
+ * Returns the full Nexus SDK instance from context.
194
+ *
195
+ * @returns Object with `flags`, `tracker`, and `nexus` properties.
196
+ * @throws {Error} If called outside of a `NexusProvider`.
197
+ *
198
+ * @example
199
+ * const { flags, tracker } = useNexus();
200
+ * const enabled = flags.isEnabled('checkout_v2');
201
+ * tracker.captureError(new Error('something failed'));
202
+ */
203
+ declare function useNexus(): NexusContextValue;
204
+ /**
205
+ * Return value of the `useFlag` hook.
206
+ */
207
+ interface UseFlagResult {
208
+ /** Whether the flag is currently enabled for the current user. */
209
+ enabled: boolean;
210
+ /**
211
+ * Retrieves a specific variant value from this flag.
212
+ *
213
+ * @param variantKey - Property name inside the variants object.
214
+ * @param defaultValue - Fallback if variant is not found.
215
+ * @returns Typed variant value.
216
+ *
217
+ * @example
218
+ * const { enabled, getVariant } = useFlag('promo_banner_v2');
219
+ * const rate = getVariant<number>('discount_rate', 10);
220
+ */
221
+ getVariant: <T = unknown>(variantKey: string, defaultValue?: T) => T;
222
+ /** Full evaluation result including reason and version. */
223
+ result: FlagEvaluationResult | null;
224
+ }
225
+ /**
226
+ * React hook for subscribing to a feature flag's real-time state.
227
+ *
228
+ * Automatically re-renders when the flag changes via SSE updates.
229
+ * Returns a stable result without triggering additional re-renders if unchanged.
230
+ *
231
+ * @param key - Flag programmatic identifier.
232
+ * @param defaultEnabled - Fallback boolean if flag is not yet evaluated. Defaults to false.
233
+ * @returns {@link UseFlagResult} with `enabled`, `getVariant`, and `result`.
234
+ *
235
+ * @example
236
+ * function CheckoutButton() {
237
+ * const { enabled, getVariant } = useFlag('checkout_redesign');
238
+ * const theme = getVariant<string>('theme', 'default');
239
+ *
240
+ * return (
241
+ * <button className={enabled ? `btn-${theme}` : 'btn-default'}>
242
+ * {enabled ? 'New Checkout' : 'Checkout'}
243
+ * </button>
244
+ * );
245
+ * }
246
+ */
247
+ declare function useFlag(key: string, defaultEnabled?: boolean): UseFlagResult;
248
+
249
+ export { NexusProvider, type NexusProviderProps, type UseFlagResult, useFlag, useNexus };
package/dist/react.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import N,{createContext,useRef,useMemo,useEffect,useContext,useState}from'react';import {NexusFlagsClient}from'@nexussdk/flags';import {NexusTrackerClient}from'@nexussdk/tracker';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 NexusFlagsClient({apiKey:t,baseUrl:s,user:i,...p}),this.tracker=new 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=createContext(null);function y({children:e,...n}){let t=useRef(null);t.current||(t.current=a.init(n));let s=useMemo(()=>({flags:t.current.flags,tracker:t.current.tracker,nexus:t.current}),[]);return useEffect(()=>()=>{a.destroy();},[]),N.createElement(x.Provider,{value:s},e)}function C(){let e=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]=useState(()=>t.isEnabled(e)!==n?{key:e,enabled:t.isEnabled(e),variants:{},reason:"DEFAULT_ENABLED",version:0}:null);return 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]),useMemo(()=>({enabled:s?.enabled??t.isEnabled(e,n),getVariant:(r,u)=>t.getVariant(e,r,u),result:s}),[s,e,t,n])}export{y as NexusProvider,I as useFlag,C as useNexus};//# sourceMappingURL=react.mjs.map
2
+ //# sourceMappingURL=react.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/nexus.ts","../src/react.tsx"],"names":["Nexus","_Nexus","options","apiKey","baseUrl","user","environment","tags","autoCapture","flagsOpts","trackerOpts","NexusFlagsClient","NexusTrackerClient","key","defaultValue","variantKey","error","extra","instance","NexusContext","createContext","NexusProvider","children","initOptions","nexusRef","useRef","contextValue","useMemo","useEffect","React","useNexus","ctx","useContext","useFlag","defaultEnabled","flags","result","setResult","useState","currentEnabled","newResult","def"],"mappings":"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","file":"react.mjs","sourcesContent":["/**\n * @fileoverview Unified Nexus singleton facade wrapping Flags and Tracker clients.\n * @module @nexus/sdk/nexus\n */\n\nimport { NexusFlagsClient } from '@nexussdk/flags';\nimport type { NexusFlagsOptions } from '@nexussdk/flags';\nimport { NexusTrackerClient } from '@nexussdk/tracker';\nimport type { NexusTrackerOptions } from '@nexussdk/tracker';\nimport type { UserContext } from '@nexussdk/contracts';\n\n/**\n * Unified initialization options for the Nexus SDK umbrella.\n *\n * @example\n * Nexus.init({\n * apiKey: 'pk_live_...',\n * baseUrl: 'http://localhost:8080',\n * user: { id: 'usr_12345', country: 'VN' },\n * environment: 'production',\n * autoCapture: true,\n * });\n */\nexport interface NexusInitOptions {\n /** Public API key. Resolved from env if omitted. */\n apiKey?: string;\n /** Base URL for all API calls. */\n baseUrl?: string;\n /** Initial user context for flag targeting and error attribution. */\n user?: UserContext;\n /** Target environment for telemetry routing. Defaults to 'production'. */\n environment?: string;\n /** Global tags attached to all telemetry events. */\n tags?: Record<string, string>;\n /** Toggle automated global error capture. Defaults to true. */\n autoCapture?: boolean;\n /** Additional flags-specific options. */\n flags?: Partial<NexusFlagsOptions>;\n /** Additional tracker-specific options. */\n tracker?: Partial<NexusTrackerOptions>;\n}\n\n/**\n * The Nexus singleton class — the primary unified entry point for the SDK.\n *\n * Provides access to both the feature flags client and the error tracker client.\n * Initialize once, then use throughout your application.\n *\n * @example\n * // Initialize (call once at app startup)\n * Nexus.init({ apiKey: 'pk_live_...' });\n *\n * // Feature flags\n * const showBanner = Nexus.isEnabled('promo_banner_v2', false);\n *\n * // Error tracking\n * Nexus.captureError(new Error('Something went wrong'));\n *\n * // Update user context\n * await Nexus.identify({ id: 'usr_12345', country: 'VN' });\n */\nexport class Nexus {\n private static instance: Nexus | null = null;\n\n /** The underlying feature flags client instance. */\n public readonly flags: NexusFlagsClient;\n /** The underlying error tracker client instance. */\n public readonly tracker: NexusTrackerClient;\n\n private constructor(options: NexusInitOptions = {}) {\n const { apiKey, baseUrl, user, environment, tags, autoCapture, flags: flagsOpts, tracker: trackerOpts } = options;\n\n this.flags = new NexusFlagsClient({\n apiKey,\n baseUrl,\n user,\n ...flagsOpts,\n });\n\n this.tracker = new NexusTrackerClient({\n apiKey,\n baseUrl,\n environment,\n tags,\n autoCapture,\n ...trackerOpts,\n });\n }\n\n /**\n * Initializes the Nexus SDK singleton.\n * Must be called before any other SDK methods.\n * Safe to call multiple times — returns existing instance after first init.\n *\n * @param options - SDK configuration options.\n * @returns The initialized Nexus singleton instance.\n *\n * @example\n * const nexus = Nexus.init({ apiKey: 'pk_live_...' });\n */\n public static init(options: NexusInitOptions = {}): Nexus {\n if (!Nexus.instance) {\n Nexus.instance = new Nexus(options);\n }\n return Nexus.instance;\n }\n\n /**\n * Returns the current Nexus singleton instance.\n *\n * @returns The active Nexus instance.\n * @throws {Error} If `Nexus.init()` has not been called yet.\n *\n * @example\n * const nexus = Nexus.getInstance();\n * nexus.flags.isEnabled('checkout_v2');\n */\n public static getInstance(): Nexus {\n if (!Nexus.instance) {\n throw new Error('[Nexus SDK] Not initialized. Call Nexus.init({ apiKey: \"...\" }) first.');\n }\n return Nexus.instance;\n }\n\n /**\n * Convenience method: Check if a feature flag is enabled.\n *\n * @param key - Flag identifier.\n * @param defaultValue - Fallback if flag is missing.\n * @returns Boolean enabled state.\n *\n * @example\n * if (Nexus.isEnabled('checkout_redesign')) { ... }\n */\n public static isEnabled(key: string, defaultValue = false): boolean {\n return Nexus.getInstance().flags.isEnabled(key, defaultValue);\n }\n\n /**\n * Convenience method: Get a flag variant value.\n *\n * @param key - Flag identifier.\n * @param variantKey - Variant property name.\n * @param defaultValue - Fallback value.\n * @returns Variant value cast to type T.\n *\n * @example\n * const rate = Nexus.getVariant<number>('promo_banner_v2', 'discount_rate', 10);\n */\n public static getVariant<T = unknown>(key: string, variantKey: string, defaultValue?: T): T {\n return Nexus.getInstance().flags.getVariant<T>(key, variantKey, defaultValue);\n }\n\n /**\n * Convenience method: Capture an error manually.\n *\n * @param error - Error instance, string, or unknown value.\n * @param extra - Optional metadata tags.\n *\n * @example\n * Nexus.captureError(new TypeError('Cannot read properties of null'));\n */\n public static captureError(error: unknown, extra?: Record<string, unknown>): void {\n Nexus.getInstance().tracker.captureError(error, extra);\n }\n\n /**\n * Convenience method: Update user context for both flags and tracker.\n *\n * @param user - New user context (merged with existing).\n * @returns Promise resolving after flags refresh.\n *\n * @example\n * await Nexus.identify({ id: 'usr_12345', country: 'VN' });\n */\n public static async identify(user: UserContext): Promise<void> {\n const instance = Nexus.getInstance();\n instance.tracker.setUser(user);\n await instance.flags.identify(user);\n }\n\n /**\n * Resets user context to anonymous state (e.g. on logout).\n *\n * @example\n * Nexus.reset(); // called on user logout\n */\n public static reset(): void {\n const instance = Nexus.getInstance();\n instance.tracker.setUser(null);\n instance.flags.reset();\n }\n\n /**\n * Gracefully tears down both clients, closing SSE connections and flushing pending events.\n *\n * @example\n * await Nexus.destroy();\n */\n public static async destroy(): Promise<void> {\n if (Nexus.instance) {\n await Nexus.instance.tracker.flush();\n Nexus.instance.tracker.destroy();\n Nexus.instance.flags.destroy();\n Nexus.instance = null;\n }\n }\n}\n","'use client';\n\n/**\n * @fileoverview React Context Provider and hooks for the Nexus SDK umbrella.\n * @module @nexus/sdk/react\n */\n\nimport React, {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Nexus } from './nexus.js';\nimport type { NexusInitOptions } from './nexus.js';\nimport type { FlagEvaluationResult } from '@nexussdk/contracts';\nimport type { NexusFlagsClient } from '@nexussdk/flags';\nimport type { NexusTrackerClient } from '@nexussdk/tracker';\n\n// ---------------------------------------------------------------------------\n// Context Definition\n// ---------------------------------------------------------------------------\n\ninterface NexusContextValue {\n flags: NexusFlagsClient;\n tracker: NexusTrackerClient;\n nexus: Nexus;\n}\n\nconst NexusContext = createContext<NexusContextValue | null>(null);\n\n// ---------------------------------------------------------------------------\n// Provider\n// ---------------------------------------------------------------------------\n\n/**\n * Props for the NexusProvider component.\n */\nexport interface NexusProviderProps extends NexusInitOptions {\n /** Child components that will have access to Nexus context. */\n children?: React.ReactNode | any;\n}\n\n/**\n * React Context Provider that initializes the Nexus SDK and makes it available\n * to all descendant components via `useFlag` and `useNexus` hooks.\n *\n * Mount once at the root of your application (e.g. in `layout.tsx`).\n *\n * @param props - Provider configuration options (see {@link NexusProviderProps}).\n * @returns Provider-wrapped children.\n *\n * @example\n * // app/layout.tsx\n * import { NexusProvider } from '@nexussdk/sdk/react';\n *\n * export default function RootLayout({ children }) {\n * return (\n * <html>\n * <body>\n * <NexusProvider apiKey={process.env.NEXT_PUBLIC_NEXUS_API_KEY}>\n * {children}\n * </NexusProvider>\n * </body>\n * </html>\n * );\n * }\n */\nexport function NexusProvider({ children, ...initOptions }: NexusProviderProps): React.ReactElement {\n const nexusRef = useRef<Nexus | null>(null);\n\n if (!nexusRef.current) {\n nexusRef.current = Nexus.init(initOptions);\n }\n\n const contextValue = useMemo<NexusContextValue>(\n () => ({\n flags: nexusRef.current!.flags,\n tracker: nexusRef.current!.tracker,\n nexus: nexusRef.current!,\n }),\n [],\n );\n\n useEffect(() => {\n return () => {\n void Nexus.destroy();\n };\n }, []);\n\n return React.createElement(NexusContext.Provider, { value: contextValue }, children);\n}\n\n// ---------------------------------------------------------------------------\n// Hooks\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the full Nexus SDK instance from context.\n *\n * @returns Object with `flags`, `tracker`, and `nexus` properties.\n * @throws {Error} If called outside of a `NexusProvider`.\n *\n * @example\n * const { flags, tracker } = useNexus();\n * const enabled = flags.isEnabled('checkout_v2');\n * tracker.captureError(new Error('something failed'));\n */\nexport function useNexus(): NexusContextValue {\n const ctx = useContext(NexusContext);\n if (!ctx) {\n throw new Error('[Nexus SDK] useNexus() must be called inside a <NexusProvider>.');\n }\n return ctx;\n}\n\n/**\n * Return value of the `useFlag` hook.\n */\nexport interface UseFlagResult {\n /** Whether the flag is currently enabled for the current user. */\n enabled: boolean;\n /**\n * Retrieves a specific variant value from this flag.\n *\n * @param variantKey - Property name inside the variants object.\n * @param defaultValue - Fallback if variant is not found.\n * @returns Typed variant value.\n *\n * @example\n * const { enabled, getVariant } = useFlag('promo_banner_v2');\n * const rate = getVariant<number>('discount_rate', 10);\n */\n getVariant: <T = unknown>(variantKey: string, defaultValue?: T) => T;\n /** Full evaluation result including reason and version. */\n result: FlagEvaluationResult | null;\n}\n\n/**\n * React hook for subscribing to a feature flag's real-time state.\n *\n * Automatically re-renders when the flag changes via SSE updates.\n * Returns a stable result without triggering additional re-renders if unchanged.\n *\n * @param key - Flag programmatic identifier.\n * @param defaultEnabled - Fallback boolean if flag is not yet evaluated. Defaults to false.\n * @returns {@link UseFlagResult} with `enabled`, `getVariant`, and `result`.\n *\n * @example\n * function CheckoutButton() {\n * const { enabled, getVariant } = useFlag('checkout_redesign');\n * const theme = getVariant<string>('theme', 'default');\n *\n * return (\n * <button className={enabled ? `btn-${theme}` : 'btn-default'}>\n * {enabled ? 'New Checkout' : 'Checkout'}\n * </button>\n * );\n * }\n */\nexport function useFlag(key: string, defaultEnabled = false): UseFlagResult {\n const { flags } = useNexus();\n\n const [result, setResult] = useState<FlagEvaluationResult | null>(() => {\n const cached = flags.isEnabled(key) !== defaultEnabled\n ? { key, enabled: flags.isEnabled(key), variants: {}, reason: 'DEFAULT_ENABLED' as const, version: 0 }\n : null;\n return cached;\n });\n\n useEffect(() => {\n // Get current state immediately\n const currentEnabled = flags.isEnabled(key, defaultEnabled);\n if (currentEnabled !== (result?.enabled ?? defaultEnabled)) {\n setResult({\n key,\n enabled: currentEnabled,\n variants: {},\n reason: 'DEFAULT_ENABLED',\n version: 0,\n });\n }\n\n // Subscribe to real-time updates\n const unsubscribe = flags.onFlagChange(key, (newResult) => {\n setResult(newResult);\n });\n\n return unsubscribe;\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [key]);\n\n return useMemo(\n () => ({\n enabled: result?.enabled ?? flags.isEnabled(key, defaultEnabled),\n getVariant: <T = unknown>(variantKey: string, def?: T): T =>\n flags.getVariant<T>(key, variantKey, def),\n result,\n }),\n [result, key, flags, defaultEnabled],\n );\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@nexussdk/sdk",
3
+ "version": "0.0.1",
4
+ "private": false,
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "description": "Unified umbrella SDK for Nexus Platform — feature flags + error tracking + React hooks",
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.mjs",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./react": {
19
+ "types": "./dist/react.d.ts",
20
+ "import": "./dist/react.mjs",
21
+ "require": "./dist/react.cjs"
22
+ }
23
+ },
24
+ "dependencies": {
25
+ "@nexussdk/core": "0.0.1",
26
+ "@nexussdk/flags": "0.0.1",
27
+ "@nexussdk/tracker": "0.0.1",
28
+ "@nexussdk/contracts": "0.0.1"
29
+ },
30
+ "peerDependencies": {
31
+ "react": ">=18.0.0"
32
+ },
33
+ "peerDependenciesMeta": {
34
+ "react": {
35
+ "optional": true
36
+ }
37
+ },
38
+ "devDependencies": {
39
+ "@types/react": "^18.3.0",
40
+ "react": "^18.3.0",
41
+ "tsup": "^8.0.2",
42
+ "typescript": "^5.4.5",
43
+ "rimraf": "^5.0.5"
44
+ },
45
+ "scripts": {
46
+ "build": "tsup",
47
+ "dev": "tsup --watch",
48
+ "lint": "tsc --noEmit",
49
+ "clean": "rimraf dist"
50
+ }
51
+ }
package/src/index.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @fileoverview Main entry point for @nexussdk/sdk umbrella package.
3
+ * Exports the unified Nexus singleton and all sub-package types.
4
+ *
5
+ * @example
6
+ * import { Nexus } from '@nexussdk/sdk';
7
+ * import { NexusProvider, useFlag } from '@nexussdk/sdk/react';
8
+ */
9
+
10
+ export { Nexus } from './nexus.js';
11
+ export type { NexusInitOptions } from './nexus.js';
12
+
13
+ // Re-export SDK sub-packages for direct access
14
+ export { NexusFlagsClient } from '@nexussdk/flags';
15
+ export type { NexusFlagsOptions, INexusFlagsClient } from '@nexussdk/flags';
16
+
17
+ export { NexusTrackerClient } from '@nexussdk/tracker';
18
+ export type { NexusTrackerOptions, INexusTrackerClient } from '@nexussdk/tracker';
19
+
20
+ // Re-export core contracts for consumer convenience
21
+ export type {
22
+ FeatureFlag,
23
+ FlagEvaluationResult,
24
+ UserContext,
25
+ ErrorEventPayload,
26
+ ProblemDetails,
27
+ } from '@nexussdk/contracts';