// @flow import * as Sentry from '@sentry/node'; import { createQueue } from './utils/queue'; import services from './services'; export type UserEvent = | { name: | 'users.create' // eslint-disable-line | 'users.update' | 'users.suspend' | 'users.activate' | 'users.delete', userId: string, teamId: string, actorId: string, } | { name: 'users.invite', teamId: string, actorId: string, data: { email: string, name: string, }, }; export type DocumentEvent = | { name: | 'documents.create' // eslint-disable-line | 'documents.publish' | 'documents.delete' | 'documents.pin' | 'documents.unpin' | 'documents.archive' | 'documents.unarchive' | 'documents.restore' | 'documents.star' | 'documents.unstar', documentId: string, collectionId: string, teamId: string, actorId: string, } | { name: 'documents.move', documentId: string, collectionId: string, teamId: string, actorId: string, data: { collectionIds: string[], documentIds: string[], }, } | { name: 'documents.update', documentId: string, collectionId: string, teamId: string, actorId: string, data: { autosave: boolean, done: boolean, }, }; export type CollectionEvent = | { name: | 'collections.create' // eslint-disable-line | 'collections.update' | 'collections.delete', collectionId: string, teamId: string, actorId: string, } | { name: 'collections.add_user' | 'collections.remove_user', userId: string, collectionId: string, teamId: string, actorId: string, } | { name: 'collections.add_group' | 'collections.remove_group', collectionId: string, teamId: string, actorId: string, data: { name: string, groupId: string }, ip: string, }; export type GroupEvent = | { name: 'groups.create' | 'groups.delete' | 'groups.update', actorId: string, modelId: string, teamId: string, data: { name: string }, ip: string, } | { name: 'groups.add_user' | 'groups.remove_user', actorId: string, userId: string, modelId: string, teamId: string, data: { name: string }, ip: string, }; export type IntegrationEvent = { name: 'integrations.create' | 'integrations.update', modelId: string, teamId: string, actorId: string, }; export type Event = | UserEvent | DocumentEvent | CollectionEvent | IntegrationEvent | GroupEvent; const globalEventsQueue = createQueue('global events'); const serviceEventsQueue = createQueue('service events'); // this queue processes global events and hands them off to service hooks globalEventsQueue.process(async job => { const names = Object.keys(services); names.forEach(name => { const service = services[name]; if (service.on) { serviceEventsQueue.add( { service: name, ...job.data }, { removeOnComplete: true } ); } }); }); // this queue processes an individual event for a specific service serviceEventsQueue.process(async job => { const event = job.data; const service = services[event.service]; if (service.on) { service.on(event).catch(error => { if (process.env.SENTRY_DSN) { Sentry.withScope(function(scope) { scope.setExtra('event', event); Sentry.captureException(error); }); } else { throw error; } }); } }); export default globalEventsQueue;