@adminforth/import-export 1.5.4 → 1.6.1
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/dist/index.js +51 -8
- package/index.ts +47 -8
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -7,8 +7,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
-
import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth";
|
|
10
|
+
import { AdminForthPlugin, parseBody, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth";
|
|
11
11
|
import pLimit from 'p-limit';
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
const exportCsvBodySchema = z.object({
|
|
14
|
+
filters: z.any(),
|
|
15
|
+
sort: z.any(),
|
|
16
|
+
}).strict();
|
|
17
|
+
const importCsvBodySchema = z.object({
|
|
18
|
+
data: z.record(z.string(), z.array(z.unknown())),
|
|
19
|
+
}).strict();
|
|
12
20
|
export default class ImportExport extends AdminForthPlugin {
|
|
13
21
|
constructor(options) {
|
|
14
22
|
super(options, import.meta.url);
|
|
@@ -113,8 +121,12 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
113
121
|
server.endpoint({
|
|
114
122
|
method: 'POST',
|
|
115
123
|
path: `/plugin/${this.pluginInstanceId}/export-csv`,
|
|
116
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers }) {
|
|
117
|
-
const
|
|
124
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, headers, response }) {
|
|
125
|
+
const parsed = parseBody(exportCsvBodySchema, body, response);
|
|
126
|
+
if ('error' in parsed)
|
|
127
|
+
return parsed.error;
|
|
128
|
+
const payload = parsed.data;
|
|
129
|
+
const { filters, sort } = payload;
|
|
118
130
|
if (!filters || !sort) {
|
|
119
131
|
return { ok: false, error: 'Missing filters or sort in request body' };
|
|
120
132
|
}
|
|
@@ -146,7 +158,14 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
146
158
|
});
|
|
147
159
|
const fields = columns.map((col) => col.name);
|
|
148
160
|
const rows = data.data.map((row) => {
|
|
149
|
-
return columns.map((col) =>
|
|
161
|
+
return columns.map((col) => {
|
|
162
|
+
var _a;
|
|
163
|
+
const value = row[col.name];
|
|
164
|
+
if (col.type === AdminForthDataTypes.JSON || ((_a = col.isArray) === null || _a === void 0 ? void 0 : _a.enabled)) {
|
|
165
|
+
return value == null ? value : JSON.stringify(value);
|
|
166
|
+
}
|
|
167
|
+
return value;
|
|
168
|
+
});
|
|
150
169
|
});
|
|
151
170
|
this.tryToAuditLogAction('export', `Export CSV with filters: ${JSON.stringify(filters)} and sort: ${JSON.stringify(sort)}. Total records: ${rows.length}`, adminUser, headers);
|
|
152
171
|
return {
|
|
@@ -161,7 +180,11 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
161
180
|
method: 'POST',
|
|
162
181
|
path: `/plugin/${this.pluginInstanceId}/import-csv`,
|
|
163
182
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, query, headers, cookies, requestUrl, response }) {
|
|
164
|
-
const
|
|
183
|
+
const parsed = parseBody(importCsvBodySchema, body, response);
|
|
184
|
+
if ('error' in parsed)
|
|
185
|
+
return parsed.error;
|
|
186
|
+
const payload = parsed.data;
|
|
187
|
+
const { data } = payload;
|
|
165
188
|
if (!data || typeof data !== 'object') {
|
|
166
189
|
return { ok: false, error: 'Invalid data format. Expected an object with column names as keys and arrays of values as values.' };
|
|
167
190
|
}
|
|
@@ -233,7 +256,11 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
233
256
|
method: 'POST',
|
|
234
257
|
path: `/plugin/${this.pluginInstanceId}/import-csv-new-only`,
|
|
235
258
|
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, query, headers, cookies, requestUrl, response }) {
|
|
236
|
-
const
|
|
259
|
+
const parsed = parseBody(importCsvBodySchema, body, response);
|
|
260
|
+
if ('error' in parsed)
|
|
261
|
+
return parsed.error;
|
|
262
|
+
const payload = parsed.data;
|
|
263
|
+
const { data } = payload;
|
|
237
264
|
if (!data || typeof data !== 'object') {
|
|
238
265
|
return { ok: false, error: 'Invalid data format. Expected an object with column names as keys and arrays of values as values.' };
|
|
239
266
|
}
|
|
@@ -284,7 +311,11 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
284
311
|
server.endpoint({
|
|
285
312
|
method: 'POST',
|
|
286
313
|
path: `/plugin/${this.pluginInstanceId}/check-records`,
|
|
287
|
-
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser }) {
|
|
314
|
+
handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, adminUser, response }) {
|
|
315
|
+
const parsed = parseBody(importCsvBodySchema, body, response);
|
|
316
|
+
if ('error' in parsed)
|
|
317
|
+
return parsed.error;
|
|
318
|
+
const payload = parsed.data;
|
|
288
319
|
const access = yield this.ensureAnyAllowed(adminUser, [
|
|
289
320
|
{ source: ActionCheckSource.ListRequest, action: AllowedActionsEnum.list },
|
|
290
321
|
{ source: ActionCheckSource.ShowRequest, action: AllowedActionsEnum.show },
|
|
@@ -292,7 +323,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
292
323
|
if (!access.ok) {
|
|
293
324
|
return { ok: false, error: access.error };
|
|
294
325
|
}
|
|
295
|
-
const { data } =
|
|
326
|
+
const { data } = payload;
|
|
296
327
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
297
328
|
const columns = this.getColumnNames(data);
|
|
298
329
|
const rows = this.buildRowsFromData(data, columns, undefined, { coerceTypes: false });
|
|
@@ -355,6 +386,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
355
386
|
return rows;
|
|
356
387
|
}
|
|
357
388
|
coerceValue(resourceCol, val) {
|
|
389
|
+
var _a;
|
|
358
390
|
if (!resourceCol || val === '') {
|
|
359
391
|
return val;
|
|
360
392
|
}
|
|
@@ -368,6 +400,17 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
368
400
|
}
|
|
369
401
|
return val === 1 || val === true;
|
|
370
402
|
}
|
|
403
|
+
if (resourceCol.type === AdminForthDataTypes.JSON || ((_a = resourceCol.isArray) === null || _a === void 0 ? void 0 : _a.enabled)) {
|
|
404
|
+
if (typeof val === 'string') {
|
|
405
|
+
try {
|
|
406
|
+
return JSON.parse(val);
|
|
407
|
+
}
|
|
408
|
+
catch (_b) {
|
|
409
|
+
return val;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
return val;
|
|
413
|
+
}
|
|
371
414
|
return val;
|
|
372
415
|
}
|
|
373
416
|
}
|
package/index.ts
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import { AdminForthPlugin, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth";
|
|
1
|
+
import { AdminForthPlugin, parseBody, suggestIfTypo, AdminForthFilterOperators, Filters, AdminForthDataTypes, rejectApiRawFilters, interpretResource, ActionCheckSource, AllowedActionsEnum } from "adminforth";
|
|
2
2
|
import type { IAdminForth, IHttpServer, AdminForthResourceColumn, AdminForthComponentDeclaration, AdminForthResource, AdminUser } from "adminforth";
|
|
3
3
|
import type { PluginOptions } from './types.js';
|
|
4
4
|
import pLimit from 'p-limit';
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
const exportCsvBodySchema = z.object({
|
|
8
|
+
filters: z.any(),
|
|
9
|
+
sort: z.any(),
|
|
10
|
+
}).strict();
|
|
11
|
+
|
|
12
|
+
const importCsvBodySchema = z.object({
|
|
13
|
+
data: z.record(z.string(), z.array(z.unknown())),
|
|
14
|
+
}).strict();
|
|
5
15
|
|
|
6
16
|
export default class ImportExport extends AdminForthPlugin {
|
|
7
17
|
options: PluginOptions;
|
|
@@ -127,8 +137,11 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
127
137
|
server.endpoint({
|
|
128
138
|
method: 'POST',
|
|
129
139
|
path: `/plugin/${this.pluginInstanceId}/export-csv`,
|
|
130
|
-
handler: async ({ body, adminUser, headers }) => {
|
|
131
|
-
const
|
|
140
|
+
handler: async ({ body, adminUser, headers, response }) => {
|
|
141
|
+
const parsed = parseBody(exportCsvBodySchema, body, response);
|
|
142
|
+
if ('error' in parsed) return parsed.error;
|
|
143
|
+
const payload = parsed.data;
|
|
144
|
+
const { filters, sort } = payload;
|
|
132
145
|
if (!filters || !sort) {
|
|
133
146
|
return { ok: false, error: 'Missing filters or sort in request body' };
|
|
134
147
|
}
|
|
@@ -168,7 +181,13 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
168
181
|
const fields = columns.map((col) => col.name);
|
|
169
182
|
|
|
170
183
|
const rows = data.data.map((row) => {
|
|
171
|
-
return columns.map((col) =>
|
|
184
|
+
return columns.map((col) => {
|
|
185
|
+
const value = row[col.name];
|
|
186
|
+
if (col.type === AdminForthDataTypes.JSON || col.isArray?.enabled) {
|
|
187
|
+
return value == null ? value : JSON.stringify(value);
|
|
188
|
+
}
|
|
189
|
+
return value;
|
|
190
|
+
});
|
|
172
191
|
});
|
|
173
192
|
|
|
174
193
|
this.tryToAuditLogAction('export', `Export CSV with filters: ${JSON.stringify(filters)} and sort: ${JSON.stringify(sort)}. Total records: ${rows.length}`, adminUser, headers);
|
|
@@ -186,7 +205,10 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
186
205
|
method: 'POST',
|
|
187
206
|
path: `/plugin/${this.pluginInstanceId}/import-csv`,
|
|
188
207
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
189
|
-
const
|
|
208
|
+
const parsed = parseBody(importCsvBodySchema, body, response);
|
|
209
|
+
if ('error' in parsed) return parsed.error;
|
|
210
|
+
const payload = parsed.data;
|
|
211
|
+
const { data } = payload;
|
|
190
212
|
if (!data || typeof data !== 'object') {
|
|
191
213
|
return { ok: false, error: 'Invalid data format. Expected an object with column names as keys and arrays of values as values.' };
|
|
192
214
|
}
|
|
@@ -268,7 +290,10 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
268
290
|
method: 'POST',
|
|
269
291
|
path: `/plugin/${this.pluginInstanceId}/import-csv-new-only`,
|
|
270
292
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
271
|
-
const
|
|
293
|
+
const parsed = parseBody(importCsvBodySchema, body, response);
|
|
294
|
+
if ('error' in parsed) return parsed.error;
|
|
295
|
+
const payload = parsed.data;
|
|
296
|
+
const { data } = payload;
|
|
272
297
|
if (!data || typeof data !== 'object') {
|
|
273
298
|
return { ok: false, error: 'Invalid data format. Expected an object with column names as keys and arrays of values as values.' };
|
|
274
299
|
}
|
|
@@ -328,7 +353,10 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
328
353
|
server.endpoint({
|
|
329
354
|
method: 'POST',
|
|
330
355
|
path: `/plugin/${this.pluginInstanceId}/check-records`,
|
|
331
|
-
handler: async ({ body, adminUser }) => {
|
|
356
|
+
handler: async ({ body, adminUser, response }) => {
|
|
357
|
+
const parsed = parseBody(importCsvBodySchema, body, response);
|
|
358
|
+
if ('error' in parsed) return parsed.error;
|
|
359
|
+
const payload = parsed.data;
|
|
332
360
|
const access = await this.ensureAnyAllowed(
|
|
333
361
|
adminUser,
|
|
334
362
|
[
|
|
@@ -340,7 +368,7 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
340
368
|
if (!access.ok) {
|
|
341
369
|
return { ok: false, error: access.error };
|
|
342
370
|
}
|
|
343
|
-
const { data } =
|
|
371
|
+
const { data } = payload;
|
|
344
372
|
const primaryKeyColumn = this.resourceConfig.columns.find(col => col.primaryKey);
|
|
345
373
|
const columns = this.getColumnNames(data);
|
|
346
374
|
const rows = this.buildRowsFromData(data, columns, undefined, { coerceTypes: false });
|
|
@@ -446,6 +474,17 @@ export default class ImportExport extends AdminForthPlugin {
|
|
|
446
474
|
return val === 1 || val === true;
|
|
447
475
|
}
|
|
448
476
|
|
|
477
|
+
if (resourceCol.type === AdminForthDataTypes.JSON || resourceCol.isArray?.enabled) {
|
|
478
|
+
if (typeof val === 'string') {
|
|
479
|
+
try {
|
|
480
|
+
return JSON.parse(val);
|
|
481
|
+
} catch {
|
|
482
|
+
return val;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
return val;
|
|
486
|
+
}
|
|
487
|
+
|
|
449
488
|
return val;
|
|
450
489
|
}
|
|
451
490
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adminforth/import-export",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"license": "MIT",
|
|
26
26
|
"description": "CSV import/export plugin for adminforth",
|
|
27
27
|
"peerDependencies": {
|
|
28
|
-
"adminforth": "^3.
|
|
28
|
+
"adminforth": "^3.7.1"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@types/node": "^22.10.7",
|
|
32
|
-
"adminforth": "^3.
|
|
32
|
+
"adminforth": "^3.7.1",
|
|
33
33
|
"semantic-release": "^24.2.1",
|
|
34
34
|
"semantic-release-slack-bot": "^4.0.2",
|
|
35
35
|
"typescript": "^5.7.3"
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
]
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"p-limit": "^7.3.0"
|
|
63
|
+
"p-limit": "^7.3.0",
|
|
64
|
+
"zod": "^4.3.6"
|
|
64
65
|
}
|
|
65
66
|
}
|