dzql 0.4.4 → 0.4.5

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.
@@ -6,17 +6,11 @@ The DZQL Compiler transforms declarative entity definitions into optimized Postg
6
6
 
7
7
  - **[Quickstart Guide](QUICKSTART.md)** - Get started with the compiler in 5 minutes
8
8
 
9
- ## Guides
9
+ ## Reference
10
10
 
11
11
  - **[Advanced Filters](ADVANCED_FILTERS.md)** - Complex search operators and patterns
12
12
  - **[Coding Standards](CODING_STANDARDS.md)** - Best practices for DZQL code
13
-
14
- ## Reference
15
-
16
- - **[Comparison](COMPARISON.md)** - How DZQL compares to other approaches
17
- - **[Session Summary](SESSION_SUMMARY.md)** - Development session documentation
18
- - **[Summary](SUMMARY.md)** - Compiler overview and architecture
19
- - **[Overnight Build](OVERNIGHT_BUILD.md)** - Batch compilation process
13
+ - **[Comparison](COMPARISON.md)** - Runtime vs compiled side-by-side
20
14
 
21
15
  ## Using the Compiler
22
16
 
@@ -0,0 +1,38 @@
1
+ # DZQL Examples
2
+
3
+ SQL examples demonstrating DZQL entity registration patterns.
4
+
5
+ ## Files
6
+
7
+ ### blog.sql
8
+ A complete blog application with:
9
+ - Multiple entities (users, posts, comments, tags)
10
+ - Many-to-many relationships (posts ↔ tags)
11
+ - Soft delete
12
+ - FK includes
13
+ - Permission paths
14
+ - Notification paths
15
+
16
+ ### venue-detail-simple.sql
17
+ Basic subscribable definition for venue data.
18
+
19
+ ### venue-detail-subscribable.sql
20
+ Full subscribable with relations and permission paths. Demonstrates:
21
+ - Root entity with FK includes
22
+ - Child entity filtering
23
+ - Permission path syntax
24
+
25
+ ## Usage
26
+
27
+ These files are meant to be run after DZQL core migrations. See the [Tutorial](../getting-started/tutorial.md) for complete setup instructions.
28
+
29
+ ```bash
30
+ # After setting up your database with DZQL migrations
31
+ psql $DATABASE_URL < examples/blog.sql
32
+ ```
33
+
34
+ ## See Also
35
+
36
+ - [API Reference](../reference/api.md) - Entity registration parameters
37
+ - [Many-to-Many Guide](../guides/many-to-many.md) - M2M configuration
38
+ - [Subscriptions Guide](../guides/subscriptions.md) - Subscribable patterns
@@ -0,0 +1,160 @@
1
+ -- ============================================================================
2
+ -- Blog Application Example
3
+ -- ============================================================================
4
+ --
5
+ -- This example demonstrates:
6
+ -- - Multiple related entities (users, posts, comments, tags)
7
+ -- - Many-to-many relationships (posts <-> tags via post_tags junction)
8
+ -- - Soft delete (posts.deleted_at)
9
+ -- - FK includes (dereferencing author, post)
10
+ -- - Permission paths (author can edit/delete own content)
11
+ -- - Notification paths (notify post author when comments added)
12
+ --
13
+ -- To use this example:
14
+ -- 1. Create tables first (see CREATE TABLE statements below)
15
+ -- 2. Run the dzql.register_entity() calls to enable CRUD operations
16
+ -- 3. Use the generated API: save_posts, get_posts, search_posts, etc.
17
+ --
18
+ -- For a complete working example with Docker, tests, and frontend:
19
+ -- See packages/blog/ in the DZQL repository
20
+ --
21
+ -- ============================================================================
22
+
23
+ -- Create tables
24
+ CREATE TABLE IF NOT EXISTS users (
25
+ id SERIAL PRIMARY KEY,
26
+ name VARCHAR(255) NOT NULL,
27
+ email VARCHAR(255) UNIQUE NOT NULL,
28
+ password_hash TEXT NOT NULL,
29
+ created_at TIMESTAMP DEFAULT NOW()
30
+ );
31
+
32
+ CREATE TABLE IF NOT EXISTS posts (
33
+ id SERIAL PRIMARY KEY,
34
+ title VARCHAR(500) NOT NULL,
35
+ content TEXT NOT NULL,
36
+ summary TEXT,
37
+ author_id INT REFERENCES users(id),
38
+ created_at TIMESTAMP DEFAULT NOW(),
39
+ deleted_at TIMESTAMP
40
+ );
41
+
42
+ CREATE TABLE IF NOT EXISTS comments (
43
+ id SERIAL PRIMARY KEY,
44
+ content TEXT NOT NULL,
45
+ post_id INT REFERENCES posts(id),
46
+ author_id INT REFERENCES users(id),
47
+ created_at TIMESTAMP DEFAULT NOW()
48
+ );
49
+
50
+ -- Tags table for categorizing posts
51
+ CREATE TABLE IF NOT EXISTS tags (
52
+ id SERIAL PRIMARY KEY,
53
+ name VARCHAR(50) UNIQUE NOT NULL,
54
+ color VARCHAR(7) DEFAULT '#3788d8'
55
+ );
56
+
57
+ -- Junction table for post-tag many-to-many relationship
58
+ CREATE TABLE IF NOT EXISTS post_tags (
59
+ post_id INT NOT NULL REFERENCES posts(id) ON DELETE CASCADE,
60
+ tag_id INT NOT NULL REFERENCES tags(id) ON DELETE CASCADE,
61
+ PRIMARY KEY (post_id, tag_id)
62
+ );
63
+
64
+ CREATE INDEX IF NOT EXISTS idx_post_tags_post_id ON post_tags(post_id);
65
+ CREATE INDEX IF NOT EXISTS idx_post_tags_tag_id ON post_tags(tag_id);
66
+
67
+ -- ============================================================================
68
+ -- DZQL Entity Registrations
69
+ -- ============================================================================
70
+
71
+ -- Users entity - blog authors
72
+ select dzql.register_entity(
73
+ 'users',
74
+ 'name',
75
+ array['name', 'email'],
76
+ '{}', -- no FK includes
77
+ false, -- hard delete
78
+ '{}', -- no reverse FK
79
+ '{}', -- no notifications
80
+ jsonb_build_object(
81
+ 'view', array[]::text[], -- Anyone can view users
82
+ 'create', array[]::text[], -- Anyone can register
83
+ 'update', array['@id'], -- Only update own profile
84
+ 'delete', array['@id'] -- Only delete own account
85
+ )
86
+ );
87
+
88
+ -- Register tags entity first
89
+ select dzql.register_entity(
90
+ 'tags',
91
+ 'name',
92
+ array['name'],
93
+ '{}', -- no FK includes
94
+ false, -- hard delete
95
+ '{}', -- no temporal
96
+ '{}', -- no notifications
97
+ jsonb_build_object(
98
+ 'view', array[]::text[], -- Anyone can view tags
99
+ 'create', array[]::text[], -- Anyone can create tags
100
+ 'update', array[]::text[], -- Anyone can update tags
101
+ 'delete', array[]::text[] -- Anyone can delete tags
102
+ )
103
+ );
104
+
105
+ -- Posts entity - blog posts with M2M tags
106
+ select dzql.register_entity(
107
+ 'posts',
108
+ 'title',
109
+ array['title', 'content', 'summary'],
110
+ jsonb_build_object(
111
+ 'author', 'users' -- FK to users
112
+ ),
113
+ true, -- soft delete (deleted_at)
114
+ '{}', -- no temporal
115
+ '{}', -- no notification paths
116
+ jsonb_build_object(
117
+ 'view', array[]::text[], -- Anyone can view posts
118
+ 'create', array[]::text[], -- Anyone can create posts
119
+ 'update', array['@author_id'], -- Only author can update
120
+ 'delete', array['@author_id'] -- Only author can delete
121
+ ),
122
+ jsonb_build_object(
123
+ 'many_to_many', jsonb_build_object(
124
+ 'tags', jsonb_build_object(
125
+ 'junction_table', 'post_tags',
126
+ 'local_key', 'post_id',
127
+ 'foreign_key', 'tag_id',
128
+ 'target_entity', 'tags',
129
+ 'id_field', 'tag_ids',
130
+ 'expand', true -- Include full tag objects in response
131
+ )
132
+ )
133
+ ) -- graph_rules with M2M
134
+ );
135
+
136
+ -- Comments entity - blog comments
137
+ select dzql.register_entity(
138
+ 'comments',
139
+ 'content',
140
+ array['content'],
141
+ jsonb_build_object(
142
+ 'post', 'posts',
143
+ 'author', 'users'
144
+ ),
145
+ false, -- hard delete
146
+ '{}', -- no reverse FK
147
+ jsonb_build_object(
148
+ 'post_author', array['@post_id->posts.author_id'],
149
+ 'commenters', array['@post_id']
150
+ ),
151
+ jsonb_build_object(
152
+ 'view', array[]::text[], -- Anyone can view comments
153
+ 'create', array[]::text[], -- Anyone can comment
154
+ 'update', array['@author_id'], -- Only author can update
155
+ 'delete', array[
156
+ '@author_id', -- Author can delete
157
+ '@post_id->posts.author_id' -- Post author can delete
158
+ ]
159
+ )
160
+ );
@@ -0,0 +1,8 @@
1
+ -- Simplified test subscribable for initial testing
2
+ SELECT dzql.register_subscribable(
3
+ 'venue_detail',
4
+ '{"subscribe": ["@org_id->acts_for[org_id=$]{active}.user_id"]}'::jsonb,
5
+ '{"venue_id": "int"}'::jsonb,
6
+ 'venues',
7
+ '{"org": "organisations", "sites": {"entity": "sites", "filter": "venue_id=$venue_id"}}'::jsonb
8
+ );
@@ -0,0 +1,45 @@
1
+ -- Example: Venue Detail Subscribable
2
+ -- This subscribable builds a denormalized document containing:
3
+ -- - The venue record
4
+ -- - The organization (FK expanded)
5
+ -- - All sites belonging to the venue
6
+ -- - All packages with their allocations
7
+
8
+ SELECT dzql.register_subscribable(
9
+ 'venue_detail',
10
+
11
+ -- Permission: who can subscribe?
12
+ -- Users who act_for the venue's organization (active roles only)
13
+ jsonb_build_object(
14
+ 'subscribe', ARRAY['@org_id->acts_for[org_id=$]{active}.user_id']
15
+ ),
16
+
17
+ -- Parameters: subscription key
18
+ jsonb_build_object(
19
+ 'venue_id', 'int'
20
+ ),
21
+
22
+ -- Root entity
23
+ 'venues',
24
+
25
+ -- Relations to include in document
26
+ jsonb_build_object(
27
+ -- FK expansion: organisation
28
+ 'org', 'organisations',
29
+
30
+ -- Child collection: sites
31
+ 'sites', jsonb_build_object(
32
+ 'entity', 'sites',
33
+ 'filter', 'venue_id=$venue_id'
34
+ ),
35
+
36
+ -- Child collection: packages with nested allocations
37
+ 'packages', jsonb_build_object(
38
+ 'entity', 'packages',
39
+ 'filter', 'venue_id=$venue_id',
40
+ 'include', jsonb_build_object(
41
+ 'allocations', 'allocations'
42
+ )
43
+ )
44
+ )
45
+ );
@@ -28,7 +28,7 @@ Live Query Subscriptions (Pattern 1 from vision.md) enable clients to subscribe
28
28
  Create a SQL file with your subscribable definition:
