@carbonorm/carbonnode 6.0.19 → 6.1.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 (89) hide show
  1. package/README.md +46 -1
  2. package/dist/constants/C6Constants.d.ts +342 -338
  3. package/dist/executors/SqlExecutor.d.ts +8 -0
  4. package/dist/index.cjs.js +751 -272
  5. package/dist/index.cjs.js.map +1 -1
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.esm.js +744 -273
  8. package/dist/index.esm.js.map +1 -1
  9. package/dist/orm/builders/AggregateBuilder.d.ts +5 -1
  10. package/dist/orm/builders/ConditionBuilder.d.ts +2 -3
  11. package/dist/orm/builders/ExpressionSerializer.d.ts +22 -0
  12. package/dist/orm/builders/PaginationBuilder.d.ts +4 -6
  13. package/dist/orm/queryHelpers.d.ts +12 -1
  14. package/dist/types/mysqlTypes.d.ts +6 -1
  15. package/dist/types/ormInterfaces.d.ts +7 -5
  16. package/dist/utils/cacheManager.d.ts +3 -2
  17. package/package.json +2 -2
  18. package/scripts/assets/handlebars/C6.test.ts.handlebars +4 -4
  19. package/src/__tests__/cacheManager.test.ts +28 -0
  20. package/src/__tests__/expressServer.e2e.test.ts +26 -17
  21. package/src/__tests__/httpExecutorSingular.e2e.test.ts +53 -14
  22. package/src/__tests__/normalizeSingularRequest.test.ts +26 -8
  23. package/src/__tests__/sakila-db/C6.js +1 -1
  24. package/src/__tests__/sakila-db/C6.mysqldump.json +1 -1
  25. package/src/__tests__/sakila-db/C6.mysqldump.sql +1 -1
  26. package/src/__tests__/sakila-db/C6.sqlAllowList.json +1 -1
  27. package/src/__tests__/sakila-db/C6.test.ts +4 -4
  28. package/src/__tests__/sakila-db/C6.ts +1 -1
  29. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.json +11 -4
  30. package/src/__tests__/sakila-db/sqlResponses/C6.actor.post.latest.json +3 -3
  31. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.json +1 -1
  32. package/src/__tests__/sakila-db/sqlResponses/C6.actor.put.lookup.json +3 -3
  33. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.json +26 -7
  34. package/src/__tests__/sakila-db/sqlResponses/C6.address.post.latest.json +5 -5
  35. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.json +1 -1
  36. package/src/__tests__/sakila-db/sqlResponses/C6.address.put.lookup.json +5 -5
  37. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.json +9 -3
  38. package/src/__tests__/sakila-db/sqlResponses/C6.category.post.latest.json +2 -2
  39. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.json +1 -1
  40. package/src/__tests__/sakila-db/sqlResponses/C6.category.put.lookup.json +2 -2
  41. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.json +10 -3
  42. package/src/__tests__/sakila-db/sqlResponses/C6.city.post.latest.json +2 -2
  43. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.json +1 -1
  44. package/src/__tests__/sakila-db/sqlResponses/C6.city.put.lookup.json +2 -2
  45. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.json +9 -3
  46. package/src/__tests__/sakila-db/sqlResponses/C6.country.post.latest.json +2 -2
  47. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.json +1 -1
  48. package/src/__tests__/sakila-db/sqlResponses/C6.country.put.lookup.json +2 -2
  49. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.json +18 -6
  50. package/src/__tests__/sakila-db/sqlResponses/C6.customer.post.latest.json +5 -5
  51. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.json +1 -1
  52. package/src/__tests__/sakila-db/sqlResponses/C6.customer.put.lookup.json +5 -5
  53. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.json +18 -3
  54. package/src/__tests__/sakila-db/sqlResponses/C6.film.post.latest.json +2 -2
  55. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.json +1 -1
  56. package/src/__tests__/sakila-db/sqlResponses/C6.film.put.lookup.json +2 -2
  57. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.json +9 -2
  58. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.post.latest.json +1 -1
  59. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.json +1 -1
  60. package/src/__tests__/sakila-db/sqlResponses/C6.inventory.put.lookup.json +1 -1
  61. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.json +9 -3
  62. package/src/__tests__/sakila-db/sqlResponses/C6.language.post.latest.json +2 -2
  63. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.json +1 -1
  64. package/src/__tests__/sakila-db/sqlResponses/C6.language.put.lookup.json +2 -2
  65. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.json +13 -3
  66. package/src/__tests__/sakila-db/sqlResponses/C6.payment.post.latest.json +2 -2
  67. package/src/__tests__/sakila-db/sqlResponses/C6.payment.put.lookup.json +2 -2
  68. package/src/__tests__/sakila-db/sqlResponses/C6.rental.join.json +10 -10
  69. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.json +14 -4
  70. package/src/__tests__/sakila-db/sqlResponses/C6.rental.post.latest.json +3 -3
  71. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.json +1 -1
  72. package/src/__tests__/sakila-db/sqlResponses/C6.rental.put.lookup.json +3 -3
  73. package/src/__tests__/sqlBuilders.complex.test.ts +62 -74
  74. package/src/__tests__/sqlBuilders.expressions.test.ts +58 -30
  75. package/src/__tests__/sqlBuilders.test.ts +68 -4
  76. package/src/__tests__/sqlExecutorPostUuid.test.ts +185 -0
  77. package/src/constants/C6Constants.ts +3 -1
  78. package/src/executors/HttpExecutor.ts +35 -6
  79. package/src/executors/SqlExecutor.ts +232 -4
  80. package/src/index.ts +1 -0
  81. package/src/orm/builders/AggregateBuilder.ts +67 -106
  82. package/src/orm/builders/ConditionBuilder.ts +69 -93
  83. package/src/orm/builders/ExpressionSerializer.ts +275 -0
  84. package/src/orm/builders/PaginationBuilder.ts +24 -34
  85. package/src/orm/queryHelpers.ts +29 -0
  86. package/src/types/mysqlTypes.ts +130 -9
  87. package/src/types/ormInterfaces.ts +7 -7
  88. package/src/utils/cacheManager.ts +6 -4
  89. package/src/utils/normalizeSingularRequest.ts +11 -4
