@touchcastllc/napster-companion-api 1.0.0-alpha.3 → 1.0.0-alpha.31
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 +527 -731
- package/lib/components/Avatar/index.d.ts +31 -2
- package/lib/components/Embed/index.d.ts +21 -2
- package/lib/components/InactiveOverlay/index.d.ts +15 -2
- package/lib/components/Preview/index.d.ts +18 -2
- package/lib/components/StyledTooltip/index.d.ts +16 -2
- package/lib/components/VolumeControl/index.d.ts +18 -0
- package/lib/components/WaveForm/index.d.ts +16 -2
- package/lib/components/index.d.ts +2 -7
- package/lib/constants/events.d.ts +50 -0
- package/lib/constants/greenscreen.d.ts +28 -0
- package/lib/constants/index.d.ts +6 -0
- package/lib/constants/waveform.d.ts +34 -0
- package/lib/index.css +1 -1
- package/lib/index.d.ts +20 -14
- package/lib/index.esm.js +1 -2
- package/lib/index.js +1 -2
- package/lib/index.standalone.js +1 -22616
- package/lib/services/analytics.d.ts +59 -41
- package/lib/services/webrtc.d.ts +27 -0
- package/lib/setupTests.d.ts +0 -1
- package/lib/stores/index.d.ts +3 -4
- package/lib/stores/middleware/featuresUpdateMiddleware.d.ts +0 -1
- package/lib/stores/selectors.d.ts +30 -0
- package/lib/stores/slices/appSlice.d.ts +2 -2
- package/lib/stores/slices/avatarSlice.d.ts +1 -3
- package/lib/stores/store.d.ts +4 -5
- package/lib/types/abstract-typing.d.ts +35 -0
- package/lib/types/analytics.d.ts +95 -0
- package/lib/types/errors.d.ts +0 -1
- package/lib/types/index.d.ts +120 -39
- package/lib/umd.d.ts +0 -1
- package/lib/utils/InactiveOverlayManager.d.ts +77 -0
- package/lib/utils/classnames.d.ts +49 -0
- package/lib/utils/debug.d.ts +84 -0
- package/lib/utils/domFactory.d.ts +56 -0
- package/lib/utils/greenscreen/GreenScreenProcessor.d.ts +25 -0
- package/lib/utils/greenscreen/index.d.ts +1 -0
- package/lib/utils/index.d.ts +5 -1
- package/lib/utils/sendCommand.d.ts +2 -0
- package/lib/utils/svg.d.ts +32 -0
- package/package.json +19 -24
- package/lib/CompanionApiProvider.d.ts +0 -22
- package/lib/CompanionApiProvider.d.ts.map +0 -1
- package/lib/assets/fonts/segoe/SegoeUI-Bold.eot +0 -0
- package/lib/assets/fonts/segoe/SegoeUI-Bold.svg +0 -1541
- package/lib/assets/fonts/segoe/SegoeUI-Bold.ttf +0 -0
- package/lib/assets/fonts/segoe/SegoeUI-Bold.woff +0 -0
- package/lib/assets/fonts/segoe/SegoeUI-Bold.woff2 +0 -0
- package/lib/assets/fonts/segoe/SegoeUI.eot +0 -0
- package/lib/assets/fonts/segoe/SegoeUI.svg +0 -1521
- package/lib/assets/fonts/segoe/SegoeUI.ttf +0 -0
- package/lib/assets/fonts/segoe/SegoeUI.woff +0 -0
- package/lib/assets/fonts/segoe/SegoeUI.woff2 +0 -0
- package/lib/components/Avatar/Avatar.d.ts +0 -12
- package/lib/components/Avatar/Avatar.d.ts.map +0 -1
- package/lib/components/Avatar/index.d.ts.map +0 -1
- package/lib/components/Embed/Embed.d.ts +0 -17
- package/lib/components/Embed/Embed.d.ts.map +0 -1
- package/lib/components/Embed/index.d.ts.map +0 -1
- package/lib/components/InactiveOverlay/InactiveOverlay.d.ts +0 -12
- package/lib/components/InactiveOverlay/InactiveOverlay.d.ts.map +0 -1
- package/lib/components/InactiveOverlay/index.d.ts.map +0 -1
- package/lib/components/Preview/Preview.d.ts +0 -13
- package/lib/components/Preview/Preview.d.ts.map +0 -1
- package/lib/components/Preview/index.d.ts.map +0 -1
- package/lib/components/StyledTooltip/StyledTooltip.d.ts +0 -12
- package/lib/components/StyledTooltip/StyledTooltip.d.ts.map +0 -1
- package/lib/components/StyledTooltip/index.d.ts.map +0 -1
- package/lib/components/WaveForm/WaveForm.d.ts +0 -16
- package/lib/components/WaveForm/WaveForm.d.ts.map +0 -1
- package/lib/components/WaveForm/index.d.ts.map +0 -1
- package/lib/components/index.d.ts.map +0 -1
- package/lib/hooks/index.d.ts +0 -5
- package/lib/hooks/index.d.ts.map +0 -1
- package/lib/hooks/useApp.d.ts +0 -25
- package/lib/hooks/useApp.d.ts.map +0 -1
- package/lib/hooks/useAvatar.d.ts +0 -70
- package/lib/hooks/useAvatar.d.ts.map +0 -1
- package/lib/hooks/useMicrophones.d.ts +0 -8
- package/lib/hooks/useMicrophones.d.ts.map +0 -1
- package/lib/hooks/useWebRTC.d.ts +0 -22
- package/lib/hooks/useWebRTC.d.ts.map +0 -1
- package/lib/index-legacy.d.ts +0 -27
- package/lib/index-legacy.d.ts.map +0 -1
- package/lib/index-legacy.esm.js +0 -2
- package/lib/index-legacy.esm.js.map +0 -1
- package/lib/index-legacy.js +0 -2
- package/lib/index-legacy.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.esm.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/index.standalone.js.map +0 -1
- package/lib/index.standalone.min.js +0 -11
- package/lib/index.standalone.min.js.map +0 -1
- package/lib/index.umd.js +0 -19945
- package/lib/index.umd.js.map +0 -1
- package/lib/index.umd.min.js +0 -11
- package/lib/index.umd.min.js.map +0 -1
- package/lib/sdk-base-CfUSsjvT.js +0 -7
- package/lib/sdk-base-CfUSsjvT.js.map +0 -1
- package/lib/sdk-base-DYRT4bHm.js +0 -7
- package/lib/sdk-base-DYRT4bHm.js.map +0 -1
- package/lib/sdk-base.d.ts +0 -69
- package/lib/sdk-base.d.ts.map +0 -1
- package/lib/services/analytics.d.ts.map +0 -1
- package/lib/setupTests.d.ts.map +0 -1
- package/lib/stores/hooks.d.ts +0 -8
- package/lib/stores/hooks.d.ts.map +0 -1
- package/lib/stores/index.d.ts.map +0 -1
- package/lib/stores/middleware/featuresUpdateMiddleware.d.ts.map +0 -1
- package/lib/stores/slices/appSlice.d.ts.map +0 -1
- package/lib/stores/slices/avatarSlice.d.ts.map +0 -1
- package/lib/stores/store.d.ts.map +0 -1
- package/lib/types/errors.d.ts.map +0 -1
- package/lib/types/index.d.ts.map +0 -1
- package/lib/umd.d.ts.map +0 -1
- package/lib/utils/index.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/@touchcastllc/napster-companion-api)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
|
|
6
|
-
>
|
|
6
|
+
> Real-time conversational video AI for web applications. Embed AI companions that users can talk to face-to-face via WebRTC. Attaches to any DOM element, handles video streaming and avatar rendering, connects to Azure OpenAI for conversation.
|
|
7
7
|
|
|
8
8
|
**Supported Environments:**
|
|
9
9
|
|
|
@@ -15,47 +15,37 @@
|
|
|
15
15
|
|
|
16
16
|
**Key Capabilities:**
|
|
17
17
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- 🔧 **TypeScript Support**: Full type definitions for a great developer experience
|
|
25
|
-
- 🚀 **Production Ready**: Minified builds with source maps for debugging
|
|
18
|
+
- **WebRTC Video Streaming:** Real-time video with AI avatars
|
|
19
|
+
- **Framework Agnostic:** React, Vue, Angular, or vanilla JS
|
|
20
|
+
- **Zero External Dependencies:** Drop in a script tag and go
|
|
21
|
+
- **TypeScript Support:** Fully typed APIs
|
|
22
|
+
- **Tree-Shakeable:** Import only what you need
|
|
23
|
+
- **Production Ready:** Minified builds with type definitions
|
|
26
24
|
|
|
27
25
|
---
|
|
28
26
|
|
|
29
|
-
##
|
|
27
|
+
## 1. Quick Start
|
|
30
28
|
|
|
31
29
|
Get up and running in minutes. Follow these four steps to integrate the SDK into your project.
|
|
32
30
|
|
|
33
|
-
###
|
|
31
|
+
### 1.1 Choose Your Setup
|
|
34
32
|
|
|
35
33
|
Pick the integration method that matches your project:
|
|
36
34
|
|
|
37
|
-
| Build Type
|
|
38
|
-
|
|
|
39
|
-
| **
|
|
40
|
-
| **
|
|
41
|
-
| **UMD** (Script Tag) | Browser, bring your own React 18+ | `lib/index.umd.min.js` | No |
|
|
42
|
-
| **Standalone** (Script Tag) | Browser, zero dependencies | `lib/index.standalone.min.js` | Yes |
|
|
43
|
-
| **Core** (Headless) | Custom UI, framework-agnostic | `@touchcastllc/napster-companion-api/core` | No |
|
|
35
|
+
| Build Type | Best For | Import Path | Dependencies |
|
|
36
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | -------------------- |
|
|
37
|
+
| **ESM** | ✅ **Recommended for most projects**<br>✅ You use a bundler (Vite, Webpack, Rollup, etc.)<br>✅ You want optimal bundle size (dependencies not bundled)<br>✅ You're using TypeScript or modern JavaScript | `@touchcastllc/napster-companion-api` | Redux Toolkit (peer) |
|
|
38
|
+
| **Standalone** | ✅ You want a `<script>` tag (no bundler, no external dependencies)<br>✅ You want zero external dependencies<br>✅ You don't want to manage dependencies separately<br>✅ You're okay with a slightly larger file (all dependencies included) | `lib/index.standalone.js` | All bundled |
|
|
44
39
|
|
|
45
|
-
|
|
40
|
+
---
|
|
46
41
|
|
|
47
|
-
|
|
48
|
-
- [React 16/17 Example](#react-1617-class-component)
|
|
49
|
-
- [Vue 3 Example](#vue-3)
|
|
50
|
-
- [Vue 2 Example](#vue-2)
|
|
51
|
-
- [Angular Example](#angular)
|
|
52
|
-
- [Vanilla JS Example](#vanilla-js--core-no-build-tools)
|
|
42
|
+
### 1.2 Installation & Setup
|
|
53
43
|
|
|
54
|
-
|
|
44
|
+
#### 1.2.1 For ESM Build Type (Recommended)
|
|
55
45
|
|
|
56
|
-
|
|
46
|
+
**Step 1: Install the SDK**
|
|
57
47
|
|
|
58
|
-
|
|
48
|
+
Install the package:
|
|
59
49
|
|
|
60
50
|
```bash
|
|
61
51
|
npm install @touchcastllc/napster-companion-api
|
|
@@ -63,117 +53,150 @@ npm install @touchcastllc/napster-companion-api
|
|
|
63
53
|
yarn add @touchcastllc/napster-companion-api
|
|
64
54
|
```
|
|
65
55
|
|
|
66
|
-
|
|
56
|
+
Install peer dependencies:
|
|
67
57
|
|
|
68
58
|
```bash
|
|
69
|
-
|
|
70
|
-
npm install react@^18 react-dom@^18 @reduxjs/toolkit@^2 react-redux@^9
|
|
71
|
-
|
|
72
|
-
# For React 16/17
|
|
73
|
-
npm install react@^16 react-dom@^16 @reduxjs/toolkit@^2 react-redux@^8
|
|
59
|
+
npm install @reduxjs/toolkit
|
|
74
60
|
```
|
|
75
61
|
|
|
76
|
-
**Import the SDK
|
|
62
|
+
**Step 2: Import the SDK**
|
|
77
63
|
|
|
78
64
|
```typescript
|
|
79
|
-
// React 18+
|
|
80
65
|
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
|
|
81
|
-
|
|
82
|
-
// React 16/17
|
|
83
|
-
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api/legacy";
|
|
84
66
|
```
|
|
85
67
|
|
|
86
|
-
**
|
|
68
|
+
**Also, import CSS Stylesheet (required):**
|
|
69
|
+
|
|
70
|
+
The SDK comes with a complete stylesheet for all components. Import it in your application:
|
|
71
|
+
|
|
72
|
+
**ESM/TypeScript:**
|
|
87
73
|
|
|
88
74
|
```typescript
|
|
89
|
-
import "@touchcastllc/napster-companion-api/
|
|
75
|
+
import "@touchcastllc/napster-companion-api/styles";
|
|
90
76
|
```
|
|
91
77
|
|
|
92
|
-
|
|
78
|
+
**CommonJS:**
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
require("@touchcastllc/napster-companion-api/styles");
|
|
82
|
+
```
|
|
93
83
|
|
|
94
|
-
**
|
|
84
|
+
**HTML `<link>` Tag:**
|
|
95
85
|
|
|
96
86
|
```html
|
|
97
|
-
<
|
|
87
|
+
<link
|
|
88
|
+
rel="stylesheet"
|
|
89
|
+
href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
|
|
90
|
+
/>
|
|
98
91
|
```
|
|
99
92
|
|
|
100
|
-
**
|
|
93
|
+
**CSS `@import`:**
|
|
94
|
+
|
|
95
|
+
```css
|
|
96
|
+
@import url("https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css");
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The CSS file (`index.css`) is minified and contains all styles needed for the avatar widget, controls, tooltips, and more.
|
|
100
|
+
|
|
101
|
+
#### 1.2.2 For Standalone Build Type
|
|
102
|
+
|
|
103
|
+
**Step 1: Import the SDK**
|
|
101
104
|
|
|
102
105
|
```html
|
|
103
|
-
|
|
104
|
-
<script src="https://cdn.jsdelivr.net/npm/
|
|
105
|
-
<script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.umd.min.js"></script>
|
|
106
|
+
<!-- All dependencies bundled (easier, larger file) -->
|
|
107
|
+
<script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### 1.3 Initialization
|
|
113
|
+
|
|
114
|
+
#### 1.3.1 For ESM Build Type
|
|
109
115
|
|
|
110
116
|
Initialize the SDK by calling `NapsterCompanionApiSdk.init()` with your auth token and configuration options.
|
|
111
117
|
|
|
118
|
+
See the [1.4 Authentication](#14-authentication) section for details on generating auth tokens.
|
|
119
|
+
|
|
112
120
|
**Basic Example:**
|
|
113
121
|
|
|
114
122
|
```typescript
|
|
115
|
-
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
|
|
116
|
-
|
|
117
123
|
const widget = await NapsterCompanionApiSdk.init("YOUR_AUTH_TOKEN", {
|
|
118
124
|
mountContainer: "#avatar-container",
|
|
119
|
-
position: "bottom-right",
|
|
120
|
-
features: {
|
|
121
|
-
waveform: { enabled: true },
|
|
122
|
-
backgroundRemoval: { enabled: false },
|
|
123
|
-
inactiveTimeout: { enabled: true, timeoutDuration: 60000 },
|
|
124
|
-
},
|
|
125
125
|
});
|
|
126
|
-
|
|
127
|
-
// The returned widget object exposes control methods:
|
|
128
|
-
// widget.showAvatar() - Show the avatar
|
|
129
|
-
// widget.hideAvatar() - Hide the avatar
|
|
130
|
-
// widget.destroy() - Destroy and unmount the widget
|
|
131
|
-
// widget.updateStyles({...}) - Update widget styles dynamically
|
|
132
|
-
// widget.enableFeature("waveform") - Enable a specific feature
|
|
133
|
-
// widget.disableFeature("waveform") - Disable a specific feature
|
|
134
|
-
// widget.updateFeatureConfig("waveform", { enabled: false }) - Update feature configuration
|
|
135
|
-
// widget.setPosition("top-left") - Update widget position dynamically
|
|
136
|
-
// widget.sendQuestion("Your question here") - Send a question to the avatar
|
|
137
126
|
```
|
|
138
127
|
|
|
139
|
-
|
|
128
|
+
#### 1.3.2 For Standalone Build Type
|
|
129
|
+
|
|
130
|
+
Initialize the SDK by calling `window.napsterCompanionApiSDK.init()` with your auth token and configuration options.
|
|
140
131
|
|
|
141
|
-
|
|
132
|
+
See the [1.4 Authentication](#14-authentication) section for details on generating auth tokens.
|
|
142
133
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
134
|
+
**Step 1: Add container to your HTML**
|
|
135
|
+
|
|
136
|
+
```html
|
|
137
|
+
<div id="sdk-container"></div>
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Step 2: Initialize globally**
|
|
141
|
+
|
|
142
|
+
```html
|
|
143
|
+
<script>
|
|
144
|
+
window.napsterCompanionApiSDK.init("AUTH_TOKEN", {
|
|
145
|
+
mountContainer: "#sdk-container",
|
|
146
|
+
});
|
|
147
|
+
</script>
|
|
148
|
+
```
|
|
154
149
|
|
|
155
150
|
---
|
|
156
151
|
|
|
157
|
-
###
|
|
152
|
+
### 1.4 Authentication
|
|
158
153
|
|
|
159
154
|
The SDK requires an **auth token** to connect to the Napster Companion API.
|
|
160
155
|
|
|
161
156
|
**Important:** **Do not generate tokens in client-side code** — use a backend service to keep your API key secure.
|
|
162
157
|
|
|
163
|
-
#### Step 1: Generate Napster API Key
|
|
158
|
+
#### Step 1: Generate Napster Companion API Key
|
|
164
159
|
|
|
165
|
-
1. Visit the [Napster API Keys page](https://
|
|
160
|
+
1. Visit the [Napster Companion API Keys page](https://companion-api.napster.com/admin/organization/keys)
|
|
166
161
|
2. Click **Generate API key** and enter your details
|
|
167
162
|
3. Store your API key securely on your backend server
|
|
168
163
|
|
|
169
164
|
#### Step 2: Create Connection & Get Token (Backend)
|
|
170
165
|
|
|
171
|
-
Create a backend API call to the Napster API to generate auth tokens:
|
|
166
|
+
Create a backend API call to the Napster Companion API to generate auth tokens:
|
|
167
|
+
|
|
168
|
+
**Request URL:**
|
|
172
169
|
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
170
|
+
```
|
|
171
|
+
POST https://companion-api.napster.com/public/connections
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Request Headers:**
|
|
175
|
+
|
|
176
|
+
| Header | Value |
|
|
177
|
+
| -------------- | ------------------- |
|
|
178
|
+
| `content-type` | `application/json` |
|
|
179
|
+
| `x-api-key` | `YOUR_API_KEY_HERE` |
|
|
180
|
+
|
|
181
|
+
**Request Body:**
|
|
182
|
+
|
|
183
|
+
| Field | Type | Description |
|
|
184
|
+
| ----------------------------------------------------------- | ------- | ------------------------------------ |
|
|
185
|
+
| `companionId` | string | Your Napster Companion ID |
|
|
186
|
+
| `providerConfig.type` | string | Provider type (e.g., `azureOpenAI`) |
|
|
187
|
+
| `providerConfig.voiceId` | string | Voice identifier (e.g., `alloy`) |
|
|
188
|
+
| `providerConfig.settings.instructions` | string | Custom instructions for the avatar |
|
|
189
|
+
| `providerConfig.settings.turnDetection.threshold` | number | Voice detection threshold |
|
|
190
|
+
| `providerConfig.settings.turnDetection.prefix_padding_ms` | number | Padding before speech detection (ms) |
|
|
191
|
+
| `providerConfig.settings.turnDetection.silence_duration_ms` | number | Silence duration threshold (ms) |
|
|
192
|
+
| `providerConfig.settings.temperature` | number | Response temperature (0-1) |
|
|
193
|
+
| `providerConfig.useGreenVideo` | boolean | Enable green screen background |
|
|
194
|
+
| `disableIdleTimeout` | boolean | Disable idle timeout |
|
|
195
|
+
|
|
196
|
+
**Example Request:**
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
curl 'https://companion-api.napster.com/public/connections' \
|
|
177
200
|
-H 'content-type: application/json' \
|
|
178
201
|
-H 'x-api-key: YOUR_API_KEY_HERE' \
|
|
179
202
|
--data-raw '{
|
|
@@ -191,7 +214,8 @@ curl 'https://management-api.cogcache.com/public/connections' \
|
|
|
191
214
|
"temperature": 0
|
|
192
215
|
},
|
|
193
216
|
"useGreenVideo": true
|
|
194
|
-
}
|
|
217
|
+
},
|
|
218
|
+
"disableIdleTimeout": false
|
|
195
219
|
}'
|
|
196
220
|
```
|
|
197
221
|
|
|
@@ -200,835 +224,607 @@ curl 'https://management-api.cogcache.com/public/connections' \
|
|
|
200
224
|
Fetch the token from your backend and pass it to the SDK:
|
|
201
225
|
|
|
202
226
|
```typescript
|
|
203
|
-
//
|
|
227
|
+
// Possible client-side code for token retrieval
|
|
204
228
|
async function initializeAvatar() {
|
|
205
229
|
// Fetch token from your backend
|
|
206
|
-
const response = await fetch("/
|
|
230
|
+
const response = await fetch("/your-backend-endpoint", { method: "POST" });
|
|
207
231
|
const { token } = await response.json();
|
|
208
|
-
|
|
209
|
-
// Initialize SDK with the token
|
|
210
|
-
const widget = await NapsterCompanionApiSdk.init(token, {
|
|
211
|
-
mountContainer: "#avatar-container",
|
|
212
|
-
position: "bottom-right",
|
|
213
|
-
});
|
|
214
232
|
}
|
|
215
233
|
```
|
|
216
234
|
|
|
217
235
|
---
|
|
218
236
|
|
|
219
|
-
##
|
|
237
|
+
## 2. Examples
|
|
220
238
|
|
|
221
|
-
|
|
239
|
+
We provide example implementations for popular frameworks and vanilla JavaScript:
|
|
222
240
|
|
|
223
|
-
###
|
|
241
|
+
### 2.1 React
|
|
224
242
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
| `inactiveTimeout` | Auto-hide avatar after period of inactivity | `{ enabled: false, timeoutDuration: 60000 }` |
|
|
230
|
-
| `disclaimer` | Show disclaimer text above the avatar | `{ enabled: false, text: "" }` |
|
|
243
|
+
```tsx
|
|
244
|
+
import React, { useEffect, useRef, useState } from "react";
|
|
245
|
+
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
|
|
246
|
+
import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
|
|
231
247
|
|
|
232
|
-
|
|
248
|
+
export function CompanionWidget() {
|
|
249
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
250
|
+
const [instance, setInstance] = useState<NapsterCompanionApiInstance | null>(
|
|
251
|
+
null
|
|
252
|
+
);
|
|
233
253
|
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
position: "bottom-right",
|
|
238
|
-
features: {
|
|
239
|
-
autoplay: { enabled: true },
|
|
240
|
-
waveform: { enabled: true },
|
|
241
|
-
backgroundRemoval: { enabled: false },
|
|
242
|
-
inactiveTimeout: {
|
|
243
|
-
enabled: true,
|
|
244
|
-
timeoutDuration: 60000, // 60 seconds
|
|
245
|
-
},
|
|
246
|
-
},
|
|
247
|
-
});
|
|
248
|
-
```
|
|
254
|
+
useEffect(() => {
|
|
255
|
+
const initSDK = async () => {
|
|
256
|
+
if (!containerRef.current) return;
|
|
249
257
|
|
|
250
|
-
|
|
258
|
+
const result = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
|
|
259
|
+
mountContainer: containerRef.current,
|
|
260
|
+
position: "bottom-right",
|
|
261
|
+
});
|
|
262
|
+
setInstance(result);
|
|
263
|
+
};
|
|
251
264
|
|
|
252
|
-
|
|
265
|
+
initSDK();
|
|
253
266
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
autoplay: { enabled: true },
|
|
262
|
-
inactiveTimeout: {
|
|
263
|
-
enabled: true,
|
|
264
|
-
timeoutDuration: 30000, // 30 seconds
|
|
265
|
-
},
|
|
266
|
-
});
|
|
267
|
+
return () => {
|
|
268
|
+
instance?.destroy();
|
|
269
|
+
};
|
|
270
|
+
}, []);
|
|
271
|
+
|
|
272
|
+
return <div ref={containerRef} style={{ width: "100%", height: "100%" }} />;
|
|
273
|
+
}
|
|
267
274
|
```
|
|
268
275
|
|
|
269
|
-
|
|
276
|
+
### 2.2 Vue 3
|
|
270
277
|
|
|
271
|
-
|
|
278
|
+
```html
|
|
279
|
+
<template>
|
|
280
|
+
<div ref="containerRef"></div>
|
|
281
|
+
</template>
|
|
272
282
|
|
|
273
|
-
|
|
283
|
+
<script setup lang="ts">
|
|
284
|
+
import { onMounted, onUnmounted, ref } from "vue";
|
|
285
|
+
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
|
|
286
|
+
import type { NapsterCompanionApiInstance } from "@touchcastllc/napster-companion-api";
|
|
274
287
|
|
|
275
|
-
|
|
288
|
+
const containerRef = ref<HTMLElement>();
|
|
289
|
+
let instance: NapsterCompanionApiInstance | null = null;
|
|
276
290
|
|
|
277
|
-
|
|
291
|
+
onMounted(async () => {
|
|
292
|
+
if (!containerRef.value) return;
|
|
278
293
|
|
|
279
|
-
|
|
294
|
+
instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
|
|
295
|
+
mountContainer: containerRef.value,
|
|
296
|
+
position: "bottom-right",
|
|
297
|
+
});
|
|
298
|
+
});
|
|
280
299
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
300
|
+
onUnmounted(() => {
|
|
301
|
+
instance?.destroy();
|
|
302
|
+
});
|
|
303
|
+
</script>
|
|
304
|
+
```
|
|
285
305
|
|
|
286
|
-
|
|
306
|
+
### 2.3 Angular
|
|
287
307
|
|
|
288
308
|
```typescript
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
height?: string;
|
|
301
|
-
zIndex?: number;
|
|
302
|
-
};
|
|
303
|
-
onReady?: () => void;
|
|
304
|
-
onError?: (error: Error) => void;
|
|
305
|
-
onData?: (data: EventMessage) => void;
|
|
306
|
-
onAvatarReady?: () => void;
|
|
307
|
-
onDestroy?: () => void;
|
|
308
|
-
}
|
|
309
|
-
```
|
|
309
|
+
import {
|
|
310
|
+
Component,
|
|
311
|
+
OnInit,
|
|
312
|
+
OnDestroy,
|
|
313
|
+
ElementRef,
|
|
314
|
+
ViewChild,
|
|
315
|
+
} from "@angular/core";
|
|
316
|
+
import {
|
|
317
|
+
NapsterCompanionApiSdk,
|
|
318
|
+
NapsterCompanionApiInstance,
|
|
319
|
+
} from "@touchcastllc/napster-companion-api";
|
|
310
320
|
|
|
311
|
-
|
|
321
|
+
@Component({
|
|
322
|
+
selector: "app-companion",
|
|
323
|
+
template: "<div #containerRef></div>",
|
|
324
|
+
})
|
|
325
|
+
export class CompanionComponent implements OnInit, OnDestroy {
|
|
326
|
+
@ViewChild("containerRef") containerRef!: ElementRef<HTMLDivElement>;
|
|
327
|
+
private instance: NapsterCompanionApiInstance | null = null;
|
|
312
328
|
|
|
313
|
-
|
|
329
|
+
async ngOnInit() {
|
|
330
|
+
this.instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
|
|
331
|
+
mountContainer: this.containerRef.nativeElement,
|
|
332
|
+
position: "bottom-right",
|
|
333
|
+
});
|
|
334
|
+
}
|
|
314
335
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
});
|
|
336
|
+
ngOnDestroy() {
|
|
337
|
+
this.instance?.destroy();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
320
340
|
```
|
|
321
341
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
### Widget Instance Methods
|
|
342
|
+
### 2.4 Vanilla JavaScript/TypeScript
|
|
325
343
|
|
|
326
|
-
|
|
344
|
+
```html
|
|
345
|
+
<div id="sdk-container"></div>
|
|
346
|
+
<script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.js"></script>
|
|
347
|
+
<script>
|
|
348
|
+
const sdk = window.napsterCompanionApiSDK;
|
|
349
|
+
|
|
350
|
+
sdk
|
|
351
|
+
.init("YOUR_TOKEN", {
|
|
352
|
+
mountContainer: "#sdk-container",
|
|
353
|
+
position: "bottom-right",
|
|
354
|
+
})
|
|
355
|
+
.then(instance => {
|
|
356
|
+
// Control the avatar
|
|
357
|
+
instance.showAvatar();
|
|
358
|
+
|
|
359
|
+
// Hide after 10 seconds
|
|
360
|
+
setTimeout(() => instance.hideAvatar(), 10000);
|
|
361
|
+
});
|
|
362
|
+
</script>
|
|
363
|
+
```
|
|
327
364
|
|
|
328
|
-
|
|
365
|
+
### 2.5 Advanced Configuration
|
|
329
366
|
|
|
330
367
|
```typescript
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
368
|
+
async function initAdvancedAvatar() {
|
|
369
|
+
const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
|
|
370
|
+
mountContainer: "#avatar-container",
|
|
371
|
+
position: "bottom-right",
|
|
335
372
|
|
|
336
|
-
|
|
373
|
+
avatarStyle: {
|
|
374
|
+
view: "round", // Options: "round" | "rectangle" | "silhouette"
|
|
375
|
+
},
|
|
337
376
|
|
|
338
|
-
|
|
377
|
+
features: {
|
|
378
|
+
inactiveTimeout: { enabled: true, duration: 120000, countdown: 15 },
|
|
379
|
+
showSDKLoader: { enabled: true, bgColor: "#f0f0f0" },
|
|
380
|
+
},
|
|
339
381
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
382
|
+
style: {
|
|
383
|
+
borderRadius: "12px",
|
|
384
|
+
boxShadow: "0 4px 20px rgba(0,0,0,0.3)",
|
|
385
|
+
},
|
|
343
386
|
|
|
344
|
-
|
|
387
|
+
onReady: () => console.log("Avatar ready!"),
|
|
388
|
+
onError: error => console.error("Error:", error),
|
|
389
|
+
onAvatarReady: ready => console.log("Avatar loaded:", ready),
|
|
390
|
+
});
|
|
345
391
|
|
|
346
|
-
|
|
392
|
+
return instance;
|
|
393
|
+
}
|
|
394
|
+
```
|
|
347
395
|
|
|
348
|
-
|
|
396
|
+
### 2.6 Dynamic Feature Control
|
|
349
397
|
|
|
350
398
|
```typescript
|
|
351
|
-
|
|
352
|
-
|
|
399
|
+
async function controlFeatures() {
|
|
400
|
+
const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
|
|
401
|
+
mountContainer: "#avatar-container",
|
|
402
|
+
});
|
|
353
403
|
|
|
354
|
-
|
|
404
|
+
// Change position dynamically
|
|
405
|
+
document.getElementById("move-avatar")?.addEventListener("click", () => {
|
|
406
|
+
instance.setPosition("top-left");
|
|
407
|
+
});
|
|
355
408
|
|
|
356
|
-
|
|
409
|
+
return instance;
|
|
410
|
+
}
|
|
411
|
+
```
|
|
357
412
|
|
|
358
|
-
|
|
413
|
+
### 2.7 Custom Styling
|
|
359
414
|
|
|
360
|
-
|
|
415
|
+
#### Inline Styles
|
|
361
416
|
|
|
362
417
|
```typescript
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
418
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
419
|
+
style: {
|
|
420
|
+
border: "2px solid #00ff00",
|
|
421
|
+
borderRadius: "8px",
|
|
422
|
+
boxShadow: "0 2px 10px rgba(0,0,0,0.2)",
|
|
423
|
+
background: "rgba(255,255,255,0.95)",
|
|
424
|
+
},
|
|
425
|
+
});
|
|
369
426
|
```
|
|
370
427
|
|
|
371
|
-
|
|
428
|
+
#### CSS Classes
|
|
372
429
|
|
|
373
430
|
```typescript
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
height: "600px",
|
|
377
|
-
zIndex: 1000,
|
|
378
|
-
position: "top-right",
|
|
431
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
432
|
+
className: "my-custom-avatar",
|
|
379
433
|
});
|
|
380
434
|
```
|
|
381
435
|
|
|
382
|
-
|
|
436
|
+
```css
|
|
437
|
+
.my-custom-avatar {
|
|
438
|
+
border: 2px solid #007acc;
|
|
439
|
+
border-radius: 12px;
|
|
440
|
+
backdrop-filter: blur(10px);
|
|
441
|
+
}
|
|
442
|
+
```
|
|
383
443
|
|
|
384
|
-
####
|
|
444
|
+
#### Dynamic Style Updates
|
|
385
445
|
|
|
386
|
-
|
|
446
|
+
```typescript
|
|
447
|
+
// Update styles after initialization
|
|
448
|
+
instance.updateStyles({
|
|
449
|
+
opacity: "0.9",
|
|
450
|
+
transform: "scale(1.1)",
|
|
451
|
+
transition: "all 0.3s ease",
|
|
452
|
+
});
|
|
453
|
+
```
|
|
387
454
|
|
|
388
|
-
|
|
455
|
+
### 2.8 Avatar Style Configuration
|
|
389
456
|
|
|
390
|
-
|
|
457
|
+
Customize the avatar's visual appearance using the `avatarStyle` configuration. Control the avatar's view mode, and other visual properties.
|
|
391
458
|
|
|
392
|
-
|
|
459
|
+
#### Avatar View Modes
|
|
393
460
|
|
|
394
461
|
```typescript
|
|
395
|
-
|
|
462
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
463
|
+
avatarStyle: {
|
|
464
|
+
view: "round", // Options: "round" | "rectangle" | "silhouette"
|
|
465
|
+
},
|
|
466
|
+
});
|
|
396
467
|
```
|
|
397
468
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
#### `widget.disableFeature(featureName)`
|
|
401
|
-
|
|
402
|
-
Disable a specific feature.
|
|
403
|
-
|
|
404
|
-
**Parameters:**
|
|
469
|
+
**Available View Modes:**
|
|
405
470
|
|
|
406
|
-
- `
|
|
471
|
+
- `"round"` (default) - Circular avatar with rounded appearance
|
|
472
|
+
- `"rectangle"` - Rectangular container, ideal for custom styling
|
|
473
|
+
- `"silhouette"` - Full view without background styling. (**Note: works only with green screen feature enabled in [Create Connection](#step-2-create-connection--get-token-backend) API**)
|
|
407
474
|
|
|
408
|
-
|
|
475
|
+
#### Avatar Style Example
|
|
409
476
|
|
|
410
477
|
```typescript
|
|
411
|
-
|
|
478
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
479
|
+
avatarStyle: {
|
|
480
|
+
view: "rectangle",
|
|
481
|
+
},
|
|
482
|
+
style: {
|
|
483
|
+
borderRadius: "16px", // Works well with rectangle
|
|
484
|
+
boxShadow: "0 8px 32px rgba(0,0,0,0.2)",
|
|
485
|
+
},
|
|
486
|
+
});
|
|
412
487
|
```
|
|
413
488
|
|
|
414
489
|
---
|
|
415
490
|
|
|
416
|
-
|
|
491
|
+
## 3. Feature Configuration
|
|
417
492
|
|
|
418
|
-
|
|
493
|
+
### 3.1 Core Features
|
|
419
494
|
|
|
420
|
-
|
|
495
|
+
#### Inactivity Timeout
|
|
421
496
|
|
|
422
|
-
|
|
423
|
-
interface FeatureConfig {
|
|
424
|
-
autoplay?: { enabled: boolean };
|
|
425
|
-
waveform?: { enabled: boolean };
|
|
426
|
-
backgroundRemoval?: { enabled: boolean };
|
|
427
|
-
inactiveTimeout?: { enabled: boolean; timeoutDuration?: number };
|
|
428
|
-
}
|
|
429
|
-
```
|
|
430
|
-
|
|
431
|
-
**Example:**
|
|
497
|
+
Automatically disconnect the avatar after a period of user inactivity. Users receive a countdown notification before disconnection.
|
|
432
498
|
|
|
433
499
|
```typescript
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
500
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
501
|
+
features: {
|
|
502
|
+
inactiveTimeout: {
|
|
503
|
+
enabled: true,
|
|
504
|
+
duration: 60000, // 60 seconds (max: 180000ms)
|
|
505
|
+
countdown: 10, // 10 second countdown (max: 60s)
|
|
506
|
+
},
|
|
507
|
+
},
|
|
437
508
|
});
|
|
438
509
|
```
|
|
439
510
|
|
|
440
|
-
|
|
511
|
+
#### SDK Loading Screen
|
|
441
512
|
|
|
442
|
-
|
|
513
|
+
Display a loading screen while the avatar assets are being loaded. Customize the background color to match your application's design.
|
|
443
514
|
|
|
444
515
|
```typescript
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
onData?: (data: EventMessage) => void;
|
|
454
|
-
onAvatarReady?: () => void;
|
|
455
|
-
onDestroy?: () => void;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Feature configuration
|
|
459
|
-
interface FeatureConfig {
|
|
460
|
-
autoplay?: { enabled: boolean };
|
|
461
|
-
waveform?: { enabled: boolean };
|
|
462
|
-
backgroundRemoval?: { enabled: boolean };
|
|
463
|
-
inactiveTimeout?: { enabled: boolean; timeoutDuration?: number };
|
|
464
|
-
}
|
|
465
|
-
|
|
466
|
-
// Widget instance returned by init()
|
|
467
|
-
interface NapsterCompanionApiInstance {
|
|
468
|
-
showAvatar(): void;
|
|
469
|
-
hideAvatar(): void;
|
|
470
|
-
destroy(): void;
|
|
471
|
-
updateStyles(styles: React.CSSProperties): void;
|
|
472
|
-
enableFeature(feature: string): void;
|
|
473
|
-
disableFeature(feature: string): void;
|
|
474
|
-
updateFeatureConfig(config: FeatureConfig): void;
|
|
475
|
-
}
|
|
516
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
517
|
+
features: {
|
|
518
|
+
showSDKLoader: {
|
|
519
|
+
enabled: true,
|
|
520
|
+
bgColor: "#ffffff", // Optional background color
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
});
|
|
476
524
|
```
|
|
477
525
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
## 5. Usage Examples
|
|
526
|
+
### 3.2 Position & Layout
|
|
481
527
|
|
|
482
|
-
|
|
528
|
+
Customize the avatar's position on the screen using predefined positions or custom styles. Also you can override the position using style properties.
|
|
483
529
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
async function initialize() {
|
|
498
|
-
try {
|
|
499
|
-
// Fetch token from your backend
|
|
500
|
-
const response = await fetch("/api/get-napster-token", {
|
|
501
|
-
method: "POST",
|
|
502
|
-
});
|
|
503
|
-
const { token } = await response.json();
|
|
504
|
-
|
|
505
|
-
// Initialize widget
|
|
506
|
-
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
507
|
-
mountContainer: containerRef.current,
|
|
508
|
-
position: "bottom-right",
|
|
509
|
-
features: {
|
|
510
|
-
autoplay: { enabled: true },
|
|
511
|
-
waveform: { enabled: true },
|
|
512
|
-
},
|
|
513
|
-
});
|
|
514
|
-
|
|
515
|
-
if (mounted) {
|
|
516
|
-
setWidget(instance);
|
|
517
|
-
}
|
|
518
|
-
} catch (error) {
|
|
519
|
-
console.error("Failed to initialize avatar:", error);
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
initialize();
|
|
524
|
-
|
|
525
|
-
// Cleanup on unmount
|
|
526
|
-
return () => {
|
|
527
|
-
mounted = false;
|
|
528
|
-
widget?.destroy();
|
|
529
|
-
};
|
|
530
|
-
}, []);
|
|
531
|
-
|
|
532
|
-
return <div ref={containerRef} style={{ width: "100%", height: "100%" }} />;
|
|
533
|
-
}
|
|
530
|
+
```typescript
|
|
531
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
532
|
+
mountContainer: "#my-container", // CSS selector or HTMLElement
|
|
533
|
+
position: "bottom-right", // Predefined positions
|
|
534
|
+
// Apply custom inline styles to override default SDK styles, will be added to root container
|
|
535
|
+
style: {
|
|
536
|
+
top: "20px",
|
|
537
|
+
left: "20px",
|
|
538
|
+
zIndex: "1000",
|
|
539
|
+
},
|
|
540
|
+
// Apply CSS class name to override default SDK styles, will be added to root container
|
|
541
|
+
className: "my-custom-class",
|
|
542
|
+
});
|
|
534
543
|
```
|
|
535
544
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
### React 16/17 (Class Component)
|
|
545
|
+
**Available Positions:**
|
|
539
546
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
async componentDidMount() {
|
|
549
|
-
try {
|
|
550
|
-
// Fetch token from your backend
|
|
551
|
-
const response = await fetch("/api/get-napster-token", {
|
|
552
|
-
method: "POST",
|
|
553
|
-
});
|
|
554
|
-
const { token } = await response.json();
|
|
547
|
+
- `"bottom-right"` (default)
|
|
548
|
+
- `"bottom-left"`
|
|
549
|
+
- `"bottom-center"`
|
|
550
|
+
- `"top-right"`
|
|
551
|
+
- `"top-left"`
|
|
552
|
+
- `"top-center"`
|
|
553
|
+
- `"center"`
|
|
555
554
|
|
|
556
|
-
|
|
557
|
-
this.widget = await NapsterCompanionApiSdk.init(token, {
|
|
558
|
-
mountContainer: this.containerRef.current,
|
|
559
|
-
position: "bottom-right",
|
|
560
|
-
features: {
|
|
561
|
-
autoplay: { enabled: true },
|
|
562
|
-
},
|
|
563
|
-
});
|
|
564
|
-
} catch (error) {
|
|
565
|
-
console.error("Failed to initialize avatar:", error);
|
|
566
|
-
}
|
|
567
|
-
}
|
|
555
|
+
## 4. Event Handling
|
|
568
556
|
|
|
569
|
-
|
|
570
|
-
// Cleanup on unmount
|
|
571
|
-
this.widget?.destroy();
|
|
572
|
-
}
|
|
557
|
+
The SDK provides several event callbacks for monitoring status and handling errors.
|
|
573
558
|
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
559
|
+
```typescript
|
|
560
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
561
|
+
// Fires when the SDK is initialized and ready to use
|
|
562
|
+
onReady: () => console.log("SDK ready!"),
|
|
563
|
+
// Fires on any SDK error
|
|
564
|
+
onError: error => console.error("SDK error:", error),
|
|
565
|
+
// Fires when the avatar is fully loaded and ready
|
|
566
|
+
onAvatarReady: isReady => console.log("Avatar ready:", isReady),
|
|
567
|
+
// Fires when user inactivity status changes
|
|
568
|
+
onInactivityStatusChange: isInactive => console.log("Inactive:", isInactive),
|
|
569
|
+
// Fires when the SDK is destroyed
|
|
570
|
+
onDestroy: () => console.log("SDK destroyed"),
|
|
571
|
+
// Fires when data is received from the WEBRTC data channel
|
|
572
|
+
onData: data => console.log("Data received:", data),
|
|
573
|
+
});
|
|
580
574
|
```
|
|
581
575
|
|
|
582
576
|
---
|
|
583
577
|
|
|
584
|
-
|
|
578
|
+
## 5. API Reference
|
|
585
579
|
|
|
586
|
-
|
|
587
|
-
<template>
|
|
588
|
-
<div ref="containerRef" style="width: 100%; height: 100%;"></div>
|
|
589
|
-
</template>
|
|
580
|
+
### 5.1 Core Methods
|
|
590
581
|
|
|
591
|
-
<
|
|
592
|
-
import { ref, onMounted, onBeforeUnmount } from "vue";
|
|
593
|
-
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
|
|
594
|
-
import "@touchcastllc/napster-companion-api/lib/index.css";
|
|
595
|
-
|
|
596
|
-
const containerRef = ref(null);
|
|
597
|
-
let widget = null;
|
|
582
|
+
#### `init(token: string, config?: NapsterCompanionApiConfig): Promise<NapsterCompanionApiInstance>`
|
|
598
583
|
|
|
599
|
-
|
|
600
|
-
try {
|
|
601
|
-
// Fetch token from your backend
|
|
602
|
-
const response = await fetch("/api/get-napster-token", {
|
|
603
|
-
method: "POST",
|
|
604
|
-
});
|
|
605
|
-
const { token } = await response.json();
|
|
584
|
+
Initialize the SDK with authentication token and configuration.
|
|
606
585
|
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
autoplay: { enabled: true },
|
|
613
|
-
waveform: { enabled: true },
|
|
614
|
-
},
|
|
615
|
-
});
|
|
616
|
-
} catch (error) {
|
|
617
|
-
console.error("Failed to initialize avatar:", error);
|
|
618
|
-
}
|
|
619
|
-
});
|
|
620
|
-
|
|
621
|
-
onBeforeUnmount(() => {
|
|
622
|
-
// Cleanup on unmount
|
|
623
|
-
widget?.destroy();
|
|
624
|
-
});
|
|
625
|
-
</script>
|
|
586
|
+
```typescript
|
|
587
|
+
const instance = await NapsterCompanionApiSdk.init("YOUR_TOKEN", {
|
|
588
|
+
mountContainer: "#avatar-container",
|
|
589
|
+
position: "bottom-right",
|
|
590
|
+
});
|
|
626
591
|
```
|
|
627
592
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
### Vue 2
|
|
593
|
+
#### `showAvatar(): void`
|
|
631
594
|
|
|
632
|
-
|
|
633
|
-
<template>
|
|
634
|
-
<div ref="container" style="width: 100%; height: 100%;"></div>
|
|
635
|
-
</template>
|
|
595
|
+
Make the avatar visible on screen.
|
|
636
596
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
import "@touchcastllc/napster-companion-api/lib/index.css";
|
|
640
|
-
|
|
641
|
-
export default {
|
|
642
|
-
name: "AvatarWidget",
|
|
643
|
-
data() {
|
|
644
|
-
return {
|
|
645
|
-
widget: null,
|
|
646
|
-
};
|
|
647
|
-
},
|
|
648
|
-
async mounted() {
|
|
649
|
-
try {
|
|
650
|
-
// Fetch token from your backend
|
|
651
|
-
const response = await fetch("/api/get-napster-token", {
|
|
652
|
-
method: "POST",
|
|
653
|
-
});
|
|
654
|
-
const { token } = await response.json();
|
|
655
|
-
|
|
656
|
-
// Initialize widget
|
|
657
|
-
this.widget = await NapsterCompanionApiSdk.init(token, {
|
|
658
|
-
mountContainer: this.$refs.container,
|
|
659
|
-
position: "bottom-right",
|
|
660
|
-
features: {
|
|
661
|
-
autoplay: { enabled: true },
|
|
662
|
-
},
|
|
663
|
-
});
|
|
664
|
-
} catch (error) {
|
|
665
|
-
console.error("Failed to initialize avatar:", error);
|
|
666
|
-
}
|
|
667
|
-
},
|
|
668
|
-
beforeDestroy() {
|
|
669
|
-
// Cleanup on unmount
|
|
670
|
-
this.widget?.destroy();
|
|
671
|
-
},
|
|
672
|
-
};
|
|
673
|
-
</script>
|
|
597
|
+
```typescript
|
|
598
|
+
instance.showAvatar();
|
|
674
599
|
```
|
|
675
600
|
|
|
676
|
-
|
|
601
|
+
#### `hideAvatar(): void`
|
|
677
602
|
|
|
678
|
-
|
|
603
|
+
Hide the avatar from screen.
|
|
679
604
|
|
|
680
605
|
```typescript
|
|
681
|
-
|
|
682
|
-
Component,
|
|
683
|
-
OnInit,
|
|
684
|
-
OnDestroy,
|
|
685
|
-
ElementRef,
|
|
686
|
-
ViewChild,
|
|
687
|
-
} from "@angular/core";
|
|
688
|
-
import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api";
|
|
689
|
-
|
|
690
|
-
@Component({
|
|
691
|
-
selector: "app-avatar-widget",
|
|
692
|
-
template: ` <div #container style="width: 100%; height: 100%;"></div> `,
|
|
693
|
-
styles: [
|
|
694
|
-
`
|
|
695
|
-
@import "@touchcastllc/napster-companion-api/lib/index.css";
|
|
696
|
-
`,
|
|
697
|
-
],
|
|
698
|
-
})
|
|
699
|
-
export class AvatarWidgetComponent implements OnInit, OnDestroy {
|
|
700
|
-
@ViewChild("container", { static: true }) container!: ElementRef;
|
|
701
|
-
private widget: any = null;
|
|
702
|
-
|
|
703
|
-
async ngOnInit() {
|
|
704
|
-
try {
|
|
705
|
-
// Fetch token from your backend
|
|
706
|
-
const response = await fetch("/api/get-napster-token", {
|
|
707
|
-
method: "POST",
|
|
708
|
-
});
|
|
709
|
-
const { token } = await response.json();
|
|
710
|
-
|
|
711
|
-
// Initialize widget
|
|
712
|
-
this.widget = await NapsterCompanionApiSdk.init(token, {
|
|
713
|
-
mountContainer: this.container.nativeElement,
|
|
714
|
-
position: "bottom-right",
|
|
715
|
-
features: {
|
|
716
|
-
autoplay: { enabled: true },
|
|
717
|
-
waveform: { enabled: true },
|
|
718
|
-
},
|
|
719
|
-
});
|
|
720
|
-
} catch (error) {
|
|
721
|
-
console.error("Failed to initialize avatar:", error);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
ngOnDestroy() {
|
|
726
|
-
// Cleanup on unmount
|
|
727
|
-
this.widget?.destroy();
|
|
728
|
-
}
|
|
729
|
-
}
|
|
606
|
+
instance.hideAvatar();
|
|
730
607
|
```
|
|
731
608
|
|
|
732
|
-
|
|
609
|
+
#### `avatarIsVisible(): boolean`
|
|
733
610
|
|
|
734
|
-
|
|
611
|
+
Check if the avatar is currently visible.
|
|
735
612
|
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
<meta charset="UTF-8" />
|
|
741
|
-
<title>Napster Avatar SDK</title>
|
|
742
|
-
</head>
|
|
743
|
-
<body>
|
|
744
|
-
<div id="avatar-container"></div>
|
|
745
|
-
|
|
746
|
-
<script src="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.standalone.min.js"></script>
|
|
747
|
-
<script>
|
|
748
|
-
(async function () {
|
|
749
|
-
try {
|
|
750
|
-
// Fetch token from your backend
|
|
751
|
-
const response = await fetch("/api/get-napster-token", {
|
|
752
|
-
method: "POST",
|
|
753
|
-
});
|
|
754
|
-
const { token } = await response.json();
|
|
755
|
-
|
|
756
|
-
// Initialize widget
|
|
757
|
-
const widget = await window.CompanionApiSDK.init(token, {
|
|
758
|
-
mountContainer: "#avatar-container",
|
|
759
|
-
position: "bottom-right",
|
|
760
|
-
features: {
|
|
761
|
-
autoplay: { enabled: true },
|
|
762
|
-
waveform: { enabled: true },
|
|
763
|
-
},
|
|
764
|
-
});
|
|
765
|
-
|
|
766
|
-
// Widget controls
|
|
767
|
-
// widget.showAvatar();
|
|
768
|
-
// widget.hideAvatar();
|
|
769
|
-
// widget.destroy();
|
|
770
|
-
} catch (error) {
|
|
771
|
-
console.error("Failed to initialize avatar:", error);
|
|
772
|
-
}
|
|
773
|
-
})();
|
|
774
|
-
</script>
|
|
775
|
-
</body>
|
|
776
|
-
</html>
|
|
613
|
+
```typescript
|
|
614
|
+
if (instance.avatarIsVisible()) {
|
|
615
|
+
console.log("Avatar is visible");
|
|
616
|
+
}
|
|
777
617
|
```
|
|
778
618
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
## 6. Styling & Customization
|
|
782
|
-
|
|
783
|
-
### CSS Import Path
|
|
619
|
+
#### `destroy(): void`
|
|
784
620
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
**For Bundler Projects:**
|
|
621
|
+
Cleanup and remove the SDK completely.
|
|
788
622
|
|
|
789
623
|
```typescript
|
|
790
|
-
|
|
624
|
+
instance.destroy();
|
|
791
625
|
```
|
|
792
626
|
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
```html
|
|
796
|
-
<link
|
|
797
|
-
rel="stylesheet"
|
|
798
|
-
href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
|
|
799
|
-
/>
|
|
800
|
-
```
|
|
627
|
+
### 5.2 Styling & Position Methods
|
|
801
628
|
|
|
802
|
-
|
|
629
|
+
#### `updateStyles(styles: StyleObject): void`
|
|
803
630
|
|
|
804
|
-
|
|
631
|
+
Update container styles dynamically.
|
|
805
632
|
|
|
806
633
|
```typescript
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
width: "400px",
|
|
812
|
-
height: "600px",
|
|
813
|
-
zIndex: 9999,
|
|
814
|
-
},
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
// Update styles dynamically
|
|
818
|
-
widget.updateStyles({
|
|
819
|
-
width: "500px",
|
|
820
|
-
height: "700px",
|
|
821
|
-
position: "top-right",
|
|
634
|
+
instance.updateStyles({
|
|
635
|
+
top: "50px",
|
|
636
|
+
left: "50px",
|
|
637
|
+
opacity: "0.8",
|
|
822
638
|
});
|
|
823
639
|
```
|
|
824
640
|
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
## 7. Troubleshooting
|
|
828
|
-
|
|
829
|
-
Common integration errors and their quick resolutions.
|
|
830
|
-
|
|
831
|
-
### React Version Mismatch
|
|
832
|
-
|
|
833
|
-
**Error:** `Error: Invalid hook call` or `React version mismatch`
|
|
834
|
-
|
|
835
|
-
**Cause:** Using the wrong SDK entry point for your React version.
|
|
836
|
-
|
|
837
|
-
**Solution:**
|
|
641
|
+
#### `setPosition(position: Position): void`
|
|
838
642
|
|
|
839
|
-
|
|
840
|
-
- For React 16/17, use: `import { NapsterCompanionApiSdk } from "@touchcastllc/napster-companion-api/legacy";`
|
|
643
|
+
Change avatar position on screen.
|
|
841
644
|
|
|
842
|
-
```
|
|
843
|
-
|
|
844
|
-
|
|
645
|
+
```typescript
|
|
646
|
+
instance.setPosition("top-left");
|
|
647
|
+
// or using enum
|
|
648
|
+
import { Position } from "@touchcastllc/napster-companion-api";
|
|
649
|
+
instance.setPosition(Position.TOP_LEFT);
|
|
845
650
|
```
|
|
846
651
|
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
### Missing CSS Styles
|
|
850
|
-
|
|
851
|
-
**Error:** Widget appears unstyled or invisible
|
|
852
|
-
|
|
853
|
-
**Cause:** CSS file not imported.
|
|
652
|
+
#### `clearPosition(): void`
|
|
854
653
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
Add the CSS import:
|
|
654
|
+
Reset position to default/configured value.
|
|
858
655
|
|
|
859
656
|
```typescript
|
|
860
|
-
|
|
861
|
-
```
|
|
862
|
-
|
|
863
|
-
For HTML script tags:
|
|
864
|
-
|
|
865
|
-
```html
|
|
866
|
-
<link
|
|
867
|
-
rel="stylesheet"
|
|
868
|
-
href="https://cdn.jsdelivr.net/npm/@touchcastllc/napster-companion-api@latest/lib/index.css"
|
|
869
|
-
/>
|
|
657
|
+
instance.clearPosition();
|
|
870
658
|
```
|
|
871
659
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
### CORS Errors
|
|
875
|
-
|
|
876
|
-
**Error:** `Cross-Origin Request Blocked` when fetching token
|
|
660
|
+
### 5.3 Feature Control Methods
|
|
877
661
|
|
|
878
|
-
|
|
662
|
+
#### `enableFeature(feature: string): void`
|
|
879
663
|
|
|
880
|
-
|
|
664
|
+
Enable a specific feature.
|
|
881
665
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
```javascript
|
|
885
|
-
// Backend (Node.js/Express)
|
|
886
|
-
app.post("/api/get-napster-token", async (req, res) => {
|
|
887
|
-
const response = await fetch(
|
|
888
|
-
"https://management-api.cogcache.com/public/connections",
|
|
889
|
-
{
|
|
890
|
-
method: "POST",
|
|
891
|
-
headers: {
|
|
892
|
-
"Content-Type": "application/json",
|
|
893
|
-
"x-api-key": process.env.NAPSTER_API_KEY,
|
|
894
|
-
},
|
|
895
|
-
body: JSON.stringify({
|
|
896
|
-
companionId: process.env.COMPANION_ID,
|
|
897
|
-
providerConfig: {
|
|
898
|
-
/* your config */
|
|
899
|
-
},
|
|
900
|
-
}),
|
|
901
|
-
}
|
|
902
|
-
);
|
|
903
|
-
const data = await response.json();
|
|
904
|
-
res.json({ token: data.token });
|
|
905
|
-
});
|
|
666
|
+
```typescript
|
|
667
|
+
instance.enableFeature("disclaimer");
|
|
906
668
|
```
|
|
907
669
|
|
|
908
|
-
|
|
670
|
+
#### `disableFeature(feature: string): void`
|
|
671
|
+
|
|
672
|
+
Disable a specific feature.
|
|
909
673
|
|
|
910
674
|
```typescript
|
|
911
|
-
|
|
912
|
-
const { token } = await response.json();
|
|
675
|
+
instance.disableFeature("disclaimer");
|
|
913
676
|
```
|
|
914
677
|
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
### Authentication / Token Issues
|
|
918
|
-
|
|
919
|
-
**Error:** `401 Unauthorized` or `Invalid token`
|
|
678
|
+
#### `isFeatureEnabled(feature: string): boolean`
|
|
920
679
|
|
|
921
|
-
|
|
680
|
+
Check if a feature is currently enabled.
|
|
922
681
|
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
682
|
+
```typescript
|
|
683
|
+
if (instance.isFeatureEnabled("disclaimer")) {
|
|
684
|
+
console.log("Disclaimer is enabled");
|
|
685
|
+
}
|
|
686
|
+
```
|
|
926
687
|
|
|
927
|
-
|
|
688
|
+
### 5.4 Communication Methods
|
|
928
689
|
|
|
929
|
-
|
|
930
|
-
2. **Check token expiration** - generate a fresh token
|
|
931
|
-
3. **Verify companion ID** matches your configuration
|
|
932
|
-
4. **Ensure backend endpoint** is working:
|
|
690
|
+
#### `sendCommand(command: { type: string; data?: object }): void`
|
|
933
691
|
|
|
934
|
-
|
|
692
|
+
Send a command to the avatar via the data channel.
|
|
935
693
|
|
|
936
|
-
|
|
694
|
+
```typescript
|
|
695
|
+
// Send a message to the avatar
|
|
696
|
+
instance.sendCommand({ type: "send_message", data: { text: "Hello, how are you?" } });
|
|
937
697
|
|
|
938
|
-
|
|
698
|
+
// Cancel the current response
|
|
699
|
+
instance.sendCommand({ type: "cancel" });
|
|
700
|
+
```
|
|
939
701
|
|
|
940
|
-
|
|
702
|
+
## 6. Configuration Interface
|
|
941
703
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
704
|
+
```typescript
|
|
705
|
+
interface NapsterCompanionApiConfig {
|
|
706
|
+
// Container mounting
|
|
707
|
+
mountContainer?: HTMLElement | string | null;
|
|
708
|
+
|
|
709
|
+
// Positioning
|
|
710
|
+
position?:
|
|
711
|
+
| "bottom-right"
|
|
712
|
+
| "bottom-left"
|
|
713
|
+
| "bottom-center"
|
|
714
|
+
| "top-right"
|
|
715
|
+
| "top-left"
|
|
716
|
+
| "top-center"
|
|
717
|
+
| "center";
|
|
718
|
+
|
|
719
|
+
// Styling
|
|
720
|
+
style?: StyleObject;
|
|
721
|
+
className?: string;
|
|
722
|
+
avatarStyle?: {
|
|
723
|
+
view: "round" | "rectangle" | "silhouette";
|
|
724
|
+
borderWidth?: string;
|
|
725
|
+
borderColor?: string;
|
|
726
|
+
borderStyle?: string;
|
|
727
|
+
};
|
|
945
728
|
|
|
946
|
-
|
|
729
|
+
// Features
|
|
730
|
+
features?: {
|
|
731
|
+
backgroundRemoval?: { enabled: boolean };
|
|
732
|
+
inactiveTimeout?: {
|
|
733
|
+
enabled: boolean;
|
|
734
|
+
duration?: number; // max: 180000ms
|
|
735
|
+
countdown?: number; // max: 60s
|
|
736
|
+
};
|
|
737
|
+
disclaimer?: { enabled: boolean; text?: string };
|
|
738
|
+
showSDKLoader?: { enabled: boolean; bgColor?: string };
|
|
739
|
+
};
|
|
947
740
|
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
useEffect(() => {
|
|
951
|
-
const container = document.querySelector("#avatar-container");
|
|
952
|
-
if (container) {
|
|
953
|
-
NapsterCompanionApiSdk.init(token, {
|
|
954
|
-
mountContainer: container, // Use DOM element directly
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
}, []);
|
|
741
|
+
// Configuration
|
|
742
|
+
debug?: boolean;
|
|
958
743
|
|
|
959
|
-
//
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
744
|
+
// Event callbacks
|
|
745
|
+
onReady?: () => void;
|
|
746
|
+
onError?: (error: Error) => void;
|
|
747
|
+
onData?: (data: EventMessage) => void;
|
|
748
|
+
onAvatarReady?: (isReady?: boolean) => void;
|
|
749
|
+
onInactivityStatusChange?: (isInactive: boolean) => void;
|
|
750
|
+
onDestroy?: () => void;
|
|
751
|
+
onFeaturesUpdate?: (features: FeatureConfig) => void;
|
|
752
|
+
}
|
|
963
753
|
```
|
|
964
754
|
|
|
965
755
|
---
|
|
966
756
|
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
**Error:** `Cannot find module '@touchcastllc/napster-companion-api'`
|
|
757
|
+
## 7. Troubleshooting
|
|
970
758
|
|
|
971
|
-
|
|
759
|
+
### 7.1 Common Issues
|
|
972
760
|
|
|
761
|
+
**Problem: "Module not found" Error**
|
|
973
762
|
**Solution:**
|
|
974
763
|
|
|
975
764
|
```bash
|
|
765
|
+
# Ensure package is installed
|
|
976
766
|
npm install @touchcastllc/napster-companion-api
|
|
977
|
-
# or
|
|
978
|
-
yarn add @touchcastllc/napster-companion-api
|
|
979
|
-
```
|
|
980
767
|
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
768
|
+
# Install peer dependencies
|
|
769
|
+
npm install @reduxjs/toolkit
|
|
770
|
+
```
|
|
984
771
|
|
|
985
|
-
**
|
|
772
|
+
**Problem: Invalid or expired token**
|
|
773
|
+
**Solution:**
|
|
986
774
|
|
|
987
|
-
|
|
775
|
+
- Generate new token from backend API
|
|
776
|
+
- Ensure token is passed correctly to `init()`
|
|
988
777
|
|
|
778
|
+
**Problem: Avatar appears unstyled**
|
|
989
779
|
**Solution:**
|
|
990
780
|
|
|
991
|
-
|
|
781
|
+
See the style import guide from [1.2.1 Installation & Setup](#121-for-esm-build-type-recommended)
|
|
992
782
|
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
npm install react@^18 react-dom@^18 @reduxjs/toolkit@^2 react-redux@^9
|
|
783
|
+
**Problem:** `mountContainer` element doesn't exist
|
|
784
|
+
**Solution:**
|
|
996
785
|
|
|
997
|
-
|
|
998
|
-
|
|
786
|
+
```typescript
|
|
787
|
+
// Wait for DOM to load
|
|
788
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
789
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
790
|
+
mountContainer: "#avatar-container", // Ensure element exists
|
|
791
|
+
});
|
|
792
|
+
});
|
|
999
793
|
```
|
|
1000
794
|
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
### TypeScript Errors
|
|
1004
|
-
|
|
1005
|
-
**Error:** `Cannot find type definitions`
|
|
795
|
+
### 7.2 Debug Mode
|
|
1006
796
|
|
|
1007
|
-
|
|
797
|
+
Enable debug logging:
|
|
1008
798
|
|
|
1009
|
-
|
|
799
|
+
```typescript
|
|
800
|
+
const instance = await NapsterCompanionApiSdk.init(token, {
|
|
801
|
+
debug: true, // Enable debug logs
|
|
802
|
+
onError: error => console.error("SDK Error:", error),
|
|
803
|
+
onData: data => console.log("SDK Data:", data),
|
|
804
|
+
});
|
|
805
|
+
```
|
|
1010
806
|
|
|
1011
|
-
|
|
807
|
+
### 7.3 Performance Issues
|
|
1012
808
|
|
|
1013
|
-
|
|
1014
|
-
{
|
|
1015
|
-
"compilerOptions": {
|
|
1016
|
-
"moduleResolution": "node",
|
|
1017
|
-
"esModuleInterop": true,
|
|
1018
|
-
"skipLibCheck": true
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
```
|
|
809
|
+
#### Large Bundle Size
|
|
1022
810
|
|
|
1023
|
-
|
|
811
|
+
- Use ESM build instead of standalone
|
|
812
|
+
- Import only needed features
|
|
813
|
+
- Enable tree-shaking in bundler
|
|
1024
814
|
|
|
1025
|
-
|
|
815
|
+
#### Memory Leaks
|
|
1026
816
|
|
|
1027
|
-
|
|
1028
|
-
|
|
817
|
+
```typescript
|
|
818
|
+
// Always cleanup when done
|
|
819
|
+
useEffect(() => {
|
|
820
|
+
return () => {
|
|
821
|
+
instance?.destroy();
|
|
822
|
+
};
|
|
823
|
+
}, [instance]);
|
|
824
|
+
```
|
|
1029
825
|
|
|
1030
826
|
---
|
|
1031
827
|
|
|
1032
|
-
##
|
|
828
|
+
## License
|
|
1033
829
|
|
|
1034
|
-
MIT License
|
|
830
|
+
This project is licensed under the MIT License - see the [LICENSE](/LICENSE) file for details.
|