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

@twasik4/pocket-service

v1.0.4

Published

Pocket service is a wrapper that provides you a variety of options for a easy, boiler plate free, typescript service.

Readme

Pocket Service

Pocket service is a wrapper that provides you a variety of options for a easy, boiler plate free, typescript service.

Pocket service comes with the following features built in:

  • Express API with a few built in endpoints
  • Full type support via a builder pattern
  • An optional mongo module
  • An optional clickhouse module
  • An optional redis module
  • An optional redis worker module for consuming redis streams
  • A way to add your own modules/startup hooks that run during the build phase

Creating a service

Creating a service is done with the service class. It will streamline the creation process and reduce boilerplate.

The following is the most basic service you can create.

const service = new Service().build();

This basic service will include an express server with a few built in endpoints as well as a built in winston instance for logging.

Built-in Endpoints

The following are the base routes available:

| Method | Route | Description | | ------ | ------- | ------------------------------------------ | | GET | / | OK Check | | GET | /health | Used for health information on the service |

Modules

  1. withMongo()

A full MongoDB instance with a custom collection abstraction that offers full type support and auto completion.

  1. withRedis()

A full Redis instance, this has built in service registration.

  1. withClickhouse()

A WIP, this will be similar to the mongo abstraction and offer strong typing for queries.

  1. withWorkers()

This adds built in workers to consume Redis streams off the main loop.

The following additional routes will get added to express:

| Method | Route | Description | | ------ | ------------------------------ | --------------------------------------------------- | | GET | /workers | Used for worker health information | | GET | /workers/:stream | Gets all messages from this services stream | | POST | /workers/:stream/:id/ack | Force acknowledge a message in this services stream | | GET | /workers/:stream/dlq | Gets all messages from this services DLQ stream | | POST | /workers/:stream/dlq/:id/retry | Force retry a message in this services DLQ stream |

  1. withModules(customModules: CustomModule[])

Use this to register custom modules to the service.

Configurations

  1. withName()

Sets the name of the service, used primarily with service registration via Redis. Defaults to a random byte string.

const service = new Service().withName("Service Name").build();
  1. withPort()

Set the port of the express server. Defaults to 3100.

const service = new Service().withPort(8111).build();

Setting the port to the above would make the express instance listen on that port. So your root endpoint would be http://localhost:8111/ and display the following

{
  "isSuccess": true,
  "message": "Service Name service is running",
  "uptime": {
    "days": 0,
    "hours": 0,
    "minutes": 0,
    "seconds": 4
  }
}
  1. withUrl()

Sets the base url of the service. Useful if you use service registration via Redis.

const service = new Service().withUrl("https://my-domain.com").build();
  1. withExpressOptions()

Manually configure various express options like CORS, custom middleware, etc.

const service = new Service()
  .withExpressOptions({
    asJson: true,
    corsWhitelist: ["http://localhost:5173"],
    credentials: true,
  })
  .build();

The above code snippet would parse all incoming bodies with the express JSON parser as well as enforce CORS, whitelisting localhost on 5173 and pass credentials.

  1. addRouter()

Registers a custom router with express. This offers ways to set additional metadata and offers the ability to add validation via Zod schemas.

An example auth router could look like the following.

const { router, routes, addRoute } = createMetaRouter();

addRoute(
  {
    fullPath: "/login",
    method: "POST",
    requireAuth: false,
    bodyValidator: z.object({
      email: z.email(),
      password: z.string(),
    }),
    meta: {
      description: "Login endpoint",
    },
  },
  async (req, res) => {
    // contents here
    res
      .status(200)
      .json({ isSuccess: true, message: "Successfully logged in." });
  },
);

addRoute(
  {
    fullPath: "/register",
    method: "POST",
    requireAuth: false,
    bodyValidator: z.object({
      email: z.email(),
      password: z.string().min(6),
    }),
    meta: {
      description: "Register endpoint",
    },
  },
  async (req, res) => {
    // contents here
    res.status(200).json({ isSuccess: true, message: "Registered" });
  },
);

addRoute(
  {
    fullPath: "/logout",
    method: "POST",
    requireAuth: true,
    bodyValidator: z.object({
      refreshToken: z.string(),
    }),
    meta: {
      description: "Logout endpoint",
    },
  },
  async (req, res) => {
    // contents here
    res.status(200).json({ isSuccess: true, message: "Logged out" });
  },
);

addRoute(
  {
    fullPath: "/me",
    method: "GET",
    requireAuth: true,
    meta: {
      description: "Get current authenticated user info",
    },
  },
  async (req, res) => {
    // contents here
    res.status(200).json({ isSuccess: true, message: "Me" });
  },
);

addRoute(
  {
    fullPath: "/refresh",
    method: "POST",
    requireAuth: false,
    meta: {
      description: "Register endpoint",
    },
  },
  async (req, res) => {
    // contents here
    res.json({ isSuccess: true, message: "Token refreshed" });
  },
);

export { router as AuthRouter, routes as AuthRoutes };
  1. withAuthStrategy() / withAuthStrategies()

Use these hooks to plug in JWT, mTLS, or custom auth behavior while keeping route-level requireAuth unchanged.

import {
  Service,
  createJoseJwtVerifier,
  createJwtAuthStrategy,
  createMtlsAuthStrategy,
} from "@twasik4/pocket-service";

const mtlsStrategy = createMtlsAuthStrategy({
  requireAuthorized: true,
});

const jwtStrategy = createJwtAuthStrategy({
  verifyToken: createJoseJwtVerifier({
    jwksUri: "http://auth-service:3101/.well-known/jwks.json",
    issuer: "auth-service",
    audience: "gateway-service",
  }),
});

const service = new Service()
  .withAuthStrategies([mtlsStrategy, jwtStrategy])
  .withoutDefaultHeaderAuthFallback()
  .build();

If you use HMAC-signed tokens instead of JWKS:

import {
  Service,
  createJoseJwtVerifier,
  createJwtAuthStrategy,
} from "@twasik4/pocket-service";

const jwtStrategy = createJwtAuthStrategy({
  verifyToken: createJoseJwtVerifier({
    secret: process.env.INTERNAL_JWT_SECRET!,
    issuer: "auth-service",
    audience: "gateway-service",
    algorithms: ["HS256"],
  }),
});

const service = new Service()
  .withAuthStrategy(jwtStrategy)
  .withoutDefaultHeaderAuthFallback()
  .build();

Default behavior remains backward compatible. If no strategy authenticates and fallback is enabled, the service still reads x-user-id / x-user-meta headers.

Methods

  1. shutdown()

This shuts down the service, gracefully stopping all modules and the service itself.

  1. build()

The build phase, this is where all modules get initialized and loaded as well as what starts up the express server.

  1. heartbeat()

A method to start an interval for service registration with Redis. This gets automatically called during the build phase if the Redis module has been loaded.

  1. register()

A method to immediately register the service with Redis.