adminforth 1.3.54-next.22 → 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 (125) hide show
  1. package/dist/auth.js +41 -56
  2. package/dist/auth.js.map +1 -1
  3. package/dist/dataConnectors/baseConnector.js +107 -128
  4. package/dist/dataConnectors/baseConnector.js.map +1 -1
  5. package/dist/dataConnectors/clickhouse.js +125 -148
  6. package/dist/dataConnectors/clickhouse.js.map +1 -1
  7. package/dist/dataConnectors/mongo.js +74 -101
  8. package/dist/dataConnectors/mongo.js.map +1 -1
  9. package/dist/dataConnectors/postgres.js +117 -142
  10. package/dist/dataConnectors/postgres.js.map +1 -1
  11. package/dist/dataConnectors/sqlite.js +106 -129
  12. package/dist/dataConnectors/sqlite.js.map +1 -1
  13. package/dist/index.js +196 -217
  14. package/dist/index.js.map +1 -1
  15. package/dist/modules/codeInjector.js +470 -495
  16. package/dist/modules/codeInjector.js.map +1 -1
  17. package/dist/modules/configValidator.js +13 -22
  18. package/dist/modules/configValidator.js.map +1 -1
  19. package/dist/modules/operationalResource.js +49 -70
  20. package/dist/modules/operationalResource.js.map +1 -1
  21. package/dist/modules/restApi.js +103 -116
  22. package/dist/modules/restApi.js.map +1 -1
  23. package/dist/plugins/audit-log/types.js +2 -0
  24. package/dist/plugins/audit-log/types.js.map +1 -0
  25. package/dist/plugins/chat-gpt/types.js +2 -0
  26. package/dist/plugins/chat-gpt/types.js.map +1 -0
  27. package/dist/plugins/email-password-reset/types.js +2 -0
  28. package/dist/plugins/email-password-reset/types.js.map +1 -0
  29. package/dist/plugins/foreign-inline-list/types.js +2 -0
  30. package/dist/plugins/foreign-inline-list/types.js.map +1 -0
  31. package/dist/plugins/import-export/types.js +2 -0
  32. package/dist/plugins/import-export/types.js.map +1 -0
  33. package/dist/plugins/rich-editor/custom/async-queue.js +29 -0
  34. package/dist/plugins/rich-editor/custom/async-queue.js.map +1 -0
  35. package/dist/plugins/rich-editor/dist/async-queue.js +41 -0
  36. package/dist/plugins/rich-editor/dist/custom/async-queue.js +29 -0
  37. package/dist/plugins/rich-editor/dist/custom/async-queue.js.map +1 -0
  38. package/dist/plugins/rich-editor/types.js +16 -0
  39. package/dist/plugins/rich-editor/types.js.map +1 -0
  40. package/dist/plugins/two-factors-auth/types.js +2 -0
  41. package/dist/plugins/two-factors-auth/types.js.map +1 -0
  42. package/dist/plugins/upload/types.js +2 -0
  43. package/dist/plugins/upload/types.js.map +1 -0
  44. package/dist/servers/express.js +29 -42
  45. package/dist/servers/express.js.map +1 -1
  46. package/package.json +4 -1
  47. package/auth.ts +0 -140
  48. package/basePlugin.ts +0 -70
  49. package/dataConnectors/baseConnector.ts +0 -222
  50. package/dataConnectors/clickhouse.ts +0 -343
  51. package/dataConnectors/mongo.ts +0 -202
  52. package/dataConnectors/postgres.ts +0 -310
  53. package/dataConnectors/sqlite.ts +0 -258
  54. package/index.ts +0 -428
  55. package/modules/codeInjector.ts +0 -747
  56. package/modules/configValidator.ts +0 -588
  57. package/modules/operationalResource.ts +0 -98
  58. package/modules/restApi.ts +0 -718
  59. package/modules/styleGenerator.ts +0 -55
  60. package/modules/styles.ts +0 -126
  61. package/modules/utils.ts +0 -472
  62. package/servers/express.ts +0 -259
  63. package/spa/.eslintrc.cjs +0 -14
  64. package/spa/README.md +0 -39
  65. package/spa/env.d.ts +0 -1
  66. package/spa/index.html +0 -23
  67. package/spa/package-lock.json +0 -4659
  68. package/spa/package.json +0 -52
  69. package/spa/postcss.config.js +0 -6
  70. package/spa/public/assets/favicon.png +0 -0
  71. package/spa/src/App.vue +0 -418
  72. package/spa/src/assets/base.css +0 -2
  73. package/spa/src/assets/logo.svg +0 -19
  74. package/spa/src/components/AcceptModal.vue +0 -45
  75. package/spa/src/components/Breadcrumbs.vue +0 -41
  76. package/spa/src/components/BreadcrumbsWithButtons.vue +0 -26
  77. package/spa/src/components/CustomDatePicker.vue +0 -176
  78. package/spa/src/components/CustomDateRangePicker.vue +0 -218
  79. package/spa/src/components/CustomRangePicker.vue +0 -156
  80. package/spa/src/components/Dropdown.vue +0 -168
  81. package/spa/src/components/Filters.vue +0 -222
  82. package/spa/src/components/HelloWorld.vue +0 -17
  83. package/spa/src/components/MenuLink.vue +0 -27
  84. package/spa/src/components/ResourceForm.vue +0 -325
  85. package/spa/src/components/ResourceListTable.vue +0 -466
  86. package/spa/src/components/SingleSkeletLoader.vue +0 -13
  87. package/spa/src/components/SkeleteLoader.vue +0 -23
  88. package/spa/src/components/ThreeDotsMenu.vue +0 -43
  89. package/spa/src/components/Toast.vue +0 -78
  90. package/spa/src/components/ValueRenderer.vue +0 -141
  91. package/spa/src/components/icons/IconCalendar.vue +0 -5
  92. package/spa/src/components/icons/IconCommunity.vue +0 -7
  93. package/spa/src/components/icons/IconDocumentation.vue +0 -7
  94. package/spa/src/components/icons/IconEcosystem.vue +0 -7
  95. package/spa/src/components/icons/IconSupport.vue +0 -7
  96. package/spa/src/components/icons/IconTime.vue +0 -5
  97. package/spa/src/components/icons/IconTooling.vue +0 -19
  98. package/spa/src/composables/useFrontendApi.ts +0 -26
  99. package/spa/src/composables/useStores.ts +0 -131
  100. package/spa/src/index.scss +0 -31
  101. package/spa/src/main.ts +0 -18
  102. package/spa/src/renderers/CompactUUID.vue +0 -48
  103. package/spa/src/renderers/CountryFlag.vue +0 -69
  104. package/spa/src/router/index.ts +0 -59
  105. package/spa/src/spa_types/core.ts +0 -53
  106. package/spa/src/stores/core.ts +0 -148
  107. package/spa/src/stores/filters.ts +0 -27
  108. package/spa/src/stores/modal.ts +0 -48
  109. package/spa/src/stores/toast.ts +0 -31
  110. package/spa/src/stores/user.ts +0 -72
  111. package/spa/src/utils.ts +0 -160
  112. package/spa/src/views/CreateView.vue +0 -167
  113. package/spa/src/views/EditView.vue +0 -170
  114. package/spa/src/views/ListView.vue +0 -352
  115. package/spa/src/views/LoginView.vue +0 -192
  116. package/spa/src/views/ResourceParent.vue +0 -17
  117. package/spa/src/views/ShowView.vue +0 -194
  118. package/spa/tailwind.config.js +0 -17
  119. package/spa/tsconfig.app.json +0 -14
  120. package/spa/tsconfig.json +0 -11
  121. package/spa/tsconfig.node.json +0 -19
  122. package/spa/vite.config.ts +0 -56
  123. package/tsconfig.json +0 -112
  124. package/types/AdminForthConfig.ts +0 -1762
  125. package/types/FrontendAPI.ts +0 -143
