dzql 0.5.33 → 0.6.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.
Files changed (150) hide show
  1. package/.env.sample +28 -0
  2. package/compose.yml +28 -0
  3. package/dist/client/index.ts +1 -0
  4. package/dist/client/stores/useMyProfileStore.ts +114 -0
  5. package/dist/client/stores/useOrgDashboardStore.ts +131 -0
  6. package/dist/client/stores/useVenueDetailStore.ts +117 -0
  7. package/dist/client/ws.ts +716 -0
  8. package/dist/db/migrations/000_core.sql +92 -0
  9. package/dist/db/migrations/20251229T212912022Z_schema.sql +3020 -0
  10. package/dist/db/migrations/20251229T212912022Z_subscribables.sql +371 -0
  11. package/dist/runtime/manifest.json +1562 -0
  12. package/docs/README.md +293 -36
  13. package/docs/feature-requests/applyPatch-bug-report.md +85 -0
  14. package/docs/feature-requests/connection-ready-profile.md +57 -0
  15. package/docs/feature-requests/hidden-bug-report.md +111 -0
  16. package/docs/feature-requests/hidden-fields-subscribables.md +34 -0
  17. package/docs/feature-requests/subscribable-param-key-bug.md +38 -0
  18. package/docs/feature-requests/todo.md +146 -0
  19. package/docs/for_ai.md +641 -0
  20. package/docs/project-setup.md +432 -0
  21. package/examples/blog.ts +50 -0
  22. package/examples/invalid.ts +18 -0
  23. package/examples/venues.js +485 -0
  24. package/package.json +23 -60
  25. package/src/cli/codegen/client.ts +99 -0
  26. package/src/cli/codegen/manifest.ts +95 -0
  27. package/src/cli/codegen/pinia.ts +174 -0
  28. package/src/cli/codegen/realtime.ts +58 -0
  29. package/src/cli/codegen/sql.ts +698 -0
  30. package/src/cli/codegen/subscribable_sql.ts +547 -0
  31. package/src/cli/codegen/subscribable_store.ts +184 -0
  32. package/src/cli/codegen/types.ts +142 -0
  33. package/src/cli/compiler/analyzer.ts +52 -0
  34. package/src/cli/compiler/graph_rules.ts +251 -0
  35. package/src/cli/compiler/ir.ts +233 -0
  36. package/src/cli/compiler/loader.ts +132 -0
  37. package/src/cli/compiler/permissions.ts +227 -0
  38. package/src/cli/index.ts +164 -0
  39. package/src/client/index.ts +1 -0
  40. package/src/client/ws.ts +286 -0
  41. package/src/create/.env.example +8 -0
  42. package/src/create/README.md +101 -0
  43. package/src/create/compose.yml +14 -0
  44. package/src/create/domain.ts +153 -0
  45. package/src/create/package.json +24 -0
  46. package/src/create/server.ts +18 -0
  47. package/src/create/setup.sh +11 -0
  48. package/src/create/tsconfig.json +15 -0
  49. package/src/runtime/auth.ts +39 -0
  50. package/src/runtime/db.ts +33 -0
  51. package/src/runtime/errors.ts +51 -0
  52. package/src/runtime/index.ts +98 -0
  53. package/src/runtime/js_functions.ts +63 -0
  54. package/src/runtime/manifest_loader.ts +29 -0
  55. package/src/runtime/namespace.ts +483 -0
  56. package/src/runtime/server.ts +87 -0
  57. package/src/runtime/ws.ts +197 -0
  58. package/src/shared/ir.ts +197 -0
  59. package/tests/client.test.ts +38 -0
  60. package/tests/codegen.test.ts +71 -0
  61. package/tests/compiler.test.ts +45 -0
  62. package/tests/graph_rules.test.ts +173 -0
  63. package/tests/integration/db.test.ts +174 -0
  64. package/tests/integration/e2e.test.ts +65 -0
  65. package/tests/integration/features.test.ts +922 -0
  66. package/tests/integration/full_stack.test.ts +262 -0
  67. package/tests/integration/setup.ts +45 -0
  68. package/tests/ir.test.ts +32 -0
  69. package/tests/namespace.test.ts +395 -0
  70. package/tests/permissions.test.ts +55 -0
  71. package/tests/pinia.test.ts +48 -0
  72. package/tests/realtime.test.ts +22 -0
  73. package/tests/runtime.test.ts +80 -0
  74. package/tests/subscribable_gen.test.ts +72 -0
  75. package/tests/subscribable_reactivity.test.ts +258 -0
  76. package/tests/venues_gen.test.ts +25 -0
  77. package/tsconfig.json +20 -0
  78. package/tsconfig.tsbuildinfo +1 -0
  79. package/README.md +0 -90
  80. package/bin/cli.js +0 -727
  81. package/docs/compiler/ADVANCED_FILTERS.md +0 -183
  82. package/docs/compiler/CODING_STANDARDS.md +0 -415
  83. package/docs/compiler/COMPARISON.md +0 -673
  84. package/docs/compiler/QUICKSTART.md +0 -326
  85. package/docs/compiler/README.md +0 -134
  86. package/docs/examples/README.md +0 -38
  87. package/docs/examples/blog.sql +0 -160
  88. package/docs/examples/venue-detail-simple.sql +0 -8
  89. package/docs/examples/venue-detail-subscribable.sql +0 -45
  90. package/docs/for-ai/claude-guide.md +0 -1210
  91. package/docs/getting-started/quickstart.md +0 -125
  92. package/docs/getting-started/subscriptions-quick-start.md +0 -203
  93. package/docs/getting-started/tutorial.md +0 -1104
  94. package/docs/guides/atomic-updates.md +0 -299
  95. package/docs/guides/client-stores.md +0 -730
  96. package/docs/guides/composite-primary-keys.md +0 -158
  97. package/docs/guides/custom-functions.md +0 -362
  98. package/docs/guides/drop-semantics.md +0 -554
  99. package/docs/guides/field-defaults.md +0 -240
  100. package/docs/guides/interpreter-vs-compiler.md +0 -237
  101. package/docs/guides/many-to-many.md +0 -929
  102. package/docs/guides/subscriptions.md +0 -537
  103. package/docs/reference/api.md +0 -1373
  104. package/docs/reference/client.md +0 -224
  105. package/src/client/stores/index.js +0 -8
  106. package/src/client/stores/useAppStore.js +0 -285
  107. package/src/client/stores/useWsStore.js +0 -289
  108. package/src/client/ws.js +0 -762
  109. package/src/compiler/cli/compile-example.js +0 -33
  110. package/src/compiler/cli/compile-subscribable.js +0 -43
  111. package/src/compiler/cli/debug-compile.js +0 -44
  112. package/src/compiler/cli/debug-parse.js +0 -26
  113. package/src/compiler/cli/debug-path-parser.js +0 -18
  114. package/src/compiler/cli/debug-subscribable-parser.js +0 -21
  115. package/src/compiler/cli/index.js +0 -174
  116. package/src/compiler/codegen/auth-codegen.js +0 -153
  117. package/src/compiler/codegen/drop-semantics-codegen.js +0 -553
  118. package/src/compiler/codegen/graph-rules-codegen.js +0 -450
  119. package/src/compiler/codegen/notification-codegen.js +0 -232
  120. package/src/compiler/codegen/operation-codegen.js +0 -1382
  121. package/src/compiler/codegen/permission-codegen.js +0 -318
  122. package/src/compiler/codegen/subscribable-codegen.js +0 -827
  123. package/src/compiler/compiler.js +0 -371
  124. package/src/compiler/index.js +0 -11
  125. package/src/compiler/parser/entity-parser.js +0 -440
  126. package/src/compiler/parser/path-parser.js +0 -290
  127. package/src/compiler/parser/subscribable-parser.js +0 -244
  128. package/src/database/dzql-core.sql +0 -161
  129. package/src/database/migrations/001_schema.sql +0 -60
  130. package/src/database/migrations/002_functions.sql +0 -890
  131. package/src/database/migrations/003_operations.sql +0 -1135
  132. package/src/database/migrations/004_search.sql +0 -581
  133. package/src/database/migrations/005_entities.sql +0 -730
  134. package/src/database/migrations/006_auth.sql +0 -94
  135. package/src/database/migrations/007_events.sql +0 -133
  136. package/src/database/migrations/008_hello.sql +0 -18
  137. package/src/database/migrations/008a_meta.sql +0 -172
  138. package/src/database/migrations/009_subscriptions.sql +0 -240
  139. package/src/database/migrations/010_atomic_updates.sql +0 -157
  140. package/src/database/migrations/010_fix_m2m_events.sql +0 -94
  141. package/src/index.js +0 -40
  142. package/src/server/api.js +0 -9
  143. package/src/server/db.js +0 -442
  144. package/src/server/index.js +0 -317
  145. package/src/server/logger.js +0 -259
  146. package/src/server/mcp.js +0 -594
  147. package/src/server/meta-route.js +0 -251
  148. package/src/server/namespace.js +0 -292
  149. package/src/server/subscriptions.js +0 -351
  150. package/src/server/ws.js +0 -573
