@chevre/domain 23.1.0-alpha.29 → 23.1.0-alpha.30
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/example/src/chevre/actions/checkAcceptPayActions.ts +60 -0
- package/example/src/chevre/assetTransaction/checkPayTransactionsTicketToken.ts +67 -0
- package/example/src/chevre/stockHolder/findSeatsBySection.ts +59 -0
- package/example/src/chevre/stockHolder/searchSeats.ts +2 -2
- package/lib/chevre/repo/place/seat.d.ts +24 -0
- package/lib/chevre/repo/place/seat.js +103 -21
- package/package.json +1 -1
- package/example/src/chevre/checkReplaceActions.ts +0 -65
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// tslint:disable:no-console
|
|
2
|
+
import * as moment from 'moment';
|
|
3
|
+
import * as mongoose from 'mongoose';
|
|
4
|
+
|
|
5
|
+
import { chevre } from '../../../../lib/index';
|
|
6
|
+
|
|
7
|
+
// tslint:disable-next-line:max-func-body-length
|
|
8
|
+
async function main() {
|
|
9
|
+
await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
|
|
10
|
+
|
|
11
|
+
const actionRepo = await chevre.repository.Action.createInstance(mongoose.connection);
|
|
12
|
+
|
|
13
|
+
const cursor = actionRepo.getCursor(
|
|
14
|
+
{
|
|
15
|
+
typeOf: { $eq: chevre.factory.actionType.AcceptAction },
|
|
16
|
+
'object.typeOf': { $exists: true, $eq: chevre.factory.assetTransactionType.Pay },
|
|
17
|
+
startDate: {
|
|
18
|
+
$gte: moment()
|
|
19
|
+
// tslint:disable-next-line:no-magic-numbers
|
|
20
|
+
.add(-3, 'days')
|
|
21
|
+
.toDate()
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
console.log('docs found');
|
|
28
|
+
|
|
29
|
+
let i = 0;
|
|
30
|
+
let ticketTokenCount = 0;
|
|
31
|
+
await cursor.eachAsync(async (doc) => {
|
|
32
|
+
i += 1;
|
|
33
|
+
const acceptAction = <chevre.factory.action.accept.pay.IAction>doc.toObject();
|
|
34
|
+
|
|
35
|
+
const ticketTokenByInstrument = acceptAction.instrument?.find((instrument) => instrument.typeOf === 'Ticket')?.ticketToken;
|
|
36
|
+
if (typeof ticketTokenByInstrument === 'string' && ticketTokenByInstrument !== '') {
|
|
37
|
+
console.log(
|
|
38
|
+
ticketTokenByInstrument,
|
|
39
|
+
' ticket token exists.',
|
|
40
|
+
acceptAction.project.id, acceptAction.typeOf, acceptAction.object.typeOf,
|
|
41
|
+
acceptAction.startDate, acceptAction.identifier, i
|
|
42
|
+
);
|
|
43
|
+
ticketTokenCount += 1;
|
|
44
|
+
} else {
|
|
45
|
+
console.log(
|
|
46
|
+
ticketTokenByInstrument,
|
|
47
|
+
' ticket token does not exists.',
|
|
48
|
+
acceptAction.project.id, acceptAction.typeOf, acceptAction.object.typeOf,
|
|
49
|
+
acceptAction.startDate, acceptAction.identifier, i
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
console.log(i, 'docs checked');
|
|
55
|
+
console.log(ticketTokenCount, 'ticketToken exist');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
main()
|
|
59
|
+
.then()
|
|
60
|
+
.catch(console.error);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// tslint:disable:no-console
|
|
2
|
+
import * as moment from 'moment';
|
|
3
|
+
import * as mongoose from 'mongoose';
|
|
4
|
+
|
|
5
|
+
import { chevre } from '../../../../lib/index';
|
|
6
|
+
|
|
7
|
+
// tslint:disable-next-line:max-func-body-length
|
|
8
|
+
async function main() {
|
|
9
|
+
await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
|
|
10
|
+
|
|
11
|
+
const assetTransactionRepo = await chevre.repository.AssetTransaction.createInstance(mongoose.connection);
|
|
12
|
+
|
|
13
|
+
const cursor = assetTransactionRepo.getCursor(
|
|
14
|
+
{
|
|
15
|
+
typeOf: { $eq: chevre.factory.assetTransactionType.Pay },
|
|
16
|
+
startDate: {
|
|
17
|
+
$gte: moment()
|
|
18
|
+
// tslint:disable-next-line:no-magic-numbers
|
|
19
|
+
.add(-3, 'days')
|
|
20
|
+
.toDate()
|
|
21
|
+
},
|
|
22
|
+
'object.typeOf': {
|
|
23
|
+
$exists: true,
|
|
24
|
+
$in: [
|
|
25
|
+
// chevre.factory.service.paymentService.PaymentServiceType.FaceToFace,
|
|
26
|
+
// chevre.factory.service.paymentService.PaymentServiceType.MovieTicket,
|
|
27
|
+
chevre.factory.service.paymentService.PaymentServiceType.CreditCard
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
}
|
|
33
|
+
);
|
|
34
|
+
console.log('docs found');
|
|
35
|
+
|
|
36
|
+
let i = 0;
|
|
37
|
+
let ticketTokenCount = 0;
|
|
38
|
+
await cursor.eachAsync(async (doc) => {
|
|
39
|
+
i += 1;
|
|
40
|
+
const payTransaction = <chevre.factory.assetTransaction.pay.ITransaction>doc.toObject();
|
|
41
|
+
|
|
42
|
+
const ticketTokenByInstrument = payTransaction.instrument?.find((instrument) => instrument.typeOf === 'Ticket')?.ticketToken;
|
|
43
|
+
if (typeof ticketTokenByInstrument === 'string' && ticketTokenByInstrument !== '') {
|
|
44
|
+
console.log(
|
|
45
|
+
ticketTokenByInstrument,
|
|
46
|
+
' ticket token exists.',
|
|
47
|
+
payTransaction.project.id, payTransaction.typeOf, payTransaction.object.typeOf,
|
|
48
|
+
payTransaction.startDate, payTransaction.transactionNumber, i
|
|
49
|
+
);
|
|
50
|
+
ticketTokenCount += 1;
|
|
51
|
+
} else {
|
|
52
|
+
console.log(
|
|
53
|
+
ticketTokenByInstrument,
|
|
54
|
+
' ticket token does not exists.',
|
|
55
|
+
payTransaction.project.id, payTransaction.typeOf, payTransaction.object.typeOf,
|
|
56
|
+
payTransaction.startDate, payTransaction.transactionNumber, i
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
console.log(i, 'docs checked');
|
|
62
|
+
console.log(ticketTokenCount, 'ticketToken exist');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
main()
|
|
66
|
+
.then()
|
|
67
|
+
.catch(console.error);
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// tslint:disable:no-console
|
|
2
|
+
import * as mongoose from 'mongoose';
|
|
3
|
+
|
|
4
|
+
import { chevre } from '../../../../lib/index';
|
|
5
|
+
|
|
6
|
+
const PROJECT_ID = String(process.env.PROJECT_ID);
|
|
7
|
+
const SCREEN_CODE = '100';
|
|
8
|
+
const MOVIE_THEATER_CODE = '118';
|
|
9
|
+
const SELLER_ID = '59d20831e53ebc2b4e774466';
|
|
10
|
+
|
|
11
|
+
const formatter = new Intl.NumberFormat('ja-JP');
|
|
12
|
+
|
|
13
|
+
// tslint:disable-next-line:max-func-body-length
|
|
14
|
+
async function main() {
|
|
15
|
+
let startTime: [number, number] = process.hrtime();
|
|
16
|
+
let diff: [number, number] = process.hrtime(startTime);
|
|
17
|
+
|
|
18
|
+
await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
|
|
19
|
+
|
|
20
|
+
const seatRepo = await chevre.repository.place.Seat.createInstance(mongoose.connection);
|
|
21
|
+
|
|
22
|
+
setInterval(
|
|
23
|
+
async () => {
|
|
24
|
+
startTime = process.hrtime();
|
|
25
|
+
const seats = await seatRepo.findSeatsBySection(
|
|
26
|
+
{
|
|
27
|
+
limit: 100,
|
|
28
|
+
page: 100,
|
|
29
|
+
projectId: PROJECT_ID,
|
|
30
|
+
sellerId: SELLER_ID,
|
|
31
|
+
movieTheaterCode: MOVIE_THEATER_CODE,
|
|
32
|
+
roomCode: SCREEN_CODE,
|
|
33
|
+
sectionCode: 'Default'
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
// branchCode: { $in: ['Z-384'] },
|
|
37
|
+
// containedInPlace: {
|
|
38
|
+
// branchCode: {
|
|
39
|
+
// $in: ['Default']
|
|
40
|
+
// }
|
|
41
|
+
// }
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
diff = process.hrtime(startTime);
|
|
45
|
+
// tslint:disable-next-line:no-null-keyword
|
|
46
|
+
console.dir(seats, { depth: null });
|
|
47
|
+
console.log(seats.length, 'seats found');
|
|
48
|
+
console.log('diff:', [diff[0], formatter.format(diff[1])]);
|
|
49
|
+
},
|
|
50
|
+
// tslint:disable-next-line:no-magic-numbers
|
|
51
|
+
1000
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
main()
|
|
56
|
+
.then(() => {
|
|
57
|
+
console.log('success!');
|
|
58
|
+
})
|
|
59
|
+
.catch(console.error);
|
|
@@ -28,8 +28,8 @@ async function main() {
|
|
|
28
28
|
'containedInPlace.containedInPlace': 0,
|
|
29
29
|
'containedInPlace.typeOf': 0,
|
|
30
30
|
'containedInPlace.name': 0,
|
|
31
|
-
typeOf: 0
|
|
32
|
-
additionalProperty: 0
|
|
31
|
+
typeOf: 0
|
|
32
|
+
// additionalProperty: 0
|
|
33
33
|
},
|
|
34
34
|
project: { id: { $eq: PROJECT_ID } },
|
|
35
35
|
screeningRoom: {
|
|
@@ -79,6 +79,30 @@ export declare class SeatRepo {
|
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
81
|
}): Promise<factory.place.seat.IPlace[]>;
|
|
82
|
+
/**
|
|
83
|
+
* セクション指定の座席検索として再定義(2025-12-06~)
|
|
84
|
+
*/
|
|
85
|
+
findSeatsBySection(params: {
|
|
86
|
+
limit: number;
|
|
87
|
+
page: number;
|
|
88
|
+
projectId: string;
|
|
89
|
+
/**
|
|
90
|
+
* 販売者ID
|
|
91
|
+
*/
|
|
92
|
+
sellerId: string;
|
|
93
|
+
/**
|
|
94
|
+
* 施設コード
|
|
95
|
+
*/
|
|
96
|
+
movieTheaterCode: string;
|
|
97
|
+
/**
|
|
98
|
+
* ルームコード
|
|
99
|
+
*/
|
|
100
|
+
roomCode: string;
|
|
101
|
+
/**
|
|
102
|
+
* セクションコード
|
|
103
|
+
*/
|
|
104
|
+
sectionCode: string;
|
|
105
|
+
}, options: Pick<factory.place.seat.ISearchConditions, 'branchCode' | 'seatingType'>): Promise<Pick<factory.place.seat.IPlace, 'additionalProperty' | 'branchCode' | 'maximumAttendeeCapacity' | 'name' | 'seatingType'>[]>;
|
|
82
106
|
/**
|
|
83
107
|
* 座席区分集計検索
|
|
84
108
|
*/
|
|
@@ -39,30 +39,29 @@ class SeatRepo {
|
|
|
39
39
|
const includeSectionName = params['containedInPlace.name'] !== 0;
|
|
40
40
|
const includeSectionTypeOf = params['containedInPlace.typeOf'] !== 0;
|
|
41
41
|
const includeScreeningRooms = params['containedInPlace.containedInPlace'] !== 0;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
? {
|
|
51
|
-
containedInPlace: {
|
|
52
|
-
typeOf: '$typeOf',
|
|
53
|
-
branchCode: '$branchCode',
|
|
54
|
-
name: '$name',
|
|
42
|
+
/**
|
|
43
|
+
* containedInPlaceについて何かしたprojectするかどうか
|
|
44
|
+
*/
|
|
45
|
+
const includeContaindInPlace = includeSectionBranchCode || includeSectionName || includeSectionTypeOf || includeScreeningRooms;
|
|
46
|
+
const projectStage = Object.assign(Object.assign({ _id: 0, typeOf: '$containsPlace.containsPlace.typeOf', branchCode: '$containsPlace.containsPlace.branchCode', name: '$containsPlace.containsPlace.name', seatingType: '$containsPlace.containsPlace.seatingType', maximumAttendeeCapacity: '$containsPlace.containsPlace.maximumAttendeeCapacity' }, (includeContaindInPlace)
|
|
47
|
+
? {
|
|
48
|
+
containedInPlace: Object.assign(Object.assign(Object.assign(Object.assign({}, (includeSectionBranchCode) ? { branchCode: '$containsPlace.branchCode' } : undefined), (includeSectionName) ? { name: '$containsPlace.name' } : undefined), (includeSectionTypeOf) ? { typeOf: '$containsPlace.typeOf' } : undefined), (includeScreeningRooms)
|
|
49
|
+
? {
|
|
55
50
|
containedInPlace: {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
typeOf: '$typeOf',
|
|
52
|
+
branchCode: '$branchCode',
|
|
53
|
+
name: '$name',
|
|
54
|
+
containedInPlace: {
|
|
55
|
+
id: '$containedInPlace.id',
|
|
56
|
+
typeOf: '$containedInPlace.typeOf',
|
|
57
|
+
branchCode: '$containedInPlace.branchCode',
|
|
58
|
+
name: '$containedInPlace.name'
|
|
59
|
+
}
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
additionalProperty: '$containsPlace.containsPlace.additionalProperty'
|
|
65
|
-
};
|
|
62
|
+
: undefined)
|
|
63
|
+
}
|
|
64
|
+
: undefined), { additionalProperty: '$containsPlace.containsPlace.additionalProperty' });
|
|
66
65
|
Object.keys(params)
|
|
67
66
|
.forEach((field) => {
|
|
68
67
|
if (typeof projectStage[field] === 'string') {
|
|
@@ -445,6 +444,89 @@ class SeatRepo {
|
|
|
445
444
|
.exec();
|
|
446
445
|
});
|
|
447
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* セクション指定の座席検索として再定義(2025-12-06~)
|
|
449
|
+
*/
|
|
450
|
+
findSeatsBySection(params, options) {
|
|
451
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
452
|
+
const { limit, page, projectId, sellerId, movieTheaterCode, roomCode, sectionCode } = params;
|
|
453
|
+
// まずルーム検索
|
|
454
|
+
const screeningRoomDoc = yield this.placeModel.findOne({
|
|
455
|
+
typeOf: { $eq: factory.placeType.ScreeningRoom },
|
|
456
|
+
'project.id': { $eq: projectId },
|
|
457
|
+
'parentOrganization.id': { $exists: true, $eq: sellerId },
|
|
458
|
+
'containedInPlace.branchCode': { $exists: true, $eq: movieTheaterCode },
|
|
459
|
+
branchCode: { $eq: roomCode }
|
|
460
|
+
}, { _id: 1 })
|
|
461
|
+
.lean()
|
|
462
|
+
.exec();
|
|
463
|
+
// console.log('screeningRoomDoc:', screeningRoomDoc);
|
|
464
|
+
if (screeningRoomDoc === null) {
|
|
465
|
+
return [];
|
|
466
|
+
}
|
|
467
|
+
const matchStageBeforeUnwind = {
|
|
468
|
+
$match: { _id: { $eq: screeningRoomDoc._id } }
|
|
469
|
+
};
|
|
470
|
+
const matchStages = SeatRepo.CREATE_MATCH_STAGES(Object.assign(Object.assign({}, options), { containedInPlace: {
|
|
471
|
+
branchCode: { $eq: sectionCode },
|
|
472
|
+
containedInPlace: {
|
|
473
|
+
containedInPlace: {}
|
|
474
|
+
}
|
|
475
|
+
} }), { filterTypeOf: false });
|
|
476
|
+
const pageMustBeOne = (typeof page === 'number' && page > 0) ? page : 1;
|
|
477
|
+
let skipStage;
|
|
478
|
+
let limitStage;
|
|
479
|
+
if (typeof limit === 'number' && limit > 0) {
|
|
480
|
+
skipStage = { $skip: limit * (pageMustBeOne - 1) };
|
|
481
|
+
limitStage = { $limit: limit };
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
throw new factory.errors.Argument('limit', 'must be number > 0');
|
|
485
|
+
}
|
|
486
|
+
const pipeline = [
|
|
487
|
+
// uniwind前はドキュメントの_id指定
|
|
488
|
+
matchStageBeforeUnwind,
|
|
489
|
+
{
|
|
490
|
+
$unwind: {
|
|
491
|
+
path: '$containsPlace'
|
|
492
|
+
// includeArrayIndex: 'sectionIndex'
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
$unwind: {
|
|
497
|
+
path: '$containsPlace.containsPlace'
|
|
498
|
+
// includeArrayIndex: 'seatIndex'
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
...matchStages,
|
|
502
|
+
{
|
|
503
|
+
$project: {
|
|
504
|
+
_id: 0,
|
|
505
|
+
branchCode: '$containsPlace.containsPlace.branchCode',
|
|
506
|
+
name: '$containsPlace.containsPlace.name',
|
|
507
|
+
seatingType: '$containsPlace.containsPlace.seatingType',
|
|
508
|
+
maximumAttendeeCapacity: '$containsPlace.containsPlace.maximumAttendeeCapacity',
|
|
509
|
+
additionalProperty: '$containsPlace.containsPlace.additionalProperty'
|
|
510
|
+
}
|
|
511
|
+
},
|
|
512
|
+
// {
|
|
513
|
+
// $sort: {
|
|
514
|
+
// // branchCode: factory.sortType.Ascending
|
|
515
|
+
// }
|
|
516
|
+
// },
|
|
517
|
+
skipStage,
|
|
518
|
+
limitStage
|
|
519
|
+
];
|
|
520
|
+
// console.log(pipeline);
|
|
521
|
+
return this.placeModel.aggregate(pipeline)
|
|
522
|
+
.option({
|
|
523
|
+
maxTimeMS: settings_1.MONGO_MAX_TIME_MS
|
|
524
|
+
// explain: true,
|
|
525
|
+
// hint: 'searchSeatsSort'
|
|
526
|
+
})
|
|
527
|
+
.exec();
|
|
528
|
+
});
|
|
529
|
+
}
|
|
448
530
|
/**
|
|
449
531
|
* 座席区分集計検索
|
|
450
532
|
*/
|
package/package.json
CHANGED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// tslint:disable:no-console
|
|
2
|
-
import * as moment from 'moment';
|
|
3
|
-
import * as mongoose from 'mongoose';
|
|
4
|
-
|
|
5
|
-
import { chevre } from '../../../lib/index';
|
|
6
|
-
|
|
7
|
-
const CONSOLE_CLIENT_ID = 'xxx';
|
|
8
|
-
// const project = { id: String(process.env.PROJECT_ID) };
|
|
9
|
-
type IAction = chevre.factory.action.IAction<chevre.factory.action.IAttributes<chevre.factory.actionType, any, any>>;
|
|
10
|
-
|
|
11
|
-
// tslint:disable-next-line:max-func-body-length
|
|
12
|
-
async function main() {
|
|
13
|
-
await mongoose.connect(<string>process.env.MONGOLAB_URI, { autoIndex: false });
|
|
14
|
-
|
|
15
|
-
const actionRepo = await chevre.repository.Action.createInstance(mongoose.connection);
|
|
16
|
-
|
|
17
|
-
const cursor = actionRepo.getCursor(
|
|
18
|
-
{
|
|
19
|
-
typeOf: { $eq: chevre.factory.actionType.ReplaceAction },
|
|
20
|
-
'object.typeOf': { $exists: true, $eq: chevre.factory.eventType.ScreeningEventSeries },
|
|
21
|
-
startDate: {
|
|
22
|
-
$gte: moment()
|
|
23
|
-
// tslint:disable-next-line:no-magic-numbers
|
|
24
|
-
.add(-60, 'days')
|
|
25
|
-
.toDate()
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
}
|
|
30
|
-
);
|
|
31
|
-
console.log('actions found');
|
|
32
|
-
|
|
33
|
-
let i = 0;
|
|
34
|
-
await cursor.eachAsync(async (doc) => {
|
|
35
|
-
i += 1;
|
|
36
|
-
const action = <IAction>doc.toObject();
|
|
37
|
-
// const size = JSON.stringify(action).length;
|
|
38
|
-
// // console.log(JSON.stringify(action).length);
|
|
39
|
-
// if (action.typeOf !== chevre.factory.actionType.InformAction
|
|
40
|
-
// && action.typeOf !== chevre.factory.actionType.AuthorizeAction
|
|
41
|
-
// && action.typeOf !== chevre.factory.actionType.CheckAction
|
|
42
|
-
// && size > 2000) {
|
|
43
|
-
// console.log(action.typeOf, action.object?.typeOf);
|
|
44
|
-
// console.log(size);
|
|
45
|
-
// }
|
|
46
|
-
|
|
47
|
-
const eventCount = (Array.isArray(action.object))
|
|
48
|
-
? action.object.filter(({ typeOf }) => typeOf === chevre.factory.eventType.ScreeningEventSeries)
|
|
49
|
-
.length
|
|
50
|
-
: 0;
|
|
51
|
-
if (action.instrument?.id !== CONSOLE_CLIENT_ID) {
|
|
52
|
-
console.log(eventCount, 'events created', action.project.id, action.startDate, action.instrument?.id, i);
|
|
53
|
-
// tslint:disable-next-line:no-magic-numbers
|
|
54
|
-
if (eventCount > 20) {
|
|
55
|
-
throw new Error('eventCount too large');
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
console.log(i, 'actions checked');
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
main()
|
|
64
|
-
.then()
|
|
65
|
-
.catch(console.error);
|