dzql 0.6.2 → 0.6.5
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/README.md +33 -0
- package/docs/for_ai.md +14 -18
- package/docs/project-setup.md +15 -14
- package/package.json +28 -6
- package/src/cli/codegen/client.ts +5 -6
- package/src/cli/codegen/subscribable_sql.ts +64 -3
- package/src/cli/codegen/subscribable_store.ts +5 -5
- package/src/runtime/ws.ts +18 -15
- package/.env.sample +0 -28
- package/compose.yml +0 -28
- package/examples/blog.ts +0 -50
- package/examples/invalid.ts +0 -18
- package/examples/venues.js +0 -485
- package/tests/client.test.ts +0 -38
- package/tests/codegen.test.ts +0 -71
- package/tests/compiler.test.ts +0 -45
- package/tests/graph_rules.test.ts +0 -173
- package/tests/integration/db.test.ts +0 -174
- package/tests/integration/e2e.test.ts +0 -65
- package/tests/integration/features.test.ts +0 -922
- package/tests/integration/full_stack.test.ts +0 -262
- package/tests/integration/setup.ts +0 -45
- package/tests/ir.test.ts +0 -32
- package/tests/namespace.test.ts +0 -395
- package/tests/permissions.test.ts +0 -55
- package/tests/pinia.test.ts +0 -48
- package/tests/realtime.test.ts +0 -22
- package/tests/runtime.test.ts +0 -80
- package/tests/subscribable_gen.test.ts +0 -72
- package/tests/subscribable_reactivity.test.ts +0 -258
- package/tests/venues_gen.test.ts +0 -25
- package/tsconfig.json +0 -20
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect } from "bun:test";
|
|
2
|
-
import { compileGraphRules } from "../src/cli/compiler/graph_rules.js";
|
|
3
|
-
import type { GraphRuleIR } from "../src/shared/ir.js";
|
|
4
|
-
|
|
5
|
-
// Mock entity graph rules in IR format
|
|
6
|
-
const mockGraphRules = {
|
|
7
|
-
onCreate: [
|
|
8
|
-
{
|
|
9
|
-
trigger: 'create' as const,
|
|
10
|
-
action: 'reactor' as const,
|
|
11
|
-
target: 'notify_subscribers',
|
|
12
|
-
params: { post_id: '@id' }
|
|
13
|
-
}
|
|
14
|
-
] as GraphRuleIR[],
|
|
15
|
-
onDelete: [
|
|
16
|
-
{
|
|
17
|
-
trigger: 'delete' as const,
|
|
18
|
-
action: 'delete' as const,
|
|
19
|
-
target: 'comments',
|
|
20
|
-
params: { post_id: '@id' }
|
|
21
|
-
}
|
|
22
|
-
] as GraphRuleIR[]
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
describe("Graph Rules Compiler", () => {
|
|
26
|
-
|
|
27
|
-
test("should compile reactor to event insertion", () => {
|
|
28
|
-
// Should insert into dzql_v2.events with op='reactor:notify_subscribers'
|
|
29
|
-
const sql = compileGraphRules('posts', 'create', mockGraphRules.onCreate);
|
|
30
|
-
|
|
31
|
-
expect(sql).toContain("INSERT INTO dzql_v2.events");
|
|
32
|
-
expect(sql).toContain("'reactor:notify_subscribers'");
|
|
33
|
-
// Simply check for the variable resolution logic
|
|
34
|
-
expect(sql).toContain("v_result->>'id'");
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test("should compile delete action to SQL delete", () => {
|
|
38
|
-
// Should generate DELETE FROM comments ...
|
|
39
|
-
const sql = compileGraphRules('posts', 'delete', mockGraphRules.onDelete);
|
|
40
|
-
|
|
41
|
-
expect(sql).toContain("DELETE FROM comments");
|
|
42
|
-
expect(sql).toContain("post_id = (v_old_data->>'id')::int"); // Variable resolution from old record
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("should compile create action with field defaults", () => {
|
|
46
|
-
const rules: GraphRuleIR[] = [{
|
|
47
|
-
trigger: 'create',
|
|
48
|
-
action: 'create',
|
|
49
|
-
target: 'memberships',
|
|
50
|
-
params: { user_id: '@user_id', org_id: '@id', valid_from: '@today' }
|
|
51
|
-
}];
|
|
52
|
-
|
|
53
|
-
const sql = compileGraphRules('organisations', 'create', rules);
|
|
54
|
-
|
|
55
|
-
expect(sql).toContain("INSERT INTO memberships");
|
|
56
|
-
expect(sql).toContain("user_id, org_id, valid_from");
|
|
57
|
-
expect(sql).toContain("p_user_id");
|
|
58
|
-
expect(sql).toContain("(v_result->>'id')::int");
|
|
59
|
-
expect(sql).toContain("CURRENT_DATE");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("should compile update action with match clause", () => {
|
|
63
|
-
const rules: GraphRuleIR[] = [{
|
|
64
|
-
trigger: 'update',
|
|
65
|
-
action: 'update',
|
|
66
|
-
target: 'audit_log',
|
|
67
|
-
params: { last_modified: '@now' },
|
|
68
|
-
match: { entity_id: '@id' }
|
|
69
|
-
}];
|
|
70
|
-
|
|
71
|
-
const sql = compileGraphRules('posts', 'update', rules);
|
|
72
|
-
|
|
73
|
-
expect(sql).toContain("UPDATE audit_log");
|
|
74
|
-
expect(sql).toContain("SET last_modified = NOW()");
|
|
75
|
-
expect(sql).toContain("WHERE entity_id = (v_result->>'id')::int");
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test("should compile validate action", () => {
|
|
79
|
-
const rules: GraphRuleIR[] = [{
|
|
80
|
-
trigger: 'create',
|
|
81
|
-
action: 'validate',
|
|
82
|
-
target: 'check_quota',
|
|
83
|
-
params: { user_id: '@user_id' },
|
|
84
|
-
error_message: 'Quota exceeded'
|
|
85
|
-
}];
|
|
86
|
-
|
|
87
|
-
const sql = compileGraphRules('posts', 'create', rules);
|
|
88
|
-
|
|
89
|
-
expect(sql).toContain("IF NOT check_quota(");
|
|
90
|
-
expect(sql).toContain("user_id => p_user_id");
|
|
91
|
-
expect(sql).toContain("RAISE EXCEPTION 'Quota exceeded'");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test("should compile execute action", () => {
|
|
95
|
-
const rules: GraphRuleIR[] = [{
|
|
96
|
-
trigger: 'create',
|
|
97
|
-
action: 'execute',
|
|
98
|
-
target: 'send_notification',
|
|
99
|
-
params: { post_id: '@id', author_id: '@author_id' }
|
|
100
|
-
}];
|
|
101
|
-
|
|
102
|
-
const sql = compileGraphRules('posts', 'create', rules);
|
|
103
|
-
|
|
104
|
-
expect(sql).toContain("PERFORM send_notification(");
|
|
105
|
-
expect(sql).toContain("post_id => (v_result->>'id')");
|
|
106
|
-
expect(sql).toContain("author_id => (v_result->>'author_id')");
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test("should compile conditional rule with @before/@after", () => {
|
|
110
|
-
const rules: GraphRuleIR[] = [{
|
|
111
|
-
trigger: 'update',
|
|
112
|
-
action: 'reactor',
|
|
113
|
-
target: 'status_changed',
|
|
114
|
-
condition: "@before.status = 'draft' AND @after.status = 'published'",
|
|
115
|
-
params: { post_id: '@id' }
|
|
116
|
-
}];
|
|
117
|
-
|
|
118
|
-
const sql = compileGraphRules('posts', 'update', rules);
|
|
119
|
-
|
|
120
|
-
expect(sql).toContain("-- Condition:");
|
|
121
|
-
expect(sql).toContain("IF (v_old_data->>'status') = 'draft' AND (v_result->>'status') = 'published' THEN");
|
|
122
|
-
expect(sql).toContain("INSERT INTO dzql_v2.events");
|
|
123
|
-
expect(sql).toContain("END IF;");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test("should resolve @before variables in delete trigger", () => {
|
|
127
|
-
const rules: GraphRuleIR[] = [{
|
|
128
|
-
trigger: 'delete',
|
|
129
|
-
action: 'execute',
|
|
130
|
-
target: 'archive_post',
|
|
131
|
-
params: { title: '@before.title', author_id: '@before.author_id' }
|
|
132
|
-
}];
|
|
133
|
-
|
|
134
|
-
const sql = compileGraphRules('posts', 'delete', rules);
|
|
135
|
-
|
|
136
|
-
expect(sql).toContain("PERFORM archive_post(");
|
|
137
|
-
expect(sql).toContain("title => (v_old_data->>'title')");
|
|
138
|
-
// Note: execute/validate params don't get ::int cast - they're named parameters
|
|
139
|
-
expect(sql).toContain("author_id => (v_old_data->>'author_id')");
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
test("should handle multiple actions", () => {
|
|
143
|
-
const rules: GraphRuleIR[] = [
|
|
144
|
-
{
|
|
145
|
-
trigger: 'create',
|
|
146
|
-
action: 'validate',
|
|
147
|
-
target: 'check_permissions',
|
|
148
|
-
params: { user_id: '@user_id' },
|
|
149
|
-
error_message: 'Not allowed'
|
|
150
|
-
},
|
|
151
|
-
{
|
|
152
|
-
trigger: 'create',
|
|
153
|
-
action: 'create',
|
|
154
|
-
target: 'audit_log',
|
|
155
|
-
params: { entity_id: '@id', action: 'created' }
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
trigger: 'create',
|
|
159
|
-
action: 'reactor',
|
|
160
|
-
target: 'notify_admins',
|
|
161
|
-
params: { post_id: '@id' }
|
|
162
|
-
}
|
|
163
|
-
];
|
|
164
|
-
|
|
165
|
-
const sql = compileGraphRules('posts', 'create', rules);
|
|
166
|
-
|
|
167
|
-
// Should have all three actions
|
|
168
|
-
expect(sql).toContain("IF NOT check_permissions");
|
|
169
|
-
expect(sql).toContain("INSERT INTO audit_log");
|
|
170
|
-
expect(sql).toContain("reactor:notify_admins");
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
});
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeAll, afterAll } from "bun:test";
|
|
2
|
-
import { V2TestDatabase } from "./setup.js";
|
|
3
|
-
import { generateCoreSQL, generateEntitySQL, generateSchemaSQL } from "../../src/cli/codegen/sql.js";
|
|
4
|
-
import { generateIR } from "../../src/cli/compiler/ir.js";
|
|
5
|
-
import { entities } from "../../examples/blog.js";
|
|
6
|
-
|
|
7
|
-
const blogDomain = { entities, subscribables: {} };
|
|
8
|
-
|
|
9
|
-
describe("V2 Database Integration (Real Postgres)", () => {
|
|
10
|
-
let db: V2TestDatabase;
|
|
11
|
-
let sql: any;
|
|
12
|
-
|
|
13
|
-
beforeAll(async () => {
|
|
14
|
-
db = new V2TestDatabase();
|
|
15
|
-
// This connects to localhost:5433 by default (from setup.ts)
|
|
16
|
-
sql = await db.setup();
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
// 1. Generate SQL
|
|
20
|
-
const ir = generateIR(blogDomain);
|
|
21
|
-
const coreSQL = generateCoreSQL();
|
|
22
|
-
const postsSchema = generateSchemaSQL("posts", ir.entities.posts);
|
|
23
|
-
const commentsSchema = generateSchemaSQL("comments", ir.entities.comments);
|
|
24
|
-
const postsSQL = generateEntitySQL("posts", ir.entities.posts);
|
|
25
|
-
const commentsSQL = generateEntitySQL("comments", ir.entities.comments);
|
|
26
|
-
|
|
27
|
-
// 2. Apply SQL to the real DB
|
|
28
|
-
await db.applySQL(coreSQL);
|
|
29
|
-
await db.applySQL(postsSchema);
|
|
30
|
-
await db.applySQL(commentsSchema);
|
|
31
|
-
await db.applySQL(postsSQL);
|
|
32
|
-
await db.applySQL(commentsSQL);
|
|
33
|
-
} catch (e) {
|
|
34
|
-
console.error("Setup failed:", e);
|
|
35
|
-
throw e;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
afterAll(async () => {
|
|
40
|
-
await db.teardown();
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
test("should save a post via compiled function (Atomic Upsert)", async () => {
|
|
44
|
-
const userId = 1;
|
|
45
|
-
const postData = { id: 1, title: "Real DB Test", content: "It works!", author_id: 1 };
|
|
46
|
-
|
|
47
|
-
// Call the compiled PL/pgSQL function
|
|
48
|
-
const result = await sql`
|
|
49
|
-
SELECT dzql_v2.save_posts(${userId}, ${sql.json(postData)}) as data
|
|
50
|
-
`;
|
|
51
|
-
|
|
52
|
-
const saved = result[0].data;
|
|
53
|
-
expect(saved.id).toBe(1);
|
|
54
|
-
expect(saved.title).toBe("Real DB Test");
|
|
55
|
-
|
|
56
|
-
// Verify persistence
|
|
57
|
-
const rows = await sql`SELECT * FROM posts WHERE id = 1`;
|
|
58
|
-
expect(rows.length).toBe(1);
|
|
59
|
-
expect(rows[0].title).toBe("Real DB Test");
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("should enforce permissions (Inlined SQL)", async () => {
|
|
63
|
-
const hackerId = 2;
|
|
64
|
-
const postData = { id: 2, title: "Hacked", content: "Bad", author_id: 1 };
|
|
65
|
-
|
|
66
|
-
// Should fail because @author_id (1) != @user_id (2)
|
|
67
|
-
try {
|
|
68
|
-
await sql`
|
|
69
|
-
SELECT dzql_v2.save_posts(${hackerId}, ${sql.json(postData)})
|
|
70
|
-
`;
|
|
71
|
-
expect(true).toBe(false); // Should not fail
|
|
72
|
-
} catch (e: any) {
|
|
73
|
-
expect(e.message).toContain("permission_denied");
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test("should emit normalized row events (Commit Batching)", async () => {
|
|
78
|
-
// We expect the 'insert' from the first test to be in the events table
|
|
79
|
-
const events = await sql`
|
|
80
|
-
SELECT * FROM dzql_v2.events
|
|
81
|
-
WHERE table_name = 'posts'
|
|
82
|
-
ORDER BY id DESC LIMIT 1
|
|
83
|
-
`;
|
|
84
|
-
|
|
85
|
-
expect(events.length).toBe(1);
|
|
86
|
-
expect(events[0].op).toBe("insert");
|
|
87
|
-
expect(events[0].data.title).toBe("Real DB Test");
|
|
88
|
-
expect(events[0].old_data).toBeNull(); // Insert has no old data
|
|
89
|
-
expect(events[0].commit_id).toBeDefined(); // Ensure commit ID was generated
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("should populate old_data on update", async () => {
|
|
93
|
-
const userId = 1;
|
|
94
|
-
// Update the existing post (id: 1)
|
|
95
|
-
const updateData = { id: 1, title: "Updated Title" };
|
|
96
|
-
|
|
97
|
-
await sql`
|
|
98
|
-
SELECT dzql_v2.save_posts(${userId}, ${sql.json(updateData)})
|
|
99
|
-
`;
|
|
100
|
-
|
|
101
|
-
const events = await sql`
|
|
102
|
-
SELECT * FROM dzql_v2.events
|
|
103
|
-
WHERE table_name = 'posts' AND op = 'update'
|
|
104
|
-
ORDER BY id DESC LIMIT 1
|
|
105
|
-
`;
|
|
106
|
-
|
|
107
|
-
expect(events.length).toBe(1);
|
|
108
|
-
expect(events[0].op).toBe("update");
|
|
109
|
-
expect(events[0].data.title).toBe("Updated Title");
|
|
110
|
-
expect(events[0].old_data).not.toBeNull();
|
|
111
|
-
expect(events[0].old_data.title).toBe("Real DB Test"); // Previous title
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
test("should trigger reactors (Graph Rules)", async () => {
|
|
115
|
-
// The blog.ts example has a reactor 'notify_subscribers' on create
|
|
116
|
-
const reactorEvents = await sql`
|
|
117
|
-
SELECT * FROM dzql_v2.events
|
|
118
|
-
WHERE op LIKE 'reactor:%'
|
|
119
|
-
ORDER BY id DESC LIMIT 1
|
|
120
|
-
`;
|
|
121
|
-
|
|
122
|
-
expect(reactorEvents.length).toBe(1);
|
|
123
|
-
expect(reactorEvents[0].op).toBe("reactor:notify_subscribers");
|
|
124
|
-
expect(reactorEvents[0].data.post_id).toBe("1");
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test("should delete a post via compiled function (Atomic Delete)", async () => {
|
|
128
|
-
const userId = 1;
|
|
129
|
-
// Call the compiled PL/pgSQL function
|
|
130
|
-
const result = await sql`
|
|
131
|
-
SELECT dzql_v2.delete_posts(${userId}, ${sql.json({ id: 1 })}) as data
|
|
132
|
-
`;
|
|
133
|
-
|
|
134
|
-
const deleted = result[0].data;
|
|
135
|
-
expect(deleted.id).toBe(1);
|
|
136
|
-
|
|
137
|
-
// Verify gone
|
|
138
|
-
const rows = await sql`SELECT * FROM posts WHERE id = 1`;
|
|
139
|
-
expect(rows.length).toBe(0);
|
|
140
|
-
|
|
141
|
-
// Verify Event
|
|
142
|
-
const events = await sql`
|
|
143
|
-
SELECT * FROM dzql_v2.events
|
|
144
|
-
WHERE table_name = 'posts' AND op = 'delete'
|
|
145
|
-
ORDER BY id DESC LIMIT 1
|
|
146
|
-
`;
|
|
147
|
-
expect(events.length).toBe(1);
|
|
148
|
-
expect(events[0].pk.id).toBe(1);
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
test("should get a post via compiled function", async () => {
|
|
152
|
-
// Re-create post first
|
|
153
|
-
await sql`INSERT INTO posts (id, title, author_id) VALUES (100, 'Get Test', 1)`;
|
|
154
|
-
|
|
155
|
-
const userId = 1;
|
|
156
|
-
const result = await sql`
|
|
157
|
-
SELECT dzql_v2.get_posts(${userId}, ${sql.json({ id: 100 })}) as data
|
|
158
|
-
`;
|
|
159
|
-
|
|
160
|
-
expect(result[0].data.title).toBe("Get Test");
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
test("should search posts via compiled function", async () => {
|
|
164
|
-
// Search
|
|
165
|
-
const userId = 1;
|
|
166
|
-
const result = await sql`
|
|
167
|
-
SELECT dzql_v2.search_posts(${userId}, ${sql.json({ limit: 5 })}) as data
|
|
168
|
-
`;
|
|
169
|
-
|
|
170
|
-
expect(result[0].data).toBeArray();
|
|
171
|
-
expect(result[0].data.length).toBeGreaterThan(0);
|
|
172
|
-
expect(result[0].data[0].title).toBe("Get Test");
|
|
173
|
-
});
|
|
174
|
-
});
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeAll } from "bun:test";
|
|
2
|
-
import { generateCoreSQL, generateEntitySQL } from "../../src/cli/codegen/sql.js";
|
|
3
|
-
import { generateIR } from "../../src/cli/compiler/ir.js";
|
|
4
|
-
|
|
5
|
-
// Load our blog example directly (bypassing loader for test isolation)
|
|
6
|
-
import { entities } from "../../examples/blog.js";
|
|
7
|
-
|
|
8
|
-
const blogDomain = { entities, subscribables: {} };
|
|
9
|
-
|
|
10
|
-
describe("V2 End-to-End Compiler Integration", () => {
|
|
11
|
-
let ir: any;
|
|
12
|
-
let coreSQL: string;
|
|
13
|
-
let postsSQL: string;
|
|
14
|
-
let commentsSQL: string;
|
|
15
|
-
|
|
16
|
-
beforeAll(() => {
|
|
17
|
-
// 1. Generate IR from Domain Object
|
|
18
|
-
ir = generateIR(blogDomain);
|
|
19
|
-
|
|
20
|
-
// 2. Generate SQL
|
|
21
|
-
coreSQL = generateCoreSQL();
|
|
22
|
-
postsSQL = generateEntitySQL("posts", ir.entities.posts);
|
|
23
|
-
commentsSQL = generateEntitySQL("comments", ir.entities.comments);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("should generate valid IR for blog", () => {
|
|
27
|
-
expect(ir.entities.posts).toBeDefined();
|
|
28
|
-
expect(ir.entities.posts.primaryKey).toEqual(["id"]);
|
|
29
|
-
// Check permission parsing
|
|
30
|
-
expect(ir.entities.posts.permissions.create).toEqual(['@author_id == @user_id']);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("should generate core SQL schema", () => {
|
|
34
|
-
expect(coreSQL).toContain("CREATE SCHEMA IF NOT EXISTS dzql_v2");
|
|
35
|
-
expect(coreSQL).toContain("CREATE TABLE IF NOT EXISTS dzql_v2.events");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
test("should generate atomic UPSERT for posts", () => {
|
|
39
|
-
// Check function signature
|
|
40
|
-
expect(postsSQL).toContain("CREATE OR REPLACE FUNCTION dzql_v2.save_posts");
|
|
41
|
-
|
|
42
|
-
// Check security
|
|
43
|
-
expect(postsSQL).toContain("SECURITY DEFINER");
|
|
44
|
-
expect(postsSQL).toContain("SET search_path = dzql_v2, public");
|
|
45
|
-
|
|
46
|
-
// Check Update/Insert Branching (New V2 Pattern with composite PK support)
|
|
47
|
-
expect(postsSQL).toContain("AND EXISTS(SELECT 1 FROM posts WHERE");
|
|
48
|
-
expect(postsSQL).toContain("UPDATE posts SET");
|
|
49
|
-
expect(postsSQL).toContain("INSERT INTO posts");
|
|
50
|
-
|
|
51
|
-
// Check column handling in update
|
|
52
|
-
expect(postsSQL).toContain("title = CASE WHEN (p_data ? 'title')");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("should inline permission checks", () => {
|
|
56
|
-
// Check that @author_id == @user_id was compiled correctly
|
|
57
|
-
expect(postsSQL).toContain("IF NOT ((p_data->>'author_id')::int = p_user_id) THEN");
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test("should compile graph rules", () => {
|
|
61
|
-
// Check reactor trigger
|
|
62
|
-
expect(postsSQL).toContain("INSERT INTO dzql_v2.events");
|
|
63
|
-
expect(postsSQL).toContain("'reactor:notify_subscribers'");
|
|
64
|
-
});
|
|
65
|
-
});
|