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
@@ -1,240 +0,0 @@
1
- # Field Defaults
2
-
3
- Auto-populate fields with default values during entity creation.
4
-
5
- ## Overview
6
-
7
- Field defaults allow you to automatically set field values when creating new records, eliminating the need for clients to manually send fields like `owner_id`, `created_at`, or `status` on every save operation.
8
-
9
- ## Benefits
10
-
11
- - **Less Client Code** - No need to send the same fields repeatedly
12
- - **Prevents Errors** - Can't forget required fields
13
- - **Enforces Security** - Server controls defaults (e.g., current user as owner)
14
- - **Cleaner API** - Focus on actual data, not boilerplate
15
-
16
- ## Configuration
17
-
18
- Field defaults are configured in the 10th parameter of `dzql.register_entity()`:
19
-
20
- ```sql
21
- SELECT dzql.register_entity(
22
- 'resources',
23
- 'title',
24
- ARRAY['title'],
25
- '{}', -- fk_includes
26
- false, -- soft_delete
27
- '{}', -- temporal_fields
28
- '{}', -- notification_paths
29
- '{}', -- permission_paths
30
- '{}', -- graph_rules
31
- '{
32
- "owner_id": "@user_id",
33
- "created_by": "@user_id",
34
- "created_at": "@now",
35
- "status": "draft"
36
- }' -- field_defaults (10th parameter)
37
- );
38
- ```
39
-
40
- ## Available Variables
41
-
42
- Field defaults support special variables that are resolved at runtime:
43
-
44
- | Variable | Value | Example Use Case |
45
- |----------|-------|------------------|
46
- | `@user_id` | Current user ID from `p_user_id` | Ownership, audit trails |
47
- | `@now` | Current timestamp | `created_at`, `updated_at` |
48
- | `@today` | Current date | `valid_from`, `date_created` |
49
- | Literal values | Any JSON value | `"draft"`, `0`, `true` |
50
-
51
- ## Behavior
52
-
53
- ### INSERT Operations
54
-
55
- Field defaults are **only applied during INSERT** (creating new records):
56
-
57
- ```javascript
58
- // Client doesn't send owner_id
59
- await api.save_resources({
60
- data: { title: "Conference Room A" }
61
- })
62
-
63
- // Server auto-populates:
64
- // - owner_id = current user ID
65
- // - created_at = current timestamp
66
- // - status = "draft"
67
- ```
68
-
69
- ### UPDATE Operations
70
-
71
- Field defaults are **NOT applied during UPDATE** (modifying existing records):
72
-
73
- ```javascript
74
- // Updating existing record
75
- await api.save_resources({
76
- data: {
77
- id: 1,
78
- title: "Updated Title"
79
- }
80
- })
81
-
82
- // created_at is NOT changed
83
- // owner_id is NOT changed
84
- ```
85
-
86
- ### Explicit Values Override Defaults
87
-
88
- If the client explicitly provides a value, it takes precedence:
89
-
90
- ```javascript
91
- await api.save_resources({
92
- data: {
93
- title: "Room A",
94
- status: "published" // Overrides "draft" default
95
- }
96
- })
97
- ```
98
-
99
- ## Common Use Cases
100
-
101
- ### Ownership Tracking
102
-
103
- ```sql
104
- SELECT dzql.register_entity(
105
- 'documents',
106
- 'title',
107
- ARRAY['title'],
108
- '{}', false, '{}', '{}', '{}', '{}',
109
- '{
110
- "owner_id": "@user_id",
111
- "created_by": "@user_id"
112
- }'
113
- );
114
- ```
115
-
116
- ### Timestamps
117
-
118
- ```sql
119
- SELECT dzql.register_entity(
120
- 'posts',
121
- 'title',
122
- ARRAY['title'],
123
- '{}', false, '{}', '{}', '{}', '{}',
124
- '{
125
- "created_at": "@now",
126
- "published_at": "@now"
127
- }'
128
- );
129
- ```
130
-
131
- ### Status/Workflow
132
-
133
- ```sql
134
- SELECT dzql.register_entity(
135
- 'orders',
136
- 'order_number',
137
- ARRAY['order_number'],
138
- '{}', false, '{}', '{}', '{}', '{}',
139
- '{
140
- "status": "pending",
141
- "priority": "normal",
142
- "auto_process": "true"
143
- }'
144
- );
145
- ```
146
-
147
- ### Multi-Tenant
148
-
149
- ```sql
150
- SELECT dzql.register_entity(
151
- 'items',
152
- 'name',
153
- ARRAY['name'],
154
- '{}', false, '{}', '{}', '{}', '{}',
155
- '{
156
- "tenant_id": "@user_id",
157
- "created_at": "@now",
158
- "is_active": "true"
159
- }'
160
- );
161
- ```
162
-
163
- ## Security Considerations
164
-
165
- Field defaults improve security by:
166
-
167
- 1. **Preventing client-side tampering** - Server controls sensitive defaults
168
- 2. **Enforcing ownership** - Can't set wrong `owner_id`
169
- 3. **Audit trail integrity** - Timestamps set server-side
170
- 4. **Consistent initialization** - Every record starts in known state
171
-
172
- ## Example: Before vs After
173
-
174
- ### Before (Manual)
175
-
176
- ```javascript
177
- // Client must remember to send owner_id every time
178
- await api.save_tags({
179
- data: {
180
- name: "Important",
181
- owner_id: user.id, // ← Easy to forget
182
- created_at: new Date(), // ← Manual
183
- status: "active" // ← Repetitive
184
- }
185
- })
186
- ```
187
-
188
- ### After (Automatic)
189
-
190
- ```javascript
191
- // Client sends only actual data
192
- await api.save_tags({
193
- data: {
194
- name: "Important"
195
- // owner_id, created_at, status auto-populated!
196
- }
197
- })
198
- ```
199
-
200
- ## Backwards Compatibility
201
-
202
- Field defaults are **completely optional**:
203
-
204
- - Entities without field defaults work exactly as before
205
- - No migration needed for existing entities
206
- - Can be added incrementally
207
-
208
- ## Implementation Details
209
-
210
- ### Storage
211
-
212
- Field defaults are stored in the `dzql.entities` table:
213
-
214
- ```sql
215
- SELECT field_defaults FROM dzql.entities WHERE table_name = 'resources';
216
- ```
217
-
218
- Result:
219
- ```json
220
- {
221
- "owner_id": "@user_id",
222
- "created_at": "@now",
223
- "status": "draft"
224
- }
225
- ```
226
-
227
- ### Resolution
228
-
229
- Variables are resolved in `generic_save()` using the existing `dzql.resolve_graph_variable()` function:
230
-
231
- 1. Check if field is missing in `p_data`
232
- 2. Get default value from entity config
233
- 3. If starts with `@`, resolve the variable
234
- 4. Add to data being inserted
235
-
236
- ## See Also
237
-
238
- - [Entity Registration](../reference/api.md#register_entity) - Full registration API
239
- - [Many-to-Many Support](./many-to-many.md) - Relationship defaults
240
- - [Custom Functions](./custom-functions.md) - Extending entities
@@ -1,237 +0,0 @@
1
- # Interpreter vs Compiler Mode
2
-
3
- DZQL offers two execution modes for your entities. Understanding when to use each is fundamental to getting the best out of the framework.
4
-
5
- ## Quick Summary
6
-
7
- | Aspect | Interpreter | Compiler |
8
- |--------|-------------|----------|
9
- | **Setup** | Register entity, use immediately | Register entity, compile, deploy SQL |
10
- | **Performance** | ~8-12ms per operation | ~2-4ms per operation |
11
- | **Debugging** | Opaque (dynamic SQL) | Transparent (static SQL) |
12
- | **Best For** | Development, prototyping | Production, performance-critical |
13
-
14
- ## How It Works
15
-
16
- ### Interpreter Mode (Runtime)
17
-
18
- Entity configuration is stored as JSON in `dzql.entities` table and parsed at runtime:
19
-
20
- ```
21
- Client Request → generic_exec() → Parse JSON config → Build SQL → Execute
22
- ```
23
-
24
- **Characteristics:**
25
- - Zero build step - changes take effect immediately
26
- - JSON config parsed on every request
27
- - Dynamic SQL generated at runtime
28
- - Generic query plans (harder to optimize)
29
-
30
- **Usage:**
31
- ```sql
32
- -- Register entity
33
- SELECT dzql.register_entity('todos', 'title', ARRAY['title'], ...);
34
-
35
- -- Use immediately via generic executor
36
- SELECT dzql.generic_exec('save', 'todos', '{"title": "Buy milk"}'::jsonb, 1);
37
- ```
38
-
39
- ### Compiler Mode (Static)
40
-
41
- Entity configuration is compiled into dedicated PostgreSQL functions:
42
-
43
- ```
44
- Entity Definition → dzql compile → Static SQL Functions → Deploy → Execute
45
- ```
46
-
47
- **Characteristics:**
48
- - Build step required
49
- - No JSON parsing at runtime
50
- - Static SQL with specific query plans
51
- - PostgreSQL can optimize and cache plans
52
-
53
- **Usage:**
54
- ```bash
55
- # Compile entities to SQL
56
- dzql compile entities.sql -o compiled/
57
-
58
- # Deploy to database
59
- psql < compiled/entities.sql
60
- ```
61
-
62
- ```sql
63
- -- Use compiled functions directly
64
- SELECT save_todos('{"title": "Buy milk"}'::jsonb, 1);
65
- ```
66
-
67
- ## The Server Automatically Chooses
68
-
69
- The DZQL server (`db.js`) automatically tries compiled functions first:
70
-
71
- ```javascript
72
- // In callDZQLOperation()
73
- try {
74
- // Try compiled function: save_todos()
75
- const result = await sql.unsafe(`SELECT save_todos($1, $2)`, [data, userId]);
76
- return result[0].result;
77
- } catch (error) {
78
- // If compiled function doesn't exist, fall back to interpreter
79
- if (error.message.includes('save_todos') && error.code === '42883') {
80
- return await sql`SELECT dzql.generic_exec('save', 'todos', ${data}, ${userId})`;
81
- }
82
- throw error;
83
- }
84
- ```
85
-
86
- This means you can:
87
- 1. Start with interpreter mode during development
88
- 2. Compile and deploy when ready for production
89
- 3. Mix and match - some entities compiled, others interpreted
90
-
91
- ## Performance Comparison
92
-
93
- ### Interpreter (Runtime Parsing)
94
-
95
- ```sql
96
- SELECT dzql.generic_exec('save', 'venues', '{"name": "MSG"}'::jsonb, 42);
97
- ```
98
-
99
- **Execution steps:**
100
- 1. Fetch entity config from `dzql.entities` (table lookup)
101
- 2. Parse `permission_paths` JSONB
102
- 3. Build permission query dynamically
103
- 4. Parse `graph_rules` JSONB
104
- 5. Execute rules via dynamic SQL
105
- 6. Parse `notification_paths` JSONB
106
- 7. Resolve paths dynamically
107
- 8. Execute the actual save
108
-
109
- **Cost:** ~8-12ms, 3-5 JSONB parses, unpredictable query plans
110
-
111
- ### Compiler (Pre-built Functions)
112
-
113
- ```sql
114
- SELECT save_venues('{"name": "MSG"}'::jsonb, 42);
115
- ```
116
-
117
- **Execution steps:**
118
- 1. Call `can_update_venues()` - pre-compiled permission check
119
- 2. Execute INSERT/UPDATE - direct SQL
120
- 3. Call `graph_venues_on_create()` - pre-compiled graph rules
121
- 4. Call `resolve_notification_paths_venues()` - pre-compiled
122
- 5. Done
123
-
124
- **Cost:** ~2-4ms, 0 JSONB parses, optimized query plans
125
-
126
- ## When to Use Each
127
-
128
- ### Use Interpreter When:
129
- - Rapid prototyping and development
130
- - Schema changes frequently
131
- - Learning DZQL concepts
132
- - Small applications with low traffic
133
- - Need maximum flexibility
134
-
135
- ### Use Compiler When:
136
- - Production deployments
137
- - Performance is critical
138
- - Need predictable query performance
139
- - Want reviewable/auditable SQL
140
- - Large teams (generated SQL is easy to review)
141
- - Complex permission or graph rules
142
-
143
- ### Recommended Workflow:
144
- 1. **Development:** Use interpreter for fast iteration
145
- 2. **Staging:** Compile and test performance
146
- 3. **Production:** Deploy compiled functions
147
-
148
- ## Compiling Entities
149
-
150
- ### Via CLI
151
-
152
- ```bash
153
- # Single file
154
- dzql compile database/entities.sql -o compiled/
155
-
156
- # Multiple files
157
- dzql compile database/*.sql -o compiled/
158
- ```
159
-
160
- ### Programmatically
161
-
162
- ```javascript
163
- import { DZQLCompiler } from 'dzql/compiler';
164
-
165
- const compiler = new DZQLCompiler();
166
- const result = compiler.compileFromSQL(sqlContent);
167
-
168
- console.log(result.sql); // Generated PostgreSQL functions
169
- ```
170
-
171
- ### What Gets Generated
172
-
173
- For each entity, the compiler generates:
174
-
175
- | Function | Purpose |
176
- |----------|---------|
177
- | `get_{entity}(id, user_id)` | Retrieve single record |
178
- | `save_{entity}(data, user_id)` | Create or update |
179
- | `delete_{entity}(id, user_id)` | Delete record |
180
- | `lookup_{entity}(term, user_id)` | Autocomplete search |
181
- | `search_{entity}(filters, user_id)` | Paginated search |
182
- | `can_view_{entity}(user_id, record)` | Permission check |
183
- | `can_create_{entity}(user_id, record)` | Permission check |
184
- | `can_update_{entity}(user_id, record)` | Permission check |
185
- | `can_delete_{entity}(user_id, record)` | Permission check |
186
-
187
- ## Debugging
188
-
189
- ### Interpreter Mode
190
-
191
- Debugging is harder because SQL is generated dynamically:
192
-
193
- ```sql
194
- -- You see this
195
- EXPLAIN ANALYZE SELECT dzql.generic_exec('save', 'venues', '...');
196
-
197
- -- But the actual query is hidden inside
198
- ```
199
-
200
- ### Compiler Mode
201
-
202
- Standard PostgreSQL tools work:
203
-
204
- ```sql
205
- -- See the actual function
206
- \sf save_venues
207
-
208
- -- Analyze performance
209
- EXPLAIN ANALYZE SELECT save_venues('{"name": "MSG"}'::jsonb, 42);
210
-
211
- -- Check slow queries
212
- SELECT * FROM pg_stat_statements WHERE query LIKE '%save_venues%';
213
- ```
214
-
215
- ## Feature Parity
216
-
217
- Both modes support the same features:
218
-
219
- | Feature | Interpreter | Compiler |
220
- |---------|-------------|----------|
221
- | CRUD operations | ✅ | ✅ |
222
- | Permission paths | ✅ | ✅ |
223
- | Graph rules | ✅ | ✅ |
224
- | Notification paths | ✅ | ✅ |
225
- | FK includes | ✅ | ✅ |
226
- | Many-to-many | ✅ | ✅ |
227
- | Field defaults | ✅ | ✅ |
228
- | Soft delete | ✅ | ✅ |
229
- | Temporal fields | ✅ | ✅ |
230
-
231
- The difference is purely in execution speed and debuggability, not functionality.
232
-
233
- ## See Also
234
-
235
- - [Compiler Quickstart](../compiler/QUICKSTART.md) - Get started with compilation
236
- - [Compiler Comparison](../compiler/COMPARISON.md) - Detailed side-by-side analysis
237
- - [API Reference](../reference/api.md) - The 5 operations