@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 +3090 -0
- package/package.json +1 -1
- package/src/lib/controllers/{index.ts → index.d.ts} +1 -8
- package/src/lib/controllers/paynow/paynow.controller.d.ts +8 -0
- package/src/lib/controllers/paypal/paypal.controller.d.ts +12 -0
- package/src/lib/controllers/payu/payu.controller.d.ts +10 -0
- package/src/lib/controllers/trans/trans.controller.d.ts +11 -0
- package/src/lib/nestjs.module.d.ts +43 -0
- package/.eslintrc.json +0 -11
- package/jest.config.ts +0 -27
- package/project.json +0 -39
- package/src/lib/controllers/paynow/paynow.controller.ts +0 -20
- package/src/lib/controllers/paypal/paypal.controller.ts +0 -69
- package/src/lib/controllers/payu/payu.controller.ts +0 -22
- package/src/lib/controllers/trans/trans.controller.ts +0 -27
- package/src/lib/nestjs.module.ts +0 -171
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -11
- package/tsconfig.spec.json +0 -20
- /package/src/{index.ts → index.d.ts} +0 -0
- /package/{test-setup.ts → test-setup.d.ts} +0 -0
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
|
+
};
|