@viceme-ai/sdk-poc 0.1.7-poc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +71 -0
  2. package/dist/bootstrap.min.js +2 -0
  3. package/dist/bootstrap.min.js.map +1 -0
  4. package/dist/chunks/client-DgGpWHrf.js +959 -0
  5. package/dist/chunks/client-DgGpWHrf.js.map +1 -0
  6. package/dist/chunks/version-mxCwx8AO.js +51 -0
  7. package/dist/chunks/version-mxCwx8AO.js.map +1 -0
  8. package/dist/core/build-endpoints.d.ts +9 -0
  9. package/dist/core/build-endpoints.d.ts.map +1 -0
  10. package/dist/core/capabilities.d.ts +63 -0
  11. package/dist/core/capabilities.d.ts.map +1 -0
  12. package/dist/core/client.d.ts +65 -0
  13. package/dist/core/client.d.ts.map +1 -0
  14. package/dist/core/config.d.ts +32 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/errors.d.ts +37 -0
  17. package/dist/core/errors.d.ts.map +1 -0
  18. package/dist/core/lifecycle.d.ts +25 -0
  19. package/dist/core/lifecycle.d.ts.map +1 -0
  20. package/dist/core/presentation.d.ts +32 -0
  21. package/dist/core/presentation.d.ts.map +1 -0
  22. package/dist/danmaku/anchor.d.ts +14 -0
  23. package/dist/danmaku/anchor.d.ts.map +1 -0
  24. package/dist/danmaku/index.d.ts +8 -0
  25. package/dist/danmaku/index.d.ts.map +1 -0
  26. package/dist/danmaku/mount.d.ts +4 -0
  27. package/dist/danmaku/mount.d.ts.map +1 -0
  28. package/dist/danmaku.js +143 -0
  29. package/dist/danmaku.js.map +1 -0
  30. package/dist/generated/public-contract.d.ts +700 -0
  31. package/dist/generated/public-contract.d.ts.map +1 -0
  32. package/dist/index.d.ts +28 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +128 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/loader/attributes.d.ts +21 -0
  37. package/dist/loader/attributes.d.ts.map +1 -0
  38. package/dist/loader/auto-loader.d.ts +51 -0
  39. package/dist/loader/auto-loader.d.ts.map +1 -0
  40. package/dist/loader/bootstrap.d.ts +1 -0
  41. package/dist/loader/bootstrap.d.ts.map +1 -0
  42. package/dist/loader/events.d.ts +45 -0
  43. package/dist/loader/events.d.ts.map +1 -0
  44. package/dist/loader/main.d.ts +11 -0
  45. package/dist/loader/main.d.ts.map +1 -0
  46. package/dist/loader/mount-handle.d.ts +25 -0
  47. package/dist/loader/mount-handle.d.ts.map +1 -0
  48. package/dist/loader/registry.d.ts +42 -0
  49. package/dist/loader/registry.d.ts.map +1 -0
  50. package/dist/manifest.json +52 -0
  51. package/dist/session/session.d.ts +67 -0
  52. package/dist/session/session.d.ts.map +1 -0
  53. package/dist/testing/test-adapter.d.ts +59 -0
  54. package/dist/testing/test-adapter.d.ts.map +1 -0
  55. package/dist/testing.d.ts +9 -0
  56. package/dist/testing.d.ts.map +1 -0
  57. package/dist/testing.js +75 -0
  58. package/dist/testing.js.map +1 -0
  59. package/dist/transport/transport.d.ts +44 -0
  60. package/dist/transport/transport.d.ts.map +1 -0
  61. package/dist/version.d.ts +10 -0
  62. package/dist/version.d.ts.map +1 -0
  63. package/dist/viceme.min.js +2 -0
  64. package/dist/viceme.min.js.map +1 -0
  65. package/package.json +63 -0
