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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@angsana_consulting/api-core

v1.1.1

Published

Core API utilities for Angsana platform

Readme

@angsana_consulting/api-core

Foundation toolkit for building authenticated Retool APIs on Firestore. Ships a hardened base handler, query parser, and Firestore query builder that match the router’s standards.


1. Purpose

@angsana_consulting/api-core standardises how Retool-powered APIs interact with Firestore:

  • Guard rails – only registered collections and operations execute.
  • Declarative querying – parse complex where expressions (AND/OR, parentheses, custom operators).
  • Efficient pagination – translates compatible filters to native Firestore queries with automatic client-side fallbacks.
  • Observability – pluggable logger hook for duration/error reporting.

Use it inside Cloud Functions, Express handlers, or any service that fronts Firestore collections for Retool.


2. Architecture Overview

 Retool Request ──▶ BaseRetoolApi.handleRequest()
                      │
                      ├── validate collection + allowed ops
                      ├── parse query params → Where AST
                      ├── build Firestore query (native or hybrid)
                      ├── run custom hooks (before*/after*)
                      └── return typed ApiResponse

| Component | Description | |-----------|-------------| | BaseRetoolApi | Main request router, enforces collection policy and HTTP method guards. | | whereParser | Tokenises/astifies Retool where strings (supports contains, startsWith, nested groups). | | firestoreQueryBuilder | Converts AST → Firestore queries, falling back to client filtering when necessary. | | types | Re-export of Firebase/Express types plus shared interfaces. |


3. Directory Structure

api-core/
├── src/
│   ├── handlers/
│   │   └── baseRetoolApi.ts      # Core handler class
│   ├── parsers/
│   │   ├── whereParser.ts        # WHERE clause tokenizer/parser
│   │   └── firestoreQueryBuilder.ts
│   ├── index.ts                  # Public exports
│   └── types/                    # Type aliases + re-exports
├── dist/                         # Compiled JS/typings
└── package.json

4. Installation

npm install @angsana_consulting/api-core

Peer dependencies: firebase-admin (v11/v12) and express.


5. Quick Start

import { BaseRetoolApi, CollectionRegistry } from '@angsana_consulting/api-core';
import { db } from 'firebase-admin';

const collections: CollectionRegistry = {
  ClientNumbers: {
    autoId: false,
    customIdField: 'number',
    allowedOperations: ['GET', 'POST', 'PUT'],
    notes: 'Client phone numbers synced from Retool'
  }
};

const handler = new BaseRetoolApi(db(), collections, 'dialer', console);

export const retoolApi = onRequest((req, res) => handler.handleRequest(req, res));
  1. Register every collection with allowed HTTP verbs.
  2. Optionally provide customHandlers for lifecycle hooks.
  3. Deploy as an HTTPS/Express handler (e.g., Cloud Functions, Cloud Run).

6. Advanced Querying

Supported WHERE Syntax

status==active AND (priority>=3 OR country in['GB','US'])
createdAt>=2024-01-01 AND createdAt<2024-02-01
message contains "callback failed"
  • Logical groups with parentheses.
  • Operators: ==, !=, <, <=, >, >=, in, array-contains, array-contains-any, startsWith, contains.
  • Timestamp hints (t, x, createdAt, etc.) auto-cast to Firestore timestamps.

Firestore Compatibility

  • Automatic detection when filters can run entirely server-side.
  • Mixed inequality fields or OR trees fall back to client filtering with warning messages.
  • Pagination helpers (limit, startAfter) work alongside the hybrid model.

7. Custom Hooks

Every collection entry can declare async hooks:

customHandlers: {
  beforeCreate: async (data, ctx) => ({ ...data, createdAt: Date.now() }),
  afterCreate: async (docRef, data) => audit(docRef.id, data),
  beforeDelete: async (docId, ctx) => ctx.userId === 'admin'
}
  • Returning modified data allows sanitisation/enrichment.
  • Throwing an error aborts the request with a 400/500.
  • beforeDelete returning false denies the deletion.

8. Responses & Errors

Every route returns the standard ApiResponse interface:

{
  "success": true,
  "count": 25,
  "documents": [
    { "id": "abc123", "data": { "number": "+44123..." } }
  ],
  "nextPageToken": "xyz"
}

Failures include contextual information:

{
  "error": "Operation not allowed",
  "allowed": ["GET", "POST"]
}

9. Logging Integration

Pass any logger with info/error methods (e.g., pino, @angsana_consulting/utils logger wrappers). The handler automatically logs request duration and failures for observability parity with the router.


10. Publishing

The package ships compiled JS in dist/. Run:

cd packages/api-core
npm run build
npm publish --access public

See PUBLISHING.md for the workspace workflow.