adminforth 1.2.99 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/auth.ts +6 -5
- package/dataConnectors/baseConnector.ts +20 -3
- package/dataConnectors/clickhouse.ts +1 -0
- package/dist/auth.js +6 -6
- package/dist/dataConnectors/baseConnector.js +16 -3
- package/dist/dataConnectors/clickhouse.js +1 -0
- package/dist/index.js +34 -16
- package/dist/modules/configValidator.js +10 -14
- package/dist/modules/operationalResource.js +6 -22
- package/dist/modules/restApi.js +75 -90
- package/dist/modules/utils.js +16 -0
- package/index.ts +37 -17
- package/modules/configValidator.ts +11 -16
- package/modules/operationalResource.ts +14 -38
- package/modules/restApi.ts +59 -72
- package/modules/utils.ts +20 -0
- package/package.json +2 -1
- package/types/AdminForthConfig.ts +27 -29
package/auth.ts
CHANGED
|
@@ -88,12 +88,13 @@ class AdminForthAuth {
|
|
|
88
88
|
console.error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`);
|
|
89
89
|
return null;
|
|
90
90
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
91
|
+
const dbUser = await this.adminforth.getUserByPk(pk);
|
|
92
|
+
if (!dbUser) {
|
|
93
|
+
console.error(`User with pk ${pk} not found in database`);
|
|
94
|
+
// will logout user which was deleted
|
|
95
|
+
return null;
|
|
96
96
|
}
|
|
97
|
+
decoded.dbUser = dbUser;
|
|
97
98
|
return decoded;
|
|
98
99
|
}
|
|
99
100
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { get } from "http";
|
|
2
2
|
import { AdminForthResource, IAdminForthDataSourceConnectorBase, AdminForthSortDirections, AdminForthFilterOperators, AdminForthResourceColumn, IAdminForthSort, IAdminForthFilter } from "../types/AdminForthConfig.js";
|
|
3
|
+
import { suggestIfTypo } from "../modules/utils.js";
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
export default class AdminForthBaseConnector implements IAdminForthDataSourceConnectorBase {
|
|
@@ -56,10 +57,21 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
|
|
|
56
57
|
throw new Error('Method not implemented.');
|
|
57
58
|
}
|
|
58
59
|
|
|
59
|
-
createRecord({ resource, record }: {
|
|
60
|
+
createRecord({ resource, record, adminUser }: {
|
|
61
|
+
resource: AdminForthResource; record: any; adminUser: any;
|
|
62
|
+
}): Promise<void> {
|
|
60
63
|
// transform value using setFieldValue and call createRecordOriginalValues
|
|
61
64
|
const newRecord = {...record};
|
|
65
|
+
|
|
62
66
|
for (const col of resource.dataSourceColumns) {
|
|
67
|
+
if (col.fillOnCreate) {
|
|
68
|
+
if (record[col.name] === undefined) {
|
|
69
|
+
record[col.name] = col.fillOnCreate({
|
|
70
|
+
initialRecord: record, adminUser
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
63
75
|
newRecord[col.name] = this.setFieldValue(col, record[col.name]);
|
|
64
76
|
}
|
|
65
77
|
process.env.HEAVY_DEBUG && console.log('🪲🪲🪲🪲 creating record', newRecord);
|
|
@@ -85,10 +97,15 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
|
|
|
85
97
|
}): Promise<{ data: any[], total: number }> {
|
|
86
98
|
if (filters) {
|
|
87
99
|
filters.map((f) => {
|
|
100
|
+
const fieldObj = resource.dataSourceColumns.find((col) => col.name == f.field);
|
|
101
|
+
if (!fieldObj) {
|
|
102
|
+
const similar = suggestIfTypo(resource.dataSourceColumns.map((col) => col.name), f.field);
|
|
103
|
+
throw new Error(`Field '${f.field}' not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}`);
|
|
104
|
+
}
|
|
88
105
|
if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
|
|
89
|
-
f.value = f.value.map((val) => this.setFieldValue(
|
|
106
|
+
f.value = f.value.map((val) => this.setFieldValue(fieldObj, val));
|
|
90
107
|
} else {
|
|
91
|
-
f.value = this.setFieldValue(
|
|
108
|
+
f.value = this.setFieldValue(fieldObj, f.value);
|
|
92
109
|
}
|
|
93
110
|
});
|
|
94
111
|
}
|
|
@@ -220,6 +220,7 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
|
|
|
220
220
|
sort: { field: string, direction: AdminForthSortDirections }[],
|
|
221
221
|
filters: { field: string, operator: AdminForthFilterOperators, value: any }[],
|
|
222
222
|
}): Promise<any[]> {
|
|
223
|
+
console.log('getDataWithOriginalTypes', resource, limit, offset, sort, filters);
|
|
223
224
|
const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
|
|
224
225
|
const tableName = resource.table;
|
|
225
226
|
|
package/dist/auth.js
CHANGED
|
@@ -80,13 +80,13 @@ class AdminForthAuth {
|
|
|
80
80
|
console.error(`Invalid token type during verification: ${t}, must be ${mustHaveType}`);
|
|
81
81
|
return null;
|
|
82
82
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
decoded.dbUser = dbUser;
|
|
83
|
+
const dbUser = yield this.adminforth.getUserByPk(pk);
|
|
84
|
+
if (!dbUser) {
|
|
85
|
+
console.error(`User with pk ${pk} not found in database`);
|
|
86
|
+
// will logout user which was deleted
|
|
87
|
+
return null;
|
|
89
88
|
}
|
|
89
|
+
decoded.dbUser = dbUser;
|
|
90
90
|
return decoded;
|
|
91
91
|
});
|
|
92
92
|
}
|
|
@@ -8,6 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { AdminForthFilterOperators } from "../types/AdminForthConfig.js";
|
|
11
|
+
import { suggestIfTypo } from "../modules/utils.js";
|
|
11
12
|
export default class AdminForthBaseConnector {
|
|
12
13
|
getPrimaryKey(resource) {
|
|
13
14
|
for (const col of resource.dataSourceColumns) {
|
|
@@ -49,10 +50,17 @@ export default class AdminForthBaseConnector {
|
|
|
49
50
|
createRecordOriginalValues({ resource, record }) {
|
|
50
51
|
throw new Error('Method not implemented.');
|
|
51
52
|
}
|
|
52
|
-
createRecord({ resource, record }) {
|
|
53
|
+
createRecord({ resource, record, adminUser }) {
|
|
53
54
|
// transform value using setFieldValue and call createRecordOriginalValues
|
|
54
55
|
const newRecord = Object.assign({}, record);
|
|
55
56
|
for (const col of resource.dataSourceColumns) {
|
|
57
|
+
if (col.fillOnCreate) {
|
|
58
|
+
if (record[col.name] === undefined) {
|
|
59
|
+
record[col.name] = col.fillOnCreate({
|
|
60
|
+
initialRecord: record, adminUser
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
56
64
|
newRecord[col.name] = this.setFieldValue(col, record[col.name]);
|
|
57
65
|
}
|
|
58
66
|
process.env.HEAVY_DEBUG && console.log('🪲🪲🪲🪲 creating record', newRecord);
|
|
@@ -68,11 +76,16 @@ export default class AdminForthBaseConnector {
|
|
|
68
76
|
return __awaiter(this, arguments, void 0, function* ({ resource, limit, offset, sort, filters, getTotals }) {
|
|
69
77
|
if (filters) {
|
|
70
78
|
filters.map((f) => {
|
|
79
|
+
const fieldObj = resource.dataSourceColumns.find((col) => col.name == f.field);
|
|
80
|
+
if (!fieldObj) {
|
|
81
|
+
const similar = suggestIfTypo(resource.dataSourceColumns.map((col) => col.name), f.field);
|
|
82
|
+
throw new Error(`Field '${f.field}' not found in resource '${resource.resourceId}'. ${similar ? `Did you mean '${similar}'?` : ''}`);
|
|
83
|
+
}
|
|
71
84
|
if (f.operator == AdminForthFilterOperators.IN || f.operator == AdminForthFilterOperators.NIN) {
|
|
72
|
-
f.value = f.value.map((val) => this.setFieldValue(
|
|
85
|
+
f.value = f.value.map((val) => this.setFieldValue(fieldObj, val));
|
|
73
86
|
}
|
|
74
87
|
else {
|
|
75
|
-
f.value = this.setFieldValue(
|
|
88
|
+
f.value = this.setFieldValue(fieldObj, f.value);
|
|
76
89
|
}
|
|
77
90
|
});
|
|
78
91
|
}
|
|
@@ -217,6 +217,7 @@ class ClickhouseConnector extends AdminForthBaseConnector {
|
|
|
217
217
|
}
|
|
218
218
|
getDataWithOriginalTypes(_a) {
|
|
219
219
|
return __awaiter(this, arguments, void 0, function* ({ resource, limit, offset, sort, filters }) {
|
|
220
|
+
console.log('getDataWithOriginalTypes', resource, limit, offset, sort, filters);
|
|
220
221
|
const columns = resource.dataSourceColumns.map((col) => col.name).join(', ');
|
|
221
222
|
const tableName = resource.table;
|
|
222
223
|
const where = this.whereClause(resource, filters);
|
package/dist/index.js
CHANGED
|
@@ -19,16 +19,18 @@ import PostgresConnector from './dataConnectors/postgres.js';
|
|
|
19
19
|
import SQLiteConnector from './dataConnectors/sqlite.js';
|
|
20
20
|
import CodeInjector from './modules/codeInjector.js';
|
|
21
21
|
import ExpressServer from './servers/express.js';
|
|
22
|
-
import { ADMINFORTH_VERSION, listify } from './modules/utils.js';
|
|
22
|
+
import { ADMINFORTH_VERSION, listify, suggestIfTypo } from './modules/utils.js';
|
|
23
23
|
import { AdminForthFilterOperators, AdminForthDataTypes, AdminForthResourcePages, } from './types/AdminForthConfig.js';
|
|
24
24
|
import AdminForthPlugin from './basePlugin.js';
|
|
25
25
|
import ConfigValidator from './modules/configValidator.js';
|
|
26
26
|
import AdminForthRestAPI, { interpretResource } from './modules/restApi.js';
|
|
27
27
|
import ClickhouseConnector from './dataConnectors/clickhouse.js';
|
|
28
|
+
import OperationalResource from './modules/operationalResource.js';
|
|
28
29
|
// exports
|
|
29
30
|
export * from './types/AdminForthConfig.js';
|
|
30
31
|
export { interpretResource };
|
|
31
32
|
export { AdminForthPlugin };
|
|
33
|
+
export { suggestIfTypo };
|
|
32
34
|
class AdminForth {
|
|
33
35
|
constructor(config) {
|
|
34
36
|
_AdminForth_defaultConfig.set(this, {
|
|
@@ -85,20 +87,22 @@ class AdminForth {
|
|
|
85
87
|
this.config.dataSources.forEach((ds) => {
|
|
86
88
|
const dbType = ds.url.split(':')[0];
|
|
87
89
|
if (!this.config.databaseConnectors[dbType]) {
|
|
88
|
-
throw new Error(`Database type ${dbType} is not supported, consider using
|
|
90
|
+
throw new Error(`Database type '${dbType}' is not supported, consider using one of ${Object.keys(this.connectorClasses).join(', ')} or create your own data-source connector`);
|
|
89
91
|
}
|
|
90
92
|
this.connectors[ds.id] = new this.config.databaseConnectors[dbType]({ url: ds.url });
|
|
91
93
|
});
|
|
92
94
|
yield Promise.all(this.config.resources.map((res) => __awaiter(this, void 0, void 0, function* () {
|
|
93
95
|
if (!this.connectors[res.dataSource]) {
|
|
94
|
-
|
|
96
|
+
const similar = suggestIfTypo(Object.keys(this.connectors), res.dataSource);
|
|
97
|
+
throw new Error(`Resource '${res.table}' refers to unknown dataSource '${res.dataSource}' ${similar
|
|
98
|
+
? `. Did you mean '${similar}'?` : 'Available dataSources: ' + Object.keys(this.connectors).join(', ')}`);
|
|
95
99
|
}
|
|
96
100
|
const fieldTypes = yield this.connectors[res.dataSource].discoverFields(res);
|
|
97
101
|
if (fieldTypes !== null && !Object.keys(fieldTypes).length) {
|
|
98
102
|
throw new Error(`Table '${res.table}' (In resource '${res.resourceId}') has no fields or does not exist`);
|
|
99
103
|
}
|
|
100
104
|
if (fieldTypes === null) {
|
|
101
|
-
console.error(
|
|
105
|
+
console.error(`⛔ DataSource ${res.dataSource} was not able to perform field discovery. It will not work properly`);
|
|
102
106
|
return;
|
|
103
107
|
}
|
|
104
108
|
if (!res.columns) {
|
|
@@ -106,7 +110,8 @@ class AdminForth {
|
|
|
106
110
|
}
|
|
107
111
|
res.columns.forEach((col, i) => {
|
|
108
112
|
if (!fieldTypes[col.name] && !col.virtual) {
|
|
109
|
-
|
|
113
|
+
const similar = suggestIfTypo(Object.keys(fieldTypes), col.name);
|
|
114
|
+
throw new Error(`Resource '${res.table}' has no column '${col.name}'. ${similar ? `Did you mean '${similar}'?` : ''}`);
|
|
110
115
|
}
|
|
111
116
|
// first find discovered values, but allow override
|
|
112
117
|
res.columns[i] = Object.assign(Object.assign({}, fieldTypes[col.name]), col);
|
|
@@ -118,6 +123,10 @@ class AdminForth {
|
|
|
118
123
|
}
|
|
119
124
|
})));
|
|
120
125
|
this.statuses.dbDiscover = 'done';
|
|
126
|
+
this.operationalResources = {};
|
|
127
|
+
this.config.resources.forEach((resource) => {
|
|
128
|
+
this.operationalResources[resource.resourceId] = new OperationalResource(this.connectors[resource.dataSource], resource);
|
|
129
|
+
});
|
|
121
130
|
// console.log('⚙️⚙️⚙️ Database discovery done', JSON.stringify(this.config.resources, null, 2));
|
|
122
131
|
});
|
|
123
132
|
}
|
|
@@ -128,9 +137,11 @@ class AdminForth {
|
|
|
128
137
|
}
|
|
129
138
|
getUserByPk(pk) {
|
|
130
139
|
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
-
const resource = this.config.resources.find((res) => res.resourceId === this.config.auth.
|
|
140
|
+
const resource = this.config.resources.find((res) => res.resourceId === this.config.auth.usersResourceId);
|
|
132
141
|
if (!resource) {
|
|
133
|
-
|
|
142
|
+
const similar = suggestIfTypo(this.config.resources.map((res) => res.resourceId), this.config.auth.usersResourceId);
|
|
143
|
+
throw new Error(`No resource with ${this.config.auth.usersResourceId} found. ${similar ?
|
|
144
|
+
`Did you mean '${similar}' in config.auth.usersResourceId?` : 'Please set correct resource in config.auth.usersResourceId'}`);
|
|
134
145
|
}
|
|
135
146
|
const users = yield this.connectors[resource.dataSource].getData({
|
|
136
147
|
resource,
|
|
@@ -148,13 +159,6 @@ class AdminForth {
|
|
|
148
159
|
return __awaiter(this, arguments, void 0, function* ({ resource, record, adminUser }) {
|
|
149
160
|
var _c, _d, _e, _f, _g;
|
|
150
161
|
for (const column of resource.columns) {
|
|
151
|
-
if (column.fillOnCreate) {
|
|
152
|
-
if (record[column.name] === undefined) {
|
|
153
|
-
record[column.name] = column.fillOnCreate({
|
|
154
|
-
initialRecord: record, adminUser
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
162
|
if (((_c = column.required) === null || _c === void 0 ? void 0 : _c.create) &&
|
|
159
163
|
record[column.name] === undefined &&
|
|
160
164
|
column.showIn.includes(AdminForthResourcePages.create)) {
|
|
@@ -191,7 +195,7 @@ class AdminForth {
|
|
|
191
195
|
}
|
|
192
196
|
const connector = this.connectors[resource.dataSource];
|
|
193
197
|
process.env.HEAVY_DEBUG && console.log('🪲🪲🪲🪲 creating record createResourceRecord', record);
|
|
194
|
-
yield connector.createRecord({ resource, record });
|
|
198
|
+
yield connector.createRecord({ resource, record, adminUser });
|
|
195
199
|
// execute hook if needed
|
|
196
200
|
for (const hook of listify((_g = (_f = resource.hooks) === null || _f === void 0 ? void 0 : _f.create) === null || _g === void 0 ? void 0 : _g.afterSave)) {
|
|
197
201
|
console.log('Hook afterSave', hook);
|
|
@@ -207,7 +211,21 @@ class AdminForth {
|
|
|
207
211
|
});
|
|
208
212
|
}
|
|
209
213
|
resource(resourceId) {
|
|
210
|
-
|
|
214
|
+
if (this.statuses.dbDiscover !== 'done') {
|
|
215
|
+
if (this.statuses.dbDiscover === 'running') {
|
|
216
|
+
throw new Error('Database discovery is running. You can\'t use data API while database discovery is not finished.\n' +
|
|
217
|
+
'Consider moving your code to a place where it will be executed after database discovery is already done (after await admin.discoverDatabases())');
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
throw new Error('Database discovery is not yet started. You can\'t use data API before database discovery is done. \n' +
|
|
221
|
+
'Call admin.discoverDatabases() first and await it before using data API');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!this.operationalResources[resourceId]) {
|
|
225
|
+
const closeName = suggestIfTypo(Object.keys(this.operationalResources), resourceId);
|
|
226
|
+
throw new Error(`Resource with id '${resourceId}' not found${closeName ? `. Did you mean '${closeName}'?` : ''}`);
|
|
227
|
+
}
|
|
228
|
+
return this.operationalResources[resourceId];
|
|
211
229
|
}
|
|
212
230
|
setupEndpoints(server) {
|
|
213
231
|
this.restApi.registerEndpoints(server);
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
import { AdminForthResourcePages, AllowedActionsEnum, } from "../types/AdminForthConfig.js";
|
|
11
11
|
import fs from 'fs';
|
|
12
12
|
import path from 'path';
|
|
13
|
-
import { guessLabelFromName } from './utils.js';
|
|
13
|
+
import { guessLabelFromName, suggestIfTypo } from './utils.js';
|
|
14
14
|
import crypto from 'crypto';
|
|
15
15
|
export default class ConfigValidator {
|
|
16
16
|
constructor(adminforth, config) {
|
|
@@ -47,15 +47,6 @@ export default class ConfigValidator {
|
|
|
47
47
|
validateConfig() {
|
|
48
48
|
var _a;
|
|
49
49
|
const errors = [];
|
|
50
|
-
if (this.config.rootUser) {
|
|
51
|
-
if (!this.config.rootUser.username) {
|
|
52
|
-
throw new Error('rootUser.username is required');
|
|
53
|
-
}
|
|
54
|
-
if (!this.config.rootUser.password) {
|
|
55
|
-
throw new Error('rootUser.password is required');
|
|
56
|
-
}
|
|
57
|
-
console.log('\n ☝️☝️☝️ [INSECURE ALERT] config.rootUser is set, please create a new user to login in backoffice and remove config.rootUser from config ASAP when you are in production\n');
|
|
58
|
-
}
|
|
59
50
|
if (!this.config.customization.customComponentsDir) {
|
|
60
51
|
this.config.customization.customComponentsDir = './custom';
|
|
61
52
|
}
|
|
@@ -67,8 +58,12 @@ export default class ConfigValidator {
|
|
|
67
58
|
this.config.customization.customComponentsDir = undefined;
|
|
68
59
|
}
|
|
69
60
|
if (this.config.auth) {
|
|
70
|
-
|
|
71
|
-
|
|
61
|
+
// TODO: remove in future releases
|
|
62
|
+
if (!this.config.auth.usersResourceId && this.config.auth.resourceId) {
|
|
63
|
+
this.config.auth.usersResourceId = this.config.auth.resourceId;
|
|
64
|
+
}
|
|
65
|
+
if (!this.config.auth.usersResourceId) {
|
|
66
|
+
throw new Error('No config.auth.usersResourceId defined');
|
|
72
67
|
}
|
|
73
68
|
if (!this.config.auth.passwordHashField) {
|
|
74
69
|
throw new Error('No config.auth.passwordHashField defined');
|
|
@@ -79,9 +74,10 @@ export default class ConfigValidator {
|
|
|
79
74
|
if (this.config.auth.loginBackgroundImage) {
|
|
80
75
|
errors.push(...this.checkCustomFileExists(this.config.auth.loginBackgroundImage));
|
|
81
76
|
}
|
|
82
|
-
const userResource = this.config.resources.find((res) => res.resourceId === this.config.auth.
|
|
77
|
+
const userResource = this.config.resources.find((res) => res.resourceId === this.config.auth.usersResourceId);
|
|
83
78
|
if (!userResource) {
|
|
84
|
-
|
|
79
|
+
const similar = suggestIfTypo(this.config.resources.map((res) => res.resourceId || res.table), this.config.auth.usersResourceId);
|
|
80
|
+
throw new Error(`Resource with id "${this.config.auth.usersResourceId}" not found. ${similar ? `Did you mean "${similar}"?` : ''}`);
|
|
85
81
|
}
|
|
86
82
|
if (!this.config.auth.beforeLoginConfirmation) {
|
|
87
83
|
this.config.auth.beforeLoginConfirmation = [];
|
|
@@ -7,42 +7,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
// export interface IOperationalResource {
|
|
11
|
-
// get: (filters: IAdminForthFilter | IAdminForthFilter[]) => Promise<any[]>;
|
|
12
|
-
// list: (filters: IAdminForthFilter | IAdminForthFilter[], limit: number, offset: number, sort: IAdminForthSort | IAdminForthSort[]) => Promise<any[]>;
|
|
13
|
-
// count: (filters: IAdminForthFilter | IAdminForthFilter[]) => Promise<number>;
|
|
14
|
-
// create: (record: any) => Promise<any>;
|
|
15
|
-
// update: (primaryKey: any, record: any) => Promise<any>;
|
|
16
|
-
// delete: (primaryKey: any) => Promise<boolean>;
|
|
17
|
-
// deleteMany: (primaryKeys: any[]) => Promise<boolean>;
|
|
18
|
-
// }
|
|
19
|
-
// async getData({ resource, limit, offset, sort, filters }: {
|
|
20
|
-
// resource: AdminForthResource,
|
|
21
|
-
// limit: number,
|
|
22
|
-
// offset: number,
|
|
23
|
-
// sort: { field: string, direction: AdminForthSortDirections }[],
|
|
24
|
-
// filters: { field: string, operator: AdminForthFilterOperators, value: any }[]
|
|
25
|
-
// }): Promise<{ data: any[], total: number }> {
|
|
26
10
|
function filtersIfFilter(filter) {
|
|
27
|
-
return (
|
|
11
|
+
return (Array.isArray(filter) ? filter : [filter]);
|
|
28
12
|
}
|
|
29
13
|
function sortsIfSort(sort) {
|
|
30
|
-
return (
|
|
14
|
+
return (Array.isArray(sort) ? sort : [sort]);
|
|
31
15
|
}
|
|
32
|
-
export class OperationalResource {
|
|
16
|
+
export default class OperationalResource {
|
|
33
17
|
constructor(dataConnector, resourceConfig) {
|
|
34
18
|
this.dataConnector = dataConnector;
|
|
35
19
|
this.resourceConfig = resourceConfig;
|
|
36
20
|
}
|
|
37
21
|
get(filter) {
|
|
38
22
|
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
-
return yield this.dataConnector.getData({
|
|
23
|
+
return (yield this.dataConnector.getData({
|
|
40
24
|
resource: this.resourceConfig,
|
|
41
25
|
filters: filtersIfFilter(filter),
|
|
42
26
|
limit: 1,
|
|
43
27
|
offset: 0,
|
|
44
28
|
sort: [],
|
|
45
|
-
})[0];
|
|
29
|
+
})).data[0] || null;
|
|
46
30
|
});
|
|
47
31
|
}
|
|
48
32
|
list(filter, limit, offset, sort) {
|
|
@@ -68,7 +52,7 @@ export class OperationalResource {
|
|
|
68
52
|
}
|
|
69
53
|
create(record) {
|
|
70
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
71
|
-
return yield this.dataConnector.createRecord({ resource: this.resourceConfig, record });
|
|
55
|
+
return yield this.dataConnector.createRecord({ resource: this.resourceConfig, record, adminUser: null });
|
|
72
56
|
});
|
|
73
57
|
}
|
|
74
58
|
update(primaryKey, record) {
|