{"id":40836,"library":"drizzle-audit","title":"drizzle-audit","description":"Configurable audit logging for Drizzle ORM (v0.1.12). Provides automatic CRUD audit interception, custom action logging, scoped tracking with duration, and field-level transforms (redact, mask, hash, omit). Supports PostgreSQL, SQLite, and MySQL with pluggable storage (same DB, external DB, webhook, MongoDB). Integrates with frameworks (Hono, Elysia, Express, etc.) and workers (BullMQ, Temporal). Features AsyncLocalStorage context propagation, transaction awareness, and skip-on-noop. Zero-config start, progressive enhancement, and strict TypeScript. Active development with weekly releases.","status":"active","version":"0.1.12","language":"javascript","source_language":"en","source_url":"https://github.com/xantiagoma/drizzle-audit","tags":["javascript","audit","audit-log","audit-trail","changelog","database","drizzle","drizzle-orm","history","typescript"],"install":[{"cmd":"npm install drizzle-audit","lang":"bash","label":"npm"},{"cmd":"yarn add drizzle-audit","lang":"bash","label":"yarn"},{"cmd":"pnpm add drizzle-audit","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency: >= 0.33.0 < 2. Required for database operations and type integration.","package":"drizzle-orm","optional":false},{"reason":"Peer dependency: ^5. Required for type safety and TypeScript features.","package":"typescript","optional":true}],"imports":[{"note":"ESM-only package; CommonJS require() will fail. Use dynamic import if needed: import('drizzle-audit').","wrong":"const withDrizzleAudit = require('drizzle-audit')","symbol":"withDrizzleAudit","correct":"import { withDrizzleAudit } from 'drizzle-audit'"},{"note":"Storage implementations are imported from subpaths: 'drizzle-audit/storage/drizzle', 'drizzle-audit/storage/http', etc.","wrong":"import { drizzleTableStorage } from 'drizzle-audit'","symbol":"drizzleTableStorage","correct":"import { drizzleTableStorage } from 'drizzle-audit/storage/drizzle'"},{"note":"Dialect-specific table builders: 'drizzle-audit/pg', 'drizzle-audit/sqlite', 'drizzle-audit/mysql'.","wrong":"import { pgAuditTable } from 'drizzle-audit'","symbol":"pgAuditTable","correct":"import { pgAuditTable } from 'drizzle-audit/pg'"},{"note":"The $audit namespace is only available on the wrapped db returned by withDrizzleAudit, not on the raw drizzle instance.","wrong":"const db = drizzle(client); await db.$audit.action(...)","symbol":"db.$audit","correct":"const db = withDrizzleAudit(rawDb, config); await db.$audit.action(...)"},{"note":"Type imports are available for custom storage implementations and configuration.","wrong":null,"symbol":"types","correct":"import type { AuditEntry, AuditStorage, AuditConfig } from 'drizzle-audit'"}],"quickstart":{"code":"import { drizzle } from 'drizzle-orm/postgres-js';\nimport { withDrizzleAudit } from 'drizzle-audit';\nimport { drizzleTableStorage } from 'drizzle-audit/storage/drizzle';\nimport { pgAuditTable } from 'drizzle-audit/pg';\nimport postgres from 'postgres';\n\nconst client = postgres(process.env.DATABASE_URL ?? '');\nconst rawDb = drizzle(client);\n\nconst auditLog = pgAuditTable();\n\nconst db = withDrizzleAudit(rawDb, {\n  storage: drizzleTableStorage(auditLog, { db: rawDb }),\n  auditTable: auditLog,\n  context: { userId: 'system' },\n});\n\nawait db.insert(users).values({ name: 'Alice' }).returning();\nawait db.$audit.action({ action: 'EXPORT', tableName: 'users', metadata: { reason: 'backup' } });","lang":"typescript","description":"Wrap a PostgreSQL Drizzle instance with audit logging using drizzleTableStorage, enabling automatic CRUD audit and custom actions."},"warnings":[{"fix":"Add .returning() to all DML operations you want audited. For MySQL (no RETURNING), use db.$audit.action() manually.","message":"Automatic audit interception requires .returning() on insert/update/delete calls. Without .returning(), no audit entry is created.","severity":"breaking","affected_versions":">=0.1.0"},{"fix":"Use manual audit entries via db.$audit.action() after each DML operation. See examples/express-mysql-sqlite for a pattern.","message":"MySQL does not support RETURNING. Drizzle-audit cannot intercept changes for MySQL automatically.","severity":"breaking","affected_versions":">=0.1.0"},{"fix":"Use withAuditContext(context) helper or framework middlewares to set context per request/worker.","message":"The context option in withDrizzleAudit config is deprecated in favor of AsyncLocalStorage-based context propagation.","severity":"deprecated","affected_versions":">=0.1.0"},{"fix":"Always include `auditTable: auditLog` in the config passed to withDrizzleAudit.","message":"The audit table itself must be excluded from auditing by passing it in the auditTable config option, otherwise infinite loops occur.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"If per-statement auditing is required inside transactions, use manual db.$audit.action() calls instead of relying on automatic interception.","message":"Transactions are tracked as a single audit entry for the entire transaction. You cannot get per-statement entries inside a transaction.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"search_vec":"'action':17 'activ':77 'asynclocalstorag':58 'audit':3,5,14,83,85,88 'audit-log':84 'audit-trail':87 'automat':12 'awar':62 'bullmq':55 'changelog':90 'config':70 'configur':4 'context':59 'crud':13 'custom':16 'databas':91 'db':41,43 'develop':78 'drizzl':2,8,92,94 'drizzle-audit':1 'drizzle-orm':93 'durat':22 'elysia':50 'enhanc':73 'etc':52 'express':51 'extern':42 'featur':57 'field':25 'field-level':24 'framework':48 'hash':30 'histori':96 'hono':49 'integr':46 'intercept':15 'javascript':82 'level':26 'log':6,18,86 'mask':29 'mongodb':45 'mysql':36 'noop':67 'omit':31 'orm':9,95 'pluggabl':38 'postgresql':33 'progress':72 'propag':60 'provid':11 'redact':28 'releas':81 'scope':19 'skip':65 'skip-on-noop':64 'sqlite':34 'start':71 'storag':39 'strict':75 'support':32 'tempor':56 'track':20 'trail':89 'transact':61 'transform':27 'typescript':76,97 'v0.1.12':10 'webhook':44 'week':80 'worker':54 'zero':69 'zero-config':68","created_at":"2026-06-04T18:49:30.110797+00:00","updated_at":"2026-06-04T18:49:30.110797+00:00","problems":[{"fix":"Ensure drizzle-orm >= 0.33.0 is installed: npm install drizzle-orm@latest","cause":"Missing peer dependency drizzle-orm or incompatible version.","error":"Cannot find module 'drizzle-audit' or its corresponding type declarations."},{"fix":"Wrap your drizzle instance: const db = withDrizzleAudit(rawDb, config);","cause":"Using the raw drizzle instance instead of the wrapped instance returned by withDrizzleAudit.","error":"TypeError: db.$audit is undefined"},{"fix":"Add `auditTable: myAuditTable` to the config object.","cause":"Missing auditTable option in withDrizzleAudit config, or the table is not excluded from auditing.","error":"Error: auditTable is not defined in config"},{"fix":"Use ESM imports (import) and ensure your bundler supports Node.js subpath exports, or use a full path like './node_modules/drizzle-audit/storage/drizzle.js'.","cause":"Using a bundler that doesn't support subpath exports or using CommonJS require.","error":"Cannot find module 'drizzle-audit/storage/drizzle'"}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":null,"cli_version":null,"type":"library","homepage":"https://github.com/xantiagoma/drizzle-audit#readme","github":"https://github.com/xantiagoma/drizzle-audit","docs":null,"changelog":null,"pypi":null,"npm":"drizzle-audit","openapi_spec":null,"status_page":null,"smithery":null,"categories":["database"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-04","next_check":"2026-09-02","install_tag":null}}