From 90aa74bfce55e5ce21aba2ebe09826c497f733ad Mon Sep 17 00:00:00 2001 From: rijkvanzanten Date: Wed, 1 Jul 2020 13:46:45 -0400 Subject: [PATCH] Add read fields endpoint --- src/app.ts | 2 ++ src/exceptions/field-not-found.ts | 11 ++++++ src/exceptions/index.ts | 5 +-- src/knex-schema-inspector | 2 +- src/routes/fields.ts | 39 ++++++++++++++++++++ src/services/collections.ts | 2 ++ src/services/fields.ts | 59 +++++++++++++++++++++++++++++++ 7 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 src/exceptions/field-not-found.ts create mode 100644 src/routes/fields.ts diff --git a/src/app.ts b/src/app.ts index 6caf032162..97fa20ba6a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -16,6 +16,7 @@ import authRouter from './routes/auth'; import collectionsRouter from './routes/collections'; import collectionPresetsRouter from './routes/collection-presets'; import extensionsRouter from './routes/extensions'; +import fieldsRouter from './routes/fields'; import filesRouter from './routes/files'; import foldersRouter from './routes/folders'; import itemsRouter from './routes/items'; @@ -43,6 +44,7 @@ const app = express() .use('/collections', collectionsRouter) .use('/collection_presets', collectionPresetsRouter) .use('/extensions', extensionsRouter) + .use('/fields', fieldsRouter) .use('/files', filesRouter) .use('/folders', foldersRouter) .use('/items', itemsRouter) diff --git a/src/exceptions/field-not-found.ts b/src/exceptions/field-not-found.ts new file mode 100644 index 0000000000..27dd3c540e --- /dev/null +++ b/src/exceptions/field-not-found.ts @@ -0,0 +1,11 @@ +import { BaseException } from './base'; + +export class FieldNotFoundException extends BaseException { + constructor(collection: string, field: string) { + super( + `Field "${field}" in collection "${collection}" doesn't exist.`, + 404, + 'FIELD_NOT_FOUND' + ); + } +} diff --git a/src/exceptions/index.ts b/src/exceptions/index.ts index c35145cc91..25619832ff 100644 --- a/src/exceptions/index.ts +++ b/src/exceptions/index.ts @@ -1,8 +1,9 @@ export * from './base'; +export * from './collection-not-found'; +export * from './field-not-found'; export * from './invalid-credentials'; export * from './invalid-payload'; export * from './invalid-query'; export * from './item-limit'; -export * from './route-not-found'; export * from './item-not-found'; -export * from './collection-not-found'; +export * from './route-not-found'; diff --git a/src/knex-schema-inspector b/src/knex-schema-inspector index 5b60c08c32..7afe3b04d1 160000 --- a/src/knex-schema-inspector +++ b/src/knex-schema-inspector @@ -1 +1 @@ -Subproject commit 5b60c08c32493095fbcd51701a9470ac4ddd4d2f +Subproject commit 7afe3b04d1bc47669292491c1befc35c5344d679 diff --git a/src/routes/fields.ts b/src/routes/fields.ts new file mode 100644 index 0000000000..4797a5d1ba --- /dev/null +++ b/src/routes/fields.ts @@ -0,0 +1,39 @@ +import { Router } from 'express'; +import asyncHandler from 'express-async-handler'; +import * as FieldsService from '../services/fields'; +import validateCollection from '../middleware/validate-collection'; +import { schemaInspector } from '../database'; +import { FieldNotFoundException } from '../exceptions'; + +const router = Router(); + +router.get( + '/', + asyncHandler(async (req, res) => { + const fields = await FieldsService.readAll(); + return res.json({ data: fields }); + }) +); + +router.get( + '/:collection', + validateCollection, + asyncHandler(async (req, res) => { + const fields = await FieldsService.readAll(req.collection); + return res.json({ data: fields }); + }) +); + +router.get( + '/:collection/:field', + validateCollection, + asyncHandler(async (req, res) => { + const exists = await schemaInspector.hasColumn(req.collection, req.params.field); + if (exists === false) throw new FieldNotFoundException(req.collection, req.params.field); + + const field = await FieldsService.readOne(req.collection, req.params.field); + return res.json({ data: field }); + }) +); + +export default router; diff --git a/src/services/collections.ts b/src/services/collections.ts index 5ec4d5914e..1acc7a8f3c 100644 --- a/src/services/collections.ts +++ b/src/services/collections.ts @@ -11,6 +11,8 @@ export const create = async (payload: any) => { table.comment(payload.note); } + /** @todo move this into fields service */ + payload.fields?.forEach((field: any) => { let column: ColumnBuilder; diff --git a/src/services/fields.ts b/src/services/fields.ts index e69de29bb2..c5c5c5415f 100644 --- a/src/services/fields.ts +++ b/src/services/fields.ts @@ -0,0 +1,59 @@ +import database, { schemaInspector } from '../database'; + +export const readAll = async (collection?: string) => { + const fieldsQuery = database.select('*').from('directus_fields'); + + if (collection) { + fieldsQuery.where({ collection }); + } + + const [columns, fields] = await Promise.all([ + schemaInspector.columnInfo(collection), + fieldsQuery, + ]); + + return columns.map((column) => { + const field = fields.find( + (field) => field.field === column.name && field.collection === column.table + ); + + /** @TODO + * return field defaults if field doesn't exist in directus_fields + */ + + const data = { + ...column, + ...field, + collection: column.table, + field: column.name, + }; + + delete data.table; + delete data.name; + + return data; + }); +}; + +export const readOne = async (collection: string, field: string) => { + const [column, fieldInfo] = await Promise.all([ + schemaInspector.columnInfo(collection, field), + database.select('*').from('directus_fields').where({ collection, field }).first(), + ]); + + /** @TODO + * return field defaults if field doesn't exist in directus_fields + */ + + const data = { + ...column, + ...fieldInfo, + collection: column.table, + field: column.name, + }; + + delete data.table; + delete data.name; + + return data; +};