@youidian/sdk 3.1.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.cjs +547 -2
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +2 -1
- package/dist/client.d.ts +2 -1
- package/dist/client.js +543 -1
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +386 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -2
- package/dist/index.d.ts +1 -2
- package/dist/index.js +388 -153
- package/dist/index.js.map +1 -1
- package/dist/login-D_VaJqQX.d.cts +86 -0
- package/dist/login-D_VaJqQX.d.ts +86 -0
- package/dist/login.cjs +277 -41
- package/dist/login.cjs.map +1 -1
- package/dist/login.d.cts +1 -62
- package/dist/login.d.ts +1 -62
- package/dist/login.js +275 -40
- package/dist/login.js.map +1 -1
- package/package.json +36 -24
- package/dist/hosted-modal-BZmYmXTU.d.cts +0 -20
- package/dist/hosted-modal-BZmYmXTU.d.ts +0 -20
package/dist/client.cjs
CHANGED
|
@@ -22,12 +22,92 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
|
|
|
22
22
|
// src/client.ts
|
|
23
23
|
var client_exports = {};
|
|
24
24
|
__export(client_exports, {
|
|
25
|
+
LoginUI: () => LoginUI,
|
|
25
26
|
PaymentUI: () => PaymentUI,
|
|
26
|
-
|
|
27
|
+
createLoginUI: () => createLoginUI,
|
|
28
|
+
createPaymentUI: () => createPaymentUI,
|
|
29
|
+
handleLoginCallbackIfPresent: () => handleLoginCallbackIfPresent
|
|
27
30
|
});
|
|
28
31
|
module.exports = __toCommonJS(client_exports);
|
|
29
32
|
|
|
30
33
|
// src/hosted-modal.ts
|
|
34
|
+
var SDK_SUPPORTED_LOCALES = [
|
|
35
|
+
"en",
|
|
36
|
+
"zh-CN",
|
|
37
|
+
"zh-Hant",
|
|
38
|
+
"fr",
|
|
39
|
+
"de",
|
|
40
|
+
"ja",
|
|
41
|
+
"es",
|
|
42
|
+
"ko",
|
|
43
|
+
"nl",
|
|
44
|
+
"it",
|
|
45
|
+
"pt"
|
|
46
|
+
];
|
|
47
|
+
var SDK_DEFAULT_LOCALE = "zh-CN";
|
|
48
|
+
var SDK_LOCALE_ALIASES = {
|
|
49
|
+
en: "en",
|
|
50
|
+
"en-us": "en",
|
|
51
|
+
"en-gb": "en",
|
|
52
|
+
zh: "zh-CN",
|
|
53
|
+
"zh-cn": "zh-CN",
|
|
54
|
+
"zh-tw": "zh-Hant",
|
|
55
|
+
"zh-hk": "zh-Hant",
|
|
56
|
+
"zh-hant": "zh-Hant",
|
|
57
|
+
"zh-hans": "zh-CN",
|
|
58
|
+
fr: "fr",
|
|
59
|
+
de: "de",
|
|
60
|
+
ja: "ja",
|
|
61
|
+
es: "es",
|
|
62
|
+
ko: "ko",
|
|
63
|
+
nl: "nl",
|
|
64
|
+
it: "it",
|
|
65
|
+
pt: "pt"
|
|
66
|
+
};
|
|
67
|
+
function matchSupportedBaseLocale(locale) {
|
|
68
|
+
const base = locale.toLowerCase().split("-")[0];
|
|
69
|
+
return SDK_SUPPORTED_LOCALES.find((item) => item.toLowerCase() === base);
|
|
70
|
+
}
|
|
71
|
+
function normalizeSdkLocale(locale) {
|
|
72
|
+
if (!locale) return;
|
|
73
|
+
const sanitized = locale.trim().replace(/_/g, "-");
|
|
74
|
+
if (!sanitized) return;
|
|
75
|
+
const lower = sanitized.toLowerCase();
|
|
76
|
+
if (SDK_LOCALE_ALIASES[lower]) {
|
|
77
|
+
return SDK_LOCALE_ALIASES[lower];
|
|
78
|
+
}
|
|
79
|
+
let canonical;
|
|
80
|
+
try {
|
|
81
|
+
canonical = Intl.getCanonicalLocales(sanitized)[0];
|
|
82
|
+
} catch {
|
|
83
|
+
canonical = void 0;
|
|
84
|
+
}
|
|
85
|
+
const candidates = [canonical, sanitized].filter(Boolean);
|
|
86
|
+
for (const candidate of candidates) {
|
|
87
|
+
const candidateLower = candidate.toLowerCase();
|
|
88
|
+
if (SDK_LOCALE_ALIASES[candidateLower]) {
|
|
89
|
+
return SDK_LOCALE_ALIASES[candidateLower];
|
|
90
|
+
}
|
|
91
|
+
if (SDK_SUPPORTED_LOCALES.includes(candidate)) {
|
|
92
|
+
return candidate;
|
|
93
|
+
}
|
|
94
|
+
const baseMatch = matchSupportedBaseLocale(candidate);
|
|
95
|
+
if (baseMatch) {
|
|
96
|
+
return baseMatch;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function getBrowserLocale() {
|
|
101
|
+
if (typeof navigator === "undefined") return;
|
|
102
|
+
for (const candidate of navigator.languages || []) {
|
|
103
|
+
const normalized = normalizeSdkLocale(candidate);
|
|
104
|
+
if (normalized) return normalized;
|
|
105
|
+
}
|
|
106
|
+
return normalizeSdkLocale(navigator.language);
|
|
107
|
+
}
|
|
108
|
+
function getAutoResolvedLocale(locale) {
|
|
109
|
+
return normalizeSdkLocale(locale) || getBrowserLocale() || SDK_DEFAULT_LOCALE;
|
|
110
|
+
}
|
|
31
111
|
function applyLocaleToUrl(urlValue, locale) {
|
|
32
112
|
if (!locale) return urlValue;
|
|
33
113
|
try {
|
|
@@ -147,6 +227,468 @@ var HostedFrameModal = class {
|
|
|
147
227
|
}
|
|
148
228
|
};
|
|
149
229
|
|
|
230
|
+
// src/login.ts
|
|
231
|
+
function getOrigin(value) {
|
|
232
|
+
if (!value) return null;
|
|
233
|
+
try {
|
|
234
|
+
return new URL(value).origin;
|
|
235
|
+
} catch {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function createLoginCallbackState() {
|
|
240
|
+
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
241
|
+
return crypto.randomUUID().replace(/-/g, "");
|
|
242
|
+
}
|
|
243
|
+
return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}`;
|
|
244
|
+
}
|
|
245
|
+
function buildLoginCallbackUrl(callbackState, callbackUrl) {
|
|
246
|
+
const baseUrl = callbackUrl || window.location.href;
|
|
247
|
+
const url = new URL(baseUrl, window.location.href);
|
|
248
|
+
const returnHash = url.hash.replace(/^#/, "");
|
|
249
|
+
url.hash = "";
|
|
250
|
+
url.searchParams.set(LOGIN_CALLBACK_MARKER, "1");
|
|
251
|
+
url.searchParams.set(LOGIN_CALLBACK_STATE_PARAM, callbackState);
|
|
252
|
+
if (returnHash) {
|
|
253
|
+
url.searchParams.set(LOGIN_CALLBACK_RETURN_HASH_PARAM, returnHash);
|
|
254
|
+
} else {
|
|
255
|
+
url.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM);
|
|
256
|
+
}
|
|
257
|
+
return url.toString();
|
|
258
|
+
}
|
|
259
|
+
function buildLoginLaunchPayload(params, options, callbackState) {
|
|
260
|
+
const parentOrigin = typeof window !== "undefined" ? window.location.origin : void 0;
|
|
261
|
+
const callbackUrl = typeof window !== "undefined" && callbackState ? buildLoginCallbackUrl(callbackState, options?.callbackUrl) : void 0;
|
|
262
|
+
return {
|
|
263
|
+
autoClose: options?.autoClose ?? true,
|
|
264
|
+
callbackUrl,
|
|
265
|
+
callbackState,
|
|
266
|
+
origin: parentOrigin,
|
|
267
|
+
preferredChannel: params.preferredChannel
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function appendLoginLaunchHash(urlValue, payload) {
|
|
271
|
+
const hashParams = new URLSearchParams();
|
|
272
|
+
if (payload.autoClose === false) {
|
|
273
|
+
hashParams.set("ydAutoClose", "false");
|
|
274
|
+
}
|
|
275
|
+
if (payload.origin) {
|
|
276
|
+
hashParams.set("ydOrigin", payload.origin);
|
|
277
|
+
}
|
|
278
|
+
if (payload.callbackUrl) {
|
|
279
|
+
hashParams.set("ydCallbackUrl", payload.callbackUrl);
|
|
280
|
+
}
|
|
281
|
+
if (payload.preferredChannel) {
|
|
282
|
+
hashParams.set("ydPreferredChannel", payload.preferredChannel);
|
|
283
|
+
}
|
|
284
|
+
const hash = hashParams.toString();
|
|
285
|
+
if (!hash) {
|
|
286
|
+
return urlValue;
|
|
287
|
+
}
|
|
288
|
+
try {
|
|
289
|
+
const url = new URL(urlValue);
|
|
290
|
+
url.hash = hash;
|
|
291
|
+
return url.toString();
|
|
292
|
+
} catch (_error) {
|
|
293
|
+
return `${urlValue}#${hash}`;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function buildLoginPopupName(payload) {
|
|
297
|
+
return `youidian-login:${JSON.stringify(payload)}`;
|
|
298
|
+
}
|
|
299
|
+
function buildLoginUrl(params, options, launchPayload) {
|
|
300
|
+
const { appId, baseUrl = "https://pay.imgto.link", loginUrl } = params;
|
|
301
|
+
const rawBase = (loginUrl || baseUrl).replace(/\/$/, "");
|
|
302
|
+
const parentOrigin = launchPayload.origin;
|
|
303
|
+
let finalUrl;
|
|
304
|
+
try {
|
|
305
|
+
const url = new URL(rawBase);
|
|
306
|
+
if (!/\/auth\/connect\/[^/]+$/.test(url.pathname)) {
|
|
307
|
+
url.pathname = `${url.pathname.replace(/\/$/, "")}/auth/connect/${appId}`.replace(
|
|
308
|
+
/\/{2,}/g,
|
|
309
|
+
"/"
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
finalUrl = url.toString();
|
|
313
|
+
} catch (_error) {
|
|
314
|
+
if (/\/auth\/connect\/[^/]+$/.test(rawBase)) {
|
|
315
|
+
finalUrl = rawBase;
|
|
316
|
+
} else {
|
|
317
|
+
finalUrl = `${rawBase}/auth/connect/${appId}`.replace(/\/{2,}/g, "/");
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
finalUrl = applyLocaleToUrl(finalUrl, getAutoResolvedLocale(params.locale));
|
|
321
|
+
try {
|
|
322
|
+
const url = new URL(finalUrl);
|
|
323
|
+
if (params.preferredChannel) {
|
|
324
|
+
url.searchParams.set("preferredChannel", params.preferredChannel);
|
|
325
|
+
}
|
|
326
|
+
if (options?.autoClose === false) {
|
|
327
|
+
url.searchParams.set("autoClose", "false");
|
|
328
|
+
}
|
|
329
|
+
if (parentOrigin) {
|
|
330
|
+
url.searchParams.set("origin", parentOrigin);
|
|
331
|
+
}
|
|
332
|
+
if (launchPayload.callbackUrl) {
|
|
333
|
+
url.searchParams.set("callbackUrl", launchPayload.callbackUrl);
|
|
334
|
+
}
|
|
335
|
+
return appendLoginLaunchHash(url.toString(), launchPayload);
|
|
336
|
+
} catch (_error) {
|
|
337
|
+
const searchParams = new URLSearchParams();
|
|
338
|
+
if (params.preferredChannel) {
|
|
339
|
+
searchParams.set("preferredChannel", params.preferredChannel);
|
|
340
|
+
}
|
|
341
|
+
if (options?.autoClose === false) {
|
|
342
|
+
searchParams.set("autoClose", "false");
|
|
343
|
+
}
|
|
344
|
+
if (parentOrigin) {
|
|
345
|
+
searchParams.set("origin", parentOrigin);
|
|
346
|
+
}
|
|
347
|
+
if (launchPayload.callbackUrl) {
|
|
348
|
+
searchParams.set("callbackUrl", launchPayload.callbackUrl);
|
|
349
|
+
}
|
|
350
|
+
const query = searchParams.toString();
|
|
351
|
+
if (!query) {
|
|
352
|
+
return appendLoginLaunchHash(finalUrl, launchPayload);
|
|
353
|
+
}
|
|
354
|
+
const separator = finalUrl.includes("?") ? "&" : "?";
|
|
355
|
+
return appendLoginLaunchHash(
|
|
356
|
+
`${finalUrl}${separator}${query}`,
|
|
357
|
+
launchPayload
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function extractLoginResult(data) {
|
|
362
|
+
return {
|
|
363
|
+
avatar: data.avatar,
|
|
364
|
+
channel: data.channel,
|
|
365
|
+
email: data.email,
|
|
366
|
+
expiresAt: data.expiresAt,
|
|
367
|
+
legacyCasdoorId: data.legacyCasdoorId,
|
|
368
|
+
loginToken: data.loginToken,
|
|
369
|
+
name: data.name,
|
|
370
|
+
userId: data.userId,
|
|
371
|
+
wechatOpenId: data.wechatOpenId,
|
|
372
|
+
wechatUnionId: data.wechatUnionId
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
var LOGIN_UI_LOG_PREFIX = "[Youidian LoginUI]";
|
|
376
|
+
var LOGIN_CALLBACK_MARKER = "yd_login_callback";
|
|
377
|
+
var LOGIN_CALLBACK_RESULT_PARAM = "yd_login_result";
|
|
378
|
+
var LOGIN_CALLBACK_RETURN_HASH_PARAM = "yd_login_return_hash";
|
|
379
|
+
var LOGIN_CALLBACK_STATE_PARAM = "yd_login_state";
|
|
380
|
+
var LOGIN_CALLBACK_STORAGE_PREFIX = "yd-login-callback:";
|
|
381
|
+
function decodeCallbackPayload(value) {
|
|
382
|
+
try {
|
|
383
|
+
const padded = value.padEnd(
|
|
384
|
+
value.length + (4 - value.length % 4) % 4,
|
|
385
|
+
"="
|
|
386
|
+
);
|
|
387
|
+
const base64 = padded.replaceAll("-", "+").replaceAll("_", "/");
|
|
388
|
+
const binary = atob(base64);
|
|
389
|
+
const json = decodeURIComponent(
|
|
390
|
+
Array.from(
|
|
391
|
+
binary,
|
|
392
|
+
(char) => `%${char.charCodeAt(0).toString(16).padStart(2, "0")}`
|
|
393
|
+
).join("")
|
|
394
|
+
);
|
|
395
|
+
const parsed = JSON.parse(json);
|
|
396
|
+
return parsed && typeof parsed === "object" && parsed.type ? parsed : null;
|
|
397
|
+
} catch {
|
|
398
|
+
return null;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
function getLoginCallbackChannelName(state) {
|
|
402
|
+
return `youidian-login:${state}`;
|
|
403
|
+
}
|
|
404
|
+
function getLoginCallbackStorageKey(state) {
|
|
405
|
+
return `${LOGIN_CALLBACK_STORAGE_PREFIX}${state}`;
|
|
406
|
+
}
|
|
407
|
+
function publishLoginCallback(state, data) {
|
|
408
|
+
try {
|
|
409
|
+
const channel = new BroadcastChannel(getLoginCallbackChannelName(state));
|
|
410
|
+
channel.postMessage(data);
|
|
411
|
+
channel.close();
|
|
412
|
+
} catch {
|
|
413
|
+
}
|
|
414
|
+
try {
|
|
415
|
+
const storageKey = getLoginCallbackStorageKey(state);
|
|
416
|
+
window.localStorage.setItem(storageKey, JSON.stringify(data));
|
|
417
|
+
window.setTimeout(() => {
|
|
418
|
+
try {
|
|
419
|
+
window.localStorage.removeItem(storageKey);
|
|
420
|
+
} catch {
|
|
421
|
+
}
|
|
422
|
+
}, 800);
|
|
423
|
+
} catch {
|
|
424
|
+
}
|
|
425
|
+
try {
|
|
426
|
+
window.opener?.postMessage(data, window.location.origin);
|
|
427
|
+
} catch {
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
function cleanLoginCallbackUrl(url) {
|
|
431
|
+
url.searchParams.delete(LOGIN_CALLBACK_MARKER);
|
|
432
|
+
url.searchParams.delete(LOGIN_CALLBACK_STATE_PARAM);
|
|
433
|
+
const returnHash = url.searchParams.get(LOGIN_CALLBACK_RETURN_HASH_PARAM);
|
|
434
|
+
url.searchParams.delete(LOGIN_CALLBACK_RETURN_HASH_PARAM);
|
|
435
|
+
url.hash = returnHash ? `#${returnHash}` : "";
|
|
436
|
+
return url.toString();
|
|
437
|
+
}
|
|
438
|
+
function handleLoginCallbackIfPresent() {
|
|
439
|
+
if (typeof window === "undefined") {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
const url = new URL(window.location.href);
|
|
443
|
+
if (url.searchParams.get(LOGIN_CALLBACK_MARKER) !== "1") {
|
|
444
|
+
return false;
|
|
445
|
+
}
|
|
446
|
+
const state = url.searchParams.get(LOGIN_CALLBACK_STATE_PARAM) || "";
|
|
447
|
+
const hashParams = new URLSearchParams(url.hash.replace(/^#/, ""));
|
|
448
|
+
const rawResult = hashParams.get(LOGIN_CALLBACK_RESULT_PARAM);
|
|
449
|
+
const data = rawResult && state ? decodeCallbackPayload(rawResult) : {
|
|
450
|
+
type: "LOGIN_ERROR",
|
|
451
|
+
message: "Missing login callback result"
|
|
452
|
+
};
|
|
453
|
+
try {
|
|
454
|
+
document.documentElement.style.visibility = "hidden";
|
|
455
|
+
} catch {
|
|
456
|
+
}
|
|
457
|
+
if (state && data) {
|
|
458
|
+
publishLoginCallback(state, data);
|
|
459
|
+
}
|
|
460
|
+
try {
|
|
461
|
+
window.history.replaceState(null, "", cleanLoginCallbackUrl(url));
|
|
462
|
+
} catch {
|
|
463
|
+
}
|
|
464
|
+
window.setTimeout(() => {
|
|
465
|
+
try {
|
|
466
|
+
window.close();
|
|
467
|
+
} catch {
|
|
468
|
+
}
|
|
469
|
+
}, 30);
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
function logLoginDebug(message, details) {
|
|
473
|
+
if (typeof console === "undefined") return;
|
|
474
|
+
console.debug(LOGIN_UI_LOG_PREFIX, message, details || {});
|
|
475
|
+
}
|
|
476
|
+
function logLoginInfo(message, details) {
|
|
477
|
+
if (typeof console === "undefined") return;
|
|
478
|
+
console.info(LOGIN_UI_LOG_PREFIX, message, details || {});
|
|
479
|
+
}
|
|
480
|
+
function logLoginWarn(message, details) {
|
|
481
|
+
if (typeof console === "undefined") return;
|
|
482
|
+
console.warn(LOGIN_UI_LOG_PREFIX, message, details || {});
|
|
483
|
+
}
|
|
484
|
+
var LoginUI = class {
|
|
485
|
+
constructor() {
|
|
486
|
+
__publicField(this, "popup", null);
|
|
487
|
+
__publicField(this, "callbackChannel", null);
|
|
488
|
+
__publicField(this, "callbackStorageHandler", null);
|
|
489
|
+
__publicField(this, "messageHandler", null);
|
|
490
|
+
__publicField(this, "closeMonitor", null);
|
|
491
|
+
__publicField(this, "completed", false);
|
|
492
|
+
}
|
|
493
|
+
cleanup() {
|
|
494
|
+
if (this.callbackChannel) {
|
|
495
|
+
this.callbackChannel.close();
|
|
496
|
+
}
|
|
497
|
+
if (typeof window !== "undefined" && this.callbackStorageHandler) {
|
|
498
|
+
window.removeEventListener("storage", this.callbackStorageHandler);
|
|
499
|
+
}
|
|
500
|
+
if (typeof window !== "undefined" && this.messageHandler) {
|
|
501
|
+
window.removeEventListener("message", this.messageHandler);
|
|
502
|
+
}
|
|
503
|
+
this.callbackChannel = null;
|
|
504
|
+
this.callbackStorageHandler = null;
|
|
505
|
+
if (typeof window !== "undefined" && this.closeMonitor) {
|
|
506
|
+
window.clearInterval(this.closeMonitor);
|
|
507
|
+
}
|
|
508
|
+
this.messageHandler = null;
|
|
509
|
+
this.closeMonitor = null;
|
|
510
|
+
this.popup = null;
|
|
511
|
+
this.completed = false;
|
|
512
|
+
}
|
|
513
|
+
handleLoginEvent(data, options) {
|
|
514
|
+
if (!data || typeof data !== "object" || !data.type) {
|
|
515
|
+
logLoginDebug("Ignored non-login event payload");
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
logLoginInfo("Received login event", {
|
|
519
|
+
type: data.type
|
|
520
|
+
});
|
|
521
|
+
switch (data.type) {
|
|
522
|
+
case "LOGIN_SUCCESS":
|
|
523
|
+
if (this.completed) {
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
this.completed = true;
|
|
527
|
+
logLoginInfo("Login succeeded", {
|
|
528
|
+
channel: data.channel || null,
|
|
529
|
+
userId: data.userId || null
|
|
530
|
+
});
|
|
531
|
+
options?.onSuccess?.(extractLoginResult(data));
|
|
532
|
+
break;
|
|
533
|
+
case "LOGIN_CANCELLED":
|
|
534
|
+
logLoginInfo("Login cancelled");
|
|
535
|
+
options?.onCancel?.();
|
|
536
|
+
break;
|
|
537
|
+
case "LOGIN_RESIZE":
|
|
538
|
+
break;
|
|
539
|
+
case "LOGIN_ERROR":
|
|
540
|
+
if (this.completed) {
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
logLoginWarn("Login flow reported an error", {
|
|
544
|
+
message: data.message || data.error || null
|
|
545
|
+
});
|
|
546
|
+
options?.onError?.(data.message || data.error, data);
|
|
547
|
+
break;
|
|
548
|
+
case "LOGIN_CLOSE":
|
|
549
|
+
if (options?.autoClose === false) {
|
|
550
|
+
logLoginInfo(
|
|
551
|
+
"Login popup requested close; autoClose disabled, keeping popup open"
|
|
552
|
+
);
|
|
553
|
+
options?.onClose?.();
|
|
554
|
+
break;
|
|
555
|
+
}
|
|
556
|
+
logLoginInfo("Login popup requested close; autoClose enabled");
|
|
557
|
+
this.close();
|
|
558
|
+
options?.onClose?.();
|
|
559
|
+
break;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
listenForLoginCallback(callbackState, options) {
|
|
563
|
+
try {
|
|
564
|
+
this.callbackChannel = new BroadcastChannel(
|
|
565
|
+
getLoginCallbackChannelName(callbackState)
|
|
566
|
+
);
|
|
567
|
+
this.callbackChannel.onmessage = (event) => {
|
|
568
|
+
this.handleLoginEvent(event.data, options);
|
|
569
|
+
this.handleLoginEvent({ type: "LOGIN_CLOSE" }, options);
|
|
570
|
+
};
|
|
571
|
+
} catch {
|
|
572
|
+
logLoginDebug("BroadcastChannel is unavailable for login callback");
|
|
573
|
+
}
|
|
574
|
+
this.callbackStorageHandler = (event) => {
|
|
575
|
+
if (event.key !== getLoginCallbackStorageKey(callbackState) || !event.newValue) {
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
try {
|
|
579
|
+
const data = JSON.parse(event.newValue);
|
|
580
|
+
this.handleLoginEvent(data, options);
|
|
581
|
+
this.handleLoginEvent({ type: "LOGIN_CLOSE" }, options);
|
|
582
|
+
} catch {
|
|
583
|
+
logLoginWarn("Failed to parse login callback storage payload");
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
window.addEventListener("storage", this.callbackStorageHandler);
|
|
587
|
+
}
|
|
588
|
+
close() {
|
|
589
|
+
logLoginInfo("close() called", {
|
|
590
|
+
hasPopup: Boolean(this.popup),
|
|
591
|
+
popupClosed: this.popup?.closed ?? true
|
|
592
|
+
});
|
|
593
|
+
if (this.popup && !this.popup.closed) {
|
|
594
|
+
this.popup.close();
|
|
595
|
+
}
|
|
596
|
+
this.cleanup();
|
|
597
|
+
}
|
|
598
|
+
openLogin(params, options) {
|
|
599
|
+
if (typeof window === "undefined") return;
|
|
600
|
+
if (this.popup && !this.popup.closed) return;
|
|
601
|
+
const callbackState = createLoginCallbackState();
|
|
602
|
+
const launchPayload = buildLoginLaunchPayload(
|
|
603
|
+
params,
|
|
604
|
+
options,
|
|
605
|
+
callbackState
|
|
606
|
+
);
|
|
607
|
+
const finalUrl = buildLoginUrl(params, options, launchPayload);
|
|
608
|
+
logLoginInfo("Opening hosted login popup", {
|
|
609
|
+
appId: params.appId,
|
|
610
|
+
loginUrl: finalUrl,
|
|
611
|
+
allowedOrigin: options?.allowedOrigin || null,
|
|
612
|
+
autoClose: options?.autoClose ?? true
|
|
613
|
+
});
|
|
614
|
+
const popupWidth = 520;
|
|
615
|
+
const popupHeight = 720;
|
|
616
|
+
const left = Math.max(
|
|
617
|
+
0,
|
|
618
|
+
Math.round(window.screenX + (window.outerWidth - popupWidth) / 2)
|
|
619
|
+
);
|
|
620
|
+
const top = Math.max(
|
|
621
|
+
0,
|
|
622
|
+
Math.round(window.screenY + (window.outerHeight - popupHeight) / 2)
|
|
623
|
+
);
|
|
624
|
+
const features = [
|
|
625
|
+
"popup=yes",
|
|
626
|
+
`width=${popupWidth}`,
|
|
627
|
+
`height=${popupHeight}`,
|
|
628
|
+
`left=${left}`,
|
|
629
|
+
`top=${top}`,
|
|
630
|
+
"resizable=yes",
|
|
631
|
+
"scrollbars=yes"
|
|
632
|
+
].join(",");
|
|
633
|
+
const popupName = buildLoginPopupName(launchPayload);
|
|
634
|
+
const popup = window.open(finalUrl, popupName, features);
|
|
635
|
+
if (!popup) {
|
|
636
|
+
logLoginWarn("Popup blocked by the browser");
|
|
637
|
+
options?.onError?.("Login popup was blocked");
|
|
638
|
+
return;
|
|
639
|
+
}
|
|
640
|
+
this.popup = popup;
|
|
641
|
+
this.completed = false;
|
|
642
|
+
this.listenForLoginCallback(callbackState, options);
|
|
643
|
+
const allowedOrigin = options?.allowedOrigin;
|
|
644
|
+
const popupOrigin = getOrigin(finalUrl);
|
|
645
|
+
this.messageHandler = (event) => {
|
|
646
|
+
if (allowedOrigin && allowedOrigin !== "*" && event.origin !== allowedOrigin) {
|
|
647
|
+
logLoginWarn("Ignored message due to allowedOrigin mismatch", {
|
|
648
|
+
allowedOrigin,
|
|
649
|
+
eventOrigin: event.origin
|
|
650
|
+
});
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
653
|
+
if (!allowedOrigin && popupOrigin && event.origin !== popupOrigin) {
|
|
654
|
+
logLoginWarn("Ignored message due to popup origin mismatch", {
|
|
655
|
+
expectedOrigin: popupOrigin,
|
|
656
|
+
eventOrigin: event.origin
|
|
657
|
+
});
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
const data = event.data;
|
|
661
|
+
if (!data || typeof data !== "object" || !data.type) {
|
|
662
|
+
logLoginDebug("Ignored non-login postMessage payload");
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
logLoginInfo("Received login event", {
|
|
666
|
+
type: data.type,
|
|
667
|
+
eventOrigin: event.origin
|
|
668
|
+
});
|
|
669
|
+
this.handleLoginEvent(data, options);
|
|
670
|
+
};
|
|
671
|
+
window.addEventListener("message", this.messageHandler);
|
|
672
|
+
this.closeMonitor = window.setInterval(() => {
|
|
673
|
+
if (!this.popup || this.popup.closed) {
|
|
674
|
+
const shouldTreatAsCancel = !this.completed;
|
|
675
|
+
logLoginInfo("Detected popup closed", {
|
|
676
|
+
shouldTreatAsCancel
|
|
677
|
+
});
|
|
678
|
+
this.cleanup();
|
|
679
|
+
if (shouldTreatAsCancel) {
|
|
680
|
+
options?.onCancel?.();
|
|
681
|
+
}
|
|
682
|
+
options?.onClose?.();
|
|
683
|
+
}
|
|
684
|
+
}, 500);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
function createLoginUI() {
|
|
688
|
+
return new LoginUI();
|
|
689
|
+
}
|
|
690
|
+
handleLoginCallbackIfPresent();
|
|
691
|
+
|
|
150
692
|
// src/client.ts
|
|
151
693
|
var PaymentUI = class extends HostedFrameModal {
|
|
152
694
|
/**
|
|
@@ -257,7 +799,10 @@ function createPaymentUI() {
|
|
|
257
799
|
}
|
|
258
800
|
// Annotate the CommonJS export names for ESM import in node:
|
|
259
801
|
0 && (module.exports = {
|
|
802
|
+
LoginUI,
|
|
260
803
|
PaymentUI,
|
|
261
|
-
|
|
804
|
+
createLoginUI,
|
|
805
|
+
createPaymentUI,
|
|
806
|
+
handleLoginCallbackIfPresent
|
|
262
807
|
});
|
|
263
808
|
//# sourceMappingURL=client.cjs.map
|