import { afterAll, beforeAll, expect, test } from 'vitest' import pgMeta, { safeSql } from '../src/index' import { cleanupRoot, createTestDatabase } from './db/utils' beforeAll(async () => { // Any global setup if needed }) afterAll(async () => { await cleanupRoot() }) const withTestDatabase = ( name: string, fn: (db: Awaited>) => Promise ) => { test(name, async () => { const db = await createTestDatabase() try { await fn(db) } finally { await db.cleanup() } }) } withTestDatabase('retrieve, create, update, delete', async ({ executeQuery }) => { // Create trigger const { sql: createSql } = pgMeta.triggers.create({ name: 'test_trigger', schema: 'public', table: 'users_audit', function_schema: 'public', function_name: 'audit_action', function_args: ['test1', 'test2'], activation: 'AFTER', events: ['UPDATE'], orientation: 'ROW', condition: safeSql`(old.* IS DISTINCT FROM new.*)`, }) await executeQuery(createSql) const { sql: listTriggers, zod: listZod } = pgMeta.triggers.list() const listedTriggers = await listZod.parse(await executeQuery(listTriggers)) const createdTriggers = listedTriggers.find( (t) => t.name === 'test_trigger' && t.table === 'users_audit' && t.schema === 'public' ) expect(createdTriggers!).toMatchInlineSnapshot( { id: expect.any(Number), table_id: expect.any(Number) }, ` { "activation": "AFTER", "condition": "(old.* IS DISTINCT FROM new.*)", "enabled_mode": "ORIGIN", "events": [ "UPDATE", ], "function_args": [ "test1", "test2", ], "function_name": "audit_action", "function_schema": "public", "id": Any, "name": "test_trigger", "orientation": "ROW", "schema": "public", "table": "users_audit", "table_id": Any, } ` ) // Retrieve created trigger by name const { sql: retrieveSqlByName, zod: retrieveZod } = pgMeta.triggers.retrieve({ name: 'test_trigger', table: 'users_audit', schema: 'public', }) const trigger = retrieveZod.parse((await executeQuery(retrieveSqlByName))[0]) expect(trigger!).toMatchInlineSnapshot( { id: expect.any(Number), table_id: expect.any(Number) }, ` { "activation": "AFTER", "condition": "(old.* IS DISTINCT FROM new.*)", "enabled_mode": "ORIGIN", "events": [ "UPDATE", ], "function_args": [ "test1", "test2", ], "function_name": "audit_action", "function_schema": "public", "id": Any, "name": "test_trigger", "orientation": "ROW", "schema": "public", "table": "users_audit", "table_id": Any, } ` ) // Retrieve created trigger by id const { sql: retrieveSqlById } = pgMeta.triggers.retrieve({ id: trigger!.id, }) const triggerById = retrieveZod.parse((await executeQuery(retrieveSqlById))[0]) expect(triggerById!).toMatchInlineSnapshot( { id: expect.any(Number), table_id: expect.any(Number) }, ` { "activation": "AFTER", "condition": "(old.* IS DISTINCT FROM new.*)", "enabled_mode": "ORIGIN", "events": [ "UPDATE", ], "function_args": [ "test1", "test2", ], "function_name": "audit_action", "function_schema": "public", "id": Any, "name": "test_trigger", "orientation": "ROW", "schema": "public", "table": "users_audit", "table_id": Any, } ` ) // Update trigger const { sql: updateSql } = pgMeta.triggers.update(trigger!, { name: 'test_trigger_renamed', enabled_mode: 'DISABLED', }) await executeQuery(updateSql) // Verify update const { sql: retrieveUpdatedSql } = pgMeta.triggers.retrieve({ id: trigger!.id, }) const updatedTrigger = retrieveZod.parse((await executeQuery(retrieveUpdatedSql))[0]) expect(updatedTrigger).toMatchInlineSnapshot( { id: expect.any(Number), table_id: expect.any(Number) }, ` { "activation": "AFTER", "condition": "(old.* IS DISTINCT FROM new.*)", "enabled_mode": "DISABLED", "events": [ "UPDATE", ], "function_args": [ "test1", "test2", ], "function_name": "audit_action", "function_schema": "public", "id": Any, "name": "test_trigger_renamed", "orientation": "ROW", "schema": "public", "table": "users_audit", "table_id": Any, } ` ) // Update trigger again const { sql: updateSql2 } = pgMeta.triggers.update(updatedTrigger!, { enabled_mode: 'REPLICA', }) await executeQuery(updateSql2) // Verify second update const { sql: retrieveUpdated2Sql } = pgMeta.triggers.retrieve({ name: 'test_trigger_renamed', table: 'users_audit', schema: 'public', }) const updatedTrigger2 = retrieveZod.parse((await executeQuery(retrieveUpdated2Sql))[0]) expect(updatedTrigger2).toMatchObject({ enabled_mode: 'REPLICA', }) // Remove trigger const { sql: removeSql } = pgMeta.triggers.remove(updatedTrigger2!) await executeQuery(removeSql) // Verify removal const { sql: verifyRemoveSql } = pgMeta.triggers.retrieve({ name: 'test_trigger_renamed', table: 'users_audit', schema: 'public', }) const result = retrieveZod.parse((await executeQuery(verifyRemoveSql))[0]) expect(result).toBeUndefined() }) withTestDatabase('multi event', async ({ executeQuery }) => { // Create trigger const { sql: createSql } = pgMeta.triggers.create({ name: 'test_multi_event_trigger', schema: 'public', table: 'users_audit', function_schema: 'public', function_name: 'audit_action', function_args: ['test1', 'test2'], activation: 'AFTER', events: ['insert', 'update', 'delete'], orientation: 'ROW', }) await executeQuery(createSql) // Verify created trigger const { sql: retrieveSql, zod: retrieveZod } = pgMeta.triggers.retrieve({ name: 'test_multi_event_trigger', table: 'users_audit', schema: 'public', }) const trigger = retrieveZod.parse((await executeQuery(retrieveSql))[0]) expect(trigger).toMatchInlineSnapshot( { id: expect.any(Number), table_id: expect.any(Number) }, ` { "activation": "AFTER", "condition": null, "enabled_mode": "ORIGIN", "events": [ "INSERT", "DELETE", "UPDATE", ], "function_args": [ "test1", "test2", ], "function_name": "audit_action", "function_schema": "public", "id": Any, "name": "test_multi_event_trigger", "orientation": "ROW", "schema": "public", "table": "users_audit", "table_id": Any, } ` ) // Remove trigger const { sql: removeSql } = pgMeta.triggers.remove(trigger!) await executeQuery(removeSql) // Verify removal const { sql: verifyRemoveSql } = pgMeta.triggers.retrieve({ name: 'test_multi_event_trigger', table: 'users_audit', schema: 'public', }) const result = retrieveZod.parse((await executeQuery(verifyRemoveSql))[0]) expect(result).toBeUndefined() }) withTestDatabase('triggers with the same name on different schemas', async ({ executeQuery }) => { // Create test schemas and triggers await executeQuery(` create function tr_f() returns trigger language plpgsql as 'begin end'; create schema s1; create table s1.t(); create trigger tr before insert on s1.t execute function tr_f(); create schema s2; create table s2.t(); create trigger tr before insert on s2.t execute function tr_f(); `) // List and verify triggers const { sql: listSql, zod: listZod } = pgMeta.triggers.list() const triggers = listZod.parse(await executeQuery(listSql)) expect(triggers.map(({ id, table_id, ...trigger }) => trigger)).toMatchInlineSnapshot(` [ { "activation": "BEFORE", "condition": null, "enabled_mode": "ORIGIN", "events": [ "INSERT", ], "function_args": [], "function_name": "tr_f", "function_schema": "public", "name": "tr", "orientation": "STATEMENT", "schema": "s1", "table": "t", }, { "activation": "BEFORE", "condition": null, "enabled_mode": "ORIGIN", "events": [ "INSERT", ], "function_args": [], "function_name": "tr_f", "function_schema": "public", "name": "tr", "orientation": "STATEMENT", "schema": "s2", "table": "t", }, ] `) }) withTestDatabase('triggers on capitalized schema and table names', async ({ executeQuery }) => { // Create test schema and trigger await executeQuery(` CREATE SCHEMA "MySchema"; CREATE TABLE "MySchema"."MyTable" ( id SERIAL PRIMARY KEY, name TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP ); CREATE OR REPLACE FUNCTION "MySchema"."my_trigger_function"() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at := CURRENT_TIMESTAMP; RETURN NEW; END; $$ LANGUAGE plpgsql; CREATE TRIGGER "my_trigger" BEFORE INSERT ON "MySchema"."MyTable" FOR EACH ROW EXECUTE FUNCTION "MySchema"."my_trigger_function"(); `) // List and verify triggers const { sql: listSql, zod: listZod } = pgMeta.triggers.list() const triggers = listZod.parse(await executeQuery(listSql)) expect(triggers.map(({ id, table_id, ...trigger }) => trigger)).toMatchInlineSnapshot(` [ { "activation": "BEFORE", "condition": null, "enabled_mode": "ORIGIN", "events": [ "INSERT", ], "function_args": [], "function_name": "my_trigger_function", "function_schema": "MySchema", "name": "my_trigger", "orientation": "ROW", "schema": "MySchema", "table": "MyTable", }, ] `) })