@supertokens-plugins/rownd-nodejs 0.2.0 → 0.3.0-beta.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/README.md +20 -0
- package/dist/bulkMigrate.js +1096 -0
- package/dist/cli.js +54 -0
- package/dist/generateAppConfig.js +731 -0
- package/dist/index.d.mts +826 -0
- package/dist/index.d.ts +826 -0
- package/dist/index.js +2752 -0
- package/dist/index.mjs +2732 -0
- package/dist/initConfig.js +136 -0
- package/dist/setupCoreInstance.js +295 -0
- package/package.json +13 -10
- package/scripts/bulkMigrate.ts +0 -450
- package/scripts/config.yaml +0 -27
- package/src/constants.ts +0 -5
- package/src/errors.ts +0 -13
- package/src/index.ts +0 -7
- package/src/logger.ts +0 -7
- package/src/plugin.test.ts +0 -790
- package/src/plugin.ts +0 -189
- package/src/pluginImplementation.ts +0 -187
- package/src/telemetry/axiomTelemetryClient.ts +0 -34
- package/src/telemetry/createTelemetryClient.ts +0 -87
- package/src/telemetry/openTelemetryClient.ts +0 -32
- package/src/types.ts +0 -124
|
@@ -0,0 +1,1096 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
};
|
|
12
|
+
var __export = (target, all) => {
|
|
13
|
+
for (var name in all)
|
|
14
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
15
|
+
};
|
|
16
|
+
var __copyProps = (to, from, except, desc) => {
|
|
17
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
18
|
+
for (let key of __getOwnPropNames(from))
|
|
19
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
20
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
25
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
26
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
27
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
28
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
29
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
30
|
+
mod
|
|
31
|
+
));
|
|
32
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
|
+
|
|
34
|
+
// ../../node_modules/has-flag/index.js
|
|
35
|
+
var require_has_flag = __commonJS({
|
|
36
|
+
"../../node_modules/has-flag/index.js"(exports2, module2) {
|
|
37
|
+
"use strict";
|
|
38
|
+
module2.exports = (flag, argv = process.argv) => {
|
|
39
|
+
const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
|
|
40
|
+
const position = argv.indexOf(prefix + flag);
|
|
41
|
+
const terminatorPosition = argv.indexOf("--");
|
|
42
|
+
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// ../../node_modules/supports-color/index.js
|
|
48
|
+
var require_supports_color = __commonJS({
|
|
49
|
+
"../../node_modules/supports-color/index.js"(exports2, module2) {
|
|
50
|
+
"use strict";
|
|
51
|
+
var os = require("os");
|
|
52
|
+
var tty = require("tty");
|
|
53
|
+
var hasFlag = require_has_flag();
|
|
54
|
+
var { env } = process;
|
|
55
|
+
var forceColor;
|
|
56
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
57
|
+
forceColor = 0;
|
|
58
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
59
|
+
forceColor = 1;
|
|
60
|
+
}
|
|
61
|
+
if ("FORCE_COLOR" in env) {
|
|
62
|
+
if (env.FORCE_COLOR === "true") {
|
|
63
|
+
forceColor = 1;
|
|
64
|
+
} else if (env.FORCE_COLOR === "false") {
|
|
65
|
+
forceColor = 0;
|
|
66
|
+
} else {
|
|
67
|
+
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function translateLevel(level) {
|
|
71
|
+
if (level === 0) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
return {
|
|
75
|
+
level,
|
|
76
|
+
hasBasic: true,
|
|
77
|
+
has256: level >= 2,
|
|
78
|
+
has16m: level >= 3
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function supportsColor(haveStream, streamIsTTY) {
|
|
82
|
+
if (forceColor === 0) {
|
|
83
|
+
return 0;
|
|
84
|
+
}
|
|
85
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
86
|
+
return 3;
|
|
87
|
+
}
|
|
88
|
+
if (hasFlag("color=256")) {
|
|
89
|
+
return 2;
|
|
90
|
+
}
|
|
91
|
+
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
92
|
+
return 0;
|
|
93
|
+
}
|
|
94
|
+
const min = forceColor || 0;
|
|
95
|
+
if (env.TERM === "dumb") {
|
|
96
|
+
return min;
|
|
97
|
+
}
|
|
98
|
+
if (process.platform === "win32") {
|
|
99
|
+
const osRelease = os.release().split(".");
|
|
100
|
+
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
101
|
+
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
102
|
+
}
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
if ("CI" in env) {
|
|
106
|
+
if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
|
|
107
|
+
return 1;
|
|
108
|
+
}
|
|
109
|
+
return min;
|
|
110
|
+
}
|
|
111
|
+
if ("TEAMCITY_VERSION" in env) {
|
|
112
|
+
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
|
|
113
|
+
}
|
|
114
|
+
if (env.COLORTERM === "truecolor") {
|
|
115
|
+
return 3;
|
|
116
|
+
}
|
|
117
|
+
if ("TERM_PROGRAM" in env) {
|
|
118
|
+
const version = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
|
|
119
|
+
switch (env.TERM_PROGRAM) {
|
|
120
|
+
case "iTerm.app":
|
|
121
|
+
return version >= 3 ? 3 : 2;
|
|
122
|
+
case "Apple_Terminal":
|
|
123
|
+
return 2;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (/-256(color)?$/i.test(env.TERM)) {
|
|
127
|
+
return 2;
|
|
128
|
+
}
|
|
129
|
+
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
if ("COLORTERM" in env) {
|
|
133
|
+
return 1;
|
|
134
|
+
}
|
|
135
|
+
return min;
|
|
136
|
+
}
|
|
137
|
+
function getSupportLevel(stream) {
|
|
138
|
+
const level = supportsColor(stream, stream && stream.isTTY);
|
|
139
|
+
return translateLevel(level);
|
|
140
|
+
}
|
|
141
|
+
module2.exports = {
|
|
142
|
+
supportsColor: getSupportLevel,
|
|
143
|
+
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
|
|
144
|
+
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// scripts/bulkMigrate.ts
|
|
150
|
+
var bulkMigrate_exports = {};
|
|
151
|
+
__export(bulkMigrate_exports, {
|
|
152
|
+
migrateRowndUsersToSuperTokens: () => migrateRowndUsersToSuperTokens,
|
|
153
|
+
runCli: () => runCli,
|
|
154
|
+
stageUsersForImport: () => stageUsersForImport
|
|
155
|
+
});
|
|
156
|
+
module.exports = __toCommonJS(bulkMigrate_exports);
|
|
157
|
+
var fs2 = __toESM(require("fs/promises"));
|
|
158
|
+
var import_zod2 = require("zod");
|
|
159
|
+
|
|
160
|
+
// src/pluginImplementation.ts
|
|
161
|
+
var import_supertokens_node = __toESM(require("supertokens-node"));
|
|
162
|
+
var import_accountlinking = __toESM(require("supertokens-node/recipe/accountlinking"));
|
|
163
|
+
var import_emailverification = __toESM(require("supertokens-node/recipe/emailverification"));
|
|
164
|
+
var import_passwordless = __toESM(require("supertokens-node/recipe/passwordless"));
|
|
165
|
+
var import_session = __toESM(require("supertokens-node/recipe/session"));
|
|
166
|
+
var import_claims = require("supertokens-node/recipe/session/claims");
|
|
167
|
+
var import_thirdparty = __toESM(require("supertokens-node/recipe/thirdparty"));
|
|
168
|
+
var import_usermetadata2 = __toESM(require("supertokens-node/recipe/usermetadata"));
|
|
169
|
+
|
|
170
|
+
// src/constants.ts
|
|
171
|
+
var PLUGIN_ID = "supertokens-plugin-rownd";
|
|
172
|
+
var PLUGIN_SDK_VERSION = ["23.0.0", "23.0.1", ">=23.0.1"];
|
|
173
|
+
var GUEST_AUTH_METHOD_ID = "guest";
|
|
174
|
+
var ANONYMOUS_AUTH_METHOD_ID = "anonymous";
|
|
175
|
+
|
|
176
|
+
// ../../shared/nodejs/src/pluginUserMetadata.ts
|
|
177
|
+
var import_usermetadata = __toESM(require("supertokens-node/recipe/usermetadata"));
|
|
178
|
+
|
|
179
|
+
// ../../shared/nodejs/src/log/logger.ts
|
|
180
|
+
var import_util = __toESM(require("util"));
|
|
181
|
+
|
|
182
|
+
// ../../shared/nodejs/src/log/common.ts
|
|
183
|
+
function setup(env) {
|
|
184
|
+
createDebug.debug = createDebug;
|
|
185
|
+
createDebug.default = createDebug;
|
|
186
|
+
createDebug.coerce = coerce;
|
|
187
|
+
createDebug.disable = disable;
|
|
188
|
+
createDebug.enable = enable;
|
|
189
|
+
createDebug.enabled = enabled;
|
|
190
|
+
createDebug.humanize = env.humanize;
|
|
191
|
+
createDebug.destroy = destroy;
|
|
192
|
+
Object.keys(env).forEach((key) => {
|
|
193
|
+
createDebug[key] = env[key];
|
|
194
|
+
});
|
|
195
|
+
createDebug.names = [];
|
|
196
|
+
createDebug.skips = [];
|
|
197
|
+
createDebug.formatters = {};
|
|
198
|
+
function selectColor(namespace) {
|
|
199
|
+
let hash = 0;
|
|
200
|
+
for (let i = 0; i < namespace.length; i++) {
|
|
201
|
+
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
202
|
+
hash |= 0;
|
|
203
|
+
}
|
|
204
|
+
return createDebug.colors[Math.abs(hash) % createDebug.colors.length];
|
|
205
|
+
}
|
|
206
|
+
createDebug.selectColor = selectColor;
|
|
207
|
+
function createDebug(namespace) {
|
|
208
|
+
let prevTime;
|
|
209
|
+
let enableOverride = null;
|
|
210
|
+
let namespacesCache;
|
|
211
|
+
let enabledCache;
|
|
212
|
+
function debug(...args) {
|
|
213
|
+
if (!debug.enabled) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const self = debug;
|
|
217
|
+
const curr = Number(/* @__PURE__ */ new Date());
|
|
218
|
+
const ms = curr - (prevTime || curr);
|
|
219
|
+
self.diff = ms;
|
|
220
|
+
self.prev = prevTime;
|
|
221
|
+
self.curr = curr;
|
|
222
|
+
prevTime = curr;
|
|
223
|
+
args[0] = createDebug.coerce(args[0]);
|
|
224
|
+
if (typeof args[0] !== "string") {
|
|
225
|
+
args.unshift("%O");
|
|
226
|
+
}
|
|
227
|
+
let index = 0;
|
|
228
|
+
args[0] = args[0].replace(/%([a-zA-Z%])/g, (match, format) => {
|
|
229
|
+
if (match === "%%") {
|
|
230
|
+
return "%";
|
|
231
|
+
}
|
|
232
|
+
index++;
|
|
233
|
+
const formatter = createDebug.formatters[format];
|
|
234
|
+
if (typeof formatter === "function") {
|
|
235
|
+
const val = args[index];
|
|
236
|
+
match = formatter.call(self, val);
|
|
237
|
+
args.splice(index, 1);
|
|
238
|
+
index--;
|
|
239
|
+
}
|
|
240
|
+
return match;
|
|
241
|
+
});
|
|
242
|
+
createDebug.formatArgs.call(self, args);
|
|
243
|
+
const logFn = self.log || createDebug.log;
|
|
244
|
+
logFn.apply(self, args);
|
|
245
|
+
}
|
|
246
|
+
debug.namespace = namespace;
|
|
247
|
+
debug.useColors = createDebug.useColors();
|
|
248
|
+
debug.color = createDebug.selectColor(namespace);
|
|
249
|
+
debug.extend = extend;
|
|
250
|
+
debug.destroy = createDebug.destroy;
|
|
251
|
+
Object.defineProperty(debug, "enabled", {
|
|
252
|
+
enumerable: true,
|
|
253
|
+
configurable: false,
|
|
254
|
+
get: () => {
|
|
255
|
+
if (enableOverride !== null) {
|
|
256
|
+
return enableOverride;
|
|
257
|
+
}
|
|
258
|
+
if (namespacesCache !== createDebug.namespaces) {
|
|
259
|
+
namespacesCache = createDebug.namespaces;
|
|
260
|
+
enabledCache = createDebug.enabled(namespace);
|
|
261
|
+
}
|
|
262
|
+
return enabledCache;
|
|
263
|
+
},
|
|
264
|
+
set: (v) => {
|
|
265
|
+
enableOverride = v;
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
if (typeof createDebug.init === "function") {
|
|
269
|
+
createDebug.init(debug);
|
|
270
|
+
}
|
|
271
|
+
return debug;
|
|
272
|
+
}
|
|
273
|
+
function extend(namespace, delimiter) {
|
|
274
|
+
const newDebug = createDebug(this.namespace + (typeof delimiter === "undefined" ? ":" : delimiter) + namespace);
|
|
275
|
+
newDebug.log = this.log;
|
|
276
|
+
return newDebug;
|
|
277
|
+
}
|
|
278
|
+
function enable(namespaces) {
|
|
279
|
+
createDebug.save(namespaces);
|
|
280
|
+
createDebug.namespaces = namespaces;
|
|
281
|
+
createDebug.names = [];
|
|
282
|
+
createDebug.skips = [];
|
|
283
|
+
const split = (typeof namespaces === "string" ? namespaces : "").trim().replace(/\s+/g, ",").split(",").filter(Boolean);
|
|
284
|
+
for (const ns of split) {
|
|
285
|
+
if (ns[0] === "-") {
|
|
286
|
+
createDebug.skips.push(ns.slice(1));
|
|
287
|
+
} else {
|
|
288
|
+
createDebug.names.push(ns);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function matchesTemplate(search, template) {
|
|
293
|
+
let searchIndex = 0;
|
|
294
|
+
let templateIndex = 0;
|
|
295
|
+
let starIndex = -1;
|
|
296
|
+
let matchIndex = 0;
|
|
297
|
+
while (searchIndex < search.length) {
|
|
298
|
+
if (templateIndex < template.length && (template[templateIndex] === search[searchIndex] || template[templateIndex] === "*")) {
|
|
299
|
+
if (template[templateIndex] === "*") {
|
|
300
|
+
starIndex = templateIndex;
|
|
301
|
+
matchIndex = searchIndex;
|
|
302
|
+
templateIndex++;
|
|
303
|
+
} else {
|
|
304
|
+
searchIndex++;
|
|
305
|
+
templateIndex++;
|
|
306
|
+
}
|
|
307
|
+
} else if (starIndex !== -1) {
|
|
308
|
+
templateIndex = starIndex + 1;
|
|
309
|
+
matchIndex++;
|
|
310
|
+
searchIndex = matchIndex;
|
|
311
|
+
} else {
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
while (templateIndex < template.length && template[templateIndex] === "*") {
|
|
316
|
+
templateIndex++;
|
|
317
|
+
}
|
|
318
|
+
return templateIndex === template.length;
|
|
319
|
+
}
|
|
320
|
+
function disable() {
|
|
321
|
+
const namespaces = [...createDebug.names, ...createDebug.skips.map((namespace) => "-" + namespace)].join(",");
|
|
322
|
+
createDebug.enable("");
|
|
323
|
+
return namespaces;
|
|
324
|
+
}
|
|
325
|
+
function enabled(name) {
|
|
326
|
+
for (const skip of createDebug.skips) {
|
|
327
|
+
if (matchesTemplate(name, skip)) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
for (const ns of createDebug.names) {
|
|
332
|
+
if (matchesTemplate(name, ns)) {
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return false;
|
|
337
|
+
}
|
|
338
|
+
function coerce(val) {
|
|
339
|
+
if (val instanceof Error) {
|
|
340
|
+
return val.stack || val.message;
|
|
341
|
+
}
|
|
342
|
+
return val;
|
|
343
|
+
}
|
|
344
|
+
function destroy() {
|
|
345
|
+
console.warn(
|
|
346
|
+
"Instance method `debug.destroy()` is deprecated and no longer does anything. It will be removed in the next major version of `debug`."
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
createDebug.enable(createDebug.load());
|
|
350
|
+
return createDebug;
|
|
351
|
+
}
|
|
352
|
+
var common_default = setup;
|
|
353
|
+
|
|
354
|
+
// ../../shared/nodejs/src/log/logger.ts
|
|
355
|
+
var BASIC_COLORS = [6, 2, 3, 4, 5, 1];
|
|
356
|
+
var EXTENDED_COLORS = [
|
|
357
|
+
20,
|
|
358
|
+
21,
|
|
359
|
+
26,
|
|
360
|
+
27,
|
|
361
|
+
32,
|
|
362
|
+
33,
|
|
363
|
+
38,
|
|
364
|
+
39,
|
|
365
|
+
40,
|
|
366
|
+
41,
|
|
367
|
+
42,
|
|
368
|
+
43,
|
|
369
|
+
44,
|
|
370
|
+
45,
|
|
371
|
+
56,
|
|
372
|
+
57,
|
|
373
|
+
62,
|
|
374
|
+
63,
|
|
375
|
+
68,
|
|
376
|
+
69,
|
|
377
|
+
74,
|
|
378
|
+
75,
|
|
379
|
+
76,
|
|
380
|
+
77,
|
|
381
|
+
78,
|
|
382
|
+
79,
|
|
383
|
+
80,
|
|
384
|
+
81,
|
|
385
|
+
92,
|
|
386
|
+
93,
|
|
387
|
+
98,
|
|
388
|
+
99,
|
|
389
|
+
112,
|
|
390
|
+
113,
|
|
391
|
+
128,
|
|
392
|
+
129,
|
|
393
|
+
134,
|
|
394
|
+
135,
|
|
395
|
+
148,
|
|
396
|
+
149,
|
|
397
|
+
160,
|
|
398
|
+
161,
|
|
399
|
+
162,
|
|
400
|
+
163,
|
|
401
|
+
164,
|
|
402
|
+
165,
|
|
403
|
+
166,
|
|
404
|
+
167,
|
|
405
|
+
168,
|
|
406
|
+
169,
|
|
407
|
+
170,
|
|
408
|
+
171,
|
|
409
|
+
172,
|
|
410
|
+
173,
|
|
411
|
+
178,
|
|
412
|
+
179,
|
|
413
|
+
184,
|
|
414
|
+
185,
|
|
415
|
+
196,
|
|
416
|
+
197,
|
|
417
|
+
198,
|
|
418
|
+
199,
|
|
419
|
+
200,
|
|
420
|
+
201,
|
|
421
|
+
202,
|
|
422
|
+
203,
|
|
423
|
+
204,
|
|
424
|
+
205,
|
|
425
|
+
206,
|
|
426
|
+
207,
|
|
427
|
+
208,
|
|
428
|
+
209,
|
|
429
|
+
214,
|
|
430
|
+
215,
|
|
431
|
+
220,
|
|
432
|
+
221
|
|
433
|
+
];
|
|
434
|
+
function supportsExtendedColors() {
|
|
435
|
+
try {
|
|
436
|
+
const supportsColor = require_supports_color();
|
|
437
|
+
return supportsColor && (supportsColor.stderr || supportsColor).level >= 2;
|
|
438
|
+
} catch {
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function shouldUseColors() {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
function formatArgs(args) {
|
|
446
|
+
const { namespace, useColors, color } = this;
|
|
447
|
+
if (useColors) {
|
|
448
|
+
const colorCode = color < 8 ? `3${color}` : `38;5;${color}`;
|
|
449
|
+
const prefix = `\x1B[${colorCode};1m${namespace}\x1B[0m`;
|
|
450
|
+
args[0] = `${prefix} ${args[0]}`.split("\n").join(`
|
|
451
|
+
${prefix} `);
|
|
452
|
+
args.push(`\x1B[${colorCode}m+${humanizeTime(this.diff)}\x1B[0m`);
|
|
453
|
+
} else {
|
|
454
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
455
|
+
args[0] = `${timestamp} ${namespace} ${args[0]}`;
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
function writeOutput(...args) {
|
|
459
|
+
process.stderr.write(import_util.default.format(...args) + "\n");
|
|
460
|
+
}
|
|
461
|
+
function saveConfig(namespaces) {
|
|
462
|
+
if (namespaces) {
|
|
463
|
+
process.env.DEBUG = namespaces;
|
|
464
|
+
} else {
|
|
465
|
+
delete process.env.DEBUG;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
function loadConfig() {
|
|
469
|
+
return process.env.DEBUG;
|
|
470
|
+
}
|
|
471
|
+
function humanizeTime(milliseconds) {
|
|
472
|
+
if (milliseconds >= 1e3) {
|
|
473
|
+
const seconds = Math.round(milliseconds / 1e3);
|
|
474
|
+
return `${seconds}s`;
|
|
475
|
+
}
|
|
476
|
+
return `${milliseconds}ms`;
|
|
477
|
+
}
|
|
478
|
+
function createLoggerConfig() {
|
|
479
|
+
const colors = supportsExtendedColors() ? EXTENDED_COLORS : BASIC_COLORS;
|
|
480
|
+
return {
|
|
481
|
+
colors,
|
|
482
|
+
useColors: shouldUseColors,
|
|
483
|
+
formatArgs,
|
|
484
|
+
log: writeOutput,
|
|
485
|
+
save: saveConfig,
|
|
486
|
+
load: loadConfig,
|
|
487
|
+
humanize: humanizeTime
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
var config = createLoggerConfig();
|
|
491
|
+
var logger = common_default(config);
|
|
492
|
+
if (logger.formatters) {
|
|
493
|
+
logger.formatters.o = function(value) {
|
|
494
|
+
return import_util.default.inspect(value, { colors: this.useColors, compact: true }).split("\n").map((line) => line.trim()).join(" ");
|
|
495
|
+
};
|
|
496
|
+
logger.formatters.O = function(value) {
|
|
497
|
+
return import_util.default.inspect(value, { colors: this.useColors, compact: false });
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
var logger_default = logger;
|
|
501
|
+
|
|
502
|
+
// ../../shared/nodejs/src/log/index.ts
|
|
503
|
+
var log_default = logger_default;
|
|
504
|
+
|
|
505
|
+
// ../../shared/nodejs/src/logger.ts
|
|
506
|
+
var getFileLocation = () => {
|
|
507
|
+
let errorObject = new Error();
|
|
508
|
+
if (errorObject.stack === void 0) {
|
|
509
|
+
return "N/A";
|
|
510
|
+
}
|
|
511
|
+
let errorStack = errorObject.stack.split("\n");
|
|
512
|
+
for (let i = 1; i < errorStack.length; i++) {
|
|
513
|
+
if (!errorStack[i]?.includes("logger.js")) {
|
|
514
|
+
return errorStack[i]?.match(/(?<=\().+?(?=\))/g);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return "N/A";
|
|
518
|
+
};
|
|
519
|
+
var buildLogger = (pluginId, version, { fileLocation = true } = {}) => {
|
|
520
|
+
const namespace = `com.supertokens.plugin.${pluginId}`;
|
|
521
|
+
function logDebugMessage2(message) {
|
|
522
|
+
if (log_default.enabled(namespace)) {
|
|
523
|
+
log_default(namespace)(
|
|
524
|
+
`{t: "${(/* @__PURE__ */ new Date()).toISOString()}", message: "${message}", file: "${fileLocation ? getFileLocation() : "N/A"}" version: "${version}"}`
|
|
525
|
+
);
|
|
526
|
+
console.log();
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
function enableDebugLogs2() {
|
|
530
|
+
log_default.enable(namespace);
|
|
531
|
+
}
|
|
532
|
+
return {
|
|
533
|
+
logDebugMessage: logDebugMessage2,
|
|
534
|
+
enableDebugLogs: enableDebugLogs2
|
|
535
|
+
};
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// src/logger.ts
|
|
539
|
+
var { logDebugMessage, enableDebugLogs } = buildLogger(
|
|
540
|
+
PLUGIN_ID,
|
|
541
|
+
PLUGIN_SDK_VERSION
|
|
542
|
+
);
|
|
543
|
+
|
|
544
|
+
// src/pluginImplementation.ts
|
|
545
|
+
function mapRowndUserToSuperTokens(rowndUser) {
|
|
546
|
+
const loginMethods = [];
|
|
547
|
+
const rowndUserData = rowndUser.data || {};
|
|
548
|
+
const rowndUserVerifiedData = rowndUser.verified_data || {};
|
|
549
|
+
if (!rowndUserData.user_id) {
|
|
550
|
+
throw new Error("Rownd user has no user_id");
|
|
551
|
+
}
|
|
552
|
+
if (rowndUserData.google_id) {
|
|
553
|
+
if (!rowndUserData.email) {
|
|
554
|
+
throw new Error("Rownd Google user is missing email");
|
|
555
|
+
}
|
|
556
|
+
loginMethods.push({
|
|
557
|
+
recipeId: "thirdparty",
|
|
558
|
+
thirdPartyId: "google",
|
|
559
|
+
thirdPartyUserId: rowndUserData.google_id,
|
|
560
|
+
email: rowndUserData.email,
|
|
561
|
+
isVerified: !!rowndUserVerifiedData.google_id
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (rowndUserData.apple_id) {
|
|
565
|
+
if (!rowndUserData.email) {
|
|
566
|
+
throw new Error("Rownd Apple user is missing email");
|
|
567
|
+
}
|
|
568
|
+
loginMethods.push({
|
|
569
|
+
recipeId: "thirdparty",
|
|
570
|
+
thirdPartyId: "apple",
|
|
571
|
+
thirdPartyUserId: rowndUserData.apple_id,
|
|
572
|
+
email: rowndUserData.email,
|
|
573
|
+
isVerified: !!rowndUserVerifiedData.apple_id
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
if (rowndUserData.phone_number) {
|
|
577
|
+
loginMethods.push({
|
|
578
|
+
recipeId: "passwordless",
|
|
579
|
+
phoneNumber: rowndUserData.phone_number,
|
|
580
|
+
isVerified: !!rowndUserVerifiedData.phone_number
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
if (rowndUserData.email && !rowndUserData.google_id && !rowndUserData.apple_id) {
|
|
584
|
+
loginMethods.push({
|
|
585
|
+
recipeId: "passwordless",
|
|
586
|
+
email: rowndUserData.email,
|
|
587
|
+
isVerified: !!rowndUserVerifiedData.email
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
let authLevel = rowndUser.auth_level;
|
|
591
|
+
if (loginMethods.length === 0) {
|
|
592
|
+
const thirdPartyId = authLevel === GUEST_AUTH_METHOD_ID ? GUEST_AUTH_METHOD_ID : ANONYMOUS_AUTH_METHOD_ID;
|
|
593
|
+
if (!authLevel) authLevel = thirdPartyId;
|
|
594
|
+
loginMethods.push({
|
|
595
|
+
recipeId: "thirdparty",
|
|
596
|
+
thirdPartyId,
|
|
597
|
+
thirdPartyUserId: rowndUserData.user_id,
|
|
598
|
+
email: `${rowndUserData.user_id}@anonymous.local`,
|
|
599
|
+
isVerified: false
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
const userMetadata = buildRowndUserMetadata(rowndUser);
|
|
603
|
+
return {
|
|
604
|
+
externalUserId: rowndUserData.user_id,
|
|
605
|
+
loginMethods,
|
|
606
|
+
userMetadata
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
var IDENTITY_USER_DATA_FIELDS = /* @__PURE__ */ new Set([
|
|
610
|
+
"user_id",
|
|
611
|
+
"email",
|
|
612
|
+
"phone_number",
|
|
613
|
+
"google_id",
|
|
614
|
+
"apple_id"
|
|
615
|
+
]);
|
|
616
|
+
function isIdentityField(field) {
|
|
617
|
+
return IDENTITY_USER_DATA_FIELDS.has(field);
|
|
618
|
+
}
|
|
619
|
+
function buildRowndUserMetadata(rowndUser) {
|
|
620
|
+
const metadata = {
|
|
621
|
+
...rowndUser.meta || {},
|
|
622
|
+
original_rownd_user: rowndUser
|
|
623
|
+
};
|
|
624
|
+
for (const [key, value] of Object.entries(rowndUser.data || {})) {
|
|
625
|
+
if (!isIdentityField(key) && value !== void 0) {
|
|
626
|
+
metadata[key] = value;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
return metadata;
|
|
630
|
+
}
|
|
631
|
+
var RowndIsAnonymousClaim = new import_claims.BooleanClaim({
|
|
632
|
+
key: "is_anonymous",
|
|
633
|
+
fetchValue: async (userId) => {
|
|
634
|
+
const user = await import_supertokens_node.default.getUser(userId);
|
|
635
|
+
const effectiveAuthLevel = getEffectiveAuthLevel(user);
|
|
636
|
+
return effectiveAuthLevel === GUEST_AUTH_METHOD_ID;
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
function getThirdPartyId(method) {
|
|
640
|
+
return method.thirdPartyId || method.thirdParty?.id;
|
|
641
|
+
}
|
|
642
|
+
function getThirdPartyUserId(method) {
|
|
643
|
+
return method.thirdPartyUserId || method.thirdParty?.userId;
|
|
644
|
+
}
|
|
645
|
+
function getGuestAuthLevel(user) {
|
|
646
|
+
const guestMethod = user?.loginMethods.find(isGuestLoginMethod);
|
|
647
|
+
return guestMethod ? GUEST_AUTH_METHOD_ID : void 0;
|
|
648
|
+
}
|
|
649
|
+
function isGuestLoginMethod(method) {
|
|
650
|
+
const thirdPartyId = getThirdPartyId(method);
|
|
651
|
+
return method.recipeId === "thirdparty" && (thirdPartyId === GUEST_AUTH_METHOD_ID || thirdPartyId === ANONYMOUS_AUTH_METHOD_ID);
|
|
652
|
+
}
|
|
653
|
+
function hasVerifiedRealLoginMethod(user) {
|
|
654
|
+
return !!user?.loginMethods.some((method) => {
|
|
655
|
+
if (isGuestLoginMethod(method)) {
|
|
656
|
+
return false;
|
|
657
|
+
}
|
|
658
|
+
if (method.recipeId === "passwordless") {
|
|
659
|
+
return !!(method.email || method.phoneNumber);
|
|
660
|
+
}
|
|
661
|
+
if (method.recipeId === "thirdparty") {
|
|
662
|
+
return !!getThirdPartyUserId(method) && method.verified === true;
|
|
663
|
+
}
|
|
664
|
+
if (method.recipeId === "emailpassword") {
|
|
665
|
+
return !!method.email && method.verified === true;
|
|
666
|
+
}
|
|
667
|
+
return method.verified === true;
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
function getEffectiveAuthLevel(user, originalAuthLevel, verifiedData) {
|
|
671
|
+
if (hasVerifiedRealLoginMethod(user)) {
|
|
672
|
+
return "verified";
|
|
673
|
+
}
|
|
674
|
+
return getGuestAuthLevel(user) || originalAuthLevel || (verifiedData && Object.keys(verifiedData).length > 0 ? "verified" : "unverified");
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// scripts/scriptUtils.ts
|
|
678
|
+
var fs = __toESM(require("fs/promises"));
|
|
679
|
+
var import_node_path = require("path");
|
|
680
|
+
var import_yaml = require("yaml");
|
|
681
|
+
var import_zod = require("zod");
|
|
682
|
+
var SCRIPT_DIR = __dirname;
|
|
683
|
+
var ConfigSchema = import_zod.z.object({
|
|
684
|
+
limit: import_zod.z.preprocess(
|
|
685
|
+
(value) => value === void 0 ? Number.POSITIVE_INFINITY : value,
|
|
686
|
+
import_zod.z.union([import_zod.z.literal(Number.POSITIVE_INFINITY), import_zod.z.number().int().positive()])
|
|
687
|
+
),
|
|
688
|
+
checkpoint: import_zod.z.object({
|
|
689
|
+
file: import_zod.z.string(),
|
|
690
|
+
resume: import_zod.z.boolean().default(false)
|
|
691
|
+
}),
|
|
692
|
+
retry: import_zod.z.object({
|
|
693
|
+
maxAttempts: import_zod.z.number().int().positive(),
|
|
694
|
+
initialDelayMs: import_zod.z.number().int().positive()
|
|
695
|
+
}),
|
|
696
|
+
rownd: import_zod.z.object({
|
|
697
|
+
appId: import_zod.z.string(),
|
|
698
|
+
appKey: import_zod.z.string(),
|
|
699
|
+
appSecret: import_zod.z.string(),
|
|
700
|
+
bearerToken: import_zod.z.string().optional(),
|
|
701
|
+
pageSize: import_zod.z.number().int().positive()
|
|
702
|
+
}),
|
|
703
|
+
supertokens: import_zod.z.object({
|
|
704
|
+
connectionURI: import_zod.z.string(),
|
|
705
|
+
apiKey: import_zod.z.string().optional(),
|
|
706
|
+
batchSize: import_zod.z.number().int().positive()
|
|
707
|
+
}),
|
|
708
|
+
thirdPartyProviders: import_zod.z.array(
|
|
709
|
+
import_zod.z.object({
|
|
710
|
+
thirdPartyId: import_zod.z.string(),
|
|
711
|
+
name: import_zod.z.string().optional(),
|
|
712
|
+
clients: import_zod.z.array(
|
|
713
|
+
import_zod.z.object({
|
|
714
|
+
clientType: import_zod.z.string().optional(),
|
|
715
|
+
clientId: import_zod.z.string(),
|
|
716
|
+
clientSecret: import_zod.z.string().optional(),
|
|
717
|
+
scope: import_zod.z.array(import_zod.z.string()).optional()
|
|
718
|
+
})
|
|
719
|
+
)
|
|
720
|
+
})
|
|
721
|
+
).optional()
|
|
722
|
+
});
|
|
723
|
+
var RowndUserRecordSchema = import_zod.z.looseObject({
|
|
724
|
+
user_id: import_zod.z.string().optional(),
|
|
725
|
+
rownd_user: import_zod.z.string().optional(),
|
|
726
|
+
subject: import_zod.z.string().optional(),
|
|
727
|
+
state: import_zod.z.string().optional(),
|
|
728
|
+
auth_level: import_zod.z.string().optional(),
|
|
729
|
+
data: import_zod.z.looseObject({
|
|
730
|
+
user_id: import_zod.z.string(),
|
|
731
|
+
email: import_zod.z.string().optional(),
|
|
732
|
+
phone_number: import_zod.z.string().optional(),
|
|
733
|
+
google_id: import_zod.z.string().optional(),
|
|
734
|
+
apple_id: import_zod.z.string().optional(),
|
|
735
|
+
first_name: import_zod.z.string().optional(),
|
|
736
|
+
last_name: import_zod.z.string().optional()
|
|
737
|
+
}),
|
|
738
|
+
verified_data: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).default({}),
|
|
739
|
+
attributes: import_zod.z.record(import_zod.z.string(), import_zod.z.array(import_zod.z.string())).optional(),
|
|
740
|
+
groups: import_zod.z.array(import_zod.z.unknown()).optional(),
|
|
741
|
+
meta: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
|
|
742
|
+
connection_map: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional()
|
|
743
|
+
});
|
|
744
|
+
var RowndUserListItemSchema = import_zod.z.object({
|
|
745
|
+
data: RowndUserRecordSchema
|
|
746
|
+
});
|
|
747
|
+
var RowndUsersPageSchema = import_zod.z.object({
|
|
748
|
+
results: import_zod.z.array(RowndUserRecordSchema).optional(),
|
|
749
|
+
data: import_zod.z.array(RowndUserListItemSchema).optional(),
|
|
750
|
+
total_results: import_zod.z.number().optional()
|
|
751
|
+
}).superRefine((value, context) => {
|
|
752
|
+
if (!value.results && !value.data) {
|
|
753
|
+
context.addIssue({
|
|
754
|
+
code: import_zod.z.ZodIssueCode.custom,
|
|
755
|
+
message: "Rownd API response is missing a results/data array."
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
function formatIssuePath(path) {
|
|
760
|
+
if (path.length === 0) {
|
|
761
|
+
return "<root>";
|
|
762
|
+
}
|
|
763
|
+
return path.map((segment, index) => {
|
|
764
|
+
if (typeof segment === "number") {
|
|
765
|
+
return `[${segment}]`;
|
|
766
|
+
}
|
|
767
|
+
return index === 0 ? segment : `.${segment}`;
|
|
768
|
+
}).join("");
|
|
769
|
+
}
|
|
770
|
+
function formatZodError(error) {
|
|
771
|
+
return error.issues.map(
|
|
772
|
+
(issue) => `${formatIssuePath(issue.path.filter((segment) => typeof segment === "string" || typeof segment === "number"))}: ${issue.message}`
|
|
773
|
+
).join("\n");
|
|
774
|
+
}
|
|
775
|
+
function parseConfig(rawConfig, configDir = SCRIPT_DIR) {
|
|
776
|
+
const parsed = ConfigSchema.parse(rawConfig);
|
|
777
|
+
const checkpointFile = (0, import_node_path.isAbsolute)(parsed.checkpoint.file) ? parsed.checkpoint.file : (0, import_node_path.resolve)(configDir, parsed.checkpoint.file);
|
|
778
|
+
return {
|
|
779
|
+
limit: parsed.limit,
|
|
780
|
+
checkpoint: {
|
|
781
|
+
file: checkpointFile,
|
|
782
|
+
resume: parsed.checkpoint.resume
|
|
783
|
+
},
|
|
784
|
+
retry: parsed.retry,
|
|
785
|
+
rownd: parsed.rownd,
|
|
786
|
+
supertokens: parsed.supertokens,
|
|
787
|
+
thirdPartyProviders: parsed.thirdPartyProviders
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
async function loadConfig2(configFilePath) {
|
|
791
|
+
const configFile = await fs.readFile(configFilePath, "utf8");
|
|
792
|
+
return parseConfig((0, import_yaml.parse)(configFile), (0, import_node_path.dirname)(configFilePath));
|
|
793
|
+
}
|
|
794
|
+
function parseRequiredConfigArg(args) {
|
|
795
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
796
|
+
const arg = args[i];
|
|
797
|
+
if (arg === "--config" || arg === "-c") {
|
|
798
|
+
const value = args[i + 1];
|
|
799
|
+
if (!value) {
|
|
800
|
+
throw new Error(`Missing value for ${arg}`);
|
|
801
|
+
}
|
|
802
|
+
return (0, import_node_path.resolve)(value);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
throw new Error("Missing required --config <path>");
|
|
806
|
+
}
|
|
807
|
+
function hasHelpArg(args) {
|
|
808
|
+
return args.includes("--help") || args.includes("-h");
|
|
809
|
+
}
|
|
810
|
+
function parseRowndUser(parsed) {
|
|
811
|
+
const rowndUserId = parsed.data.user_id;
|
|
812
|
+
const rowndUser = {
|
|
813
|
+
state: parsed.state ?? "",
|
|
814
|
+
auth_level: parsed.auth_level ?? "",
|
|
815
|
+
data: {
|
|
816
|
+
...parsed.data,
|
|
817
|
+
user_id: rowndUserId
|
|
818
|
+
},
|
|
819
|
+
verified_data: parsed.verified_data ?? {},
|
|
820
|
+
attributes: parsed.attributes,
|
|
821
|
+
groups: parsed.groups,
|
|
822
|
+
meta: parsed.meta
|
|
823
|
+
};
|
|
824
|
+
return { rowndUser, rowndUserId };
|
|
825
|
+
}
|
|
826
|
+
async function fetchRowndUsersPage(config2, cursor, pageSize) {
|
|
827
|
+
const url = new URL(
|
|
828
|
+
`/applications/${config2.rownd.appId}/users/data`,
|
|
829
|
+
"https://api.rownd.io"
|
|
830
|
+
);
|
|
831
|
+
if (cursor) {
|
|
832
|
+
url.searchParams.set("after", cursor);
|
|
833
|
+
}
|
|
834
|
+
url.searchParams.set("include_duplicates", "true");
|
|
835
|
+
url.searchParams.set("page_size", String(pageSize ?? config2.rownd.pageSize));
|
|
836
|
+
const response = await fetchWithRetry({
|
|
837
|
+
url: url.toString(),
|
|
838
|
+
requestInit: {
|
|
839
|
+
headers: {
|
|
840
|
+
"x-rownd-app-key": config2.rownd.appKey,
|
|
841
|
+
"x-rownd-app-secret": config2.rownd.appSecret
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
retryConfig: config2.retry,
|
|
845
|
+
operation: "Fetching Rownd users"
|
|
846
|
+
});
|
|
847
|
+
if (!response.ok) {
|
|
848
|
+
throw new Error(
|
|
849
|
+
`Rownd API error: ${response.status} ${await response.text()}`
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
const page = RowndUsersPageSchema.parse(await response.json());
|
|
853
|
+
const users = page.data?.map((entry) => entry.data) ?? page.results ?? [];
|
|
854
|
+
return users.map(parseRowndUser);
|
|
855
|
+
}
|
|
856
|
+
function isRetryableStatus(status) {
|
|
857
|
+
return status === 429 || status >= 500;
|
|
858
|
+
}
|
|
859
|
+
async function fetchWithRetry({
|
|
860
|
+
url,
|
|
861
|
+
requestInit,
|
|
862
|
+
retryConfig,
|
|
863
|
+
operation
|
|
864
|
+
}) {
|
|
865
|
+
let lastError;
|
|
866
|
+
for (let attempt = 1; attempt <= retryConfig.maxAttempts; attempt += 1) {
|
|
867
|
+
try {
|
|
868
|
+
const response = await fetch(url, requestInit);
|
|
869
|
+
if (response.ok || !isRetryableStatus(response.status) || attempt === retryConfig.maxAttempts) {
|
|
870
|
+
return response;
|
|
871
|
+
}
|
|
872
|
+
const responseText = await response.text();
|
|
873
|
+
lastError = new Error(
|
|
874
|
+
`${operation} failed with ${response.status}${responseText ? ` ${responseText}` : ""}`
|
|
875
|
+
);
|
|
876
|
+
} catch (error) {
|
|
877
|
+
if (attempt === retryConfig.maxAttempts) {
|
|
878
|
+
throw error;
|
|
879
|
+
}
|
|
880
|
+
lastError = error instanceof Error ? error : new Error(`${operation} failed`);
|
|
881
|
+
}
|
|
882
|
+
const delayMs = Math.round(
|
|
883
|
+
retryConfig.initialDelayMs * 2 ** (attempt - 1) * (1 + Math.random() * 0.2)
|
|
884
|
+
);
|
|
885
|
+
console.log(
|
|
886
|
+
`${operation} attempt ${attempt} failed. Retrying in ${delayMs}ms.`
|
|
887
|
+
);
|
|
888
|
+
await new Promise((resolve2) => setTimeout(resolve2, delayMs));
|
|
889
|
+
}
|
|
890
|
+
throw lastError ?? new Error(`${operation} failed`);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// scripts/bulkMigrate.ts
|
|
894
|
+
function printHelp() {
|
|
895
|
+
console.log(`Usage: rownd-nodejs bulk-migrate --config <path>
|
|
896
|
+
|
|
897
|
+
Options:
|
|
898
|
+
-c, --config <path> Path to the bulk migration config file
|
|
899
|
+
-h, --help Show this help message`);
|
|
900
|
+
}
|
|
901
|
+
var CheckpointSchema = import_zod2.z.object({
|
|
902
|
+
cursor: import_zod2.z.string().optional(),
|
|
903
|
+
importedCount: import_zod2.z.number().int().nonnegative().optional(),
|
|
904
|
+
updatedAt: import_zod2.z.string()
|
|
905
|
+
});
|
|
906
|
+
async function loadCheckpoint(checkpointFile) {
|
|
907
|
+
try {
|
|
908
|
+
const checkpoint = await fs2.readFile(checkpointFile, "utf8");
|
|
909
|
+
return CheckpointSchema.parse(JSON.parse(checkpoint));
|
|
910
|
+
} catch (error) {
|
|
911
|
+
if (error.code === "ENOENT") {
|
|
912
|
+
return null;
|
|
913
|
+
}
|
|
914
|
+
throw error;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
async function saveCheckpoint(checkpointFile, checkpoint) {
|
|
918
|
+
const tempFile = `${checkpointFile}.tmp`;
|
|
919
|
+
await fs2.writeFile(tempFile, JSON.stringify(checkpoint, null, 2), "utf8");
|
|
920
|
+
await fs2.rename(tempFile, checkpointFile);
|
|
921
|
+
}
|
|
922
|
+
function getFailedMappingsFilePath(checkpointFile) {
|
|
923
|
+
return `${checkpointFile}.failed-mappings.json`;
|
|
924
|
+
}
|
|
925
|
+
async function loadFailedMappings(filePath) {
|
|
926
|
+
try {
|
|
927
|
+
const contents = await fs2.readFile(filePath, "utf8");
|
|
928
|
+
const parsed = JSON.parse(contents);
|
|
929
|
+
if (!Array.isArray(parsed)) {
|
|
930
|
+
throw new Error("Failed mappings file must contain a JSON array.");
|
|
931
|
+
}
|
|
932
|
+
return parsed;
|
|
933
|
+
} catch (error) {
|
|
934
|
+
if (error.code === "ENOENT") {
|
|
935
|
+
return [];
|
|
936
|
+
}
|
|
937
|
+
throw error;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
async function appendFailedMappings(filePath, failedMappings) {
|
|
941
|
+
if (failedMappings.length === 0) {
|
|
942
|
+
return;
|
|
943
|
+
}
|
|
944
|
+
const existingMappings = await loadFailedMappings(filePath);
|
|
945
|
+
const tempFile = `${filePath}.tmp`;
|
|
946
|
+
await fs2.writeFile(
|
|
947
|
+
tempFile,
|
|
948
|
+
JSON.stringify([...existingMappings, ...failedMappings], null, 2),
|
|
949
|
+
"utf8"
|
|
950
|
+
);
|
|
951
|
+
await fs2.rename(tempFile, filePath);
|
|
952
|
+
}
|
|
953
|
+
async function stageUsersForImport(config2) {
|
|
954
|
+
const headers = {
|
|
955
|
+
"Content-Type": "application/json"
|
|
956
|
+
};
|
|
957
|
+
if (config2.supertokens.apiKey) {
|
|
958
|
+
headers["api-key"] = config2.supertokens.apiKey;
|
|
959
|
+
}
|
|
960
|
+
const response = await fetchWithRetry({
|
|
961
|
+
url: new URL(
|
|
962
|
+
"/bulk-import/users",
|
|
963
|
+
config2.supertokens.connectionURI
|
|
964
|
+
).toString(),
|
|
965
|
+
requestInit: {
|
|
966
|
+
method: "POST",
|
|
967
|
+
headers,
|
|
968
|
+
body: JSON.stringify({ users: config2.users })
|
|
969
|
+
},
|
|
970
|
+
retryConfig: config2.retry,
|
|
971
|
+
operation: "Importing users into SuperTokens"
|
|
972
|
+
});
|
|
973
|
+
if (!response.ok) {
|
|
974
|
+
throw new Error(
|
|
975
|
+
`SuperTokens bulk import error: ${response.status} ${await response.text()}`
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
async function importUsersBatch(config2, users, totalImportedBeforeBatch) {
|
|
980
|
+
for (let index = 0; index < users.length; index += config2.supertokens.batchSize) {
|
|
981
|
+
const batch = users.slice(index, index + config2.supertokens.batchSize);
|
|
982
|
+
console.log(
|
|
983
|
+
`Importing batch ${Math.floor(totalImportedBeforeBatch / config2.supertokens.batchSize) + 1} (${batch.length} users)`
|
|
984
|
+
);
|
|
985
|
+
await stageUsersForImport({
|
|
986
|
+
users: batch.map((entry) => entry.user),
|
|
987
|
+
supertokens: config2.supertokens,
|
|
988
|
+
retry: config2.retry
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
async function migrateRowndUsersToSuperTokens(config2) {
|
|
993
|
+
const checkpoint = config2.checkpoint.resume ? await loadCheckpoint(config2.checkpoint.file) : null;
|
|
994
|
+
const failedMappingsFile = getFailedMappingsFilePath(config2.checkpoint.file);
|
|
995
|
+
let cursor = checkpoint?.cursor;
|
|
996
|
+
let totalProcessed = 0;
|
|
997
|
+
let totalImported = checkpoint?.importedCount ?? 0;
|
|
998
|
+
let totalSkipped = 0;
|
|
999
|
+
if (config2.checkpoint.resume) {
|
|
1000
|
+
console.log(
|
|
1001
|
+
checkpoint ? `Resuming migration from cursor ${checkpoint.cursor ?? "<start>"}` : "No checkpoint found. Starting a fresh migration."
|
|
1002
|
+
);
|
|
1003
|
+
}
|
|
1004
|
+
while (totalProcessed < config2.limit) {
|
|
1005
|
+
const remaining = Number.isFinite(config2.limit) ? Math.max(config2.limit - totalProcessed, 0) : config2.rownd.pageSize;
|
|
1006
|
+
const requestedPageSize = Number.isFinite(config2.limit) ? Math.min(config2.rownd.pageSize, remaining) : config2.rownd.pageSize;
|
|
1007
|
+
if (requestedPageSize === 0) {
|
|
1008
|
+
break;
|
|
1009
|
+
}
|
|
1010
|
+
console.log(
|
|
1011
|
+
`Fetching page ${Math.floor(totalProcessed / config2.rownd.pageSize) + 1}`
|
|
1012
|
+
);
|
|
1013
|
+
const pageUsers = await fetchRowndUsersPage(
|
|
1014
|
+
config2,
|
|
1015
|
+
cursor,
|
|
1016
|
+
requestedPageSize
|
|
1017
|
+
);
|
|
1018
|
+
if (pageUsers.length === 0) {
|
|
1019
|
+
break;
|
|
1020
|
+
}
|
|
1021
|
+
const mappedUsers = [];
|
|
1022
|
+
const failedMappings = [];
|
|
1023
|
+
for (const { rowndUser, rowndUserId } of pageUsers) {
|
|
1024
|
+
try {
|
|
1025
|
+
mappedUsers.push({
|
|
1026
|
+
rowndUserId,
|
|
1027
|
+
user: mapRowndUserToSuperTokens(rowndUser)
|
|
1028
|
+
});
|
|
1029
|
+
} catch (error) {
|
|
1030
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown mapping error";
|
|
1031
|
+
failedMappings.push({
|
|
1032
|
+
user: rowndUser,
|
|
1033
|
+
error: errorMessage
|
|
1034
|
+
});
|
|
1035
|
+
console.warn(
|
|
1036
|
+
`Skipping Rownd user ${rowndUserId}: ${errorMessage}. Saved to ${failedMappingsFile}`
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
await appendFailedMappings(failedMappingsFile, failedMappings);
|
|
1041
|
+
totalSkipped += failedMappings.length;
|
|
1042
|
+
await importUsersBatch(config2, mappedUsers, totalImported);
|
|
1043
|
+
totalProcessed += pageUsers.length;
|
|
1044
|
+
totalImported += mappedUsers.length;
|
|
1045
|
+
cursor = pageUsers[pageUsers.length - 1]?.rowndUserId;
|
|
1046
|
+
await saveCheckpoint(config2.checkpoint.file, {
|
|
1047
|
+
cursor,
|
|
1048
|
+
importedCount: totalImported,
|
|
1049
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1050
|
+
});
|
|
1051
|
+
console.log(`Processed ${totalProcessed} users so far`);
|
|
1052
|
+
console.log(`Imported ${totalImported} users so far`);
|
|
1053
|
+
if (pageUsers.length < requestedPageSize) {
|
|
1054
|
+
break;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
return {
|
|
1058
|
+
totalProcessed,
|
|
1059
|
+
totalImported,
|
|
1060
|
+
totalSkipped,
|
|
1061
|
+
cursor
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
async function runCli() {
|
|
1065
|
+
const args = process.argv.slice(2);
|
|
1066
|
+
if (hasHelpArg(args)) {
|
|
1067
|
+
printHelp();
|
|
1068
|
+
return;
|
|
1069
|
+
}
|
|
1070
|
+
const config2 = await loadConfig2(parseRequiredConfigArg(args));
|
|
1071
|
+
const result = await migrateRowndUsersToSuperTokens(config2);
|
|
1072
|
+
console.log(`Migrated ${result.totalImported} users`);
|
|
1073
|
+
if (result.totalSkipped > 0) {
|
|
1074
|
+
console.warn(
|
|
1075
|
+
`Skipped ${result.totalSkipped} users. Details saved to ${getFailedMappingsFilePath(config2.checkpoint.file)}`
|
|
1076
|
+
);
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
if (require.main === module) {
|
|
1080
|
+
runCli().catch((error) => {
|
|
1081
|
+
if (error instanceof import_zod2.z.ZodError) {
|
|
1082
|
+
console.error(formatZodError(error));
|
|
1083
|
+
} else {
|
|
1084
|
+
console.error(
|
|
1085
|
+
error instanceof Error ? error.message : "Bulk migration failed"
|
|
1086
|
+
);
|
|
1087
|
+
}
|
|
1088
|
+
process.exitCode = 1;
|
|
1089
|
+
});
|
|
1090
|
+
}
|
|
1091
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1092
|
+
0 && (module.exports = {
|
|
1093
|
+
migrateRowndUsersToSuperTokens,
|
|
1094
|
+
runCli,
|
|
1095
|
+
stageUsersForImport
|
|
1096
|
+
});
|