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
@@ -0,0 +1,456 @@
1
+ # DZQL Project Setup Guide
2
+
3
+ Complete guide for setting up a Vue/Pinia client project with DZQL.
4
+
5
+ ## Quick Start
6
+
7
+ The fastest way to get started is with `bun create`:
8
+
9
+ ```bash
10
+ bun create dzql my-app
11
+ cd my-app
12
+ bun install
13
+ bun run db:rebuild
14
+ bun run dev
15
+ ```
16
+
17
+ This creates a full-stack app with the structure described below.
18
+
19
+ ## Manual Setup
20
+
21
+ If you prefer to set up manually:
22
+
23
+ ## Project Structure
24
+
25
+ ```
26
+ my-app/
27
+ ├── package.json # Workspaces root
28
+ ├── bun.lock # Single lockfile
29
+ ├── domain.js # TZQL domain definition
30
+ ├── .env # Environment variables
31
+ ├── compose.yml # PostgreSQL for development
32
+ ├── generated/ # DO NOT EDIT - compiled output
33
+ │ ├── client/ # WebSocket client, Pinia stores, types
34
+ │ ├── db/migrations/ # PostgreSQL schema
35
+ │ └── runtime/ # Server manifest
36
+ ├── src/ # Vue client workspace
37
+ │ ├── package.json
38
+ │ ├── vite.config.ts
39
+ │ ├── tsconfig.app.json
40
+ │ └── src/
41
+ │ ├── main.ts
42
+ │ ├── App.vue
43
+ │ ├── composables/
44
+ │ ├── components/
45
+ │ └── views/
46
+ └── server/ # TZQL server workspace
47
+ ├── package.json
48
+ └── index.ts
49
+ ```
50
+
51
+ ## 1. Bun Workspaces
52
+
53
+ Root `package.json`:
54
+
55
+ ```json
56
+ {
57
+ "name": "my-app",
58
+ "private": true,
59
+ "workspaces": ["src", "server"],
60
+ "scripts": {
61
+ "compile": "bunx dzql domain.js -o generated",
62
+ "db": "docker compose down -v && docker compose up -d",
63
+ "logs": "docker compose logs -f",
64
+ "dev": "concurrently -n server,client -c blue,green \"bun run --filter @my-app/server dev\" \"bun run --filter @my-app/client dev\""
65
+ },
66
+ "devDependencies": {
67
+ "concurrently": "^9.2.1",
68
+ "dzql": "^0.6.0"
69
+ }
70
+ }
71
+ ```
72
+
73
+ Client `src/package.json`:
74
+
75
+ ```json
76
+ {
77
+ "name": "@my-app/client",
78
+ "private": true,
79
+ "type": "module",
80
+ "scripts": {
81
+ "dev": "vite",
82
+ "build": "vite build"
83
+ },
84
+ "dependencies": {
85
+ "pinia": "^3.0.4",
86
+ "vue": "^3.5.25",
87
+ "vue-router": "^4.6.3"
88
+ },
89
+ "devDependencies": {
90
+ "@vitejs/plugin-vue": "^6.0.2",
91
+ "vite": "^7.2.4",
92
+ "typescript": "~5.9.0"
93
+ }
94
+ }
95
+ ```
96
+
97
+ Server `server/package.json`:
98
+
99
+ ```json
100
+ {
101
+ "name": "@my-app/server",
102
+ "private": true,
103
+ "type": "module",
104
+ "scripts": {
105
+ "dev": "cd .. && bun run server/index.ts"
106
+ },
107
+ "dependencies": {
108
+ "dzql": "^0.6.0"
109
+ }
110
+ }
111
+ ```
112
+
113
+ **Important:** The server script uses `cd ..` to run from the project root so that:
114
+ - `.env` is found (dotenv loads from `process.cwd()`)
115
+ - `MANIFEST_PATH=./generated/runtime/manifest.json` resolves correctly
116
+
117
+ Server `server/index.ts`:
118
+
119
+ ```typescript
120
+ import { createServer } from "dzql";
121
+
122
+ const server = createServer({
123
+ port: process.env.PORT || 3000,
124
+ });
125
+
126
+ console.log(`DZQL Server running on port ${server.port}`);
127
+ ```
128
+
129
+ ## 2. Docker Compose for PostgreSQL
130
+
131
+ `compose.yml`:
132
+
133
+ ```yaml
134
+ services:
135
+ db:
136
+ image: postgres:16-alpine
137
+ environment:
138
+ POSTGRES_USER: myapp
139
+ POSTGRES_PASSWORD: myapp
140
+ POSTGRES_DB: myapp
141
+ ports:
142
+ - "5432:5432"
143
+ volumes:
144
+ - pgdata:/var/lib/postgresql/data
145
+ - ./generated/db/migrations:/docker-entrypoint-initdb.d:ro
146
+
147
+ volumes:
148
+ pgdata:
149
+ ```
150
+
151
+ **Key:** Mount `generated/db/migrations` to `/docker-entrypoint-initdb.d` for automatic schema initialization on first run.
152
+
153
+ ## 3. Environment Variables
154
+
155
+ `.env`:
156
+
157
+ ```
158
+ # Database
159
+ DATABASE_URL=postgres://myapp:myapp@localhost:5432/myapp
160
+
161
+ # Server
162
+ PORT=3000
163
+ MANIFEST_PATH=./generated/runtime/manifest.json
164
+ JWT_SECRET=dev-secret-change-in-production
165
+
166
+ # Client (Vite)
167
+ VITE_TZQL_TOKEN_NAME=myapp_token
168
+ ```
169
+
170
+ ## 4. Vite Configuration
171
+
172
+ `src/vite.config.ts`:
173
+
174
+ ```typescript
175
+ import { fileURLToPath, URL } from 'node:url'
176
+ import { defineConfig } from 'vite'
177
+ import vue from '@vitejs/plugin-vue'
178
+
179
+ export default defineConfig({
180
+ plugins: [vue()],
181
+ resolve: {
182
+ alias: {
183
+ '@': fileURLToPath(new URL('./src', import.meta.url)),
184
+ '@generated': fileURLToPath(new URL('../generated', import.meta.url)),
185
+ },
186
+ },
187
+ server: {
188
+ // Allow external access (for Docker-based tools like Playwright MCP)
189
+ host: '0.0.0.0',
190
+ allowedHosts: ['host.docker.internal'],
191
+
192
+ // Proxy WebSocket to TZQL server
193
+ proxy: {
194
+ '/ws': {
195
+ target: 'ws://localhost:3000',
196
+ ws: true,
197
+ },
198
+ },
199
+ },
200
+ })
201
+ ```
202
+
203
+ **Configuration explained:**
204
+
205
+ - `host: '0.0.0.0'` - Binds to all interfaces, required for Docker access
206
+ - `allowedHosts: ['host.docker.internal']` - Allows Playwright MCP (running in Docker) to connect
207
+ - `proxy: { '/ws': ... }` - Client connects to `/ws` on Vite's port, proxied to TZQL server on port 3000
208
+
209
+ **For Playwright MCP testing:** Navigate to `http://host.docker.internal:5173`
210
+
211
+ ## 5. TypeScript Path Aliases
212
+
213
+ `src/tsconfig.app.json`:
214
+
215
+ ```json
216
+ {
217
+ "extends": "@vue/tsconfig/tsconfig.dom.json",
218
+ "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
219
+ "compilerOptions": {
220
+ "paths": {
221
+ "@/*": ["./src/*"],
222
+ "@generated/*": ["../generated/*"]
223
+ }
224
+ }
225
+ }
226
+ ```
227
+
228
+ ## 6. Authentication Composable
229
+
230
+ `src/src/composables/useTzql.ts`:
231
+
232
+ ```typescript
233
+ import { ref } from 'vue'
234
+ import { ws } from '@generated/client'
235
+
236
+ const ready = ref(false)
237
+ const user = ref<any>(null)
238
+ const connectionError = ref<string | null>(null)
239
+
240
+ export function useTzql() {
241
+ async function connect(url?: string) {
242
+ try {
243
+ connectionError.value = null
244
+ ready.value = false
245
+
246
+ ws.onReady((profile: any) => {
247
+ if (!profile && localStorage.getItem('token')) {
248
+ localStorage.removeItem('token')
249
+ }
250
+ user.value = profile
251
+ ready.value = true
252
+ })
253
+
254
+ await ws.connect(url)
255
+ } catch (e: any) {
256
+ connectionError.value = e.message
257
+ throw e
258
+ }
259
+ }
260
+
261
+ async function login(email: string, password: string) {
262
+ const result = await ws.login({ email, password })
263
+ if (result?.user_id) {
264
+ user.value = result
265
+ }
266
+ return result
267
+ }
268
+
269
+ async function register(name: string, email: string, password: string) {
270
+ const result = await ws.register({ name, email, password })
271
+ if (result?.user_id) {
272
+ user.value = result
273
+ }
274
+ return result
275
+ }
276
+
277
+ async function logout() {
278
+ await ws.logout()
279
+ user.value = null
280
+ }
281
+
282
+ return { ws, ready, user, connectionError, connect, login, register, logout }
283
+ }
284
+ ```
285
+
286
+ ## 7. App Entry Point
287
+
288
+ `src/src/main.ts`:
289
+
290
+ ```typescript
291
+ import './assets/main.css'
292
+ import { createApp } from 'vue'
293
+ import { createPinia } from 'pinia'
294
+ import App from './App.vue'
295
+ import router from './router'
296
+ import { useTzql } from './composables/useTzql'
297
+
298
+ const app = createApp(App)
299
+ app.use(createPinia())
300
+ app.use(router)
301
+ app.mount('#app')
302
+
303
+ // Connect to TZQL server
304
+ const { connect } = useTzql()
305
+ connect()
306
+ ```
307
+
308
+ ## 8. App Component Pattern
309
+
310
+ `src/src/App.vue`:
311
+
312
+ ```vue
313
+ <script setup lang="ts">
314
+ import { useTzql } from '@/composables/useTzql'
315
+ import LoginModal from '@/components/LoginModal.vue'
316
+
317
+ const { ready, user, logout } = useTzql()
318
+ </script>
319
+
320
+ <template>
321
+ <div v-if="!ready" class="loading">Connecting...</div>
322
+ <LoginModal v-else-if="!user" />
323
+ <template v-else>
324
+ <header>
325
+ <nav>
326
+ <RouterLink to="/">Home</RouterLink>
327
+ <span>{{ user.name }}</span>
328
+ <button @click="logout">Logout</button>
329
+ </nav>
330
+ </header>
331
+ <main>
332
+ <RouterView />
333
+ </main>
334
+ </template>
335
+ </template>
336
+ ```
337
+
338
+ **Key points:**
339
+ - No router guards needed - WebSocket `connection:ready` is the source of truth
340
+ - Shows loading until connection established
341
+ - Shows login if no user, app content if authenticated
342
+ - Login/logout reactively update UI - no page reload needed
343
+
344
+ ## 9. Using Generated Stores
345
+
346
+ ```vue
347
+ <script setup lang="ts">
348
+ import { computed, watchEffect } from 'vue'
349
+ import { useRoute } from 'vue-router'
350
+ import { useTzql } from '@/composables/useTzql'
351
+ import { useVenueDetailStore } from '@generated/client/stores/useVenueDetailStore.js'
352
+
353
+ const route = useRoute()
354
+ const { ws } = useTzql()
355
+ const store = useVenueDetailStore()
356
+
357
+ const venueId = computed(() => Number(route.params.id))
358
+ const docKey = computed(() => JSON.stringify({ venue_id: venueId.value }))
359
+
360
+ // Bind to subscription when venueId changes
361
+ watchEffect(() => {
362
+ if (venueId.value) {
363
+ store.bind({ venue_id: venueId.value })
364
+ }
365
+ })
366
+
367
+ // Reactive data from store
368
+ const doc = computed(() => store.documents[docKey.value])
369
+ const loading = computed(() => !doc.value || doc.value.loading.value)
370
+ const venue = computed(() => doc.value?.data.value)
371
+ const sites = computed(() => doc.value?.data.value?.sites ?? [])
372
+
373
+ // CRUD operations
374
+ async function createSite(name: string) {
375
+ await ws.api.save_sites({ venue_id: venueId.value, name })
376
+ // No refetch needed - patch arrives via WebSocket
377
+ }
378
+
379
+ async function updateSite(id: number, name: string) {
380
+ await ws.api.save_sites({ id, venue_id: venueId.value, name })
381
+ }
382
+
383
+ async function deleteSite(id: number) {
384
+ await ws.api.delete_sites({ id })
385
+ }
386
+ </script>
387
+ ```
388
+
389
+ ## 10. CLI Database Access with invj
390
+
391
+ Create `tasks.js` in the project root to enable CLI database operations:
392
+
393
+ ```javascript
394
+ import { TzqlNamespace } from "tzql/namespace";
395
+
396
+ export class Tasks {
397
+ constructor() {
398
+ this.tzql = new TzqlNamespace();
399
+ }
400
+ }
401
+ ```
402
+
403
+ This integrates with `invj` to provide direct database access:
404
+
405
+ ```bash
406
+ # List available commands
407
+ invj -l
408
+
409
+ # Available tzql commands:
410
+ # tzql:entities - List all entities
411
+ # tzql:subscribables - List all subscribables
412
+ # tzql:functions - List all functions
413
+ # tzql:search <entity> [json] - Search records
414
+ # tzql:get <entity> [json] - Get single record
415
+ # tzql:save <entity> [json] - Create/update record
416
+ # tzql:delete <entity> [json] - Delete record
417
+ # tzql:lookup <entity> [json] - Autocomplete lookup
418
+ # tzql:call <func> [json] - Call custom function
419
+ # tzql:subscribe <name> [json] - Get subscribable data
420
+
421
+ # Examples
422
+ invj tzql:entities
423
+ invj tzql:search venues
424
+ invj tzql:search venues '{"org_id": 1}'
425
+ invj tzql:get venues '{"id": 1}'
426
+ invj tzql:save venues '{"org_id": 1, "name": "New Venue", "address": "123 Main St"}'
427
+ invj tzql:delete venues '{"id": 1}'
428
+ ```
429
+
430
+ ## Development Workflow
431
+
432
+ ```bash
433
+ # 1. Start PostgreSQL
434
+ bun run db
435
+
436
+ # 2. Compile domain (after any domain.js changes)
437
+ bun run compile
438
+
439
+ # 3. Start dev servers
440
+ bun run dev
441
+ ```
442
+
443
+ After `bun run db`, the database initializes with migrations automatically. After domain changes, run `bun run compile` then restart the server.
444
+
445
+ ## Linking TZQL for Local Development
446
+
447
+ If developing TZQL locally:
448
+
449
+ ```bash
450
+ cd /path/to/tzql
451
+ bun link
452
+
453
+ cd /path/to/my-app
454
+ # tzql is already in package.json as "link:tzql"
455
+ bun install
456
+ ```
@@ -0,0 +1,50 @@
1
+ // TZQL Entity Definition Example
2
+
3
+ export const entities = {
4
+ posts: {
5
+ schema: {
6
+ id: 'serial PRIMARY KEY',
7
+ title: 'text NOT NULL',
8
+ content: 'text',
9
+ author_id: 'int NOT NULL', // In a real app, this would reference users(id)
10
+ created_at: 'timestamptz DEFAULT now()'
11
+ },
12
+ permissions: {
13
+ view: [], // Public
14
+ create: ['@author_id == @user_id'], // Only create for self
15
+ update: ['@author_id == @user_id'], // Only owner
16
+ delete: ['@author_id == @user_id'] // Only owner
17
+ },
18
+ graphRules: {
19
+ on_create: {
20
+ actions: [
21
+ { type: 'reactor', name: 'notify_subscribers', params: { post_id: '@id' } }
22
+ ]
23
+ }
24
+ }
25
+ },
26
+ comments: {
27
+ schema: {
28
+ id: 'serial PRIMARY KEY',
29
+ post_id: 'int NOT NULL REFERENCES posts(id) ON DELETE CASCADE',
30
+ content: 'text NOT NULL',
31
+ author_id: 'int NOT NULL'
32
+ },
33
+ permissions: {
34
+ view: [],
35
+ create: [],
36
+ delete: ['@author_id == @user_id']
37
+ }
38
+ }
39
+ };
40
+
41
+ export const subscribables = {
42
+ post_detail: {
43
+ params: { post_id: 'int' },
44
+ root: { entity: 'posts', key: 'post_id' },
45
+ includes: {
46
+ comments: { entity: 'comments', filter: { post_id: '@id' } }
47
+ },
48
+ scopeTables: ['posts', 'comments']
49
+ }
50
+ };
@@ -0,0 +1,18 @@
1
+ // TZQL Entity Definition Example (INVALID)
2
+
3
+ export const entities = {
4
+ posts: {
5
+ schema: { id: 'serial PRIMARY KEY' },
6
+ permissions: {}
7
+ }
8
+ };
9
+
10
+ export const subscribables = {
11
+ broken_feed: {
12
+ params: {},
13
+ root: { entity: 'posts' },
14
+ includes: {
15
+ comments: { entity: 'missing_table' } // <--- Error: 'missing_table' does not exist
16
+ }
17
+ }
18
+ };