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

@wetransform/core

v3.4.0

Published

WeTransform browser SDK — embed the WeTransform app in your site.

Readme

@wetransform/core

Headless browser SDK to open WeTransform in your app (modal or inline), authenticate, and interact through a typed event API.

SDK Guide — overview of the SDK packages and how to integrate them into your website

Installation

npm install @wetransform/core

Browser support

The SDK relies on Promise.withResolvers (ES2024): Chrome/Edge 119+, Firefox 121+, Safari 17.4+, Opera 105+. To support older browsers, load a Promise.withResolvers polyfill before calling createWeTransform.

Usage

import { createWeTransform } from '@wetransform/core'

const sdk = createWeTransform({
  organizationHandle: 'your_organization_handle',
  locale: 'en',
  displayAsModal: true,
  authentication: {
    customerId: 'your_customer_id',
    signature: 'your_signed_token',
  },
})

// Subscribing to the successSubmit event
sdk.on('successSubmit', (payload) => console.log('File successfully submitted', payload))

// Opening WeTransform
await sdk.open()
// Dynamically switch locale without remounting
await sdk.setLocale('fr')
// Close WeTransform
await sdk.close()
// Destroy WeTransform session
await sdk.destroy()

API

createWeTransform(config)

Returns a WeTransformInstance with:

  • open(): Promise<void> - initializes auth and mounts WeTransform
  • close(): Promise<void> - closes SDK UI and unmounts WeTransform
  • destroy(): Promise<void> - closes and tears down SDK resources
  • setLocale(locale): Promise<void> - updates locale/auth context and syncs iframe locale when active
  • on(event, handler): () => void - subscribes to SDK events, returns unsubscribe function

Calling open() more than once

  • While an open is already in flight, open() joins it: the returned promise resolves when the in-flight open settles, and no second open is started.
  • While the SDK is already open, closing, or destroyed, open() is a no-op that resolves immediately.
  • After close() has finished, open() can be called again to reopen the SDK.

WeTransformConfig

  • organizationHandle: string
  • locale?: 'en' | 'fr'
  • authentication: WeTransformAuthenticationConfig
  • initialLocation?: 'transformations' | 'uploader' | 'mapper' | 'finalize' | 'sourcePreview' | 'sourceUpdate' | 'loadSource' | 'scheduler'
  • displayAsModal?: boolean (default: true)
  • mountElement?: string | HTMLElement (default id: weTransform_iframeContainer, used when displayAsModal is false)
  • urlOverwrite?: { apiUrl?: string; baseUrl?: string } (override SDK URLs, mainly for testing)
  • customization?: WeTransformSDKCustomization (colors, font, border radius; see Customization)
  • agentChat?: WeTransformAgentChat (open the Agent chat, give it an Agent context; see Agent chat)

locale defaults to 'en' when not provided.

Initial location

initialLocation selects the screen WeTransform opens on. When omitted, it is inferred from the auth fields you pass:

| initialLocation | What it shows | Required auth fields | Inferred when | | ----------------- | --------------------------------------- | ------------------------------ | ---------------------------------------- | | transformations | List of the customer's transformations | customerId, signature | no templateHandle and no sourceId | | uploader | File upload screen for a template | + templateHandle | templateHandle set, sourceId not set | | finalize | Final review/submit screen for a source | + templateHandle, sourceId | both templateHandle and sourceId set | | mapper | Column/field mapping for a source | + templateHandle, sourceId | — | | sourcePreview | Read-only preview of a source | + templateHandle, sourceId | — | | sourceUpdate | Update an existing source | + templateHandle, sourceId | — | | loadSource | Load/import a source | + templateHandle, sourceId | — | | scheduler | Schedule a source run | + templateHandle, sourceId | — |

Inference only picks transformations, uploader, or finalize. The remaining locations (mapper, sourcePreview, sourceUpdate, loadSource, scheduler) must be set explicitly and require both templateHandle and sourceId. TypeScript enforces these auth requirements per location.

Customization

type WeTransformSDKCustomization = {
  colors?: {
    // hex or rgb() / rgba() only
    primary?: string
    secondary?: string
    background?: string // page background: light, or dark together with `dark: true`
    text?: string // body text; pass it together with textSubtle
    textSubtle?: string // hints, captions, labels
    surface?: string // cards, dialogs, menus, tooltips and other panels on the page
  }
  font?: {
    family: string // CSS font-family value, e.g. "'Inter', sans-serif"
    url?: string // https stylesheet declaring the font (Google Fonts-style), weights 300 to 600
  }
  borderRadius?: {
    button?: string // buttons and search-style inputs (pill by default)
    base?: string // inputs, cards, menus and the modal (10px by default, 12px on the modal)
  }
  dark?: boolean // dark mode, off unless true
}

Pass your theme through config.customization:

