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

url-query-to-prisma

v2.0.2

Published

Express middleware to turn a url query into a formatted object suitable for inclusion in a Prisma ORM client query

Downloads

16

Readme

url-query-to-prisma

Express middleware to turn a URL query/body into an object formatted to match the object shape to filter a Prisma ORM client query.

Suitable for something like a blogs page where you want the user to be able to search for blogs by a particular user, date range or sort them into date order, etc.

The prisma query object ends up on req.prismaQueryParams. The idea is, when you eventually get to your query you can just put something like:

prismaClient.modelName.find(req.prismaQueryParams)

Install

npm install url-query-to-prisma

Usage

Here's an example of a custom formatter made with the formatter helper functions and the output it generates. By default, values of foreign relations can be accessed with dots in the key, e.g. blogAuthor.name.

import express from 'express';
import { PrismaClient } from '../generated/prisma/client.js';
import { urlQueryToPrisma, formatters, processors } from 'urlQueryToPrisma';

const app = express();
const prisma = new PrismaClient();

const customFormatter = {
  title: formatters.whereContains({ caseSensitive: false }),
  author: formatters.whereContains({ caseSensitive: false, tableColName: 'owner.name' }),
  fromDate: formatters.where({ 
    filterType: 'gte', 
    valueProcessor: processors.date, 
    tableColName: 'publishedAt'
  }),
  toDate: formatters.where({ 
    filterType: 'lte', 
    valueProcessor: processors.date, 
    tableColName: 'publishedAt'
  }),
}

app.use(
  '/blogs', 
  urlQueryToPrisma(customFormatter), 
  async (req, res, next) => {
    try {
      const blogs = await prisma.blog.findMany(req.prismaQueryParams);
      res.send(blogs);
    } catch (error) {
      next(error);
    }
});

// A request with the following url will give this result... 
// /blogs?title=myBlog&author=jimbo&fromDate=2020-01-01&toDate=2020-12-31
const result = {
  where: {
    title: {
      contains: 'myBlog',
      mode: 'insensitive'
    },
    owner: {
      name: {
        contains: 'jimbo',
        mode: 'insensitive'
      },
    },
    publishedAt: {
      gte: '2020-01-01', // Date object representing this date.
      lte: '2020-12-31'  // Date object representing this date.
    }
  }
}

An instance of the middleware is created by calling urlQueryToPrisma as a function. It takes a customFormatter parameter and a customOptions parameter.

Custom Formatters

The custom formatter is an object that tells the middleware what to do with each parameter in the url query. Each object key in the custom formatter relates to the respective url query parameter, and its corresponding value should be a function that takes four parameters: the query object, query parameter key, query parameter value, and an options object. As the middleware runs through each formatter it will directly modify the properties on the query object, building it up into its final form.

By default, the middleware will take the following url parameters and turn them into a prismaQueryParams object:

  • skip
  • take
  • cursor
  • orderBy
  • sortOrder

If you want to change any of these behaviours, you can define your own in your custom formatter which will overwrite the defaults. If you want one of the default parameters to be ignored, assign null to it instead of a function.

const customFormatter = {
  cursor: null
}

urlQueryToPrisma(customFormatter);

Custom Options

The custom options parameter is an optional parameter of type object. This object is passed to all formatter functions, so if you have some option you want to set once and use in multiple formatters, this is the place to do it. The middleware and defaultFormatter use the following properties:

|Property|Purpose| |-|-| |querySource|Defaults to query. This is where the middleware will look for the url query. You can change this to access any property on the req object, e.g. body after a form has been submitted.| |pathSeparator|Defaults to . but can be changed to anything you want. This character is used to structure the prismaQueryParams object to allow access to fields of foreign relations.|

Formatters

Where

Each formatter can be written manually but generally it is easier to use the provided where formatter, as in the above example. It takes a single parameter of type object: customOptions. Here is an explanation of the different properties that can be set on the customOptions object.

|Property|Purpose| |-|-| |filterType|Defaults to null. A string that determines a specific prisma where filter type, e.g. includes, lte, etc.| |filterOptions|Defaults to an empty object. This is an object that is added onto the where filter. Useful to include { mode: 'insensitive' } on the filter, which is required to run case-insensitive string queries on postgreSQL and mongoDB databases.| |valueProcessor|Defaults to a function that returns the query value in its raw form. A function that takes a value parameter and should return a value. This is for applying any processing on the value we are going to match against the database. Since a http url query or body always has string values, this is useful for turning the string into a number or a date. Import processors as shown in the usage section to get some convenient functions to do this (since typing these functions over and over gets boring).| |tableColName|Defaults to null. By default, the where formatter will match against a table column that has the same name as the url query parameter. By setting tableColName, you can match a url query parameter against a differently named table column. This is also necessary to group multiple url query parameters on a filter for a single table column.|

WhereContains

This is a convenience method that wraps around the standard Where formatter function, to streamline the process of getting partial, case-insensitive string matches. It takes a customOptions parameter just like the where formatter, but this time the customOptions object can also take a property called caseSensitive. Some databases are case-insensitive already so this property will not need to be set, but if you are working on postgreSQL or mongoDB and you want case-insensitive matches, you'll need to set caseSensitive to false. It defaults to true, but if you are working on a case-insensitive database this won't do anything.

With standard where:

formatters.where({
  filterType: 'contains',
  // Required on case-sensitive dbs to facilitate case-insensitive matching. Will give errors on case-insensitive dbs.
  filterOptions: { mode: 'insensitive' }
})

You can do the equivalent more concisely with whereContains:

// On a db with case-sensitivity, e.g. postgreSQL or mongoDB.
formatters.whereContains({ caseSensitive: false });
// On a db with no case-sensitivity, e.g. mySQL.
formatters.whereContains();

Doesn't look like much of a difference, but if your customFormatter has 5 of these in a row, whereContains will make it a lot cleaner.

If your database is already case-insensitive, do not set caseSensitive: false as this will cause prisma to throw an error. The case sensitivity is based on a 'mode' property, but on case-insensitive databases, it is not available on the generated prisma client API.

Processors

These are tiny functions for turning the url query parameter values from their default strings into other kinds of data. Added purely for convenience since writing stuff like (value) => new Date(value) for various formatters gets old quickly.

Writing a custom formatter

If you want to write your own formatter for a query parameter without using formatters.where(), the function should look something like this:

const myFormatter = {
  // The options object here is passed from urlQueryToPrisma, i.e. it was the 
  // customOptions object passed to that when urlQueryToPrisma was instantiated.
  myQueryParam: (obj, key, value, options) => {
    obj.where = {
      ...obj.where,
      [key]: value,
    };
  },
};

This is a simple function that just adds the key value pair onto the where object. However, formatters.where() uses the deepMerge package to allow for cumulative queries like in the usage example, where two different url query parameters were mapped to lte and gte filters on one table column. It also uses the pathToNestedObj package to allow accessing the values of foreign relations.

At the start of processing, an empty temp object on the prismaQueryParams object can be used if information needs to be stored from one formatting function to another, as is the case with the defaultFormatter formatters for orderBy and sortOrder. The temp object gets deleted at the end of the middleware function.

Previous versions

Docs for v1 are in docs/README_v1.md.