dzql 0.5.15 → 0.5.16

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dzql",
3
- "version": "0.5.15",
3
+ "version": "0.5.16",
4
4
  "description": "PostgreSQL-powered framework with zero boilerplate CRUD operations and real-time WebSocket synchronization",
5
5
  "type": "module",
6
6
  "main": "src/server/index.js",
@@ -17,7 +17,7 @@
17
17
  "files": [
18
18
  "bin/**/*.js",
19
19
  "src/**/*.js",
20
- "src/database/migrations/**/*.sql",
20
+ "src/database/**/*.sql",
21
21
  "docs/**/*.md",
22
22
  "docs/examples/*.sql",
23
23
  "README.md",
@@ -0,0 +1,161 @@
1
+ -- ============================================================================
2
+ -- DZQL Core - Minimal Foundation
3
+ -- ============================================================================
4
+ -- This is the minimal SQL needed for DZQL compiled mode.
5
+ -- Run: dzql db:init
6
+ -- Or: psql $DATABASE_URL -f dzql-core.sql
7
+ -- ============================================================================
8
+
9
+ CREATE EXTENSION IF NOT EXISTS pgcrypto;
10
+
11
+ CREATE SCHEMA IF NOT EXISTS dzql;
12
+
13
+ -- Version tracking
14
+ CREATE TABLE IF NOT EXISTS dzql.meta (
15
+ installed_at TIMESTAMPTZ DEFAULT now(),
16
+ version TEXT NOT NULL
17
+ );
18
+
19
+ INSERT INTO dzql.meta (version)
20
+ SELECT '0.5.14'
21
+ WHERE NOT EXISTS (SELECT 1 FROM dzql.meta);
22
+
23
+ -- Entity registry
24
+ CREATE TABLE IF NOT EXISTS dzql.entities (
25
+ table_name TEXT PRIMARY KEY,
26
+ label_field TEXT NOT NULL,
27
+ searchable_fields TEXT[] NOT NULL,
28
+ fk_includes JSONB DEFAULT '{}',
29
+ soft_delete BOOLEAN DEFAULT false,
30
+ temporal_fields JSONB DEFAULT '{}',
31
+ notification_paths JSONB DEFAULT '{}',
32
+ permission_paths JSONB DEFAULT '{}',
33
+ graph_rules JSONB DEFAULT '{}',
34
+ field_defaults JSONB DEFAULT '{}',
35
+ many_to_many JSONB DEFAULT '{}'
36
+ );
37
+
38
+ -- Function allowlist
39
+ CREATE TABLE IF NOT EXISTS dzql.registry (
40
+ fn_regproc REGPROC PRIMARY KEY,
41
+ description TEXT
42
+ );
43
+
44
+ -- Event audit table
45
+ CREATE TABLE IF NOT EXISTS dzql.events (
46
+ event_id BIGSERIAL PRIMARY KEY,
47
+ table_name TEXT NOT NULL,
48
+ op TEXT NOT NULL,
49
+ pk JSONB NOT NULL,
50
+ data JSONB,
51
+ user_id INT,
52
+ notify_users INT[],
53
+ at TIMESTAMPTZ DEFAULT now()
54
+ );
55
+
56
+ CREATE INDEX IF NOT EXISTS dzql_events_at_idx ON dzql.events (at);
57
+ CREATE INDEX IF NOT EXISTS dzql_events_table_pk_idx ON dzql.events (table_name, pk, at);
58
+
59
+ -- NOTIFY trigger for real-time updates
60
+ CREATE OR REPLACE FUNCTION dzql.notify_event()
61
+ RETURNS TRIGGER LANGUAGE plpgsql AS $$
62
+ BEGIN
63
+ PERFORM pg_notify('dzql', jsonb_build_object(
64
+ 'event_id', NEW.event_id,
65
+ 'table', NEW.table_name,
66
+ 'op', NEW.op,
67
+ 'pk', NEW.pk,
68
+ 'data', NEW.data,
69
+ 'user_id', NEW.user_id,
70
+ 'at', NEW.at,
71
+ 'notify_users', NEW.notify_users
72
+ )::text);
73
+ RETURN NULL;
74
+ END $$;
75
+
76
+ DROP TRIGGER IF EXISTS dzql_events_notify ON dzql.events;
77
+ CREATE TRIGGER dzql_events_notify
78
+ AFTER INSERT ON dzql.events
79
+ FOR EACH ROW EXECUTE FUNCTION dzql.notify_event();
80
+
81
+ -- Subscribables registry (for compiled subscribables)
82
+ CREATE TABLE IF NOT EXISTS dzql.subscribables (
83
+ name TEXT PRIMARY KEY,
84
+ permission_paths JSONB DEFAULT '{}',
85
+ param_schema JSONB DEFAULT '{}',
86
+ root_entity TEXT NOT NULL,
87
+ relations JSONB DEFAULT '{}',
88
+ scope_tables TEXT[] DEFAULT '{}',
89
+ created_at TIMESTAMPTZ DEFAULT now()
90
+ );
91
+
92
+ -- Helper to register entities
93
+ CREATE OR REPLACE FUNCTION dzql.register_entity(
94
+ p_table_name TEXT,
95
+ p_label_field TEXT,
96
+ p_searchable_fields TEXT[],
97
+ p_fk_includes JSONB DEFAULT '{}',
98
+ p_soft_delete BOOLEAN DEFAULT false,
99
+ p_temporal_fields JSONB DEFAULT '{}',
100
+ p_notification_paths JSONB DEFAULT '{}',
101
+ p_permission_paths JSONB DEFAULT '{}',
102
+ p_graph_rules JSONB DEFAULT '{}',
103
+ p_field_defaults JSONB DEFAULT '{}',
104
+ p_many_to_many JSONB DEFAULT '{}'
105
+ ) RETURNS VOID AS $$
106
+ BEGIN
107
+ INSERT INTO dzql.entities (
108
+ table_name, label_field, searchable_fields, fk_includes,
109
+ soft_delete, temporal_fields, notification_paths, permission_paths,
110
+ graph_rules, field_defaults, many_to_many
111
+ ) VALUES (
112
+ p_table_name, p_label_field, p_searchable_fields, p_fk_includes,
113
+ p_soft_delete, p_temporal_fields, p_notification_paths, p_permission_paths,
114
+ p_graph_rules, p_field_defaults, p_many_to_many
115
+ )
116
+ ON CONFLICT (table_name) DO UPDATE SET
117
+ label_field = EXCLUDED.label_field,
118
+ searchable_fields = EXCLUDED.searchable_fields,
119
+ fk_includes = EXCLUDED.fk_includes,
120
+ soft_delete = EXCLUDED.soft_delete,
121
+ temporal_fields = EXCLUDED.temporal_fields,
122
+ notification_paths = EXCLUDED.notification_paths,
123
+ permission_paths = EXCLUDED.permission_paths,
124
+ graph_rules = EXCLUDED.graph_rules,
125
+ field_defaults = EXCLUDED.field_defaults,
126
+ many_to_many = EXCLUDED.many_to_many;
127
+ END;
128
+ $$ LANGUAGE plpgsql;
129
+
130
+ -- Helper to register subscribables
131
+ CREATE OR REPLACE FUNCTION dzql.register_subscribable(
132
+ p_name TEXT,
133
+ p_permission_paths JSONB,
134
+ p_param_schema JSONB,
135
+ p_root_entity TEXT,
136
+ p_relations JSONB DEFAULT '{}'
137
+ ) RETURNS VOID AS $$
138
+ DECLARE
139
+ v_scope_tables TEXT[];
140
+ BEGIN
141
+ -- Extract scope tables from relations
142
+ SELECT array_agg(DISTINCT tbl) INTO v_scope_tables
143
+ FROM (
144
+ SELECT p_root_entity AS tbl
145
+ UNION ALL
146
+ SELECT value->>'entity' AS tbl
147
+ FROM jsonb_each(p_relations)
148
+ WHERE value->>'entity' IS NOT NULL
149
+ ) t
150
+ WHERE tbl IS NOT NULL;
151
+
152
+ INSERT INTO dzql.subscribables (name, permission_paths, param_schema, root_entity, relations, scope_tables)
153
+ VALUES (p_name, p_permission_paths, p_param_schema, p_root_entity, p_relations, v_scope_tables)
154
+ ON CONFLICT (name) DO UPDATE SET
155
+ permission_paths = EXCLUDED.permission_paths,
156
+ param_schema = EXCLUDED.param_schema,
157
+ root_entity = EXCLUDED.root_entity,
158
+ relations = EXCLUDED.relations,
159
+ scope_tables = EXCLUDED.scope_tables;
160
+ END;
161
+ $$ LANGUAGE plpgsql;