@drax/crud-back 0.4.0 → 0.5.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/controllers/AbstractFastifyController.js +113 -44
- package/dist/exports/AbstractExport.js +41 -0
- package/dist/exports/ExportCsv.js +86 -0
- package/dist/exports/ExportJson.js +51 -0
- package/dist/repository/AbstractMongoRepository.js +11 -0
- package/dist/services/AbstractService.js +44 -0
- package/dist/workers/ExportCsvWorker.js +12 -0
- package/package.json +8 -6
- package/src/controllers/AbstractFastifyController.ts +130 -46
- package/src/exports/AbstractExport.ts +74 -0
- package/src/exports/ExportCsv.ts +107 -0
- package/src/exports/ExportJson.ts +64 -0
- package/src/index.ts +0 -3
- package/src/repository/AbstractMongoRepository.ts +25 -5
- package/src/repository/AbstractSqliteRepository.ts +1 -1
- package/src/services/AbstractService.ts +81 -10
- package/src/workers/ExportCsvWorker.js +12 -0
- package/src/workers/ExportCsvWorker.ts +12 -0
- package/test/_mocks/MockRepository.ts +58 -0
- package/test/exports/ExportCsv.test.ts +137 -0
- package/test/services/AbstractService.test.ts +40 -0
- package/test/workers/ExportCsvWorker.test.ts +92 -0
- package/tsconfig.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
- package/types/controllers/AbstractFastifyController.d.ts +19 -7
- package/types/controllers/AbstractFastifyController.d.ts.map +1 -1
- package/types/exports/AbstractExport.d.ts +23 -0
- package/types/exports/AbstractExport.d.ts.map +1 -0
- package/types/exports/ExportCsv.d.ts +13 -0
- package/types/exports/ExportCsv.d.ts.map +1 -0
- package/types/exports/ExportFsCsv.d.ts +17 -0
- package/types/exports/ExportFsCsv.d.ts.map +1 -0
- package/types/exports/ExportJson.d.ts +8 -0
- package/types/exports/ExportJson.d.ts.map +1 -0
- package/types/index.d.ts +0 -2
- package/types/index.d.ts.map +1 -1
- package/types/interfaces/ICrudRepository.d.ts +2 -1
- package/types/interfaces/ICrudRepository.d.ts.map +1 -1
- package/types/repository/AbstractMongoRepository.d.ts +3 -3
- package/types/repository/AbstractMongoRepository.d.ts.map +1 -1
- package/types/repository/AbstractSqliteRepository.d.ts +1 -1
- package/types/repository/AbstractSqliteRepository.d.ts.map +1 -1
- package/types/services/AbstractService.d.ts +8 -5
- package/types/services/AbstractService.d.ts.map +1 -1
- package/types/workers/ExportCsvWorker.d.ts +2 -0
- package/types/workers/ExportCsvWorker.d.ts.map +1 -0
- package/src/interfaces/ICrudRepository.ts +0 -16
- package/src/interfaces/IEntityPermission.ts +0 -10
|
@@ -1,20 +1,65 @@
|
|
|
1
|
-
import { ValidationError } from "@drax/common-back";
|
|
1
|
+
import { CommonConfig, DraxConfig, ValidationError } from "@drax/common-back";
|
|
2
2
|
import { UnauthorizedError } from "@drax/identity-back";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
const BASE_FILE_DIR = DraxConfig.getOrLoad(CommonConfig.FileDir) || 'files';
|
|
5
|
+
const BASE_URL = DraxConfig.getOrLoad(CommonConfig.BaseUrl) ? DraxConfig.get(CommonConfig.BaseUrl).replace(/\/$/, '') : '';
|
|
3
6
|
class AbstractFastifyController {
|
|
4
7
|
constructor(service, permission) {
|
|
5
8
|
this.service = service;
|
|
6
9
|
this.permission = permission;
|
|
7
10
|
console.log("AbstractFastifyController created. Permissions", this.permission);
|
|
8
11
|
}
|
|
9
|
-
|
|
12
|
+
parseFilters(stringFilters) {
|
|
10
13
|
try {
|
|
11
|
-
|
|
14
|
+
if (!stringFilters) {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
const filterArray = stringFilters.split(";");
|
|
18
|
+
const filters = [];
|
|
19
|
+
filterArray.forEach((filter) => {
|
|
20
|
+
const [field, operator, value] = filter.split(",");
|
|
21
|
+
filters.push({ field, operator, value });
|
|
22
|
+
});
|
|
23
|
+
return filters;
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.error(e);
|
|
27
|
+
throw e;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async create(request, reply) {
|
|
31
|
+
try {
|
|
32
|
+
request.rbac.assertPermission(this.permission.Create);
|
|
33
|
+
const payload = request.body;
|
|
34
|
+
let item = await this.service.create(payload);
|
|
35
|
+
return item;
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.error(e);
|
|
39
|
+
if (e instanceof ValidationError) {
|
|
40
|
+
reply.statusCode = e.statusCode;
|
|
41
|
+
reply.send({ error: e.message, inputErrors: e.errors });
|
|
42
|
+
}
|
|
43
|
+
else if (e instanceof UnauthorizedError) {
|
|
44
|
+
reply.statusCode = e.statusCode;
|
|
45
|
+
reply.send({ error: e.message });
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
reply.statusCode = 500;
|
|
49
|
+
reply.send({ error: 'INTERNAL_SERVER_ERROR' });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async update(request, reply) {
|
|
54
|
+
try {
|
|
55
|
+
request.rbac.assertPermission(this.permission.Update);
|
|
12
56
|
if (!request.params.id) {
|
|
13
57
|
reply.statusCode = 400;
|
|
14
58
|
reply.send({ error: 'BAD REQUEST' });
|
|
15
59
|
}
|
|
16
60
|
const id = request.params.id;
|
|
17
|
-
|
|
61
|
+
const payload = request.body;
|
|
62
|
+
let item = await this.service.update(id, payload);
|
|
18
63
|
return item;
|
|
19
64
|
}
|
|
20
65
|
catch (e) {
|
|
@@ -33,16 +78,16 @@ class AbstractFastifyController {
|
|
|
33
78
|
}
|
|
34
79
|
}
|
|
35
80
|
}
|
|
36
|
-
async
|
|
81
|
+
async delete(request, reply) {
|
|
37
82
|
try {
|
|
38
|
-
request.rbac.assertPermission(this.permission.
|
|
39
|
-
if (!request.params.
|
|
83
|
+
request.rbac.assertPermission(this.permission.Delete);
|
|
84
|
+
if (!request.params.id) {
|
|
40
85
|
reply.statusCode = 400;
|
|
41
86
|
reply.send({ error: 'BAD REQUEST' });
|
|
42
87
|
}
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
88
|
+
const id = request.params.id;
|
|
89
|
+
await this.service.delete(id);
|
|
90
|
+
reply.send({ message: 'Item deleted successfully' });
|
|
46
91
|
}
|
|
47
92
|
catch (e) {
|
|
48
93
|
console.error(e);
|
|
@@ -60,11 +105,15 @@ class AbstractFastifyController {
|
|
|
60
105
|
}
|
|
61
106
|
}
|
|
62
107
|
}
|
|
63
|
-
async
|
|
108
|
+
async findById(request, reply) {
|
|
64
109
|
try {
|
|
65
110
|
request.rbac.assertPermission(this.permission.View);
|
|
66
|
-
|
|
67
|
-
|
|
111
|
+
if (!request.params.id) {
|
|
112
|
+
reply.statusCode = 400;
|
|
113
|
+
reply.send({ error: 'BAD REQUEST' });
|
|
114
|
+
}
|
|
115
|
+
const id = request.params.id;
|
|
116
|
+
let item = await this.service.findById(id);
|
|
68
117
|
return item;
|
|
69
118
|
}
|
|
70
119
|
catch (e) {
|
|
@@ -83,16 +132,16 @@ class AbstractFastifyController {
|
|
|
83
132
|
}
|
|
84
133
|
}
|
|
85
134
|
}
|
|
86
|
-
async
|
|
135
|
+
async findByIds(request, reply) {
|
|
87
136
|
try {
|
|
88
137
|
request.rbac.assertPermission(this.permission.View);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const
|
|
94
|
-
let
|
|
95
|
-
return
|
|
138
|
+
if (!request.params.ids) {
|
|
139
|
+
reply.statusCode = 400;
|
|
140
|
+
reply.send({ error: 'BAD REQUEST' });
|
|
141
|
+
}
|
|
142
|
+
const ids = request.params.ids.split(",");
|
|
143
|
+
let items = await this.service.findByIds(ids);
|
|
144
|
+
return items;
|
|
96
145
|
}
|
|
97
146
|
catch (e) {
|
|
98
147
|
console.error(e);
|
|
@@ -110,11 +159,11 @@ class AbstractFastifyController {
|
|
|
110
159
|
}
|
|
111
160
|
}
|
|
112
161
|
}
|
|
113
|
-
async
|
|
162
|
+
async search(request, reply) {
|
|
114
163
|
try {
|
|
115
|
-
request.rbac.assertPermission(this.permission.
|
|
116
|
-
const
|
|
117
|
-
let item = await this.service.
|
|
164
|
+
request.rbac.assertPermission(this.permission.View);
|
|
165
|
+
const search = request.query.search;
|
|
166
|
+
let item = await this.service.search(search);
|
|
118
167
|
return item;
|
|
119
168
|
}
|
|
120
169
|
catch (e) {
|
|
@@ -133,17 +182,17 @@ class AbstractFastifyController {
|
|
|
133
182
|
}
|
|
134
183
|
}
|
|
135
184
|
}
|
|
136
|
-
async
|
|
185
|
+
async paginate(request, reply) {
|
|
137
186
|
try {
|
|
138
|
-
request.rbac.assertPermission(this.permission.
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
let
|
|
146
|
-
return
|
|
187
|
+
request.rbac.assertPermission(this.permission.View);
|
|
188
|
+
const page = request.query.page;
|
|
189
|
+
const limit = request.query.limit;
|
|
190
|
+
const orderBy = request.query.orderBy;
|
|
191
|
+
const order = request.query.order;
|
|
192
|
+
const search = request.query.search;
|
|
193
|
+
//const filters = this.parseFilters(request.query.filters)
|
|
194
|
+
let paginateResult = await this.service.paginate({ page, limit, orderBy, order, search });
|
|
195
|
+
return paginateResult;
|
|
147
196
|
}
|
|
148
197
|
catch (e) {
|
|
149
198
|
console.error(e);
|
|
@@ -161,16 +210,36 @@ class AbstractFastifyController {
|
|
|
161
210
|
}
|
|
162
211
|
}
|
|
163
212
|
}
|
|
164
|
-
async
|
|
213
|
+
async export(request, reply) {
|
|
165
214
|
try {
|
|
166
|
-
request.rbac.assertPermission(this.permission.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
215
|
+
request.rbac.assertPermission(this.permission.View);
|
|
216
|
+
const format = request.query.format || 'JSON';
|
|
217
|
+
const headers = request.query.headers ? request.query.headers.split(",") : [];
|
|
218
|
+
const separator = request.query.separator || ";";
|
|
219
|
+
const limit = request.query.limit;
|
|
220
|
+
const orderBy = request.query.orderBy;
|
|
221
|
+
const order = request.query.order;
|
|
222
|
+
const search = request.query.search;
|
|
223
|
+
const year = (new Date().getFullYear()).toString();
|
|
224
|
+
const month = (new Date().getMonth() + 1).toString().padStart(2, '0');
|
|
225
|
+
const exportPath = 'exports';
|
|
226
|
+
const destinationPath = join(BASE_FILE_DIR, 'exports', year, month);
|
|
227
|
+
let result = await this.service.export({
|
|
228
|
+
separator,
|
|
229
|
+
format,
|
|
230
|
+
headers,
|
|
231
|
+
limit,
|
|
232
|
+
orderBy,
|
|
233
|
+
order,
|
|
234
|
+
search,
|
|
235
|
+
}, destinationPath);
|
|
236
|
+
const url = `${BASE_URL}/api/file/${exportPath}/${year}/${month}/${result.fileName}`;
|
|
237
|
+
return {
|
|
238
|
+
url: url,
|
|
239
|
+
rowCount: result.rowCount,
|
|
240
|
+
time: result.time,
|
|
241
|
+
fileName: result.fileName,
|
|
242
|
+
};
|
|
174
243
|
}
|
|
175
244
|
catch (e) {
|
|
176
245
|
console.error(e);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createDirIfNotExist } from "@drax/common-back";
|
|
2
|
+
import crypto from "crypto";
|
|
3
|
+
class AbstractExport {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.cursor = options.cursor;
|
|
6
|
+
this.destinationPath = options.destinationPath;
|
|
7
|
+
this.headers = Array.isArray(options.headers) ? options.headers : options.headers.split(',');
|
|
8
|
+
}
|
|
9
|
+
createDirIfNotExist() {
|
|
10
|
+
createDirIfNotExist(this.destinationPath);
|
|
11
|
+
}
|
|
12
|
+
generateFileName(extension) {
|
|
13
|
+
if (!this.fileName) {
|
|
14
|
+
const randomUUID = crypto.randomUUID().toString();
|
|
15
|
+
this.fileName = `export_${randomUUID}.${extension}`;
|
|
16
|
+
}
|
|
17
|
+
return this.fileName;
|
|
18
|
+
}
|
|
19
|
+
generateFilePath(extension) {
|
|
20
|
+
this.createDirIfNotExist();
|
|
21
|
+
this.generateFileName(extension);
|
|
22
|
+
this.relativeFilePath = `${this.destinationPath}/${this.fileName}`;
|
|
23
|
+
return this.relativeFilePath;
|
|
24
|
+
}
|
|
25
|
+
isIterableAsync(value) {
|
|
26
|
+
return value != null && typeof value[Symbol.asyncIterator] === 'function';
|
|
27
|
+
}
|
|
28
|
+
isIterableSync(value) {
|
|
29
|
+
return value != null && typeof value[Symbol.iterator] === 'function';
|
|
30
|
+
}
|
|
31
|
+
getNestedProperty(obj, path) {
|
|
32
|
+
return path.split('.').reduce((acc, part) => {
|
|
33
|
+
if (Array.isArray(acc)) {
|
|
34
|
+
return acc.map(item => item[part]).join('|');
|
|
35
|
+
}
|
|
36
|
+
return acc && acc[part];
|
|
37
|
+
}, obj);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export { AbstractExport, };
|
|
41
|
+
export default AbstractExport;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import AbstractExport from "./AbstractExport.js";
|
|
3
|
+
class ExportCsv extends AbstractExport {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
super(options);
|
|
6
|
+
this.separator = ';';
|
|
7
|
+
this.separator = options.separator ? options.separator : ';';
|
|
8
|
+
}
|
|
9
|
+
// Método principal para procesar los datos y generar el CSV
|
|
10
|
+
process() {
|
|
11
|
+
return new Promise(async (resolve, reject) => {
|
|
12
|
+
try {
|
|
13
|
+
this.generateFilePath('csv');
|
|
14
|
+
let rowCount = 0;
|
|
15
|
+
const start = Date.now();
|
|
16
|
+
const writableStream = fs.createWriteStream(this.relativeFilePath);
|
|
17
|
+
writableStream.on('error', reject);
|
|
18
|
+
writableStream.on('finish', () => resolve({
|
|
19
|
+
status: 'success',
|
|
20
|
+
destinationPath: this.destinationPath,
|
|
21
|
+
fileName: this.fileName,
|
|
22
|
+
filePath: this.destinationPath + '/' + this.fileName,
|
|
23
|
+
relativeFilePath: this.relativeFilePath,
|
|
24
|
+
rowCount: rowCount,
|
|
25
|
+
time: Date.now() - start,
|
|
26
|
+
message: 'Export successful',
|
|
27
|
+
}));
|
|
28
|
+
const csvHeaders = this.headers.join(this.separator);
|
|
29
|
+
writableStream.write(csvHeaders + '\n');
|
|
30
|
+
if (this.isIterableAsync(this.cursor)) {
|
|
31
|
+
for await (const record of this.cursor) {
|
|
32
|
+
const csvRow = this.convertRecordToCSVrow(record);
|
|
33
|
+
console.log("csvRow", csvRow);
|
|
34
|
+
writableStream.write(csvRow + '\n');
|
|
35
|
+
rowCount++;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else if (this.isIterableSync(this.cursor)) {
|
|
39
|
+
// Si es un cursor de SQLite (better-sqlite3), usamos iterate()
|
|
40
|
+
for (const record of this.cursor) {
|
|
41
|
+
const csvRow = this.convertRecordToCSVrow(record);
|
|
42
|
+
writableStream.write(csvRow + '\n');
|
|
43
|
+
rowCount++;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
writableStream.end();
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
reject(e);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Método que convierte un registro en una o más filas de CSV
|
|
54
|
+
convertRecordToCSVrow(record) {
|
|
55
|
+
let fields = [];
|
|
56
|
+
for (const header of this.headers) {
|
|
57
|
+
let value;
|
|
58
|
+
if (header.includes('.')) {
|
|
59
|
+
value = this.getNestedProperty(record, header);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
value = record[header];
|
|
63
|
+
}
|
|
64
|
+
if (value === undefined) {
|
|
65
|
+
fields.push('');
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (Array.isArray(value)) {
|
|
69
|
+
if (value.length > 0 && typeof value[0] === 'object') {
|
|
70
|
+
fields.push(JSON.stringify(value));
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
fields.push(value.join(','));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (typeof value === 'object') {
|
|
77
|
+
fields.push(JSON.stringify(value));
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
fields.push(value.toString());
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return fields.join(this.separator);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
export default ExportCsv;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import AbstractExport from "./AbstractExport.js";
|
|
3
|
+
class ExportJson extends AbstractExport {
|
|
4
|
+
constructor(options) {
|
|
5
|
+
super(options);
|
|
6
|
+
}
|
|
7
|
+
// Método principal para procesar los datos y generar el CSV
|
|
8
|
+
process() {
|
|
9
|
+
return new Promise(async (resolve, reject) => {
|
|
10
|
+
try {
|
|
11
|
+
this.generateFilePath('json');
|
|
12
|
+
let rowCount = 0;
|
|
13
|
+
const start = Date.now();
|
|
14
|
+
const writableStream = fs.createWriteStream(this.relativeFilePath);
|
|
15
|
+
writableStream.on('error', reject);
|
|
16
|
+
writableStream.on('finish', () => resolve({
|
|
17
|
+
status: 'success',
|
|
18
|
+
destinationPath: this.destinationPath,
|
|
19
|
+
fileName: this.fileName,
|
|
20
|
+
filePath: this.destinationPath + '/' + this.fileName,
|
|
21
|
+
relativeFilePath: this.relativeFilePath,
|
|
22
|
+
rowCount: rowCount,
|
|
23
|
+
time: Date.now() - start,
|
|
24
|
+
message: 'Export successful',
|
|
25
|
+
}));
|
|
26
|
+
writableStream.write('[');
|
|
27
|
+
if (this.isIterableAsync(this.cursor)) {
|
|
28
|
+
for await (const record of this.cursor) {
|
|
29
|
+
const csvRow = JSON.stringify(record);
|
|
30
|
+
console.log("csvRow", csvRow);
|
|
31
|
+
writableStream.write(csvRow + ',\n');
|
|
32
|
+
rowCount++;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (this.isIterableSync(this.cursor)) {
|
|
36
|
+
for (const record of this.cursor) {
|
|
37
|
+
const csvRow = JSON.stringify(record);
|
|
38
|
+
writableStream.write(csvRow + ',\n');
|
|
39
|
+
rowCount++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
writableStream.write(']');
|
|
43
|
+
writableStream.end();
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
reject(e);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export default ExportJson;
|
|
@@ -82,6 +82,17 @@ class AbstractMongoRepository {
|
|
|
82
82
|
items: items.docs
|
|
83
83
|
};
|
|
84
84
|
}
|
|
85
|
+
async find({ limit = 0, orderBy = '', order = false, search = '', filters = [] }) {
|
|
86
|
+
const query = {};
|
|
87
|
+
if (search) {
|
|
88
|
+
query['$or'] = this._searchFields.map(field => ({ [field]: new RegExp(search, 'i') }));
|
|
89
|
+
}
|
|
90
|
+
MongooseQueryFilter.applyFilters(query, filters);
|
|
91
|
+
const sort = MongooseSort.applySort(orderBy, order);
|
|
92
|
+
const populate = this._populateFields;
|
|
93
|
+
const items = await this._model.find(query).sort(sort).populate(populate);
|
|
94
|
+
return items;
|
|
95
|
+
}
|
|
85
96
|
}
|
|
86
97
|
export default AbstractMongoRepository;
|
|
87
98
|
export { AbstractMongoRepository };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ZodErrorToValidationError } from "@drax/common-back";
|
|
2
2
|
import { ZodError } from "zod";
|
|
3
|
+
import ExportCsv from "../exports/ExportCsv.js";
|
|
4
|
+
import ExportJson from "../exports/ExportJson.js";
|
|
3
5
|
class AbstractService {
|
|
4
6
|
constructor(repository, schema) {
|
|
5
7
|
this._repository = repository;
|
|
@@ -117,6 +119,48 @@ class AbstractService {
|
|
|
117
119
|
throw e;
|
|
118
120
|
}
|
|
119
121
|
}
|
|
122
|
+
async find({ orderBy = '', order = false, search = '', filters = [] }) {
|
|
123
|
+
try {
|
|
124
|
+
const items = await this._repository.find({ orderBy, order, search, filters });
|
|
125
|
+
return items;
|
|
126
|
+
}
|
|
127
|
+
catch (e) {
|
|
128
|
+
console.error("Error paginating", e);
|
|
129
|
+
throw e;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
async export({ format = 'JSON', headers = [], separator = ';', orderBy = '', order = false, search = '', filters = [] }, destinationPath) {
|
|
133
|
+
try {
|
|
134
|
+
console.log("ExportOptions", {
|
|
135
|
+
format,
|
|
136
|
+
headers,
|
|
137
|
+
separator,
|
|
138
|
+
outputPath: destinationPath,
|
|
139
|
+
orderBy,
|
|
140
|
+
order,
|
|
141
|
+
search,
|
|
142
|
+
filters
|
|
143
|
+
});
|
|
144
|
+
let cursor;
|
|
145
|
+
let exporter;
|
|
146
|
+
switch (format) {
|
|
147
|
+
case 'JSON':
|
|
148
|
+
cursor = await this._repository.find({ orderBy, order, search, filters });
|
|
149
|
+
exporter = new ExportJson({ cursor, destinationPath: destinationPath, headers });
|
|
150
|
+
return await exporter.process();
|
|
151
|
+
case 'CSV':
|
|
152
|
+
cursor = await this._repository.find({ orderBy, order, search, filters });
|
|
153
|
+
exporter = new ExportCsv({ cursor, destinationPath: destinationPath, headers, separator });
|
|
154
|
+
return await exporter.process();
|
|
155
|
+
default:
|
|
156
|
+
throw new Error(`Unsupported export format: ${format}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (e) {
|
|
160
|
+
console.error("Error exporting", e);
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
120
164
|
}
|
|
121
165
|
export default AbstractService;
|
|
122
166
|
export { AbstractService };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { parentPort } from 'worker_threads';
|
|
2
|
+
import ExportCsv from '../exports/ExportCsv'; // Ajusta la ruta según sea necesario
|
|
3
|
+
parentPort.on('message', async (options) => {
|
|
4
|
+
const exporter = new ExportCsv(options);
|
|
5
|
+
try {
|
|
6
|
+
let result = await exporter.process();
|
|
7
|
+
parentPort.postMessage({ result: result });
|
|
8
|
+
}
|
|
9
|
+
catch (error) {
|
|
10
|
+
parentPort.postMessage({ error: error.message });
|
|
11
|
+
}
|
|
12
|
+
});
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.5.1",
|
|
7
7
|
"description": "Crud utils across modules",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "types/index.d.ts",
|
|
@@ -15,14 +15,16 @@
|
|
|
15
15
|
"copygql": "copyfiles -u 1 ./**/*.graphql dist/",
|
|
16
16
|
"tsc": "tsc -b tsconfig.json",
|
|
17
17
|
"test": "node --import tsx --test test/**/*",
|
|
18
|
-
"
|
|
19
|
-
"
|
|
18
|
+
"testService": "node --import tsx --test test/services/*.ts",
|
|
19
|
+
"testExports": "node --import tsx --test test/exports/*.ts",
|
|
20
|
+
"testWorkers": "node --import tsx --test test/workers/*.ts"
|
|
20
21
|
},
|
|
21
22
|
"author": "Cristian Incarnato & Drax Team",
|
|
22
23
|
"license": "ISC",
|
|
23
24
|
"dependencies": {
|
|
24
|
-
"@drax/common-back": "^0.
|
|
25
|
-
"@drax/common-share": "^0.
|
|
25
|
+
"@drax/common-back": "^0.5.1",
|
|
26
|
+
"@drax/common-share": "^0.5.1",
|
|
27
|
+
"@drax/media-back": "^0.5.1",
|
|
26
28
|
"@graphql-tools/load-files": "^7.0.0",
|
|
27
29
|
"@graphql-tools/merge": "^9.0.4",
|
|
28
30
|
"mongoose": "^8.6.3",
|
|
@@ -41,5 +43,5 @@
|
|
|
41
43
|
"tsc-alias": "^1.8.10",
|
|
42
44
|
"typescript": "^5.6.2"
|
|
43
45
|
},
|
|
44
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "6f507c8b52e134f10839fd7698c2466ff65a3d08"
|
|
45
47
|
}
|