@@ -0,0 +1,371 @@
1
+ -- ============================================================================
2
+ -- Subscribable: venue_detail
3
+ -- Root Entity: venues
4
+ -- Scope Tables: venues, organisations, sites, allocations
5
+ -- Generated: 2025-12-29T21:29:12.021Z
6
+ -- ============================================================================
7
+
8
+ CREATE OR REPLACE FUNCTION dzql_v2.venue_detail_can_subscribe(
9
+ p_user_id INT,
10
+ p_params JSONB
11
+ ) RETURNS BOOLEAN
12
+ LANGUAGE plpgsql
13
+ STABLE
14
+ SECURITY DEFINER
15
+ SET search_path = dzql_v2, public
16
+ AS $$
17
+ DECLARE
18
+ v_venue_id int;
19
+ v_root RECORD;
20
+ BEGIN
21
+ -- Extract parameters
22
+ v_venue_id := (p_params->>'venue_id')::int;
23
+
24
+ -- Fetch root entity
25
+ SELECT * INTO v_root
26
+ FROM venues
27
+ WHERE id = v_venue_id;
28
+
29
+ IF NOT FOUND THEN
30
+ RETURN FALSE;
31
+ END IF;
32
+
33
+ -- Check permissions
34
+ RETURN (
35
+ p_user_id IS NOT NULL -- Fallback: multi-level paths not yet supported
36
+ );
37
+ END;
38
+ $$;
39
+
40
+ CREATE OR REPLACE FUNCTION dzql_v2.get_venue_detail(
41
+ p_params JSONB,
42
+ p_user_id INT
43
+ ) RETURNS JSONB
44
+ LANGUAGE plpgsql
45
+ SECURITY DEFINER
46
+ SET search_path = dzql_v2, public
47
+ AS $$
48
+ DECLARE
49
+ v_venue_id int;
50
+ v_data JSONB;
51
+ BEGIN
52
+ -- Extract parameters
53
+ v_venue_id := (p_params->>'venue_id')::int;
54
+
55
+ -- Check access control
56
+ IF NOT dzql_v2.venue_detail_can_subscribe(p_user_id, p_params) THEN
57
+ RAISE EXCEPTION 'permission_denied';
58
+ END IF;
59
+
60
+ -- Build document with root and all relations
61
+ SELECT jsonb_build_object(
62
+ 'venues', row_to_json(root.*),
63
+ 'org', (
64
+ SELECT row_to_json(rel.*)
65
+ FROM organisations rel
66
+ WHERE rel.id = root.org_id
67
+ ),
68
+ 'sites', COALESCE((
69
+ SELECT jsonb_agg(
70
+ to_jsonb(rel.*) || jsonb_build_object(
71
+ 'allocations', COALESCE((
72
+ SELECT jsonb_agg(row_to_json(nested.*))
73
+ FROM allocations nested
74
+ WHERE nested.site_id = rel.id
75
+ ), '[]'::jsonb))
76
+ )
77
+ FROM sites rel
78
+ WHERE rel.venue_id = root.id
79
+ ), '[]'::jsonb)
80
+ )
81
+ INTO v_data
82
+ FROM venues root
83
+ WHERE root.id = v_venue_id;
84
+
85
+ -- Return data with embedded schema for atomic updates
86
+ RETURN jsonb_build_object(
87
+ 'data', v_data,
88
+ 'schema', '{"root":"venues","paths":{"venues":".","organisations":"org","sites":"sites","allocations":"sites.allocations"},"scopeTables":["venues","organisations","sites","allocations"]}'::jsonb
89
+ );
90
+ END;
91
+ $$;
92
+
93
+ CREATE OR REPLACE FUNCTION dzql_v2.venue_detail_affected_keys(
94
+ p_table TEXT,
95
+ p_op TEXT,
96
+ p_data JSONB
97
+ ) RETURNS TEXT[]
98
+ LANGUAGE plpgsql
99
+ IMMUTABLE
100
+ AS $$
101
+ DECLARE
102
+ v_keys TEXT[];
103
+ BEGIN
104
+ CASE p_table
105
+ WHEN 'venues' THEN
106
+ RETURN ARRAY['venue_detail:' || (p_data->>'id')];
107
+ WHEN 'organisations' THEN
108
+ RETURN ARRAY['venue_detail:' || (p_data->>'venue_id')];
109
+ WHEN 'sites' THEN
110
+ RETURN ARRAY['venue_detail:' || (p_data->>'venue_id')];
111
+ WHEN 'allocations' THEN
112
+ -- Nested: traverse via sites
113
+ SELECT ARRAY_AGG('venue_detail:' || parent.venue_id)
114
+ INTO v_keys
115
+ FROM sites parent
116
+ WHERE parent.id = (p_data->>'site_id')::int;
117
+ RETURN COALESCE(v_keys, ARRAY[]::text[]);
118
+ ELSE
119
+ RETURN ARRAY[]::text[];
120
+ END CASE;
121
+ END;
122
+ $$;
123
+
124
+ -- ============================================================================
125
+ -- Subscribable: org_dashboard
126
+ -- Root Entity: organisations
127
+ -- Scope Tables: organisations, venues, sites, products, packages, brands, artwork
128
+ -- Generated: 2025-12-29T21:29:12.022Z
129
+ -- ============================================================================
130
+
131
+ CREATE OR REPLACE FUNCTION dzql_v2.org_dashboard_can_subscribe(
132
+ p_user_id INT,
133
+ p_params JSONB
134
+ ) RETURNS BOOLEAN
135
+ LANGUAGE plpgsql
136
+ STABLE
137
+ SECURITY DEFINER
138
+ SET search_path = dzql_v2, public
139
+ AS $$
140
+ DECLARE
141
+ v_org_id int;
142
+ v_root RECORD;
143
+ BEGIN
144
+ -- Extract parameters
145
+ v_org_id := (p_params->>'org_id')::int;
146
+
147
+ -- Fetch root entity
148
+ SELECT * INTO v_root
149
+ FROM organisations
150
+ WHERE id = v_org_id;
151
+
152
+ IF NOT FOUND THEN
153
+ RETURN FALSE;
154
+ END IF;
155
+
156
+ -- Check permissions
157
+ RETURN (
158
+ EXISTS (SELECT 1 FROM acts_for WHERE acts_for.org_id = v_root.id AND acts_for.user_id = p_user_id AND acts_for.active)
159
+ );
160
+ END;
161
+ $$;
162
+
163
+ CREATE OR REPLACE FUNCTION dzql_v2.get_org_dashboard(
164
+ p_params JSONB,
165
+ p_user_id INT
166
+ ) RETURNS JSONB
167
+ LANGUAGE plpgsql
168
+ SECURITY DEFINER
169
+ SET search_path = dzql_v2, public
170
+ AS $$
171
+ DECLARE
172
+ v_org_id int;
173
+ v_data JSONB;
174
+ BEGIN
175
+ -- Extract parameters
176
+ v_org_id := (p_params->>'org_id')::int;
177
+
178
+ -- Check access control
179
+ IF NOT dzql_v2.org_dashboard_can_subscribe(p_user_id, p_params) THEN
180
+ RAISE EXCEPTION 'permission_denied';
181
+ END IF;
182
+
183
+ -- Build document with root and all relations
184
+ SELECT jsonb_build_object(
185
+ 'organisations', row_to_json(root.*),
186
+ 'venues', COALESCE((
187
+ SELECT jsonb_agg(
188
+ to_jsonb(rel.*) || jsonb_build_object(
189
+ 'sites', COALESCE((
190
+ SELECT jsonb_agg(row_to_json(nested.*))
191
+ FROM sites nested
192
+ WHERE nested.venue_id = rel.id
193
+ ), '[]'::jsonb))
194
+ )
195
+ FROM venues rel
196
+ WHERE rel.org_id = v_org_id
197
+ ), '[]'::jsonb),
198
+ 'products', COALESCE((
199
+ SELECT jsonb_agg(row_to_json(rel.*))
200
+ FROM products rel
201
+ WHERE rel.org_id = v_org_id
202
+ ), '[]'::jsonb),
203
+ 'packages', COALESCE((
204
+ SELECT jsonb_agg(row_to_json(rel.*))
205
+ FROM packages rel
206
+ WHERE rel.owner_org_id = v_org_id
207
+ ), '[]'::jsonb),
208
+ 'brands', COALESCE((
209
+ SELECT jsonb_agg(
210
+ to_jsonb(rel.*) || jsonb_build_object(
211
+ 'artwork', COALESCE((
212
+ SELECT jsonb_agg(row_to_json(nested.*))
213
+ FROM artwork nested
214
+ WHERE nested.brand_id = rel.id
215
+ ), '[]'::jsonb))
216
+ )
217
+ FROM brands rel
218
+ WHERE rel.org_id = v_org_id
219
+ ), '[]'::jsonb)
220
+ )
221
+ INTO v_data
222
+ FROM organisations root
223
+ WHERE root.id = v_org_id;
224
+
225
+ -- Return data with embedded schema for atomic updates
226
+ RETURN jsonb_build_object(
227
+ 'data', v_data,
228
+ 'schema', '{"root":"organisations","paths":{"organisations":".","venues":"venues","sites":"venues.sites","products":"products","packages":"packages","brands":"brands","artwork":"brands.artwork"},"scopeTables":["organisations","venues","sites","products","packages","brands","artwork"]}'::jsonb
229
+ );
230
+ END;
231
+ $$;
232
+
233
+ CREATE OR REPLACE FUNCTION dzql_v2.org_dashboard_affected_keys(
234
+ p_table TEXT,
235
+ p_op TEXT,
236
+ p_data JSONB
237
+ ) RETURNS TEXT[]
238
+ LANGUAGE plpgsql
239
+ IMMUTABLE
240
+ AS $$
241
+ DECLARE
242
+ v_keys TEXT[];
243
+ BEGIN
244
+ CASE p_table
245
+ WHEN 'organisations' THEN
246
+ RETURN ARRAY['org_dashboard:' || (p_data->>'id')];
247
+ WHEN 'venues' THEN
248
+ RETURN ARRAY['org_dashboard:' || (p_data->>'org_id')];
249
+ WHEN 'sites' THEN
250
+ -- Nested: traverse via venues
251
+ SELECT ARRAY_AGG('org_dashboard:' || parent.organisation_id)
252
+ INTO v_keys
253
+ FROM venues parent
254
+ WHERE parent.id = (p_data->>'venue_id')::int;
255
+ RETURN COALESCE(v_keys, ARRAY[]::text[]);
256
+ WHEN 'products' THEN
257
+ RETURN ARRAY['org_dashboard:' || (p_data->>'org_id')];
258
+ WHEN 'packages' THEN
259
+ RETURN ARRAY['org_dashboard:' || (p_data->>'owner_org_id')];
260
+ WHEN 'brands' THEN
261
+ RETURN ARRAY['org_dashboard:' || (p_data->>'org_id')];
262
+ WHEN 'artwork' THEN
263
+ -- Nested: traverse via brands
264
+ SELECT ARRAY_AGG('org_dashboard:' || parent.organisation_id)
265
+ INTO v_keys
266
+ FROM brands parent
267
+ WHERE parent.id = (p_data->>'brand_id')::int;
268
+ RETURN COALESCE(v_keys, ARRAY[]::text[]);
269
+ ELSE
270
+ RETURN ARRAY[]::text[];
271
+ END CASE;
272
+ END;
273
+ $$;
274
+
275
+ -- ============================================================================
276
+ -- Subscribable: my_profile
277
+ -- Root Entity: users
278
+ -- Scope Tables: users, acts_for, organisations
279
+ -- Generated: 2025-12-29T21:29:12.022Z
280
+ -- ============================================================================
281
+
282
+ CREATE OR REPLACE FUNCTION dzql_v2.my_profile_can_subscribe(
283
+ p_user_id INT,
284
+ p_params JSONB
285
+ ) RETURNS BOOLEAN
286
+ LANGUAGE plpgsql
287
+ STABLE
288
+ SECURITY DEFINER
289
+ SET search_path = dzql_v2, public
290
+ AS $$
291
+ BEGIN
292
+ RETURN TRUE; -- Public access
293
+ END;
294
+ $$;
295
+
296
+ CREATE OR REPLACE FUNCTION dzql_v2.get_my_profile(
297
+ p_params JSONB,
298
+ p_user_id INT
299
+ ) RETURNS JSONB
300
+ LANGUAGE plpgsql
301
+ SECURITY DEFINER
302
+ SET search_path = dzql_v2, public
303
+ AS $$
304
+ DECLARE
305
+
306
+ v_data JSONB;
307
+ BEGIN
308
+ -- Extract parameters
309
+
310
+
311
+ -- Check access control
312
+ IF NOT dzql_v2.my_profile_can_subscribe(p_user_id, p_params) THEN
313
+ RAISE EXCEPTION 'permission_denied';
314
+ END IF;
315
+
316
+ -- Build document with root and all relations
317
+ SELECT jsonb_build_object(
318
+ 'users', jsonb_build_object('id', root.id, 'name', root.name, 'email', root.email, 'created_at', root.created_at),
319
+ 'memberships', COALESCE((
320
+ SELECT jsonb_agg(
321
+ to_jsonb(rel.*) || jsonb_build_object(
322
+ 'org', (
323
+ SELECT row_to_json(nested.*)
324
+ FROM organisations nested
325
+ WHERE nested.id = rel.org_id
326
+ ))
327
+ )
328
+ FROM acts_for rel
329
+ WHERE rel.user_id = p_user_id
330
+ ), '[]'::jsonb)
331
+ )
332
+ INTO v_data
333
+ FROM users root
334
+ WHERE root.id = p_user_id;
335
+
336
+ -- Return data with embedded schema for atomic updates
337
+ RETURN jsonb_build_object(
338
+ 'data', v_data,
339
+ 'schema', '{"root":"users","paths":{"users":".","acts_for":"memberships","organisations":"memberships.org"},"scopeTables":["users","acts_for","organisations"]}'::jsonb
340
+ );
341
+ END;
342
+ $$;
343
+
344
+ CREATE OR REPLACE FUNCTION dzql_v2.my_profile_affected_keys(
345
+ p_table TEXT,
346
+ p_op TEXT,
347
+ p_data JSONB
348
+ ) RETURNS TEXT[]
349
+ LANGUAGE plpgsql
350
+ IMMUTABLE
351
+ AS $$
352
+ DECLARE
353
+ v_keys TEXT[];
354
+ BEGIN
355
+ CASE p_table
356
+ WHEN 'users' THEN
357
+ RETURN ARRAY['my_profile:' || (p_data->>'id')];
358
+ WHEN 'acts_for' THEN
359
+ RETURN ARRAY['my_profile:' || (p_data->>'user_id')];
360
+ WHEN 'organisations' THEN
361
+ -- Nested: traverse via acts_for
362
+ SELECT ARRAY_AGG('my_profile:' || parent.user_id)
363
+ INTO v_keys
364
+ FROM acts_for parent
365
+ WHERE parent.id = (p_data->>'acts_for_id')::int;
366
+ RETURN COALESCE(v_keys, ARRAY[]::text[]);
367
+ ELSE
368
+ RETURN ARRAY[]::text[];
369
+ END CASE;
370
+ END;
371
+ $$;