@soulbatical/tetra-core 0.1.13 → 0.1.15

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.

Potentially problematic release.


This version of @soulbatical/tetra-core might be problematic. Click here for more details.

Files changed (77) hide show
  1. package/dist/generators/rls-auditor.d.ts +39 -0
  2. package/dist/generators/rls-auditor.d.ts.map +1 -0
  3. package/dist/generators/rls-auditor.js +505 -0
  4. package/dist/generators/rls-auditor.js.map +1 -0
  5. package/dist/generators/rls-checker.d.ts +94 -0
  6. package/dist/generators/rls-checker.d.ts.map +1 -0
  7. package/dist/generators/rls-checker.js +215 -0
  8. package/dist/generators/rls-checker.js.map +1 -0
  9. package/dist/generators/rls-generator.d.ts +77 -0
  10. package/dist/generators/rls-generator.d.ts.map +1 -0
  11. package/dist/generators/rls-generator.js +402 -0
  12. package/dist/generators/rls-generator.js.map +1 -0
  13. package/dist/generators/rpc/detail-rpc-generator.d.ts +58 -0
  14. package/dist/generators/rpc/detail-rpc-generator.d.ts.map +1 -0
  15. package/dist/generators/rpc/detail-rpc-generator.js +163 -0
  16. package/dist/generators/rpc/detail-rpc-generator.js.map +1 -0
  17. package/dist/generators/rpc/index.d.ts +24 -0
  18. package/dist/generators/rpc/index.d.ts.map +1 -0
  19. package/dist/generators/rpc/index.js +20 -0
  20. package/dist/generators/rpc/index.js.map +1 -0
  21. package/dist/generators/rpc/rpc-generator.d.ts +150 -0
  22. package/dist/generators/rpc/rpc-generator.d.ts.map +1 -0
  23. package/dist/generators/rpc/rpc-generator.js +743 -0
  24. package/dist/generators/rpc/rpc-generator.js.map +1 -0
  25. package/dist/generators/rpc/templates/array.d.ts +29 -0
  26. package/dist/generators/rpc/templates/array.d.ts.map +1 -0
  27. package/dist/generators/rpc/templates/array.js +40 -0
  28. package/dist/generators/rpc/templates/array.js.map +1 -0
  29. package/dist/generators/rpc/templates/auth.d.ts +85 -0
  30. package/dist/generators/rpc/templates/auth.d.ts.map +1 -0
  31. package/dist/generators/rpc/templates/auth.js +233 -0
  32. package/dist/generators/rpc/templates/auth.js.map +1 -0
  33. package/dist/generators/rpc/templates/column.d.ts +39 -0
  34. package/dist/generators/rpc/templates/column.d.ts.map +1 -0
  35. package/dist/generators/rpc/templates/column.js +97 -0
  36. package/dist/generators/rpc/templates/column.js.map +1 -0
  37. package/dist/generators/rpc/templates/enum.d.ts +33 -0
  38. package/dist/generators/rpc/templates/enum.d.ts.map +1 -0
  39. package/dist/generators/rpc/templates/enum.js +93 -0
  40. package/dist/generators/rpc/templates/enum.js.map +1 -0
  41. package/dist/generators/rpc/templates/nullable.d.ts +31 -0
  42. package/dist/generators/rpc/templates/nullable.d.ts.map +1 -0
  43. package/dist/generators/rpc/templates/nullable.js +50 -0
  44. package/dist/generators/rpc/templates/nullable.js.map +1 -0
  45. package/dist/generators/rpc/templates/related.d.ts +47 -0
  46. package/dist/generators/rpc/templates/related.d.ts.map +1 -0
  47. package/dist/generators/rpc/templates/related.js +182 -0
  48. package/dist/generators/rpc/templates/related.js.map +1 -0
  49. package/dist/generators/rpc/templates/search.d.ts +42 -0
  50. package/dist/generators/rpc/templates/search.d.ts.map +1 -0
  51. package/dist/generators/rpc/templates/search.js +81 -0
  52. package/dist/generators/rpc/templates/search.js.map +1 -0
  53. package/dist/generators/rpc/templates/time.d.ts +44 -0
  54. package/dist/generators/rpc/templates/time.d.ts.map +1 -0
  55. package/dist/generators/rpc/templates/time.js +143 -0
  56. package/dist/generators/rpc/templates/time.js.map +1 -0
  57. package/dist/generators/rpc/utils.d.ts +58 -0
  58. package/dist/generators/rpc/utils.d.ts.map +1 -0
  59. package/dist/generators/rpc/utils.js +92 -0
  60. package/dist/generators/rpc/utils.js.map +1 -0
  61. package/dist/generators/rpc/validator.d.ts +21 -0
  62. package/dist/generators/rpc/validator.d.ts.map +1 -0
  63. package/dist/generators/rpc/validator.js +398 -0
  64. package/dist/generators/rpc/validator.js.map +1 -0
  65. package/dist/index.d.ts +9 -1
  66. package/dist/index.d.ts.map +1 -1
  67. package/dist/index.js +6 -0
  68. package/dist/index.js.map +1 -1
  69. package/dist/shared/auth/index.d.ts +1 -1
  70. package/dist/shared/auth/index.d.ts.map +1 -1
  71. package/dist/shared/auth/routes.d.ts +4 -1
  72. package/dist/shared/auth/routes.d.ts.map +1 -1
  73. package/dist/shared/auth/routes.js +83 -1
  74. package/dist/shared/auth/routes.js.map +1 -1
  75. package/dist/shared/auth/types.d.ts +24 -0
  76. package/dist/shared/auth/types.d.ts.map +1 -1
  77. package/package.json +1 -1
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Enum Filter Template
3
+ * For filters with predefined values (status, phase, etc.)
4
+ */
5
+ import { escapeIdentifier, getTableAlias } from '../utils.js';
6
+ /**
7
+ * Generate WHERE clause for enum filter
8
+ *
9
+ * @example
10
+ * // Input: { name: 'status', column: 'status', values: ['paid', 'pending'] }
11
+ * // Output: AND (p_status IS NULL OR p_status = 'all' OR status = p_status)
12
+ */
13
+ export function generateEnumWhere(filter, tableName, aliasMap) {
14
+ const paramName = `p_${filter.rpcParam || filter.name}`;
15
+ const column = escapeIdentifier(filter.column);
16
+ const alias = getTableAlias(tableName, aliasMap);
17
+ // Check if this is a boolean column with mapping
18
+ const booleanMapping = filter.sqlGeneration?.booleanMapping;
19
+ if (booleanMapping) {
20
+ // Generate conditions for boolean mapping (e.g., 'yes' → true, 'no' → false)
21
+ const conditions = Object.entries(booleanMapping)
22
+ .map(([textValue, boolValue]) => `(${paramName} = '${textValue}' AND ${alias}.${column} = ${boolValue})`)
23
+ .join('\n OR ');
24
+ return `
25
+ -- ${filter.name} (enum filter - boolean column)
26
+ AND (
27
+ ${paramName} IS NULL OR ${paramName} = 'all'
28
+ OR ${conditions}
29
+ )`;
30
+ }
31
+ return `
32
+ -- ${filter.name} (enum filter)
33
+ AND (${paramName} IS NULL OR ${paramName} = 'all' OR ${alias}.${column}::text = ${paramName})`;
34
+ }
35
+ /**
36
+ * Generate counts query for enum filter
37
+ * Uses UNION ALL pattern to ensure all values are present (even with count 0)
38
+ *
39
+ * @example
40
+ * // Input: { name: 'status', values: ['paid', 'pending', 'cancelled'] }
41
+ * // Output:
42
+ * // 'byStatus', (
43
+ * // SELECT jsonb_object_agg(status_value, cnt)
44
+ * // FROM (
45
+ * // SELECT 'paid' as status_value, COUNT(*)::int as cnt FROM filtered_items WHERE status = 'paid'
46
+ * // UNION ALL
47
+ * // SELECT 'pending' as status_value, COUNT(*)::int as cnt FROM filtered_items WHERE status = 'pending'
48
+ * // UNION ALL
49
+ * // SELECT 'cancelled' as status_value, COUNT(*)::int as cnt FROM filtered_items WHERE status = 'cancelled'
50
+ * // )
51
+ * // )
52
+ */
53
+ export function generateEnumCounts(filter) {
54
+ const countsKey = filter.countsKey || `by${filter.name.charAt(0).toUpperCase()}${filter.name.slice(1)}`;
55
+ let column = filter.column;
56
+ // Map joined columns to CTE aliases
57
+ if (column === 'o.status') {
58
+ column = 'order_status';
59
+ }
60
+ else if (column === 'o.source') {
61
+ column = 'order_source';
62
+ }
63
+ else {
64
+ column = escapeIdentifier(column);
65
+ }
66
+ if (!filter.values || filter.values.length === 0) {
67
+ throw new Error(`Enum filter "${filter.name}" missing values array`);
68
+ }
69
+ // Check if this is a boolean column with mapping
70
+ const booleanMapping = filter.sqlGeneration?.booleanMapping;
71
+ // Generate UNION ALL queries for each value
72
+ const unionQueries = filter.values.map(value => {
73
+ if (booleanMapping && booleanMapping[value] !== undefined) {
74
+ // Boolean column - compare with true/false
75
+ const boolValue = booleanMapping[value];
76
+ return ` SELECT '${value}' as ${filter.name}_value, COUNT(*)::int as cnt
77
+ FROM filtered_items WHERE ${column} = ${boolValue}`;
78
+ }
79
+ else {
80
+ // Regular text/enum column - compare with string (cast to text for enum types)
81
+ return ` SELECT '${value}' as ${filter.name}_value, COUNT(*)::int as cnt
82
+ FROM filtered_items WHERE ${column}::text = '${value}'`;
83
+ }
84
+ }).join('\n UNION ALL\n');
85
+ return `
86
+ '${countsKey}', (
87
+ SELECT jsonb_object_agg(${filter.name}_value, cnt)
88
+ FROM (
89
+ ${unionQueries}
90
+ ) subquery
91
+ )`;
92
+ }
93
+ //# sourceMappingURL=enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"enum.js","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/enum.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Nullable Filter Template
3
+ * For filters checking if field has value or is NULL (user presence, etc.)
4
+ */
5
+ import { FilterConfig } from '../../../shared/types/feature-config.js';
6
+ /**
7
+ * Generate WHERE clause for nullable filter
8
+ *
9
+ * @example
10
+ * // Input: { name: 'user', column: 'user_id' }
11
+ * // Output:
12
+ * // AND (
13
+ * // p_user IS NULL OR p_user = 'all'
14
+ * // OR (p_user = 'with' AND user_id IS NOT NULL)
15
+ * // OR (p_user = 'without' AND user_id IS NULL)
16
+ * // )
17
+ */
18
+ export declare function generateNullableWhere(filter: FilterConfig, tableName: string, aliasMap?: Record<string, string>): string;
19
+ /**
20
+ * Generate counts query for nullable filter
21
+ *
22
+ * @example
23
+ * // Input: { name: 'user', column: 'user_id' }
24
+ * // Output:
25
+ * // 'byUser', jsonb_build_object(
26
+ * // 'with', (SELECT COUNT(*)::int FROM filtered_items WHERE user_id IS NOT NULL),
27
+ * // 'without', (SELECT COUNT(*)::int FROM filtered_items WHERE user_id IS NULL)
28
+ * // )
29
+ */
30
+ export declare function generateNullableCounts(filter: FilterConfig): string;
31
+ //# sourceMappingURL=nullable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nullable.d.ts","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/nullable.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGvE;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAYxH;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CASnE"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Nullable Filter Template
3
+ * For filters checking if field has value or is NULL (user presence, etc.)
4
+ */
5
+ import { escapeIdentifier, getTableAlias } from '../utils.js';
6
+ /**
7
+ * Generate WHERE clause for nullable filter
8
+ *
9
+ * @example
10
+ * // Input: { name: 'user', column: 'user_id' }
11
+ * // Output:
12
+ * // AND (
13
+ * // p_user IS NULL OR p_user = 'all'
14
+ * // OR (p_user = 'with' AND user_id IS NOT NULL)
15
+ * // OR (p_user = 'without' AND user_id IS NULL)
16
+ * // )
17
+ */
18
+ export function generateNullableWhere(filter, tableName, aliasMap) {
19
+ const paramName = `p_${filter.rpcParam || filter.name}`;
20
+ const column = escapeIdentifier(filter.column);
21
+ const alias = getTableAlias(tableName, aliasMap);
22
+ return `
23
+ -- ${filter.name} (nullable filter - with/without)
24
+ AND (
25
+ ${paramName} IS NULL OR ${paramName} = 'all'
26
+ OR (${paramName} = 'with' AND ${alias}.${column} IS NOT NULL)
27
+ OR (${paramName} = 'without' AND ${alias}.${column} IS NULL)
28
+ )`;
29
+ }
30
+ /**
31
+ * Generate counts query for nullable filter
32
+ *
33
+ * @example
34
+ * // Input: { name: 'user', column: 'user_id' }
35
+ * // Output:
36
+ * // 'byUser', jsonb_build_object(
37
+ * // 'with', (SELECT COUNT(*)::int FROM filtered_items WHERE user_id IS NOT NULL),
38
+ * // 'without', (SELECT COUNT(*)::int FROM filtered_items WHERE user_id IS NULL)
39
+ * // )
40
+ */
41
+ export function generateNullableCounts(filter) {
42
+ const countsKey = filter.countsKey || `by${filter.name.charAt(0).toUpperCase()}${filter.name.slice(1)}`;
43
+ const column = escapeIdentifier(filter.column);
44
+ return `
45
+ '${countsKey}', jsonb_build_object(
46
+ 'with', (SELECT COUNT(*)::int FROM filtered_items WHERE ${column} IS NOT NULL),
47
+ 'without', (SELECT COUNT(*)::int FROM filtered_items WHERE ${column} IS NULL)
48
+ )`;
49
+ }
50
+ //# sourceMappingURL=nullable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nullable.js","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/nullable.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAoB,EAAE,SAAiB,EAAE,QAAiC;IAC9G,MAAM,SAAS,GAAG,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEjD,OAAO;WACE,MAAM,CAAC,IAAI;;UAEZ,SAAS,eAAe,SAAS;cAC7B,SAAS,iBAAiB,KAAK,IAAI,MAAM;cACzC,SAAS,oBAAoB,KAAK,IAAI,MAAM;QAClD,CAAC;AACT,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAoB;IACzD,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACxG,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAO,CAAC,CAAC;IAEhD,OAAO;OACF,SAAS;gEACgD,MAAM;mEACH,MAAM;MACnE,CAAC;AACP,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Related Filter Template
3
+ * For filters checking relationship existence (voucher, production, etc.)
4
+ */
5
+ import { FilterConfig } from '../../../shared/types/feature-config.js';
6
+ /**
7
+ * Generate WHERE clause for related filter
8
+ * Uses EXISTS/NOT EXISTS subqueries
9
+ *
10
+ * @example
11
+ * // Input:
12
+ * // {
13
+ * // name: 'voucher',
14
+ * // relatedTable: 'orderitems',
15
+ * // foreignKey: 'orderid',
16
+ * // sqlGeneration: {
17
+ * // joins: [
18
+ * // { table: 'orderitems oi', on: 'oi.orderid = o.id', type: 'LEFT' },
19
+ * // { table: 'vouchers v', on: 'v.orderitemid = oi.id', type: 'LEFT' }
20
+ * // ]
21
+ * // }
22
+ * // }
23
+ * //
24
+ * // Output:
25
+ * // AND (
26
+ * // p_voucher IS NULL OR p_voucher = 'all'
27
+ * // OR (p_voucher = 'with' AND EXISTS (
28
+ * // SELECT 1 FROM vouchers v
29
+ * // JOIN orderitems oi ON v.orderitemid = oi.id
30
+ * // WHERE oi.orderid = o.id
31
+ * // ))
32
+ * // OR (p_voucher = 'without' AND NOT EXISTS (...))
33
+ * // )
34
+ */
35
+ export declare function generateRelatedWhere(filter: FilterConfig, tableName: string, aliasMap?: Record<string, string>): string;
36
+ /**
37
+ * Generate counts query for related filter
38
+ *
39
+ * @example
40
+ * // Output:
41
+ * // 'byVoucher', jsonb_build_object(
42
+ * // 'with', (SELECT COUNT(*)::int FROM filtered_items WHERE EXISTS (...)),
43
+ * // 'without', (SELECT COUNT(*)::int FROM filtered_items WHERE NOT EXISTS (...))
44
+ * // )
45
+ */
46
+ export declare function generateRelatedCounts(filter: FilterConfig, tableName: string, aliasMap?: Record<string, string>): string;
47
+ //# sourceMappingURL=related.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"related.d.ts","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/related.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAcvH;AA8ED;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAUxH"}
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Related Filter Template
3
+ * For filters checking relationship existence (voucher, production, etc.)
4
+ */
5
+ import { getTableAlias } from '../utils.js';
6
+ /**
7
+ * Generate WHERE clause for related filter
8
+ * Uses EXISTS/NOT EXISTS subqueries
9
+ *
10
+ * @example
11
+ * // Input:
12
+ * // {
13
+ * // name: 'voucher',
14
+ * // relatedTable: 'orderitems',
15
+ * // foreignKey: 'orderid',
16
+ * // sqlGeneration: {
17
+ * // joins: [
18
+ * // { table: 'orderitems oi', on: 'oi.orderid = o.id', type: 'LEFT' },
19
+ * // { table: 'vouchers v', on: 'v.orderitemid = oi.id', type: 'LEFT' }
20
+ * // ]
21
+ * // }
22
+ * // }
23
+ * //
24
+ * // Output:
25
+ * // AND (
26
+ * // p_voucher IS NULL OR p_voucher = 'all'
27
+ * // OR (p_voucher = 'with' AND EXISTS (
28
+ * // SELECT 1 FROM vouchers v
29
+ * // JOIN orderitems oi ON v.orderitemid = oi.id
30
+ * // WHERE oi.orderid = o.id
31
+ * // ))
32
+ * // OR (p_voucher = 'without' AND NOT EXISTS (...))
33
+ * // )
34
+ */
35
+ export function generateRelatedWhere(filter, tableName, aliasMap) {
36
+ const paramName = `p_${filter.rpcParam || filter.name}`;
37
+ const alias = getTableAlias(tableName, aliasMap);
38
+ // Check for custom joins configuration
39
+ const joins = filter.sqlGeneration?.joins;
40
+ if (joins && joins.length > 0) {
41
+ // Complex related filter with custom joins
42
+ return generateComplexRelatedWhere(filter, tableName, alias, paramName, joins);
43
+ }
44
+ // Simple related filter (single table JOIN)
45
+ return generateSimpleRelatedWhere(filter, alias, paramName);
46
+ }
47
+ /**
48
+ * Generate simple related WHERE clause (single table)
49
+ * v3.11: Add public. prefix for Postgres v17 compatibility
50
+ */
51
+ function generateSimpleRelatedWhere(filter, alias, paramName) {
52
+ const relatedTable = filter.relatedTable;
53
+ const foreignKey = filter.foreignKey;
54
+ return `
55
+ -- ${filter.name} (related filter - with/without)
56
+ AND (
57
+ ${paramName} IS NULL OR ${paramName} = 'all'
58
+ OR (${paramName} = 'with' AND EXISTS (
59
+ SELECT 1 FROM public.${relatedTable}
60
+ WHERE ${foreignKey} = ${alias}.id
61
+ ))
62
+ OR (${paramName} = 'without' AND NOT EXISTS (
63
+ SELECT 1 FROM public.${relatedTable}
64
+ WHERE ${foreignKey} = ${alias}.id
65
+ ))
66
+ )`;
67
+ }
68
+ /**
69
+ * Generate complex related WHERE clause (multiple JOINs)
70
+ * v3.11: Add public. prefix for Postgres v17 compatibility
71
+ */
72
+ function generateComplexRelatedWhere(filter, _tableName, _alias, paramName, joins) {
73
+ // Build JOIN chain - add public. prefix to table names
74
+ const firstJoin = joins[0];
75
+ const firstJoinTable = addPublicPrefix(firstJoin.table);
76
+ const remainingJoins = joins.slice(1);
77
+ const joinChain = remainingJoins
78
+ .map(join => ` ${join.type} JOIN ${addPublicPrefix(join.table)} ON ${join.on}`)
79
+ .join('\n');
80
+ return `
81
+ -- ${filter.name} (related filter - complex with joins)
82
+ AND (
83
+ ${paramName} IS NULL OR ${paramName} = 'all'
84
+ OR (${paramName} = 'with' AND EXISTS (
85
+ SELECT 1 FROM ${firstJoinTable}
86
+ ${joinChain}
87
+ WHERE ${firstJoin.on}
88
+ ))
89
+ OR (${paramName} = 'without' AND NOT EXISTS (
90
+ SELECT 1 FROM ${firstJoinTable}
91
+ ${joinChain}
92
+ WHERE ${firstJoin.on}
93
+ ))
94
+ )`;
95
+ }
96
+ /**
97
+ * Add public. prefix to table reference (handles "tablename alias" format)
98
+ */
99
+ function addPublicPrefix(tableWithAlias) {
100
+ // Handle "tablename alias" format (e.g., "orderitems oi" → "public.orderitems oi")
101
+ const parts = tableWithAlias.trim().split(/\s+/);
102
+ if (parts.length >= 1) {
103
+ parts[0] = `public.${parts[0]}`;
104
+ }
105
+ return parts.join(' ');
106
+ }
107
+ /**
108
+ * Generate counts query for related filter
109
+ *
110
+ * @example
111
+ * // Output:
112
+ * // 'byVoucher', jsonb_build_object(
113
+ * // 'with', (SELECT COUNT(*)::int FROM filtered_items WHERE EXISTS (...)),
114
+ * // 'without', (SELECT COUNT(*)::int FROM filtered_items WHERE NOT EXISTS (...))
115
+ * // )
116
+ */
117
+ export function generateRelatedCounts(filter, tableName, aliasMap) {
118
+ const countsKey = filter.countsKey || `by${filter.name.charAt(0).toUpperCase()}${filter.name.slice(1)}`;
119
+ const alias = getTableAlias(tableName, aliasMap);
120
+ const joins = filter.sqlGeneration?.joins;
121
+ if (joins && joins.length > 0) {
122
+ return generateComplexRelatedCounts(filter, countsKey, alias, joins);
123
+ }
124
+ return generateSimpleRelatedCounts(filter, countsKey, alias);
125
+ }
126
+ /**
127
+ * Generate simple related counts (single table)
128
+ * v3.11: Add public. prefix for Postgres v17 compatibility
129
+ */
130
+ function generateSimpleRelatedCounts(filter, countsKey, alias) {
131
+ const relatedTable = filter.relatedTable;
132
+ const foreignKey = filter.foreignKey;
133
+ return `
134
+ '${countsKey}', jsonb_build_object(
135
+ 'with', (
136
+ SELECT COUNT(*)::int FROM filtered_items ${alias}
137
+ WHERE EXISTS (
138
+ SELECT 1 FROM public.${relatedTable}
139
+ WHERE ${foreignKey} = ${alias}.id
140
+ )
141
+ ),
142
+ 'without', (
143
+ SELECT COUNT(*)::int FROM filtered_items ${alias}
144
+ WHERE NOT EXISTS (
145
+ SELECT 1 FROM public.${relatedTable}
146
+ WHERE ${foreignKey} = ${alias}.id
147
+ )
148
+ )
149
+ )`;
150
+ }
151
+ /**
152
+ * Generate complex related counts (multiple JOINs)
153
+ * v3.11: Add public. prefix for Postgres v17 compatibility
154
+ */
155
+ function generateComplexRelatedCounts(filter, countsKey, alias, joins) {
156
+ const firstJoin = joins[0];
157
+ const firstJoinTable = addPublicPrefix(firstJoin.table);
158
+ const remainingJoins = joins.slice(1);
159
+ const joinChain = remainingJoins
160
+ .map(join => ` ${join.type} JOIN ${addPublicPrefix(join.table)} ON ${join.on}`)
161
+ .join('\n');
162
+ return `
163
+ '${countsKey}', jsonb_build_object(
164
+ 'with', (
165
+ SELECT COUNT(*)::int FROM filtered_items ${alias}
166
+ WHERE EXISTS (
167
+ SELECT 1 FROM ${firstJoinTable}
168
+ ${joinChain}
169
+ WHERE ${firstJoin.on}
170
+ )
171
+ ),
172
+ 'without', (
173
+ SELECT COUNT(*)::int FROM filtered_items ${alias}
174
+ WHERE NOT EXISTS (
175
+ SELECT 1 FROM ${firstJoinTable}
176
+ ${joinChain}
177
+ WHERE ${firstJoin.on}
178
+ )
179
+ )
180
+ )`;
181
+ }
182
+ //# sourceMappingURL=related.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"related.js","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/related.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Search Filter Template
3
+ * For multi-field text search filters
4
+ */
5
+ import { FilterConfig } from '../../../shared/types/feature-config.js';
6
+ /**
7
+ * Generate WHERE clause for search filter
8
+ * Uses ILIKE for case-insensitive search + pg_trgm for fuzzy matching
9
+ *
10
+ * Features:
11
+ * - ILIKE: Fast wildcard search (e.g., 'test' finds 'Test Product')
12
+ * - pg_trgm similarity: Fuzzy matching (e.g., 'tst' finds 'test')
13
+ * - Threshold: 0.2 for trigram similarity (lower = more fuzzy)
14
+ *
15
+ * @example
16
+ * // Input:
17
+ * // {
18
+ * // name: 'search',
19
+ * // sqlGeneration: {
20
+ * // searchFields: ['reference', 'first_name', 'last_name', 'user_email']
21
+ * // }
22
+ * // }
23
+ * //
24
+ * // Output:
25
+ * // AND (
26
+ * // p_search IS NULL OR p_search = '' OR p_search = 'all'
27
+ * // OR (
28
+ * // o.reference ILIKE '%' || p_search || '%'
29
+ * // OR similarity(o.reference, p_search) > 0.2
30
+ * // OR o.first_name ILIKE '%' || p_search || '%'
31
+ * // OR similarity(o.first_name, p_search) > 0.2
32
+ * // ...
33
+ * // )
34
+ * // )
35
+ */
36
+ export declare function generateSearchWhere(filter: FilterConfig, tableName: string, aliasMap?: Record<string, string>): string;
37
+ /**
38
+ * Search filters don't have counts (no aggregation needed)
39
+ * Returns empty string
40
+ */
41
+ export declare function generateSearchCounts(_filter: FilterConfig): string;
42
+ //# sourceMappingURL=search.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAwCtH;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM,CAElE"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Search Filter Template
3
+ * For multi-field text search filters
4
+ */
5
+ import { escapeIdentifier, getTableAlias } from '../utils.js';
6
+ /**
7
+ * Generate WHERE clause for search filter
8
+ * Uses ILIKE for case-insensitive search + pg_trgm for fuzzy matching
9
+ *
10
+ * Features:
11
+ * - ILIKE: Fast wildcard search (e.g., 'test' finds 'Test Product')
12
+ * - pg_trgm similarity: Fuzzy matching (e.g., 'tst' finds 'test')
13
+ * - Threshold: 0.2 for trigram similarity (lower = more fuzzy)
14
+ *
15
+ * @example
16
+ * // Input:
17
+ * // {
18
+ * // name: 'search',
19
+ * // sqlGeneration: {
20
+ * // searchFields: ['reference', 'first_name', 'last_name', 'user_email']
21
+ * // }
22
+ * // }
23
+ * //
24
+ * // Output:
25
+ * // AND (
26
+ * // p_search IS NULL OR p_search = '' OR p_search = 'all'
27
+ * // OR (
28
+ * // o.reference ILIKE '%' || p_search || '%'
29
+ * // OR similarity(o.reference, p_search) > 0.2
30
+ * // OR o.first_name ILIKE '%' || p_search || '%'
31
+ * // OR similarity(o.first_name, p_search) > 0.2
32
+ * // ...
33
+ * // )
34
+ * // )
35
+ */
36
+ export function generateSearchWhere(filter, tableName, aliasMap) {
37
+ const paramName = `p_${filter.rpcParam || filter.name}`;
38
+ const alias = getTableAlias(tableName, aliasMap);
39
+ // Get search fields from sqlGeneration config
40
+ const searchFields = filter.sqlGeneration?.searchFields;
41
+ if (!searchFields || searchFields.length === 0) {
42
+ throw new Error(`Search filter "${filter.name}" missing searchFields in sqlGeneration config`);
43
+ }
44
+ // Generate ILIKE + similarity conditions for each field
45
+ // Support format: 'field' or 'relation.field' (e.g., 'user.firstname')
46
+ // v3.11: Use extensions.similarity() for Postgres v17 compatibility (pg_trgm is in extensions schema)
47
+ const searchCond = searchFields
48
+ .map(field => {
49
+ if (field.includes('.')) {
50
+ // Relational field (e.g., 'user.firstname')
51
+ const [relation, relField] = field.split('.');
52
+ const relAlias = relation.substring(0, 1); // 'u' for 'user'
53
+ const escapedField = escapeIdentifier(relField);
54
+ // Both ILIKE (exact substring) AND fuzzy similarity
55
+ return ` ${relAlias}.${escapedField} ILIKE '%' || ${paramName} || '%'\n OR extensions.similarity(${relAlias}.${escapedField}, ${paramName}) > 0.2`;
56
+ }
57
+ else {
58
+ // Direct field on main table
59
+ const escapedField = escapeIdentifier(field);
60
+ // Both ILIKE (exact substring) AND fuzzy similarity
61
+ return ` ${alias}.${escapedField} ILIKE '%' || ${paramName} || '%'\n OR extensions.similarity(${alias}.${escapedField}, ${paramName}) > 0.2`;
62
+ }
63
+ })
64
+ .join('\n OR ');
65
+ return `
66
+ -- ${filter.name} (search filter - ILIKE + fuzzy matching with pg_trgm)
67
+ AND (
68
+ ${paramName} IS NULL OR ${paramName} = '' OR ${paramName} = 'all'
69
+ OR (
70
+ ${searchCond}
71
+ )
72
+ )`;
73
+ }
74
+ /**
75
+ * Search filters don't have counts (no aggregation needed)
76
+ * Returns empty string
77
+ */
78
+ export function generateSearchCounts(_filter) {
79
+ return ''; // Search filters don't generate counts
80
+ }
81
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search.js","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAoB,EAAE,SAAiB,EAAE,QAAiC;IAC5G,MAAM,SAAS,GAAG,KAAK,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;IACxD,MAAM,KAAK,GAAG,aAAa,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEjD,8CAA8C;IAC9C,MAAM,YAAY,GAAG,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC;IAExD,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,kBAAkB,MAAM,CAAC,IAAI,gDAAgD,CAAC,CAAC;IACjG,CAAC;IAED,wDAAwD;IACxD,uEAAuE;IACvE,sGAAsG;IACtG,MAAM,UAAU,GAAG,YAAY;SAC5B,GAAG,CAAC,KAAK,CAAC,EAAE;QACX,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,4CAA4C;YAC5C,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC9C,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,iBAAiB;YAC5D,MAAM,YAAY,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YAChD,oDAAoD;YACpD,OAAO,WAAW,QAAQ,IAAI,YAAY,iBAAiB,SAAS,6CAA6C,QAAQ,IAAI,YAAY,KAAK,SAAS,SAAS,CAAC;QACnK,CAAC;aAAM,CAAC;YACN,6BAA6B;YAC7B,MAAM,YAAY,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC7C,oDAAoD;YACpD,OAAO,WAAW,KAAK,IAAI,YAAY,iBAAiB,SAAS,6CAA6C,KAAK,IAAI,YAAY,KAAK,SAAS,SAAS,CAAC;QAC7J,CAAC;IACH,CAAC,CAAC;SACD,IAAI,CAAC,eAAe,CAAC,CAAC;IAEzB,OAAO;WACE,MAAM,CAAC,IAAI;;UAEZ,SAAS,eAAe,SAAS,YAAY,SAAS;;EAE9D,UAAU;;QAEJ,CAAC;AACT,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAqB;IACxD,OAAO,EAAE,CAAC,CAAC,uCAAuC;AACpD,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Time Filter Template
3
+ * For filters based on date ranges (this-week, this-month, older)
4
+ */
5
+ import { FilterConfig } from '../../../shared/types/feature-config.js';
6
+ /**
7
+ * Generate WHERE clause for time filter
8
+ *
9
+ * @example
10
+ * // Input:
11
+ * // {
12
+ * // name: 'time_period',
13
+ * // dateField: 'order_date',
14
+ * // sqlGeneration: {
15
+ * // timePeriods: {
16
+ * // thisWeek: { interval: '7 days', operator: '>=' },
17
+ * // thisMonth: { interval: '30 days', operator: '>=' },
18
+ * // older: { interval: '30 days', operator: '<' }
19
+ * // }
20
+ * // }
21
+ * // }
22
+ * //
23
+ * // Output:
24
+ * // AND (
25
+ * // p_time_period IS NULL OR p_time_period = 'all'
26
+ * // OR (p_time_period = 'thisWeek' AND order_date >= CURRENT_DATE - INTERVAL '7 days')
27
+ * // OR (p_time_period = 'thisMonth' AND order_date >= CURRENT_DATE - INTERVAL '30 days')
28
+ * // OR (p_time_period = 'older' AND order_date < CURRENT_DATE - INTERVAL '30 days')
29
+ * // )
30
+ */
31
+ export declare function generateTimeWhere(filter: FilterConfig, tableName: string, aliasMap?: Record<string, string>): string;
32
+ /**
33
+ * Generate counts query for time filter
34
+ *
35
+ * @example
36
+ * // Output:
37
+ * // 'byTimePeriod', jsonb_build_object(
38
+ * // 'thisWeek', (SELECT COUNT(*)::int FROM filtered_items WHERE order_date >= CURRENT_DATE - INTERVAL '7 days'),
39
+ * // 'thisMonth', (SELECT COUNT(*)::int FROM filtered_items WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'),
40
+ * // 'older', (SELECT COUNT(*)::int FROM filtered_items WHERE order_date < CURRENT_DATE - INTERVAL '30 days')
41
+ * // )
42
+ */
43
+ export declare function generateTimeCounts(filter: FilterConfig): string;
44
+ //# sourceMappingURL=time.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/time.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,yCAAyC,CAAC;AAGvE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAcpH;AAgDD;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAa/D"}