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

@leendev/onramp-vue

v0.0.2

Published

Vue 3 wrapper for Leen OnRamp

Readme

Leen OnRamp for Vue

OnRamp is Leen's embeddable connection onboarding component. By integrating OnRamp into your workflow, you enable your users to effortlessly create new connections with all of the vendors supported by Leen.

npm i @leendev/onramp-vue

Requires Vue 3.4 or newer. For the full documentation, refer to Leen's docs on creating connections with OnRamp here.

Usage

<script setup lang="ts">
import { ref } from 'vue';
import { LeenOnRamp, type LeenOnRampResponse } from '@leendev/onramp-vue';

const props = defineProps<{ connectionInviteToken: string }>();

const showOnRamp = ref(false);
const response = ref<LeenOnRampResponse | undefined>(undefined);
</script>

<template>
  <button @click="showOnRamp = true">Open Leen OnRamp</button>

  <LeenOnRamp
    v-if="showOnRamp"
    v-model:show="showOnRamp"
    :token="connectionInviteToken"
    @response="response = $event"
  />
</template>

v-model:show is two-way: OnRamp sets it to false when the user closes the modal, which unmounts the component and destroys the underlying instance.

Global registration

If you would rather register the component once instead of importing it per call site:

import { createApp } from 'vue';
import { LeenOnRampPlugin } from '@leendev/onramp-vue';

createApp(App).use(LeenOnRampPlugin).mount('#app');

Props

Only token is required. Defaults below are the OnRamp bundle's own defaults, so omitting a prop and passing its default value are equivalent.

| Prop | Type | Default | Description | | --- | --- | --- | --- | | token | string | — | Required. Connection invite token from the Create Connection Invite Token API. Scoped to one vendor and one connection. | | show | boolean | true | Read side of v-model:show. Setting it to false destroys the instance. | | bundleVersion | string | "latest" | Which bundle to load: "dev" for static.leen.dev/dev, otherwise a version pinned under static.leen.dev/prod/<version>. | | containerId | string | auto-generated | Id of the element OnRamp mounts into. Defaults to a unique leenOnRampComponent-N, so several instances can coexist. | | requireIdentifier | boolean | false | Require the user to supply a connection identifier. | | modalSize | 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Modal width. | | primaryColor | string | '#B5FF56' | Accent color for primary buttons. Any CSS color. | | logoUrl | string | Leen's logo | Logo shown in the modal header. | | docsUrlOverrides | Record<string, string> | Leen's docs | Per-vendor documentation links, keyed by vendor. See below. | | fontFamily | string | 'Inter' | Font family name. Pair with fontUrl. | | fontUrl | string | Inter from Google Fonts | Stylesheet URL for the font. Required if fontFamily is not already loaded by your page. | | fontSizes | OnRampFontSizeOptions | see below | Per-element font sizes. | | darkMode | boolean | false | Switch to the dark theme. | | darkModeColor | DarkModeColorOptions | Leen's dark palette | Dark theme color overrides. Only applies when darkMode is true. | | textOverrides | TextOverrides | — | Override button copy. | | config | LeenConfig | — | Passed through to the bundle. Use region here for non-US Leen regions. |

Object-shaped props

interface OnRampFontSizeOptions {
  headerSize?: string; // default '1.25rem'
  bodySize?: string;   // default '1rem'
  buttonSize?: string; // default '0.875rem'
}

// Only used when darkMode is true.
interface DarkModeColorOptions {
  primary?: string;   // hex
  secondary?: string; // hex
  border?: string;    // hex
}

interface TextOverrides {
  button?: {
    create?: string; // copy for the create-connection button
    update?: string; // copy for the update-connection button
  };
}

// Keyed by vendor, as returned by Leen's vendor enum.
type DocsUrlMapping = Record<string, string>;

interface LeenConfig {
  region?: string;      // e.g. 'eu-c1'. Defaults to Leen's US region.
  containerId?: string; // set by the component; do not pass it here
  [key: string]: unknown;
}

Any CSS unit works for the font sizes (px, rem, em, …).

Events

| Event | Payload | Description | | --- | --- | --- | | response | LeenOnRampResponse \| undefined | Emitted when a connection is created or updated. | | update:show | boolean | Backs v-model:show. Emitted with false when the user closes the modal. |

interface LeenOnRampResponse {
  data: ConnectionResponse;
  httpStatus: number;
  message: string;
}

interface ConnectionResponse {
  id: string;
  vendor: string;
  refresh_interval_secs: number;
  timeout_secs: number;
  organization_id: string;
  is_active: boolean;
  oauth2_authorize_url?: string;
  identifier: string;
}

