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.
- package/.env.sample +28 -0
- package/compose.yml +28 -0
- package/dist/client/index.ts +1 -0
- package/dist/client/stores/useMyProfileStore.ts +114 -0
- package/dist/client/stores/useOrgDashboardStore.ts +131 -0
- package/dist/client/stores/useVenueDetailStore.ts +117 -0
- package/dist/client/ws.ts +716 -0
- package/dist/db/migrations/000_core.sql +92 -0
- package/dist/db/migrations/20251229T212912022Z_schema.sql +3020 -0
- package/dist/db/migrations/20251229T212912022Z_subscribables.sql +371 -0
- package/dist/runtime/manifest.json +1562 -0
- package/docs/README.md +293 -36
- package/docs/feature-requests/applyPatch-bug-report.md +85 -0
- package/docs/feature-requests/connection-ready-profile.md +57 -0
- package/docs/feature-requests/hidden-bug-report.md +111 -0
- package/docs/feature-requests/hidden-fields-subscribables.md +34 -0
- package/docs/feature-requests/subscribable-param-key-bug.md +38 -0
- package/docs/feature-requests/todo.md +146 -0
- package/docs/for_ai.md +641 -0
- package/docs/project-setup.md +432 -0
- package/examples/blog.ts +50 -0
- package/examples/invalid.ts +18 -0
- package/examples/venues.js +485 -0
- package/package.json +23 -60
- package/src/cli/codegen/client.ts +99 -0
- package/src/cli/codegen/manifest.ts +95 -0
- package/src/cli/codegen/pinia.ts +174 -0
- package/src/cli/codegen/realtime.ts +58 -0
- package/src/cli/codegen/sql.ts +698 -0
- package/src/cli/codegen/subscribable_sql.ts +547 -0
- package/src/cli/codegen/subscribable_store.ts +184 -0
- package/src/cli/codegen/types.ts +142 -0
- package/src/cli/compiler/analyzer.ts +52 -0
- package/src/cli/compiler/graph_rules.ts +251 -0
- package/src/cli/compiler/ir.ts +233 -0
- package/src/cli/compiler/loader.ts +132 -0
- package/src/cli/compiler/permissions.ts +227 -0
- package/src/cli/index.ts +164 -0
- package/src/client/index.ts +1 -0
- package/src/client/ws.ts +286 -0
- package/src/create/.env.example +8 -0
- package/src/create/README.md +101 -0
- package/src/create/compose.yml +14 -0
- package/src/create/domain.ts +153 -0
- package/src/create/package.json +24 -0
- package/src/create/server.ts +18 -0
- package/src/create/setup.sh +11 -0
- package/src/create/tsconfig.json +15 -0
- package/src/runtime/auth.ts +39 -0
- package/src/runtime/db.ts +33 -0
- package/src/runtime/errors.ts +51 -0
- package/src/runtime/index.ts +98 -0
- package/src/runtime/js_functions.ts +63 -0
- package/src/runtime/manifest_loader.ts +29 -0
- package/src/runtime/namespace.ts +483 -0
- package/src/runtime/server.ts +87 -0
- package/src/runtime/ws.ts +197 -0
- package/src/shared/ir.ts +197 -0
- package/tests/client.test.ts +38 -0
- package/tests/codegen.test.ts +71 -0
- package/tests/compiler.test.ts +45 -0
- package/tests/graph_rules.test.ts +173 -0
- package/tests/integration/db.test.ts +174 -0
- package/tests/integration/e2e.test.ts +65 -0
- package/tests/integration/features.test.ts +922 -0
- package/tests/integration/full_stack.test.ts +262 -0
- package/tests/integration/setup.ts +45 -0
- package/tests/ir.test.ts +32 -0
- package/tests/namespace.test.ts +395 -0
- package/tests/permissions.test.ts +55 -0
- package/tests/pinia.test.ts +48 -0
- package/tests/realtime.test.ts +22 -0
- package/tests/runtime.test.ts +80 -0
- package/tests/subscribable_gen.test.ts +72 -0
- package/tests/subscribable_reactivity.test.ts +258 -0
- package/tests/venues_gen.test.ts +25 -0
- package/tsconfig.json +20 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/README.md +0 -90
- package/bin/cli.js +0 -727
- package/docs/compiler/ADVANCED_FILTERS.md +0 -183
- package/docs/compiler/CODING_STANDARDS.md +0 -415
- package/docs/compiler/COMPARISON.md +0 -673
- package/docs/compiler/QUICKSTART.md +0 -326
- package/docs/compiler/README.md +0 -134
- package/docs/examples/README.md +0 -38
- package/docs/examples/blog.sql +0 -160
- package/docs/examples/venue-detail-simple.sql +0 -8
- package/docs/examples/venue-detail-subscribable.sql +0 -45
- package/docs/for-ai/claude-guide.md +0 -1210
- package/docs/getting-started/quickstart.md +0 -125
- package/docs/getting-started/subscriptions-quick-start.md +0 -203
- package/docs/getting-started/tutorial.md +0 -1104
- package/docs/guides/atomic-updates.md +0 -299
- package/docs/guides/client-stores.md +0 -730
- package/docs/guides/composite-primary-keys.md +0 -158
- package/docs/guides/custom-functions.md +0 -362
- package/docs/guides/drop-semantics.md +0 -554
- package/docs/guides/field-defaults.md +0 -240
- package/docs/guides/interpreter-vs-compiler.md +0 -237
- package/docs/guides/many-to-many.md +0 -929
- package/docs/guides/subscriptions.md +0 -537
- package/docs/reference/api.md +0 -1373
- package/docs/reference/client.md +0 -224
- package/src/client/stores/index.js +0 -8
- package/src/client/stores/useAppStore.js +0 -285
- package/src/client/stores/useWsStore.js +0 -289
- package/src/client/ws.js +0 -762
- package/src/compiler/cli/compile-example.js +0 -33
- package/src/compiler/cli/compile-subscribable.js +0 -43
- package/src/compiler/cli/debug-compile.js +0 -44
- package/src/compiler/cli/debug-parse.js +0 -26
- package/src/compiler/cli/debug-path-parser.js +0 -18
- package/src/compiler/cli/debug-subscribable-parser.js +0 -21
- package/src/compiler/cli/index.js +0 -174
- package/src/compiler/codegen/auth-codegen.js +0 -153
- package/src/compiler/codegen/drop-semantics-codegen.js +0 -553
- package/src/compiler/codegen/graph-rules-codegen.js +0 -450
- package/src/compiler/codegen/notification-codegen.js +0 -232
- package/src/compiler/codegen/operation-codegen.js +0 -1382
- package/src/compiler/codegen/permission-codegen.js +0 -318
- package/src/compiler/codegen/subscribable-codegen.js +0 -827
- package/src/compiler/compiler.js +0 -371
- package/src/compiler/index.js +0 -11
- package/src/compiler/parser/entity-parser.js +0 -440
- package/src/compiler/parser/path-parser.js +0 -290
- package/src/compiler/parser/subscribable-parser.js +0 -244
- package/src/database/dzql-core.sql +0 -161
- package/src/database/migrations/001_schema.sql +0 -60
- package/src/database/migrations/002_functions.sql +0 -890
- package/src/database/migrations/003_operations.sql +0 -1135
- package/src/database/migrations/004_search.sql +0 -581
- package/src/database/migrations/005_entities.sql +0 -730
- package/src/database/migrations/006_auth.sql +0 -94
- package/src/database/migrations/007_events.sql +0 -133
- package/src/database/migrations/008_hello.sql +0 -18
- package/src/database/migrations/008a_meta.sql +0 -172
- package/src/database/migrations/009_subscriptions.sql +0 -240
- package/src/database/migrations/010_atomic_updates.sql +0 -157
- package/src/database/migrations/010_fix_m2m_events.sql +0 -94
- package/src/index.js +0 -40
- package/src/server/api.js +0 -9
- package/src/server/db.js +0 -442
- package/src/server/index.js +0 -317
- package/src/server/logger.js +0 -259
- package/src/server/mcp.js +0 -594
- package/src/server/meta-route.js +0 -251
- package/src/server/namespace.js +0 -292
- package/src/server/subscriptions.js +0 -351
- 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! 🚀
|
package/docs/compiler/README.md
DELETED
|
@@ -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
|
package/docs/examples/README.md
DELETED
|
@@ -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
|
package/docs/examples/blog.sql
DELETED
|
@@ -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
|
-
);
|