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

@doubling/types

v0.7.0

Published

Shared Firestore document interfaces, MIME / path helpers, and CRDT constants consumed by web/, sync/, and functions/. Single source of truth so consumers cannot drift on a document shape or a content-hash encoding.

Readme

@doubling/types

Shared TypeScript interfaces and pure helpers consumed by web/, sync/, and functions/ (verified via each package's package.json dependency and import … from '@doubling/types' sites). Single source of truth for Firestore document shapes (file/folder entities, org membership, teams, user profiles), file-extension to MIME mappings, storage-path helpers, the file-body Y.Text key, and the content-hash helper.

functions/ installs a staged copy of this package as file:./vendor/types so Cloud Run's reinstall, which sees only the uploaded functions/ tree, can resolve it without a registry publish. Restage with npm run stage:types-for-functions after rebuilding types/. functions/ still keeps a local mirror of OrgMember (see functions/src/index.ts) pending a later migration of that shape.

Lives at the repo root as an npm workspace (@doubling/types). The compiled output is shipped at dist/, regenerated on npm install via the prepare script and rebuilt explicitly via npm run build.

Why this exists

Before this package, web/ and sync/ each kept their own copy of:

  • File / folder document shapes (web as a TS interface, sync via JSDoc).
  • The EXT_TO_MIME table mapping extensions to MIME types.
  • mimeTypeFromExt, isTextMimeType, extFromPath, storagePathFor.

The duplication was load-bearing for shipping (web and sync run in different environments and the byte-coercion helpers are necessarily environment-specific), but the static parts drifted. New text extensions that landed on one side and not the other caused the daemon to upload with application/octet-stream while the web's eager-load path skipped the file because the mime didn't match. Adding @doubling/types collapses both copies for the static parts. The content hash later joined them: three hand-rolled SHA-256 hex encodings could drift and stay green, so the helper lives here too. Env-specific byte coercion (toBytes, contentByteSize) stays in each consumer.

Layout

  • src/crdt-store.ts: UpdateRecord, Snapshot, UpdateStore, isAfterBaseline, isVisibleAfterFirestoreBaseline, firestoreBaselineInclusiveMillis, isReconnectFromCache, compactionPublishedCoveringBaseline (covering also requires remainingRows and refusedFutureRows to be absent or a finite zero), isTransientResyncError, snapshotReloadUnchanged, and updateStoreConformance. The CRDT update-store contract plus the behavioural cases both web/ and sync/ run against their own backends. Contract comparison is the full record id. Firestore replay also keeps the rest of the baseline millisecond because auto-ids are random and a losing fold can leave a lower-id row from that millisecond in the log. It lives here because it is the only dependency-free part of the CRDT stack (types over Uint8Array and string, since a store treats updates as opaque bytes) and because a package with shared runtime deps cannot be shared at all under this repo's nested install strategy (DOU-379).
  • src/crdt-text.ts: YTEXT_KEY, the Y.Text name the file body lives in.
  • src/content-hash.ts: contentBytes and computeContentHash (Web Crypto, async). Shared SHA-256 hex of the UTF-8 bytes.
  • src/content-hash-node.ts: sync Node adapter, exported as @doubling/types/node so a browser bundle never pulls node:crypto.
  • src/firestore.ts: FileEntity, FolderEntity, Entity, OrgMembership, OrgMember, Team, TeamMember, UserProfile, Scope.
  • src/mime.ts: EXT_TO_MIME, mimeTypeFromExt, isTextMimeType.
  • src/paths.ts: extFromPath, storagePathFor.
  • src/index.ts: barrel export. The Node hash adapter is not on the barrel.

Adding a new extension

Edit EXT_TO_MIME in src/mime.ts. That's it. Both web/ and sync/ pick up the new entry on the next tsc build. No need to touch any other file.

Build

npm run -w types build

Emits dist/index.js plus dist/*.d.ts. The dist/ directory is gitignored; CI runs the build automatically via the prepare script on npm install (prepack re-runs tsc before packaging). Only dist/ and README.md are shipped in the published tarball (see the files field in package.json).

Publish

Published to the public npm registry as @doubling/types. The .github/workflows/publish-types.yml workflow (Publish Types to npm) fires on every published GitHub Release, gated on the @doubling/types@ tag prefix so a sibling sync release does not trigger it. It runs npm ci, npm run build -w types, skips cleanly if types/package.json's version is already on npm, then npm publish --access public via npm Trusted Publishing (OIDC — no NPM_TOKEN). workflow_dispatch is exposed for bootstrap and transient-failure recovery. Version bumps are cut by Changesets (see CHANGELOG.md).

The package is published because @doubling/compound-sync is itself a published npm package that depends on @doubling/types at runtime, so the dependency must resolve from the registry outside the monorepo.

Docs