npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@supertokens-plugins/rownd-nodejs

v0.6.1

Published

Rownd User Migration Plugin for SuperTokens

Readme

SuperTokens Rownd User Migration Plugin

This plugin facilitates the migration of users and sessions from Rownd to SuperTokens.

Installation

npm install @supertokens-plugins/rownd-nodejs

Quick Start

Backend Configuration

Initialize the plugin in your SuperTokens backend configuration.

[!IMPORTANT] This plugin always requires the Session and UserMetadata recipes. Enable Passwordless for email/phone, ThirdParty for Google/Apple/guest/anonymous users, EmailVerification for verified email profile updates, and AccountLinking when migrated Rownd users may have multiple supported login methods.

import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
import UserMetadata from "supertokens-node/recipe/usermetadata";
import RowndMigrationPlugin from "@supertokens-plugins/rownd-nodejs";

SuperTokens.init({
  appInfo: {
    // your app info
  },
  recipeList: [
    Session.init(),
    UserMetadata.init(),
    // your other recipes
  ],
  experimental: {
    plugins: [
      RowndMigrationPlugin.init({
        rowndAppKey: process.env.ROWND_APP_KEY,
        rowndAppSecret: process.env.ROWND_APP_SECRET,
        enableDebugLogs: process.env.ENABLE_DEBUG_LOGS === "true",
      }),
    ],
  },
});

Disabling Rownd User Migration

After migration is complete, disable Rownd user and session migration to run the compatibility endpoints without Rownd credentials:

RowndMigrationPlugin.init({
  disableRowndUserMigration: true,
});

This prevents the Rownd API client and the /plugin/rownd/migrate and /plugin/migrate-session routes from being initialized. Other compatibility endpoints remain enabled. Passwordless and email-verification links continue to use the Rownd Hub with an internal dummy app key when rowndAppKey is omitted. The plugin logs a warning during initialization while migration is disabled.

Without disableRowndUserMigration: true, both rowndAppKey and rowndAppSecret are required.

Session Claim Fields

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.

RowndMigrationPlugin.init({
  rowndAppKey: process.env.ROWND_APP_KEY,
  rowndAppSecret: process.env.ROWND_APP_SECRET,
  schema: {
    employee_id: {
      display_name: "Employee ID",
      type: "string",
      user_visible: false,
      include_in_session_claims: true,
      session_claim_name: "employee_id_claim",
    },
  },
});

Client Link Domains

Set clientDomains to rewrite account links to different frontend URL bases. Values must be absolute URL bases, including custom schemes for native deep links. The plugin selects mobile for mobile_app display context and browser otherwise. Consumers can pass rownd_client_domain to select any custom key.

RowndMigrationPlugin.init({
  rowndAppKey: process.env.ROWND_APP_KEY,
  rowndAppSecret: process.env.ROWND_APP_SECRET,
  clientDomains: {
    browser: "https://app.example.com",
    mobile: "customDomain://",
    browser_local: "http://localhost:3000",
  },
});

Passwordless Confirmation Bypass

Use createMagicLinkWithConfirmationBypass when your backend needs to create a passwordless magic link that can be opened on a different device without showing the SuperTokens cross-device confirmation prompt. This is intended for trusted server-side flows only.

First, configure the exact post-login paths that may use the bypass:

const rowndPluginConfig = {
  rowndAppKey: process.env.ROWND_APP_KEY,
  rowndAppSecret: process.env.ROWND_APP_SECRET,
  clientDomains: {
    browser: "https://app.example.com",
  },
  crossDeviceConfirmationBypass: {
    allowedRedirectPaths: ["/profile", "/settings/security"],
  },
};

const superTokensConfig = {
  // your app info and recipe list
  experimental: {
    plugins: [RowndMigrationPlugin.init(rowndPluginConfig)],
  },
};

SuperTokens.init(superTokensConfig);

Then call the helper from your backend:

import { createMagicLinkWithConfirmationBypass } from "@supertokens-plugins/rownd-nodejs";

const magicLink = await createMagicLinkWithConfirmationBypass({
  email: "[email protected]",
  tenantId: "tenant-a",
  clientDomain: "browser",
  redirectToPath: "/profile",
  displayContext: "browser",
});

redirectToPath is required and must match crossDeviceConfirmationBypass.allowedRedirectPaths exactly after normalization. Absolute URLs are accepted only when their origin matches the resolved clientDomain; they are normalized back to a relative path before being added to the magic link.