@@ -1,15 +1,119 @@
1
-
2
1
  // ========================
3
- // 🔧 SQL Operator & Helpers
2
+ // SQL Operators & Expressions
4
3
  // ========================
5
4
 
6
- export type SQLFunction =
7
- | 'COUNT'
8
- | 'GROUP_CONCAT'
9
- | 'MAX'
10
- | 'MIN'
11
- | 'SUM'
12
- | 'DISTINCT';
5
+ export const SQL_KNOWN_FUNCTIONS = [
6
+ 'ADDDATE',
7
+ 'ADDTIME',
8
+ 'CONCAT',
9
+ 'CONVERT_TZ',
10
+ 'COUNT',
11
+ 'COUNT_ALL',
12
+ 'CURRENT_DATE',
13
+ 'CURRENT_TIMESTAMP',
14
+ 'DAY',
15
+ 'DAY_HOUR',
16
+ 'DAY_MICROSECOND',
17
+ 'DAY_MINUTE',
18
+ 'DAY_SECOND',
19
+ 'DAYNAME',
20
+ 'DAYOFMONTH',
21
+ 'DAYOFWEEK',
22
+ 'DAYOFYEAR',
23
+ 'DATE',
24
+ 'DATE_ADD',
25
+ 'DATEDIFF',
26
+ 'DATE_SUB',
27
+ 'DATE_FORMAT',
28
+ 'EXTRACT',
29
+ 'FROM_DAYS',
30
+ 'FROM_UNIXTIME',
31
+ 'GET_FORMAT',
32
+ 'GROUP_CONCAT',
33
+ 'HEX',
34
+ 'HOUR',
35
+ 'HOUR_MICROSECOND',
36
+ 'HOUR_MINUTE',
37
+ 'HOUR_SECOND',
38
+ 'INTERVAL',
39
+ 'LOCALTIME',
40
+ 'LOCALTIMESTAMP',
41
+ 'MAKEDATE',
42
+ 'MAKETIME',
43
+ 'MAX',
44
+ 'MBRContains',
45
+ 'MICROSECOND',
46
+ 'MIN',
47
+ 'MINUTE',
48
+ 'MINUTE_MICROSECOND',
49
+ 'MINUTE_SECOND',
50
+ 'MONTH',
51
+ 'MONTHNAME',
52
+ 'NOW',
53
+ 'POINT',
54
+ 'POLYGON',
55
+ 'SECOND',
56
+ 'SECOND_MICROSECOND',
57
+ 'ST_Area',
58
+ 'ST_AsBinary',
59
+ 'ST_AsText',
60
+ 'ST_Buffer',
61
+ 'ST_Contains',
62
+ 'ST_Crosses',
63
+ 'ST_Difference',
64
+ 'ST_Dimension',
65
+ 'ST_Disjoint',
66
+ 'ST_Distance',
67
+ 'ST_Distance_Sphere',
68
+ 'ST_EndPoint',
69
+ 'ST_Envelope',
70
+ 'ST_Equals',
71
+ 'ST_GeomFromGeoJSON',
72
+ 'ST_GeomFromText',
73
+ 'ST_GeomFromWKB',
74
+ 'ST_Intersects',
75
+ 'ST_Length',
76
+ 'ST_MakeEnvelope',
77
+ 'ST_Overlaps',
78
+ 'ST_Point',
79
+ 'ST_SetSRID',
80
+ 'ST_SRID',
81
+ 'ST_StartPoint',
82
+ 'ST_SymDifference',
83
+ 'ST_Touches',
84
+ 'ST_Union',
85
+ 'ST_Within',
86
+ 'ST_X',
87
+ 'ST_Y',
88
+ 'STR_TO_DATE',
89
+ 'SUBDATE',
90
+ 'SUBTIME',
91
+ 'SUM',
92
+ 'SYSDATE',
93
+ 'TIME',
94
+ 'TIME_FORMAT',
95
+ 'TIME_TO_SEC',
96
+ 'TIMEDIFF',
97
+ 'TIMESTAMP',
98
+ 'TIMESTAMPADD',
99
+ 'TIMESTAMPDIFF',
100
+ 'TO_DAYS',
101
+ 'TO_SECONDS',
102
+ 'TRANSACTION_TIMESTAMP',
103
+ 'UNHEX',
104
+ 'UNIX_TIMESTAMP',
105
+ 'UTC_DATE',
106
+ 'UTC_TIME',
107
+ 'UTC_TIMESTAMP',
108
+ 'WEEKDAY',
109
+ 'WEEKOFYEAR',
110
+ 'YEARWEEK',
111
+ ] as const;
112
+
113
+ export type SQLKnownFunction = typeof SQL_KNOWN_FUNCTIONS[number];
114
+
115
+ // Backwards alias for existing public import name.
116
+ export type SQLFunction = SQLKnownFunction;
13
117
 
14
118
  export type SQLComparisonOperator =
15
119
  | '='
@@ -31,3 +135,20 @@ export type JoinType = 'INNER' | 'LEFT_OUTER' | 'RIGHT_OUTER';
31
135
 
32
136
  export type OrderDirection = 'ASC' | 'DESC';
33
137
 
138
+ export type SQLExpression =
139
+ | string
140
+ | number
141
+ | boolean
142
+ | null
143
+ | SQLExpressionTuple;
144
+
145
+ export type SQLExpressionTuple =
146
+ | ['AS', SQLExpression, string]
147
+ | ['DISTINCT', SQLExpression]
148
+ | ['CALL', string, ...SQLExpression[]]
149
+ | ['LIT', any]
150
+ | ['PARAM', any]
151
+ | ['SUBSELECT', Record<string, any>]
152
+ | [SQLKnownFunction, ...SQLExpression[]];
153
+
154
+ export type OrderTerm = [SQLExpression, OrderDirection?];
@@ -2,7 +2,7 @@ import type {AxiosInstance, AxiosResponse} from "axios";
2
2
  import type {Pool} from "mysql2/promise";
3
3
  import {eFetchDependencies} from "./dynamicFetching";
4
4
  import {Modify} from "./modifyTypes";
5
- import {JoinType, OrderDirection, SQLComparisonOperator, SQLFunction} from "./mysqlTypes";
5
+ import {JoinType, OrderTerm, SQLComparisonOperator, SQLExpression} from "./mysqlTypes";
6
6
  import type {CarbonReact, iStateAdapter} from "@carbonorm/carbonreact";
