adminforth 1.3.54-next.23 → 1.3.54-next.24

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 (101) hide show
  1. package/dist/plugins/audit-log/types.js +2 -0
  2. package/dist/plugins/audit-log/types.js.map +1 -0
  3. package/dist/plugins/chat-gpt/types.js +2 -0
  4. package/dist/plugins/chat-gpt/types.js.map +1 -0
  5. package/dist/plugins/email-password-reset/types.js +2 -0
  6. package/dist/plugins/email-password-reset/types.js.map +1 -0
  7. package/dist/plugins/foreign-inline-list/types.js +2 -0
  8. package/dist/plugins/foreign-inline-list/types.js.map +1 -0
  9. package/dist/plugins/import-export/types.js +2 -0
  10. package/dist/plugins/import-export/types.js.map +1 -0
  11. package/dist/plugins/rich-editor/custom/async-queue.js +29 -0
  12. package/dist/plugins/rich-editor/custom/async-queue.js.map +1 -0
  13. package/dist/plugins/rich-editor/dist/async-queue.js +41 -0
  14. package/dist/plugins/rich-editor/dist/custom/async-queue.js +29 -0
  15. package/dist/plugins/rich-editor/dist/custom/async-queue.js.map +1 -0
  16. package/dist/plugins/rich-editor/types.js +16 -0
  17. package/dist/plugins/rich-editor/types.js.map +1 -0
  18. package/dist/plugins/two-factors-auth/types.js +2 -0
  19. package/dist/plugins/two-factors-auth/types.js.map +1 -0
  20. package/dist/plugins/upload/types.js +2 -0
  21. package/dist/plugins/upload/types.js.map +1 -0
  22. package/package.json +4 -1
  23. package/auth.ts +0 -140
  24. package/basePlugin.ts +0 -70
  25. package/dataConnectors/baseConnector.ts +0 -221
  26. package/dataConnectors/clickhouse.ts +0 -343
  27. package/dataConnectors/mongo.ts +0 -202
  28. package/dataConnectors/postgres.ts +0 -310
  29. package/dataConnectors/sqlite.ts +0 -258
  30. package/index.ts +0 -428
  31. package/modules/codeInjector.ts +0 -747
  32. package/modules/configValidator.ts +0 -588
  33. package/modules/operationalResource.ts +0 -98
  34. package/modules/restApi.ts +0 -718
  35. package/modules/styleGenerator.ts +0 -55
  36. package/modules/styles.ts +0 -126
  37. package/modules/utils.ts +0 -472
  38. package/servers/express.ts +0 -259
  39. package/spa/.eslintrc.cjs +0 -14
  40. package/spa/README.md +0 -39
  41. package/spa/env.d.ts +0 -1
  42. package/spa/index.html +0 -23
  43. package/spa/package-lock.json +0 -4659
  44. package/spa/package.json +0 -52
  45. package/spa/postcss.config.js +0 -6
  46. package/spa/public/assets/favicon.png +0 -0
  47. package/spa/src/App.vue +0 -418
  48. package/spa/src/assets/base.css +0 -2
  49. package/spa/src/assets/logo.svg +0 -19
  50. package/spa/src/components/AcceptModal.vue +0 -45
  51. package/spa/src/components/Breadcrumbs.vue +0 -41
  52. package/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
  53. package/spa/src/components/CustomDatePicker.vue +0 -176
  54. package/spa/src/components/CustomDateRangePicker.vue +0 -218
  55. package/spa/src/components/CustomRangePicker.vue +0 -156
  56. package/spa/src/components/Dropdown.vue +0 -168
  57. package/spa/src/components/Filters.vue +0 -222
  58. package/spa/src/components/HelloWorld.vue +0 -17
  59. package/spa/src/components/MenuLink.vue +0 -27
  60. package/spa/src/components/ResourceForm.vue +0 -325
  61. package/spa/src/components/ResourceListTable.vue +0 -466
  62. package/spa/src/components/SingleSkeletLoader.vue +0 -13
  63. package/spa/src/components/SkeleteLoader.vue +0 -23
  64. package/spa/src/components/ThreeDotsMenu.vue +0 -43
  65. package/spa/src/components/Toast.vue +0 -78
  66. package/spa/src/components/ValueRenderer.vue +0 -141
  67. package/spa/src/components/icons/IconCalendar.vue +0 -5
  68. package/spa/src/components/icons/IconCommunity.vue +0 -7
  69. package/spa/src/components/icons/IconDocumentation.vue +0 -7
  70. package/spa/src/components/icons/IconEcosystem.vue +0 -7
  71. package/spa/src/components/icons/IconSupport.vue +0 -7
  72. package/spa/src/components/icons/IconTime.vue +0 -5
  73. package/spa/src/components/icons/IconTooling.vue +0 -19
  74. package/spa/src/composables/useFrontendApi.ts +0 -26
  75. package/spa/src/composables/useStores.ts +0 -131
  76. package/spa/src/index.scss +0 -31
  77. package/spa/src/main.ts +0 -18
  78. package/spa/src/renderers/CompactUUID.vue +0 -48
  79. package/spa/src/renderers/CountryFlag.vue +0 -69
  80. package/spa/src/router/index.ts +0 -59
  81. package/spa/src/spa_types/core.ts +0 -53
  82. package/spa/src/stores/core.ts +0 -148
  83. package/spa/src/stores/filters.ts +0 -27
  84. package/spa/src/stores/modal.ts +0 -48
  85. package/spa/src/stores/toast.ts +0 -31
  86. package/spa/src/stores/user.ts +0 -72
  87. package/spa/src/utils.ts +0 -160
  88. package/spa/src/views/CreateView.vue +0 -167
  89. package/spa/src/views/EditView.vue +0 -170
  90. package/spa/src/views/ListView.vue +0 -352
  91. package/spa/src/views/LoginView.vue +0 -192
  92. package/spa/src/views/ResourceParent.vue +0 -17
  93. package/spa/src/views/ShowView.vue +0 -194
  94. package/spa/tailwind.config.js +0 -17
  95. package/spa/tsconfig.app.json +0 -14
  96. package/spa/tsconfig.json +0 -11
  97. package/spa/tsconfig.node.json +0 -19
  98. package/spa/vite.config.ts +0 -56
  99. package/tsconfig.json +0 -112
  100. package/types/AdminForthConfig.ts +0 -1762
  101. package/types/FrontendAPI.ts +0 -143
