@scalemule/nextjs 0.0.36 → 0.0.37
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.d.mts +5 -1
- package/dist/client.d.ts +5 -1
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +439 -78
- package/dist/index.mjs +439 -78
- package/dist/server/auth.js +266 -6
- package/dist/server/auth.mjs +266 -6
- package/dist/server/index.d.mts +68 -4
- package/dist/server/index.d.ts +68 -4
- package/dist/server/index.js +273 -6
- package/dist/server/index.mjs +267 -7
- package/dist/server/webhook-handler.d.mts +2 -2
- package/dist/server/webhook-handler.d.ts +2 -2
- package/dist/testing.d.mts +1 -1
- package/dist/testing.d.ts +1 -1
- package/package.json +1 -1
- package/dist/index-BoENfro3.d.mts +0 -845
- package/dist/index-BoENfro3.d.ts +0 -845
- package/dist/webhook-handler-CjSSCdvI.d.ts +0 -779
- package/dist/webhook-handler-Cz9jtet2.d.mts +0 -779
package/dist/index.js
CHANGED
|
@@ -290,78 +290,6 @@ var init_upload_compression_VOUJRAIM = __esm({
|
|
|
290
290
|
|
|
291
291
|
// node_modules/@scalemule/sdk/dist/index.mjs
|
|
292
292
|
init_chunk_3FTGBRLU();
|
|
293
|
-
|
|
294
|
-
// node_modules/@scalemule/ui/dist/phone/index.mjs
|
|
295
|
-
var PHONE_COUNTRIES = [
|
|
296
|
-
{ code: "US", name: "United States", dialCode: "+1" },
|
|
297
|
-
{ code: "CA", name: "Canada", dialCode: "+1" },
|
|
298
|
-
{ code: "GB", name: "United Kingdom", dialCode: "+44" },
|
|
299
|
-
{ code: "AU", name: "Australia", dialCode: "+61" },
|
|
300
|
-
{ code: "DE", name: "Germany", dialCode: "+49" },
|
|
301
|
-
{ code: "FR", name: "France", dialCode: "+33" },
|
|
302
|
-
{ code: "IT", name: "Italy", dialCode: "+39" },
|
|
303
|
-
{ code: "ES", name: "Spain", dialCode: "+34" },
|
|
304
|
-
{ code: "NL", name: "Netherlands", dialCode: "+31" },
|
|
305
|
-
{ code: "BE", name: "Belgium", dialCode: "+32" },
|
|
306
|
-
{ code: "CH", name: "Switzerland", dialCode: "+41" },
|
|
307
|
-
{ code: "AT", name: "Austria", dialCode: "+43" },
|
|
308
|
-
{ code: "SE", name: "Sweden", dialCode: "+46" },
|
|
309
|
-
{ code: "NO", name: "Norway", dialCode: "+47" },
|
|
310
|
-
{ code: "DK", name: "Denmark", dialCode: "+45" },
|
|
311
|
-
{ code: "FI", name: "Finland", dialCode: "+358" },
|
|
312
|
-
{ code: "IE", name: "Ireland", dialCode: "+353" },
|
|
313
|
-
{ code: "PT", name: "Portugal", dialCode: "+351" },
|
|
314
|
-
{ code: "PL", name: "Poland", dialCode: "+48" },
|
|
315
|
-
{ code: "CZ", name: "Czech Republic", dialCode: "+420" },
|
|
316
|
-
{ code: "GR", name: "Greece", dialCode: "+30" },
|
|
317
|
-
{ code: "RU", name: "Russia", dialCode: "+7" },
|
|
318
|
-
{ code: "JP", name: "Japan", dialCode: "+81" },
|
|
319
|
-
{ code: "KR", name: "South Korea", dialCode: "+82" },
|
|
320
|
-
{ code: "CN", name: "China", dialCode: "+86" },
|
|
321
|
-
{ code: "HK", name: "Hong Kong", dialCode: "+852" },
|
|
322
|
-
{ code: "TW", name: "Taiwan", dialCode: "+886" },
|
|
323
|
-
{ code: "SG", name: "Singapore", dialCode: "+65" },
|
|
324
|
-
{ code: "MY", name: "Malaysia", dialCode: "+60" },
|
|
325
|
-
{ code: "TH", name: "Thailand", dialCode: "+66" },
|
|
326
|
-
{ code: "VN", name: "Vietnam", dialCode: "+84" },
|
|
327
|
-
{ code: "PH", name: "Philippines", dialCode: "+63" },
|
|
328
|
-
{ code: "ID", name: "Indonesia", dialCode: "+62" },
|
|
329
|
-
{ code: "IN", name: "India", dialCode: "+91" },
|
|
330
|
-
{ code: "PK", name: "Pakistan", dialCode: "+92" },
|
|
331
|
-
{ code: "BD", name: "Bangladesh", dialCode: "+880" },
|
|
332
|
-
{ code: "AE", name: "UAE", dialCode: "+971" },
|
|
333
|
-
{ code: "SA", name: "Saudi Arabia", dialCode: "+966" },
|
|
334
|
-
{ code: "IL", name: "Israel", dialCode: "+972" },
|
|
335
|
-
{ code: "TR", name: "Turkey", dialCode: "+90" },
|
|
336
|
-
{ code: "EG", name: "Egypt", dialCode: "+20" },
|
|
337
|
-
{ code: "ZA", name: "South Africa", dialCode: "+27" },
|
|
338
|
-
{ code: "NG", name: "Nigeria", dialCode: "+234" },
|
|
339
|
-
{ code: "KE", name: "Kenya", dialCode: "+254" },
|
|
340
|
-
{ code: "BR", name: "Brazil", dialCode: "+55" },
|
|
341
|
-
{ code: "MX", name: "Mexico", dialCode: "+52" },
|
|
342
|
-
{ code: "AR", name: "Argentina", dialCode: "+54" },
|
|
343
|
-
{ code: "CL", name: "Chile", dialCode: "+56" },
|
|
344
|
-
{ code: "CO", name: "Colombia", dialCode: "+57" },
|
|
345
|
-
{ code: "PE", name: "Peru", dialCode: "+51" },
|
|
346
|
-
{ code: "NZ", name: "New Zealand", dialCode: "+64" }
|
|
347
|
-
];
|
|
348
|
-
function normalizePhoneNumber(input) {
|
|
349
|
-
if (typeof input !== "string") return "";
|
|
350
|
-
const trimmed = input.trim();
|
|
351
|
-
if (!trimmed) return "";
|
|
352
|
-
const digitsOnly = trimmed.replace(/\D/g, "");
|
|
353
|
-
if (!digitsOnly) return "";
|
|
354
|
-
if (trimmed.startsWith("+")) {
|
|
355
|
-
return `+${digitsOnly}`;
|
|
356
|
-
}
|
|
357
|
-
if (trimmed.startsWith("00") && digitsOnly.length > 2) {
|
|
358
|
-
return `+${digitsOnly.slice(2)}`;
|
|
359
|
-
}
|
|
360
|
-
return `+${digitsOnly}`;
|
|
361
|
-
}
|
|
362
|
-
[...PHONE_COUNTRIES].sort((a, b) => b.dialCode.length - a.dialCode.length);
|
|
363
|
-
|
|
364
|
-
// node_modules/@scalemule/sdk/dist/index.mjs
|
|
365
293
|
function buildClientContextHeaders(context) {
|
|
366
294
|
if (!context) return {};
|
|
367
295
|
const headers = {};
|
|
@@ -386,6 +314,7 @@ var WORKSPACE_STORAGE_KEY = "scalemule_workspace_id";
|
|
|
386
314
|
var ANONYMOUS_ID_STORAGE_KEY = "scalemule_anonymous_id";
|
|
387
315
|
var SESSION_POOL_KEY = "scalemule_session_pool";
|
|
388
316
|
var ACTIVE_ACCOUNT_KEY = "scalemule_active_account";
|
|
317
|
+
var KNOWN_ACCOUNTS_KEY = "scalemule_known_accounts";
|
|
389
318
|
var GATEWAY_URLS = {
|
|
390
319
|
dev: "https://api-dev.scalemule.com",
|
|
391
320
|
prod: "https://api.scalemule.com"
|
|
@@ -435,6 +364,54 @@ function statusToErrorCode(status) {
|
|
|
435
364
|
return status >= 500 ? "internal_error" : `http_${status}`;
|
|
436
365
|
}
|
|
437
366
|
}
|
|
367
|
+
var MAX_KNOWN_ACCOUNTS = 10;
|
|
368
|
+
function maskEmail(email) {
|
|
369
|
+
const parts = email.split("@");
|
|
370
|
+
const local = parts[0] ?? "";
|
|
371
|
+
const domain = parts[1];
|
|
372
|
+
if (!domain) return "***@***.***";
|
|
373
|
+
const tldDot = domain.lastIndexOf(".");
|
|
374
|
+
const tld = tldDot > 0 ? domain.slice(tldDot) : "";
|
|
375
|
+
const domainBase = tldDot > 0 ? domain.slice(0, tldDot) : domain;
|
|
376
|
+
return `${local[0] || "*"}***@${domainBase[0] || "*"}***${tld}`;
|
|
377
|
+
}
|
|
378
|
+
function stableColorIndex(userId) {
|
|
379
|
+
let hash = 0;
|
|
380
|
+
for (let i = 0; i < userId.length; i++) {
|
|
381
|
+
hash = (hash << 5) - hash + userId.charCodeAt(i) | 0;
|
|
382
|
+
}
|
|
383
|
+
return Math.abs(hash) % 8;
|
|
384
|
+
}
|
|
385
|
+
function applyPrivacy(account, privacy) {
|
|
386
|
+
switch (privacy) {
|
|
387
|
+
case "full":
|
|
388
|
+
return {
|
|
389
|
+
userId: account.userId,
|
|
390
|
+
email: account.email,
|
|
391
|
+
fullName: account.fullName,
|
|
392
|
+
avatarUrl: account.avatarUrl,
|
|
393
|
+
provider: account.provider,
|
|
394
|
+
lastActiveAt: account.lastActiveAt
|
|
395
|
+
};
|
|
396
|
+
case "masked":
|
|
397
|
+
return {
|
|
398
|
+
userId: account.userId,
|
|
399
|
+
email: account.email ? maskEmail(account.email) : void 0,
|
|
400
|
+
fullName: account.fullName && account.fullName.length > 0 ? `${account.fullName[0].toUpperCase()}.` : void 0,
|
|
401
|
+
provider: account.provider,
|
|
402
|
+
lastActiveAt: account.lastActiveAt,
|
|
403
|
+
colorIndex: stableColorIndex(account.userId)
|
|
404
|
+
};
|
|
405
|
+
case "minimal":
|
|
406
|
+
return {
|
|
407
|
+
userId: account.userId,
|
|
408
|
+
provider: account.provider,
|
|
409
|
+
lastActiveAt: account.lastActiveAt,
|
|
410
|
+
displayLabel: "Account",
|
|
411
|
+
colorIndex: stableColorIndex(account.userId)
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
438
415
|
function createDefaultStorage() {
|
|
439
416
|
if (typeof window !== "undefined" && window.localStorage) {
|
|
440
417
|
return {
|
|
@@ -581,6 +558,7 @@ var ScaleMuleClient = class {
|
|
|
581
558
|
this.workspaceId = null;
|
|
582
559
|
this.anonymousId = null;
|
|
583
560
|
this.sessionPool = /* @__PURE__ */ new Map();
|
|
561
|
+
this.knownAccounts = /* @__PURE__ */ new Map();
|
|
584
562
|
this.apiKey = config.apiKey;
|
|
585
563
|
this.applicationId = config.applicationId || null;
|
|
586
564
|
this.baseUrl = config.baseUrl || GATEWAY_URLS[config.environment || "prod"];
|
|
@@ -597,6 +575,8 @@ var ScaleMuleClient = class {
|
|
|
597
575
|
this.offlineQueue.setOnlineCallback(() => this.syncOfflineQueue());
|
|
598
576
|
}
|
|
599
577
|
this.multiSessionEnabled = config.enableMultiSession || false;
|
|
578
|
+
this.accountSwitcherEnabled = config.enableAccountSwitcher || false;
|
|
579
|
+
this.accountSwitcherPrivacy = config.accountSwitcherPrivacy || "full";
|
|
600
580
|
}
|
|
601
581
|
// --------------------------------------------------------------------------
|
|
602
582
|
// Session Management
|
|
@@ -639,6 +619,27 @@ var ScaleMuleClient = class {
|
|
|
639
619
|
this.userId = activeId;
|
|
640
620
|
}
|
|
641
621
|
}
|
|
622
|
+
if (this.accountSwitcherEnabled) {
|
|
623
|
+
const knownJson = await this.storage.getItem(KNOWN_ACCOUNTS_KEY);
|
|
624
|
+
if (knownJson) {
|
|
625
|
+
try {
|
|
626
|
+
const entries = JSON.parse(knownJson);
|
|
627
|
+
this.knownAccounts = new Map(Object.entries(entries));
|
|
628
|
+
let changed = false;
|
|
629
|
+
for (const [userId2, entry] of this.knownAccounts) {
|
|
630
|
+
const normalized = applyPrivacy(entry, this.accountSwitcherPrivacy);
|
|
631
|
+
if (JSON.stringify(normalized) !== JSON.stringify(entry)) {
|
|
632
|
+
this.knownAccounts.set(userId2, normalized);
|
|
633
|
+
changed = true;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
if (changed) {
|
|
637
|
+
await this.persistKnownAccounts();
|
|
638
|
+
}
|
|
639
|
+
} catch {
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
642
643
|
if (this.debug)
|
|
643
644
|
console.log(
|
|
644
645
|
"[ScaleMule] Initialized, session:",
|
|
@@ -646,7 +647,9 @@ var ScaleMuleClient = class {
|
|
|
646
647
|
"anonymousId:",
|
|
647
648
|
anonId,
|
|
648
649
|
"poolSize:",
|
|
649
|
-
this.sessionPool.size
|
|
650
|
+
this.sessionPool.size,
|
|
651
|
+
"knownAccounts:",
|
|
652
|
+
this.knownAccounts.size
|
|
650
653
|
);
|
|
651
654
|
}
|
|
652
655
|
async setSession(token, userId) {
|
|
@@ -770,6 +773,57 @@ var ScaleMuleClient = class {
|
|
|
770
773
|
}
|
|
771
774
|
await this.storage.setItem(SESSION_POOL_KEY, JSON.stringify(obj));
|
|
772
775
|
}
|
|
776
|
+
// --------------------------------------------------------------------------
|
|
777
|
+
// Account Switcher (Secure — metadata only, no tokens)
|
|
778
|
+
// --------------------------------------------------------------------------
|
|
779
|
+
isAccountSwitcherEnabled() {
|
|
780
|
+
return this.accountSwitcherEnabled;
|
|
781
|
+
}
|
|
782
|
+
getAccountSwitcherPrivacy() {
|
|
783
|
+
return this.accountSwitcherPrivacy;
|
|
784
|
+
}
|
|
785
|
+
/** Get all known accounts that have logged in on this device (privacy-transformed) */
|
|
786
|
+
getKnownAccounts() {
|
|
787
|
+
return Array.from(this.knownAccounts.values());
|
|
788
|
+
}
|
|
789
|
+
/**
|
|
790
|
+
* Record an account as "known" on this device.
|
|
791
|
+
* Applies privacy transforms before storing — full email is never persisted
|
|
792
|
+
* in masked/minimal modes. Evicts oldest accounts if over the cap.
|
|
793
|
+
* Called automatically after successful login/register when account switcher is enabled.
|
|
794
|
+
*/
|
|
795
|
+
async addKnownAccount(account) {
|
|
796
|
+
const display = applyPrivacy(account, this.accountSwitcherPrivacy);
|
|
797
|
+
this.knownAccounts.set(account.userId, display);
|
|
798
|
+
if (this.knownAccounts.size > MAX_KNOWN_ACCOUNTS) {
|
|
799
|
+
const sorted = Array.from(this.knownAccounts.entries()).sort(
|
|
800
|
+
(a, b) => (a[1].lastActiveAt || "").localeCompare(b[1].lastActiveAt || "")
|
|
801
|
+
);
|
|
802
|
+
while (this.knownAccounts.size > MAX_KNOWN_ACCOUNTS && sorted.length > 0) {
|
|
803
|
+
const oldest = sorted.shift();
|
|
804
|
+
this.knownAccounts.delete(oldest[0]);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
await this.persistKnownAccounts();
|
|
808
|
+
}
|
|
809
|
+
/** Remove a specific account from the known accounts list ("forget this account") */
|
|
810
|
+
async removeKnownAccount(userId) {
|
|
811
|
+
this.knownAccounts.delete(userId);
|
|
812
|
+
await this.persistKnownAccounts();
|
|
813
|
+
}
|
|
814
|
+
/** Clear all known accounts ("forget all accounts on this device") */
|
|
815
|
+
async clearKnownAccounts() {
|
|
816
|
+
this.knownAccounts.clear();
|
|
817
|
+
await this.storage.removeItem(KNOWN_ACCOUNTS_KEY);
|
|
818
|
+
}
|
|
819
|
+
/** Persist known accounts to storage */
|
|
820
|
+
async persistKnownAccounts() {
|
|
821
|
+
const obj = {};
|
|
822
|
+
for (const [k, v] of this.knownAccounts) {
|
|
823
|
+
obj[k] = v;
|
|
824
|
+
}
|
|
825
|
+
await this.storage.setItem(KNOWN_ACCOUNTS_KEY, JSON.stringify(obj));
|
|
826
|
+
}
|
|
773
827
|
getBaseUrl() {
|
|
774
828
|
return this.baseUrl;
|
|
775
829
|
}
|
|
@@ -1261,6 +1315,74 @@ function asString(parent, key) {
|
|
|
1261
1315
|
const value = parent[key];
|
|
1262
1316
|
return typeof value === "string" ? value : void 0;
|
|
1263
1317
|
}
|
|
1318
|
+
var PHONE_COUNTRIES = [
|
|
1319
|
+
{ code: "US", name: "United States", dialCode: "+1" },
|
|
1320
|
+
{ code: "CA", name: "Canada", dialCode: "+1" },
|
|
1321
|
+
{ code: "GB", name: "United Kingdom", dialCode: "+44" },
|
|
1322
|
+
{ code: "AU", name: "Australia", dialCode: "+61" },
|
|
1323
|
+
{ code: "DE", name: "Germany", dialCode: "+49" },
|
|
1324
|
+
{ code: "FR", name: "France", dialCode: "+33" },
|
|
1325
|
+
{ code: "IT", name: "Italy", dialCode: "+39" },
|
|
1326
|
+
{ code: "ES", name: "Spain", dialCode: "+34" },
|
|
1327
|
+
{ code: "NL", name: "Netherlands", dialCode: "+31" },
|
|
1328
|
+
{ code: "BE", name: "Belgium", dialCode: "+32" },
|
|
1329
|
+
{ code: "CH", name: "Switzerland", dialCode: "+41" },
|
|
1330
|
+
{ code: "AT", name: "Austria", dialCode: "+43" },
|
|
1331
|
+
{ code: "SE", name: "Sweden", dialCode: "+46" },
|
|
1332
|
+
{ code: "NO", name: "Norway", dialCode: "+47" },
|
|
1333
|
+
{ code: "DK", name: "Denmark", dialCode: "+45" },
|
|
1334
|
+
{ code: "FI", name: "Finland", dialCode: "+358" },
|
|
1335
|
+
{ code: "IE", name: "Ireland", dialCode: "+353" },
|
|
1336
|
+
{ code: "PT", name: "Portugal", dialCode: "+351" },
|
|
1337
|
+
{ code: "PL", name: "Poland", dialCode: "+48" },
|
|
1338
|
+
{ code: "CZ", name: "Czech Republic", dialCode: "+420" },
|
|
1339
|
+
{ code: "GR", name: "Greece", dialCode: "+30" },
|
|
1340
|
+
{ code: "RU", name: "Russia", dialCode: "+7" },
|
|
1341
|
+
{ code: "JP", name: "Japan", dialCode: "+81" },
|
|
1342
|
+
{ code: "KR", name: "South Korea", dialCode: "+82" },
|
|
1343
|
+
{ code: "CN", name: "China", dialCode: "+86" },
|
|
1344
|
+
{ code: "HK", name: "Hong Kong", dialCode: "+852" },
|
|
1345
|
+
{ code: "TW", name: "Taiwan", dialCode: "+886" },
|
|
1346
|
+
{ code: "SG", name: "Singapore", dialCode: "+65" },
|
|
1347
|
+
{ code: "MY", name: "Malaysia", dialCode: "+60" },
|
|
1348
|
+
{ code: "TH", name: "Thailand", dialCode: "+66" },
|
|
1349
|
+
{ code: "VN", name: "Vietnam", dialCode: "+84" },
|
|
1350
|
+
{ code: "PH", name: "Philippines", dialCode: "+63" },
|
|
1351
|
+
{ code: "ID", name: "Indonesia", dialCode: "+62" },
|
|
1352
|
+
{ code: "IN", name: "India", dialCode: "+91" },
|
|
1353
|
+
{ code: "PK", name: "Pakistan", dialCode: "+92" },
|
|
1354
|
+
{ code: "BD", name: "Bangladesh", dialCode: "+880" },
|
|
1355
|
+
{ code: "AE", name: "UAE", dialCode: "+971" },
|
|
1356
|
+
{ code: "SA", name: "Saudi Arabia", dialCode: "+966" },
|
|
1357
|
+
{ code: "IL", name: "Israel", dialCode: "+972" },
|
|
1358
|
+
{ code: "TR", name: "Turkey", dialCode: "+90" },
|
|
1359
|
+
{ code: "EG", name: "Egypt", dialCode: "+20" },
|
|
1360
|
+
{ code: "ZA", name: "South Africa", dialCode: "+27" },
|
|
1361
|
+
{ code: "NG", name: "Nigeria", dialCode: "+234" },
|
|
1362
|
+
{ code: "KE", name: "Kenya", dialCode: "+254" },
|
|
1363
|
+
{ code: "BR", name: "Brazil", dialCode: "+55" },
|
|
1364
|
+
{ code: "MX", name: "Mexico", dialCode: "+52" },
|
|
1365
|
+
{ code: "AR", name: "Argentina", dialCode: "+54" },
|
|
1366
|
+
{ code: "CL", name: "Chile", dialCode: "+56" },
|
|
1367
|
+
{ code: "CO", name: "Colombia", dialCode: "+57" },
|
|
1368
|
+
{ code: "PE", name: "Peru", dialCode: "+51" },
|
|
1369
|
+
{ code: "NZ", name: "New Zealand", dialCode: "+64" }
|
|
1370
|
+
];
|
|
1371
|
+
function normalizePhoneNumber(input) {
|
|
1372
|
+
if (typeof input !== "string") return "";
|
|
1373
|
+
const trimmed = input.trim();
|
|
1374
|
+
if (!trimmed) return "";
|
|
1375
|
+
const digitsOnly = trimmed.replace(/\D/g, "");
|
|
1376
|
+
if (!digitsOnly) return "";
|
|
1377
|
+
if (trimmed.startsWith("+")) {
|
|
1378
|
+
return `+${digitsOnly}`;
|
|
1379
|
+
}
|
|
1380
|
+
if (trimmed.startsWith("00") && digitsOnly.length > 2) {
|
|
1381
|
+
return `+${digitsOnly.slice(2)}`;
|
|
1382
|
+
}
|
|
1383
|
+
return `+${digitsOnly}`;
|
|
1384
|
+
}
|
|
1385
|
+
[...PHONE_COUNTRIES].sort((a, b) => b.dialCode.length - a.dialCode.length);
|
|
1264
1386
|
function collectDeviceFingerprint() {
|
|
1265
1387
|
if (typeof window === "undefined" || typeof navigator === "undefined") return void 0;
|
|
1266
1388
|
try {
|
|
@@ -1389,6 +1511,16 @@ var AuthService = class extends ServiceModule {
|
|
|
1389
1511
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1390
1512
|
});
|
|
1391
1513
|
}
|
|
1514
|
+
if (result.data && this.client.isAccountSwitcherEnabled()) {
|
|
1515
|
+
await this.client.addKnownAccount({
|
|
1516
|
+
userId: result.data.user.id,
|
|
1517
|
+
email: result.data.user.email,
|
|
1518
|
+
fullName: result.data.user.full_name,
|
|
1519
|
+
avatarUrl: result.data.user.avatar_url,
|
|
1520
|
+
provider: "email",
|
|
1521
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1522
|
+
});
|
|
1523
|
+
}
|
|
1392
1524
|
return result;
|
|
1393
1525
|
}
|
|
1394
1526
|
async login(data, options) {
|
|
@@ -1409,6 +1541,16 @@ var AuthService = class extends ServiceModule {
|
|
|
1409
1541
|
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1410
1542
|
});
|
|
1411
1543
|
}
|
|
1544
|
+
if (result.data && this.client.isAccountSwitcherEnabled()) {
|
|
1545
|
+
await this.client.addKnownAccount({
|
|
1546
|
+
userId: result.data.user.id,
|
|
1547
|
+
email: result.data.user.email,
|
|
1548
|
+
fullName: result.data.user.full_name,
|
|
1549
|
+
avatarUrl: result.data.user.avatar_url,
|
|
1550
|
+
provider: "email",
|
|
1551
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1412
1554
|
return result;
|
|
1413
1555
|
}
|
|
1414
1556
|
async logout(options) {
|
|
@@ -1550,7 +1692,18 @@ var AuthService = class extends ServiceModule {
|
|
|
1550
1692
|
}
|
|
1551
1693
|
async handleOAuthCallback(data, options) {
|
|
1552
1694
|
const { provider, ...rest } = data;
|
|
1553
|
-
|
|
1695
|
+
const result = await this._get(this.withQuery(`/oauth/${provider}/callback`, rest), options);
|
|
1696
|
+
if (result.data && this.client.isAccountSwitcherEnabled()) {
|
|
1697
|
+
await this.client.addKnownAccount({
|
|
1698
|
+
userId: result.data.user.id,
|
|
1699
|
+
email: result.data.user.email,
|
|
1700
|
+
fullName: result.data.user.full_name,
|
|
1701
|
+
avatarUrl: result.data.user.avatar_url,
|
|
1702
|
+
provider,
|
|
1703
|
+
lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1704
|
+
});
|
|
1705
|
+
}
|
|
1706
|
+
return result;
|
|
1554
1707
|
}
|
|
1555
1708
|
async listOAuthProviders(options) {
|
|
1556
1709
|
return this._get("/oauth/providers", options);
|
|
@@ -5251,6 +5404,71 @@ var FlagContentService = class extends ServiceModule {
|
|
|
5251
5404
|
return this._get(`/appeals/${id}`, options);
|
|
5252
5405
|
}
|
|
5253
5406
|
};
|
|
5407
|
+
var CreatorMakerService = class extends ServiceModule {
|
|
5408
|
+
constructor() {
|
|
5409
|
+
super(...arguments);
|
|
5410
|
+
this.basePath = "/v1/creator-maker";
|
|
5411
|
+
}
|
|
5412
|
+
/** Submit a generation job. */
|
|
5413
|
+
async generate(data, options) {
|
|
5414
|
+
return this.post("/jobs", data, options);
|
|
5415
|
+
}
|
|
5416
|
+
/** Get a generation job by ID. */
|
|
5417
|
+
async getJob(jobId, options) {
|
|
5418
|
+
return this._get(`/jobs/${jobId}`, options);
|
|
5419
|
+
}
|
|
5420
|
+
/** Long-poll for job completion (server holds up to 30s). */
|
|
5421
|
+
async pollJob(jobId, options) {
|
|
5422
|
+
return this._get(`/jobs/${jobId}/poll`, {
|
|
5423
|
+
...options,
|
|
5424
|
+
timeout: 35e3
|
|
5425
|
+
});
|
|
5426
|
+
}
|
|
5427
|
+
/** List the current user's generation jobs. */
|
|
5428
|
+
async listJobs(params, options) {
|
|
5429
|
+
return this._list("/jobs", params, options);
|
|
5430
|
+
}
|
|
5431
|
+
/** Cancel a pending or queued job. */
|
|
5432
|
+
async cancelJob(jobId, options) {
|
|
5433
|
+
return this.post(`/jobs/${jobId}/cancel`, void 0, options);
|
|
5434
|
+
}
|
|
5435
|
+
/** Retry a failed job. */
|
|
5436
|
+
async retryJob(jobId, options) {
|
|
5437
|
+
return this.post(`/jobs/${jobId}/retry`, void 0, options);
|
|
5438
|
+
}
|
|
5439
|
+
/** Generate variations of a completed job. */
|
|
5440
|
+
async generateVariations(jobId, options) {
|
|
5441
|
+
return this.post(`/jobs/${jobId}/variations`, void 0, options);
|
|
5442
|
+
}
|
|
5443
|
+
/** List available style presets, optionally filtered by mode. */
|
|
5444
|
+
async listPresets(params, options) {
|
|
5445
|
+
return this._get(this.withQuery("/presets", params), options);
|
|
5446
|
+
}
|
|
5447
|
+
/** Get a style preset by slug. */
|
|
5448
|
+
async getPreset(slug, options) {
|
|
5449
|
+
return this._get(`/presets/${slug}`, options);
|
|
5450
|
+
}
|
|
5451
|
+
/** Create a project. */
|
|
5452
|
+
async createProject(data, options) {
|
|
5453
|
+
return this.post("/projects", data, options);
|
|
5454
|
+
}
|
|
5455
|
+
/** List the current user's projects. */
|
|
5456
|
+
async listProjects(params, options) {
|
|
5457
|
+
return this._list("/projects", params, options);
|
|
5458
|
+
}
|
|
5459
|
+
/** Get generation usage and credit balance. */
|
|
5460
|
+
async getUsage(options) {
|
|
5461
|
+
return this._get("/usage", options);
|
|
5462
|
+
}
|
|
5463
|
+
/** Get a generation output by ID. */
|
|
5464
|
+
async getOutput(outputId, options) {
|
|
5465
|
+
return this._get(`/outputs/${outputId}`, options);
|
|
5466
|
+
}
|
|
5467
|
+
/** Get a download URL for a generation output. */
|
|
5468
|
+
async getDownloadUrl(outputId, options) {
|
|
5469
|
+
return this._get(`/outputs/${outputId}/download`, options);
|
|
5470
|
+
}
|
|
5471
|
+
};
|
|
5254
5472
|
var AgentAuthService = class extends ServiceModule {
|
|
5255
5473
|
constructor() {
|
|
5256
5474
|
super(...arguments);
|
|
@@ -5452,6 +5670,13 @@ var AgentProjectsService = class extends ServiceModule {
|
|
|
5452
5670
|
options
|
|
5453
5671
|
);
|
|
5454
5672
|
}
|
|
5673
|
+
async startTask(taskId, agentId, applicationId, options) {
|
|
5674
|
+
return this.post(
|
|
5675
|
+
this.withAppId(`/tasks/${taskId}/start`, applicationId),
|
|
5676
|
+
{ agent_id: agentId },
|
|
5677
|
+
options
|
|
5678
|
+
);
|
|
5679
|
+
}
|
|
5455
5680
|
async submit(taskId, data, applicationId, options) {
|
|
5456
5681
|
return this.post(this.withAppId(`/tasks/${taskId}/submit`, applicationId), data, options);
|
|
5457
5682
|
}
|
|
@@ -5750,6 +5975,7 @@ var ScaleMule = class {
|
|
|
5750
5975
|
this.functions = new FunctionsService(this._client);
|
|
5751
5976
|
this.photo = new PhotoService(this._client);
|
|
5752
5977
|
this.flagContent = new FlagContentService(this._client);
|
|
5978
|
+
this.creatorMaker = new CreatorMakerService(this._client);
|
|
5753
5979
|
this.compliance = new ComplianceService(this._client);
|
|
5754
5980
|
this.orchestrator = new OrchestratorService(this._client);
|
|
5755
5981
|
this.agentAuth = new AgentAuthService(this._client);
|
|
@@ -5829,6 +6055,36 @@ var ScaleMule = class {
|
|
|
5829
6055
|
async clearAllAccounts() {
|
|
5830
6056
|
return this._client.clearAllAccounts();
|
|
5831
6057
|
}
|
|
6058
|
+
// --------------------------------------------------------------------------
|
|
6059
|
+
// Account Switcher (Secure — metadata only, re-auth required)
|
|
6060
|
+
// --------------------------------------------------------------------------
|
|
6061
|
+
/** Whether the account switcher is enabled */
|
|
6062
|
+
isAccountSwitcherEnabled() {
|
|
6063
|
+
return this._client.isAccountSwitcherEnabled();
|
|
6064
|
+
}
|
|
6065
|
+
/** The configured privacy level for the account switcher */
|
|
6066
|
+
getAccountSwitcherPrivacy() {
|
|
6067
|
+
return this._client.getAccountSwitcherPrivacy();
|
|
6068
|
+
}
|
|
6069
|
+
/**
|
|
6070
|
+
* Get all accounts that have previously logged in on this device.
|
|
6071
|
+
* Returns privacy-transformed display data — no raw PII in masked/minimal modes.
|
|
6072
|
+
* Requires `enableAccountSwitcher: true` in config.
|
|
6073
|
+
*/
|
|
6074
|
+
getKnownAccounts() {
|
|
6075
|
+
return this._client.getKnownAccounts();
|
|
6076
|
+
}
|
|
6077
|
+
/**
|
|
6078
|
+
* Forget a specific account — removes it from the known accounts list.
|
|
6079
|
+
* Does NOT affect any active session.
|
|
6080
|
+
*/
|
|
6081
|
+
async removeKnownAccount(userId) {
|
|
6082
|
+
return this._client.removeKnownAccount(userId);
|
|
6083
|
+
}
|
|
6084
|
+
/** Forget all known accounts on this device. */
|
|
6085
|
+
async clearKnownAccounts() {
|
|
6086
|
+
return this._client.clearKnownAccounts();
|
|
6087
|
+
}
|
|
5832
6088
|
/** The base URL being used for API requests. */
|
|
5833
6089
|
getBaseUrl() {
|
|
5834
6090
|
return this._client.getBaseUrl();
|
|
@@ -6660,6 +6916,8 @@ function ScaleMuleProvider({
|
|
|
6660
6916
|
analyticsProxyUrl,
|
|
6661
6917
|
authProxyUrl,
|
|
6662
6918
|
publishableKey,
|
|
6919
|
+
enableAccountSwitcher,
|
|
6920
|
+
accountSwitcherPrivacy,
|
|
6663
6921
|
children,
|
|
6664
6922
|
onLogin,
|
|
6665
6923
|
onLogout,
|
|
@@ -6797,9 +7055,11 @@ function ScaleMuleProvider({
|
|
|
6797
7055
|
publishableKey,
|
|
6798
7056
|
gatewayUrl: gatewayUrl || (environment === "dev" ? "https://api-dev.scalemule.com" : "https://api.scalemule.com"),
|
|
6799
7057
|
environment: environment || void 0,
|
|
7058
|
+
enableAccountSwitcher,
|
|
7059
|
+
accountSwitcherPrivacy,
|
|
6800
7060
|
bootstrapFlags
|
|
6801
7061
|
}),
|
|
6802
|
-
[client, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, gatewayUrl, environment, bootstrapFlags]
|
|
7062
|
+
[client, baseClient, user, handleSetUser, initializing, error, analyticsProxyUrl, authProxyUrl, publishableKey, gatewayUrl, environment, enableAccountSwitcher, accountSwitcherPrivacy, bootstrapFlags]
|
|
6803
7063
|
);
|
|
6804
7064
|
return /* @__PURE__ */ jsxRuntime.jsx(ScaleMuleContext.Provider, { value, children });
|
|
6805
7065
|
}
|
|
@@ -6816,6 +7076,41 @@ function useScaleMuleClient() {
|
|
|
6816
7076
|
const { client } = useScaleMule();
|
|
6817
7077
|
return client;
|
|
6818
7078
|
}
|
|
7079
|
+
function maskEmail2(email) {
|
|
7080
|
+
const [local, domain] = email.split("@");
|
|
7081
|
+
if (!domain) return "***@***.***";
|
|
7082
|
+
const tldDot = domain.lastIndexOf(".");
|
|
7083
|
+
const tld = tldDot > 0 ? domain.slice(tldDot) : "";
|
|
7084
|
+
const domainBase = tldDot > 0 ? domain.slice(0, tldDot) : domain;
|
|
7085
|
+
return `${local[0] || "*"}***@${domainBase[0] || "*"}***${tld}`;
|
|
7086
|
+
}
|
|
7087
|
+
function stableColorIndex2(userId) {
|
|
7088
|
+
let hash = 0;
|
|
7089
|
+
for (let i = 0; i < userId.length; i++) {
|
|
7090
|
+
hash = (hash << 5) - hash + userId.charCodeAt(i) | 0;
|
|
7091
|
+
}
|
|
7092
|
+
return Math.abs(hash) % 8;
|
|
7093
|
+
}
|
|
7094
|
+
function applyClientPrivacy(entry, privacy) {
|
|
7095
|
+
if (!privacy || privacy === "full") return entry;
|
|
7096
|
+
if (privacy === "masked") {
|
|
7097
|
+
return {
|
|
7098
|
+
userId: entry.userId,
|
|
7099
|
+
email: entry.email ? maskEmail2(entry.email) : void 0,
|
|
7100
|
+
fullName: entry.fullName ? `${entry.fullName[0].toUpperCase()}.` : void 0,
|
|
7101
|
+
provider: entry.provider,
|
|
7102
|
+
lastActiveAt: entry.lastActiveAt,
|
|
7103
|
+
colorIndex: stableColorIndex2(entry.userId)
|
|
7104
|
+
};
|
|
7105
|
+
}
|
|
7106
|
+
return {
|
|
7107
|
+
userId: entry.userId,
|
|
7108
|
+
provider: entry.provider,
|
|
7109
|
+
lastActiveAt: entry.lastActiveAt,
|
|
7110
|
+
displayLabel: "Account",
|
|
7111
|
+
colorIndex: stableColorIndex2(entry.userId)
|
|
7112
|
+
};
|
|
7113
|
+
}
|
|
6819
7114
|
function getCookie(name) {
|
|
6820
7115
|
if (typeof document === "undefined") return void 0;
|
|
6821
7116
|
const match = document.cookie.match(new RegExp(`(?:^|; )${name}=([^;]*)`));
|
|
@@ -6844,7 +7139,7 @@ async function proxyFetch(proxyUrl, path, options = {}) {
|
|
|
6844
7139
|
return data;
|
|
6845
7140
|
}
|
|
6846
7141
|
function useAuth() {
|
|
6847
|
-
const { client, user, setUser, initializing, error, setError, authProxyUrl } = useScaleMule();
|
|
7142
|
+
const { client, user, setUser, initializing, error, setError, authProxyUrl, enableAccountSwitcher, accountSwitcherPrivacy } = useScaleMule();
|
|
6848
7143
|
const register = react.useCallback(
|
|
6849
7144
|
async (data) => {
|
|
6850
7145
|
setError(null);
|
|
@@ -7452,6 +7747,63 @@ function useAuth() {
|
|
|
7452
7747
|
},
|
|
7453
7748
|
[client, setUser, setError, authProxyUrl]
|
|
7454
7749
|
);
|
|
7750
|
+
const readKnownAccountsCookie = react.useCallback(() => {
|
|
7751
|
+
if (!enableAccountSwitcher) return [];
|
|
7752
|
+
if (typeof document === "undefined") return [];
|
|
7753
|
+
const match = document.cookie.match(/(?:^|; )sm_known_accounts=([^;]*)/);
|
|
7754
|
+
if (!match) return [];
|
|
7755
|
+
try {
|
|
7756
|
+
const decoded = decodeURIComponent(match[1]);
|
|
7757
|
+
const accounts = JSON.parse(decoded);
|
|
7758
|
+
let entries = Object.values(accounts);
|
|
7759
|
+
if (accountSwitcherPrivacy && accountSwitcherPrivacy !== "full") {
|
|
7760
|
+
entries = entries.map((e) => applyClientPrivacy(e, accountSwitcherPrivacy));
|
|
7761
|
+
}
|
|
7762
|
+
return entries;
|
|
7763
|
+
} catch {
|
|
7764
|
+
return [];
|
|
7765
|
+
}
|
|
7766
|
+
}, [enableAccountSwitcher, accountSwitcherPrivacy]);
|
|
7767
|
+
const [knownAccounts, setKnownAccounts] = react.useState([]);
|
|
7768
|
+
react.useEffect(() => {
|
|
7769
|
+
setKnownAccounts(readKnownAccountsCookie());
|
|
7770
|
+
}, [readKnownAccountsCookie, user]);
|
|
7771
|
+
const switchAccount = react.useCallback(
|
|
7772
|
+
async (userId) => {
|
|
7773
|
+
const target = knownAccounts.find((a) => a.userId === userId) || null;
|
|
7774
|
+
if (!target) return null;
|
|
7775
|
+
if (authProxyUrl) {
|
|
7776
|
+
await proxyFetch(authProxyUrl, "switch-account");
|
|
7777
|
+
} else {
|
|
7778
|
+
const sessionToken = client.getSessionToken();
|
|
7779
|
+
if (sessionToken) {
|
|
7780
|
+
try {
|
|
7781
|
+
await client.post("/v1/auth/logout", { session_token: sessionToken });
|
|
7782
|
+
} catch {
|
|
7783
|
+
}
|
|
7784
|
+
}
|
|
7785
|
+
await client.clearSession();
|
|
7786
|
+
}
|
|
7787
|
+
setUser(null);
|
|
7788
|
+
return target;
|
|
7789
|
+
},
|
|
7790
|
+
[client, setUser, knownAccounts, authProxyUrl]
|
|
7791
|
+
);
|
|
7792
|
+
const removeKnownAccount = react.useCallback(
|
|
7793
|
+
async (userId) => {
|
|
7794
|
+
if (authProxyUrl) {
|
|
7795
|
+
await proxyFetch(authProxyUrl, "forget-account", { body: { user_id: userId } });
|
|
7796
|
+
}
|
|
7797
|
+
setKnownAccounts((prev) => prev.filter((a) => a.userId !== userId));
|
|
7798
|
+
},
|
|
7799
|
+
[authProxyUrl]
|
|
7800
|
+
);
|
|
7801
|
+
const clearKnownAccounts = react.useCallback(async () => {
|
|
7802
|
+
if (authProxyUrl) {
|
|
7803
|
+
await proxyFetch(authProxyUrl, "forget-all-accounts");
|
|
7804
|
+
}
|
|
7805
|
+
setKnownAccounts([]);
|
|
7806
|
+
}, [authProxyUrl]);
|
|
7455
7807
|
return react.useMemo(
|
|
7456
7808
|
() => ({
|
|
7457
7809
|
user,
|
|
@@ -7483,7 +7835,12 @@ function useAuth() {
|
|
|
7483
7835
|
// Phone auth
|
|
7484
7836
|
sendPhoneCode,
|
|
7485
7837
|
verifyPhone,
|
|
7486
|
-
loginWithPhone
|
|
7838
|
+
loginWithPhone,
|
|
7839
|
+
// Account switcher
|
|
7840
|
+
knownAccounts,
|
|
7841
|
+
switchAccount,
|
|
7842
|
+
removeKnownAccount,
|
|
7843
|
+
clearKnownAccounts
|
|
7487
7844
|
}),
|
|
7488
7845
|
[
|
|
7489
7846
|
user,
|
|
@@ -7510,7 +7867,11 @@ function useAuth() {
|
|
|
7510
7867
|
regenerateBackupCodes,
|
|
7511
7868
|
sendPhoneCode,
|
|
7512
7869
|
verifyPhone,
|
|
7513
|
-
loginWithPhone
|
|
7870
|
+
loginWithPhone,
|
|
7871
|
+
knownAccounts,
|
|
7872
|
+
switchAccount,
|
|
7873
|
+
removeKnownAccount,
|
|
7874
|
+
clearKnownAccounts
|
|
7514
7875
|
]
|
|
7515
7876
|
);
|
|
7516
7877
|
}
|