@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,143 @@
1
+ /**
2
+ * Time Filter Template
3
+ * For filters based on date ranges (this-week, this-month, older)
4
+ */
5
+ import { escapeIdentifier, getTableAlias } from '../utils.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 function generateTimeWhere(filter, tableName, aliasMap) {
32
+ const paramName = `p_${filter.rpcParam || filter.name}`;
33
+ const dateField = escapeIdentifier(filter.dateField || filter.column || 'created_at');
34
+ const alias = getTableAlias(tableName, aliasMap);
35
+ // Check for custom time periods configuration
36
+ const timePeriods = filter.sqlGeneration?.timePeriods;
37
+ if (timePeriods) {
38
+ return generateCustomTimeWhere(filter, alias, paramName, dateField, timePeriods);
39
+ }
40
+ // Default time periods (standard: this-week, this-month, older)
41
+ return generateDefaultTimeWhere(filter, alias, paramName, dateField);
42
+ }
43
+ /**
44
+ * Generate default time WHERE clause
45
+ * PostgreSQL Standard: Uses snake_case for parameter values
46
+ */
47
+ function generateDefaultTimeWhere(filter, alias, paramName, dateField) {
48
+ return `
49
+ -- ${filter.name} (time filter - date ranges)
50
+ AND (
51
+ ${paramName} IS NULL OR ${paramName} = 'all'
52
+ OR (${paramName} = 'today' AND ${alias}.${dateField} >= CURRENT_DATE)
53
+ OR (${paramName} = 'yesterday' AND ${alias}.${dateField} >= CURRENT_DATE - INTERVAL '1 day' AND ${alias}.${dateField} < CURRENT_DATE)
54
+ OR (${paramName} = 'this_week' AND ${alias}.${dateField} >= CURRENT_DATE - INTERVAL '7 days')
55
+ OR (${paramName} = 'this_month' AND ${alias}.${dateField} >= CURRENT_DATE - INTERVAL '30 days')
56
+ OR (${paramName} = 'older' AND ${alias}.${dateField} >= CURRENT_DATE - INTERVAL '90 days')
57
+ )`;
58
+ }
59
+ /**
60
+ * Generate custom time WHERE clause
61
+ */
62
+ function generateCustomTimeWhere(filter, alias, paramName, dateField, timePeriods) {
63
+ const conditions = Object.entries(timePeriods)
64
+ .map(([period, config]) => {
65
+ return ` OR (${paramName} = '${period}' AND ${alias}.${dateField} ${config.operator} CURRENT_DATE - INTERVAL '${config.interval}')`;
66
+ })
67
+ .join('\n');
68
+ return `
69
+ -- ${filter.name} (time filter - custom periods)
70
+ AND (
71
+ ${paramName} IS NULL OR ${paramName} = 'all'
72
+ ${conditions}
73
+ )`;
74
+ }
75
+ /**
76
+ * Generate counts query for time filter
77
+ *
78
+ * @example
79
+ * // Output:
80
+ * // 'byTimePeriod', jsonb_build_object(
81
+ * // 'thisWeek', (SELECT COUNT(*)::int FROM filtered_items WHERE order_date >= CURRENT_DATE - INTERVAL '7 days'),
82
+ * // 'thisMonth', (SELECT COUNT(*)::int FROM filtered_items WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'),
83
+ * // 'older', (SELECT COUNT(*)::int FROM filtered_items WHERE order_date < CURRENT_DATE - INTERVAL '30 days')
84
+ * // )
85
+ */
86
+ export function generateTimeCounts(filter) {
87
+ const countsKey = filter.countsKey || `by${filter.name.charAt(0).toUpperCase()}${filter.name.slice(1)}`;
88
+ const dateField = escapeIdentifier(filter.dateField || filter.column || 'created_at');
89
+ // Check for custom time periods configuration
90
+ const timePeriods = filter.sqlGeneration?.timePeriods;
91
+ if (timePeriods) {
92
+ return generateCustomTimeCounts(countsKey, dateField, timePeriods);
93
+ }
94
+ // Default time counts
95
+ return generateDefaultTimeCounts(countsKey, dateField);
96
+ }
97
+ /**
98
+ * Generate default time counts
99
+ * PostgreSQL Standard: Uses snake_case for keys
100
+ */
101
+ function generateDefaultTimeCounts(countsKey, dateField) {
102
+ return `
103
+ '${countsKey}', jsonb_build_object(
104
+ 'today', (
105
+ SELECT COUNT(*)::int FROM filtered_items
106
+ WHERE ${dateField} >= CURRENT_DATE
107
+ ),
108
+ 'yesterday', (
109
+ SELECT COUNT(*)::int FROM filtered_items
110
+ WHERE ${dateField} >= CURRENT_DATE - INTERVAL '1 day' AND ${dateField} < CURRENT_DATE
111
+ ),
112
+ 'this_week', (
113
+ SELECT COUNT(*)::int FROM filtered_items
114
+ WHERE ${dateField} >= CURRENT_DATE - INTERVAL '7 days'
115
+ ),
116
+ 'this_month', (
117
+ SELECT COUNT(*)::int FROM filtered_items
118
+ WHERE ${dateField} >= CURRENT_DATE - INTERVAL '30 days'
119
+ ),
120
+ 'older', (
121
+ SELECT COUNT(*)::int FROM filtered_items
122
+ WHERE ${dateField} >= CURRENT_DATE - INTERVAL '90 days'
123
+ )
124
+ )`;
125
+ }
126
+ /**
127
+ * Generate custom time counts
128
+ */
129
+ function generateCustomTimeCounts(countsKey, dateField, timePeriods) {
130
+ const countQueries = Object.entries(timePeriods)
131
+ .map(([period, config]) => {
132
+ return ` '${period}', (
133
+ SELECT COUNT(*)::int FROM filtered_items
134
+ WHERE ${dateField} ${config.operator} CURRENT_DATE - INTERVAL '${config.interval}'
135
+ )`;
136
+ })
137
+ .join(',\n');
138
+ return `
139
+ '${countsKey}', jsonb_build_object(
140
+ ${countQueries}
141
+ )`;
142
+ }
143
+ //# sourceMappingURL=time.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"time.js","sourceRoot":"","sources":["../../../../src/generators/rpc/templates/time.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * SQL Generator Utilities
3
+ * Helper functions for SQL generation
4
+ */
5
+ /**
6
+ * Capitalize first letter of string
7
+ */
8
+ export declare function capitalize(str: string): string;
9
+ /**
10
+ * Convert kebab-case to camelCase
11
+ * Used for RPC parameter values
12
+ *
13
+ * @example
14
+ * kebabToCamelCase('this-week') // 'thisWeek'
15
+ * kebabToCamelCase('paid') // 'paid'
16
+ */
17
+ export declare function kebabToCamelCase(str: string): string;
18
+ /**
19
+ * Convert snake_case to camelCase
20
+ *
21
+ * @example
22
+ * snakeToCamelCase('payment_method') // 'paymentMethod'
23
+ * snakeToCamelCase('status') // 'status'
24
+ */
25
+ export declare function snakeToCamelCase(str: string): string;
26
+ /**
27
+ * Convert filter name to counts key
28
+ *
29
+ * @example
30
+ * filterNameToCountsKey('status') // 'byStatus'
31
+ * filterNameToCountsKey('payment_method') // 'byPaymentMethod'
32
+ */
33
+ export declare function filterNameToCountsKey(filterName: string): string;
34
+ /**
35
+ * Generate timestamp for migration filename
36
+ * Format: YYYYMMDDHHmmss
37
+ */
38
+ export declare function generateTimestamp(offset?: number): string;
39
+ /**
40
+ * Indent SQL string
41
+ */
42
+ export declare function indent(sql: string, spaces?: number): string;
43
+ /**
44
+ * Escape SQL identifier (table name, column name)
45
+ */
46
+ export declare function escapeIdentifier(identifier: string): string;
47
+ /**
48
+ * Get table alias from table name
49
+ *
50
+ * Accepts an optional custom alias map for project-specific overrides.
51
+ * Falls back to first character of the table name.
52
+ *
53
+ * @example
54
+ * getTableAlias('campaigns') // 'c'
55
+ * getTableAlias('orders', { orders: 'o', orderitems: 'oi' }) // 'o'
56
+ */
57
+ export declare function getTableAlias(tableName: string, aliasMap?: Record<string, string>): string;
58
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/generators/rpc/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAGhE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,MAAU,GAAG,MAAM,CAY5D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAG9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAS3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAM1F"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * SQL Generator Utilities
3
+ * Helper functions for SQL generation
4
+ */
5
+ /**
6
+ * Capitalize first letter of string
7
+ */
8
+ export function capitalize(str) {
9
+ return str.charAt(0).toUpperCase() + str.slice(1);
10
+ }
11
+ /**
12
+ * Convert kebab-case to camelCase
13
+ * Used for RPC parameter values
14
+ *
15
+ * @example
16
+ * kebabToCamelCase('this-week') // 'thisWeek'
17
+ * kebabToCamelCase('paid') // 'paid'
18
+ */
19
+ export function kebabToCamelCase(str) {
20
+ return str.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
21
+ }
22
+ /**
23
+ * Convert snake_case to camelCase
24
+ *
25
+ * @example
26
+ * snakeToCamelCase('payment_method') // 'paymentMethod'
27
+ * snakeToCamelCase('status') // 'status'
28
+ */
29
+ export function snakeToCamelCase(str) {
30
+ return str.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
31
+ }
32
+ /**
33
+ * Convert filter name to counts key
34
+ *
35
+ * @example
36
+ * filterNameToCountsKey('status') // 'byStatus'
37
+ * filterNameToCountsKey('payment_method') // 'byPaymentMethod'
38
+ */
39
+ export function filterNameToCountsKey(filterName) {
40
+ const camelCase = snakeToCamelCase(filterName);
41
+ return `by${capitalize(camelCase)}`;
42
+ }
43
+ /**
44
+ * Generate timestamp for migration filename
45
+ * Format: YYYYMMDDHHmmss
46
+ */
47
+ export function generateTimestamp(offset = 0) {
48
+ const now = new Date();
49
+ now.setSeconds(now.getSeconds() + offset);
50
+ const year = now.getFullYear();
51
+ const month = String(now.getMonth() + 1).padStart(2, '0');
52
+ const day = String(now.getDate()).padStart(2, '0');
53
+ const hours = String(now.getHours()).padStart(2, '0');
54
+ const minutes = String(now.getMinutes()).padStart(2, '0');
55
+ const seconds = String(now.getSeconds()).padStart(2, '0');
56
+ return `${year}${month}${day}${hours}${minutes}${seconds}`;
57
+ }
58
+ /**
59
+ * Indent SQL string
60
+ */
61
+ export function indent(sql, spaces = 2) {
62
+ const indentation = ' '.repeat(spaces);
63
+ return sql.split('\n').map(line => indentation + line).join('\n');
64
+ }
65
+ /**
66
+ * Escape SQL identifier (table name, column name)
67
+ */
68
+ export function escapeIdentifier(identifier) {
69
+ // PostgreSQL reserved keywords that need quoting
70
+ const reservedKeywords = ['user', 'order', 'group', 'table', 'column'];
71
+ if (reservedKeywords.includes(identifier.toLowerCase())) {
72
+ return `"${identifier}"`;
73
+ }
74
+ return identifier;
75
+ }
76
+ /**
77
+ * Get table alias from table name
78
+ *
79
+ * Accepts an optional custom alias map for project-specific overrides.
80
+ * Falls back to first character of the table name.
81
+ *
82
+ * @example
83
+ * getTableAlias('campaigns') // 'c'
84
+ * getTableAlias('orders', { orders: 'o', orderitems: 'oi' }) // 'o'
85
+ */
86
+ export function getTableAlias(tableName, aliasMap) {
87
+ if (aliasMap && aliasMap[tableName]) {
88
+ return aliasMap[tableName];
89
+ }
90
+ return tableName.charAt(0);
91
+ }
92
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/generators/rpc/utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * SQL Generator Validator
3
+ * Validates feature configs before generating SQL
4
+ */
5
+ import { FeatureConfig } from '../../shared/types/feature-config.js';
6
+ export interface ValidationError {
7
+ type: 'error' | 'warning';
8
+ field: string;
9
+ message: string;
10
+ suggestion?: string;
11
+ }
12
+ export interface ValidationResult {
13
+ valid: boolean;
14
+ errors: ValidationError[];
15
+ warnings: ValidationError[];
16
+ }
17
+ /**
18
+ * Validate feature config for SQL generation
19
+ */
20
+ export declare function validateConfig(config: FeatureConfig): ValidationResult;
21
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../../src/generators/rpc/validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,aAAa,EAAgB,MAAM,sCAAsC,CAAC;AAEnF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,GAAG,SAAS,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,CAiJtE"}