@@ -1,343 +0,0 @@
1
- import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections, IAdminForthDataSourceConnector, AdminForthResource, AdminForthResourceColumn } from '../types/AdminForthConfig.js';
2
- import AdminForthBaseConnector from './baseConnector.js';
3
- import dayjs from 'dayjs';
4
- import { createClient } from '@clickhouse/client'
5
- import { base } from '@faker-js/faker';
6
-
7
-
8
-
9
- class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
10
-
11
- client: any;
12
- dbName: string;
13
- url: string;
14
-
15
- /**
16
- * url: http[s]://[username:password@]hostname:port[/database][?param1=value1&param2=value2]
17
- * @param param0
18
- */
19
- constructor({ url }: { url: string }) {
20
- super();
21
- this.dbName = new URL(url).pathname.replace('/', '');
22
- this.url = url;;
23
- // create connection here
24
- this.client = createClient({
25
- url: url.replace('clickhouse://', 'http://'),
26
- clickhouse_settings: {
27
- // Allows to insert serialized JS Dates (such as '2023-12-06T10:54:48.000Z')
28
- date_time_input_format: 'best_effort',
29
-
30
- // Recommended for cluster usage to avoid situations where a query processing error occurred after the response code,
31
- // and HTTP headers were already sent to the client.
32
- // See https://clickhouse.com/docs/en/interfaces/http/#response-buffering
33
- wait_end_of_query: 1,
34
- },
35
- // log:{
36
- // level: ClickHouseLogLevel.TRACE,
37
- // }
38
- });
39
-
40
- }
41
-
42
- async discoverFields(resource: AdminForthResource): Promise<{[key: string]: AdminForthResourceColumn}> {
43
- const tableName = resource.table;
44
-
45
- let rows;
46
- try {
47
- const q = await this.client.query({
48
- query: `SELECT * FROM system.columns WHERE table = '${tableName}' and database = '${this.dbName}'`,
49
- format: 'JSONEachRow',
50
- });
51
- rows = await q.json();
52
- } catch (e) {
53
- console.error(` 🛑Error connecting to datasource URL ${this.url}:`, e);
54
- return null;
55
- }
56
-
57
- const fieldTypes = {};
58
- rows.forEach((row) => {
59
- const field: any = {};
60
- const baseType = row.type;
61
- if (baseType.startsWith('Int') || baseType.startsWith('UInt')) {
62
- field.type = AdminForthDataTypes.INTEGER;
63
- } else if (baseType === 'FixedString' || baseType === 'String') {
64
- field.type = AdminForthDataTypes.STRING;
65
- // TODO
66
- // const length = baseType.match(/\d+/g);
67
- // field.maxLength = length ? parseInt(length[0]) : null;
68
- } else if (baseType == 'UUID') {
69
- field.type = AdminForthDataTypes.STRING;
70
- } else if (baseType.startsWith('Decimal')) {
71
- field.type = AdminForthDataTypes.DECIMAL;
72
- const [precision, scale] = baseType.match(/\d+/g);
73
- field.precision = parseInt(precision);
74
- field.scale = parseInt(scale);
75
- } else if (baseType.startsWith('Float')) {
76
- field.type = AdminForthDataTypes.FLOAT;
77
- } else if (baseType == 'DateTime64' || baseType == 'DateTime' || baseType.startsWith('DateTime64(')) {
78
- field.type = AdminForthDataTypes.DATETIME;
79
- } else if (baseType == 'Date' || baseType == 'Date64') {
80
- field.type = AdminForthDataTypes.DATE;
81
- } else if (baseType == 'Boolean' || baseType == 'Bool') {
82
- field.type = AdminForthDataTypes.BOOLEAN;
83
- field._underlineType = 'boolean';
84
- } else {
85
- field.type = 'unknown'
86
- }
87
- field._underlineType = baseType;
88
- field._baseTypeDebug = baseType;
89
- field.required = row.notnull == 1;
90
- field.primaryKey = row.pk == 1;
91
- field.default = row.dflt_value;
92
- fieldTypes[row.name] = field
93
- });
94
- return fieldTypes;
95
- }
96
-
97
- getFieldValue(field: AdminForthResourceColumn, value: any): any {
98
- if (field.type == AdminForthDataTypes.DATETIME) {
99
- if (!value) {
100
- return null;
101
- }
102
- if (field._underlineType.startsWith('Int') || field._underlineType.startsWith('UInt')) {
103
- return dayjs.unix(+value).toISOString();
104
- } else if (field._underlineType.startsWith('DateTime')
105
- || field._underlineType.startsWith('String')
106
- || field._underlineType.startsWith('FixedString')) {
107
- const v = dayjs(value).toISOString();
108
- return v;
109
- } else {
110
- throw new Error(`AdminForth does not support row type: ${field._underlineType} for timestamps, use VARCHAR (with iso strings) or TIMESTAMP/INT (with unix timestamps). Issue in field "${field.name}"`);
111
- }
112
- } else if (field.type == AdminForthDataTypes.DATE) {
113
- if (!value) {
114
- return null;
115
- }
116
- return dayjs(value).toISOString().split('T')[0];
117
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
118
- return !!value;
119
- } else if (field.type == AdminForthDataTypes.JSON) {
120
- if (field._underlineType.startsWith('String') || field._underlineType.startsWith('FixedString')) {
121
- try {
122
- return JSON.parse(value);
123
- } catch (e) {
124
- return {'error': `Failed to parse JSON: ${e.message}`}
125
- }
126
- } else {
127
- console.error(`AdminForth: JSON field is not a string but ${field._underlineType}, this is not supported yet`);
128
- }
129
- }
130
- return value;
131
- }
132
-
133
- setFieldValue(field: AdminForthResourceColumn, value: any): any {
134
- if (field.type == AdminForthDataTypes.DATETIME) {
135
- if (!value) {
136
- return null;
137
- }
138
- if (field._underlineType.startsWith('Int') || field._underlineType.startsWith('UInt')) {
139
- // value is iso string now, convert to unix timestamp
140
- return dayjs(value).unix();
141
- } else if (field._underlineType.startsWith('DateTime')
142
- || field._underlineType.startsWith('String')
143
- || field._underlineType.startsWith('FixedString')) {
144
- // value is iso string now, convert to unix timestamp
145
- const iso = dayjs(value).toISOString();
146
- return iso;
147
- }
148
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
149
- return value ? 1 : 0;
150
- } else if (field.type == AdminForthDataTypes.JSON) {
151
- // check underline type is text or string
152
- if (field._underlineType.startsWith('String') || field._underlineType.startsWith('FixedString')) {
153
- return JSON.stringify(value);
154
- } else {
155
- console.error(`AdminForth: JSON field is not a string/text but ${field._underlineType}, this is not supported yet`);
156
- }
157
- }
158
-
159
- return value;
160
- }
161
-
162
- OperatorsMap = {
163
- [AdminForthFilterOperators.EQ]: '=',
164
- [AdminForthFilterOperators.NE]: '!=',
165
- [AdminForthFilterOperators.GT]: '>',
166
- [AdminForthFilterOperators.LT]: '<',
167
- [AdminForthFilterOperators.GTE]: '>=',
168
- [AdminForthFilterOperators.LTE]: '<=',
169
- [AdminForthFilterOperators.LIKE]: 'LIKE',
170
- [AdminForthFilterOperators.ILIKE]: 'ILIKE',
171
- [AdminForthFilterOperators.IN]: 'IN',
172
- [AdminForthFilterOperators.NIN]: 'NOT IN',
173
- };
174
-
175
- SortDirectionsMap = {
176
- [AdminForthSortDirections.asc]: 'ASC',
177
- [AdminForthSortDirections.desc]: 'DESC',
178
- };
179
-
180
- whereClause(
181
- resource: AdminForthResource,
182
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
183
- ): string {
184
- return filters.length ? `WHERE ${filters.map((f, i) => {
185
- const column = resource.dataSourceColumns.find((col) => col.name == f.field);
186
- let placeholder = `{f${i}:${column._underlineType}}`;
187
- let field = f.field;
188
- let operator = this.OperatorsMap[f.operator];
189
- if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
190
- placeholder = `(${f.value.map((_, j) => `{p${i}_${j}:${
191
- column._underlineType
192
- }}`).join(', ')})`;
193
- }
194
-
195
- return `${field} ${operator} ${placeholder}`
196
- }).join(' AND ')}` : '';
197
- }
198
-
199
- whereParams(
200
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
201
- ): any {
202
- const params = {};
203
- filters.length ? filters.forEach((f, i) => {
204
- // for arrays do set in map
205
- const v = f.value;
206
-
207
- if (f.operator == AdminForthFilterOperators.LIKE || f.operator == AdminForthFilterOperators.ILIKE) {
208
- params[`f${i}`] = `%${v}%`;
209
- } else if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
210
- v.forEach((_, j) => {
211
- params[`p${i}_${j}`] = v[j];
212
- });
213
- } else {
214
- params[`f${i}`] = v;
215
- }
216
- }) : [];
217
-
218
- return params;
219
- }
220
-
221
- async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }: {
222
- resource: AdminForthResource,
223
- limit: number,
224
- offset: number,
225
- sort: { field: string, direction: AdminForthSortDirections }[],
226
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[],
227
- }): Promise<any[]> {
228
- console.log('getDataWithOriginalTypes', resource, limit, offset, sort, filters);
229
- const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
230
- const tableName = resource.table;
231
-
232
- const where = this.whereClause(resource, filters);
233
-
234
- const params = this.whereParams(filters);
235
-
236
- const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `${s.field} ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
237
-
238
-
239
- const q = `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT {limit:Int} OFFSET {offset:Int}`;
240
- const d = {
241
- ...params,
242
- limit,
243
- offset,
244
- };
245
-
246
- const stmt = await this.client.query({
247
- query: q,
248
- format: 'JSONEachRow',
249
- query_params: d,
250
- });
251
-
252
- const rows = await stmt.json();
253
-
254
- return rows.map((row) => {
255
- const newRow = {};
256
- for (const [key, value] of Object.entries(row)) {
257
- newRow[key] = value;
258
- }
259
- return newRow;
260
- });
261
- }
262
-
263
- async getCount({
264
- resource,
265
- filters,
266
- }: {
267
- resource: AdminForthResource;
268
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[];
269
- }): Promise<number> {
270
- const tableName = resource.table;
271
- const where = this.whereClause(resource, filters);
272
- const d = this.whereParams(filters);
273
-
274
- const countQ = await this.client.query({
275
- query: `SELECT COUNT(*) as count FROM ${tableName} ${where}`,
276
- format: 'JSONEachRow',
277
- query_params: d,
278
- });
279
- const countResp = await countQ.json()
280
- return +countResp[0]['count'];
281
- }
282
-
283
- async getMinMaxForColumnsWithOriginalTypes({ resource, columns }: { resource: AdminForthResource, columns: AdminForthResourceColumn[] }): Promise<{ [key: string]: { min: any, max: any } }> {
284
- const tableName = resource.table;
285
- const result = {};
286
- await Promise.all(columns.map(async (col) => {
287
- const stmt = await this.client.query({
288
- query: `SELECT MIN(${col.name}) as min, MAX(${col.name}) as max FROM ${tableName}`,
289
- format: 'JSONEachRow',
290
- });
291
- const rows = await stmt.json();
292
- result[col.name] = {
293
- min: rows[0].min,
294
- max: rows[0].max,
295
- };
296
-
297
- }))
298
- return result;
299
- }
300
- async createRecordOriginalValues({ resource, record }: { resource: AdminForthResource, record: any }) {
301
- const tableName = resource.table;
302
- const columns = Object.keys(record);
303
- await this.client.insert({
304
- database: this.dbName,
305
- table: tableName,
306
- columns: columns,
307
- values: [Object.values(record)],
308
- });
309
- }
310
-
311
- async updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource, recordId: any, newValues: any }) {
312
- const columnsWithPlaceholders = Object.keys(newValues).map((col) => {
313
- return `${col} = {${col}:${resource.dataSourceColumns.find((c) => c.name == col)._underlineType}}`
314
- });
315
-
316
- await this.client.command(
317
- {
318
- query: `ALTER TABLE ${this.dbName}.${resource.table} UPDATE ${columnsWithPlaceholders.join(', ')} WHERE ${this.getPrimaryKey(resource)} = {recordId:${resource.dataSourceColumns.find((c) => c.primaryKey)._underlineType}}`,
319
- query_params: { ...newValues, recordId },
320
- }
321
- );
322
- }
323
-
324
- async deleteRecord({ resource, recordId }: { resource: AdminForthResource, recordId: any }): Promise<boolean> {
325
- const pkColumn = resource.dataSourceColumns.find((col) => col.primaryKey);
326
- const res = await this.client.command(
327
- {
328
- query: `ALTER TABLE ${this.dbName}.${resource.table} DELETE WHERE ${
329
- pkColumn.name
330
- } = {recordId:${pkColumn._underlineType}}`,
331
- query_params: { recordId },
332
- }
333
- );
334
- // todo test what is in res
335
- return res;
336
- }
337
-
338
- close() {
339
- this.client.disconnect();
340
- }
341
- }
342
-
343
- export default ClickhouseConnector;
@@ -1,202 +0,0 @@
1
- import dayjs from 'dayjs';
2
- import { MongoClient } from 'mongodb';
3
- import { AdminForthDataTypes, AdminForthFilterOperators, AdminForthSortDirections,
4
- IAdminForthDataSourceConnector, AdminForthResource } from '../types/AdminForthConfig.js';
5
- import AdminForthBaseConnector from './baseConnector.js';
6
-
7
- class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataSourceConnector {
8
- db: MongoClient
9
-
10
- constructor({ url }: { url: string }) {
11
- super();
12
- this.db = new MongoClient(url);
13
- (async () => {
14
- try {
15
- await this.db.connect();
16
- this.db.on('error', (err) => {
17
- console.log('Mongo error: ', err.message)
18
- });
19
- console.log('Connected to Mongo');
20
- } catch (e) {
21
- console.error('ERROR: Failed to connect to Mongo', e);
22
- }
23
- })();
24
- }
25
-
26
- OperatorsMap = {
27
- [AdminForthFilterOperators.EQ]: (value) => value,
28
- [AdminForthFilterOperators.NE]: (value) => ({ $ne: value }),
29
- [AdminForthFilterOperators.GT]: (value) => ({ $gt: value }),
30
- [AdminForthFilterOperators.LT]: (value) => ({ $lt: value }),
31
- [AdminForthFilterOperators.GTE]: (value) => ({ $gte: value }),
32
- [AdminForthFilterOperators.LTE]: (value) => ({ $lte: value }),
33
- [AdminForthFilterOperators.LIKE]: (value) => ({ $regex: value }),
34
- [AdminForthFilterOperators.ILIKE]: (value) => ({ $regex: value, $options: 'i' }),
35
- [AdminForthFilterOperators.IN]: (value) => ({ $in: value }),
36
- [AdminForthFilterOperators.NIN]: (value) => ({ $nin: value }),
37
- };
38
-
39
- SortDirectionsMap = {
40
- [AdminForthSortDirections.asc]: 1,
41
- [AdminForthSortDirections.desc]: -1,
42
- };
43
-
44
- async discoverFields(resource) {
45
- return resource.columns.filter((col) => !col.virtual).reduce((acc, col) => {
46
- if (!col.type) {
47
- throw new Error(`Type is not defined for column ${col.name} in resource ${resource.table}`);
48
- }
49
-
50
- acc[col.name] = {
51
- name: col.name,
52
- type: col.type,
53
- primaryKey: col.primaryKey,
54
- virtual: col.virtual,
55
- _underlineType: col._underlineType,
56
- };
57
- return acc;
58
- }, {});
59
- }
60
-
61
- getPrimaryKey(resource) {
62
- for (const col of resource.dataSourceColumns) {
63
- if (col.primaryKey) {
64
- return col.name;
65
- }
66
- }
67
- }
68
-
69
- getFieldValue(field, value) {
70
- if (field.type == AdminForthDataTypes.DATETIME) {
71
- if (!value) {
72
- return null;
73
- }
74
- return dayjs(Date.parse(value)).toISOString();
75
-
76
- } else if (field.type == AdminForthDataTypes.DATE) {
77
- if (!value) {
78
- return null;
79
- }
80
- return dayjs(Date.parse(value)).toISOString().split('T')[0];
81
-
82
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
83
- return !!value;
84
- } else if (field.type == AdminForthDataTypes.DECIMAL) {
85
- return value.toString();
86
- }
87
-
88
- return value;
89
- }
90
-
91
-
92
- setFieldValue(field, value) {
93
- if (field.type == AdminForthDataTypes.DATETIME) {
94
- if (!value) {
95
- return null;
96
- }
97
- if (field._underlineType == 'timestamp' || field._underlineType == 'int') {
98
- // value is iso string now, convert to unix timestamp
99
- return dayjs(value).unix();
100
- } else if (field._underlineType == 'varchar') {
101
- // value is iso string now, convert to unix timestamp
102
- return dayjs(value).toISOString();
103
- }
104
- } else if (field.type == AdminForthDataTypes.BOOLEAN) {
105
- return value ? 1 : 0;
106
- }
107
- return value;
108
- }
109
-
110
- async genQuery({ filters }) {
111
- const query = {};
112
- for (const filter of filters) {
113
- query[filter.field] = this.OperatorsMap[filter.operator](filter.value);
114
- }
115
- return query;
116
- }
117
-
118
- async getDataWithOriginalTypes({ resource, limit, offset, sort, filters }:
119
- {
120
- resource: AdminForthResource,
121
- limit: number,
122
- offset: number,
123
- sort: { field: string, direction: AdminForthSortDirections }[],
124
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
125
- }
126
- ): Promise<any[]> {
127
-
128
- // const columns = resource.dataSourceColumns.filter(c=> !c.virtual).map((col) => col.name).join(', ');
129
- const tableName = resource.table;
130
-
131
- const collection = this.db.db().collection(tableName);
132
- const query = await this.genQuery({ filters });
133
-
134
- const sortArray: any[] = sort.map((s) => {
135
- return [s.field, this.SortDirectionsMap[s.direction]];
136
- });
137
-
138
- const result = await collection.find(query)
139
- .sort(sortArray)
140
- .skip(offset)
141
- .limit(limit)
142
- .toArray();
143
-
144
- return result
145
- }
146
-
147
- async getCount({ resource, filters }: {
148
- resource: AdminForthResource,
149
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
150
- }): Promise<number> {
151
-
152
- const collection = this.db.db().collection(resource.table);
153
- const query = {};
154
- for (const filter of filters) {
155
- query[filter.field] = this.OperatorsMap[filter.operator](filter.value);
156
- }
157
- return await collection.countDocuments(query);
158
- }
159
-
160
- async getMinMaxForColumnsWithOriginalTypes({ resource, columns }) {
161
- const tableName = resource.table;
162
- const collection = this.db.db().collection(tableName);
163
- const result = {};
164
- for (const column of columns) {
165
- result[column] = await collection
166
- .aggregate([
167
- { $group: { _id: null, min: { $min: `$${column}` }, max: { $max: `$${column}` } } },
168
- ])
169
- .toArray();
170
- }
171
- return result;
172
- }
173
-
174
- async createRecordOriginalValues({ resource, record }) {
175
- const tableName = resource.table;
176
- const collection = this.db.db().collection(tableName);
177
- const columns = Object.keys(record);
178
- const newRecord = {};
179
- for (const colName of columns) {
180
- newRecord[colName] = record[colName];
181
- }
182
- await collection.insertOne(newRecord);
183
- }
184
-
185
- async updateRecordOriginalValues({ resource, recordId, newValues }) {
186
- const collection = this.db.db().collection(resource.table);
187
- await collection.updateOne({ [this.getPrimaryKey(resource)]: recordId }, { $set: newValues });
188
- }
189
-
190
- async deleteRecord({ resource, recordId }): Promise<boolean> {
191
- const primaryKey = this.getPrimaryKey(resource);
192
- const collection = this.db.db().collection(resource.table);
193
- const res = await collection.deleteOne({ [primaryKey]: recordId });
194
- return res.deletedCount > 0;
195
- }
196
-
197
- async close() {
198
- await this.db.close()
199
- }
200
- }
201
-
202
- export default MongoConnector;