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

@interlinked-svcs/firebase-plugin

v0.0.5

Published

Core interlinked-svcs lib for connecting to firebase services.

Downloads

587

Readme

@interlinked-svcs/firebase-plugin

Firestore + Firebase Auth helpers for Node, with OData-shaped query parsing aligned to connectSpec REST conventions (same options surface as @interlinked-svcs/core GetOptions / APIResource.getQuery). Use this to turn $filter, $orderby, $top, and $skip into firebase-admin queries.

Requirements: Node 20+, Firebase project credentials (environment / ADC as usual for firebase-admin).


Install

npm install @interlinked-svcs/firebase-plugin firebase-admin fastify

Peer usage also expects @interlinked-svcs/core if you reuse buildOpenIdArrayElementMatchFilter or GetOptions types from that package.


Fastify plugin

Register once; decorators expose the Admin SDK app, Firestore, Auth, and CRUD helpers.

import Fastify from "fastify";
import { firebase } from "@interlinked-svcs/firebase-plugin";

const app = Fastify();

await app.register(firebase);

// Examples (after configuring firebase-admin credentials in your environment):
const user = await app.auth.getUser(uid);
await app.firestoreOps.create("orders", { customerId: "c1", total: 100 });
const doc = await app.firestoreOps.read("orders", documentId);

Listing with OData-style options

Pass ListOptions (where / orderBy / limit / offset) directly to firestoreOps.list:

await app.firestoreOps.list("services", {

    where: [{ field: "status", operator: "==", value: "active" }],

    orderByClauses: [{ field: "updatedAt", direction: "desc" }],

    limit: 50,
    offset: 0,

});

Or build ListOptions from a query string / object shaped like OData query parameters:

import { parseODataToListOptions } from "@interlinked-svcs/firebase-plugin";

const options = parseODataToListOptions({
    $filter: "status eq 'active'",
    $orderby: "updatedAt desc",
    $top: "50",
    $skip: "10",
});

const rows = await app.firestoreOps.list("services", options);

Equivalent with a raw query substring (leading ? is optional):

parseODataToListOptions("?$filter=typeCode eq 'Session'&$top=100");

OData → Firestore (without Fastify)

Parse $filter only

import { parseWhereFilter } from "@interlinked-svcs/firebase-plugin";

const conditions = parseWhereFilter(`tier ne 'trial' and count ge 10`);
// Maps to Firestore-compatible where clauses before running a query builder.

Apply options to any collection reference

import { getFirestore } from "firebase-admin/firestore";
import { applyFirestoreListOptions, parseGetOptionsToListOptions } from "@interlinked-svcs/firebase-plugin";
import type { GetOptions } from "@interlinked-svcs/core/types";

const db = getFirestore();

const opts: GetOptions = {
    $filter: "status eq 'open'",
    $orderby: "createdAt asc",
    $top: 25,
};

const listOpts = parseGetOptionsToListOptions(opts);


const snapshot = await applyFirestoreListOptions(db.collection("orders"), listOpts).get();

Shortcut that parses GetOptions and runs get():

import { queryCollectionFromGetOptions } from "@interlinked-svcs/firebase-plugin";
import type { GetOptions } from "@interlinked-svcs/core/types";

const orders: Array<{ id: string } & Record<string, unknown>> = await queryCollectionFromGetOptions(getFirestore(), "orders", {
    $filter: `amount lt 500 and region eq 'US'`,
    $top: 10,
});

Ignore path on GetOptions here: that field is only for HTTP routes in APIResource.getQuery. You always pass the Firestore collection ID as the second argument above.


OpenId arrays and @interlinked-svcs/core

If $filter uses the OData fragment produced by buildOpenIdArrayElementMatchFilter (Party / Service id arrays), it looks like:

id/any(i: i/content eq '…' and i/schemeId eq 'service-name')

That form is rewritten internally to array_contains with a JSON map so Firestore can match one element:

import { buildOpenIdArrayElementMatchFilter } from "@interlinked-svcs/core/utils";
import { parseWhereFilter } from "@interlinked-svcs/firebase-plugin";

const $filter =
    "(" +
    buildOpenIdArrayElementMatchFilter({
        content: "my-service",
        schemeId: "service-name",
        collectionPath: "id",
    }) +
    ") and typeCode eq 'Session'";


parseWhereFilter($filter);

You can also express the same predicate directly with array_contains + a JSON object in $filter (see tests in test/).


What is supported vs not

Supported on parseGetOptionsToListOptions / queryCollectionFromGetOptions:

| Input | Maps to | |------------------|--------------------------------------------------------| | $filter | where[] (see parser rules below) | | $orderby | Multiple fields, field asc / desc, comma-separated | | $top / $skip | limit / offset |

These GetOptions fields are rejected with ODataParseError (they do not map to a single bare collection get): $select, $expand, $search, $count.

$filter grammar (combined with and only; or is rejected):

  • Comparators eq ne lt le gt ge

  • field in (...) / field not in (...)

  • Extensions: array_contains(field, literal | {…}), array_contains_any(field, …)

  • Slash paths a/b become dotted Firestore paths a.b


Scripts

npm run build       # compile to dist/
npm run test        # jest
npm run typecheck   # tsc --noEmit over src — see tsconfig.test.json for tests

License

MIT. See package.json.