playsout-web-sdk 1.0.62 → 1.0.63
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 +206 -366
- package/dist/arrow-DVB3ZH4I.png +0 -0
- package/dist/bofang-7CYHXAOR.png +0 -0
- package/dist/chunk-DXJDUM6W.js +2 -0
- package/dist/chunk-FQSZP2MS.cjs +2 -0
- package/dist/chunk-GZLJ3BX5.js +1929 -0
- package/dist/chunk-RBKA52ZP.cjs +1929 -0
- package/dist/chunk-VZ5ZVHY4.js +2 -0
- package/dist/chunk-ZWHQXIXN.cjs +2 -0
- package/dist/clock-UCOJBATJ.png +0 -0
- package/dist/comment-CYSCAN7M.png +0 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -0
- package/{core → dist/core}/api.d.ts +1 -5
- package/dist/core/api.d.ts.map +1 -0
- package/{core → dist/core}/errors.d.ts +1 -4
- package/dist/core/errors.d.ts.map +1 -0
- package/{core → dist/core}/events.d.ts +1 -9
- package/{core → dist/core}/events.d.ts.map +1 -1
- package/{core → dist/core}/index.d.ts.map +1 -1
- package/{core → dist/core}/storage.d.ts +0 -1
- package/{core → dist/core}/storage.d.ts.map +1 -1
- package/{core → dist/core}/types.d.ts +2 -37
- package/dist/core/types.d.ts.map +1 -0
- package/dist/data/games.d.ts +3 -0
- package/dist/data/games.d.ts.map +1 -0
- package/dist/fenxiang-SHOVHZII.png +0 -0
- package/dist/index.cjs +1 -0
- package/{index.d.ts → dist/index.d.ts} +1 -1
- package/dist/index.d.ts.map +1 -0
- package/dist/index.global.js +1929 -0
- package/dist/index.iife.js +1929 -0
- package/{index.js → dist/index.js} +1 -1
- package/dist/like-UTHO5POC.png +0 -0
- package/dist/live-like-4WE6H52V.png +0 -0
- package/dist/next-T6TSGXOI.png +0 -0
- package/dist/react/PlaysoutVideoWidget.d.ts +16 -0
- package/dist/react/PlaysoutVideoWidget.d.ts.map +1 -0
- package/dist/react/index.cjs +1 -0
- package/{react → dist/react}/index.d.ts +2 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +1 -0
- package/dist/share-2WNZMMZ6.png +0 -0
- package/dist/shoucang-CSI3UBYK.png +0 -0
- package/dist/shuqian-KOBOMTMJ.png +0 -0
- package/dist/shuqian1-VMWYGXP3.png +0 -0
- package/dist/vue/PlaysoutVideoWidget.d.ts +31 -0
- package/dist/vue/PlaysoutVideoWidget.d.ts.map +1 -0
- package/{vue → dist/vue}/composable.d.ts +4 -2
- package/{vue → dist/vue}/composable.d.ts.map +1 -1
- package/dist/vue/index.cjs +1 -0
- package/{vue → dist/vue}/index.d.ts +1 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +1 -0
- package/dist/web-components/PlaysoutVideoWidget.d.ts +59 -0
- package/dist/web-components/PlaysoutVideoWidget.d.ts.map +1 -0
- package/{web-components → dist/web-components}/PlaysoutWidget.d.ts +6 -3
- package/dist/web-components/PlaysoutWidget.d.ts.map +1 -0
- package/dist/web-components/index.cjs +1 -0
- package/dist/web-components/index.d.ts +5 -0
- package/dist/web-components/index.d.ts.map +1 -0
- package/dist/web-components/index.js +1 -0
- package/package.json +77 -63
- package/chunk-EZLO3WY6.js +0 -2
- package/chunk-MDSUYVLI.cjs +0 -2
- package/chunk-Z2CIDSTP.cjs +0 -2
- package/chunk-Z5PDR5PA.js +0 -2
- package/core/api.d.ts.map +0 -1
- package/core/errors.d.ts.map +0 -1
- package/core/types.d.ts.map +0 -1
- package/data/games.d.ts +0 -30
- package/data/games.d.ts.map +0 -1
- package/index.cjs +0 -1
- package/index.d.ts.map +0 -1
- package/index.global.js +0 -1546
- package/index.iife.js +0 -1546
- package/react/index.cjs +0 -1
- package/react/index.d.ts.map +0 -1
- package/react/index.js +0 -1
- package/vue/index.cjs +0 -1
- package/vue/index.d.ts.map +0 -1
- package/vue/index.js +0 -1
- package/web-components/PlaysoutWidget.d.ts.map +0 -1
- package/web-components/imageCache.d.ts +0 -13
- package/web-components/imageCache.d.ts.map +0 -1
- package/web-components/index.cjs +0 -1546
- package/web-components/index.d.ts +0 -3
- package/web-components/index.d.ts.map +0 -1
- package/web-components/index.js +0 -1546
- /package/{core → dist/core}/index.d.ts +0 -0
- /package/{iife-entry.d.ts → dist/iife-entry.d.ts} +0 -0
- /package/{iife-entry.d.ts.map → dist/iife-entry.d.ts.map} +0 -0
- /package/{public-api.d.ts → dist/public-api.d.ts} +0 -0
- /package/{public-api.d.ts.map → dist/public-api.d.ts.map} +0 -0
- /package/{react → dist/react}/context.d.ts +0 -0
- /package/{react → dist/react}/context.d.ts.map +0 -0
- /package/{vue → dist/vue}/plugin.d.ts +0 -0
- /package/{vue → dist/vue}/plugin.d.ts.map +0 -0
- /package/{web-components → dist/web-components}/PrivyBridge.d.ts +0 -0
- /package/{web-components → dist/web-components}/PrivyBridge.d.ts.map +0 -0
- /package/{web-components → dist/web-components}/assetUrl.d.ts +0 -0
- /package/{web-components → dist/web-components}/assetUrl.d.ts.map +0 -0
package/README.md
CHANGED
|
@@ -1,370 +1,210 @@
|
|
|
1
|
-
# Playsout Web SDK
|
|
2
|
-
|
|
3
|
-
Playsout
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
vue({
|
|
157
|
-
template: {
|
|
158
|
-
compilerOptions: {
|
|
159
|
-
isCustomElement: (tag) => tag.startsWith('playsout-'),
|
|
160
|
-
},
|
|
161
|
-
},
|
|
162
|
-
}),
|
|
163
|
-
],
|
|
164
|
-
});
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Without this configuration, Vue may report:
|
|
168
|
-
|
|
169
|
-
```text
|
|
170
|
-
Failed to resolve component: playsout-widget
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
### 2. Initialize the SDK in `src/main.js`
|
|
174
|
-
|
|
175
|
-
Place this code in the Vue entry file, usually `src/main.js` or `src/main.ts`.
|
|
176
|
-
|
|
177
|
-
```js
|
|
178
|
-
import { createApp } from 'vue';
|
|
179
|
-
import { createPlaysoutPlugin } from 'playsout-web-sdk/vue';
|
|
180
|
-
import 'playsout-web-sdk/web-components';
|
|
181
|
-
import App from './App.vue';
|
|
182
|
-
|
|
183
|
-
const app = createApp(App);
|
|
184
|
-
|
|
185
|
-
app.use(createPlaysoutPlugin({
|
|
186
|
-
config: {
|
|
187
|
-
locale: 'en',
|
|
188
|
-
},
|
|
189
|
-
}));
|
|
190
|
-
|
|
191
|
-
app.mount('#app');
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
`createPlaysoutPlugin({ config })` automatically calls `init(config)` when the plugin is installed. Vue components normally should not call `init()` again.
|
|
195
|
-
|
|
196
|
-
### 3. Use the SDK in the game page
|
|
197
|
-
|
|
198
|
-
Place this code in the page component that displays the game list. In a new Vue project, it can be placed directly in `src/App.vue`.
|
|
199
|
-
|
|
200
|
-
```vue
|
|
201
|
-
<script setup>
|
|
202
|
-
import { watch } from 'vue';
|
|
203
|
-
import { usePlaysout } from 'playsout-web-sdk/vue';
|
|
204
|
-
|
|
205
|
-
const {
|
|
206
|
-
isInitialized,
|
|
207
|
-
isLoggedIn,
|
|
208
|
-
locale,
|
|
209
|
-
Login,
|
|
210
|
-
} = usePlaysout();
|
|
211
|
-
|
|
212
|
-
let initialLoginChecked = false;
|
|
213
|
-
|
|
214
|
-
watch(isInitialized, (initialized) => {
|
|
215
|
-
if (!initialized || initialLoginChecked) return;
|
|
216
|
-
initialLoginChecked = true;
|
|
217
|
-
if (isLoggedIn.value) return;
|
|
218
|
-
|
|
219
|
-
Login({
|
|
220
|
-
platform: 'eros',
|
|
221
|
-
platformUserId: '10',
|
|
222
|
-
platformToken: 'random-string',
|
|
223
|
-
username: 'TestUser',
|
|
224
|
-
}).catch((error) => {
|
|
225
|
-
console.error('Playsout login flow failed:', error);
|
|
226
|
-
});
|
|
227
|
-
}, { immediate: true });
|
|
228
|
-
</script>
|
|
229
|
-
|
|
230
|
-
<template>
|
|
231
|
-
<playsout-widget
|
|
232
|
-
:locale="locale"
|
|
233
|
-
/>
|
|
234
|
-
</template>
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
Vue notes:
|
|
238
|
-
|
|
239
|
-
- The page waits for plugin initialization, then checks the login state and runs the login flow automatically.
|
|
240
|
-
- `locale` controls the widget language.
|
|
241
|
-
- For a fixed default language, `config: { locale: 'en' }` in the entry file is sufficient. If the application later needs dynamic locale switching, call `setLocale()` and bind `locale`.
|
|
242
|
-
- If the application already has a game page, place the logic in that page component.
|
|
243
|
-
|
|
244
|
-
## React Integration
|
|
245
|
-
|
|
246
|
-
### 1. Initialize the SDK in `src/main.jsx`
|
|
247
|
-
|
|
248
|
-
Place this code in the React entry file, usually `src/main.jsx` or `src/main.tsx`.
|
|
249
|
-
|
|
250
|
-
React does not require `isCustomElement` configuration. Tags containing a hyphen, such as `<playsout-widget>`, are handled as Custom Elements.
|
|
251
|
-
|
|
252
|
-
```jsx
|
|
253
|
-
import { createRoot } from 'react-dom/client';
|
|
254
|
-
import { PlaysoutProvider } from 'playsout-web-sdk/react';
|
|
255
|
-
import 'playsout-web-sdk/web-components';
|
|
256
|
-
import App from './App.jsx';
|
|
257
|
-
|
|
258
|
-
createRoot(document.getElementById('root')).render(
|
|
259
|
-
<PlaysoutProvider config={{ locale: 'en' }}>
|
|
260
|
-
<App />
|
|
261
|
-
</PlaysoutProvider>
|
|
262
|
-
);
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
`PlaysoutProvider` automatically calls `init(config)` after receiving `config`. Page components normally should not call `init()` again.
|
|
266
|
-
|
|
267
|
-
### 2. Use the SDK in the game page
|
|
268
|
-
|
|
269
|
-
Place this code in the page component that displays the game list. In a new React project, it can be placed directly in `src/App.jsx`.
|
|
270
|
-
|
|
271
|
-
```jsx
|
|
272
|
-
import { useEffect, useRef } from 'react';
|
|
273
|
-
import { usePlaysout } from 'playsout-web-sdk/react';
|
|
274
|
-
|
|
275
|
-
export default function App() {
|
|
276
|
-
const initialLoginChecked = useRef(false);
|
|
277
|
-
const {
|
|
278
|
-
isInitialized,
|
|
279
|
-
isLoggedIn,
|
|
280
|
-
locale,
|
|
281
|
-
Login,
|
|
282
|
-
} = usePlaysout();
|
|
283
|
-
|
|
284
|
-
useEffect(() => {
|
|
285
|
-
if (!isInitialized || initialLoginChecked.current) return;
|
|
286
|
-
initialLoginChecked.current = true;
|
|
287
|
-
if (isLoggedIn) return;
|
|
288
|
-
|
|
289
|
-
Login({
|
|
290
|
-
platform: 'eros',
|
|
291
|
-
platformUserId: '10',
|
|
292
|
-
platformToken: 'random-string',
|
|
293
|
-
username: 'TestUser',
|
|
294
|
-
})
|
|
295
|
-
.catch((error) => {
|
|
296
|
-
console.error('Playsout login flow failed:', error);
|
|
297
|
-
});
|
|
298
|
-
}, [isInitialized, isLoggedIn, Login]);
|
|
299
|
-
|
|
1
|
+
# Playsout Web SDK
|
|
2
|
+
|
|
3
|
+
Embed Playsout games and short dramas in HTML, Vue 3, or React applications.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install playsout-web-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Game List
|
|
12
|
+
|
|
13
|
+
Game details open in an iframe by default.
|
|
14
|
+
|
|
15
|
+
### HTML
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<div id="game-container"></div>
|
|
19
|
+
|
|
20
|
+
<script src="https://unpkg.com/playsout-web-sdk@1.0.63/dist/index.iife.js"></script>
|
|
21
|
+
<script>
|
|
22
|
+
async function bootstrap() {
|
|
23
|
+
await window.Playsout.init({ locale: "en" });
|
|
24
|
+
|
|
25
|
+
await window.Playsout.Login({
|
|
26
|
+
platform: "eros",
|
|
27
|
+
platformUserId: "10",
|
|
28
|
+
platformToken: "random-string",
|
|
29
|
+
username: "TestUser",
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
window.Playsout.mount("#game-container");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
bootstrap().catch(console.error);
|
|
36
|
+
</script>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Vue 3
|
|
40
|
+
|
|
41
|
+
Configure Vite so Vue recognizes Playsout custom elements:
|
|
42
|
+
|
|
43
|
+
```js
|
|
44
|
+
// vite.config.js
|
|
45
|
+
import { defineConfig } from "vite";
|
|
46
|
+
import vue from "@vitejs/plugin-vue";
|
|
47
|
+
|
|
48
|
+
export default defineConfig({
|
|
49
|
+
plugins: [
|
|
50
|
+
vue({
|
|
51
|
+
template: {
|
|
52
|
+
compilerOptions: {
|
|
53
|
+
isCustomElement: (tag) => tag.startsWith("playsout-"),
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
}),
|
|
57
|
+
],
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Initialize the SDK once in your entry file:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
// main.js
|
|
65
|
+
import { createApp } from "vue";
|
|
66
|
+
import { createPlaysoutPlugin } from "playsout-web-sdk/vue";
|
|
67
|
+
import "playsout-web-sdk/web-components";
|
|
68
|
+
import App from "./App.vue";
|
|
69
|
+
|
|
70
|
+
const app = createApp(App);
|
|
71
|
+
app.use(createPlaysoutPlugin({ config: { locale: "en" } }));
|
|
72
|
+
app.mount("#app");
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Then render the game list:
|
|
76
|
+
|
|
77
|
+
```vue
|
|
78
|
+
<script setup>
|
|
79
|
+
import { usePlaysout } from "playsout-web-sdk/vue";
|
|
80
|
+
|
|
81
|
+
const { locale } = usePlaysout();
|
|
82
|
+
</script>
|
|
83
|
+
|
|
84
|
+
<template>
|
|
85
|
+
<playsout-widget :locale="locale" />
|
|
86
|
+
</template>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### React
|
|
90
|
+
|
|
91
|
+
Initialize the SDK once at the application root:
|
|
92
|
+
|
|
93
|
+
```jsx
|
|
94
|
+
// main.jsx
|
|
95
|
+
import { createRoot } from "react-dom/client";
|
|
96
|
+
import { PlaysoutProvider } from "playsout-web-sdk/react";
|
|
97
|
+
import "playsout-web-sdk/web-components";
|
|
98
|
+
import App from "./App.jsx";
|
|
99
|
+
|
|
100
|
+
createRoot(document.getElementById("root")).render(
|
|
101
|
+
<PlaysoutProvider config={{ locale: "en" }}>
|
|
102
|
+
<App />
|
|
103
|
+
</PlaysoutProvider>,
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Then render the game list:
|
|
108
|
+
|
|
109
|
+
```jsx
|
|
110
|
+
import { usePlaysout } from "playsout-web-sdk/react";
|
|
111
|
+
|
|
112
|
+
export default function App() {
|
|
113
|
+
const { locale } = usePlaysout();
|
|
114
|
+
return <playsout-widget locale={locale} />;
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Short Drama
|
|
119
|
+
|
|
120
|
+
Short dramas are an independent full-screen component. Locked episodes are unlocked by watching an ad.
|
|
121
|
+
|
|
122
|
+
### HTML
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<playsout-video-widget id="short-drama" locale="en"></playsout-video-widget>
|
|
126
|
+
<script src="https://unpkg.com/playsout-web-sdk@1.0.63/dist/index.iife.js"></script>
|
|
127
|
+
<script>
|
|
128
|
+
document.querySelector("#short-drama").addEventListener("ad-complete", (event) => {
|
|
129
|
+
console.log("Episode unlocked:", event.detail);
|
|
130
|
+
});
|
|
131
|
+
</script>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Vue 3
|
|
135
|
+
|
|
136
|
+
```vue
|
|
137
|
+
<script setup>
|
|
138
|
+
import { PlaysoutVideoWidget } from "playsout-web-sdk/vue";
|
|
139
|
+
|
|
140
|
+
function onAdComplete(event) {
|
|
141
|
+
console.log("Episode unlocked:", event.detail);
|
|
142
|
+
}
|
|
143
|
+
</script>
|
|
144
|
+
|
|
145
|
+
<template>
|
|
146
|
+
<PlaysoutVideoWidget locale="en" @ad-complete="onAdComplete" />
|
|
147
|
+
</template>
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### React
|
|
151
|
+
|
|
152
|
+
```jsx
|
|
153
|
+
import { PlaysoutVideoWidget } from "playsout-web-sdk/react";
|
|
154
|
+
|
|
155
|
+
export default function DramaPage() {
|
|
300
156
|
return (
|
|
301
|
-
<
|
|
302
|
-
locale=
|
|
157
|
+
<PlaysoutVideoWidget
|
|
158
|
+
locale="en"
|
|
159
|
+
onAdComplete={(event) => console.log("Episode unlocked:", event.detail)}
|
|
303
160
|
/>
|
|
304
161
|
);
|
|
305
162
|
}
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
|
319
|
-
| --- | --- | --- |
|
|
320
|
-
|
|
|
321
|
-
|
|
|
322
|
-
|
|
|
323
|
-
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
4. After a successful re-login, the SDK stores both the new token and user information, then retries the original request.
|
|
355
|
-
|
|
356
|
-
The automatic re-login is attempted at most once for an authentication recovery. If it fails, the SDK clears the stored token, user information, and reusable login parameters, changes `isLoggedIn` to `false`, emits `authExpired`, and throws the error to the calling application. TikTok login parameters are not reused automatically.
|
|
357
|
-
|
|
358
|
-
`authExpired` is an optional final-failure notification. Do not start another automatic login loop from this event:
|
|
359
|
-
|
|
360
|
-
```js
|
|
361
|
-
window.Playsout.on('authExpired', function () {
|
|
362
|
-
console.error('Playsout authentication recovery failed');
|
|
363
|
-
});
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
React and Vue adapters synchronize their reactive login state after final recovery failure. The application should catch the failed SDK operation and decide how to present the error to the user.
|
|
367
|
-
|
|
368
|
-
## Image Loading
|
|
369
|
-
|
|
370
|
-
The SDK currently uses online image URLs directly. Persistent SDK image caching is disabled by default, so the SDK does not proactively store images in persistent browser storage.
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Configure the component
|
|
166
|
+
|
|
167
|
+
| Attribute | Description | Example |
|
|
168
|
+
| --- | --- | --- |
|
|
169
|
+
| `locale` | Sets the component language. Defaults to `en`. | `locale="zh"` |
|
|
170
|
+
|
|
171
|
+
### Listen for events
|
|
172
|
+
|
|
173
|
+
Use a browser event listener in HTML, an `on...` callback in React, or an `@...` listener in Vue. Events provide the current drama's `id` and `title` in `event.detail`; `video-error` also includes `source`.
|
|
174
|
+
|
|
175
|
+
| Event | When it fires | HTML listener |
|
|
176
|
+
| --- | --- | --- |
|
|
177
|
+
| `video-play` | A video starts playing. | `addEventListener("video-play", handler)` |
|
|
178
|
+
| `video-close` | The player closes. | `addEventListener("video-close", handler)` |
|
|
179
|
+
| `video-error` | A video cannot be loaded. | `addEventListener("video-error", handler)` |
|
|
180
|
+
| `ad-complete` | An ad finishes and unlocks an episode. | `addEventListener("ad-complete", handler)` |
|
|
181
|
+
|
|
182
|
+
## Login
|
|
183
|
+
|
|
184
|
+
Call `Login()` after initialization when your application needs a platform session:
|
|
185
|
+
|
|
186
|
+
```js
|
|
187
|
+
await Playsout.Login({
|
|
188
|
+
platform: "eros", // "grab" or "eros"
|
|
189
|
+
platformUserId: "10",
|
|
190
|
+
platformToken: "random-string",
|
|
191
|
+
username: "TestUser",
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
For Grab and Eros, `platformUserId`, `platformToken`, and `username` are required.
|
|
196
|
+
|
|
197
|
+
## Common APIs
|
|
198
|
+
|
|
199
|
+
```js
|
|
200
|
+
Playsout.init({ locale: "en" });
|
|
201
|
+
Playsout.Login(params);
|
|
202
|
+
Playsout.logout();
|
|
203
|
+
Playsout.isLoggedIn;
|
|
204
|
+
Playsout.getUser();
|
|
205
|
+
Playsout.getUserInfo();
|
|
206
|
+
Playsout.setLocale("zh");
|
|
207
|
+
Playsout.getLocale();
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Supported locales: `zh`, `en`, `ja`, `ko`, `vi`, `th`, `id`, and `ms`.
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
var i=(s=>(s.INITIALIZED="initialized",s.LOGIN="login",s.LOGOUT="logout",s.LOCALE_CHANGE="localeChange",s.ERROR="error",s.GAME_CLICK="gameClick",s.LOGIN_REQUIRED="loginRequired",s.AUTH_EXPIRED="authExpired",s))(i||{}),a=class{constructor(){this.events=new Map;}on(e,t){return this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t),()=>{this.off(e,t);}}once(e,t){let r=o=>{t(o),this.off(e,r);};return this.on(e,r)}off(e,t){this.events.get(e)?.delete(t),this.events.get(e)?.size===0&&this.events.delete(e);}emit(e,t){this.events.get(e)?.forEach(r=>{try{r(t);}catch(o){console.error(`[PlaysoutSDK] Event handler error for "${e}":`,o);}});}clear(){this.events.clear();}},c=new a;var l="https://games.playsout.com/resources/icon/image";function d(n){if(!n||/^(data:|https?:|blob:)/i.test(n))return n;let e=n.replace(/^\.\//,"");return `${l}/${e}`}
|
|
2
|
+
export{i as a,c as b,d as c};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkZWHQXIXN_cjs=require('./chunk-ZWHQXIXN.cjs');var b=(d=>(d.NOT_INITIALIZED="NOT_INITIALIZED",d.ALREADY_INITIALIZED="ALREADY_INITIALIZED",d.NOT_LOGGED_IN="NOT_LOGGED_IN",d.TOKEN_EXPIRED="TOKEN_EXPIRED",d.NETWORK_ERROR="NETWORK_ERROR",d.TIMEOUT="TIMEOUT",d.SERVER_ERROR="SERVER_ERROR",d.API_ERROR="API_ERROR",d.INVALID_PARAMS="INVALID_PARAMS",d.MISSING_PARAMS="MISSING_PARAMS",d.FEATURE_NOT_SUPPORTED="FEATURE_NOT_SUPPORTED",d.UNKNOWN="UNKNOWN",d))(b||{}),y=class extends Error{constructor(t,o,i){super(o);this.code=t;this.details=i;this.name="SDKError";}toJSON(){return {name:this.name,code:this.code,message:this.message,details:this.details}}},q={NOT_INITIALIZED:"SDK not initialized. Please call PlaysoutSDK.init() first.",ALREADY_INITIALIZED:"SDK already initialized. Please do not call init() more than once.",NOT_LOGGED_IN:"User not logged in. Please log in first.",TOKEN_EXPIRED:"Login token has expired. Please log in again.",NETWORK_ERROR:"Network connection failed. Please check your network.",TIMEOUT:"Request timed out. Please try again later.",SERVER_ERROR:"Server is busy. Please try again later.",API_ERROR:"API request failed.",INVALID_PARAMS:"Invalid parameter(s).",MISSING_PARAMS:"Missing required parameter(s).",FEATURE_NOT_SUPPORTED:"This feature is not supported in the current environment.",UNKNOWN:"An unknown error occurred."};function n(r,e){return new y(r,q[r],e)}var w="playsout_",R=class{constructor(e){this.storage=e;}get(e){try{return this.storage.getItem(w+e)}catch{return null}}set(e,t){try{this.storage.setItem(w+e,t);}catch(o){console.warn("[PlaysoutSDK] Storage set failed:",o);}}remove(e){try{this.storage.removeItem(w+e);}catch{}}clear(){try{let e=[];for(let t=0;t<this.storage.length;t++){let o=this.storage.key(t);o&&o.startsWith(w)&&e.push(o);}e.forEach(t=>this.storage.removeItem(t));}catch{}}},N=class{constructor(){this.store=new Map;}get(e){return this.store.get(e)??null}set(e,t){this.store.set(e,t);}remove(e){this.store.delete(e);}clear(){this.store.clear();}};function x(r="localStorage"){return typeof window>"u"||r==="memory"?new N:r==="sessionStorage"?new R(sessionStorage):new R(localStorage)}var E=x(),l={get:r=>E.get(r),set:(r,e)=>{E.set(r,e);},remove:r=>{E.remove(r);},clear:()=>{E.clear();},getJSON:r=>{let e=E.get(r);if(!e)return null;try{return JSON.parse(e)}catch{return null}},setJSON:(r,e)=>{E.set(r,JSON.stringify(e));},configure(r){E=x(r);}},c={TOKEN_DATA:"token_data",USER:"user",LOGIN_PARAMS:"login_params",LOCALE:"locale"};var W=r=>{if(!r)return r;try{let e=new URL(r);if(e.hostname==="games.playsout.com"){let t=e.pathname,o=t.endsWith("/"),i=/\.[a-z0-9]+$/i.test(t);!o&&!i&&(e.pathname=`${t}/`);}return e.toString()}catch{return r}},Z=r=>r.map(e=>{if(!e.externalUrl)return e;let t=W(e.externalUrl);return t===e.externalUrl?e:{...e,externalUrl:t}}),J=[{id:"BlockCrushFun",title:"Block Crush Fun",category:"Puzzle",image:chunkZWHQXIXN_cjs.c("./games/BlockCrushFun.png"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/BlockCrushFun/"},{id:"KittyEscape",title:"Kitty Escape",category:"Puzzle",image:chunkZWHQXIXN_cjs.c("./games/KittyEscape.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/KittyEscape/"},{id:"ProjectGarden",title:"Project: Garden",category:"Adventure",image:chunkZWHQXIXN_cjs.c("./games/SimulatedAdventures.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/simulated/"},{id:"ProjectIDLE",title:"Project: IDLE",category:"Simulation",image:chunkZWHQXIXN_cjs.c("./games/ProjectIDLE.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/idle/"},{id:"SoccerDASH",title:"Soccer Dash",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/Soccer Dash.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SoccerDASH/"},{id:"SoccerSurvivor",title:"Soccer Survivor",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/SoccerSurvivor.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SoccerSurvivors/"},{id:"CulinaryStarWeb",title:"Culinary Star",category:"Casual",image:chunkZWHQXIXN_cjs.c("./games/CulinaryStar.webp"),description:"Cooking game",isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CulinaryStar/"},{id:"PickaxeQuest",title:"Pickaxe Quest",category:"Adventure",image:chunkZWHQXIXN_cjs.c("./games/PickaxeQuest.jpg"),description:"Mining and adventure game",isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/PickaxeQuest/",apiGameId:73},{id:"MonsterSurvivors",title:"Monster Survivors",category:"Adventure",image:chunkZWHQXIXN_cjs.c("./games/MonsterSurvivors.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/MonsterSurvivors/"},{id:"IdleTowerDefense",title:"Idle Tower Defense",category:"RPG",image:chunkZWHQXIXN_cjs.c("./games/IdleTowerDefense.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/IdleTowerDefense/"},{id:"MushroomWarriors",title:"Mushroom Warriors",category:"RPG",image:chunkZWHQXIXN_cjs.c("./games/MushroomWarriors.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/MushroomWarriors/"},{id:"FollowThePath",title:"Follow The Path",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/FollowThePath.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/FollowThePath/"},{id:"SoccerCascade",title:"Soccer Cascade",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/Soccer Cascade.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SoccerCascade/"},{id:"CatDelta",title:"Cat Delta",category:"Adventure",image:chunkZWHQXIXN_cjs.c("./games/CatDelta.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/CatDelta/"},{id:"ColorRun",title:"Color Run",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/ColorRun.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/ColorRun/"},{id:"SoccerZombies",title:"Soccer vs. Zombies",category:"Tower Defense",image:chunkZWHQXIXN_cjs.c("./games/Soccer vs. Zombies.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SoccerZombies/"},{id:"MiniSoccer",title:"Mini Soccer",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/minisoccer.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/minisoccer/"},{id:"SoccerMaze",title:"Soccer Maze",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/Soccer Maze.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SoccerMaze/"},{id:"StupidArrow",title:"Stupid Arrow",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/StupidArrow.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/StupidArrow/"},{id:"ZigZag",title:"Zig Zag",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/ZigZag.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/ZigZag/"},{id:"SpikesEverywhere",title:"Spikes Everywhere",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/SpikesEverywhere.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SpikesEverywhere/"},{id:"ArrowRacer",title:"Arrow Racer",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/ArrowRacer.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/ArrowRacer/"},{id:"CircleLeap",title:"Circle Leap",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/CircleLeap.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/CircleLeap/"},{id:"ColorMatcher",title:"Color Matcher",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/ColorMatcher.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/ColorMatcher/"},{id:"EndlessMaze",title:"Endless Maze",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/EndlessMaze.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/EndlessMaze/"},{id:"SpinningAround",title:"Spinning Around",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/SpinningAround.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/SpinningAround/"},{id:"BoomBallz",title:"Boom Ballz",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/BoomBallz.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/BoomBallz/"},{id:"CubeHead",title:"Cube Head",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/CubeHead.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/CubeHead/"},{id:"CapybaraLink",title:"Capybara Link",category:"Puzzle",image:chunkZWHQXIXN_cjs.c("./games/CapybaraLink.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CapybaraLink/"},{id:"Snake2048",title:"Snake 2048",category:"Puzzle",image:chunkZWHQXIXN_cjs.c("./games/Snake2048.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Snake2048/"},{id:"FishTankFury",title:"Fish Tank Fury",category:"Puzzle",image:chunkZWHQXIXN_cjs.c("./games/FishTankFury.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/FishTankFury/"},{id:"ConnectBalls",title:"Connect Balls",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/ConnectBalls.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/ConnectBalls/"},{id:"CircularBreaker",title:"Circular Breaker",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/CircularBreaker.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/CircularBreaker/"},{id:"OneDoor",title:"One Door",category:"Arcade",image:chunkZWHQXIXN_cjs.c("./games/OneDoor.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/OneDoor/"},{id:"CatchtheFruits",title:"Catch the Fruits",category:"Casual",image:chunkZWHQXIXN_cjs.c("./games/CatchtheFruits.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CatchtheFruits/"},{id:"Falling2048",title:"Falling 2048",category:"Casual",image:chunkZWHQXIXN_cjs.c("./games/Falling2048.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/grab/Falling2048/"}],$=Z(J),V=r=>r.enable!==false&&r.isEnabled!==false,P=()=>$.filter(V);var O="https://api.playsout.com",C=3e4;function X(r){let e=String(r?.platform||"").toLowerCase();if(e==="tiktok"){let t=r.authorizationCode;if(typeof t!="string"||!t.trim())throw n("MISSING_PARAMS","authorizationCode is required for TikTok login");return {platform:e,authorizationCode:t}}if(e==="grab"||e==="eros"){let t=r;if(typeof t.platformUserId!="string"||!t.platformUserId.trim())throw n("MISSING_PARAMS","platformUserId is required for Grab/Eros login");if(typeof t.platformToken!="string"||!t.platformToken.trim())throw n("MISSING_PARAMS","platformToken is required for Grab/Eros login");if(typeof t.username!="string"||!t.username.trim())throw n("MISSING_PARAMS","username is required for Grab/Eros login");return {platform:e,platformUserId:t.platformUserId,platformToken:t.platformToken,username:t.username,inviteCode:typeof t.inviteCode=="string"?t.inviteCode:void 0}}throw n("INVALID_PARAMS","Unsupported platform. Expected grab, eros, or tiktok")}var A=null,D=null,v=null,U=null;function G(r){D=r;}function H(r){v=r;}function j(r){U=r;}function K(){if(U)try{U();}catch{}}async function Y(r){if(!v)throw K(),r instanceof y?r:n("TOKEN_EXPIRED",r);try{return await v()}catch(e){throw K(),e instanceof y?e:n("TOKEN_EXPIRED",e)}}async function M(r,e={},t,o=false,i=o){let m=t?.apiBaseUrl||O,p=r.startsWith("http")?r:`${m}${r}`,u=new AbortController,f=setTimeout(()=>u.abort(),C);try{let g=l.getJSON(c.TOKEN_DATA),S={"Content-Type":"application/json",...e.headers};o&&g?.accessToken&&!S.token&&(S.token=g.accessToken);let T=await fetch(p,{...e,signal:u.signal,headers:S});if(clearTimeout(f),!T.ok){if(T.status===401&&o&&i)return await z(r,e,t);throw n(T.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${T.status}: ${T.statusText}`)}let d=await T.json();if(d.code!==1e4){if(o&&i)return await z(r,e,t);throw n("API_ERROR",d.msg||"API request failed")}return d.data}catch(g){throw clearTimeout(f),g instanceof y?g:g instanceof Error?g.name==="AbortError"?n("TIMEOUT"):n("NETWORK_ERROR",g.message):n("UNKNOWN")}}async function z(r,e,t){await F(t);let o=t?.apiBaseUrl||O,i=r.startsWith("http")?r:`${o}${r}`,m=new AbortController,p=setTimeout(()=>m.abort(),C);try{let u=l.getJSON(c.TOKEN_DATA),f={"Content-Type":"application/json",...e.headers};u?.accessToken&&(f.token=u.accessToken);let g=await fetch(i,{...e,signal:m.signal,headers:f});if(clearTimeout(p),!g.ok)throw n(g.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${g.status}: ${g.statusText}`);let S=await g.json();if(S.code!==1e4)throw n("API_ERROR",S.msg||"API request failed");return S.data}catch(u){throw clearTimeout(p),u instanceof y?u:u instanceof Error&&u.name==="AbortError"?n("TIMEOUT"):n("NETWORK_ERROR",u?.message||"Request failed")}}async function F(r){if(A)return A;let e=(async()=>{try{let t=l.getJSON(c.TOKEN_DATA),o=Math.floor(Date.now()/1e3);if(!t?.refreshToken||t.refreshExpiresAt<=o)throw n("TOKEN_EXPIRED","Refresh token has expired");let i=r?.apiBaseUrl||O,m=new AbortController,p=setTimeout(()=>m.abort(),C);try{let u=await fetch(`${i}/platform/refreshToken`,{method:"POST",signal:m.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:t.refreshToken})});if(clearTimeout(p),!u.ok)throw u.status>=500?n("SERVER_ERROR",`HTTP ${u.status}: ${u.statusText}`):n("TOKEN_EXPIRED",`HTTP ${u.status}: ${u.statusText}`);let f=await u.json();if(f.code!==1e4||!f.data)throw n("TOKEN_EXPIRED",f.msg||"Failed to refresh token");let g=f.data;if(l.setJSON(c.TOKEN_DATA,g),D)try{D(g);}catch{}return g}catch(u){throw clearTimeout(p),u instanceof y?u:u instanceof Error&&u.name==="AbortError"?n("TIMEOUT"):n("NETWORK_ERROR",u?.message||"Refresh token failed")}}catch(t){return await Y(t)}})();A=e;try{return await e}finally{A===e&&(A=null);}}var L=class{constructor(){this.config=null;}configure(e){this.config=e;}async refreshToken(){return await F(this.config||void 0)}async loginOnly(e){let t=X(e);return await M("/platform/login",{method:"POST",body:JSON.stringify(t)},this.config??void 0)}async Login(e){let t=await this.loginOnly(e);l.setJSON(c.TOKEN_DATA,t);try{let o=await this.getUserInfo(!1);return {tokenData:t,user:o}}catch(o){throw l.remove(c.TOKEN_DATA),l.remove(c.USER),o}}async getUserInfo(e=true){return await M("/platform/user",{method:"GET"},this.config??void 0,true,e)}async getUser(){return l.getJSON(c.USER)}async validateToken(e){return !!e}},_=null;function k(){return _||(_=new L),_}var Q="https://api.playsout.com",B="zh",I=class r{constructor(){this.config=null;this._isInitialized=false;this._user=null;this._token=null;this._locale=B;this._widget=null;}clearAuthState(){let e=!!(this._token||l.get(c.TOKEN_DATA)||l.get(c.USER));return this._user=null,this._token=null,l.remove(c.TOKEN_DATA),l.remove(c.USER),l.remove(c.LOGIN_PARAMS),e}updateUser(e){this._user={userId:String(e.id),username:e.username},l.setJSON(c.USER,this._user);}saveLoginParams(e){if(e.platform==="grab"||e.platform==="eros"){l.setJSON(c.LOGIN_PARAMS,{...e});return}l.remove(c.LOGIN_PARAMS);}async performLogin(e,t){let o=k();o.configure(this.config);let i=await o.loginOnly(e);l.setJSON(c.TOKEN_DATA,i);let m=await o.getUserInfo(false);return this._token=i.accessToken,this.updateUser(m),t&&this.saveLoginParams(e),chunkZWHQXIXN_cjs.b.emit("login",{user:this._user,token:this._token}),{tokenData:i,user:m}}async recoverAuthentication(){let e=l.getJSON(c.LOGIN_PARAMS);if(!e||e.platform!=="grab"&&e.platform!=="eros")throw n("TOKEN_EXPIRED","No reusable login parameters available");return (await this.performLogin(e,false)).tokenData}handleAuthExpired(){this.clearAuthState()&&chunkZWHQXIXN_cjs.b.emit("authExpired"),this.config?.debug&&console.warn("[PlaysoutSDK] Auth expired, logged out");}static getInstance(){return r.instance||(r.instance=new r),r.instance}async init(e={}){if(this._isInitialized)throw n("ALREADY_INITIALIZED");this.config={apiBaseUrl:e.apiBaseUrl||Q,debug:e.debug||false,storage:e.storage||"localStorage",locale:e.locale||B},l.configure(this.config.storage),G(i=>{this._token=i.accessToken;}),H(()=>this.recoverAuthentication()),j(()=>{this.handleAuthExpired();});let t=l.getJSON(c.TOKEN_DATA);this._user=l.getJSON(c.USER),this._locale=l.get(c.LOCALE)||this.config.locale;let o=Math.floor(Date.now()/1e3);if(t){let i=k();if(i.configure(this.config),t.accessToken&&t.expiresAt>o?this._token=t.accessToken:await i.refreshToken(),this._token&&!this._user){let m=await i.getUserInfo();this.updateUser(m);}}else this._user&&(this._user=null,l.remove(c.USER));this._isInitialized=true,this.config.debug&&(console.log("[PlaysoutSDK] Initialized with config:",this.config),console.log("[PlaysoutSDK] Restored token:",this._token?this._token.substring(0,20)+"...":"(none)")),chunkZWHQXIXN_cjs.b.emit("initialized");}destroy(){this.config=null,this._isInitialized=false,this._user=null,this._token=null,l.clear(),chunkZWHQXIXN_cjs.b.clear();}get isInitialized(){return this._isInitialized}get isLoggedIn(){return !!(this._token&&this._user)}get user(){return this._user}get token(){return this._token}get locale(){return this._locale}get sdkConfig(){return this.config}async Login(e){this.ensureInitialized(),this.config?.debug&&console.log("[PlaysoutSDK] Login with params:",e);try{let t=await this.performLogin(e,!0);return this.config?.debug&&console.log("[PlaysoutSDK] Login success, user:",t.user),t}catch(t){throw this.clearAuthState(),t}}async getUserInfo(){if(this.ensureInitialized(),!this.isLoggedIn)throw n("NOT_LOGGED_IN","Please login first");let e=k();e.configure(this.config);let t=await e.getUserInfo();return this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo result:",t),t&&this.updateUser(t),t}logout(){this.clearAuthState(),chunkZWHQXIXN_cjs.b.emit("logout");}getToken(){return this.ensureInitialized(),this._token}getUser(){return this.ensureInitialized(),this._user}setLocale(e){if(this.ensureInitialized(),!["zh","en","ja","ko","vi","th","id","ms"].includes(e))throw n("INVALID_PARAMS",`Unsupported locale: ${e}`);this._locale=e,l.set(c.LOCALE,e),this.config?.debug&&console.log("[PlaysoutSDK] Locale changed to:",e);let t=this._widget||document.querySelector("playsout-widget");t&&t.getAttribute("locale")!==e&&t.setAttribute("locale",e),chunkZWHQXIXN_cjs.b.emit("localeChange",e);}getLocale(){return this.ensureInitialized(),this._locale}async getGames(e){this.ensureInitialized();let t=P();if(e?.category&&(t=t.filter(o=>o.category===e.category)),e?.search){let o=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(o)||i.category.toLowerCase().includes(o)||i.description&&i.description.toLowerCase().includes(o));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(o=>o.isNew).concat(t.filter(o=>!o.isNew));break;case "rating":t=t.filter(o=>o.isHot).concat(t.filter(o=>!o.isHot));break}if(e?.page&&e?.pageSize){let o=(e.page-1)*e.pageSize;t=t.slice(o,o+e.pageSize);}return t}async getCategories(){this.ensureInitialized();let e=P(),t=new Map;return e.forEach(o=>{if(!o.category)return;let i=t.get(o.category)||0;t.set(o.category,i+1);}),Array.from(t.entries()).map(([o,i])=>({id:o,name:o,count:i}))}async getGameById(e){return this.ensureInitialized(),P().find(t=>t.id===e)}mount(e,t){if(this.ensureInitialized(),typeof document>"u")throw n("FEATURE_NOT_SUPPORTED","mount requires DOM environment");let o=document.querySelector(e);if(!o)throw n("INVALID_PARAMS",`Container not found: ${e}`);let i=document.createElement("playsout-widget");i.setAttribute("locale",t?.locale||this._locale),t?.detailMode&&i.setAttribute("detail-mode",t.detailMode),this._widget=i,t?.onGameClick&&i.addEventListener("game-click",m=>{let p=m;t.onGameClick(p.detail);}),t?.onLoginRequired&&i.addEventListener("login-required",t.onLoginRequired),t?.onLocaleChange&&i.addEventListener("locale-change",m=>{let p=m;t.onLocaleChange(p.detail);}),o.appendChild(i),this.config?.debug&&console.log("[PlaysoutSDK] Widget mounted to:",e);}unmount(){let e=document.querySelector("playsout-widget");e&&e.remove(),this._widget=null;}on(e,t){return this.ensureInitialized(),chunkZWHQXIXN_cjs.b.on(e,t)}off(e,t){this.ensureInitialized(),chunkZWHQXIXN_cjs.b.off(e,t);}ensureInitialized(){if(!this._isInitialized)throw n("NOT_INITIALIZED")}},s=I.getInstance(),pe=s;typeof window<"u"&&(window.__playsout_sdk_instance=s);var ye=Object.freeze({init:s.init.bind(s),mount:s.mount.bind(s),unmount:s.unmount.bind(s),destroy:s.destroy.bind(s),Login:s.Login.bind(s),logout:s.logout.bind(s),getToken:s.getToken.bind(s),getUserInfo:s.getUserInfo.bind(s),getUser:s.getUser.bind(s),setLocale:s.setLocale.bind(s),getLocale:s.getLocale.bind(s),getGames:s.getGames.bind(s),getCategories:s.getCategories.bind(s),on:s.on.bind(s),off:s.off.bind(s),get isInitialized(){return s.isInitialized},get isLoggedIn(){return s.isLoggedIn},instance:s,PlaysoutSDKClass:I});
|
|
2
|
+
exports.a=b;exports.b=y;exports.c=l;exports.d=c;exports.e=I;exports.f=s;exports.g=pe;exports.h=ye;
|