playsout-web-sdk 1.0.1 → 1.0.3
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 +398 -0
- package/{chunk-MUMDBAO7.cjs → chunk-LU6AS3JQ.cjs} +2 -2
- package/{chunk-AJVRILLC.js → chunk-NZCZLXPA.js} +2 -2
- package/core/index.d.ts.map +1 -1
- package/core/types.d.ts +0 -1
- package/core/types.d.ts.map +1 -1
- package/index.cjs +1 -1
- package/index.global.js +224 -46
- package/index.iife.js +224 -46
- package/index.js +1 -1
- package/package.json +1 -1
- package/react/index.cjs +1 -1
- package/react/index.js +1 -1
- package/vue/index.cjs +1 -1
- package/vue/index.js +1 -1
- package/web-components/PlaysoutWidget.d.ts +9 -0
- package/web-components/PlaysoutWidget.d.ts.map +1 -1
- package/web-components/PrivyBridge.d.ts +58 -0
- package/web-components/PrivyBridge.d.ts.map +1 -0
- package/web-components/index.cjs +223 -45
- package/web-components/index.js +223 -45
package/README.md
ADDED
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
# Playsout Web SDK Integration Guide
|
|
2
|
+
|
|
3
|
+
Playsout Web SDK lets HTML, Vue 3, and React applications embed the Playsout game list widget. It also provides SDK initialization, platform login, login state, user information, locale switching, and user points display.
|
|
4
|
+
|
|
5
|
+
This guide is organized so that integrators can select their project type and use the corresponding code directly.
|
|
6
|
+
|
|
7
|
+
## Key Points
|
|
8
|
+
|
|
9
|
+
- `appId` is not required.
|
|
10
|
+
- Game details use iframe mode by default, so `detailMode` does not need to be provided.
|
|
11
|
+
- Persistent SDK image caching is currently disabled. Images use their online URLs directly.
|
|
12
|
+
- `user-points` seeds the widget's frontend gem balance. The SDK does not fetch or persist the balance through a backend.
|
|
13
|
+
- In iframe detail mode, games can request simulated gem payment through the `privy-bridge` postMessage protocol.
|
|
14
|
+
- Vue 3 projects built with Vite must configure `isCustomElement`.
|
|
15
|
+
- React projects do not need Vue's `isCustomElement` configuration. Import `playsout-web-sdk/web-components` once instead.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install playsout-web-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Choose an Integration
|
|
24
|
+
|
|
25
|
+
| Project type | Guide |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| HTML / IIFE | [HTML integration](#html-integration) |
|
|
28
|
+
| Vue 3 + Vite | [Vue 3 integration](#vue-3-integration) |
|
|
29
|
+
| React | [React integration](#react-integration) |
|
|
30
|
+
|
|
31
|
+
## Recommended Integration Flow
|
|
32
|
+
|
|
33
|
+
Use the following sequence when the application starts:
|
|
34
|
+
|
|
35
|
+
1. Initialize the SDK.
|
|
36
|
+
2. Read the current login state.
|
|
37
|
+
3. If the user is not logged in, call `Login()`.
|
|
38
|
+
4. If the user is already logged in, optionally call `getUserInfo()` when the page requires the latest user information from the backend.
|
|
39
|
+
5. Render `<playsout-widget>`.
|
|
40
|
+
6. Use `locale` to control the language and `user-points` to display the gem amount.
|
|
41
|
+
|
|
42
|
+
`Login()` already fetches and stores the user information internally, so do not call `getUserInfo()` again immediately after a successful login. The SDK also stores the token and basic user information locally. When a session is restored and the page needs the latest backend data, call `getUserInfo()` once.
|
|
43
|
+
|
|
44
|
+
## Login Parameters
|
|
45
|
+
|
|
46
|
+
Grab and Eros use the same public login method:
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
await Playsout.Login(params);
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Required parameters:
|
|
53
|
+
|
|
54
|
+
| Parameter | Description |
|
|
55
|
+
| --- | --- |
|
|
56
|
+
| `platform` | Platform identifier. Use `'grab'` or `'eros'`. |
|
|
57
|
+
| `platformUserId` | Unique user ID from the host platform. |
|
|
58
|
+
| `platformToken` | Login credential issued by the host platform for the current user. |
|
|
59
|
+
| `username` | User display name. |
|
|
60
|
+
|
|
61
|
+
Example:
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
await Playsout.Login({
|
|
65
|
+
platform: 'eros',
|
|
66
|
+
platformUserId: '10',
|
|
67
|
+
platformToken: 'platform_token',
|
|
68
|
+
username: 'TestUser',
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`platformToken` is a required, non-empty string. Playsout Web SDK does not impose any specific format or content requirements; it only validates the type and forwards the value to the backend unchanged.
|
|
73
|
+
|
|
74
|
+
## HTML Integration
|
|
75
|
+
|
|
76
|
+
Use this method for a page that does not use a Vue or React build setup.
|
|
77
|
+
|
|
78
|
+
Place the following code in `index.html`:
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<!doctype html>
|
|
82
|
+
<html lang="en">
|
|
83
|
+
<head>
|
|
84
|
+
<meta charset="UTF-8" />
|
|
85
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
86
|
+
<title>Playsout HTML Demo</title>
|
|
87
|
+
</head>
|
|
88
|
+
<body>
|
|
89
|
+
<div id="game-container"></div>
|
|
90
|
+
|
|
91
|
+
<script src="https://unpkg.com/playsout-web-sdk/index.iife.js"></script>
|
|
92
|
+
<script>
|
|
93
|
+
async function ensureLogin() {
|
|
94
|
+
if (!window.Playsout.isLoggedIn) {
|
|
95
|
+
await window.Playsout.Login({
|
|
96
|
+
platform: 'eros',
|
|
97
|
+
platformUserId: '10',
|
|
98
|
+
platformToken: 'platform_token',
|
|
99
|
+
username: 'TestUser'
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Refresh once only when the page needs the latest backend user data.
|
|
105
|
+
return window.Playsout.getUserInfo();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
async function bootstrap() {
|
|
109
|
+
await window.Playsout.init({ locale: 'zh' });
|
|
110
|
+
|
|
111
|
+
await ensureLogin();
|
|
112
|
+
|
|
113
|
+
window.Playsout.mount('#game-container');
|
|
114
|
+
|
|
115
|
+
document
|
|
116
|
+
.querySelector('playsout-widget')
|
|
117
|
+
?.setAttribute('user-points', '1000');
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
bootstrap().catch(function (error) {
|
|
121
|
+
console.error('Playsout bootstrap failed:', error);
|
|
122
|
+
});
|
|
123
|
+
</script>
|
|
124
|
+
</body>
|
|
125
|
+
</html>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Common HTML / IIFE APIs:
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
window.Playsout.init({ locale: 'zh' });
|
|
132
|
+
window.Playsout.isLoggedIn;
|
|
133
|
+
window.Playsout.Login(params);
|
|
134
|
+
window.Playsout.getUserInfo();
|
|
135
|
+
window.Playsout.getUser();
|
|
136
|
+
window.Playsout.setLocale('en');
|
|
137
|
+
window.Playsout.getLocale();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Vue 3 Integration
|
|
141
|
+
|
|
142
|
+
### 1. Configure `vite.config.js`
|
|
143
|
+
|
|
144
|
+
Add this configuration to `vite.config.js` or `vite.config.ts` in the Vue project.
|
|
145
|
+
|
|
146
|
+
It tells the Vue compiler that `<playsout-widget>` is a native Web Component rather than a Vue component.
|
|
147
|
+
|
|
148
|
+
```js
|
|
149
|
+
import { defineConfig } from 'vite';
|
|
150
|
+
import vue from '@vitejs/plugin-vue';
|
|
151
|
+
|
|
152
|
+
export default defineConfig({
|
|
153
|
+
plugins: [
|
|
154
|
+
vue({
|
|
155
|
+
template: {
|
|
156
|
+
compilerOptions: {
|
|
157
|
+
isCustomElement: (tag) => tag.startsWith('playsout-'),
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
}),
|
|
161
|
+
],
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Without this configuration, Vue may report:
|
|
166
|
+
|
|
167
|
+
```text
|
|
168
|
+
Failed to resolve component: playsout-widget
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### 2. Initialize the SDK in `src/main.js`
|
|
172
|
+
|
|
173
|
+
Place this code in the Vue entry file, usually `src/main.js` or `src/main.ts`.
|
|
174
|
+
|
|
175
|
+
```js
|
|
176
|
+
import { createApp } from 'vue';
|
|
177
|
+
import { createPlaysoutPlugin } from 'playsout-web-sdk/vue';
|
|
178
|
+
import 'playsout-web-sdk/web-components';
|
|
179
|
+
import App from './App.vue';
|
|
180
|
+
|
|
181
|
+
const app = createApp(App);
|
|
182
|
+
|
|
183
|
+
app.use(createPlaysoutPlugin({
|
|
184
|
+
config: {
|
|
185
|
+
locale: 'zh',
|
|
186
|
+
},
|
|
187
|
+
}));
|
|
188
|
+
|
|
189
|
+
app.mount('#app');
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`createPlaysoutPlugin({ config })` automatically calls `init(config)` when the plugin is installed. Vue components normally should not call `init()` again.
|
|
193
|
+
|
|
194
|
+
### 3. Use the SDK in the game page
|
|
195
|
+
|
|
196
|
+
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`.
|
|
197
|
+
|
|
198
|
+
```vue
|
|
199
|
+
<script setup>
|
|
200
|
+
import { watch } from 'vue';
|
|
201
|
+
import { usePlaysout, Playsout } from 'playsout-web-sdk/vue';
|
|
202
|
+
|
|
203
|
+
const {
|
|
204
|
+
isInitialized,
|
|
205
|
+
isLoggedIn,
|
|
206
|
+
locale,
|
|
207
|
+
Login,
|
|
208
|
+
} = usePlaysout();
|
|
209
|
+
|
|
210
|
+
async function ensureLoginAndUserInfo() {
|
|
211
|
+
if (!isLoggedIn.value) {
|
|
212
|
+
await Login({
|
|
213
|
+
platform: 'eros',
|
|
214
|
+
platformUserId: '10',
|
|
215
|
+
platformToken: 'platform_token',
|
|
216
|
+
username: 'TestUser',
|
|
217
|
+
});
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Refresh once only when the page needs the latest backend user data.
|
|
222
|
+
await Playsout.getUserInfo();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
watch(isInitialized, (initialized) => {
|
|
226
|
+
if (!initialized) return;
|
|
227
|
+
|
|
228
|
+
ensureLoginAndUserInfo().catch((error) => {
|
|
229
|
+
console.error('Playsout login flow failed:', error);
|
|
230
|
+
});
|
|
231
|
+
}, { immediate: true });
|
|
232
|
+
</script>
|
|
233
|
+
|
|
234
|
+
<template>
|
|
235
|
+
<playsout-widget
|
|
236
|
+
:locale="locale"
|
|
237
|
+
user-points="1000"
|
|
238
|
+
/>
|
|
239
|
+
</template>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
Vue notes:
|
|
243
|
+
|
|
244
|
+
- The page waits for plugin initialization, then checks the login state and runs the login flow automatically.
|
|
245
|
+
- `locale` controls the widget language.
|
|
246
|
+
- For a fixed default language, `config: { locale: 'zh' }` in the entry file is sufficient. If the application later needs dynamic locale switching, call `setLocale('en')` and bind `locale`.
|
|
247
|
+
- `user-points="1000"` seeds the widget's frontend gem balance. Iframe game payments can deduct from this in-session balance only.
|
|
248
|
+
- If the application already has a game page, place the logic in that page component.
|
|
249
|
+
|
|
250
|
+
## React Integration
|
|
251
|
+
|
|
252
|
+
### 1. Initialize the SDK in `src/main.jsx`
|
|
253
|
+
|
|
254
|
+
Place this code in the React entry file, usually `src/main.jsx` or `src/main.tsx`.
|
|
255
|
+
|
|
256
|
+
React does not require `isCustomElement` configuration. Tags containing a hyphen, such as `<playsout-widget>`, are handled as Custom Elements.
|
|
257
|
+
|
|
258
|
+
```jsx
|
|
259
|
+
import { createRoot } from 'react-dom/client';
|
|
260
|
+
import { PlaysoutProvider } from 'playsout-web-sdk/react';
|
|
261
|
+
import 'playsout-web-sdk/web-components';
|
|
262
|
+
import App from './App.jsx';
|
|
263
|
+
|
|
264
|
+
createRoot(document.getElementById('root')).render(
|
|
265
|
+
<PlaysoutProvider config={{ locale: 'zh' }}>
|
|
266
|
+
<App />
|
|
267
|
+
</PlaysoutProvider>
|
|
268
|
+
);
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
`PlaysoutProvider` automatically calls `init(config)` after receiving `config`. Page components normally should not call `init()` again.
|
|
272
|
+
|
|
273
|
+
### 2. Use the SDK in the game page
|
|
274
|
+
|
|
275
|
+
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`.
|
|
276
|
+
|
|
277
|
+
```jsx
|
|
278
|
+
import { useEffect, useRef } from 'react';
|
|
279
|
+
import { usePlaysout } from 'playsout-web-sdk/react';
|
|
280
|
+
|
|
281
|
+
export default function App() {
|
|
282
|
+
const loginFlowStarted = useRef(false);
|
|
283
|
+
const {
|
|
284
|
+
isInitialized,
|
|
285
|
+
isLoggedIn,
|
|
286
|
+
locale,
|
|
287
|
+
Login,
|
|
288
|
+
getUserInfo,
|
|
289
|
+
} = usePlaysout();
|
|
290
|
+
|
|
291
|
+
useEffect(() => {
|
|
292
|
+
if (!isInitialized || loginFlowStarted.current) return;
|
|
293
|
+
loginFlowStarted.current = true;
|
|
294
|
+
|
|
295
|
+
async function ensureLoginAndUserInfo() {
|
|
296
|
+
if (!isLoggedIn) {
|
|
297
|
+
await Login({
|
|
298
|
+
platform: 'eros',
|
|
299
|
+
platformUserId: '10',
|
|
300
|
+
platformToken: 'platform_token',
|
|
301
|
+
username: 'TestUser',
|
|
302
|
+
});
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Refresh once only when the page needs the latest backend user data.
|
|
307
|
+
await getUserInfo();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
ensureLoginAndUserInfo().catch((error) => {
|
|
311
|
+
loginFlowStarted.current = false;
|
|
312
|
+
console.error('Playsout login flow failed:', error);
|
|
313
|
+
});
|
|
314
|
+
}, [isInitialized, isLoggedIn, Login, getUserInfo]);
|
|
315
|
+
|
|
316
|
+
return (
|
|
317
|
+
<playsout-widget
|
|
318
|
+
locale={locale}
|
|
319
|
+
user-points="1000"
|
|
320
|
+
/>
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
React notes:
|
|
326
|
+
|
|
327
|
+
- `PlaysoutProvider` initializes the SDK.
|
|
328
|
+
- After Provider initialization, the page checks the login state and runs the login flow once.
|
|
329
|
+
- `usePlaysout()` provides the login state, login method, user information method, and locale APIs.
|
|
330
|
+
- For a fixed default language, `<PlaysoutProvider config={{ locale: 'zh' }}>` is sufficient. If the application later needs dynamic locale switching, call `setLocale('en')` and bind `locale`.
|
|
331
|
+
- React does not need Vue's `isCustomElement` configuration.
|
|
332
|
+
|
|
333
|
+
## Common API Reference
|
|
334
|
+
|
|
335
|
+
| Capability | HTML / IIFE | Vue 3 | React |
|
|
336
|
+
| --- | --- | --- | --- |
|
|
337
|
+
| Initialize | `Playsout.init(config)` | `createPlaysoutPlugin({ config })` | `<PlaysoutProvider config={...}>` |
|
|
338
|
+
| Check login state | `Playsout.isLoggedIn` | `isLoggedIn.value` | `isLoggedIn` |
|
|
339
|
+
| Log in | `Playsout.Login(params)` | `Login(params)` | `Login(params)` |
|
|
340
|
+
| Fetch latest user information | `Playsout.getUserInfo()` | `Playsout.getUserInfo()` | `getUserInfo()` |
|
|
341
|
+
| Read locally stored user information | `Playsout.getUser()` | `Playsout.getUser()` | `user` |
|
|
342
|
+
| Change locale | `Playsout.setLocale('en')` | `setLocale('en')` | `setLocale('en')` |
|
|
343
|
+
| Read current locale | `Playsout.getLocale()` | `locale.value` | `locale` |
|
|
344
|
+
| Log out | `Playsout.logout()` | `logout()` | `logout()` |
|
|
345
|
+
|
|
346
|
+
## Supported Locales
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
'zh' | 'en' | 'ja' | 'ko' | 'vi' | 'th' | 'id' | 'ms'
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## User Points and Simulated Payment
|
|
353
|
+
|
|
354
|
+
Pass the value through the `user-points` attribute:
|
|
355
|
+
|
|
356
|
+
```html
|
|
357
|
+
<playsout-widget user-points="1000"></playsout-widget>
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
The SDK currently does not fetch, persist, or recharge the user's gem amount through a backend. `user-points` is supplied by the host application and becomes the widget's in-session frontend balance.
|
|
361
|
+
|
|
362
|
+
When a game is opened in iframe detail mode, the widget listens for `privy-bridge` `postMessage` requests from the current iframe only. Supported methods are:
|
|
363
|
+
|
|
364
|
+
- `bridge.handshake`
|
|
365
|
+
- `auth.getUser`
|
|
366
|
+
- `pay.createOrder`
|
|
367
|
+
- `pay.request`
|
|
368
|
+
- `pay.query`
|
|
369
|
+
|
|
370
|
+
`pay.request` opens a localized confirmation dialog. Confirm deducts gems from the in-session balance and emits `gem-balance-change`; cancel and insufficient balance do not deduct gems.
|
|
371
|
+
|
|
372
|
+
## Authentication Expiration
|
|
373
|
+
|
|
374
|
+
The SDK handles an expired access token internally:
|
|
375
|
+
|
|
376
|
+
1. A protected API reports that the token is invalid.
|
|
377
|
+
2. The SDK automatically calls the refresh token endpoint.
|
|
378
|
+
3. After a successful refresh, the SDK stores the new token and retries the original request.
|
|
379
|
+
|
|
380
|
+
If the refresh token is also invalid, the SDK:
|
|
381
|
+
|
|
382
|
+
- Clears the local token.
|
|
383
|
+
- Changes the login state to logged out.
|
|
384
|
+
- Emits the `authExpired` event.
|
|
385
|
+
|
|
386
|
+
HTML / IIFE example:
|
|
387
|
+
|
|
388
|
+
```js
|
|
389
|
+
window.Playsout.on('authExpired', function () {
|
|
390
|
+
// Get a new platform credential, then call Playsout.Login() again.
|
|
391
|
+
});
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
React and Vue applications can also listen through the public `Playsout.on('authExpired', handler)` API.
|
|
395
|
+
|
|
396
|
+
## Image Loading
|
|
397
|
+
|
|
398
|
+
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.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var chunkZ2CIDSTP_cjs=require('./chunk-Z2CIDSTP.cjs');var N=(m=>(m.NOT_INITIALIZED="NOT_INITIALIZED",m.ALREADY_INITIALIZED="ALREADY_INITIALIZED",m.NOT_LOGGED_IN="NOT_LOGGED_IN",m.TOKEN_EXPIRED="TOKEN_EXPIRED",m.INVALID_TOKEN="INVALID_TOKEN",m.NETWORK_ERROR="NETWORK_ERROR",m.TIMEOUT="TIMEOUT",m.SERVER_ERROR="SERVER_ERROR",m.API_ERROR="API_ERROR",m.INVALID_PARAMS="INVALID_PARAMS",m.MISSING_PARAMS="MISSING_PARAMS",m.FEATURE_NOT_SUPPORTED="FEATURE_NOT_SUPPORTED",m.UNKNOWN="UNKNOWN",m.PAYMENT_FAILED="PAYMENT_FAILED",m.SHARE_FAILED="SHARE_FAILED",m))(N||{}),T=class extends Error{constructor(t,r,i){super(r);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.",INVALID_TOKEN:"Invalid login token. 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.",PAYMENT_FAILED:"Payment failed.",SHARE_FAILED:"Share failed."};function l(o,e){return new T(o,q[o],e)}var P="playsout_",D=class{constructor(e){this.storage=e;}get(e){try{return this.storage.getItem(P+e)}catch{return null}}set(e,t){try{this.storage.setItem(P+e,t);}catch(r){console.warn("[PlaysoutSDK] Storage set failed:",r);}}remove(e){try{this.storage.removeItem(P+e);}catch{}}clear(){try{let e=[];for(let t=0;t<this.storage.length;t++){let r=this.storage.key(t);r&&r.startsWith(P)&&e.push(r);}e.forEach(t=>this.storage.removeItem(t));}catch{}}},_=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 v(o="localStorage"){return typeof window>"u"||o==="memory"?new _:o==="sessionStorage"?new D(sessionStorage):new D(localStorage)}var S=v(),g={get:o=>S.get(o),set:(o,e)=>{S.set(o,e);},remove:o=>{S.remove(o);},clear:()=>{S.clear();},getJSON:o=>{let e=S.get(o);if(!e)return null;try{return JSON.parse(e)}catch{return null}},setJSON:(o,e)=>{S.set(o,JSON.stringify(e));},configure(o){S=v(o);}},c={TOKEN_DATA:"token_data",USER:"user",LOCALE:"locale",CONFIG:"config"};var W=o=>{if(!o)return o;try{let e=new URL(o);if(e.hostname==="games.playsout.com"){let t=e.pathname,r=t.endsWith("/"),i=/\.[a-z0-9]+$/i.test(t);!r&&!i&&(e.pathname=`${t}/`);}return e.toString()}catch{return o}},J=o=>o.map(e=>{if(!e.externalUrl)return e;let t=W(e.externalUrl);return t===e.externalUrl?e:{...e,externalUrl:t}}),Z=[{id:"BlockCrushFun",title:"Block Crush Fun",category:"Puzzle",image:chunkZ2CIDSTP_cjs.c("./games/BlockCrushFun.png"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/BlockCrushFun"},{id:"DogeSurvivors",title:"Doge Survivors",category:"Doge OS",image:chunkZ2CIDSTP_cjs.c("./games/DogeSurvivors.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeSurvivors/"},{id:"DogeMaze",title:"Doge Maze",category:"Doge OS",image:chunkZ2CIDSTP_cjs.c("./games/DogeMaze.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMaze/"},{id:"DogeMart",title:"Doge Mart",category:"Doge OS",image:chunkZ2CIDSTP_cjs.c("./games/DogeMart.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMart/"},{id:"KittyEscape",title:"Kitty Escape",category:"Puzzle",image:chunkZ2CIDSTP_cjs.c("./games/KittyEscape.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/KittyEscape/"},{id:"ProjectGarden",title:"Project: Garden",category:"Adventure",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/ProjectIDLE.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/idle/"},{id:"CulinaryStarWeb",title:"Culinary Star",category:"Casual",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/PickaxeQuest.jpg"),description:"Mining and adventure game",isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/PickaxeQuest/",apiGameId:73},{id:"MonsterSurvivors",title:"Monster Survivors",category:"Adventure",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/MushroomWarriors.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/MushroomWarriors/"},{id:"FollowThePath",title:"Follow The Path",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/FollowThePath.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FollowThePath/"},{id:"ColorRun",title:"Color Run",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ColorRun.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorRun/"},{id:"StupidArrow",title:"Stupid Arrow",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/StupidArrow.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/StupidArrow/"},{id:"ZigZag",title:"Zig Zag",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ZigZag.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ZigZag/"},{id:"SpikesEverywhere",title:"Spikes Everywhere",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/SpikesEverywhere.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpikesEverywhere/"},{id:"ArrowRacer",title:"Arrow Racer",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ArrowRacer.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ArrowRacer/"},{id:"CircleLeap",title:"Circle Leap",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/CircleLeap.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircleLeap/"},{id:"ColorMatcher",title:"Color Matcher",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ColorMatcher.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorMatcher/"},{id:"EndlessMaze",title:"Endless Maze",category:"Arcade",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/SpinningAround.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpinningAround/"},{id:"BoomBallz",title:"Boom Ballz",category:"Arcade",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/CubeHead.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CubeHead/"},{id:"CapybaraLink",title:"Capybara Link",category:"Puzzle",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/FishTankFury.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FishTankFury/"},{id:"ConnectBalls",title:"Connect Balls",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ConnectBalls.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ConnectBalls/"},{id:"CircularBreaker",title:"Circular Breaker",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/CircularBreaker.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircularBreaker/"},{id:"OneDoor",title:"One Door",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/OneDoor.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/OneDoor/"},{id:"CatchtheFruits",title:"Catch the Fruits",category:"Casual",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/Falling2048.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Falling2048/"}],x=J(Z),h=()=>x.filter(o=>o.enable);({Adventure:h().filter(o=>o.category==="Adventure"),Moba:h().filter(o=>o.category==="Moba")});var G=o=>x.find(e=>e.id===o);var K=()=>Array.from(new Set(h().map(o=>o.category)));var C="https://api.playsout.com",U=3e4,V=new Set([10010,10011,10012,10013]);function $(o){let e=String(o?.platform||"").toLowerCase();if(e==="tiktok"){let t=o.authorizationCode;if(typeof t!="string"||!t.trim())throw l("MISSING_PARAMS","authorizationCode is required for TikTok login");return {platform:e,authorizationCode:t}}if(e==="grab"||e==="eros"){let t=o;if(typeof t.platformUserId!="string"||!t.platformUserId.trim())throw l("MISSING_PARAMS","platformUserId is required for Grab/Eros login");if(typeof t.platformToken!="string"||!t.platformToken.trim())throw l("MISSING_PARAMS","platformToken is required for Grab/Eros login");return {platform:e,platformUserId:t.platformUserId,platformToken:t.platformToken,username:typeof t.username=="string"?t.username:void 0,inviteCode:typeof t.inviteCode=="string"?t.inviteCode:void 0}}throw l("INVALID_PARAMS","Unsupported platform. Expected grab, eros, or tiktok")}var A=null,L=null,w=null;function H(o){L=o;}function F(o){w=o;}async function M(o,e={},t,r=false){let i=t?.apiBaseUrl||C,s=o.startsWith("http")?o:`${i}${o}`,u=new AbortController,d=setTimeout(()=>u.abort(),U);try{let f=g.getJSON(c.TOKEN_DATA),y={"Content-Type":"application/json",...e.headers};f?.accessToken&&!y.token&&(y.token=f.accessToken);let p=await fetch(s,{...e,signal:u.signal,headers:y});if(clearTimeout(d),!p.ok){if(p.status===401&&!r)return await z(o,e,t);throw l(p.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${p.status}: ${p.statusText}`)}let I=await p.json();if(I.code!==void 0&&V.has(I.code)&&!r){if(o.includes("/platform/refreshToken"))throw l("TOKEN_EXPIRED",I.msg||"Token expired");return await z(o,e,t)}if(I.code!==0&&I.code!==1e4)throw l("API_ERROR",I.msg||"API request failed");return I.data}catch(f){throw clearTimeout(d),f instanceof T?f:f instanceof Error?f.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",f.message):l("UNKNOWN")}}async function z(o,e,t){await j(t);let r=t?.apiBaseUrl||C,i=o.startsWith("http")?o:`${r}${o}`,s=new AbortController,u=setTimeout(()=>s.abort(),U);try{let d=g.getJSON(c.TOKEN_DATA),f={"Content-Type":"application/json",...e.headers};d?.accessToken&&(f.token=d.accessToken);let y=await fetch(i,{...e,signal:s.signal,headers:f});if(clearTimeout(u),!y.ok)throw l(y.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${y.status}: ${y.statusText}`);let p=await y.json();if(p.code!==0&&p.code!==1e4)throw l("API_ERROR",p.msg||"API request failed");return p.data}catch(d){throw clearTimeout(u),d instanceof T?d:d instanceof Error&&d.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",d?.message||"Request failed")}}async function j(o){return A||(A=(async()=>{let e=g.getJSON(c.TOKEN_DATA);if(!e?.refreshToken)throw l("NOT_LOGGED_IN","No refresh token available");let t=o?.apiBaseUrl||C,r=new AbortController,i=setTimeout(()=>r.abort(),U);try{let s=await fetch(`${t}/platform/refreshToken`,{method:"POST",signal:r.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e.refreshToken})});if(clearTimeout(i),!s.ok)throw l("TOKEN_EXPIRED","Failed to refresh token");let u=await s.json();if(u.code!==0&&u.code!==1e4||!u.data)throw l("TOKEN_EXPIRED",u.msg||"Failed to refresh token");let d=u.data;if(g.setJSON(c.TOKEN_DATA,d),L)try{L(d);}catch{}return d}catch(s){if(clearTimeout(i),s instanceof T){if(w)try{w();}catch{}throw s}if(s instanceof Error&&s.name==="AbortError")throw l("TIMEOUT");if(w)try{w();}catch{}throw l("TOKEN_EXPIRED","Refresh token failed")}finally{A=null;}})(),A)}var O=class{constructor(){this.config=null;}configure(e){this.config=e;}async refreshToken(){return await j(this.config||void 0)}async getGames(e){let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return G(e)}async getCategoryNames(){return K()}async loginOnly(e){let t=$(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),r;try{r=await this.getUserInfo();}catch{}return {tokenData:t,user:r}}async getUserInfo(){return await M("/platform/user",{method:"GET"},this.config??void 0)}async getUser(){return g.getJSON(c.USER)}async validateToken(e){return !!e}},b=null;function R(){return b||(b=new O),b}var Y="https://api.playsout.com",B="zh",k=class o{constructor(){this.config=null;this._isInitialized=false;this._user=null;this._token=null;this._locale=B;this._widget=null;}static getInstance(){return o.instance||(o.instance=new o),o.instance}async init(e={}){if(this._isInitialized)throw l("ALREADY_INITIALIZED");this.config={apiBaseUrl:e.apiBaseUrl||Y,debug:e.debug||false,storage:e.storage||"localStorage",locale:e.locale||B,appId:e.appId||""},g.configure(this.config.storage),H(i=>{this._token=i.accessToken;}),F(()=>{this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),chunkZ2CIDSTP_cjs.b.emit("authExpired"),this.config?.debug&&console.warn("[PlaysoutSDK] Auth expired, logged out");});let t=g.getJSON(c.TOKEN_DATA);this._user=g.getJSON(c.USER),this._locale=g.get(c.LOCALE)||this.config.locale;let r=Math.floor(Date.now()/1e3);if(t&&t.refreshExpiresAt>r&&(this._token=t.accessToken),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)")),chunkZ2CIDSTP_cjs.b.emit("initialized"),t){let i=Math.floor(Date.now()/1e3);if(t.expiresAt-i<=300)try{let s=R();s.configure(this.config),await s.refreshToken();let u=g.getJSON(c.TOKEN_DATA);u&&(this._token=u.accessToken),this.config.debug&&console.log("[PlaysoutSDK] Token proactively refreshed at init");}catch(s){this.config.debug&&console.warn("[PlaysoutSDK] Proactive refresh failed, will retry on next request:",s);}}}destroy(){this.config=null,this._isInitialized=false,this._user=null,this._token=null,g.clear(),chunkZ2CIDSTP_cjs.b.clear();}get isInitialized(){return this._isInitialized}get isLoggedIn(){return !!this._token}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);let t=R();t.configure(this.config);let r=await t.loginOnly(e);g.setJSON(c.TOKEN_DATA,r),this.config?.debug&&console.log("[PlaysoutSDK] Token saved, expires at:",new Date(r.expiresAt*1e3).toISOString());let i;try{i=await t.getUserInfo();}catch(s){this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo failed, login still success:",s);}return this._token=r.accessToken,i&&(this._user={userId:String(i.id),username:i.username},g.setJSON(c.USER,this._user)),this.config?.debug&&console.log("[PlaysoutSDK] Login success, user:",i),chunkZ2CIDSTP_cjs.b.emit("login",{user:this._user,token:this._token}),{tokenData:r,user:i}}async getUserInfo(){if(this.ensureInitialized(),!this._token)throw l("NOT_LOGGED_IN","Please login first");let e=R();e.configure(this.config);let t=await e.getUserInfo();return this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo result:",t),t&&(this._user={userId:String(t.id),username:t.username},g.setJSON(c.USER,this._user)),t}logout(){this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),chunkZ2CIDSTP_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 l("INVALID_PARAMS",`Unsupported locale: ${e}`);this._locale=e,g.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),chunkZ2CIDSTP_cjs.b.emit("localeChange",e);}getLocale(){return this.ensureInitialized(),this._locale}async getGames(e){this.ensureInitialized();let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){this.ensureInitialized();let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return this.ensureInitialized(),h().find(t=>t.id===e)}mount(e,t){if(this.ensureInitialized(),typeof document>"u")throw l("FEATURE_NOT_SUPPORTED","mount requires DOM environment");let r=document.querySelector(e);if(!r)throw l("INVALID_PARAMS",`Container not found: ${e}`);let i=document.createElement("playsout-widget");this.config?.appId&&i.setAttribute("app-id",this.config.appId),i.setAttribute("locale",t?.locale||this._locale),i.setAttribute("theme",t?.theme||"dark"),t?.detailMode&&i.setAttribute("detail-mode",t.detailMode),this._widget=i,t?.onGameClick&&i.addEventListener("game-click",s=>{let u=s;t.onGameClick(u.detail);}),t?.onLoginRequired&&i.addEventListener("login-required",t.onLoginRequired),t?.onLocaleChange&&i.addEventListener("locale-change",s=>{let u=s;t.onLocaleChange(u.detail);}),r.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(),chunkZ2CIDSTP_cjs.b.on(e,t)}off(e,t){this.ensureInitialized(),chunkZ2CIDSTP_cjs.b.off(e,t);}ensureInitialized(){if(!this._isInitialized)throw l("NOT_INITIALIZED")}},a=k.getInstance(),he=a;typeof window<"u"&&(window.__playsout_sdk_instance=a);var Ie=Object.freeze({init:a.init.bind(a),mount:a.mount.bind(a),unmount:a.unmount.bind(a),destroy:a.destroy.bind(a),Login:a.Login.bind(a),logout:a.logout.bind(a),getToken:a.getToken.bind(a),getUserInfo:a.getUserInfo.bind(a),getUser:a.getUser.bind(a),setLocale:a.setLocale.bind(a),getLocale:a.getLocale.bind(a),getGames:a.getGames.bind(a),getCategories:a.getCategories.bind(a),on:a.on.bind(a),off:a.off.bind(a),get isInitialized(){return a.isInitialized},get isLoggedIn(){return a.isLoggedIn},instance:a,PlaysoutSDKClass:k});
|
|
2
|
-
exports.a=N;exports.b=T;exports.c=g;exports.d=c;exports.e=
|
|
1
|
+
'use strict';var chunkZ2CIDSTP_cjs=require('./chunk-Z2CIDSTP.cjs');var N=(m=>(m.NOT_INITIALIZED="NOT_INITIALIZED",m.ALREADY_INITIALIZED="ALREADY_INITIALIZED",m.NOT_LOGGED_IN="NOT_LOGGED_IN",m.TOKEN_EXPIRED="TOKEN_EXPIRED",m.INVALID_TOKEN="INVALID_TOKEN",m.NETWORK_ERROR="NETWORK_ERROR",m.TIMEOUT="TIMEOUT",m.SERVER_ERROR="SERVER_ERROR",m.API_ERROR="API_ERROR",m.INVALID_PARAMS="INVALID_PARAMS",m.MISSING_PARAMS="MISSING_PARAMS",m.FEATURE_NOT_SUPPORTED="FEATURE_NOT_SUPPORTED",m.UNKNOWN="UNKNOWN",m.PAYMENT_FAILED="PAYMENT_FAILED",m.SHARE_FAILED="SHARE_FAILED",m))(N||{}),T=class extends Error{constructor(t,r,i){super(r);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.",INVALID_TOKEN:"Invalid login token. 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.",PAYMENT_FAILED:"Payment failed.",SHARE_FAILED:"Share failed."};function l(o,e){return new T(o,q[o],e)}var k="playsout_",D=class{constructor(e){this.storage=e;}get(e){try{return this.storage.getItem(k+e)}catch{return null}}set(e,t){try{this.storage.setItem(k+e,t);}catch(r){console.warn("[PlaysoutSDK] Storage set failed:",r);}}remove(e){try{this.storage.removeItem(k+e);}catch{}}clear(){try{let e=[];for(let t=0;t<this.storage.length;t++){let r=this.storage.key(t);r&&r.startsWith(k)&&e.push(r);}e.forEach(t=>this.storage.removeItem(t));}catch{}}},_=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 v(o="localStorage"){return typeof window>"u"||o==="memory"?new _:o==="sessionStorage"?new D(sessionStorage):new D(localStorage)}var S=v(),g={get:o=>S.get(o),set:(o,e)=>{S.set(o,e);},remove:o=>{S.remove(o);},clear:()=>{S.clear();},getJSON:o=>{let e=S.get(o);if(!e)return null;try{return JSON.parse(e)}catch{return null}},setJSON:(o,e)=>{S.set(o,JSON.stringify(e));},configure(o){S=v(o);}},c={TOKEN_DATA:"token_data",USER:"user",LOCALE:"locale",CONFIG:"config"};var W=o=>{if(!o)return o;try{let e=new URL(o);if(e.hostname==="games.playsout.com"){let t=e.pathname,r=t.endsWith("/"),i=/\.[a-z0-9]+$/i.test(t);!r&&!i&&(e.pathname=`${t}/`);}return e.toString()}catch{return o}},J=o=>o.map(e=>{if(!e.externalUrl)return e;let t=W(e.externalUrl);return t===e.externalUrl?e:{...e,externalUrl:t}}),Z=[{id:"BlockCrushFun",title:"Block Crush Fun",category:"Puzzle",image:chunkZ2CIDSTP_cjs.c("./games/BlockCrushFun.png"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/BlockCrushFun"},{id:"DogeSurvivors",title:"Doge Survivors",category:"Doge OS",image:chunkZ2CIDSTP_cjs.c("./games/DogeSurvivors.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeSurvivors/"},{id:"DogeMaze",title:"Doge Maze",category:"Doge OS",image:chunkZ2CIDSTP_cjs.c("./games/DogeMaze.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMaze/"},{id:"DogeMart",title:"Doge Mart",category:"Doge OS",image:chunkZ2CIDSTP_cjs.c("./games/DogeMart.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMart/"},{id:"KittyEscape",title:"Kitty Escape",category:"Puzzle",image:chunkZ2CIDSTP_cjs.c("./games/KittyEscape.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/KittyEscape/"},{id:"ProjectGarden",title:"Project: Garden",category:"Adventure",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/ProjectIDLE.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/idle/"},{id:"CulinaryStarWeb",title:"Culinary Star",category:"Casual",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/PickaxeQuest.jpg"),description:"Mining and adventure game",isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/PickaxeQuest/",apiGameId:73},{id:"MonsterSurvivors",title:"Monster Survivors",category:"Adventure",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/MushroomWarriors.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/MushroomWarriors/"},{id:"FollowThePath",title:"Follow The Path",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/FollowThePath.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FollowThePath/"},{id:"ColorRun",title:"Color Run",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ColorRun.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorRun/"},{id:"StupidArrow",title:"Stupid Arrow",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/StupidArrow.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/StupidArrow/"},{id:"ZigZag",title:"Zig Zag",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ZigZag.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ZigZag/"},{id:"SpikesEverywhere",title:"Spikes Everywhere",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/SpikesEverywhere.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpikesEverywhere/"},{id:"ArrowRacer",title:"Arrow Racer",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ArrowRacer.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ArrowRacer/"},{id:"CircleLeap",title:"Circle Leap",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/CircleLeap.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircleLeap/"},{id:"ColorMatcher",title:"Color Matcher",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ColorMatcher.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorMatcher/"},{id:"EndlessMaze",title:"Endless Maze",category:"Arcade",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/SpinningAround.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpinningAround/"},{id:"BoomBallz",title:"Boom Ballz",category:"Arcade",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/CubeHead.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CubeHead/"},{id:"CapybaraLink",title:"Capybara Link",category:"Puzzle",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/FishTankFury.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FishTankFury/"},{id:"ConnectBalls",title:"Connect Balls",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/ConnectBalls.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ConnectBalls/"},{id:"CircularBreaker",title:"Circular Breaker",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/CircularBreaker.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircularBreaker/"},{id:"OneDoor",title:"One Door",category:"Arcade",image:chunkZ2CIDSTP_cjs.c("./games/OneDoor.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/OneDoor/"},{id:"CatchtheFruits",title:"Catch the Fruits",category:"Casual",image:chunkZ2CIDSTP_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:chunkZ2CIDSTP_cjs.c("./games/Falling2048.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Falling2048/"}],x=J(Z),h=()=>x.filter(o=>o.enable);({Adventure:h().filter(o=>o.category==="Adventure"),Moba:h().filter(o=>o.category==="Moba")});var G=o=>x.find(e=>e.id===o);var K=()=>Array.from(new Set(h().map(o=>o.category)));var C="https://api.playsout.com",U=3e4,V=new Set([10010,10011,10012,10013]);function $(o){let e=String(o?.platform||"").toLowerCase();if(e==="tiktok"){let t=o.authorizationCode;if(typeof t!="string"||!t.trim())throw l("MISSING_PARAMS","authorizationCode is required for TikTok login");return {platform:e,authorizationCode:t}}if(e==="grab"||e==="eros"){let t=o;if(typeof t.platformUserId!="string"||!t.platformUserId.trim())throw l("MISSING_PARAMS","platformUserId is required for Grab/Eros login");if(typeof t.platformToken!="string"||!t.platformToken.trim())throw l("MISSING_PARAMS","platformToken is required for Grab/Eros login");return {platform:e,platformUserId:t.platformUserId,platformToken:t.platformToken,username:typeof t.username=="string"?t.username:void 0,inviteCode:typeof t.inviteCode=="string"?t.inviteCode:void 0}}throw l("INVALID_PARAMS","Unsupported platform. Expected grab, eros, or tiktok")}var A=null,L=null,w=null;function H(o){L=o;}function F(o){w=o;}async function M(o,e={},t,r=false){let i=t?.apiBaseUrl||C,s=o.startsWith("http")?o:`${i}${o}`,u=new AbortController,d=setTimeout(()=>u.abort(),U);try{let f=g.getJSON(c.TOKEN_DATA),y={"Content-Type":"application/json",...e.headers};f?.accessToken&&!y.token&&(y.token=f.accessToken);let p=await fetch(s,{...e,signal:u.signal,headers:y});if(clearTimeout(d),!p.ok){if(p.status===401&&!r)return await z(o,e,t);throw l(p.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${p.status}: ${p.statusText}`)}let I=await p.json();if(I.code!==void 0&&V.has(I.code)&&!r){if(o.includes("/platform/refreshToken"))throw l("TOKEN_EXPIRED",I.msg||"Token expired");return await z(o,e,t)}if(I.code!==0&&I.code!==1e4)throw l("API_ERROR",I.msg||"API request failed");return I.data}catch(f){throw clearTimeout(d),f instanceof T?f:f instanceof Error?f.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",f.message):l("UNKNOWN")}}async function z(o,e,t){await j(t);let r=t?.apiBaseUrl||C,i=o.startsWith("http")?o:`${r}${o}`,s=new AbortController,u=setTimeout(()=>s.abort(),U);try{let d=g.getJSON(c.TOKEN_DATA),f={"Content-Type":"application/json",...e.headers};d?.accessToken&&(f.token=d.accessToken);let y=await fetch(i,{...e,signal:s.signal,headers:f});if(clearTimeout(u),!y.ok)throw l(y.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${y.status}: ${y.statusText}`);let p=await y.json();if(p.code!==0&&p.code!==1e4)throw l("API_ERROR",p.msg||"API request failed");return p.data}catch(d){throw clearTimeout(u),d instanceof T?d:d instanceof Error&&d.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",d?.message||"Request failed")}}async function j(o){return A||(A=(async()=>{let e=g.getJSON(c.TOKEN_DATA);if(!e?.refreshToken)throw l("NOT_LOGGED_IN","No refresh token available");let t=o?.apiBaseUrl||C,r=new AbortController,i=setTimeout(()=>r.abort(),U);try{let s=await fetch(`${t}/platform/refreshToken`,{method:"POST",signal:r.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e.refreshToken})});if(clearTimeout(i),!s.ok)throw l("TOKEN_EXPIRED","Failed to refresh token");let u=await s.json();if(u.code!==0&&u.code!==1e4||!u.data)throw l("TOKEN_EXPIRED",u.msg||"Failed to refresh token");let d=u.data;if(g.setJSON(c.TOKEN_DATA,d),L)try{L(d);}catch{}return d}catch(s){if(clearTimeout(i),s instanceof T){if(w)try{w();}catch{}throw s}if(s instanceof Error&&s.name==="AbortError")throw l("TIMEOUT");if(w)try{w();}catch{}throw l("TOKEN_EXPIRED","Refresh token failed")}finally{A=null;}})(),A)}var O=class{constructor(){this.config=null;}configure(e){this.config=e;}async refreshToken(){return await j(this.config||void 0)}async getGames(e){let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return G(e)}async getCategoryNames(){return K()}async loginOnly(e){let t=$(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),r;try{r=await this.getUserInfo();}catch{}return {tokenData:t,user:r}}async getUserInfo(){return await M("/platform/user",{method:"GET"},this.config??void 0)}async getUser(){return g.getJSON(c.USER)}async validateToken(e){return !!e}},b=null;function R(){return b||(b=new O),b}var Y="https://api.playsout.com",B="zh",P=class o{constructor(){this.config=null;this._isInitialized=false;this._user=null;this._token=null;this._locale=B;this._widget=null;}static getInstance(){return o.instance||(o.instance=new o),o.instance}async init(e={}){if(this._isInitialized)throw l("ALREADY_INITIALIZED");this.config={apiBaseUrl:e.apiBaseUrl||Y,debug:e.debug||false,storage:e.storage||"localStorage",locale:e.locale||B,appId:e.appId||""},g.configure(this.config.storage),H(i=>{this._token=i.accessToken;}),F(()=>{this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),chunkZ2CIDSTP_cjs.b.emit("authExpired"),this.config?.debug&&console.warn("[PlaysoutSDK] Auth expired, logged out");});let t=g.getJSON(c.TOKEN_DATA);this._user=g.getJSON(c.USER),this._locale=g.get(c.LOCALE)||this.config.locale;let r=Math.floor(Date.now()/1e3);if(t&&t.refreshExpiresAt>r&&(this._token=t.accessToken),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)")),chunkZ2CIDSTP_cjs.b.emit("initialized"),t){let i=Math.floor(Date.now()/1e3);if(t.expiresAt-i<=300)try{let s=R();s.configure(this.config),await s.refreshToken();let u=g.getJSON(c.TOKEN_DATA);u&&(this._token=u.accessToken),this.config.debug&&console.log("[PlaysoutSDK] Token proactively refreshed at init");}catch(s){this.config.debug&&console.warn("[PlaysoutSDK] Proactive refresh failed, will retry on next request:",s);}}}destroy(){this.config=null,this._isInitialized=false,this._user=null,this._token=null,g.clear(),chunkZ2CIDSTP_cjs.b.clear();}get isInitialized(){return this._isInitialized}get isLoggedIn(){return !!this._token}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);let t=R();t.configure(this.config);let r=await t.loginOnly(e);g.setJSON(c.TOKEN_DATA,r),this.config?.debug&&console.log("[PlaysoutSDK] Token saved, expires at:",new Date(r.expiresAt*1e3).toISOString());let i;try{i=await t.getUserInfo();}catch(s){this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo failed, login still success:",s);}return this._token=r.accessToken,i&&(this._user={userId:String(i.id),username:i.username},g.setJSON(c.USER,this._user)),this.config?.debug&&console.log("[PlaysoutSDK] Login success, user:",i),chunkZ2CIDSTP_cjs.b.emit("login",{user:this._user,token:this._token}),{tokenData:r,user:i}}async getUserInfo(){if(this.ensureInitialized(),!this._token)throw l("NOT_LOGGED_IN","Please login first");let e=R();e.configure(this.config);let t=await e.getUserInfo();return this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo result:",t),t&&(this._user={userId:String(t.id),username:t.username},g.setJSON(c.USER,this._user)),t}logout(){this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),chunkZ2CIDSTP_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 l("INVALID_PARAMS",`Unsupported locale: ${e}`);this._locale=e,g.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),chunkZ2CIDSTP_cjs.b.emit("localeChange",e);}getLocale(){return this.ensureInitialized(),this._locale}async getGames(e){this.ensureInitialized();let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){this.ensureInitialized();let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return this.ensureInitialized(),h().find(t=>t.id===e)}mount(e,t){if(this.ensureInitialized(),typeof document>"u")throw l("FEATURE_NOT_SUPPORTED","mount requires DOM environment");let r=document.querySelector(e);if(!r)throw l("INVALID_PARAMS",`Container not found: ${e}`);let i=document.createElement("playsout-widget");this.config?.appId&&i.setAttribute("app-id",this.config.appId),i.setAttribute("locale",t?.locale||this._locale),t?.detailMode&&i.setAttribute("detail-mode",t.detailMode),this._widget=i,t?.onGameClick&&i.addEventListener("game-click",s=>{let u=s;t.onGameClick(u.detail);}),t?.onLoginRequired&&i.addEventListener("login-required",t.onLoginRequired),t?.onLocaleChange&&i.addEventListener("locale-change",s=>{let u=s;t.onLocaleChange(u.detail);}),r.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(),chunkZ2CIDSTP_cjs.b.on(e,t)}off(e,t){this.ensureInitialized(),chunkZ2CIDSTP_cjs.b.off(e,t);}ensureInitialized(){if(!this._isInitialized)throw l("NOT_INITIALIZED")}},a=P.getInstance(),he=a;typeof window<"u"&&(window.__playsout_sdk_instance=a);var Ie=Object.freeze({init:a.init.bind(a),mount:a.mount.bind(a),unmount:a.unmount.bind(a),destroy:a.destroy.bind(a),Login:a.Login.bind(a),logout:a.logout.bind(a),getToken:a.getToken.bind(a),getUserInfo:a.getUserInfo.bind(a),getUser:a.getUser.bind(a),setLocale:a.setLocale.bind(a),getLocale:a.getLocale.bind(a),getGames:a.getGames.bind(a),getCategories:a.getCategories.bind(a),on:a.on.bind(a),off:a.off.bind(a),get isInitialized(){return a.isInitialized},get isLoggedIn(){return a.isLoggedIn},instance:a,PlaysoutSDKClass:P});
|
|
2
|
+
exports.a=N;exports.b=T;exports.c=g;exports.d=c;exports.e=P;exports.f=a;exports.g=he;exports.h=Ie;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {c as c$1,b as b$1}from'./chunk-EZLO3WY6.js';var N=(m=>(m.NOT_INITIALIZED="NOT_INITIALIZED",m.ALREADY_INITIALIZED="ALREADY_INITIALIZED",m.NOT_LOGGED_IN="NOT_LOGGED_IN",m.TOKEN_EXPIRED="TOKEN_EXPIRED",m.INVALID_TOKEN="INVALID_TOKEN",m.NETWORK_ERROR="NETWORK_ERROR",m.TIMEOUT="TIMEOUT",m.SERVER_ERROR="SERVER_ERROR",m.API_ERROR="API_ERROR",m.INVALID_PARAMS="INVALID_PARAMS",m.MISSING_PARAMS="MISSING_PARAMS",m.FEATURE_NOT_SUPPORTED="FEATURE_NOT_SUPPORTED",m.UNKNOWN="UNKNOWN",m.PAYMENT_FAILED="PAYMENT_FAILED",m.SHARE_FAILED="SHARE_FAILED",m))(N||{}),T=class extends Error{constructor(t,r,i){super(r);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.",INVALID_TOKEN:"Invalid login token. 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.",PAYMENT_FAILED:"Payment failed.",SHARE_FAILED:"Share failed."};function l(o,e){return new T(o,q[o],e)}var P="playsout_",D=class{constructor(e){this.storage=e;}get(e){try{return this.storage.getItem(P+e)}catch{return null}}set(e,t){try{this.storage.setItem(P+e,t);}catch(r){console.warn("[PlaysoutSDK] Storage set failed:",r);}}remove(e){try{this.storage.removeItem(P+e);}catch{}}clear(){try{let e=[];for(let t=0;t<this.storage.length;t++){let r=this.storage.key(t);r&&r.startsWith(P)&&e.push(r);}e.forEach(t=>this.storage.removeItem(t));}catch{}}},_=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 v(o="localStorage"){return typeof window>"u"||o==="memory"?new _:o==="sessionStorage"?new D(sessionStorage):new D(localStorage)}var S=v(),g={get:o=>S.get(o),set:(o,e)=>{S.set(o,e);},remove:o=>{S.remove(o);},clear:()=>{S.clear();},getJSON:o=>{let e=S.get(o);if(!e)return null;try{return JSON.parse(e)}catch{return null}},setJSON:(o,e)=>{S.set(o,JSON.stringify(e));},configure(o){S=v(o);}},c={TOKEN_DATA:"token_data",USER:"user",LOCALE:"locale",CONFIG:"config"};var W=o=>{if(!o)return o;try{let e=new URL(o);if(e.hostname==="games.playsout.com"){let t=e.pathname,r=t.endsWith("/"),i=/\.[a-z0-9]+$/i.test(t);!r&&!i&&(e.pathname=`${t}/`);}return e.toString()}catch{return o}},J=o=>o.map(e=>{if(!e.externalUrl)return e;let t=W(e.externalUrl);return t===e.externalUrl?e:{...e,externalUrl:t}}),Z=[{id:"BlockCrushFun",title:"Block Crush Fun",category:"Puzzle",image:c$1("./games/BlockCrushFun.png"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/BlockCrushFun"},{id:"DogeSurvivors",title:"Doge Survivors",category:"Doge OS",image:c$1("./games/DogeSurvivors.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeSurvivors/"},{id:"DogeMaze",title:"Doge Maze",category:"Doge OS",image:c$1("./games/DogeMaze.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMaze/"},{id:"DogeMart",title:"Doge Mart",category:"Doge OS",image:c$1("./games/DogeMart.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMart/"},{id:"KittyEscape",title:"Kitty Escape",category:"Puzzle",image:c$1("./games/KittyEscape.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/KittyEscape/"},{id:"ProjectGarden",title:"Project: Garden",category:"Adventure",image:c$1("./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:c$1("./games/ProjectIDLE.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/idle/"},{id:"CulinaryStarWeb",title:"Culinary Star",category:"Casual",image:c$1("./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:c$1("./games/PickaxeQuest.jpg"),description:"Mining and adventure game",isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/PickaxeQuest/",apiGameId:73},{id:"MonsterSurvivors",title:"Monster Survivors",category:"Adventure",image:c$1("./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:c$1("./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:c$1("./games/MushroomWarriors.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/MushroomWarriors/"},{id:"FollowThePath",title:"Follow The Path",category:"Arcade",image:c$1("./games/FollowThePath.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FollowThePath/"},{id:"ColorRun",title:"Color Run",category:"Arcade",image:c$1("./games/ColorRun.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorRun/"},{id:"StupidArrow",title:"Stupid Arrow",category:"Arcade",image:c$1("./games/StupidArrow.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/StupidArrow/"},{id:"ZigZag",title:"Zig Zag",category:"Arcade",image:c$1("./games/ZigZag.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ZigZag/"},{id:"SpikesEverywhere",title:"Spikes Everywhere",category:"Arcade",image:c$1("./games/SpikesEverywhere.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpikesEverywhere/"},{id:"ArrowRacer",title:"Arrow Racer",category:"Arcade",image:c$1("./games/ArrowRacer.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ArrowRacer/"},{id:"CircleLeap",title:"Circle Leap",category:"Arcade",image:c$1("./games/CircleLeap.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircleLeap/"},{id:"ColorMatcher",title:"Color Matcher",category:"Arcade",image:c$1("./games/ColorMatcher.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorMatcher/"},{id:"EndlessMaze",title:"Endless Maze",category:"Arcade",image:c$1("./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:c$1("./games/SpinningAround.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpinningAround/"},{id:"BoomBallz",title:"Boom Ballz",category:"Arcade",image:c$1("./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:c$1("./games/CubeHead.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CubeHead/"},{id:"CapybaraLink",title:"Capybara Link",category:"Puzzle",image:c$1("./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:c$1("./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:c$1("./games/FishTankFury.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FishTankFury/"},{id:"ConnectBalls",title:"Connect Balls",category:"Arcade",image:c$1("./games/ConnectBalls.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ConnectBalls/"},{id:"CircularBreaker",title:"Circular Breaker",category:"Arcade",image:c$1("./games/CircularBreaker.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircularBreaker/"},{id:"OneDoor",title:"One Door",category:"Arcade",image:c$1("./games/OneDoor.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/OneDoor/"},{id:"CatchtheFruits",title:"Catch the Fruits",category:"Casual",image:c$1("./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:c$1("./games/Falling2048.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Falling2048/"}],x=J(Z),h=()=>x.filter(o=>o.enable);({Adventure:h().filter(o=>o.category==="Adventure"),Moba:h().filter(o=>o.category==="Moba")});var G=o=>x.find(e=>e.id===o);var K=()=>Array.from(new Set(h().map(o=>o.category)));var C="https://api.playsout.com",U=3e4,V=new Set([10010,10011,10012,10013]);function $(o){let e=String(o?.platform||"").toLowerCase();if(e==="tiktok"){let t=o.authorizationCode;if(typeof t!="string"||!t.trim())throw l("MISSING_PARAMS","authorizationCode is required for TikTok login");return {platform:e,authorizationCode:t}}if(e==="grab"||e==="eros"){let t=o;if(typeof t.platformUserId!="string"||!t.platformUserId.trim())throw l("MISSING_PARAMS","platformUserId is required for Grab/Eros login");if(typeof t.platformToken!="string"||!t.platformToken.trim())throw l("MISSING_PARAMS","platformToken is required for Grab/Eros login");return {platform:e,platformUserId:t.platformUserId,platformToken:t.platformToken,username:typeof t.username=="string"?t.username:void 0,inviteCode:typeof t.inviteCode=="string"?t.inviteCode:void 0}}throw l("INVALID_PARAMS","Unsupported platform. Expected grab, eros, or tiktok")}var A=null,L=null,w=null;function H(o){L=o;}function F(o){w=o;}async function M(o,e={},t,r=false){let i=t?.apiBaseUrl||C,s=o.startsWith("http")?o:`${i}${o}`,u=new AbortController,d=setTimeout(()=>u.abort(),U);try{let f=g.getJSON(c.TOKEN_DATA),y={"Content-Type":"application/json",...e.headers};f?.accessToken&&!y.token&&(y.token=f.accessToken);let p=await fetch(s,{...e,signal:u.signal,headers:y});if(clearTimeout(d),!p.ok){if(p.status===401&&!r)return await z(o,e,t);throw l(p.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${p.status}: ${p.statusText}`)}let I=await p.json();if(I.code!==void 0&&V.has(I.code)&&!r){if(o.includes("/platform/refreshToken"))throw l("TOKEN_EXPIRED",I.msg||"Token expired");return await z(o,e,t)}if(I.code!==0&&I.code!==1e4)throw l("API_ERROR",I.msg||"API request failed");return I.data}catch(f){throw clearTimeout(d),f instanceof T?f:f instanceof Error?f.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",f.message):l("UNKNOWN")}}async function z(o,e,t){await j(t);let r=t?.apiBaseUrl||C,i=o.startsWith("http")?o:`${r}${o}`,s=new AbortController,u=setTimeout(()=>s.abort(),U);try{let d=g.getJSON(c.TOKEN_DATA),f={"Content-Type":"application/json",...e.headers};d?.accessToken&&(f.token=d.accessToken);let y=await fetch(i,{...e,signal:s.signal,headers:f});if(clearTimeout(u),!y.ok)throw l(y.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${y.status}: ${y.statusText}`);let p=await y.json();if(p.code!==0&&p.code!==1e4)throw l("API_ERROR",p.msg||"API request failed");return p.data}catch(d){throw clearTimeout(u),d instanceof T?d:d instanceof Error&&d.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",d?.message||"Request failed")}}async function j(o){return A||(A=(async()=>{let e=g.getJSON(c.TOKEN_DATA);if(!e?.refreshToken)throw l("NOT_LOGGED_IN","No refresh token available");let t=o?.apiBaseUrl||C,r=new AbortController,i=setTimeout(()=>r.abort(),U);try{let s=await fetch(`${t}/platform/refreshToken`,{method:"POST",signal:r.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e.refreshToken})});if(clearTimeout(i),!s.ok)throw l("TOKEN_EXPIRED","Failed to refresh token");let u=await s.json();if(u.code!==0&&u.code!==1e4||!u.data)throw l("TOKEN_EXPIRED",u.msg||"Failed to refresh token");let d=u.data;if(g.setJSON(c.TOKEN_DATA,d),L)try{L(d);}catch{}return d}catch(s){if(clearTimeout(i),s instanceof T){if(w)try{w();}catch{}throw s}if(s instanceof Error&&s.name==="AbortError")throw l("TIMEOUT");if(w)try{w();}catch{}throw l("TOKEN_EXPIRED","Refresh token failed")}finally{A=null;}})(),A)}var O=class{constructor(){this.config=null;}configure(e){this.config=e;}async refreshToken(){return await j(this.config||void 0)}async getGames(e){let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return G(e)}async getCategoryNames(){return K()}async loginOnly(e){let t=$(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),r;try{r=await this.getUserInfo();}catch{}return {tokenData:t,user:r}}async getUserInfo(){return await M("/platform/user",{method:"GET"},this.config??void 0)}async getUser(){return g.getJSON(c.USER)}async validateToken(e){return !!e}},b=null;function R(){return b||(b=new O),b}var Y="https://api.playsout.com",B="zh",k=class o{constructor(){this.config=null;this._isInitialized=false;this._user=null;this._token=null;this._locale=B;this._widget=null;}static getInstance(){return o.instance||(o.instance=new o),o.instance}async init(e={}){if(this._isInitialized)throw l("ALREADY_INITIALIZED");this.config={apiBaseUrl:e.apiBaseUrl||Y,debug:e.debug||false,storage:e.storage||"localStorage",locale:e.locale||B,appId:e.appId||""},g.configure(this.config.storage),H(i=>{this._token=i.accessToken;}),F(()=>{this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),b$1.emit("authExpired"),this.config?.debug&&console.warn("[PlaysoutSDK] Auth expired, logged out");});let t=g.getJSON(c.TOKEN_DATA);this._user=g.getJSON(c.USER),this._locale=g.get(c.LOCALE)||this.config.locale;let r=Math.floor(Date.now()/1e3);if(t&&t.refreshExpiresAt>r&&(this._token=t.accessToken),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)")),b$1.emit("initialized"),t){let i=Math.floor(Date.now()/1e3);if(t.expiresAt-i<=300)try{let s=R();s.configure(this.config),await s.refreshToken();let u=g.getJSON(c.TOKEN_DATA);u&&(this._token=u.accessToken),this.config.debug&&console.log("[PlaysoutSDK] Token proactively refreshed at init");}catch(s){this.config.debug&&console.warn("[PlaysoutSDK] Proactive refresh failed, will retry on next request:",s);}}}destroy(){this.config=null,this._isInitialized=false,this._user=null,this._token=null,g.clear(),b$1.clear();}get isInitialized(){return this._isInitialized}get isLoggedIn(){return !!this._token}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);let t=R();t.configure(this.config);let r=await t.loginOnly(e);g.setJSON(c.TOKEN_DATA,r),this.config?.debug&&console.log("[PlaysoutSDK] Token saved, expires at:",new Date(r.expiresAt*1e3).toISOString());let i;try{i=await t.getUserInfo();}catch(s){this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo failed, login still success:",s);}return this._token=r.accessToken,i&&(this._user={userId:String(i.id),username:i.username},g.setJSON(c.USER,this._user)),this.config?.debug&&console.log("[PlaysoutSDK] Login success, user:",i),b$1.emit("login",{user:this._user,token:this._token}),{tokenData:r,user:i}}async getUserInfo(){if(this.ensureInitialized(),!this._token)throw l("NOT_LOGGED_IN","Please login first");let e=R();e.configure(this.config);let t=await e.getUserInfo();return this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo result:",t),t&&(this._user={userId:String(t.id),username:t.username},g.setJSON(c.USER,this._user)),t}logout(){this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),b$1.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 l("INVALID_PARAMS",`Unsupported locale: ${e}`);this._locale=e,g.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),b$1.emit("localeChange",e);}getLocale(){return this.ensureInitialized(),this._locale}async getGames(e){this.ensureInitialized();let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){this.ensureInitialized();let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return this.ensureInitialized(),h().find(t=>t.id===e)}mount(e,t){if(this.ensureInitialized(),typeof document>"u")throw l("FEATURE_NOT_SUPPORTED","mount requires DOM environment");let r=document.querySelector(e);if(!r)throw l("INVALID_PARAMS",`Container not found: ${e}`);let i=document.createElement("playsout-widget");this.config?.appId&&i.setAttribute("app-id",this.config.appId),i.setAttribute("locale",t?.locale||this._locale),i.setAttribute("theme",t?.theme||"dark"),t?.detailMode&&i.setAttribute("detail-mode",t.detailMode),this._widget=i,t?.onGameClick&&i.addEventListener("game-click",s=>{let u=s;t.onGameClick(u.detail);}),t?.onLoginRequired&&i.addEventListener("login-required",t.onLoginRequired),t?.onLocaleChange&&i.addEventListener("locale-change",s=>{let u=s;t.onLocaleChange(u.detail);}),r.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(),b$1.on(e,t)}off(e,t){this.ensureInitialized(),b$1.off(e,t);}ensureInitialized(){if(!this._isInitialized)throw l("NOT_INITIALIZED")}},a=k.getInstance(),he=a;typeof window<"u"&&(window.__playsout_sdk_instance=a);var Ie=Object.freeze({init:a.init.bind(a),mount:a.mount.bind(a),unmount:a.unmount.bind(a),destroy:a.destroy.bind(a),Login:a.Login.bind(a),logout:a.logout.bind(a),getToken:a.getToken.bind(a),getUserInfo:a.getUserInfo.bind(a),getUser:a.getUser.bind(a),setLocale:a.setLocale.bind(a),getLocale:a.getLocale.bind(a),getGames:a.getGames.bind(a),getCategories:a.getCategories.bind(a),on:a.on.bind(a),off:a.off.bind(a),get isInitialized(){return a.isInitialized},get isLoggedIn(){return a.isLoggedIn},instance:a,PlaysoutSDKClass:k});
|
|
2
|
-
export{N as a,T as b,g as c,c as d,
|
|
1
|
+
import {c as c$1,b as b$1}from'./chunk-EZLO3WY6.js';var N=(m=>(m.NOT_INITIALIZED="NOT_INITIALIZED",m.ALREADY_INITIALIZED="ALREADY_INITIALIZED",m.NOT_LOGGED_IN="NOT_LOGGED_IN",m.TOKEN_EXPIRED="TOKEN_EXPIRED",m.INVALID_TOKEN="INVALID_TOKEN",m.NETWORK_ERROR="NETWORK_ERROR",m.TIMEOUT="TIMEOUT",m.SERVER_ERROR="SERVER_ERROR",m.API_ERROR="API_ERROR",m.INVALID_PARAMS="INVALID_PARAMS",m.MISSING_PARAMS="MISSING_PARAMS",m.FEATURE_NOT_SUPPORTED="FEATURE_NOT_SUPPORTED",m.UNKNOWN="UNKNOWN",m.PAYMENT_FAILED="PAYMENT_FAILED",m.SHARE_FAILED="SHARE_FAILED",m))(N||{}),T=class extends Error{constructor(t,r,i){super(r);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.",INVALID_TOKEN:"Invalid login token. 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.",PAYMENT_FAILED:"Payment failed.",SHARE_FAILED:"Share failed."};function l(o,e){return new T(o,q[o],e)}var k="playsout_",D=class{constructor(e){this.storage=e;}get(e){try{return this.storage.getItem(k+e)}catch{return null}}set(e,t){try{this.storage.setItem(k+e,t);}catch(r){console.warn("[PlaysoutSDK] Storage set failed:",r);}}remove(e){try{this.storage.removeItem(k+e);}catch{}}clear(){try{let e=[];for(let t=0;t<this.storage.length;t++){let r=this.storage.key(t);r&&r.startsWith(k)&&e.push(r);}e.forEach(t=>this.storage.removeItem(t));}catch{}}},_=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 v(o="localStorage"){return typeof window>"u"||o==="memory"?new _:o==="sessionStorage"?new D(sessionStorage):new D(localStorage)}var S=v(),g={get:o=>S.get(o),set:(o,e)=>{S.set(o,e);},remove:o=>{S.remove(o);},clear:()=>{S.clear();},getJSON:o=>{let e=S.get(o);if(!e)return null;try{return JSON.parse(e)}catch{return null}},setJSON:(o,e)=>{S.set(o,JSON.stringify(e));},configure(o){S=v(o);}},c={TOKEN_DATA:"token_data",USER:"user",LOCALE:"locale",CONFIG:"config"};var W=o=>{if(!o)return o;try{let e=new URL(o);if(e.hostname==="games.playsout.com"){let t=e.pathname,r=t.endsWith("/"),i=/\.[a-z0-9]+$/i.test(t);!r&&!i&&(e.pathname=`${t}/`);}return e.toString()}catch{return o}},J=o=>o.map(e=>{if(!e.externalUrl)return e;let t=W(e.externalUrl);return t===e.externalUrl?e:{...e,externalUrl:t}}),Z=[{id:"BlockCrushFun",title:"Block Crush Fun",category:"Puzzle",image:c$1("./games/BlockCrushFun.png"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/BlockCrushFun"},{id:"DogeSurvivors",title:"Doge Survivors",category:"Doge OS",image:c$1("./games/DogeSurvivors.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeSurvivors/"},{id:"DogeMaze",title:"Doge Maze",category:"Doge OS",image:c$1("./games/DogeMaze.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMaze/"},{id:"DogeMart",title:"Doge Mart",category:"Doge OS",image:c$1("./games/DogeMart.jpg"),isNew:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Doge/DogeMart/"},{id:"KittyEscape",title:"Kitty Escape",category:"Puzzle",image:c$1("./games/KittyEscape.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/KittyEscape/"},{id:"ProjectGarden",title:"Project: Garden",category:"Adventure",image:c$1("./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:c$1("./games/ProjectIDLE.jpg"),isNew:true,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/idle/"},{id:"CulinaryStarWeb",title:"Culinary Star",category:"Casual",image:c$1("./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:c$1("./games/PickaxeQuest.jpg"),description:"Mining and adventure game",isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/PickaxeQuest/",apiGameId:73},{id:"MonsterSurvivors",title:"Monster Survivors",category:"Adventure",image:c$1("./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:c$1("./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:c$1("./games/MushroomWarriors.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/MushroomWarriors/"},{id:"FollowThePath",title:"Follow The Path",category:"Arcade",image:c$1("./games/FollowThePath.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FollowThePath/"},{id:"ColorRun",title:"Color Run",category:"Arcade",image:c$1("./games/ColorRun.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorRun/"},{id:"StupidArrow",title:"Stupid Arrow",category:"Arcade",image:c$1("./games/StupidArrow.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/StupidArrow/"},{id:"ZigZag",title:"Zig Zag",category:"Arcade",image:c$1("./games/ZigZag.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ZigZag/"},{id:"SpikesEverywhere",title:"Spikes Everywhere",category:"Arcade",image:c$1("./games/SpikesEverywhere.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpikesEverywhere/"},{id:"ArrowRacer",title:"Arrow Racer",category:"Arcade",image:c$1("./games/ArrowRacer.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ArrowRacer/"},{id:"CircleLeap",title:"Circle Leap",category:"Arcade",image:c$1("./games/CircleLeap.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircleLeap/"},{id:"ColorMatcher",title:"Color Matcher",category:"Arcade",image:c$1("./games/ColorMatcher.jpg"),isNew:false,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ColorMatcher/"},{id:"EndlessMaze",title:"Endless Maze",category:"Arcade",image:c$1("./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:c$1("./games/SpinningAround.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/SpinningAround/"},{id:"BoomBallz",title:"Boom Ballz",category:"Arcade",image:c$1("./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:c$1("./games/CubeHead.jpg"),isNew:false,isHot:true,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CubeHead/"},{id:"CapybaraLink",title:"Capybara Link",category:"Puzzle",image:c$1("./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:c$1("./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:c$1("./games/FishTankFury.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/FishTankFury/"},{id:"ConnectBalls",title:"Connect Balls",category:"Arcade",image:c$1("./games/ConnectBalls.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/ConnectBalls/"},{id:"CircularBreaker",title:"Circular Breaker",category:"Arcade",image:c$1("./games/CircularBreaker.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/CircularBreaker/"},{id:"OneDoor",title:"One Door",category:"Arcade",image:c$1("./games/OneDoor.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/OneDoor/"},{id:"CatchtheFruits",title:"Catch the Fruits",category:"Casual",image:c$1("./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:c$1("./games/Falling2048.jpg"),isNew:true,isHot:false,enable:true,orientation:"portrait",externalUrl:"https://games.playsout.com/Falling2048/"}],x=J(Z),h=()=>x.filter(o=>o.enable);({Adventure:h().filter(o=>o.category==="Adventure"),Moba:h().filter(o=>o.category==="Moba")});var G=o=>x.find(e=>e.id===o);var K=()=>Array.from(new Set(h().map(o=>o.category)));var C="https://api.playsout.com",U=3e4,V=new Set([10010,10011,10012,10013]);function $(o){let e=String(o?.platform||"").toLowerCase();if(e==="tiktok"){let t=o.authorizationCode;if(typeof t!="string"||!t.trim())throw l("MISSING_PARAMS","authorizationCode is required for TikTok login");return {platform:e,authorizationCode:t}}if(e==="grab"||e==="eros"){let t=o;if(typeof t.platformUserId!="string"||!t.platformUserId.trim())throw l("MISSING_PARAMS","platformUserId is required for Grab/Eros login");if(typeof t.platformToken!="string"||!t.platformToken.trim())throw l("MISSING_PARAMS","platformToken is required for Grab/Eros login");return {platform:e,platformUserId:t.platformUserId,platformToken:t.platformToken,username:typeof t.username=="string"?t.username:void 0,inviteCode:typeof t.inviteCode=="string"?t.inviteCode:void 0}}throw l("INVALID_PARAMS","Unsupported platform. Expected grab, eros, or tiktok")}var A=null,L=null,w=null;function H(o){L=o;}function F(o){w=o;}async function M(o,e={},t,r=false){let i=t?.apiBaseUrl||C,s=o.startsWith("http")?o:`${i}${o}`,u=new AbortController,d=setTimeout(()=>u.abort(),U);try{let f=g.getJSON(c.TOKEN_DATA),y={"Content-Type":"application/json",...e.headers};f?.accessToken&&!y.token&&(y.token=f.accessToken);let p=await fetch(s,{...e,signal:u.signal,headers:y});if(clearTimeout(d),!p.ok){if(p.status===401&&!r)return await z(o,e,t);throw l(p.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${p.status}: ${p.statusText}`)}let I=await p.json();if(I.code!==void 0&&V.has(I.code)&&!r){if(o.includes("/platform/refreshToken"))throw l("TOKEN_EXPIRED",I.msg||"Token expired");return await z(o,e,t)}if(I.code!==0&&I.code!==1e4)throw l("API_ERROR",I.msg||"API request failed");return I.data}catch(f){throw clearTimeout(d),f instanceof T?f:f instanceof Error?f.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",f.message):l("UNKNOWN")}}async function z(o,e,t){await j(t);let r=t?.apiBaseUrl||C,i=o.startsWith("http")?o:`${r}${o}`,s=new AbortController,u=setTimeout(()=>s.abort(),U);try{let d=g.getJSON(c.TOKEN_DATA),f={"Content-Type":"application/json",...e.headers};d?.accessToken&&(f.token=d.accessToken);let y=await fetch(i,{...e,signal:s.signal,headers:f});if(clearTimeout(u),!y.ok)throw l(y.status>=500?"SERVER_ERROR":"API_ERROR",`HTTP ${y.status}: ${y.statusText}`);let p=await y.json();if(p.code!==0&&p.code!==1e4)throw l("API_ERROR",p.msg||"API request failed");return p.data}catch(d){throw clearTimeout(u),d instanceof T?d:d instanceof Error&&d.name==="AbortError"?l("TIMEOUT"):l("NETWORK_ERROR",d?.message||"Request failed")}}async function j(o){return A||(A=(async()=>{let e=g.getJSON(c.TOKEN_DATA);if(!e?.refreshToken)throw l("NOT_LOGGED_IN","No refresh token available");let t=o?.apiBaseUrl||C,r=new AbortController,i=setTimeout(()=>r.abort(),U);try{let s=await fetch(`${t}/platform/refreshToken`,{method:"POST",signal:r.signal,headers:{"Content-Type":"application/json"},body:JSON.stringify({refreshToken:e.refreshToken})});if(clearTimeout(i),!s.ok)throw l("TOKEN_EXPIRED","Failed to refresh token");let u=await s.json();if(u.code!==0&&u.code!==1e4||!u.data)throw l("TOKEN_EXPIRED",u.msg||"Failed to refresh token");let d=u.data;if(g.setJSON(c.TOKEN_DATA,d),L)try{L(d);}catch{}return d}catch(s){if(clearTimeout(i),s instanceof T){if(w)try{w();}catch{}throw s}if(s instanceof Error&&s.name==="AbortError")throw l("TIMEOUT");if(w)try{w();}catch{}throw l("TOKEN_EXPIRED","Refresh token failed")}finally{A=null;}})(),A)}var O=class{constructor(){this.config=null;}configure(e){this.config=e;}async refreshToken(){return await j(this.config||void 0)}async getGames(e){let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return G(e)}async getCategoryNames(){return K()}async loginOnly(e){let t=$(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),r;try{r=await this.getUserInfo();}catch{}return {tokenData:t,user:r}}async getUserInfo(){return await M("/platform/user",{method:"GET"},this.config??void 0)}async getUser(){return g.getJSON(c.USER)}async validateToken(e){return !!e}},b=null;function R(){return b||(b=new O),b}var Y="https://api.playsout.com",B="zh",P=class o{constructor(){this.config=null;this._isInitialized=false;this._user=null;this._token=null;this._locale=B;this._widget=null;}static getInstance(){return o.instance||(o.instance=new o),o.instance}async init(e={}){if(this._isInitialized)throw l("ALREADY_INITIALIZED");this.config={apiBaseUrl:e.apiBaseUrl||Y,debug:e.debug||false,storage:e.storage||"localStorage",locale:e.locale||B,appId:e.appId||""},g.configure(this.config.storage),H(i=>{this._token=i.accessToken;}),F(()=>{this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),b$1.emit("authExpired"),this.config?.debug&&console.warn("[PlaysoutSDK] Auth expired, logged out");});let t=g.getJSON(c.TOKEN_DATA);this._user=g.getJSON(c.USER),this._locale=g.get(c.LOCALE)||this.config.locale;let r=Math.floor(Date.now()/1e3);if(t&&t.refreshExpiresAt>r&&(this._token=t.accessToken),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)")),b$1.emit("initialized"),t){let i=Math.floor(Date.now()/1e3);if(t.expiresAt-i<=300)try{let s=R();s.configure(this.config),await s.refreshToken();let u=g.getJSON(c.TOKEN_DATA);u&&(this._token=u.accessToken),this.config.debug&&console.log("[PlaysoutSDK] Token proactively refreshed at init");}catch(s){this.config.debug&&console.warn("[PlaysoutSDK] Proactive refresh failed, will retry on next request:",s);}}}destroy(){this.config=null,this._isInitialized=false,this._user=null,this._token=null,g.clear(),b$1.clear();}get isInitialized(){return this._isInitialized}get isLoggedIn(){return !!this._token}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);let t=R();t.configure(this.config);let r=await t.loginOnly(e);g.setJSON(c.TOKEN_DATA,r),this.config?.debug&&console.log("[PlaysoutSDK] Token saved, expires at:",new Date(r.expiresAt*1e3).toISOString());let i;try{i=await t.getUserInfo();}catch(s){this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo failed, login still success:",s);}return this._token=r.accessToken,i&&(this._user={userId:String(i.id),username:i.username},g.setJSON(c.USER,this._user)),this.config?.debug&&console.log("[PlaysoutSDK] Login success, user:",i),b$1.emit("login",{user:this._user,token:this._token}),{tokenData:r,user:i}}async getUserInfo(){if(this.ensureInitialized(),!this._token)throw l("NOT_LOGGED_IN","Please login first");let e=R();e.configure(this.config);let t=await e.getUserInfo();return this.config?.debug&&console.log("[PlaysoutSDK] getUserInfo result:",t),t&&(this._user={userId:String(t.id),username:t.username},g.setJSON(c.USER,this._user)),t}logout(){this._user=null,this._token=null,g.remove(c.TOKEN_DATA),g.remove(c.USER),b$1.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 l("INVALID_PARAMS",`Unsupported locale: ${e}`);this._locale=e,g.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),b$1.emit("localeChange",e);}getLocale(){return this.ensureInitialized(),this._locale}async getGames(e){this.ensureInitialized();let t=h();if(e?.category&&(t=t.filter(r=>r.category===e.category)),e?.search){let r=e.search.toLowerCase();t=t.filter(i=>i.title.toLowerCase().includes(r)||i.category.toLowerCase().includes(r)||i.description&&i.description.toLowerCase().includes(r));}if(e?.sortBy)switch(e.sortBy){case "newest":t=t.filter(r=>r.isNew).concat(t.filter(r=>!r.isNew));break;case "rating":t=t.filter(r=>r.isHot).concat(t.filter(r=>!r.isHot));break}if(e?.page&&e?.pageSize){let r=(e.page-1)*e.pageSize;t=t.slice(r,r+e.pageSize);}return t}async getCategories(){this.ensureInitialized();let e=h(),t=new Map;return e.forEach(r=>{let i=t.get(r.category)||0;t.set(r.category,i+1);}),Array.from(t.entries()).map(([r,i],s)=>({id:`category_${s}`,name:r,count:i}))}async getGameById(e){return this.ensureInitialized(),h().find(t=>t.id===e)}mount(e,t){if(this.ensureInitialized(),typeof document>"u")throw l("FEATURE_NOT_SUPPORTED","mount requires DOM environment");let r=document.querySelector(e);if(!r)throw l("INVALID_PARAMS",`Container not found: ${e}`);let i=document.createElement("playsout-widget");this.config?.appId&&i.setAttribute("app-id",this.config.appId),i.setAttribute("locale",t?.locale||this._locale),t?.detailMode&&i.setAttribute("detail-mode",t.detailMode),this._widget=i,t?.onGameClick&&i.addEventListener("game-click",s=>{let u=s;t.onGameClick(u.detail);}),t?.onLoginRequired&&i.addEventListener("login-required",t.onLoginRequired),t?.onLocaleChange&&i.addEventListener("locale-change",s=>{let u=s;t.onLocaleChange(u.detail);}),r.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(),b$1.on(e,t)}off(e,t){this.ensureInitialized(),b$1.off(e,t);}ensureInitialized(){if(!this._isInitialized)throw l("NOT_INITIALIZED")}},a=P.getInstance(),he=a;typeof window<"u"&&(window.__playsout_sdk_instance=a);var Ie=Object.freeze({init:a.init.bind(a),mount:a.mount.bind(a),unmount:a.unmount.bind(a),destroy:a.destroy.bind(a),Login:a.Login.bind(a),logout:a.logout.bind(a),getToken:a.getToken.bind(a),getUserInfo:a.getUserInfo.bind(a),getUser:a.getUser.bind(a),setLocale:a.setLocale.bind(a),getLocale:a.getLocale.bind(a),getGames:a.getGames.bind(a),getCategories:a.getCategories.bind(a),on:a.on.bind(a),off:a.off.bind(a),get isInitialized(){return a.isInitialized},get isLoggedIn(){return a.isLoggedIn},instance:a,PlaysoutSDKClass:P});
|
|
2
|
+
export{N as a,T as b,g as c,c as d,P as e,a as f,he as g,Ie as h};
|
package/core/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,SAAS,CAAC;AAejB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAc;IAErC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAmC;IAGlD,OAAO,CAAC,OAAO,CAA4B;IAE3C,OAAO;IAKP,MAAM,CAAC,WAAW,IAAI,WAAW;IAW3B,IAAI,CAAC,MAAM,GAAE,SAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoFjD,OAAO,IAAI,IAAI;IAYf,IAAI,aAAa,IAAI,OAAO,CAE3B;IAGD,IAAI,UAAU,IAAI,OAAO,CAExB;IAGD,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAEtB;IAGD,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAGD,IAAI,MAAM,IAAI,eAAe,CAE5B;IAGD,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAEhC;IAQK,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAuDhE,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC;IA8B9C,MAAM,IAAI,IAAI;IAYd,QAAQ,IAAI,MAAM,GAAG,IAAI;IAQzB,OAAO,IAAI,IAAI,GAAG,IAAI;IAiBtB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IA0BxC,SAAS,IAAI,eAAe;IAYtB,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IA8ClD,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAqBpC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAYxD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,SAAS,EACT,eAAe,EACf,IAAI,EACJ,IAAI,EACJ,QAAQ,EACR,cAAc,EACd,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,EAEjB,MAAM,SAAS,CAAC;AAejB,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAc;IAErC,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAmC;IAGlD,OAAO,CAAC,OAAO,CAA4B;IAE3C,OAAO;IAKP,MAAM,CAAC,WAAW,IAAI,WAAW;IAW3B,IAAI,CAAC,MAAM,GAAE,SAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoFjD,OAAO,IAAI,IAAI;IAYf,IAAI,aAAa,IAAI,OAAO,CAE3B;IAGD,IAAI,UAAU,IAAI,OAAO,CAExB;IAGD,IAAI,IAAI,IAAI,IAAI,GAAG,IAAI,CAEtB;IAGD,IAAI,KAAK,IAAI,MAAM,GAAG,IAAI,CAEzB;IAGD,IAAI,MAAM,IAAI,eAAe,CAE5B;IAGD,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAEhC;IAQK,KAAK,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IAuDhE,WAAW,IAAI,OAAO,CAAC,gBAAgB,CAAC;IA8B9C,MAAM,IAAI,IAAI;IAYd,QAAQ,IAAI,MAAM,GAAG,IAAI;IAQzB,OAAO,IAAI,IAAI,GAAG,IAAI;IAiBtB,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI;IA0BxC,SAAS,IAAI,eAAe;IAYtB,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IA8ClD,aAAa,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IAqBpC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAYxD,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IAsDrD,OAAO,IAAI,IAAI;IAaf,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAQvE,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI;IAO3D,OAAO,CAAC,iBAAiB;CAK1B;AAMD,eAAO,MAAM,GAAG,aAA4B,CAAC;AAG7C,eAAe,GAAG,CAAC"}
|