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

@sabeesoft/idempotix-typeorm

v0.1.0

Published

TypeORM (PostgreSQL) store adapter and query/pool instrumentation for idempotix.

Readme

@sabeesoft/idempotix-typeorm

TypeORM (1.x) / PostgreSQL store adapter for idempotix. The idempotency record is written through your EntityManager — inside your transaction when you hand the store the transaction's manager — so the record and your business write commit or roll back together.

Install

pnpm add @sabeesoft/idempotix-core @sabeesoft/idempotix-typeorm

typeorm (1.x) and @opentelemetry/api are peer dependencies. The store talks to Postgres through EntityManager.query() with bound parameters and does not depend on the entity below.

1. Add the table

Either register the shipped entity (entities: [IdempotencyKeyEntity]) and let TypeORM migrations / synchronize create the table, or apply migration.sql with your own tooling. Nothing is applied automatically. The entity declares every column type explicitly, so it works without emitDecoratorMetadata.

2. Create the store

import { createTypeormIdempotencyStore } from '@sabeesoft/idempotix-typeorm';

// Non-transactional: every store call uses the data source's manager.
const store = createTypeormIdempotencyStore({ manager: () => dataSource.manager });

// Joining the application's transaction: return whatever transaction manager is
// active for the current request. With @nestjs-cls/transactional that is
// `() => transactionHost.tx`.
const store = createTypeormIdempotencyStore({
  manager: () => transactionHost.tx,
  tableName: 'app.idempotency_keys', // optional, default "idempotency_keys"
});

With NestJS:

ClsModule.forRoot({
  middleware: { mount: true },
  plugins: [
    new ClsPluginTransactional({
      imports: [DatabaseModule],
      adapter: new TransactionalAdapterTypeOrm({ dataSourceToken: DataSource }),
    }),
  ]),
IdempotixModule.forRootAsync({
  inject: [TransactionHost],
  useFactory: (host: TransactionHost<TransactionalAdapterTypeOrm>) => ({
    store: createTypeormIdempotencyStore({ manager: () => host.tx }),
    runInTransaction: (fn) => host.withTransaction(fn),
  }),
}),

The SQL is the same as the Prisma adapter's (both come from @sabeesoft/idempotix-pg): one INSERT … ON CONFLICT DO UPDATE … WHERE that acquires or reclaims, SELECT … FOR UPDATE, a jsonb body that keeps JSON null distinct from SQL NULL, and a validated, quoted table name as the only interpolated identifier.

Metrics: instrumentTypeorm()

Standalone OpenTelemetry instrumentation for a TypeORM + Postgres DataSource; call it after initialize():

const { dispose } = instrumentTypeorm({ dataSource, poolName: 'primary' });

| Metric | Type | Attributes | | ----------------------------------------------------------------------------------------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | db.client.operation.duration | histogram s | db.system.name=postgresql, db.operation.name (the statement's leading keyword: SELECT, INSERT, UPDATE, DELETE, WITH, START, COMMIT, ROLLBACK, … or OTHER), error.type (Postgres error code) on failure | | db.client.connection.{count,max,pending_requests,wait_time,use_time,timeouts}, idempotix.db.pool.errors | see @sabeesoft/idempotix-pg | pool name |

Query durations come from TypeORM's own afterQuery subscriber event — nothing is patched. db.collection.name is deliberately not set: TypeORM only exposes the SQL text, and extracting table names from it is neither reliable nor safe for metric cardinality. Query text and parameters never become attributes. queries: false / pool: false switch either group off.

Expired rows

DELETE FROM idempotency_keys WHERE locked_until < now();

Run it from a scheduled job; the store never deletes rows on its own.

Running this package's tests

Same as @sabeesoft/idempotix-prisma: a Docker-compatible runtime for Testcontainers (rootless podman works with docker.host=unix:///run/user/1000/podman/podman.sock in ~/.testcontainers.properties). Without one the Postgres suites are reported as skipped.