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,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