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

@glydi/passkey-store-drizzle

v0.1.0

Published

First-party Drizzle/Postgres adapter for Glide passkeys. Schema exposed as data — consumers run their own drizzle-kit generate.

Readme

@glydi/passkey-store-drizzle

First-party Drizzle/Postgres adapter for Glide passkeys. Provides a conformant GlideStore backed by two PostgreSQL tables — schema exposed as data, zero numbered .sql files.

Quick Start

import { drizzle } from "drizzle-orm/node-postgres";
import { createDrizzleStore } from "@glydi/passkey-store-drizzle";
import { createGlideServerFromEnv } from "@glydi/passkey-server";
import { usersTable } from "./schema"; // your own users table

const db = drizzle(pool);
const store = createDrizzleStore({
  db,
  usersTable,
  userIdColumn:   usersTable.id,
  usernameColumn: usersTable.email, // required for findByUsername / upsert(email)
});
const glide = createGlideServerFromEnv({ store });

createGlideServerFromEnv defaults: userVerification defaults to "preferred". Set GLIDE_USER_VERIFICATION=required in your environment for stricter behavior (recommended for production). GLIDE_RP_NAME is required — set it to your app's display name (e.g. "My App").

Add the passkey tables to your schema barrel:

// schema.ts (your schema barrel)
import { buildSchema } from "@glydi/passkey-store-drizzle/schema";
import { usersTable } from "./users";

export const { passkeyCredentials, passkeyChallenges } = buildSchema({
  usersTable,
  userIdColumn: usersTable.id,
});

Then run your own migration generator — you own your data, you own your migrations:

npx drizzle-kit generate

Consumer-Owns-Migrations

This adapter ships no numbered .sql files. Instead, the ./schema subpath exports live Drizzle pgTable objects via buildSchema(). Import them into your own schema barrel alongside your existing tables and run drizzle-kit generate to produce SQL migrations that fit into your own sequence.

This avoids the 0013 migration collision problem seen when adapters ship their own numbered files that overlap with a consumer's migration counter.

Schema Changelog

SCHEMA_VERSION is exported from @glydi/passkey-store-drizzle/schema so your app can assert compatibility at startup.

v2

Columns widened in passkey_credentials:

| Column | v1 Type | v2 Type | Reason | |--------|---------|---------|--------| | counter | INTEGER | BIGINT | WebAuthn signature counters are uint32 (max 4,294,967,295), which exceeds PostgreSQL INT4 max of 2,147,483,647 | | created_at | INTEGER | BIGINT | Stored as unix milliseconds; Date.now() ≈ 1.75 × 10¹² overflows INT4 |

Migration for existing deployments: Regenerate your migration from buildSchema() and apply:

ALTER TABLE passkey_credentials
  ALTER COLUMN counter TYPE BIGINT,
  ALTER COLUMN created_at TYPE BIGINT;

This is a safe, backward-compatible widening — no data is lost and no application code changes are required.

SCHEMA_VERSION exported from @glydi/passkey-store-drizzle/schema is now 2. You can assert compatibility at startup:

import { SCHEMA_VERSION } from "@glydi/passkey-store-drizzle/schema";
assert(SCHEMA_VERSION === 2, "passkey schema version mismatch");

v1

Tables introduced: passkey_credentials, passkey_challenges

passkey_credentials

| Column | Type | Notes | |--------|------|-------| | credential_id | TEXT PRIMARY KEY | WebAuthn credential ID (base64url) | | user_id | TEXT NOT NULL | FK → your users table id column | | public_key | BYTEA NOT NULL | Raw COSE public key bytes | | counter | BIGINT NOT NULL DEFAULT 0 | Signature counter (replay protection) | | transports | TEXT | JSON-serialized array of AuthenticatorTransport | | device_type | TEXT | "singleDevice" or "multiDevice" | | backed_up | INTEGER | 1 = backed up, 0 = not, NULL = unknown | | name | TEXT | Consumer-supplied display name | | created_at | BIGINT | Unix milliseconds timestamp |

Index: idx_passkey_credentials_user on user_id. FK: fk_passkey_credentials_useruserIdColumn argument passed to buildSchema().

passkey_challenges

| Column | Type | Notes | |--------|------|-------| | session_id | TEXT PRIMARY KEY | Challenge session identifier | | challenge | TEXT NOT NULL | WebAuthn challenge (base64url) | | expires | BIGINT NOT NULL | Unix milliseconds — BIGINT avoids INT4 overflow of Date.now() |

expires is stored as unix milliseconds. BIGINT (not INTEGER) is required because Date.now() returns ~1.7 trillion ms, which exceeds PostgreSQL INT4's maximum of ~2.1 billion. The adapter uses lazy TTL eviction: expired challenges are deleted on read, no background sweeper.

Upgrade notes: No prior version exists. Fresh install — run drizzle-kit generate after adding buildSchema() output to your schema barrel.