@@ -0,0 +1,959 @@
1
+ import { a as Y, c as C, V as S, b as D, S as X, A as ee } from "./version-mxCwx8AO.js";
2
+ const te = /* @__PURE__ */ new Set(["cn", "global"]), ae = {
3
+ cn: Y.cn,
4
+ global: Y.global
5
+ };
6
+ function ve(t) {
7
+ return ae[t];
8
+ }
9
+ function ie(t) {
10
+ return typeof t == "string" && /^wrk_[A-Za-z0-9_-]{4,124}$/.test(t);
11
+ }
12
+ function ne(t) {
13
+ return typeof t == "string" && te.has(t);
14
+ }
15
+ function be(t) {
16
+ if (typeof t != "object" || t === null)
17
+ throw C("createViceMe expects a configuration object.");
18
+ const e = t, a = /* @__PURE__ */ new Set(["workKey", "region", "signal"]);
19
+ for (const i of Object.keys(e))
20
+ if (!a.has(i))
21
+ throw C(`Unknown configuration field "${i}".`);
22
+ if (!ie(e.workKey))
23
+ throw C('Configuration field "workKey" must be a public work key ("wrk_…").');
24
+ if (!ne(e.region))
25
+ throw C('Configuration field "region" must be "cn" or "global".');
26
+ if (e.signal !== void 0 && !(e.signal instanceof AbortSignal))
27
+ throw C('Configuration field "signal" must be an AbortSignal.');
28
+ return {
29
+ workKey: e.workKey,
30
+ region: e.region,
31
+ signal: e.signal
32
+ };
33
+ }
34
+ const oe = {
35
+ CREATED: ["INITIALIZING", "DESTROYED"],
36
+ INITIALIZING: ["READY", "FAILED", "DESTROYED"],
37
+ READY: ["DEGRADED", "DESTROYED"],
38
+ DEGRADED: ["DESTROYED"],
39
+ FAILED: ["INITIALIZING", "DESTROYED"],
40
+ DESTROYED: []
41
+ };
42
+ class re {
43
+ #e = "CREATED";
44
+ #t = /* @__PURE__ */ new Set();
45
+ get state() {
46
+ return this.#e;
47
+ }
48
+ get destroyed() {
49
+ return this.#e === "DESTROYED";
50
+ }
51
+ transition(e) {
52
+ if (e !== this.#e) {
53
+ if (!oe[this.#e].includes(e))
54
+ throw new S({
55
+ code: "INTERNAL_ERROR",
56
+ message: `Illegal lifecycle transition ${this.#e} -> ${e}.`,
57
+ retryable: !1
58
+ });
59
+ this.#e = e;
60
+ for (const a of this.#t) a(e);
61
+ }
62
+ }
63
+ /** Any operation on a destroyed client must fail closed with this guard. */
64
+ assertAlive() {
65
+ if (this.destroyed) throw D();
66
+ }
67
+ subscribe(e) {
68
+ return this.#t.add(e), () => {
69
+ this.#t.delete(e);
70
+ };
71
+ }
72
+ clearListeners() {
73
+ this.#t.clear();
74
+ }
75
+ }
76
+ function se(t, e) {
77
+ if (typeof t != "object" || t === null)
78
+ throw N();
79
+ const a = t, i = a.work;
80
+ if (typeof i != "object" || i === null || typeof i.key != "string" || !Array.isArray(i.capabilities) || !i.capabilities.every((g) => typeof g == "string"))
81
+ throw N();
82
+ if (i.key !== e)
83
+ throw new S({
84
+ code: "WORK_NOT_FOUND",
85
+ message: "Work-session response did not match the requested work key.",
86
+ retryable: !1
87
+ });
88
+ const d = {
89
+ work: {
90
+ key: i.key,
91
+ capabilities: i.capabilities
92
+ }
93
+ };
94
+ return typeof a.token == "string" && (d.token = a.token), typeof a.expiresAt == "number" && (d.expiresAt = a.expiresAt), d;
95
+ }
96
+ function N() {
97
+ return new S({
98
+ code: "INTERNAL_ERROR",
99
+ message: "Malformed work-session response.",
100
+ retryable: !0
101
+ });
102
+ }
103
+ class ce {
104
+ #e;
105
+ #t;
106
+ #a;
107
+ #i;
108
+ constructor(e) {
109
+ this.#e = e, this.#t = e.now ?? (() => Date.now());
110
+ }
111
+ get snapshot() {
112
+ return this.#a;
113
+ }
114
+ /** True when the cached snapshot's server-provided expiry has passed. */
115
+ #n() {
116
+ const e = this.#a?.expiresAt;
117
+ return e !== void 0 && e <= this.#t();
118
+ }
119
+ /**
120
+ * Establish (or return the established) public session.
121
+ *
122
+ * A cached snapshot is reused only while it is unexpired; an expired
123
+ * snapshot is dropped and re-authenticated. Concurrent callers share one
124
+ * in-flight request (single flight).
125
+ */
126
+ establish() {
127
+ if (this.#a) {
128
+ if (!this.#n()) return Promise.resolve(this.#a);
129
+ this.#a = void 0;
130
+ }
131
+ return this.#i ??= this.#e.transport.request({
132
+ method: "POST",
133
+ path: "/v1/public/v1/work-sessions",
134
+ body: { workKey: this.#e.workKey },
135
+ signal: this.#e.signal,
136
+ timeoutMs: this.#e.timeoutMs
137
+ }).then((e) => {
138
+ const a = se(e.body, this.#e.workKey);
139
+ return this.#a = a, a;
140
+ }).finally(() => {
141
+ this.#i = void 0;
142
+ }), this.#i;
143
+ }
144
+ async request(e) {
145
+ const a = await this.establish();
146
+ if (!a.token) throw N();
147
+ return this.#e.transport.request({
148
+ ...e,
149
+ authorization: a.token,
150
+ signal: this.#e.signal
151
+ });
152
+ }
153
+ authenticate(e) {
154
+ if (!this.#a) throw N();
155
+ this.#a = {
156
+ ...this.#a,
157
+ token: e.token,
158
+ expiresAt: e.expiresAt,
159
+ user: e.user
160
+ };
161
+ }
162
+ async signOut() {
163
+ this.invalidate(), await this.establish();
164
+ }
165
+ /** Drop the token; next `establish()` re-authenticates. */
166
+ invalidate() {
167
+ this.#a = void 0;
168
+ }
169
+ /** Hard cleanup: forget the token and pending work. */
170
+ destroy() {
171
+ this.invalidate(), this.#i = void 0;
172
+ }
173
+ }
174
+ const z = "viceme-access-layer";
175
+ function de(t) {
176
+ switch (t) {
177
+ case "SIGN_IN":
178
+ return {
179
+ title: "登录后继续",
180
+ description: "登录 ViceMe 后即可继续检查此功能权限。",
181
+ label: "微信登录"
182
+ };
183
+ case "FOLLOW":
184
+ return {
185
+ title: "",
186
+ description: "",
187
+ label: "关注"
188
+ };
189
+ case "CHECKOUT":
190
+ return {
191
+ title: "购买后解锁",
192
+ description: "完成支付后即可继续使用此功能。",
193
+ label: "重新打开"
194
+ };
195
+ }
196
+ }
197
+ function le() {
198
+ if (customElements.get(z)) return;
199
+ class t extends HTMLElement {
200
+ interaction;
201
+ connectedCallback() {
202
+ const a = de(this.interaction.action), i = this.attachShadow({ mode: "open" });
203
+ i.innerHTML = `
204
+ <style>
205
+ :host {
206
+ position: fixed;
207
+ inset: 0;
208
+ z-index: 2147483000;
209
+ display: grid;
210
+ align-items: end;
211
+ color: #18181b;
212
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
213
+ font-size: 16px;
214
+ line-height: 1.5;
215
+ }
216
+ [data-viceme='backdrop'] {
217
+ position: absolute;
218
+ inset: 0;
219
+ border: 0;
220
+ border-radius: 0;
221
+ background: rgb(0 0 0 / 56%);
222
+ }
223
+ [data-viceme='panel'] {
224
+ position: relative;
225
+ box-sizing: border-box;
226
+ display: flex;
227
+ width: 100%;
228
+ max-height: min(78dvh, 36rem);
229
+ flex-direction: column;
230
+ overflow: auto;
231
+ border-radius: 1.25rem 1.25rem 0 0;
232
+ background: #ffffff;
233
+ color: #18181b;
234
+ padding: 1rem 1.25rem calc(1.25rem + env(safe-area-inset-bottom));
235
+ box-shadow: 0 -1rem 3rem rgb(0 0 0 / 18%);
236
+ }
237
+ [data-viceme='header'] {
238
+ display: flex;
239
+ align-items: center;
240
+ }
241
+ [data-viceme='title'] {
242
+ margin: 0;
243
+ font-size: 1.125rem;
244
+ font-weight: 700;
245
+ }
246
+ [data-viceme='content'] { display: flex; min-height: 0; flex: 1; flex-direction: column; }
247
+ [data-viceme='description'] { margin: 0.75rem 0 1.25rem; color: #71717a; line-height: 1.6; }
248
+ [data-viceme='profile'] {
249
+ display: none;
250
+ margin: 0 0 1.25rem;
251
+ border: 1px solid #e4e4e7;
252
+ border-radius: 1rem;
253
+ padding: 1.5rem;
254
+ background: #ffffff;
255
+ box-shadow: 0 0.75rem 2rem rgb(0 0 0 / 6%);
256
+ text-align: center;
257
+ }
258
+ [data-viceme='profile'][data-visible='true'] { display: block; }
259
+ [data-viceme='avatar'] {
260
+ display: block;
261
+ width: 5.5rem;
262
+ height: 5.5rem;
263
+ margin: 0 auto 1rem;
264
+ border-radius: 999px;
265
+ object-fit: cover;
266
+ background: #f4f4f5;
267
+ }
268
+ [data-viceme='avatar-fallback'] {
269
+ display: grid;
270
+ width: 5.5rem;
271
+ height: 5.5rem;
272
+ margin: 0 auto 1rem;
273
+ place-items: center;
274
+ border-radius: 999px;
275
+ background: #f4f4f5;
276
+ color: #18181b;
277
+ font-size: 2rem;
278
+ font-weight: 700;
279
+ }
280
+ [data-viceme='avatar'][hidden], [data-viceme='avatar-fallback'][hidden] { display: none; }
281
+ [data-viceme='profile-name'] { margin: 0; font-size: 1.375rem; font-weight: 700; }
282
+ [data-viceme='profile-description'] { margin: 0.25rem 0 0; color: #71717a; }
283
+ [data-viceme='panel'][data-action='FOLLOW'] { min-height: 18rem; }
284
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='header'],
285
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='description'] { display: none; }
286
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='profile'][data-visible='true'] {
287
+ display: flex;
288
+ align-items: center;
289
+ gap: 0.875rem;
290
+ margin: 0;
291
+ border: 0;
292
+ padding: 0;
293
+ background: transparent;
294
+ box-shadow: none;
295
+ text-align: left;
296
+ }
297
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='avatar'],
298
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='avatar-fallback'] {
299
+ width: 3.25rem;
300
+ height: 3.25rem;
301
+ margin: 0;
302
+ flex: 0 0 3.25rem;
303
+ font-size: 1.25rem;
304
+ }
305
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='profile-name'] {
306
+ font-size: 1.125rem;
307
+ }
308
+ [data-viceme='panel'][data-action='FOLLOW'] [data-viceme='profile-description'] {
309
+ display: none;
310
+ }
311
+ [data-viceme='actions'] {
312
+ display: flex;
313
+ justify-content: flex-end;
314
+ gap: 0.75rem;
315
+ margin-top: auto;
316
+ padding-top: 0.5rem;
317
+ }
318
+ [data-viceme='phone-form'] {
319
+ display: none;
320
+ min-height: 0;
321
+ flex: 1;
322
+ flex-direction: column;
323
+ gap: 0.875rem;
324
+ padding-top: 1rem;
325
+ }
326
+ [data-viceme='panel'][data-phone='true'] [data-viceme='description'],
327
+ [data-viceme='panel'][data-phone='true'] [data-viceme='profile'],
328
+ [data-viceme='panel'][data-phone='true'] > [data-viceme='content'] > [data-viceme='actions'] { display: none; }
329
+ [data-viceme='panel'][data-phone='true'] [data-viceme='phone-form'] { display: flex; }
330
+ [data-viceme='field'] { display: grid; gap: 0.375rem; }
331
+ [data-viceme='field-label'] { color: #3f3f46; font-size: 0.875rem; font-weight: 600; }
332
+ [data-viceme='input'] {
333
+ box-sizing: border-box;
334
+ width: 100%;
335
+ min-height: 2.75rem;
336
+ border: 1px solid #d4d4d8;
337
+ border-radius: 0.75rem;
338
+ padding: 0.625rem 0.75rem;
339
+ background: #ffffff;
340
+ color: #18181b;
341
+ font: 400 1rem/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
342
+ }
343
+ [data-viceme='input']:focus { border-color: #18181b; outline: 2px solid #18181b; outline-offset: 2px; }
344
+ [data-viceme='code-row'] { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 0.625rem; }
345
+ [data-viceme='send-code'] { min-width: 7.5rem; border: 1px solid #18181b; background: #ffffff; color: #18181b; }
346
+ [data-viceme='phone-hint'] { margin: 0; color: #71717a; font-size: 0.75rem; }
347
+ button {
348
+ min-height: 2.75rem;
349
+ border-radius: 0.75rem;
350
+ padding: 0.625rem 1rem;
351
+ font: 600 1rem/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
352
+ cursor: pointer;
353
+ }
354
+ button:focus-visible, iframe:focus-visible { outline: 2px solid #18181b; outline-offset: 2px; }
355
+ [data-viceme='action'] {
356
+ width: min(11rem, 48%);
357
+ border: 1px solid #18181b;
358
+ background: #18181b;
359
+ color: #ffffff;
360
+ }
361
+ [data-viceme='secondary-action'] {
362
+ width: min(11rem, 48%);
363
+ border: 1px solid #18181b;
364
+ background: #ffffff;
365
+ color: #18181b;
366
+ }
367
+ [data-viceme='secondary-action']:hover { background: #f4f4f5; }
368
+ [data-viceme='action']:hover { background: #3f3f46; border-color: #3f3f46; }
369
+ [data-viceme='actions'][data-single='true'] [data-viceme='action'] { width: 100%; }
370
+ button:disabled { cursor: wait; opacity: 0.5; }
371
+ button[hidden] { display: none; }
372
+ [data-viceme='error'] { min-height: 1.25rem; margin: 0 0 0.75rem; color: #b91c1c; font-size: 0.875rem; }
373
+ [data-viceme='frame'] {
374
+ display: none;
375
+ width: 100%;
376
+ height: min(72dvh, 42rem);
377
+ border: 0;
378
+ border-radius: 0.75rem;
379
+ background: #ffffff;
380
+ }
381
+ [data-viceme='panel'][data-frame='true'] { max-height: 92dvh; }
382
+ [data-viceme='panel'][data-frame='true'] [data-viceme='content'] { display: none; }
383
+ [data-viceme='panel'][data-frame='true'] [data-viceme='frame'] { display: block; margin-top: 0.75rem; }
384
+ [data-viceme='panel'][data-action='SIGN_IN'][data-frame='true'] [data-viceme='frame'] {
385
+ height: min(62dvh, 31rem);
386
+ }
387
+ @media (min-width: 48rem) {
388
+ :host { place-items: center; padding: 1.5rem; }
389
+ [data-viceme='panel'] {
390
+ width: min(28rem, 100%);
391
+ min-height: 22rem;
392
+ border-radius: 1.25rem;
393
+ padding: 1.25rem;
394
+ box-shadow: 0 1.5rem 4rem rgb(0 0 0 / 24%);
395
+ }
396
+ [data-viceme='panel'][data-action='FOLLOW'] { min-height: 16rem; }
397
+ [data-viceme='panel'][data-frame='true'] { width: min(52rem, 100%); }
398
+ [data-viceme='panel'][data-action='SIGN_IN'][data-frame='true'] { width: min(30rem, 100%); }
399
+ }
400
+ @media (prefers-reduced-motion: no-preference) {
401
+ [data-viceme='panel'] { animation: viceme-enter 160ms ease-out; }
402
+ @keyframes viceme-enter { from { opacity: 0; transform: translateY(1rem); } }
403
+ }
404
+ </style>
405
+ <button data-viceme="backdrop" type="button" tabindex="-1" aria-label="关闭"></button>
406
+ <section data-viceme="panel" role="dialog" aria-modal="true" aria-labelledby="viceme-layer-title">
407
+ <div data-viceme="header">
408
+ <h2 data-viceme="title" id="viceme-layer-title"></h2>
409
+ </div>
410
+ <div data-viceme="content">
411
+ <p data-viceme="description"></p>
412
+ <section data-viceme="profile" aria-label="关注对象">
413
+ <img data-viceme="avatar" hidden />
414
+ <span data-viceme="avatar-fallback" aria-hidden="true"></span>
415
+ <p data-viceme="profile-name"></p>
416
+ <p data-viceme="profile-description"></p>
417
+ </section>
418
+ <p data-viceme="error" role="alert" aria-live="polite"></p>
419
+ <div data-viceme="actions">
420
+ <button data-viceme="secondary-action" data-viceme-cancel type="button">取消</button>
421
+ <button data-viceme="secondary-action" data-viceme-phone-action type="button">手机号登录</button>
422
+ <button data-viceme="action" type="button"></button>
423
+ </div>
424
+ <form data-viceme="phone-form">
425
+ <label data-viceme="field">
426
+ <span data-viceme="field-label">手机号</span>
427
+ <input data-viceme="input" data-viceme-phone type="tel" inputmode="numeric" autocomplete="tel" maxlength="11" placeholder="请输入中国大陆手机号" />
428
+ </label>
429
+ <label data-viceme="field">
430
+ <span data-viceme="field-label">验证码</span>
431
+ <span data-viceme="code-row">
432
+ <input data-viceme="input" data-viceme-code type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" placeholder="6 位验证码" />
433
+ <button data-viceme="send-code" type="button">获取验证码</button>
434
+ </span>
435
+ </label>
436
+ <p data-viceme="phone-hint">未注册的手机号验证后将自动创建 ViceMe 账号。</p>
437
+ <div data-viceme="actions">
438
+ <button data-viceme="secondary-action" data-viceme-phone-back type="button">返回</button>
439
+ <button data-viceme="action" data-viceme-phone-submit type="submit">登录</button>
440
+ </div>
441
+ </form>
442
+ </div>
443
+ <iframe data-viceme="frame" title="" referrerpolicy="no-referrer" allow="payment"></iframe>
444
+ </section>
445
+ `;
446
+ const d = i.querySelector("[data-viceme='panel']");
447
+ d.dataset.action = this.interaction.action;
448
+ const g = i.querySelector("[data-viceme='title']"), q = i.querySelector("[data-viceme='description']");
449
+ g.textContent = a.title, q.textContent = a.description;
450
+ const l = i.querySelector("[data-viceme='action']"), R = l.parentElement, k = i.querySelector("[data-viceme-cancel]"), A = i.querySelector("[data-viceme-phone-action]"), G = i.querySelector("[data-viceme='backdrop']"), n = i.querySelector("[data-viceme='error']"), o = i.querySelector("[data-viceme='frame']"), s = i.querySelector("[data-viceme='profile']"), r = i.querySelector("[data-viceme='avatar']"), c = i.querySelector("[data-viceme='avatar-fallback']"), y = i.querySelector("[data-viceme='profile-name']"), O = i.querySelector(
451
+ "[data-viceme='profile-description']"
452
+ ), I = i.querySelector("[data-viceme='phone-form']"), v = i.querySelector("[data-viceme-phone]"), E = i.querySelector("[data-viceme-code]"), f = i.querySelector("[data-viceme='send-code']"), w = i.querySelector("[data-viceme-phone-back]"), h = i.querySelector("[data-viceme-phone-submit]");
453
+ l.textContent = a.label, l.hidden = this.interaction.action === "CHECKOUT", k.hidden = this.interaction.action !== "FOLLOW", A.hidden = !this.interaction.phoneAuth, R.dataset.single = String(k.hidden && A.hidden);
454
+ const Q = a.label;
455
+ o.title = a.title;
456
+ const x = this.interaction.followTarget;
457
+ x && (d.removeAttribute("aria-labelledby"), d.setAttribute("aria-label", `关注 ${x.displayName}`), s.dataset.visible = "true", y.textContent = x.displayName, O.textContent = "", c.textContent = x.displayName.trim().slice(0, 1) || "V", x.avatarUrl && (r.src = x.avatarUrl, r.alt = `${x.displayName}的头像`, r.hidden = !1, c.hidden = !0));
458
+ let L = null, T = null;
459
+ const _ = () => {
460
+ T !== null && window.clearInterval(T), T = null;
461
+ }, F = (m) => {
462
+ _(), this.dispatchEvent(new CustomEvent("viceme:access-layer-close", { detail: m }));
463
+ }, M = () => {
464
+ L?.cancel(), F("dismissed");
465
+ };
466
+ G.addEventListener("click", M), k.addEventListener("click", M), this.addEventListener("keydown", (m) => {
467
+ if (m.key === "Escape" && M(), m.key === "Tab") {
468
+ if (m.preventDefault(), L) {
469
+ o.focus();
470
+ return;
471
+ }
472
+ const p = (d.dataset.phone === "true" ? [v, E, f, w, h] : [
473
+ ...k.hidden ? [] : [k],
474
+ ...A.hidden ? [] : [A],
475
+ ...l.hidden ? [] : [l]
476
+ ]).filter((j) => !j.disabled && !j.hidden);
477
+ if (p.length === 0) return;
478
+ const Z = p.indexOf(
479
+ i.activeElement
480
+ ), J = m.shiftKey ? -1 : 1;
481
+ p[(Z + J + p.length) % p.length]?.focus();
482
+ }
483
+ }), v.addEventListener("input", () => {
484
+ v.value = v.value.replace(/\D/g, "").slice(0, 11);
485
+ }), E.addEventListener("input", () => {
486
+ E.value = E.value.replace(/\D/g, "").slice(0, 6);
487
+ }), A.addEventListener("click", () => {
488
+ d.dataset.phone = "true", g.textContent = "手机号登录", n.textContent = "", v.focus();
489
+ }), w.addEventListener("click", () => {
490
+ d.dataset.phone = "false", g.textContent = a.title, n.textContent = "", A.focus();
491
+ }), f.addEventListener("click", async () => {
492
+ const m = v.value;
493
+ if (!/^1[3-9]\d{9}$/.test(m)) {
494
+ n.textContent = "请输入正确的中国大陆手机号。", v.focus();
495
+ return;
496
+ }
497
+ f.disabled = !0, f.textContent = "发送中…", n.textContent = "";
498
+ try {
499
+ let p = (await this.interaction.phoneAuth.sendCode(m)).retryAfterSeconds;
500
+ f.textContent = `${p} 秒后重试`, _(), T = window.setInterval(() => {
501
+ if (p -= 1, p <= 0) {
502
+ _(), f.disabled = !1, f.textContent = "重新获取";
503
+ return;
504
+ }
505
+ f.textContent = `${p} 秒后重试`;
506
+ }, 1e3), E.focus();
507
+ } catch {
508
+ f.disabled = !1, f.textContent = "获取验证码", n.textContent = "验证码发送失败,请稍后重试。";
509
+ }
510
+ }), I.addEventListener("submit", async (m) => {
511
+ m.preventDefault();
512
+ const U = v.value, p = E.value;
513
+ if (!/^1[3-9]\d{9}$/.test(U) || !/^\d{6}$/.test(p)) {
514
+ n.textContent = "请输入正确的手机号和 6 位验证码。";
515
+ return;
516
+ }
517
+ h.disabled = !0, h.textContent = "登录中…", n.textContent = "";
518
+ try {
519
+ await this.interaction.phoneAuth.signIn(U, p), F("acted");
520
+ } catch {
521
+ h.disabled = !1, h.textContent = "登录", n.textContent = "手机号或验证码不正确,请重试。";
522
+ }
523
+ });
524
+ const H = async () => {
525
+ l.disabled = !0, l.setAttribute("aria-busy", "true"), l.textContent = "正在打开…", n.textContent = "";
526
+ try {
527
+ const m = await this.interaction.perform();
528
+ m.type === "frame" && (L = m, d.dataset.frame = "true", o.src = m.url, o.focus(), await m.completion), F("acted");
529
+ } catch {
530
+ L?.cancel(), L = null, d.dataset.frame = "false", o.removeAttribute("src"), n.textContent = "操作未完成,请重试。", l.hidden = !1, l.disabled = !1, l.removeAttribute("aria-busy"), l.textContent = Q, l.focus();
531
+ }
532
+ };
533
+ l.addEventListener("click", H), this.interaction.action === "CHECKOUT" ? queueMicrotask(() => {
534
+ H();
535
+ }) : queueMicrotask(() => l.focus());
536
+ }
537
+ }
538
+ customElements.define(z, t);
539
+ }
540
+ const P = async (t) => {
541
+ if (typeof document > "u" || typeof customElements > "u")
542
+ return "dismissed";
543
+ le();
544
+ const e = document.createElement(z);
545
+ e.interaction = t;
546
+ const a = document.documentElement.style.overflow, i = document.activeElement instanceof HTMLElement ? document.activeElement : null;
547
+ document.documentElement.style.overflow = "hidden", document.body.append(e);
548
+ try {
549
+ return await new Promise((d) => {
550
+ e.addEventListener(
551
+ "viceme:access-layer-close",
552
+ (g) => d(g.detail),
553
+ { once: !0 }
554
+ );
555
+ });
556
+ } finally {
557
+ e.remove(), document.documentElement.style.overflow = a, i?.focus();
558
+ }
559
+ };
560
+ function b(t) {
561
+ if (typeof t != "object" || t === null) throw u();
562
+ return t;
563
+ }
564
+ function u() {
565
+ return new S({
566
+ code: "INTERNAL_ERROR",
567
+ message: "Malformed public API response.",
568
+ retryable: !0
569
+ });
570
+ }
571
+ function V(t) {
572
+ const e = b(t);
573
+ if (typeof e.subject != "string" || !(typeof e.nickname == "string" || e.nickname === null) || !(typeof e.avatarUrl == "string" || e.avatarUrl === null))
574
+ throw u();
575
+ return {
576
+ subject: e.subject,
577
+ nickname: e.nickname,
578
+ avatarUrl: e.avatarUrl
579
+ };
580
+ }
581
+ function K(t) {
582
+ const e = b(t);
583
+ if (typeof e.following != "boolean" || !(typeof e.followedAt == "string" || e.followedAt === null))
584
+ throw u();
585
+ const a = b(e.target);
586
+ if (!(a.kind === "CREATOR" || a.kind === "USER") || typeof a.displayName != "string" || !(typeof a.avatarUrl == "string" || a.avatarUrl === null) || !(typeof a.description == "string" || a.description === null))
587
+ throw u();
588
+ return {
589
+ following: e.following,
590
+ followedAt: e.followedAt,
591
+ target: {
592
+ kind: a.kind,
593
+ displayName: a.displayName,
594
+ avatarUrl: a.avatarUrl,
595
+ description: a.description
596
+ }
597
+ };
598
+ }
599
+ function me(t) {
600
+ const e = b(t), a = /* @__PURE__ */ new Set([
601
+ "OWNER",
602
+ "FOLLOWING",
603
+ "PURCHASED",
604
+ "AUTH_REQUIRED",
605
+ "FOLLOW_REQUIRED",
606
+ "PURCHASE_REQUIRED",
607
+ "FEATURE_NOT_FOUND",
608
+ "FEATURE_DISABLED",
609
+ "POLICY_UNSUPPORTED"
610
+ ]), i = /* @__PURE__ */ new Set([null, "SIGN_IN", "FOLLOW", "CHECKOUT"]);
611
+ if (typeof e.allowed != "boolean" || typeof e.reason != "string" || !a.has(e.reason) || !i.has(e.nextAction))
612
+ throw u();
613
+ return {
614
+ allowed: e.allowed,
615
+ reason: e.reason,
616
+ nextAction: e.nextAction
617
+ };
618
+ }
619
+ function $(t) {
620
+ if (typeof t != "string") throw u();
621
+ try {
622
+ const e = new URL(t).origin;
623
+ if (e !== t) throw u();
624
+ return e;
625
+ } catch (e) {
626
+ throw e instanceof S ? e : u();
627
+ }
628
+ }
629
+ function W() {
630
+ const t = crypto.getRandomValues(new Uint8Array(32));
631
+ return B(t);
632
+ }
633
+ function B(t) {
634
+ let e = "";
635
+ for (const a of t) e += String.fromCharCode(a);
636
+ return btoa(e).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
637
+ }
638
+ async function ue(t) {
639
+ const e = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(t));
640
+ return B(new Uint8Array(e));
641
+ }
642
+ function fe() {
643
+ if (typeof navigator > "u") return "pc";
644
+ const t = navigator.userAgentData, e = navigator.userAgent;
645
+ return t?.mobile === !0 || /Android|iPhone|iPad|iPod|Mobile|IEMobile|Opera Mini/i.test(e) || /Macintosh/i.test(e) && navigator.maxTouchPoints > 1 || typeof window < "u" && navigator.maxTouchPoints > 0 && window.matchMedia("(pointer: coarse)").matches && window.matchMedia("(max-width: 48rem)").matches ? "h5" : "pc";
646
+ }
647
+ function he(t) {
648
+ const e = async (n, o) => {
649
+ const s = b(
650
+ (await t.session.request({
651
+ method: "POST",
652
+ path: "/v1/public/v1/auth/exchange",
653
+ body: { code: n, codeVerifier: o }
654
+ })).body
655
+ );
656
+ if (typeof s.token != "string" || typeof s.expiresAt != "number")
657
+ throw u();
658
+ const r = V(s.user);
659
+ return t.session.authenticate({ token: s.token, expiresAt: s.expiresAt, user: r }), { authenticated: !0, user: r };
660
+ }, a = () => new S({
661
+ code: "AUTH_CANCELLED",
662
+ message: "The interactive action was cancelled.",
663
+ retryable: !1
664
+ }), i = (n, o, s, r, c) => {
665
+ if (typeof window > "u")
666
+ throw new S({
667
+ code: "CONFIG_INVALID",
668
+ message: "Interactive access requires a browser window.",
669
+ retryable: !1
670
+ });
671
+ let y = !0, O, I;
672
+ const v = () => {
673
+ y && (y = !1, window.removeEventListener("message", f));
674
+ }, E = new Promise((w, h) => {
675
+ O = w, I = h;
676
+ }), f = (w) => {
677
+ if (!y || w.origin !== o || typeof w.data != "object" || w.data === null) return;
678
+ const h = w.data;
679
+ if (!(h.workKey !== t.workKey || h.channel !== s)) {
680
+ if (h.type === `viceme:${r}:cancelled`) {
681
+ v(), I(a());
682
+ return;
683
+ }
684
+ h.type === `viceme:${r}:complete` && (v(), c(h).then(O, I));
685
+ }
686
+ };
687
+ return window.addEventListener("message", f), {
688
+ type: "frame",
689
+ url: n,
690
+ completion: E,
691
+ cancel() {
692
+ v(), O();
693
+ }
694
+ };
695
+ }, d = async () => {
696
+ await t.ready();
697
+ const n = W(), o = W(), s = await t.session.request({
698
+ method: "POST",
699
+ path: "/v1/public/v1/auth/wechat/authorize",
700
+ body: {
701
+ codeChallenge: await ue(n),
702
+ channel: o,
703
+ clientType: fe()
704
+ }
705
+ }), r = b(s.body);
706
+ if (typeof r.authorizationUrl != "string") throw u();
707
+ return i(
708
+ r.authorizationUrl,
709
+ $(r.completionOrigin),
710
+ o,
711
+ "auth",
712
+ async (c) => {
713
+ if (typeof c.code != "string") throw u();
714
+ await e(c.code, n);
715
+ }
716
+ );
717
+ }, g = {
718
+ async sendCode(n) {
719
+ await t.ready();
720
+ const o = b(
721
+ (await t.session.request({
722
+ method: "POST",
723
+ path: "/v1/public/v1/auth/phone/verification-codes",
724
+ body: { phone: n }
725
+ })).body
726
+ );
727
+ if (typeof o.expiresInSeconds != "number" || typeof o.retryAfterSeconds != "number")
728
+ throw u();
729
+ return {
730
+ expiresInSeconds: o.expiresInSeconds,
731
+ retryAfterSeconds: o.retryAfterSeconds
732
+ };
733
+ },
734
+ async signIn(n, o) {
735
+ await t.ready();
736
+ const s = await t.session.request({
737
+ method: "POST",
738
+ path: "/v1/public/v1/auth/phone/login",
739
+ body: { phone: n, code: o }
740
+ }), r = b(s.body);
741
+ if (typeof r.token != "string" || typeof r.expiresAt != "number")
742
+ throw u();
743
+ const c = V(r.user);
744
+ t.session.authenticate({ token: r.token, expiresAt: r.expiresAt, user: c });
745
+ }
746
+ }, q = {
747
+ async getState() {
748
+ await t.ready();
749
+ const n = t.session.snapshot?.user ?? null;
750
+ return { authenticated: n !== null, user: n };
751
+ },
752
+ async signIn() {
753
+ if (await (t.presenter ?? P)({
754
+ featureKey: "auth",
755
+ reason: "AUTH_REQUIRED",
756
+ action: "SIGN_IN",
757
+ phoneAuth: g,
758
+ perform: d
759
+ }) === "dismissed") throw a();
760
+ return this.getState();
761
+ },
762
+ async signOut() {
763
+ await t.ready(), await t.session.signOut();
764
+ }
765
+ }, l = {
766
+ async getState() {
767
+ return await t.ready(), K(
768
+ (await t.session.request({ method: "GET", path: "/v1/public/v1/follow" })).body
769
+ );
770
+ },
771
+ async follow() {
772
+ return await t.ready(), K(
773
+ (await t.session.request({ method: "PUT", path: "/v1/public/v1/follow" })).body
774
+ );
775
+ },
776
+ async unfollow() {
777
+ return await t.ready(), K(
778
+ (await t.session.request({ method: "DELETE", path: "/v1/public/v1/follow" })).body
779
+ );
780
+ }
781
+ }, R = async (n) => {
782
+ await t.ready();
783
+ const o = b(
784
+ (await t.session.request({
785
+ method: "POST",
786
+ path: "/v1/public/v1/access/check",
787
+ body: { featureKeys: n }
788
+ })).body
789
+ ), s = b(o.decisions);
790
+ return Object.fromEntries(
791
+ Object.entries(s).map(([r, c]) => [r, me(c)])
792
+ );
793
+ }, k = async (n = {}) => {
794
+ await t.ready();
795
+ const o = W(), s = {
796
+ locale: n.locale ?? "zh-CN",
797
+ channel: o
798
+ }, r = b(
799
+ (await t.session.request({
800
+ method: "POST",
801
+ path: "/v1/public/v1/checkout/sessions",
802
+ body: s
803
+ })).body
804
+ );
805
+ if (typeof r.checkoutUrl != "string" || typeof r.alreadyOwned != "boolean")
806
+ throw u();
807
+ const c = $(r.completionOrigin), y = {
808
+ checkoutUrl: r.checkoutUrl,
809
+ alreadyOwned: r.alreadyOwned
810
+ };
811
+ return {
812
+ result: y,
813
+ action: y.alreadyOwned ? { type: "completed" } : i(y.checkoutUrl, c, o, "checkout", async () => {
814
+ })
815
+ };
816
+ };
817
+ return { auth: q, follow: l, access: {
818
+ async check(n) {
819
+ const s = (await R([n]))[n];
820
+ if (!s) throw u();
821
+ return s;
822
+ },
823
+ checkMany: R,
824
+ async require(n) {
825
+ let o = await this.check(n);
826
+ const s = t.presenter ?? P;
827
+ for (let r = 0; !o.allowed && o.nextAction && r < 3; r += 1) {
828
+ const c = o.nextAction, y = c === "FOLLOW" ? (await l.getState()).target : void 0;
829
+ if (await s({
830
+ featureKey: n,
831
+ reason: o.reason,
832
+ action: c,
833
+ ...y ? { followTarget: y } : {},
834
+ ...c === "SIGN_IN" ? { phoneAuth: g } : {},
835
+ perform: async () => c === "SIGN_IN" ? d() : c === "FOLLOW" ? (await l.follow(), { type: "completed" }) : (await k()).action
836
+ }) === "dismissed") return o;
837
+ o = await this.check(n);
838
+ }
839
+ return o;
840
+ },
841
+ async refresh() {
842
+ await t.ready();
843
+ }
844
+ }, checkout: {
845
+ async open(n = {}) {
846
+ const o = t.presenter ?? P;
847
+ let s;
848
+ if (await o({
849
+ featureKey: "checkout",
850
+ reason: "PURCHASE_REQUIRED",
851
+ action: "CHECKOUT",
852
+ perform: async () => {
853
+ const c = await k(n);
854
+ return s = c.result, c.action;
855
+ }
856
+ }) === "dismissed" || !s) throw a();
857
+ return s;
858
+ }
859
+ } };
860
+ }
861
+ class pe extends DOMException {
862
+ constructor() {
863
+ super("ViceMe client destroyed.", "AbortError");
864
+ }
865
+ }
866
+ class ge {
867
+ #e = new re();
868
+ #t;
869
+ #a;
870
+ #i = new AbortController();
871
+ #n;
872
+ auth;
873
+ access;
874
+ checkout;
875
+ constructor(e) {
876
+ this.#a = e.config, this.#t = new ce({
877
+ workKey: e.config.workKey,
878
+ transport: e.transport,
879
+ signal: this.#i.signal,
880
+ ...e.now !== void 0 ? { now: e.now } : {}
881
+ });
882
+ const a = he({
883
+ session: this.#t,
884
+ workKey: e.config.workKey,
885
+ presenter: e.presenter,
886
+ ready: () => this.ready()
887
+ });
888
+ this.auth = a.auth, this.access = a.access, this.checkout = a.checkout;
889
+ const i = e.config.signal;
890
+ if (i) {
891
+ const d = () => {
892
+ this.#i.abort(
893
+ i.reason instanceof Error ? i.reason : new DOMException("Caller signal aborted.", "AbortError")
894
+ );
895
+ };
896
+ i.aborted ? d() : i.addEventListener("abort", d, { once: !0 });
897
+ }
898
+ }
899
+ get version() {
900
+ return X;
901
+ }
902
+ get workKey() {
903
+ return this.#a.workKey;
904
+ }
905
+ get region() {
906
+ return this.#a.region;
907
+ }
908
+ get state() {
909
+ return this.#e.state;
910
+ }
911
+ /** Internal: public API major, used by the loader registry namespace. */
912
+ get apiMajor() {
913
+ return ee;
914
+ }
915
+ ready() {
916
+ return this.#e.destroyed ? Promise.reject(D()) : (this.#n ??= this.#o(), this.#n);
917
+ }
918
+ async #o() {
919
+ if (this.#e.destroyed) throw D();
920
+ this.#e.transition("INITIALIZING");
921
+ try {
922
+ if (await this.#t.establish(), this.#e.destroyed) throw D();
923
+ this.#e.transition("READY");
924
+ } catch (e) {
925
+ throw this.#e.destroyed ? D() : (this.#e.transition("FAILED"), this.#n = void 0, this.#t.invalidate(), e);
926
+ }
927
+ }
928
+ hasCapability(e) {
929
+ if (this.#e.destroyed) return !1;
930
+ const a = this.#t.snapshot?.work.capabilities;
931
+ return a !== void 0 && a.includes(e);
932
+ }
933
+ /** Names of capabilities enabled for this work (empty before `ready()`). */
934
+ get capabilities() {
935
+ return this.#t.snapshot?.work.capabilities ?? [];
936
+ }
937
+ /**
938
+ * Internal: mark one capability unavailable without taking down the client
939
+ * (loader uses this when a feature chunk fails after the core is READY).
940
+ */
941
+ markDegraded() {
942
+ this.#e.state === "READY" && this.#e.transition("DEGRADED");
943
+ }
944
+ /** Internal: session snapshot access for capability modules. */
945
+ get sessionSnapshot() {
946
+ return this.#t.snapshot;
947
+ }
948
+ destroy() {
949
+ this.#e.destroyed || (this.#e.transition("DESTROYED"), this.#i.abort(new pe()), this.#t.destroy(), this.#e.clearListeners(), this.#n = void 0);
950
+ }
951
+ }
952
+ export {
953
+ ge as V,
954
+ ne as a,
955
+ ie as i,
956
+ ve as r,
957
+ be as v
958
+ };
959
+ //# sourceMappingURL=client-DgGpWHrf.js.map