@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/README.md +35 -3
- package/dist/bulkMigrate.js +24 -8
- package/dist/generateAppConfig.js +2 -1
- package/dist/index.d.mts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +127 -62
- package/dist/index.mjs +127 -62
- package/dist/initConfig.js +2 -0
- package/dist/setupCoreInstance.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,26 @@ SuperTokens.init({
|
|
|
44
44
|
});
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
### Disabling Rownd User Migration
|
|
48
|
+
|
|
49
|
+
After migration is complete, disable Rownd user and session migration to run
|
|
50
|
+
the compatibility endpoints without Rownd credentials:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
RowndMigrationPlugin.init({
|
|
54
|
+
disableRowndUserMigration: true,
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This prevents the Rownd API client and the `/plugin/rownd/migrate` and
|
|
59
|
+
`/plugin/migrate-session` routes from being initialized. Other compatibility
|
|
60
|
+
endpoints remain enabled. Passwordless and email-verification links continue to
|
|
61
|
+
use the Rownd Hub with an internal dummy app key when `rowndAppKey` is omitted.
|
|
62
|
+
The plugin logs a warning during initialization while migration is disabled.
|
|
63
|
+
|
|
64
|
+
Without `disableRowndUserMigration: true`, both `rowndAppKey` and
|
|
65
|
+
`rowndAppSecret` are required.
|
|
66
|
+
|
|
47
67
|
### Session Claim Fields
|
|
48
68
|
|
|
49
69
|
Schema fields can be copied into the SuperTokens access-token payload by setting `include_in_session_claims: true`. Use `session_claim_name` when the claim name should differ from the Rownd data field name.
|
|
@@ -116,6 +136,7 @@ import { createMagicLinkWithConfirmationBypass } from "@supertokens-plugins/rown
|
|
|
116
136
|
|
|
117
137
|
const magicLink = await createMagicLinkWithConfirmationBypass({
|
|
118
138
|
email: "user@example.com",
|
|
139
|
+
tenantId: "tenant-a",
|
|
119
140
|
clientDomain: "browser",
|
|
120
141
|
redirectToPath: "/profile",
|
|
121
142
|
displayContext: "browser",
|
|
@@ -126,7 +147,7 @@ const magicLink = await createMagicLinkWithConfirmationBypass({
|
|
|
126
147
|
|
|
127
148
|
`clientDomain` must be a configured `clientDomains` key, not a raw domain. Omit it to use the SuperTokens website domain.
|
|
128
149
|
|
|
129
|
-
Pass exactly one of `email` or `phoneNumber`. The helper returns the rewritten magic link with `bypassDeviceConfirmation=true`.
|
|
150
|
+
Pass exactly one of `email` or `phoneNumber`. `tenantId` defaults to `public`. The helper returns the rewritten magic link with `bypassDeviceConfirmation=true`.
|
|
130
151
|
|
|
131
152
|
Before skipping the cross-device confirmation prompt, the frontend should validate the callback against the plugin. Routes are mounted under your SuperTokens `apiBasePath`, which defaults to `/auth`.
|
|
132
153
|
|
|
@@ -141,16 +162,25 @@ If validation fails, the frontend should show the normal cross-device confirmati
|
|
|
141
162
|
|
|
142
163
|
Routes are mounted under your SuperTokens `apiBasePath`, which defaults to `/auth`. The migration endpoint is the main Rownd-to-SuperTokens session handoff endpoint; the plugin also exposes Rownd-compatible app config, guest, user, metadata, field, and sign-out endpoints under `{apiBasePath}/plugin/rownd/...`.
|
|
143
164
|
|
|
165
|
+
Unauthenticated migration and guest routes accept an optional `tenantId` query parameter. It defaults to `public`. SuperTokens Core validates the tenant when the operation runs. Authenticated identity-field and sign-out operations use the tenant from the current session; custom Rownd metadata remains global to the SuperTokens user.
|
|
166
|
+
|
|
144
167
|
> [!IMPORTANT]
|
|
145
|
-
> The plugin always migrates users and sessions into the `public` tenant.
|
|
146
168
|
> Rownd users with multiple supported login methods are rejected unless SuperTokens account linking is enabled in the target environment.
|
|
147
169
|
|
|
148
170
|
### Migrate
|
|
149
171
|
|
|
150
172
|
- **POST** `{apiBasePath}/plugin/rownd/migrate`
|
|
151
173
|
- **Default**: `POST /auth/plugin/rownd/migrate`
|
|
174
|
+
- **Non-public tenant**: `POST /auth/plugin/rownd/migrate?tenantId=tenant-a`
|
|
152
175
|
- **Headers**: `Authorization: Bearer <Rownd_JWT>`. Header-token clients should also send `rid: session`, `fdi-version: 1.18`, and `st-auth-mode: header`.
|
|
153
|
-
- **Description**: Validates the Rownd JWT,
|
|
176
|
+
- **Description**: Validates the Rownd JWT, imports new users with their Rownd profile data, ensures the selected login method is associated with the requested SuperTokens tenant, and then creates a new SuperTokens session in that tenant. Header-token clients must receive `st-access-token`, `st-refresh-token`, and `front-token` response headers.
|
|
177
|
+
|
|
178
|
+
### Guest
|
|
179
|
+
|
|
180
|
+
- **POST** `{apiBasePath}/plugin/rownd/guest`
|
|
181
|
+
- **Default**: `POST /auth/plugin/rownd/guest`
|
|
182
|
+
- **Non-public tenant**: `POST /auth/plugin/rownd/guest?tenantId=tenant-a`
|
|
183
|
+
- **Description**: Creates a guest or instant user and session in the requested tenant.
|
|
154
184
|
|
|
155
185
|
## Debug Logging
|
|
156
186
|
|
|
@@ -228,6 +258,8 @@ RowndMigrationPlugin.init({
|
|
|
228
258
|
|
|
229
259
|
The package includes a bulk migration script for importing Rownd users into SuperTokens.
|
|
230
260
|
|
|
261
|
+
Set `supertokens.tenantId` in the generated configuration to associate every imported login method with a non-public tenant. It defaults to `public` when omitted. Resuming from a checkpoint with a different tenant is rejected.
|
|
262
|
+
|
|
231
263
|
The script runs from a YAML config file generated from the included template.
|
|
232
264
|
|
|
233
265
|
### Usage
|
package/dist/bulkMigrate.js
CHANGED
|
@@ -64,7 +64,7 @@ function buildSuperTokensFakeEmail(thirdPartyUserId, thirdPartyId) {
|
|
|
64
64
|
function isIdentityField(field) {
|
|
65
65
|
return IDENTITY_USER_DATA_FIELDS.has(field);
|
|
66
66
|
}
|
|
67
|
-
function mapRowndUserToSuperTokens(rowndUser) {
|
|
67
|
+
function mapRowndUserToSuperTokens(rowndUser, tenantId) {
|
|
68
68
|
const loginMethods = [];
|
|
69
69
|
const rowndUserData = rowndUser.data || {};
|
|
70
70
|
const rowndUserVerifiedData = rowndUser.verified_data || {};
|
|
@@ -78,7 +78,8 @@ function mapRowndUserToSuperTokens(rowndUser) {
|
|
|
78
78
|
thirdPartyId: "google",
|
|
79
79
|
thirdPartyUserId: rowndUserData.google_id,
|
|
80
80
|
email: googleEmail,
|
|
81
|
-
isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.google_id
|
|
81
|
+
isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.google_id,
|
|
82
|
+
...tenantId ? { tenantIds: [tenantId] } : {}
|
|
82
83
|
});
|
|
83
84
|
}
|
|
84
85
|
if (rowndUserData.apple_id) {
|
|
@@ -88,21 +89,24 @@ function mapRowndUserToSuperTokens(rowndUser) {
|
|
|
88
89
|
thirdPartyId: "apple",
|
|
89
90
|
thirdPartyUserId: rowndUserData.apple_id,
|
|
90
91
|
email: appleEmail,
|
|
91
|
-
isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.apple_id
|
|
92
|
+
isVerified: !!rowndUserData.email && !!rowndUserVerifiedData.apple_id,
|
|
93
|
+
...tenantId ? { tenantIds: [tenantId] } : {}
|
|
92
94
|
});
|
|
93
95
|
}
|
|
94
96
|
if (rowndUserData.phone_number) {
|
|
95
97
|
loginMethods.push({
|
|
96
98
|
recipeId: "passwordless",
|
|
97
99
|
phoneNumber: rowndUserData.phone_number,
|
|
98
|
-
isVerified: !!rowndUserVerifiedData.phone_number
|
|
100
|
+
isVerified: !!rowndUserVerifiedData.phone_number,
|
|
101
|
+
...tenantId ? { tenantIds: [tenantId] } : {}
|
|
99
102
|
});
|
|
100
103
|
}
|
|
101
104
|
if (rowndUserData.email && !rowndUserData.google_id && !rowndUserData.apple_id) {
|
|
102
105
|
loginMethods.push({
|
|
103
106
|
recipeId: "passwordless",
|
|
104
107
|
email: rowndUserData.email,
|
|
105
|
-
isVerified: !!rowndUserVerifiedData.email
|
|
108
|
+
isVerified: !!rowndUserVerifiedData.email,
|
|
109
|
+
...tenantId ? { tenantIds: [tenantId] } : {}
|
|
106
110
|
});
|
|
107
111
|
}
|
|
108
112
|
let authLevel = rowndUser.auth_level;
|
|
@@ -114,7 +118,8 @@ function mapRowndUserToSuperTokens(rowndUser) {
|
|
|
114
118
|
thirdPartyId,
|
|
115
119
|
thirdPartyUserId: rowndUserData.user_id,
|
|
116
120
|
email: `${rowndUserData.user_id}@anonymous.local`,
|
|
117
|
-
isVerified: false
|
|
121
|
+
isVerified: false,
|
|
122
|
+
...tenantId ? { tenantIds: [tenantId] } : {}
|
|
118
123
|
});
|
|
119
124
|
}
|
|
120
125
|
const userMetadata = buildRowndUserMetadata(rowndUser);
|
|
@@ -168,7 +173,8 @@ var ConfigSchema = import_zod.z.object({
|
|
|
168
173
|
supertokens: import_zod.z.object({
|
|
169
174
|
connectionURI: import_zod.z.string(),
|
|
170
175
|
apiKey: import_zod.z.string().optional(),
|
|
171
|
-
batchSize: import_zod.z.number().int().positive()
|
|
176
|
+
batchSize: import_zod.z.number().int().positive(),
|
|
177
|
+
tenantId: import_zod.z.string().min(1).default("public")
|
|
172
178
|
}),
|
|
173
179
|
thirdPartyProviders: import_zod.z.array(
|
|
174
180
|
import_zod.z.object({
|
|
@@ -366,6 +372,7 @@ Options:
|
|
|
366
372
|
var CheckpointSchema = import_zod2.z.object({
|
|
367
373
|
cursor: import_zod2.z.string().optional(),
|
|
368
374
|
importedCount: import_zod2.z.number().int().nonnegative().optional(),
|
|
375
|
+
tenantId: import_zod2.z.string().optional(),
|
|
369
376
|
updatedAt: import_zod2.z.string()
|
|
370
377
|
});
|
|
371
378
|
async function loadCheckpoint(checkpointFile) {
|
|
@@ -456,6 +463,11 @@ async function importUsersBatch(config, users, totalImportedBeforeBatch) {
|
|
|
456
463
|
}
|
|
457
464
|
async function migrateRowndUsersToSuperTokens(config) {
|
|
458
465
|
const checkpoint = config.checkpoint.resume ? await loadCheckpoint(config.checkpoint.file) : null;
|
|
466
|
+
if (checkpoint && (checkpoint.tenantId ?? "public") !== config.supertokens.tenantId) {
|
|
467
|
+
throw new Error(
|
|
468
|
+
`Checkpoint tenant ${checkpoint.tenantId ?? "public"} does not match configured tenant ${config.supertokens.tenantId}`
|
|
469
|
+
);
|
|
470
|
+
}
|
|
459
471
|
const failedMappingsFile = getFailedMappingsFilePath(config.checkpoint.file);
|
|
460
472
|
let cursor = checkpoint?.cursor;
|
|
461
473
|
let totalProcessed = 0;
|
|
@@ -489,7 +501,10 @@ async function migrateRowndUsersToSuperTokens(config) {
|
|
|
489
501
|
try {
|
|
490
502
|
mappedUsers.push({
|
|
491
503
|
rowndUserId,
|
|
492
|
-
user: mapRowndUserToSuperTokens(
|
|
504
|
+
user: mapRowndUserToSuperTokens(
|
|
505
|
+
rowndUser,
|
|
506
|
+
config.supertokens.tenantId === "public" ? void 0 : config.supertokens.tenantId
|
|
507
|
+
)
|
|
493
508
|
});
|
|
494
509
|
} catch (error) {
|
|
495
510
|
const errorMessage = error instanceof Error ? error.message : "Unknown mapping error";
|
|
@@ -511,6 +526,7 @@ async function migrateRowndUsersToSuperTokens(config) {
|
|
|
511
526
|
await saveCheckpoint(config.checkpoint.file, {
|
|
512
527
|
cursor,
|
|
513
528
|
importedCount: totalImported,
|
|
529
|
+
tenantId: config.supertokens.tenantId,
|
|
514
530
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
515
531
|
});
|
|
516
532
|
console.log(`Processed ${totalProcessed} users so far`);
|
|
@@ -68,7 +68,8 @@ var ConfigSchema = import_zod.z.object({
|
|
|
68
68
|
supertokens: import_zod.z.object({
|
|
69
69
|
connectionURI: import_zod.z.string(),
|
|
70
70
|
apiKey: import_zod.z.string().optional(),
|
|
71
|
-
batchSize: import_zod.z.number().int().positive()
|
|
71
|
+
batchSize: import_zod.z.number().int().positive(),
|
|
72
|
+
tenantId: import_zod.z.string().min(1).default("public")
|
|
72
73
|
}),
|
|
73
74
|
thirdPartyProviders: import_zod.z.array(
|
|
74
75
|
import_zod.z.object({
|
package/dist/index.d.mts
CHANGED
|
@@ -670,8 +670,14 @@ type RowndSubBrandConfigInput = RowndAppConfigInput & {
|
|
|
670
670
|
};
|
|
671
671
|
};
|
|
672
672
|
interface RowndPluginConfig {
|
|
673
|
-
rowndAppKey
|
|
674
|
-
rowndAppSecret
|
|
673
|
+
rowndAppKey?: string;
|
|
674
|
+
rowndAppSecret?: string;
|
|
675
|
+
/**
|
|
676
|
+
* Disables Rownd user and session migration. This must be enabled when
|
|
677
|
+
* rowndAppKey or rowndAppSecret is omitted.
|
|
678
|
+
* @default false
|
|
679
|
+
*/
|
|
680
|
+
disableRowndUserMigration?: boolean;
|
|
675
681
|
enableDebugLogs?: boolean;
|
|
676
682
|
clientDomains?: RowndClientDomains;
|
|
677
683
|
crossDeviceConfirmationBypass?: {
|
|
@@ -746,6 +752,7 @@ type RowndUserMetadata = {
|
|
|
746
752
|
field: string;
|
|
747
753
|
value: string;
|
|
748
754
|
created_at: string;
|
|
755
|
+
tenantId?: string;
|
|
749
756
|
}>;
|
|
750
757
|
[key: string]: unknown;
|
|
751
758
|
};
|
|
@@ -755,7 +762,8 @@ interface MigrationResponse {
|
|
|
755
762
|
}
|
|
756
763
|
interface RowndPluginNormalisedConfig {
|
|
757
764
|
rowndAppKey: string;
|
|
758
|
-
rowndAppSecret
|
|
765
|
+
rowndAppSecret?: string;
|
|
766
|
+
disableRowndUserMigration: boolean;
|
|
759
767
|
enableDebugLogs?: boolean;
|
|
760
768
|
clientDomains?: RowndClientDomains;
|
|
761
769
|
crossDeviceConfirmationBypass?: {
|
|
@@ -860,7 +868,7 @@ type CreateMagicLinkWithConfirmationBypassInput = {
|
|
|
860
868
|
};
|
|
861
869
|
declare function createMagicLinkWithConfirmationBypass(input: CreateMagicLinkWithConfirmationBypassInput): Promise<string>;
|
|
862
870
|
|
|
863
|
-
declare function setRowndClient(client: IRowndClient): void;
|
|
871
|
+
declare function setRowndClient(client: IRowndClient | undefined): void;
|
|
864
872
|
declare function getRowndClient(): IRowndClient;
|
|
865
873
|
|
|
866
874
|
declare const _default: {
|
package/dist/index.d.ts
CHANGED
|
@@ -670,8 +670,14 @@ type RowndSubBrandConfigInput = RowndAppConfigInput & {
|
|
|
670
670
|
};
|
|
671
671
|
};
|
|
672
672
|
interface RowndPluginConfig {
|
|
673
|
-
rowndAppKey
|
|
674
|
-
rowndAppSecret
|
|
673
|
+
rowndAppKey?: string;
|
|
674
|
+
rowndAppSecret?: string;
|
|
675
|
+
/**
|
|
676
|
+
* Disables Rownd user and session migration. This must be enabled when
|
|
677
|
+
* rowndAppKey or rowndAppSecret is omitted.
|
|
678
|
+
* @default false
|
|
679
|
+
*/
|
|
680
|
+
disableRowndUserMigration?: boolean;
|
|
675
681
|
enableDebugLogs?: boolean;
|
|
676
682
|
clientDomains?: RowndClientDomains;
|
|
677
683
|
crossDeviceConfirmationBypass?: {
|
|
@@ -746,6 +752,7 @@ type RowndUserMetadata = {
|
|
|
746
752
|
field: string;
|
|
747
753
|
value: string;
|
|
748
754
|
created_at: string;
|
|
755
|
+
tenantId?: string;
|
|
749
756
|
}>;
|
|
750
757
|
[key: string]: unknown;
|
|
751
758
|
};
|
|
@@ -755,7 +762,8 @@ interface MigrationResponse {
|
|
|
755
762
|
}
|
|
756
763
|
interface RowndPluginNormalisedConfig {
|
|
757
764
|
rowndAppKey: string;
|
|
758
|
-
rowndAppSecret
|
|
765
|
+
rowndAppSecret?: string;
|
|
766
|
+
disableRowndUserMigration: boolean;
|
|
759
767
|
enableDebugLogs?: boolean;
|
|
760
768
|
clientDomains?: RowndClientDomains;
|
|
761
769
|
crossDeviceConfirmationBypass?: {
|
|
@@ -860,7 +868,7 @@ type CreateMagicLinkWithConfirmationBypassInput = {
|
|
|
860
868
|
};
|
|
861
869
|
declare function createMagicLinkWithConfirmationBypass(input: CreateMagicLinkWithConfirmationBypassInput): Promise<string>;
|
|
862
870
|
|
|
863
|
-
declare function setRowndClient(client: IRowndClient): void;
|
|
871
|
+
declare function setRowndClient(client: IRowndClient | undefined): void;
|
|
864
872
|
declare function getRowndClient(): IRowndClient;
|
|
865
873
|
|
|
866
874
|
declare const _default: {
|