@murumets-ee/logging 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { toolkitAuditLogs } from "./schema.mjs";
1
+ import { t as toolkitAuditLogs } from "./schema-D9AdiYql.mjs";
2
2
  import { Logger as Logger$1 } from "pino";
3
3
  import { PostgresJsDatabase } from "drizzle-orm/postgres-js";
4
4
 
@@ -92,7 +92,7 @@ interface AuditLogListResult {
92
92
  total: number;
93
93
  }
94
94
  declare class AuditLogClient {
95
- private db;
95
+ private client;
96
96
  constructor(db: PostgresJsDatabase);
97
97
  /** Write a single audit log entry */
98
98
  write(entry: Omit<AuditLogEntry, 'id' | 'createdAt'>): Promise<void>;
@@ -104,7 +104,7 @@ declare class AuditLogClient {
104
104
  getDistinctEntityTypes(): Promise<string[]>;
105
105
  /** Get distinct actions present in the audit log */
106
106
  getDistinctActions(): Promise<string[]>;
107
- private buildConditions;
107
+ private buildWhere;
108
108
  private buildOrderBy;
109
109
  }
110
110
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/logger.ts","../src/audit.ts","../src/audit-client.ts","../src/context.ts"],"mappings":";;;;;KAEY,MAAA,GAAS,QAAA;AAAA,UAEJ,YAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;AAHF;;iBAoCgB,YAAA,CAAa,MAAA,GAAS,YAAA,GAAe,MAAA;;;;iBAqBrC,iBAAA,CAAkB,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,MAAA,oBAA0B,MAAA;;;UCzDpE,UAAA;EACf,MAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA,GAAU,MAAA;EACV,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,WAAA;EACf,MAAA,EAAQ,MAAA;EACR,QAAA,IAAY,KAAA,EAAO,UAAA,KAAe,OAAA;AAAA;AAAA,UAGnB,WAAA;EACf,GAAA,GAAM,KAAA,EAAO,UAAA,KAAe,OAAA;AAAA;;ADoB9B;;;;;;;;;AAqBA;iBC3BgB,mBAAA,CAAoB,EAAA,EAAI,kBAAA,IAAsB,KAAA,EAAO,UAAA,KAAe,OAAA;;;;;;;;;;iBAuBpE,iBAAA,CAAkB,MAAA,EAAQ,WAAA,GAAc,WAAA;;;UCjDvC,oBAAA;EACf,MAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA,GAAW,IAAA;EACX,MAAA,GAAS,IAAA;EFZU;EEcnB,MAAA;EFZe;EEcf,KAAA;EACA,MAAA;EACA,SAAA;EACA,aAAA;AAAA;AAAA,UAGe,aAAA;EACf,EAAA;EACA,MAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA,EAAS,MAAA;EACT,QAAA,EAAU,MAAA;EACV,SAAA,EAAW,IAAA;AAAA;AAAA,UAGI,kBAAA;EACf,KAAA,EAAO,aAAA;EACP,KAAA;AAAA;AAAA,cAcW,cAAA;EAAA,QACS,EAAA;cAAA,EAAA,EAAI,kBAAA;EFQiE;EELnF,KAAA,CAAM,KAAA,EAAO,IAAA,CAAK,aAAA,wBAAqC,OAAA;EFKrB;EEQlC,KAAA,CAAM,OAAA,GAAS,oBAAA,GAA4B,OAAA,CAAQ,kBAAA;EFRA;EEkCnD,QAAA,CAAS,EAAA,WAAa,OAAA,CAAQ,aAAA;EFlC+C;EE6C7E,sBAAA,CAAA,GAA0B,OAAA;EF7CyD;EEwDnF,kBAAA,CAAA,GAAsB,OAAA;EAAA,QAapB,eAAA;EAAA,QAmCA,YAAA;AAAA;;;UCnKO,cAAA;EACf,SAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;AAAA;;;;AHFF;iBGSgB,kBAAA,CAAmB,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,cAAA,GAAiB,MAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/logger.ts","../src/audit.ts","../src/audit-client.ts","../src/context.ts"],"mappings":";;;;;KAEY,MAAA,GAAS,QAAA;AAAA,UAEJ,YAAA;EACf,IAAA;EACA,KAAA;EACA,MAAA;AAAA;;;;AAHF;;iBAoCgB,YAAA,CAAa,MAAA,GAAS,YAAA,GAAe,MAAA;;;;iBAqBrC,iBAAA,CAAkB,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,MAAA,oBAA0B,MAAA;;;UCzDpE,UAAA;EACf,MAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA,GAAU,MAAA;EACV,QAAA,GAAW,MAAA;AAAA;AAAA,UAGI,WAAA;EACf,MAAA,EAAQ,MAAA;EACR,QAAA,IAAY,KAAA,EAAO,UAAA,KAAe,OAAA;AAAA;AAAA,UAGnB,WAAA;EACf,GAAA,GAAM,KAAA,EAAO,UAAA,KAAe,OAAA;AAAA;;ADoB9B;;;;;;;;;AAqBA;iBC3BgB,mBAAA,CAAoB,EAAA,EAAI,kBAAA,IAAsB,KAAA,EAAO,UAAA,KAAe,OAAA;;;;;;;;;;iBAuBpE,iBAAA,CAAkB,MAAA,EAAQ,WAAA,GAAc,WAAA;;;UCjDvC,oBAAA;EACf,MAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA,GAAW,IAAA;EACX,MAAA,GAAS,IAAA;EFZU;EEcnB,MAAA;EFZe;EEcf,KAAA;EACA,MAAA;EACA,SAAA;EACA,aAAA;AAAA;AAAA,UAGe,aAAA;EACf,EAAA;EACA,MAAA;EACA,UAAA;EACA,QAAA;EACA,MAAA;EACA,QAAA;EACA,OAAA,EAAS,MAAA;EACT,QAAA,EAAU,MAAA;EACV,SAAA,EAAW,IAAA;AAAA;AAAA,UAGI,kBAAA;EACf,KAAA,EAAO,aAAA;EACP,KAAA;AAAA;AAAA,cAqBW,cAAA;EAAA,QACH,MAAA;cAEI,EAAA,EAAI,kBAAA;EFDyE;EEMnF,KAAA,CAAM,KAAA,EAAO,IAAA,CAAK,aAAA,wBAAqC,OAAA;EFNrB;EEmBlC,KAAA,CAAM,OAAA,GAAS,oBAAA,GAA4B,OAAA,CAAQ,kBAAA;EFnBA;EEsCnD,QAAA,CAAS,EAAA,WAAa,OAAA,CAAQ,aAAA;EFtC+C;EE2C7E,sBAAA,CAAA,GAA0B,OAAA;EF3CyD;EEkDnF,kBAAA,CAAA,GAAsB,OAAA;EAAA,QAQpB,UAAA;EAAA,QAgCA,YAAA;AAAA;;;UCrJO,cAAA;EACf,SAAA;EACA,MAAA;EACA,MAAA;EACA,MAAA;AAAA;;;;AHFF;iBGSgB,kBAAA,CAAmB,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,cAAA,GAAiB,MAAA"}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{toolkitAuditLogs as e}from"./schema.mjs";import{and as t,asc as n,count as r,desc as i,eq as a,gte as o,ilike as s,isNotNull as c,lte as l,or as u}from"drizzle-orm";import d from"pino";var f=class{constructor(e){this.db=e}async write(t){await this.db.insert(e).values({action:t.action,entityType:t.entityType,entityId:t.entityId,userId:t.userId,userName:t.userName,changes:t.changes,metadata:t.metadata})}async query(n={}){let i=Math.min(Math.max(n.limit??50,1),100),a=Math.max(n.offset??0,0),o=this.buildConditions(n),s=o.length>0?t(...o):void 0,c=this.buildOrderBy(n.sortField,n.sortDirection),[l,u]=await Promise.all([this.db.select().from(e).where(s).orderBy(c).limit(i).offset(a),this.db.select({count:r()}).from(e).where(s)]);return{items:l,total:u[0]?.count??0}}async findById(t){return(await this.db.select().from(e).where(a(e.id,t)).limit(1))[0]??null}async getDistinctEntityTypes(){return(await this.db.selectDistinct({entityType:e.entityType}).from(e).where(c(e.entityType)).orderBy(n(e.entityType))).map(e=>e.entityType).filter(Boolean)}async getDistinctActions(){return(await this.db.selectDistinct({action:e.action}).from(e).orderBy(n(e.action))).map(e=>e.action)}buildConditions(t){let n=[];if(t.action&&n.push(a(e.action,t.action)),t.entityType&&n.push(a(e.entityType,t.entityType)),t.entityId&&n.push(a(e.entityId,t.entityId)),t.userId&&n.push(a(e.userId,t.userId)),t.dateFrom&&n.push(o(e.createdAt,t.dateFrom)),t.dateTo&&n.push(l(e.createdAt,t.dateTo)),t.search){let r=`%${t.search}%`;n.push(u(s(e.action,r),s(e.entityType,r),s(e.userName,r)))}return n}buildOrderBy(t,r){let a=r===`asc`?n:i;switch(t){case`action`:return a(e.action);case`entityType`:return a(e.entityType);default:return a(e.createdAt)}}};function p(e){let t=new f(e);return e=>t.write({action:e.action,entityType:e.entityType??null,entityId:e.entityId??null,userId:e.userId??null,userName:e.userName??null,changes:e.changes??null,metadata:e.metadata??null})}function m(e){return{log:async t=>{e.logger.info({audit:!0,action:t.action,entityType:t.entityType,entityId:t.entityId,userId:t.userId,userName:t.userName,changes:t.changes,metadata:t.metadata},`Audit: ${t.action}`),e.dbWriter&&e.dbWriter(t).catch(n=>{e.logger.error({err:n,auditEntry:t},`Failed to write audit log to database`)})}}}function h(e,t){return e.child(t)}const g=d({level:process.env.LOG_LEVEL||`info`,formatters:{level:e=>({level:e})},timestamp:!1,serializers:{err:d.stdSerializers.err,error:d.stdSerializers.err},redact:{paths:[`password`,`token`,`secret`,`apiKey`,`accessToken`,`refreshToken`],censor:`[REDACTED]`}});function _(e){if(!e)return g;let t={};e.name&&(t.name=e.name);let n={};return e.level&&(n.level=e.level),g.child(t,n)}function v(e,t){return e.child(t)}export{f as AuditLogClient,h as bindRequestContext,p as createAuditDbWriter,m as createAuditLogger,v as createChildLogger,_ as createLogger,e as toolkitAuditLogs};
1
+ import{n as e,t}from"./schema-D9vWDK2q.mjs";import n from"pino";var r=class{client;constructor(e){this.client=t.makeClient(e)}async write(e){await this.client.insert({action:e.action,entityType:e.entityType,entityId:e.entityId,userId:e.userId,userName:e.userName,changes:e.changes,metadata:e.metadata})}async query(e={}){let t=Math.min(Math.max(e.limit??50,1),100),n=Math.max(e.offset??0,0),r=this.buildWhere(e),i=this.buildOrderBy(e.sortField,e.sortDirection),[a,o]=await Promise.all([this.client.findMany({where:r,orderBy:i,limit:t,offset:n}),this.client.count(r)]);return{items:a,total:o}}async findById(e){return this.client.findOne({id:e})}async getDistinctEntityTypes(){return this.client.distinct(`entityType`,{orderBy:`asc`})}async getDistinctActions(){return this.client.distinct(`action`,{orderBy:`asc`})}buildWhere(e){let t=[];if(e.action&&t.push({action:e.action}),e.entityType&&t.push({entityType:e.entityType}),e.entityId&&t.push({entityId:e.entityId}),e.userId&&t.push({userId:e.userId}),e.dateFrom||e.dateTo){let n={};e.dateFrom&&(n.gte=e.dateFrom),e.dateTo&&(n.lte=e.dateTo),t.push({createdAt:n})}if(e.search&&t.push({$or:[{action:{ilike:e.search}},{entityType:{ilike:e.search}},{userName:{ilike:e.search}}]}),t.length!==0)return t.length===1?t[0]:{$and:t}}buildOrderBy(e,t){let n=t===`asc`?`asc`:`desc`;switch(e){case`action`:return[{column:`action`,dir:n}];case`entityType`:return[{column:`entityType`,dir:n}];default:return[{column:`createdAt`,dir:n}]}}};function i(e){let t=new r(e);return e=>t.write({action:e.action,entityType:e.entityType??null,entityId:e.entityId??null,userId:e.userId??null,userName:e.userName??null,changes:e.changes??null,metadata:e.metadata??null})}function a(e){return{log:async t=>{e.logger.info({audit:!0,action:t.action,entityType:t.entityType,entityId:t.entityId,userId:t.userId,userName:t.userName,changes:t.changes,metadata:t.metadata},`Audit: ${t.action}`),e.dbWriter&&e.dbWriter(t).catch(n=>{e.logger.error({err:n,auditEntry:t},`Failed to write audit log to database`)})}}}function o(e,t){return e.child(t)}const s=n({level:process.env.LOG_LEVEL||`info`,formatters:{level:e=>({level:e})},timestamp:!1,serializers:{err:n.stdSerializers.err,error:n.stdSerializers.err},redact:{paths:[`password`,`token`,`secret`,`apiKey`,`accessToken`,`refreshToken`],censor:`[REDACTED]`}});function c(e){if(!e)return s;let t={};e.name&&(t.name=e.name);let n={};return e.level&&(n.level=e.level),s.child(t,n)}function l(e,t){return e.child(t)}export{r as AuditLogClient,o as bindRequestContext,i as createAuditDbWriter,a as createAuditLogger,l as createChildLogger,c as createLogger,e as toolkitAuditLogs};
2
2
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/audit-client.ts","../src/audit.ts","../src/context.ts","../src/logger.ts"],"sourcesContent":["import { and, asc, count, desc, eq, gte, ilike, isNotNull, lte, or, type SQL } from 'drizzle-orm'\nimport type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { toolkitAuditLogs } from './schema.js'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AuditLogQueryOptions {\n action?: string\n entityType?: string\n entityId?: string\n userId?: string\n dateFrom?: Date\n dateTo?: Date\n /** Free-text search across action, entityType, userName */\n search?: string\n /** Default 50, max 100 */\n limit?: number\n offset?: number\n sortField?: 'createdAt' | 'action' | 'entityType'\n sortDirection?: 'asc' | 'desc'\n}\n\nexport interface AuditLogEntry {\n id: string\n action: string\n entityType: string | null\n entityId: string | null\n userId: string | null\n userName: string | null\n changes: Record<string, unknown> | null\n metadata: Record<string, unknown> | null\n createdAt: Date\n}\n\nexport interface AuditLogListResult {\n items: AuditLogEntry[]\n total: number\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst MAX_LIMIT = 100\nconst DEFAULT_LIMIT = 50\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class AuditLogClient {\n constructor(private db: PostgresJsDatabase) {}\n\n /** Write a single audit log entry */\n async write(entry: Omit<AuditLogEntry, 'id' | 'createdAt'>): Promise<void> {\n await this.db.insert(toolkitAuditLogs).values({\n action: entry.action,\n entityType: entry.entityType,\n entityId: entry.entityId,\n userId: entry.userId,\n userName: entry.userName,\n changes: entry.changes,\n metadata: entry.metadata,\n })\n }\n\n /** Query audit logs with filters and pagination */\n async query(options: AuditLogQueryOptions = {}): Promise<AuditLogListResult> {\n const limit = Math.min(Math.max(options.limit ?? DEFAULT_LIMIT, 1), MAX_LIMIT)\n const offset = Math.max(options.offset ?? 0, 0)\n\n const conditions = this.buildConditions(options)\n const where = conditions.length > 0 ? and(...conditions) : undefined\n const orderBy = this.buildOrderBy(options.sortField, options.sortDirection)\n\n const [items, totalResult] = await Promise.all([\n this.db\n .select()\n .from(toolkitAuditLogs)\n .where(where)\n .orderBy(orderBy)\n .limit(limit)\n .offset(offset),\n this.db.select({ count: count() }).from(toolkitAuditLogs).where(where),\n ])\n\n return {\n items: items as AuditLogEntry[],\n total: totalResult[0]?.count ?? 0,\n }\n }\n\n /** Get a single audit log entry by ID */\n async findById(id: string): Promise<AuditLogEntry | null> {\n const rows = await this.db\n .select()\n .from(toolkitAuditLogs)\n .where(eq(toolkitAuditLogs.id, id))\n .limit(1)\n\n return (rows[0] as AuditLogEntry) ?? null\n }\n\n /** Get distinct entity types present in the audit log */\n async getDistinctEntityTypes(): Promise<string[]> {\n const rows = await this.db\n .selectDistinct({ entityType: toolkitAuditLogs.entityType })\n .from(toolkitAuditLogs)\n .where(isNotNull(toolkitAuditLogs.entityType))\n .orderBy(asc(toolkitAuditLogs.entityType))\n\n return rows.map((r) => r.entityType!).filter(Boolean)\n }\n\n /** Get distinct actions present in the audit log */\n async getDistinctActions(): Promise<string[]> {\n const rows = await this.db\n .selectDistinct({ action: toolkitAuditLogs.action })\n .from(toolkitAuditLogs)\n .orderBy(asc(toolkitAuditLogs.action))\n\n return rows.map((r) => r.action)\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private buildConditions(options: AuditLogQueryOptions): SQL[] {\n const conditions: SQL[] = []\n\n if (options.action) {\n conditions.push(eq(toolkitAuditLogs.action, options.action))\n }\n if (options.entityType) {\n conditions.push(eq(toolkitAuditLogs.entityType, options.entityType))\n }\n if (options.entityId) {\n conditions.push(eq(toolkitAuditLogs.entityId, options.entityId))\n }\n if (options.userId) {\n conditions.push(eq(toolkitAuditLogs.userId, options.userId))\n }\n if (options.dateFrom) {\n conditions.push(gte(toolkitAuditLogs.createdAt, options.dateFrom))\n }\n if (options.dateTo) {\n conditions.push(lte(toolkitAuditLogs.createdAt, options.dateTo))\n }\n if (options.search) {\n const pattern = `%${options.search}%`\n conditions.push(\n or(\n ilike(toolkitAuditLogs.action, pattern),\n ilike(toolkitAuditLogs.entityType, pattern),\n ilike(toolkitAuditLogs.userName, pattern),\n )!,\n )\n }\n\n return conditions\n }\n\n private buildOrderBy(sortField?: string, sortDirection?: string): SQL {\n const dirFn = sortDirection === 'asc' ? asc : desc\n switch (sortField) {\n case 'action':\n return dirFn(toolkitAuditLogs.action)\n case 'entityType':\n return dirFn(toolkitAuditLogs.entityType)\n case 'createdAt':\n default:\n return dirFn(toolkitAuditLogs.createdAt)\n }\n }\n}\n","import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { AuditLogClient } from './audit-client.js'\nimport type { Logger } from './logger.js'\n\nexport interface AuditEntry {\n action: string\n entityType?: string\n entityId?: string\n userId?: string\n userName?: string\n changes?: Record<string, unknown>\n metadata?: Record<string, unknown>\n}\n\nexport interface AuditConfig {\n logger: Logger\n dbWriter?: (entry: AuditEntry) => Promise<void>\n}\n\nexport interface AuditLogger {\n log: (entry: AuditEntry) => Promise<void>\n}\n\n/**\n * Create a dbWriter callback wired to AuditLogClient.\n *\n * Pass the returned function as `dbWriter` to `createAuditLogger`:\n * ```typescript\n * const auditLogger = createAuditLogger({\n * logger,\n * dbWriter: createAuditDbWriter(db),\n * })\n * ```\n */\nexport function createAuditDbWriter(db: PostgresJsDatabase): (entry: AuditEntry) => Promise<void> {\n const client = new AuditLogClient(db)\n return (entry) =>\n client.write({\n action: entry.action,\n entityType: entry.entityType ?? null,\n entityId: entry.entityId ?? null,\n userId: entry.userId ?? null,\n userName: entry.userName ?? null,\n changes: entry.changes ?? null,\n metadata: entry.metadata ?? null,\n })\n}\n\n/**\n * Create an audit logger\n *\n * Audit logs are written to stdout immediately (non-blocking).\n * Optionally, they can also be written to the database if dbWriter is provided.\n *\n * Database writes are fire-and-forget to avoid blocking the main operation.\n * If DB write fails, it's logged to stderr but doesn't throw.\n */\nexport function createAuditLogger(config: AuditConfig): AuditLogger {\n return {\n log: async (entry: AuditEntry) => {\n // Log to stdout immediately (structured log with audit: true marker)\n config.logger.info(\n {\n audit: true,\n action: entry.action,\n entityType: entry.entityType,\n entityId: entry.entityId,\n userId: entry.userId,\n userName: entry.userName,\n changes: entry.changes,\n metadata: entry.metadata,\n },\n `Audit: ${entry.action}`,\n )\n\n // Write to DB if configured (fire and forget)\n if (config.dbWriter) {\n config.dbWriter(entry).catch((err) => {\n config.logger.error({ err, auditEntry: entry }, 'Failed to write audit log to database')\n })\n }\n },\n }\n}\n","import type { Logger } from './logger.js'\n\nexport interface RequestContext {\n requestId?: string\n userId?: string\n teamId?: string\n locale?: string\n}\n\n/**\n * Bind request context to a logger\n * Returns a child logger with the context automatically included in all log entries\n */\nexport function bindRequestContext(logger: Logger, context: RequestContext): Logger {\n return logger.child(context)\n}\n","import pino, { type Logger as PinoLogger } from 'pino'\n\nexport type Logger = PinoLogger\n\nexport interface LoggerConfig {\n name?: string\n level?: string\n redact?: string[]\n}\n\n/**\n * Root logger instance\n *\n * IMPORTANT: No transports are used to avoid Next.js bundler issues.\n * Pino transports use worker threads that break webpack/turbopack.\n *\n * For dev pretty-printing, pipe to pino-pretty:\n * pnpm dev | pnpm pino-pretty\n */\nconst rootLogger = pino({\n level: process.env.LOG_LEVEL || 'info',\n formatters: {\n level: (label) => ({ level: label }),\n },\n timestamp: false,\n serializers: {\n err: pino.stdSerializers.err,\n error: pino.stdSerializers.err,\n },\n redact: {\n paths: ['password', 'token', 'secret', 'apiKey', 'accessToken', 'refreshToken'],\n censor: '[REDACTED]',\n },\n})\n\n/**\n * Create a logger instance\n * If no config provided, returns the root logger\n * If config provided, returns a child logger with the specified context\n */\nexport function createLogger(config?: LoggerConfig): Logger {\n if (!config) {\n return rootLogger\n }\n\n const bindings: Record<string, unknown> = {}\n if (config.name) {\n bindings.name = config.name\n }\n\n const options: { level?: string } = {}\n if (config.level) {\n options.level = config.level\n }\n\n return rootLogger.child(bindings, options)\n}\n\n/**\n * Create a child logger from an existing logger with additional context\n */\nexport function createChildLogger(parent: Logger, context: Record<string, unknown>): Logger {\n return parent.child(context)\n}\n"],"mappings":"gMAoDA,IAAa,EAAb,KAA4B,CAC1B,YAAY,EAAgC,CAAxB,KAAA,GAAA,EAGpB,MAAM,MAAM,EAA+D,CACzE,MAAM,KAAK,GAAG,OAAO,EAAiB,CAAC,OAAO,CAC5C,OAAQ,EAAM,OACd,WAAY,EAAM,WAClB,SAAU,EAAM,SAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,QAAS,EAAM,QACf,SAAU,EAAM,SACjB,CAAC,CAIJ,MAAM,MAAM,EAAgC,EAAE,CAA+B,CAC3E,IAAM,EAAQ,KAAK,IAAI,KAAK,IAAI,EAAQ,OAAS,GAAe,EAAE,CAAE,IAAU,CACxE,EAAS,KAAK,IAAI,EAAQ,QAAU,EAAG,EAAE,CAEzC,EAAa,KAAK,gBAAgB,EAAQ,CAC1C,EAAQ,EAAW,OAAS,EAAI,EAAI,GAAG,EAAW,CAAG,IAAA,GACrD,EAAU,KAAK,aAAa,EAAQ,UAAW,EAAQ,cAAc,CAErE,CAAC,EAAO,GAAe,MAAM,QAAQ,IAAI,CAC7C,KAAK,GACF,QAAQ,CACR,KAAK,EAAiB,CACtB,MAAM,EAAM,CACZ,QAAQ,EAAQ,CAChB,MAAM,EAAM,CACZ,OAAO,EAAO,CACjB,KAAK,GAAG,OAAO,CAAE,MAAO,GAAO,CAAE,CAAC,CAAC,KAAK,EAAiB,CAAC,MAAM,EAAM,CACvE,CAAC,CAEF,MAAO,CACE,QACP,MAAO,EAAY,IAAI,OAAS,EACjC,CAIH,MAAM,SAAS,EAA2C,CAOxD,OANa,MAAM,KAAK,GACrB,QAAQ,CACR,KAAK,EAAiB,CACtB,MAAM,EAAG,EAAiB,GAAI,EAAG,CAAC,CAClC,MAAM,EAAE,EAEE,IAAwB,KAIvC,MAAM,wBAA4C,CAOhD,OANa,MAAM,KAAK,GACrB,eAAe,CAAE,WAAY,EAAiB,WAAY,CAAC,CAC3D,KAAK,EAAiB,CACtB,MAAM,EAAU,EAAiB,WAAW,CAAC,CAC7C,QAAQ,EAAI,EAAiB,WAAW,CAAC,EAEhC,IAAK,GAAM,EAAE,WAAY,CAAC,OAAO,QAAQ,CAIvD,MAAM,oBAAwC,CAM5C,OALa,MAAM,KAAK,GACrB,eAAe,CAAE,OAAQ,EAAiB,OAAQ,CAAC,CACnD,KAAK,EAAiB,CACtB,QAAQ,EAAI,EAAiB,OAAO,CAAC,EAE5B,IAAK,GAAM,EAAE,OAAO,CAOlC,gBAAwB,EAAsC,CAC5D,IAAM,EAAoB,EAAE,CAoB5B,GAlBI,EAAQ,QACV,EAAW,KAAK,EAAG,EAAiB,OAAQ,EAAQ,OAAO,CAAC,CAE1D,EAAQ,YACV,EAAW,KAAK,EAAG,EAAiB,WAAY,EAAQ,WAAW,CAAC,CAElE,EAAQ,UACV,EAAW,KAAK,EAAG,EAAiB,SAAU,EAAQ,SAAS,CAAC,CAE9D,EAAQ,QACV,EAAW,KAAK,EAAG,EAAiB,OAAQ,EAAQ,OAAO,CAAC,CAE1D,EAAQ,UACV,EAAW,KAAK,EAAI,EAAiB,UAAW,EAAQ,SAAS,CAAC,CAEhE,EAAQ,QACV,EAAW,KAAK,EAAI,EAAiB,UAAW,EAAQ,OAAO,CAAC,CAE9D,EAAQ,OAAQ,CAClB,IAAM,EAAU,IAAI,EAAQ,OAAO,GACnC,EAAW,KACT,EACE,EAAM,EAAiB,OAAQ,EAAQ,CACvC,EAAM,EAAiB,WAAY,EAAQ,CAC3C,EAAM,EAAiB,SAAU,EAAQ,CAC1C,CACF,CAGH,OAAO,EAGT,aAAqB,EAAoB,EAA6B,CACpE,IAAM,EAAQ,IAAkB,MAAQ,EAAM,EAC9C,OAAQ,EAAR,CACE,IAAK,SACH,OAAO,EAAM,EAAiB,OAAO,CACvC,IAAK,aACH,OAAO,EAAM,EAAiB,WAAW,CAE3C,QACE,OAAO,EAAM,EAAiB,UAAU,IC5IhD,SAAgB,EAAoB,EAA8D,CAChG,IAAM,EAAS,IAAI,EAAe,EAAG,CACrC,MAAQ,IACN,EAAO,MAAM,CACX,OAAQ,EAAM,OACd,WAAY,EAAM,YAAc,KAChC,SAAU,EAAM,UAAY,KAC5B,OAAQ,EAAM,QAAU,KACxB,SAAU,EAAM,UAAY,KAC5B,QAAS,EAAM,SAAW,KAC1B,SAAU,EAAM,UAAY,KAC7B,CAAC,CAYN,SAAgB,EAAkB,EAAkC,CAClE,MAAO,CACL,IAAK,KAAO,IAAsB,CAEhC,EAAO,OAAO,KACZ,CACE,MAAO,GACP,OAAQ,EAAM,OACd,WAAY,EAAM,WAClB,SAAU,EAAM,SAChB,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,QAAS,EAAM,QACf,SAAU,EAAM,SACjB,CACD,UAAU,EAAM,SACjB,CAGG,EAAO,UACT,EAAO,SAAS,EAAM,CAAC,MAAO,GAAQ,CACpC,EAAO,OAAO,MAAM,CAAE,MAAK,WAAY,EAAO,CAAE,wCAAwC,EACxF,EAGP,CCrEH,SAAgB,EAAmB,EAAgB,EAAiC,CAClF,OAAO,EAAO,MAAM,EAAQ,CCK9B,MAAM,EAAa,EAAK,CACtB,MAAO,QAAQ,IAAI,WAAa,OAChC,WAAY,CACV,MAAQ,IAAW,CAAE,MAAO,EAAO,EACpC,CACD,UAAW,GACX,YAAa,CACX,IAAK,EAAK,eAAe,IACzB,MAAO,EAAK,eAAe,IAC5B,CACD,OAAQ,CACN,MAAO,CAAC,WAAY,QAAS,SAAU,SAAU,cAAe,eAAe,CAC/E,OAAQ,aACT,CACF,CAAC,CAOF,SAAgB,EAAa,EAA+B,CAC1D,GAAI,CAAC,EACH,OAAO,EAGT,IAAM,EAAoC,EAAE,CACxC,EAAO,OACT,EAAS,KAAO,EAAO,MAGzB,IAAM,EAA8B,EAAE,CAKtC,OAJI,EAAO,QACT,EAAQ,MAAQ,EAAO,OAGlB,EAAW,MAAM,EAAU,EAAQ,CAM5C,SAAgB,EAAkB,EAAgB,EAA0C,CAC1F,OAAO,EAAO,MAAM,EAAQ"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/audit-client.ts","../src/audit.ts","../src/context.ts","../src/logger.ts"],"sourcesContent":["import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport type { TableClient, WhereClause } from '@murumets-ee/db'\nimport { auditLogTable } from './audit-table.js'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface AuditLogQueryOptions {\n action?: string\n entityType?: string\n entityId?: string\n userId?: string\n dateFrom?: Date\n dateTo?: Date\n /** Free-text search across action, entityType, userName */\n search?: string\n /** Default 50, max 100 */\n limit?: number\n offset?: number\n sortField?: 'createdAt' | 'action' | 'entityType'\n sortDirection?: 'asc' | 'desc'\n}\n\nexport interface AuditLogEntry {\n id: string\n action: string\n entityType: string | null\n entityId: string | null\n userId: string | null\n userName: string | null\n changes: Record<string, unknown> | null\n metadata: Record<string, unknown> | null\n createdAt: Date\n}\n\nexport interface AuditLogListResult {\n items: AuditLogEntry[]\n total: number\n}\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst MAX_LIMIT = 100\nconst DEFAULT_LIMIT = 50\n\n// ---------------------------------------------------------------------------\n// Internal types\n// ---------------------------------------------------------------------------\n\ntype AuditCols = typeof auditLogTable.schema.columns\ntype AuditWhere = WhereClause<AuditCols>\n\n// ---------------------------------------------------------------------------\n// Client\n// ---------------------------------------------------------------------------\n\nexport class AuditLogClient {\n private client: TableClient<AuditCols>\n\n constructor(db: PostgresJsDatabase) {\n this.client = auditLogTable.makeClient(db)\n }\n\n /** Write a single audit log entry */\n async write(entry: Omit<AuditLogEntry, 'id' | 'createdAt'>): Promise<void> {\n await this.client.insert({\n action: entry.action,\n entityType: entry.entityType,\n entityId: entry.entityId,\n userId: entry.userId,\n userName: entry.userName,\n changes: entry.changes,\n metadata: entry.metadata,\n })\n }\n\n /** Query audit logs with filters and pagination */\n async query(options: AuditLogQueryOptions = {}): Promise<AuditLogListResult> {\n const limit = Math.min(Math.max(options.limit ?? DEFAULT_LIMIT, 1), MAX_LIMIT)\n const offset = Math.max(options.offset ?? 0, 0)\n\n const where = this.buildWhere(options)\n const orderBy = this.buildOrderBy(options.sortField, options.sortDirection)\n\n const [items, total] = await Promise.all([\n this.client.findMany({ where, orderBy, limit, offset }),\n this.client.count(where),\n ])\n\n return {\n items: items as AuditLogEntry[],\n total,\n }\n }\n\n /** Get a single audit log entry by ID */\n async findById(id: string): Promise<AuditLogEntry | null> {\n return this.client.findOne({ id }) as Promise<AuditLogEntry | null>\n }\n\n /** Get distinct entity types present in the audit log */\n async getDistinctEntityTypes(): Promise<string[]> {\n // entityType is nullable, but distinct() excludes nulls by default —\n // the cast is safe because includeNull is not set.\n return this.client.distinct('entityType', { orderBy: 'asc' }) as Promise<string[]>\n }\n\n /** Get distinct actions present in the audit log */\n async getDistinctActions(): Promise<string[]> {\n return this.client.distinct('action', { orderBy: 'asc' })\n }\n\n // -------------------------------------------------------------------------\n // Private helpers\n // -------------------------------------------------------------------------\n\n private buildWhere(options: AuditLogQueryOptions): AuditWhere | undefined {\n const parts: AuditWhere[] = []\n\n if (options.action) parts.push({ action: options.action })\n if (options.entityType) parts.push({ entityType: options.entityType })\n if (options.entityId) parts.push({ entityId: options.entityId })\n if (options.userId) parts.push({ userId: options.userId })\n\n // Date range: combine into a single createdAt condition\n if (options.dateFrom || options.dateTo) {\n const dateOps: Record<string, unknown> = {}\n if (options.dateFrom) dateOps.gte = options.dateFrom\n if (options.dateTo) dateOps.lte = options.dateTo\n parts.push({ createdAt: dateOps } as AuditWhere)\n }\n\n // Free-text search across action, entityType, userName\n if (options.search) {\n parts.push({\n $or: [\n { action: { ilike: options.search } },\n { entityType: { ilike: options.search } },\n { userName: { ilike: options.search } },\n ],\n })\n }\n\n if (parts.length === 0) return undefined\n if (parts.length === 1) return parts[0]\n return { $and: parts }\n }\n\n private buildOrderBy(\n sortField?: string,\n sortDirection?: string,\n ): { column: keyof AuditCols & string; dir: 'asc' | 'desc' }[] {\n const dir: 'asc' | 'desc' = sortDirection === 'asc' ? 'asc' : 'desc'\n switch (sortField) {\n case 'action':\n return [{ column: 'action', dir }]\n case 'entityType':\n return [{ column: 'entityType', dir }]\n case 'createdAt':\n default:\n return [{ column: 'createdAt', dir }]\n }\n }\n}\n","import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js'\nimport { AuditLogClient } from './audit-client.js'\nimport type { Logger } from './logger.js'\n\nexport interface AuditEntry {\n action: string\n entityType?: string\n entityId?: string\n userId?: string\n userName?: string\n changes?: Record<string, unknown>\n metadata?: Record<string, unknown>\n}\n\nexport interface AuditConfig {\n logger: Logger\n dbWriter?: (entry: AuditEntry) => Promise<void>\n}\n\nexport interface AuditLogger {\n log: (entry: AuditEntry) => Promise<void>\n}\n\n/**\n * Create a dbWriter callback wired to AuditLogClient.\n *\n * Pass the returned function as `dbWriter` to `createAuditLogger`:\n * ```typescript\n * const auditLogger = createAuditLogger({\n * logger,\n * dbWriter: createAuditDbWriter(db),\n * })\n * ```\n */\nexport function createAuditDbWriter(db: PostgresJsDatabase): (entry: AuditEntry) => Promise<void> {\n const client = new AuditLogClient(db)\n return (entry) =>\n client.write({\n action: entry.action,\n entityType: entry.entityType ?? null,\n entityId: entry.entityId ?? null,\n userId: entry.userId ?? null,\n userName: entry.userName ?? null,\n changes: entry.changes ?? null,\n metadata: entry.metadata ?? null,\n })\n}\n\n/**\n * Create an audit logger\n *\n * Audit logs are written to stdout immediately (non-blocking).\n * Optionally, they can also be written to the database if dbWriter is provided.\n *\n * Database writes are fire-and-forget to avoid blocking the main operation.\n * If DB write fails, it's logged to stderr but doesn't throw.\n */\nexport function createAuditLogger(config: AuditConfig): AuditLogger {\n return {\n log: async (entry: AuditEntry) => {\n // Log to stdout immediately (structured log with audit: true marker)\n config.logger.info(\n {\n audit: true,\n action: entry.action,\n entityType: entry.entityType,\n entityId: entry.entityId,\n userId: entry.userId,\n userName: entry.userName,\n changes: entry.changes,\n metadata: entry.metadata,\n },\n `Audit: ${entry.action}`,\n )\n\n // Write to DB if configured (fire and forget)\n if (config.dbWriter) {\n config.dbWriter(entry).catch((err) => {\n config.logger.error({ err, auditEntry: entry }, 'Failed to write audit log to database')\n })\n }\n },\n }\n}\n","import type { Logger } from './logger.js'\n\nexport interface RequestContext {\n requestId?: string\n userId?: string\n teamId?: string\n locale?: string\n}\n\n/**\n * Bind request context to a logger\n * Returns a child logger with the context automatically included in all log entries\n */\nexport function bindRequestContext(logger: Logger, context: RequestContext): Logger {\n return logger.child(context)\n}\n","import pino, { type Logger as PinoLogger } from 'pino'\n\nexport type Logger = PinoLogger\n\nexport interface LoggerConfig {\n name?: string\n level?: string\n redact?: string[]\n}\n\n/**\n * Root logger instance\n *\n * IMPORTANT: No transports are used to avoid Next.js bundler issues.\n * Pino transports use worker threads that break webpack/turbopack.\n *\n * For dev pretty-printing, pipe to pino-pretty:\n * pnpm dev | pnpm pino-pretty\n */\nconst rootLogger = pino({\n level: process.env.LOG_LEVEL || 'info',\n formatters: {\n level: (label) => ({ level: label }),\n },\n timestamp: false,\n serializers: {\n err: pino.stdSerializers.err,\n error: pino.stdSerializers.err,\n },\n redact: {\n paths: ['password', 'token', 'secret', 'apiKey', 'accessToken', 'refreshToken'],\n censor: '[REDACTED]',\n },\n})\n\n/**\n * Create a logger instance\n * If no config provided, returns the root logger\n * If config provided, returns a child logger with the specified context\n */\nexport function createLogger(config?: LoggerConfig): Logger {\n if (!config) {\n return rootLogger\n }\n\n const bindings: Record<string, unknown> = {}\n if (config.name) {\n bindings.name = config.name\n }\n\n const options: { level?: string } = {}\n if (config.level) {\n options.level = config.level\n }\n\n return rootLogger.child(bindings, options)\n}\n\n/**\n * Create a child logger from an existing logger with additional context\n */\nexport function createChildLogger(parent: Logger, context: Record<string, unknown>): Logger {\n return parent.child(context)\n}\n"],"mappings":"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"}
package/dist/plugin.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import{toolkitAuditLogs as e}from"./schema.mjs";function t(){return{name:`@murumets-ee/logging`,tables:{toolkitAuditLogs:e}}}export{t as logging};
1
+ import{n as e}from"./schema-D9vWDK2q.mjs";function t(){return{name:`@murumets-ee/logging`,tables:{toolkitAuditLogs:e}}}export{t as logging};
2
2
  //# sourceMappingURL=plugin.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.mjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["// biome-ignore lint/suspicious/noExplicitAny: structural PgTable\nimport type { PgTable } from 'drizzle-orm/pg-core'\nimport { toolkitAuditLogs } from './schema.js'\n\n// Structural Plugin shape — kept in sync with @murumets-ee/core. Not imported\n// from core because core depends on logging (circular dep would fail).\ninterface LoggingPlugin {\n name: string\n // biome-ignore lint/suspicious/noExplicitAny: as above\n tables: Record<string, PgTable<any>>\n}\n\n/**\n * Logging plugin — registers the `toolkit_audit_logs` table so it shows up\n * in generated migrations. Zero runtime behavior; the audit logger is wired\n * up separately via `createAuditLogger()`.\n *\n * @example\n * ```typescript\n * import { logging } from '@murumets-ee/logging/plugin'\n *\n * export default defineConfig({\n * plugins: [logging()],\n * })\n * ```\n */\nexport function logging(): LoggingPlugin {\n return {\n name: '@murumets-ee/logging',\n tables: { toolkitAuditLogs },\n }\n}\n"],"mappings":"gDA0BA,SAAgB,GAAyB,CACvC,MAAO,CACL,KAAM,uBACN,OAAQ,CAAE,mBAAkB,CAC7B"}
1
+ {"version":3,"file":"plugin.mjs","names":[],"sources":["../src/plugin.ts"],"sourcesContent":["// biome-ignore lint/suspicious/noExplicitAny: structural PgTable\nimport type { PgTable } from 'drizzle-orm/pg-core'\nimport { toolkitAuditLogs } from './schema.js'\n\n// Structural Plugin shape — kept in sync with @murumets-ee/core. Not imported\n// from core because core depends on logging (circular dep would fail).\ninterface LoggingPlugin {\n name: string\n // biome-ignore lint/suspicious/noExplicitAny: as above\n tables: Record<string, PgTable<any>>\n}\n\n/**\n * Logging plugin — registers the `toolkit_audit_logs` table so it shows up\n * in generated migrations. Zero runtime behavior; the audit logger is wired\n * up separately via `createAuditLogger()`.\n *\n * @example\n * ```typescript\n * import { logging } from '@murumets-ee/logging/plugin'\n *\n * export default defineConfig({\n * plugins: [logging()],\n * })\n * ```\n */\nexport function logging(): LoggingPlugin {\n return {\n name: '@murumets-ee/logging',\n tables: { toolkitAuditLogs },\n }\n}\n"],"mappings":"0CA0BA,SAAgB,GAAyB,CACvC,MAAO,CACL,KAAM,uBACN,OAAQ,CAAE,mBAAkB,CAC7B"}
@@ -0,0 +1,32 @@
1
+ import * as _$drizzle_orm0 from "drizzle-orm";
2
+ import * as _$drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
3
+
4
+ //#region src/audit-table.d.ts
5
+ /** Backward-compatible re-export — consumers importing `toolkitAuditLogs` see the same PgTable. */
6
+ declare const toolkitAuditLogs: _$drizzle_orm_pg_core0.PgTableWithColumns<{
7
+ name: string;
8
+ schema: undefined;
9
+ columns: {
10
+ [x: string]: _$drizzle_orm_pg_core0.PgColumn<{
11
+ name: string;
12
+ tableName: string;
13
+ dataType: _$drizzle_orm0.ColumnDataType;
14
+ columnType: string;
15
+ data: unknown;
16
+ driverParam: unknown;
17
+ notNull: false;
18
+ hasDefault: false;
19
+ isPrimaryKey: false;
20
+ isAutoincrement: false;
21
+ hasRuntimeDefault: false;
22
+ enumValues: string[] | undefined;
23
+ baseColumn: never;
24
+ identity: undefined;
25
+ generated: undefined;
26
+ }, {}, {}>;
27
+ };
28
+ dialect: "pg";
29
+ }>;
30
+ //#endregion
31
+ export { toolkitAuditLogs as t };
32
+ //# sourceMappingURL=schema-D9AdiYql.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-D9AdiYql.d.mts","names":[],"sources":["../src/audit-table.ts"],"mappings":";;;;;cAsCa,gBAAA,yBAAgB,kBAAA;;;;;;;gBAAsB,cAAA,CAAA,cAAA"}
@@ -0,0 +1,2 @@
1
+ import{column as e,defineTable as t}from"@murumets-ee/db";const n=t({name:`toolkit_audit_logs`,columns:{id:e.uuid({primaryKey:!0,defaultRandom:!0}),action:e.varchar({length:100,notNull:!0}),entityType:e.varchar({length:100,pgName:`entity_type`}),entityId:e.varchar({length:255,pgName:`entity_id`}),userId:e.varchar({length:255,pgName:`user_id`}),userName:e.varchar({length:255,pgName:`user_name`}),changes:e.jsonb(),metadata:e.jsonb(),createdAt:e.timestamp({notNull:!0,defaultNow:!0,withTimezone:!0,pgName:`created_at`})},indexes:[{on:[`entityType`,`createdAt`],name:`audit_entity_type_created_at_idx`},{on:[`userId`,`createdAt`],name:`audit_user_id_created_at_idx`},{on:[`action`,`createdAt`],name:`audit_action_created_at_idx`},{on:[`createdAt`],name:`audit_created_at_idx`},{on:[`entityId`],name:`audit_entity_id_idx`}]}),r=n.table;export{r as n,n as t};
2
+ //# sourceMappingURL=schema-D9vWDK2q.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-D9vWDK2q.mjs","names":[],"sources":["../src/audit-table.ts"],"sourcesContent":["/**\n * `toolkit_audit_logs` table definition via `defineTable`.\n *\n * Replaces the hand-written `pgTable` in `schema.ts`. Uses `pgName` to\n * preserve the existing snake_case Postgres column names so no migration\n * is required.\n */\n\nimport { column, defineTable } from '@murumets-ee/db'\n\nexport const auditLogTable = defineTable({\n name: 'toolkit_audit_logs',\n columns: {\n id: column.uuid({ primaryKey: true, defaultRandom: true }),\n action: column.varchar({ length: 100, notNull: true }),\n entityType: column.varchar({ length: 100, pgName: 'entity_type' }),\n entityId: column.varchar({ length: 255, pgName: 'entity_id' }),\n userId: column.varchar({ length: 255, pgName: 'user_id' }),\n userName: column.varchar({ length: 255, pgName: 'user_name' }),\n changes: column.jsonb<Record<string, unknown>>(),\n metadata: column.jsonb<Record<string, unknown>>(),\n createdAt: column.timestamp({\n notNull: true,\n defaultNow: true,\n withTimezone: true,\n pgName: 'created_at',\n }),\n },\n indexes: [\n { on: ['entityType', 'createdAt'], name: 'audit_entity_type_created_at_idx' },\n { on: ['userId', 'createdAt'], name: 'audit_user_id_created_at_idx' },\n { on: ['action', 'createdAt'], name: 'audit_action_created_at_idx' },\n { on: ['createdAt'], name: 'audit_created_at_idx' },\n { on: ['entityId'], name: 'audit_entity_id_idx' },\n ],\n})\n\n/** Backward-compatible re-export — consumers importing `toolkitAuditLogs` see the same PgTable. */\nexport const toolkitAuditLogs = auditLogTable.table\n"],"mappings":"0DAUA,MAAa,EAAgB,EAAY,CACvC,KAAM,qBACN,QAAS,CACP,GAAI,EAAO,KAAK,CAAE,WAAY,GAAM,cAAe,GAAM,CAAC,CAC1D,OAAQ,EAAO,QAAQ,CAAE,OAAQ,IAAK,QAAS,GAAM,CAAC,CACtD,WAAY,EAAO,QAAQ,CAAE,OAAQ,IAAK,OAAQ,cAAe,CAAC,CAClE,SAAU,EAAO,QAAQ,CAAE,OAAQ,IAAK,OAAQ,YAAa,CAAC,CAC9D,OAAQ,EAAO,QAAQ,CAAE,OAAQ,IAAK,OAAQ,UAAW,CAAC,CAC1D,SAAU,EAAO,QAAQ,CAAE,OAAQ,IAAK,OAAQ,YAAa,CAAC,CAC9D,QAAS,EAAO,OAAgC,CAChD,SAAU,EAAO,OAAgC,CACjD,UAAW,EAAO,UAAU,CAC1B,QAAS,GACT,WAAY,GACZ,aAAc,GACd,OAAQ,aACT,CAAC,CACH,CACD,QAAS,CACP,CAAE,GAAI,CAAC,aAAc,YAAY,CAAE,KAAM,mCAAoC,CAC7E,CAAE,GAAI,CAAC,SAAU,YAAY,CAAE,KAAM,+BAAgC,CACrE,CAAE,GAAI,CAAC,SAAU,YAAY,CAAE,KAAM,8BAA+B,CACpE,CAAE,GAAI,CAAC,YAAY,CAAE,KAAM,uBAAwB,CACnD,CAAE,GAAI,CAAC,WAAW,CAAE,KAAM,sBAAuB,CAClD,CACF,CAAC,CAGW,EAAmB,EAAc"}
package/dist/schema.d.mts CHANGED
@@ -1,180 +1,2 @@
1
- import * as _$drizzle_orm_pg_core0 from "drizzle-orm/pg-core";
2
-
3
- //#region src/schema.d.ts
4
- declare const toolkitAuditLogs: _$drizzle_orm_pg_core0.PgTableWithColumns<{
5
- name: "toolkit_audit_logs";
6
- schema: undefined;
7
- columns: {
8
- id: _$drizzle_orm_pg_core0.PgColumn<{
9
- name: "id";
10
- tableName: "toolkit_audit_logs";
11
- dataType: "string";
12
- columnType: "PgUUID";
13
- data: string;
14
- driverParam: string;
15
- notNull: true;
16
- hasDefault: true;
17
- isPrimaryKey: true;
18
- isAutoincrement: false;
19
- hasRuntimeDefault: false;
20
- enumValues: undefined;
21
- baseColumn: never;
22
- identity: undefined;
23
- generated: undefined;
24
- }, {}, {}>;
25
- action: _$drizzle_orm_pg_core0.PgColumn<{
26
- name: "action";
27
- tableName: "toolkit_audit_logs";
28
- dataType: "string";
29
- columnType: "PgVarchar";
30
- data: string;
31
- driverParam: string;
32
- notNull: true;
33
- hasDefault: false;
34
- isPrimaryKey: false;
35
- isAutoincrement: false;
36
- hasRuntimeDefault: false;
37
- enumValues: [string, ...string[]];
38
- baseColumn: never;
39
- identity: undefined;
40
- generated: undefined;
41
- }, {}, {
42
- length: 100;
43
- }>;
44
- entityType: _$drizzle_orm_pg_core0.PgColumn<{
45
- name: "entity_type";
46
- tableName: "toolkit_audit_logs";
47
- dataType: "string";
48
- columnType: "PgVarchar";
49
- data: string;
50
- driverParam: string;
51
- notNull: false;
52
- hasDefault: false;
53
- isPrimaryKey: false;
54
- isAutoincrement: false;
55
- hasRuntimeDefault: false;
56
- enumValues: [string, ...string[]];
57
- baseColumn: never;
58
- identity: undefined;
59
- generated: undefined;
60
- }, {}, {
61
- length: 100;
62
- }>;
63
- entityId: _$drizzle_orm_pg_core0.PgColumn<{
64
- name: "entity_id";
65
- tableName: "toolkit_audit_logs";
66
- dataType: "string";
67
- columnType: "PgVarchar";
68
- data: string;
69
- driverParam: string;
70
- notNull: false;
71
- hasDefault: false;
72
- isPrimaryKey: false;
73
- isAutoincrement: false;
74
- hasRuntimeDefault: false;
75
- enumValues: [string, ...string[]];
76
- baseColumn: never;
77
- identity: undefined;
78
- generated: undefined;
79
- }, {}, {
80
- length: 255;
81
- }>;
82
- userId: _$drizzle_orm_pg_core0.PgColumn<{
83
- name: "user_id";
84
- tableName: "toolkit_audit_logs";
85
- dataType: "string";
86
- columnType: "PgVarchar";
87
- data: string;
88
- driverParam: string;
89
- notNull: false;
90
- hasDefault: false;
91
- isPrimaryKey: false;
92
- isAutoincrement: false;
93
- hasRuntimeDefault: false;
94
- enumValues: [string, ...string[]];
95
- baseColumn: never;
96
- identity: undefined;
97
- generated: undefined;
98
- }, {}, {
99
- length: 255;
100
- }>;
101
- userName: _$drizzle_orm_pg_core0.PgColumn<{
102
- name: "user_name";
103
- tableName: "toolkit_audit_logs";
104
- dataType: "string";
105
- columnType: "PgVarchar";
106
- data: string;
107
- driverParam: string;
108
- notNull: false;
109
- hasDefault: false;
110
- isPrimaryKey: false;
111
- isAutoincrement: false;
112
- hasRuntimeDefault: false;
113
- enumValues: [string, ...string[]];
114
- baseColumn: never;
115
- identity: undefined;
116
- generated: undefined;
117
- }, {}, {
118
- length: 255;
119
- }>;
120
- changes: _$drizzle_orm_pg_core0.PgColumn<{
121
- name: "changes";
122
- tableName: "toolkit_audit_logs";
123
- dataType: "json";
124
- columnType: "PgJsonb";
125
- data: Record<string, unknown>;
126
- driverParam: unknown;
127
- notNull: false;
128
- hasDefault: false;
129
- isPrimaryKey: false;
130
- isAutoincrement: false;
131
- hasRuntimeDefault: false;
132
- enumValues: undefined;
133
- baseColumn: never;
134
- identity: undefined;
135
- generated: undefined;
136
- }, {}, {
137
- $type: Record<string, unknown>;
138
- }>;
139
- metadata: _$drizzle_orm_pg_core0.PgColumn<{
140
- name: "metadata";
141
- tableName: "toolkit_audit_logs";
142
- dataType: "json";
143
- columnType: "PgJsonb";
144
- data: Record<string, unknown>;
145
- driverParam: unknown;
146
- notNull: false;
147
- hasDefault: false;
148
- isPrimaryKey: false;
149
- isAutoincrement: false;
150
- hasRuntimeDefault: false;
151
- enumValues: undefined;
152
- baseColumn: never;
153
- identity: undefined;
154
- generated: undefined;
155
- }, {}, {
156
- $type: Record<string, unknown>;
157
- }>;
158
- createdAt: _$drizzle_orm_pg_core0.PgColumn<{
159
- name: "created_at";
160
- tableName: "toolkit_audit_logs";
161
- dataType: "date";
162
- columnType: "PgTimestamp";
163
- data: Date;
164
- driverParam: string;
165
- notNull: true;
166
- hasDefault: true;
167
- isPrimaryKey: false;
168
- isAutoincrement: false;
169
- hasRuntimeDefault: false;
170
- enumValues: undefined;
171
- baseColumn: never;
172
- identity: undefined;
173
- generated: undefined;
174
- }, {}, {}>;
175
- };
176
- dialect: "pg";
177
- }>;
178
- //#endregion
179
- export { toolkitAuditLogs };
180
- //# sourceMappingURL=schema.d.mts.map
1
+ import { t as toolkitAuditLogs } from "./schema-D9AdiYql.mjs";
2
+ export { toolkitAuditLogs };
package/dist/schema.mjs CHANGED
@@ -1,2 +1 @@
1
- import{index as e,jsonb as t,pgTable as n,timestamp as r,uuid as i,varchar as a}from"drizzle-orm/pg-core";const o=n(`toolkit_audit_logs`,{id:i(`id`).primaryKey().defaultRandom(),action:a(`action`,{length:100}).notNull(),entityType:a(`entity_type`,{length:100}),entityId:a(`entity_id`,{length:255}),userId:a(`user_id`,{length:255}),userName:a(`user_name`,{length:255}),changes:t(`changes`).$type(),metadata:t(`metadata`).$type(),createdAt:r(`created_at`,{withTimezone:!0}).notNull().defaultNow()},t=>({entityTypeCreatedAtIdx:e(`audit_entity_type_created_at_idx`).on(t.entityType,t.createdAt),userIdCreatedAtIdx:e(`audit_user_id_created_at_idx`).on(t.userId,t.createdAt),actionCreatedAtIdx:e(`audit_action_created_at_idx`).on(t.action,t.createdAt),createdAtIdx:e(`audit_created_at_idx`).on(t.createdAt),entityIdIdx:e(`audit_entity_id_idx`).on(t.entityId)}));export{o as toolkitAuditLogs};
2
- //# sourceMappingURL=schema.mjs.map
1
+ import{n as e}from"./schema-D9vWDK2q.mjs";export{e as toolkitAuditLogs};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@murumets-ee/logging",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -27,7 +27,8 @@
27
27
  "dependencies": {
28
28
  "drizzle-orm": ">=0.40.0",
29
29
  "pino": "^9.5.0",
30
- "zod": ">=3.0.0"
30
+ "zod": ">=3.0.0",
31
+ "@murumets-ee/db": "0.4.0"
31
32
  },
32
33
  "devDependencies": {
33
34
  "tsdown": "^0.21.7",
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.mts","names":[],"sources":["../src/schema.ts"],"mappings":";;;cAEa,gBAAA,yBAAgB,kBAAA;;;;QAuB5B,sBAAA,CAAA,QAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.mjs","names":[],"sources":["../src/schema.ts"],"sourcesContent":["import { index, jsonb, pgTable, timestamp, uuid, varchar } from 'drizzle-orm/pg-core'\n\nexport const toolkitAuditLogs = pgTable(\n 'toolkit_audit_logs',\n {\n id: uuid('id').primaryKey().defaultRandom(),\n action: varchar('action', { length: 100 }).notNull(),\n entityType: varchar('entity_type', { length: 100 }),\n entityId: varchar('entity_id', { length: 255 }),\n userId: varchar('user_id', { length: 255 }),\n userName: varchar('user_name', { length: 255 }),\n changes: jsonb('changes').$type<Record<string, unknown>>(),\n metadata: jsonb('metadata').$type<Record<string, unknown>>(),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),\n },\n (table) => ({\n entityTypeCreatedAtIdx: index('audit_entity_type_created_at_idx').on(\n table.entityType,\n table.createdAt,\n ),\n userIdCreatedAtIdx: index('audit_user_id_created_at_idx').on(table.userId, table.createdAt),\n actionCreatedAtIdx: index('audit_action_created_at_idx').on(table.action, table.createdAt),\n createdAtIdx: index('audit_created_at_idx').on(table.createdAt),\n entityIdIdx: index('audit_entity_id_idx').on(table.entityId),\n }),\n)\n"],"mappings":"0GAEA,MAAa,EAAmB,EAC9B,qBACA,CACE,GAAI,EAAK,KAAK,CAAC,YAAY,CAAC,eAAe,CAC3C,OAAQ,EAAQ,SAAU,CAAE,OAAQ,IAAK,CAAC,CAAC,SAAS,CACpD,WAAY,EAAQ,cAAe,CAAE,OAAQ,IAAK,CAAC,CACnD,SAAU,EAAQ,YAAa,CAAE,OAAQ,IAAK,CAAC,CAC/C,OAAQ,EAAQ,UAAW,CAAE,OAAQ,IAAK,CAAC,CAC3C,SAAU,EAAQ,YAAa,CAAE,OAAQ,IAAK,CAAC,CAC/C,QAAS,EAAM,UAAU,CAAC,OAAgC,CAC1D,SAAU,EAAM,WAAW,CAAC,OAAgC,CAC5D,UAAW,EAAU,aAAc,CAAE,aAAc,GAAM,CAAC,CAAC,SAAS,CAAC,YAAY,CAClF,CACA,IAAW,CACV,uBAAwB,EAAM,mCAAmC,CAAC,GAChE,EAAM,WACN,EAAM,UACP,CACD,mBAAoB,EAAM,+BAA+B,CAAC,GAAG,EAAM,OAAQ,EAAM,UAAU,CAC3F,mBAAoB,EAAM,8BAA8B,CAAC,GAAG,EAAM,OAAQ,EAAM,UAAU,CAC1F,aAAc,EAAM,uBAAuB,CAAC,GAAG,EAAM,UAAU,CAC/D,YAAa,EAAM,sBAAsB,CAAC,GAAG,EAAM,SAAS,CAC7D,EACF"}