29
29
 
30
30
  ```sql
31
- -- examples/subscribables/venue_detail.sql
31
+ -- examples/venue-detail-subscribable.sql
32
32
  SELECT dzql.register_subscribable(
33
33
  'venue_detail',
34
34
  '{"subscribe": ["@org_id->acts_for[org_id=$]{active}.user_id"]}'::jsonb,
@@ -56,7 +56,7 @@ SELECT dzql.register_subscribable(
56
56
  ```bash
57
57
  # Compile subscribable to SQL functions
58
58
  bun packages/dzql/src/compiler/cli/compile-subscribable.js \
59
- examples/subscribables/venue_detail.sql \
59
+ examples/venue-detail-subscribable.sql \
60
60
  > /tmp/venue_detail.sql
61
61
 
62
62
  # Deploy to database
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dzql",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "description": "PostgreSQL-powered framework with zero boilerplate CRUD operations and real-time WebSocket synchronization",
5
5
  "type": "module",
6
6
  "main": "src/server/index.js",
@@ -19,6 +19,7 @@
19
19
  "src/**/*.js",
20
20
  "src/database/migrations/**/*.sql",
21
21
  "docs/**/*.md",
22
+ "docs/examples/*.sql",
22
23
  "README.md",
23
24
  "LICENSE"
24
25
  ],