@adminforth/import-export 1.6.2 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.log +2 -2
- package/custom/ExportCsv.vue +107 -16
- package/dist/custom/ExportCsv.vue +107 -16
- package/dist/index.d.ts +56 -1
- package/dist/index.js +221 -159
- package/index.ts +265 -176
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
const exportCsvBodySchema = z.object({
|
|
14
14
|
filters: z.any(),
|
|
15
15
|
sort: z.any(),
|
|
16
|
+
selectedIds: z.array(z.any()).optional(),
|
|
16
17
|
}).strict();
|
|
17
18
|
const importCsvBodySchema = z.object({
|
|
18
19
|
data: z.record(z.string(), z.array(z.unknown())),
|
|
@@ -92,10 +93,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
92
93
|
}
|
|
93
94
|
resourceConfig.options.pageInjections.list.threeDotsDropdownItems.push({
|
|
94
95
|
file: this.componentPath('ExportCsv.vue'),
|
|
95
|
-
meta: { pluginInstanceId: this.pluginInstanceId
|
|
96
|
-
}, {
|
|
97
|
-
file: this.componentPath('ExportCsv.vue'),
|
|
98
|
-
meta: { pluginInstanceId: this.pluginInstanceId, select: 'filtered' }
|
|
96
|
+
meta: { pluginInstanceId: this.pluginInstanceId }
|
|
99
97
|
}, {
|
|
100
98
|
file: this.componentPath('ImportCsv.vue'),
|
|
101
99
|
meta: { pluginInstanceId: this.pluginInstanceId }
|
|
@@ -122,9 +120,8 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
122
120
|
method: 'POST',
|
|
123
121
|
path: `/plugin/${this.pluginInstanceId}/export-csv`,
|
|
124
122
|
request_schema: exportCsvBodySchema,
|
|
125
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers
|
|
126
|
-
const
|
|
127
|
-
const { filters, sort } = payload;
|
|
123
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
|
|
124
|
+
const { filters, sort, selectedIds } = body;
|
|
128
125
|
if (!filters || !sort) {
|
|
129
126
|
return { ok: false, error: 'Missing filters or sort in request body' };
|
|
130
127
|
}
|
|
@@ -139,39 +136,19 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
139
136
|
if (rawFilterError) {
|
|
140
137
|
return rawFilterError;
|
|
141
138
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
&& col.type !== AdminForthDataTypes.BOOLEAN;
|
|
156
|
-
});
|
|
157
|
-
const fields = columns.map((col) => col.name);
|
|
158
|
-
const rows = data.data.map((row) => {
|
|
159
|
-
return columns.map((col) => {
|
|
160
|
-
var _a;
|
|
161
|
-
const value = row[col.name];
|
|
162
|
-
if (col.type === AdminForthDataTypes.JSON || ((_a = col.isArray) === null || _a === void 0 ? void 0 : _a.enabled)) {
|
|
163
|
-
return value == null ? value : JSON.stringify(value);
|
|
164
|
-
}
|
|
165
|
-
return value;
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
this.tryToAuditLogAction('export', `Export CSV with filters: ${JSON.stringify(filters)} and sort: ${JSON.stringify(sort)}. Total records: ${rows.length}`, adminUser, headers);
|
|
169
|
-
return {
|
|
170
|
-
data: { fields, data: rows },
|
|
171
|
-
columnsToForceQuote,
|
|
172
|
-
exportedCount: data.total,
|
|
173
|
-
ok: true
|
|
174
|
-
};
|
|
139
|
+
let effectiveFilters = filters;
|
|
140
|
+
if (Array.isArray(selectedIds) && selectedIds.length > 0) {
|
|
141
|
+
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
142
|
+
if (!primaryKeyColumn) {
|
|
143
|
+
return { ok: false, error: 'Cannot export selected records: resource has no primary key' };
|
|
144
|
+
}
|
|
145
|
+
effectiveFilters = [{
|
|
146
|
+
field: primaryKeyColumn.name,
|
|
147
|
+
operator: AdminForthFilterOperators.IN,
|
|
148
|
+
value: selectedIds,
|
|
149
|
+
}];
|
|
150
|
+
}
|
|
151
|
+
return this.exportCsv(effectiveFilters, sort, { adminUser, headers });
|
|
175
152
|
})
|
|
176
153
|
});
|
|
177
154
|
server.endpoint({
|
|
@@ -179,8 +156,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
179
156
|
path: `/plugin/${this.pluginInstanceId}/import-csv`,
|
|
180
157
|
request_schema: importCsvBodySchema,
|
|
181
158
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, query, headers, cookies, requestUrl, response }) {
|
|
182
|
-
const
|
|
183
|
-
const { data } = payload;
|
|
159
|
+
const { data } = body;
|
|
184
160
|
if (!data || typeof data !== 'object') {
|
|
185
161
|
return { ok: false, error: 'Invalid data format. Expected an object with column names as keys and arrays of values as values.' };
|
|
186
162
|
}
|
|
@@ -191,61 +167,12 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
191
167
|
if (!createEditAccess.ok) {
|
|
192
168
|
return { ok: false, error: createEditAccess.error };
|
|
193
169
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
201
|
-
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
202
|
-
console.log('Prepared rows for import:', rows);
|
|
203
|
-
this.tryToAuditLogAction('import', `Import CSV with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
204
|
-
let importedCount = 0;
|
|
205
|
-
let updatedCount = 0;
|
|
206
|
-
const limit = pLimit(100);
|
|
207
|
-
yield Promise.all(rows.map((row) => limit(() => __awaiter(this, void 0, void 0, function* () {
|
|
208
|
-
try {
|
|
209
|
-
const rowErrors = yield this.isRowValid(row);
|
|
210
|
-
if (rowErrors.length > 0) {
|
|
211
|
-
errors.push(...rowErrors);
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
const recordId = primaryKeyColumn ? row[primaryKeyColumn.name] : undefined;
|
|
215
|
-
if (primaryKeyColumn && recordId) {
|
|
216
|
-
const existingRecord = yield this.adminforth.resource(this.resourceConfig.resourceId)
|
|
217
|
-
.list([Filters.EQ(primaryKeyColumn.name, recordId)]);
|
|
218
|
-
if (existingRecord.length > 0) {
|
|
219
|
-
const connector = this.adminforth.connectors[resource.dataSource];
|
|
220
|
-
const oldRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
|
|
221
|
-
if (!oldRecord) {
|
|
222
|
-
const primaryKeyColumn = resource.columns.find((col) => col.primaryKey);
|
|
223
|
-
return { error: `Record with ${primaryKeyColumn.name} ${recordId} not found` };
|
|
224
|
-
}
|
|
225
|
-
const { error } = yield this.adminforth.updateResourceRecord({
|
|
226
|
-
resource, updates: row, adminUser, oldRecord, recordId, response,
|
|
227
|
-
extra: { body, query, headers, cookies, requestUrl, response }
|
|
228
|
-
});
|
|
229
|
-
if (error) {
|
|
230
|
-
return { error };
|
|
231
|
-
}
|
|
232
|
-
updatedCount++;
|
|
233
|
-
return;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
yield this.adminforth.createResourceRecord({
|
|
237
|
-
resource: resource,
|
|
238
|
-
record: row,
|
|
239
|
-
adminUser: adminUser,
|
|
240
|
-
extra: { body, query, headers, cookies, requestUrl, response }
|
|
241
|
-
});
|
|
242
|
-
importedCount++;
|
|
243
|
-
}
|
|
244
|
-
catch (e) {
|
|
245
|
-
errors.push(e.message);
|
|
246
|
-
}
|
|
247
|
-
}))));
|
|
248
|
-
return { ok: true, importedCount, updatedCount, errors };
|
|
170
|
+
return this.importCsv(data, {
|
|
171
|
+
adminUser,
|
|
172
|
+
headers,
|
|
173
|
+
response,
|
|
174
|
+
extra: { body, query, headers, cookies, requestUrl, response },
|
|
175
|
+
});
|
|
249
176
|
})
|
|
250
177
|
});
|
|
251
178
|
server.endpoint({
|
|
@@ -253,8 +180,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
253
180
|
path: `/plugin/${this.pluginInstanceId}/import-csv-new-only`,
|
|
254
181
|
request_schema: importCsvBodySchema,
|
|
255
182
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, query, headers, cookies, requestUrl, response }) {
|
|
256
|
-
const
|
|
257
|
-
const { data } = payload;
|
|
183
|
+
const { data } = body;
|
|
258
184
|
if (!data || typeof data !== 'object') {
|
|
259
185
|
return { ok: false, error: 'Invalid data format. Expected an object with column names as keys and arrays of values as values.' };
|
|
260
186
|
}
|
|
@@ -262,52 +188,19 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
262
188
|
if (!access.ok) {
|
|
263
189
|
return { ok: false, error: access.error };
|
|
264
190
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
}
|
|
271
|
-
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
272
|
-
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
273
|
-
this.tryToAuditLogAction('import', `Import CSV (new only) with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
274
|
-
let importedCount = 0;
|
|
275
|
-
const limit = pLimit(100);
|
|
276
|
-
yield Promise.all(rows.map((row) => limit(() => __awaiter(this, void 0, void 0, function* () {
|
|
277
|
-
try {
|
|
278
|
-
const rowErrors = yield this.isRowValid(row);
|
|
279
|
-
if (rowErrors.length > 0) {
|
|
280
|
-
errors.push(...rowErrors);
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
if (primaryKeyColumn && row[primaryKeyColumn.name]) {
|
|
284
|
-
const existingRecord = yield this.adminforth.resource(this.resourceConfig.resourceId)
|
|
285
|
-
.list([Filters.EQ(primaryKeyColumn.name, row[primaryKeyColumn.name])]);
|
|
286
|
-
if (existingRecord.length > 0) {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
yield this.adminforth.createResourceRecord({
|
|
291
|
-
resource: resource,
|
|
292
|
-
record: row,
|
|
293
|
-
adminUser: adminUser,
|
|
294
|
-
extra: { body, query, headers, cookies, requestUrl, response }
|
|
295
|
-
});
|
|
296
|
-
importedCount++;
|
|
297
|
-
}
|
|
298
|
-
catch (e) {
|
|
299
|
-
errors.push(e.message);
|
|
300
|
-
}
|
|
301
|
-
}))));
|
|
302
|
-
return { ok: true, importedCount, errors };
|
|
191
|
+
return this.importCsvNewOnly(data, {
|
|
192
|
+
adminUser,
|
|
193
|
+
headers,
|
|
194
|
+
extra: { body, query, headers, cookies, requestUrl, response },
|
|
195
|
+
});
|
|
303
196
|
})
|
|
304
197
|
});
|
|
305
198
|
server.endpoint({
|
|
306
199
|
method: 'POST',
|
|
307
200
|
path: `/plugin/${this.pluginInstanceId}/check-records`,
|
|
308
201
|
request_schema: importCsvBodySchema,
|
|
309
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser
|
|
310
|
-
const
|
|
202
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser }) {
|
|
203
|
+
const { data } = body;
|
|
311
204
|
const access = yield this.ensureAnyAllowed(adminUser, [
|
|
312
205
|
{ source: ActionCheckSource.ListRequest, action: AllowedActionsEnum.list },
|
|
313
206
|
{ source: ActionCheckSource.ShowRequest, action: AllowedActionsEnum.show },
|
|
@@ -315,29 +208,198 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
315
208
|
if (!access.ok) {
|
|
316
209
|
return { ok: false, error: access.error };
|
|
317
210
|
}
|
|
318
|
-
|
|
319
|
-
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
320
|
-
const columns = this.getColumnNames(data);
|
|
321
|
-
const rows = this.buildRowsFromData(data, columns, undefined, { coerceTypes: false });
|
|
322
|
-
const primaryKeys = rows
|
|
323
|
-
.map(row => primaryKeyColumn ? row[primaryKeyColumn.name] : undefined)
|
|
324
|
-
.filter(key => key !== undefined && key !== null && key !== '');
|
|
325
|
-
const existingRecords = yield this.adminforth
|
|
326
|
-
.resource(this.resourceConfig.resourceId)
|
|
327
|
-
.list([{
|
|
328
|
-
field: primaryKeyColumn.name,
|
|
329
|
-
operator: AdminForthFilterOperators.IN,
|
|
330
|
-
value: primaryKeys,
|
|
331
|
-
}]);
|
|
332
|
-
return {
|
|
333
|
-
ok: true,
|
|
334
|
-
total: rows.length,
|
|
335
|
-
existingCount: existingRecords.length,
|
|
336
|
-
newCount: rows.length - existingRecords.length,
|
|
337
|
-
};
|
|
211
|
+
return this.checkRecords(data);
|
|
338
212
|
})
|
|
339
213
|
});
|
|
340
214
|
}
|
|
215
|
+
/**
|
|
216
|
+
* Export resource records as CSV-ready data.
|
|
217
|
+
* Can be called programmatically, e.g. `this.exportCsv(filters, sort)`.
|
|
218
|
+
*/
|
|
219
|
+
exportCsv(filters_1, sort_1) {
|
|
220
|
+
return __awaiter(this, arguments, void 0, function* (filters, sort, options = {}) {
|
|
221
|
+
const { adminUser, headers } = options;
|
|
222
|
+
const connector = this.adminforth.connectors[this.resourceConfig.dataSource];
|
|
223
|
+
const data = yield connector.getData({
|
|
224
|
+
resource: this.resourceConfig,
|
|
225
|
+
limit: 1e6,
|
|
226
|
+
offset: 0,
|
|
227
|
+
filters: connector.validateAndNormalizeInputFilters(filters),
|
|
228
|
+
sort,
|
|
229
|
+
getTotals: true,
|
|
230
|
+
});
|
|
231
|
+
// prepare data for PapaParse unparse
|
|
232
|
+
const columns = this.resourceConfig.columns.filter((col) => !col.virtual && !col.backendOnly);
|
|
233
|
+
const columnsToForceQuote = columns.map(col => {
|
|
234
|
+
return col.type !== AdminForthDataTypes.FLOAT
|
|
235
|
+
&& col.type !== AdminForthDataTypes.INTEGER
|
|
236
|
+
&& col.type !== AdminForthDataTypes.BOOLEAN;
|
|
237
|
+
});
|
|
238
|
+
const fields = columns.map((col) => col.name);
|
|
239
|
+
const rows = data.data.map((row) => {
|
|
240
|
+
return columns.map((col) => {
|
|
241
|
+
var _a;
|
|
242
|
+
const value = row[col.name];
|
|
243
|
+
if (col.type === AdminForthDataTypes.JSON || ((_a = col.isArray) === null || _a === void 0 ? void 0 : _a.enabled)) {
|
|
244
|
+
return value == null ? value : JSON.stringify(value);
|
|
245
|
+
}
|
|
246
|
+
return value;
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
if (adminUser) {
|
|
250
|
+
this.tryToAuditLogAction('export', `Export CSV with filters: ${JSON.stringify(filters)} and sort: ${JSON.stringify(sort)}. Total records: ${rows.length}`, adminUser, headers);
|
|
251
|
+
}
|
|
252
|
+
return {
|
|
253
|
+
ok: true,
|
|
254
|
+
data: { fields, data: rows },
|
|
255
|
+
columnsToForceQuote,
|
|
256
|
+
exportedCount: data.total,
|
|
257
|
+
};
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Import records from column-oriented data, creating new records and updating
|
|
262
|
+
* existing ones (matched by primary key).
|
|
263
|
+
* Can be called programmatically, e.g. `this.importCsv(data, { adminUser })`.
|
|
264
|
+
*/
|
|
265
|
+
importCsv(data_1) {
|
|
266
|
+
return __awaiter(this, arguments, void 0, function* (data, options = {}) {
|
|
267
|
+
const { adminUser, headers, extra, response } = options;
|
|
268
|
+
const columns = this.getColumnNames(data);
|
|
269
|
+
const { errors, resourceColumns } = this.validateColumns(columns);
|
|
270
|
+
const resource = this.adminforth.config.resources.find(r => r.resourceId === this.resourceConfig.resourceId);
|
|
271
|
+
if (errors.length > 0) {
|
|
272
|
+
return { ok: false, errors };
|
|
273
|
+
}
|
|
274
|
+
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
275
|
+
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
276
|
+
if (adminUser) {
|
|
277
|
+
this.tryToAuditLogAction('import', `Import CSV with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
278
|
+
}
|
|
279
|
+
let importedCount = 0;
|
|
280
|
+
let updatedCount = 0;
|
|
281
|
+
const limit = pLimit(100);
|
|
282
|
+
yield Promise.all(rows.map((row) => limit(() => __awaiter(this, void 0, void 0, function* () {
|
|
283
|
+
try {
|
|
284
|
+
const rowErrors = yield this.isRowValid(row);
|
|
285
|
+
if (rowErrors.length > 0) {
|
|
286
|
+
errors.push(...rowErrors);
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
const recordId = primaryKeyColumn ? row[primaryKeyColumn.name] : undefined;
|
|
290
|
+
if (primaryKeyColumn && recordId) {
|
|
291
|
+
const existingRecord = yield this.adminforth.resource(this.resourceConfig.resourceId)
|
|
292
|
+
.list([Filters.EQ(primaryKeyColumn.name, recordId)]);
|
|
293
|
+
if (existingRecord.length > 0) {
|
|
294
|
+
const connector = this.adminforth.connectors[resource.dataSource];
|
|
295
|
+
const oldRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
|
|
296
|
+
if (!oldRecord) {
|
|
297
|
+
errors.push(`Record with ${primaryKeyColumn.name} ${recordId} not found`);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
const { error } = yield this.adminforth.updateResourceRecord({
|
|
301
|
+
resource, updates: row, adminUser, oldRecord, recordId, response,
|
|
302
|
+
extra,
|
|
303
|
+
});
|
|
304
|
+
if (error) {
|
|
305
|
+
errors.push(error);
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
updatedCount++;
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
yield this.adminforth.createResourceRecord({
|
|
313
|
+
resource: resource,
|
|
314
|
+
record: row,
|
|
315
|
+
adminUser: adminUser,
|
|
316
|
+
extra,
|
|
317
|
+
});
|
|
318
|
+
importedCount++;
|
|
319
|
+
}
|
|
320
|
+
catch (e) {
|
|
321
|
+
errors.push(e.message);
|
|
322
|
+
}
|
|
323
|
+
}))));
|
|
324
|
+
return { ok: true, importedCount, updatedCount, errors };
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Import only records that do not already exist (matched by primary key).
|
|
329
|
+
* Can be called programmatically, e.g. `this.importCsvNewOnly(data, { adminUser })`.
|
|
330
|
+
*/
|
|
331
|
+
importCsvNewOnly(data_1) {
|
|
332
|
+
return __awaiter(this, arguments, void 0, function* (data, options = {}) {
|
|
333
|
+
const { adminUser, headers, extra } = options;
|
|
334
|
+
const columns = this.getColumnNames(data);
|
|
335
|
+
const resource = this.adminforth.config.resources.find(r => r.resourceId === this.resourceConfig.resourceId);
|
|
336
|
+
const { errors, resourceColumns } = this.validateColumns(columns);
|
|
337
|
+
if (errors.length > 0) {
|
|
338
|
+
return { ok: false, errors };
|
|
339
|
+
}
|
|
340
|
+
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
341
|
+
const rows = this.buildRowsFromData(data, columns, resourceColumns, { coerceTypes: true });
|
|
342
|
+
if (adminUser) {
|
|
343
|
+
this.tryToAuditLogAction('import', `Import CSV (new only) with ${Object.keys(data).length} columns`, adminUser, headers);
|
|
344
|
+
}
|
|
345
|
+
let importedCount = 0;
|
|
346
|
+
const limit = pLimit(100);
|
|
347
|
+
yield Promise.all(rows.map((row) => limit(() => __awaiter(this, void 0, void 0, function* () {
|
|
348
|
+
try {
|
|
349
|
+
const rowErrors = yield this.isRowValid(row);
|
|
350
|
+
if (rowErrors.length > 0) {
|
|
351
|
+
errors.push(...rowErrors);
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
if (primaryKeyColumn && row[primaryKeyColumn.name]) {
|
|
355
|
+
const existingRecord = yield this.adminforth.resource(this.resourceConfig.resourceId)
|
|
356
|
+
.list([Filters.EQ(primaryKeyColumn.name, row[primaryKeyColumn.name])]);
|
|
357
|
+
if (existingRecord.length > 0) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
yield this.adminforth.createResourceRecord({
|
|
362
|
+
resource: resource,
|
|
363
|
+
record: row,
|
|
364
|
+
adminUser: adminUser,
|
|
365
|
+
extra,
|
|
366
|
+
});
|
|
367
|
+
importedCount++;
|
|
368
|
+
}
|
|
369
|
+
catch (e) {
|
|
370
|
+
errors.push(e.message);
|
|
371
|
+
}
|
|
372
|
+
}))));
|
|
373
|
+
return { ok: true, importedCount, errors };
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Check how many of the given records already exist (matched by primary key).
|
|
378
|
+
* Can be called programmatically, e.g. `this.checkRecords(data)`.
|
|
379
|
+
*/
|
|
380
|
+
checkRecords(data) {
|
|
381
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
382
|
+
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
383
|
+
const columns = this.getColumnNames(data);
|
|
384
|
+
const rows = this.buildRowsFromData(data, columns, undefined, { coerceTypes: false });
|
|
385
|
+
const primaryKeys = rows
|
|
386
|
+
.map(row => primaryKeyColumn ? row[primaryKeyColumn.name] : undefined)
|
|
387
|
+
.filter(key => key !== undefined && key !== null && key !== '');
|
|
388
|
+
const existingRecords = yield this.adminforth
|
|
389
|
+
.resource(this.resourceConfig.resourceId)
|
|
390
|
+
.list([{
|
|
391
|
+
field: primaryKeyColumn.name,
|
|
392
|
+
operator: AdminForthFilterOperators.IN,
|
|
393
|
+
value: primaryKeys,
|
|
394
|
+
}]);
|
|
395
|
+
return {
|
|
396
|
+
ok: true,
|
|
397
|
+
total: rows.length,
|
|
398
|
+
existingCount: existingRecords.length,
|
|
399
|
+
newCount: rows.length - existingRecords.length,
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
}
|
|
341
403
|
getColumnNames(data) {
|
|
342
404
|
return Object.keys(data !== null && data !== void 0 ? data : {});
|
|
343
405
|
}
|