package/auth.ts DELETED
@@ -1,140 +0,0 @@
1
-
2
- import jwt from 'jsonwebtoken';
3
- import crypto from 'crypto';
4
- import AdminForth from './index.js';
5
-
6
- // Function to generate a password hash using PBKDF2
7
- function calcPasswordHash(password, salt, iterations = 100000, keyLength = 64, digest = 'sha512') {
8
- return new Promise((resolve, reject) => {
9
- crypto.pbkdf2(password, salt, iterations, keyLength, digest, (err, derivedKey) => {
10
- if (err) reject(err);
11
- resolve(derivedKey.toString('hex'));
12
- });
13
- });
14
- }
15
-
16
- // Function to generate a random salt
17
- function generateSalt(length = 16) {
18
- return crypto.randomBytes(length).toString('hex');
19
- }
20
-
21
- function parseTimeToSeconds(time: string): number {
22
- const unit = time.slice(-1);
23
- const value = parseInt(time.slice(0, -1), 10);
24
- switch (unit) {
25
- case 's':
26
- return value;
27
- case 'm':
28
- return value * 60;
29
- case 'h':
30
- return value * 60 * 60;
31
- case 'd':
32
- return value * 60 * 60 * 24;
33
- default:
34
- throw new Error(`Invalid time unit: ${unit}`);
35
- }
36
- }
37
-
38
- class AdminForthAuth {
39
- adminforth: AdminForth;
40
-
41
- constructor(adminforth) {
42
- this.adminforth = adminforth;
43
- }
44
-
45
- removeAuthCookie(response) {
46
- response.setHeader('Set-Cookie', `adminforth_jwt=; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:00 GMT`);
47
- }
48
-
49
- setAuthCookie({ expireInDays, response, username, pk}: {
50
- expireInDays?: number,
51
- response: any,
52
- username: string,
53
- pk: string | null
54
- }) {
55
- const expiresIn: string = expireInDays ? `${expireInDays}d` : (process.env.ADMINFORTH_AUTH_EXPIRESIN || '24h');
56
- // might be h,m,d in string
57
- const expiresInSec = parseTimeToSeconds(expiresIn);
58
-
59
- const token = this.issueJWT({ username, pk}, 'auth', expiresIn);
60
- const expiresCookieFormat = new Date(Date.now() + expiresInSec * 1000).toUTCString();
61
-
62
- response.setHeader('Set-Cookie', `adminforth_jwt=${token}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${expiresCookieFormat}`);
63
- }
64
-
65
- removeCustomCookie({response, name}) {
66
- response.setHeader('Set-Cookie', `adminforth_${name}=; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=Thu, 01 Jan 1970 00:00:00 GMT`);
67
- }
68
-
69
- setCustomCookie({ response, payload }: {
70
- response: any, payload: {name: string, value: string, expiry: number, httpOnly: boolean}
71
- }) {
72
- const {name,value,expiry,httpOnly} = payload
73
- response.setHeader('Set-Cookie', `adminforth_${name}=${value}; Path=${this.adminforth.config.baseUrl || '/'}; HttpOnly; SameSite=Strict; Expires=${new Date(Date.now() + expiry).toUTCString() } `);
74
- }
75
-
76
- issueJWT(payload: Object, type: string, expiresIn: string = '24h'): string {
77
- // read ADMINFORH_SECRET from environment if not drop error
78
- const secret = process.env.ADMINFORTH_SECRET;
79
- if (!secret) {
80
- throw new Error('ADMINFORTH_SECRET environment not set');
81
- }
82
-
83
- // issue JWT token
84
- return jwt.sign({...payload, t: type}, secret, { expiresIn });
85
- }
86
-
87
- async verify(jwtToken: string, mustHaveType: string, decodeUser: boolean | undefined = true): Promise<Object> {
88
- // read ADMINFORH_SECRET from environment if not drop error
89
- const secret = process.env.ADMINFORTH_SECRET;
90
- if (!secret) {
91
- throw new Error('ADMINFORTH_SECRET environment not set');
92
- }
93
- let decoded;
94
- try {
95
- // verify JWT token
96
- decoded = jwt.verify(jwtToken, secret);
97
- } catch (err) {
98
- if (err.name === 'TokenExpiredError') {
99
- console.error('Token expired:', err.message);
100
- } else if (err.name === 'JsonWebTokenError') {
101
- console.error('Token error:', err.message);
102
- } else {
103
- console.error('Failed to verify JWT token', err);
104
- }
105
- return null;
106
- }
107
- const { pk, t } = decoded;
108
- if (t !== mustHaveType) {
109
- console.error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`);
110
- return null;
111
- }
112
- if (decodeUser !== false) {
113
- const dbUser = await this.adminforth.getUserByPk(pk);
114
- if (!dbUser) {
115
- console.error(`User with pk ${pk} not found in database`);
116
- // will logout user which was deleted
117
- return null;
118
- }
119
- decoded.dbUser = dbUser;
120
- }
121
-
122
- return decoded;
123
- }
124
-
125
- static async generatePasswordHash(password) {
126
- const salt = generateSalt();
127
- const hashedPassword = await calcPasswordHash(password, salt);
128
- return `${salt}:${hashedPassword}`;
129
- }
130
-
131
- static async verifyPassword(password, hashedPassword) {
132
- const [salt, hash] = hashedPassword.split(':');
133
- const newHash = await calcPasswordHash(password, salt);
134
- return newHash === hash;
135
- }
136
-
137
-
138
- }
139
-
140
- export default AdminForthAuth;
package/basePlugin.ts DELETED
@@ -1,70 +0,0 @@
1
- import { AdminForthResource, IAdminForthPlugin, IAdminForth } from './types/AdminForthConfig.js';
2
- import { getComponentNameFromPath } from './modules/utils.js';
3
- import { currentFileDir } from './modules/utils.js';
4
- import path from 'path';
5
- import fs from 'fs';
6
-
7
- import crypto from 'crypto';
8
-
9
-
10
- export default class AdminForthPlugin implements IAdminForthPlugin {
11
-
12
- adminforth: IAdminForth;
13
- pluginDir: string;
14
- customFolderName: string = 'custom';
15
- pluginInstanceId: string;
16
- customFolderPath: string;
17
- pluginOptions: any;
18
- resourceConfig: AdminForthResource;
19
- className: string;
20
- activationOrder: number = 0;
21
-
22
- constructor(pluginOptions: any, metaUrl: string) {
23
- // set up plugin here
24
- this.pluginDir = currentFileDir(metaUrl);
25
- this.customFolderPath = path.join(this.pluginDir, this.customFolderName);
26
- this.pluginOptions = pluginOptions;
27
- console.log(`🪲 🪲 🪲 🪲 🪲 🪲 AdminForthPlugin.constructor`, this.constructor.name);
28
- this.className = this.constructor.name;
29
- }
30
-
31
- setupEndpoints(server: any) {
32
-
33
- }
34
-
35
- instanceUniqueRepresentation(pluginOptions: any) : string {
36
- return 'non-uniquely-identified';
37
- }
38
-
39
- modifyResourceConfig(adminforth: IAdminForth, resourceConfig: AdminForthResource) {
40
- this.resourceConfig = resourceConfig;
41
- const uniqueness = this.instanceUniqueRepresentation(this.pluginOptions);
42
-
43
- const seed = `af_pl_${this.constructor.name}_${resourceConfig.resourceId}_${uniqueness}`;
44
- this.pluginInstanceId = crypto.createHash('sha256').update(
45
- seed
46
- ).digest('hex')
47
- process.env.HEAVY_DEBUG && console.log(`🪲 AdminForthPlugin.modifyResourceConfig`, seed, 'id', this.pluginInstanceId);
48
- this.adminforth = adminforth;
49
- }
50
-
51
- componentPath(componentFile: string) {
52
- const key = `@@/plugins/${this.constructor.name}/${componentFile}`;
53
- const componentName = getComponentNameFromPath(key);
54
-
55
- if (!this.adminforth.codeInjector.srcFoldersToSync[this.customFolderPath]) {
56
- this.adminforth.codeInjector.srcFoldersToSync[this.customFolderPath] = `./plugins/${this.constructor.name}/`;
57
- }
58
-
59
- if (!this.adminforth.codeInjector.allComponentNames[key]) {
60
- const absSrcPath = path.join(this.customFolderPath, componentFile);
61
- if (!fs.existsSync(absSrcPath)) {
62
- throw new Error(`Plugin "${this.constructor.name}" tried to use file as component which does not exist at "${absSrcPath}"`);
63
- }
64
- this.adminforth.codeInjector.allComponentNames[key] = componentName;
65
- }
66
-
67
- return key;
68
- }
69
-
70
- }
@@ -1,222 +0,0 @@
1
- import { get } from "http";
2
- import { AdminForthResource, IAdminForthDataSourceConnectorBase, AdminForthSortDirections, AdminForthFilterOperators, AdminForthResourceColumn, IAdminForthSort, IAdminForthFilter } from "../types/AdminForthConfig.js";
3
- import { suggestIfTypo } from "../modules/utils.js";
4
-
5
-
6
- export default class AdminForthBaseConnector implements IAdminForthDataSourceConnectorBase {
7
- getPrimaryKey(resource: AdminForthResource): string {
8
- for (const col of resource.dataSourceColumns) {
9
- if (col.primaryKey) {
10
- return col.name;
11
- }
12
- }
13
- }
14
-
15
- async getRecordByPrimaryKeyWithOriginalTypes(resource: AdminForthResource, id: string): Promise<any> {
16
- const data = await this.getDataWithOriginalTypes({
17
- resource,
18
- limit: 1,
19
- offset: 0,
20
- sort: [],
21
- filters: [{ field: this.getPrimaryKey(resource), operator: AdminForthFilterOperators.EQ, value: id }],
22
- });
23
- return data.length > 0 ? data[0] : null;
24
- }
25
-
26
- getDataWithOriginalTypes({ resource, limit, offset, sort, filters }: {
27
- resource: AdminForthResource,
28
- limit: number,
29
- offset: number,
30
- sort: IAdminForthSort[],
31
- filters: IAdminForthFilter[],
32
- }): Promise<any[]> {
33
- throw new Error('Method not implemented.');
34
- }
35
-
36
- getCount({ resource, filters }: { resource: AdminForthResource; filters: { field: string; operator: AdminForthFilterOperators; value: any; }[]; }): Promise<number> {
37
- throw new Error('Method not implemented.');
38
- }
39
-
40
- discoverFields(resource: AdminForthResource): Promise<{ [key: string]: AdminForthResourceColumn; }> {
41
- throw new Error('Method not implemented.');
42
- }
43
-
44
- getFieldValue(field: AdminForthResourceColumn, value: any) {
45
- throw new Error('Method not implemented.');
46
- }
47
-
48
- setFieldValue(field: AdminForthResourceColumn, value: any) {
49
- throw new Error('Method not implemented.');
50
- }
51
-
52
- getMinMaxForColumnsWithOriginalTypes({ resource, columns }: { resource: AdminForthResource; columns: AdminForthResourceColumn[]; }): Promise<{ [key: string]: { min: any; max: any; }; }> {
53
- throw new Error('Method not implemented.');
54
- }
55
-
56
- createRecordOriginalValues({ resource, record }: { resource: AdminForthResource; record: any; }): Promise<void> {
57
- throw new Error('Method not implemented.');
58
- }
59
-
60
- async checkUnique(resource: AdminForthResource, column: AdminForthResourceColumn, value: any) {
61
- process.env.HEAVY_DEBUG && console.log('☝️🪲🪲🪲🪲 checkUnique|||', column, value);
62
- const existingRecord = await this.getData({
63
- resource,
64
- filters: [{ field: column.name, operator: AdminForthFilterOperators.EQ, value }],
65
- limit: 1,
66
- sort: [],
67
- offset: 0,
68
- getTotals: false
69
- });
70
-
71
- return existingRecord.data.length > 0;
72
- }
73
-
74
- async createRecord({ resource, record, adminUser }: {
75
- resource: AdminForthResource; record: any; adminUser: any;
76
- }): Promise<{ error?: string; ok: boolean; createdRecord?: any; }> {
77
- // transform value using setFieldValue and call createRecordOriginalValues
78
- const filledRecord = {...record};
79
- const recordWithOriginalValues = {...record};
80
-
81
- for (const col of resource.dataSourceColumns) {
82
- if (col.fillOnCreate) {
83
- if (filledRecord[col.name] === undefined) {
84
- filledRecord[col.name] = col.fillOnCreate({
85
- initialRecord: record,
86
- adminUser
87
- });
88
- }
89
- }
90
- recordWithOriginalValues[col.name] = this.setFieldValue(col, filledRecord[col.name]);
91
- }
92
-
93
- let error: string | null = null;
94
- await Promise.all(
95
- resource.dataSourceColumns.map(async (col) => {
96
- if (col.isUnique && !col.virtual && !error) {
97
- const exists = await this.checkUnique(resource, col, recordWithOriginalValues[col.name]);
98
- if (exists) {
99
- error = `Record with ${col.name} ${recordWithOriginalValues[col.name]} already exists`;
100
- }
101
- }
102
- })
103
- );
104
- if (error) {
105
- process.env.HEAVY_DEBUG && console.log('🪲🆕 check unique error', error);
106
- return { error, ok: false };
107
- }
108
-
109
- process.env.HEAVY_DEBUG && console.log('🪲🆕 creating record', recordWithOriginalValues);
110
- await this.createRecordOriginalValues({ resource, record: recordWithOriginalValues });
111
-
112
- return {
113
- ok: true,
114
- createdRecord: recordWithOriginalValues,
115
- }
116
- }
117
-
118
- updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource; recordId: string; newValues: any; }): Promise<void> {
119
- throw new Error('Method not implemented.');
120
- }
121
-
122
- async updateRecord({ resource, recordId, newValues }: { resource: AdminForthResource; recordId: string; newValues: any; }): Promise<{ error?: string; ok: boolean; }> {
123
- // transform value using setFieldValue and call updateRecordOriginalValues
124
- const recordWithOriginalValues = {...newValues};
125
-
126
- for (const field of Object.keys(newValues)) {
127
- const col = resource.dataSourceColumns.find((col) => col.name == field);
128
- // todo instead of throwing error, we can just not use setFieldValue here, and pass original value to updateRecordOriginalValues
129
- // we might consider this because some users might not want to define all columns in resource with showIn:[], but still want to use them in hooks
130
- if (!col) {
131
- const similar = suggestIfTypo(resource.dataSourceColumns.map((col) => col.name), field);
132
- throw new Error(`
133
- Update record received field '${field}' (with value ${newValues[field]}), but such column not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}
134
- `);
135
- }
136
- recordWithOriginalValues[col.name] = this.setFieldValue(col, newValues[col.name]);
137
- }
138
-
139
- process.env.HEAVY_DEBUG && console.log(`🪲✏️ updating record id:${recordId}, values: ${JSON.stringify(recordWithOriginalValues)}`);
140
-
141
- await this.updateRecordOriginalValues({ resource, recordId, newValues: recordWithOriginalValues });
142
-
143
- return { ok: true };
144
- }
145
-
146
- deleteRecord({ resource, recordId }: { resource: AdminForthResource; recordId: string; }): Promise<boolean> {
147
- throw new Error('Method not implemented.');
148
- }
149
-
150
-
151
- async getData({ resource, limit, offset, sort, filters, getTotals }: {
152
- resource: AdminForthResource,
153
- limit: number,
154
- offset: number,
155
- sort: { field: string, direction: AdminForthSortDirections }[],
156
- filters: { field: string, operator: AdminForthFilterOperators, value: any }[],
157
- getTotals: boolean,
158
- }): Promise<{ data: any[], total: number }> {
159
- if (filters) {
160
- filters.map((f) => {
161
- if (!f.field) {
162
- throw new Error(`Field "field" not specified in filter object: ${JSON.stringify(f)}`);
163
- }
164
- if (!f.operator) {
165
- throw new Error(`Field "operator" not specified in filter object: ${JSON.stringify(f)}`);
166
- }
167
- const fieldObj = resource.dataSourceColumns.find((col) => col.name == f.field);
168
- if (!fieldObj) {
169
- const similar = suggestIfTypo(resource.dataSourceColumns.map((col) => col.name), f.field);
170
- throw new Error(`Field '${f.field}' not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}`);
171
- }
172
- if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
173
- f.value = f.value.map((val) => this.setFieldValue(fieldObj, val));
174
- } else {
175
- f.value = this.setFieldValue(fieldObj, f.value);
176
- }
177
- });
178
- }
179
-
180
- const promises: Promise<any>[] = [this.getDataWithOriginalTypes({ resource, limit, offset, sort, filters })];
181
- if (getTotals) {
182
- promises.push(this.getCount({ resource, filters }));
183
- } else {
184
- promises.push(Promise.resolve(undefined));
185
- }
186
-
187
- const [data, total] = await Promise.all(promises);
188
-
189
- // call getFieldValue for each field
190
- data.map((record) => {
191
- for (const col of resource.dataSourceColumns) {
192
- record[col.name] = this.getFieldValue(col, record[col.name]);
193
- }
194
- });
195
-
196
- return { data, total };
197
- }
198
-
199
- async getMinMaxForColumns({ resource, columns }: { resource: AdminForthResource; columns: AdminForthResourceColumn[]; }): Promise<{ [key: string]: { min: any; max: any; }; }> {
200
- const mm = await this.getMinMaxForColumnsWithOriginalTypes({ resource, columns });
201
- const result = {};
202
- for (const col of columns) {
203
- result[col.name] = {
204
- min: this.getFieldValue(col, mm[col.name].min),
205
- max: this.getFieldValue(col, mm[col.name].max),
206
- };
207
- }
208
- return result;
209
- }
210
-
211
- getRecordByPrimaryKey(resource: AdminForthResource, recordId: string): Promise<any> {
212
- return this.getRecordByPrimaryKeyWithOriginalTypes(resource, recordId).then((record) => {
213
- const newRecord = {};
214
- for (const col of resource.dataSourceColumns) {
215
- newRecord[col.name] = this.getFieldValue(col, record[col.name]);
216
- }
217
- return newRecord;
218
- });
219
- }
220
-
221
-
222
- }