@carbonorm/carbonnode 3.0.1 → 3.0.2

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.
@@ -14,18 +14,20 @@ import {Executor} from "./Executor";
14
14
  import {toastOptions, toastOptionsDevs } from "variables/toastOptions";
15
15
 
16
16
  export class HttpExecutor<
17
- CustomAndRequiredFields extends { [key: string]: any }, // CustomAndRequiredFields
18
- RestTableInterfaces extends { [key: string]: any }, // RestTableInterfaces
19
- RequestTableOverrides = { [key in keyof RestTableInterfaces]: any }, // RequestTableOverrides
20
- ResponseDataType = any, // ResponseDataType
21
- RestShortTableNames extends string = "" // RestShortTableNames
17
+ RestShortTableName extends string = any,
18
+ RestTableInterface extends { [key: string]: any } = any,
19
+ PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>,
20
+ CustomAndRequiredFields extends { [key: string]: any } = any,
21
+ RequestTableOverrides extends { [key: string]: any; } = { [key in keyof RestTableInterface]: any },
22
+ ResponseDataType = any
22
23
  >
23
24
  extends Executor<
25
+ RestShortTableName,
26
+ RestTableInterface,
27
+ PrimaryKey,
24
28
  CustomAndRequiredFields,
25
- RestTableInterfaces,
26
29
  RequestTableOverrides,