clientDomain must be a configured clientDomains key, not a raw domain. Omit it to use the SuperTokens website domain.

Pass exactly one of email or phoneNumber. tenantId defaults to public. The helper returns the rewritten magic link with bypassDeviceConfirmation=true.

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.

  • POST {apiBasePath}/plugin/passwordless-cross-device-confirmation/validate
  • Default: POST /auth/plugin/passwordless-cross-device-confirmation/validate
  • Body: { "clientDomain": "browser", "redirectToPath": "/profile", "appVariantId": "optional_variant" }
  • Success response: { "status": "OK", "bypass": true }

If validation fails, the frontend should show the normal cross-device confirmation prompt.

API Endpoints

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/....

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.

[!IMPORTANT] Rownd users with multiple supported login methods are rejected unless SuperTokens account linking is enabled in the target environment.

Migrate

  • POST {apiBasePath}/plugin/rownd/migrate
  • Default: POST /auth/plugin/rownd/migrate
  • Non-public tenant: POST /auth/plugin/rownd/migrate?tenantId=tenant-a
  • Headers: Authorization: Bearer <Rownd_JWT>. Header-token clients should also send rid: session, fdi-version: 1.18, and st-auth-mode: header.
  • 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.

Guest

  • POST {apiBasePath}/plugin/rownd/guest
  • Default: POST /auth/plugin/rownd/guest
  • Non-public tenant: POST /auth/plugin/rownd/guest?tenantId=tenant-a
  • Description: Creates a guest or instant user and session in the requested tenant.

Debug Logging

Set enableDebugLogs: true in the plugin config to enable debug logging.

Telemetry

Telemetry is optional. If telemetry is omitted from the plugin config, no telemetry is emitted.

The plugin emits exactly one telemetry event per /migrate call result.

Event shape

Each event includes endpoint outcome data only (not step-by-step events), including:

  • outcome: success or error
  • durationMs
  • tenantId (when available)
  • rowndUserId (when available)
  • superTokensUserId (when available)
  • for errors: error.message and error.name

[!NOTE] Telemetry failures never fail migration endpoints. Errors in telemetry reporting are swallowed.

Provider: OpenTelemetry

RowndMigrationPlugin.init({
  rowndAppKey: process.env.ROWND_APP_KEY,
  rowndAppSecret: process.env.ROWND_APP_SECRET,
  telemetry: {
    provider: "opentelemetry",
  },
});

[!IMPORTANT] This plugin uses @opentelemetry/api only. You still need to initialize OpenTelemetry SDK/exporters in your app for spans to be exported.

Provider: Axiom

RowndMigrationPlugin.init({
  rowndAppKey: process.env.ROWND_APP_KEY,
  rowndAppSecret: process.env.ROWND_APP_SECRET,
  telemetry: {
    provider: "axiom",
    token: process.env.AXIOM_TOKEN!,
    dataset: process.env.AXIOM_DATASET!,
    // optional, defaults to https://api.axiom.co/v1/datasets
    // url: "https://api.axiom.co/v1/datasets",
  },
});

Provider: Custom

RowndMigrationPlugin.init({
  rowndAppKey: process.env.ROWND_APP_KEY,
  rowndAppSecret: process.env.ROWND_APP_SECRET,
  telemetry: {
    provider: "custom",
    factory: () => ({
      recordEvent: async (event) => {
        // send to your telemetry backend
      },
    }),
  },
});

Bulk Import Script

The package includes a bulk migration script for importing Rownd users into SuperTokens.

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.

The script runs from a YAML config file generated from the included template.

Usage

  1. Generate a local config file.
  2. Edit the config with your Rownd and SuperTokens credentials.
  3. Run the migration.
npx rownd-nodejs init-config --output ./rownd-bulk-migrate.yaml
npx rownd-nodejs bulk-migrate --config ./rownd-bulk-migrate.yaml

For repo-local development, use npm run cli -- bulk-migrate --config ./rownd-bulk-migrate.yaml from packages/rownd-nodejs.

The script:

  • fetches users from Rownd page by page
  • validates the Rownd payload shape with zod
  • maps users with mapRowndUserToSuperTokens
  • imports them into SuperTokens in bounded batches
  • writes a checkpoint file so the run can resume later

Config File

All runtime config is read from the YAML file passed with --config. There is no environment variable parsing.