UNPKG

burdy

Version:

Open Source Headless Platform

526 lines (525 loc) 19.4 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const express_1 = __importDefault(require("express")); const auth_middleware_1 = __importDefault(require("../middleware/auth.middleware")); const async_middleware_1 = __importDefault(require("../middleware/async.middleware")); const typeorm_1 = require("typeorm"); const yup = __importStar(require("yup")); const content_type_model_1 = __importDefault(require("../models/content-type.model")); const bad_request_error_1 = __importDefault(require("../errors/bad-request-error")); const internal_server_error_1 = __importDefault(require("../errors/internal-server-error")); const post_model_1 = __importDefault(require("../models/post.model")); const hooks_1 = __importDefault(require("../../shared/features/hooks")); const mappers_1 = require("../common/mappers"); const utility_1 = require("../../admin/helpers/utility"); const content_type_bl_1 = require("../business-logic/content-type-bl"); const app = (0, express_1.default)(); app.get('/content-types', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _a, _b, _c, _d; const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const id = (_a = req === null || req === void 0 ? void 0 : req.query) === null || _a === void 0 ? void 0 : _a.id; const name = (_b = req === null || req === void 0 ? void 0 : req.query) === null || _b === void 0 ? void 0 : _b.name; const search = (_c = req === null || req === void 0 ? void 0 : req.query) === null || _c === void 0 ? void 0 : _c.search; const type = (_d = req === null || req === void 0 ? void 0 : req.query) === null || _d === void 0 ? void 0 : _d.type; const qb = contentTypeRepository .createQueryBuilder('contentType') .leftJoinAndSelect('contentType.author', 'author') .leftJoinAndSelect('author.meta', 'author.meta'); if (id) { qb.andWhereInIds(id.split(',')); } if (name) { qb.andWhere('contentType.name IN (:...names)', { names: name.split(','), }); } if ((search === null || search === void 0 ? void 0 : search.length) > 0) { qb.andWhere('LOWER(contentType.name) LIKE :search', { search: `%${search.toLowerCase()}%`, }); } if (type) { qb.andWhere('contentType.type IN (:...types)', { types: type.split(','), }); } const contentTypes = yield qb .addOrderBy('contentType.updatedAt', 'DESC') .getMany(); res.send(contentTypes.map(mappers_1.mapContentType)); }))); app.post('/content-types', (0, auth_middleware_1.default)(['content_types_create']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _e, _f; yield req.validate({ name: yup.string().max(256).required(), type: yup.string().max(256).required(), }, 'body'); const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); try { const contentType = yield contentTypeRepository.save({ name: req.body.name, type: req.body.type, author: (_e = req === null || req === void 0 ? void 0 : req.data) === null || _e === void 0 ? void 0 : _e.user, fields: JSON.stringify((_f = req.body.fields) !== null && _f !== void 0 ? _f : []), }); res.send((0, mappers_1.mapContentType)(contentType)); } catch (err) { if ((err === null || err === void 0 ? void 0 : err.code) === '23505') { throw new bad_request_error_1.default('duplicate_name'); } throw new internal_server_error_1.default('unknown_error'); } }))); app.delete('/content-types', (0, auth_middleware_1.default)(['content_types_delete']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _g, _h; const ids = (_g = req === null || req === void 0 ? void 0 : req.body) !== null && _g !== void 0 ? _g : []; if (!ids || (ids === null || ids === void 0 ? void 0 : ids.length) === 0) return res.send([]); const force = ((_h = req.query) === null || _h === void 0 ? void 0 : _h.force) === 'true'; const postRepository = (0, typeorm_1.getRepository)(post_model_1.default); const postCount = yield postRepository.count({ contentTypeId: (0, typeorm_1.In)(ids), }); if (postCount > 0 && !force) throw new bad_request_error_1.default('posts_exist'); const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const deleted = yield contentTypeRepository.delete({ id: (0, typeorm_1.In)(ids), }); return res.send(deleted); }))); app.put('/content-types/:contentTypeId', (0, auth_middleware_1.default)(['content_types_update']), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { yield req.validate({ name: yup.string().max(256).required(), }, 'body'); const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const contentType = yield contentTypeRepository.findOne({ relations: ['author', 'author.meta'], where: { id: req.params.contentTypeId, }, }); if (!contentType) throw new bad_request_error_1.default('invalid_content_type'); if (req.body.name) { contentType.name = req.body.name; } if (req.body.fields) { contentType.fields = JSON.stringify(req.body.fields); } yield contentTypeRepository.save(contentType); res.send((0, mappers_1.mapContentType)(contentType)); }))); app.post('/content-types/import', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _j, _k; const data = ((_j = req === null || req === void 0 ? void 0 : req.body) === null || _j === void 0 ? void 0 : _j.data) || []; const force = (_k = req === null || req === void 0 ? void 0 : req.body) === null || _k === void 0 ? void 0 : _k.force; const filtered = data.filter((contentType) => { return (!(0, utility_1.isEmptyString)(contentType.name) && !(0, utility_1.isEmptyString)(contentType.type)); }); const entityManager = (0, typeorm_1.getManager)(); let response = []; yield entityManager.transaction((transactionManager) => __awaiter(void 0, void 0, void 0, function* () { var _l; response = yield (0, content_type_bl_1.importContentTypes)({ entityManager: transactionManager, data: filtered, user: (_l = req === null || req === void 0 ? void 0 : req.data) === null || _l === void 0 ? void 0 : _l.user, options: { force, }, }); })); res.send(response); }))); app.get('/content-types/export', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _m; const ids = (((_m = req === null || req === void 0 ? void 0 : req.query) === null || _m === void 0 ? void 0 : _m.id) || '').split(','); const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const contentTypes = yield contentTypeRepository.find({ where: { id: (0, typeorm_1.In)(ids), }, }); const mapped = contentTypes.map((contentType) => { let fields = []; try { fields = JSON.parse(contentType.fields); } catch (_a) { // } return { name: contentType === null || contentType === void 0 ? void 0 : contentType.name, type: contentType === null || contentType === void 0 ? void 0 : contentType.type, fields, }; }); res.setHeader('Content-disposition', `attachment; filename=contentTypes.json`); res.setHeader('Content-type', 'application/json'); res.send(mapped); }))); app.get('/content-types/single', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { var _o; const name = (_o = req === null || req === void 0 ? void 0 : req.query) === null || _o === void 0 ? void 0 : _o.name; const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const qb = contentTypeRepository .createQueryBuilder('contentType') .leftJoinAndSelect('contentType.author', 'author') .leftJoinAndSelect('author.meta', 'author.meta'); if (name) { qb.andWhere('contentType.name = :name', { name, }); } const contentType = yield qb.getOne(); if (!contentType) throw new bad_request_error_1.default('invalid_content_type'); res.send((0, mappers_1.mapContentType)(contentType)); }))); app.get('/content-types/:contentTypeId', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const contentType = yield contentTypeRepository.findOne({ id: req.params.contentTypeId, }); if (!contentType) throw new bad_request_error_1.default('invalid_content_type'); res.send((0, mappers_1.mapContentType)(contentType)); }))); // Content types const fields = [ { type: 'richtext', name: 'Rich Text', component: './richtext.tsx', iconProps: { iconName: 'FabricTextHighlight' }, group: 'Core', }, { type: 'number', name: 'Number', iconProps: { iconName: 'NumberField' }, group: 'Core', fields: [ { name: 'required', type: 'checkbox', label: 'Required', }, { name: 'defaultValue', type: 'number', label: 'Default', }, ], }, { type: 'choicegroup', name: 'Choice Group', iconProps: { iconName: 'RadioBtnOn' }, group: 'Core', fields: [ { name: 'options', type: 'text', multiline: true, placeholder: 'green\nred\nblue', label: 'Options', }, { name: 'defaultValue', type: 'text', label: 'Default', }, ], }, { type: 'dropdown', name: 'Dropdown', iconProps: { iconName: 'Dropdown' }, group: 'Core', fields: [ { name: 'options', type: 'text', multiline: true, placeholder: 'green\nred\nblue', label: 'Options', }, { name: 'defaultValue', type: 'text', label: 'Default', }, { name: 'multiSelect', type: 'checkbox', label: 'Multi Select', }, ], }, { type: 'checkbox', name: 'Checkbox', iconProps: { iconName: 'CheckboxComposite' }, group: 'Core', fields: [ { name: 'defaultValue', type: 'choicegroup', defaultValue: 'false', label: 'Default', options: 'true\nfalse', }, ], }, { type: 'colorpicker', name: 'Color Picker', iconProps: { iconName: 'Eyedropper' }, group: 'Core', }, { type: 'datepicker', name: 'Date Picker', iconProps: { iconName: 'CalendarWeek' }, group: 'Core', }, { type: 'images', name: 'Images', iconProps: { iconName: 'FileImage' }, group: 'Core', fields: [ { name: 'multiSelect', type: 'checkbox', label: 'Multi Select', }, ], }, { type: 'assets', name: 'Assets', iconProps: { iconName: 'Document' }, group: 'Core', fields: [ { name: 'multiSelect', type: 'checkbox', label: 'Multi Select', }, ], }, { type: 'relation', name: 'Relation', description: 'Deprecated - use reference instead', iconProps: { iconName: 'Relationship' }, group: 'Core', fields: [ { type: 'post_type_dropdown', name: 'posts', multiSelect: true, label: 'Allowed post types', rules: { required: 'Field is required', }, }, ], }, { type: 'reference_single', name: 'Reference - Single', iconProps: { iconName: 'Relationship' }, group: 'Core', fields: [ { type: 'post_type_dropdown', name: 'posts', multiSelect: true, label: 'Allowed post types', }, ], }, { type: 'reference_multiple', name: 'Reference - Multiple', iconProps: { iconName: 'Relationship' }, group: 'Core', fields: [ { type: 'post_type_dropdown', name: 'posts', multiSelect: true, label: 'Allowed post types', }, ], }, { type: 'group', name: 'Group', iconProps: { iconName: 'ViewListTree' }, group: 'Layout', }, { type: 'repeatable', name: 'Repeatable', iconProps: { iconName: 'ViewList' }, group: 'Layout', fields: [ { name: 'max', type: 'number', label: 'Maximum Items', }, ], }, { type: 'tab', name: 'Tab', iconProps: { iconName: 'TabCenter' }, group: 'Layout', }, { type: 'zone', name: 'Dynamic Zone', iconProps: { iconName: 'Add' }, group: 'Layout', fields: [ { type: 'components_dropdown', name: 'components', label: 'Allowed components', multiSelect: true, rules: { required: 'Field is required', }, }, ], }, { type: 'custom', name: 'Custom Component', iconProps: { iconName: 'Add' }, group: 'Core', fields: [ { name: 'allowToggle', type: 'checkbox', label: 'Allow Toggle', }, { type: 'components_dropdown', name: 'component', label: 'Component', rules: { required: 'Field is required', }, }, ], }, { type: 'text', name: 'Text', iconProps: { iconName: 'TextField' }, group: 'Core', fields: [ { name: 'required', type: 'checkbox', label: 'Required', }, { name: 'defaultValue', type: 'text', label: 'Default', }, { name: 'multiline', type: 'checkbox', label: 'Multiline', }, ], }, { type: 'text-editor', name: 'Text Editor (Ace)', iconProps: { iconName: 'NumberSymbol' }, group: 'Core', fields: [ { name: 'mode', type: 'choicegroup', defaultValue: 'json', label: 'Type', required: true, options: 'json\nxml\nyaml\njavascript\ntypescript\ntext\nhtml\ncss\nsql\nmarkdown\nsh', }, ], }, ]; const mapComponent = (component) => { return { id: component.id, name: component.name, type: 'component', group: 'Custom Components', }; }; app.get('/components', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const contentTypeRepository = (0, typeorm_1.getRepository)(content_type_model_1.default); const contentTypes = yield contentTypeRepository.find({ type: 'component', }); res.send(contentTypes.map(mapComponent)); }))); app.get('/fields', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const allFields = yield hooks_1.default.applyFilters('contentType/fields', [ ...fields, ]); res.send(allFields); }))); app.get('/fields/:fieldType', (0, auth_middleware_1.default)(), (0, async_middleware_1.default)((req, res) => __awaiter(void 0, void 0, void 0, function* () { const allFields = yield hooks_1.default.applyFilters('contentType/fields', [ ...fields, ]); const field = allFields.find((field) => field.type === req.params.fieldType); if (!field) throw new bad_request_error_1.default('invalid_field_type'); res.send(field); }))); exports.default = app;