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

@sparkvault/sdk-mobile

v4.5.6

Published

Mobile SDK for SparkVault Identity, vault, folder, and ingot workflows

Downloads

3,321

Readme

SparkVault Mobile SDK

Mobile SDK for SparkVault Identity, vault, folder, and ingot workflows.

Install

npm install @sparkvault/sdk-mobile

Create a Client

import * as FileSystem from 'expo-file-system/legacy';
import { createSparkVaultMobileClient } from '@sparkvault/sdk-mobile';

export const sparkVault = createSparkVaultMobileClient({
  tokenStorage,
  apiBaseUrl: 'https://api.sparkvault.com/v1',
  identityBaseUrl: 'https://auth.sparkvault.com',
  identityAccountId: 'acc_00000000000000000000000000000000',
  userAgent: 'SparkVault/1.0.0 (Mobile)',
  fetch: xhrFetch,
  fileReader: {
    readAsBase64: (fileUri, { position, length }) =>
      FileSystem.readAsStringAsync(fileUri, {
        encoding: 'base64',
        position,
        length,
      }),
  },
  fileDownloader: {
    download: async (url, fileUri, options) => {
      const resumable = FileSystem.createDownloadResumable(
        url,
        fileUri,
        {},
        progress => options?.onProgress?.({
          bytesWritten: progress.totalBytesWritten,
          bytesTotal: progress.totalBytesExpectedToWrite || undefined,
        })
      );
      const result = await resumable.downloadAsync();
      return result ? { uri: result.uri, status: result.status, headers: result.headers } : null;
    },
    getInfo: async (fileUri) => {
      const info = await FileSystem.getInfoAsync(fileUri);
      return { exists: info.exists, sizeBytes: info.exists ? info.size : undefined };
    },
    delete: (fileUri) => FileSystem.deleteAsync(fileUri, { idempotent: true }),
  },
});

Dependency contract

The SDK depends on tweetnacl for Ed25519 Identity JWT verification and declares react/react-native as peer dependencies for the optional native Identity dialog. Platform behavior stays behind adapters so the SDK is portable across React Native runtimes.

| Adapter | Required | Default if omitted | |---------|----------|--------------------| | tokenStorage | Yes | Throws at client construction | | identityAccountId | Yes (must start with acc_) | Throws at client construction | | fetch | No | Falls back to globalThis.fetch; throws if neither exists | | fileReader | Only for ingots.uploadFromUri | Throws on first upload-from-URI call | | fileDownloader | Only for ingots.downloadToFile | Throws on first file-download call | | passkeyProvider | Only for passkey sign-in UI | Passkey is hidden from the Identity dialog | | logger | No | No-op logger |

Modules

  • products.identity: Identity Product config, OTP/passkey login, JWKS/JWT verification, second-factor submission, and post-login backup/recommendation flows.
  • account: First-party Core session — Identity-token exchange, signup completion, profile, and account APIs.
  • vaults: Vault CRUD, unseal/seal, sharing, access retention, and upload portal/widget settings.
  • folders: Folder CRUD, breadcrumbs, folder moves, and ingot moves.
  • ingots: List/search/get, URI streaming upload/replace, rename/delete/move, sharing, read-only audit logs, SDK-managed file downloads, and the discrete createUpload (Forge upload URL + token) / createDownloadLink primitives.
  • health: Root API availability checks.
  • sparks: SparkSync ephemeral secrets — list/get/create/delete and SparkLink sharing (share/getShare/unshare).
  • entropy: HSM-backed entropy generation.
  • pushTokens: Expo push-token registration/removal.
  • billing: Subscription status and usage, Stripe portal session, and native in-app purchase receipt validation.

Identity Dialog

SparkVaultIdentityDialog is the mobile equivalent of the web SDK Identity popup. It fetches Identity Product config, derives email/phone input from enabled delivery methods, offers enabled mobile-supported methods (passkey, otp_email, otp_sms, otp_voice), applies configured branding and light/dark mode, and returns the raw signed Identity JWT plus JWKS metadata. Passkey authentication is discoverable and routes by the SVID in the WebAuthn user handle.

import * as Passkey from 'react-native-passkeys';
import {
  SparkVaultIdentityDialog,
  type MobilePasskeyProvider,
} from '@sparkvault/sdk-mobile/identity-dialog';

const passkeyProvider: MobilePasskeyProvider = {
  isSupported: () => Passkey.isSupported(),
  authenticate: async (options) => {
    const credential = await Passkey.get({
      challenge: options.challenge,
      timeout: options.timeout,
      rpId: options.rpId,
      userVerification: options.userVerification,
    });

    return credential
      ? {
          id: credential.id,
          rawId: credential.rawId,
          type: 'public-key',
          response: {
            clientDataJSON: credential.response.clientDataJSON,
            authenticatorData: credential.response.authenticatorData,
            signature: credential.response.signature,
            // Required: the server resolves the SVID from the userHandle.
            userHandle: credential.response.userHandle,
          },
        }
      : null;
  },
};

<SparkVaultIdentityDialog
  client={sparkVault}
  visible={visible}
  passkeyProvider={passkeyProvider}
  onCancel={() => setVisible(false)}
  onSuccess={async (result) => {
    await sparkVault.products.identity.verifyIdentityToken(result.token, { jwks: result.jwks });
    const session = await sparkVault.account.exchangeIdentityToken(result.token);
    // Continue only after local verification and Core exchange succeed.
  }}
/>;

Client-side JWT verification is an app integrity gate. Third-party backends must still verify the token server-side with the JWKS endpoint and key product records by the returned svid (sub is also the SVID for managed Identity tokens).

exchangeIdentityToken() is for SparkVault Core mobile sessions. Third-party mobile apps that use SparkVault Identity as their login provider should either verify the Identity JWT server-side and issue their own app session keyed by svid, or use the OIDC authorization-code flow with PKCE. Native apps must keep refresh tokens in OS secure storage; browser-only HttpOnly cookie guidance applies to web/BFF deployments.

Health Check

const status = await sparkVault.health.check();
const online = await sparkVault.health.isOnline();

Ingot Upload

const session = await sparkVault.vaults.unseal(vaultId, { vmk });

await sparkVault.ingots.uploadFromUri({
  vaultId,
  vat: session.vat,
  fileUri,
  fileSize,
  name: 'receipt.pdf',
  contentType: 'application/pdf',
  onProgress: (uploaded, total) => console.log(uploaded / total),
});

await sparkVault.ingots.replaceFromUri({
  vaultId,
  ingotId,
  vat: session.vat,
  fileUri,
  fileSize,
  name: 'receipt.pdf',
  contentType: 'application/pdf',
});

Uploads use Forge with tus v1.0.0 and read file chunks through the configured fileReader adapter. Generated content should be staged to a file URI first so all uploads use the same streaming path.

Ingot Download

const result = await sparkVault.ingots.downloadToFile({
  vaultId,
  ingotId,
  vat: session.vat,
  fileUri: cacheFileUri,
  expectedSizeBytes,
  onProgress: (downloaded, total) => console.log(downloaded / total),
});

Downloads use the configured fileDownloader adapter for one canonical streaming path across every supported file size. Production adapters should honor abortSignal and timeoutMs, and should throw on transport failure instead of writing an error response as a successful file.