createWeTransform({
  organizationHandle: 'your_organization_handle',
  authentication: { customerId: 'your_customer_id', signature: 'your_signed_token' },
  customization: {
    colors: {
      primary: '#7c3aed',
      background: '#faf5ff',
    },
    font: {
      family: "'Inter', sans-serif",
      url: 'https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap',
    },
    borderRadius: {
      button: '8px',
      base: '8px',
    },
  },
})
  • Some values are applied immediately, host-side, before the iframe is ready:
    • colors.primary colors the opening loader spinner.
    • colors.background is the opening loader and modal background (#121212 with dark: true, white otherwise).
    • colors.text is the opening loader text color.
    • borderRadius.base shapes the modal (displayAsModal: true). Inline containers are left to you.
  • The full customization object is forwarded to WeTransform once it is ready, so it can theme itself. Every value is a CSS value; invalid ones are ignored.
  • Colors must be hex (#7c3aed) or rgb() / rgba(). Any other syntax (named, hsl(), oklch()…) is ignored.
  • font.url must use https and include weights 300 to 600, otherwise the browser fakes light and bold text.
  • Without font.url, only fonts already available to the browser (system fonts) work.

Dark mode

dark: true draws WeTransform light-on-dark. It is never detected from your background, and text follows the mode, not the background:

  • A dark colors.background without dark: true leaves dark text on it. Turn both on together.
  • Only the defaults follow the mode. Colors you pass apply as given, so also pass a primary, text, textSubtle and surface readable on dark. Without a background, WeTransform's dark page applies.
  • Pass text and textSubtle together: one alone leaves the other at the mode's default grey.
  • Nothing corrects an unreadable combination at runtime.
  • The error panel shown when opening fails stays light.
customization: {
  dark: true,
  colors: {
    primary: '#a78bfa',
    background: '#0f172a',
    text: '#e2e8f0',
    textSubtle: '#94a3b8',
    surface: '#1e293b',
  },
}

Agent chat

agentChat drives the Agent, the AI chat assistant inside WeTransform:

createWeTransform({
  // ...
  agentChat: {
    open: true,
    context: 'Help the user import their inventory into the Inventory template',
  },
})
  • open?: boolean: shows the Agent chat panel as soon as WeTransform loads, on every mount, whatever the end user's saved preference. It does not restart the conversation.
  • context?: string: the Agent context, a hidden instruction. WeTransform restarts the Agent conversation from it and the Agent speaks first. The end user never sees it. It does not open the panel. At most 4096 characters. '' behaves like no context.

The two are independent: pass both to land the user in a conversation where the Agent already greets them about their task.

Signature

The Agent context is covered by your signature, so it cannot be tampered with in the browser. Sign external_id:template_handle:source_id:success_url:agent_context, empty parts dropped. The SDK never sends success_url, so in practice you sign external_id:template_handle:source_id:agent_context (customerId, templateHandle, sourceId, context), empty parts dropped. Without a context, the signature is unchanged. A signature that does not cover the context fails like any other signature mismatch, through the error event.

When the conversation restarts

The conversation restarts from the Agent context once per SDK instance, the first time WeTransform is ready:

  • closing and reopening the modal keeps the conversation (and does not spend another AI credit);
  • closing before WeTransform is ready keeps the context for the next open();
  • destroy() then a new instance, or a page refresh, restarts it.

Like every other option, changing agentChat on a live instance needs destroy() then a new instance.

Runtime locale switching

  • setLocale('en' | 'fr') is additive and does not require destroy/recreate.
  • If the locale is unchanged, setLocale is a no-op.
  • If SDK status is open, locale is sent to iframe immediately via bridge messaging.
  • If SDK status is opening, locale is sent after iframe readiness is reached.
  • setLocale updates auth API URL context to {VITE_SENDER_API_URL}/{locale}/send/{organizationHandle} for subsequent auth calls.
  • Calling setLocale after destroy() throws Cannot set locale after destroy.

Inline mounting behavior (displayAsModal: false)

When displayAsModal is false, wetTransform SDK mounts the iframe into:

  • the element with id weTransform_iframeContainer by default, or
  • the element resolved from mountElement when you provide one.

If the target element does not exist, the SDK creates the container and appends it to document.body.

WeTransformAuthenticationConfig

  • customerId: string
  • signature: string
  • templateHandle?: string
  • sourceId?: string

Events

Supported sdk.on(...) events:

  • open
  • close
  • destroy
  • ready
  • successSubmit with payload
{
  customerId: string
  templateHandle: string
  fileUrl: string
  signature: string
  userFileName: string
}
  • error with payload { code: string; message: string; stack?: string; details?: Record<string, string | number | boolean> }

details carries diagnostic context when available. For network_error (the request got no readable response: offline, blocked, CORS, page unload…) it contains url, attempts, durationMs (of the last attempt), online, userAgent, visibility, sincePageLoadMs and pageHidden. Include it in your error reports.

Event listeners are isolated from each other and from the SDK: an exception thrown inside a listener does not stop other listeners or break SDK internals. It is reported as an error event with code listener_error (exceptions thrown by error listeners themselves are logged to the console instead, to avoid recursion).

Exports

  • createWeTransform
  • WeTransformConfig
  • WeTransformAuthenticationConfig
  • WeTransformInitialLocations
  • WeTransformSDKCustomization
  • WeTransformAgentChat
  • WeTransformEventMap
  • WeTransformInstance
  • SupportedLocales