adminforth 1.3.26 → 1.3.28
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 +0 -1
- package/dataConnectors/baseConnector.ts +19 -7
- package/dataConnectors/clickhouse.ts +1 -2
- package/dataConnectors/mongo.ts +1 -1
- package/dataConnectors/postgres.ts +1 -1
- package/dataConnectors/sqlite.ts +3 -3
- package/dist/dataConnectors/baseConnector.js +16 -4
- package/dist/dataConnectors/clickhouse.js +1 -2
- package/dist/dataConnectors/mongo.js +1 -1
- package/dist/dataConnectors/postgres.js +1 -1
- package/dist/dataConnectors/sqlite.js +3 -3
- package/dist/index.js +113 -21
- package/dist/modules/codeInjector.js +8 -8
- package/dist/modules/restApi.js +23 -88
- package/index.ts +128 -24
- package/modules/codeInjector.ts +8 -8
- package/modules/operationalResource.ts +2 -3
- package/modules/restApi.ts +23 -94
- package/package.json +1 -1
- package/spa/src/components/ResourceForm.vue +6 -16
- package/spa/src/utils.ts +34 -1
- package/types/AdminForthConfig.ts +37 -11
package/auth.ts
CHANGED
|
@@ -67,7 +67,6 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
|
|
|
67
67
|
offset: 0,
|
|
68
68
|
getTotals: false
|
|
69
69
|
});
|
|
70
|
-
process.env.HEAVY_DEBUG && console.log('☝️🪲🪲🪲🪲 existingRecord|||', existingRecord);
|
|
71
70
|
|
|
72
71
|
return existingRecord.data.length > 0;
|
|
73
72
|
}
|
|
@@ -90,14 +89,11 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
|
|
|
90
89
|
}
|
|
91
90
|
recordWithOriginalValues[col.name] = this.setFieldValue(col, filledRecord[col.name]);
|
|
92
91
|
}
|
|
93
|
-
|
|
94
92
|
|
|
95
93
|
let error: string | null = null;
|
|
96
94
|
await Promise.all(
|
|
97
95
|
resource.dataSourceColumns.map(async (col) => {
|
|
98
|
-
|
|
99
96
|
if (col.isUnique && !col.virtual && !error) {
|
|
100
|
-
|
|
101
97
|
const exists = await this.checkUnique(resource, col, recordWithOriginalValues[col.name]);
|
|
102
98
|
if (exists) {
|
|
103
99
|
error = `Record with ${col.name} ${recordWithOriginalValues[col.name]} already exists`;
|
|
@@ -105,12 +101,12 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
|
|
|
105
101
|
}
|
|
106
102
|
})
|
|
107
103
|
);
|
|
108
|
-
process.env.HEAVY_DEBUG && console.log('🪲🪲🪲🪲 error', error);
|
|
109
104
|
if (error) {
|
|
105
|
+
process.env.HEAVY_DEBUG && console.log('🪲🆕 check unique error', error);
|
|
110
106
|
return { error, ok: false };
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
process.env.HEAVY_DEBUG && console.log('
|
|
109
|
+
process.env.HEAVY_DEBUG && console.log('🪲🆕 creating record', recordWithOriginalValues);
|
|
114
110
|
await this.createRecordOriginalValues({ resource, record: recordWithOriginalValues });
|
|
115
111
|
|
|
116
112
|
return {
|
|
@@ -119,10 +115,26 @@ export default class AdminForthBaseConnector implements IAdminForthDataSourceCon
|
|
|
119
115
|
}
|
|
120
116
|
}
|
|
121
117
|
|
|
122
|
-
|
|
118
|
+
updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource; recordId: string; newValues: any; }): Promise<void> {
|
|
123
119
|
throw new Error('Method not implemented.');
|
|
124
120
|
}
|
|
125
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
|
+
recordWithOriginalValues[col.name] = this.setFieldValue(col, newValues[col.name]);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
process.env.HEAVY_DEBUG && console.log(`🪲✏️ updating record id:${recordId}, values: ${JSON.stringify(recordWithOriginalValues)}`);
|
|
132
|
+
|
|
133
|
+
await this.updateRecordOriginalValues({ resource, recordId, newValues: recordWithOriginalValues });
|
|
134
|
+
|
|
135
|
+
return { ok: true };
|
|
136
|
+
}
|
|
137
|
+
|
|
126
138
|
deleteRecord({ resource, recordId }: { resource: AdminForthResource; recordId: string; }): Promise<boolean> {
|
|
127
139
|
throw new Error('Method not implemented.');
|
|
128
140
|
}
|
|
@@ -303,11 +303,10 @@ class ClickhouseConnector extends AdminForthBaseConnector implements IAdminForth
|
|
|
303
303
|
});
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
async
|
|
306
|
+
async updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource, recordId: any, newValues: any }) {
|
|
307
307
|
const columnsWithPlaceholders = Object.keys(newValues).map((col) => {
|
|
308
308
|
return `${col} = {${col}:${resource.dataSourceColumns.find((c) => c.name == col)._underlineType}}`
|
|
309
309
|
});
|
|
310
|
-
const values = [...Object.values(newValues), recordId];
|
|
311
310
|
|
|
312
311
|
await this.client.command(
|
|
313
312
|
{
|
package/dataConnectors/mongo.ts
CHANGED
|
@@ -182,7 +182,7 @@ class MongoConnector extends AdminForthBaseConnector implements IAdminForthDataS
|
|
|
182
182
|
await collection.insertOne(newRecord);
|
|
183
183
|
}
|
|
184
184
|
|
|
185
|
-
async
|
|
185
|
+
async updateRecordOriginalValues({ resource, recordId, newValues }) {
|
|
186
186
|
const collection = this.db.db().collection(resource.table);
|
|
187
187
|
await collection.updateOne({ [this.getPrimaryKey(resource)]: recordId }, { $set: newValues });
|
|
188
188
|
}
|
|
@@ -287,7 +287,7 @@ class PostgresConnector extends AdminForthBaseConnector implements IAdminForthDa
|
|
|
287
287
|
await this.db.query(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`, values);
|
|
288
288
|
}
|
|
289
289
|
|
|
290
|
-
async
|
|
290
|
+
async updateRecordOriginalValues({ resource, recordId, newValues }) {
|
|
291
291
|
const values = [...Object.values(newValues), recordId];
|
|
292
292
|
const columnsWithPlaceholders = Object.keys(newValues).map((col, i) => `"${col}" = $${i + 1}`).join(', ');
|
|
293
293
|
await this.db.query(`UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE "${this.getPrimaryKey(resource)}" = $${values.length}`, values);
|
package/dataConnectors/sqlite.ts
CHANGED
|
@@ -181,13 +181,12 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
|
|
|
181
181
|
|
|
182
182
|
const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `${s.field} ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
|
|
183
183
|
|
|
184
|
-
console.log('🪲 SQLITE Query', `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT ? OFFSET ?`, 'params:', [...filterValues, limit, offset]);
|
|
185
184
|
const q = `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT ? OFFSET ?`;
|
|
186
185
|
const stmt = this.db.prepare(q);
|
|
187
186
|
const d = [...filterValues, limit, offset];
|
|
188
187
|
|
|
189
188
|
if (process.env.HEAVY_DEBUG) {
|
|
190
|
-
console.log('
|
|
189
|
+
console.log('🪲📜 SQLITE Q', q, 'params:', d);
|
|
191
190
|
}
|
|
192
191
|
const rows = await stmt.all(d);
|
|
193
192
|
|
|
@@ -230,13 +229,14 @@ class SQLiteConnector extends AdminForthBaseConnector implements IAdminForthData
|
|
|
230
229
|
await q.run(values);
|
|
231
230
|
}
|
|
232
231
|
|
|
233
|
-
async
|
|
232
|
+
async updateRecordOriginalValues({ resource, recordId, newValues }: { resource: AdminForthResource, recordId: any, newValues: any }) {
|
|
234
233
|
const columnsWithPlaceholders = Object.keys(newValues).map((col) => `${col} = ?`);
|
|
235
234
|
const values = [...Object.values(newValues), recordId];
|
|
236
235
|
|
|
237
236
|
const q = this.db.prepare(
|
|
238
237
|
`UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`
|
|
239
238
|
)
|
|
239
|
+
process.env.HEAVY_DEBUG && console.log('🪲 SQLITE Query', `UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`, 'params:', values);
|
|
240
240
|
await q.run(values);
|
|
241
241
|
}
|
|
242
242
|
|
|
@@ -61,7 +61,6 @@ export default class AdminForthBaseConnector {
|
|
|
61
61
|
offset: 0,
|
|
62
62
|
getTotals: false
|
|
63
63
|
});
|
|
64
|
-
process.env.HEAVY_DEBUG && console.log('☝️🪲🪲🪲🪲 existingRecord|||', existingRecord);
|
|
65
64
|
return existingRecord.data.length > 0;
|
|
66
65
|
});
|
|
67
66
|
}
|
|
@@ -90,11 +89,11 @@ export default class AdminForthBaseConnector {
|
|
|
90
89
|
}
|
|
91
90
|
}
|
|
92
91
|
})));
|
|
93
|
-
process.env.HEAVY_DEBUG && console.log('🪲🪲🪲🪲 error', error);
|
|
94
92
|
if (error) {
|
|
93
|
+
process.env.HEAVY_DEBUG && console.log('🪲🆕 check unique error', error);
|
|
95
94
|
return { error, ok: false };
|
|
96
95
|
}
|
|
97
|
-
process.env.HEAVY_DEBUG && console.log('
|
|
96
|
+
process.env.HEAVY_DEBUG && console.log('🪲🆕 creating record', recordWithOriginalValues);
|
|
98
97
|
yield this.createRecordOriginalValues({ resource, record: recordWithOriginalValues });
|
|
99
98
|
return {
|
|
100
99
|
ok: true,
|
|
@@ -102,9 +101,22 @@ export default class AdminForthBaseConnector {
|
|
|
102
101
|
};
|
|
103
102
|
});
|
|
104
103
|
}
|
|
105
|
-
|
|
104
|
+
updateRecordOriginalValues({ resource, recordId, newValues }) {
|
|
106
105
|
throw new Error('Method not implemented.');
|
|
107
106
|
}
|
|
107
|
+
updateRecord(_a) {
|
|
108
|
+
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, newValues }) {
|
|
109
|
+
// transform value using setFieldValue and call updateRecordOriginalValues
|
|
110
|
+
const recordWithOriginalValues = Object.assign({}, newValues);
|
|
111
|
+
for (const field of Object.keys(newValues)) {
|
|
112
|
+
const col = resource.dataSourceColumns.find((col) => col.name == field);
|
|
113
|
+
recordWithOriginalValues[col.name] = this.setFieldValue(col, newValues[col.name]);
|
|
114
|
+
}
|
|
115
|
+
process.env.HEAVY_DEBUG && console.log(`🪲✏️ updating record id:${recordId}, values: ${JSON.stringify(recordWithOriginalValues)}`);
|
|
116
|
+
yield this.updateRecordOriginalValues({ resource, recordId, newValues: recordWithOriginalValues });
|
|
117
|
+
return { ok: true };
|
|
118
|
+
});
|
|
119
|
+
}
|
|
108
120
|
deleteRecord({ resource, recordId }) {
|
|
109
121
|
throw new Error('Method not implemented.');
|
|
110
122
|
}
|
|
@@ -285,12 +285,11 @@ class ClickhouseConnector extends AdminForthBaseConnector {
|
|
|
285
285
|
});
|
|
286
286
|
});
|
|
287
287
|
}
|
|
288
|
-
|
|
288
|
+
updateRecordOriginalValues(_a) {
|
|
289
289
|
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, newValues }) {
|
|
290
290
|
const columnsWithPlaceholders = Object.keys(newValues).map((col) => {
|
|
291
291
|
return `${col} = {${col}:${resource.dataSourceColumns.find((c) => c.name == col)._underlineType}}`;
|
|
292
292
|
});
|
|
293
|
-
const values = [...Object.values(newValues), recordId];
|
|
294
293
|
yield this.client.command({
|
|
295
294
|
query: `ALTER TABLE ${this.dbName}.${resource.table} UPDATE ${columnsWithPlaceholders.join(', ')} WHERE ${this.getPrimaryKey(resource)} = {recordId:${resource.dataSourceColumns.find((c) => c.primaryKey)._underlineType}}`,
|
|
296
295
|
query_params: Object.assign(Object.assign({}, newValues), { recordId }),
|
|
@@ -171,7 +171,7 @@ class MongoConnector extends AdminForthBaseConnector {
|
|
|
171
171
|
yield collection.insertOne(newRecord);
|
|
172
172
|
});
|
|
173
173
|
}
|
|
174
|
-
|
|
174
|
+
updateRecordOriginalValues(_a) {
|
|
175
175
|
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, newValues }) {
|
|
176
176
|
const collection = this.db.db().collection(resource.table);
|
|
177
177
|
yield collection.updateOne({ [this.getPrimaryKey(resource)]: recordId }, { $set: newValues });
|
|
@@ -283,7 +283,7 @@ class PostgresConnector extends AdminForthBaseConnector {
|
|
|
283
283
|
yield this.db.query(`INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`, values);
|
|
284
284
|
});
|
|
285
285
|
}
|
|
286
|
-
|
|
286
|
+
updateRecordOriginalValues(_a) {
|
|
287
287
|
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, newValues }) {
|
|
288
288
|
const values = [...Object.values(newValues), recordId];
|
|
289
289
|
const columnsWithPlaceholders = Object.keys(newValues).map((col, i) => `"${col}" = $${i + 1}`).join(', ');
|
|
@@ -196,12 +196,11 @@ class SQLiteConnector extends AdminForthBaseConnector {
|
|
|
196
196
|
const where = this.whereClause(filters);
|
|
197
197
|
const filterValues = this.whereParams(filters);
|
|
198
198
|
const orderBy = sort.length ? `ORDER BY ${sort.map((s) => `${s.field} ${this.SortDirectionsMap[s.direction]}`).join(', ')}` : '';
|
|
199
|
-
console.log('🪲 SQLITE Query', `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT ? OFFSET ?`, 'params:', [...filterValues, limit, offset]);
|
|
200
199
|
const q = `SELECT ${columns} FROM ${tableName} ${where} ${orderBy} LIMIT ? OFFSET ?`;
|
|
201
200
|
const stmt = this.db.prepare(q);
|
|
202
201
|
const d = [...filterValues, limit, offset];
|
|
203
202
|
if (process.env.HEAVY_DEBUG) {
|
|
204
|
-
console.log('
|
|
203
|
+
console.log('🪲📜 SQLITE Q', q, 'params:', d);
|
|
205
204
|
}
|
|
206
205
|
const rows = yield stmt.all(d);
|
|
207
206
|
return rows.map((row) => {
|
|
@@ -246,11 +245,12 @@ class SQLiteConnector extends AdminForthBaseConnector {
|
|
|
246
245
|
yield q.run(values);
|
|
247
246
|
});
|
|
248
247
|
}
|
|
249
|
-
|
|
248
|
+
updateRecordOriginalValues(_a) {
|
|
250
249
|
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, newValues }) {
|
|
251
250
|
const columnsWithPlaceholders = Object.keys(newValues).map((col) => `${col} = ?`);
|
|
252
251
|
const values = [...Object.values(newValues), recordId];
|
|
253
252
|
const q = this.db.prepare(`UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`);
|
|
253
|
+
process.env.HEAVY_DEBUG && console.log('🪲 SQLITE Query', `UPDATE ${resource.table} SET ${columnsWithPlaceholders} WHERE ${this.getPrimaryKey(resource)} = ?`, 'params:', values);
|
|
254
254
|
yield q.run(values);
|
|
255
255
|
});
|
|
256
256
|
}
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import SQLiteConnector from './dataConnectors/sqlite.js';
|
|
|
20
20
|
import CodeInjector from './modules/codeInjector.js';
|
|
21
21
|
import ExpressServer from './servers/express.js';
|
|
22
22
|
import { ADMINFORTH_VERSION, listify, suggestIfTypo } from './modules/utils.js';
|
|
23
|
-
import { AdminForthFilterOperators, AdminForthDataTypes,
|
|
23
|
+
import { AdminForthFilterOperators, AdminForthDataTypes, } 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';
|
|
@@ -157,23 +157,15 @@ class AdminForth {
|
|
|
157
157
|
}
|
|
158
158
|
createResourceRecord(_b) {
|
|
159
159
|
return __awaiter(this, arguments, void 0, function* ({ resource, record, adminUser }) {
|
|
160
|
-
var _c, _d, _e, _f
|
|
161
|
-
for (const column of resource.columns) {
|
|
162
|
-
// TODO: assuming specifity for AdminForthResourcePages.create better to move it to api for this button
|
|
163
|
-
if (((_c = column.required) === null || _c === void 0 ? void 0 : _c.create) &&
|
|
164
|
-
record[column.name] === undefined &&
|
|
165
|
-
column.showIn.includes(AdminForthResourcePages.create)) {
|
|
166
|
-
return { error: `Column '${column.name}' is required`, ok: false };
|
|
167
|
-
}
|
|
168
|
-
}
|
|
160
|
+
var _c, _d, _e, _f;
|
|
169
161
|
// execute hook if needed
|
|
170
|
-
for (const hook of listify((
|
|
162
|
+
for (const hook of listify((_d = (_c = resource.hooks) === null || _c === void 0 ? void 0 : _c.create) === null || _d === void 0 ? void 0 : _d.beforeSave)) {
|
|
171
163
|
const resp = yield hook({ recordId: undefined, resource, record, adminUser });
|
|
172
164
|
if (!resp || (!resp.ok && !resp.error)) {
|
|
173
165
|
throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
|
|
174
166
|
}
|
|
175
167
|
if (resp.error) {
|
|
176
|
-
return { error: resp.error
|
|
168
|
+
return { error: resp.error };
|
|
177
169
|
}
|
|
178
170
|
}
|
|
179
171
|
// remove virtual columns from record
|
|
@@ -183,15 +175,15 @@ class AdminForth {
|
|
|
183
175
|
}
|
|
184
176
|
}
|
|
185
177
|
const connector = this.connectors[resource.dataSource];
|
|
186
|
-
process.env.HEAVY_DEBUG && console.log('
|
|
187
|
-
const {
|
|
188
|
-
if (
|
|
189
|
-
return {
|
|
178
|
+
process.env.HEAVY_DEBUG && console.log('🪲🆕 creating record createResourceRecord', record);
|
|
179
|
+
const { error, createdRecord } = yield connector.createRecord({ resource, record, adminUser });
|
|
180
|
+
if (error) {
|
|
181
|
+
return { error };
|
|
190
182
|
}
|
|
191
183
|
const primaryKey = record[resource.columns.find((col) => col.primaryKey).name];
|
|
192
184
|
// execute hook if needed
|
|
193
|
-
for (const hook of listify((
|
|
194
|
-
console.log('Hook afterSave', hook);
|
|
185
|
+
for (const hook of listify((_f = (_e = resource.hooks) === null || _e === void 0 ? void 0 : _e.create) === null || _f === void 0 ? void 0 : _f.afterSave)) {
|
|
186
|
+
process.env.HEAVY_DEBUG && console.log('🪲 Hook afterSave', hook);
|
|
195
187
|
const resp = yield hook({
|
|
196
188
|
recordId: primaryKey,
|
|
197
189
|
resource,
|
|
@@ -202,10 +194,100 @@ class AdminForth {
|
|
|
202
194
|
throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
|
|
203
195
|
}
|
|
204
196
|
if (resp.error) {
|
|
205
|
-
return { error: resp.error
|
|
197
|
+
return { error: resp.error };
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return { error, createdRecord };
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* record is partial record with only changed fields
|
|
205
|
+
*/
|
|
206
|
+
updateResourceRecord(_b) {
|
|
207
|
+
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, record, oldRecord, adminUser }) {
|
|
208
|
+
var _c, _d, _e, _f;
|
|
209
|
+
// execute hook if needed
|
|
210
|
+
for (const hook of listify((_d = (_c = resource.hooks) === null || _c === void 0 ? void 0 : _c.edit) === null || _d === void 0 ? void 0 : _d.beforeSave)) {
|
|
211
|
+
const resp = yield hook({
|
|
212
|
+
recordId,
|
|
213
|
+
resource,
|
|
214
|
+
record,
|
|
215
|
+
oldRecord,
|
|
216
|
+
adminUser
|
|
217
|
+
});
|
|
218
|
+
if (!resp || (!resp.ok && !resp.error)) {
|
|
219
|
+
throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
|
|
220
|
+
}
|
|
221
|
+
if (resp.error) {
|
|
222
|
+
return { error: resp.error };
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const newValues = {};
|
|
226
|
+
const connector = this.connectors[resource.dataSource];
|
|
227
|
+
for (const recordField in record) {
|
|
228
|
+
if (record[recordField] !== oldRecord[recordField]) {
|
|
229
|
+
// leave only changed fields to reduce data transfer/modifications in db
|
|
230
|
+
const column = resource.columns.find((col) => col.name === recordField);
|
|
231
|
+
if (!column || !column.virtual) {
|
|
232
|
+
// exclude virtual columns
|
|
233
|
+
newValues[recordField] = record[recordField];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (Object.keys(newValues).length > 0) {
|
|
238
|
+
yield connector.updateRecord({ resource, recordId, newValues });
|
|
239
|
+
}
|
|
240
|
+
// execute hook if needed
|
|
241
|
+
for (const hook of listify((_f = (_e = resource.hooks) === null || _e === void 0 ? void 0 : _e.edit) === null || _f === void 0 ? void 0 : _f.afterSave)) {
|
|
242
|
+
const resp = yield hook({
|
|
243
|
+
resource,
|
|
244
|
+
record,
|
|
245
|
+
adminUser,
|
|
246
|
+
oldRecord,
|
|
247
|
+
recordId,
|
|
248
|
+
});
|
|
249
|
+
if (!resp || (!resp.ok && !resp.error)) {
|
|
250
|
+
throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
|
|
251
|
+
}
|
|
252
|
+
return { error: resp.error };
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
deleteResourceRecord(_b) {
|
|
257
|
+
return __awaiter(this, arguments, void 0, function* ({ resource, recordId, adminUser, record }) {
|
|
258
|
+
var _c, _d, _e, _f;
|
|
259
|
+
// execute hook if needed
|
|
260
|
+
for (const hook of listify((_d = (_c = resource.hooks) === null || _c === void 0 ? void 0 : _c.delete) === null || _d === void 0 ? void 0 : _d.beforeSave)) {
|
|
261
|
+
const resp = yield hook({
|
|
262
|
+
resource,
|
|
263
|
+
record,
|
|
264
|
+
adminUser,
|
|
265
|
+
recordId,
|
|
266
|
+
});
|
|
267
|
+
if (!resp || (!resp.ok && !resp.error)) {
|
|
268
|
+
throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
|
|
269
|
+
}
|
|
270
|
+
if (resp.error) {
|
|
271
|
+
return { error: resp.error };
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
const connector = this.connectors[resource.dataSource];
|
|
275
|
+
yield connector.deleteRecord({ resource, recordId });
|
|
276
|
+
// execute hook if needed
|
|
277
|
+
for (const hook of listify((_f = (_e = resource.hooks) === null || _e === void 0 ? void 0 : _e.delete) === null || _f === void 0 ? void 0 : _f.afterSave)) {
|
|
278
|
+
const resp = yield hook({
|
|
279
|
+
resource,
|
|
280
|
+
record,
|
|
281
|
+
adminUser,
|
|
282
|
+
recordId,
|
|
283
|
+
});
|
|
284
|
+
if (!resp || (!resp.ok && !resp.error)) {
|
|
285
|
+
throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
|
|
286
|
+
}
|
|
287
|
+
if (resp.error) {
|
|
288
|
+
return { error: resp.error };
|
|
206
289
|
}
|
|
207
290
|
}
|
|
208
|
-
return { ok, error, createdRecord };
|
|
209
291
|
});
|
|
210
292
|
}
|
|
211
293
|
resource(resourceId) {
|
|
@@ -234,6 +316,16 @@ AdminForth.Types = AdminForthDataTypes;
|
|
|
234
316
|
AdminForth.Utils = {
|
|
235
317
|
generatePasswordHash: (password) => __awaiter(void 0, void 0, void 0, function* () {
|
|
236
318
|
return yield AdminForthAuth.generatePasswordHash(password);
|
|
237
|
-
})
|
|
319
|
+
}),
|
|
320
|
+
PASSWORD_VALIDATORS: {
|
|
321
|
+
UP_LOW_NUM_SPECIAL: {
|
|
322
|
+
regExp: '^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#\\$%\\^&\\*\\(\\)\\-_=\\+\\[\\]\\{\\}\\|;:\',\\.<>\\/\\?]).+$',
|
|
323
|
+
message: 'Password must include at least one uppercase letter, one lowercase letter, one number, and one special character'
|
|
324
|
+
},
|
|
325
|
+
UP_LOW_NUM: {
|
|
326
|
+
regExp: '^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).+$',
|
|
327
|
+
message: 'Password must include at least one uppercase letter, one lowercase letter, and one number'
|
|
328
|
+
},
|
|
329
|
+
}
|
|
238
330
|
};
|
|
239
331
|
export default AdminForth;
|
|
@@ -217,13 +217,13 @@ class CodeInjector {
|
|
|
217
217
|
dereference: true, // needed to dereference types
|
|
218
218
|
});
|
|
219
219
|
if (process.env.HEAVY_DEBUG) {
|
|
220
|
-
console.log('
|
|
220
|
+
console.log('🪲⚙️ fsExtra.copy copy single file', src, dest);
|
|
221
221
|
}
|
|
222
222
|
})));
|
|
223
223
|
}
|
|
224
224
|
else {
|
|
225
225
|
if (process.env.HEAVY_DEBUG) {
|
|
226
|
-
console.log(
|
|
226
|
+
console.log(`🪲⚙️ fsExtra.copy from ${path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa')}, -> ${CodeInjector.SPA_TMP_PATH}`);
|
|
227
227
|
}
|
|
228
228
|
// try to rm SPA_TMP_PATH/src/types directory
|
|
229
229
|
try {
|
|
@@ -237,7 +237,7 @@ class CodeInjector {
|
|
|
237
237
|
filter: (src) => {
|
|
238
238
|
const filterPasses = !src.includes('/adminforth/spa/node_modules') && !src.includes('/adminforth/spa/dist');
|
|
239
239
|
if (process.env.HEAVY_DEBUG && !filterPasses) {
|
|
240
|
-
console.log('
|
|
240
|
+
console.log('🪲⚙️ fsExtra.copy filtered out', src);
|
|
241
241
|
}
|
|
242
242
|
return filterPasses;
|
|
243
243
|
},
|
|
@@ -261,7 +261,7 @@ class CodeInjector {
|
|
|
261
261
|
for (const [src, dest] of Object.entries(this.srcFoldersToSync)) {
|
|
262
262
|
const to = path.join(CodeInjector.SPA_TMP_PATH, 'src', 'custom', dest);
|
|
263
263
|
if (process.env.HEAVY_DEBUG) {
|
|
264
|
-
console.log(
|
|
264
|
+
console.log(`🪲⚙️ fsExtra.copy from ${src}, ${to}`);
|
|
265
265
|
}
|
|
266
266
|
yield fsExtra.copy(src, to, {
|
|
267
267
|
recursive: true,
|
|
@@ -465,7 +465,7 @@ class CodeInjector {
|
|
|
465
465
|
});
|
|
466
466
|
yield collectDirectories(spaPath);
|
|
467
467
|
if (process.env.HEAVY_DEBUG) {
|
|
468
|
-
console.log('
|
|
468
|
+
console.log('🪲🔎 Watch for:', directories.join(','));
|
|
469
469
|
}
|
|
470
470
|
const watcher = filewatcher();
|
|
471
471
|
directories.forEach((dir) => {
|
|
@@ -514,11 +514,11 @@ class CodeInjector {
|
|
|
514
514
|
yield collectDirectories(customComponentsDir);
|
|
515
515
|
const watcher = filewatcher();
|
|
516
516
|
files.forEach((file) => {
|
|
517
|
-
process.env.HEAVY_DEBUG && console.log(
|
|
517
|
+
process.env.HEAVY_DEBUG && console.log(`🪲🔎 Watch for file ${file}`);
|
|
518
518
|
watcher.add(file);
|
|
519
519
|
});
|
|
520
520
|
if (process.env.HEAVY_DEBUG) {
|
|
521
|
-
console.log('
|
|
521
|
+
console.log('🪲🔎 Watch for:', directories.join(','));
|
|
522
522
|
}
|
|
523
523
|
watcher.on('change', (fileOrDir) => __awaiter(this, void 0, void 0, function* () {
|
|
524
524
|
// copy one file
|
|
@@ -568,7 +568,7 @@ class CodeInjector {
|
|
|
568
568
|
}
|
|
569
569
|
else {
|
|
570
570
|
const command = 'run dev';
|
|
571
|
-
console.log(
|
|
571
|
+
console.log(`🪲⚙️ spawn: npm ${command}...`);
|
|
572
572
|
const nodeBinary = process.execPath;
|
|
573
573
|
const npmPath = path.join(path.dirname(nodeBinary), 'npm');
|
|
574
574
|
const env = Object.assign({ VITE_ADMINFORTH_PUBLIC_PATH: this.adminforth.config.baseUrl, FORCE_COLOR: '1' }, process.env);
|