diff --git a/registry/server/templates/interfaces/index.ts b/registry/server/templates/interfaces/index.ts index ea64fc16..03696689 100644 --- a/registry/server/templates/interfaces/index.ts +++ b/registry/server/templates/interfaces/index.ts @@ -22,3 +22,5 @@ export type UpdateTemplatePayload = Omit export type CreateTemplatePayload = Omit & Partial>; + +export type PartialUpdateTemplatePayload = Pick; diff --git a/registry/server/templates/routes/index.ts b/registry/server/templates/routes/index.ts index 7fafcd26..b762fc4c 100644 --- a/registry/server/templates/routes/index.ts +++ b/registry/server/templates/routes/index.ts @@ -8,6 +8,7 @@ import createTemplate from './createTemplate'; import deleteTemplate from './deleteTemplate'; import upsertTemplateLocalizedVersion from './upsertTemplateLocalizedVersion'; import deleteTemplateLocalizedVersion from './deleteTemplateLocalizedVersion'; +import partialUpdateTemplate from './partialUpdateTemplate'; export default (authMw: RequestHandler[]) => { const templatesRouter = express.Router(); @@ -17,6 +18,7 @@ export default (authMw: RequestHandler[]) => { templatesRouter.get('/:name/rendered', ...getRenderedTemplate); templatesRouter.get('/:name', ...getTemplate); templatesRouter.put('/:name', authMw, ...updateTemplate); + templatesRouter.patch('/:name', authMw, ...partialUpdateTemplate); templatesRouter.delete('/:name', authMw, ...deleteTemplate); templatesRouter.put('/:name/localized/:locale', authMw, ...upsertTemplateLocalizedVersion); templatesRouter.delete('/:name/localized/:locale', authMw, ...deleteTemplateLocalizedVersion); diff --git a/registry/server/templates/routes/partialUpdateTemplate.ts b/registry/server/templates/routes/partialUpdateTemplate.ts new file mode 100644 index 00000000..220ea48a --- /dev/null +++ b/registry/server/templates/routes/partialUpdateTemplate.ts @@ -0,0 +1,48 @@ +import { Request, Response } from 'express'; +import Joi from 'joi'; + +import validateRequestFactory from '../../common/services/validateRequest'; +import { validateLocalesMiddleware } from '../../middleware/validatelocales'; +import { exhaustiveCheck } from '../../util/exhaustiveCheck'; +import { templatesRepository } from '../services/templatesRepository'; +import { commonTemplate, templateNameSchema } from './validation'; + +type UpdateTemplateRequestParams = { + name: string; +}; + +const validateRequestBeforeUpdateTemplate = validateRequestFactory([ + { + schema: Joi.object({ + name: templateNameSchema.required(), + }), + selector: 'params', + }, + { + schema: Joi.object({ + content: commonTemplate.content.required(), + }), + selector: 'body', + }, +]); + +const partialUpdateTemplate = async (req: Request, res: Response): Promise => { + const result = await templatesRepository.partialUpdateTemplate(req.params.name, req.body, req.user); + + switch (result.type) { + case 'notFound': { + res.status(404).send('Not found'); + return; + } + case 'ok': { + res.status(200).send(result.template); + return; + } + default: { + /* istanbul ignore next */ + exhaustiveCheck(result); + } + } +}; + +export default [validateRequestBeforeUpdateTemplate, partialUpdateTemplate]; diff --git a/registry/server/templates/routes/validation.ts b/registry/server/templates/routes/validation.ts index cd7d9648..30a5022a 100644 --- a/registry/server/templates/routes/validation.ts +++ b/registry/server/templates/routes/validation.ts @@ -6,7 +6,7 @@ import renderTemplate from '../services/renderTemplate'; export const templateNameSchema = Joi.string().min(1).max(50); -const commonTemplate = { +export const commonTemplate = { content: Joi.string() .min(1) .external(async (value) => { diff --git a/registry/server/templates/services/templatesRepository.ts b/registry/server/templates/services/templatesRepository.ts index 40bffa89..fdf1cc01 100644 --- a/registry/server/templates/services/templatesRepository.ts +++ b/registry/server/templates/services/templatesRepository.ts @@ -12,6 +12,7 @@ import Template, { CreateTemplatePayload, LocalizedTemplateRow, LocalizedVersion, + PartialUpdateTemplatePayload, TemplateWithLocalizedVersions, UpdateTemplatePayload, } from '../interfaces'; @@ -60,6 +61,17 @@ type DeleteTemplateLocalizedVersionResult = | DeleteTemplateLocalizedVersionResultOk | DeleteTemplateLocalizedVersionResultNotFound; +type PartialUpdateTemplateResultOk = { + type: 'ok'; + template: VersionedRecord