@viceme-ai/sdk 0.3.0 → 0.6.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 (84) hide show
  1. package/README.md +158 -44
  2. package/dist/browser-events.d.ts +52 -0
  3. package/dist/browser-events.d.ts.map +1 -0
  4. package/dist/capability-mount.d.ts +15 -0
  5. package/dist/capability-mount.d.ts.map +1 -0
  6. package/dist/chunks/build-endpoints-NrDmg6jf.js +12 -0
  7. package/dist/chunks/build-endpoints-NrDmg6jf.js.map +1 -0
  8. package/dist/chunks/{client-DKsaEtwq.js → client-w9vih8Ng.js} +386 -349
  9. package/dist/chunks/client-w9vih8Ng.js.map +1 -0
  10. package/dist/chunks/{version-C3KVoLNb.js → errors-C7DfLKcF.js} +14 -25
  11. package/dist/chunks/errors-C7DfLKcF.js.map +1 -0
  12. package/dist/chunks/validation-patAYhXC.js +43 -0
  13. package/dist/chunks/validation-patAYhXC.js.map +1 -0
  14. package/dist/chunks/version-uPTHb89K.js +6 -0
  15. package/dist/chunks/version-uPTHb89K.js.map +1 -0
  16. package/dist/core/build-endpoints.d.ts +2 -0
  17. package/dist/core/build-endpoints.d.ts.map +1 -1
  18. package/dist/core/capabilities.d.ts +4 -2
  19. package/dist/core/capabilities.d.ts.map +1 -1
  20. package/dist/core/client.d.ts +4 -2
  21. package/dist/core/client.d.ts.map +1 -1
  22. package/dist/core/config.d.ts +1 -1
  23. package/dist/core/config.d.ts.map +1 -1
  24. package/dist/core/errors.d.ts +1 -1
  25. package/dist/core/errors.d.ts.map +1 -1
  26. package/dist/core/lifecycle.d.ts +2 -4
  27. package/dist/core/lifecycle.d.ts.map +1 -1
  28. package/dist/core/presentation.d.ts +7 -2
  29. package/dist/core/presentation.d.ts.map +1 -1
  30. package/dist/danmaku/index.d.ts +1 -0
  31. package/dist/danmaku/index.d.ts.map +1 -1
  32. package/dist/danmaku/mount.d.ts +1 -1
  33. package/dist/danmaku/mount.d.ts.map +1 -1
  34. package/dist/danmaku.js +128 -121
  35. package/dist/danmaku.js.map +1 -1
  36. package/dist/generated/public-contract.d.ts +124 -373
  37. package/dist/generated/public-contract.d.ts.map +1 -1
  38. package/dist/index.d.ts +3 -2
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +23 -21
  41. package/dist/index.js.map +1 -1
  42. package/dist/loader/attributes.d.ts +3 -2
  43. package/dist/loader/attributes.d.ts.map +1 -1
  44. package/dist/loader/auto-loader.d.ts +1 -1
  45. package/dist/loader/auto-loader.d.ts.map +1 -1
  46. package/dist/loader/events.d.ts +1 -44
  47. package/dist/loader/events.d.ts.map +1 -1
  48. package/dist/loader/registry.d.ts +2 -1
  49. package/dist/loader/registry.d.ts.map +1 -1
  50. package/dist/manifest.json +60 -35
  51. package/dist/session/session.d.ts +7 -6
  52. package/dist/session/session.d.ts.map +1 -1
  53. package/dist/testing/test-adapter.d.ts +1 -1
  54. package/dist/testing/test-adapter.d.ts.map +1 -1
  55. package/dist/testing.js +18 -17
  56. package/dist/testing.js.map +1 -1
  57. package/dist/tip/headless.d.ts +4 -0
  58. package/dist/tip/headless.d.ts.map +1 -0
  59. package/dist/tip/index.d.ts +67 -0
  60. package/dist/tip/index.d.ts.map +1 -0
  61. package/dist/tip/mount.d.ts +5 -0
  62. package/dist/tip/mount.d.ts.map +1 -0
  63. package/dist/tip/testing.d.ts +9 -0
  64. package/dist/tip/testing.d.ts.map +1 -0
  65. package/dist/tip/testing.js +43 -0
  66. package/dist/tip/testing.js.map +1 -0
  67. package/dist/tip/validation.d.ts +7 -0
  68. package/dist/tip/validation.d.ts.map +1 -0
  69. package/dist/tip.js +472 -0
  70. package/dist/tip.js.map +1 -0
  71. package/dist/transport/transport.d.ts +3 -1
  72. package/dist/transport/transport.d.ts.map +1 -1
  73. package/dist/version.d.ts +1 -1
  74. package/dist/viceme.min.js +5 -22
  75. package/dist/viceme.min.js.map +1 -1
  76. package/package.json +12 -7
  77. package/dist/bootstrap.min.js +0 -2
  78. package/dist/bootstrap.min.js.map +0 -1
  79. package/dist/chunks/client-DKsaEtwq.js.map +0 -1
  80. package/dist/chunks/version-C3KVoLNb.js.map +0 -1
  81. package/dist/loader/bootstrap.d.ts +0 -1
  82. package/dist/loader/bootstrap.d.ts.map +0 -1
  83. package/dist/loader/mount-handle.d.ts +0 -25
  84. package/dist/loader/mount-handle.d.ts.map +0 -1
