dzql 0.6.0 → 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.
package/docs/README.md CHANGED
@@ -1,6 +1,20 @@
1
- # TZQL: The Compile-Only Realtime Database Framework
1
+ # DZQL: The Compile-Only Realtime Database Framework
2
2
 
3
- TZQL ("The Zero Query Language") is a PostgreSQL-native framework for building realtime, reactive applications without the runtime overhead or complexity of traditional ORMs or BaaS solutions.
3
+ DZQL ("Database Zero Query Language") is a PostgreSQL-native framework for building realtime, reactive applications without the runtime overhead or complexity of traditional ORMs or BaaS solutions.
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 Vue/Vite frontend, DZQL server, and PostgreSQL database.
4
18
 
5
19
  ## The Problem
6
20
 
@@ -10,11 +24,11 @@ Building realtime apps is hard. You typically have to:
10
24
  3. **Handle Atomicity:** Ensure that complex operations (e.g., "Create Order + Reserve Inventory + Notify User") happen in a single transaction.
11
25
  4. **Optimistic Updates:** Write complex client-side logic to "guess" the server's response, often leading to data divergence.
12
26
 
13
- ## The TZQL Solution
27
+ ## The DZQL Solution
14
28
 
15
- TZQL takes a radically different approach: **Compilation**.
29
+ DZQL takes a radically different approach: **Compilation**.
16
30
 
17
- Instead of a heavy runtime framework, you define your **Domain Schema** (Entities, Relationships, Permissions) in a simple TypeScript configuration. TZQL compiles this definition into:
31
+ Instead of a heavy runtime framework, you define your **Domain Schema** (Entities, Relationships, Permissions) in a simple TypeScript configuration. DZQL compiles this definition into:
18
32
 
19
33
  1. **Optimized SQL:** Specialized PostgreSQL functions (`save_order`, `get_product`) with *inlined* permission checks and *atomic* graph operations.
20
34
  2. **Type-Safe Client SDK:** A generated TypeScript client that knows your exact API surface.
