UNPKG

@ngageoint/mage.image.service

Version:

Orient images attached to MAGE observations according to EXIF meta-data and generate configurable size thumbnails.

99 lines (93 loc) 4.51 kB
import { InitPluginHook, PluginStateRepositoryToken } from '@ngageoint/mage.service/lib/plugins.api' import { GetAppRequestContext, WebRoutesHooks } from '@ngageoint/mage.service/lib/plugins.api/plugins.api.web' import { ObservationRepositoryToken, AttachmentStoreToken } from '@ngageoint/mage.service/lib/plugins.api/plugins.api.observations' import { MageEventRepositoryToken } from '@ngageoint/mage.service/lib/plugins.api/plugins.api.events' import { MongooseDbConnectionToken } from '@ngageoint/mage.service/lib/plugins.api/plugins.api.db' import { SettingPermission } from '@ngageoint/mage.service/lib/entities/authorization/entities.permissions' import { ImagePluginConfig, createImagePluginControl } from './processor' import express from 'express' import { FindUnprocessedAttachments } from './adapters.db.mongo' import { SharpImageService } from './adapters.images.sharp' const logPrefix = '[mage.image]' const logMethods = [ 'log', 'debug', 'info', 'warn', 'error' ] as const const consoleOverrides = logMethods.reduce((overrides, fn) => { return { ...overrides, [fn]: { writable: false, value: (...args: any[]): void => { globalThis.console[fn](new Date().toISOString(), '-', logPrefix, ...args) } } } as PropertyDescriptorMap }, {} as PropertyDescriptorMap) const console = Object.create(globalThis.console, consoleOverrides) as Console const InjectedServices = { stateRepo: PluginStateRepositoryToken, eventRepo: MageEventRepositoryToken, obsRepoForEvent: ObservationRepositoryToken, attachmentStore: AttachmentStoreToken, getDbConn: MongooseDbConnectionToken } /** * The MAGE Image Plugin finds images attached to MAGE observations, generates * thumbnail previews at configurable sizes, and optionally auto-orients the * images by rotating them based on the EXIF orientation tag so all clients * display the images correctly. */ const imagePluginHooks: InitPluginHook<typeof InjectedServices> = { inject: { stateRepo: PluginStateRepositoryToken, eventRepo: MageEventRepositoryToken, obsRepoForEvent: ObservationRepositoryToken, attachmentStore: AttachmentStoreToken, getDbConn: MongooseDbConnectionToken, }, init: async (services): Promise<WebRoutesHooks> => { console.info('intializing image plugin ...') const { stateRepo, eventRepo, obsRepoForEvent, attachmentStore, getDbConn } = services const queryAttachments = FindUnprocessedAttachments(getDbConn, console) const imageService = SharpImageService() const control = await createImagePluginControl(stateRepo, eventRepo, obsRepoForEvent, attachmentStore, queryAttachments, imageService, console) control.start() return { webRoutes: { protected(requestContext: GetAppRequestContext): express.Router { // TODO: add api routes to save image processing settings const routes = express.Router() .use(express.json()) .use(async (req, res, next) => { const context = requestContext(req) const user = context.requestingPrincipal() if (!user.role.permissions.find(x => x === SettingPermission.UPDATE_SETTINGS)) { return res.status(403).json({ message: 'unauthorized' }) } next() }) routes.route('/config') .get(async (req, res, next) => { const config = await control.getConfig() res.json(config) }) .put(async (req, res, next) => { const bodyConfig = req.body as any const configPatch: Partial<ImagePluginConfig> = { enabled: typeof bodyConfig.enabled === 'boolean' ? bodyConfig.enabled : undefined, intervalBatchSize: typeof bodyConfig.intervalBatchSize === 'number' ? bodyConfig.intervalBatchSize : undefined, intervalSeconds: typeof bodyConfig.intervalSeconds === 'number' ? bodyConfig.intervalSeconds : undefined, thumbnailSizes: Array.isArray(bodyConfig.thumbnailSizes) ? bodyConfig.thumbnailSizes.reduce((sizes: number[], size: any) => { return typeof size === 'number' ? [...sizes, size] : sizes }, [] as number[]) : [] } const config = await control.applyConfig(configPatch) res.json(config) }) return routes } } } } } export = imagePluginHooks