diff --git a/src/routes/collections.ts b/src/routes/collections.ts index 07a934d426..dabfe77961 100644 --- a/src/routes/collections.ts +++ b/src/routes/collections.ts @@ -4,10 +4,36 @@ import sanitizeQuery from '../middleware/sanitize-query'; import validateQuery from '../middleware/validate-query'; import * as CollectionsService from '../services/collections'; import { schemaInspector } from '../database'; -import { CollectionNotFoundException } from '../exceptions'; +import { InvalidPayloadException, CollectionNotFoundException } from '../exceptions'; +import Joi from '@hapi/joi'; const router = Router(); +const fieldSchema = Joi.object({ + field: Joi.string().required(), + datatype: Joi.string().required(), + note: Joi.string().required(), + primary_key: Joi.boolean(), + auto_increment: Joi.boolean(), +}); + +const collectionSchema = Joi.object({ + collection: Joi.string().required(), + fields: Joi.array().items(fieldSchema).min(1).unique().required(), + note: Joi.string(), +}); + +router.post( + '/', + asyncHandler(async (req, res) => { + const { error } = collectionSchema.validate(req.body); + if (error) throw new InvalidPayloadException(error.message); + + const createdCollection = await CollectionsService.create(req.body); + res.json({ data: createdCollection }); + }) +); + router.get( '/', sanitizeQuery, diff --git a/src/services/collections.ts b/src/services/collections.ts index 19a5648c69..59b7a9129f 100644 --- a/src/services/collections.ts +++ b/src/services/collections.ts @@ -1,8 +1,46 @@ -import { schemaInspector } from '../database'; +import database, { schemaInspector } from '../database'; import * as ItemsService from '../services/items'; import { Table } from '../knex-schema-inspector/lib/types/table'; import { Collection } from '../types/collection'; import { Query } from '../types/query'; +import { ColumnBuilder } from 'knex'; + +/** @Todo properly type this */ +export const create = async (payload: any) => { + await database.schema.createTable(payload.collection, (table) => { + if (payload.note) { + table.comment(payload.note); + } + + payload.fields?.forEach((field: any) => { + let column: ColumnBuilder; + + if (field.auto_increment) { + column = table.increments(field.field); + } else { + column = table.specificType(field.field, field.datatype); + + // increments() also sets primary key + if (field.primary_key) { + column.primary(); + } + } + + if (field.note) { + column.comment(field.note); + } + }); + }); + + return await ItemsService.createItem('directus_collections', { + collection: payload.collection, + hidden: payload.hidden || false, + single: payload.single || false, + icon: payload.icon || null, + note: payload.note || null, + translation: payload.translation || null, + }); +}; export const readAll = async (query?: Query) => { const [tables, collections] = await Promise.all([ diff --git a/src/services/items.ts b/src/services/items.ts index 6b8546190b..b3c5ce9efe 100644 --- a/src/services/items.ts +++ b/src/services/items.ts @@ -6,7 +6,8 @@ export const createItem = async ( data: Record, query: Query = {} ) => { - const result = await database(collection).insert(data).returning('id'); + const primaryKeyField = await schemaInspector.primary(collection); + const result = await database(collection).insert(data).returning(primaryKeyField); return readItem(collection, result[0], query); };