7
7
  import type {OrmGenerics} from "./ormGenerics";
8
8
  import {restOrm} from "../api/restOrm";
@@ -49,9 +49,7 @@ export type SubSelect<T extends { [key: string]: any } = any> = {
49
49
 
50
50
  export type SelectField<T extends { [key: string]: any } = any> =
51
51
  | keyof T
52
- | [keyof T, 'AS', string]
53
- | [SQLFunction, keyof T]
54
- | [SQLFunction, keyof T, string]
52
+ | SQLExpression
55
53
  | SubSelect<T>;
56
54
 
57
55
  export type WhereClause<T = any> = Partial<T> | LogicalGroup<T> | ComparisonClause<T>;
@@ -62,10 +60,10 @@ export type JoinTableCondition<T = any> = Partial<T> | WhereClause<T>[] | Compar
62
60
  export type JoinClause<T = any> = { [table: string]: JoinTableCondition<T>; };
63
61
  export type Join<T = any> = { [K in JoinType]?: JoinClause<T>; };
64
62
 
65
- export type Pagination<T = any> = {
63
+ export type Pagination = {
66
64
  PAGE?: number;
67
65
  LIMIT?: number | null;
68
- ORDER?: Partial<Record<keyof T, OrderDirection>>;
66
+ ORDER?: OrderTerm[];
69
67
  };
70
68
 
71
69
  export type RequestGetPutDeleteBody<T extends { [key: string]: any } = any> = T | {
@@ -74,7 +72,7 @@ export type RequestGetPutDeleteBody<T extends { [key: string]: any } = any> = T
74
72
  DELETE?: boolean;
75
73
  WHERE?: WhereClause<T>;
76
74
  JOIN?: Join<T>;
77
- PAGINATION?: Pagination<T>;
75
+ PAGINATION?: Pagination;
78
76
  };
79
77
 
80
78
  export type RequestPostBody<T extends { [key: string]: any } = any> = T | {
@@ -85,6 +83,7 @@ export type RequestPostBody<T extends { [key: string]: any } = any> = T | {
85
83
  export type iAPI<T extends { [key: string]: any }> = T & {
86
84
  dataInsertMultipleRows?: T[];
87
85
  cacheResults?: boolean;
86
+ skipReactBootstrap?: boolean;
88
87
  fetchDependencies?: number | eFetchDependencies | Awaited<iGetC6RestResponse<any>>[];
89
88
  debug?: boolean;
90
89
  success?: string | ((r: AxiosResponse) => string | void);
@@ -116,6 +115,7 @@ export interface iCacheResponse<ResponseDataType = any> {
116
115
  export interface iCacheAPI<ResponseDataType = any> {
117
116
  requestArgumentsSerialized: string;
118
117
  request: Promise<iCacheResponse<ResponseDataType>>;
118
+ allowListStatus?: "allowed" | "denied" | "not verified";
119
119
  response?: iCacheResponse<ResponseDataType> & {
120
120
  __carbonTiming?: {
121
121
  start: number;
@@ -1,6 +1,6 @@
1
1
  import type {iCacheAPI, iCacheResponse} from "../types/ormInterfaces";
2
2
  import {LogContext, LogLevel, logWithLevel, shouldLog} from "./logLevel";
3
- import logSql from "./logSql";
3
+ import logSql, { SqlAllowListStatus } from "./logSql";
4
4
 
5
5
  // -----------------------------------------------------------------------------
6
6
  // Cache Storage
@@ -61,7 +61,8 @@ export function checkCache<ResponseDataType = any>(
61
61
  method: string,
62
62
  tableName: string | string[],
63
63
  requestData: any,
64
- logContext: LogContext,
64
+ logContext?: LogContext,
65
+ allowListStatus?: SqlAllowListStatus,
65
66
  ): Promise<iCacheResponse<ResponseDataType>> | false {
66
67
  const key = makeCacheKey(method, tableName, requestData);
67
68
  const cached = apiRequestCache.get(key);
@@ -74,7 +75,7 @@ export function checkCache<ResponseDataType = any>(
74
75
  const sql = cached.response?.data?.sql?.sql ?? "";
75
76
  const sqlMethod = sql.trim().split(/\s+/, 1)[0]?.toUpperCase() || method;
76
77
  logSql({
77
- allowListStatus: "not verified",
78
+ allowListStatus: cached.allowListStatus ?? allowListStatus ?? "not verified",
78
79
  cacheStatus: "hit",
79
80
  context: logContext,
80
81
  method: sqlMethod,
@@ -103,6 +104,7 @@ export function evictCacheEntry(
103
104
  tableName: string | string[],
104
105
  requestData: any,
105
106
  logContext?: LogContext,
107
+ allowListStatus?: SqlAllowListStatus,
106
108
  ): boolean {
107
109
  const key = makeCacheKey(method, tableName, requestData);
108
110
  const cached = apiRequestCache.get(key);
@@ -112,7 +114,7 @@ export function evictCacheEntry(
112
114
  const sql = cached?.response?.data?.sql?.sql ?? "";
113
115
  const sqlMethod = sql.trim().split(/\s+/, 1)[0]?.toUpperCase() || method;
114
116
  logSql({
115
- allowListStatus: "not verified",
117
+ allowListStatus: cached?.allowListStatus ?? allowListStatus ?? "not verified",
116
118
  cacheStatus: "evicted",
117
119
  context: logContext,
118
120
  method: sqlMethod,
@@ -19,7 +19,7 @@ export function normalizeSingularRequest<
19
19
  ): RequestQueryBody<Method, T, Custom, Overrides> {
20
20
  if (request == null || typeof request !== 'object') return request;
21
21
 
22
- const specialKeys = new Set([
22
+ const specialKeys: Set<string> = new Set([
23
23
  C6C.SELECT,
24
24
  C6C.UPDATE,
25
25
  C6C.DELETE,
@@ -88,6 +88,7 @@ export function normalizeSingularRequest<
88
88
  const {
89
89
  dataInsertMultipleRows,
90
90
  cacheResults,
91
+ skipReactBootstrap,
91
92
  fetchDependencies,
92
93
  debug,
93
94
  success,
@@ -103,10 +104,13 @@ export function normalizeSingularRequest<
103
104
  const pkFullValues = Object.fromEntries(
104
105
  Object.entries(pkValues).map(([k, v]) => [shortToFull[k] ?? k, v])
105
106
  );
107
+ const pkWhereExpressions = Object.fromEntries(
108
+ Object.entries(pkFullValues).map(([column, value]) => [column, [C6C.EQUAL, [C6C.LIT, value]]]),
109
+ );
106
110
 
107
111
  if (requestMethod === C6C.GET) {
108
112
  const normalized: any = {
109
- WHERE: { ...pkFullValues },
113
+ WHERE: { ...pkWhereExpressions },
110
114
  };
111
115
  // Preserve pagination if any was added previously
112
116
  if ((request as any)[C6C.PAGINATION]) {
@@ -116,6 +120,7 @@ export function normalizeSingularRequest<
116
120
  ...normalized,
117
121
  dataInsertMultipleRows,
118
122
  cacheResults,
123
+ skipReactBootstrap,
119
124
  fetchDependencies,
120
125
  debug,
121
126
  success,
@@ -126,12 +131,13 @@ export function normalizeSingularRequest<
126
131
  if (requestMethod === C6C.DELETE) {
127
132
  const normalized: any = {
128
133
  [C6C.DELETE]: true,
129
- WHERE: { ...pkFullValues },
134
+ WHERE: { ...pkWhereExpressions },
130
135
  };
131
136
  return {
132
137
  ...normalized,
133
138
  dataInsertMultipleRows,
134
139
  cacheResults,
140
+ skipReactBootstrap,
135
141
  fetchDependencies,
136
142
  debug,
137
143
  success,
@@ -154,13 +160,14 @@ export function normalizeSingularRequest<
154
160
 
155
161
  const normalized: any = {
156
162
  [C6C.UPDATE]: updateBody,
157
- WHERE: { ...pkFullValues },
163
+ WHERE: { ...pkWhereExpressions },
158
164
  };
159
165
 
160
166
  return {
161
167
  ...normalized,
162
168
  dataInsertMultipleRows,
163
169
  cacheResults,
170
+ skipReactBootstrap,
164
171
  fetchDependencies,
165
172
  debug,
166
173
  success,