Container.ts 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. import * as winston from 'winston'
  2. import { Container, interfaces } from 'inversify'
  3. import { Env } from './Env'
  4. import TYPES from './Types'
  5. import { AppDataSource } from './DataSource'
  6. import { SNSClient, SNSClientConfig } from '@aws-sdk/client-sns'
  7. import { ItemRepositoryInterface } from '../Domain/Item/ItemRepositoryInterface'
  8. import { TypeORMItemRepository } from '../Infra/TypeORM/TypeORMItemRepository'
  9. import { Repository } from 'typeorm'
  10. import { Item } from '../Domain/Item/Item'
  11. import { ItemProjection } from '../Projection/ItemProjection'
  12. import { ProjectorInterface } from '../Projection/ProjectorInterface'
  13. import { ItemProjector } from '../Projection/ItemProjector'
  14. import {
  15. DirectCallDomainEventPublisher,
  16. DirectCallEventMessageHandler,
  17. SNSDomainEventPublisher,
  18. SQSDomainEventSubscriberFactory,
  19. SQSEventMessageHandler,
  20. SQSNewRelicEventMessageHandler,
  21. } from '@standardnotes/domain-events-infra'
  22. import { DomainEventFactoryInterface } from '../Domain/Event/DomainEventFactoryInterface'
  23. import { DomainEventFactory } from '../Domain/Event/DomainEventFactory'
  24. import { Timer, TimerInterface } from '@standardnotes/time'
  25. import { ItemTransferCalculatorInterface } from '../Domain/Item/ItemTransferCalculatorInterface'
  26. import { ItemTransferCalculator } from '../Domain/Item/ItemTransferCalculator'
  27. import { ItemConflict } from '../Domain/Item/ItemConflict'
  28. import { ItemFactory } from '../Domain/Item/ItemFactory'
  29. import { ItemFactoryInterface } from '../Domain/Item/ItemFactoryInterface'
  30. import { ItemService } from '../Domain/Item/ItemService'
  31. import { ItemServiceInterface } from '../Domain/Item/ItemServiceInterface'
  32. import { ContentFilter } from '../Domain/Item/SaveRule/ContentFilter'
  33. import { ContentTypeFilter } from '../Domain/Item/SaveRule/ContentTypeFilter'
  34. import { OwnershipFilter } from '../Domain/Item/SaveRule/OwnershipFilter'
  35. import { TimeDifferenceFilter } from '../Domain/Item/SaveRule/TimeDifferenceFilter'
  36. import { UuidFilter } from '../Domain/Item/SaveRule/UuidFilter'
  37. import { ItemSaveValidator } from '../Domain/Item/SaveValidator/ItemSaveValidator'
  38. import { ItemSaveValidatorInterface } from '../Domain/Item/SaveValidator/ItemSaveValidatorInterface'
  39. import { SyncResponseFactory20161215 } from '../Domain/Item/SyncResponse/SyncResponseFactory20161215'
  40. import { SyncResponseFactory20200115 } from '../Domain/Item/SyncResponse/SyncResponseFactory20200115'
  41. import { SyncResponseFactoryResolver } from '../Domain/Item/SyncResponse/SyncResponseFactoryResolver'
  42. import { SyncResponseFactoryResolverInterface } from '../Domain/Item/SyncResponse/SyncResponseFactoryResolverInterface'
  43. import { CheckIntegrity } from '../Domain/UseCase/CheckIntegrity/CheckIntegrity'
  44. import { GetItem } from '../Domain/UseCase/GetItem/GetItem'
  45. import { SyncItems } from '../Domain/UseCase/SyncItems'
  46. import { InversifyExpressAuthMiddleware } from '../Infra/InversifyExpressUtils/Middleware/InversifyExpressAuthMiddleware'
  47. import { ItemConflictProjection } from '../Projection/ItemConflictProjection'
  48. import { ItemConflictProjector } from '../Projection/ItemConflictProjector'
  49. import { SavedItemProjection } from '../Projection/SavedItemProjection'
  50. import { SavedItemProjector } from '../Projection/SavedItemProjector'
  51. import { S3Client } from '@aws-sdk/client-s3'
  52. import { SQSClient, SQSClientConfig } from '@aws-sdk/client-sqs'
  53. import { ContentDecoder } from '@standardnotes/common'
  54. import {
  55. DomainEventMessageHandlerInterface,
  56. DomainEventHandlerInterface,
  57. DomainEventSubscriberFactoryInterface,
  58. DomainEventPublisherInterface,
  59. } from '@standardnotes/domain-events'
  60. import axios, { AxiosInstance } from 'axios'
  61. import { AuthHttpServiceInterface } from '../Domain/Auth/AuthHttpServiceInterface'
  62. import { ExtensionsHttpService } from '../Domain/Extension/ExtensionsHttpService'
  63. import { ExtensionsHttpServiceInterface } from '../Domain/Extension/ExtensionsHttpServiceInterface'
  64. import { AccountDeletionRequestedEventHandler } from '../Domain/Handler/AccountDeletionRequestedEventHandler'
  65. import { DuplicateItemSyncedEventHandler } from '../Domain/Handler/DuplicateItemSyncedEventHandler'
  66. import { EmailBackupRequestedEventHandler } from '../Domain/Handler/EmailBackupRequestedEventHandler'
  67. import { ItemRevisionCreationRequestedEventHandler } from '../Domain/Handler/ItemRevisionCreationRequestedEventHandler'
  68. import { ItemBackupServiceInterface } from '../Domain/Item/ItemBackupServiceInterface'
  69. import { FSItemBackupService } from '../Infra/FS/FSItemBackupService'
  70. import { AuthHttpService } from '../Infra/HTTP/AuthHttpService'
  71. import { S3ItemBackupService } from '../Infra/S3/S3ItemBackupService'
  72. import { ControllerContainer, ControllerContainerInterface } from '@standardnotes/domain-core'
  73. import { HomeServerItemsController } from '../Infra/InversifyExpressUtils/HomeServer/HomeServerItemsController'
  74. import { Transform } from 'stream'
  75. export class ContainerConfigLoader {
  76. private readonly DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT = 10_000_000
  77. private readonly DEFAULT_MAX_ITEMS_LIMIT = 300
  78. private readonly DEFAULT_FILE_UPLOAD_PATH = `${__dirname}/../../uploads`
  79. async load(configuration?: {
  80. controllerConatiner?: ControllerContainerInterface
  81. directCallDomainEventPublisher?: DirectCallDomainEventPublisher
  82. logger?: Transform
  83. environmentOverrides?: { [name: string]: string }
  84. }): Promise<Container> {
  85. const directCallDomainEventPublisher =
  86. configuration?.directCallDomainEventPublisher ?? new DirectCallDomainEventPublisher()
  87. const env: Env = new Env(configuration?.environmentOverrides)
  88. env.load()
  89. const container = new Container({
  90. defaultScope: 'Singleton',
  91. })
  92. let logger: winston.Logger
  93. if (configuration?.logger) {
  94. logger = configuration.logger as winston.Logger
  95. } else {
  96. const winstonFormatters = [winston.format.splat(), winston.format.json()]
  97. if (env.get('NEW_RELIC_ENABLED', true) === 'true') {
  98. await import('newrelic')
  99. // eslint-disable-next-line @typescript-eslint/no-var-requires
  100. const newrelicFormatter = require('@newrelic/winston-enricher')
  101. const newrelicWinstonFormatter = newrelicFormatter(winston)
  102. winstonFormatters.push(newrelicWinstonFormatter())
  103. }
  104. logger = winston.createLogger({
  105. level: env.get('LOG_LEVEL', true) || 'info',
  106. format: winston.format.combine(...winstonFormatters),
  107. transports: [new winston.transports.Console({ level: env.get('LOG_LEVEL', true) || 'info' })],
  108. defaultMeta: { service: 'syncing-server' },
  109. })
  110. }
  111. container.bind<winston.Logger>(TYPES.Sync_Logger).toConstantValue(logger)
  112. const appDataSource = new AppDataSource(env)
  113. await appDataSource.initialize()
  114. logger.debug('Database initialized')
  115. const isConfiguredForHomeServer = env.get('MODE', true) === 'home-server'
  116. container.bind<Env>(TYPES.Sync_Env).toConstantValue(env)
  117. if (isConfiguredForHomeServer) {
  118. container
  119. .bind<DomainEventPublisherInterface>(TYPES.Sync_DomainEventPublisher)
  120. .toConstantValue(directCallDomainEventPublisher)
  121. } else {
  122. container.bind(TYPES.Sync_SNS_TOPIC_ARN).toConstantValue(env.get('SNS_TOPIC_ARN'))
  123. container.bind(TYPES.Sync_SNS_AWS_REGION).toConstantValue(env.get('SNS_AWS_REGION', true))
  124. container.bind(TYPES.Sync_SQS_QUEUE_URL).toConstantValue(env.get('SQS_QUEUE_URL'))
  125. container.bind(TYPES.Sync_S3_AWS_REGION).toConstantValue(env.get('S3_AWS_REGION', true))
  126. container.bind(TYPES.Sync_S3_BACKUP_BUCKET_NAME).toConstantValue(env.get('S3_BACKUP_BUCKET_NAME', true))
  127. container.bind(TYPES.Sync_EXTENSIONS_SERVER_URL).toConstantValue(env.get('EXTENSIONS_SERVER_URL', true))
  128. container.bind<SNSClient>(TYPES.Sync_SNS).toDynamicValue((context: interfaces.Context) => {
  129. const env: Env = context.container.get(TYPES.Sync_Env)
  130. const snsConfig: SNSClientConfig = {
  131. apiVersion: 'latest',
  132. region: env.get('SNS_AWS_REGION', true),
  133. }
  134. if (env.get('SNS_ENDPOINT', true)) {
  135. snsConfig.endpoint = env.get('SNS_ENDPOINT', true)
  136. }
  137. if (env.get('SNS_ACCESS_KEY_ID', true) && env.get('SNS_SECRET_ACCESS_KEY', true)) {
  138. snsConfig.credentials = {
  139. accessKeyId: env.get('SNS_ACCESS_KEY_ID', true),
  140. secretAccessKey: env.get('SNS_SECRET_ACCESS_KEY', true),
  141. }
  142. }
  143. return new SNSClient(snsConfig)
  144. })
  145. container
  146. .bind<DomainEventPublisherInterface>(TYPES.Sync_DomainEventPublisher)
  147. .toDynamicValue((context: interfaces.Context) => {
  148. return new SNSDomainEventPublisher(
  149. context.container.get(TYPES.Sync_SNS),
  150. context.container.get(TYPES.Sync_SNS_TOPIC_ARN),
  151. )
  152. })
  153. container.bind<SQSClient>(TYPES.Sync_SQS).toDynamicValue((context: interfaces.Context) => {
  154. const env: Env = context.container.get(TYPES.Sync_Env)
  155. const sqsConfig: SQSClientConfig = {
  156. region: env.get('SQS_AWS_REGION'),
  157. }
  158. if (env.get('SQS_ENDPOINT', true)) {
  159. sqsConfig.endpoint = env.get('SQS_ENDPOINT', true)
  160. }
  161. if (env.get('SQS_ACCESS_KEY_ID', true) && env.get('SQS_SECRET_ACCESS_KEY', true)) {
  162. sqsConfig.credentials = {
  163. accessKeyId: env.get('SQS_ACCESS_KEY_ID', true),
  164. secretAccessKey: env.get('SQS_SECRET_ACCESS_KEY', true),
  165. }
  166. }
  167. return new SQSClient(sqsConfig)
  168. })
  169. container.bind<S3Client | undefined>(TYPES.Sync_S3).toDynamicValue((context: interfaces.Context) => {
  170. const env: Env = context.container.get(TYPES.Sync_Env)
  171. let s3Client = undefined
  172. if (env.get('S3_AWS_REGION', true)) {
  173. s3Client = new S3Client({
  174. apiVersion: 'latest',
  175. region: env.get('S3_AWS_REGION', true),
  176. })
  177. }
  178. return s3Client
  179. })
  180. }
  181. // Repositories
  182. container.bind<ItemRepositoryInterface>(TYPES.Sync_ItemRepository).toDynamicValue((context: interfaces.Context) => {
  183. return new TypeORMItemRepository(context.container.get(TYPES.Sync_ORMItemRepository))
  184. })
  185. // ORM
  186. container
  187. .bind<Repository<Item>>(TYPES.Sync_ORMItemRepository)
  188. .toDynamicValue(() => appDataSource.getRepository(Item))
  189. // Projectors
  190. container
  191. .bind<ProjectorInterface<Item, ItemProjection>>(TYPES.Sync_ItemProjector)
  192. .toDynamicValue((context: interfaces.Context) => {
  193. return new ItemProjector(context.container.get(TYPES.Sync_Timer))
  194. })
  195. container.bind<TimerInterface>(TYPES.Sync_Timer).toDynamicValue(() => new Timer())
  196. container
  197. .bind<DomainEventFactoryInterface>(TYPES.Sync_DomainEventFactory)
  198. .toDynamicValue((context: interfaces.Context) => {
  199. return new DomainEventFactory(context.container.get(TYPES.Sync_Timer))
  200. })
  201. container
  202. .bind<ItemTransferCalculatorInterface>(TYPES.Sync_ItemTransferCalculator)
  203. .toDynamicValue((context: interfaces.Context) => {
  204. return new ItemTransferCalculator(
  205. context.container.get(TYPES.Sync_ItemRepository),
  206. context.container.get(TYPES.Sync_Logger),
  207. )
  208. })
  209. // Middleware
  210. container
  211. .bind<InversifyExpressAuthMiddleware>(TYPES.Sync_AuthMiddleware)
  212. .toDynamicValue((context: interfaces.Context) => {
  213. return new InversifyExpressAuthMiddleware(
  214. context.container.get(TYPES.Sync_AUTH_JWT_SECRET),
  215. context.container.get(TYPES.Sync_Logger),
  216. )
  217. })
  218. // Projectors
  219. container
  220. .bind<ProjectorInterface<Item, SavedItemProjection>>(TYPES.Sync_SavedItemProjector)
  221. .toDynamicValue((context: interfaces.Context) => {
  222. return new SavedItemProjector(context.container.get(TYPES.Sync_Timer))
  223. })
  224. container
  225. .bind<ProjectorInterface<ItemConflict, ItemConflictProjection>>(TYPES.Sync_ItemConflictProjector)
  226. .toDynamicValue((context: interfaces.Context) => {
  227. return new ItemConflictProjector(context.container.get(TYPES.Sync_ItemProjector))
  228. })
  229. // env vars
  230. container.bind(TYPES.Sync_AUTH_JWT_SECRET).toConstantValue(env.get('AUTH_JWT_SECRET'))
  231. container
  232. .bind(TYPES.Sync_REVISIONS_FREQUENCY)
  233. .toConstantValue(env.get('REVISIONS_FREQUENCY', true) ? +env.get('REVISIONS_FREQUENCY', true) : 300)
  234. container.bind(TYPES.Sync_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
  235. container.bind(TYPES.Sync_VERSION).toConstantValue(env.get('VERSION', true) ?? 'development')
  236. container
  237. .bind(TYPES.Sync_CONTENT_SIZE_TRANSFER_LIMIT)
  238. .toConstantValue(
  239. env.get('CONTENT_SIZE_TRANSFER_LIMIT', true)
  240. ? +env.get('CONTENT_SIZE_TRANSFER_LIMIT', true)
  241. : this.DEFAULT_CONTENT_SIZE_TRANSFER_LIMIT,
  242. )
  243. container
  244. .bind(TYPES.Sync_MAX_ITEMS_LIMIT)
  245. .toConstantValue(
  246. env.get('MAX_ITEMS_LIMIT', true) ? +env.get('MAX_ITEMS_LIMIT', true) : this.DEFAULT_MAX_ITEMS_LIMIT,
  247. )
  248. // use cases
  249. container.bind<SyncItems>(TYPES.Sync_SyncItems).toDynamicValue((context: interfaces.Context) => {
  250. return new SyncItems(context.container.get(TYPES.Sync_ItemService))
  251. })
  252. container.bind<CheckIntegrity>(TYPES.Sync_CheckIntegrity).toDynamicValue((context: interfaces.Context) => {
  253. return new CheckIntegrity(context.container.get(TYPES.Sync_ItemRepository))
  254. })
  255. container.bind<GetItem>(TYPES.Sync_GetItem).toDynamicValue((context: interfaces.Context) => {
  256. return new GetItem(context.container.get(TYPES.Sync_ItemRepository))
  257. })
  258. // Services
  259. container.bind<ItemServiceInterface>(TYPES.Sync_ItemService).toDynamicValue((context: interfaces.Context) => {
  260. return new ItemService(
  261. context.container.get(TYPES.Sync_ItemSaveValidator),
  262. context.container.get(TYPES.Sync_ItemFactory),
  263. context.container.get(TYPES.Sync_ItemRepository),
  264. context.container.get(TYPES.Sync_DomainEventPublisher),
  265. context.container.get(TYPES.Sync_DomainEventFactory),
  266. context.container.get(TYPES.Sync_REVISIONS_FREQUENCY),
  267. context.container.get(TYPES.Sync_CONTENT_SIZE_TRANSFER_LIMIT),
  268. context.container.get(TYPES.Sync_ItemTransferCalculator),
  269. context.container.get(TYPES.Sync_Timer),
  270. context.container.get(TYPES.Sync_ItemProjector),
  271. context.container.get(TYPES.Sync_MAX_ITEMS_LIMIT),
  272. context.container.get(TYPES.Sync_Logger),
  273. )
  274. })
  275. container
  276. .bind<SyncResponseFactory20161215>(TYPES.Sync_SyncResponseFactory20161215)
  277. .toDynamicValue((context: interfaces.Context) => {
  278. return new SyncResponseFactory20161215(context.container.get(TYPES.Sync_ItemProjector))
  279. })
  280. container
  281. .bind<SyncResponseFactory20200115>(TYPES.Sync_SyncResponseFactory20200115)
  282. .toDynamicValue((context: interfaces.Context) => {
  283. return new SyncResponseFactory20200115(
  284. context.container.get(TYPES.Sync_ItemProjector),
  285. context.container.get(TYPES.Sync_ItemConflictProjector),
  286. context.container.get(TYPES.Sync_SavedItemProjector),
  287. )
  288. })
  289. container
  290. .bind<SyncResponseFactoryResolverInterface>(TYPES.Sync_SyncResponseFactoryResolver)
  291. .toDynamicValue((context: interfaces.Context) => {
  292. return new SyncResponseFactoryResolver(
  293. context.container.get(TYPES.Sync_SyncResponseFactory20161215),
  294. context.container.get(TYPES.Sync_SyncResponseFactory20200115),
  295. )
  296. })
  297. container.bind<ItemFactoryInterface>(TYPES.Sync_ItemFactory).toDynamicValue((context: interfaces.Context) => {
  298. return new ItemFactory(context.container.get(TYPES.Sync_Timer), context.container.get(TYPES.Sync_ItemProjector))
  299. })
  300. container.bind<OwnershipFilter>(TYPES.Sync_OwnershipFilter).toDynamicValue(() => new OwnershipFilter())
  301. container
  302. .bind<TimeDifferenceFilter>(TYPES.Sync_TimeDifferenceFilter)
  303. .toDynamicValue(
  304. (context: interfaces.Context) => new TimeDifferenceFilter(context.container.get(TYPES.Sync_Timer)),
  305. )
  306. container.bind<UuidFilter>(TYPES.Sync_UuidFilter).toDynamicValue(() => new UuidFilter())
  307. container.bind<ContentTypeFilter>(TYPES.Sync_ContentTypeFilter).toDynamicValue(() => new ContentTypeFilter())
  308. container.bind<ContentFilter>(TYPES.Sync_ContentFilter).toDynamicValue(() => new ContentFilter())
  309. container
  310. .bind<ItemSaveValidatorInterface>(TYPES.Sync_ItemSaveValidator)
  311. .toDynamicValue((context: interfaces.Context) => {
  312. return new ItemSaveValidator([
  313. context.container.get(TYPES.Sync_OwnershipFilter),
  314. context.container.get(TYPES.Sync_TimeDifferenceFilter),
  315. context.container.get(TYPES.Sync_UuidFilter),
  316. context.container.get(TYPES.Sync_ContentTypeFilter),
  317. context.container.get(TYPES.Sync_ContentFilter),
  318. ])
  319. })
  320. // env vars
  321. container
  322. .bind(TYPES.Sync_EMAIL_ATTACHMENT_MAX_BYTE_SIZE)
  323. .toConstantValue(
  324. env.get('EMAIL_ATTACHMENT_MAX_BYTE_SIZE', true) ? +env.get('EMAIL_ATTACHMENT_MAX_BYTE_SIZE', true) : 10485760,
  325. )
  326. container.bind(TYPES.Sync_NEW_RELIC_ENABLED).toConstantValue(env.get('NEW_RELIC_ENABLED', true))
  327. container
  328. .bind(TYPES.Sync_FILE_UPLOAD_PATH)
  329. .toConstantValue(
  330. env.get('FILE_UPLOAD_PATH', true) ? env.get('FILE_UPLOAD_PATH', true) : this.DEFAULT_FILE_UPLOAD_PATH,
  331. )
  332. // Handlers
  333. container
  334. .bind<DuplicateItemSyncedEventHandler>(TYPES.Sync_DuplicateItemSyncedEventHandler)
  335. .toDynamicValue((context: interfaces.Context) => {
  336. return new DuplicateItemSyncedEventHandler(
  337. context.container.get(TYPES.Sync_ItemRepository),
  338. context.container.get(TYPES.Sync_DomainEventFactory),
  339. context.container.get(TYPES.Sync_DomainEventPublisher),
  340. context.container.get(TYPES.Sync_Logger),
  341. )
  342. })
  343. container
  344. .bind<AccountDeletionRequestedEventHandler>(TYPES.Sync_AccountDeletionRequestedEventHandler)
  345. .toDynamicValue((context: interfaces.Context) => {
  346. return new AccountDeletionRequestedEventHandler(
  347. context.container.get(TYPES.Sync_ItemRepository),
  348. context.container.get(TYPES.Sync_Logger),
  349. )
  350. })
  351. container
  352. .bind<ItemRevisionCreationRequestedEventHandler>(TYPES.Sync_ItemRevisionCreationRequestedEventHandler)
  353. .toDynamicValue((context: interfaces.Context) => {
  354. return new ItemRevisionCreationRequestedEventHandler(
  355. context.container.get(TYPES.Sync_ItemRepository),
  356. context.container.get(TYPES.Sync_ItemBackupService),
  357. context.container.get(TYPES.Sync_DomainEventFactory),
  358. context.container.get(TYPES.Sync_DomainEventPublisher),
  359. )
  360. })
  361. // Services
  362. container.bind<ContentDecoder>(TYPES.Sync_ContentDecoder).toDynamicValue(() => new ContentDecoder())
  363. container.bind<AxiosInstance>(TYPES.Sync_HTTPClient).toDynamicValue(() => axios.create())
  364. container
  365. .bind<ExtensionsHttpServiceInterface>(TYPES.Sync_ExtensionsHttpService)
  366. .toDynamicValue((context: interfaces.Context) => {
  367. return new ExtensionsHttpService(
  368. context.container.get(TYPES.Sync_HTTPClient),
  369. context.container.get(TYPES.Sync_ItemRepository),
  370. context.container.get(TYPES.Sync_ContentDecoder),
  371. context.container.get(TYPES.Sync_DomainEventPublisher),
  372. context.container.get(TYPES.Sync_DomainEventFactory),
  373. context.container.get(TYPES.Sync_Logger),
  374. )
  375. })
  376. container
  377. .bind<ItemBackupServiceInterface>(TYPES.Sync_ItemBackupService)
  378. .toDynamicValue((context: interfaces.Context) => {
  379. const env: Env = context.container.get(TYPES.Sync_Env)
  380. if (env.get('S3_AWS_REGION', true)) {
  381. return new S3ItemBackupService(
  382. context.container.get(TYPES.Sync_S3_BACKUP_BUCKET_NAME),
  383. context.container.get(TYPES.Sync_ItemProjector),
  384. context.container.get(TYPES.Sync_Logger),
  385. context.container.get(TYPES.Sync_S3),
  386. )
  387. } else {
  388. return new FSItemBackupService(
  389. context.container.get(TYPES.Sync_FILE_UPLOAD_PATH),
  390. context.container.get(TYPES.Sync_ItemProjector),
  391. context.container.get(TYPES.Sync_Logger),
  392. )
  393. }
  394. })
  395. const eventHandlers: Map<string, DomainEventHandlerInterface> = new Map([
  396. ['DUPLICATE_ITEM_SYNCED', container.get(TYPES.Sync_DuplicateItemSyncedEventHandler)],
  397. ['ACCOUNT_DELETION_REQUESTED', container.get(TYPES.Sync_AccountDeletionRequestedEventHandler)],
  398. ['ITEM_REVISION_CREATION_REQUESTED', container.get(TYPES.Sync_ItemRevisionCreationRequestedEventHandler)],
  399. ])
  400. if (!isConfiguredForHomeServer) {
  401. container.bind(TYPES.Sync_AUTH_SERVER_URL).toConstantValue(env.get('AUTH_SERVER_URL'))
  402. container
  403. .bind<AuthHttpServiceInterface>(TYPES.Sync_AuthHttpService)
  404. .toDynamicValue((context: interfaces.Context) => {
  405. return new AuthHttpService(
  406. context.container.get(TYPES.Sync_HTTPClient),
  407. context.container.get(TYPES.Sync_AUTH_SERVER_URL),
  408. )
  409. })
  410. container
  411. .bind<EmailBackupRequestedEventHandler>(TYPES.Sync_EmailBackupRequestedEventHandler)
  412. .toDynamicValue((context: interfaces.Context) => {
  413. return new EmailBackupRequestedEventHandler(
  414. context.container.get(TYPES.Sync_ItemRepository),
  415. context.container.get(TYPES.Sync_AuthHttpService),
  416. context.container.get(TYPES.Sync_ItemBackupService),
  417. context.container.get(TYPES.Sync_DomainEventPublisher),
  418. context.container.get(TYPES.Sync_DomainEventFactory),
  419. context.container.get(TYPES.Sync_EMAIL_ATTACHMENT_MAX_BYTE_SIZE),
  420. context.container.get(TYPES.Sync_ItemTransferCalculator),
  421. context.container.get(TYPES.Sync_S3_BACKUP_BUCKET_NAME),
  422. context.container.get(TYPES.Sync_Logger),
  423. )
  424. })
  425. eventHandlers.set('EMAIL_BACKUP_REQUESTED', container.get(TYPES.Sync_EmailBackupRequestedEventHandler))
  426. }
  427. if (isConfiguredForHomeServer) {
  428. const directCallEventMessageHandler = new DirectCallEventMessageHandler(
  429. eventHandlers,
  430. container.get(TYPES.Sync_Logger),
  431. )
  432. directCallDomainEventPublisher.register(directCallEventMessageHandler)
  433. container
  434. .bind<DomainEventMessageHandlerInterface>(TYPES.Sync_DomainEventMessageHandler)
  435. .toConstantValue(directCallEventMessageHandler)
  436. } else {
  437. container
  438. .bind<DomainEventMessageHandlerInterface>(TYPES.Sync_DomainEventMessageHandler)
  439. .toConstantValue(
  440. env.get('NEW_RELIC_ENABLED', true) === 'true'
  441. ? new SQSNewRelicEventMessageHandler(eventHandlers, container.get(TYPES.Sync_Logger))
  442. : new SQSEventMessageHandler(eventHandlers, container.get(TYPES.Sync_Logger)),
  443. )
  444. }
  445. container
  446. .bind<DomainEventSubscriberFactoryInterface>(TYPES.Sync_DomainEventSubscriberFactory)
  447. .toDynamicValue((context: interfaces.Context) => {
  448. return new SQSDomainEventSubscriberFactory(
  449. context.container.get(TYPES.Sync_SQS),
  450. context.container.get(TYPES.Sync_SQS_QUEUE_URL),
  451. context.container.get(TYPES.Sync_DomainEventMessageHandler),
  452. )
  453. })
  454. container
  455. .bind<ControllerContainerInterface>(TYPES.Sync_ControllerContainer)
  456. .toConstantValue(configuration?.controllerConatiner ?? new ControllerContainer())
  457. if (isConfiguredForHomeServer) {
  458. container
  459. .bind<HomeServerItemsController>(TYPES.Sync_HomeServerItemsController)
  460. .toConstantValue(
  461. new HomeServerItemsController(
  462. container.get(TYPES.Sync_SyncItems),
  463. container.get(TYPES.Sync_CheckIntegrity),
  464. container.get(TYPES.Sync_GetItem),
  465. container.get(TYPES.Sync_ItemProjector),
  466. container.get(TYPES.Sync_SyncResponseFactoryResolver),
  467. container.get(TYPES.Sync_ControllerContainer),
  468. ),
  469. )
  470. }
  471. logger.debug('Configuration complete')
  472. return container
  473. }
  474. }