Connection errors

OnRamp dispatches a leenConnectionError event on window when connection creation fails. The wrapper does not surface this as a Vue event, so listen for it directly:

import { onMounted, onBeforeUnmount } from 'vue';

const onConnectionError = (event: Event) => console.error(event);

onMounted(() => window.addEventListener('leenConnectionError', onConnectionError));
onBeforeUnmount(() =>
  window.removeEventListener('leenConnectionError', onConnectionError),
);

Fully-configured example

<script setup lang="ts">
import { ref } from 'vue';
import { LeenOnRamp, type LeenOnRampResponse } from '@leendev/onramp-vue';

const showOnRamp = ref(false);
const response = ref<LeenOnRampResponse | undefined>(undefined);

const docsUrlOverrides = {
  SNYK: 'https://link.to/docs/snyk',
  CROWDSTRIKE: 'https://link.to/docs/crowdstrike',
};
</script>

<template>
  <LeenOnRamp
    v-if="showOnRamp"
    v-model:show="showOnRamp"
    :token="connectionInviteToken"
    :require-identifier="true"
    modal-size="lg"
    primary-color="#000000"
    logo-url="https://link.to/logo"
    :docs-url-overrides="docsUrlOverrides"
    font-family="Roboto"
    font-url="https://fonts.googleapis.com/css2?family=Roboto&display=swap"
    :font-sizes="{ headerSize: '24px', bodySize: '18px', buttonSize: '12px' }"
    :dark-mode="true"
    :dark-mode-color="{ primary: '#2A004E', secondary: '#500073' }"
    :text-overrides="{ button: { create: 'Connect', update: 'Reconnect' } }"
    :config="{ region: 'eu-c1' }"
    @response="response = $event"
  />
</template>

Nuxt / SSR

The OnRamp bundle is browser-only. The component guards every window and document access and only loads the bundle on mount, so importing it during SSR is safe. Wrap it in <ClientOnly> to skip server rendering the placeholder:

<ClientOnly>
  <LeenOnRamp :token="token" v-model:show="showOnRamp" />
</ClientOnly>

Development

bun install
bun run dev        # dev harness on http://localhost:3003
bun run build      # ES + UMD bundles and .d.ts into dist/
bun run typecheck
bun run test       # unit tests (vitest, stubbed bundle)
bun run test:e2e   # end-to-end (playwright, real bundle + dev API)

Invite token

The dev harness and the e2e suite both need a connection invite token. Tokens are short-lived — roughly 30-70 minutes — so expect to re-mint often:

export LEEN_DEV_API_KEY=...   # dev environment API key
export LEEN_DEV_ORG_ID=...    # dev organization id
bun run mint-token            # writes .env.local, defaults to vendor TENABLE

The e2e specs assert against the TENABLE vendor form, so keep the default vendor unless you also update them. You can pass another vendor as an argument (bun run mint-token CROWDSTRIKE) for manual poking in the harness.

You can also paste a token straight into the harness input, or write .env.local by hand:

VITE_LEEN_INVITE_TOKEN=eyJhbGciOi...

The e2e suite checks the token's exp before running and skips with a clear reason when it is missing or expired, rather than failing every assertion on a timeout. So N skipped means "no usable token", not "broken wrapper".

CI

.github/workflows/ci.yml runs typecheck, unit tests and build on every push and pull request, plus the e2e suite in a separate job.

Invite tokens expire in under an hour, so the token itself cannot be a repository secret — CI mints a fresh one per run via bun run mint-token. That needs two secrets:

| Secret | Value | | --- | --- | | LEEN_DEV_API_KEY | An API key for the dev environment. Prefer a dedicated CI key you can rotate independently. | | LEEN_DEV_ORG_ID | The dev organization id tokens are minted against. |

gh secret set LEEN_DEV_API_KEY --repo leeninc/onRamp-wrapper-vue
gh secret set LEEN_DEV_ORG_ID  --repo leeninc/onRamp-wrapper-vue

Two behaviours worth knowing:

  • Locally, an absent or expired token skips the e2e suite. In CI it fails, because a skip there would report green having verified nothing.
  • The e2e job is skipped for pull requests from forks, which don't receive secrets. The verify job still runs.

Testing notes

OnRamp renders its UI into a shadow root hosted inside the wrapper's container div, so the container's own innerHTML is always just <div></div>. Playwright locators pierce open shadow roots, so getByRole / getByText work normally; hand-rolled querySelector checks need to go through .shadowRoot.

Support

Leen ships OnRamp wrappers for React, Angular, and Vue. If you need support for another JS runtime, reach out to [email protected].