@carbonorm/carbonnode 3.0.3 → 3.0.4
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/dist/api/convertForRequestBody.d.ts +7 -3
- package/dist/api/executors/Executor.d.ts +3 -4
- package/dist/api/executors/HttpExecutor.d.ts +4 -5
- package/dist/api/restOrm.d.ts +4 -32
- package/dist/api/restRequest.d.ts +2 -3
- package/dist/api/types/ormInterfaces.d.ts +161 -161
- package/dist/index.cjs.js +548 -97
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +550 -98
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
- package/scripts/assets/handlebars/C6.ts.handlebars +30 -23
- package/scripts/generateRestBindings.cjs +1 -0
- package/scripts/generateRestBindings.ts +1 -0
- package/src/api/convertForRequestBody.ts +62 -90
- package/src/api/executors/Executor.ts +8 -4
- package/src/api/executors/HttpExecutor.ts +80 -69
- package/src/api/restRequest.ts +7 -4
- package/src/api/types/ormInterfaces.ts +200 -321
- package/src/api/rest/C6.test.ts +0 -88
- package/src/api/rest/C6.ts +0 -5338
|
@@ -1,268 +1,51 @@
|
|
|
1
|
-
|
|
2
|
-
import {Pool} from "mysql2/promise";
|
|
3
|
-
import {eFetchDependencies} from "./dynamicFetching";
|
|
4
|
-
import {Modify} from "./modifyTypes";
|
|
5
|
-
import {JoinType, OrderDirection, SQLComparisonOperator, SQLFunction} from "./mysqlTypes";
|
|
6
|
-
import {CarbonReact} from "@carbonorm/carbonreact";
|
|
7
|
-
|
|
8
|
-
export interface stringMap {
|
|
9
|
-
[key: string]: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export interface stringNumberMap {
|
|
13
|
-
[key: string]: string | number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface RegExpMap {
|
|
17
|
-
[key: string]: RegExp | RegExpMap;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface complexMap {
|
|
21
|
-
[key: string]: stringMap | stringNumberMap | stringMap[] | RegExpMap;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export interface iTypeValidation {
|
|
25
|
-
MYSQL_TYPE: string,
|
|
26
|
-
MAX_LENGTH: string,
|
|
27
|
-
AUTO_INCREMENT: boolean,
|
|
28
|
-
SKIP_COLUMN_IN_POST: boolean
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// config, request, response
|
|
33
|
-
export type iRestReactiveLifecycle<
|
|
34
|
-
RequestMethod extends iRestMethods,
|
|
35
|
-
RestShortTableName extends string = any,
|
|
36
|
-
RestTableInterface extends { [key: string]: any } = any,
|
|
37
|
-
PrimaryKey extends keyof RestTableInterface & string = any,
|
|
38
|
-
// TODO - do we ever use these last two ever? should we make usage just any?
|
|
39
|
-
CustomAndRequiredFields extends { [key: string]: any } = any,
|
|
40
|
-
RequestTableOverrides extends { [key: string]: any } = { [key in keyof RestTableInterface]: any }
|
|
41
|
-
> = {
|
|
42
|
-
beforeProcessing?: {
|
|
43
|
-
[key: string]: (args: {
|
|
44
|
-
config: iRest<
|
|
45
|
-
RestShortTableName,
|
|
46
|
-
RestTableInterface,
|
|
47
|
-
PrimaryKey
|
|
48
|
-
>,
|
|
49
|
-
request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields;
|
|
50
|
-
}) => void | Promise<void>
|
|
51
|
-
},
|
|
52
|
-
beforeExecution?:
|
|
53
|
-
{
|
|
54
|
-
[key: string]: (args: {
|
|
55
|
-
config: iRest<
|
|
56
|
-
RestShortTableName,
|
|
57
|
-
RestTableInterface,
|
|
58
|
-
PrimaryKey
|
|
59
|
-
>,
|
|
60
|
-
request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields
|
|
61
|
-
}) => void | Promise<void>
|
|
62
|
-
};
|
|
63
|
-
afterExecution?:
|
|
64
|
-
{
|
|
65
|
-
[key: string]: (args: {
|
|
66
|
-
config: iRest<
|
|
67
|
-
RestShortTableName,
|
|
68
|
-
RestTableInterface,
|
|
69
|
-
PrimaryKey
|
|
70
|
-
>,
|
|
71
|
-
request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields;
|
|
72
|
-
response: AxiosResponse<DetermineResponseDataType<RequestMethod, RestTableInterface>>;
|
|
73
|
-
}) => void | Promise<void>
|
|
74
|
-
};
|
|
75
|
-
afterCommit?: {
|
|
76
|
-
[key: string]: (args: {
|
|
77
|
-
config: iRest<
|
|
78
|
-
RestShortTableName,
|
|
79
|
-
RestTableInterface,
|
|
80
|
-
PrimaryKey
|
|
81
|
-
>,
|
|
82
|
-
request: iAPI<Modify<RestTableInterface, RequestTableOverrides>> & CustomAndRequiredFields;
|
|
83
|
-
response: AxiosResponse<DetermineResponseDataType<RequestMethod, RestTableInterface>>;
|
|
84
|
-
}) => void | Promise<void>
|
|
85
|
-
};
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
export type iRestHooks<
|
|
89
|
-
RestShortTableName extends string = any,
|
|
90
|
-
RestTableInterface extends { [key: string]: any } = any,
|
|
91
|
-
PrimaryKey extends keyof RestTableInterface & string = any,
|
|
92
|
-
CustomAndRequiredFields extends { [key: string]: any } = any,
|
|
93
|
-
RequestTableOverrides extends { [key: string]: any } = { [key in keyof RestTableInterface]: any }
|
|
94
|
-
> = {
|
|
95
|
-
[Method in iRestMethods]: iRestReactiveLifecycle<
|
|
96
|
-
Method,
|
|
97
|
-
RestShortTableName,
|
|
98
|
-
RestTableInterface,
|
|
99
|
-
PrimaryKey,
|
|
100
|
-
CustomAndRequiredFields,
|
|
101
|
-
RequestTableOverrides
|
|
102
|
-
>
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export interface iConstraint {
|
|
106
|
-
TABLE: string,
|
|
107
|
-
COLUMN: string,
|
|
108
|
-
CONSTRAINT: string
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// This maps full column names to short column keys
|
|
112
|
-
export type tColumns<
|
|
113
|
-
TableName extends string,
|
|
114
|
-
T extends { [key: string]: any }
|
|
115
|
-
> = {
|
|
116
|
-
[K in keyof T & string as `${TableName}.${K}`]: K;
|
|
117
|
-
};
|
|
1
|
+
// Refined TypeScript types for CarbonORM
|
|
118
2
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
3
|
+
import { AxiosInstance, AxiosPromise, AxiosResponse } from "axios";
|
|
4
|
+
import { Pool } from "mysql2/promise";
|
|
5
|
+
import { eFetchDependencies } from "./dynamicFetching";
|
|
6
|
+
import { Modify } from "./modifyTypes";
|
|
7
|
+
import { JoinType, OrderDirection, SQLComparisonOperator, SQLFunction } from "./mysqlTypes";
|
|
8
|
+
import { CarbonReact } from "@carbonorm/carbonreact";
|
|
123
9
|
|
|
124
|
-
export
|
|
125
|
-
RestShortTableNames extends string,
|
|
126
|
-
RestTableInterfaces extends { [key: string]: any },
|
|
127
|
-
PK extends keyof RestTableInterfaces & string,
|
|
128
|
-
> {
|
|
129
|
-
TABLE_NAME: RestShortTableNames;
|
|
130
|
-
PRIMARY: tPrimaryKeys<RestShortTableNames, PK>[];
|
|
131
|
-
PRIMARY_SHORT: PK[];
|
|
132
|
-
COLUMNS: tColumns<RestShortTableNames, RestTableInterfaces>;
|
|
133
|
-
TYPE_VALIDATION: { [key: string]: iTypeValidation };
|
|
134
|
-
REGEX_VALIDATION: RegExpMap;
|
|
135
|
-
// TODO - I thon think theres a good way to infer the last two generics (overides)
|
|
136
|
-
LIFECYCLE_HOOKS: iRestHooks<RestShortTableNames, RestTableInterfaces, PK>;
|
|
137
|
-
TABLE_REFERENCES: { [columnName: string]: iConstraint[] };
|
|
138
|
-
TABLE_REFERENCED_BY: { [columnName: string]: iConstraint[] };
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface iRestApiFunctions<RestData = any> {
|
|
142
|
-
Delete: (request?: (iAPI<any> & any)) => apiReturn<iDeleteC6RestResponse<RestData>>;
|
|
143
|
-
Post: (request?: (iAPI<any> & any)) => apiReturn<iPostC6RestResponse<RestData>>;
|
|
144
|
-
Get: (request?: (iAPI<any> & any)) => apiReturn<iGetC6RestResponse<RestData>>;
|
|
145
|
-
Put: (request?: (iAPI<any> & any)) => apiReturn<iPutC6RestResponse<RestData>>,
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export interface iDynamicApiImport<RestData = any> {
|
|
149
|
-
default: iRestApiFunctions<RestData>
|
|
150
|
-
// the methods below are optional
|
|
151
|
-
postState?: (response: AxiosResponse<iPostC6RestResponse<RestData>>, request: iAPI<any>, id: string | number | boolean) => void,
|
|
152
|
-
deleteState?: (response: AxiosResponse<iDeleteC6RestResponse<RestData>>, request: iAPI<any>) => void,
|
|
153
|
-
putState?: (response: AxiosResponse<iPutC6RestResponse<RestData>>, request: iAPI<any>) => void
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export interface tC6Tables<
|
|
157
|
-
RestShortTableName extends string = any,
|
|
158
|
-
RestTableInterface extends { [key: string]: any } = any,
|
|
159
|
-
PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>
|
|
160
|
-
> {
|
|
161
|
-
[key: string]: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey> & { [key: string]: any }
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export interface tC6RestApi {
|
|
165
|
-
[key: string]: {
|
|
166
|
-
REST: iRestApiFunctions,
|
|
167
|
-
PUT: Function;
|
|
168
|
-
POST: Function;
|
|
169
|
-
DELETE: Function;
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// todo - I don't like that these essentially become reserved words.
|
|
174
|
-
export type iAPI<RestTableInterfaces extends { [key: string]: any }> = RestTableInterfaces & {
|
|
175
|
-
dataInsertMultipleRows?: RestTableInterfaces[],
|
|
176
|
-
cacheResults?: boolean, // aka ignoreCache
|
|
177
|
-
// todo - this should really only be used for get requests - add this to the Get interface or throw error (im actually inclined to ts ignore the function and add to iGetC6 atm; back later)
|
|
178
|
-
fetchDependencies?: number | eFetchDependencies | Awaited<apiReturn<iGetC6RestResponse<any>>>[],
|
|
179
|
-
debug?: boolean,
|
|
180
|
-
success?: string | ((r: AxiosResponse) => (string | void)),
|
|
181
|
-
error?: string | ((r: AxiosResponse) => (string | void)),
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
export interface iCacheAPI<ResponseDataType = any> {
|
|
185
|
-
requestArgumentsSerialized: string,
|
|
186
|
-
request: AxiosPromise<ResponseDataType>,
|
|
187
|
-
response?: AxiosResponse,
|
|
188
|
-
final?: boolean,
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* the first argument ....
|
|
194
|
-
*
|
|
195
|
-
* Our api returns a zero argument function iff the method is get and the previous request reached the predefined limit.
|
|
196
|
-
* This function can be aliased as GetNextPageOfResults(). If the end is reached undefined will be returned.
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
* For POST, PUT, and DELETE requests one can expect the primary key of the new or modified index, or a boolean success
|
|
200
|
-
* indication if no primary key exists.
|
|
201
|
-
**/
|
|
10
|
+
export type iRestMethods = 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
202
11
|
export const POST = 'POST';
|
|
203
12
|
export const PUT = 'PUT';
|
|
204
13
|
export const GET = 'GET';
|
|
205
14
|
export const DELETE = 'DELETE';
|
|
206
15
|
|
|
16
|
+
export interface stringMap { [key: string]: string; }
|
|
17
|
+
export interface stringNumberMap { [key: string]: string | number; }
|
|
18
|
+
export interface RegExpMap { [key: string]: RegExp | RegExpMap; }
|
|
19
|
+
export interface complexMap { [key: string]: stringMap | stringNumberMap | stringMap[] | RegExpMap; }
|
|
207
20
|
|
|
208
|
-
export
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
21
|
+
export interface iTypeValidation {
|
|
22
|
+
MYSQL_TYPE: string;
|
|
23
|
+
MAX_LENGTH: string;
|
|
24
|
+
AUTO_INCREMENT: boolean;
|
|
25
|
+
SKIP_COLUMN_IN_POST: boolean;
|
|
26
|
+
}
|
|
213
27
|
|
|
214
|
-
export type SubSelect<T = any> = {
|
|
28
|
+
export type SubSelect<T extends { [key: string]: any } = any> = {
|
|
215
29
|
subSelect: true;
|
|
216
|
-
table: string;
|
|
217
|
-
args:
|
|
30
|
+
table: string;
|
|
31
|
+
args: RequestQueryBody<'GET', T>;
|
|
218
32
|
alias: string;
|
|
219
33
|
};
|
|
220
34
|
|
|
221
|
-
export type SelectField<T = any> =
|
|
35
|
+
export type SelectField<T extends { [key: string]: any } = any> =
|
|
222
36
|
| keyof T
|
|
223
37
|
| [keyof T, 'AS', string]
|
|
224
38
|
| [SQLFunction, keyof T]
|
|
225
|
-
| [SQLFunction, keyof T, string]
|
|
226
|
-
| SubSelect<T>;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
// ========================
|
|
230
|
-
// 🧠 WHERE (Recursive)
|
|
231
|
-
// ========================
|
|
232
|
-
|
|
233
|
-
export type WhereClause<T = any> =
|
|
234
|
-
| Partial<T>
|
|
235
|
-
| LogicalGroup<T>
|
|
236
|
-
| ComparisonClause<T>;
|
|
237
|
-
|
|
238
|
-
export type LogicalGroup<T = any> = {
|
|
239
|
-
[logicalGroup: string]: Array<WhereClause<T>>;
|
|
240
|
-
};
|
|
39
|
+
| [SQLFunction, keyof T, string]
|
|
40
|
+
| SubSelect<T>;
|
|
241
41
|
|
|
42
|
+
export type WhereClause<T = any> = Partial<T> | LogicalGroup<T> | ComparisonClause<T>;
|
|
43
|
+
export type LogicalGroup<T = any> = { [logicalGroup: string]: Array<WhereClause<T>> };
|
|
242
44
|
export type ComparisonClause<T = any> = [keyof T, SQLComparisonOperator, any];
|
|
243
45
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
// ========================
|
|
248
|
-
|
|
249
|
-
export type JoinTableCondition<T = any> =
|
|
250
|
-
| Partial<T>
|
|
251
|
-
| WhereClause<T>[]
|
|
252
|
-
| ComparisonClause<T>[];
|
|
253
|
-
|
|
254
|
-
export type JoinClause<T = any> = {
|
|
255
|
-
[table: string]: JoinTableCondition<T>;
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
export type Join<T = any> = {
|
|
259
|
-
[K in JoinType]?: JoinClause<T>;
|
|
260
|
-
};
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
// ========================
|
|
264
|
-
// 📄 PAGINATION
|
|
265
|
-
// ========================
|
|
46
|
+
export type JoinTableCondition<T = any> = Partial<T> | WhereClause<T>[] | ComparisonClause<T>[];
|
|
47
|
+
export type JoinClause<T = any> = { [table: string]: JoinTableCondition<T>; };
|
|
48
|
+
export type Join<T = any> = { [K in JoinType]?: JoinClause<T>; };
|
|
266
49
|
|
|
267
50
|
export type Pagination<T = any> = {
|
|
268
51
|
PAGE?: number;
|
|
@@ -270,12 +53,7 @@ export type Pagination<T = any> = {
|
|
|
270
53
|
ORDER?: Partial<Record<keyof T, OrderDirection>>;
|
|
271
54
|
};
|
|
272
55
|
|
|
273
|
-
|
|
274
|
-
// ========================
|
|
275
|
-
// 🌐 MAIN API TYPE
|
|
276
|
-
// ========================
|
|
277
|
-
|
|
278
|
-
export type RequestGetPutDeleteBody<T = any> = {
|
|
56
|
+
export type RequestGetPutDeleteBody<T extends { [key: string]: any } = any> = {
|
|
279
57
|
SELECT?: SelectField<T>[];
|
|
280
58
|
UPDATE?: Partial<T>;
|
|
281
59
|
DELETE?: boolean;
|
|
@@ -284,110 +62,211 @@ export type RequestGetPutDeleteBody<T = any> = {
|
|
|
284
62
|
PAGINATION?: Pagination<T>;
|
|
285
63
|
};
|
|
286
64
|
|
|
65
|
+
export type iAPI<T extends { [key: string]: any }> = T & {
|
|
66
|
+
dataInsertMultipleRows?: T[];
|
|
67
|
+
cacheResults?: boolean;
|
|
68
|
+
fetchDependencies?: number | eFetchDependencies | Awaited<apiReturn<iGetC6RestResponse<any>>>[];
|
|
69
|
+
debug?: boolean;
|
|
70
|
+
success?: string | ((r: AxiosResponse) => string | void);
|
|
71
|
+
error?: string | ((r: AxiosResponse) => string | void);
|
|
72
|
+
};
|
|
287
73
|
|
|
288
|
-
export type RequestQueryBody<
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
74
|
+
export type RequestQueryBody<
|
|
75
|
+
Method extends iRestMethods,
|
|
76
|
+
T extends { [key: string]: any },
|
|
77
|
+
Custom extends { [key: string]: any } = {},
|
|
78
|
+
Overrides extends { [key: string]: any } = {}
|
|
79
|
+
> = Method extends 'GET' | 'PUT' | 'DELETE'
|
|
80
|
+
? iAPI<RequestGetPutDeleteBody<Modify<T, Overrides> & Custom>>
|
|
81
|
+
: iAPI<Modify<T, Overrides> & Custom>;
|
|
295
82
|
|
|
296
|
-
interface
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
83
|
+
export interface iCacheAPI<ResponseDataType = any> {
|
|
84
|
+
requestArgumentsSerialized: string;
|
|
85
|
+
request: AxiosPromise<ResponseDataType>;
|
|
86
|
+
response?: AxiosResponse;
|
|
87
|
+
final?: boolean;
|
|
300
88
|
}
|
|
301
89
|
|
|
302
|
-
|
|
303
|
-
interface iChangeC6Data {
|
|
304
|
-
rowCount: number,
|
|
305
|
-
}
|
|
90
|
+
export interface iChangeC6Data { rowCount: number; }
|
|
306
91
|
|
|
307
92
|
export interface iDeleteC6RestResponse<RestData = any, RequestData = any> extends iChangeC6Data, iC6RestResponse<RestData> {
|
|
308
|
-
deleted: boolean | number | string | RequestData
|
|
93
|
+
deleted: boolean | number | string | RequestData;
|
|
309
94
|
}
|
|
310
95
|
|
|
311
96
|
export interface iPostC6RestResponse<RestData = any> extends iC6RestResponse<RestData> {
|
|
312
|
-
created: boolean | number | string
|
|
97
|
+
created: boolean | number | string;
|
|
313
98
|
}
|
|
314
99
|
|
|
315
100
|
export interface iPutC6RestResponse<RestData = any, RequestData = any> extends iChangeC6Data, iC6RestResponse<RestData> {
|
|
316
|
-
updated: boolean | number | string | RequestData
|
|
101
|
+
updated: boolean | number | string | RequestData;
|
|
317
102
|
}
|
|
318
103
|
|
|
319
|
-
export interface
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
> {
|
|
324
|
-
C6VERSION: string,
|
|
325
|
-
TABLES: {
|
|
326
|
-
[key: string]: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey>
|
|
327
|
-
& {
|
|
328
|
-
[key: string]: string | number
|
|
329
|
-
}
|
|
330
|
-
},
|
|
331
|
-
PREFIX: string,
|
|
332
|
-
IMPORT: (tableName: string) => Promise<iDynamicApiImport>,
|
|
333
|
-
|
|
334
|
-
[key: string]: any
|
|
104
|
+
export interface iC6RestResponse<RestData> {
|
|
105
|
+
rest: RestData;
|
|
106
|
+
session?: any;
|
|
107
|
+
sql?: any;
|
|
335
108
|
}
|
|
336
109
|
|
|
337
|
-
|
|
338
|
-
|
|
110
|
+
export type iGetC6RestResponse<ResponseDataType, ResponseDataOverrides = {}> = iC6RestResponse<
|
|
111
|
+
Modify<ResponseDataType, ResponseDataOverrides> | Modify<ResponseDataType, ResponseDataOverrides>[]
|
|
112
|
+
>;
|
|
339
113
|
|
|
340
|
-
// returning undefined means no more results are available, thus we've queried everything possible
|
|
341
|
-
// null means the request is currently being executed
|
|
342
|
-
// https://www.typescriptlang.org/docs/handbook/2/conditional-types.html
|
|
343
114
|
export type apiReturn<Response> =
|
|
344
|
-
null
|
|
115
|
+
| null
|
|
345
116
|
| undefined
|
|
346
117
|
| AxiosPromise<Response>
|
|
347
|
-
| (Response extends iPutC6RestResponse | iDeleteC6RestResponse | iPostC6RestResponse ? null : (
|
|
348
|
-
|
|
118
|
+
| (Response extends iPutC6RestResponse | iDeleteC6RestResponse | iPostC6RestResponse ? null : () => apiReturn<Response>);
|
|
349
119
|
|
|
350
120
|
export type DetermineResponseDataType<
|
|
351
|
-
|
|
121
|
+
Method extends iRestMethods,
|
|
352
122
|
RestTableInterface extends { [key: string]: any }
|
|
353
|
-
> =
|
|
123
|
+
> = Method extends 'POST'
|
|
354
124
|
? iPostC6RestResponse<RestTableInterface>
|
|
355
|
-
:
|
|
125
|
+
: Method extends 'GET'
|
|
356
126
|
? iGetC6RestResponse<RestTableInterface>
|
|
357
|
-
:
|
|
127
|
+
: Method extends 'PUT'
|
|
358
128
|
? iPutC6RestResponse<RestTableInterface>
|
|
359
|
-
:
|
|
129
|
+
: Method extends 'DELETE'
|
|
360
130
|
? iDeleteC6RestResponse<RestTableInterface>
|
|
361
|
-
:
|
|
131
|
+
: never;
|
|
362
132
|
|
|
363
133
|
export interface iRest<
|
|
364
134
|
RestShortTableName extends string = any,
|
|
365
135
|
RestTableInterface extends { [key: string]: any } = any,
|
|
366
136
|
PrimaryKey extends keyof RestTableInterface & string = any
|
|
367
137
|
> {
|
|
368
|
-
C6: iC6Object
|
|
369
|
-
axios?: AxiosInstance
|
|
370
|
-
restURL?: string
|
|
138
|
+
C6: iC6Object;
|
|
139
|
+
axios?: AxiosInstance;
|
|
140
|
+
restURL?: string;
|
|
371
141
|
mysqlPool?: Pool;
|
|
372
|
-
withCredentials?: boolean
|
|
373
|
-
restModel: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey
|
|
374
|
-
reactBootstrap?: CarbonReact<any, any
|
|
375
|
-
requestMethod: iRestMethods
|
|
376
|
-
clearCache?: () => void
|
|
377
|
-
skipPrimaryCheck?: boolean
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
142
|
+
withCredentials?: boolean;
|
|
143
|
+
restModel: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey>;
|
|
144
|
+
reactBootstrap?: CarbonReact<any, any>;
|
|
145
|
+
requestMethod: iRestMethods;
|
|
146
|
+
clearCache?: () => void;
|
|
147
|
+
skipPrimaryCheck?: boolean;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface iConstraint {
|
|
151
|
+
TABLE: string;
|
|
152
|
+
COLUMN: string;
|
|
153
|
+
CONSTRAINT: string;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export type tColumns<TableName extends string, T extends { [key: string]: any }> = {
|
|
157
|
+
[K in keyof T & string as `${TableName}.${K}`]: K;
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
export type tPrimaryKeys<TableName extends string, PK extends string> = `${TableName}.${PK}`;
|
|
161
|
+
|
|
162
|
+
export interface iC6RestfulModel<RestShortTableNames extends string, RestTableInterfaces extends { [key: string]: any }, PK extends keyof RestTableInterfaces & string> {
|
|
163
|
+
TABLE_NAME: RestShortTableNames;
|
|
164
|
+
PRIMARY: tPrimaryKeys<RestShortTableNames, PK>[];
|
|
165
|
+
PRIMARY_SHORT: PK[];
|
|
166
|
+
COLUMNS: tColumns<RestShortTableNames, RestTableInterfaces>;
|
|
167
|
+
TYPE_VALIDATION: { [key: string]: iTypeValidation };
|
|
168
|
+
REGEX_VALIDATION: RegExpMap;
|
|
169
|
+
LIFECYCLE_HOOKS: iRestHooks<RestShortTableNames, RestTableInterfaces, PK>;
|
|
170
|
+
TABLE_REFERENCES: { [columnName: string]: iConstraint[] };
|
|
171
|
+
TABLE_REFERENCED_BY: { [columnName: string]: iConstraint[] };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export type iRestReactiveLifecycle<
|
|
175
|
+
Method extends iRestMethods,
|
|
176
|
+
RestShortTableName extends string,
|
|
177
|
+
RestTableInterface extends { [key: string]: any },
|
|
178
|
+
PrimaryKey extends keyof RestTableInterface & string,
|
|
179
|
+
CustomAndRequiredFields extends { [key: string]: any },
|
|
180
|
+
RequestTableOverrides extends { [key: string]: any }
|
|
181
|
+
> = {
|
|
182
|
+
beforeProcessing?: {
|
|
183
|
+
[key: string]: (args: {
|
|
184
|
+
config: iRest<RestShortTableName, RestTableInterface, PrimaryKey>;
|
|
185
|
+
request: RequestQueryBody<Method, RestTableInterface, CustomAndRequiredFields, RequestTableOverrides>;
|
|
186
|
+
}) => void | Promise<void>;
|
|
187
|
+
};
|
|
188
|
+
beforeExecution?: {
|
|
189
|
+
[key: string]: (args: {
|
|
190
|
+
config: iRest<RestShortTableName, RestTableInterface, PrimaryKey>;
|
|
191
|
+
request: RequestQueryBody<Method, RestTableInterface, CustomAndRequiredFields, RequestTableOverrides>;
|
|
192
|
+
}) => void | Promise<void>;
|
|
193
|
+
};
|
|
194
|
+
afterExecution?: {
|
|
195
|
+
[key: string]: (args: {
|
|
196
|
+
config: iRest<RestShortTableName, RestTableInterface, PrimaryKey>;
|
|
197
|
+
request: RequestQueryBody<Method, RestTableInterface, CustomAndRequiredFields, RequestTableOverrides>;
|
|
198
|
+
response: AxiosResponse<DetermineResponseDataType<Method, RestTableInterface>>;
|
|
199
|
+
}) => void | Promise<void>;
|
|
200
|
+
};
|
|
201
|
+
afterCommit?: {
|
|
202
|
+
[key: string]: (args: {
|
|
203
|
+
config: iRest<RestShortTableName, RestTableInterface, PrimaryKey>;
|
|
204
|
+
request: RequestQueryBody<Method, RestTableInterface, CustomAndRequiredFields, RequestTableOverrides>;
|
|
205
|
+
response: AxiosResponse<DetermineResponseDataType<Method, RestTableInterface>>;
|
|
206
|
+
}) => void | Promise<void>;
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
export type iRestHooks<
|
|
211
|
+
RestShortTableName extends string,
|
|
212
|
+
RestTableInterface extends { [key: string]: any },
|
|
213
|
+
PrimaryKey extends keyof RestTableInterface & string,
|
|
214
|
+
CustomAndRequiredFields extends { [key: string]: any } = any,
|
|
215
|
+
RequestTableOverrides extends { [key: string]: any } = { [key in keyof RestTableInterface]: any }
|
|
216
|
+
> = {
|
|
217
|
+
[Method in iRestMethods]: iRestReactiveLifecycle<
|
|
218
|
+
Method,
|
|
219
|
+
RestShortTableName,
|
|
220
|
+
RestTableInterface,
|
|
221
|
+
PrimaryKey,
|
|
222
|
+
CustomAndRequiredFields,
|
|
223
|
+
RequestTableOverrides
|
|
224
|
+
>;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
export interface iDynamicApiImport<RestData extends { [key: string]: any } = any> {
|
|
228
|
+
default: iRestApiFunctions<RestData>;
|
|
229
|
+
postState?: (response: AxiosResponse<iPostC6RestResponse<RestData>>, request: iAPI<any>, id: string | number | boolean) => void;
|
|
230
|
+
deleteState?: (response: AxiosResponse<iDeleteC6RestResponse<RestData>>, request: iAPI<any>) => void;
|
|
231
|
+
putState?: (response: AxiosResponse<iPutC6RestResponse<RestData>>, request: iAPI<any>) => void;
|
|
390
232
|
}
|
|
391
233
|
|
|
234
|
+
export interface iRestApiFunctions<RestData extends { [key: string]: any } = any> {
|
|
235
|
+
Delete: (request?: RequestQueryBody<'DELETE', RestData>) => apiReturn<iDeleteC6RestResponse<RestData>>;
|
|
236
|
+
Post: (request?: RequestQueryBody<'POST', RestData>) => apiReturn<iPostC6RestResponse<RestData>>;
|
|
237
|
+
Get: (request?: RequestQueryBody<'GET', RestData>) => apiReturn<iGetC6RestResponse<RestData>>;
|
|
238
|
+
Put: (request?: RequestQueryBody<'PUT', RestData>) => apiReturn<iPutC6RestResponse<RestData>>;
|
|
239
|
+
}
|
|
392
240
|
|
|
241
|
+
export interface iC6Object<
|
|
242
|
+
RestShortTableName extends string = any,
|
|
243
|
+
RestTableInterface extends { [key: string]: any } = any,
|
|
244
|
+
PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>
|
|
245
|
+
> {
|
|
246
|
+
C6VERSION: string;
|
|
247
|
+
TABLES: {
|
|
248
|
+
[key: string]: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey> & {
|
|
249
|
+
[key: string]: string | number;
|
|
250
|
+
};
|
|
251
|
+
};
|
|
252
|
+
PREFIX: string;
|
|
253
|
+
IMPORT: (tableName: string) => Promise<iDynamicApiImport>;
|
|
254
|
+
[key: string]: any;
|
|
255
|
+
}
|
|
393
256
|
|
|
257
|
+
export interface tC6Tables<
|
|
258
|
+
RestShortTableName extends string = any,
|
|
259
|
+
RestTableInterface extends { [key: string]: any } = any,
|
|
260
|
+
PrimaryKey extends Extract<keyof RestTableInterface, string> = Extract<keyof RestTableInterface, string>
|
|
261
|
+
> {
|
|
262
|
+
[key: string]: iC6RestfulModel<RestShortTableName, RestTableInterface, PrimaryKey> & { [key: string]: any };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export interface tC6RestApi {
|
|
266
|
+
[key: string]: {
|
|
267
|
+
REST: iRestApiFunctions;
|
|
268
|
+
PUT: Function;
|
|
269
|
+
POST: Function;
|
|
270
|
+
DELETE: Function;
|
|
271
|
+
};
|
|
272
|
+
}
|
package/src/api/rest/C6.test.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { describe, expect, test } from '@jest/globals';
|
|
2
|
-
import { checkAllRequestsComplete } from '@carbonorm/carbonnode';
|
|
3
|
-
import { act, waitFor } from '@testing-library/react';
|
|
4
|
-
import { C6 } from "./C6";
|
|
5
|
-
|
|
6
|
-
const fillString = () => Math.random().toString(36).substring(2, 12);
|
|
7
|
-
const fillNumber = () => Math.floor(Math.random() * 1000000);
|
|
8
|
-
|
|
9
|
-
const RESERVED_COLUMNS = ['created_at', 'updated_at', 'deleted_at'];
|
|
10
|
-
|
|
11
|
-
function buildTestData(tableModel: any): Record<string, any> {
|
|
12
|
-
const data: Record<string, any> = {};
|
|
13
|
-
const validation = tableModel.TYPE_VALIDATION;
|
|
14
|
-
|
|
15
|
-
for (const col of Object.keys(validation)) {
|
|
16
|
-
const { MYSQL_TYPE, SKIP_COLUMN_IN_POST, MAX_LENGTH } = validation[col];
|
|
17
|
-
|
|
18
|
-
if (SKIP_COLUMN_IN_POST || RESERVED_COLUMNS.includes(col)) continue;
|
|
19
|
-
|
|
20
|
-
if (MYSQL_TYPE.startsWith('varchar') || MYSQL_TYPE === 'text') {
|
|
21
|
-
let str = fillString();
|
|
22
|
-
if (MAX_LENGTH) str = str.substring(0, MAX_LENGTH);
|
|
23
|
-
data[col] = str;
|
|
24
|
-
} else if (MYSQL_TYPE.includes('int') || MYSQL_TYPE === 'decimal') {
|
|
25
|
-
data[col] = fillNumber();
|
|
26
|
-
} else if (MYSQL_TYPE === 'json') {
|
|
27
|
-
data[col] = {};
|
|
28
|
-
} else if (MYSQL_TYPE === 'tinyint(1)') {
|
|
29
|
-
data[col] = 1;
|
|
30
|
-
} else {
|
|
31
|
-
data[col] = null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
return data;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
describe('CarbonORM table API integration tests', () => {
|
|
39
|
-
for (const [shortName, tableModel] of Object.entries(C6.TABLES)) {
|
|
40
|
-
const primaryKeys: string[] = tableModel.PRIMARY_SHORT;
|
|
41
|
-
|
|
42
|
-
// Get restOrm binding
|
|
43
|
-
const restBinding = (C6 as any)[shortName[0].toUpperCase() + shortName.slice(1)];
|
|
44
|
-
if (!restBinding) continue;
|
|
45
|
-
|
|
46
|
-
test(`[${shortName}] GET → POST → GET → PUT → DELETE`, async () => {
|
|
47
|
-
|
|
48
|
-
const testData = buildTestData(tableModel);
|
|
49
|
-
|
|
50
|
-
await act(async () => {
|
|
51
|
-
|
|
52
|
-
// GET all
|
|
53
|
-
const all = await restBinding.Get({});
|
|
54
|
-
expect(all?.data?.rest).toBeDefined();
|
|
55
|
-
|
|
56
|
-
// POST one
|
|
57
|
-
const post = await restBinding.Post(testData);
|
|
58
|
-
expect(post?.data?.created).toBeDefined();
|
|
59
|
-
|
|
60
|
-
const postID = post?.data?.created;
|
|
61
|
-
const pkName = primaryKeys[0];
|
|
62
|
-
testData[pkName] = postID;
|
|
63
|
-
|
|
64
|
-
// GET single
|
|
65
|
-
const select = await restBinding.Get({
|
|
66
|
-
[C6.WHERE]: {
|
|
67
|
-
[tableModel[pkName.toUpperCase()]]: postID
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
expect(select?.data?.rest?.[0]?.[pkName]).toEqual(postID);
|
|
72
|
-
|
|
73
|
-
// PUT update
|
|
74
|
-
const updated = await restBinding.Put(testData);
|
|
75
|
-
expect(updated?.data?.updated).toBeDefined();
|
|
76
|
-
|
|
77
|
-
// DELETE
|
|
78
|
-
const deleted = await restBinding.Delete({ [pkName]: postID });
|
|
79
|
-
expect(deleted?.data?.deleted).toBeDefined();
|
|
80
|
-
|
|
81
|
-
// Wait for all requests to settle
|
|
82
|
-
await waitFor(() => {
|
|
83
|
-
expect(checkAllRequestsComplete()).toEqual(true);
|
|
84
|
-
}, { timeout: 10000, interval: 1000 });
|
|
85
|
-
});
|
|
86
|
-
}, 100000);
|
|
87
|
-
}
|
|
88
|
-
});
|