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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@jez.luka/iver-sdk

v0.1.9

Published

iVer SDK - Identity verification SDK for showcasing real world SDK architecture and integration.

Readme

IVer SDK

Identity verification SDK built with StencilJS for framework-agnostic web component integration.

Why StencilJS?

The goal was framework-agnostic components as close to vanilla JS as possible. While Svelte 5's minimal build size was attractive, it's designed for apps - using it would require wrapper containers and custom constructors around Svelte's rendering functions.

Web Components provide native browser support with excellent stability. After evaluating Lit and StencilJS, I chose StencilJS for superior DX and faster implementation within project constraints.

Key advantages:

  • Tree shaking support: StencilJS generates optimized, individually importable component definitions. Consumers only bundle what they use.
  • TypeScript-first: Native TypeScript support with auto-generated type definitions (components.d.ts)
  • Build optimizations: Lazy loading, code splitting, and minimal runtime overhead (~5KB per component)
  • Framework agnostic: with minimal setup, works seamlessly with React

Architecture

Challenge: Enable getIdentityData() to aggregate data from all 3 components without tight coupling.

Solution: Controller pattern with component registry instead of shared store. IVerComponentController

  • Each component registers on init, providing its ID and getData() reference
  • Controller instance passed from outside, giving consumers manual lifecycle control (inspired by React Hook Form)
  • Handles multi-step forms where components mount/unmount frequently
  • Components auto-unregister on unmount, but manual control available to preserve data flow across form steps

Shadow DOM vs Light DOM Decision

Why Light DOM?

This SDK uses Light DOM (shadow: false) rather than Shadow DOM encapsulation. This was a deliberate architectural choice: Rationale:

  • Styling flexibility: Host applications can apply their design system (Tailwind, CSS modules, styled-components) directly to SDK components without piercing shadow boundaries
  • Global styles integration: Components inherit CSS custom properties and theming variables from the parent application
  • CSS framework compatibility: Works seamlessly with utility-first frameworks like Tailwind without requiring custom element targeting
  • Simpler integration: No need for ::part() selectors or CSS custom properties workarounds

Trade-offs accepted:

  • No style isolation: Host styles can potentially conflict with component internals (mitigated by BEM naming and scoped classes)
  • DOM structure exposure: Component markup is accessible to parent selectors (acceptable for this use case where restyling is a feature, not a bug)

Data Aggregation Strategy

The getIdentityData() method uses a probabilistic verification scoring approach rather than deterministic state management.

Design rationale:

Probabilistic (current) vs Adaptive Deterministic:

  • Probabilistic: Each method invocation will calculate failure/success probability at submission time. I was thinking about this being mock for actual API. This approach doesn't have state tracking overhead.
  • Adaptive Deterministic (not implemented): Would maintain real-time validation state, track failure rate and adapt to it. More complex, requires state management and thorough testing.

Why probabilistic?

  • Simpler mental model: Verification happens when needed (submission), not continuously
  • Lower runtime cost: No state management and runtime complex calculations

Trade-off: No actual 30/70 percent split on small sample. From 100 times, this could theoretically fail 50% of the times.

Project Structure

src/
├── components/                     # SDK Components
│   ├── address-form/
│   │   ├── components/             # Sub-components
│   │   ├── test/                   # Component tests
│   │   ├── types/                  # TypeScript type definitions
│   │   ├── address-form.configs.ts # Constants and config factory fns
│   │   ├── address-form.css
│   │   ├── address-form.helpers.ts # Business or component specific logic
│   │   └── address-form.tsx        # entry file for SDK component
│   │
│   ├── phone-input/    # Phone number input component
│   │
│   └── selfie-capture/ # Selfie capture component
│
├── configs/            # Global configuration files
│   └── countries.json  # Country data
│
├── global/             # Global styles and utilities
│   └── global.css      # Application-wide styles
│
├── pages/              # Page components
│   ├── address-form.html
│   ├── phone.html
│   └── selfie.html
│
└── sdk/                # SDK utilities and types
    ├── types/          # Shared TypeScript definitions
    │   └── sdk.types.ts
    ├── iver-component-controller.ts
    ├── components.d.ts # Auto-generated component types
    ├── global.ts       # Global SDK configuration
    └── index.html      # SDK demo/test page

Installation

npm i @jez.luka/iver-sdk

Setup

1. TypeScript definitions (global.d.ts)

import { IVerComponentController } from '@jez.luka/iver-sdk'

type SDKComponent = React.DetailedHTMLProps
  React.HTMLAttributes<HTMLElement> & { controller: IVerComponentController }, 
  HTMLElement
>

declare module 'react' {
  namespace JSX {
    interface IntrinsicElements {
      'address-form': SDKComponent
      'phone-input': SDKComponent
      'selfie-capture': SDKComponent
    }
  }
}

export {}

2. Register components (iver-sdk.ts)

import { defineCustomElement as defineAddressForm } from '@jez.luka/iver-sdk/address-form'
import { defineCustomElement as definePhoneInput } from '@jez.luka/iver-sdk/phone-input'
import { defineCustomElement as defineSelfieCapture } from '@jez.luka/iver-sdk/selfie-capture'
import { IVerComponentController } from '@jez.luka/iver-sdk'

defineSelfieCapture()
definePhoneInput()
defineAddressForm()

export const iVerGlobalController = new IVerComponentController('global-controller')

3. Import in main.tsx

import './toolkit/iver-sdk/iver-sdk.ts'

Usage

Component usage (no imports needed)

<div className="flex flex-col mx-auto min-h-screen w-full gap-5">
  <selfie-capture controller={iVerGlobalController} />
  
  <div className="flex flex-col flex-1 gap-4 max-w-[350px] mx-auto w-full">
    <phone-input controller={iVerGlobalController} />
    <address-form controller={iVerGlobalController} />
    
    <Button className="mt-4" onClick={handleSubmit}>Submit</Button>
  </div>
</div>

Controller usage

import { iVerGlobalController } from '@/toolkit/iver-sdk/iver-sdk.ts'

const data = iVerGlobalController.getIdentityData<VerificationResult>()

Development

pnpm install
pnpm start
pnpm generate // to generate new SDK component