@supertokens-plugins/rownd-nodejs 0.5.1 → 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.
package/dist/index.js CHANGED
@@ -866,6 +866,9 @@ var RowndPluginError = class extends Error {
866
866
 
867
867
  // src/utils.ts
868
868
  var ROWND_OAUTH_LOGIN_CHALLENGE_PARAM = "rownd_oauth_login_challenge";
869
+ function resolveTenantId(req) {
870
+ return req.getKeyValueFromQuery("tenantId") || PUBLIC_TENANT_ID;
871
+ }
869
872
  function rewriteLinkPath(inputUrl, targetPath, searchParams) {
870
873
  try {
871
874
  const url = new URL(inputUrl);
@@ -1497,7 +1500,7 @@ function isIdentityField(field) {
1497
1500
  function isInternalMetadataField(field) {
1498
1501
  return INTERNAL_METADATA_FIELDS.has(field);
1499
1502
  }
1500
- function mapRowndUserToSuperTokens(rowndUser) {
1503
+ function mapRowndUserToSuperTokens(rowndUser, tenantId) {
1501
1504
  const loginMethods = [];
1502
1505
  const rowndUserData = rowndUser.data || {};
1503
1506
  const rowndUserVerifiedData = rowndUser.verified_data || {};
@@ -1511,7 +1514,8 @@ function mapRowndUserToSuperTokens(rowndUser) {
1511
1514
  thirdPartyId: "google",
1512
1515
  thirdPartyUserId: rowndUserData.google_id,
1513
1516
  email: googleEmail,
1514
- isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.google_id
1517
+ isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.google_id,
1518
+ ...tenantId ? { tenantIds: [tenantId] } : {}
1515
1519
  });
1516
1520
  }
1517
1521
  if (rowndUserData.apple_id) {
@@ -1521,21 +1525,24 @@ function mapRowndUserToSuperTokens(rowndUser) {
1521
1525
  thirdPartyId: "apple",
1522
1526
  thirdPartyUserId: rowndUserData.apple_id,
1523
1527
  email: appleEmail,
1524
- isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.apple_id
1528
+ isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.apple_id,
1529
+ ...tenantId ? { tenantIds: [tenantId] } : {}
1525
1530
  });
1526
1531
  }
1527
1532
  if (rowndUserData.phone_number) {
1528
1533
  loginMethods.push({
1529
1534
  recipeId: "passwordless",
1530
1535
  phoneNumber: rowndUserData.phone_number,
1531
- isVerified: !!rowndUserVerifiedData.phone_number
1536
+ isVerified: !!rowndUserVerifiedData.phone_number,
1537
+ ...tenantId ? { tenantIds: [tenantId] } : {}
1532
1538
  });
1533
1539
  }
1534
1540
  if (rowndUserData.email && !rowndUserData.google_id && !rowndUserData.apple_id) {
1535
1541
  loginMethods.push({
1536
1542
  recipeId: "passwordless",
1537
1543
  email: rowndUserData.email,
1538
- isVerified: !!rowndUserVerifiedData.email
1544
+ isVerified: !!rowndUserVerifiedData.email,
1545
+ ...tenantId ? { tenantIds: [tenantId] } : {}
1539
1546
  });
1540
1547
  }
1541
1548
  let authLevel = rowndUser.auth_level;
@@ -1547,7 +1554,8 @@ function mapRowndUserToSuperTokens(rowndUser) {
1547
1554
  thirdPartyId,
1548
1555
  thirdPartyUserId: rowndUserData.user_id,
1549
1556
  email: `${rowndUserData.user_id}@anonymous.local`,
1550
- isVerified: false
1557
+ isVerified: false,
1558
+ ...tenantId ? { tenantIds: [tenantId] } : {}
1551
1559
  });
1552
1560
  }
1553
1561
  const userMetadata = buildRowndUserMetadata(rowndUser);
@@ -2093,7 +2101,7 @@ function getPendingVerifications(metadata) {
2093
2101
  function isPendingVerification(value) {
2094
2102
  return isRecord(value) && typeof value.id === "string" && typeof value.field === "string" && typeof value.value === "string" && typeof value.created_at === "string";
2095
2103
  }
2096
- async function getUserById(userId) {
2104
+ async function getUserById(userId, tenantId = PUBLIC_TENANT_ID) {
2097
2105
  const metadata = await getUserMetadata(userId);
2098
2106
  const stUser = await import_supertokens_node2.default.getUser(userId);
2099
2107
  if (!stUser) {
@@ -2122,7 +2130,10 @@ async function getUserById(userId) {
2122
2130
  const verifiedData = {
2123
2131
  ...originalRowndUser?.verified_data || {}
2124
2132
  };
2125
- for (const method of stUser.loginMethods) {
2133
+ const tenantLoginMethods = stUser.loginMethods.filter(
2134
+ (method) => method.tenantIds.includes(tenantId)
2135
+ );
2136
+ for (const method of tenantLoginMethods) {
2126
2137
  if (method.recipeId === "passwordless") {
2127
2138
  if (method.email && !isSuperTokensFakeEmail(method.email)) {
2128
2139
  verifiedData.email = method.email;
@@ -2162,12 +2173,16 @@ async function getUserById(userId) {
2162
2173
  if (verifiedData.phone_number === true && typeof data.phone_number === "string") {
2163
2174
  verifiedData.phone_number = data.phone_number;
2164
2175
  }
2165
- const anonymousId = getAnonymousId(stUser.id, stUser, metadata);
2176
+ const tenantUser = {
2177
+ ...stUser,
2178
+ loginMethods: tenantLoginMethods
2179
+ };
2180
+ const anonymousId = getAnonymousId(stUser.id, tenantUser, metadata);
2166
2181
  if (anonymousId && data.anonymous_id === void 0) {
2167
2182
  data.anonymous_id = anonymousId;
2168
2183
  }
2169
2184
  const authLevel = getEffectiveAuthLevel(
2170
- stUser,
2185
+ tenantUser,
2171
2186
  originalRowndUser?.auth_level,
2172
2187
  verifiedData
2173
2188
  );
@@ -2176,15 +2191,15 @@ async function getUserById(userId) {
2176
2191
  data[key] = "";
2177
2192
  }
2178
2193
  }
2179
- const sortedByJoined = [...stUser.loginMethods].sort(
2194
+ const sortedByJoined = [...tenantLoginMethods].sort(
2180
2195
  (a, b) => a.timeJoined - b.timeJoined
2181
2196
  );
2182
- const latestSessionInfo = await getLatestSessionInfo(stUser.id);
2197
+ const latestSessionInfo = await getLatestSessionInfo(stUser.id, tenantId);
2183
2198
  const firstMethod = sortedByJoined[0];
2184
2199
  const latestSessionRecipeUserId = latestSessionInfo?.recipeUserId.getAsString();
2185
2200
  const lastMethod = latestSessionRecipeUserId ? stUser.loginMethods.find(
2186
2201
  (method) => method.recipeUserId.getAsString() === latestSessionRecipeUserId
2187
- ) : [...stUser.loginMethods].sort((a, b) => b.timeJoined - a.timeJoined)[0];
2202
+ ) : [...tenantLoginMethods].sort((a, b) => b.timeJoined - a.timeJoined)[0];
2188
2203
  const lastSignInAt = latestSessionInfo?.timeCreated ?? stUser.timeJoined;
2189
2204
  const metadataMeta = Object.fromEntries(
2190
2205
  Object.entries(metadata).filter(
@@ -2212,11 +2227,11 @@ async function getUserById(userId) {
2212
2227
  attributes: originalRowndUser?.attributes || {}
2213
2228
  };
2214
2229
  }
2215
- async function getLatestSessionInfo(userId) {
2230
+ async function getLatestSessionInfo(userId, tenantId) {
2216
2231
  const sessionHandles = await import_session.default.getAllSessionHandlesForUser(
2217
2232
  userId,
2218
2233
  true,
2219
- PUBLIC_TENANT_ID
2234
+ tenantId
2220
2235
  );
2221
2236
  const sessionInfos = await Promise.all(
2222
2237
  sessionHandles.map(
@@ -2231,21 +2246,21 @@ async function getLatestSessionInfo(userId) {
2231
2246
  }
2232
2247
  return latestSessionInfo;
2233
2248
  }
2234
- async function updateUserData(userId, inputData) {
2249
+ async function updateUserData(userId, inputData, tenantId = PUBLIC_TENANT_ID) {
2235
2250
  const metadata = await getUserMetadata(userId);
2236
2251
  const updatedMetadata = {
2237
2252
  ...metadata,
2238
2253
  ...inputData
2239
2254
  };
2240
2255
  await import_usermetadata3.default.updateUserMetadata(userId, updatedMetadata);
2241
- return getUserById(userId);
2256
+ return getUserById(userId, tenantId);
2242
2257
  }
2243
2258
  async function startPendingEmailVerification(input) {
2244
2259
  const metadata = await getUserMetadata(input.userId);
2245
- const currentEmail = (await getUserById(input.userId)).data.email;
2260
+ const currentEmail = (await getUserById(input.userId, input.tenantId)).data.email;
2246
2261
  const pendingVerifications = getPendingVerifications(metadata);
2247
2262
  const pendingEmailVerifications = pendingVerifications.filter(
2248
- (pendingVerification2) => pendingVerification2.field === "email"
2263
+ (pendingVerification2) => pendingVerification2.field === "email" && (pendingVerification2.tenantId ?? PUBLIC_TENANT_ID) === input.tenantId
2249
2264
  );
2250
2265
  if (currentEmail === input.email) {
2251
2266
  for (const pendingVerification2 of pendingEmailVerifications) {
@@ -2260,11 +2275,11 @@ async function startPendingEmailVerification(input) {
2260
2275
  await import_usermetadata3.default.updateUserMetadata(input.userId, {
2261
2276
  ...metadata,
2262
2277
  rownd_pending_verification: pendingVerifications.filter(
2263
- (pendingVerification2) => pendingVerification2.field !== "email"
2278
+ (pendingVerification2) => pendingVerification2.field !== "email" || (pendingVerification2.tenantId ?? PUBLIC_TENANT_ID) !== input.tenantId
2264
2279
  )
2265
2280
  });
2266
2281
  }
2267
- return getUserById(input.userId);
2282
+ return getUserById(input.userId, input.tenantId);
2268
2283
  }
2269
2284
  for (const pendingVerification2 of pendingEmailVerifications) {
2270
2285
  await import_emailverification.default.revokeEmailVerificationTokens(
@@ -2278,13 +2293,14 @@ async function startPendingEmailVerification(input) {
2278
2293
  id: input.pendingVerificationId,
2279
2294
  field: "email",
2280
2295
  value: input.email,
2281
- created_at: (/* @__PURE__ */ new Date()).toISOString()
2296
+ created_at: (/* @__PURE__ */ new Date()).toISOString(),
2297
+ tenantId: input.tenantId
2282
2298
  };
2283
2299
  await import_usermetadata3.default.updateUserMetadata(input.userId, {
2284
2300
  ...metadata,
2285
2301
  rownd_pending_verification: [
2286
2302
  ...pendingVerifications.filter(
2287
- (pendingVerification2) => pendingVerification2.field !== "email"
2303
+ (pendingVerification2) => pendingVerification2.field !== "email" || (pendingVerification2.tenantId ?? PUBLIC_TENANT_ID) !== input.tenantId
2288
2304
  ),
2289
2305
  pendingVerification
2290
2306
  ]
@@ -2303,12 +2319,14 @@ async function startPendingEmailVerification(input) {
2303
2319
  await completePendingEmailVerification({
2304
2320
  recipeUserId: input.recipeUserId,
2305
2321
  email: input.email,
2322
+ tenantId: input.tenantId,
2306
2323
  userContext: input.userContext
2307
2324
  });
2308
2325
  }
2309
- return getUserById(input.userId);
2326
+ return getUserById(input.userId, input.tenantId);
2310
2327
  }
2311
2328
  async function completePendingEmailVerification(input) {
2329
+ const tenantId = input.tenantId ?? PUBLIC_TENANT_ID;
2312
2330
  const user = await import_supertokens_node2.default.getUser(
2313
2331
  input.recipeUserId.getAsString(),
2314
2332
  input.userContext
@@ -2319,7 +2337,8 @@ async function completePendingEmailVerification(input) {
2319
2337
  const pendingVerification = pendingVerifications.find(
2320
2338
  (pendingVerification2) => isMatchingPendingEmailVerification(
2321
2339
  pendingVerification2,
2322
- input.email
2340
+ input.email,
2341
+ tenantId
2323
2342
  )
2324
2343
  );
2325
2344
  if (!pendingVerification) {
@@ -2327,7 +2346,12 @@ async function completePendingEmailVerification(input) {
2327
2346
  }
2328
2347
  let metadataUserId = userId;
2329
2348
  let verifiedRecipeUserId = input.recipeUserId;
2330
- const passwordlessEmailMethod = getPasswordlessEmailLoginMethod(user);
2349
+ const tenantLoginMethods = user?.loginMethods.filter(
2350
+ (method) => method.tenantIds.includes(tenantId)
2351
+ ) ?? [];
2352
+ const passwordlessEmailMethod = getPasswordlessEmailLoginMethod(
2353
+ tenantLoginMethods
2354
+ );
2331
2355
  if (passwordlessEmailMethod) {
2332
2356
  const updateResult = await import_passwordless.default.updateUser({
2333
2357
  recipeUserId: passwordlessEmailMethod.recipeUserId,
@@ -2340,9 +2364,9 @@ async function completePendingEmailVerification(input) {
2340
2364
  );
2341
2365
  }
2342
2366
  verifiedRecipeUserId = passwordlessEmailMethod.recipeUserId;
2343
- } else if (hasOnlyGuestLoginMethods(user)) {
2367
+ } else if (hasOnlyGuestLoginMethods(user ? { ...user, loginMethods: tenantLoginMethods } : user)) {
2344
2368
  const isPasswordlessSignUpAllowed = await import_accountlinking.default.isSignUpAllowed(
2345
- PUBLIC_TENANT_ID,
2369
+ tenantId,
2346
2370
  {
2347
2371
  recipeId: "passwordless",
2348
2372
  email: input.email
@@ -2356,7 +2380,7 @@ async function completePendingEmailVerification(input) {
2356
2380
  }
2357
2381
  const passwordlessUser = await import_passwordless.default.signInUp({
2358
2382
  email: input.email,
2359
- tenantId: PUBLIC_TENANT_ID,
2383
+ tenantId,
2360
2384
  userContext: input.userContext
2361
2385
  });
2362
2386
  verifiedRecipeUserId = passwordlessUser.recipeUserId;
@@ -2400,7 +2424,8 @@ async function completePendingEmailVerification(input) {
2400
2424
  rownd_pending_verification: targetPendingVerifications.filter(
2401
2425
  (verification) => !isMatchingPendingEmailVerification(
2402
2426
  verification,
2403
- input.email
2427
+ input.email,
2428
+ tenantId
2404
2429
  )
2405
2430
  )
2406
2431
  };
@@ -2410,8 +2435,8 @@ async function completePendingEmailVerification(input) {
2410
2435
  recipeUserId: verifiedRecipeUserId
2411
2436
  };
2412
2437
  }
2413
- function isMatchingPendingEmailVerification(verification, email) {
2414
- return verification.field === "email" && verification.value === email;
2438
+ function isMatchingPendingEmailVerification(verification, email, tenantId) {
2439
+ return verification.field === "email" && verification.value === email && (verification.tenantId ?? PUBLIC_TENANT_ID) === tenantId;
2415
2440
  }
2416
2441
  async function updateUserMetadata(userId, inputMeta) {
2417
2442
  const metadata = await getUserMetadata(userId);
@@ -2429,8 +2454,8 @@ async function updateUserMetadata(userId, inputMeta) {
2429
2454
  )
2430
2455
  };
2431
2456
  }
2432
- function getPasswordlessEmailLoginMethod(user) {
2433
- return user?.loginMethods.find((method) => {
2457
+ function getPasswordlessEmailLoginMethod(loginMethods) {
2458
+ return loginMethods.find((method) => {
2434
2459
  return method.recipeId === "passwordless" && !!method.email;
2435
2460
  });
2436
2461
  }
@@ -2440,6 +2465,7 @@ var import_crypto = require("crypto");
2440
2465
  var import_supertokens_node3 = __toESM(require("supertokens-node"));
2441
2466
  var import_session2 = __toESM(require("supertokens-node/recipe/session"));
2442
2467
  var import_thirdparty = __toESM(require("supertokens-node/recipe/thirdparty"));
2468
+ var import_multitenancy = __toESM(require("supertokens-node/recipe/multitenancy"));
2443
2469
  function isBodyString(body, key) {
2444
2470
  return isRecord(body) && typeof body[key] === "string" && body[key].length > 0;
2445
2471
  }
@@ -2504,7 +2530,9 @@ function handleGuestLogin(deps) {
2504
2530
  return async (req, res, _session, userContext) => {
2505
2531
  const startedAt = Date.now();
2506
2532
  const guestId = `guest_${(0, import_crypto.randomUUID)()}`;
2533
+ let tenantId;
2507
2534
  try {
2535
+ tenantId = resolveTenantId(req);
2508
2536
  const body = parseGuestBody(await getJsonBody(req));
2509
2537
  const appVariantId = getRequestedAppVariantIdFromRequest(req);
2510
2538
  assertRowndAppVariantIsConfigured(appVariantId);
@@ -2512,7 +2540,7 @@ function handleGuestLogin(deps) {
2512
2540
  const thirdPartyUserId = thirdPartyId === INSTANT_AUTH_METHOD_ID ? `anon_${(0, import_crypto.randomUUID)()}` : guestId;
2513
2541
  const authLevel = thirdPartyId === INSTANT_AUTH_METHOD_ID ? INSTANT_AUTH_METHOD_ID : GUEST_AUTH_METHOD_ID;
2514
2542
  const response = await import_thirdparty.default.manuallyCreateOrUpdateUser(
2515
- PUBLIC_TENANT_ID,
2543
+ tenantId,
2516
2544
  thirdPartyId,
2517
2545
  thirdPartyUserId,
2518
2546
  `${thirdPartyUserId}@anonymous.local`,
@@ -2528,7 +2556,7 @@ function handleGuestLogin(deps) {
2528
2556
  await import_session2.default.createNewSession(
2529
2557
  req,
2530
2558
  res,
2531
- PUBLIC_TENANT_ID,
2559
+ tenantId,
2532
2560
  response.recipeUserId,
2533
2561
  {
2534
2562
  ...buildRowndAudience({}, appVariantId),
@@ -2543,7 +2571,7 @@ function handleGuestLogin(deps) {
2543
2571
  deps.telemetryClient.recordSuccess({
2544
2572
  outcome: "success",
2545
2573
  durationMs: Date.now() - startedAt,
2546
- tenantId: PUBLIC_TENANT_ID,
2574
+ tenantId,
2547
2575
  superTokensUserId: response.user.id
2548
2576
  });
2549
2577
  return {
@@ -2555,7 +2583,7 @@ function handleGuestLogin(deps) {
2555
2583
  deps.telemetryClient.recordError({
2556
2584
  error,
2557
2585
  startedAt,
2558
- tenantId: PUBLIC_TENANT_ID
2586
+ tenantId
2559
2587
  });
2560
2588
  return {
2561
2589
  status: "ERROR",
@@ -2567,7 +2595,7 @@ function handleGuestLogin(deps) {
2567
2595
  function handleMigrate(deps) {
2568
2596
  return async (req, res, _session, userContext) => {
2569
2597
  const startedAt = Date.now();
2570
- let tenantId = PUBLIC_TENANT_ID;
2598
+ let tenantId;
2571
2599
  let rowndUserId;
2572
2600
  let superTokensUserId;
2573
2601
  let user;
@@ -2576,6 +2604,7 @@ function handleMigrate(deps) {
2576
2604
  if (!deps.stConfig.supertokens) {
2577
2605
  throw new Error("Supertokens config not found");
2578
2606
  }
2607
+ tenantId = resolveTenantId(req);
2579
2608
  const parsed = await parseRequest(req);
2580
2609
  const appVariantId = getRequestedAppVariantIdFromRequest(req);
2581
2610
  assertRowndAppVariantIsConfigured(appVariantId);
@@ -2583,13 +2612,16 @@ function handleMigrate(deps) {
2583
2612
  const rowndUser = await fetchOptionalRowndUserInfo(rowndUserId);
2584
2613
  if (!rowndUser) {
2585
2614
  logDebugMessage(
2586
- `Skipping migration because user does not exist in Rownd. tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
2615
+ `Skipping migration because user does not exist in Rownd. tenantId: ${tenantId}, rowndUserId: ${rowndUserId}`
2587
2616
  );
2588
2617
  return { status: "OK" };
2589
2618
  }
2590
2619
  user = await import_supertokens_node3.default.getUser(rowndUserId, userContext);
2591
2620
  if (!user) {
2592
- const stUserImport = mapRowndUserToSuperTokens(rowndUser);
2621
+ const stUserImport = mapRowndUserToSuperTokens(
2622
+ rowndUser,
2623
+ tenantId === PUBLIC_TENANT_ID ? void 0 : tenantId
2624
+ );
2593
2625
  try {
2594
2626
  await importUser(stUserImport, deps.stConfig.supertokens);
2595
2627
  clearSuperTokensCoreCallCache(userContext);
@@ -2607,29 +2639,43 @@ function handleMigrate(deps) {
2607
2639
  superTokensUserId = user.id;
2608
2640
  recipeUserId = user.loginMethods[0]?.recipeUserId;
2609
2641
  logDebugMessage(
2610
- `User already migrated (race condition). tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
2642
+ `User already migrated (race condition). tenantId: ${tenantId}, rowndUserId: ${rowndUserId}`
2611
2643
  );
2612
2644
  }
2613
2645
  logDebugMessage(
2614
- `User migrated successfully. tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
2646
+ `User migrated successfully. tenantId: ${tenantId}, rowndUserId: ${rowndUserId}`
2615
2647
  );
2616
2648
  } else {
2617
2649
  superTokensUserId = user.id;
2618
2650
  recipeUserId = user.loginMethods[0]?.recipeUserId;
2619
2651
  logDebugMessage(
2620
- `User already migrated. tenantId: ${PUBLIC_TENANT_ID}, rowndUserId: ${rowndUserId}`
2652
+ `User already migrated. tenantId: ${tenantId}, rowndUserId: ${rowndUserId}`
2621
2653
  );
2622
2654
  }
2623
2655
  if (superTokensUserId) {
2624
2656
  await recordRowndAppVariantForUser(superTokensUserId, appVariantId);
2625
2657
  }
2658
+ const tenantLoginMethod = user?.loginMethods.find(
2659
+ (method) => method.tenantIds.includes(tenantId)
2660
+ );
2661
+ recipeUserId = tenantLoginMethod?.recipeUserId ?? recipeUserId;
2626
2662
  if (!recipeUserId) {
2627
2663
  throw new Error("User not found or has no login methods");
2628
2664
  }
2665
+ if (!tenantLoginMethod) {
2666
+ const associationResult = await import_multitenancy.default.associateUserToTenant(
2667
+ tenantId,
2668
+ recipeUserId,
2669
+ userContext
2670
+ );
2671
+ if (associationResult.status !== "OK") {
2672
+ throw new Error(`Failed to associate migrated user with tenant: ${associationResult.status}`);
2673
+ }
2674
+ }
2629
2675
  await import_session2.default.createNewSession(
2630
2676
  req,
2631
2677
  res,
2632
- PUBLIC_TENANT_ID,
2678
+ tenantId,
2633
2679
  recipeUserId,
2634
2680
  {
2635
2681
  ...buildRowndAudience({}, appVariantId)
@@ -2638,7 +2684,7 @@ function handleMigrate(deps) {
2638
2684
  userContext
2639
2685
  );
2640
2686
  logDebugMessage(
2641
- `Session migrated successfully. tenantId: ${PUBLIC_TENANT_ID}, userId: ${superTokensUserId}`
2687
+ `Session migrated successfully. tenantId: ${tenantId}, userId: ${superTokensUserId}`
2642
2688
  );
2643
2689
  deps.telemetryClient.recordSuccess({
2644
2690
  outcome: "success",
@@ -2672,7 +2718,7 @@ function clearSuperTokensCoreCallCache(userContext) {
2672
2718
  }
2673
2719
  function handleGetUser() {
2674
2720
  return async (_req, _res, session) => {
2675
- const user = await getUserById(session.getUserId());
2721
+ const user = await getUserById(session.getUserId(), session.getTenantId());
2676
2722
  return {
2677
2723
  status: "OK",
2678
2724
  ...user
@@ -2698,7 +2744,11 @@ function handleUpdateUser() {
2698
2744
  return permissionError;
2699
2745
  }
2700
2746
  if (Object.keys(dataWithoutEmail).length > 0) {
2701
- await updateUserData(session.getUserId(), dataWithoutEmail);
2747
+ await updateUserData(
2748
+ session.getUserId(),
2749
+ dataWithoutEmail,
2750
+ session.getTenantId()
2751
+ );
2702
2752
  }
2703
2753
  if (hasEmailUpdate) {
2704
2754
  const pendingVerificationResult = await startPendingEmailVerification({
@@ -2714,7 +2764,7 @@ function handleUpdateUser() {
2714
2764
  ...pendingVerificationResult
2715
2765
  };
2716
2766
  }
2717
- const user = await getUserById(session.getUserId());
2767
+ const user = await getUserById(session.getUserId(), session.getTenantId());
2718
2768
  return {
2719
2769
  status: "OK",
2720
2770
  ...user
@@ -2781,7 +2831,7 @@ function handleGetUserField() {
2781
2831
  if (!field) {
2782
2832
  return missingFieldResponse();
2783
2833
  }
2784
- const user = await getUserById(session.getUserId());
2834
+ const user = await getUserById(session.getUserId(), session.getTenantId());
2785
2835
  return {
2786
2836
  status: "OK",
2787
2837
  value: user.data[field]
@@ -2815,9 +2865,11 @@ function handleUpdateUserField() {
2815
2865
  if (permissionError) {
2816
2866
  return permissionError;
2817
2867
  }
2818
- const updateUserDataResult = await updateUserData(session.getUserId(), {
2819
- [field]: payload.value
2820
- });
2868
+ const updateUserDataResult = await updateUserData(
2869
+ session.getUserId(),
2870
+ { [field]: payload.value },
2871
+ session.getTenantId()
2872
+ );
2821
2873
  return {
2822
2874
  status: "OK",
2823
2875
  ...updateUserDataResult
@@ -2837,6 +2889,7 @@ function validateWritableFields(fields) {
2837
2889
  }
2838
2890
 
2839
2891
  // src/plugin.ts
2892
+ var DISABLED_MIGRATION_ROWND_APP_KEY = "migration-disabled";
2840
2893
  var verifyRowndUserSessionOptions = {
2841
2894
  sessionRequired: true,
2842
2895
  overrideGlobalClaimValidators: (validators) => validators.filter((validator) => {
@@ -2845,10 +2898,10 @@ var verifyRowndUserSessionOptions = {
2845
2898
  };
2846
2899
  var init = createPluginInitFunction(
2847
2900
  (pluginConfig2) => {
2848
- const rowndClient2 = (0, import_node.createInstance)({
2901
+ const rowndClient2 = !pluginConfig2.disableRowndUserMigration && pluginConfig2.rowndAppSecret ? (0, import_node.createInstance)({
2849
2902
  app_key: pluginConfig2.rowndAppKey,
2850
2903
  app_secret: pluginConfig2.rowndAppSecret
2851
- });
2904
+ }) : void 0;
2852
2905
  const telemetryClient = createClient(pluginConfig2.telemetry);
2853
2906
  let hubBootstrapParams;
2854
2907
  const addHubBootstrapParams = (input, linkKey, targetPath) => {
@@ -2888,6 +2941,11 @@ var init = createPluginInitFunction(
2888
2941
  id: PLUGIN_ID,
2889
2942
  compatibleSDKVersions: PLUGIN_SDK_VERSION,
2890
2943
  init: async () => {
2944
+ if (pluginConfig2.disableRowndUserMigration) {
2945
+ console.warn(
2946
+ "RowndMigrationPlugin: Rownd user and session migration is disabled."
2947
+ );
2948
+ }
2891
2949
  if (!import_supertokens_node4.default.isRecipeInitialized("session")) {
2892
2950
  console.warn(
2893
2951
  "RowndMigrationPlugin: Session recipe is not initialized. Session migration will fail."
@@ -2931,11 +2989,11 @@ var init = createPluginInitFunction(
2931
2989
  method: "post",
2932
2990
  handler: withRequestHandler(handleGuestLogin(routeHandlerDeps))
2933
2991
  },
2934
- {
2992
+ ...!pluginConfig2.disableRowndUserMigration ? [{
2935
2993
  path: `${apiBasePath}${HANDLE_BASE_PATH}/migrate`,
2936
2994
  method: "post",
2937
2995
  handler: withRequestHandler(handleMigrate(routeHandlerDeps))
2938
- },
2996
+ }] : [],
2939
2997
  {
2940
2998
  path: `${apiBasePath}/plugin/passwordless-cross-device-confirmation/validate`,
2941
2999
  method: "post",
@@ -2943,11 +3001,11 @@ var init = createPluginInitFunction(
2943
3001
  handleValidatePasswordlessConfirmationBypass(routeHandlerDeps)
2944
3002
  )
2945
3003
  },
2946
- {
3004
+ ...!pluginConfig2.disableRowndUserMigration ? [{
2947
3005
  path: `${apiBasePath}/plugin/migrate-session`,
2948
3006
  method: "post",
2949
3007
  handler: withRequestHandler(handleMigrate(routeHandlerDeps))
2950
- },
3008
+ }] : [],
2951
3009
  {
2952
3010
  path: `${apiBasePath}${HANDLE_BASE_PATH}/signout`,
2953
3011
  method: "post",
@@ -3300,6 +3358,7 @@ var init = createPluginInitFunction(
3300
3358
  const verificationResult = await completePendingEmailVerification({
3301
3359
  recipeUserId: response.user.recipeUserId,
3302
3360
  email: response.user.email,
3361
+ tenantId: input.tenantId,
3303
3362
  userContext: input.userContext
3304
3363
  });
3305
3364
  const session = input.session;
@@ -3326,9 +3385,14 @@ var init = createPluginInitFunction(
3326
3385
  },
3327
3386
  () => ({}),
3328
3387
  (config2) => {
3329
- if (!config2?.rowndAppKey || !config2?.rowndAppSecret) {
3388
+ if (config2?.disableRowndUserMigration !== void 0 && typeof config2.disableRowndUserMigration !== "boolean") {
3389
+ throw new Error(
3390
+ "disableRowndUserMigration must be a boolean in plugin config"
3391
+ );
3392
+ }
3393
+ if (!config2?.disableRowndUserMigration && (!config2?.rowndAppKey || !config2?.rowndAppSecret)) {
3330
3394
  throw new Error(
3331
- "Missing rowndAppKey or rowndAppSecret in plugin config"
3395
+ "Missing rowndAppKey or rowndAppSecret in plugin config. Set disableRowndUserMigration to true to disable migration."
3332
3396
  );
3333
3397
  }
3334
3398
  if (config2.telemetry?.provider === "axiom") {
@@ -3349,8 +3413,9 @@ var init = createPluginInitFunction(
3349
3413
  validateClientDomainUrl(key, value);
3350
3414
  }
3351
3415
  return {
3352
- rowndAppKey: config2.rowndAppKey,
3416
+ rowndAppKey: config2.rowndAppKey ?? DISABLED_MIGRATION_ROWND_APP_KEY,
3353
3417
  rowndAppSecret: config2.rowndAppSecret,
3418
+ disableRowndUserMigration: config2.disableRowndUserMigration === true,
3354
3419
  enableDebugLogs: config2.enableDebugLogs,
3355
3420
  clientDomains: config2.clientDomains,
3356
3421
  crossDeviceConfirmationBypass: config2.crossDeviceConfirmationBypass,