@unchainedshop/core-events
Version:
Event history and tracking module for the Unchained Engine
117 lines (116 loc) • 4.39 kB
JavaScript
import { mongodb, generateDbFilterById, buildSortOptions, generateDbObjectId, } from '@unchainedshop/mongodb';
import { getRegisteredEvents } from '@unchainedshop/events';
import { SortDirection } from '@unchainedshop/utils';
import { EventsCollection } from "../db/EventsCollection.js";
import { configureEventHistoryAdapter } from "./configureEventHistoryAdapter.js";
import { createLogger } from '@unchainedshop/logger';
const logger = createLogger('unchained:core-events');
export const buildFindSelector = ({ types, queryString, created }) => {
const selector = {};
if (types && Array.isArray(types))
selector.type = { $in: types };
if (queryString) {
selector.$text = { $search: queryString };
}
if (created) {
selector.created = created?.end
? { $gte: created.start || new Date(0), $lte: created.end }
: { $gte: created.start || new Date(0) };
}
return selector;
};
export const configureEventsModule = async ({ db }) => {
const Events = await EventsCollection(db);
const create = async (doc) => {
const result = await Events.insertOne({
_id: generateDbObjectId(),
created: new Date(),
...doc,
});
return result.insertedId;
};
await configureEventHistoryAdapter(create);
return {
create,
findEvent: async ({ eventId, ...rest }, options) => {
const selector = eventId ? generateDbFilterById(eventId) : rest;
return Events.findOne(selector, options);
},
findEvents: async ({ limit, offset, sort, ...query }) => {
const defaultSort = [{ key: 'created', value: SortDirection.DESC }];
return Events.find(buildFindSelector(query), {
skip: offset,
limit,
sort: buildSortOptions(sort || defaultSort),
}).toArray();
},
type: (event) => {
if (getRegisteredEvents().includes(event.type)) {
return event.type;
}
return 'UNKNOWN';
},
count: async (query) => {
const count = await Events.countDocuments(buildFindSelector(query));
return count;
},
getReport: async ({ dateRange, types, } = {}) => {
const match = {};
if (dateRange?.start || dateRange?.end) {
const conditions = [];
if (dateRange.start) {
const fromDate = new Date(dateRange.start);
conditions.push({ created: { $gte: fromDate } });
}
if (dateRange.end) {
const toDate = new Date(dateRange.end);
conditions.push({ created: { $lte: toDate } });
}
if (conditions.length) {
match.$or = conditions;
}
}
if (types?.length) {
match.type = { $in: types };
}
const pipeline = [
Object.keys(match).length ? { $match: match } : null,
{
$group: {
_id: {
type: '$type',
day: {
$dateToString: { format: '%Y-%m-%d', date: '$created' },
},
},
count: { $sum: 1 },
},
},
{
$group: {
_id: '$_id.type',
detail: {
$push: {
date: '$_id.day',
count: '$count',
},
},
emitCount: { $sum: '$count' },
},
},
{
$project: {
_id: 0,
type: '$_id',
emitCount: 1,
detail: 1,
},
},
{ $sort: { type: 1 } },
].filter(Boolean);
const report = await Events.aggregate(pipeline).toArray();
logger.info(report);
return report ?? [];
},
};
};