package/dist/tip.js ADDED
@@ -0,0 +1,472 @@
1
+ import { B as Y } from "./chunks/build-endpoints-NrDmg6jf.js";
2
+ import { c as E, V as h } from "./chunks/errors-C7DfLKcF.js";
3
+ import { p as Z, t as M, i as U, a as ee } from "./chunks/validation-patAYhXC.js";
4
+ const te = ["work", "workKey", "environment", "currency", "amount", "providers"], J = ["id", "title"], re = ["minCents", "maxCents", "stepCents"], oe = ["statusCode", "code", "message", "requestId"], ie = ["type", "channel", "workKey"], ae = [
5
+ "type",
6
+ "channel",
7
+ "workKey",
8
+ "status",
9
+ "work",
10
+ "amountCents",
11
+ "currency"
12
+ ], ne = ["type", "channel", "workKey", "status"], se = 8e3, ce = 8e3, V = 16 * 1024, le = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
13
+ function I(e, t) {
14
+ if (typeof e != "object" || e === null || Array.isArray(e)) return !1;
15
+ const o = Object.keys(e);
16
+ return o.length === t.length && t.every((a) => o.includes(a));
17
+ }
18
+ function p() {
19
+ return new h({
20
+ code: "TIP_CONFIG_INVALID",
21
+ message: "Shop returned an invalid Tip configuration.",
22
+ retryable: !1,
23
+ capability: "tip"
24
+ });
25
+ }
26
+ function de(e) {
27
+ return I(e, oe) ? e.statusCode === 400 && e.code === "TIP_CONFIG_CREDENTIALS_NOT_ALLOWED" && typeof e.message == "string" && typeof e.requestId == "string" && e.requestId.length >= 1 && e.requestId.length <= 128 : !1;
28
+ }
29
+ function ye(e) {
30
+ return new h({
31
+ code: "TIP_CONFIG_CREDENTIALS_NOT_ALLOWED",
32
+ message: "Tip configuration requests must not include credentials.",
33
+ retryable: !1,
34
+ requestId: e,
35
+ capability: "tip"
36
+ });
37
+ }
38
+ function we(e, t) {
39
+ if (!I(e, te) || !I(e.work, J) || typeof e.work.id != "string" || !le.test(e.work.id) || !U(e.work.title) || e.workKey !== t || e.environment !== "SANDBOX" && e.environment !== "PRODUCTION" || e.workKey.startsWith("wrk_test_") && e.environment !== "SANDBOX" || e.workKey.startsWith("wrk_live_") && e.environment !== "PRODUCTION" || e.currency !== "CNY" || !I(e.amount, re) || e.amount.minCents !== 100 || e.amount.maxCents !== 2e4 || e.amount.stepCents !== 1 || !Array.isArray(e.providers) || e.providers.length < 1 || !e.providers.every(ee) || new Set(e.providers).size !== e.providers.length)
40
+ throw p();
41
+ return {
42
+ work: { id: e.work.id, title: e.work.title },
43
+ workKey: e.workKey,
44
+ environment: e.environment,
45
+ currency: e.currency,
46
+ amount: { minCents: 100, maxCents: 2e4, stepCents: 1 },
47
+ providers: [...e.providers]
48
+ };
49
+ }
50
+ function ue(e, t, o, a) {
51
+ if (typeof e != "object" || e === null || Array.isArray(e)) return;
52
+ const i = e;
53
+ if (!(i.type !== "viceme:tip-headless-result" || i.channel !== t || i.workKey !== o.workKey)) {
54
+ if (i.status === "PAID")
55
+ return !I(i, ae) || !I(i.work, J) || i.work.id !== o.work.id || i.work.title !== o.work.title || i.amountCents !== a || i.currency !== "CNY" ? void 0 : {
56
+ status: "PAID",
57
+ work: { id: o.work.id, title: o.work.title },
58
+ amountCents: a,
59
+ currency: "CNY"
60
+ };
61
+ if ((i.status === "CANCELLED" || i.status === "UNKNOWN") && I(i, ne))
62
+ return { status: i.status };
63
+ }
64
+ }
65
+ function _() {
66
+ return new h({
67
+ code: "INTERNAL_ERROR",
68
+ message: "Unable to open the hosted Tip flow.",
69
+ capability: "tip"
70
+ });
71
+ }
72
+ function D() {
73
+ return new h({
74
+ code: "CAPABILITY_DISABLED",
75
+ message: "Tip is not available for this Work or region.",
76
+ retryable: !1,
77
+ capability: "tip"
78
+ });
79
+ }
80
+ async function z(e) {
81
+ const t = e.headers.get("content-length");
82
+ if (t !== null) {
83
+ const y = Number(t);
84
+ if (!Number.isInteger(y) || y < 0 || y > V)
85
+ throw await e.body?.cancel().catch(() => {
86
+ }), p();
87
+ }
88
+ const o = e.body?.getReader();
89
+ if (!o) throw p();
90
+ const a = new TextDecoder("utf-8", { fatal: !0 });
91
+ let i = 0, c = "";
92
+ try {
93
+ for (; ; ) {
94
+ const y = await o.read();
95
+ if (y.done) break;
96
+ if (i += y.value.byteLength, i > V)
97
+ throw await o.cancel().catch(() => {
98
+ }), p();
99
+ try {
100
+ c += a.decode(y.value, { stream: !0 });
101
+ } catch {
102
+ throw await o.cancel().catch(() => {
103
+ }), p();
104
+ }
105
+ }
106
+ try {
107
+ c += a.decode();
108
+ } catch {
109
+ throw await o.cancel().catch(() => {
110
+ }), p();
111
+ }
112
+ } finally {
113
+ o.releaseLock();
114
+ }
115
+ try {
116
+ return JSON.parse(c);
117
+ } catch {
118
+ throw p();
119
+ }
120
+ }
121
+ async function fe(e, t) {
122
+ if (await e.ready(), !e.hasCapability("tip") || e.region !== "cn") throw D();
123
+ if (t.aborted) throw E();
124
+ const o = new AbortController(), a = () => o.abort();
125
+ t.addEventListener("abort", a, { once: !0 });
126
+ const i = globalThis.setTimeout(() => o.abort(), ce), c = Y[e.region], y = new URL(
127
+ `/v1/work-sdk/${encodeURIComponent(e.workKey)}/tip-config`,
128
+ c
129
+ );
130
+ try {
131
+ const n = await fetch(y.toString(), {
132
+ method: "GET",
133
+ credentials: "omit",
134
+ redirect: "error",
135
+ headers: { accept: "application/json" },
136
+ signal: o.signal
137
+ }), u = n.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
138
+ let l;
139
+ try {
140
+ l = n.url ? new URL(n.url).origin : void 0;
141
+ } catch {
142
+ l = "invalid";
143
+ }
144
+ if (n.status !== 200) {
145
+ if (n.status === 404)
146
+ throw await n.body?.cancel().catch(() => {
147
+ }), D();
148
+ if (n.status === 400 && u === "application/json" && (!l || l === c)) {
149
+ let v;
150
+ try {
151
+ v = await z(n);
152
+ } catch {
153
+ throw _();
154
+ }
155
+ if (de(v))
156
+ throw ye(v.requestId);
157
+ } else
158
+ await n.body?.cancel().catch(() => {
159
+ });
160
+ throw new h({
161
+ code: "INTERNAL_ERROR",
162
+ message: "Unable to load Tip configuration.",
163
+ capability: "tip"
164
+ });
165
+ }
166
+ if (u !== "application/json" || l && l !== c)
167
+ throw await n.body?.cancel().catch(() => {
168
+ }), p();
169
+ const w = await z(n);
170
+ return we(w, e.workKey);
171
+ } catch (n) {
172
+ throw t.aborted ? E() : n instanceof h ? n : _();
173
+ } finally {
174
+ o.abort(), globalThis.clearTimeout(i), t.removeEventListener("abort", a);
175
+ }
176
+ }
177
+ function me(e) {
178
+ return {
179
+ work: { ...e.work },
180
+ workKey: e.workKey,
181
+ environment: e.environment,
182
+ currency: e.currency,
183
+ amount: { ...e.amount },
184
+ providers: [...e.providers]
185
+ };
186
+ }
187
+ function pe(e) {
188
+ let t = !1, o, a;
189
+ const i = new AbortController(), c = () => t || e.state === "DESTROYED", y = () => {
190
+ if (!a) {
191
+ const n = fe(e, i.signal);
192
+ a = n, n.then(
193
+ () => {
194
+ a === n && (a = void 0);
195
+ },
196
+ () => {
197
+ a === n && (a = void 0);
198
+ }
199
+ );
200
+ }
201
+ return a;
202
+ };
203
+ return {
204
+ async getConfig() {
205
+ if (c()) throw E();
206
+ const n = await y();
207
+ if (c()) throw E();
208
+ return me(n);
209
+ },
210
+ open(n) {
211
+ if (c()) return Promise.reject(E());
212
+ if (o)
213
+ return Promise.reject(
214
+ new h({
215
+ code: "TIP_OPEN_IN_PROGRESS",
216
+ message: "This Tip client already has an open flow.",
217
+ retryable: !1,
218
+ capability: "tip"
219
+ })
220
+ );
221
+ if (!e.hasCapability("tip") || e.region !== "cn") return Promise.reject(D());
222
+ let u;
223
+ try {
224
+ u = Z(n);
225
+ } catch (s) {
226
+ return Promise.reject(s);
227
+ }
228
+ if (typeof document > "u")
229
+ return Promise.reject(M());
230
+ const l = document, w = l.defaultView;
231
+ if (!l.body || !w) return Promise.reject(M());
232
+ const v = Y[e.region], d = l.documentElement.lang || w.navigator.language, O = u.locale ?? (d.toLowerCase().startsWith("zh") ? "zh-CN" : "en-US"), L = u.appearance ?? "auto", S = L === "auto" ? w.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light" : L;
233
+ let C, K;
234
+ try {
235
+ const s = new Uint8Array(16);
236
+ w.crypto.getRandomValues(s), C = Array.from(s, (b) => b.toString(16).padStart(2, "0")).join(""), K = e.ready();
237
+ } catch {
238
+ return Promise.reject(_());
239
+ }
240
+ const m = l.createElement("div");
241
+ m.dataset.vicemeTipHeadless = "open", m.style.all = "initial", m.style.position = "fixed", m.style.inset = "0", m.style.display = "block", m.style.width = "100vw", m.style.height = "100vh", m.style.zIndex = "2147483647";
242
+ const f = l.createElement("iframe"), T = new URL(`/widget/tip/${encodeURIComponent(e.workKey)}`, v);
243
+ T.searchParams.set("mode", "headless"), T.searchParams.set("channel", C), T.searchParams.set("appearance", S), T.searchParams.set("locale", O), f.title = "ViceMe Tip", f.src = T.toString(), f.loading = "eager", f.referrerPolicy = "strict-origin", f.setAttribute(
244
+ "sandbox",
245
+ "allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
246
+ ), f.setAttribute("allow", "payment"), f.style.display = "block", f.style.width = "100%", f.style.height = "100%", f.style.border = "0", f.style.background = "transparent", f.style.colorScheme = S, m.attachShadow({ mode: "open" }).append(f);
247
+ let k = !1, g = !1, r = !1, R, A, j, W;
248
+ const Q = new Promise((s, b) => {
249
+ j = s, W = b;
250
+ }), x = () => {
251
+ A !== void 0 && (w.clearTimeout(A), A = void 0), w.removeEventListener("message", H), m.remove(), o === B && (o = void 0);
252
+ }, G = (s) => {
253
+ k || (k = !0, x(), j(s));
254
+ }, N = (s) => {
255
+ k || (k = !0, x(), W(s));
256
+ }, B = () => G({ status: "UNKNOWN" }), q = () => {
257
+ if (!g || !R || r || k) return;
258
+ if (u.provider && !R.providers.includes(u.provider)) {
259
+ N(M());
260
+ return;
261
+ }
262
+ r = !0;
263
+ const s = {
264
+ type: "viceme:tip-headless-init",
265
+ channel: C,
266
+ workKey: e.workKey,
267
+ amountCents: u.amountCents,
268
+ ...u.provider === void 0 ? {} : { provider: u.provider },
269
+ locale: O,
270
+ appearance: S
271
+ };
272
+ try {
273
+ const b = f.contentWindow;
274
+ if (!b) {
275
+ N(_());
276
+ return;
277
+ }
278
+ b.postMessage(s, v);
279
+ } catch {
280
+ N(_());
281
+ }
282
+ }, H = (s) => {
283
+ if (s.origin !== v || s.source !== f.contentWindow) return;
284
+ if (!r) {
285
+ if (!I(s.data, ie) || s.data.type !== "viceme:tip-headless-ready" || s.data.channel !== C || s.data.workKey !== e.workKey)
286
+ return;
287
+ g = !0, A !== void 0 && (w.clearTimeout(A), A = void 0), q();
288
+ return;
289
+ }
290
+ if (!R) return;
291
+ const b = ue(s.data, C, R, u.amountCents);
292
+ b && b.status !== "UNKNOWN" && G(b);
293
+ };
294
+ return o = B, w.addEventListener("message", H), A = w.setTimeout(() => {
295
+ N(
296
+ new h({
297
+ code: "TIP_READY_TIMEOUT",
298
+ message: "Hosted Tip did not become ready in time.",
299
+ retryable: !0,
300
+ capability: "tip"
301
+ })
302
+ );
303
+ }, se), l.body.append(m), K.catch((s) => {
304
+ N(s instanceof h ? s : _());
305
+ }), y().then((s) => {
306
+ R = s, q();
307
+ }).catch((s) => {
308
+ N(s instanceof h ? s : _());
309
+ }), Q;
310
+ },
311
+ destroy() {
312
+ t || (t = !0, i.abort(), o?.());
313
+ }
314
+ };
315
+ }
316
+ const he = /* @__PURE__ */ new Map([
317
+ ["viceme:ready", /* @__PURE__ */ new Set(["clientKey", "workKey", "capabilities", "version"])],
318
+ ["viceme:capability-ready", /* @__PURE__ */ new Set(["clientKey", "instanceKey", "capability", "version"])],
319
+ [
320
+ "viceme:error",
321
+ /* @__PURE__ */ new Set(["clientKey", "instanceKey", "capability", "code", "retryable", "requestId"])
322
+ ],
323
+ ["viceme:destroyed", /* @__PURE__ */ new Set(["clientKey", "instanceKey", "capability"])],
324
+ ["viceme:widget-close", /* @__PURE__ */ new Set(["workId"])],
325
+ ["viceme:tip-paid", /* @__PURE__ */ new Set(["status", "work", "amountCents", "currency"])]
326
+ ]);
327
+ function ge(e, t) {
328
+ if (e === "viceme:tip-paid") {
329
+ const i = t;
330
+ return {
331
+ status: i.status,
332
+ work: { id: i.work.id, title: i.work.title },
333
+ amountCents: i.amountCents,
334
+ currency: i.currency
335
+ };
336
+ }
337
+ const o = he.get(e), a = {};
338
+ for (const [i, c] of Object.entries(t))
339
+ o.has(i) && c !== void 0 && (a[i] = c);
340
+ return a;
341
+ }
342
+ function F(e, t, o) {
343
+ const a = new CustomEvent(t, {
344
+ detail: ge(t, o),
345
+ bubbles: !0,
346
+ composed: !0,
347
+ cancelable: !1
348
+ });
349
+ e.dispatchEvent(a);
350
+ }
351
+ const be = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, ve = 100, ke = 2e4, Ee = 2048, Te = 8e3, Ie = ["type", "workId", "work", "height"], Ce = ["type", "workId"], Ae = ["type", "workKey", "status", "work", "amountCents", "currency"], $ = ["id", "title"];
352
+ function P(e, t) {
353
+ if (typeof e != "object" || e === null || Array.isArray(e)) return !1;
354
+ const o = Object.keys(e);
355
+ return o.length === t.length && t.every((a) => o.includes(a));
356
+ }
357
+ async function _e(e, t) {
358
+ if (t.signal?.aborted) throw E();
359
+ if (await e.ready(), t.signal?.aborted) throw E();
360
+ if (!e.hasCapability("tip"))
361
+ throw new h({
362
+ code: "CAPABILITY_DISABLED",
363
+ message: "Tip is not available in this SDK build.",
364
+ retryable: !1,
365
+ capability: "tip"
366
+ });
367
+ if (e.region !== "cn")
368
+ throw new h({
369
+ code: "CAPABILITY_DISABLED",
370
+ message: "Tip is not available in this region.",
371
+ retryable: !1,
372
+ capability: "tip"
373
+ });
374
+ const o = t.target.ownerDocument, a = o.defaultView;
375
+ if (!a)
376
+ throw new h({
377
+ code: "CONFIG_INVALID",
378
+ message: "Tip requires a browser document.",
379
+ retryable: !1,
380
+ capability: "tip"
381
+ });
382
+ const i = Y[e.region], c = t.theme === "auto" ? a.matchMedia("(prefers-color-scheme: dark)") : void 0;
383
+ let y = t.theme === "auto" ? c?.matches ? "dark" : "light" : t.theme, n = !1, u, l;
384
+ const w = o.createElement("div");
385
+ w.dataset.vicemeTip = "mounted", w.style.all = "initial", w.style.display = "block", w.style.width = "100%", w.style.maxWidth = "100%", w.style.contain = "layout style";
386
+ const v = w.attachShadow({ mode: "open" }), d = o.createElement("iframe"), O = new URL(`/widget/tip/${encodeURIComponent(e.workKey)}`, i);
387
+ O.searchParams.set("appearance", y), d.title = "ViceMe Tip", d.src = O.toString(), d.loading = "eager", d.referrerPolicy = "strict-origin", d.setAttribute(
388
+ "sandbox",
389
+ "allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
390
+ ), d.setAttribute("allow", "payment"), d.style.boxSizing = "border-box", d.style.display = "block", d.style.width = "100%", d.style.height = "0px", d.style.margin = "0", d.style.border = "0", d.style.background = "transparent", d.style.colorScheme = y, d.style.pointerEvents = "none", v.append(d);
391
+ let L, S;
392
+ const C = new Promise((g, r) => {
393
+ L = g, S = r, u = a.setTimeout(() => {
394
+ r(
395
+ new h({
396
+ code: "INTERNAL_ERROR",
397
+ message: "Hosted Tip widget did not become ready in time.",
398
+ retryable: !0,
399
+ capability: "tip"
400
+ })
401
+ );
402
+ }, Te);
403
+ }), K = (g) => {
404
+ if (g.origin !== i || g.source !== d.contentWindow) return;
405
+ const r = g.data;
406
+ if (!(typeof r != "object" || r === null || Array.isArray(r))) {
407
+ if (P(r, Ie) && r.type === "viceme:widget-resize") {
408
+ if (typeof r.workId != "string" || !be.test(r.workId) || !P(r.work, $) || r.work.id !== r.workId || !U(r.work.title) || typeof r.height != "number" || !Number.isInteger(r.height) || r.height < 1 || r.height > Ee || l !== void 0 && (r.work.id !== l.id || r.work.title !== l.title))
409
+ return;
410
+ d.style.height = `${r.height}px`, l === void 0 && (l = { id: r.workId, title: r.work.title }, d.style.pointerEvents = "auto", u !== void 0 && (a.clearTimeout(u), u = void 0), L?.());
411
+ return;
412
+ }
413
+ if (P(r, Ce) && r.type === "viceme:widget-close") {
414
+ if (typeof r.workId != "string" || r.workId !== l?.id) return;
415
+ F(t.target, "viceme:widget-close", { workId: r.workId });
416
+ return;
417
+ }
418
+ P(r, Ae) && r.type === "viceme:tip-paid" && r.workKey === e.workKey && P(r.work, $) && l !== void 0 && typeof r.work.id == "string" && r.work.id === l.id && U(r.work.title) && r.work.title === l.title && r.status === "PAID" && typeof r.amountCents == "number" && Number.isInteger(r.amountCents) && r.amountCents >= ve && r.amountCents <= ke && r.currency === "CNY" && F(t.target, "viceme:tip-paid", {
419
+ status: "PAID",
420
+ work: { id: r.work.id, title: r.work.title },
421
+ amountCents: r.amountCents,
422
+ currency: "CNY"
423
+ });
424
+ }
425
+ }, m = (g) => {
426
+ y = g.matches ? "dark" : "light", d.style.colorScheme = y, d.contentWindow?.postMessage(
427
+ { type: "viceme:widget-appearance", appearance: y },
428
+ i
429
+ );
430
+ };
431
+ let f;
432
+ const T = () => {
433
+ S?.(E()), k();
434
+ }, k = () => {
435
+ n || (n = !0, u !== void 0 && a.clearTimeout(u), a.removeEventListener("message", K), f?.(), t.signal?.removeEventListener("abort", T), w.remove());
436
+ };
437
+ try {
438
+ if (a.addEventListener("message", K), c && (typeof c.addEventListener == "function" ? (c.addEventListener("change", m), f = () => c.removeEventListener("change", m)) : (c.addListener(m), f = () => c.removeListener(m))), t.signal?.addEventListener("abort", T, { once: !0 }), t.signal?.aborted) throw E();
439
+ t.target.appendChild(w), await C;
440
+ } catch (g) {
441
+ throw k(), g;
442
+ }
443
+ return { capability: "tip", destroy: k };
444
+ }
445
+ const X = /* @__PURE__ */ new WeakMap();
446
+ function Le(e) {
447
+ return pe(e);
448
+ }
449
+ function Ke(e, t) {
450
+ let o = X.get(e);
451
+ o || (o = /* @__PURE__ */ new WeakMap(), X.set(e, o));
452
+ const a = o.get(t.target);
453
+ if (a) return a;
454
+ const i = _e(e, t).then((c) => {
455
+ let y = !1;
456
+ const n = {
457
+ capability: "tip",
458
+ destroy() {
459
+ y || (y = !0, t.signal?.removeEventListener("abort", n.destroy), o.get(t.target) === i && o.delete(t.target), c.destroy());
460
+ }
461
+ };
462
+ return t.signal?.addEventListener("abort", n.destroy, { once: !0 }), t.signal?.aborted && n.destroy(), n;
463
+ }).catch((c) => {
464
+ throw o.get(t.target) === i && o.delete(t.target), c;
465
+ });
466
+ return o.set(t.target, i), i;
467
+ }
468
+ export {
469
+ Le as createTip,
470
+ Ke as mountTip
471
+ };
472
+ //# sourceMappingURL=tip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tip.js","sources":["../src/tip/headless.ts","../src/browser-events.ts","../src/tip/mount.ts","../src/tip/index.ts"],"sourcesContent":["import type { ViceMeClient } from '../core/client.ts';\nimport { BUILD_WIDGET_ORIGINS } from '../core/build-endpoints.ts';\nimport { clientDestroyed, ViceMeError } from '../core/errors.ts';\nimport type { TipClient, TipConfig, TipOpenOptions, TipOpenResult } from './index.ts';\nimport {\n isTipProvider,\n isValidTipWorkTitle,\n parseTipOpenOptions,\n tipOptionInvalid,\n} from './validation.ts';\n\nconst TIP_CONFIG_KEYS = ['work', 'workKey', 'environment', 'currency', 'amount', 'providers'];\nconst TIP_WORK_KEYS = ['id', 'title'];\nconst TIP_AMOUNT_KEYS = ['minCents', 'maxCents', 'stepCents'];\nconst PUBLIC_ERROR_KEYS = ['statusCode', 'code', 'message', 'requestId'];\nconst HEADLESS_READY_KEYS = ['type', 'channel', 'workKey'];\nconst HEADLESS_PAID_KEYS = [\n 'type',\n 'channel',\n 'workKey',\n 'status',\n 'work',\n 'amountCents',\n 'currency',\n];\nconst HEADLESS_TERMINAL_KEYS = ['type', 'channel', 'workKey', 'status'];\nconst HEADLESS_READY_TIMEOUT_MS = 8_000;\nconst TIP_CONFIG_TIMEOUT_MS = 8_000;\nconst TIP_CONFIG_MAX_BYTES = 16 * 1024;\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\ntype WidgetAppearance = 'light' | 'dark';\n\nfunction isStrictRecord(value: unknown, keys: string[]): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const actualKeys = Object.keys(value);\n return actualKeys.length === keys.length && keys.every((key) => actualKeys.includes(key));\n}\n\nfunction tipConfigInvalid(): ViceMeError {\n return new ViceMeError({\n code: 'TIP_CONFIG_INVALID',\n message: 'Shop returned an invalid Tip configuration.',\n retryable: false,\n capability: 'tip',\n });\n}\n\nfunction isCredentialsNotAllowedError(input: unknown): input is { requestId: string } {\n if (!isStrictRecord(input, PUBLIC_ERROR_KEYS)) return false;\n return (\n input.statusCode === 400 &&\n input.code === 'TIP_CONFIG_CREDENTIALS_NOT_ALLOWED' &&\n typeof input.message === 'string' &&\n typeof input.requestId === 'string' &&\n input.requestId.length >= 1 &&\n input.requestId.length <= 128\n );\n}\n\nfunction tipConfigCredentialsNotAllowed(requestId: string): ViceMeError {\n return new ViceMeError({\n code: 'TIP_CONFIG_CREDENTIALS_NOT_ALLOWED',\n message: 'Tip configuration requests must not include credentials.',\n retryable: false,\n requestId,\n capability: 'tip',\n });\n}\n\nfunction parseTipConfig(input: unknown, expectedWorkKey: string): TipConfig {\n if (!isStrictRecord(input, TIP_CONFIG_KEYS)) throw tipConfigInvalid();\n if (!isStrictRecord(input.work, TIP_WORK_KEYS)) throw tipConfigInvalid();\n if (\n typeof input.work.id !== 'string' ||\n !UUID_PATTERN.test(input.work.id) ||\n !isValidTipWorkTitle(input.work.title)\n ) {\n throw tipConfigInvalid();\n }\n if (input.workKey !== expectedWorkKey) {\n throw tipConfigInvalid();\n }\n if (input.environment !== 'SANDBOX' && input.environment !== 'PRODUCTION') {\n throw tipConfigInvalid();\n }\n if (\n (input.workKey.startsWith('wrk_test_') && input.environment !== 'SANDBOX') ||\n (input.workKey.startsWith('wrk_live_') && input.environment !== 'PRODUCTION')\n ) {\n throw tipConfigInvalid();\n }\n if (input.currency !== 'CNY') throw tipConfigInvalid();\n if (\n !isStrictRecord(input.amount, TIP_AMOUNT_KEYS) ||\n input.amount.minCents !== 100 ||\n input.amount.maxCents !== 20_000 ||\n input.amount.stepCents !== 1\n ) {\n throw tipConfigInvalid();\n }\n if (\n !Array.isArray(input.providers) ||\n input.providers.length < 1 ||\n !input.providers.every(isTipProvider) ||\n new Set(input.providers).size !== input.providers.length\n ) {\n throw tipConfigInvalid();\n }\n\n return {\n work: { id: input.work.id, title: input.work.title },\n workKey: input.workKey,\n environment: input.environment,\n currency: input.currency,\n amount: { minCents: 100, maxCents: 20_000, stepCents: 1 },\n providers: [...input.providers],\n };\n}\n\nfunction parseHeadlessResult(\n input: unknown,\n channel: string,\n config: TipConfig,\n amountCents: number,\n): TipOpenResult | undefined {\n if (typeof input !== 'object' || input === null || Array.isArray(input)) return undefined;\n const message = input as Record<string, unknown>;\n if (\n message.type !== 'viceme:tip-headless-result' ||\n message.channel !== channel ||\n message.workKey !== config.workKey\n ) {\n return undefined;\n }\n if (message.status === 'PAID') {\n if (\n !isStrictRecord(message, HEADLESS_PAID_KEYS) ||\n !isStrictRecord(message.work, TIP_WORK_KEYS) ||\n message.work.id !== config.work.id ||\n message.work.title !== config.work.title ||\n message.amountCents !== amountCents ||\n message.currency !== 'CNY'\n ) {\n return undefined;\n }\n return {\n status: 'PAID',\n work: { id: config.work.id, title: config.work.title },\n amountCents,\n currency: 'CNY',\n };\n }\n if (\n (message.status === 'CANCELLED' || message.status === 'UNKNOWN') &&\n isStrictRecord(message, HEADLESS_TERMINAL_KEYS)\n ) {\n return { status: message.status };\n }\n return undefined;\n}\n\nfunction internalTipError(): ViceMeError {\n return new ViceMeError({\n code: 'INTERNAL_ERROR',\n message: 'Unable to open the hosted Tip flow.',\n capability: 'tip',\n });\n}\n\nfunction tipCapabilityDisabled(): ViceMeError {\n return new ViceMeError({\n code: 'CAPABILITY_DISABLED',\n message: 'Tip is not available for this Work or region.',\n retryable: false,\n capability: 'tip',\n });\n}\n\nasync function readTipConfigBody(response: Response): Promise<unknown> {\n const contentLength = response.headers.get('content-length');\n if (contentLength !== null) {\n const declaredBytes = Number(contentLength);\n if (\n !Number.isInteger(declaredBytes) ||\n declaredBytes < 0 ||\n declaredBytes > TIP_CONFIG_MAX_BYTES\n ) {\n await response.body?.cancel().catch(() => undefined);\n throw tipConfigInvalid();\n }\n }\n\n const reader = response.body?.getReader();\n if (!reader) throw tipConfigInvalid();\n\n const decoder = new TextDecoder('utf-8', { fatal: true });\n let bytes = 0;\n let text = '';\n try {\n while (true) {\n const chunk = await reader.read();\n if (chunk.done) break;\n bytes += chunk.value.byteLength;\n if (bytes > TIP_CONFIG_MAX_BYTES) {\n await reader.cancel().catch(() => undefined);\n throw tipConfigInvalid();\n }\n try {\n text += decoder.decode(chunk.value, { stream: true });\n } catch {\n await reader.cancel().catch(() => undefined);\n throw tipConfigInvalid();\n }\n }\n try {\n text += decoder.decode();\n } catch {\n await reader.cancel().catch(() => undefined);\n throw tipConfigInvalid();\n }\n } finally {\n reader.releaseLock();\n }\n\n try {\n return JSON.parse(text) as unknown;\n } catch {\n throw tipConfigInvalid();\n }\n}\n\nasync function fetchTipConfig(client: ViceMeClient, ownerSignal: AbortSignal): Promise<TipConfig> {\n await client.ready();\n if (!client.hasCapability('tip')) throw tipCapabilityDisabled();\n if (client.region !== 'cn') throw tipCapabilityDisabled();\n if (ownerSignal.aborted) throw clientDestroyed();\n const controller = new AbortController();\n const abortRequest = (): void => controller.abort();\n ownerSignal.addEventListener('abort', abortRequest, { once: true });\n const timeout = globalThis.setTimeout(() => controller.abort(), TIP_CONFIG_TIMEOUT_MS);\n const widgetOrigin = BUILD_WIDGET_ORIGINS[client.region];\n const requestUrl = new URL(\n `/v1/work-sdk/${encodeURIComponent(client.workKey)}/tip-config`,\n widgetOrigin,\n );\n try {\n const response = await fetch(requestUrl.toString(), {\n method: 'GET',\n credentials: 'omit',\n redirect: 'error',\n headers: { accept: 'application/json' },\n signal: controller.signal,\n });\n const contentType = response.headers\n .get('content-type')\n ?.split(';', 1)[0]\n ?.trim()\n .toLowerCase();\n let responseOrigin: string | undefined;\n try {\n responseOrigin = response.url ? new URL(response.url).origin : undefined;\n } catch {\n responseOrigin = 'invalid';\n }\n if (response.status !== 200) {\n if (response.status === 404) {\n await response.body?.cancel().catch(() => undefined);\n throw tipCapabilityDisabled();\n }\n if (\n response.status === 400 &&\n contentType === 'application/json' &&\n (!responseOrigin || responseOrigin === widgetOrigin)\n ) {\n let body: unknown;\n try {\n body = await readTipConfigBody(response);\n } catch {\n throw internalTipError();\n }\n if (isCredentialsNotAllowedError(body)) {\n throw tipConfigCredentialsNotAllowed(body.requestId);\n }\n } else {\n await response.body?.cancel().catch(() => undefined);\n }\n throw new ViceMeError({\n code: 'INTERNAL_ERROR',\n message: 'Unable to load Tip configuration.',\n capability: 'tip',\n });\n }\n if (contentType !== 'application/json' || (responseOrigin && responseOrigin !== widgetOrigin)) {\n await response.body?.cancel().catch(() => undefined);\n throw tipConfigInvalid();\n }\n const body = await readTipConfigBody(response);\n return parseTipConfig(body, client.workKey);\n } catch (error) {\n if (ownerSignal.aborted) throw clientDestroyed();\n if (error instanceof ViceMeError) throw error;\n throw internalTipError();\n } finally {\n controller.abort();\n globalThis.clearTimeout(timeout);\n ownerSignal.removeEventListener('abort', abortRequest);\n }\n}\n\nfunction copyTipConfig(config: TipConfig): TipConfig {\n return {\n work: { ...config.work },\n workKey: config.workKey,\n environment: config.environment,\n currency: config.currency,\n amount: { ...config.amount },\n providers: [...config.providers],\n };\n}\n\nexport function createHeadlessTip(client: ViceMeClient): TipClient {\n let destroyed = false;\n let cancelActive: (() => void) | undefined;\n let configPromise: Promise<TipConfig> | undefined;\n const configController = new AbortController();\n const isDestroyed = (): boolean => destroyed || client.state === 'DESTROYED';\n\n const loadTrustedConfig = (): Promise<TipConfig> => {\n if (!configPromise) {\n const pending = fetchTipConfig(client, configController.signal);\n configPromise = pending;\n void pending.then(\n () => {\n if (configPromise === pending) configPromise = undefined;\n },\n () => {\n if (configPromise === pending) configPromise = undefined;\n },\n );\n }\n return configPromise;\n };\n\n return {\n async getConfig(): Promise<TipConfig> {\n if (isDestroyed()) throw clientDestroyed();\n const config = await loadTrustedConfig();\n if (isDestroyed()) throw clientDestroyed();\n return copyTipConfig(config);\n },\n\n open(input: TipOpenOptions): Promise<TipOpenResult> {\n if (isDestroyed()) return Promise.reject(clientDestroyed());\n if (cancelActive) {\n return Promise.reject(\n new ViceMeError({\n code: 'TIP_OPEN_IN_PROGRESS',\n message: 'This Tip client already has an open flow.',\n retryable: false,\n capability: 'tip',\n }),\n );\n }\n if (!client.hasCapability('tip')) {\n return Promise.reject(tipCapabilityDisabled());\n }\n if (client.region !== 'cn') return Promise.reject(tipCapabilityDisabled());\n\n let options: TipOpenOptions;\n try {\n options = parseTipOpenOptions(input);\n } catch (error) {\n return Promise.reject(error);\n }\n\n if (typeof document === 'undefined') {\n return Promise.reject(tipOptionInvalid());\n }\n const documentObject = document;\n const windowObject = documentObject.defaultView;\n if (!documentObject.body || !windowObject) return Promise.reject(tipOptionInvalid());\n const widgetOrigin = BUILD_WIDGET_ORIGINS[client.region];\n const hostLanguage = documentObject.documentElement.lang || windowObject.navigator.language;\n const locale =\n options.locale ?? (hostLanguage.toLowerCase().startsWith('zh') ? 'zh-CN' : 'en-US');\n const requestedAppearance = options.appearance ?? 'auto';\n const appearance: WidgetAppearance =\n requestedAppearance === 'auto'\n ? windowObject.matchMedia('(prefers-color-scheme: dark)').matches\n ? 'dark'\n : 'light'\n : requestedAppearance;\n\n let channel: string;\n let clientReady: Promise<void>;\n try {\n const channelBytes = new Uint8Array(16);\n windowObject.crypto.getRandomValues(channelBytes);\n channel = Array.from(channelBytes, (byte) => byte.toString(16).padStart(2, '0')).join('');\n clientReady = client.ready();\n } catch {\n return Promise.reject(internalTipError());\n }\n\n const portal = documentObject.createElement('div');\n portal.dataset.vicemeTipHeadless = 'open';\n portal.style.all = 'initial';\n portal.style.position = 'fixed';\n portal.style.inset = '0';\n portal.style.display = 'block';\n portal.style.width = '100vw';\n portal.style.height = '100vh';\n portal.style.zIndex = '2147483647';\n\n const frame = documentObject.createElement('iframe');\n const frameUrl = new URL(`/widget/tip/${encodeURIComponent(client.workKey)}`, widgetOrigin);\n frameUrl.searchParams.set('mode', 'headless');\n frameUrl.searchParams.set('channel', channel);\n frameUrl.searchParams.set('appearance', appearance);\n frameUrl.searchParams.set('locale', locale);\n frame.title = 'ViceMe Tip';\n frame.src = frameUrl.toString();\n frame.loading = 'eager';\n frame.referrerPolicy = 'strict-origin';\n frame.setAttribute(\n 'sandbox',\n 'allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts',\n );\n frame.setAttribute('allow', 'payment');\n frame.style.display = 'block';\n frame.style.width = '100%';\n frame.style.height = '100%';\n frame.style.border = '0';\n frame.style.background = 'transparent';\n frame.style.colorScheme = appearance;\n portal.attachShadow({ mode: 'open' }).append(frame);\n\n let settled = false;\n let ready = false;\n let initialized = false;\n let trustedConfig: TipConfig | undefined;\n let readyTimer: number | undefined;\n let resolveOpen: (result: TipOpenResult) => void;\n let rejectOpen: (error: unknown) => void;\n const pending = new Promise<TipOpenResult>((resolve, reject) => {\n resolveOpen = resolve;\n rejectOpen = reject;\n });\n\n const cleanup = (): void => {\n if (readyTimer !== undefined) {\n windowObject.clearTimeout(readyTimer);\n readyTimer = undefined;\n }\n windowObject.removeEventListener('message', onMessage);\n portal.remove();\n if (cancelActive === cancel) cancelActive = undefined;\n };\n const finish = (result: TipOpenResult): void => {\n if (settled) return;\n settled = true;\n cleanup();\n resolveOpen(result);\n };\n const fail = (error: unknown): void => {\n if (settled) return;\n settled = true;\n cleanup();\n rejectOpen(error);\n };\n const cancel = (): void => finish({ status: 'UNKNOWN' });\n const initialize = (): void => {\n if (!ready || !trustedConfig || initialized || settled) return;\n if (options.provider && !trustedConfig.providers.includes(options.provider)) {\n fail(tipOptionInvalid());\n return;\n }\n initialized = true;\n const init = {\n type: 'viceme:tip-headless-init',\n channel,\n workKey: client.workKey,\n amountCents: options.amountCents,\n ...(options.provider === undefined ? {} : { provider: options.provider }),\n locale,\n appearance,\n };\n try {\n const frameWindow = frame.contentWindow;\n if (!frameWindow) {\n fail(internalTipError());\n return;\n }\n frameWindow.postMessage(init, widgetOrigin);\n } catch {\n fail(internalTipError());\n }\n };\n const onMessage = (event: MessageEvent<unknown>): void => {\n if (event.origin !== widgetOrigin || event.source !== frame.contentWindow) return;\n if (!initialized) {\n if (!isStrictRecord(event.data, HEADLESS_READY_KEYS)) return;\n if (\n event.data.type !== 'viceme:tip-headless-ready' ||\n event.data.channel !== channel ||\n event.data.workKey !== client.workKey\n ) {\n return;\n }\n ready = true;\n if (readyTimer !== undefined) {\n windowObject.clearTimeout(readyTimer);\n readyTimer = undefined;\n }\n initialize();\n return;\n }\n if (!trustedConfig) return;\n const result = parseHeadlessResult(event.data, channel, trustedConfig, options.amountCents);\n if (result && result.status !== 'UNKNOWN') finish(result);\n };\n\n cancelActive = cancel;\n windowObject.addEventListener('message', onMessage);\n readyTimer = windowObject.setTimeout(() => {\n fail(\n new ViceMeError({\n code: 'TIP_READY_TIMEOUT',\n message: 'Hosted Tip did not become ready in time.',\n retryable: true,\n capability: 'tip',\n }),\n );\n }, HEADLESS_READY_TIMEOUT_MS);\n documentObject.body.append(portal);\n void clientReady.catch((error: unknown) => {\n fail(error instanceof ViceMeError ? error : internalTipError());\n });\n void loadTrustedConfig()\n .then((config) => {\n trustedConfig = config;\n initialize();\n })\n .catch((error: unknown) => {\n fail(error instanceof ViceMeError ? error : internalTipError());\n });\n\n return pending;\n },\n\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n configController.abort();\n cancelActive?.();\n },\n };\n}\n","/** Stable, allowlisted `viceme:*` DOM events shared by hosted capabilities. */\n\nimport type { ViceMeErrorCode } from './core/errors.ts';\n\nexport interface VicemeReadyDetail {\n clientKey: string;\n workKey: string;\n capabilities: string[];\n version: string;\n}\n\nexport interface VicemeCapabilityReadyDetail {\n clientKey: string;\n instanceKey: string;\n capability: string;\n version: string;\n}\n\nexport interface VicemeErrorDetail {\n clientKey?: string;\n instanceKey?: string;\n capability?: string;\n code: ViceMeErrorCode;\n retryable: boolean;\n requestId?: string;\n}\n\nexport interface VicemeDestroyedDetail {\n clientKey: string;\n instanceKey: string;\n capability: string;\n}\n\nexport interface VicemeWidgetCloseDetail {\n workId: string;\n}\n\nexport interface VicemeTipPaidDetail {\n status: 'PAID';\n work: {\n id: string;\n title: string;\n };\n amountCents: number;\n currency: 'CNY';\n}\n\nexport type VicemeEventType =\n | 'viceme:ready'\n | 'viceme:capability-ready'\n | 'viceme:error'\n | 'viceme:destroyed'\n | 'viceme:widget-close'\n | 'viceme:tip-paid';\n\nexport type VicemeEventDetailMap = {\n 'viceme:ready': VicemeReadyDetail;\n 'viceme:capability-ready': VicemeCapabilityReadyDetail;\n 'viceme:error': VicemeErrorDetail;\n 'viceme:destroyed': VicemeDestroyedDetail;\n 'viceme:widget-close': VicemeWidgetCloseDetail;\n 'viceme:tip-paid': VicemeTipPaidDetail;\n};\n\nconst ALLOWED_KEYS: ReadonlyMap<VicemeEventType, ReadonlySet<string>> = new Map([\n ['viceme:ready', new Set(['clientKey', 'workKey', 'capabilities', 'version'])],\n ['viceme:capability-ready', new Set(['clientKey', 'instanceKey', 'capability', 'version'])],\n [\n 'viceme:error',\n new Set(['clientKey', 'instanceKey', 'capability', 'code', 'retryable', 'requestId']),\n ],\n ['viceme:destroyed', new Set(['clientKey', 'instanceKey', 'capability'])],\n ['viceme:widget-close', new Set(['workId'])],\n ['viceme:tip-paid', new Set(['status', 'work', 'amountCents', 'currency'])],\n]);\n\n/** Strip anything outside the documented allowlist before dispatch. */\nexport function sanitizeDetail(\n type: VicemeEventType,\n detail: VicemeEventDetailMap[VicemeEventType],\n): VicemeEventDetailMap[VicemeEventType] {\n if (type === 'viceme:tip-paid') {\n const paid = detail as VicemeTipPaidDetail;\n return {\n status: paid.status,\n work: { id: paid.work.id, title: paid.work.title },\n amountCents: paid.amountCents,\n currency: paid.currency,\n };\n }\n const allowed = ALLOWED_KEYS.get(type)!;\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(detail)) {\n if (allowed.has(key) && value !== undefined) result[key] = value;\n }\n return result as unknown as VicemeEventDetailMap[VicemeEventType];\n}\n\nexport function dispatchViceMeEvent<K extends VicemeEventType>(\n target: EventTarget,\n type: K,\n detail: VicemeEventDetailMap[K],\n): void {\n const event = new CustomEvent(type, {\n detail: sanitizeDetail(type, detail),\n bubbles: true,\n composed: true,\n cancelable: false,\n });\n target.dispatchEvent(event);\n}\n","import type { ViceMeClient } from '../core/client.ts';\nimport { BUILD_WIDGET_ORIGINS } from '../core/build-endpoints.ts';\nimport { clientDestroyed, ViceMeError } from '../core/errors.ts';\nimport { dispatchViceMeEvent } from '../browser-events.ts';\nimport type { CapabilityMountHandle, CapabilityMountOptions } from '../capability-mount.ts';\nimport { isValidTipWorkTitle } from './validation.ts';\n\ntype WidgetAppearance = 'light' | 'dark';\n\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst TIP_AMOUNT_MIN = 100;\nconst TIP_AMOUNT_MAX = 20_000;\nconst WIDGET_HEIGHT_MAX = 2_048;\nexport const FRAME_READY_TIMEOUT_MS = 8_000;\nconst RESIZE_MESSAGE_KEYS = ['type', 'workId', 'work', 'height'];\nconst CLOSE_MESSAGE_KEYS = ['type', 'workId'];\nconst PAID_MESSAGE_KEYS = ['type', 'workKey', 'status', 'work', 'amountCents', 'currency'];\nconst WORK_KEYS = ['id', 'title'];\n\nfunction isStrictRecord(value: unknown, keys: string[]): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false;\n const actualKeys = Object.keys(value);\n return actualKeys.length === keys.length && keys.every((key) => actualKeys.includes(key));\n}\n\nexport async function mount(\n client: ViceMeClient,\n options: CapabilityMountOptions,\n): Promise<CapabilityMountHandle> {\n if (options.signal?.aborted) throw clientDestroyed();\n await client.ready();\n if (options.signal?.aborted) throw clientDestroyed();\n if (!client.hasCapability('tip')) {\n throw new ViceMeError({\n code: 'CAPABILITY_DISABLED',\n message: 'Tip is not available in this SDK build.',\n retryable: false,\n capability: 'tip',\n });\n }\n if (client.region !== 'cn') {\n throw new ViceMeError({\n code: 'CAPABILITY_DISABLED',\n message: 'Tip is not available in this region.',\n retryable: false,\n capability: 'tip',\n });\n }\n const documentObject = options.target.ownerDocument;\n const windowObject = documentObject.defaultView;\n if (!windowObject) {\n throw new ViceMeError({\n code: 'CONFIG_INVALID',\n message: 'Tip requires a browser document.',\n retryable: false,\n capability: 'tip',\n });\n }\n\n const widgetOrigin = BUILD_WIDGET_ORIGINS[client.region];\n const mediaQuery =\n options.theme === 'auto' ? windowObject.matchMedia('(prefers-color-scheme: dark)') : undefined;\n let appearance: WidgetAppearance =\n options.theme === 'auto' ? (mediaQuery?.matches ? 'dark' : 'light') : options.theme;\n let destroyed = false;\n let readyTimer: number | undefined;\n let boundWork: { id: string; title: string } | undefined;\n\n const portal = documentObject.createElement('div');\n portal.dataset.vicemeTip = 'mounted';\n portal.style.all = 'initial';\n portal.style.display = 'block';\n portal.style.width = '100%';\n portal.style.maxWidth = '100%';\n portal.style.contain = 'layout style';\n\n const shadow = portal.attachShadow({ mode: 'open' });\n const frame = documentObject.createElement('iframe');\n const frameUrl = new URL(`/widget/tip/${encodeURIComponent(client.workKey)}`, widgetOrigin);\n frameUrl.searchParams.set('appearance', appearance);\n frame.title = 'ViceMe Tip';\n frame.src = frameUrl.toString();\n frame.loading = 'eager';\n frame.referrerPolicy = 'strict-origin';\n frame.setAttribute(\n 'sandbox',\n 'allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts',\n );\n frame.setAttribute('allow', 'payment');\n frame.style.boxSizing = 'border-box';\n frame.style.display = 'block';\n frame.style.width = '100%';\n frame.style.height = '0px';\n frame.style.margin = '0';\n frame.style.border = '0';\n frame.style.background = 'transparent';\n frame.style.colorScheme = appearance;\n frame.style.pointerEvents = 'none';\n shadow.append(frame);\n\n let resolveReady: (() => void) | undefined;\n let rejectReady: ((error: ViceMeError) => void) | undefined;\n const readiness = new Promise<void>((resolve, reject) => {\n resolveReady = resolve;\n rejectReady = reject;\n readyTimer = windowObject.setTimeout(() => {\n reject(\n new ViceMeError({\n code: 'INTERNAL_ERROR',\n message: 'Hosted Tip widget did not become ready in time.',\n retryable: true,\n capability: 'tip',\n }),\n );\n }, FRAME_READY_TIMEOUT_MS);\n });\n\n const onMessage = (event: MessageEvent<unknown>): void => {\n if (event.origin !== widgetOrigin || event.source !== frame.contentWindow) return;\n const message = event.data;\n if (typeof message !== 'object' || message === null || Array.isArray(message)) return;\n\n if (isStrictRecord(message, RESIZE_MESSAGE_KEYS) && message.type === 'viceme:widget-resize') {\n if (\n typeof message.workId !== 'string' ||\n !UUID_PATTERN.test(message.workId) ||\n !isStrictRecord(message.work, WORK_KEYS) ||\n message.work.id !== message.workId ||\n !isValidTipWorkTitle(message.work.title) ||\n typeof message.height !== 'number' ||\n !Number.isInteger(message.height) ||\n message.height < 1 ||\n message.height > WIDGET_HEIGHT_MAX ||\n (boundWork !== undefined &&\n (message.work.id !== boundWork.id || message.work.title !== boundWork.title))\n ) {\n return;\n }\n frame.style.height = `${message.height}px`;\n if (boundWork === undefined) {\n boundWork = { id: message.workId, title: message.work.title };\n frame.style.pointerEvents = 'auto';\n if (readyTimer !== undefined) {\n windowObject.clearTimeout(readyTimer);\n readyTimer = undefined;\n }\n resolveReady?.();\n }\n return;\n }\n\n if (isStrictRecord(message, CLOSE_MESSAGE_KEYS) && message.type === 'viceme:widget-close') {\n if (typeof message.workId !== 'string' || message.workId !== boundWork?.id) return;\n dispatchViceMeEvent(options.target, 'viceme:widget-close', { workId: message.workId });\n return;\n }\n if (\n isStrictRecord(message, PAID_MESSAGE_KEYS) &&\n message.type === 'viceme:tip-paid' &&\n message.workKey === client.workKey &&\n isStrictRecord(message.work, WORK_KEYS) &&\n boundWork !== undefined &&\n typeof message.work.id === 'string' &&\n message.work.id === boundWork.id &&\n isValidTipWorkTitle(message.work.title) &&\n message.work.title === boundWork.title &&\n message.status === 'PAID' &&\n typeof message.amountCents === 'number' &&\n Number.isInteger(message.amountCents) &&\n message.amountCents >= TIP_AMOUNT_MIN &&\n message.amountCents <= TIP_AMOUNT_MAX &&\n message.currency === 'CNY'\n ) {\n dispatchViceMeEvent(options.target, 'viceme:tip-paid', {\n status: 'PAID',\n work: { id: message.work.id, title: message.work.title },\n amountCents: message.amountCents,\n currency: 'CNY',\n });\n }\n };\n\n const onAppearanceChange = (event: MediaQueryListEvent): void => {\n appearance = event.matches ? 'dark' : 'light';\n frame.style.colorScheme = appearance;\n frame.contentWindow?.postMessage(\n { type: 'viceme:widget-appearance', appearance },\n widgetOrigin,\n );\n };\n\n let removeAppearanceListener: (() => void) | undefined;\n const onAbort = (): void => {\n rejectReady?.(clientDestroyed());\n cleanup();\n };\n const cleanup = (): void => {\n if (destroyed) return;\n destroyed = true;\n if (readyTimer !== undefined) windowObject.clearTimeout(readyTimer);\n windowObject.removeEventListener('message', onMessage);\n removeAppearanceListener?.();\n options.signal?.removeEventListener('abort', onAbort);\n portal.remove();\n };\n\n try {\n windowObject.addEventListener('message', onMessage);\n if (mediaQuery) {\n if (typeof mediaQuery.addEventListener === 'function') {\n mediaQuery.addEventListener('change', onAppearanceChange);\n removeAppearanceListener = () =>\n mediaQuery.removeEventListener('change', onAppearanceChange);\n } else {\n mediaQuery.addListener(onAppearanceChange);\n removeAppearanceListener = () => mediaQuery.removeListener(onAppearanceChange);\n }\n }\n options.signal?.addEventListener('abort', onAbort, { once: true });\n if (options.signal?.aborted) throw clientDestroyed();\n options.target.appendChild(portal);\n await readiness;\n } catch (error) {\n cleanup();\n throw error;\n }\n\n return { capability: 'tip', destroy: cleanup };\n}\n","import type { ViceMeClient } from '../core/client.ts';\nimport { createHeadlessTip } from './headless.ts';\nimport { mount } from './mount.ts';\n\nexport type TipProvider = 'WECHAT_PAY' | 'ALIPAY';\n\nexport interface TipConfig {\n work: {\n id: string;\n title: string;\n };\n workKey: string;\n environment: 'SANDBOX' | 'PRODUCTION';\n currency: 'CNY';\n amount: {\n minCents: 100;\n maxCents: 20_000;\n stepCents: 1;\n };\n providers: TipProvider[];\n}\n\nexport interface TipOpenOptions {\n amountCents: number;\n provider?: TipProvider;\n locale?: 'zh-CN' | 'en-US';\n appearance?: 'light' | 'dark' | 'auto';\n}\n\nexport type TipOpenResult =\n | {\n status: 'PAID';\n work: {\n id: string;\n title: string;\n };\n amountCents: number;\n currency: 'CNY';\n }\n | { status: 'CANCELLED' }\n | { status: 'UNKNOWN' };\n\nexport interface TipClient {\n getConfig(): Promise<TipConfig>;\n open(options: TipOpenOptions): Promise<TipOpenResult>;\n destroy(): void;\n}\n\nexport interface TipMountOptions {\n target: Element;\n theme: 'light' | 'dark' | 'auto';\n signal?: AbortSignal;\n}\n\nexport interface TipMountHandle {\n readonly capability: 'tip';\n destroy(): void;\n}\n\nexport interface TipWidgetCloseDetail {\n workId: string;\n}\n\nexport interface TipPaidDetail {\n status: 'PAID';\n work: {\n id: string;\n title: string;\n };\n amountCents: number;\n currency: 'CNY';\n}\n\nconst mounts = new WeakMap<ViceMeClient, WeakMap<Element, Promise<TipMountHandle>>>();\n\n/** Create a framework-independent controller for a host-rendered Tip flow. */\nexport function createTip(client: ViceMeClient): TipClient {\n return createHeadlessTip(client);\n}\n\n/** Explicit ESM/npm entry point; the CDN loader calls the same mount function. */\nexport function mountTip(client: ViceMeClient, options: TipMountOptions): Promise<TipMountHandle> {\n let byTarget = mounts.get(client);\n if (!byTarget) {\n byTarget = new WeakMap();\n mounts.set(client, byTarget);\n }\n const existing = byTarget.get(options.target);\n if (existing) return existing;\n\n const pending: Promise<TipMountHandle> = mount(client, options)\n .then((raw) => {\n let destroyed = false;\n const handle: TipMountHandle = {\n capability: 'tip' as const,\n destroy(): void {\n if (destroyed) return;\n destroyed = true;\n options.signal?.removeEventListener('abort', handle.destroy);\n if (byTarget.get(options.target) === pending) byTarget.delete(options.target);\n raw.destroy();\n },\n };\n options.signal?.addEventListener('abort', handle.destroy, { once: true });\n if (options.signal?.aborted) handle.destroy();\n return handle;\n })\n .catch((error: unknown) => {\n if (byTarget.get(options.target) === pending) byTarget.delete(options.target);\n throw error;\n });\n byTarget.set(options.target, pending);\n return pending;\n}\n"],"names":["TIP_CONFIG_KEYS","TIP_WORK_KEYS","TIP_AMOUNT_KEYS","PUBLIC_ERROR_KEYS","HEADLESS_READY_KEYS","HEADLESS_PAID_KEYS","HEADLESS_TERMINAL_KEYS","HEADLESS_READY_TIMEOUT_MS","TIP_CONFIG_TIMEOUT_MS","TIP_CONFIG_MAX_BYTES","UUID_PATTERN","isStrictRecord","value","keys","actualKeys","key","tipConfigInvalid","ViceMeError","isCredentialsNotAllowedError","input","tipConfigCredentialsNotAllowed","requestId","parseTipConfig","expectedWorkKey","isValidTipWorkTitle","isTipProvider","parseHeadlessResult","channel","config","amountCents","message","internalTipError","tipCapabilityDisabled","readTipConfigBody","response","contentLength","declaredBytes","reader","decoder","bytes","text","chunk","fetchTipConfig","client","ownerSignal","clientDestroyed","controller","abortRequest","timeout","widgetOrigin","BUILD_WIDGET_ORIGINS","requestUrl","contentType","responseOrigin","body","error","copyTipConfig","createHeadlessTip","destroyed","cancelActive","configPromise","configController","isDestroyed","loadTrustedConfig","pending","options","parseTipOpenOptions","tipOptionInvalid","documentObject","windowObject","hostLanguage","locale","requestedAppearance","appearance","clientReady","channelBytes","byte","portal","frame","frameUrl","settled","ready","initialized","trustedConfig","readyTimer","resolveOpen","rejectOpen","resolve","reject","cleanup","onMessage","cancel","finish","result","fail","initialize","init","frameWindow","event","ALLOWED_KEYS","sanitizeDetail","type","detail","paid","allowed","dispatchViceMeEvent","target","TIP_AMOUNT_MIN","TIP_AMOUNT_MAX","WIDGET_HEIGHT_MAX","FRAME_READY_TIMEOUT_MS","RESIZE_MESSAGE_KEYS","CLOSE_MESSAGE_KEYS","PAID_MESSAGE_KEYS","WORK_KEYS","mount","mediaQuery","boundWork","shadow","resolveReady","rejectReady","readiness","onAppearanceChange","removeAppearanceListener","onAbort","mounts","createTip","mountTip","byTarget","existing","raw","handle"],"mappings":"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"}
@@ -8,12 +8,14 @@
8
8
  */
