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

@dwtechs/gatelin-express

v0.3.0

Published

Express.js middleware to extract and validate Gatelin consumer and ACL headers

Readme

License: MIT npm version last version release date Jest:coverage

Open source Express.js middleware to extract and validate Gatelin consumer and ACL headers.

  • 🪶 Very lightweight
  • 🧪 100% code coverage
  • 🚚 Shipped as ESM
  • 📝 Written in TypeScript
  • 🔒 Strict input validation

Installation

$ npm i @dwtechs/gatelin-express

Usage


// @ts-check
import express from "express";
const router = express.Router();

import { getConsumer, getAcl, stripUnallowedFields } from "@dwtechs/gatelin-express";

// Routes
// Add new items
router.post("/", getConsumer, getAcl, stripUnallowedFields, createItems);

Use getConsumer to read and validate the consumer headers injected by Gatelin into each request. It stores the validated consumer information in res.locals.consumer ({ userId, nickname }) for use by subsequent middleware in the request pipeline. Add it to any route that needs to identify the caller.

Use getAcl to read and validate the ACL headers injected by Gatelin into each request. It stores the parsed ACL in res.locals.acl ({ fields, conditions }) for use by subsequent middleware in the request pipeline. getAcl only validates the header shape (structure, size, allowed operators): it does not know your service's entity model, so each service must still check the returned field names and conditions against its own data before applying them. Add it to any route that needs to enforce field- or row-level permissions forwarded by Gatelin.

Use stripUnallowedFields after getAcl to project req.body.rows onto the caller's field allow-list (res.locals.acl.fields), keeping only id and allowed keys on each row. It is a no-op (rows passed through unchanged) when res.locals.acl.fields is null (unrestricted) or req.body.rows is not an array. Add it to write routes (create/update) that need to silently drop fields the caller isn't allowed to set, rather than trusting your own entity validation alone.

API Reference


/**
 * Middleware to extract and validate consumer information from request headers.
 * Retrieves consumer ID from 'x-consumer-user-id' header and consumer nickname from 
 * 'x-consumer-name' header.
 * Validates that the ID is a valid integer between 1 and 999999999, and the nickname
 * is a string of 3 to 30 characters.
 * Stores the validated consumer information in res.locals.consumer ({ userId, nickname })
 * for use by subsequent middleware in the request pipeline.
 *
 * @param {Request} req - The Express request object containing consumer headers 
 *                  (x-consumer-user-id and x-consumer-name).
 * @param {Response} res - The Express response object where consumer data will be stored 
 *                   in res.locals.consumer.
 * @param {NextFunction} next - The next middleware function in the Express.js 
 *                       request-response cycle.
 *
 * @returns {void} Calls the next middleware function with an error if consumer validation
 *                 fails, otherwise proceeds to the next middleware function.
 * 
 */
function getConsumer(req: Request, res: Response, next: NextFunction): void {}

/**
 * Middleware to extract and validate ACL headers injected by Gatelin.
 * Retrieves the field allow-list from the 'x-acl-fields' header (comma-separated) and
 * the query conditions from the 'x-acl-conditions' header (JSON array of
 * { field, op, value }).
 * Only validates the header shape (structure, size, allowed operators): field names
 * are meaningless without a service's own entity metadata, so each service is
 * responsible for checking returned fields/conditions against its own data model.
 * Stores the parsed result in res.locals.acl ({ fields, conditions }) for use by
 * subsequent middleware in the request pipeline.
 *
 * @param {Request} req - The Express request object containing ACL headers
 *                  (x-acl-fields and x-acl-conditions).
 * @param {Response} res - The Express response object where the parsed ACL will be
 *                   stored in res.locals.acl.
 * @param {NextFunction} next - The next middleware function in the Express.js
 *                       request-response cycle.
 *
 * @returns {void} Calls the next middleware function with an error if a header is
 *                 malformed, otherwise proceeds to the next middleware function.
 *
 */
function getAcl(req: Request, res: Response, next: NextFunction): void {}

/**
 * Middleware that strips fields not on the allow-list parsed by getAcl
 * (res.locals.acl.fields) from req.body.rows, keeping only "id" and allowed keys on
 * each row. This is the Gatelin-contract part of field-level ACL enforcement: it only
 * knows about the { rows: [...] } write-payload shape, not any particular entity/ORM,
 * so services still validate field names against their own data model before calling
 * this.
 * Requires getAcl to have run first so res.locals.acl.fields is populated; treated as
 * unrestricted (rows passed through unchanged) when absent.
 *
 * @param {Request} req - The Express request object. req.body.rows is filtered in
 *                  place when it is an array; left untouched otherwise.
 * @param {Response} res - The Express response object holding res.locals.acl.fields.
 * @param {NextFunction} next - The next middleware function in the Express.js
 *                       request-response cycle.
 *
 * @returns {void} Always proceeds to the next middleware function.
 */
function stripUnallowedFields(req: Request, res: Response, next: NextFunction): void {}

The Consumer, Acl and AclCondition interfaces are exported and can be used to type res.locals.consumer / res.locals.acl in downstream middleware or route handlers:


import type { Consumer, Acl } from "@dwtechs/gatelin-express";

// Type res.locals.consumer in downstream middleware
const consumer = res.locals.consumer as Consumer;
// consumer.userId   → number
// consumer.nickname → string

// Type res.locals.acl in downstream middleware
const acl = res.locals.acl as Acl;
// acl.fields     → Set<string> | null (null = unrestricted, empty Set = id only)
// acl.conditions → { field, op, value }[]

Support

| Environment | Version | | :---------- | :-----: | | Node.js | >= 22 |

Logs

Gatelin-express.js uses @dwtechs/Winstan library for logging. All logs are in debug mode. Meaning they should not appear in production mode.

Stack

| Purpose | Choice | Motivation | | :-------------- | :------------------------------------------: | -------------------------------------------------------------: | | repository | Github | hosting for software development version control using Git | | package manager | npm | default node.js package manager | | language | TypeScript | static type checking along with the latest ECMAScript features | | module bundler | Rollup | advanced module bundler for ES6 modules | | unit testing | Jest | delightful testing with a focus on simplicity |