@smartsoft001/trans-shell-nestjs 2.76.0 → 2.80.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/index.js ADDED
@@ -0,0 +1,3090 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __decorateClass = (decorators, target, key, kind) => {
4
+ var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
+ if (decorator = decorators[i])
7
+ result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
+ if (kind && result)
9
+ __defProp(target, key, result);
10
+ return result;
11
+ };
12
+ var __decorateParam = (index, decorator) => (target, key) => decorator(target, key, index);
13
+
14
+ // packages/trans/shell/nestjs/src/lib/nestjs.module.ts
15
+ import { HttpModule } from "@nestjs/axios";
16
+ import { Module as Module2 } from "@nestjs/common";
17
+ import { JwtModule as JwtModule2 } from "@nestjs/jwt";
18
+ import { PassportModule as PassportModule2 } from "@nestjs/passport";
19
+
20
+ // packages/crud/shell/nestjs/src/lib/nestjs.module.ts
21
+ import { Module } from "@nestjs/common";
22
+ import { JwtModule } from "@nestjs/jwt";
23
+ import { PassportModule } from "@nestjs/passport";
24
+
25
+ // packages/crud/shell/app-services/src/lib/services/crud/crud.service.ts
26
+ import { Injectable, Logger } from "@nestjs/common";
27
+ import * as CombinedStream from "combined-stream";
28
+ import { Guid as Guid2 } from "guid-typescript";
29
+ import { Memoize } from "lodash-decorators";
30
+
31
+ // packages/shared/models/src/lib/symbols.ts
32
+ var SYMBOL_MODEL = Symbol.for("smartsoft:model");
33
+ var SYMBOL_FIELD = Symbol.for("smartsoft:field");
34
+
35
+ // packages/shared/models/src/lib/decorators/model/model.decorator.ts
36
+ import "reflect-metadata";
37
+
38
+ // packages/shared/models/src/lib/decorators/field/field.decorator.ts
39
+ import "reflect-metadata";
40
+
41
+ // packages/shared/utils/src/lib/services/password/password.service.ts
42
+ import * as md5_ from "md5";
43
+ var md5 = md5_;
44
+ var PasswordService = class _PasswordService {
45
+ /**
46
+ * Hash password text
47
+ * @param p {string} - text
48
+ * @return - hashed text
49
+ */
50
+ static hash(p) {
51
+ return Promise.resolve(md5(p));
52
+ }
53
+ /**
54
+ * Compare password text with hashed text
55
+ * @param p {string} - password text
56
+ * @param h {string} - hashed text
57
+ */
58
+ static async compare(p, h) {
59
+ const hp = await _PasswordService.hash(p);
60
+ return hp === h;
61
+ }
62
+ };
63
+
64
+ // packages/shared/utils/src/lib/services/object/object.service.ts
65
+ import { stringify } from "flatted";
66
+ var ObjectService = class {
67
+ /***
68
+ * Create object with data
69
+ * @param data {object} - data to set
70
+ * @param type {type} - new type
71
+ * @return - new type object
72
+ */
73
+ static createByType(data, type) {
74
+ if (!data)
75
+ return data;
76
+ try {
77
+ if (data instanceof type)
78
+ return data;
79
+ } catch (e) {
80
+ console.warn(e);
81
+ }
82
+ const result = new type();
83
+ Object.keys(data).forEach((key) => {
84
+ result[key] = data[key];
85
+ });
86
+ return result;
87
+ }
88
+ /***
89
+ * Remove object type from data
90
+ * @param obj {object} - object
91
+ * @return - object without type
92
+ */
93
+ static removeTypes(obj) {
94
+ if (!obj)
95
+ return obj;
96
+ const result = {};
97
+ Object.keys(obj).forEach((key) => {
98
+ if (obj[key] && obj[key].constructor && !(obj[key] instanceof Date)) {
99
+ let stringValue = "";
100
+ try {
101
+ stringValue = JSON.stringify(obj[key]);
102
+ } catch (e) {
103
+ console.warn("can't stringify without circular package");
104
+ stringValue = stringify(obj[key]);
105
+ }
106
+ result[key] = JSON.parse(stringValue);
107
+ } else {
108
+ result[key] = obj[key];
109
+ }
110
+ });
111
+ return result;
112
+ }
113
+ };
114
+
115
+ // packages/shared/utils/src/lib/services/guid/guid.service.ts
116
+ import { Guid } from "guid-typescript";
117
+ var GuidService = class {
118
+ /***
119
+ * Create guid as string
120
+ */
121
+ static create() {
122
+ return Guid.raw();
123
+ }
124
+ };
125
+
126
+ // packages/shared/utils/src/lib/services/array/array.service.ts
127
+ import * as _ from "lodash";
128
+
129
+ // packages/shared/models/src/lib/utils.ts
130
+ function getModelFieldKeys(type) {
131
+ if (!type["__fields"])
132
+ return [];
133
+ return Object.keys(type["__fields"]);
134
+ }
135
+ function getModelFieldOptions(instance, fieldKey) {
136
+ return Reflect.getMetadata(SYMBOL_FIELD, instance, fieldKey);
137
+ }
138
+ function getModelFieldsWithOptions(instance) {
139
+ const keys = getModelFieldKeys(instance.constructor);
140
+ return keys.map((item) => {
141
+ return {
142
+ key: item,
143
+ options: getModelFieldOptions(instance, item)
144
+ };
145
+ });
146
+ }
147
+ function isModel(instance) {
148
+ if (!instance || !instance.constructor)
149
+ return false;
150
+ return Reflect.hasMetadata(SYMBOL_MODEL, instance.constructor);
151
+ }
152
+ function getInvalidFields(instance, mode, permissions) {
153
+ const result = [];
154
+ getModelFieldsWithOptions(instance).forEach(({ key, options }) => {
155
+ let required = options.required;
156
+ if ((mode === "create" || mode === "update") && options[mode] && options[mode]?.constructor) {
157
+ required = options[mode].required;
158
+ if (required && permissions && options[mode].permissions) {
159
+ required = options[mode]?.permissions?.some(
160
+ (op) => permissions.some((p) => p === op)
161
+ );
162
+ }
163
+ }
164
+ if (required && (instance[key] === null || instance[key] === void 0 || instance[key] === ""))
165
+ result.push(key);
166
+ });
167
+ return result;
168
+ }
169
+ function castModel(instance, mode, permissions) {
170
+ if (!isModel(instance))
171
+ return;
172
+ const fieldsWithOptions = getModelFieldsWithOptions(instance);
173
+ Object.keys(instance).filter((key) => key !== "id").forEach((key) => {
174
+ const fieldWidthOptions = fieldsWithOptions.find((f) => f.key === key);
175
+ if (!fieldWidthOptions) {
176
+ delete instance[key];
177
+ return;
178
+ }
179
+ if ((mode === "create" || mode === "update") && (!fieldWidthOptions.options[mode] || permissions && fieldWidthOptions.options[mode].permissions && !fieldWidthOptions.options[mode]?.permissions?.some((op) => permissions.some((p) => op === p)))) {
180
+ delete instance[key];
181
+ return;
182
+ } else if (mode !== "create" && mode !== "update" && (!fieldWidthOptions.options.customs || !fieldWidthOptions.options.customs.some((c) => c.mode === mode))) {
183
+ delete instance[key];
184
+ return;
185
+ }
186
+ });
187
+ }
188
+
189
+ // packages/shared/domain-core/src/lib/errors.ts
190
+ var DomainValidationError = class _DomainValidationError extends Error {
191
+ constructor(msg) {
192
+ super(msg);
193
+ this.type = _DomainValidationError;
194
+ }
195
+ };
196
+ var DomainForbiddenError = class _DomainForbiddenError extends Error {
197
+ constructor(msg) {
198
+ super(msg);
199
+ this.type = _DomainForbiddenError;
200
+ }
201
+ };
202
+
203
+ // packages/shared/domain-core/src/lib/repositories.ts
204
+ var IUnitOfWork = class {
205
+ };
206
+ var IItemRepository = class {
207
+ };
208
+ var IAttachmentRepository = class {
209
+ };
210
+
211
+ // packages/crud/shell/app-services/src/lib/services/crud/crud.service.ts
212
+ var CrudService = class {
213
+ constructor(permissionService, repository, attachmentRepository) {
214
+ this.permissionService = permissionService;
215
+ this.repository = repository;
216
+ this.attachmentRepository = attachmentRepository;
217
+ this._logger = new Logger(CrudService.name, { timestamp: true });
218
+ }
219
+ async create(data, user) {
220
+ data.id = Guid2.raw();
221
+ try {
222
+ this.permissionService.valid("create", user);
223
+ castModel(data, "create", user.permissions);
224
+ this.checkValidCreate(data, user.permissions);
225
+ if (data["password"]) {
226
+ data["password"] = await PasswordService.hash(data["password"]);
227
+ }
228
+ if (data["passwordConfirm"]) {
229
+ delete data["passwordConfirm"];
230
+ }
231
+ await this.repository.create(data, user);
232
+ return data.id;
233
+ } catch (e) {
234
+ this._logger.error(e);
235
+ throw e;
236
+ }
237
+ }
238
+ async createMany(data, user, options) {
239
+ data.forEach((item) => {
240
+ item.id = Guid2.raw();
241
+ });
242
+ try {
243
+ this.permissionService.valid("create", user);
244
+ data.forEach((item) => {
245
+ castModel(item, "create", user.permissions);
246
+ this.checkValidCreate(item, user.permissions);
247
+ });
248
+ if (options && options.mode === "replace") {
249
+ await this.repository.clear(user);
250
+ }
251
+ for (let index = 0; index < data.length; index++) {
252
+ const item = data[index];
253
+ if (item["password"]) {
254
+ item["password"] = await PasswordService.hash(item["password"]);
255
+ }
256
+ if (item["passwordConfirm"]) {
257
+ delete item["passwordConfirm"];
258
+ }
259
+ }
260
+ await this.repository.createMany(data, user);
261
+ } catch (e) {
262
+ this._logger.error(e);
263
+ throw e;
264
+ }
265
+ return data;
266
+ }
267
+ async readById(id, user) {
268
+ try {
269
+ this.permissionService.valid("read", user);
270
+ const result = await this.repository.getById(id);
271
+ delete result["password"];
272
+ return result;
273
+ } catch (e) {
274
+ this._logger.error(e);
275
+ throw e;
276
+ }
277
+ }
278
+ async read(criteria, options, user) {
279
+ try {
280
+ this.permissionService.valid("read", user);
281
+ const result = await this.repository.getByCriteria(criteria, options);
282
+ result.data.forEach((item) => delete item["password"]);
283
+ return result;
284
+ } catch (e) {
285
+ this._logger.error(e);
286
+ throw e;
287
+ }
288
+ }
289
+ readBySpec(spec, options, user) {
290
+ return this.read(spec.criteria, options, user);
291
+ }
292
+ async update(id, data, user) {
293
+ try {
294
+ data.id = id;
295
+ this.permissionService.valid("update", user);
296
+ castModel(data, "update", user.permissions);
297
+ this.checkValidUpdate(data, user.permissions);
298
+ if (data["password"]) {
299
+ data["password"] = await PasswordService.hash(data["password"]);
300
+ }
301
+ if (data["passwordConfirm"]) {
302
+ delete data["passwordConfirm"];
303
+ }
304
+ await this.repository.update(data, user);
305
+ } catch (e) {
306
+ this._logger.error(e);
307
+ throw e;
308
+ }
309
+ }
310
+ async updatePartial(id, data, user) {
311
+ try {
312
+ data.id = id;
313
+ this.permissionService.valid("update", user);
314
+ castModel(data, "update", user.permissions);
315
+ this.checkValidUpdatePartial(data, user.permissions);
316
+ if (data["password"]) {
317
+ data["password"] = await PasswordService.hash(data["password"]);
318
+ }
319
+ if (data["passwordConfirm"]) {
320
+ delete data["passwordConfirm"];
321
+ }
322
+ await this.repository.updatePartial(data, user);
323
+ } catch (e) {
324
+ this._logger.error(e);
325
+ throw e;
326
+ }
327
+ }
328
+ async delete(id, user) {
329
+ try {
330
+ this.permissionService.valid("delete", user);
331
+ await this.repository.delete(id, user);
332
+ } catch (e) {
333
+ this._logger.error(e);
334
+ throw e;
335
+ }
336
+ }
337
+ async uploadAttachment(data, options) {
338
+ if (!data.id) {
339
+ data.id = GuidService.create();
340
+ }
341
+ let oldId = null;
342
+ if (options?.start) {
343
+ oldId = data.id;
344
+ const stream = await this.attachmentRepository.getStream(data.id, {
345
+ start: 0,
346
+ end: options.start - 1
347
+ });
348
+ const combinedStream = CombinedStream.create();
349
+ combinedStream.append(stream);
350
+ combinedStream.append(data.stream);
351
+ data.stream = combinedStream;
352
+ data.id = GuidService.create();
353
+ }
354
+ this.attachmentRepository.upload(data, options);
355
+ if (oldId)
356
+ await this.attachmentRepository.delete(data.id);
357
+ return data.id;
358
+ }
359
+ getAttachmentInfo(id) {
360
+ return this.attachmentRepository.getInfo(id);
361
+ }
362
+ getAttachmentStream(id, options) {
363
+ return this.attachmentRepository.getStream(id, options);
364
+ }
365
+ async deleteAttachment(id) {
366
+ return this.attachmentRepository.delete(id);
367
+ }
368
+ changes(criteria) {
369
+ return this.repository.changesByCriteria(criteria);
370
+ }
371
+ checkValidCreate(item, permissions) {
372
+ const array = getInvalidFields(item, "create", permissions);
373
+ if (array.length) {
374
+ throw new DomainValidationError("Required fields: " + array.join(", "));
375
+ }
376
+ }
377
+ checkValidUpdate(item, permissions) {
378
+ const array = getInvalidFields(item, "update", permissions);
379
+ if (array.length) {
380
+ throw new DomainValidationError("Required fields: " + array.join(", "));
381
+ }
382
+ }
383
+ checkValidUpdatePartial(item, permissions) {
384
+ if (!isModel(item))
385
+ return;
386
+ const keys = Object.keys(item);
387
+ const array = getInvalidFields(item, "update", permissions).filter(
388
+ (invalidField) => keys.some((key) => key === invalidField)
389
+ );
390
+ if (array.length) {
391
+ throw new DomainValidationError("Required fields: " + array.join(", "));
392
+ }
393
+ }
394
+ };
395
+ __decorateClass([
396
+ Memoize()
397
+ ], CrudService.prototype, "getAttachmentInfo", 1);
398
+ CrudService = __decorateClass([
399
+ Injectable()
400
+ ], CrudService);
401
+
402
+ // packages/crud/shell/app-services/src/lib/services/index.ts
403
+ var SERVICES = [CrudService];
404
+
405
+ // packages/shared/mongo/src/lib/mongo.config.ts
406
+ var MongoConfig = class {
407
+ };
408
+
409
+ // packages/shared/mongo/src/lib/mongo.unitofwork.ts
410
+ import { Injectable as Injectable2 } from "@nestjs/common";
411
+ import { MongoClient } from "mongodb";
412
+
413
+ // packages/shared/mongo/src/lib/mongo.utils.ts
414
+ function getMongoUrl(config) {
415
+ let url;
416
+ if (config.username && config.password)
417
+ url = `mongodb://${config.username}:${config.password}@${config.host}:${config.port}`;
418
+ else
419
+ url = `mongodb://${config.host}:${config.port}`;
420
+ url = url + "?authSource=" + config.database;
421
+ if (config.host.indexOf("ondigitalocean.com") > -1) {
422
+ url = url.replace("mongodb://", "mongodb+srv://");
423
+ url = url + "&tls=true";
424
+ }
425
+ return url;
426
+ }
427
+
428
+ // packages/shared/mongo/src/lib/mongo.unitofwork.ts
429
+ var MongoUnitOfWork = class extends IUnitOfWork {
430
+ constructor(config) {
431
+ super();
432
+ this.config = config;
433
+ }
434
+ async scope(definition) {
435
+ const client = await MongoClient.connect(this.getUrl());
436
+ const session = client.startSession();
437
+ const transactionOptions = {
438
+ readPreference: "primary",
439
+ readConcern: { level: "local" },
440
+ writeConcern: { w: "majority" }
441
+ };
442
+ let error = null;
443
+ try {
444
+ await session.withTransaction(async () => {
445
+ await definition({
446
+ session,
447
+ connection: client
448
+ });
449
+ }, transactionOptions);
450
+ } catch (e) {
451
+ error = e;
452
+ } finally {
453
+ await session.endSession();
454
+ await client.close();
455
+ }
456
+ if (error)
457
+ throw error;
458
+ }
459
+ getUrl() {
460
+ return getMongoUrl(this.config);
461
+ }
462
+ };
463
+ MongoUnitOfWork = __decorateClass([
464
+ Injectable2()
465
+ ], MongoUnitOfWork);
466
+
467
+ // packages/shared/mongo/src/lib/repositories/attachment.repository.ts
468
+ import { Injectable as Injectable3 } from "@nestjs/common";
469
+ import { MongoClient as MongoClient2 } from "mongodb";
470
+ import * as mongo from "mongodb";
471
+ var MongoAttachmentRepository = class extends IAttachmentRepository {
472
+ constructor(config) {
473
+ super();
474
+ this.config = config;
475
+ }
476
+ async upload(data, options) {
477
+ const client = await MongoClient2.connect(this.getUrl());
478
+ return await new Promise((res, rej) => {
479
+ const db = client.db(this.config.database);
480
+ const bucket = new mongo.GridFSBucket(db, {
481
+ bucketName: this.config.collection
482
+ });
483
+ const writeStream = bucket.openUploadStreamWithId(
484
+ data.id,
485
+ data.fileName,
486
+ {
487
+ contentType: data.mimeType
488
+ }
489
+ );
490
+ if (options?.streamCallback)
491
+ options.streamCallback(writeStream);
492
+ data.stream.pipe(writeStream);
493
+ writeStream.on("error", (error) => {
494
+ rej(error);
495
+ });
496
+ writeStream.on("finish", () => {
497
+ res();
498
+ });
499
+ });
500
+ }
501
+ async getInfo(id) {
502
+ const client = await MongoClient2.connect(this.getUrl());
503
+ const db = client.db(this.config.database);
504
+ const bucket = new mongo.GridFSBucket(db, {
505
+ bucketName: this.config.collection
506
+ });
507
+ const items = await bucket.find({
508
+ _id: id
509
+ }).toArray();
510
+ if (!items || items.length === 0)
511
+ return null;
512
+ return {
513
+ fileName: items[0].filename,
514
+ contentType: items[0].contentType,
515
+ length: items[0].length
516
+ };
517
+ }
518
+ async getStream(id, options) {
519
+ const client = await MongoClient2.connect(this.getUrl());
520
+ const db = client.db(this.config.database);
521
+ const bucket = new mongo.GridFSBucket(db, {
522
+ bucketName: this.config.collection
523
+ });
524
+ return bucket.openDownloadStream(id, options);
525
+ }
526
+ async delete(id) {
527
+ const client = await MongoClient2.connect(this.getUrl());
528
+ const db = client.db(this.config.database);
529
+ const bucket = new mongo.GridFSBucket(db, {
530
+ bucketName: this.config.collection
531
+ });
532
+ await bucket.delete(id);
533
+ await client.close();
534
+ }
535
+ getUrl() {
536
+ return getMongoUrl(this.config);
537
+ }
538
+ };
539
+ MongoAttachmentRepository = __decorateClass([
540
+ Injectable3()
541
+ ], MongoAttachmentRepository);
542
+
543
+ // packages/shared/mongo/src/lib/repositories/item.repository.ts
544
+ import { Injectable as Injectable4 } from "@nestjs/common";
545
+ import {
546
+ MongoClient as MongoClient3
547
+ } from "mongodb";
548
+ import { Observable } from "rxjs";
549
+ import { finalize, share } from "rxjs/operators";
550
+ var MongoItemRepository = class extends IItemRepository {
551
+ constructor(config) {
552
+ super();
553
+ this.config = config;
554
+ }
555
+ async create(item, user, repoOptions) {
556
+ await this.collectionContext(async (collection) => {
557
+ try {
558
+ await collection.insertOne(this.getModelToCreate(item, user), {
559
+ session: repoOptions?.transaction?.session
560
+ });
561
+ this.logChange("create", item, repoOptions, user, null).then();
562
+ } catch (errInsert) {
563
+ this.logChange("create", item, repoOptions, user, errInsert).then();
564
+ throw errInsert;
565
+ }
566
+ });
567
+ }
568
+ async clear(user, repoOptions) {
569
+ await this.collectionContext(async (collection) => {
570
+ try {
571
+ await collection.deleteMany(
572
+ {},
573
+ { session: repoOptions?.transaction?.session }
574
+ );
575
+ this.logChange("clear", null, repoOptions, user, null).then();
576
+ } catch (errClear) {
577
+ this.logChange("clear", null, repoOptions, user, errClear).then();
578
+ throw errClear;
579
+ }
580
+ });
581
+ }
582
+ async createMany(list, user, repoOptions) {
583
+ await this.collectionContext(async (collection) => {
584
+ try {
585
+ await collection.insertMany(
586
+ list.map((item) => this.getModelToCreate(item, user)),
587
+ { session: repoOptions?.transaction?.session }
588
+ );
589
+ this.logChange("createMany", null, repoOptions, user, null).then();
590
+ } catch (errInsert) {
591
+ this.logChange("createMany", null, repoOptions, user, errInsert).then();
592
+ throw errInsert;
593
+ }
594
+ });
595
+ }
596
+ async update(item, user, repoOptions) {
597
+ await this.collectionContext(async (collection) => {
598
+ try {
599
+ const info = await this.getInfo(item.id, collection);
600
+ await collection.replaceOne(
601
+ { _id: item.id },
602
+ this.getModelToUpdate(item, user, info),
603
+ { session: repoOptions?.transaction?.session }
604
+ );
605
+ this.logChange("update", item, repoOptions, user, null).then();
606
+ } catch (errInsert) {
607
+ this.logChange("update", item, repoOptions, user, errInsert).then();
608
+ throw errInsert;
609
+ }
610
+ });
611
+ }
612
+ async updatePartial(item, user, repoOptions) {
613
+ await this.collectionContext(async (collection) => {
614
+ try {
615
+ const info = await this.getInfo(item.id, collection);
616
+ await collection.updateOne(
617
+ { _id: item.id },
618
+ {
619
+ $set: this.getModelToUpdate(item, user, info)
620
+ },
621
+ { session: repoOptions?.transaction?.session }
622
+ );
623
+ this.logChange("updatePartial", item, repoOptions, user, null).then();
624
+ } catch (errUpdate) {
625
+ this.logChange(
626
+ "updatePartial",
627
+ item,
628
+ repoOptions,
629
+ user,
630
+ errUpdate
631
+ ).then();
632
+ throw errUpdate;
633
+ }
634
+ });
635
+ }
636
+ async updatePartialManyByCriteria(criteria, set, user, repoOptions) {
637
+ await this.collectionContext(async (collection) => {
638
+ try {
639
+ this.convertIdInCriteria(criteria);
640
+ await collection.updateMany(
641
+ criteria,
642
+ {
643
+ $set: {
644
+ ...set,
645
+ "__info.update": {
646
+ username: user?.username,
647
+ date: /* @__PURE__ */ new Date()
648
+ }
649
+ }
650
+ },
651
+ { session: repoOptions?.transaction?.session }
652
+ );
653
+ this.logChange(
654
+ "updatePartialManyByCriteria",
655
+ {
656
+ ...criteria,
657
+ set
658
+ },
659
+ repoOptions,
660
+ user,
661
+ null
662
+ ).then();
663
+ } catch (errUpdate) {
664
+ this.logChange(
665
+ "updatePartialManyByCriteria",
666
+ {
667
+ ...criteria,
668
+ set
669
+ },
670
+ repoOptions,
671
+ user,
672
+ errUpdate
673
+ ).then();
674
+ throw errUpdate;
675
+ }
676
+ });
677
+ }
678
+ updatePartialManyBySpecification(spec, set, user, repoOptions) {
679
+ return this.updatePartialManyByCriteria(
680
+ spec.criteria,
681
+ set,
682
+ user,
683
+ repoOptions
684
+ );
685
+ }
686
+ async delete(id, user, repoOptions) {
687
+ await this.collectionContext(async (collection) => {
688
+ try {
689
+ await collection.deleteOne(
690
+ { _id: id },
691
+ { session: repoOptions?.transaction?.session }
692
+ );
693
+ this.logChange(
694
+ "delete",
695
+ {
696
+ id
697
+ },
698
+ repoOptions,
699
+ user,
700
+ null
701
+ ).then();
702
+ } catch (errDelete) {
703
+ this.logChange(
704
+ "delete",
705
+ {
706
+ id
707
+ },
708
+ repoOptions,
709
+ user,
710
+ errDelete
711
+ ).then();
712
+ throw errDelete;
713
+ }
714
+ });
715
+ }
716
+ async getById(id, repoOptions) {
717
+ return await this.collectionContext(async (collection) => {
718
+ const item = await collection.findOne(
719
+ { _id: id },
720
+ {
721
+ session: repoOptions?.transaction?.session
722
+ }
723
+ );
724
+ return this.getModelToResult(item);
725
+ });
726
+ }
727
+ async getByCriteria(criteria, options = {}) {
728
+ return await this.collectionContext(async (collection) => {
729
+ this.convertIdInCriteria(criteria);
730
+ this.generateSearch(criteria);
731
+ const totalCount = await this.getCount(criteria, collection);
732
+ const aggregate = [];
733
+ if (criteria) {
734
+ aggregate.push({ $match: criteria });
735
+ }
736
+ if (options?.sort) {
737
+ aggregate.push({ $sort: options.sort });
738
+ }
739
+ if (options?.skip) {
740
+ aggregate.push({ $skip: options.skip });
741
+ }
742
+ if (options?.limit) {
743
+ aggregate.push({ $limit: options.limit });
744
+ }
745
+ if (options?.project) {
746
+ aggregate.push({ $project: options.project });
747
+ }
748
+ if (options?.min) {
749
+ aggregate.push({ $min: options.min });
750
+ }
751
+ if (options?.max) {
752
+ aggregate.push({ $max: options.max });
753
+ }
754
+ if (options?.group) {
755
+ aggregate.push({ $group: options.group });
756
+ }
757
+ const list = await collection.aggregate(aggregate, {
758
+ allowDiskUse: options?.allowDiskUse,
759
+ session: options?.session
760
+ }).toArray();
761
+ return {
762
+ data: list.map((item) => this.getModelToResult(item)),
763
+ totalCount
764
+ };
765
+ });
766
+ }
767
+ getBySpecification(spec, options = {}) {
768
+ return this.getByCriteria(spec.criteria, options);
769
+ }
770
+ async countByCriteria(criteria) {
771
+ return await this.collectionContext(async (collection) => {
772
+ this.convertIdInCriteria(criteria);
773
+ this.generateSearch(criteria);
774
+ return await this.getCount(criteria, collection);
775
+ });
776
+ }
777
+ countBySpecification(spec) {
778
+ return this.countByCriteria(spec.criteria);
779
+ }
780
+ changesByCriteria(criteria) {
781
+ let stream;
782
+ let client;
783
+ return new Observable((observer) => {
784
+ (async () => {
785
+ try {
786
+ client = await MongoClient3.connect(this.getUrl());
787
+ const db = client.db(this.config.database);
788
+ const collection = db.collection(this.config.collection);
789
+ const pipeline = criteria.id ? [
790
+ {
791
+ $match: {
792
+ "documentKey._id": criteria.id
793
+ }
794
+ }
795
+ ] : [];
796
+ stream = collection.watch(pipeline).on("change", (result) => {
797
+ observer.next({
798
+ id: result["documentKey"]["_id"],
799
+ type: this.mapChangeType(result.operationType),
800
+ data: result.operationType === "update" ? result["updateDescription"] : this.getModelToResult(result["fullDocument"])
801
+ });
802
+ });
803
+ } catch (err) {
804
+ observer.error(err);
805
+ }
806
+ })();
807
+ }).pipe(
808
+ finalize(async () => {
809
+ console.log("Stop watch");
810
+ await stream.close();
811
+ await client.close();
812
+ }),
813
+ share()
814
+ );
815
+ }
816
+ async getContext(handler) {
817
+ const client = await MongoClient3.connect(this.getUrl());
818
+ const db = client.db(this.config.database);
819
+ try {
820
+ const result = await handler(db);
821
+ await client.close();
822
+ return result;
823
+ } catch (e) {
824
+ await client.close();
825
+ throw e;
826
+ }
827
+ }
828
+ async getCount(criteria, collection) {
829
+ this.convertIdInCriteria(criteria);
830
+ return await collection.countDocuments(criteria);
831
+ }
832
+ async getInfo(id, collection) {
833
+ const array = await collection.aggregate([{ $match: { _id: id } }, { $project: { __info: 1 } }]).toArray();
834
+ return array[0] ? array[0]["__info"] : {};
835
+ }
836
+ getModelToCreate(item, user) {
837
+ const result = ObjectService.removeTypes(item);
838
+ result["_id"] = result.id;
839
+ delete result.id;
840
+ result["__info"] = {
841
+ create: {
842
+ username: user ? user.username : null,
843
+ date: /* @__PURE__ */ new Date()
844
+ }
845
+ };
846
+ return result;
847
+ }
848
+ mapChangeType(dbType) {
849
+ const map = {
850
+ insert: "create",
851
+ update: "update",
852
+ delete: "delete"
853
+ };
854
+ return map[dbType];
855
+ }
856
+ getModelToUpdate(item, user, info) {
857
+ const result = ObjectService.removeTypes(item);
858
+ result["_id"] = result.id;
859
+ delete result.id;
860
+ result["__info"] = {
861
+ ...info,
862
+ update: {
863
+ username: user ? user.username : null,
864
+ date: /* @__PURE__ */ new Date()
865
+ }
866
+ };
867
+ return result;
868
+ }
869
+ getModelToResult(item) {
870
+ if (!item)
871
+ return null;
872
+ const result = ObjectService.removeTypes(item);
873
+ result["id"] = result._id;
874
+ delete result._id;
875
+ delete result["__info"];
876
+ return result;
877
+ }
878
+ getUrl() {
879
+ return getMongoUrl(this.config);
880
+ }
881
+ async logChange(type, item, options, user, error) {
882
+ const client = await MongoClient3.connect(this.getUrl());
883
+ const db = client.db(this.config.database);
884
+ try {
885
+ await db.collection("changes").insertOne({
886
+ type,
887
+ collection: this.config.collection,
888
+ item,
889
+ options,
890
+ user,
891
+ error,
892
+ date: /* @__PURE__ */ new Date()
893
+ });
894
+ } catch (e) {
895
+ console.warn(e);
896
+ } finally {
897
+ await client.close();
898
+ }
899
+ }
900
+ generateSearch(criteria) {
901
+ if (!criteria["$search"])
902
+ return;
903
+ if (this.config.type) {
904
+ const modelFields = getModelFieldsWithOptions(
905
+ new this.config.type()
906
+ ).filter((i) => i.options.search);
907
+ if (modelFields.length) {
908
+ const searchArray = [];
909
+ modelFields.forEach((val) => {
910
+ const res = {};
911
+ res[val.key] = {
912
+ $regex: this.convertRegex(criteria["$search"]),
913
+ $options: "i"
914
+ };
915
+ searchArray.push(res);
916
+ });
917
+ if (!criteria["$or"])
918
+ criteria["$or"] = searchArray;
919
+ else if (criteria["$or"] && !criteria["$and"]) {
920
+ criteria["$and"] = [{ $or: criteria["$or"] }, { $or: searchArray }];
921
+ delete criteria["$or"];
922
+ } else if (criteria["$and"]) {
923
+ criteria["$and"] = [...criteria["$and"], { $or: searchArray }];
924
+ }
925
+ delete criteria["$search"];
926
+ return;
927
+ }
928
+ }
929
+ const customCriteria = {
930
+ $text: { $search: ' "' + this.convertRegex(criteria["$search"]) + '" ' }
931
+ };
932
+ delete criteria["$search"];
933
+ criteria = {
934
+ ...criteria,
935
+ ...customCriteria
936
+ };
937
+ }
938
+ convertIdInCriteria(criteria) {
939
+ if (criteria["id"]) {
940
+ criteria["_id"] = criteria["id"];
941
+ delete criteria["id"];
942
+ }
943
+ }
944
+ convertRegex(val) {
945
+ return val.toString().replace(/\*/g, "[*]");
946
+ }
947
+ async collectionContext(callback, repoOptions) {
948
+ const client = repoOptions?.transaction?.connection ? repoOptions.transaction.connection : await MongoClient3.connect(this.getUrl());
949
+ const db = client.db(this.config.database);
950
+ let result;
951
+ try {
952
+ result = await callback(db.collection(this.config.collection));
953
+ } finally {
954
+ if (!repoOptions?.transaction)
955
+ await client.close();
956
+ }
957
+ return result;
958
+ }
959
+ };
960
+ MongoItemRepository = __decorateClass([
961
+ Injectable4()
962
+ ], MongoItemRepository);
963
+
964
+ // packages/shared/mongo/src/lib/mongo.module.ts
965
+ var MongoModule = class _MongoModule {
966
+ static forRoot(config) {
967
+ const providers = [
968
+ { provide: MongoConfig, useValue: config },
969
+ { provide: IItemRepository, useClass: MongoItemRepository },
970
+ { provide: IAttachmentRepository, useClass: MongoAttachmentRepository },
971
+ { provide: IUnitOfWork, useClass: MongoUnitOfWork }
972
+ ];
973
+ return {
974
+ module: _MongoModule,
975
+ providers,
976
+ exports: providers
977
+ };
978
+ }
979
+ };
980
+
981
+ // packages/shared/nestjs/src/lib/shared.config.ts
982
+ import { Injectable as Injectable5 } from "@nestjs/common";
983
+ var SharedConfig = class {
984
+ };
985
+ SharedConfig = __decorateClass([
986
+ Injectable5()
987
+ ], SharedConfig);
988
+
989
+ // packages/shared/nestjs/src/lib/auth/jwt.strategy.ts
990
+ import { Injectable as Injectable6 } from "@nestjs/common";
991
+ import { PassportStrategy } from "@nestjs/passport";
992
+ import { ExtractJwt, Strategy } from "passport-jwt";
993
+ var JwtStrategy = class extends PassportStrategy(Strategy) {
994
+ constructor(config) {
995
+ super({
996
+ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
997
+ ignoreExpiration: false,
998
+ secretOrKey: config.tokenConfig?.secretOrPrivateKey
999
+ });
1000
+ this.config = config;
1001
+ }
1002
+ async validate(payload) {
1003
+ return {
1004
+ ...payload,
1005
+ permissions: payload.permissions,
1006
+ username: payload.sub
1007
+ };
1008
+ }
1009
+ };
1010
+ JwtStrategy = __decorateClass([
1011
+ Injectable6()
1012
+ ], JwtStrategy);
1013
+
1014
+ // packages/shared/nestjs/src/lib/auth/permission.service.ts
1015
+ import { Injectable as Injectable7 } from "@nestjs/common";
1016
+ var PermissionService = class {
1017
+ constructor(config) {
1018
+ this.config = config;
1019
+ }
1020
+ /**
1021
+ * Validates if the user has the required permissions for a given type.
1022
+ * @param {PermissionType} type - The type of permission to validate.
1023
+ * @param {IUser} user - The user object containing permissions.
1024
+ * @throws {DomainForbiddenError} If the user does not have the required permissions.
1025
+ */
1026
+ valid(type, user) {
1027
+ if (!this.config.permissions)
1028
+ return;
1029
+ const typeConfig = this.config.permissions[type];
1030
+ if (!typeConfig)
1031
+ return;
1032
+ if (!user.permissions)
1033
+ throw new DomainForbiddenError(`Context forbidden`);
1034
+ if (!typeConfig.some((tc) => user.permissions.some((up) => tc === up)))
1035
+ throw new DomainForbiddenError(`Context forbidden`);
1036
+ }
1037
+ };
1038
+ PermissionService = __decorateClass([
1039
+ Injectable7()
1040
+ ], PermissionService);
1041
+
1042
+ // packages/shared/nestjs/src/lib/shared.module.ts
1043
+ var SharedModule = class _SharedModule {
1044
+ /**
1045
+ * Configures the module's core functionalities.
1046
+ *
1047
+ * @param {SharedConfig} config - An object containing the module's configuration.
1048
+ * @returns {DynamicModule} A DynamicModule object with providers and exports.
1049
+ */
1050
+ static forFeature(config) {
1051
+ return {
1052
+ module: _SharedModule,
1053
+ providers: [
1054
+ { provide: SharedConfig, useValue: config },
1055
+ JwtStrategy,
1056
+ PermissionService
1057
+ ],
1058
+ exports: [
1059
+ { provide: SharedConfig, useValue: config },
1060
+ PermissionService,
1061
+ JwtStrategy
1062
+ ]
1063
+ };
1064
+ }
1065
+ /**
1066
+ * Extends the forFeature() configuration by adding database settings. Use in AppModule.
1067
+ *
1068
+ * @param {SharedConfig & { db: { host: string; port: number; database: string; username?: string; password?: string; }}} config - An extended SharedConfig object that includes additional database settings.
1069
+ * @returns {DynamicModule} A DynamicModule object that imports and exports the forFeature() configuration.
1070
+ */
1071
+ static forRoot(config) {
1072
+ return {
1073
+ module: _SharedModule,
1074
+ imports: [_SharedModule.forFeature(config)],
1075
+ exports: [_SharedModule.forFeature(config)]
1076
+ };
1077
+ }
1078
+ };
1079
+
1080
+ // packages/shared/nestjs/src/lib/filters/execution/exception.filter.ts
1081
+ import {
1082
+ Catch,
1083
+ HttpException,
1084
+ HttpStatus,
1085
+ Logger as Logger2
1086
+ } from "@nestjs/common";
1087
+ var AppExceptionFilter = class {
1088
+ /**
1089
+ * Method to catch and handle exceptions.
1090
+ *
1091
+ * @param {any} exception - The exception thrown.
1092
+ * @param {ArgumentsHost} host - The arguments host.
1093
+ */
1094
+ catch(exception, host) {
1095
+ const ctx = host.switchToHttp();
1096
+ const response = ctx.getResponse();
1097
+ let status = HttpStatus.INTERNAL_SERVER_ERROR;
1098
+ let message = null;
1099
+ if (exception instanceof HttpException) {
1100
+ status = exception.getStatus();
1101
+ message = exception["message"];
1102
+ } else if (exception["type"] === DomainValidationError) {
1103
+ status = HttpStatus.BAD_REQUEST;
1104
+ message = exception["message"];
1105
+ } else if (exception["type"] === DomainForbiddenError) {
1106
+ status = HttpStatus.FORBIDDEN;
1107
+ message = exception["message"];
1108
+ } else {
1109
+ status = HttpStatus.INTERNAL_SERVER_ERROR;
1110
+ message = "Internal server error";
1111
+ }
1112
+ Logger2.error(
1113
+ exception["stack"] || exception["message"] || exception,
1114
+ AppExceptionFilter.name
1115
+ );
1116
+ const result = response.status(status);
1117
+ if (message && result.json) {
1118
+ result.json({
1119
+ details: message
1120
+ });
1121
+ } else if (!message && result.json) {
1122
+ result.json();
1123
+ } else if (message && !result.json) {
1124
+ result.send({
1125
+ details: message
1126
+ });
1127
+ } else {
1128
+ result.send();
1129
+ }
1130
+ }
1131
+ };
1132
+ AppExceptionFilter = __decorateClass([
1133
+ Catch()
1134
+ ], AppExceptionFilter);
1135
+
1136
+ // packages/shared/nestjs/src/lib/decorators/user/user.decorator.ts
1137
+ import { createParamDecorator } from "@nestjs/common";
1138
+ var User = createParamDecorator((_3, context) => {
1139
+ const [req] = context.getArgs();
1140
+ return req.user;
1141
+ });
1142
+
1143
+ // packages/crud/shell/nestjs/src/lib/controllers/crud/crud.controller.ts
1144
+ import {
1145
+ Body,
1146
+ Controller,
1147
+ Delete,
1148
+ Get,
1149
+ HttpCode,
1150
+ NotFoundException,
1151
+ Param,
1152
+ Patch,
1153
+ Post,
1154
+ Put,
1155
+ Query,
1156
+ Req,
1157
+ Res,
1158
+ UseGuards
1159
+ } from "@nestjs/common";
1160
+ import * as Busboy from "busboy";
1161
+ import { Parser } from "json2csv";
1162
+ import * as _2 from "lodash";
1163
+ import * as moment from "moment-timezone";
1164
+ import * as XLSX from "xlsx";
1165
+ import { Readable } from "stream";
1166
+
1167
+ // packages/crud/shell/nestjs/src/lib/controllers/crud/query-to-mongo.ts
1168
+ import * as querystring from "querystring";
1169
+ var iso8601 = /^\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01]))?)?(T([01][0-9]|2[0-3]):[0-5]\d(:[0-5]\d(\.\d+)?)?(Z|[+-]\d{2}:\d{2}))?$/;
1170
+ function fieldsToMongo(fields) {
1171
+ if (!fields)
1172
+ return null;
1173
+ const hash = {};
1174
+ fields.split(",").forEach(function(field) {
1175
+ hash[field.trim()] = 1;
1176
+ });
1177
+ return hash;
1178
+ }
1179
+ function convertRegex(val) {
1180
+ return val.toString().replace(/\*/g, "[*]");
1181
+ }
1182
+ function omitFieldsToMongo(omitFields) {
1183
+ if (!omitFields)
1184
+ return null;
1185
+ const hash = {};
1186
+ omitFields.split(",").forEach(function(omitField) {
1187
+ hash[omitField.trim()] = 0;
1188
+ });
1189
+ return hash;
1190
+ }
1191
+ function sortToMongo(sort) {
1192
+ if (!sort)
1193
+ return null;
1194
+ const hash = {};
1195
+ let c;
1196
+ sort.split(",").forEach(function(field) {
1197
+ c = field.charAt(0);
1198
+ if (c === "-")
1199
+ field = field.substr(1);
1200
+ hash[field.trim()] = c === "-" ? -1 : 1;
1201
+ });
1202
+ return hash;
1203
+ }
1204
+ function typedValue(value) {
1205
+ if (value[0] === "!")
1206
+ value = value.substr(1);
1207
+ const regex = value.match(/^\/(.*)\/(i?)$/);
1208
+ const quotedString = value.match(/(["'])(?:\\\1|.)*?\1/);
1209
+ if (regex) {
1210
+ return new RegExp(regex[1], regex[2]);
1211
+ } else if (quotedString) {
1212
+ return quotedString[0].substr(1, quotedString[0].length - 2);
1213
+ } else if (value === "true") {
1214
+ return true;
1215
+ } else if (value === "false") {
1216
+ return false;
1217
+ } else if (iso8601.test(value) && value.length !== 4 && value.length !== 10) {
1218
+ return new Date(value);
1219
+ } else if (!isNaN(Number(value))) {
1220
+ return Number(value);
1221
+ }
1222
+ return value;
1223
+ }
1224
+ function typedValues(svalue) {
1225
+ const commaSplit = /("[^"]*")|('[^']*')|(\/[^/]*\/i?)|([^,]+)/g;
1226
+ const values = [];
1227
+ svalue.match(commaSplit).forEach(function(value) {
1228
+ values.push(typedValue(value));
1229
+ });
1230
+ return values;
1231
+ }
1232
+ function comparisonToMongo(key, value) {
1233
+ const join = value === "" ? key : key.concat("=", value);
1234
+ const parts = join.match(/^(!?[^><~!=:]+)(?:=?([><]=?|~?=|!?=|:.+=)(.+))?$/);
1235
+ let op;
1236
+ const hash = {};
1237
+ if (!parts)
1238
+ return null;
1239
+ key = parts[1];
1240
+ op = parts[2];
1241
+ if (!op) {
1242
+ if (key[0] !== "!")
1243
+ value = { $exists: true };
1244
+ else {
1245
+ key = key.substr(1);
1246
+ value = { $exists: false };
1247
+ }
1248
+ } else if (op === "=" && parts[3] === "!") {
1249
+ value = { $exists: false };
1250
+ } else if (op === "=" || op === "!=") {
1251
+ if (op === "=" && parts[3][0] === "!")
1252
+ op = "!=";
1253
+ const array = typedValues(parts[3]);
1254
+ if (array.length > 1) {
1255
+ value = {};
1256
+ op = op === "=" ? "$in" : "$nin";
1257
+ value[op] = array;
1258
+ } else if (op === "!=") {
1259
+ value = array[0] instanceof RegExp ? { $not: array[0] } : { $ne: array[0] };
1260
+ } else if (array[0][0] === "!") {
1261
+ const sValue = array[0].substr(1);
1262
+ const regex = sValue.match(/^\/(.*)\/(i?)$/);
1263
+ value = regex ? { $not: new RegExp(regex[1], regex[2]) } : { $ne: sValue };
1264
+ } else {
1265
+ value = array[0];
1266
+ }
1267
+ } else if (op[0] === ":" && op[op.length - 1] === "=") {
1268
+ op = "$" + op.substr(1, op.length - 2);
1269
+ const array = [];
1270
+ parts[3].split(",").forEach(function(value2) {
1271
+ array.push(typedValue(value2));
1272
+ });
1273
+ value = {};
1274
+ value[op] = array.length === 1 ? array[0] : array;
1275
+ } else {
1276
+ value = typedValue(parts[3]);
1277
+ if (op === ">")
1278
+ value = { $gt: value };
1279
+ else if (op === ">=")
1280
+ value = { $gte: value };
1281
+ else if (op === "<")
1282
+ value = { $lt: value };
1283
+ else if (op === "<=")
1284
+ value = { $lte: value };
1285
+ else if (op === "~=")
1286
+ value = {
1287
+ $regex: value ? convertRegex(value) : "",
1288
+ $options: "i"
1289
+ };
1290
+ }
1291
+ hash.key = key;
1292
+ hash.value = value;
1293
+ return hash;
1294
+ }
1295
+ function hasOrdinalKeys(obj) {
1296
+ let c = 0;
1297
+ for (const key in obj) {
1298
+ if (Number(key) !== c++)
1299
+ return false;
1300
+ }
1301
+ return true;
1302
+ }
1303
+ function queryCriteriaToMongo(query, options = null) {
1304
+ const hash = {};
1305
+ let deep, p;
1306
+ options = options || {};
1307
+ for (const key in query) {
1308
+ if (Object.prototype.hasOwnProperty.call(query, key) && (!options.ignore || options.ignore.indexOf(key) === -1)) {
1309
+ deep = typeof query[key] === "object" && !hasOrdinalKeys(query[key]);
1310
+ if (deep) {
1311
+ p = {
1312
+ key,
1313
+ value: queryCriteriaToMongo(query[key])
1314
+ };
1315
+ } else {
1316
+ p = comparisonToMongo(key, query[key]);
1317
+ }
1318
+ if (p) {
1319
+ if (!hash[p.key]) {
1320
+ hash[p.key] = p.value;
1321
+ } else if (typeof p.value === "string") {
1322
+ hash[p.key] = Object.assign(hash[p.key], {
1323
+ $eq: p.value
1324
+ });
1325
+ } else {
1326
+ hash[p.key] = Object.assign(hash[p.key], p.value);
1327
+ }
1328
+ }
1329
+ }
1330
+ }
1331
+ return hash;
1332
+ }
1333
+ function queryOptionsToMongo(query, options) {
1334
+ const hash = {}, fields = fieldsToMongo(query[options.keywords.fields]), omitFields = omitFieldsToMongo(query[options.keywords.omit]), sort = sortToMongo(query[options.keywords.sort]), maxLimit = options.maxLimit || 9007199254740992;
1335
+ let limit = options.maxLimit || 0;
1336
+ if (fields)
1337
+ hash.fields = fields;
1338
+ if (omitFields)
1339
+ hash.fields = omitFields;
1340
+ if (sort)
1341
+ hash.sort = sort;
1342
+ if (query[options.keywords.offset])
1343
+ hash.skip = Number(query[options.keywords.offset]);
1344
+ if (query[options.keywords.limit])
1345
+ limit = Math.min(Number(query[options.keywords.limit]), maxLimit);
1346
+ if (limit) {
1347
+ hash.limit = limit;
1348
+ } else if (options.maxLimit) {
1349
+ hash.limit = maxLimit;
1350
+ }
1351
+ return hash;
1352
+ }
1353
+ function q2m(query = null, options = null) {
1354
+ query = query || {};
1355
+ options = options || {};
1356
+ options.keywords = options.keywords || {};
1357
+ const defaultKeywords = {
1358
+ fields: "fields",
1359
+ omit: "omit",
1360
+ sort: "sort",
1361
+ offset: "offset",
1362
+ limit: "limit"
1363
+ };
1364
+ options.keywords = Object.assign(defaultKeywords, options.keywords);
1365
+ const ignoreKeywords = [
1366
+ options.keywords.fields,
1367
+ options.keywords.omit,
1368
+ options.keywords.sort,
1369
+ options.keywords.offset,
1370
+ options.keywords.limit
1371
+ ];
1372
+ if (!options.ignore) {
1373
+ options.ignore = [];
1374
+ } else {
1375
+ options.ignore = typeof options.ignore === "string" ? [options.ignore] : options.ignore;
1376
+ }
1377
+ options.ignore = options.ignore.concat(ignoreKeywords);
1378
+ if (!options.parser)
1379
+ options.parser = querystring;
1380
+ if (typeof query === "string")
1381
+ query = options.parser.parse(query);
1382
+ return {
1383
+ criteria: queryCriteriaToMongo(query, options),
1384
+ options: queryOptionsToMongo(query, options),
1385
+ links: function(url, totalCount) {
1386
+ const offset = this.options.skip || 0;
1387
+ const limit = Math.min(this.options.limit || 0, totalCount);
1388
+ const links = {};
1389
+ const last = {};
1390
+ if (!limit)
1391
+ return null;
1392
+ options = options || {};
1393
+ if (offset > 0) {
1394
+ query[options.keywords.offset] = Math.max(offset - limit, 0);
1395
+ links["prev"] = url + "?" + options.parser.stringify(query);
1396
+ query[options.keywords.offset] = 0;
1397
+ links["first"] = url + "?" + options.parser.stringify(query);
1398
+ }
1399
+ if (offset + limit < totalCount) {
1400
+ last.pages = Math.ceil(totalCount / limit);
1401
+ last.offset = (last.pages - 1) * limit;
1402
+ query[options.keywords.offset] = Math.min(offset + limit, last.offset);
1403
+ links["next"] = url + "?" + options.parser.stringify(query);
1404
+ query[options.keywords.offset] = last.offset;
1405
+ links["last"] = url + "?" + options.parser.stringify(query);
1406
+ }
1407
+ return links;
1408
+ }
1409
+ };
1410
+ }
1411
+
1412
+ // packages/crud/shell/nestjs/src/lib/guards/auth/auth.guard.ts
1413
+ import { Injectable as Injectable8, UnauthorizedException, Logger as Logger3 } from "@nestjs/common";
1414
+ import { AuthGuard } from "@nestjs/passport";
1415
+ var AuthJwtGuard = class extends AuthGuard("jwt") {
1416
+ constructor() {
1417
+ super(...arguments);
1418
+ this.logger = new Logger3(AuthJwtGuard.name, { timestamp: true });
1419
+ }
1420
+ handleRequest(err, user, info) {
1421
+ if (err || !user) {
1422
+ this.logger.warn(JSON.stringify(info));
1423
+ throw err || new UnauthorizedException();
1424
+ }
1425
+ return user;
1426
+ }
1427
+ };
1428
+ AuthJwtGuard = __decorateClass([
1429
+ Injectable8()
1430
+ ], AuthJwtGuard);
1431
+ var AuthOrAnonymousJwtGuard = class extends AuthGuard("jwt") {
1432
+ handleRequest(err, user, info) {
1433
+ return user;
1434
+ }
1435
+ };
1436
+ AuthOrAnonymousJwtGuard = __decorateClass([
1437
+ Injectable8()
1438
+ ], AuthOrAnonymousJwtGuard);
1439
+
1440
+ // packages/crud/shell/nestjs/src/lib/controllers/crud/crud.controller.ts
1441
+ var CrudController = class {
1442
+ constructor(service) {
1443
+ this.service = service;
1444
+ }
1445
+ static getLink(req) {
1446
+ return req.protocol + "://" + req.headers.host + req.url;
1447
+ }
1448
+ async create(data, user, res) {
1449
+ const id = await this.service.create(data, user);
1450
+ res.set("Location", CrudController.getLink(res.req) + "/" + id);
1451
+ return res.send({
1452
+ id
1453
+ });
1454
+ }
1455
+ async createMany(data, user, res, mode) {
1456
+ const result = await this.service.createMany(data, user, { mode });
1457
+ return res.send(result);
1458
+ }
1459
+ async readById(params, user) {
1460
+ const result = await this.service.readById(params.id, user);
1461
+ if (!result) {
1462
+ throw new NotFoundException("Invalid id");
1463
+ }
1464
+ return result;
1465
+ }
1466
+ async read(user, req, res) {
1467
+ const object = this.getQueryObject(req.query);
1468
+ const { data, totalCount } = await this.service.read(
1469
+ object.criteria,
1470
+ {
1471
+ ...object.options,
1472
+ allowDiskUse: req.headers["content-type"] === "text/csv" || req.headers["content-type"] === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1473
+ },
1474
+ user
1475
+ );
1476
+ if (req.headers["content-type"] === "text/csv") {
1477
+ res.set({
1478
+ "Content-Type": "text/csv"
1479
+ });
1480
+ res.send(this.parseToCsv(data));
1481
+ }
1482
+ if (req.headers["content-type"] === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
1483
+ res.set({
1484
+ "Content-Type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1485
+ });
1486
+ res.send(this.parseToXlsx(data));
1487
+ }
1488
+ res.send({
1489
+ data,
1490
+ totalCount,
1491
+ links: object.links(
1492
+ CrudController.getLink(req).split("?")[0],
1493
+ totalCount
1494
+ )
1495
+ });
1496
+ }
1497
+ async update(params, data, user) {
1498
+ await this.service.update(params.id, data, user);
1499
+ }
1500
+ async updatePartial(params, data, user) {
1501
+ await this.service.updatePartial(params.id, data, user);
1502
+ }
1503
+ async delete(params, user) {
1504
+ await this.service.delete(params.id, user);
1505
+ }
1506
+ uploadAttachment(request, response) {
1507
+ const busboy = new Busboy({
1508
+ headers: request.headers
1509
+ });
1510
+ const id = GuidService.create();
1511
+ const readable = new Readable();
1512
+ readable._read = () => {
1513
+ };
1514
+ let fileName, encoding, mimeType;
1515
+ busboy.on(
1516
+ "file",
1517
+ (field, file, resultFileName, resultEncoding, resultMimeType) => {
1518
+ fileName = resultFileName;
1519
+ encoding = resultEncoding;
1520
+ mimeType = resultMimeType;
1521
+ this.service.uploadAttachment({
1522
+ id,
1523
+ stream: readable,
1524
+ fileName,
1525
+ encoding,
1526
+ mimeType
1527
+ });
1528
+ file.on("data", (data) => {
1529
+ readable.push(data);
1530
+ });
1531
+ }
1532
+ );
1533
+ busboy.on("finish", function() {
1534
+ readable.push(null);
1535
+ response.set("Location", CrudController.getLink(response.req) + "/" + id);
1536
+ response.json({
1537
+ id,
1538
+ fileName,
1539
+ contentType: mimeType,
1540
+ length: readable.readableLength
1541
+ });
1542
+ response.end();
1543
+ });
1544
+ return request.pipe(busboy);
1545
+ }
1546
+ async downloadAttachment(id, request, response) {
1547
+ const fileInfo = await this.service.getAttachmentInfo(id);
1548
+ if (request.headers.range) {
1549
+ const range = request.headers.range.substr(6).split("-");
1550
+ const start = parseInt(range[0], 10);
1551
+ const end = parseInt(range[1], 10) || null;
1552
+ const readstream = await this.service.getAttachmentStream(id, {
1553
+ start,
1554
+ end
1555
+ });
1556
+ response.status(206);
1557
+ response.set({
1558
+ "Accept-Ranges": "bytes",
1559
+ "Content-Type": fileInfo.contentType,
1560
+ "Content-Range": `bytes ${start}-${end ? end : fileInfo.length - 1}/${fileInfo.length}`,
1561
+ "Content-Length": (end ? end : fileInfo.length) - start,
1562
+ "Content-Disposition": `attachment; filename="${encodeURI(fileInfo.fileName)}"`
1563
+ });
1564
+ response.on("close", () => {
1565
+ readstream.destroy();
1566
+ });
1567
+ readstream.pipe(response);
1568
+ } else {
1569
+ const readstream = await this.service.getAttachmentStream(id);
1570
+ response.on("close", () => {
1571
+ readstream.destroy();
1572
+ });
1573
+ response.status(200);
1574
+ response.set({
1575
+ "Accept-Range": "bytes",
1576
+ "Content-Type": fileInfo.contentType,
1577
+ "Content-Length": fileInfo.length,
1578
+ "Content-Disposition": `attachment; filename="${encodeURI(fileInfo.fileName)}"`
1579
+ });
1580
+ readstream.pipe(response);
1581
+ }
1582
+ }
1583
+ async deleteAttachment(id) {
1584
+ await this.service.deleteAttachment(id);
1585
+ }
1586
+ getQueryObject(queryObject) {
1587
+ let q = "";
1588
+ Object.keys(queryObject).forEach((key) => {
1589
+ q += `&${key}=${queryObject[key]}`;
1590
+ });
1591
+ const result = q2m(q);
1592
+ return result;
1593
+ }
1594
+ parseToXlsx(data) {
1595
+ if (!data || !data.length) {
1596
+ return "";
1597
+ }
1598
+ const { res } = this.getDataWithFields(data);
1599
+ const ws = XLSX.utils.json_to_sheet(res);
1600
+ const wb = XLSX.utils.book_new();
1601
+ XLSX.utils.book_append_sheet(wb, ws, "data");
1602
+ return XLSX.write(wb, { bookType: "xlsx", type: "buffer" });
1603
+ }
1604
+ parseToCsv(data) {
1605
+ if (!data || !data.length) {
1606
+ return "";
1607
+ }
1608
+ const { res, fields } = this.getDataWithFields(data);
1609
+ return new Parser(fields).parse(data);
1610
+ }
1611
+ getDataWithFields(data) {
1612
+ const fields = [];
1613
+ const execute = (item, baseKey, baseItem) => {
1614
+ Object.keys(item).forEach((key) => {
1615
+ if (item[key] && typeof item[key] === "string") {
1616
+ item[key] = item[key].replace(/<[^>]*>?/gm, "");
1617
+ }
1618
+ if (item[key] && item[key] instanceof Date) {
1619
+ item[key] = moment(item[key]).tz("Europe/Warsaw").format("YYYY-MM-DD HH:mm:ss");
1620
+ }
1621
+ const val = item[key];
1622
+ if (_2.isArray(val)) {
1623
+ return;
1624
+ } else if (_2.isObject(val) && Object.keys(val).length) {
1625
+ execute(val, baseKey + key + "_", baseItem);
1626
+ } else if (baseKey) {
1627
+ baseItem[baseKey + key] = val;
1628
+ if (!fields.some((f) => f === baseKey + key))
1629
+ fields.push(baseKey + key);
1630
+ } else {
1631
+ if (!fields.some((f) => f === key))
1632
+ fields.push(key);
1633
+ }
1634
+ });
1635
+ };
1636
+ data.forEach((item) => {
1637
+ execute(item, "", item);
1638
+ });
1639
+ data.forEach((item) => {
1640
+ Object.keys(item).forEach((key) => {
1641
+ if (!fields.some((f) => f === key)) {
1642
+ delete item[key];
1643
+ }
1644
+ });
1645
+ });
1646
+ return { res: data, fields };
1647
+ }
1648
+ };
1649
+ __decorateClass([
1650
+ UseGuards(AuthJwtGuard),
1651
+ Post(),
1652
+ HttpCode(200),
1653
+ __decorateParam(0, Body()),
1654
+ __decorateParam(1, User()),
1655
+ __decorateParam(2, Res())
1656
+ ], CrudController.prototype, "create", 1);
1657
+ __decorateClass([
1658
+ UseGuards(AuthJwtGuard),
1659
+ Post("bulk"),
1660
+ __decorateParam(0, Body()),
1661
+ __decorateParam(1, User()),
1662
+ __decorateParam(2, Res()),
1663
+ __decorateParam(3, Query("mode"))
1664
+ ], CrudController.prototype, "createMany", 1);
1665
+ __decorateClass([
1666
+ UseGuards(AuthOrAnonymousJwtGuard),
1667
+ Get(":id"),
1668
+ __decorateParam(0, Param()),
1669
+ __decorateParam(1, User())
1670
+ ], CrudController.prototype, "readById", 1);
1671
+ __decorateClass([
1672
+ UseGuards(AuthOrAnonymousJwtGuard),
1673
+ Get(),
1674
+ __decorateParam(0, User()),
1675
+ __decorateParam(1, Req()),
1676
+ __decorateParam(2, Res())
1677
+ ], CrudController.prototype, "read", 1);
1678
+ __decorateClass([
1679
+ UseGuards(AuthJwtGuard),
1680
+ Put(":id"),
1681
+ __decorateParam(0, Param()),
1682
+ __decorateParam(1, Body()),
1683
+ __decorateParam(2, User())
1684
+ ], CrudController.prototype, "update", 1);
1685
+ __decorateClass([
1686
+ UseGuards(AuthJwtGuard),
1687
+ Patch(":id"),
1688
+ __decorateParam(0, Param()),
1689
+ __decorateParam(1, Body()),
1690
+ __decorateParam(2, User())
1691
+ ], CrudController.prototype, "updatePartial", 1);
1692
+ __decorateClass([
1693
+ UseGuards(AuthJwtGuard),
1694
+ Delete(":id"),
1695
+ __decorateParam(0, Param()),
1696
+ __decorateParam(1, User())
1697
+ ], CrudController.prototype, "delete", 1);
1698
+ __decorateClass([
1699
+ Post("attachments"),
1700
+ __decorateParam(0, Req()),
1701
+ __decorateParam(1, Res())
1702
+ ], CrudController.prototype, "uploadAttachment", 1);
1703
+ __decorateClass([
1704
+ Get("attachments/:id"),
1705
+ __decorateParam(0, Param("id")),
1706
+ __decorateParam(1, Req()),
1707
+ __decorateParam(2, Res())
1708
+ ], CrudController.prototype, "downloadAttachment", 1);
1709
+ __decorateClass([
1710
+ Delete("attachments/:id"),
1711
+ __decorateParam(0, Param("id"))
1712
+ ], CrudController.prototype, "deleteAttachment", 1);
1713
+ CrudController = __decorateClass([
1714
+ Controller("")
1715
+ ], CrudController);
1716
+
1717
+ // packages/crud/shell/nestjs/src/lib/controllers/index.ts
1718
+ var CONTROLLERS = [CrudController];
1719
+
1720
+ // packages/crud/shell/nestjs/src/lib/gateways/crud/crud.gateway.ts
1721
+ import {
1722
+ ConnectedSocket,
1723
+ MessageBody,
1724
+ SubscribeMessage,
1725
+ WebSocketGateway
1726
+ } from "@nestjs/websockets";
1727
+ import { Observable as Observable2 } from "rxjs";
1728
+ var CrudGateway = class {
1729
+ constructor(service) {
1730
+ this.service = service;
1731
+ }
1732
+ handleFilter(data, client) {
1733
+ const event = "changes";
1734
+ return new Observable2((observer) => {
1735
+ this.clearSubscription(client);
1736
+ this._clientsSubscriptions.set(
1737
+ client.id,
1738
+ this.service.changes(data).subscribe(
1739
+ (res) => {
1740
+ observer.next({ event, data: res });
1741
+ },
1742
+ (error) => observer.error(error)
1743
+ )
1744
+ );
1745
+ });
1746
+ }
1747
+ afterInit(server) {
1748
+ this._clientsSubscriptions = /* @__PURE__ */ new Map();
1749
+ console.log("CrudGateway Init");
1750
+ }
1751
+ handleDisconnect(client) {
1752
+ this.clearSubscription(client);
1753
+ console.log(`Client disconnected: ${client.id}`);
1754
+ }
1755
+ clearSubscription(client) {
1756
+ if (this._clientsSubscriptions.has(client.id)) {
1757
+ this._clientsSubscriptions.get(client.id).unsubscribe();
1758
+ this._clientsSubscriptions.delete(client.id);
1759
+ }
1760
+ }
1761
+ handleConnection(client, ...args) {
1762
+ console.log(`Client connected: ${client.id}`);
1763
+ }
1764
+ };
1765
+ __decorateClass([
1766
+ SubscribeMessage("changes"),
1767
+ __decorateParam(0, MessageBody()),
1768
+ __decorateParam(1, ConnectedSocket())
1769
+ ], CrudGateway.prototype, "handleFilter", 1);
1770
+ CrudGateway = __decorateClass([
1771
+ WebSocketGateway({
1772
+ transports: ["websocket"],
1773
+ path: "/" + process.env.URL_PREFIX + "/_socket",
1774
+ namespace: "/" + process.env.URL_PREFIX
1775
+ })
1776
+ ], CrudGateway);
1777
+
1778
+ // packages/crud/shell/nestjs/src/lib/gateways/index.ts
1779
+ var GATEWAYS = [CrudGateway];
1780
+
1781
+ // packages/crud/shell/nestjs/src/lib/nestjs.module.ts
1782
+ var CrudShellNestjsModule = class {
1783
+ static forRoot(options) {
1784
+ return {
1785
+ module: CrudShellNestjsModule,
1786
+ controllers: options.restApi ? CONTROLLERS : [],
1787
+ providers: [
1788
+ ...SERVICES,
1789
+ ...options.socket ? GATEWAYS : [],
1790
+ AuthJwtGuard
1791
+ ],
1792
+ imports: [
1793
+ ...options.restApi && options.tokenConfig.secretOrPrivateKey ? [
1794
+ PassportModule.register({
1795
+ defaultStrategy: "jwt",
1796
+ session: false
1797
+ }),
1798
+ JwtModule.register({
1799
+ secret: options.tokenConfig.secretOrPrivateKey,
1800
+ signOptions: {
1801
+ expiresIn: options.tokenConfig.expiredIn
1802
+ }
1803
+ })
1804
+ ] : [],
1805
+ SharedModule.forFeature(options),
1806
+ MongoModule.forRoot(options.db)
1807
+ ],
1808
+ exports: [...SERVICES, AuthJwtGuard, MongoModule.forRoot(options.db)]
1809
+ };
1810
+ }
1811
+ };
1812
+ CrudShellNestjsModule = __decorateClass([
1813
+ Module({})
1814
+ ], CrudShellNestjsModule);
1815
+ var CrudShellNestjsCoreModule = class {
1816
+ static forRoot(options) {
1817
+ return {
1818
+ module: CrudShellNestjsModule,
1819
+ providers: [...SERVICES, ...GATEWAYS, AuthJwtGuard],
1820
+ imports: [
1821
+ PassportModule.register({ defaultStrategy: "jwt", session: false }),
1822
+ JwtModule.register({
1823
+ secret: options.tokenConfig.secretOrPrivateKey,
1824
+ signOptions: {
1825
+ expiresIn: options.tokenConfig.expiredIn
1826
+ }
1827
+ }),
1828
+ SharedModule.forRoot(options),
1829
+ MongoModule.forRoot(options.db)
1830
+ ],
1831
+ exports: []
1832
+ };
1833
+ }
1834
+ };
1835
+ CrudShellNestjsCoreModule = __decorateClass([
1836
+ Module({})
1837
+ ], CrudShellNestjsCoreModule);
1838
+
1839
+ // packages/shared/paynow/src/lib/paynow.service.ts
1840
+ import { Injectable as Injectable9, Logger as Logger4 } from "@nestjs/common";
1841
+ import * as CryptoJS from "crypto-js";
1842
+
1843
+ // packages/shared/paynow/src/lib/paynow.config.ts
1844
+ var PaynowConfig = class {
1845
+ };
1846
+ var PAYNOW_CONFIG_PROVIDER = "PAYNOW_CONFIG_PROVIDER";
1847
+
1848
+ // packages/shared/paynow/src/lib/paynow.service.ts
1849
+ var PaynowService = class {
1850
+ constructor(httpService, config, moduleRef) {
1851
+ this.httpService = httpService;
1852
+ this.config = config;
1853
+ this.moduleRef = moduleRef;
1854
+ }
1855
+ async create(obj) {
1856
+ const config = await this.getConfig(obj.data);
1857
+ const data = {
1858
+ externalId: obj.id,
1859
+ description: obj.name,
1860
+ currency: "PLN",
1861
+ amount: obj.amount,
1862
+ continueUrl: config.continueUrl,
1863
+ buyer: {
1864
+ email: obj.email
1865
+ }
1866
+ };
1867
+ if (obj.contactPhone || obj.firstName || obj.lastName) {
1868
+ data["buyer"] = {
1869
+ email: obj.email,
1870
+ phone: obj.contactPhone,
1871
+ firstName: obj.firstName,
1872
+ lastName: obj.lastName
1873
+ };
1874
+ }
1875
+ const signature = this.getSignature(data, config);
1876
+ const response = await this.httpService.post(this.getBaseUrl(config) + "/v1/payments", data, {
1877
+ headers: {
1878
+ "Content-Type": "application/json",
1879
+ "Api-Key": config.apiKey,
1880
+ "Idempotency-Key": GuidService.create(),
1881
+ Signature: signature
1882
+ },
1883
+ maxRedirects: 0
1884
+ }).toPromise();
1885
+ return {
1886
+ redirectUrl: response.data.redirectUrl,
1887
+ orderId: response.data.paymentId
1888
+ };
1889
+ }
1890
+ async getStatus(trans) {
1891
+ const orderId = this.getOrderId(trans);
1892
+ const config = await this.getConfig(trans.data);
1893
+ const response = await this.httpService.get(this.getBaseUrl(config) + "/v1/payments/" + orderId + "/status", {
1894
+ headers: {
1895
+ "Content-Type": "application/json",
1896
+ "Api-Key": config.apiKey
1897
+ }
1898
+ }).toPromise();
1899
+ return {
1900
+ status: this.getStatusFromExternal(response.data.status),
1901
+ data: response.data
1902
+ };
1903
+ }
1904
+ async refund(trans, comment) {
1905
+ const orderId = this.getOrderId(trans);
1906
+ const config = await this.getConfig(trans.data);
1907
+ const data = {
1908
+ amount: trans.amount
1909
+ };
1910
+ const signature = this.getSignature(data, config);
1911
+ const response = await this.httpService.post(
1912
+ this.getBaseUrl(config) + "/v1/payments/" + orderId + "/refunds",
1913
+ data,
1914
+ {
1915
+ headers: {
1916
+ "Content-Type": "application/json",
1917
+ "Api-Key": config.apiKey,
1918
+ "Idempotency-Key": GuidService.create(),
1919
+ Signature: signature
1920
+ }
1921
+ }
1922
+ ).toPromise();
1923
+ return response.data;
1924
+ }
1925
+ getOrderId(trans) {
1926
+ const historyItem = trans.history.find((x) => x.status === "started");
1927
+ if (!historyItem) {
1928
+ console.warn("Transaction without start status");
1929
+ return null;
1930
+ }
1931
+ return historyItem.data.orderId;
1932
+ }
1933
+ async getConfig(data) {
1934
+ try {
1935
+ const provider = this.moduleRef.get(
1936
+ PAYNOW_CONFIG_PROVIDER,
1937
+ { strict: false }
1938
+ );
1939
+ return await provider.get(data);
1940
+ } catch (e) {
1941
+ Logger4.warn("Paynow config provider not found", PaynowService.name);
1942
+ }
1943
+ return this.config;
1944
+ }
1945
+ getBaseUrl(config) {
1946
+ if (config.test)
1947
+ return "https://api.sandbox.paynow.pl";
1948
+ return "https://api.paynow.pl";
1949
+ }
1950
+ getStatusFromExternal(status) {
1951
+ switch (status) {
1952
+ case "CONFIRMED":
1953
+ return "completed";
1954
+ case "REJECTED":
1955
+ return "canceled";
1956
+ case "PENDING":
1957
+ return "pending";
1958
+ default:
1959
+ return status;
1960
+ }
1961
+ }
1962
+ getSignature(data, config) {
1963
+ return CryptoJS.enc.Base64.stringify(
1964
+ CryptoJS.HmacSHA256(JSON.stringify(data), config.apiSignatureKey)
1965
+ );
1966
+ }
1967
+ };
1968
+ PaynowService = __decorateClass([
1969
+ Injectable9()
1970
+ ], PaynowService);
1971
+
1972
+ // packages/shared/paypal/src/lib/paypal.config.ts
1973
+ var PaypalConfig = class {
1974
+ constructor(clientId, clientSecret, currencyCode, returnUrl, apiUrl, cancelUrl, test) {
1975
+ this.clientId = clientId;
1976
+ this.clientSecret = clientSecret;
1977
+ this.currencyCode = currencyCode;
1978
+ this.returnUrl = returnUrl;
1979
+ this.apiUrl = apiUrl;
1980
+ this.cancelUrl = cancelUrl;
1981
+ this.test = test;
1982
+ }
1983
+ };
1984
+ var PAYPAL_CONFIG_PROVIDER = "PAYPAL_CONFIG_PROVIDER";
1985
+
1986
+ // packages/shared/paypal/src/lib/paypal.service.ts
1987
+ import { Injectable as Injectable10, Logger as Logger5 } from "@nestjs/common";
1988
+ import * as paypal from "paypal-rest-sdk";
1989
+ var PaypalService = class {
1990
+ constructor(httpService, config, moduleRef) {
1991
+ this.httpService = httpService;
1992
+ this.config = config;
1993
+ this.moduleRef = moduleRef;
1994
+ }
1995
+ async create(obj) {
1996
+ const config = await this.getConfig(obj.data);
1997
+ const data = {
1998
+ intent: "sale",
1999
+ payer: {
2000
+ payment_method: "paypal"
2001
+ },
2002
+ redirect_urls: {
2003
+ return_url: config.apiUrl + "paypal/" + obj.id + "/confirm",
2004
+ cancel_url: config.cancelUrl
2005
+ },
2006
+ transactions: [
2007
+ {
2008
+ item_list: {
2009
+ items: [
2010
+ {
2011
+ name: obj.name,
2012
+ sku: obj.id,
2013
+ price: obj.amount / 100,
2014
+ currency: config.currencyCode,
2015
+ quantity: 1
2016
+ }
2017
+ ]
2018
+ },
2019
+ amount: {
2020
+ currency: config.currencyCode,
2021
+ total: obj.amount / 100
2022
+ },
2023
+ description: obj.name
2024
+ }
2025
+ ]
2026
+ };
2027
+ const result = await new Promise((res, rej) => {
2028
+ paypal.payment.create(
2029
+ data,
2030
+ this.getEnv(config),
2031
+ (error, payment2) => {
2032
+ if (error) {
2033
+ rej(error);
2034
+ } else {
2035
+ res(payment2);
2036
+ }
2037
+ }
2038
+ );
2039
+ });
2040
+ return {
2041
+ redirectUrl: result.links.find(
2042
+ (l) => l.rel === "approval_url"
2043
+ ).href,
2044
+ orderId: result.id
2045
+ };
2046
+ }
2047
+ async confirm(payerId, paymentId, amount, externalData) {
2048
+ const config = await this.getConfig(externalData);
2049
+ const data = {
2050
+ payer_id: payerId,
2051
+ transactions: [
2052
+ {
2053
+ amount: {
2054
+ currency: config.currencyCode,
2055
+ total: amount
2056
+ }
2057
+ }
2058
+ ]
2059
+ };
2060
+ return await new Promise((res, rej) => {
2061
+ paypal.payment.execute(
2062
+ paymentId,
2063
+ data,
2064
+ this.getEnv(config),
2065
+ (error, payment2) => {
2066
+ if (error) {
2067
+ rej(error);
2068
+ } else {
2069
+ res(payment2);
2070
+ }
2071
+ }
2072
+ );
2073
+ });
2074
+ }
2075
+ async getStatus(trans) {
2076
+ const orderId = this.getOrderId(trans) ?? "";
2077
+ const config = await this.getConfig(trans.data);
2078
+ const payment2 = await new Promise((res, rej) => {
2079
+ paypal.payment.get(
2080
+ orderId,
2081
+ this.getEnv(config),
2082
+ (error, result) => {
2083
+ if (error) {
2084
+ rej(error);
2085
+ } else {
2086
+ res(result);
2087
+ }
2088
+ }
2089
+ );
2090
+ });
2091
+ return {
2092
+ status: this.getStatusFromExternal(payment2.state),
2093
+ data: payment2
2094
+ };
2095
+ }
2096
+ async refund(trans, comment) {
2097
+ const orderId = this.getOrderId(trans);
2098
+ const config = await this.getConfig(trans.data);
2099
+ const transactionId = this.getTransactionId(trans);
2100
+ if (!transactionId) {
2101
+ throw new Error("Paypal transaction ID not found for refund");
2102
+ }
2103
+ const refundData = {
2104
+ amount: {
2105
+ total: (trans.amount / 100).toString(),
2106
+ currency: config.currencyCode
2107
+ },
2108
+ description: comment
2109
+ };
2110
+ return new Promise((resolve, reject) => {
2111
+ paypal.sale.refund(
2112
+ transactionId,
2113
+ refundData,
2114
+ this.getEnv(config),
2115
+ (error, refund) => {
2116
+ if (error) {
2117
+ reject(error);
2118
+ } else {
2119
+ resolve(refund);
2120
+ }
2121
+ }
2122
+ );
2123
+ });
2124
+ }
2125
+ getOrderId(trans) {
2126
+ const historyItem = trans.history.find((x) => x.status === "started");
2127
+ if (!historyItem) {
2128
+ console.warn("Transaction without start status");
2129
+ return null;
2130
+ }
2131
+ return historyItem.data.orderId;
2132
+ }
2133
+ getStatusFromExternal(status) {
2134
+ status = status.toUpperCase();
2135
+ switch (status) {
2136
+ case "COMPLETED":
2137
+ return "completed";
2138
+ case "VOIDED":
2139
+ return "canceled";
2140
+ case "CREATED":
2141
+ return "pending";
2142
+ case "SAVED":
2143
+ return "pending";
2144
+ case "APPROVED":
2145
+ return "completed";
2146
+ default:
2147
+ return status;
2148
+ }
2149
+ }
2150
+ async getConfig(data) {
2151
+ try {
2152
+ const provider = this.moduleRef.get(
2153
+ PAYPAL_CONFIG_PROVIDER,
2154
+ { strict: false }
2155
+ );
2156
+ return await provider.get(data);
2157
+ } catch (e) {
2158
+ Logger5.warn("PayPal config provider not found", PaypalService.name);
2159
+ }
2160
+ return this.config;
2161
+ }
2162
+ getEnv(config) {
2163
+ return {
2164
+ mode: config.test ? "sandbox" : "live",
2165
+ client_id: config.clientId,
2166
+ client_secret: config.clientSecret
2167
+ };
2168
+ }
2169
+ getApiUrl(config) {
2170
+ return config.test ? "https://api-m.sandbox.paypal.com/" : "https://api-m.paypal.com/";
2171
+ }
2172
+ getTransactionId(trans) {
2173
+ const historyItem = trans.history.find(
2174
+ (i) => i.status === "completed" && i.data && i.data.customData && i.data.customData.transactions && i.data.customData.transactions.length && i.data.customData.transactions[0].related_resources && i.data.customData.transactions[0].related_resources.length && i.data.customData.transactions[0].related_resources[0].sale
2175
+ );
2176
+ return historyItem ? historyItem.data.customData.transactions[0].related_resources[0].sale.id : null;
2177
+ }
2178
+ };
2179
+ PaypalService = __decorateClass([
2180
+ Injectable10()
2181
+ ], PaypalService);
2182
+
2183
+ // packages/shared/payu/src/lib/payu.service.ts
2184
+ import { Injectable as Injectable11, Logger as Logger6 } from "@nestjs/common";
2185
+
2186
+ // packages/shared/payu/src/lib/payu.config.ts
2187
+ var PayuConfig = class {
2188
+ };
2189
+ var PAYU_CONFIG_PROVIDER = "PAYU_CONFIG_PROVIDER";
2190
+
2191
+ // packages/shared/payu/src/lib/payu.service.ts
2192
+ var PayuService = class {
2193
+ constructor(httpService, config, moduleRef) {
2194
+ this.httpService = httpService;
2195
+ this.config = config;
2196
+ this.moduleRef = moduleRef;
2197
+ }
2198
+ async create(obj) {
2199
+ const config = await this.getConfig(obj.data);
2200
+ const token = await this.getToken(config);
2201
+ const data = {
2202
+ customerIp: obj.clientIp,
2203
+ extOrderId: obj.id,
2204
+ merchantPosId: config.posId,
2205
+ description: obj.name,
2206
+ currencyCode: "PLN",
2207
+ totalAmount: obj.amount,
2208
+ notifyUrl: config.notifyUrl,
2209
+ continueUrl: config.continueUrl,
2210
+ products: [
2211
+ {
2212
+ name: obj.name,
2213
+ unitPrice: obj.amount,
2214
+ quantity: "1"
2215
+ }
2216
+ ]
2217
+ };
2218
+ if (obj.options && obj.options["payMethod"]) {
2219
+ data["payMethods"] = {
2220
+ payMethod: obj.options["payMethod"]
2221
+ };
2222
+ }
2223
+ if (obj.contactPhone || obj.email || obj.firstName || obj.lastName) {
2224
+ data["buyer"] = {
2225
+ email: obj.email,
2226
+ phone: obj.contactPhone,
2227
+ firstName: obj.firstName,
2228
+ lastName: obj.lastName
2229
+ };
2230
+ }
2231
+ try {
2232
+ await this.httpService.post(this.getBaseUrl(config) + "/api/v2_1/orders", data, {
2233
+ headers: {
2234
+ "Content-Type": "application/json",
2235
+ Authorization: "Bearer " + token,
2236
+ "X-Requested-With": "XMLHttpRequest"
2237
+ },
2238
+ maxRedirects: 0
2239
+ }).toPromise();
2240
+ return null;
2241
+ } catch (e) {
2242
+ if (e.response && e.response.status === 302) {
2243
+ return {
2244
+ redirectUrl: e.response.data.redirectUri,
2245
+ orderId: e.response.data.orderId
2246
+ };
2247
+ }
2248
+ console.error(e);
2249
+ throw e;
2250
+ }
2251
+ }
2252
+ async getStatus(trans) {
2253
+ const orderId = this.getOrderId(trans);
2254
+ const config = await this.getConfig(trans.data);
2255
+ const token = await this.getToken(config);
2256
+ const response = await this.httpService.get(this.getBaseUrl(config) + "/api/v2_1/orders/" + orderId, {
2257
+ headers: {
2258
+ "Content-Type": "application/json",
2259
+ Authorization: "Bearer " + token,
2260
+ "X-Requested-With": "XMLHttpRequest"
2261
+ },
2262
+ maxRedirects: 0
2263
+ }).toPromise();
2264
+ if (!response.data.orders)
2265
+ return null;
2266
+ const order = response.data.orders[0];
2267
+ return {
2268
+ status: this.getStatusFromExternal(order.status),
2269
+ data: order
2270
+ };
2271
+ }
2272
+ async refund(trans, comment) {
2273
+ const orderId = this.getOrderId(trans);
2274
+ const config = await this.getConfig(trans.data);
2275
+ const token = await this.getToken(config);
2276
+ const response = await this.httpService.post(
2277
+ this.getBaseUrl(config) + "/api/v2_1/orders/" + orderId,
2278
+ {
2279
+ refund: {
2280
+ description: comment
2281
+ }
2282
+ },
2283
+ {
2284
+ headers: {
2285
+ "Content-Type": "application/json",
2286
+ Authorization: "Bearer " + token,
2287
+ "X-Requested-With": "XMLHttpRequest"
2288
+ },
2289
+ maxRedirects: 0
2290
+ }
2291
+ ).toPromise();
2292
+ return response.data;
2293
+ }
2294
+ getOrderId(trans) {
2295
+ const historyItem = trans.history.find((x) => x.status === "started");
2296
+ if (!historyItem) {
2297
+ console.warn("Transaction without start status");
2298
+ return null;
2299
+ }
2300
+ return historyItem.data.orderId;
2301
+ }
2302
+ async getToken(config) {
2303
+ try {
2304
+ const response = await this.httpService.post(
2305
+ this.getBaseUrl(config) + "/pl/standard/user/oauth/authorize",
2306
+ `grant_type=client_credentials&client_id=${config.clientId}&client_secret=${config.clientSecret}`
2307
+ ).toPromise();
2308
+ return response.data["access_token"];
2309
+ } catch (e) {
2310
+ console.error({
2311
+ url: this.getBaseUrl(config) + "/pl/standard/user/oauth/authorize",
2312
+ data: `grant_type=client_credentials&client_id=${config.clientId}&client_secret=${config.clientSecret}`,
2313
+ ex: e
2314
+ });
2315
+ throw e;
2316
+ }
2317
+ }
2318
+ async getConfig(data) {
2319
+ try {
2320
+ const provider = this.moduleRef.get(
2321
+ PAYU_CONFIG_PROVIDER,
2322
+ { strict: false }
2323
+ );
2324
+ return await provider.get(data);
2325
+ } catch (e) {
2326
+ Logger6.warn("PayPal config provider not found", PayuService.name);
2327
+ }
2328
+ return this.config;
2329
+ }
2330
+ getBaseUrl(config) {
2331
+ if (config.test)
2332
+ return "https://secure.snd.payu.com";
2333
+ return "https://secure.payu.com";
2334
+ }
2335
+ getStatusFromExternal(status) {
2336
+ switch (status) {
2337
+ case "COMPLETED":
2338
+ return "completed";
2339
+ case "CANCELED":
2340
+ return "canceled";
2341
+ case "PENDING":
2342
+ return "pending";
2343
+ default:
2344
+ return status;
2345
+ }
2346
+ }
2347
+ };
2348
+ PayuService = __decorateClass([
2349
+ Injectable11()
2350
+ ], PayuService);
2351
+
2352
+ // packages/shared/revolut/src/lib/revolut.config.ts
2353
+ var RevolutConfig = class {
2354
+ };
2355
+ var REVOLUT_CONFIG_PROVIDER = "REVOLUT_CONFIG_PROVIDER";
2356
+
2357
+ // packages/shared/revolut/src/lib/revolut.service.ts
2358
+ import { Injectable as Injectable12, Logger as Logger7, Optional as Optional2 } from "@nestjs/common";
2359
+ var RevolutService = class {
2360
+ constructor(httpService, moduleRef, config) {
2361
+ this.httpService = httpService;
2362
+ this.moduleRef = moduleRef;
2363
+ this.config = config;
2364
+ }
2365
+ async create(obj) {
2366
+ const config = await this.getConfig(obj.data);
2367
+ const data = {
2368
+ amount: obj.amount,
2369
+ description: obj.name,
2370
+ capture_mode: "AUTOMATIC",
2371
+ merchant_order_ext_ref: obj.id,
2372
+ customer_email: obj.email,
2373
+ currency: "PLN"
2374
+ };
2375
+ const response = await this.httpService.post(this.getBaseUrl(config) + "/api/1.0/orders", data, {
2376
+ headers: {
2377
+ "Content-Type": "application/json",
2378
+ Authorization: "Bearer " + config.token
2379
+ },
2380
+ maxRedirects: 0
2381
+ }).toPromise();
2382
+ return {
2383
+ responseData: response.data,
2384
+ orderId: response.data["public_id"]
2385
+ };
2386
+ }
2387
+ async getStatus(trans) {
2388
+ const config = await this.getConfig(trans.data);
2389
+ const historyItem = trans.history.find((h) => h.status === "started");
2390
+ const response = await this.httpService.get(
2391
+ this.getBaseUrl(config) + "/api/1.0/orders/" + historyItem.data.responseData.id,
2392
+ {
2393
+ headers: {
2394
+ "Content-Type": "application/json",
2395
+ Authorization: "Bearer " + config.token
2396
+ },
2397
+ maxRedirects: 0
2398
+ }
2399
+ ).toPromise();
2400
+ return {
2401
+ data: response.data,
2402
+ status: this.getStatusFromExternal(response.data["state"])
2403
+ };
2404
+ }
2405
+ refund(trans, comment) {
2406
+ return Promise.reject("Revolut does not support refund");
2407
+ }
2408
+ getBaseUrl(config) {
2409
+ if (config.test)
2410
+ return "https://sandbox-merchant.revolut.com";
2411
+ return "https://merchant.revolut.com/api";
2412
+ }
2413
+ async getConfig(data) {
2414
+ try {
2415
+ const provider = this.moduleRef.get(
2416
+ REVOLUT_CONFIG_PROVIDER,
2417
+ { strict: false }
2418
+ );
2419
+ return await provider.get(data);
2420
+ } catch (e) {
2421
+ Logger7.warn("Revolut config provider not found", RevolutService.name);
2422
+ }
2423
+ return this.config;
2424
+ }
2425
+ getStatusFromExternal(status) {
2426
+ switch (status) {
2427
+ case "PROCESSING":
2428
+ return "completed";
2429
+ case "CANCELLED":
2430
+ return "canceled";
2431
+ case "FAILED":
2432
+ return "canceled";
2433
+ case "PENDING":
2434
+ return "pending";
2435
+ default:
2436
+ return status;
2437
+ }
2438
+ }
2439
+ };
2440
+ RevolutService = __decorateClass([
2441
+ Injectable12(),
2442
+ __decorateParam(2, Optional2())
2443
+ ], RevolutService);
2444
+
2445
+ // packages/trans/domain/src/lib/feature-create-trans/creator.service.ts
2446
+ import { Injectable as Injectable13 } from "@nestjs/common";
2447
+ import { Guid as Guid3 } from "guid-typescript";
2448
+
2449
+ // packages/trans/domain/src/lib/entities/trans.entity.ts
2450
+ import { Column, Entity, ObjectIdColumn } from "typeorm";
2451
+ var Trans = class {
2452
+ };
2453
+ __decorateClass([
2454
+ ObjectIdColumn({ generated: false })
2455
+ ], Trans.prototype, "id", 2);
2456
+ __decorateClass([
2457
+ Column()
2458
+ ], Trans.prototype, "externalId", 2);
2459
+ __decorateClass([
2460
+ Column()
2461
+ ], Trans.prototype, "name", 2);
2462
+ __decorateClass([
2463
+ Column()
2464
+ ], Trans.prototype, "amount", 2);
2465
+ __decorateClass([
2466
+ Column()
2467
+ ], Trans.prototype, "firstName", 2);
2468
+ __decorateClass([
2469
+ Column()
2470
+ ], Trans.prototype, "lastName", 2);
2471
+ __decorateClass([
2472
+ Column()
2473
+ ], Trans.prototype, "email", 2);
2474
+ __decorateClass([
2475
+ Column()
2476
+ ], Trans.prototype, "contactPhone", 2);
2477
+ __decorateClass([
2478
+ Column()
2479
+ ], Trans.prototype, "data", 2);
2480
+ __decorateClass([
2481
+ Column()
2482
+ ], Trans.prototype, "system", 2);
2483
+ __decorateClass([
2484
+ Column()
2485
+ ], Trans.prototype, "options", 2);
2486
+ __decorateClass([
2487
+ Column()
2488
+ ], Trans.prototype, "status", 2);
2489
+ __decorateClass([
2490
+ Column()
2491
+ ], Trans.prototype, "modifyDate", 2);
2492
+ __decorateClass([
2493
+ Column(() => TransHistory)
2494
+ ], Trans.prototype, "history", 2);
2495
+ __decorateClass([
2496
+ Column()
2497
+ ], Trans.prototype, "clientIp", 2);
2498
+ Trans = __decorateClass([
2499
+ Entity("trans")
2500
+ ], Trans);
2501
+ var TransHistory = class {
2502
+ };
2503
+ __decorateClass([
2504
+ Column()
2505
+ ], TransHistory.prototype, "amount", 2);
2506
+ __decorateClass([
2507
+ Column()
2508
+ ], TransHistory.prototype, "data", 2);
2509
+ __decorateClass([
2510
+ Column()
2511
+ ], TransHistory.prototype, "system", 2);
2512
+ __decorateClass([
2513
+ Column()
2514
+ ], TransHistory.prototype, "status", 2);
2515
+ __decorateClass([
2516
+ Column()
2517
+ ], TransHistory.prototype, "modifyDate", 2);
2518
+ var TRANS_SYSTEMS = ["payu", "paypal", "revolut", "paynow"];
2519
+
2520
+ // packages/trans/domain/src/lib/trans.service.ts
2521
+ var TransBaseService = class {
2522
+ constructor(repository) {
2523
+ this.repository = repository;
2524
+ }
2525
+ addHistory(trans, data) {
2526
+ const historyItem = new TransHistory();
2527
+ historyItem.amount = trans.amount;
2528
+ historyItem.modifyDate = trans.modifyDate;
2529
+ historyItem.data = ObjectService.removeTypes(data);
2530
+ historyItem.system = trans.system;
2531
+ historyItem.status = trans.status;
2532
+ if (!trans.history)
2533
+ trans.history = [];
2534
+ trans.history.push(historyItem);
2535
+ }
2536
+ async setError(trans, error) {
2537
+ trans.modifyDate = /* @__PURE__ */ new Date();
2538
+ trans.status = "error";
2539
+ this.addHistory(trans, error);
2540
+ await this.repository.update(trans, null);
2541
+ }
2542
+ };
2543
+
2544
+ // packages/trans/domain/src/lib/feature-create-trans/creator.service.ts
2545
+ var CreatorService = class extends TransBaseService {
2546
+ constructor(repository) {
2547
+ super(repository);
2548
+ }
2549
+ create(config, internalService, paymentService) {
2550
+ this.valid(config);
2551
+ let trans = null;
2552
+ return this.prepare(config).then((r) => {
2553
+ trans = r;
2554
+ return this.setAsNew(trans, internalService);
2555
+ }).then(() => {
2556
+ return this.setAsStarted(trans, paymentService);
2557
+ }).catch((e) => {
2558
+ if (trans) {
2559
+ this.setError(trans, e);
2560
+ }
2561
+ console.error(e);
2562
+ throw e;
2563
+ });
2564
+ }
2565
+ async setAsStarted(trans, paymentService) {
2566
+ const paymentResult = await paymentService[trans.system].create({
2567
+ id: trans.id,
2568
+ name: trans.name,
2569
+ amount: trans.amount,
2570
+ firstName: trans.firstName,
2571
+ lastName: trans.lastName,
2572
+ email: trans.email,
2573
+ contactPhone: trans.contactPhone,
2574
+ clientIp: trans.clientIp,
2575
+ data: trans.data,
2576
+ options: trans.options
2577
+ });
2578
+ trans.status = "started";
2579
+ trans.modifyDate = /* @__PURE__ */ new Date();
2580
+ trans.externalId = paymentResult.orderId;
2581
+ this.addHistory(trans, paymentResult);
2582
+ await this.repository.update(trans, null);
2583
+ return paymentResult;
2584
+ }
2585
+ async setAsNew(trans, internalService) {
2586
+ const internalResult = await internalService.create(trans);
2587
+ if (internalResult.amount) {
2588
+ trans.amount = internalResult.amount;
2589
+ }
2590
+ trans.status = "new";
2591
+ trans.modifyDate = /* @__PURE__ */ new Date();
2592
+ this.addHistory(trans, internalResult);
2593
+ await this.repository.update(trans, null);
2594
+ }
2595
+ async prepare(config) {
2596
+ const trans = new Trans();
2597
+ Object.keys(config).forEach((key) => {
2598
+ trans[key] = config[key];
2599
+ });
2600
+ trans.id = Guid3.raw();
2601
+ trans.modifyDate = /* @__PURE__ */ new Date();
2602
+ trans.status = "prepare";
2603
+ this.addHistory(trans, trans.data);
2604
+ await this.repository.create(trans, null);
2605
+ return trans;
2606
+ }
2607
+ valid(req) {
2608
+ if (!req)
2609
+ throw new DomainValidationError("config is empty");
2610
+ if (!req.name)
2611
+ throw new DomainValidationError("name is empty");
2612
+ if (!req.clientIp)
2613
+ throw new DomainValidationError("client ip is empty");
2614
+ if (!req.amount || req.amount < 1)
2615
+ throw new DomainValidationError("amount is empty");
2616
+ if (!req.data)
2617
+ throw new DomainValidationError("data is empty");
2618
+ if (!req.system || !TRANS_SYSTEMS.some((s) => s === req.system))
2619
+ throw new DomainValidationError("system is empty");
2620
+ }
2621
+ };
2622
+ CreatorService = __decorateClass([
2623
+ Injectable13()
2624
+ ], CreatorService);
2625
+
2626
+ // packages/trans/domain/src/lib/feature-refresh-trans/refresher.service.ts
2627
+ import { Injectable as Injectable14, NotFoundException as NotFoundException2 } from "@nestjs/common";
2628
+ var RefresherService = class extends TransBaseService {
2629
+ constructor(repository) {
2630
+ super(repository);
2631
+ }
2632
+ async refresh(transId, internalService, paymentService, customData = {}) {
2633
+ const trans = (await this.repository.getByCriteria({
2634
+ externalId: transId
2635
+ })).data[0];
2636
+ if (!trans) {
2637
+ throw new NotFoundException2("Transaction not found: " + transId);
2638
+ }
2639
+ try {
2640
+ const { status, data } = await paymentService[trans.system].getStatus(trans);
2641
+ if (status === trans.status)
2642
+ return;
2643
+ trans.modifyDate = /* @__PURE__ */ new Date();
2644
+ trans.status = status;
2645
+ data["customData"] = customData;
2646
+ this.addHistory(trans, data);
2647
+ const internalRes = await internalService.refresh(trans);
2648
+ if (!internalRes)
2649
+ return;
2650
+ this.addHistory(trans, internalRes);
2651
+ await this.repository.updatePartial(
2652
+ {
2653
+ id: trans.id,
2654
+ modifyDate: trans.modifyDate,
2655
+ status: trans.status,
2656
+ history: trans.history
2657
+ },
2658
+ null
2659
+ );
2660
+ } catch (err) {
2661
+ console.error(err);
2662
+ await this.setError(trans, err);
2663
+ throw err;
2664
+ }
2665
+ }
2666
+ };
2667
+ RefresherService = __decorateClass([
2668
+ Injectable14()
2669
+ ], RefresherService);
2670
+
2671
+ // packages/trans/domain/src/lib/feature-refund-trans/refund.service.ts
2672
+ import { Injectable as Injectable15, NotFoundException as NotFoundException3 } from "@nestjs/common";
2673
+ var RefundService = class extends TransBaseService {
2674
+ constructor(repository) {
2675
+ super(repository);
2676
+ }
2677
+ async refund(transId, internalService, paymentService, comment = "Refund") {
2678
+ const trans = await this.repository.getById(transId);
2679
+ if (!trans) {
2680
+ throw new NotFoundException3("Transaction not found: " + transId);
2681
+ }
2682
+ if (trans.status !== "completed") {
2683
+ throw new NotFoundException3(
2684
+ "Transaction is not completed/error: " + transId
2685
+ );
2686
+ }
2687
+ try {
2688
+ const data = await paymentService[trans.system].refund(trans, comment);
2689
+ trans.modifyDate = /* @__PURE__ */ new Date();
2690
+ trans.status = "refund";
2691
+ data["customData"] = {
2692
+ comment
2693
+ };
2694
+ this.addHistory(trans, data);
2695
+ await this.repository.update(trans, null);
2696
+ } catch (err) {
2697
+ console.error(err);
2698
+ await this.setError(trans, err);
2699
+ throw err;
2700
+ }
2701
+ }
2702
+ };
2703
+ RefundService = __decorateClass([
2704
+ Injectable15()
2705
+ ], RefundService);
2706
+
2707
+ // packages/trans/domain/src/lib/trans.config.ts
2708
+ var TransConfig = class {
2709
+ constructor(internalApiUrl, tokenConfig) {
2710
+ this.internalApiUrl = internalApiUrl;
2711
+ this.tokenConfig = tokenConfig;
2712
+ }
2713
+ };
2714
+
2715
+ // packages/trans/domain/src/index.ts
2716
+ var DOMAIN_SERVICES = [
2717
+ CreatorService,
2718
+ RefresherService,
2719
+ RefundService
2720
+ ];
2721
+
2722
+ // packages/trans/shell/app-services/src/lib/services/trans/trans.service.ts
2723
+ import { Injectable as Injectable16, Optional as Optional3 } from "@nestjs/common";
2724
+
2725
+ // packages/trans/shell/app-services/src/lib/services/internal/internal.service.ts
2726
+ var TRANS_TOKEN_INTERNAL_SERVICE = "TRANS_TOKEN_INTERNAL_SERVICE";
2727
+
2728
+ // packages/trans/shell/app-services/src/lib/services/trans/trans.service.ts
2729
+ var TransService = class {
2730
+ constructor(moduleRef, creatorService, refresherService, refundService, httpService, config, repository, payuService, paynowService, paypalService, revolutService) {
2731
+ this.moduleRef = moduleRef;
2732
+ this.creatorService = creatorService;
2733
+ this.refresherService = refresherService;
2734
+ this.refundService = refundService;
2735
+ this.httpService = httpService;
2736
+ this.config = config;
2737
+ this.repository = repository;
2738
+ this.payuService = payuService;
2739
+ this.paynowService = paynowService;
2740
+ this.paypalService = paypalService;
2741
+ this.revolutService = revolutService;
2742
+ this._paymentService = {
2743
+ payu: this.payuService,
2744
+ paypal: this.paypalService,
2745
+ paynow: this.paynowService,
2746
+ revolut: this.revolutService
2747
+ };
2748
+ this._internalService = {
2749
+ create: (trans) => {
2750
+ if (!this.config.internalApiUrl)
2751
+ return Promise.resolve({
2752
+ date: /* @__PURE__ */ new Date(),
2753
+ req: trans
2754
+ });
2755
+ return this.httpService.post(this.config.internalApiUrl, trans).toPromise().then((res) => res.data);
2756
+ },
2757
+ refresh: (trans) => {
2758
+ if (!this.config.internalApiUrl)
2759
+ return Promise.resolve({
2760
+ date: /* @__PURE__ */ new Date(),
2761
+ req: trans,
2762
+ id: trans.id
2763
+ });
2764
+ return this.httpService.put(this.config.internalApiUrl + "/" + trans.id, trans).toPromise().then((res) => res.data);
2765
+ }
2766
+ };
2767
+ }
2768
+ create(ops) {
2769
+ return this.creatorService.create(
2770
+ ops,
2771
+ this.getInternalService(),
2772
+ this._paymentService
2773
+ );
2774
+ }
2775
+ async refresh(transId, data = {}) {
2776
+ await this.refresherService.refresh(
2777
+ transId,
2778
+ this.getInternalService(),
2779
+ this._paymentService,
2780
+ data
2781
+ );
2782
+ }
2783
+ async refund(transId, comment = "Refund") {
2784
+ await this.refundService.refund(
2785
+ transId,
2786
+ this.getInternalService(),
2787
+ this._paymentService,
2788
+ comment
2789
+ );
2790
+ }
2791
+ async getById(id) {
2792
+ return await this.repository.getById(id);
2793
+ }
2794
+ getInternalService() {
2795
+ try {
2796
+ return this.moduleRef.get(TRANS_TOKEN_INTERNAL_SERVICE, {
2797
+ strict: false
2798
+ });
2799
+ } catch (e) {
2800
+ return this._internalService;
2801
+ }
2802
+ }
2803
+ };
2804
+ TransService = __decorateClass([
2805
+ Injectable16(),
2806
+ __decorateParam(7, Optional3()),
2807
+ __decorateParam(8, Optional3()),
2808
+ __decorateParam(9, Optional3()),
2809
+ __decorateParam(10, Optional3())
2810
+ ], TransService);
2811
+
2812
+ // packages/trans/shell/app-services/src/lib/services/index.ts
2813
+ var SERVICES2 = [TransService];
2814
+
2815
+ // packages/trans/shell/nestjs/src/lib/controllers/paynow/paynow.controller.ts
2816
+ import { Body as Body2, Controller as Controller2, HttpCode as HttpCode2, Post as Post2 } from "@nestjs/common";
2817
+ var PaynowController = class {
2818
+ constructor(service) {
2819
+ this.service = service;
2820
+ }
2821
+ async refreshStatus(obj) {
2822
+ try {
2823
+ await this.service.refresh(obj.paymentId, obj);
2824
+ return "ok";
2825
+ } catch (e) {
2826
+ console.error(e);
2827
+ throw e;
2828
+ }
2829
+ }
2830
+ };
2831
+ __decorateClass([
2832
+ Post2(),
2833
+ HttpCode2(200),
2834
+ __decorateParam(0, Body2())
2835
+ ], PaynowController.prototype, "refreshStatus", 1);
2836
+ PaynowController = __decorateClass([
2837
+ Controller2("paynow")
2838
+ ], PaynowController);
2839
+
2840
+ // packages/trans/shell/nestjs/src/lib/controllers/paypal/paypal.controller.ts
2841
+ import {
2842
+ Body as Body3,
2843
+ Controller as Controller3,
2844
+ HttpCode as HttpCode3,
2845
+ Post as Post3,
2846
+ Get as Get2,
2847
+ Param as Param2,
2848
+ Query as Query2,
2849
+ Res as Res2,
2850
+ HttpStatus as HttpStatus2,
2851
+ Optional as Optional4
2852
+ } from "@nestjs/common";
2853
+ var PaypalController = class {
2854
+ constructor(service, config, paypalService) {
2855
+ this.service = service;
2856
+ this.config = config;
2857
+ this.paypalService = paypalService;
2858
+ }
2859
+ async refreshStatus(obj) {
2860
+ try {
2861
+ const trans = await this.service.getById(obj.item_number1);
2862
+ await this.service.refresh(trans.externalId, obj);
2863
+ return "ok";
2864
+ } catch (e) {
2865
+ console.error("ERROR ---> ", obj);
2866
+ console.error(e);
2867
+ throw e;
2868
+ }
2869
+ }
2870
+ async confirm(id, payerId, paymentId, res) {
2871
+ try {
2872
+ const trans = await this.service.getById(id);
2873
+ if (trans.externalId !== paymentId) {
2874
+ throw new Error("Invalid externaId");
2875
+ }
2876
+ const payment2 = await this.paypalService.confirm(
2877
+ payerId,
2878
+ paymentId,
2879
+ trans.amount / 100,
2880
+ trans.data
2881
+ );
2882
+ await this.service.refresh(paymentId, payment2);
2883
+ return res.redirect(HttpStatus2.MOVED_PERMANENTLY, this.config.returnUrl);
2884
+ } catch (e) {
2885
+ console.log(e);
2886
+ return res.redirect(HttpStatus2.MOVED_PERMANENTLY, this.config.cancelUrl);
2887
+ }
2888
+ }
2889
+ };
2890
+ __decorateClass([
2891
+ Post3(),
2892
+ HttpCode3(200),
2893
+ __decorateParam(0, Body3())
2894
+ ], PaypalController.prototype, "refreshStatus", 1);
2895
+ __decorateClass([
2896
+ Get2(":id/confirm"),
2897
+ __decorateParam(0, Param2("id")),
2898
+ __decorateParam(1, Query2("PayerID")),
2899
+ __decorateParam(2, Query2("paymentId")),
2900
+ __decorateParam(3, Res2())
2901
+ ], PaypalController.prototype, "confirm", 1);
2902
+ PaypalController = __decorateClass([
2903
+ Controller3("paypal"),
2904
+ __decorateParam(1, Optional4()),
2905
+ __decorateParam(2, Optional4())
2906
+ ], PaypalController);
2907
+
2908
+ // packages/trans/shell/nestjs/src/lib/controllers/payu/payu.controller.ts
2909
+ import { Body as Body4, Controller as Controller4, HttpCode as HttpCode4, Post as Post4 } from "@nestjs/common";
2910
+ var PayUController = class {
2911
+ constructor(service) {
2912
+ this.service = service;
2913
+ }
2914
+ async refreshStatus(obj) {
2915
+ try {
2916
+ await this.service.refresh(obj.order.orderId, obj);
2917
+ return "ok";
2918
+ } catch (e) {
2919
+ console.error(e);
2920
+ throw e;
2921
+ }
2922
+ }
2923
+ };
2924
+ __decorateClass([
2925
+ Post4(),
2926
+ HttpCode4(200),
2927
+ __decorateParam(0, Body4())
2928
+ ], PayUController.prototype, "refreshStatus", 1);
2929
+ PayUController = __decorateClass([
2930
+ Controller4("payu")
2931
+ ], PayUController);
2932
+
2933
+ // packages/trans/shell/nestjs/src/lib/controllers/trans/trans.controller.ts
2934
+ import { Body as Body5, Controller as Controller5, Param as Param3, Post as Post5, Req as Req2 } from "@nestjs/common";
2935
+ var TransController = class {
2936
+ constructor(service) {
2937
+ this.service = service;
2938
+ }
2939
+ async create(obj, req) {
2940
+ obj.clientIp = req.connection.remoteAddress.indexOf("::") === 0 ? "10.0.0.1" : req.connection.remoteAddress;
2941
+ const { redirectUrl, orderId } = await this.service.create(obj);
2942
+ return {
2943
+ url: redirectUrl,
2944
+ orderId
2945
+ };
2946
+ }
2947
+ async refresh(orderId, obj) {
2948
+ await this.service.refresh(orderId, {});
2949
+ }
2950
+ };
2951
+ __decorateClass([
2952
+ Post5(),
2953
+ __decorateParam(0, Body5()),
2954
+ __decorateParam(1, Req2())
2955
+ ], TransController.prototype, "create", 1);
2956
+ __decorateClass([
2957
+ Post5(":id/refresh"),
2958
+ __decorateParam(0, Param3("id")),
2959
+ __decorateParam(1, Body5())
2960
+ ], TransController.prototype, "refresh", 1);
2961
+ TransController = __decorateClass([
2962
+ Controller5("")
2963
+ ], TransController);
2964
+
2965
+ // packages/trans/shell/nestjs/src/lib/controllers/index.ts
2966
+ var CONTROLLERS2 = [
2967
+ TransController,
2968
+ PayUController,
2969
+ PaypalController,
2970
+ PaynowController
2971
+ ];
2972
+
2973
+ // packages/trans/shell/nestjs/src/lib/nestjs.module.ts
2974
+ var TransShellNestjsModule = class {
2975
+ static forRoot(config) {
2976
+ return {
2977
+ module: TransShellNestjsModule,
2978
+ controllers: CONTROLLERS2,
2979
+ providers: [
2980
+ ...SERVICES2,
2981
+ ...DOMAIN_SERVICES,
2982
+ { provide: TransConfig, useValue: config },
2983
+ ...config.payuConfig ? [{ provide: PayuConfig, useValue: config.payuConfig }, PayuService] : [],
2984
+ ...config.paypalConfig ? [
2985
+ { provide: PaypalConfig, useValue: config.paypalConfig },
2986
+ PaypalService
2987
+ ] : [],
2988
+ ...config.revolutConfig ? [
2989
+ { provide: RevolutConfig, useValue: config.revolutConfig },
2990
+ RevolutService
2991
+ ] : [],
2992
+ ...config.paynowConfig ? [
2993
+ { provide: PaynowConfig, useValue: config.paynowConfig },
2994
+ PaynowService
2995
+ ] : []
2996
+ ],
2997
+ imports: [
2998
+ CrudShellNestjsModule.forRoot({
2999
+ ...config,
3000
+ db: {
3001
+ ...config.db,
3002
+ collection: "trans"
3003
+ },
3004
+ restApi: false,
3005
+ socket: false
3006
+ }),
3007
+ PassportModule2.register({ defaultStrategy: "jwt", session: false }),
3008
+ JwtModule2.register({
3009
+ secret: config.tokenConfig.secretOrPrivateKey,
3010
+ signOptions: {
3011
+ expiresIn: config.tokenConfig.expiredIn
3012
+ }
3013
+ })
3014
+ ],
3015
+ exports: [
3016
+ ...SERVICES2,
3017
+ TransConfig,
3018
+ ...config.payuConfig ? [PayuConfig, PayuService] : [],
3019
+ ...config.paypalConfig ? [PaypalConfig, PaypalService] : [],
3020
+ ...config.revolutConfig ? [RevolutConfig, RevolutService] : []
3021
+ ]
3022
+ };
3023
+ }
3024
+ };
3025
+ TransShellNestjsModule = __decorateClass([
3026
+ Module2({
3027
+ imports: [HttpModule]
3028
+ })
3029
+ ], TransShellNestjsModule);
3030
+ var TransShellNestjsCoreModule = class {
3031
+ static forRoot(config) {
3032
+ return {
3033
+ module: TransShellNestjsCoreModule,
3034
+ providers: [
3035
+ ...SERVICES2,
3036
+ ...DOMAIN_SERVICES,
3037
+ { provide: TransConfig, useValue: config },
3038
+ ...config.payuConfig ? [{ provide: PayuConfig, useValue: config.payuConfig }, PayuService] : [],
3039
+ ...config.paypalConfig ? [
3040
+ { provide: PaypalConfig, useValue: config.paypalConfig },
3041
+ PaypalService
3042
+ ] : [],
3043
+ ...config.paynowConfig ? [
3044
+ { provide: PaynowConfig, useValue: config.paynowConfig },
3045
+ PaynowService
3046
+ ] : []
3047
+ ],
3048
+ imports: [
3049
+ CrudShellNestjsModule.forRoot({
3050
+ ...config,
3051
+ db: {
3052
+ ...config.db,
3053
+ collection: "trans"
3054
+ },
3055
+ restApi: false,
3056
+ socket: false
3057
+ }),
3058
+ PassportModule2.register({ defaultStrategy: "jwt", session: false }),
3059
+ JwtModule2.register({
3060
+ secret: config.tokenConfig.secretOrPrivateKey,
3061
+ signOptions: {
3062
+ expiresIn: config.tokenConfig.expiredIn
3063
+ }
3064
+ })
3065
+ ],
3066
+ exports: [
3067
+ ...SERVICES2,
3068
+ TransConfig,
3069
+ ...config.payuConfig ? [PayuConfig, PayuService] : [],
3070
+ ...config.paypalConfig ? [PaypalConfig, PaypalService] : [],
3071
+ ...config.revolutConfig ? [RevolutConfig, RevolutService] : [],
3072
+ ...config.paynowConfig ? [PaynowConfig, PaynowService] : []
3073
+ ]
3074
+ };
3075
+ }
3076
+ };
3077
+ TransShellNestjsCoreModule = __decorateClass([
3078
+ Module2({
3079
+ imports: [HttpModule]
3080
+ })
3081
+ ], TransShellNestjsCoreModule);
3082
+ export {
3083
+ CONTROLLERS2 as CONTROLLERS,
3084
+ PayUController,
3085
+ PaynowController,
3086
+ PaypalController,
3087
+ TransController,
3088
+ TransShellNestjsCoreModule,
3089
+ TransShellNestjsModule
3090
+ };