@touchcastllc/napster-companion-api-dev 1.6.0-alpha.0 → 1.6.0-alpha.2

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,30 @@
1
+ /**
2
+ * Handle returned by {@link gateOnMicrophone}. Lets the caller tear down an
3
+ * active recovery card (e.g. on session destroy) independent of whether the
4
+ * user ever retries.
5
+ */
6
+ export interface MicGateController {
7
+ /** Force-hide the recovery card, if one is mounted. Safe to call unconditionally. */
8
+ dismiss(): void;
9
+ }
10
+ export interface MicGateOptions {
11
+ /** Element the recovery card mounts into on denial. */
12
+ root: HTMLElement;
13
+ /**
14
+ * The microphone is available. Fires once for an immediate grant, and
15
+ * again after each successful "Check again" retry. May return a promise —
16
+ * {@link gateOnMicrophone}'s own promise waits for it, so a caller that
17
+ * awaits the gate call also waits for whatever `onGranted` kicks off.
18
+ */
19
+ onGranted: () => void | Promise<void>;
20
+ /** Reported once, on the FIRST failure only — never on a refused retry. */
21
+ onError?: (error: Error) => void;
22
+ /** Fires immediately before the recovery card mounts. */
23
+ onBeforeRecovery?: () => void;
24
+ }
25
+ /**
26
+ * Gate a session on microphone access (CA-622): try once, and on denial keep
27
+ * the widget mounted with a recovery card ("Check again", CA-774) instead of
28
+ * tearing it down.
29
+ */
30
+ export declare function gateOnMicrophone(opts: MicGateOptions): Promise<MicGateController>;
@@ -3,9 +3,7 @@ import type { MediaCapture } from "../utils/MediaCapture";
3
3
  export interface WebRTCController {
4
4
  startWithToken: (token: string) => Promise<void>;
5
5
  close: () => void;
6
- forceReconnect: () => Promise<void>;
7
6
  getConnectionStatus: () => string;
8
- getReconnectAttempts: () => number;
9
7
  getError: () => Error | null;
10
8
  updateAudioDevice: (deviceId: string) => Promise<void>;
11
9
  }
@@ -19,9 +17,6 @@ interface WebRTCParams {
19
17
  videoStream?: MediaStream | null;
20
18
  audioStream?: MediaStream | null;
21
19
  }) => void;
22
- onDataChannel?: (dc: RTCDataChannel) => void;
23
- maxReconnectAttempts?: number;
24
- reconnectInterval?: number;
25
20
  /**
26
21
  * ICE servers for the peer connection. When omitted, servers from the
27
22
  * connection token are used, else {@link DEFAULT_ICE_SERVERS}. Provide this to
@@ -303,8 +303,7 @@ export interface NavigationProgressOptions {
303
303
  height?: string;
304
304
  }
305
305
  /**
306
- * Cross-page persistence options. Works with BOTH entry points — `init` and
307
- * `initWithButton` share the same persistence engine.
306
+ * Cross-page persistence options.
308
307
  */
