UNPKG

@deconz-community/directus-extension-ddf-store

Version:

Extension for Directus to store DDF files in the database, used only by the Deconz Community

138 lines (115 loc) 4.99 kB
import type { Accountability } from '@directus/types' import type { Collections } from '../../client' import type { GlobalContext } from '../types' import { asyncHandler } from '../utils' const HARD_LIMIT = 20 export function searchEndpoint({ router, context, services, schema }: GlobalContext) { router.get('/search', asyncHandler(async (req, res) => { const accountability = 'accountability' in req ? req.accountability as Accountability : null const serviceOptions = { schema, knex: context.database, accountability } const vendor = typeof req.query.vendor === 'string' && req.query.vendor !== '' ? req.query.vendor : null const product = typeof req.query.product === 'string' && req.query.product !== '' ? req.query.product : null const manufacturer = typeof req.query.manufacturer === 'string' && req.query.manufacturer !== '' ? req.query.manufacturer : null const model = typeof req.query.model === 'string' && req.query.model !== '' ? req.query.model : null const hasKey = typeof req.query.hasKey === 'string' && req.query.hasKey !== '' ? req.query.hasKey : null const showDeprecated = req.query.showDeprecated === 'true' let limit = HARD_LIMIT let page = typeof req.query.page === 'string' ? Number.parseInt(req.query.page) : 1 if (Number.isNaN(page) || page < 1) page = 1 const subquery = context.database('bundles') .select('bundles.ddf_uuid') .max('bundles.source_last_modified as max_source_last_modified') .max('bundles.date_created as max_date_created') .orderBy('max_source_last_modified', 'desc') .orderBy('max_date_created', 'desc') .groupBy('ddf_uuid') if (vendor) subquery.whereLike('vendor', `%${vendor}%`) if (product) subquery.whereLike('product', `%${product}%`) if ((manufacturer) || (model)) { subquery .join('bundles_device_identifiers', 'bundles.id', '=', 'bundles_device_identifiers.bundles_id') .join('device_identifiers', 'bundles_device_identifiers.device_identifiers_id', '=', 'device_identifiers.id') if (manufacturer) subquery.whereLike('manufacturer', `%${manufacturer}%`) if (model) subquery.whereLike('model', `%${model}%`) } if (hasKey) { subquery .join('signatures', 'bundles.id', '=', 'signatures.bundle') .where('signatures.key', hasKey) } if (showDeprecated === false) { subquery .join('ddf_uuids', 'bundles.ddf_uuid', '=', 'ddf_uuids.id') .whereNull('bundles.deprecation_message') } const query = context.database .select('bundles.id') .from('bundles') .join(subquery.as('subquery'), function () { this.on('bundles.ddf_uuid', '=', 'subquery.ddf_uuid') .andOn('bundles.source_last_modified', '=', 'subquery.max_source_last_modified') .andOn('bundles.date_created', '=', 'subquery.max_date_created') }) if (typeof req.query.limit === 'string' && req.query.limit !== '') { limit = Number.parseInt(req.query.limit) if (Number.isNaN(limit) || limit > HARD_LIMIT || limit < 1) limit = HARD_LIMIT } query.offset(limit * (page - 1)) query.limit(limit) query.orderBy('bundles.source_last_modified', 'desc') query.orderBy('bundles.date_created', 'desc') const bundleService = new services.ItemsService<Collections.Bundles>('bundles', serviceOptions) const items = await bundleService.readByQuery({ fields: [ 'id', 'ddf_uuid', 'vendor', 'product', 'version_deconz', 'info', 'source_last_modified', 'content_hash', 'device_identifiers.device_identifiers_id.manufacturer', 'device_identifiers.device_identifiers_id.model', 'signatures.key', 'signatures.type', ], filter: { id: { _in: (await query).map(item => item.id), }, }, sort: ['-source_last_modified'], }) let totalCount = Number.POSITIVE_INFINITY if (items.length < limit) { totalCount = items.length + limit * (page - 1) } else { const queryCount = query .clone() .clearSelect() .clear('limit') .clear('offset') .count('bundles.id as count') .clear('join') .join(subquery.clone().as('subquery'), function () { this.on('bundles.ddf_uuid', '=', 'subquery.ddf_uuid') .andOn('bundles.source_last_modified', '=', 'subquery.max_source_last_modified') .andOn('bundles.date_created', '=', 'subquery.max_date_created') }) if (showDeprecated === false) queryCount.join('ddf_uuids', 'bundles.ddf_uuid', '=', 'ddf_uuids.id') const countResult = (await queryCount.clone()).shift() if (countResult && countResult.count && typeof countResult.count === 'number') totalCount = countResult.count } res.json({ items, totalCount }) })) }