9
9
  export interface TransportRequest {
10
10
  method: 'GET' | 'POST' | 'PUT' | 'DELETE';
11
- /** Absolute path under the public API base, e.g. `/v1/public/v1/work-sessions`. */
11
+ /** Absolute path under the public API base. */
12
12
  path: string;
13
13
  /** JSON-serializable request body. */
14
14
  body?: unknown;
15
15
  /** Work-session token. It is never persisted by the transport. */
16
16
  authorization?: string;
17
+ /** Optional memory-only signed-in widget token. */
18
+ userAuthorization?: string;
17
19
  signal?: AbortSignal;
18
20
  /** Per-request timeout; defaults to the transport default. */
19
21
  timeoutMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,mFAAmF;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAC;CAClC;AAqED,qBAAa,cAAe,YAAW,SAAS;;gBAMlC,OAAO,EAAE,qBAAqB;IAOpC,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAuGrE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,CAE9E"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport/transport.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;IAC1C,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAC;CAClC;AAqED,qBAAa,cAAe,YAAW,SAAS;;gBAMlC,OAAO,EAAE,qBAAqB;IAOpC,OAAO,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC;CA0GrE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,CAE9E"}
package/dist/version.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * Kept in sync with `packages/sdk/package.json#version`; a unit test enforces
5
5
  * the match so the loader, release manifest, and npm metadata can never drift.
6
6
  */
7
- export declare const SDK_VERSION = "0.3.0";
7
+ export declare const SDK_VERSION = "0.6.1";
8
8
  /** Public API major carried by this build (loader namespace `v1`). */
9
9
  export declare const API_MAJOR = 1;
10
10
  //# sourceMappingURL=version.d.ts.map