dzql 0.5.32 → 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
@@ -1,326 +0,0 @@
1
- # DZQL Compiler - Quick Start Guide
2
-
3
- Get up and running with the DZQL Compiler in 5 minutes.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- cd /home/user/dzql/packages/dzql-compiler
9
- bun install
10
- ```
11
-
12
- ## Basic Usage
13
-
14
- ### 1. Compile Your First Entity
15
-
16
- ```bash
17
- # Compile the venues domain (9 entities)
18
- bun src/cli/index.js /home/user/dzql/packages/venues/database/init_db/009_venues_domain.sql -o compiled/
19
-
20
- # Output will be in compiled/ directory
21
- ```
22
-
23
- ### 2. Examine the Output
24
-
25
- ```bash
26
- # View generated SQL for venues
27
- cat compiled/venues.sql
28
-
29
- # Check checksums
30
- cat compiled/checksums.json
31
- ```
32
-
33
- ### 3. Run the Tests
34
-
35
- ```bash
36
- # All tests should pass
37
- bun test
38
- ```
39
-
40
- ## What You Get
41
-
42
- For each entity, the compiler generates:
43
-
44
- ### Permission Functions
45
- ```sql
46
- can_create_venues(p_user_id INT, p_record JSONB) → BOOLEAN
47
- can_update_venues(p_user_id INT, p_record JSONB) → BOOLEAN
48
- can_delete_venues(p_user_id INT, p_record JSONB) → BOOLEAN
49
- can_view_venues(p_user_id INT, p_record JSONB) → BOOLEAN
50
- ```
51
-
52
- ### CRUD Operations
53
- ```sql
54
- get_venues(p_user_id INT, p_id INT) → JSONB
55
- save_venues(p_user_id INT, p_data JSONB) → JSONB
56
- delete_venues(p_user_id INT, p_id INT) → JSONB
57
- lookup_venues(p_user_id INT, p_filter TEXT) → JSONB
58
- search_venues(p_user_id INT, p_filters JSONB, p_search TEXT, ...) → JSONB
59
- ```
60
-
61
- > **Note:** `p_user_id` is always the first parameter in all functions. See [CODING_STANDARDS.md](./CODING_STANDARDS.md).
62
-
63
- ## Example: Compile a Simple Entity
64
-
65
- Create `examples/todos.sql`:
66
-
67
- ```sql
68
- select dzql.register_entity(
69
- 'todos',
70
- 'title',
71
- array['title', 'description'],
72
- '{}', -- no FK includes
73
- false, -- no soft delete
74
- '{}', -- no temporal fields
75
- '{}', -- no notifications
76
- jsonb_build_object(
77
- 'view', array[]::text[], -- public
78
- 'create', array[]::text[], -- public
79
- 'update', array['@owner_id'], -- owner only
80
- 'delete', array['@owner_id'] -- owner only
81
- )
82
- );
83
- ```
84
-
85
- Compile it:
86
-
87
- ```bash
88
- bun src/cli/index.js examples/todos.sql -o compiled/
89
- ```
90
-
91
- Result: `compiled/todos.sql` with 5 operations + 4 permission checks.
92
-
93
- ## Using Compiled Functions
94
-
95
- Once deployed to PostgreSQL:
96
-
97
- ```sql
98
- -- Get a todo (p_user_id first, then p_id)
99
- SELECT get_todos(42, 1); -- user_id=42, id=1
100
-
101
- -- Create a todo (p_user_id first, then p_data)
102
- SELECT save_todos(42, '{"title": "Learn DZQL", "owner_id": 42}'::jsonb);
103
-
104
- -- Search todos (p_user_id first)
105
- SELECT search_todos(
106
- 42, -- user_id
107
- '{}', -- filters
108
- 'DZQL', -- search text
109
- '{"field": "title", "order": "asc"}', -- sort
110
- 1, -- page
111
- 25 -- limit
112
- );
113
-
114
- -- Delete a todo (p_user_id first, then p_id)
115
- SELECT delete_todos(42, 1);
116
- ```
117
-
118
- ## Development Workflow
119
-
120
- ### 1. Define Entity
121
-
122
- Edit `entities/my_entity.sql`:
123
-
124
- ```sql
125
- select dzql.register_entity(
126
- 'my_entity',
127
- 'name',
128
- array['name'],
129
- '{}',
130
- false
131
- );
132
- ```
133
-
134
- ### 2. Compile
135
-
136
- ```bash
137
- bun src/cli/index.js entities/my_entity.sql -o compiled/
138
- ```
139
-
140
- ### 3. Deploy
141
-
142
- ```bash
143
- psql -U dzql -d dzql < compiled/my_entity.sql
144
- ```
145
-
146
- ### 4. Use
147
-
148
- ```sql
149
- SELECT save_my_entity(1, '{"name": "Test"}'::jsonb); -- user_id first, then data
150
- ```
151
-
152
- ## Programmatic API
153
-
154
- ```javascript
155
- import { DZQLCompiler } from './src/compiler.js';
156
-
157
- const compiler = new DZQLCompiler();
158
-
159
- // Compile from object
160
- const result = compiler.compile({
161
- tableName: 'posts',
162
- labelField: 'title',
163
- searchableFields: ['title', 'body'],
164
- permissionPaths: {
165
- view: [],
166
- update: ['@author_id']
167
- }
168
- });
169
-
170
- console.log(result.sql);
171
- console.log(result.checksum);
172
-
173
- // Compile from SQL
174
- import { readFileSync } from 'fs';
175
-
176
- const sql = readFileSync('entities/posts.sql', 'utf-8');
177
- const results = compiler.compileFromSQL(sql);
178
-
179
- for (const entity of results.results) {
180
- console.log(`Compiled ${entity.tableName}: ${entity.checksum}`);
181
- }
182
- ```
183
-
184
- ## Verifying Compilation
185
-
186
- ### Check Checksums
187
-
188
- ```javascript
189
- import { readFileSync } from 'fs';
190
-
191
- const checksums = JSON.parse(readFileSync('compiled/checksums.json', 'utf-8'));
192
-
193
- console.log(checksums.venues);
194
- // {
195
- // checksum: "9c116484...",
196
- // generatedAt: "2025-11-16T01:38:54.321Z",
197
- // compilationTime: 12
198
- // }
199
- ```
200
-
201
- ### Test Functions
202
-
203
- ```sql
204
- -- Test permission check (p_user_id first)
205
- SELECT can_update_venues(42, '{"org_id": 1}'::jsonb);
206
-
207
- -- Test GET with FK expansion (p_user_id first, then p_id)
208
- SELECT get_venues(42, 1);
209
- -- Returns: { id: 1, name: "...", org: { id: 1, name: "..." }, sites: [...] }
210
-
211
- -- Test SEARCH (p_user_id first)
212
- SELECT search_venues(42, '{}', 'garden', null, 1, 10);
213
- -- Returns: { data: [...], total: 5, page: 1, limit: 10 }
214
- ```
215
-
216
- ## Common Patterns
217
-
218
- ### Public Read, Owner Write
219
-
220
- ```sql
221
- select dzql.register_entity(
222
- 'blog_posts',
223
- 'title',
224
- array['title', 'body'],
225
- '{}',
226
- false,
227
- '{}',
228
- '{}',
229
- jsonb_build_object(
230
- 'view', array[]::text[], -- anyone can read
231
- 'create', array[]::text[], -- anyone can create
232
- 'update', array['@author_id'], -- only author can update
233
- 'delete', array['@author_id'] -- only author can delete
234
- )
235
- );
236
- ```
237
-
238
- ### Organization-Scoped
239
-
240
- ```sql
241
- select dzql.register_entity(
242
- 'projects',
243
- 'name',
244
- array['name', 'description'],
245
- '{"org": "organisations"}',
246
- false,
247
- '{}',
248
- '{}',
249
- jsonb_build_object(
250
- 'view', array['@org_id->members[org_id=$]{active}.user_id'],
251
- 'update', array['@org_id->members[org_id=$,role=admin]{active}.user_id'],
252
- 'delete', array['@org_id->members[org_id=$,role=admin]{active}.user_id'],
253
- 'create', array['@org_id->members[org_id=$]{active}.user_id']
254
- )
255
- );
256
- ```
257
-
258
- ### Temporal Data
259
-
260
- ```sql
261
- select dzql.register_entity(
262
- 'memberships',
263
- 'user_id',
264
- array['user_id', 'org_id'],
265
- '{"user": "users", "org": "organisations"}',
266
- false,
267
- '{"valid_from": "valid_from", "valid_to": "valid_to"}', -- temporal!
268
- '{}',
269
- '{}'
270
- );
271
- ```
272
-
273
- ## Debugging
274
-
275
- ### View Generated SQL
276
-
277
- ```bash
278
- # Pretty print generated SQL
279
- cat compiled/venues.sql | less
280
-
281
- # Search for specific function
282
- grep -A 20 "CREATE OR REPLACE FUNCTION get_venues" compiled/venues.sql
283
- ```
284
-
285
- ### Check Compilation Errors
286
-
287
- ```bash
288
- # Compile with verbose output
289
- DZQL_COMPILER_VERBOSE=true bun src/cli/index.js entities/my_entity.sql -o compiled/
290
- ```
291
-
292
- ### Test in PostgreSQL
293
-
294
- ```sql
295
- -- Enable query logging
296
- SET log_statement = 'all';
297
-
298
- -- Test function (p_user_id first)
299
- SELECT get_venues(42, 1);
300
-
301
- -- View execution plan
302
- EXPLAIN ANALYZE SELECT get_venues(42, 1);
303
- ```
304
-
305
- ## Next Steps
306
-
307
- 1. **Compile existing entities** - Try compiling your current DZQL entities
308
- 2. **Review generated SQL** - Understand what the compiler produces
309
- 3. **Test in staging** - Deploy to a test database and verify behavior
310
- 4. **Benchmark performance** - Compare runtime vs compiled versions
311
- 5. **Report issues** - Let us know what works and what doesn't!
312
-
313
- ## Need Help?
314
-
315
- - **README.md** - Complete documentation
316
- - **SUMMARY.md** - What was built and how
317
- - **tests/compiler.test.js** - Usage examples
318
- - **examples/compiled/** - Real compiled output
319
-
320
- ## Resources
321
-
322
- - Vision document: `/home/user/dzql/vision.md`
323
- - Current DZQL: `/home/user/dzql/packages/dzql/`
324
- - Example apps: `/home/user/dzql/packages/venues/`
325
-
326
- Happy compiling! 🚀
@@ -1,134 +0,0 @@
1
- # DZQL Compiler Documentation
2
-
3
- The DZQL Compiler transforms declarative entity definitions into optimized PostgreSQL stored procedures.
4
-
5
- ## Quick Start
6
-
7
- - **[Quickstart Guide](QUICKSTART.md)** - Get started with the compiler in 5 minutes
8
-
9
- ## Reference
10
-
11
- - **[Advanced Filters](ADVANCED_FILTERS.md)** - Complex search operators and patterns
12
- - **[Coding Standards](CODING_STANDARDS.md)** - Best practices for DZQL code
13
- - **[Comparison](COMPARISON.md)** - Runtime vs compiled side-by-side
14
-
15
- ## Using the Compiler
16
-
17
- ### Via CLI
18
-
19
- ```bash
20
- dzql compile database/domain.sql -o compiled/
21
- ```
22
-
23
- ### Programmatically
24
-
25
- ```javascript
26
- import { DZQLCompiler } from 'dzql/compiler';
27
-
28
- const compiler = new DZQLCompiler();
29
- const result = compiler.compileFromSQL(sqlContent);
30
-
31
- console.log(result.sql); // Generated PostgreSQL
32
- ```
33
-
34
- ### Registering Entities
35
-
36
- ```sql
37
- SELECT dzql.register_entity(
38
- 'todos', -- Table name
39
- 'title', -- Label field
40
- array['title', 'description'], -- Searchable fields
41
- '{}'::jsonb, -- FK includes
42
- false, -- Soft delete
43
- '{}'::jsonb, -- Temporal config
44
- '{}'::jsonb, -- Notification paths
45
- '{}'::jsonb, -- Permission paths
46
- '{}'::jsonb, -- Graph rules (including M2M)
47
- '{}'::jsonb -- Field defaults
48
- );
49
- ```
50
-
51
- This generates 5 PostgreSQL functions:
52
- - `get_todos(params, user_id)` - Retrieve single record
53
- - `save_todos(params, user_id)` - Create or update
54
- - `delete_todos(params, user_id)` - Delete record
55
- - `lookup_todos(params, user_id)` - Autocomplete
56
- - `search_todos(params, user_id)` - Search with filters
57
-
58
- ## Compiler Features (v0.3.1+)
59
-
60
- The compiler generates **static, optimized SQL** with zero runtime interpretation:
61
-
62
- ### Many-to-Many Relationships
63
- ```sql
64
- SELECT dzql.register_entity(
65
- 'brands', 'name', ARRAY['name'],
66
- '{}', false, '{}', '{}', '{}',
67
- '{
68
- "many_to_many": {
69
- "tags": {
70
- "junction_table": "brand_tags",
71
- "local_key": "brand_id",
72
- "foreign_key": "tag_id",
73
- "target_entity": "tags",
74
- "id_field": "tag_ids",
75
- "expand": false
76
- }
77
- }
78
- }',
79
- '{}'
80
- );
81
- ```
82
-
83
- **Generated code:** Static M2M sync blocks (50-100x faster than generic operations)
84
- - No runtime loops
85
- - All table/column names are literals
86
- - PostgreSQL can fully optimize and cache plans
87
-
88
- See [Many-to-Many Guide](../guides/many-to-many.md) for details.
89
-
90
- ### Composite Primary Keys
91
- ```sql
92
- SELECT dzql.register_entity(
93
- 'product_task_template_dependencies', 'template_id', ARRAY[]::text[],
94
- '{}', false, '{}', '{}', '{}',
95
- '{
96
- "primary_key": ["template_id", "depends_on_template_id"]
97
- }',
98
- '{}'
99
- );
100
- ```
101
-
102
- **Generated code:** Event records use all primary key columns
103
- - Default assumes `id` column
104
- - Composite keys generate `jsonb_build_object('col1', v_result.col1, 'col2', v_result.col2)`
105
- - Required for junction tables and other composite PK scenarios
106
-
107
- ### Field Defaults
108
- ```sql
109
- '{
110
- "owner_id": "@user_id",
111
- "created_at": "@now",
112
- "status": "draft"
113
- }'
114
- ```
115
-
116
- **Generated code:** Auto-populates fields on INSERT
117
-
118
- See [Field Defaults Guide](../guides/field-defaults.md) for details.
119
-
120
- ## Architecture
121
-
122
- The compiler uses a three-phase approach:
123
-
124
- 1. **Parse** - Extract entity definitions from SQL
125
- 2. **Generate** - Create optimized PostgreSQL functions
126
- 3. **Deploy** - Execute generated SQL
127
-
128
- All business logic runs in PostgreSQL, not application code.
129
-
130
- ## See Also
131
-
132
- - [Main Documentation](../) - Full DZQL documentation
133
- - [API Reference](../reference/api.md) - The 5 operations
134
- - [For AI](../for-ai/claude-guide.md) - AI-assisted development
@@ -1,38 +0,0 @@
1
- # DZQL Examples
2
-
3
- SQL examples demonstrating DZQL entity registration patterns.
4
-
5
- ## Files
6
-
7
- ### blog.sql
8
- A complete blog application with:
9
- - Multiple entities (users, posts, comments, tags)
10
- - Many-to-many relationships (posts ↔ tags)
11
- - Soft delete
12
- - FK includes
13
- - Permission paths
14
- - Notification paths
15
-
16
- ### venue-detail-simple.sql
17
- Basic subscribable definition for venue data.
18
-
19
- ### venue-detail-subscribable.sql
20
- Full subscribable with relations and permission paths. Demonstrates:
21
- - Root entity with FK includes
22
- - Child entity filtering
23
- - Permission path syntax
24
-
25
- ## Usage
26
-
27
- These files are meant to be run after DZQL core migrations. See the [Tutorial](../getting-started/tutorial.md) for complete setup instructions.
28
-
29
- ```bash
30
- # After setting up your database with DZQL migrations
31
- psql $DATABASE_URL < examples/blog.sql
32
- ```
33
-
34
- ## See Also
35
-
36
- - [API Reference](../reference/api.md) - Entity registration parameters
37
- - [Many-to-Many Guide](../guides/many-to-many.md) - M2M configuration
38
- - [Subscriptions Guide](../guides/subscriptions.md) - Subscribable patterns
@@ -1,160 +0,0 @@
1
- -- ============================================================================
2
- -- Blog Application Example
3
- -- ============================================================================
4
- --
5
- -- This example demonstrates:
6
- -- - Multiple related entities (users, posts, comments, tags)
7
- -- - Many-to-many relationships (posts <-> tags via post_tags junction)
8
- -- - Soft delete (posts.deleted_at)
9
- -- - FK includes (dereferencing author, post)
10
- -- - Permission paths (author can edit/delete own content)
11
- -- - Notification paths (notify post author when comments added)
12
- --
13
- -- To use this example:
14
- -- 1. Create tables first (see CREATE TABLE statements below)
15
- -- 2. Run the dzql.register_entity() calls to enable CRUD operations
16
- -- 3. Use the generated API: save_posts, get_posts, search_posts, etc.
17
- --
18
- -- For a complete working example with Docker, tests, and frontend:
19
- -- See packages/blog/ in the DZQL repository
20
- --
21
- -- ============================================================================
22
-
23
- -- Create tables
24
- CREATE TABLE IF NOT EXISTS users (
25
- id SERIAL PRIMARY KEY,
26
- name VARCHAR(255) NOT NULL,
27
- email VARCHAR(255) UNIQUE NOT NULL,
28
- password_hash TEXT NOT NULL,
29
- created_at TIMESTAMP DEFAULT NOW()
30
- );
31
-
32
- CREATE TABLE IF NOT EXISTS posts (
33
- id SERIAL PRIMARY KEY,
34
- title VARCHAR(500) NOT NULL,
35
- content TEXT NOT NULL,
36
- summary TEXT,
37
- author_id INT REFERENCES users(id),
38
- created_at TIMESTAMP DEFAULT NOW(),
39
- deleted_at TIMESTAMP
40
- );
41
-
42
- CREATE TABLE IF NOT EXISTS comments (
43
- id SERIAL PRIMARY KEY,
44
- content TEXT NOT NULL,
45
- post_id INT REFERENCES posts(id),
46
- author_id INT REFERENCES users(id),
47
- created_at TIMESTAMP DEFAULT NOW()
48
- );
49
-
50
- -- Tags table for categorizing posts
51
- CREATE TABLE IF NOT EXISTS tags (
52
- id SERIAL PRIMARY KEY,
53
- name VARCHAR(50) UNIQUE NOT NULL,
54
- color VARCHAR(7) DEFAULT '#3788d8'
55
- );
56
-
57
- -- Junction table for post-tag many-to-many relationship
58
- CREATE TABLE IF NOT EXISTS post_tags (
59
- post_id INT NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
60
- tag_id INT NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
61
- PRIMARY KEY (post_id, tag_id)
62
- );
63
-
64
- CREATE INDEX IF NOT EXISTS idx_post_tags_post_id ON post_tags(post_id);
65
- CREATE INDEX IF NOT EXISTS idx_post_tags_tag_id ON post_tags(tag_id);
66
-
67
- -- ============================================================================
68
- -- DZQL Entity Registrations
69
- -- ============================================================================
70
-
71
- -- Users entity - blog authors
72
- select dzql.register_entity(
73
- 'users',
74
- 'name',
75
- array['name', 'email'],
76
- '{}', -- no FK includes
77
- false, -- hard delete
78
- '{}', -- no reverse FK
79
- '{}', -- no notifications
80
- jsonb_build_object(
81
- 'view', array[]::text[], -- Anyone can view users
82
- 'create', array[]::text[], -- Anyone can register
83
- 'update', array['@id'], -- Only update own profile
84
- 'delete', array['@id'] -- Only delete own account
85
- )
86
- );
87
-
88
- -- Register tags entity first
89
- select dzql.register_entity(
90
- 'tags',
91
- 'name',
92
- array['name'],
93
- '{}', -- no FK includes
94
- false, -- hard delete
95
- '{}', -- no temporal
96
- '{}', -- no notifications
97
- jsonb_build_object(
98
- 'view', array[]::text[], -- Anyone can view tags
99
- 'create', array[]::text[], -- Anyone can create tags
100
- 'update', array[]::text[], -- Anyone can update tags
101
- 'delete', array[]::text[] -- Anyone can delete tags
102
- )
103
- );
104
-
105
- -- Posts entity - blog posts with M2M tags
106
- select dzql.register_entity(
107
- 'posts',
108
- 'title',
109
- array['title', 'content', 'summary'],
110
- jsonb_build_object(
111
- 'author', 'users' -- FK to users
112
- ),
113
- true, -- soft delete (deleted_at)
114
- '{}', -- no temporal
115
- '{}', -- no notification paths
116
- jsonb_build_object(
117
- 'view', array[]::text[], -- Anyone can view posts
118
- 'create', array[]::text[], -- Anyone can create posts
119
- 'update', array['@author_id'], -- Only author can update
120
- 'delete', array['@author_id'] -- Only author can delete
121
- ),
122
- jsonb_build_object(
123
- 'many_to_many', jsonb_build_object(
124
- 'tags', jsonb_build_object(
125
- 'junction_table', 'post_tags',
126
- 'local_key', 'post_id',
127
- 'foreign_key', 'tag_id',
128
- 'target_entity', 'tags',
129
- 'id_field', 'tag_ids',
130
- 'expand', true -- Include full tag objects in response
131
- )
132
- )
133
- ) -- graph_rules with M2M
134
- );
135
-
136
- -- Comments entity - blog comments
137
- select dzql.register_entity(
138
- 'comments',
139
- 'content',
140
- array['content'],
141
- jsonb_build_object(
142
- 'post', 'posts',
143
- 'author', 'users'
144
- ),
145
- false, -- hard delete
146
- '{}', -- no reverse FK
147
- jsonb_build_object(
148
- 'post_author', array['@post_id->posts.author_id'],
149
- 'commenters', array['@post_id']
150
- ),
151
- jsonb_build_object(
152
- 'view', array[]::text[], -- Anyone can view comments
153
- 'create', array[]::text[], -- Anyone can comment
154
- 'update', array['@author_id'], -- Only author can update
155
- 'delete', array[
156
- '@author_id', -- Author can delete
157
- '@post_id->posts.author_id' -- Post author can delete
158
- ]
159
- )
160
- );
@@ -1,8 +0,0 @@
1
- -- Simplified test subscribable for initial testing
2
- SELECT dzql.register_subscribable(
3
- 'venue_detail',
4
- '{"subscribe": ["@org_id->acts_for[org_id=$]{active}.user_id"]}'::jsonb,
5
- '{"venue_id": "int"}'::jsonb,
6
- 'venues',
7
- '{"org": "organisations", "sites": {"entity": "sites", "filter": "venue_id=$venue_id"}}'::jsonb
8
- );
@@ -1,45 +0,0 @@
1
- -- Example: Venue Detail Subscribable
2
- -- This subscribable builds a denormalized document containing:
3
- -- - The venue record
4
- -- - The organization (FK expanded)
5
- -- - All sites belonging to the venue
6
- -- - All packages with their allocations
7
-
8
- SELECT dzql.register_subscribable(
9
- 'venue_detail',
10
-
11
- -- Permission: who can subscribe?
12
- -- Users who act_for the venue's organization (active roles only)
13
- jsonb_build_object(
14
- 'subscribe', ARRAY['@org_id->acts_for[org_id=$]{active}.user_id']
15
- ),
16
-
17
- -- Parameters: subscription key
18
- jsonb_build_object(
19
- 'venue_id', 'int'
20
- ),
21
-
22
- -- Root entity
23
- 'venues',
24
-
25
- -- Relations to include in document
26
- jsonb_build_object(
27
- -- FK expansion: organisation
28
- 'org', 'organisations',
29
-
30
- -- Child collection: sites
31
- 'sites', jsonb_build_object(
32
- 'entity', 'sites',
33
- 'filter', 'venue_id=$venue_id'
34
- ),
35
-
36
- -- Child collection: packages with nested allocations
37
- 'packages', jsonb_build_object(
38
- 'entity', 'packages',
39
- 'filter', 'venue_id=$venue_id',
40
- 'include', jsonb_build_object(
41
- 'allocations', 'allocations'
42
- )
43
- )
44
- )
45
- );