import { FastifyInstance } from 'fastify' import { FromSchema } from 'json-schema-to-ts' import { objectSchema } from '../../schemas/object' import { AuthenticatedRequest } from '../../types/types' import { transformPostgrestError } from '../../utils' import { createDefaultSchema } from '../../utils/generic-routes' const searchRequestParamsSchema = { type: 'object', properties: { bucketName: { type: 'string' }, }, required: ['bucketName'], } as const const searchRequestBodySchema = { type: 'object', properties: { prefix: { type: 'string', example: 'folder/subfolder' }, limit: { type: 'integer', minimum: 1, example: 10 }, offset: { type: 'integer', minimum: 0, example: 0 }, sortBy: { type: 'object', properties: { column: { type: 'string', enum: ['name', 'updated_at', 'created_at', 'last_accessed_at'] }, order: { type: 'string', enum: ['asc', 'desc'] }, }, required: ['column'], }, search: { type: 'string', }, }, required: ['prefix'], } as const const successResponseSchema = { type: 'array', items: objectSchema, } interface searchRequestInterface extends AuthenticatedRequest { Body: FromSchema<typeof searchRequestBodySchema> Params: FromSchema<typeof searchRequestParamsSchema> } // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export default async function routes(fastify: FastifyInstance) { const summary = 'Search for objects under a prefix' const schema = createDefaultSchema(successResponseSchema, { body: searchRequestBodySchema, params: searchRequestParamsSchema, summary, tags: ['object'], }) fastify.post<searchRequestInterface>( '/list/:bucketName', { schema, }, async (request, response) => { const { bucketName } = request.params const { limit, offset, sortBy, search } = request.body let sortColumn, sortOrder if (sortBy?.column) { sortColumn = sortBy.column sortOrder = sortBy.order ?? 'asc' } else { sortColumn = 'name' sortOrder = 'asc' } let { prefix } = request.body if (prefix.length > 0 && !prefix.endsWith('/')) { // assuming prefix is always a folder prefix = `${prefix}/` } request.log.info(request.body) request.log.info(`searching for %s`, prefix) const { data: results, error, status, } = await request.postgrest.rpc('search', { prefix, bucketname: bucketName, limits: limit, offsets: offset, levels: prefix.split('/').length, search, sortcolumn: sortColumn, sortorder: sortOrder, }) if (error) { request.log.error({ error }, 'search rpc') return response.status(status).send(transformPostgrestError(error, status)) } request.log.info({ results }, 'results') response.status(200).send(results) } ) }