27
- ResponseDataType,
28
- RestShortTableNames
30
+ ResponseDataType
29
31
  > {
30
32
 
31
33
  public async execute() : Promise<apiReturn<ResponseDataType>> {
@@ -35,7 +37,7 @@ export class HttpExecutor<
35
37
  axios,
36
38
  restURL,
37
39
  withCredentials,
38
- tableName,
40
+ restModel,
39
41
  requestMethod,
40
42
  queryCallback,
41
43
  responseCallback,
@@ -43,6 +45,8 @@ export class HttpExecutor<
43
45
  clearCache,
44
46
  } = this.config
45
47
 
48
+ const tableName = restModel.TABLE_NAME;
49
+
46
50
  const fullTableList = Array.isArray(tableName) ? tableName : [tableName];
47
51
 
48
52
  const operatingTableFullName = fullTableList[0];
@@ -75,7 +79,7 @@ export class HttpExecutor<
75
79
 
76
80
  // an undefined query would indicate queryCallback returned undefined,
77
81
  // thus the request shouldn't fire as is in custom cache
78
- let query: RequestQueryBody<Modify<RestTableInterfaces, RequestTableOverrides>> | undefined | null;
82
+ let query: RequestQueryBody<Modify<RestTableInterface, RequestTableOverrides>> | undefined | null;
79
83
 
80
84
  if ('function' === typeof queryCallback) {
81
85
 
@@ -250,7 +254,7 @@ export class HttpExecutor<
250
254
 
251
255
  let addBackPK: (() => void) | undefined;
252
256
 
253
- let apiResponse: string | boolean | number | undefined;
257
+ let apiResponse: RestTableInterface[PrimaryKey] | string | boolean | number | undefined;
254
258
 
255
259
  let returnGetNextPageFunction = false;
256
260
 
@@ -381,7 +385,7 @@ export class HttpExecutor<
381
385
  }
382
386
 
383
387
  return [
384
- convertForRequestBody<RestTableInterfaces>(query as RestTableInterfaces, fullTableList, C6, (message) => toast.error(message, toastOptions)),
388
+ convertForRequestBody<RestTableInterface>(query as RestTableInterface, fullTableList, C6, (message) => toast.error(message, toastOptions)),
385
389
  {
386
390
  withCredentials: withCredentials,
387
391
  }
@@ -390,7 +394,7 @@ export class HttpExecutor<
390
394
  } else if (requestMethod === PUT) {
391
395
 
392
396
  return [
393
- convertForRequestBody<RestTableInterfaces>(query as RestTableInterfaces, fullTableList, C6, (message) => toast.error(message, toastOptions)),
397
+ convertForRequestBody<RestTableInterface>(query as RestTableInterface, fullTableList, C6, (message) => toast.error(message, toastOptions)),
394
398
  {
395
399
  withCredentials: withCredentials,
396
400
  }
@@ -399,7 +403,7 @@ export class HttpExecutor<
399
403
 
400
404
  return [{
401
405
  withCredentials: withCredentials,
402
- data: convertForRequestBody<RestTableInterfaces>(query as RestTableInterfaces, fullTableList, C6, (message) => toast.error(message, toastOptions))
406
+ data: convertForRequestBody<RestTableInterface>(query as RestTableInterface, fullTableList, C6, (message) => toast.error(message, toastOptions))
403
407
  }]
404
408
 
405
409
  } else {
@@ -4,23 +4,37 @@ import {buildSelectQuery} from "../builders/sqlBuilder";
4
4
  import {Executor} from "./Executor";
5
5
 
6
6
 
7
- export class SqlExecutor<CustomAndRequiredFields extends object, RestTableInterfaces extends object, RequestTableOverrides extends object, ResponseDataType, RestShortTableNames extends string>
8
- extends Executor<CustomAndRequiredFields, RestTableInterfaces, RequestTableOverrides, ResponseDataType, RestShortTableNames> {
7
+ export class SqlExecutor<
8
+ RestShortTableName extends string = any,
9
+ RestTableInterface extends { [key: string]: any } = any,
10
+ PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>,
11
+ CustomAndRequiredFields extends { [key: string]: any } = any,
12
+ RequestTableOverrides extends { [key: string]: any; } = { [key in keyof RestTableInterface]: any },
13
+ ResponseDataType = any
14
+ >
15
+ extends Executor<
16
+ RestShortTableName,
17
+ RestTableInterface,
18
+ PrimaryKey,
19
+ CustomAndRequiredFields,
20
+ RequestTableOverrides,
21
+ ResponseDataType
22
+ > {
9
23
 
10
24
  public execute(): Promise<apiReturn<ResponseDataType>> {
11
25
  switch (this.config.requestMethod) {
12
26
  case 'GET':
13
27
  return (this.select(
14
- this.config.tableName as RestShortTableNames,
28
+ this.config.restModel.TABLE_NAME,
15
29
  undefined,
16
30
  this.request
17
31
  ) as Promise<any>).then(rows => ({rest: rows})) as any;
18
32
  case 'POST':
19
- return this.insert(this.config.tableName as RestShortTableNames, this.request) as any;
33
+ return this.insert(this.config.restModel.TABLE_NAME, this.request) as any;
20
34
  case 'PUT':
21
- return this.update(this.config.tableName as RestShortTableNames, undefined, this.request) as any;
35
+ return this.update(this.config.restModel.TABLE_NAME, undefined, this.request) as any;
22
36
  case 'DELETE':
23
- return this.delete(this.config.tableName as RestShortTableNames, undefined, this.request) as any;
37
+ return this.delete(this.config.restModel.TABLE_NAME, undefined, this.request) as any;
24
38
  }
25
39
  }
26
40
 
@@ -6,34 +6,50 @@ import {apiReturn, iAPI, iRest} from "./types/ormInterfaces";
6
6
  * Facade: routes API calls to SQL or HTTP executors based on runtime context.
7
7
  */
8
8
  export default function restRequest<
9
- CustomAndRequiredFields extends {
10
- [key: string]: any;
11
- } = any,
12
- RestTableInterfaces extends {
13
- [key: string]: any
14
- } = any,
15
- RequestTableOverrides extends {
16
- [key: string]: any;
17
- } = any,
18
- ResponseDataType = any,
19
- RestShortTableNames extends string = any
9
+ RestShortTableName extends string = any,
10
+ RestTableInterface extends { [key: string]: any } = any,
11
+ PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>,
12
+ CustomAndRequiredFields extends { [key: string]: any } = any,
13
+ RequestTableOverrides extends { [key: string]: any } = { [key in keyof RestTableInterface]: any },
14
+ ResponseDataType = any
20
15
  >(
21
- config: iRest<CustomAndRequiredFields, RestTableInterfaces, RequestTableOverrides, ResponseDataType, RestShortTableNames>
16
+ config: iRest<
17
+ RestShortTableName,
18
+ RestTableInterface,
19
+ PrimaryKey,
20
+ CustomAndRequiredFields,
21
+ RequestTableOverrides,
22
+ ResponseDataType
23
+ >
22
24
  ) {
23
25
  return async (
24
- request: iAPI<Modify<RestTableInterfaces, RequestTableOverrides>> & CustomAndRequiredFields = {} as iAPI<Modify<RestTableInterfaces, RequestTableOverrides>> & CustomAndRequiredFields
26
+ request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields = {} as iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields
25
27
  ): Promise<apiReturn<ResponseDataType>> => {
26
28
 
27
29
  // SQL path if on Node with a provided pool
28
30
  if (isNode && config.mysqlPool) {
29
31
  const {SqlExecutor} = await import('./executors/SqlExecutor');
30
- const executor = new SqlExecutor<CustomAndRequiredFields, RestTableInterfaces, RequestTableOverrides, ResponseDataType, RestShortTableNames>(config, request);
32
+ const executor = new SqlExecutor<
33
+ RestShortTableName,
34
+ RestTableInterface,
35
+ PrimaryKey,
36
+ CustomAndRequiredFields,
37
+ RequestTableOverrides,
38
+ ResponseDataType
39
+ >(config, request);
31
40
  return executor.execute();
32
41
  }
33
42
 
34
43
  // HTTP path fallback
35
44
  const {HttpExecutor} = await import('./executors/HttpExecutor');
36
- const http = new HttpExecutor<CustomAndRequiredFields, RestTableInterfaces, RequestTableOverrides, ResponseDataType, RestShortTableNames>(config, request);
45
+ const http = new HttpExecutor<
46
+ RestShortTableName,
47
+ RestTableInterface,
48
+ PrimaryKey,
49
+ CustomAndRequiredFields,
50
+ RequestTableOverrides,
51
+ ResponseDataType
52
+ >(config, request);
37
53
  return http.execute();
38
54
  };
39
55
  }
@@ -1,4 +1,3 @@
1
- import restRequest from "api/restRequest";
2
1
  import {AxiosInstance, AxiosPromise, AxiosResponse} from "axios";
3
2
  import {Pool} from "mysql2/promise";
4
3
  import {eFetchDependencies} from "./dynamicFetching";
@@ -41,16 +40,33 @@ export interface iConstraint {
41
40
  CONSTRAINT: string
42
41
  }
43
42
 
44
- export interface iC6RestfulModel<RestShortTableNames extends string = string> {
45
- TABLE_NAME: RestShortTableNames,
46
- PRIMARY: string[],
47
- PRIMARY_SHORT: string[],
48
- COLUMNS: stringMap,
49
- LIFECYCLE_HOOKS: iRestReactiveLifecycle<RequestGetPutDeleteBody>[],
50
- REGEX_VALIDATION: RegExpMap,
51
- TYPE_VALIDATION: { [key: string]: iTypeValidation },
52
- TABLE_REFERENCES: { [columnName: string]: iConstraint[] },
53
- TABLE_REFERENCED_BY: { [columnName: string]: iConstraint[] },
43
+ // This maps full column names to short column keys
44
+ export type tColumns<
45
+ TableName extends string,
46
+ T extends { [key: string]: any }
47
+ > = {
48
+ [K in keyof T & string as `${TableName}.${K}`]: K;
49
+ };
50
+
51
+ export type tPrimaryKeys<
52
+ TableName extends string,
53
+ PK extends string
54
+ > = `${TableName}.${PK}`;
55
+
56
+ export interface iC6RestfulModel<
57
+ RestShortTableNames extends string,
58
+ RestTableInterfaces extends { [key: string]: any },
59
+ PK extends keyof RestTableInterfaces & string,
60
+ > {
61
+ TABLE_NAME: RestShortTableNames;
62
+ PRIMARY: tPrimaryKeys<RestShortTableNames, PK>[];
63
+ PRIMARY_SHORT: PK[];
64
+ COLUMNS: tColumns<RestShortTableNames, RestTableInterfaces>;
65
+ TYPE_VALIDATION: { [key: string]: iTypeValidation };
66
+ REGEX_VALIDATION: RegExpMap;
67
+ LIFECYCLE_HOOKS: iRestReactiveLifecycle<RequestGetPutDeleteBody>[];
68
+ TABLE_REFERENCES: { [columnName: string]: iConstraint[] };
69
+ TABLE_REFERENCED_BY: { [columnName: string]: iConstraint[] };
54
70
  }
55
71
 
56
72
  export interface iRestApiFunctions<RestData = any> {
@@ -68,7 +84,13 @@ export interface iDynamicApiImport<RestData = any> {
68
84
  putState?: (response: AxiosResponse<iPutC6RestResponse<RestData>>, request: iAPI<any>) => void
69
85
  }
70
86
 
71
- export interface tC6Tables { [key: string]: (iC6RestfulModel & { [key: string]: any }) }
87
+ export interface tC6Tables<
88
+ RestShortTableName extends string = any,
89
+ RestTableInterface extends { [key: string]: any } = any,
90
+ PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>
91
+ > {
92
+ [key: string]: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey> & { [key: string]: any }
93
+ }
72
94
 
73
95
  export interface tC6RestApi {
74
96
  [key: string]: {
@@ -98,7 +120,6 @@ export interface iCacheAPI<ResponseDataType = any> {
98
120
  }
99
121
 
100
122
 
101
-
102
123
  /**
103
124
  * the first argument ....
104
125
  *
@@ -226,11 +247,17 @@ export interface iPutC6RestResponse<RestData = any, RequestData = any> extends i
226
247
  updated: boolean | number | string | RequestData,
227
248
  }
228
249
 
229
- export interface iC6Object {
250
+ export interface iC6Object<
251
+ RestShortTableName extends string = any,
252
+ RestTableInterface extends { [key: string]: any } = any,
253
+ PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>
254
+ > {
230
255
  C6VERSION: string,
231
256
  TABLES: {
232
- [key: string]: iC6RestfulModel &
233
- { [key: string]: string | number }
257
+ [key: string]: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey>
258
+ & {
259
+ [key: string]: string | number
260
+ }
234
261
  },
235
262
  PREFIX: string,
236
263
  IMPORT: (tableName: string) => Promise<iDynamicApiImport>,
@@ -252,36 +279,32 @@ export type apiReturn<Response> =
252
279
 
253
280
 
254
281
  export interface iRest<
255
- CustomAndRequiredFields extends { [key: string]: any },
256
- RestTableInterfaces extends { [key: string]: any },
257
- RequestTableOverrides = { [key in keyof RestTableInterfaces]: any },
258
- ResponseDataType = any,
259
- RestShortTableNames extends string = any
282
+ RestShortTableName extends string = any,
283
+ RestTableInterface extends { [key: string]: any } = any,
284
+ PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>,
285
+ CustomAndRequiredFields extends { [key: string]: any } = any,
286
+ RequestTableOverrides = { [key in keyof RestTableInterface]: any },
287
+ ResponseDataType = any
260
288
  > {
261
289
  C6: iC6Object,
262
290
  axios?: AxiosInstance,
263
291
  restURL?: string,
264
292
  mysqlPool?: Pool;
265
293
  withCredentials?: boolean,
266
- tableName: RestShortTableNames | RestShortTableNames[],
294
+ restModel: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey>,
267
295
  requestMethod: iRestMethods,
268
296
  clearCache?: () => void,
269
297
  skipPrimaryCheck?: boolean,
270
- queryCallback: RequestQueryBody<Modify<RestTableInterfaces, RequestTableOverrides>> | ((request: iAPI<Modify<RestTableInterfaces, RequestTableOverrides>> & CustomAndRequiredFields) => (null | undefined | RequestQueryBody<Modify<RestTableInterfaces, RequestTableOverrides>>)),
298
+ queryCallback: RequestQueryBody<Modify<RestTableInterface, RequestTableOverrides>> | ((request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields) => (null | undefined | RequestQueryBody<Modify<RestTableInterface, RequestTableOverrides>>)),
271
299
  responseCallback?: (response: AxiosResponse<ResponseDataType>,
272
- request: iAPI<Modify<RestTableInterfaces, RequestTableOverrides>> & CustomAndRequiredFields,
273
- success: (ResponseDataType extends iPutC6RestResponse | iDeleteC6RestResponse ? RequestQueryBody<Modify<RestTableInterfaces, RequestTableOverrides>> : string) | string | number | boolean) => any // keep this set to any, it allows easy arrow functions and the results unused here
300
+ request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields,
301
+ success: (ResponseDataType extends iPutC6RestResponse | iDeleteC6RestResponse
302
+ ? RequestQueryBody<Modify<RestTableInterface, RequestTableOverrides>>
303
+ : string)
304
+ | RestTableInterface[PrimaryKey] // Rest PK
305
+ | string | number | boolean // Toast and validations
306
+ ) => any // keep this set to any, it allows easy arrow functions and the results unused here
274
307
  }
275
308
 
276
- export function extendedTypeHints<RestTableInterfaces extends {
277
- [key: string]: any
278
- }, RestShortTableNames extends string>() {
279
- return <CustomAndRequiredFields extends {
280
- [key: string]: any
281
- } = any, RequestTableTypes extends RestTableInterfaces = any, RequestTableOverrides extends {
282
- [key: string]: any
283
- } = any, ResponseDataType extends {
284
- [key: string]: any
285
- } = any>(argv) => restRequest<CustomAndRequiredFields, RequestTableTypes, RequestTableOverrides, ResponseDataType, RestShortTableNames>(argv)
286
- }
309
+
287
310
 
@@ -36,7 +36,6 @@ export function TestRestfulResponse(response: AxiosResponse | any, success: ((r:
36
36
 
37
37
  return false;
38
38
 
39
-
40
39
  }
41
40
 
42
41
  export function removePrefixIfExists(tableName: string, prefix: string): string {
@@ -47,7 +46,7 @@ export function removePrefixIfExists(tableName: string, prefix: string): string
47
46
  }
48
47
 
49
48
  export function removeInvalidKeys<iRestObject>(request: any, c6Tables: {
50
- [key: string]: (iC6RestfulModel & { [key: string]: any })
49
+ [key: string]: (iC6RestfulModel<any,any,any> & { [key: string]: any })
51
50
  }): iRestObject {
52
51
 
53
52
  let intersection: iRestObject = {} as iRestObject
@@ -0,0 +1,46 @@
1
+ import {iC6RestfulModel} from "../types/ormInterfaces";
2
+
3
+ type JsPrimitive = 'string' | 'number' | 'boolean' | 'buffer' | 'object';
4
+
5
+ export function determineRuntimeJsType(mysqlType: string): JsPrimitive {
6
+ const base = mysqlType.toLowerCase().split('(')[0];
7
+
8
+ if ([
9
+ 'binary', 'varbinary', 'blob', 'tinyblob', 'mediumblob', 'longblob'
10
+ ].includes(base)) return 'buffer';
11
+
12
+ if ([
13
+ 'json', 'geometry', 'point', 'polygon', 'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection'
14
+ ].includes(base)) return 'object';
15
+
16
+ if ([
17
+ 'tinyint', 'smallint', 'mediumint', 'int', 'integer', 'bigint',
18
+ 'decimal', 'dec', 'numeric', 'float', 'double', 'real'
19
+ ].includes(base)) return 'number';
20
+
21
+ if ([
22
+ 'boolean', 'bool'
23
+ ].includes(base)) return 'boolean';
24
+
25
+ return 'string';
26
+ }
27
+
28
+ export function getPrimaryKeyTypes(
29
+ table: iC6RestfulModel<string, any, any>
30
+ ): Record<string, JsPrimitive> {
31
+ const result: Record<string, JsPrimitive> = {};
32
+
33
+ for (const key of table.PRIMARY_SHORT) {
34
+ const fullKey = Object.entries(table.COLUMNS).find(([_, short]) => short === key)?.[0];
35
+
36
+ if (typeof fullKey === 'string') {
37
+ const validation = table.TYPE_VALIDATION[fullKey];
38
+ if (!validation) continue;
39
+
40
+ result[key] = determineRuntimeJsType(validation.MYSQL_TYPE);
41
+ }
42
+ }
43
+
44
+ return result;
45
+ }
46
+
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ export * from "./api/types/mysqlTypes";
21
21
  export * from "./api/types/ormInterfaces";
22
22
  export * from "./api/utils/apiHelpers";
23
23
  export * from "./api/utils/cacheManager";
24
+ export * from "./api/utils/determineRuntimeJsType";
24
25
  export * from "./api/utils/logger";
25
26
  export * from "./api/utils/sortAndSerializeQueryObject";
26
27
  export * from "./api/utils/testHelpers";