dzql 0.5.33 → 0.6.1

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 (142) 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 +309 -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 +653 -0
  20. package/docs/project-setup.md +456 -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 +166 -0
  39. package/src/client/index.ts +1 -0
  40. package/src/client/ws.ts +286 -0
  41. package/src/runtime/auth.ts +39 -0
  42. package/src/runtime/db.ts +33 -0
  43. package/src/runtime/errors.ts +51 -0
  44. package/src/runtime/index.ts +98 -0
  45. package/src/runtime/js_functions.ts +63 -0
  46. package/src/runtime/manifest_loader.ts +29 -0
  47. package/src/runtime/namespace.ts +483 -0
  48. package/src/runtime/server.ts +87 -0
  49. package/src/runtime/ws.ts +197 -0
  50. package/src/shared/ir.ts +197 -0
  51. package/tests/client.test.ts +38 -0
  52. package/tests/codegen.test.ts +71 -0
  53. package/tests/compiler.test.ts +45 -0
  54. package/tests/graph_rules.test.ts +173 -0
  55. package/tests/integration/db.test.ts +174 -0
  56. package/tests/integration/e2e.test.ts +65 -0
  57. package/tests/integration/features.test.ts +922 -0
  58. package/tests/integration/full_stack.test.ts +262 -0
  59. package/tests/integration/setup.ts +45 -0
  60. package/tests/ir.test.ts +32 -0
  61. package/tests/namespace.test.ts +395 -0
  62. package/tests/permissions.test.ts +55 -0
  63. package/tests/pinia.test.ts +48 -0
  64. package/tests/realtime.test.ts +22 -0
  65. package/tests/runtime.test.ts +80 -0
  66. package/tests/subscribable_gen.test.ts +72 -0
  67. package/tests/subscribable_reactivity.test.ts +258 -0
  68. package/tests/venues_gen.test.ts +25 -0
  69. package/tsconfig.json +20 -0
  70. package/tsconfig.tsbuildinfo +1 -0
  71. package/README.md +0 -90
  72. package/bin/cli.js +0 -727
  73. package/docs/compiler/ADVANCED_FILTERS.md +0 -183
  74. package/docs/compiler/CODING_STANDARDS.md +0 -415
  75. package/docs/compiler/COMPARISON.md +0 -673
  76. package/docs/compiler/QUICKSTART.md +0 -326
  77. package/docs/compiler/README.md +0 -134
  78. package/docs/examples/README.md +0 -38
  79. package/docs/examples/blog.sql +0 -160
  80. package/docs/examples/venue-detail-simple.sql +0 -8
  81. package/docs/examples/venue-detail-subscribable.sql +0 -45
  82. package/docs/for-ai/claude-guide.md +0 -1210
  83. package/docs/getting-started/quickstart.md +0 -125
  84. package/docs/getting-started/subscriptions-quick-start.md +0 -203
  85. package/docs/getting-started/tutorial.md +0 -1104
  86. package/docs/guides/atomic-updates.md +0 -299
  87. package/docs/guides/client-stores.md +0 -730
  88. package/docs/guides/composite-primary-keys.md +0 -158
  89. package/docs/guides/custom-functions.md +0 -362
  90. package/docs/guides/drop-semantics.md +0 -554
  91. package/docs/guides/field-defaults.md +0 -240
  92. package/docs/guides/interpreter-vs-compiler.md +0 -237
  93. package/docs/guides/many-to-many.md +0 -929
  94. package/docs/guides/subscriptions.md +0 -537
  95. package/docs/reference/api.md +0 -1373
  96. package/docs/reference/client.md +0 -224
  97. package/src/client/stores/index.js +0 -8
  98. package/src/client/stores/useAppStore.js +0 -285
  99. package/src/client/stores/useWsStore.js +0 -289
  100. package/src/client/ws.js +0 -762
  101. package/src/compiler/cli/compile-example.js +0 -33
  102. package/src/compiler/cli/compile-subscribable.js +0 -43
  103. package/src/compiler/cli/debug-compile.js +0 -44
  104. package/src/compiler/cli/debug-parse.js +0 -26
  105. package/src/compiler/cli/debug-path-parser.js +0 -18
  106. package/src/compiler/cli/debug-subscribable-parser.js +0 -21
  107. package/src/compiler/cli/index.js +0 -174
  108. package/src/compiler/codegen/auth-codegen.js +0 -153
  109. package/src/compiler/codegen/drop-semantics-codegen.js +0 -553
  110. package/src/compiler/codegen/graph-rules-codegen.js +0 -450
  111. package/src/compiler/codegen/notification-codegen.js +0 -232
  112. package/src/compiler/codegen/operation-codegen.js +0 -1382
  113. package/src/compiler/codegen/permission-codegen.js +0 -318
  114. package/src/compiler/codegen/subscribable-codegen.js +0 -827
  115. package/src/compiler/compiler.js +0 -371
  116. package/src/compiler/index.js +0 -11
  117. package/src/compiler/parser/entity-parser.js +0 -440
  118. package/src/compiler/parser/path-parser.js +0 -290
  119. package/src/compiler/parser/subscribable-parser.js +0 -244
  120. package/src/database/dzql-core.sql +0 -161
  121. package/src/database/migrations/001_schema.sql +0 -60
  122. package/src/database/migrations/002_functions.sql +0 -890
  123. package/src/database/migrations/003_operations.sql +0 -1135
  124. package/src/database/migrations/004_search.sql +0 -581
  125. package/src/database/migrations/005_entities.sql +0 -730
  126. package/src/database/migrations/006_auth.sql +0 -94
  127. package/src/database/migrations/007_events.sql +0 -133
  128. package/src/database/migrations/008_hello.sql +0 -18
  129. package/src/database/migrations/008a_meta.sql +0 -172
  130. package/src/database/migrations/009_subscriptions.sql +0 -240
  131. package/src/database/migrations/010_atomic_updates.sql +0 -157
  132. package/src/database/migrations/010_fix_m2m_events.sql +0 -94
  133. package/src/index.js +0 -40
  134. package/src/server/api.js +0 -9
  135. package/src/server/db.js +0 -442
  136. package/src/server/index.js +0 -317
  137. package/src/server/logger.js +0 -259
  138. package/src/server/mcp.js +0 -594
  139. package/src/server/meta-route.js +0 -251
  140. package/src/server/namespace.js +0 -292
  141. package/src/server/subscriptions.js +0 -351
  142. package/src/server/ws.js +0 -573