309
308
  export interface PersistenceOptions {
310
309
  /** Turn persistence on. Required — there is no boolean shorthand. */
@@ -405,6 +404,19 @@ export interface PersistenceOptions {
405
404
  * All fields are optional; sensible defaults are used by the SDK.
406
405
  */
407
406
  export interface NapsterCompanionApiConfig {
407
+ /**
408
+ * Connection transport. Only `"webrtc"` exists today — any other value is a
409
+ * compile-time error. Reserved for future transports (e.g. WebSocket); until
410
+ * then the SDK defaults to `"webrtc"` and there is no reason to set this.
411
+ */
412
+ transport?: "webrtc";
413
+ /**
414
+ * Connection modality. Only `"video"` exists today — any other value is a
415
+ * compile-time error. Reserved for future modalities (e.g. audio-only,
416
+ * text); until then the SDK defaults to `"video"` and there is no reason to
417
+ * set this.
418
+ */
419
+ modality?: "video";
408
420
  /** Position of the avatar on screen. See `Position` enum. */
409
421
  position?: Position;
410
422
  /** CSS class name(s) to add to the SDK root container. Useful for theming. */
@@ -461,20 +473,10 @@ export interface NapsterCompanionApiConfig {
461
473
  /**
462
474
  * Keep the session alive across page navigation. When enabled, the page is wrapped in
463
475
  * a same-origin iframe so navigation happens inside it while the avatar stays in the
464
- * top document, which never reloads. Works with both `init` and `initWithButton`.
476
+ * top document, which never reloads.
465
477
  * When on, `mountContainer` is ignored — the avatar must live in the top document.
466
478
  */
467
479
  persistence?: PersistenceOptions;
468
- /**
469
- * The click-to-start button's appearance. **Only used by `initWithButton()`** —
470
- * passing it to `init()` (which connects immediately, with no button) throws.
471
- */
472
- button?: {
473
- /** Button text. Default: `"Talk to an agent"`. */
474
- label?: string;
475
- /** Optional companion picture shown on the button. */
476
- avatarUrl?: string;
477
- };
478
480
  /** Lifecycle callbacks. All are optional. */
479
481
  /** Called when the SDK has finished initialization and is ready to render. */
480
482
  onReady?: () => void;
@@ -585,42 +587,17 @@ export interface NapsterCompanionApiInstance {
585
587
  readonly isUserTalking: boolean;
586
588
  }
587
589
  /**
588
- * Top-level SDK object exposed by the package. Call `init(token, config)` to
590
+ * Top-level SDK object exposed by the package. Call `init(getToken, config)` to
589
591
  * bootstrap the SDK and receive a `NapsterCompanionApiInstance` for runtime control.
590
592
  */
591
593
  export interface NapsterCompanionApiSDK {
592
594
  /**
593
- * Initialize the SDK using the provided connection token and optional config.
594
- * Returns a Promise that resolves to a controllable `NapsterCompanionApiInstance`.
595
- */
596
- init(token: string, config?: Partial<NapsterCompanionApiConfig>): Promise<NapsterCompanionApiInstance>;
597
- /**
598
- * Render a button and connect on click (instead of connecting immediately like
599
- * `init`). Returns a `NapsterCompanionApiController` synchronously — nothing connects
600
- * until the user clicks. With `persistence`, the session survives navigation. No-op
601
- * when run inside the persistence site frame.
602
- */
603
- initWithButton(getToken: () => Promise<string>, config?: Partial<NapsterCompanionApiConfig>): import("../button").NapsterCompanionApiController;
604
- /**
605
- * Prompt for the microphone WITHOUT starting a session, so permission is settled
606
- * before a connection token exists. A connection's lifetime starts the moment the
607
- * backend creates it, and a prompt the user leaves open for seconds spends that
608
- * budget before signaling runs — the session then fails to come up.
609
- *
610
- * `initWithButton` does this internally. Use it on the `init` path, where the host
611
- * app owns when the token is minted:
612
- *
613
- * ```js
614
- * await SDK.requestMicrophoneAccess();
615
- * const token = await mintConnectionToken();
616
- * await SDK.init(token, config);
617
- * ```
618
- *
619
- * Rejects with a `ConnectionError` whose `context.name` is the underlying
620
- * DOMException — `"NotAllowedError"` (refused) or `"NotFoundError"` (no device).
621
- * Calling it is free once granted: the stream is cached and reused by the session.
595
+ * Initialize the SDK. `getToken` is called by the SDK itself once the microphone
596
+ * permission has settled, so the connection token is always fresh when signaling
597
+ * starts. A pre-minted token string is not accepted — minting it before the mic
598
+ * prompt lets it go stale while the user is deciding.
622
599
  */
623
- requestMicrophoneAccess(): Promise<void>;
600
+ init(getToken: () => Promise<string>, config?: Partial<NapsterCompanionApiConfig>): Promise<NapsterCompanionApiInstance>;
624
601
  /** The SDK version string (useful for diagnostics). */
625
602
  version: string;
626
603
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@touchcastllc/napster-companion-api-dev",
3
- "version": "1.6.0-alpha.0",
3
+ "version": "1.6.0-alpha.2",
4
4
  "keywords": [
5
5
  "napster",
6
6
  "companion-api",
@@ -1,6 +0,0 @@
1
- export interface ButtonElementOptions {
2
- label: string;
3
- avatarUrl?: string;
4
- onClick: () => void;
5
- }
6
- export declare function createButtonElement(options: ButtonElementOptions): HTMLButtonElement;
@@ -1,46 +0,0 @@
1
- import "./Button.css";
2
- import type { NapsterCompanionApiConfig, NapsterCompanionApiInstance } from "../types";
3
- /**
4
- * Returned by {@link initWithButton}. A session controller: start/end the agent session,
5
- * reach the live instance, or tear the button down. Created synchronously — nothing
6
- * connects until `start()` (or a button click).
7
- *
8
- * Inside the SDK's own persistence frame (and during SSR) the call no-ops and every
9
- * method here is a harmless no-op — `getInstance()` stays `null`. With
10
- * `debug: true` the skip is logged.
11
- */
12
- export interface NapsterCompanionApiController {
13
- /** The live avatar instance once connected, else `null`. */
14
- getInstance(): NapsterCompanionApiInstance | null;
15
- /** Start the session (as if the button was clicked). */
16
- start(): Promise<void>;
17
- /** End the session (and, if persisted, unwrap back to the plain site). The button reappears. */
18
- end(): void;
19
- /** Remove the button and any active session/iframe. */
20
- destroy(): void;
21
- }
22
- /**
23
- * What the button entry point needs from the SDK. Wired by the SDK's `initWithButton`
24
- * method so this module never reaches into the singleton's internals.
25
- */
26
- export interface ButtonDeps {
27
- /** Connect a session; mounts the avatar into the button-owned root. */
28
- init: (token: string, config?: Partial<NapsterCompanionApiConfig>) => Promise<NapsterCompanionApiInstance>;
29
- /** Create + position the persistent, button-owned `#np_companion-sdk-root` and return it. */
30
- mountRoot: (config: Partial<NapsterCompanionApiConfig>) => HTMLElement;
31
- /** Remove the button-owned root and release SDK ownership (on destroy). */
32
- unmountRoot: () => void;
33
- /**
34
- * Tear down any live session AND its persisted iframe WITHOUT navigating — reveal the
35
- * page in place. Called when the whole widget is being removed (`destroy()`), where a
36
- * page reload would be the wrong response. Private to the SDK↔button seam.
37
- */
38
- disposeSession: () => void;
39
- }
40
- /**
41
- * Build the button entry point. Returns a {@link NapsterCompanionApiController}.
42
- *
43
- * A no-op (returns an inert controller) when run inside the persistence site frame,
44
- * so the same snippet is safe on every page.
45
- */
46
- export declare function createButton(deps: ButtonDeps, getToken: () => Promise<string>, config?: Partial<NapsterCompanionApiConfig>): NapsterCompanionApiController;