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

prisma-soft-delete

v1.0.2

Published

Transparent soft delete extension for Prisma using $extends API

Readme

prisma-soft-delete

npm version License: MIT

Transparent soft deletes for Prisma using the official $extends client extension API. After you attach the extension, reads ignore deleted rows, deletes become updates that set your flags, and you get helpers for bypassing filters and restoring rows—without wrapping every call site in manual where clauses.

Features

  • Automatic query filteringfindMany, findFirst, count, aggregate, groupBy, and nested reads exclude soft-deleted rows by default.
  • Deletes become soft deletesdelete / deleteMany are rewritten to updates that set your configured fields (e.g. deleted, deletedAt).
  • Optional cascade — Configure related models to soft-delete in sync with a parent.
  • Escape hatchwithDeleted() runs a callback where filters are not applied (e.g. admin or auditing).
  • Restore — Per-model restore() for undoing a soft delete.
  • TypeScript-first — Typed config and extension integration with @prisma/client.

Requirements

  • Node.js 18+.
  • Prisma 5+ (@prisma/client as a peer dependency).

ESM and CommonJS

The published package includes both an ESM build (import) and a CommonJS build (require). Use whichever matches your project:

ESM ("type": "module" or bundlers):

import { softDeleteExtension, withDeleted } from 'prisma-soft-delete';
import type { SoftDeleteConfig } from 'prisma-soft-delete';

CommonJS:

const { softDeleteExtension, withDeleted } = require('prisma-soft-delete');

The repo uses "type": "module" so local source is authored as ESM; that does not restrict consumers—Node and TypeScript resolve the correct file via package.json exports.

Installation

npm install prisma-soft-delete
pnpm add prisma-soft-delete
yarn add prisma-soft-delete
bun add prisma-soft-delete

Ensure @prisma/client is installed in your app (it is not bundled here):

npm install @prisma/client

Schema setup

Add the fields your extension will use on each soft-deleted model (names can differ; configure them in code). Example:

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  deleted   Boolean  @default(false)
  deletedAt DateTime? @map("deleted_at")

  posts Post[]

  @@index([deleted])
}

model Post {
  id       String @id @default(cuid())
  title    String
  authorId String
  deleted   Boolean  @default(false)
  deletedAt DateTime? @map("deleted_at")

  author User @relation(fields: [authorId], references: [id])

  @@index([deleted])
}

Run prisma generate after changing the schema.

Quick start

import { PrismaClient } from '@prisma/client';
import { softDeleteExtension } from 'prisma-soft-delete';
import type { SoftDeleteConfig } from 'prisma-soft-delete';

const softDeleteConfig: SoftDeleteConfig = {
  models: {
    user: {
      field: 'deleted',
      deletedAtField: 'deletedAt',
      cascadeRelations: [
        { model: 'post', foreignKey: 'authorId', sourceKey: 'id' },
      ],
    },
    post: { field: 'deleted', deletedAtField: 'deletedAt' },
  },
  relationToModel: {
    posts: 'post',
    author: 'user',
  },
};

const db = new PrismaClient().$extends(softDeleteExtension(softDeleteConfig));

// Reads exclude soft-deleted rows automatically
const activeUsers = await db.user.findMany();

// Include deleted rows when needed
import { withDeleted } from 'prisma-soft-delete';

const allUsers = await withDeleted(() => db.user.findMany());

// Restore a soft-deleted row
await db.user.restore({ where: { id: '...' } });

Configuration (SoftDeleteConfig)

  • models — Map each Prisma model name (camelCase delegate name, e.g. user for User) to:
    • field — Boolean column used as the soft-delete flag.
    • deletedAtField — Optional DateTime? column updated on delete/restore.
    • cascadeRelations (optional) — Related models to soft-delete when this row is deleted.
  • relationToModel — Maps relation field names on your models to delegate names (e.g. postspost) so nested queries and cascades resolve correctly.

Apply softDeleteExtension before other extensions (pagination, logging, etc.) so their internal queries still pass through the soft-delete layer.

Limitations & caveats

  • $queryRaw / $executeRaw bypass client extensions. Add deleted = false (or your equivalent) manually in raw SQL.
  • Unique constraints still see soft-deleted rows unless you use partial unique indexes (e.g. WHERE deleted = false) at the database level.
  • Extension order matters; put this extension first in the $extends chain when combining with other plugins.

Development

Clone the repo and install dependencies with npm install (this repo keeps a package-lock.json for reproducible installs and CI—Bun is optional locally, but bun.lock is not tracked).

Published npm tarball: Only the built dist/ output is listed in package.json files; npm also ships package.json, README.md, and LICENSE by default. Source, lockfiles, and config are not published.

| Script | Description | |--------|-------------| | npm run build | ESM (dist/index.js) + CJS (dist/index.cjs) via esbuild; declarations with tsc; copy index.d.tsindex.d.cts for require typings | | npm run typecheck | Typecheck without emit | | npm run lint | Run Biome on src/ |

Publishing runs prepublishOnlynpm run build automatically.

License

MIT