@mission_sciences/provider-sdk 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,767 @@
1
+ /**
2
+ * Dark theme matching gw-spa design system
3
+ */
4
+ export declare const darkTheme: Theme;
5
+
6
+ /**
7
+ * Extract JWT token from URL parameter
8
+ * @param paramName - URL parameter name (default: 'jwt')
9
+ * @param url - URL to extract from (default: window.location.href)
10
+ * @returns JWT token or null if not found
11
+ */
12
+ export declare function extractTokenFromURL(paramName?: string, url?: string): string | null;
13
+
14
+ /**
15
+ * Generate CSS string from theme colors for inline styles
16
+ */
17
+ export declare function generateCSSVariables(theme: Theme): string;
18
+
19
+ /**
20
+ * Get theme based on user preference or system setting
21
+ */
22
+ export declare function getTheme(prefersDark?: boolean): Theme;
23
+
24
+ /**
25
+ * Heartbeat Manager for active session tracking
26
+ * Phase 2 Feature - Sends periodic heartbeats to backend
27
+ */
28
+ export declare class HeartbeatManager {
29
+ private sessionId;
30
+ private apiEndpoint;
31
+ private token;
32
+ private onSync?;
33
+ private onError?;
34
+ private intervalId;
35
+ private heartbeatInterval;
36
+ private failureCount;
37
+ private maxFailures;
38
+ private isEnabled;
39
+ private logger;
40
+ constructor(sessionId: string, apiEndpoint: string, token: string, onSync?: ((remainingSeconds: number) => void) | undefined, onError?: ((error: Error) => void) | undefined, heartbeatIntervalSeconds?: number, debug?: boolean);
41
+ /**
42
+ * Start sending heartbeats
43
+ */
44
+ start(): void;
45
+ /**
46
+ * Stop sending heartbeats
47
+ */
48
+ stop(): void;
49
+ /**
50
+ * Send a single heartbeat to backend
51
+ */
52
+ private sendHeartbeat;
53
+ /**
54
+ * Check if heartbeat is running
55
+ */
56
+ isRunning(): boolean;
57
+ /**
58
+ * Get failure count
59
+ */
60
+ getFailureCount(): number;
61
+ /**
62
+ * Update heartbeat interval
63
+ */
64
+ updateInterval(seconds: number): void;
65
+ }
66
+
67
+ /**
68
+ * Check if code is running in browser environment
69
+ */
70
+ export declare function isBrowser(): boolean;
71
+
72
+ /**
73
+ * JWKS Key
74
+ */
75
+ export declare interface JWKSKey {
76
+ kty: string;
77
+ use: string;
78
+ kid: string;
79
+ alg: string;
80
+ n: string;
81
+ e: string;
82
+ }
83
+
84
+ /**
85
+ * JWKS Response
86
+ */
87
+ export declare interface JWKSResponse {
88
+ keys: JWKSKey[];
89
+ }
90
+
91
+ /**
92
+ * JWKS Validator for RS256 JWT signature verification
93
+ * Uses jose library for browser and Node.js compatibility
94
+ */
95
+ export declare class JWKSValidator {
96
+ private jwksUri;
97
+ private logger;
98
+ private jwks;
99
+ constructor(jwksUri: string, debug?: boolean);
100
+ /**
101
+ * Verify JWT signature using JWKS public key
102
+ * @param token - JWT token to verify
103
+ * @param expectedIssuer - Expected issuer (default: 'generalwisdom.com')
104
+ * @param expectedApplicationId - Optional application ID to validate
105
+ * @returns Decoded and verified JWT claims
106
+ */
107
+ verify(token: string, expectedIssuer?: string, expectedApplicationId?: string): Promise<JWTClaims>;
108
+ /**
109
+ * Update JWKS URI
110
+ * @param jwksUri - New JWKS URI
111
+ */
112
+ updateJwksUri(jwksUri: string): void;
113
+ }
114
+
115
+ /**
116
+ * JWT Claims (raw payload from token)
117
+ */
118
+ export declare interface JWTClaims {
119
+ sessionId: string;
120
+ applicationId: string;
121
+ userId: string;
122
+ orgId: string;
123
+ startTime: number;
124
+ durationMinutes: number;
125
+ iat: number;
126
+ exp: number;
127
+ iss: string;
128
+ sub: string;
129
+ }
130
+
131
+ /**
132
+ * JWT Header
133
+ */
134
+ export declare interface JWTHeader {
135
+ alg: string;
136
+ typ: string;
137
+ kid: string;
138
+ }
139
+
140
+ /**
141
+ * JWT Parser for client-side token decoding
142
+ * Note: Does NOT verify signature - use JWKSValidator for verification
143
+ */
144
+ export declare class JWTParser {
145
+ /**
146
+ * Decode JWT payload without verification
147
+ * @param token - JWT token string
148
+ * @returns Decoded payload
149
+ */
150
+ static decode(token: string): JWTClaims;
151
+ /**
152
+ * Decode JWT header
153
+ * @param token - JWT token string
154
+ * @returns Decoded header
155
+ */
156
+ static decodeHeader(token: string): JWTHeader;
157
+ /**
158
+ * Extract specific claim from JWT
159
+ * @param token - JWT token string
160
+ * @param claim - Claim name to extract
161
+ * @returns Claim value
162
+ */
163
+ static extractClaim<T = any>(token: string, claim: string): T;
164
+ /**
165
+ * Check if JWT is expired (client-side only, not authoritative)
166
+ * @param token - JWT token string
167
+ * @returns True if token is expired
168
+ */
169
+ static isExpired(token: string): boolean;
170
+ /**
171
+ * Get time remaining until expiration
172
+ * @param token - JWT token string
173
+ * @returns Seconds remaining (0 if expired)
174
+ */
175
+ static getTimeRemaining(token: string): number;
176
+ /**
177
+ * Base64 URL decode
178
+ * @param str - Base64 URL encoded string
179
+ * @returns Decoded string
180
+ */
181
+ private static base64UrlDecode;
182
+ }
183
+
184
+ /**
185
+ * Light theme matching gw-spa design system
186
+ */
187
+ export declare const lightTheme: Theme;
188
+
189
+ /**
190
+ * Simple logger with debug mode support
191
+ */
192
+ export declare class Logger {
193
+ private debug;
194
+ private prefix;
195
+ constructor(debug?: boolean, prefix?: string);
196
+ /**
197
+ * Log debug message (only if debug enabled)
198
+ */
199
+ log(...args: any[]): void;
200
+ /**
201
+ * Log info message (only if debug enabled)
202
+ */
203
+ info(...args: any[]): void;
204
+ /**
205
+ * Log warning message (always shown)
206
+ */
207
+ warn(...args: any[]): void;
208
+ /**
209
+ * Log error message (always shown)
210
+ */
211
+ error(...args: any[]): void;
212
+ }
213
+
214
+ /**
215
+ * Marketplace SDK with Phase 2 Features
216
+ * - Heartbeat system
217
+ * - Multi-tab synchronization
218
+ * - Visibility API integration
219
+ * - Session extension/completion
220
+ * - Backend validation
221
+ */
222
+ declare class MarketplaceSDK {
223
+ private config;
224
+ private validator;
225
+ private timer;
226
+ private heartbeat;
227
+ private tabSync;
228
+ private modal;
229
+ private logger;
230
+ private events;
231
+ private sessionData;
232
+ private jwtToken;
233
+ private endReason;
234
+ constructor(config: SDKConfig);
235
+ /**
236
+ * Register event handlers
237
+ */
238
+ on<K extends keyof SDKEvents>(event: K, handler: SDKEvents[K]): void;
239
+ /**
240
+ * Execute a lifecycle hook with timeout
241
+ */
242
+ private executeHook;
243
+ /**
244
+ * Calculate actual session duration in minutes
245
+ */
246
+ private calculateActualDuration;
247
+ /**
248
+ * Initialize SDK and validate session
249
+ */
250
+ initialize(): Promise<SessionData>;
251
+ /**
252
+ * Phase 2: Validate JWT with backend
253
+ */
254
+ private validateWithBackend;
255
+ /**
256
+ * Phase 2: Handle tab sync messages
257
+ */
258
+ private handleTabSyncMessage;
259
+ /**
260
+ * Phase 2: Initialize Visibility API handling
261
+ */
262
+ private initializeVisibilityHandling;
263
+ /**
264
+ * Start session timer manually
265
+ */
266
+ startTimer(): void;
267
+ /**
268
+ * Pause session timer
269
+ */
270
+ pauseTimer(): void;
271
+ /**
272
+ * Resume session timer
273
+ */
274
+ resumeTimer(): void;
275
+ /**
276
+ * Phase 2: Extend session
277
+ */
278
+ extendSession(additionalMinutes: number): Promise<void>;
279
+ /**
280
+ * Phase 2: Complete session
281
+ */
282
+ completeSession(actualUsageMinutes?: number): Promise<void>;
283
+ /**
284
+ * End session
285
+ */
286
+ endSession(): Promise<void>;
287
+ /**
288
+ * Show warning modal
289
+ */
290
+ private showWarningModal;
291
+ /**
292
+ * Get current session data
293
+ */
294
+ getSessionData(): SessionData | null;
295
+ /**
296
+ * Get remaining time
297
+ */
298
+ getRemainingTime(): number;
299
+ /**
300
+ * Get formatted time (MM:SS)
301
+ */
302
+ getFormattedTime(): string;
303
+ /**
304
+ * Get formatted time with hours (HH:MM:SS)
305
+ */
306
+ getFormattedTimeWithHours(): string;
307
+ /**
308
+ * Check if timer is running
309
+ */
310
+ isTimerRunning(): boolean;
311
+ /**
312
+ * Cleanup and destroy SDK instance
313
+ */
314
+ destroy(): void;
315
+ }
316
+ export { MarketplaceSDK }
317
+ export default MarketplaceSDK;
318
+
319
+ /**
320
+ * Modal styling options (Legacy - prefer using theme)
321
+ * @deprecated Use theme configuration from src/styles/theme.ts instead
322
+ */
323
+ export declare interface ModalStyles {
324
+ backgroundColor: string;
325
+ textColor: string;
326
+ primaryColor: string;
327
+ borderRadius: string;
328
+ fontFamily: string;
329
+ }
330
+
331
+ /**
332
+ * SDK Configuration
333
+ */
334
+ export declare interface SDKConfig {
335
+ /** JWKS endpoint URL (default: https://api.generalwisdom.com/.well-known/jwks.json) */
336
+ jwksUri?: string;
337
+ /** API endpoint for backend integration (Phase 2) */
338
+ apiEndpoint?: string;
339
+ /** Enable debug logging */
340
+ debug?: boolean;
341
+ /** Auto-start timer after initialization */
342
+ autoStart?: boolean;
343
+ /** Warning threshold in seconds (default: 300 = 5 minutes) */
344
+ warningThresholdSeconds?: number;
345
+ /** Custom styling for warning modal (Legacy - prefer using themeMode) */
346
+ customStyles?: Partial<ModalStyles>;
347
+ /** Theme mode for modal styling (default: 'light') */
348
+ themeMode?: ThemeMode;
349
+ /** Application ID for validation */
350
+ applicationId?: string;
351
+ /** Marketplace URL for redirects (default: https://d3p2yqofgy75sz.cloudfront.net/) */
352
+ marketplaceUrl?: string;
353
+ /** Enable heartbeat system (default: false) */
354
+ enableHeartbeat?: boolean;
355
+ /** Heartbeat interval in seconds (default: 30) */
356
+ heartbeatIntervalSeconds?: number;
357
+ /** Enable multi-tab synchronization (default: false) */
358
+ enableTabSync?: boolean;
359
+ /** Pause timer when tab is hidden (default: false) */
360
+ pauseOnHidden?: boolean;
361
+ /** Use backend validation instead of JWKS (default: false) */
362
+ useBackendValidation?: boolean;
363
+ /** Optional hooks for synchronizing app auth state with marketplace sessions */
364
+ hooks?: SessionLifecycleHooks;
365
+ /** Hook execution timeout in milliseconds (default: 5000) */
366
+ hookTimeoutMs?: number;
367
+ }
368
+
369
+ /**
370
+ * Custom SDK Error
371
+ */
372
+ export declare class SDKError extends Error {
373
+ code: string;
374
+ statusCode?: number | undefined;
375
+ constructor(message: string, code: string, statusCode?: number | undefined);
376
+ }
377
+
378
+ /**
379
+ * SDK Event Handlers
380
+ */
381
+ export declare interface SDKEvents {
382
+ /** Called when session successfully initialized */
383
+ onSessionStart: (data: SessionData) => void;
384
+ /** Called when warning threshold reached */
385
+ onSessionWarning: (data: {
386
+ remainingSeconds: number;
387
+ }) => void;
388
+ /** Called when session expires or is ended */
389
+ onSessionEnd: () => void;
390
+ /** Called on any error */
391
+ onError: (error: Error) => void;
392
+ }
393
+
394
+ /**
395
+ * Session Data extracted from JWT
396
+ */
397
+ export declare interface SessionData {
398
+ /** Unique session UUID */
399
+ sessionId: string;
400
+ /** Application ID */
401
+ applicationId: string;
402
+ /** User ID */
403
+ userId: string;
404
+ /** Organization ID */
405
+ orgId: string;
406
+ /** Session start time (Unix timestamp seconds) */
407
+ startTime: number;
408
+ /** Session duration in minutes */
409
+ durationMinutes: number;
410
+ /** Issued at timestamp (Unix seconds) */
411
+ iat: number;
412
+ /** Expiration timestamp (Unix seconds) */
413
+ exp: number;
414
+ /** Issuer */
415
+ iss: string;
416
+ /** Subject (user ID) */
417
+ sub: string;
418
+ }
419
+
420
+ export declare interface SessionEndContext {
421
+ /** Unique session UUID */
422
+ sessionId: string;
423
+ /** User ID */
424
+ userId: string;
425
+ /** Reason for session end */
426
+ reason: 'expired' | 'manual' | 'error';
427
+ /** Actual session duration in minutes (if available) */
428
+ actualDurationMinutes?: number;
429
+ }
430
+
431
+ export declare interface SessionExtendContext {
432
+ /** Unique session UUID */
433
+ sessionId: string;
434
+ /** User ID */
435
+ userId: string;
436
+ /** Additional minutes added to session */
437
+ additionalMinutes: number;
438
+ /** New expiration timestamp (Unix seconds) */
439
+ newExpiresAt: number;
440
+ }
441
+
442
+ /**
443
+ * Session Header Component
444
+ * Compact header widget showing session timer with extend/end controls
445
+ */
446
+ export declare class SessionHeader {
447
+ private container;
448
+ private theme;
449
+ private updateInterval;
450
+ private timeDisplay;
451
+ private getTimeCallback;
452
+ private onExtendCallback;
453
+ private onEndCallback;
454
+ private mounted;
455
+ constructor(themeMode?: ThemeMode);
456
+ private detectDarkMode;
457
+ /**
458
+ * Mount the session header to a DOM element
459
+ * @param targetElement - Element to mount to (or selector string)
460
+ * @param options - Configuration options
461
+ */
462
+ mount(targetElement: HTMLElement | string, options: {
463
+ getTime: () => string;
464
+ onExtend?: () => void;
465
+ onEnd?: () => void;
466
+ position?: 'left' | 'center' | 'right';
467
+ }): void;
468
+ /**
469
+ * Start updating the time display
470
+ */
471
+ private startUpdating;
472
+ /**
473
+ * Unmount and cleanup the session header
474
+ */
475
+ unmount(): void;
476
+ /**
477
+ * Check if component is mounted
478
+ */
479
+ isMounted(): boolean;
480
+ /**
481
+ * Update the theme
482
+ */
483
+ updateTheme(themeMode: ThemeMode): void;
484
+ }
485
+
486
+ /**
487
+ * Session Lifecycle Hooks
488
+ * Optional callbacks that allow applications to synchronize their auth state with marketplace sessions
489
+ */
490
+ export declare interface SessionLifecycleHooks {
491
+ /**
492
+ * Called after JWT validation succeeds but before session timer starts
493
+ * Use to: Auto-login user to your app's auth system
494
+ * Note: Hook failure will prevent session from starting
495
+ */
496
+ onSessionStart?: (context: SessionStartContext) => Promise<void> | void;
497
+ /**
498
+ * Called when session expires or is manually ended, before redirect
499
+ * Use to: Force logout user from your app's auth system
500
+ * Note: Hook failure will be logged but won't prevent session end
501
+ */
502
+ onSessionEnd?: (context: SessionEndContext) => Promise<void> | void;
503
+ /**
504
+ * Called when session extension succeeds
505
+ * Use to: Refresh app auth tokens if needed
506
+ */
507
+ onSessionExtend?: (context: SessionExtendContext) => Promise<void> | void;
508
+ /**
509
+ * Called before session warning modal is shown
510
+ * Use to: Prepare user for session expiration
511
+ */
512
+ onSessionWarning?: (context: SessionWarningContext) => Promise<void> | void;
513
+ }
514
+
515
+ /**
516
+ * Session Lifecycle Hook Contexts
517
+ */
518
+ export declare interface SessionStartContext {
519
+ /** Unique session UUID */
520
+ sessionId: string;
521
+ /** User ID from JWT */
522
+ userId: string;
523
+ /** User email (if available in JWT) */
524
+ email?: string;
525
+ /** Organization ID */
526
+ orgId: string;
527
+ /** Application ID */
528
+ applicationId: string;
529
+ /** Session duration in minutes */
530
+ durationMinutes: number;
531
+ /** Expiration timestamp (Unix seconds) */
532
+ expiresAt: number;
533
+ /** Full JWT token for app use */
534
+ jwt: string;
535
+ }
536
+
537
+ export declare interface SessionWarningContext {
538
+ /** Unique session UUID */
539
+ sessionId: string;
540
+ /** User ID */
541
+ userId: string;
542
+ /** Remaining seconds until expiration */
543
+ remainingSeconds: number;
544
+ }
545
+
546
+ /**
547
+ * Tab Synchronization Manager
548
+ * Phase 2 Feature - Syncs session state across multiple tabs
549
+ */
550
+ export declare class TabSyncManager {
551
+ private sessionId;
552
+ private onMessage;
553
+ private channel;
554
+ private storageKey;
555
+ private logger;
556
+ private isMaster;
557
+ constructor(sessionId: string, onMessage: (message: TabSyncMessage) => void, debug?: boolean);
558
+ /**
559
+ * Initialize sync mechanism
560
+ */
561
+ private initialize;
562
+ /**
563
+ * Broadcast message to other tabs
564
+ */
565
+ broadcast(type: TabSyncMessage['type'], data?: Partial<TabSyncMessage>): void;
566
+ /**
567
+ * Handle incoming message
568
+ */
569
+ private handleMessage;
570
+ /**
571
+ * Handle storage event (fallback mechanism)
572
+ */
573
+ private handleStorageEvent;
574
+ /**
575
+ * Elect this tab as master if appropriate
576
+ * Master tab is responsible for heartbeats
577
+ */
578
+ private electMaster;
579
+ /**
580
+ * Check if this tab is the master
581
+ */
582
+ isMasterTab(): boolean;
583
+ /**
584
+ * Cleanup and destroy
585
+ */
586
+ destroy(): void;
587
+ }
588
+
589
+ export declare interface TabSyncMessage {
590
+ type: 'timer_update' | 'pause' | 'resume' | 'end';
591
+ sessionId: string;
592
+ remainingSeconds?: number;
593
+ timestamp: number;
594
+ }
595
+
596
+ export declare interface Theme {
597
+ colors: ThemeColors;
598
+ typography: ThemeTypography;
599
+ spacing: ThemeSpacing;
600
+ }
601
+
602
+ /**
603
+ * Theme configuration matching the General Wisdom SPA design system
604
+ * Based on gw-spa/src/styles/globals.css and Tailwind CSS v4
605
+ */
606
+ export declare interface ThemeColors {
607
+ background: string;
608
+ foreground: string;
609
+ card: string;
610
+ cardForeground: string;
611
+ popover: string;
612
+ popoverForeground: string;
613
+ primary: string;
614
+ primaryForeground: string;
615
+ secondary: string;
616
+ secondaryForeground: string;
617
+ muted: string;
618
+ mutedForeground: string;
619
+ accent: string;
620
+ accentForeground: string;
621
+ destructive: string;
622
+ destructiveForeground: string;
623
+ success: string;
624
+ successForeground: string;
625
+ border: string;
626
+ input: string;
627
+ ring: string;
628
+ }
629
+
630
+ /**
631
+ * Theme mode for modal styling
632
+ */
633
+ export declare type ThemeMode = 'light' | 'dark' | 'auto';
634
+
635
+ export declare interface ThemeSpacing {
636
+ borderRadius: {
637
+ sm: string;
638
+ md: string;
639
+ lg: string;
640
+ };
641
+ padding: {
642
+ sm: string;
643
+ md: string;
644
+ lg: string;
645
+ xl: string;
646
+ };
647
+ gap: {
648
+ sm: string;
649
+ md: string;
650
+ lg: string;
651
+ };
652
+ }
653
+
654
+ export declare interface ThemeTypography {
655
+ fontFamily: string;
656
+ fontSize: {
657
+ xs: string;
658
+ sm: string;
659
+ base: string;
660
+ lg: string;
661
+ xl: string;
662
+ '2xl': string;
663
+ };
664
+ fontWeight: {
665
+ normal: string;
666
+ medium: string;
667
+ semibold: string;
668
+ bold: string;
669
+ };
670
+ lineHeight: {
671
+ tight: string;
672
+ normal: string;
673
+ relaxed: string;
674
+ };
675
+ }
676
+
677
+ /**
678
+ * Timer Manager for session countdown
679
+ */
680
+ export declare class TimerManager {
681
+ private remainingSeconds;
682
+ private intervalId;
683
+ private warningThreshold;
684
+ private warningShown;
685
+ private logger;
686
+ private events;
687
+ constructor(durationSeconds: number, warningThresholdSeconds?: number, events?: Partial<SDKEvents>, debug?: boolean);
688
+ /**
689
+ * Start countdown timer
690
+ */
691
+ start(): void;
692
+ /**
693
+ * Stop timer
694
+ */
695
+ stop(): void;
696
+ /**
697
+ * Pause timer
698
+ */
699
+ pause(): void;
700
+ /**
701
+ * Resume timer
702
+ */
703
+ resume(): void;
704
+ /**
705
+ * Get remaining time in seconds
706
+ */
707
+ getRemainingSeconds(): number;
708
+ /**
709
+ * Get formatted time string (MM:SS)
710
+ */
711
+ getFormattedTime(): string;
712
+ /**
713
+ * Get formatted time string with hours (HH:MM:SS)
714
+ */
715
+ getFormattedTimeWithHours(): string;
716
+ /**
717
+ * Check if timer is running
718
+ */
719
+ isRunning(): boolean;
720
+ /**
721
+ * Check if warning has been shown
722
+ */
723
+ hasWarningBeenShown(): boolean;
724
+ /**
725
+ * Update remaining time (useful for syncing with server)
726
+ */
727
+ updateRemainingTime(seconds: number): void;
728
+ }
729
+
730
+ /**
731
+ * Warning Modal for session expiration alerts
732
+ */
733
+ export declare class WarningModal {
734
+ private modal;
735
+ private theme;
736
+ private legacyStyles;
737
+ private updateInterval;
738
+ private timeDisplay;
739
+ private startTime;
740
+ private initialSeconds;
741
+ private onEndCallback;
742
+ constructor(themeMode?: ThemeMode, customStyles?: Partial<ModalStyles>);
743
+ private detectDarkMode;
744
+ /**
745
+ * Show warning modal
746
+ */
747
+ show(options: {
748
+ remainingSeconds: number;
749
+ onExtend?: () => void;
750
+ onEnd?: () => void;
751
+ }): void;
752
+ /**
753
+ * Hide and remove modal
754
+ */
755
+ hide(): void;
756
+ /**
757
+ * Check if modal is currently shown
758
+ */
759
+ isShown(): boolean;
760
+ /**
761
+ * Show "Session Ending" modal before redirect
762
+ * Displays for a fixed duration (3 seconds) then calls callback
763
+ */
764
+ showEndingMessage(onComplete: () => void, durationMs?: number): void;
765
+ }
766
+
767
+ export { }