@cuboapp/api-backend 1.0.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.
package/.prettierrc ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "trailingComma": "none",
3
+ "tabWidth": 2,
4
+ "semi": false,
5
+ "singleQuote": true,
6
+ "eslintIntegration": true,
7
+ "printWidth": 140
8
+ }
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@cuboapp/api-backend",
3
+ "version": "1.0.0",
4
+ "description": "Backend Api for CuboApp",
5
+ "main": "src/index.ts",
6
+ "repository": "git@github.com:cuboapp/api-backend.git",
7
+ "author": "CuboSoft",
8
+ "license": "MIT",
9
+ "type": "module",
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "dependencies": {
14
+ "@cuboapp/config": "^0.0.6",
15
+ "@cuboapp/types": "^1.0.19",
16
+ "lodash-es": "^4.17.21",
17
+ "pg": "^8.13.3",
18
+ "sequelize": "^6.37.6"
19
+ },
20
+ "devDependencies": {
21
+ "@types/lodash-es": "^4.17.12",
22
+ "@types/node": "^22.0.0",
23
+ "typescript": "^5.8.2"
24
+ }
25
+ }
package/pnpm-lock.yaml ADDED
@@ -0,0 +1,378 @@
1
+ lockfileVersion: '9.0'
2
+
3
+ settings:
4
+ autoInstallPeers: true
5
+ excludeLinksFromLockfile: false
6
+
7
+ importers:
8
+
9
+ .:
10
+ dependencies:
11
+ '@cuboapp/config':
12
+ specifier: ^0.0.6
13
+ version: 0.0.6
14
+ '@cuboapp/types':
15
+ specifier: ^1.0.19
16
+ version: 1.0.19
17
+ lodash-es:
18
+ specifier: ^4.17.21
19
+ version: 4.17.21
20
+ pg:
21
+ specifier: ^8.13.3
22
+ version: 8.13.3
23
+ sequelize:
24
+ specifier: ^6.37.6
25
+ version: 6.37.6(pg@8.13.3)
26
+ devDependencies:
27
+ '@types/lodash-es':
28
+ specifier: ^4.17.12
29
+ version: 4.17.12
30
+ '@types/node':
31
+ specifier: ^22.0.0
32
+ version: 22.13.9
33
+ typescript:
34
+ specifier: ^5.8.2
35
+ version: 5.8.2
36
+
37
+ packages:
38
+
39
+ '@cuboapp/config@0.0.6':
40
+ resolution: {integrity: sha512-2sQKqPYUK3YH46CPgbJXzvzD8QLxHm5CVrSAj78rxDzqX/xnnAAqOYfn4QS6B/4GZxRexNp2OkKH5c2ea+dXRg==}
41
+
42
+ '@cuboapp/types@1.0.19':
43
+ resolution: {integrity: sha512-CZyut9MmCT+5bBBbZF3ETiJnRbgnExvx/+zT/UKj4NxZKlqQAnzX8hWIFMBbed3YoSkbS+cdZcJE26k5mLNPjw==}
44
+
45
+ '@types/debug@4.1.12':
46
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
47
+
48
+ '@types/events@3.0.3':
49
+ resolution: {integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==}
50
+
51
+ '@types/lodash-es@4.17.12':
52
+ resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==}
53
+
54
+ '@types/lodash@4.17.16':
55
+ resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==}
56
+
57
+ '@types/ms@2.1.0':
58
+ resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==}
59
+
60
+ '@types/node@22.13.9':
61
+ resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==}
62
+
63
+ '@types/validator@13.12.2':
64
+ resolution: {integrity: sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA==}
65
+
66
+ debug@4.4.0:
67
+ resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==}
68
+ engines: {node: '>=6.0'}
69
+ peerDependencies:
70
+ supports-color: '*'
71
+ peerDependenciesMeta:
72
+ supports-color:
73
+ optional: true
74
+
75
+ dotenv-expand@12.0.1:
76
+ resolution: {integrity: sha512-LaKRbou8gt0RNID/9RoI+J2rvXsBRPMV7p+ElHlPhcSARbCPDYcYG2s1TIzAfWv4YSgyY5taidWzzs31lNV3yQ==}
77
+ engines: {node: '>=12'}
78
+
79
+ dotenv@16.4.7:
80
+ resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==}
81
+ engines: {node: '>=12'}
82
+
83
+ dottie@2.0.6:
84
+ resolution: {integrity: sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==}
85
+
86
+ inflection@1.13.4:
87
+ resolution: {integrity: sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==}
88
+ engines: {'0': node >= 0.4.0}
89
+
90
+ lodash-es@4.17.21:
91
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
92
+
93
+ lodash@4.17.21:
94
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
95
+
96
+ moment-timezone@0.5.47:
97
+ resolution: {integrity: sha512-UbNt/JAWS0m/NJOebR0QMRHBk0hu03r5dx9GK8Cs0AS3I81yDcOc9k+DytPItgVvBP7J6Mf6U2n3BPAacAV9oA==}
98
+
99
+ moment@2.30.1:
100
+ resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==}
101
+
102
+ ms@2.1.3:
103
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
104
+
105
+ pg-cloudflare@1.1.1:
106
+ resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
107
+
108
+ pg-connection-string@2.7.0:
109
+ resolution: {integrity: sha512-PI2W9mv53rXJQEOb8xNR8lH7Hr+EKa6oJa38zsK0S/ky2er16ios1wLKhZyxzD7jUReiWokc9WK5nxSnC7W1TA==}
110
+
111
+ pg-int8@1.0.1:
112
+ resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
113
+ engines: {node: '>=4.0.0'}
114
+
115
+ pg-pool@3.7.1:
116
+ resolution: {integrity: sha512-xIOsFoh7Vdhojas6q3596mXFsR8nwBQBXX5JiV7p9buEVAGqYL4yFzclON5P9vFrpu1u7Zwl2oriyDa89n0wbw==}
117
+ peerDependencies:
118
+ pg: '>=8.0'
119
+
120
+ pg-protocol@1.7.1:
121
+ resolution: {integrity: sha512-gjTHWGYWsEgy9MsY0Gp6ZJxV24IjDqdpTW7Eh0x+WfJLFsm/TJx1MzL6T0D88mBvkpxotCQ6TwW6N+Kko7lhgQ==}
122
+
123
+ pg-types@2.2.0:
124
+ resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
125
+ engines: {node: '>=4'}
126
+
127
+ pg@8.13.3:
128
+ resolution: {integrity: sha512-P6tPt9jXbL9HVu/SSRERNYaYG++MjnscnegFh9pPHihfoBSujsrka0hyuymMzeJKFWrcG8wvCKy8rCe8e5nDUQ==}
129
+ engines: {node: '>= 8.0.0'}
130
+ peerDependencies:
131
+ pg-native: '>=3.0.1'
132
+ peerDependenciesMeta:
133
+ pg-native:
134
+ optional: true
135
+
136
+ pgpass@1.0.5:
137
+ resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
138
+
139
+ postgres-array@2.0.0:
140
+ resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
141
+ engines: {node: '>=4'}
142
+
143
+ postgres-bytea@1.0.0:
144
+ resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
145
+ engines: {node: '>=0.10.0'}
146
+
147
+ postgres-date@1.0.7:
148
+ resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
149
+ engines: {node: '>=0.10.0'}
150
+
151
+ postgres-interval@1.2.0:
152
+ resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
153
+ engines: {node: '>=0.10.0'}
154
+
155
+ retry-as-promised@7.1.1:
156
+ resolution: {integrity: sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw==}
157
+
158
+ semver@7.7.1:
159
+ resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==}
160
+ engines: {node: '>=10'}
161
+ hasBin: true
162
+
163
+ sequelize-pool@7.1.0:
164
+ resolution: {integrity: sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==}
165
+ engines: {node: '>= 10.0.0'}
166
+
167
+ sequelize@6.37.6:
168
+ resolution: {integrity: sha512-4Slqjqpktofs7AVqWviFOInzP9w8ZRQDhF+DnRtm4WKIdIATpyzGgedyseP3xbgpBxapvfQcJv6CeIdZe4ZL2A==}
169
+ engines: {node: '>=10.0.0'}
170
+ peerDependencies:
171
+ ibm_db: '*'
172
+ mariadb: '*'
173
+ mysql2: '*'
174
+ oracledb: '*'
175
+ pg: '*'
176
+ pg-hstore: '*'
177
+ snowflake-sdk: '*'
178
+ sqlite3: '*'
179
+ tedious: '*'
180
+ peerDependenciesMeta:
181
+ ibm_db:
182
+ optional: true
183
+ mariadb:
184
+ optional: true
185
+ mysql2:
186
+ optional: true
187
+ oracledb:
188
+ optional: true
189
+ pg:
190
+ optional: true
191
+ pg-hstore:
192
+ optional: true
193
+ snowflake-sdk:
194
+ optional: true
195
+ sqlite3:
196
+ optional: true
197
+ tedious:
198
+ optional: true
199
+
200
+ split2@4.2.0:
201
+ resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
202
+ engines: {node: '>= 10.x'}
203
+
204
+ toposort-class@1.0.1:
205
+ resolution: {integrity: sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==}
206
+
207
+ typescript@5.8.2:
208
+ resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==}
209
+ engines: {node: '>=14.17'}
210
+ hasBin: true
211
+
212
+ undici-types@6.20.0:
213
+ resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==}
214
+
215
+ uuid@8.3.2:
216
+ resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
217
+ hasBin: true
218
+
219
+ validator@13.12.0:
220
+ resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
221
+ engines: {node: '>= 0.10'}
222
+
223
+ wkx@0.5.0:
224
+ resolution: {integrity: sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==}
225
+
226
+ xtend@4.0.2:
227
+ resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
228
+ engines: {node: '>=0.4'}
229
+
230
+ snapshots:
231
+
232
+ '@cuboapp/config@0.0.6':
233
+ dependencies:
234
+ '@cuboapp/types': 1.0.19
235
+ dotenv: 16.4.7
236
+ dotenv-expand: 12.0.1
237
+
238
+ '@cuboapp/types@1.0.19':
239
+ dependencies:
240
+ '@types/events': 3.0.3
241
+
242
+ '@types/debug@4.1.12':
243
+ dependencies:
244
+ '@types/ms': 2.1.0
245
+
246
+ '@types/events@3.0.3': {}
247
+
248
+ '@types/lodash-es@4.17.12':
249
+ dependencies:
250
+ '@types/lodash': 4.17.16
251
+
252
+ '@types/lodash@4.17.16': {}
253
+
254
+ '@types/ms@2.1.0': {}
255
+
256
+ '@types/node@22.13.9':
257
+ dependencies:
258
+ undici-types: 6.20.0
259
+
260
+ '@types/validator@13.12.2': {}
261
+
262
+ debug@4.4.0:
263
+ dependencies:
264
+ ms: 2.1.3
265
+
266
+ dotenv-expand@12.0.1:
267
+ dependencies:
268
+ dotenv: 16.4.7
269
+
270
+ dotenv@16.4.7: {}
271
+
272
+ dottie@2.0.6: {}
273
+
274
+ inflection@1.13.4: {}
275
+
276
+ lodash-es@4.17.21: {}
277
+
278
+ lodash@4.17.21: {}
279
+
280
+ moment-timezone@0.5.47:
281
+ dependencies:
282
+ moment: 2.30.1
283
+
284
+ moment@2.30.1: {}
285
+
286
+ ms@2.1.3: {}
287
+
288
+ pg-cloudflare@1.1.1:
289
+ optional: true
290
+
291
+ pg-connection-string@2.7.0: {}
292
+
293
+ pg-int8@1.0.1: {}
294
+
295
+ pg-pool@3.7.1(pg@8.13.3):
296
+ dependencies:
297
+ pg: 8.13.3
298
+
299
+ pg-protocol@1.7.1: {}
300
+
301
+ pg-types@2.2.0:
302
+ dependencies:
303
+ pg-int8: 1.0.1
304
+ postgres-array: 2.0.0
305
+ postgres-bytea: 1.0.0
306
+ postgres-date: 1.0.7
307
+ postgres-interval: 1.2.0
308
+
309
+ pg@8.13.3:
310
+ dependencies:
311
+ pg-connection-string: 2.7.0
312
+ pg-pool: 3.7.1(pg@8.13.3)
313
+ pg-protocol: 1.7.1
314
+ pg-types: 2.2.0
315
+ pgpass: 1.0.5
316
+ optionalDependencies:
317
+ pg-cloudflare: 1.1.1
318
+
319
+ pgpass@1.0.5:
320
+ dependencies:
321
+ split2: 4.2.0
322
+
323
+ postgres-array@2.0.0: {}
324
+
325
+ postgres-bytea@1.0.0: {}
326
+
327
+ postgres-date@1.0.7: {}
328
+
329
+ postgres-interval@1.2.0:
330
+ dependencies:
331
+ xtend: 4.0.2
332
+
333
+ retry-as-promised@7.1.1: {}
334
+
335
+ semver@7.7.1: {}
336
+
337
+ sequelize-pool@7.1.0: {}
338
+
339
+ sequelize@6.37.6(pg@8.13.3):
340
+ dependencies:
341
+ '@types/debug': 4.1.12
342
+ '@types/validator': 13.12.2
343
+ debug: 4.4.0
344
+ dottie: 2.0.6
345
+ inflection: 1.13.4
346
+ lodash: 4.17.21
347
+ moment: 2.30.1
348
+ moment-timezone: 0.5.47
349
+ pg-connection-string: 2.7.0
350
+ retry-as-promised: 7.1.1
351
+ semver: 7.7.1
352
+ sequelize-pool: 7.1.0
353
+ toposort-class: 1.0.1
354
+ uuid: 8.3.2
355
+ validator: 13.12.0
356
+ wkx: 0.5.0
357
+ optionalDependencies:
358
+ pg: 8.13.3
359
+ transitivePeerDependencies:
360
+ - supports-color
361
+
362
+ split2@4.2.0: {}
363
+
364
+ toposort-class@1.0.1: {}
365
+
366
+ typescript@5.8.2: {}
367
+
368
+ undici-types@6.20.0: {}
369
+
370
+ uuid@8.3.2: {}
371
+
372
+ validator@13.12.0: {}
373
+
374
+ wkx@0.5.0:
375
+ dependencies:
376
+ '@types/node': 22.13.9
377
+
378
+ xtend@4.0.2: {}
@@ -0,0 +1,74 @@
1
+ import { CuboEntityField } from '@cuboapp/types'
2
+
3
+ import { CUBO_ENTITY_FIELD_TYPE } from './base'
4
+
5
+ export const CUBO_CRUD_QUERY_KEY_REGEX = /[^a-zA-Z\.\_]/g
6
+
7
+ export const CUBO_CRUD_QUERY_SYMBOL_NOT = 'not'
8
+
9
+ export const CUBO_CRUD_DEFAULT_PAGE_LIMIT = 25
10
+ export const CUBO_CRUD_MAX_PAGE_LIMIT = 500
11
+
12
+ export const CUBO_CRUD_QUERY_CONDITION = {
13
+ EQ: 'eq',
14
+ EX: 'ex',
15
+ LIKE: 'like',
16
+ ILIKE: 'ilike',
17
+ IN: 'in',
18
+ NIN: 'nin',
19
+ GT: 'gt',
20
+ LT: 'lt',
21
+ GTE: 'gte',
22
+ LTE: 'lte'
23
+ }
24
+
25
+ export const CUBO_CRUD_DEFAULT_FIELDS: Pick<CuboEntityField, 'type_id' | 'alias' | 'extra'>[] = [
26
+ {
27
+ type_id: CUBO_ENTITY_FIELD_TYPE.NUMBER,
28
+ alias: 'id',
29
+ extra: {
30
+ number_subtype: 'int'
31
+ }
32
+ },
33
+ {
34
+ type_id: CUBO_ENTITY_FIELD_TYPE.TIMESTAMP,
35
+ alias: 'created_at',
36
+ extra: {}
37
+ },
38
+ {
39
+ type_id: CUBO_ENTITY_FIELD_TYPE.SELECT,
40
+ alias: 'created_by',
41
+ extra: {
42
+ select_subtype: 'user',
43
+ select_entity_key: 'created_by'
44
+ }
45
+ },
46
+ {
47
+ type_id: CUBO_ENTITY_FIELD_TYPE.TIMESTAMP,
48
+ alias: 'modified_at',
49
+ extra: {}
50
+ },
51
+ {
52
+ type_id: CUBO_ENTITY_FIELD_TYPE.SELECT,
53
+ alias: 'modified_by',
54
+ extra: {
55
+ select_subtype: 'user',
56
+ select_entity_key: 'modified_by'
57
+ }
58
+ },
59
+ {
60
+ type_id: CUBO_ENTITY_FIELD_TYPE.TIMESTAMP,
61
+ alias: 'deleted_at',
62
+ extra: {}
63
+ },
64
+ {
65
+ type_id: CUBO_ENTITY_FIELD_TYPE.SELECT,
66
+ alias: 'deleted_by',
67
+ extra: {
68
+ select_subtype: 'user',
69
+ select_entity_key: 'modified_by'
70
+ }
71
+ }
72
+ ]
73
+
74
+ export const CUBO_CRUD_DEFAULT_FIELDS_ALIASES = CUBO_CRUD_DEFAULT_FIELDS.map((i) => i.alias)
@@ -0,0 +1,11 @@
1
+ export const CUBO_ENTITY_FIELD_TYPE = {
2
+ TEXT: 1,
3
+ NUMBER: 2,
4
+ TEXTAREA: 3,
5
+ BOOLEAN: 4,
6
+ SELECT: 5,
7
+ DATE: 6,
8
+ TIMESTAMP: 7,
9
+ FILE: 8,
10
+ JSON: 9
11
+ }
@@ -0,0 +1,2 @@
1
+ export * from './backend'
2
+ export * from './base'
@@ -0,0 +1,135 @@
1
+ import get from 'lodash-es/get'
2
+ import set from 'lodash-es/set'
3
+ import unset from 'lodash-es/unset'
4
+
5
+ import { CUBO_CRUD_DEFAULT_FIELDS, CUBO_ENTITY_FIELD_TYPE } from '../../constants'
6
+ import { CuboCrudFindQuery, CuboCrudRequest, CuboEntitiesMap, CuboEntityFieldModel, CuboEntityModel } from '../../types'
7
+
8
+ import { ApiHelpers } from '.'
9
+
10
+ export class ApiHelpersConvert<T extends CuboEntitiesMap<T>> {
11
+ constructor(public helpers: ApiHelpers<T>) {}
12
+
13
+ public async prepareAll(req: CuboCrudRequest, entity: CuboEntityModel, rows: any[], query?: Partial<CuboCrudFindQuery>): Promise<any[]> {
14
+ for (const rowKey in rows) {
15
+ rows[rowKey] = await this.prepareOne(req, entity, rows[rowKey], query)
16
+ }
17
+
18
+ return rows
19
+ }
20
+
21
+ public async prepareOne(req: CuboCrudRequest, entity: CuboEntityModel, row: any, query?: Partial<CuboCrudFindQuery>) {
22
+ const usersDefaultFields = ['created_by', 'modified_by', 'deleted_by']
23
+
24
+ const toPrepare: Record<string, any> = {}
25
+ const toRemove: string[] = []
26
+ const userFieldsPrepared: string[] = []
27
+
28
+ // console.log('query?.withes', query?.withes)
29
+
30
+ // добавялем базовые поля
31
+ for (const field of [...entity.fields, ...CUBO_CRUD_DEFAULT_FIELDS]) {
32
+ if (!userFieldsPrepared.includes(field.alias)) {
33
+ toPrepare[field.alias] = field
34
+ }
35
+ }
36
+
37
+ // добавялем поля-with-ы
38
+ for (const withEl of query?.withes || []) {
39
+ const valueKey = withEl.table_name
40
+ const initialValueKey = usersDefaultFields.includes(withEl.key) ? valueKey : valueKey + '_id'
41
+
42
+ const rowValue = get(row, initialValueKey, undefined)
43
+
44
+ if (!withEl.entity.id && withEl.entity.alias === 'users') {
45
+ userFieldsPrepared.push(withEl.full_key)
46
+
47
+ switch (rowValue) {
48
+ case null:
49
+ case undefined:
50
+ set(row, withEl.full_key, null)
51
+ break
52
+ case 0:
53
+ set(row, withEl.full_key, { id: 0, name: this.helpers.api.account.name })
54
+ break
55
+ default:
56
+ const user = await this.helpers.users.getById(rowValue)
57
+
58
+ set(
59
+ row,
60
+ withEl.full_key,
61
+ user ? { id: user.id, name: user.name, email: user.email } : { id: rowValue, name: `User #${rowValue}` }
62
+ )
63
+ break
64
+ }
65
+ } else {
66
+ const rowValueEmpty = [0, '0', '', null, 'null'].includes(rowValue)
67
+
68
+ if (rowValueEmpty) {
69
+ set(row, withEl.full_key, null)
70
+ }
71
+
72
+ if (toPrepare[withEl.key]) {
73
+ delete toPrepare[withEl.key]
74
+ }
75
+
76
+ // console.log('rowValue', withEl.full_key, { rowValueEmpty, rowValue })
77
+
78
+ for (const field of [...withEl.entity.fields, ...CUBO_CRUD_DEFAULT_FIELDS]) {
79
+ const fieldValueKey = withEl.table_name.toLowerCase() + '_' + field.alias
80
+
81
+ // console.log('add field', field.alias, rowValueEmpty)
82
+
83
+ if (!rowValueEmpty && !usersDefaultFields.includes(field.alias)) {
84
+ const fieldKeyPath = withEl.full_key + '.' + field.alias
85
+ const rowRelationValue = get(row, fieldValueKey, undefined)
86
+
87
+ set(row, fieldKeyPath, this.prepareFieldValue(field, rowRelationValue))
88
+
89
+ toPrepare[fieldKeyPath] = field
90
+ }
91
+
92
+ if (field.alias !== 'id') {
93
+ toRemove.push(fieldValueKey)
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ for (const el of toRemove) {
100
+ unset(row, el)
101
+ }
102
+
103
+ // console.log('toPrepare', { toRemove, row })
104
+
105
+ for (const key in toPrepare) {
106
+ // console.log('set row field', key, this.prepareFieldValue(toPrepare[key], get(row, key)))
107
+
108
+ set(row, key, this.prepareFieldValue(toPrepare[key], get(row, key)))
109
+ }
110
+
111
+ return row
112
+ }
113
+
114
+ private prepareFieldValue(field: Pick<CuboEntityFieldModel, 'type_id' | 'alias' | 'extra'>, value: any) {
115
+ switch (field.type_id) {
116
+ case CUBO_ENTITY_FIELD_TYPE.BOOLEAN:
117
+ return value !== undefined ? (['true', true].includes(value) ? true : false) : null
118
+ case CUBO_ENTITY_FIELD_TYPE.DATE:
119
+ return value
120
+ case CUBO_ENTITY_FIELD_TYPE.FILE:
121
+ console.warn('field type "file" is not implemented yet')
122
+ return undefined
123
+ case CUBO_ENTITY_FIELD_TYPE.JSON:
124
+ return value
125
+ case CUBO_ENTITY_FIELD_TYPE.NUMBER:
126
+ return ![undefined, null].includes(value) ? parseFloat(value) : null
127
+ case CUBO_ENTITY_FIELD_TYPE.SELECT:
128
+ return ![undefined, null].includes(value) ? parseInt(value, 10) : null
129
+ case CUBO_ENTITY_FIELD_TYPE.TEXT:
130
+ case CUBO_ENTITY_FIELD_TYPE.TEXTAREA:
131
+ case CUBO_ENTITY_FIELD_TYPE.TIMESTAMP:
132
+ return value !== undefined ? value : null
133
+ }
134
+ }
135
+ }