dzql 0.6.29 → 0.6.30
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/for_ai.md
CHANGED
|
@@ -44,11 +44,16 @@ SUBSCRIBABLE PATTERN
|
|
|
44
44
|
====================
|
|
45
45
|
sub_name: {
|
|
46
46
|
params: { param: 'type' },
|
|
47
|
-
root: { entity: 'table', key: 'param' },
|
|
47
|
+
root: { entity: 'table', key: 'param' }, // key must be in params, or '@user_id', or empty for lists
|
|
48
48
|
includes: { rel: { entity: 'table', includes: {...} } },
|
|
49
49
|
scopeTables: ['all', 'affected', 'tables'],
|
|
50
50
|
canSubscribe: ['permission_path']
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
ROOT KEY RULES:
|
|
54
|
+
- key: 'venue_id' -> must have params: { venue_id: 'int' }
|
|
55
|
+
- key: '@user_id' -> uses current user, no param needed
|
|
56
|
+
- key: '' or omit -> list subscribable (returns filtered array)
|
|
52
57
|
```
|
|
53
58
|
|
|
54
59
|
## Entity Definition
|
|
@@ -235,7 +240,7 @@ export const subscribables = {
|
|
|
235
240
|
|
|
236
241
|
root: {
|
|
237
242
|
entity: 'venues',
|
|
238
|
-
key: 'venue_id' //
|
|
243
|
+
key: 'venue_id' // Must match a param name
|
|
239
244
|
},
|
|
240
245
|
|
|
241
246
|
includes: {
|
package/package.json
CHANGED
|
@@ -11,6 +11,17 @@
|
|
|
11
11
|
import type { SubscribableIR, IncludeIR, EntityIR } from "../../shared/ir.js";
|
|
12
12
|
|
|
13
13
|
export function generateSubscribableSQL(name: string, sub: SubscribableIR, entities: Record<string, EntityIR> = {}): string {
|
|
14
|
+
// Validate: if root.key is set, it must exist in params or start with '@'
|
|
15
|
+
const rootKey = sub.root.key;
|
|
16
|
+
const paramNames = Object.keys(sub.params);
|
|
17
|
+
if (rootKey && !rootKey.startsWith('@') && !paramNames.includes(rootKey)) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`[Compiler] Subscribable '${name}' has root.key='${rootKey}' but no matching param. ` +
|
|
20
|
+
`Either add '${rootKey}' to params, use '@user_id' for user-scoped subscribables, ` +
|
|
21
|
+
`or remove the key for list subscribables.`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
14
25
|
const sections: string[] = [];
|
|
15
26
|
|
|
16
27
|
sections.push(generateHeader(name, sub));
|
|
@@ -69,6 +80,13 @@ $$;`;
|
|
|
69
80
|
` v_${p} := (p_params->>'${p}')::${sub.params[p]};`
|
|
70
81
|
).join('\n');
|
|
71
82
|
|
|
83
|
+
// Determine how to reference the root key in the WHERE clause
|
|
84
|
+
// Validation already done at top of generateSubscribableSQL
|
|
85
|
+
const rootKey = sub.root.key;
|
|
86
|
+
const rootKeyExpr = rootKey.startsWith('@')
|
|
87
|
+
? `p_${rootKey.slice(1)}` // @user_id -> p_user_id
|
|
88
|
+
: `v_${rootKey}`; // venue_id -> v_venue_id
|
|
89
|
+
|
|
72
90
|
return `CREATE OR REPLACE FUNCTION dzql_v2.${name}_can_subscribe(
|
|
73
91
|
p_user_id INT,
|
|
74
92
|
p_params JSONB
|
|
@@ -88,7 +106,7 @@ ${paramExtracts}
|
|
|
88
106
|
-- Fetch root entity
|
|
89
107
|
SELECT * INTO v_root
|
|
90
108
|
FROM ${sub.root.entity}
|
|
91
|
-
WHERE id =
|
|
109
|
+
WHERE id = ${rootKeyExpr};
|
|
92
110
|
|
|
93
111
|
IF NOT FOUND THEN
|
|
94
112
|
RETURN FALSE;
|
|
@@ -220,9 +238,9 @@ function generateGetFunction(name: string, sub: SubscribableIR, entities: Record
|
|
|
220
238
|
` v_${p} := (p_params->>'${p}')::${sub.params[p]};`
|
|
221
239
|
).join('\n');
|
|
222
240
|
|
|
223
|
-
// Handle special @
|
|
241
|
+
// Handle special @ prefixed root keys (e.g., @user_id -> p_user_id)
|
|
224
242
|
const rootKey = sub.root.key;
|
|
225
|
-
const
|
|
243
|
+
const isSpecialKey = rootKey.startsWith('@');
|
|
226
244
|
const isList = !rootKey; // No key means it's a list subscribable
|
|
227
245
|
|
|
228
246
|
// Build root select expression excluding hidden fields
|
|
@@ -242,7 +260,7 @@ function generateGetFunction(name: string, sub: SubscribableIR, entities: Record
|
|
|
242
260
|
// Build WHERE clause based on root filter and key
|
|
243
261
|
const whereConditions: string[] = [];
|
|
244
262
|
if (rootKey) {
|
|
245
|
-
const rootWhereValue =
|
|
263
|
+
const rootWhereValue = isSpecialKey ? `p_${rootKey.slice(1)}` : `v_${rootKey}`;
|
|
246
264
|
whereConditions.push(`root.id = ${rootWhereValue}`);
|
|
247
265
|
}
|
|
248
266
|
if (sub.root.filter) {
|