@drax/crud-back 1.1.1 → 1.3.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.
@@ -17,8 +17,10 @@ import {IDraxFindOneOptions} from "@drax/crud-share/types/interfaces/IDraxFindOn
17
17
  abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
18
18
 
19
19
  protected _repository: IDraxCrudRepository<T, C, U>
20
- protected _schema?: ZodObject<ZodRawShape> | undefined
20
+ protected _baseSchema?: ZodObject<ZodRawShape> | undefined
21
+ protected _fullSchema?: ZodObject<ZodRawShape> | undefined
21
22
  protected _defaultOrder?: string | undefined
23
+ protected _validateOutput: boolean = true
22
24
 
23
25
  transformCreate?: (data: C) => Promise<C>;
24
26
  transformUpdate?: (data: U) => Promise<U>;
@@ -29,88 +31,139 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
29
31
  onDeleted?: (id: string) => Promise<void>;
30
32
 
31
33
 
32
-
33
- constructor(repository: IDraxCrudRepository<T, C, U>, schema?: ZodObject<ZodRawShape>) {
34
+ constructor(repository: IDraxCrudRepository<T, C, U>, baseSchema?: ZodObject<ZodRawShape>, fullSchema?: ZodObject<ZodRawShape>) {
34
35
  this._repository = repository
35
- this._schema = schema
36
+ this._baseSchema = baseSchema
37
+ this._fullSchema = fullSchema
36
38
  }
37
39
 
38
-
39
- async create(data: C): Promise<T> {
40
- try {
41
- if (this._schema) {
42
- data = await this._schema.parseAsync(data) as C
40
+ async validateInputCreate(data: C): Promise<C> {
41
+ if (this._baseSchema) {
42
+ try {
43
+ return await this._baseSchema.parseAsync(data) as C
44
+ } catch (e) {
45
+ console.error("Error on validateInput", {
46
+ name: e?.name,
47
+ message: e?.message,
48
+ stack: e?.stack,
49
+ });
50
+ if (e instanceof ZodError) {
51
+ throw ZodErrorToValidationError(e, data)
52
+ }
53
+ throw e
43
54
  }
44
- if (this.transformCreate) {
45
- data = await this.transformCreate(data)
55
+ }
56
+ return data
57
+ }
58
+
59
+ async validateInputUpdate(data: U): Promise<U> {
60
+ if (this._baseSchema) {
61
+ try {
62
+ return await this._baseSchema.parseAsync(data) as U
63
+ } catch (e) {
64
+ console.error("Error on validateInput", {
65
+ name: e?.name,
66
+ message: e?.message,
67
+ stack: e?.stack,
68
+ });
69
+ if (e instanceof ZodError) {
70
+ throw ZodErrorToValidationError(e, data)
71
+ }
72
+ throw e
46
73
  }
47
- const item: T = await this._repository.create(data)
48
- if (this.onCreated) {
49
- await this.onCreated(item)
74
+ }
75
+ return data
76
+ }
77
+
78
+ async validateInputUpdatePartial(data: U): Promise<U> {
79
+ if (this._baseSchema) {
80
+ try {
81
+ return await this._baseSchema.partial().parseAsync(data) as U
82
+ } catch (e) {
83
+ console.error("Error on validateInput", {
84
+ name: e?.name,
85
+ message: e?.message,
86
+ stack: e?.stack,
87
+ });
88
+ if (e instanceof ZodError) {
89
+ throw ZodErrorToValidationError(e, data)
90
+ }
91
+ throw e
50
92
  }
51
- return item
52
- } catch (e) {
53
- console.error("Error create", {
54
- name: e?.name,
55
- message: e?.message,
56
- stack: e?.stack,
57
- });
58
- if (e instanceof ZodError) {
59
- throw ZodErrorToValidationError(e, data)
93
+ }
94
+ return data
95
+ }
96
+
97
+ async validateOutput(item: T): Promise<T> {
98
+ if (this._validateOutput && item && this._fullSchema) {
99
+ try {
100
+ return await this._fullSchema.parseAsync(item) as T
101
+ } catch (e) {
102
+ console.error("Error on validateOutput", {
103
+ name: e?.name,
104
+ message: e?.message,
105
+ stack: e?.stack,
106
+ });
107
+ throw e
60
108
  }
61
- throw e
62
109
  }
110
+ return item
111
+ }
112
+
113
+ async create(data: C): Promise<T> {
114
+
115
+ data = await this.validateInputCreate(data)
116
+
117
+ if (this.transformCreate) {
118
+ data = await this.transformCreate(data)
119
+ }
120
+
121
+ let item: T = await this._repository.create(data)
122
+
123
+ if (this.onCreated) {
124
+ await this.onCreated(item)
125
+ }
126
+
127
+ item = await this.validateOutput(item)
128
+
129
+ return item
130
+
63
131
  }
64
132
 
65
133
  async update(id: string, data: U): Promise<T> {
66
- try {
67
- if (this._schema) {
68
- data = await this._schema.parseAsync(data) as U
69
- }
70
- if (this.transformUpdate) {
71
- data = await this.transformUpdate(data)
72
- }
73
- const item: T = await this._repository.update(id, data)
74
- if (this.onUpdated) {
75
- await this.onUpdated(item)
76
- }
77
- return item
78
- } catch (e) {
79
- console.error("Error update", {
80
- name: e?.name,
81
- message: e?.message,
82
- stack: e?.stack,
83
- });
84
- if (e instanceof ZodError) {
85
- throw ZodErrorToValidationError(e, data)
86
- }
87
- throw e
134
+
135
+ data = await this.validateInputUpdate(data)
136
+
137
+ if (this.transformUpdate) {
138
+ data = await this.transformUpdate(data)
88
139
  }
140
+
141
+ let item: T = await this._repository.update(id, data)
142
+
143
+ if (this.onUpdated) {
144
+ await this.onUpdated(item)
145
+ }
146
+
147
+ item = await this.validateOutput(item)
148
+
149
+ return item
150
+
89
151
  }
90
152
 
91
153
  async updatePartial(id: string, data: any): Promise<T> {
92
- try {
93
154
 
94
- if (this._schema) {
95
- data = await this._schema.partial().parseAsync(data)
96
- }
155
+ data = await this.validateInputUpdatePartial(data)
97
156
 
98
- const item: T = await this._repository.updatePartial(id, data)
99
- if (this.onUpdated) {
100
- await this.onUpdated(item)
101
- }
102
- return item
103
- } catch (e) {
104
- console.error("Error updatePartial", {
105
- name: e?.name,
106
- message: e?.message,
107
- stack: e?.stack,
108
- });
109
- if (e instanceof ZodError) {
110
- throw ZodErrorToValidationError(e, data)
111
- }
112
- throw e
157
+ let item: T = await this._repository.updatePartial(id, data)
158
+
159
+ if (this.onUpdated) {
160
+ await this.onUpdated(item)
113
161
  }
162
+
163
+ item = await this.validateOutput(item)
164
+
165
+ return item
166
+
114
167
  }
115
168
 
116
169
  async delete(id: string): Promise<boolean> {
@@ -119,7 +172,7 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
119
172
  if (!result) {
120
173
  throw new Error("error.deletionFailed");
121
174
  }
122
- if(this.onDeleted) {
175
+ if (this.onDeleted) {
123
176
  await this.onDeleted(id)
124
177
  }
125
178
  return result;
@@ -136,11 +189,17 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
136
189
 
137
190
  async findById(id: string): Promise<T | null> {
138
191
  try {
139
- let item: T = await this._repository.findById(id);
192
+
193
+ let item: T = await this._repository.findById(id)
194
+
140
195
  if (item && this.transformRead) {
141
196
  item = await this.transformRead(item)
142
197
  }
198
+
199
+ item = await this.validateOutput(item)
200
+
143
201
  return item
202
+
144
203
  } catch (e) {
145
204
  console.error("Error findById", {
146
205
  name: e?.name,
@@ -151,32 +210,47 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
151
210
  }
152
211
  }
153
212
 
154
- async findByIds(ids: Array<string>): Promise<T[]> {
213
+
214
+
215
+ async findOneBy(field: string, value: any): Promise<T | null> {
155
216
  try {
156
- let items: T[] = await this._repository.findByIds(ids);
157
- if (this.transformRead) {
158
- items = await Promise.all(items.map(item => this.transformRead(item)))
217
+
218
+ let item: T = await this._repository.findOneBy(field, value)
219
+
220
+ if (item && this.transformRead) {
221
+ item = await this.transformRead(item)
159
222
  }
160
- return items
223
+
224
+ item = await this.validateOutput(item)
225
+
226
+ return item
161
227
  } catch (e) {
162
- console.error("Error findByIds", {
228
+ console.error("Error findOneBy", {
163
229
  name: e?.name,
164
230
  message: e?.message,
165
231
  stack: e?.stack,
166
232
  });
167
233
  throw e;
168
234
  }
235
+
169
236
  }
170
237
 
171
- async findOneBy(field: string, value: any): Promise<T | null> {
238
+ async findOne({
239
+ search = '',
240
+ filters = []
241
+ }: IDraxFindOneOptions): Promise<T> {
172
242
  try {
173
- let item: T = await this._repository.findOneBy(field, value);
243
+ let item = await this._repository.findOne({search, filters});
244
+
174
245
  if (item && this.transformRead) {
175
246
  item = await this.transformRead(item)
176
247
  }
248
+
249
+ item = await this.validateOutput(item)
250
+
177
251
  return item
178
252
  } catch (e) {
179
- console.error("Error findOneBy", {
253
+ console.error("Error findOne", {
180
254
  name: e?.name,
181
255
  message: e?.message,
182
256
  stack: e?.stack,
@@ -186,6 +260,30 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
186
260
 
187
261
  }
188
262
 
263
+ async findByIds(ids: Array<string>): Promise<T[]> {
264
+ try {
265
+
266
+ let items: T[] = await this._repository.findByIds(ids)
267
+
268
+ if (this.transformRead) {
269
+ items = await Promise.all(items.map(item => this.transformRead(item)))
270
+ }
271
+
272
+ if(this._fullSchema){
273
+ items = await Promise.all(items.map(item => this.validateOutput(item)))
274
+ }
275
+
276
+ return items
277
+ } catch (e) {
278
+ console.error("Error findByIds", {
279
+ name: e?.name,
280
+ message: e?.message,
281
+ stack: e?.stack,
282
+ });
283
+ throw e;
284
+ }
285
+ }
286
+
189
287
  async findBy(field: string, value: any, limit: number = 1000): Promise<T[] | null> {
190
288
  try {
191
289
 
@@ -193,6 +291,9 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
193
291
  if (this.transformRead) {
194
292
  items = await Promise.all(items.map(item => this.transformRead(item)))
195
293
  }
294
+ if(this._fullSchema){
295
+ items = await Promise.all(items.map(item => this.validateOutput(item)))
296
+ }
196
297
  return items
197
298
  } catch (e) {
198
299
  console.error("Error findBy", {
@@ -211,6 +312,9 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
211
312
  if (this.transformRead) {
212
313
  items = await Promise.all(items.map(item => this.transformRead(item)))
213
314
  }
315
+ if(this._fullSchema){
316
+ items = await Promise.all(items.map(item => this.validateOutput(item)))
317
+ }
214
318
  return items
215
319
  } catch (e) {
216
320
  console.error("Error fetchAll", {
@@ -230,6 +334,9 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
230
334
  if (this.transformRead) {
231
335
  items = await Promise.all(items.map(item => this.transformRead(item)))
232
336
  }
337
+ if(this._fullSchema){
338
+ items = await Promise.all(items.map(item => this.validateOutput(item)))
339
+ }
233
340
  return items
234
341
  } catch (e) {
235
342
  console.error("Error search", {
@@ -259,6 +366,10 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
259
366
  pagination.items = await Promise.all(pagination.items.map(item => this.transformRead(item)))
260
367
  }
261
368
 
369
+ if(this._fullSchema){
370
+ pagination.items = await Promise.all(pagination.items.map(item => this.validateOutput(item)))
371
+ }
372
+
262
373
  return pagination;
263
374
  } catch (e) {
264
375
  console.error("Error paginate", {
@@ -284,6 +395,9 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
284
395
  if (this.transformRead) {
285
396
  items = await Promise.all(items.map(item => this.transformRead(item)))
286
397
  }
398
+ if(this._fullSchema){
399
+ items = await Promise.all(items.map(item => this.validateOutput(item)))
400
+ }
287
401
  return items;
288
402
  } catch (e) {
289
403
  console.error("Error find", {
@@ -296,25 +410,9 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
296
410
 
297
411
  }
298
412
 
299
- async findOne({
300
- search = '',
301
- filters = []
302
- }: IDraxFindOneOptions): Promise<T> {
303
- try {
304
- let item = await this._repository.findOne({search, filters});
305
- return item;
306
- } catch (e) {
307
- console.error("Error findOne", {
308
- name: e?.name,
309
- message: e?.message,
310
- stack: e?.stack,
311
- });
312
- throw e;
313
- }
314
413
 
315
- }
316
414
 
317
- async groupBy({fields= [], filters= [], dateFormat= 'day'}: IDraxGroupByOptions): Promise<Array<any>> {
415
+ async groupBy({fields = [], filters = [], dateFormat = 'day'}: IDraxGroupByOptions): Promise<Array<any>> {
318
416
  return await this._repository.groupBy({fields, filters, dateFormat})
319
417
  }
320
418
 
@@ -346,7 +444,14 @@ abstract class AbstractService<T, C, U> implements IDraxCrudService<T, C, U> {
346
444
  exporter = new ExportJson({cursor, destinationPath: destinationPath, headers, fileName});
347
445
  return await exporter.process()
348
446
  case 'CSV':
349
- exporter = new ExportCsv({cursor, destinationPath: destinationPath, headers, headersTranslate, fileName, separator});
447
+ exporter = new ExportCsv({
448
+ cursor,
449
+ destinationPath: destinationPath,
450
+ headers,
451
+ headersTranslate,
452
+ fileName,
453
+ separator
454
+ });
350
455
  return await exporter.process()
351
456
  default:
352
457
  throw new Error(`Unsupported export format: ${format}`);