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,157 +0,0 @@
1
- -- Migration 010: Atomic Updates for Subscribables
2
- -- Adds extract_scope_tables function and updates register_subscribable to auto-populate scope_tables
3
-
4
- -- ============================================================================
5
- -- Helper function to extract scope tables from relations
6
- -- ============================================================================
7
-
8
- CREATE OR REPLACE FUNCTION dzql.extract_scope_tables(
9
- p_root_entity TEXT,
10
- p_relations JSONB
11
- ) RETURNS TEXT[] AS $$
12
- DECLARE
13
- v_tables TEXT[];
14
- v_key TEXT;
15
- v_value JSONB;
16
- v_entity TEXT;
17
- v_nested JSONB;
18
- BEGIN
19
- -- Start with root entity (may be NULL for dashboard mode)
20
- IF p_root_entity IS NOT NULL AND p_root_entity != '' THEN
21
- v_tables := ARRAY[p_root_entity];
22
- ELSE
23
- v_tables := ARRAY[]::TEXT[];
24
- END IF;
25
-
26
- -- Return early if no relations
27
- IF p_relations IS NULL OR p_relations = '{}'::jsonb THEN
28
- RETURN v_tables;
29
- END IF;
30
-
31
- -- Iterate through relations
32
- FOR v_key, v_value IN SELECT * FROM jsonb_each(p_relations)
33
- LOOP
34
- -- Handle string relation (simple FK expansion): "org": "organisations"
35
- IF jsonb_typeof(v_value) = 'string' THEN
36
- v_entity := v_value #>> '{}';
37
- IF v_entity IS NOT NULL AND v_entity != '' THEN
38
- v_tables := array_append(v_tables, v_entity);
39
- END IF;
40
- -- Handle object relation: {"entity": "sites", "filter": "..."}
41
- ELSIF jsonb_typeof(v_value) = 'object' THEN
42
- v_entity := v_value ->> 'entity';
43
- IF v_entity IS NOT NULL AND v_entity != '' THEN
44
- v_tables := array_append(v_tables, v_entity);
45
- END IF;
46
-
47
- -- Recursively handle nested relations (include or relations)
48
- v_nested := v_value -> 'include';
49
- IF v_nested IS NOT NULL AND jsonb_typeof(v_nested) = 'object' THEN
50
- v_tables := v_tables || dzql.extract_scope_tables(NULL, v_nested);
51
- END IF;
52
-
53
- v_nested := v_value -> 'relations';
54
- IF v_nested IS NOT NULL AND jsonb_typeof(v_nested) = 'object' THEN
55
- v_tables := v_tables || dzql.extract_scope_tables(NULL, v_nested);
56
- END IF;
57
- END IF;
58
- END LOOP;
59
-
60
- -- Remove duplicates and nulls
61
- SELECT array_agg(DISTINCT t) INTO v_tables
62
- FROM unnest(v_tables) t
63
- WHERE t IS NOT NULL;
64
-
65
- RETURN COALESCE(v_tables, ARRAY[]::TEXT[]);
66
- END;
67
- $$ LANGUAGE plpgsql IMMUTABLE;
68
-
69
- COMMENT ON FUNCTION dzql.extract_scope_tables IS
70
- 'Extract all table names from a subscribable definition (root entity + all relations recursively)';
71
-
72
- -- ============================================================================
73
- -- Update register_subscribable to auto-populate scope_tables
74
- -- ============================================================================
75
-
76
- CREATE OR REPLACE FUNCTION dzql.register_subscribable(
77
- p_name TEXT,
78
- p_permission_paths JSONB,
79
- p_param_schema JSONB,
80
- p_root_entity TEXT,
81
- p_relations JSONB
82
- ) RETURNS TEXT AS $$
83
- DECLARE
84
- v_result TEXT;
85
- v_scope_tables TEXT[];
86
- BEGIN
87
- -- Validate inputs
88
- IF p_name IS NULL OR p_name = '' THEN
89
- RAISE EXCEPTION 'Subscribable name cannot be empty';
90
- END IF;
91
-
92
- -- NULL root_entity is allowed for dashboard mode (pure collections)
93
- -- But if relations is also empty, that's an error
94
- IF (p_root_entity IS NULL OR p_root_entity = '') AND
95
- (p_relations IS NULL OR p_relations = '{}'::jsonb) THEN
96
- RAISE EXCEPTION 'Subscribable must have either a root entity or relations';
97
- END IF;
98
-
99
- -- Extract scope tables from root entity and relations
100
- v_scope_tables := dzql.extract_scope_tables(p_root_entity, p_relations);
101
-
102
- -- Insert or update subscribable
103
- INSERT INTO dzql.subscribables (
104
- name,
105
- permission_paths,
106
- param_schema,
107
- root_entity,
108
- relations,
109
- scope_tables,
110
- created_at,
111
- updated_at
112
- ) VALUES (
113
- p_name,
114
- COALESCE(p_permission_paths, '{}'::jsonb),
115
- COALESCE(p_param_schema, '{}'::jsonb),
116
- NULLIF(p_root_entity, ''), -- Store empty string as NULL
117
- COALESCE(p_relations, '{}'::jsonb),
118
- v_scope_tables,
119
- NOW(),
120
- NOW()
121
- )
122
- ON CONFLICT (name) DO UPDATE SET
123
- permission_paths = EXCLUDED.permission_paths,
124
- param_schema = EXCLUDED.param_schema,
125
- root_entity = EXCLUDED.root_entity,
126
- relations = EXCLUDED.relations,
127
- scope_tables = EXCLUDED.scope_tables,
128
- updated_at = NOW();
129
-
130
- v_result := format('Subscribable "%s" registered successfully with scope tables: %s',
131
- p_name, array_to_string(v_scope_tables, ', '));
132
-
133
- RAISE NOTICE '%', v_result;
134
-
135
- RETURN v_result;
136
- END;
137
- $$ LANGUAGE plpgsql;
138
-
139
- -- ============================================================================
140
- -- Backfill existing subscribables with scope_tables
141
- -- ============================================================================
142
-
143
- UPDATE dzql.subscribables s
144
- SET scope_tables = dzql.extract_scope_tables(s.root_entity, s.relations)
145
- WHERE scope_tables = '{}' OR scope_tables IS NULL;
146
-
147
- -- ============================================================================
148
- -- Verification
149
- -- ============================================================================
150
-
151
- DO $$
152
- BEGIN
153
- RAISE NOTICE 'Migration 010: Atomic Updates - Complete';
154
- RAISE NOTICE 'Created dzql.extract_scope_tables() function';
155
- RAISE NOTICE 'Updated dzql.register_subscribable() to auto-populate scope_tables';
156
- RAISE NOTICE 'Backfilled existing subscribables';
157
- END $$;
@@ -1,94 +0,0 @@
1
- -- ============================================================================
2
- -- Migration 010: Fix M2M in Event "before" Field
3
- -- ============================================================================
4
- --
5
- -- Issue: UPDATE events don't include M2M data in the "before" field
6
- -- Root cause: l_existing_record in generic_save doesn't expand M2M relationships
7
- -- Fix: Create a helper function to expand M2M, then update generic_save to use it
8
- --
9
- -- This ensures UPDATE events have complete before/after state including M2M data
10
- -- ============================================================================
11
-
12
- DO $$ BEGIN
13
- RAISE NOTICE 'Migration 010: Fixing M2M in event before field...';
14
- END $$;
15
-
16
- -- Create helper function to expand M2M relationships for a record
17
- CREATE OR REPLACE FUNCTION dzql.expand_m2m_for_record(
18
- p_entity text,
19
- p_record jsonb,
20
- p_entity_config record,
21
- p_pk_cols text[]
22
- ) RETURNS jsonb
23
- LANGUAGE plpgsql
24
- AS $$
25
- DECLARE
26
- l_result jsonb := p_record;
27
- l_m2m_key text;
28
- l_m2m_config jsonb;
29
- l_id_field text;
30
- l_junction_table text;
31
- l_local_key text;
32
- l_foreign_key text;
33
- l_target_entity text;
34
- l_expand boolean;
35
- l_record_id text;
36
- l_id_array jsonb;
37
- l_expanded_objects jsonb;
38
- BEGIN
39
- -- Only expand if entity has M2M configuration
40
- IF p_entity_config.many_to_many IS NULL OR p_entity_config.many_to_many = '{}'::jsonb THEN
41
- RETURN l_result;
42
- END IF;
43
-
44
- -- Get the primary key value from the record
45
- l_record_id := l_result->>p_pk_cols[1]; -- Assume single PK for now
46
-
47
- IF l_record_id IS NULL THEN
48
- RETURN l_result;
49
- END IF;
50
-
51
- -- Loop through all M2M relationships
52
- FOR l_m2m_key IN SELECT jsonb_object_keys(p_entity_config.many_to_many)
53
- LOOP
54
- l_m2m_config := p_entity_config.many_to_many->l_m2m_key;
55
- l_id_field := l_m2m_config->>'id_field';
56
- l_junction_table := l_m2m_config->>'junction_table';
57
- l_local_key := l_m2m_config->>'local_key';
58
- l_foreign_key := l_m2m_config->>'foreign_key';
59
- l_target_entity := l_m2m_config->>'target_entity';
60
- l_expand := COALESCE((l_m2m_config->>'expand')::boolean, false);
61
-
62
- -- Always include array of IDs
63
- EXECUTE format('
64
- SELECT COALESCE(jsonb_agg(%I ORDER BY %I), ''[]''::jsonb)
65
- FROM %I
66
- WHERE %I = $1::int
67
- ', l_foreign_key, l_foreign_key, l_junction_table, l_local_key)
68
- INTO l_id_array
69
- USING l_record_id;
70
-
71
- l_result := l_result || jsonb_build_object(l_id_field, l_id_array);
72
-
73
- -- Conditionally include expanded objects if expand: true
74
- IF l_expand THEN
75
- EXECUTE format('
76
- SELECT COALESCE(jsonb_agg(to_jsonb(t.*) ORDER BY t.id), ''[]''::jsonb)
77
- FROM %I jt
78
- JOIN %I t ON t.id = jt.%I
79
- WHERE jt.%I = $1::int
80
- ', l_junction_table, l_target_entity, l_foreign_key, l_local_key)
81
- INTO l_expanded_objects
82
- USING l_record_id;
83
-
84
- l_result := l_result || jsonb_build_object(l_m2m_key, l_expanded_objects);
85
- END IF;
86
- END LOOP;
87
-
88
- RETURN l_result;
89
- END $$;
90
-
91
- DO $$ BEGIN
92
- RAISE NOTICE 'Migration 010: M2M expansion helper function created';
93
- RAISE NOTICE 'Note: generic_save still needs updating to use this helper - will be done in next migration';
94
- END $$;
package/src/index.js DELETED
@@ -1,40 +0,0 @@
1
- #!/usr/bin/env bun
2
- /**
3
- * DZQL Demo Server
4
- *
5
- * Minimal example server that serves demo.html and provides WebSocket functionality.
6
- * Run with: bun packages/dzql/src/index.js
7
- */
8
-
9
- import { createServer } from './server/index.js';
10
- import { fileURLToPath } from 'url';
11
- import { dirname, join } from 'path';
12
-
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = dirname(__filename);
15
-
16
- // Path to demo.html
17
- const demoPath = join(__dirname, 'client/demo.html');
18
-
19
- // Create DZQL server with demo route
20
- const app = createServer({
21
- port: 3000,
22
- routes: {
23
- '/': async () => {
24
- const file = Bun.file(demoPath);
25
- return new Response(file, {
26
- headers: { 'Content-Type': 'text/html' }
27
- });
28
- },
29
- '/demo': async () => {
30
- const file = Bun.file(demoPath);
31
- return new Response(file, {
32
- headers: { 'Content-Type': 'text/html' }
33
- });
34
- }
35
- }
36
- });
37
-
38
- console.log('🚀 DZQL Demo Server running');
39
- console.log('📝 Visit http://localhost:3000 to see the demo');
40
- console.log('🔌 WebSocket available at ws://localhost:3000/ws');
package/src/server/api.js DELETED
@@ -1,9 +0,0 @@
1
- export async function goodbye(userId, params = {}) {
2
- const { name = "World" } = params;
3
-
4
- return {
5
- message: `Goodbye, ${name}!`,
6
- from: "Bun",
7
- user_id: userId,
8
- };
9
- }