@@ -1,125 +0,0 @@
1
- # DZQL Quick Start
2
-
3
- Get a real-time API with automatic CRUD in 5 minutes.
4
-
5
- ## Prerequisites
6
-
7
- - PostgreSQL (local or Docker)
8
- - Bun or Node.js 18+
9
-
10
- ## 1. Install
11
-
12
- ```bash
13
- mkdir my-app && cd my-app
14
- bun init -y
15
- bun add dzql
16
- ```
17
-
18
- ## 2. Start PostgreSQL
19
-
20
- ```bash
21
- docker run -d --name dzql-db \
22
- -e POSTGRES_USER=dzql \
23
- -e POSTGRES_PASSWORD=dzql \
24
- -e POSTGRES_DB=dzql \
25
- -p 5432:5432 \
26
- postgres:latest
27
-
28
- export DATABASE_URL="postgresql://dzql:dzql@localhost:5432/dzql"
29
- ```
30
-
31
- ## 3. Initialize Database
32
-
33
- ```bash
34
- bunx dzql db:init
35
- ```
36
-
37
- ## 4. Define Entities
38
-
39
- Create `entities.sql`:
40
-
41
- ```sql
42
- -- Schema
43
- CREATE TABLE users (
44
- id SERIAL PRIMARY KEY,
45
- email TEXT UNIQUE NOT NULL,
46
- name TEXT,
47
- created_at TIMESTAMPTZ DEFAULT now()
48
- );
49
-
50
- CREATE TABLE todos (
51
- id SERIAL PRIMARY KEY,
52
- title TEXT NOT NULL,
53
- completed BOOLEAN DEFAULT false,
54
- user_id INT REFERENCES users(id),
55
- created_at TIMESTAMPTZ DEFAULT now()
56
- );
57
-
58
- -- Register with DZQL
59
- SELECT dzql.register_entity('users', 'name', ARRAY['name', 'email']);
60
- SELECT dzql.register_entity('todos', 'title', ARRAY['title']);
61
- ```
62
-
63
- ## 5. Compile
64
-
65
- ```bash
66
- bunx dzql compile entities.sql -o init_db/
67
- ```
68
-
69
- ## 6. Apply
70
-
71
- ```bash
72
- psql $DATABASE_URL -f init_db/001_schema.sql
73
- psql $DATABASE_URL -f init_db/users.sql
74
- psql $DATABASE_URL -f init_db/todos.sql
75
- ```
76
-
77
- ## 7. Create Server
78
-
79
- Create `index.js`:
80
-
81
- ```javascript
82
- import { createServer } from 'dzql/server';
83
-
84
- createServer({ port: 3000 });
85
- console.log('Server running at http://localhost:3000');
86
- ```
87
-
88
- ## 8. Use
89
-
90
- ```javascript
91
- import { WebSocketManager } from 'dzql/client';
92
-
93
- const ws = new WebSocketManager();
94
- await ws.connect();
95
-
96
- // Auto-generated CRUD
97
- const todo = await ws.api.save.todos({ title: 'Buy milk' });
98
- const todos = await ws.api.search.todos({});
99
- await ws.api.save.todos({ id: todo.id, completed: true });
100
- await ws.api.delete.todos({ id: todo.id });
101
-
102
- // Real-time updates
103
- ws.onBroadcast((method, params) => {
104
- console.log('Change:', method, params);
105
- });
106
- ```
107
-
108
- ## What You Get
109
-
110
- For each entity:
111
- - `get_<entity>(user_id, id)` - Get by ID
112
- - `save_<entity>(user_id, data)` - Create or update
113
- - `delete_<entity>(user_id, id)` - Delete
114
- - `search_<entity>(user_id, filters, search, sort, page, limit)` - Search
115
-
116
- Plus:
117
- - Real-time updates via WebSocket
118
- - Permission checks in SQL
119
- - Audit trail in `dzql.events`
120
-
121
- ## Next Steps
122
-
123
- - [Full Tutorial](./tutorial.md) - Complete walkthrough
124
- - [Subscriptions](./subscriptions-quick-start.md) - Real-time denormalized documents
125
- - [API Reference](../reference/api.md) - All operations
@@ -1,203 +0,0 @@
1
- # Live Query Subscriptions - Quick Start
2
-
3
- Get up and running with live query subscriptions in 5 minutes.
4
-
5
- ## Step 1: Create a Subscribable (2 min)
6
-
7
- Create `my_subscribable.sql`:
8
-
9
- ```sql
10
- SELECT dzql.register_subscribable(
11
- 'venue_detail', -- Name (use in API)
12
- '{"subscribe": ["@org_id->acts_for[org_id=$]{active}.user_id"]}'::jsonb, -- Who can subscribe
13
- '{"venue_id": "int"}'::jsonb, -- Subscription parameters
14
- 'venues', -- Root table
15
- '{"org": "organisations", "sites": {"entity": "sites", "filter": "venue_id=$venue_id"}}'::jsonb -- Related data
16
- );
17
- ```
18
-
19
- ## Step 2: Compile and Deploy (1 min)
20
-
21
- ```bash
22
- # Compile to PostgreSQL functions
23
- bun packages/dzql/src/compiler/cli/compile-subscribable.js my_subscribable.sql | psql $DATABASE_URL
24
- ```
25
-
26
- This creates 3 functions:
27
- - `venue_detail_can_subscribe(user_id, params)` - permission check
28
- - `get_venue_detail(params, user_id)` - query builder
29
- - `venue_detail_affected_documents(table, op, old, new)` - change detector
30
-
31
- ## Step 3: Subscribe from Client (2 min)
32
-
33
- ```javascript
34
- import { WebSocketManager } from '@dzql/client';
35
-
36
- const ws = new WebSocketManager('ws://localhost:3000/ws');
37
- await ws.connect();
38
-
39
- // Subscribe - get initial data + live updates
40
- const { data, unsubscribe } = await ws.api.subscribe_venue_detail(
41
- { venue_id: 123 },
42
- (updatedData) => {
43
- console.log('Venue changed!', updatedData);
44
- }
45
- );
46
-
47
- console.log('Initial data:', data);
48
-
49
- // Later: cleanup
50
- await unsubscribe();
51
- ```
52
-
53
- ## That's It!
54
-
55
- Your client now receives real-time updates whenever:
56
- - The venue record changes
57
- - Related organisation changes
58
- - Related sites change
59
-
60
- All change detection happens in PostgreSQL - zero configuration needed on the server!
61
-
62
- ## Next Steps
63
-
64
- - [Full Documentation](../guides/subscriptions.md)
65
- - [Permission Paths Guide](../../../../docs/architecture/PERMISSIONS.md)
66
- - [API Reference](../reference/api.md)
67
-
68
- ## Common Patterns
69
-
70
- ### Simple Document (Single Table)
71
-
72
- ```sql
73
- SELECT dzql.register_subscribable(
74
- 'user_settings',
75
- '{"subscribe": ["@user_id"]}'::jsonb, -- Only owner
76
- '{"user_id": "int"}'::jsonb,
77
- 'user_settings',
78
- '{}'::jsonb -- No relations
79
- );
80
- ```
81
-
82
- ### With One Relation
83
-
84
- ```sql
85
- SELECT dzql.register_subscribable(
86
- 'booking_summary',
87
- '{"subscribe": ["@user_id"]}'::jsonb,
88
- '{"booking_id": "int"}'::jsonb,
89
- 'bookings',
90
- '{"venue": "venues"}'::jsonb -- Include venue
91
- );
92
- ```
93
-
94
- ### With Filtered Relations
95
-
96
- ```sql
97
- SELECT dzql.register_subscribable(
98
- 'organisation_dashboard',
99
- '{"subscribe": ["@id->acts_for[org_id=$]{active}.user_id"]}'::jsonb,
100
- '{"org_id": "int"}'::jsonb,
101
- 'organisations',
102
- '{
103
- "members": {
104
- "entity": "acts_for",
105
- "filter": "org_id=$org_id AND valid_to IS NULL"
106
- },
107
- "venues": {
108
- "entity": "venues",
109
- "filter": "org_id=$org_id"
110
- }
111
- }'::jsonb
112
- );
113
- ```
114
-
115
- ### Multiple Permission Paths (OR logic)
116
-
117
- ```sql
118
- SELECT dzql.register_subscribable(
119
- 'venue_admin',
120
- '{
121
- "subscribe": [
122
- "@owner_id", -- Direct owner
123
- "@org_id->acts_for[org_id=$]{active}.user_id" -- OR org member
124
- ]
125
- }'::jsonb,
126
- '{"venue_id": "int"}'::jsonb,
127
- 'venues',
128
- '{"sites": {"entity": "sites", "filter": "venue_id=$venue_id"}}'::jsonb
129
- );
130
- ```
131
-
132
- ## Debugging Tips
133
-
134
- ### Test the functions manually:
135
-
136
- ```sql
137
- -- Check permission
138
- SELECT venue_detail_can_subscribe(1, '{"venue_id": 123}'::jsonb);
139
-
140
- -- Get data
141
- SELECT get_venue_detail('{"venue_id": 123}'::jsonb, 1);
142
-
143
- -- Test change detection
144
- SELECT venue_detail_affected_documents(
145
- 'venues',
146
- 'update',
147
- '{"id": 123}'::jsonb,
148
- '{"id": 123, "name": "New"}'::jsonb
149
- );
150
- ```
151
-
152
- ### Check active subscriptions:
153
-
154
- ```javascript
155
- // Client-side
156
- console.log('My subscriptions:', ws.subscriptions.size);
157
- ```
158
-
159
- ## FAQ
160
-
161
- **Q: When should I use subscriptions vs. simple queries?**
162
- A: Use subscriptions when data changes frequently and client needs to stay in sync. Use simple queries for one-time lookups.
163
-
164
- **Q: What happens when client disconnects?**
165
- A: Server automatically cleans up all subscriptions for that connection.
166
-
167
- **Q: Can multiple clients subscribe to the same data?**
168
- A: Yes! Each subscription is independent. All will receive updates.
169
-
170
- **Q: How do I update the subscribable definition?**
171
- A: Re-compile and deploy. The `register_subscribable()` call uses `ON CONFLICT UPDATE`, so it's safe to run repeatedly.
172
-
173
- **Q: What if the underlying data is deleted?**
174
- A: The `get_<name>()` function returns `null`. Handle this in your callback:
175
- ```javascript
176
- (data) => {
177
- if (!data) {
178
- console.log('Record was deleted');
179
- return;
180
- }
181
- updateUI(data);
182
- }
183
- ```
184
-
185
- **Q: How do I subscribe to a list of items?**
186
- A: Create a subscribable with array parameters or use multiple subscriptions. For dashboard-style views, consider a single subscribable that returns an array.
187
-
188
- ## Performance Tips
189
-
190
- 1. **Index your joins**: Make sure foreign keys are indexed
191
- 2. **Keep _affected_documents() simple**: Early return for unrelated tables
192
- 3. **Limit relation depth**: Avoid deeply nested relations (max 2-3 levels)
193
- 4. **Use specific subscription keys**: `venue_id` is better than `org_id` (fewer false positives)
194
- 5. **Unsubscribe when done**: Always cleanup to free server resources
195
-
196
- ## Architecture Benefits
197
-
198
- - ✅ **PostgreSQL-First**: All logic in database, not application code
199
- - ✅ **Zero Configuration**: No server changes needed for new subscribables
200
- - ✅ **Type Safe**: Compiled functions validated at deploy time
201
- - ✅ **Efficient**: In-memory registry, PostgreSQL does matching
202
- - ✅ **Secure**: Permission paths enforced at database level
203
- - ✅ **Scalable**: Stateless server, can add instances freely