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

@stamprally/core

v0.25.6

Published

A dependency-free stamp rally domain engine and storage-agnostic client.

Readme

@stamprally/core v0.25.6

Dependency-free domain models, immutable state transitions, storage adapters, browser detectors, and safe configuration parsers.

The client exposes provider-neutral linkAccount, exportCloudSnapshot, and importCloudSnapshot methods through a host-provided CloudSyncAdapter. Use migrateAnonymousProgress to merge an anonymous session into a verified account without mutating either input state.

import { InMemoryStorage, StampRallyClient, type PublicRallyConfig } from "@stamprally/core";

const config: PublicRallyConfig = {
  id: "city-tour",
  version: "0.25.6",
  title: "City Tour",
  spots: [{ id: "station", orderIndex: 0, name: "Central Station", conditions: [{ type: "passcode" }] }],
  rewards: [],
};
const client = new StampRallyClient(config, new InMemoryStorage());
await client.init();
const result = await client.checkIn("station", "ARRIVED");

Use toPublicConfig(adminConfig) to remove QR tokens, passcodes, NFC identifiers, custom secret parameters, staff credentials, and gated digital content before sending configuration to a browser. Use safeParseAdminConfig and safeParsePublicConfig at JSON boundaries; failures include paths such as spots[0].conditions[1].latitude.

The browser detectors getCurrentGeoContext, readNfcContext, and readQrContext return typed results and do not throw for unsupported environments, denied permissions, timeouts, or device errors. Keep manual fallbacks for browsers without Web NFC or BarcodeDetector.

InMemoryStorage, LocalStorageAdapter, and IndexedDBAdapter implement StampStorage. updateLocalizedField updates one locale without dropping existing translations.

Spots may include validated location coordinates and localized addresses. Configure completion.condition with all_spots, stamp_count, or selected stamps; use getNextSpotSuggestions to derive order-based or nearest-location suggestions without coupling the domain engine to a map or navigation provider.

v0.22.0 offline synchronization

Configure OfflineQueue with rallyId and userId to persist pending work under stamprally:queue:<rallyId>:<userId-or-anonymous>. switchUser loads the other user's queue. The default authoritative_replay policy uses the server state as the conflict baseline; it is the only supported conflict policy. Sync adapters may return ACCEPTED, REJECTED_PERMANENT, or RETRYABLE_ERROR; only the first two remove an operation.

When no authenticated user is supplied, the client creates a persistent UUID v4 anonymousSessionId and includes it in sync requests. Queue replay uses Web Locks when available and supports bounded exponential backoff through retryOptions.

v0.22.0 batch sync, queue capability, and storage capability

An adapter can return SyncProgressResponse from sync when it sends queued operations to a server-side syncProgress endpoint. The adapter passes queued operations to its transport and maps the server request shape as needed:

const batchAdapter: SyncAdapter = {
  sync: async ({ rallyId, userId, state, operations }) =>
    postBatch({ rallyId, userId, state, operations }),
};
await client.sync(batchAdapter);

Each SyncOperationResult is ACCEPTED, REJECTED_PERMANENT, or FAILED_RETRYABLE. Accepted and permanent results are removed from the queue; permanent reasons are added to rejectedHistory, while retryable operations are kept for the next send. A permanent prerequisite failure does not prevent later independent operations from being evaluated.

client.queueCapabilities.multiTabSync is "supported_web_locks" when the Web Locks API is available. Otherwise it is "disabled_unsafe_environment": cross-tab automatic synchronization is disabled, the foreground tab must trigger sync explicitly, and a storageCapabilityWarning event is emitted. localStorage may still be used for durable queue data, but it is never used as a lock.

client.queueCapability remains the legacy storage string ("indexeddb", "localstorage", "memory", "custom", or "disabled") so string comparisons such as client.queueCapability === "indexeddb" remain valid. New code can use client.queueCapabilities, which provides storageType, isPersistent, and multiTabSync. An omitted or false offlineQueue is reported as disabled with storageType: "none".

evaluateSpotStatus derives UNCLAIMED, CLAIMED, LOCKED, or VERIFYING without mutating state. A spot with incomplete prerequisites is LOCKED and must not be verified by a client or viewer.

License

MIT