@willyim/drizzle-audit 0.1.3

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.
Files changed (56) hide show
  1. package/README.md +278 -0
  2. package/dist/src/cli/generate-migration.d.ts +14 -0
  3. package/dist/src/cli/generate-migration.d.ts.map +1 -0
  4. package/dist/src/cli/generate-migration.js +118 -0
  5. package/dist/src/cli/runner.d.ts +2 -0
  6. package/dist/src/cli/runner.d.ts.map +1 -0
  7. package/dist/src/cli/runner.js +23 -0
  8. package/dist/src/d1/audit-log-schema.d.ts +181 -0
  9. package/dist/src/d1/audit-log-schema.d.ts.map +1 -0
  10. package/dist/src/d1/audit-log-schema.js +30 -0
  11. package/dist/src/d1/index.d.ts +7 -0
  12. package/dist/src/d1/index.d.ts.map +1 -0
  13. package/dist/src/d1/index.js +3 -0
  14. package/dist/src/d1/runtime.d.ts +44 -0
  15. package/dist/src/d1/runtime.d.ts.map +1 -0
  16. package/dist/src/d1/runtime.js +68 -0
  17. package/dist/src/d1/sql.d.ts +37 -0
  18. package/dist/src/d1/sql.d.ts.map +1 -0
  19. package/dist/src/d1/sql.js +261 -0
  20. package/dist/src/d1/types.d.ts +22 -0
  21. package/dist/src/d1/types.d.ts.map +1 -0
  22. package/dist/src/d1/types.js +1 -0
  23. package/dist/src/d1-runtime/index.d.ts +3 -0
  24. package/dist/src/d1-runtime/index.d.ts.map +1 -0
  25. package/dist/src/d1-runtime/index.js +1 -0
  26. package/dist/src/d1-runtime/with-audit.d.ts +77 -0
  27. package/dist/src/d1-runtime/with-audit.d.ts.map +1 -0
  28. package/dist/src/d1-runtime/with-audit.js +130 -0
  29. package/dist/src/index.d.ts +4 -0
  30. package/dist/src/index.d.ts.map +1 -0
  31. package/dist/src/index.js +3 -0
  32. package/dist/src/postgres/audit-log-schema.d.ts +140 -0
  33. package/dist/src/postgres/audit-log-schema.d.ts.map +1 -0
  34. package/dist/src/postgres/audit-log-schema.js +25 -0
  35. package/dist/src/postgres/index.d.ts +6 -0
  36. package/dist/src/postgres/index.d.ts.map +1 -0
  37. package/dist/src/postgres/index.js +3 -0
  38. package/dist/src/postgres/runtime.d.ts +10 -0
  39. package/dist/src/postgres/runtime.d.ts.map +1 -0
  40. package/dist/src/postgres/runtime.js +21 -0
  41. package/dist/src/postgres/sql.d.ts +14 -0
  42. package/dist/src/postgres/sql.d.ts.map +1 -0
  43. package/dist/src/postgres/sql.js +190 -0
  44. package/dist/src/postgres/types.d.ts +22 -0
  45. package/dist/src/postgres/types.d.ts.map +1 -0
  46. package/dist/src/postgres/types.js +1 -0
  47. package/dist/test/d1-runtime.integration.test.d.ts +2 -0
  48. package/dist/test/d1-runtime.integration.test.d.ts.map +1 -0
  49. package/dist/test/d1-runtime.integration.test.js +222 -0
  50. package/dist/test/d1.integration.test.d.ts +2 -0
  51. package/dist/test/d1.integration.test.d.ts.map +1 -0
  52. package/dist/test/d1.integration.test.js +223 -0
  53. package/dist/test/postgres.integration.test.d.ts +2 -0
  54. package/dist/test/postgres.integration.test.d.ts.map +1 -0
  55. package/dist/test/postgres.integration.test.js +286 -0
  56. package/package.json +66 -0
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ # drizzle-audit
2
+
3
+ Automatic audit logging for [Drizzle ORM](https://orm.drizzle.team). Supports Postgres (triggers) and D1/SQLite (triggers or app-level wrapper).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @willyim/drizzle-audit
9
+ ```
10
+
11
+ Peer dependencies: `drizzle-orm`. Optional: `drizzle-kit` (for CLI), `tsx` (for TS config files).
12
+
13
+ ## Quick Start
14
+
15
+ ### Postgres (triggers)
16
+
17
+ ```ts
18
+ import {
19
+ pgAuditLogTable,
20
+ createAuditInstallSql,
21
+ createAttachAuditTriggersSql,
22
+ withAuditedTransaction,
23
+ } from "@willyim/drizzle-audit/postgres"
24
+
25
+ // 1. Add to your Drizzle schema
26
+ export const auditLogs = pgAuditLogTable()
27
+
28
+ // 2. Generate migration SQL
29
+ const migrationSql = [
30
+ createAuditInstallSql(),
31
+ createAttachAuditTriggersSql([
32
+ { table: "users" },
33
+ { table: "invoices", rowIdColumn: "invoice_id" },
34
+ ]),
35
+ ].join("\n\n")
36
+
37
+ // 3. Use in your app
38
+ await withAuditedTransaction(db, currentUser.id, async (tx) => {
39
+ await tx.insert(users).values({ id: "u1", name: "Ada" })
40
+ await tx.update(users).set({ name: "Ada Lovelace" }).where(eq(users.id, "u1"))
41
+ })
42
+ ```
43
+
44
+ Postgres triggers capture full row snapshots (`old_data`/`new_data` as JSONB) automatically.
45
+
46
+ ### D1/SQLite — App-Level Wrapper (recommended)
47
+
48
+ For D1 and SQLite, the `withAudit` wrapper is the simplest approach. No triggers, no context tables — it intercepts operations in your JS code where you already have the user session.
49
+
50
+ ```ts
51
+ import { d1AuditLogTable } from "@willyim/drizzle-audit/d1"
52
+ import { withAudit } from "@willyim/drizzle-audit/d1-runtime"
53
+
54
+ // 1. Add to your schema
55
+ export const auditLogs = d1AuditLogTable()
56
+
57
+ // 2. Create the audit_logs table (in a migration or setup script)
58
+ // CREATE TABLE audit_logs (
59
+ // id INTEGER PRIMARY KEY AUTOINCREMENT,
60
+ // table_name TEXT NOT NULL,
61
+ // operation TEXT NOT NULL,
62
+ // row_id TEXT,
63
+ // user_id TEXT,
64
+ // old_data TEXT,
65
+ // new_data TEXT,
66
+ // created_at TEXT NOT NULL DEFAULT (datetime('now'))
67
+ // );
68
+
69
+ // 3. Use in your app (e.g. React Router action)
70
+ const audit = withAudit(db, auditLogs, { userId: session.userId })
71
+
72
+ audit.insert(users, { id: "u1", name: "Ada" })
73
+ audit.update(users, eq(users.id, "u1"), { name: "Ada Lovelace" })
74
+ audit.delete(users, eq(users.id, "u1"))
75
+
76
+ // Non-audited access is still available
77
+ audit.db.select().from(users).all()
78
+ ```
79
+
80
+ The wrapper auto-detects primary keys from your Drizzle table schema, captures old/new row data, and runs each operation + audit log insert in a transaction.
81
+
82
+ ### D1/SQLite — Triggers
83
+
84
+ If you prefer trigger-based auditing on SQLite (works with D1, better-sqlite3, libsql):
85
+
86
+ ```ts
87
+ import {
88
+ createD1AuditInstallSql,
89
+ createAttachD1AuditTriggersSql,
90
+ d1AuditLogTable,
91
+ d1AuditContextTable,
92
+ withD1AuditedTransaction,
93
+ } from "@willyim/drizzle-audit/d1"
94
+
95
+ // 1. Add to schema
96
+ export const auditLogs = d1AuditLogTable()
97
+ export const auditContext = d1AuditContextTable()
98
+
99
+ // 2. Install (creates audit_logs + _audit_context tables + triggers)
100
+ sqlite.exec(createD1AuditInstallSql())
101
+ sqlite.exec(createAttachD1AuditTriggersSql([
102
+ { table: "users" },
103
+ ]))
104
+
105
+ // 3. Use — context is passed via _audit_context table within a transaction
106
+ withD1AuditedTransaction(db, "user_123", (tx) => {
107
+ tx.insert(users).values({ id: "u1", name: "Ada" }).run()
108
+ })
109
+ ```
110
+
111
+ Since SQLite has no session variables, context (user_id) is stored in a `_audit_context` table that triggers read from within the transaction.
112
+
113
+ For full row snapshots, use the column-aware variant (SQLite can't enumerate columns dynamically):
114
+
115
+ ```ts
116
+ sqlite.exec(createAttachD1AuditTriggersSqlWithColumns([
117
+ { table: "users", columns: ["id", "name", "email"] },
118
+ ]))
119
+ ```
120
+
121
+ ## Workspace / Tenant Scoping
122
+
123
+ All three approaches support an optional workspace column for multi-tenant apps.
124
+
125
+ ### Postgres
126
+
127
+ ```ts
128
+ // Install with workspace column
129
+ createAuditInstallSql({ workspaceIdColumn: "workspace_id" })
130
+ export const auditLogs = pgAuditLogTable({ workspaceIdColumn: "workspace_id" })
131
+
132
+ // Pass workspace at runtime
133
+ await withAuditedTransaction(
134
+ db, userId, async (tx) => { /* ... */ },
135
+ "app.user_id",
136
+ { workspaceId: "ws_1" },
137
+ )
138
+ ```
139
+
140
+ To add workspace to an existing install, use `createAuditAddWorkspaceColumnSql()`.
141
+
142
+ ### D1 Runtime
143
+
144
+ ```ts
145
+ const audit = withAudit(db, auditLogs, {
146
+ userId: "user_1",
147
+ workspaceId: "ws_1",
148
+ })
149
+ ```
150
+
151
+ ### D1 Triggers
152
+
153
+ ```ts
154
+ createD1AuditInstallSql({ workspaceIdColumn: "workspace_id" })
155
+ createAttachD1AuditTriggersSql(
156
+ [{ table: "users" }],
157
+ { workspaceIdColumn: "workspace_id" },
158
+ )
159
+
160
+ withD1AuditedTransaction(db, "user_1", (tx) => { /* ... */ }, {
161
+ workspaceId: "ws_1",
162
+ })
163
+ ```
164
+
165
+ ## CLI
166
+
167
+ Generate a Drizzle migration with audit SQL appended:
168
+
169
+ ```bash
170
+ npx drizzle-audit generate \
171
+ --config app/db/audit.ts \
172
+ --drizzle-config drizzle.config.ts \
173
+ --migrations-dir drizzle
174
+ ```
175
+
176
+ Your config file exports a `createAuditSql()` function:
177
+
178
+ ```ts
179
+ // app/db/audit.ts
180
+ import { createAuditInstallSql, createAttachAuditTriggersSql } from "@willyim/drizzle-audit/postgres"
181
+
182
+ export function createAuditSql() {
183
+ return [
184
+ createAuditInstallSql(),
185
+ createAttachAuditTriggersSql([
186
+ { table: "users" },
187
+ { table: "workspaces" },
188
+ ]),
189
+ ].join("\n\n")
190
+ }
191
+ ```
192
+
193
+ ## API Reference
194
+
195
+ ### `@willyim/drizzle-audit/postgres`
196
+
197
+ | Export | Description |
198
+ |---|---|
199
+ | `pgAuditLogTable(options?)` | Drizzle table definition for `audit_logs` |
200
+ | `createAuditInstallSql(options?)` | SQL to create the audit table, indexes, and trigger function |
201
+ | `createAttachAuditTriggerSql(target, options?)` | SQL to attach audit trigger to one table |
202
+ | `createAttachAuditTriggersSql(targets, options?)` | Same, for multiple tables |
203
+ | `createAuditAddWorkspaceColumnSql(options)` | SQL to add workspace column to existing install |
204
+ | `setAuditContext(db, actorId, contextKey?, options?)` | Set actor context in current transaction |
205
+ | `withAuditedTransaction(db, actorId, callback, contextKey?, options?)` | Transaction wrapper with actor context |
206
+
207
+ ### `@willyim/drizzle-audit/d1`
208
+
209
+ | Export | Description |
210
+ |---|---|
211
+ | `d1AuditLogTable(options?)` | Drizzle SQLite table definition for `audit_logs` |
212
+ | `d1AuditContextTable(options?)` | Drizzle SQLite table definition for `_audit_context` |
213
+ | `createD1AuditInstallSql(options?)` | SQL to create audit + context tables and indexes |
214
+ | `createAttachD1AuditTriggerSql(target, options?)` | SQL for audit triggers (one table) |
215
+ | `createAttachD1AuditTriggersSql(targets, options?)` | Same, for multiple tables |
216
+ | `createAttachD1AuditTriggerSqlWithColumns(target, options?)` | Column-aware triggers with full row snapshots |
217
+ | `createAttachD1AuditTriggersSqlWithColumns(targets, options?)` | Same, for multiple tables |
218
+ | `setD1AuditContext(db, actorId, options?)` | Set actor in `_audit_context` table |
219
+ | `clearD1AuditContext(db, options?)` | Clear actor from `_audit_context` table |
220
+ | `withD1AuditedTransaction(db, actorId, callback, options?)` | Transaction wrapper with context management |
221
+
222
+ ### `@willyim/drizzle-audit/d1-runtime`
223
+
224
+ | Export | Description |
225
+ |---|---|
226
+ | `withAudit(db, auditTable, context)` | App-level audit wrapper (no triggers needed) |
227
+
228
+ `withAudit` returns an object with:
229
+ - `.insert(table, data)` — Insert + audit log
230
+ - `.update(table, where, data)` — Fetch old rows, update, audit log (per row)
231
+ - `.delete(table, where)` — Fetch old rows, delete, audit log (per row)
232
+ - `.db` — Raw Drizzle instance for non-audited operations
233
+
234
+ ## Audit Log Schema
235
+
236
+ ### Postgres
237
+
238
+ ```sql
239
+ CREATE TABLE audit_logs (
240
+ id BIGSERIAL PRIMARY KEY,
241
+ table_name TEXT NOT NULL,
242
+ operation TEXT NOT NULL CHECK (operation IN ('INSERT', 'UPDATE', 'DELETE')),
243
+ row_id TEXT,
244
+ user_id TEXT,
245
+ old_data JSONB,
246
+ new_data JSONB,
247
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now()
248
+ );
249
+ ```
250
+
251
+ ### D1/SQLite
252
+
253
+ ```sql
254
+ CREATE TABLE audit_logs (
255
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
256
+ table_name TEXT NOT NULL,
257
+ operation TEXT NOT NULL CHECK (operation IN ('INSERT', 'UPDATE', 'DELETE')),
258
+ row_id TEXT,
259
+ user_id TEXT,
260
+ old_data TEXT, -- JSON string
261
+ new_data TEXT, -- JSON string
262
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
263
+ );
264
+ ```
265
+
266
+ ## Which Approach Should I Use?
267
+
268
+ | | Postgres Triggers | D1 Runtime (`withAudit`) | D1 Triggers |
269
+ |---|---|---|---|
270
+ | **Setup** | Migration SQL | Create table only | Migration SQL + context table |
271
+ | **Row snapshots** | Automatic (full JSONB) | Automatic (full JSON) | Requires listing columns |
272
+ | **User context** | Native session vars | Available in JS | `_audit_context` table |
273
+ | **Bypass risk** | Low (DB-level) | Medium (must use wrapper) | Low (DB-level) |
274
+ | **Best for** | Postgres apps | D1/Cloudflare Workers | SQLite apps needing DB-level guarantees |
275
+
276
+ ## License
277
+
278
+ MIT
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI: run drizzle-kit generate, then append audit SQL from the consumer's
4
+ * config to the newly created migration file.
5
+ *
6
+ * Usage: drizzle-audit generate [options]
7
+ * Options:
8
+ * --config <path> Path to audit config (TS or JS) exporting createAuditSql/createWebAuditSql
9
+ * --drizzle-config <path> Path to drizzle config for drizzle-kit (default: drizzle.config.ts)
10
+ * --migrations-dir <path> Dir for migrations relative to cwd (default: drizzle)
11
+ * --cwd <path> Working directory (default: process.cwd())
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=generate-migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-migration.d.ts","sourceRoot":"","sources":["../../../src/cli/generate-migration.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * CLI: run drizzle-kit generate, then append audit SQL from the consumer's
4
+ * config to the newly created migration file.
5
+ *
6
+ * Usage: drizzle-audit generate [options]
7
+ * Options:
8
+ * --config <path> Path to audit config (TS or JS) exporting createAuditSql/createWebAuditSql
9
+ * --drizzle-config <path> Path to drizzle config for drizzle-kit (default: drizzle.config.ts)
10
+ * --migrations-dir <path> Dir for migrations relative to cwd (default: drizzle)
11
+ * --cwd <path> Working directory (default: process.cwd())
12
+ */
13
+ import { execSync, spawnSync } from "node:child_process";
14
+ import { readFileSync, readdirSync, writeFileSync } from "node:fs";
15
+ import { resolve } from "node:path";
16
+ import { fileURLToPath, pathToFileURL } from "node:url";
17
+ const DEFAULT_DRIZZLE_CONFIG = "drizzle.config.ts";
18
+ const DEFAULT_MIGRATIONS_DIR = "drizzle";
19
+ function parseArgs() {
20
+ const args = process.argv.slice(2);
21
+ if (args[0] !== "generate") {
22
+ console.error("Usage: drizzle-audit generate --config <path> [options]");
23
+ process.exit(1);
24
+ }
25
+ let config = "";
26
+ let drizzleConfig = DEFAULT_DRIZZLE_CONFIG;
27
+ let migrationsDir = DEFAULT_MIGRATIONS_DIR;
28
+ let cwd = process.cwd();
29
+ for (let i = 1; i < args.length; i++) {
30
+ if (args[i] === "--config" && args[i + 1]) {
31
+ config = args[++i];
32
+ }
33
+ else if (args[i] === "--drizzle-config" && args[i + 1]) {
34
+ drizzleConfig = args[++i];
35
+ }
36
+ else if (args[i] === "--migrations-dir" && args[i + 1]) {
37
+ migrationsDir = args[++i];
38
+ }
39
+ else if (args[i] === "--cwd" && args[i + 1]) {
40
+ cwd = args[++i];
41
+ }
42
+ }
43
+ if (!config) {
44
+ console.error("Missing required --config <path>");
45
+ process.exit(1);
46
+ }
47
+ return { config, drizzleConfig, migrationsDir, cwd };
48
+ }
49
+ function findNewestMigrationDir(migrationsDir) {
50
+ const abs = resolve(migrationsDir);
51
+ const entries = readdirSync(abs, { withFileTypes: true });
52
+ const dirs = entries
53
+ .filter((e) => e.isDirectory())
54
+ .map((e) => e.name)
55
+ .filter((n) => /^\d+_.+/.test(n))
56
+ .sort();
57
+ const newest = dirs[dirs.length - 1];
58
+ if (!newest) {
59
+ throw new Error(`No migration folders found in ${abs}`);
60
+ }
61
+ return resolve(abs, newest);
62
+ }
63
+ async function getAuditSql(configPath, cwd) {
64
+ const resolved = resolve(cwd, configPath);
65
+ const ext = resolved.endsWith(".ts")
66
+ ? ".ts"
67
+ : resolved.endsWith(".mts")
68
+ ? ".mts"
69
+ : "";
70
+ if (ext) {
71
+ try {
72
+ const __dirname = fileURLToPath(new URL(".", import.meta.url));
73
+ const runnerPath = resolve(__dirname, "runner.js");
74
+ const out = execSync(`node --experimental-strip-types "${runnerPath}" "${resolved}"`, { cwd, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
75
+ return out.trim();
76
+ }
77
+ catch (e) {
78
+ const err = e;
79
+ console.error("Failed to load .ts config. Requires Node >= 22.6.0.");
80
+ console.error(err.stderr ?? err.message);
81
+ process.exit(1);
82
+ }
83
+ }
84
+ const url = pathToFileURL(resolved).href;
85
+ const mod = await import(url);
86
+ const fn = mod.createAuditSql ?? mod.createWebAuditSql;
87
+ if (typeof fn !== "function") {
88
+ console.error("Config module must export createAuditSql() or createWebAuditSql()");
89
+ process.exit(1);
90
+ }
91
+ return String(fn()).trim();
92
+ }
93
+ async function main() {
94
+ const { config, drizzleConfig, migrationsDir, cwd } = parseArgs();
95
+ const drizzleConfigPath = resolve(cwd, drizzleConfig);
96
+ const migrationsAbs = resolve(cwd, migrationsDir);
97
+ console.log("Running drizzle-kit generate...");
98
+ const kit = spawnSync("npx", ["drizzle-kit", "generate", "--config", drizzleConfigPath], {
99
+ cwd,
100
+ stdio: ["pipe", "inherit", "inherit"],
101
+ input: "\n\n",
102
+ encoding: "utf-8",
103
+ });
104
+ if (kit.status !== 0) {
105
+ process.exit(kit.status ?? 1);
106
+ }
107
+ const migrationDir = findNewestMigrationDir(migrationsAbs);
108
+ const migrationFile = resolve(migrationDir, "migration.sql");
109
+ const existing = readFileSync(migrationFile, "utf-8");
110
+ const auditSql = await getAuditSql(config, cwd);
111
+ const separator = "\n\n";
112
+ writeFileSync(migrationFile, existing + separator + "-- drizzle-audit\n\n" + auditSql, "utf-8");
113
+ console.log("Appended audit SQL to", migrationFile);
114
+ }
115
+ main().catch((e) => {
116
+ console.error(e);
117
+ process.exit(1);
118
+ });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=runner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../src/cli/runner.ts"],"names":[],"mappings":"AAyBA,OAAO,EAAE,CAAA"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Runner script used to load a consumer's audit config (TS or JS) and print the
3
+ * generated SQL to stdout. Invoked with: node --experimental-strip-types runner.js <config-path>
4
+ * Config module must export createAuditSql() or createWebAuditSql().
5
+ */
6
+ const configPath = process.argv[2];
7
+ if (!configPath) {
8
+ process.stderr.write("Usage: runner.js <config-path>\n");
9
+ process.exit(1);
10
+ }
11
+ const path = await import("node:path");
12
+ const { pathToFileURL } = await import("node:url");
13
+ const resolved = path.resolve(process.cwd(), configPath);
14
+ const url = pathToFileURL(resolved).href;
15
+ const mod = await import(url);
16
+ const fn = mod.createAuditSql ?? mod.createWebAuditSql;
17
+ if (typeof fn !== "function") {
18
+ process.stderr.write("Config module must export createAuditSql() or createWebAuditSql()\n");
19
+ process.exit(1);
20
+ }
21
+ const sql = String(fn());
22
+ process.stdout.write(sql);
23
+ export {};
@@ -0,0 +1,181 @@
1
+ export type D1AuditLogTableOptions = {
2
+ /** When set (e.g. "workspace_id"), the table definition includes this optional column. */
3
+ workspaceIdColumn?: string;
4
+ };
5
+ export declare function d1AuditLogTable(options?: D1AuditLogTableOptions): import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
6
+ name: "audit_logs";
7
+ schema: undefined;
8
+ columns: {
9
+ old_data: import("drizzle-orm/sqlite-core").SQLiteColumn<{
10
+ name: string;
11
+ tableName: "audit_logs";
12
+ dataType: "string";
13
+ data: string;
14
+ driverParam: string;
15
+ notNull: false;
16
+ hasDefault: false;
17
+ isPrimaryKey: false;
18
+ isAutoincrement: false;
19
+ hasRuntimeDefault: false;
20
+ enumValues: [string, ...string[]];
21
+ baseColumn: never;
22
+ identity: undefined;
23
+ generated: undefined;
24
+ }, {}>;
25
+ new_data: import("drizzle-orm/sqlite-core").SQLiteColumn<{
26
+ name: string;
27
+ tableName: "audit_logs";
28
+ dataType: "string";
29
+ data: string;
30
+ driverParam: string;
31
+ notNull: false;
32
+ hasDefault: false;
33
+ isPrimaryKey: false;
34
+ isAutoincrement: false;
35
+ hasRuntimeDefault: false;
36
+ enumValues: [string, ...string[]];
37
+ baseColumn: never;
38
+ identity: undefined;
39
+ generated: undefined;
40
+ }, {}>;
41
+ created_at: import("drizzle-orm/sqlite-core").SQLiteColumn<{
42
+ name: string;
43
+ tableName: "audit_logs";
44
+ dataType: "string";
45
+ data: string;
46
+ driverParam: string;
47
+ notNull: true;
48
+ hasDefault: true;
49
+ isPrimaryKey: false;
50
+ isAutoincrement: false;
51
+ hasRuntimeDefault: false;
52
+ enumValues: [string, ...string[]];
53
+ baseColumn: never;
54
+ identity: undefined;
55
+ generated: undefined;
56
+ }, {}>;
57
+ id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
58
+ name: string;
59
+ tableName: "audit_logs";
60
+ dataType: "number int53";
61
+ data: number;
62
+ driverParam: number;
63
+ notNull: true;
64
+ hasDefault: true;
65
+ isPrimaryKey: true;
66
+ isAutoincrement: false;
67
+ hasRuntimeDefault: false;
68
+ enumValues: undefined;
69
+ baseColumn: never;
70
+ identity: undefined;
71
+ generated: undefined;
72
+ }, {}>;
73
+ table_name: import("drizzle-orm/sqlite-core").SQLiteColumn<{
74
+ name: string;
75
+ tableName: "audit_logs";
76
+ dataType: "string";
77
+ data: string;
78
+ driverParam: string;
79
+ notNull: true;
80
+ hasDefault: false;
81
+ isPrimaryKey: false;
82
+ isAutoincrement: false;
83
+ hasRuntimeDefault: false;
84
+ enumValues: [string, ...string[]];
85
+ baseColumn: never;
86
+ identity: undefined;
87
+ generated: undefined;
88
+ }, {}>;
89
+ operation: import("drizzle-orm/sqlite-core").SQLiteColumn<{
90
+ name: string;
91
+ tableName: "audit_logs";
92
+ dataType: "string";
93
+ data: string;
94
+ driverParam: string;
95
+ notNull: true;
96
+ hasDefault: false;
97
+ isPrimaryKey: false;
98
+ isAutoincrement: false;
99
+ hasRuntimeDefault: false;
100
+ enumValues: [string, ...string[]];
101
+ baseColumn: never;
102
+ identity: undefined;
103
+ generated: undefined;
104
+ }, {}>;
105
+ row_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
106
+ name: string;
107
+ tableName: "audit_logs";
108
+ dataType: "string";
109
+ data: string;
110
+ driverParam: string;
111
+ notNull: false;
112
+ hasDefault: false;
113
+ isPrimaryKey: false;
114
+ isAutoincrement: false;
115
+ hasRuntimeDefault: false;
116
+ enumValues: [string, ...string[]];
117
+ baseColumn: never;
118
+ identity: undefined;
119
+ generated: undefined;
120
+ }, {}>;
121
+ user_id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
122
+ name: string;
123
+ tableName: "audit_logs";
124
+ dataType: "string";
125
+ data: string;
126
+ driverParam: string;
127
+ notNull: false;
128
+ hasDefault: false;
129
+ isPrimaryKey: false;
130
+ isAutoincrement: false;
131
+ hasRuntimeDefault: false;
132
+ enumValues: [string, ...string[]];
133
+ baseColumn: never;
134
+ identity: undefined;
135
+ generated: undefined;
136
+ }, {}>;
137
+ };
138
+ dialect: "sqlite";
139
+ }>;
140
+ export declare function d1AuditContextTable(options?: {
141
+ contextTable?: string;
142
+ }): import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
143
+ name: string;
144
+ schema: undefined;
145
+ columns: {
146
+ key: import("drizzle-orm/sqlite-core").SQLiteColumn<{
147
+ name: string;
148
+ tableName: string;
149
+ dataType: "string";
150
+ data: string;
151
+ driverParam: string;
152
+ notNull: true;
153
+ hasDefault: false;
154
+ isPrimaryKey: true;
155
+ isAutoincrement: false;
156
+ hasRuntimeDefault: false;
157
+ enumValues: [string, ...string[]];
158
+ baseColumn: never;
159
+ identity: undefined;
160
+ generated: undefined;
161
+ }, {}>;
162
+ value: import("drizzle-orm/sqlite-core").SQLiteColumn<{
163
+ name: string;
164
+ tableName: string;
165
+ dataType: "string";
166
+ data: string;
167
+ driverParam: string;
168
+ notNull: false;
169
+ hasDefault: false;
170
+ isPrimaryKey: false;
171
+ isAutoincrement: false;
172
+ hasRuntimeDefault: false;
173
+ enumValues: [string, ...string[]];
174
+ baseColumn: never;
175
+ identity: undefined;
176
+ generated: undefined;
177
+ }, {}>;
178
+ };
179
+ dialect: "sqlite";
180
+ }>;
181
+ //# sourceMappingURL=audit-log-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-log-schema.d.ts","sourceRoot":"","sources":["../../../src/d1/audit-log-schema.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,sBAAsB,GAAG;IACnC,0FAA0F;IAC1F,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyB/D;AAED,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAMtE"}
@@ -0,0 +1,30 @@
1
+ import { index, integer, sqliteTable, text, } from "drizzle-orm/sqlite-core";
2
+ export function d1AuditLogTable(options) {
3
+ const workspaceIdColumn = options?.workspaceIdColumn?.trim();
4
+ const columns = {
5
+ id: integer("id").primaryKey({ autoIncrement: true }),
6
+ table_name: text("table_name").notNull(),
7
+ operation: text("operation").notNull(),
8
+ row_id: text("row_id"),
9
+ user_id: text("user_id"),
10
+ ...(workspaceIdColumn
11
+ ? { [workspaceIdColumn]: text(workspaceIdColumn) }
12
+ : {}),
13
+ old_data: text("old_data"),
14
+ new_data: text("new_data"),
15
+ created_at: text("created_at").notNull().default("(datetime('now'))"),
16
+ };
17
+ return sqliteTable("audit_logs", columns, (table) => [
18
+ index("audit_logs_table_name_idx").on(table.table_name),
19
+ index("audit_logs_row_id_idx").on(table.row_id),
20
+ index("audit_logs_user_id_idx").on(table.user_id),
21
+ index("audit_logs_created_at_idx").on(table.created_at),
22
+ ]);
23
+ }
24
+ export function d1AuditContextTable(options) {
25
+ const tableName = options?.contextTable ?? "_audit_context";
26
+ return sqliteTable(tableName, {
27
+ key: text("key").primaryKey(),
28
+ value: text("value"),
29
+ });
30
+ }
@@ -0,0 +1,7 @@
1
+ export { d1AuditLogTable, d1AuditContextTable } from "./audit-log-schema.js";
2
+ export type { D1AuditLogTableOptions } from "./audit-log-schema.js";
3
+ export { createAttachD1AuditTriggerSql, createAttachD1AuditTriggersSql, createAttachD1AuditTriggerSqlWithColumns, createAttachD1AuditTriggersSqlWithColumns, createD1AuditInstallSql, } from "./sql.js";
4
+ export type { D1AuditTriggerTargetWithColumns } from "./sql.js";
5
+ export { clearD1AuditContext, setD1AuditContext, withD1AuditedTransaction, } from "./runtime.js";
6
+ export type { D1AuditInstallOptions, D1AuditSqlExecutor, D1AuditTriggerTarget, } from "./types.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/d1/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AACnE,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,wCAAwC,EACxC,yCAAyC,EACzC,uBAAuB,GACxB,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,YAAY,CAAA"}
@@ -0,0 +1,3 @@
1
+ export { d1AuditLogTable, d1AuditContextTable } from "./audit-log-schema.js";
2
+ export { createAttachD1AuditTriggerSql, createAttachD1AuditTriggersSql, createAttachD1AuditTriggerSqlWithColumns, createAttachD1AuditTriggersSqlWithColumns, createD1AuditInstallSql, } from "./sql.js";
3
+ export { clearD1AuditContext, setD1AuditContext, withD1AuditedTransaction, } from "./runtime.js";