gemcap-be-common 1.2.63 → 1.2.65

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/db/reports.db.ts CHANGED
@@ -7,7 +7,7 @@ import mongoose from 'mongoose';
7
7
  import { BorrowerModel } from '../models/Borrower.model';
8
8
  import {
9
9
  ELoanTransactionTypes,
10
- ILoanTransactionDocWithProduct,
10
+ ILoanTransactionDoc,
11
11
  LoanTransaction,
12
12
  } from '../models/LoanTransaction.model';
13
13
  import { ELoanTypes } from '../enums/loan-types.enum';
@@ -77,42 +77,87 @@ export interface ILedgerDataRow {
77
77
  isBrokerFee?: boolean;
78
78
  }
79
79
 
80
- export const getLedger = async (productId: string, startDate: Date, endDate: Date, reportType: ELedgerReportType, showFloatedBalance = true) => {
81
- const product: ILoanProductDoc = await LoanProduct.findById(productId).lean();
80
+ export type LedgerTransactions = {
81
+ transactions: ILoanTransactionDoc[];
82
+ product: ILoanProductDoc;
83
+ productId: mongoose.Types.ObjectId;
84
+ }
85
+
86
+ export type ReportLedgerParams = {
87
+ productIds: string[],
88
+ startDate: Date,
89
+ endDate: Date,
90
+ reportType: ELedgerReportType,
91
+ }
92
+
93
+ export type ReportLedgerOptions = {
94
+ showFloatedBalance: boolean,
95
+ showBalances: boolean,
96
+ }
97
+
98
+ const defaultReportLedgerOptions: ReportLedgerOptions = {
99
+ showBalances: true,
100
+ showFloatedBalance: true,
101
+ };
82
102
 
83
- const emptyWorkBook = { [`${product.code} - ${product.name}`]: [['']] };
84
- if (startDate === null || endDate === null) {
85
- return emptyWorkBook;
86
- }
87
- const fullTransactions = await getLedgerData(productId, startDate, endDate);
103
+ export const getLedger = async (params: ReportLedgerParams, options = defaultReportLedgerOptions): Promise<{
104
+ [productId: string]: ILedgerReportRow []
105
+ }> => {
106
+ const { productIds, reportType } = params;
107
+ const fullTransactions = await getLedgerData(params, options);
108
+ const products = await LoanProduct
109
+ .find({ _id: { $in: productIds.map((id) => new mongoose.Types.ObjectId(id)) } })
110
+ .sort({ code: 1 })
111
+ .lean();
88
112
 
89
113
  const header = ledgerHeadersMap[reportType];
90
- const headerKeys = showFloatedBalance
114
+ const headerKeys = options.showFloatedBalance
91
115
  ? Object.keys(header).filter((key) => key !== 'floatedBalance')
92
116
  : Object.keys(header);
93
117
 
94
118
  const sumKeys = ['amount', 'statementAmount'];
95
119
  const groupKeys = headerKeys.filter((key) => !sumKeys.includes(key));
96
- const finalTransactions = reportType === ELedgerReportType.SHORT
97
- ? mergeLedgerData(fullTransactions, groupKeys, sumKeys)
98
- : fullTransactions;
99
120
 
100
- const mappedArray = _.map([header, ...finalTransactions], (obj) => _.pick(obj, headerKeys));
101
- const sheetName = `${product.code} - ${product.name}`;
102
- return { [sheetName]: mappedArray };
121
+ return products.reduce((acc, product) => {
122
+ const transactions = fullTransactions[product._id.toString()];
123
+ const finalTransactions = reportType === ELedgerReportType.SHORT
124
+ ? mergeLedgerData(transactions, groupKeys, sumKeys)
125
+ : transactions;
126
+ const sheetName = `${product.code} - ${product.name}`;
127
+ return {
128
+ ...acc,
129
+ [sheetName]: _.map(finalTransactions, (obj) => _.pick(obj, headerKeys)) as ILedgerReportRow[],
130
+ };
131
+ }, {});
103
132
  };
104
133
 
105
- const getLedgerData = async (productId: string, startDate: Date, endDate: Date): Promise<ILedgerReportRow[]> => {
134
+ const getLedgerData = async (params: ReportLedgerParams, options = defaultReportLedgerOptions): Promise<{
135
+ [productId: string]: ILedgerReportRow[]
136
+ }> => {
137
+ const { productIds, startDate, endDate } = params;
138
+
106
139
  const addBrokers = true;
107
- const product: ILoanProductDoc = await LoanProduct.findById(productId).lean();
108
- const borrower = await BorrowerModel.findById(product.borrowerId).lean();
109
- const transactions = await LoanTransaction.aggregate<ILoanTransactionDocWithProduct>([
140
+ const products = await LoanProduct.find({ _id: { $in: productIds.map((id) => new mongoose.Types.ObjectId(id)) } }).lean();
141
+ const borrowers = await BorrowerModel.find({ _id: { $in: products.map((product) => product.borrowerId) } }).lean();
142
+ const borrowerMap = borrowers.reduce((acc, borrower) => (
143
+ { ...acc, [borrower._id.toString()]: borrower.code }
144
+ ), {});
145
+ const borrowerCodesMap = products.reduce((acc, product): { [productId: string]: string } => ({
146
+ ...acc,
147
+ [product._id.toString()]: borrowerMap[product.borrowerId.toString()],
148
+ }), {});
149
+
150
+ const groupedTransactions = await LoanTransaction.aggregate<LedgerTransactions>([
110
151
  {
111
152
  $match: {
112
153
  $and: [
113
154
  { 'date': { $gte: startDate } },
114
155
  { 'date': { $lte: dayjs(endDate).endOf('day').toDate() } },
115
- { 'productId': new mongoose.Types.ObjectId(productId) },
156
+ {
157
+ productId: {
158
+ $in: products.map((product) => product._id),
159
+ },
160
+ },
116
161
  ],
117
162
  },
118
163
  }, {
@@ -132,207 +177,240 @@ const getLedgerData = async (productId: string, startDate: Date, endDate: Date):
132
177
  'order': 1,
133
178
  },
134
179
  },
135
- ]);
136
- const convertTypes = (transactionType: ELoanTransactionTypes) => {
137
- if (product.type === ELoanTypes.TERM && transactionType === ELoanTransactionTypes.COLLECTION) {
138
- return 'PRINCIPAL';
139
- }
140
- return transactionType;
141
- };
142
- const mappedTransactions = transactions.map((transaction) => {
143
- return <ILedgerDataRow>{
144
- typeOrder: 0,
145
- order: transaction.order,
146
- date: transaction.date,
147
- type: convertTypes(transaction.transactionType),
148
- amount: transaction.amount,
149
- statementAmount: null,
150
- title: convertTypes(transaction.transactionType),
151
- balance: transaction.balance,
152
- floatedBalance: transaction.floatedBalance,
153
- chargeCode: transaction.product.code,
154
- PLCode: null,
155
- productCode: transaction.product.code,
156
- productName: transaction.product.name,
157
- createdAt: transaction['createdAt'],
158
- info: transaction.reference,
159
- paymentDate: null,
160
- };
161
- });
162
-
163
- const loanCharges = await getLoanChargeForProduct(productId);
164
- const chargesIds = loanCharges.map((charge) => charge._id);
165
- const statementTransactions = await LoanStatementTransactionModel.aggregate<ILoanStatementTransactionDocWithCharge>([
166
180
  {
167
- $match: {
168
- $and: [
169
- { 'date': { $gte: startDate } },
170
- { 'date': { $lte: dayjs(endDate).endOf('day').toDate() } },
171
- { 'chargeId': { '$in': chargesIds } },
172
- ],
173
- },
174
- }, {
175
- $lookup: {
176
- from: 'loan_charges',
177
- localField: 'chargeId',
178
- foreignField: '_id',
179
- as: 'charge',
180
- },
181
- }, {
182
- $unwind: {
183
- path: '$charge',
181
+ $group: {
182
+ _id: '$productId',
183
+ transactions: { $push: '$$ROOT' },
184
+ product: { $first: '$product' },
184
185
  },
185
- }, {
186
- $sort: {
187
- 'date': 1,
188
- 'createdAt': 1,
189
- 'order': 1,
186
+ },
187
+ {
188
+ $project: {
189
+ _id: 0,
190
+ productId: '$_id',
191
+ product: 1,
192
+ transactions: 1,
190
193
  },
191
194
  },
192
195
  ]);
193
196
 
194
- const statementTransactionsWithBalance = await Promise.all(statementTransactions.map(async (statement) => {
195
- const balances = await getLoanProductBalance(productId, statement.date);
197
+ const convertTypes = (transactionType: ELoanTransactionTypes, product: ILoanProductDoc): EChargeType => {
198
+ if (product.type === ELoanTypes.TERM && transactionType === ELoanTransactionTypes.COLLECTION) {
199
+ return EChargeType.PRINCIPAL;
200
+ }
201
+ return EChargeType[transactionType];
202
+ };
203
+
204
+ const mappedGroups: {
205
+ [productId: string]: { transactions: ILedgerDataRow[], product: ILoanProductDoc }
206
+ } = groupedTransactions.reduce((acc, group) => {
196
207
  return {
197
- ...statement,
198
- balance: balances.balance,
199
- floatedBalance: balances.floatedBalance,
208
+ ...acc,
209
+ [group.productId.toString()]: {
210
+ product: group.product,
211
+ transactions: group.transactions.map((transaction): ILedgerDataRow => {
212
+ return {
213
+ typeOrder: 0,
214
+ order: transaction.order,
215
+ date: transaction.date,
216
+ type: convertTypes(transaction.transactionType, group.product),
217
+ amount: transaction.amount,
218
+ statementAmount: null,
219
+ title: convertTypes(transaction.transactionType, group.product),
220
+ balance: transaction.balance,
221
+ floatedBalance: transaction.floatedBalance,
222
+ chargeCode: group.product.code,
223
+ PLCode: null,
224
+ productCode: group.product.code,
225
+ productName: group.product.name,
226
+ createdAt: transaction['createdAt'],
227
+ info: transaction.reference,
228
+ paymentDate: null,
229
+ };
230
+ }),
231
+ },
200
232
  };
201
- }));
233
+ }, {});
202
234
 
203
- const isParticipant = product.isParticipant;
204
- const groupedMappedStatementTransactions = await Promise.all(statementTransactionsWithBalance.map(async (statement) => {
235
+ const allData = {};
236
+ await Promise.all(Object.entries(mappedGroups).map(async ([productId, group]) => {
237
+ const loanCharges = await getLoanChargeForProduct(productId);
238
+ const chargesIds = loanCharges.map((charge) => charge._id);
239
+ const statementTransactions = await LoanStatementTransactionModel.aggregate<ILoanStatementTransactionDocWithCharge>([
240
+ {
241
+ $match: {
242
+ $and: [
243
+ { 'date': { $gte: startDate } },
244
+ { 'date': { $lte: dayjs(endDate).endOf('day').toDate() } },
245
+ { 'chargeId': { '$in': chargesIds } },
246
+ ],
247
+ },
248
+ }, {
249
+ $lookup: {
250
+ from: 'loan_charges',
251
+ localField: 'chargeId',
252
+ foreignField: '_id',
253
+ as: 'charge',
254
+ },
255
+ }, {
256
+ $unwind: {
257
+ path: '$charge',
258
+ },
259
+ }, {
260
+ $sort: {
261
+ 'date': 1,
262
+ 'createdAt': 1,
263
+ 'order': 1,
264
+ },
265
+ },
266
+ ]);
205
267
 
206
- const transactions = [];
268
+ const statementTransactionsWithBalance = options.showBalances
269
+ ? await Promise.all(statementTransactions.map(async (statement) => {
270
+ const balances = await getLoanProductBalance(productId, statement.date);
271
+ return {
272
+ ...statement,
273
+ balance: balances.balance,
274
+ floatedBalance: balances.floatedBalance,
275
+ };
276
+ }))
277
+ : statementTransactions.slice();
207
278
 
208
- if (statement.amountPaid > 0) {
209
- const payments = await getPaymentForTransaction(productId, statement._id.toString());
210
- for (const payment of payments) {
211
- transactions.push({
212
- typeOrder: 1,
213
- order: statement.order,
214
- date: statement.date,
215
- type: statement.charge.chargeType,
216
- amount: null,
217
- statementAmount: isParticipant ? statement.amountPaid : -statement.amountPaid,
218
- title: `${statement.charge.name} PAID`,
219
- chargeCode: statement.charge.code,
220
- PLCode: statement.charge.PLCode,
221
- productCode: product.code,
222
- productName: product.name,
223
- balance: statement.balance,
224
- floatedBalance: statement.floatedBalance,
225
- createdAt: statement['createdAt'],
226
- info: statement.memo,
227
- paymentDate: dayjs(payment.date).format(defaultDateFormat),
228
- });
229
- }
230
- }
231
- return [...transactions, {
232
- typeOrder: 1,
233
- order: statement.order,
234
- date: statement.date,
235
- type: statement.charge.chargeType,
236
- amount: null,
237
- statementAmount: isParticipant ? -statement.amount : statement.amount,
238
- title: `${statement.charge.name} ACCRUED`,
239
- chargeCode: statement.charge.code,
240
- PLCode: statement.charge.PLCode,
241
- productCode: product.code,
242
- productName: product.name,
243
- balance: statement.balance,
244
- floatedBalance: statement.floatedBalance,
245
- createdAt: statement['createdAt'],
246
- info: statement.memo,
247
- paymentDate: null,
248
- }];
249
- }));
250
- const mappedStatementTransactions: ILedgerDataRow[] = groupedMappedStatementTransactions
251
- .reduce((acc, group) => [...acc, ...group], []);
252
- const statementTransactionsWithBrokers = addBrokers
253
- ? await enrichWithBrokers(mappedStatementTransactions, product)
254
- : mappedStatementTransactions;
255
- const sortedTransactions = [...statementTransactionsWithBrokers, ...mappedTransactions]
256
- .sort((a, b) => {
257
- if (a.date.valueOf() !== b.date.valueOf()) {
258
- return b.date.valueOf() - a.date.valueOf();
259
- }
260
- if (a.typeOrder !== b.typeOrder) {
261
- return b.typeOrder - a.typeOrder;
262
- }
263
- return b.createdAt.valueOf() - a.createdAt.valueOf();
264
- });
279
+ const isParticipant = group.product.isParticipant;
280
+ const groupedMappedStatementTransactions = await Promise.all(statementTransactionsWithBalance.map(async (statement) => {
265
281
 
266
- const fullTransactions = sortedTransactions
267
- .map((row): ILedgerReportRow => ({
268
- borrowerCode: borrower.code,
269
- date: formatDate(row.date),
270
- type: !!row.isBrokerFee ? `${EChargeType[row.type]} BROKER` : EChargeType[row.type],
271
- chargeCode: row.chargeCode,
272
- PLCode: row.PLCode,
273
- productCode: row.productCode,
274
- productName: row.productName,
275
- amount: row.amount,
276
- statementAmount: row.statementAmount,
277
- title: row.title,
278
- balance: row.balance,
279
- floatedBalance: row.floatedBalance,
280
- info: row.info,
281
- paymentDate: row.paymentDate ? formatDate(row.paymentDate) : '',
282
- }));
282
+ const transactions = [];
283
283
 
284
- const termLoan = await TermLoanModel.findOne({ productId, actual: true });
285
- if (termLoan) {
286
- const calculatedTermLoan = await TermLoanCalculatedModel.findOne({
287
- termLoanId: termLoan._id.toString(),
288
- relevantStatement: dayjs(endDate).format('YYYY-MM-DD'),
289
- });
290
- if (calculatedTermLoan) {
291
- const expectedPayment = <ILedgerReportRow>{
292
- borrowerCode: borrower.code,
293
- date: formatDate(endDate),
294
- type: EChargeType.EXPECTED_PRINCIPAL,
295
- chargeCode: null,
296
- PLCode: null,
297
- productCode: product.code,
298
- amount: isParticipant ? -calculatedTermLoan.monthlyPrincipal : calculatedTermLoan.monthlyPrincipal,
299
- statementAmount: null,
300
- title: EChargeType.EXPECTED_PRINCIPAL,
301
- balance: null,
302
- floatedBalance: null,
303
- info: EChargeType.EXPECTED_PRINCIPAL,
284
+ if (statement.amountPaid > 0) {
285
+ const payments = await getPaymentForTransaction(productId, statement._id.toString());
286
+ for (const payment of payments) {
287
+ transactions.push({
288
+ typeOrder: 1,
289
+ order: statement.order,
290
+ date: statement.date,
291
+ type: statement.charge.chargeType,
292
+ amount: null,
293
+ statementAmount: isParticipant ? statement.amountPaid : -statement.amountPaid,
294
+ title: `${statement.charge.name} PAID`,
295
+ chargeCode: statement.charge.code,
296
+ PLCode: statement.charge.PLCode,
297
+ productCode: group.product.code,
298
+ productName: group.product.name,
299
+ balance: statement.balance,
300
+ floatedBalance: statement.floatedBalance,
301
+ createdAt: statement['createdAt'],
302
+ info: statement.memo,
303
+ paymentDate: dayjs(payment.date).format(defaultDateFormat),
304
+ });
305
+ }
306
+ }
307
+ return [...transactions, {
308
+ typeOrder: 1,
309
+ order: statement.order,
310
+ date: statement.date,
311
+ type: statement.charge.chargeType,
312
+ amount: null,
313
+ statementAmount: isParticipant ? -statement.amount : statement.amount,
314
+ title: `${statement.charge.name} ACCRUED`,
315
+ chargeCode: statement.charge.code,
316
+ PLCode: statement.charge.PLCode,
317
+ productCode: group.product.code,
318
+ productName: group.product.name,
319
+ balance: statement.balance,
320
+ floatedBalance: statement.floatedBalance,
321
+ createdAt: statement['createdAt'],
322
+ info: statement.memo,
304
323
  paymentDate: null,
305
- };
306
- fullTransactions.unshift(expectedPayment);
307
- if (calculatedTermLoan.payments && calculatedTermLoan.payments.length > 0) {
308
- for (const payment of calculatedTermLoan.payments) {
309
- const paymentDoc = await LoanTransaction.findById(payment.paymentId).lean();
310
- if (paymentDoc) {
311
- const expectedPayment = <ILedgerReportRow>{
312
- borrowerCode: borrower.code,
313
- date: formatDate(endDate),
314
- type: EChargeType.EXPECTED_PRINCIPAL_PAID,
315
- chargeCode: null,
316
- PLCode: null,
317
- productCode: product.code,
318
- amount: isParticipant ? -payment.amount : payment.amount,
319
- statementAmount: null,
320
- title: EChargeType.EXPECTED_PRINCIPAL_PAID,
321
- balance: null,
322
- floatedBalance: null,
323
- info: EChargeType.EXPECTED_PRINCIPAL_PAID,
324
- paymentDate: formatDate(paymentDoc.date),
325
- };
326
- fullTransactions.unshift(expectedPayment);
324
+ }];
325
+ }));
326
+ const mappedStatementTransactions: ILedgerDataRow[] = groupedMappedStatementTransactions
327
+ .reduce((acc, group) => [...acc, ...group], []);
328
+ const statementTransactionsWithBrokers = addBrokers
329
+ ? await enrichWithBrokers(mappedStatementTransactions, group.product)
330
+ : mappedStatementTransactions;
331
+ const sortedTransactions = [...statementTransactionsWithBrokers, ...group.transactions]
332
+ .sort((a, b) => {
333
+ if (a.date.valueOf() !== b.date.valueOf()) {
334
+ return b.date.valueOf() - a.date.valueOf();
335
+ }
336
+ if (a.typeOrder !== b.typeOrder) {
337
+ return b.typeOrder - a.typeOrder;
338
+ }
339
+ return b.createdAt.valueOf() - a.createdAt.valueOf();
340
+ });
341
+
342
+ const fullTransactions = sortedTransactions
343
+ .map((row): ILedgerReportRow => ({
344
+ borrowerCode: borrowerCodesMap[productId],
345
+ date: formatDate(row.date),
346
+ type: row.isBrokerFee ? `${EChargeType[row.type]} BROKER` : EChargeType[row.type],
347
+ chargeCode: row.chargeCode,
348
+ PLCode: row.PLCode,
349
+ productCode: row.productCode,
350
+ productName: row.productName,
351
+ amount: row.amount,
352
+ statementAmount: row.statementAmount,
353
+ title: row.title,
354
+ balance: row.balance,
355
+ floatedBalance: row.floatedBalance,
356
+ info: row.info,
357
+ paymentDate: row.paymentDate ? formatDate(row.paymentDate) : '',
358
+ }));
359
+
360
+ const termLoan = await TermLoanModel.findOne({ productId, actual: true });
361
+ if (termLoan) {
362
+ const calculatedTermLoan = await TermLoanCalculatedModel.findOne({
363
+ termLoanId: termLoan._id.toString(),
364
+ relevantStatement: dayjs(endDate).format('YYYY-MM-DD'),
365
+ });
366
+ if (calculatedTermLoan) {
367
+ const expectedPayment = <ILedgerReportRow>{
368
+ borrowerCode: borrowerCodesMap[productId],
369
+ date: formatDate(endDate),
370
+ type: EChargeType.EXPECTED_PRINCIPAL,
371
+ chargeCode: null,
372
+ PLCode: null,
373
+ productCode: group.product.code,
374
+ amount: isParticipant ? -calculatedTermLoan.monthlyPrincipal : calculatedTermLoan.monthlyPrincipal,
375
+ statementAmount: null,
376
+ title: EChargeType.EXPECTED_PRINCIPAL,
377
+ balance: null,
378
+ floatedBalance: null,
379
+ info: EChargeType.EXPECTED_PRINCIPAL,
380
+ paymentDate: null,
381
+ };
382
+ fullTransactions.unshift(expectedPayment);
383
+ if (calculatedTermLoan.payments && calculatedTermLoan.payments.length > 0) {
384
+ for (const payment of calculatedTermLoan.payments) {
385
+ const paymentDoc = await LoanTransaction.findById(payment.paymentId).lean();
386
+ if (paymentDoc) {
387
+ const expectedPayment = <ILedgerReportRow>{
388
+ borrowerCode: borrowerCodesMap[productId],
389
+ date: formatDate(endDate),
390
+ type: EChargeType.EXPECTED_PRINCIPAL_PAID,
391
+ chargeCode: null,
392
+ PLCode: null,
393
+ productCode: group.product.code,
394
+ amount: isParticipant ? -payment.amount : payment.amount,
395
+ statementAmount: null,
396
+ title: EChargeType.EXPECTED_PRINCIPAL_PAID,
397
+ balance: null,
398
+ floatedBalance: null,
399
+ info: EChargeType.EXPECTED_PRINCIPAL_PAID,
400
+ paymentDate: formatDate(paymentDoc.date),
401
+ };
402
+ fullTransactions.unshift(expectedPayment);
403
+ }
327
404
  }
328
405
  }
329
406
  }
330
407
  }
331
- }
332
- return fullTransactions;
408
+ allData[productId] = fullTransactions;
409
+ }));
410
+ return allData;
333
411
  };
334
412
 
335
- const mergeLedgerData = (transactions: ILedgerReportRow[], groupKeys: string[], sumKeys: string[]) => {
413
+ const mergeLedgerData = (transactions: ILedgerReportRow[], groupKeys: string[], sumKeys: string[]): ILedgerReportRow[] => {
336
414
  const groupedObjects = _.groupBy(
337
415
  transactions,
338
416
  (obj) => groupKeys.reduce((acc, key) => `${acc}${obj[key]}`, ''),
@@ -3,5 +3,6 @@ export declare enum EMicroserviceTask {
3
3
  ENABLE_PLAID_NOTIFICATION = "enable_plaid_notification",
4
4
  QUERY = "query",
5
5
  YIELD = "yield",
6
- REPORT = "report"
6
+ REPORT = "report",
7
+ POST_UPLOAD = "post_upload"
7
8
  }
@@ -8,4 +8,5 @@ var EMicroserviceTask;
8
8
  EMicroserviceTask["QUERY"] = "query";
9
9
  EMicroserviceTask["YIELD"] = "yield";
10
10
  EMicroserviceTask["REPORT"] = "report";
11
+ EMicroserviceTask["POST_UPLOAD"] = "post_upload";
11
12
  })(EMicroserviceTask || (exports.EMicroserviceTask = EMicroserviceTask = {}));
@@ -4,4 +4,5 @@ export enum EMicroserviceTask {
4
4
  QUERY = 'query',
5
5
  YIELD = 'yield',
6
6
  REPORT = 'report',
7
+ POST_UPLOAD = 'post_upload',
7
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemcap-be-common",
3
- "version": "1.2.63",
3
+ "version": "1.2.65",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {