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

@datrix/api

v0.1.2

Published

HTTP request handling, query parsing, and response serialization for Datrix framework

Readme

@datrix/api

HTTP REST API plugin for Datrix. Turns any Datrix instance into a fully-featured REST API — auto-generates CRUD routes for every schema, handles JWT and session authentication, RBAC permissions, and optionally manages file uploads via @datrix/api-upload.

Installation

pnpm add @datrix/api

Setup

import { defineConfig } from "@datrix/core"
import { ApiPlugin } from "@datrix/api"

export default defineConfig(() => ({
  adapter,
  schemas,
  plugins: [
    new ApiPlugin({
      prefix:           "/api",  // default: "/api"
      defaultPageSize:  25,      // default: 25
      maxPageSize:      100,     // default: 100
      maxPopulateDepth: 5,       // default: 5
      excludeSchemas:   [],      // always excludes _datrix and _datrix_migrations
    }),
  ],
}))

Request handling

handleRequest

import { handleRequest } from "@datrix/api"

handleRequest(datrix: IDatrix, request: Request): Promise<Response>

Main entry point. Routes to the appropriate handler (auth, CRUD, or upload). Always returns a Response, never throws.

Next.js App Router

import datrix from "@/datrix.config"
import { handleRequest } from "@datrix/api"

async function handler(request: Request): Promise<Response> {
  return handleRequest(await datrix(), request)
}

export const GET = handler
export const POST = handler
export const PATCH = handler
export const PUT = handler
export const DELETE = handler

Express

import express from "express"
import { handleRequest, toWebRequest, sendWebResponse } from "@datrix/api"

const app = express()
app.use(express.raw({ type: "*/*" }))

app.all("*", async (req, res) => {
  const request  = toWebRequest(req)
  const response = await handleRequest(await datrix(), request)
  await sendWebResponse(res, response)
})

toWebRequest / sendWebResponse work with any Node.js-style request/response — Fastify, Koa, raw http.createServer.

Auto-generated CRUD routes

For every registered schema:

| Method | Path | Description | | -------- | ------------------ | ---------------------------------------- | | GET | /api/:schema | List records — pagination, filtering, sorting, populate | | GET | /api/:schema/:id | Get a single record | | POST | /api/:schema | Create a record | | PATCH | /api/:schema/:id | Update a record | | DELETE | /api/:schema/:id | Delete a record |

The :schema segment matches the schema's table name (e.g. schema "product"/api/products).

Filtering, sorting, pagination

Pass query parameters as a serialized ParsedQuery object. Use queryToParams to build them:

import { queryToParams } from "@datrix/api"

const qs = queryToParams({
  where:   { status: "active" },
  orderBy: { createdAt: "desc" },
  page:    1,
  pageSize: 20,
})

fetch(`/api/products?${qs}`)

Authentication

Enable by adding an auth block to ApiPlugin:

const roles = ["admin", "editor", "user"] as const
type Role = (typeof roles)[number]

new ApiPlugin<Role>({
  auth: {
    roles,
    defaultRole: "user",
    jwt: {
      secret:    "your-secret-key-at-least-32-characters",
      expiresIn: "7d",
    },
    session: {
      store:  "memory",  // or a custom SessionStore instance
      maxAge: 86400,
    },
    defaultPermission: {
      create: ["admin"],
      read:   true,
      update: ["admin", "editor"],
      delete: ["admin"],
    },
  },
})

JWT and session can be active simultaneously. Responses include both a token and a sessionId cookie.

A user schema with an email field must exist before enabling auth. The plugin creates an authentication table automatically.

Auth endpoints

| Method | Path | Description | | ------ | --------------------- | ---------------------------------------- | | POST | /api/auth/register | Create a new user account | | POST | /api/auth/login | Login — returns token and/or sets cookie | | POST | /api/auth/logout | Invalidate session | | GET | /api/auth/me | Get the currently authenticated user |

Endpoint paths are configurable via auth.endpoints. Registration can be disabled with auth.endpoints.disableRegister: true.

Authenticated requests

GET /api/products
Authorization: Bearer eyJ...

Or send the sessionId cookie — the browser handles this automatically.

Permissions

Defined per schema in SchemaDefinition.permission:

defineSchema({
  name: "product",
  fields: { ... },
  permission: {
    create: ["admin", "editor"],
    read:   true,               // public
    update: ["admin", "editor"],
    delete: ["admin"],
  },
})

Permission values: true (public), false (blocked), role array, async function, or a mixed array (OR logic). Field-level read/write permissions are also supported per field.

File uploads

File upload support is in a separate package to keep sharp out of the core dependency tree. See @datrix/api-upload for the full setup, storage provider docs, format conversion, and resolution variants.

import { Upload, LocalStorageProvider } from "@datrix/api-upload"

new ApiPlugin({
  upload: new Upload({
    provider: new LocalStorageProvider({
      basePath: "./uploads",
      baseUrl:  "https://example.com/uploads",
    }),
    format:  "webp",
    quality: 80,
    resolutions: {
      thumbnail: { width: 150, height: 150, fit: "cover" },
      small:     { width: 320 },
    },
  }),
})

Architecture

src/
├── api.ts                   # ApiPlugin class — plugin lifecycle, schema injection, request routing
├── interface.ts             # IApiPlugin interface — used internally to avoid circular deps
├── types.ts                 # ApiConfig type
├── index.ts                 # Public exports
├── helper/
│   └── index.ts             # handleRequest, toWebRequest, sendWebResponse, queryToParams
├── handler/
│   ├── unified.ts           # CRUD request handler (GET / POST / PATCH / DELETE)
│   ├── auth-handler.ts      # Auth endpoint handlers (register, login, logout, me)
│   └── utils.ts             # jsonResponse, datrixErrorResponse helpers
├── auth/
│   ├── manager.ts           # AuthManager — coordinates JWT, session, and password
│   ├── jwt.ts               # JwtStrategy — signing/verification (no external deps)
│   ├── session.ts           # SessionStrategy + MemorySessionStore
│   ├── password.ts          # PasswordManager — PBKDF2 hashing
│   └── types.ts             # AuthConfig, SessionConfig, JwtConfig, SessionData, etc.
├── middleware/
│   ├── context.ts           # RequestContext builder
│   ├── permission.ts        # Schema and field permission evaluation
│   └── types.ts             # RequestContext type
└── errors/
    ├── api-error.ts         # DatrixApiError and handlerError factory
    └── auth-error.ts        # DatrixAuthError and authError factory