@@ -28,7 +42,9 @@ Instead of a heavy runtime framework, you define your **Domain Schema** (Entitie
28
42
  * **Realtime by Default:** Every database write emits an atomic event batch. The client SDK automatically patches your local state. No "refetching" required.
29
43
  * **JavaScript/TypeScript Native:** Define your schema in code you understand, get full type safety end-to-end.
30
44
 
31
- ## Quick Start
45
+ ## Manual Setup
46
+
47
+ If you prefer to set up manually instead of using `bun create dzql`:
32
48
 
33
49
  ### 1. Define your Domain (`domain.ts`)
34
50
 
@@ -51,13 +67,13 @@ export const subscribables = {
51
67
  ### 2. Compile
52
68
 
53
69
  ```bash
54
- bun run tzql compile domain.ts -o src/generated
70
+ bunx dzql domain.ts -o generated
55
71
  ```
56
72
 
57
73
  ### 3. Use in Client
58
74
 
59
75
  ```typescript
60
- import { usePostFeedStore } from '@/generated/client/stores';
76
+ import { usePostFeedStore } from '@generated/client/stores';
61
77
 
62
78
  const feed = usePostFeedStore();
63
79
  // Automatically fetches data AND subscribes to realtime updates
@@ -76,10 +92,10 @@ const { data, loading } = await feed.bind({ user_id: 1 });
76
92
  ## Package Exports
77
93
 
78
94
  ```typescript
79
- import { ... } from 'tzql'; // Runtime server
80
- import { ... } from 'tzql/client'; // WebSocket client SDK
81
- import { ... } from 'tzql/compiler'; // CLI compiler
82
- import { TzqlNamespace } from 'tzql/namespace'; // CLI/invokej integration
95
+ import { ... } from 'dzql'; // Runtime server
96
+ import { ... } from 'dzql/client'; // WebSocket client SDK
97
+ import { ... } from 'dzql/compiler'; // CLI compiler
98
+ import { DzqlNamespace } from 'dzql/namespace'; // CLI/invokej integration
83
99
  ```
84
100
 
85
101
  ## Client Connection & Authentication
@@ -96,7 +112,7 @@ When a client connects to the WebSocket server, it immediately receives a `conne
96
112
  ### Client API
97
113
 
98
114
  ```typescript
99
- import { WebSocketManager } from 'tzql/client';
115
+ import { WebSocketManager } from 'dzql/client';
100
116
 
101
117
  const ws = new WebSocketManager();
102
118
  await ws.connect('ws://localhost:3000/ws');
package/docs/for_ai.md CHANGED
@@ -1,10 +1,22 @@
1
- # TZQL Guide for AI Assistants
1
+ # DZQL Guide for AI Assistants
2
2
 
3
- This document defines the patterns and conventions for generating valid TZQL domain definitions. Use this guide when asked to "Create a TZQL app" or "Add an entity".
3
+ This document defines the patterns and conventions for generating valid DZQL domain definitions. Use this guide when asked to "Create a DZQL app" or "Add an entity".
4
+
5
+ ## Quick Start
6
+
7
+ The fastest way to create a new DZQL app:
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
+ ```
4
16
 
5
17
  ## Core Concept: The Domain Definition
6
18
 
7
- A TZQL application is defined by a single TypeScript/JavaScript module exporting `entities` and `subscribables`.
19
+ A DZQL application is defined by a single TypeScript/JavaScript module exporting `entities` and `subscribables`.
8
20
 
9
21
  ### 1. Entity Definition Pattern
10
22
 
@@ -523,7 +535,7 @@ When a client connects to the WebSocket server, it immediately receives a `conne
523
535
  ### WebSocketManager API
524
536
 
525
537
  ```typescript
526
- import { WebSocketManager } from 'tzql/client';
538
+ import { WebSocketManager } from 'dzql/client';
527
539
 
528
540
  const ws = new WebSocketManager();
529
541
  await ws.connect('ws://localhost:3000/ws');
@@ -574,13 +586,13 @@ TZQL provides a namespace export for CLI tools like `invokej` to interact with t
574
586
 
575
587
  ```typescript
576
588
  // cli.ts or server-side script
577
- import { TzqlNamespace } from 'tzql/namespace';
589
+ import { DzqlNamespace } from 'dzql/namespace';
578
590
  import postgres from 'postgres';
579
591
 
580
592
  const sql = postgres(process.env.DATABASE_URL);
581
593
  const manifest = await import('./dist/runtime/manifest.json');
582
594
 
583
- const tzql = new TzqlNamespace(sql, manifest);
595
+ const dzql = new DzqlNamespace(sql, manifest);
584
596
  ```
585
597
 
586
598
  ### CRUD Operations
@@ -1,6 +1,24 @@
1
- # TZQL Project Setup Guide
1
+ # DZQL Project Setup Guide
2
2
 
3
- Complete guide for setting up a Vue/Pinia client project with TZQL.
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:
4
22
 
5
23
  ## Project Structure
6
24
 
@@ -40,14 +58,14 @@ Root `package.json`:
40
58
  "private": true,
41
59
  "workspaces": ["src", "server"],
42
60
  "scripts": {
43
- "compile": "tzql compile domain.js -o generated",
61
+ "compile": "bunx dzql domain.js -o generated",
44
62
  "db": "docker compose down -v && docker compose up -d",
45
63
  "logs": "docker compose logs -f",
46
64
  "dev": "concurrently -n server,client -c blue,green \"bun run --filter @my-app/server dev\" \"bun run --filter @my-app/client dev\""
47
65
  },
48
66
  "devDependencies": {
49
67
  "concurrently": "^9.2.1",
50
- "tzql": "link:tzql"
68
+ "dzql": "^0.6.0"
51
69
  }
52
70
  }
53
71
  ```
@@ -87,7 +105,7 @@ Server `server/package.json`:
87
105
  "dev": "cd .. && bun run server/index.ts"
88
106
  },
89
107
  "dependencies": {
90
- "tzql": "link:tzql"
108
+ "dzql": "^0.6.0"
91
109
  }
92
110
  }
93
111
  ```
@@ -99,7 +117,13 @@ Server `server/package.json`:
99
117
  Server `server/index.ts`:
100
118
 
101
119
  ```typescript
102
- import "tzql";
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}`);
103
127
  ```
104
128
 
105
129
  ## 2. Docker Compose for PostgreSQL
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dzql",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "Database-first real-time framework with TypeScript support",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli/index.ts CHANGED
@@ -11,10 +11,16 @@ import { writeFileSync, mkdirSync, copyFileSync, rmSync } from "fs";
11
11
  import { resolve, dirname } from "path";
12
12
 
13
13
  const args = process.argv.slice(2);
14
- const command = args[0];
15
- const input = args[1];
14
+ let command = args[0];
15
+ let input = args[1];
16
16
  let outputDir = "dist"; // Default output directory
17
17
 
18
+ // If first arg looks like a file (ends with .ts or .js), treat it as compile target
19
+ if (command && (command.endsWith('.ts') || command.endsWith('.js'))) {
20
+ input = command;
21
+ command = 'compile';
22
+ }
23
+
18
24
  // Parse optional output directory flag
19
25
  const outputFlagIndex = args.indexOf('-o');
20
26
  const longOutputFlagIndex = args.indexOf('--output');
@@ -26,11 +32,11 @@ if (outputFlagIndex > -1 && args[outputFlagIndex + 1]) {
26
32
  }
27
33
 
28
34
  async function main() {
29
- console.log("TZQL Compiler v0.0.1");
35
+ console.log("DZQL Compiler v0.6.0");
30
36
 
31
37
  if (command === "compile") {
32
38
  if (!input) {
33
- console.error("Usage: tzql compile <file>");
39
+ console.error("Usage: dzql <file> or dzql compile <file>");
34
40
  process.exit(1);
35
41
  }
36
42
 
@@ -88,10 +94,6 @@ async function main() {
88
94
 
89
95
  // Phase 4: Generate Manifest
90
96
  const manifest = generateManifest(ir);
91
- console.log(`[Compiler] Manifest functions: ${Object.keys(manifest.functions).length}`);
92
- if (!manifest.functions['subscribe_venue_detail']) {
93
- console.error("[Compiler] ERROR: subscribe_venue_detail missing from manifest functions!");
94
- }
95
97
 
96
98
  // --- OUTPUT GENERATION ---
97
99
 
@@ -1,8 +0,0 @@
1
- # Database connection
2
- DATABASE_URL=postgres://{{name}}:{{name}}@localhost:5432/{{name}}
3
-
4
- # JWT Secret (change in production!)
5
- JWT_SECRET=dev-secret-change-in-production
6
-
7
- # Server port
8
- PORT=3000
@@ -1,101 +0,0 @@
1
- # {{name}}
2
-
3
- A real-time database application powered by [DZQL](https://github.com/blueshed/dzql).
4
-
5
- ## Quick Start
6
-
7
- ```bash
8
- # Start PostgreSQL
9
- bun run db:up
10
-
11
- # Copy environment file
12
- cp .env.example .env
13
-
14
- # Compile domain and generate SQL
15
- bun run compile
16
-
17
- # Run migrations
18
- bun run db:migrate
19
-
20
- # Start development server
21
- bun run dev
22
- ```
23
-
24
- ## Project Structure
25
-
26
- ```
27
- ├── domain.ts # Entity definitions and subscriptions
28
- ├── server.ts # Runtime server configuration
29
- ├── compose.yml # Docker Compose for PostgreSQL
30
- ├── dist/ # Generated output (after compile)
31
- │ ├── db/ # SQL migrations
32
- │ ├── runtime/ # Server manifest
33
- │ └── client/ # TypeScript SDK & Pinia stores
34
- └── .env # Environment variables
35
- ```
36
-
37
- ## Domain Definition
38
-
39
- Edit `domain.ts` to define your entities:
40
-
41
- ```typescript
42
- export const entities = {
43
- posts: {
44
- schema: {
45
- id: 'serial PRIMARY KEY',
46
- title: 'text NOT NULL',
47
- content: 'text'
48
- },
49
- permissions: {
50
- view: [],
51
- create: [],
52
- update: ['@author_id'],
53
- delete: ['@author_id']
54
- }
55
- }
56
- };
57
- ```
58
-
59
- ## API Endpoints
60
-
61
- After starting the server:
62
-
63
- - **WebSocket**: `ws://localhost:3000/ws`
64
- - **Health**: `GET http://localhost:3000/health`
65
-
66
- ## Client Usage
67
-
68
- ```typescript
69
- import { TzqlClient } from './dist/client';
70
-
71
- const client = new TzqlClient('ws://localhost:3000/ws');
72
-
73
- // Register
74
- await client.api.register_user({
75
- email: 'user@example.com',
76
- password: 'secret'
77
- });
78
-
79
- // Login
80
- const { token } = await client.api.login_user({
81
- email: 'user@example.com',
82
- password: 'secret'
83
- });
84
-
85
- // CRUD operations
86
- const post = await client.api.save_posts({
87
- title: 'Hello World'
88
- });
89
-
90
- // Real-time subscription
91
- await client.api.subscribe_post_detail(
92
- { post_id: post.id },
93
- (data) => console.log('Updated:', data)
94
- );
95
- ```
96
-
97
- ## Learn More
98
-
99
- - [DZQL Documentation](https://github.com/blueshed/dzql)
100
- - [Graph Rules](https://github.com/blueshed/dzql/docs/guides/graph-rules.md)
101
- - [Subscriptions](https://github.com/blueshed/dzql/docs/guides/subscriptions.md)
@@ -1,14 +0,0 @@
1
- services:
2
- postgres:
3
- image: postgres:16
4
- environment:
5
- POSTGRES_USER: {{name}}
6
- POSTGRES_PASSWORD: {{name}}
7
- POSTGRES_DB: {{name}}
8
- ports:
9
- - "5432:5432"
10
- volumes:
11
- - pgdata:/var/lib/postgresql/data
12
-
13
- volumes:
14
- pgdata:
@@ -1,153 +0,0 @@
1
- // domain.ts - DZQL Domain Definition
2
- // Run: bunx dzql domain.ts
3
-
4
- export const entities = {
5
-
6
- // Users table with authentication
7
- users: {
8
- schema: {
9
- id: 'serial PRIMARY KEY',
10
- name: 'text NOT NULL',
11
- email: 'text UNIQUE NOT NULL',
12
- password_hash: 'text NOT NULL',
13
- created_at: 'timestamptz DEFAULT now()'
14
- },
15
- label: 'name',
16
- searchable: ['name', 'email'],
17
- hidden: ['password_hash'],
18
- permissions: {
19
- view: [],
20
- create: [],
21
- update: ['@id'], // Users can only update themselves
22
- delete: []
23
- }
24
- },
25
-
26
- // Posts table with author relationship
27
- posts: {
28
- schema: {
29
- id: 'serial PRIMARY KEY',
30
- author_id: 'int NOT NULL REFERENCES users(id)',
31
- title: 'text NOT NULL',
32
- content: 'text',
33
- published: 'boolean DEFAULT false',
34
- created_at: 'timestamptz DEFAULT now()',
35
- updated_at: 'timestamptz'
36
- },
37
- label: 'title',
38
- searchable: ['title', 'content'],
39
- includes: {
40
- author: 'users'
41
- },
42
- fieldDefaults: {
43
- author_id: '@user_id',
44
- created_at: '@now'
45
- },
46
- permissions: {
47
- view: [], // Anyone can view
48
- create: [], // Anyone logged in can create
49
- update: ['@author_id'], // Only author can update
50
- delete: ['@author_id'] // Only author can delete
51
- },
52
- graphRules: {
53
- on_create: {
54
- notify_followers: {
55
- description: 'Notify when new post is created',
56
- actions: [
57
- {
58
- type: 'reactor',
59
- name: 'new_post',
60
- params: { post_id: '@id', author_id: '@author_id' }
61
- }
62
- ]
63
- }
64
- },
65
- on_update: {
66
- track_updates: {
67
- description: 'Set updated_at on edit',
68
- condition: "@before.title != @after.title OR @before.content != @after.content",
69
- actions: [
70
- {
71
- type: 'update',
72
- target: 'posts',
73
- data: { updated_at: '@now' },
74
- match: { id: '@id' }
75
- }
76
- ]
77
- }
78
- }
79
- }
80
- },
81
-
82
- // Comments on posts
83
- comments: {
84
- schema: {
85
- id: 'serial PRIMARY KEY',
86
- post_id: 'int NOT NULL REFERENCES posts(id) ON DELETE CASCADE',
87
- author_id: 'int NOT NULL REFERENCES users(id)',
88
- content: 'text NOT NULL',
89
- created_at: 'timestamptz DEFAULT now()'
90
- },
91
- label: 'content',
92
- searchable: ['content'],
93
- includes: {
94
- post: 'posts',
95
- author: 'users'
96
- },
97
- fieldDefaults: {
98
- author_id: '@user_id',
99
- created_at: '@now'
100
- },
101
- permissions: {
102
- view: [],
103
- create: [],
104
- update: ['@author_id'],
105
- delete: ['@author_id', '@post_id->posts.author_id'] // Author or post owner can delete
106
- }
107
- }
108
-
109
- };
110
-
111
- // Real-time subscriptions
112
- export const subscribables = {
113
-
114
- // Post detail with comments
115
- post_detail: {
116
- params: {
117
- post_id: 'int'
118
- },
119
- root: {
120
- entity: 'posts',
121
- key: 'post_id'
122
- },
123
- includes: {
124
- author: 'users',
125
- comments: {
126
- entity: 'comments',
127
- includes: {
128
- author: 'users'
129
- }
130
- }
131
- },
132
- scopeTables: ['posts', 'users', 'comments'],
133
- canSubscribe: [] // Anyone can subscribe
134
- },
135
-
136
- // User's posts feed
137
- my_posts: {
138
- params: {},
139
- root: {
140
- entity: 'users',
141
- key: '@user_id'
142
- },
143
- includes: {
144
- posts: {
145
- entity: 'posts',
146
- filter: { author_id: '@user_id' }
147
- }
148
- },
149
- scopeTables: ['users', 'posts'],
150
- canSubscribe: []
151
- }
152
-
153
- };
@@ -1,24 +0,0 @@
1
- {
2
- "name": "{{name}}",
3
- "version": "0.0.1",
4
- "type": "module",
5
- "scripts": {
6
- "dev": "bun run --watch server.ts",
7
- "compile": "bunx dzql domain.ts",
8
- "db:up": "docker compose up -d",
9
- "db:down": "docker compose down",
10
- "db:migrate": "bun run compile && psql $DATABASE_URL -f dist/db/migrations/*.sql"
11
- },
12
- "dependencies": {
13
- "dzql": "^0.6.0",
14
- "postgres": "^3.4.3"
15
- },
16
- "devDependencies": {
17
- "@types/bun": "latest",
18
- "typescript": "^5.0.0"
19
- },
20
- "bun-create": {
21
- "postinstall": ["./setup.sh", "rm setup.sh"],
22
- "start": "bun run dev"
23
- }
24
- }
@@ -1,18 +0,0 @@
1
- // server.ts - DZQL Runtime Server
2
- import { createServer } from "dzql";
3
-
4
- const server = createServer({
5
- manifestPath: "./dist/runtime/manifest.json",
6
- jwtSecret: process.env.JWT_SECRET || "dev-secret-change-in-production",
7
- });
8
-
9
- const port = process.env.PORT || 3000;
10
-
11
- console.log(`DZQL Server running at http://localhost:${port}`);
12
- console.log(`WebSocket endpoint: ws://localhost:${port}/ws`);
13
-
14
- export default {
15
- port,
16
- fetch: server.fetch,
17
- websocket: server.websocket,
18
- };
@@ -1,11 +0,0 @@
1
- #!/bin/bash
2
- # Replace {{name}} with project name from package.json
3
- NAME=$(grep -o '"name": *"[^"]*"' package.json | head -1 | cut -d'"' -f4)
4
- if [ -z "$NAME" ] || [ "$NAME" = "{{name}}" ]; then
5
- NAME=$(basename "$PWD")
6
- fi
7
- sed -i.bak "s/{{name}}/$NAME/g" compose.yml .env.example README.md package.json 2>/dev/null || \
8
- sed -i "s/{{name}}/$NAME/g" compose.yml .env.example README.md package.json
9
- cp .env.example .env
10
- rm -f compose.yml.bak .env.example.bak README.md.bak package.json.bak
11
- echo "✓ Configured project: $NAME"
@@ -1,15 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ESNext",
4
- "module": "ESNext",
5
- "moduleResolution": "bundler",
6
- "strict": true,
7
- "esModuleInterop": true,
8
- "skipLibCheck": true,
9
- "outDir": "./dist",
10
- "rootDir": ".",
11
- "types": ["bun-types"]
12
- },
13
- "include": ["*.ts", "domain.ts"],
14
- "exclude": ["node_modules", "dist"]
15
- }