From 2a988f5ab50630a0dadb0355474acdea9d4e97a8 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 16 Apr 2021 13:12:28 +0200 Subject: [PATCH 1/2] Typing Cliam root instance --- ROADMAP.md | 12 ++-- lib/classes/cliam.class.d.ts | 36 ++--------- lib/services/compiler.service.js | 24 +++---- lib/validations/mail.validation.js | 9 +-- src/classes/cliam.class.ts | 2 +- src/services/compiler.service.ts | 24 +++---- src/validations/mail.validation.ts | 13 +--- test/units/02-request-payload.unit.test.js | 74 +++++++++++++++------- tsconfig.json | 2 +- 9 files changed, 92 insertions(+), 104 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 11dd7fd..89ea325 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -3,16 +3,13 @@ - [ ] **v1.0.3** - [ ] Headers images - [ ] Integration HTML/CSS for all transactions. Factored code. 4 colours - - [ ] Export views in lib - - [ ] Check meta.to validation - - [ ] Le merge des propriétés addresse ne semble pas fonctionner - - [ ] Validation sur le meta replyTo ne semble pas fonctionner - + - [ ] .d.ts + - [ ] **v1.1.0** - - [ ] Check / sanitize payloads + - [ ] Check / sanitize / securize payloads & addresses - [ ] Support inlines images - [ ] SMTP custom sandbox - - [ ] Fix sendgrid / sendinblue tests + - [ ] Fix sendgrid / sendinblue tests - [ ] **v1.2.0** - [ ] Support Mandrill @@ -26,7 +23,6 @@ - [ ] **v1.5.0** - [ ] Concrete classes for Error, Body, ... of each transporter - [ ] Support SMTP and WEB API in same process - - [ ] Allow cliamrc.json as -g config (by the way allow multiple configurations) - [ ] CLI tool - [ ] **v1.6.0** diff --git a/lib/classes/cliam.class.d.ts b/lib/classes/cliam.class.d.ts index 96c5e65..f62ba90 100644 --- a/lib/classes/cliam.class.d.ts +++ b/lib/classes/cliam.class.d.ts @@ -2,36 +2,8 @@ import { Event } from './../types/types/event.type'; import { IPayload } from './../types/interfaces/IPayload.interface'; import { SendingResponse } from './sending-response.class'; import { SendingError } from './sending-error.class'; -/** - * @summary Main class of cliam project. The Cliam class act as entry point and open wrapped methods such subscribe and emit. - * - * @public - */ -declare class Cliam { - /** - * @description - */ - private static instance; - /** - * @description - */ - private emitter; - private constructor(); - /** - * - * @param emitter - */ - static get(emitter: any): Cliam; - /** - * @description - * - * @param event - */ - subscribe(event: Event | string): void; - /** - * @description - */ - emit(event: Event, payload: IPayload): Promise; -} -declare const cliam: Cliam; +declare const cliam: { + emit: (event: Event, payload: IPayload) => Promise; + subscribe: (event: Event | string) => void; +}; export { cliam as Cliam }; diff --git a/lib/services/compiler.service.js b/lib/services/compiler.service.js index 076c184..e5186aa 100644 --- a/lib/services/compiler.service.js +++ b/lib/services/compiler.service.js @@ -60,18 +60,18 @@ class Compiler { * @description */ this.COLORS = [ - { key: '111111', value: container_service_1.Container.configuration.consumer.theme.primaryColor }, - { key: '222222', value: container_service_1.Container.configuration.consumer.theme.secondaryColor }, - { key: '333333', value: container_service_1.Container.configuration.consumer.theme.tertiaryColor }, - { key: '444444', value: container_service_1.Container.configuration.consumer.theme.quaternaryColor }, - { key: 'fffff1', value: Color(`#${container_service_1.Container.configuration.consumer.theme.primaryColor}`).lighten(0.50).hex().substring(1) }, - { key: 'fffff2', value: Color(`#${container_service_1.Container.configuration.consumer.theme.secondaryColor}`).lighten(0.50).hex().substring(1) }, - { key: 'fffff3', value: Color(`#${container_service_1.Container.configuration.consumer.theme.tertiaryColor}`).lighten(0.50).hex().substring(1) }, - { key: 'fffff4', value: Color(`#${container_service_1.Container.configuration.consumer.theme.quaternaryColor}`).lighten(0.50).hex().substring(1) }, - { key: '000001', value: Color(`#${container_service_1.Container.configuration.consumer.theme.primaryColor}`).darken(0.50).hex().substring(1) }, - { key: '000002', value: Color(`#${container_service_1.Container.configuration.consumer.theme.secondaryColor}`).darken(0.50).hex().substring(1) }, - { key: '000003', value: Color(`#${container_service_1.Container.configuration.consumer.theme.tertiaryColor}`).darken(0.50).hex().substring(1) }, - { key: '000004', value: Color(`#${container_service_1.Container.configuration.consumer.theme.quaternaryColor}`).darken(0.50).hex().substring(1) } + { key: '111111', value: container_service_1.Container.configuration.consumer?.theme?.primaryColor }, + { key: '222222', value: container_service_1.Container.configuration.consumer?.theme?.secondaryColor }, + { key: '333333', value: container_service_1.Container.configuration.consumer?.theme?.tertiaryColor }, + { key: '444444', value: container_service_1.Container.configuration.consumer?.theme?.quaternaryColor }, + { key: 'fffff1', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.primaryColor}`).lighten(0.50).hex().substring(1) }, + { key: 'fffff2', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.secondaryColor}`).lighten(0.50).hex().substring(1) }, + { key: 'fffff3', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.tertiaryColor}`).lighten(0.50).hex().substring(1) }, + { key: 'fffff4', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.quaternaryColor}`).lighten(0.50).hex().substring(1) }, + { key: '000001', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.primaryColor}`).darken(0.50).hex().substring(1) }, + { key: '000002', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.secondaryColor}`).darken(0.50).hex().substring(1) }, + { key: '000003', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.tertiaryColor}`).darken(0.50).hex().substring(1) }, + { key: '000004', value: Color(`#${container_service_1.Container.configuration.consumer?.theme?.quaternaryColor}`).darken(0.50).hex().substring(1) } ]; Hbs.handlebars.registerHelper('year', () => { return new Date().getFullYear(); diff --git a/lib/validations/mail.validation.js b/lib/validations/mail.validation.js index c708e6b..2a7badc 100644 --- a/lib/validations/mail.validation.js +++ b/lib/validations/mail.validation.js @@ -8,18 +8,15 @@ const attachment_disposition_enum_1 = require("../types/enums/attachment-disposi const buffer_mime_type_enum_1 = require("../types/enums/buffer-mime-type.enum"); const recipient_schema_1 = require("../types/schemas/recipient.schema"); const enum_util_1 = require("../utils/enum.util"); -const addresses = () => { - return Joi.alternatives().try(recipient_schema_1.recipient().required(), Joi.array().items(recipient_schema_1.recipient()).required()); -}; const mailSchema = Joi.object({ compiler: Joi.any().valid(...enum_util_1.list(compiler_enum_1.COMPILER)), meta: Joi.object({ subject: Joi.string().max(128).required(), from: recipient_schema_1.recipient(), replyTo: recipient_schema_1.recipient(), - to: addresses().required(), - cc: addresses(), - bcc: addresses(), + to: Joi.array().items(recipient_schema_1.recipient()).required(), + cc: Joi.array().items(recipient_schema_1.recipient()), + bcc: Joi.array().items(recipient_schema_1.recipient()), attachments: Joi.array().items(Joi.object({ content: Joi.alternatives([Joi.string().base64(), Joi.string().regex(/^data:[a-zA-Z-\/]{1,48};base64,.*$/)]).required(), type: Joi.any().valid(...enum_util_1.list(attachment_mime_type_enum_1.ATTACHMENT_MIME_TYPE)), diff --git a/src/classes/cliam.class.ts b/src/classes/cliam.class.ts index 86641fa..d465903 100644 --- a/src/classes/cliam.class.ts +++ b/src/classes/cliam.class.ts @@ -70,6 +70,6 @@ class Cliam { } } -const cliam = Cliam.get( Emitter.get( Container.configuration ) ); +const cliam = Cliam.get( Emitter.get( Container.configuration ) ) as { emit: (event: Event, payload: IPayload) => Promise, subscribe: (event: Event | string) => void }; export { cliam as Cliam } \ No newline at end of file diff --git a/src/services/compiler.service.ts b/src/services/compiler.service.ts index cf4ae8e..fa59e06 100644 --- a/src/services/compiler.service.ts +++ b/src/services/compiler.service.ts @@ -71,18 +71,18 @@ class Compiler { * @description */ private readonly COLORS: Array<{key: string, value: string}> = [ - { key: '111111', value: Container.configuration.consumer.theme.primaryColor }, - { key: '222222', value: Container.configuration.consumer.theme.secondaryColor }, - { key: '333333', value: Container.configuration.consumer.theme.tertiaryColor }, - { key: '444444', value: Container.configuration.consumer.theme.quaternaryColor }, - { key: 'fffff1', value: Color(`#${Container.configuration.consumer.theme.primaryColor}`).lighten(0.50).hex().substring(1) }, - { key: 'fffff2', value: Color(`#${Container.configuration.consumer.theme.secondaryColor}`).lighten(0.50).hex().substring(1) }, - { key: 'fffff3', value: Color(`#${Container.configuration.consumer.theme.tertiaryColor}`).lighten(0.50).hex().substring(1) }, - { key: 'fffff4', value: Color(`#${Container.configuration.consumer.theme.quaternaryColor}`).lighten(0.50).hex().substring(1) }, - { key: '000001', value: Color(`#${Container.configuration.consumer.theme.primaryColor}`).darken(0.50).hex().substring(1) }, - { key: '000002', value: Color(`#${Container.configuration.consumer.theme.secondaryColor}`).darken(0.50).hex().substring(1) }, - { key: '000003', value: Color(`#${Container.configuration.consumer.theme.tertiaryColor}`).darken(0.50).hex().substring(1) }, - { key: '000004', value: Color(`#${Container.configuration.consumer.theme.quaternaryColor}`).darken(0.50).hex().substring(1) } + { key: '111111', value: Container.configuration.consumer?.theme?.primaryColor }, + { key: '222222', value: Container.configuration.consumer?.theme?.secondaryColor }, + { key: '333333', value: Container.configuration.consumer?.theme?.tertiaryColor }, + { key: '444444', value: Container.configuration.consumer?.theme?.quaternaryColor }, + { key: 'fffff1', value: Color(`#${Container.configuration.consumer?.theme?.primaryColor}`).lighten(0.50).hex().substring(1) }, + { key: 'fffff2', value: Color(`#${Container.configuration.consumer?.theme?.secondaryColor}`).lighten(0.50).hex().substring(1) }, + { key: 'fffff3', value: Color(`#${Container.configuration.consumer?.theme?.tertiaryColor}`).lighten(0.50).hex().substring(1) }, + { key: 'fffff4', value: Color(`#${Container.configuration.consumer?.theme?.quaternaryColor}`).lighten(0.50).hex().substring(1) }, + { key: '000001', value: Color(`#${Container.configuration.consumer?.theme?.primaryColor}`).darken(0.50).hex().substring(1) }, + { key: '000002', value: Color(`#${Container.configuration.consumer?.theme?.secondaryColor}`).darken(0.50).hex().substring(1) }, + { key: '000003', value: Color(`#${Container.configuration.consumer?.theme?.tertiaryColor}`).darken(0.50).hex().substring(1) }, + { key: '000004', value: Color(`#${Container.configuration.consumer?.theme?.quaternaryColor}`).darken(0.50).hex().substring(1) } ]; constructor() { diff --git a/src/validations/mail.validation.ts b/src/validations/mail.validation.ts index e0a1127..c3bcf5f 100644 --- a/src/validations/mail.validation.ts +++ b/src/validations/mail.validation.ts @@ -9,22 +9,15 @@ import { recipient } from '../types/schemas/recipient.schema'; import { list } from '../utils/enum.util'; -const addresses = () => { - return Joi.alternatives().try( - recipient().required(), - Joi.array().items( recipient() ).required() - ) -}; - const mailSchema = Joi.object({ compiler: Joi.any().valid(...list(COMPILER)), meta: Joi.object({ subject: Joi.string().max(128).required(), from: recipient(), replyTo: recipient(), - to: addresses().required(), - cc: addresses(), - bcc: addresses(), + to: Joi.array().items( recipient() ).required(), + cc: Joi.array().items( recipient() ), + bcc: Joi.array().items( recipient() ), attachments: Joi.array().items( Joi.object({ content: Joi.alternatives([ Joi.string().base64(), Joi.string().regex(/^data:[a-zA-Z-\/]{1,48};base64,.*$/) ]).required(), diff --git a/test/units/02-request-payload.unit.test.js b/test/units/02-request-payload.unit.test.js index 8e04af9..68ea1ce 100644 --- a/test/units/02-request-payload.unit.test.js +++ b/test/units/02-request-payload.unit.test.js @@ -56,43 +56,73 @@ describe('Request payload', () => { ['from', 'replyTo', 'to', 'cc', 'bcc'].forEach(property => { describe(`.${property}`, () => { + + if ( ['to', 'cc', 'bcc'].includes(property) ) { + + if ( property === 'to' ) { + + it(`error - ${property} is required`, (done) => { + payload.meta[property] = undefined; + const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; + expect(error.details[0].message).to.be.eqls(`"meta.${property}" is required`); + done(); + }); + + } - if (property === 'to') { + it(`error - ${property} must be an array`, (done) => { + payload.meta[property] = {}; + const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; + expect(error.details[0].message).to.be.eqls(`"meta.${property}" must be an array`); + done(); + }); it(`error - ${property}.name is required`, (done) => { - payload.meta[property] = { name: null, email: 'info@example.com' }; + payload.meta[property] = [ { name: null, email: 'info@example.com' } ]; const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; - expect(error.details[0].message).to.be.eqls(`"meta.${property}.name" must be a string`); + expect(error.details[0].message).to.be.eqls(`"meta.${property}[0].name" must be a string`); done(); }); - } - - it(`error - ${property}.name should be less than or equal to 48 chars`, (done) => { - payload.meta[property] = { name: chance.string({ length: 49 }), email: 'info@example.com' }; - const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; - expect(error.details[0].message).to.be.eqls(`"meta.${property}.name" length must be less than or equal to 48 characters long`); - done(); - }); - - if (property === 'to') { + it(`error - ${property}.name should be less than or equal to 48 chars`, (done) => { + payload.meta[property] = [ { name: chance.string({ length: 49 }), email: 'info@example.com' } ]; + const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; + expect(error.details[0].message).to.be.eqls(`"meta.${property}[0].name" length must be less than or equal to 48 characters long`); + done(); + }); it(`error - ${property}.email is required`, (done) => { - payload.meta[property] = { name: 'Yoda', email : null }; + payload.meta[property] = [ { name: 'Yoda', email : null } ]; + const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; + expect(error.details[0].message).to.be.eqls(`"meta.${property}[0].email" must be a string`); + done(); + }); + + it(`error - ${property}.email should be a valid email address`, (done) => { + payload.meta[property] = [ { name: 'Yoda', email : 'Yoda' } ]; const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; - expect(error.details[0].message).to.be.eqls(`"meta.${property}.email" must be a string`); + expect(error.details[0].message).to.be.eqls(`"meta.${property}[0].email" must be a valid email`); + done(); + }); + + } else { + + it(`error - ${property}.name should be less than or equal to 48 chars`, (done) => { + payload.meta[property] = { name: chance.string({ length: 49 }), email: 'info@example.com' }; + const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; + expect(error.details[0].message).to.be.eqls(`"meta.${property}.name" length must be less than or equal to 48 characters long`); + done(); + }); + + it(`error - ${property}.email should be a valid email address`, (done) => { + payload.meta[property] = { name: 'Yoda', email : 'Yoda' }; + const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; + expect(error.details[0].message).to.be.eqls(`"meta.${property}.email" must be a valid email`); done(); }); } - it(`error - ${property}.email should be a valid email address`, (done) => { - payload.meta[property] = { name: 'Yoda', email : 'Yoda' }; - const error = mailSchema.validate(payload, { abortEarly: true, allowUnknown: false })?.error; - expect(error.details[0].message).to.be.eqls(`"meta.${property}.email" must be a valid email`); - done(); - }); - }); }); diff --git a/tsconfig.json b/tsconfig.json index a6da53a..2568de1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,7 @@ "baseUrl": "./src", "lib": ["dom", "esNext"], "target": "esNext", - "declaration": false, + "declaration": true, "module": "commonjs", "allowSyntheticDefaultImports": true, "emitDecoratorMetadata": true, From 52d8b51ac895a293e9b31732d57b64371b405ce2 Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 16 Apr 2021 13:13:10 +0200 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 9 ++++++++- package.json | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c07a7de..d31fbc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). -## [v1.0.4](https://github.com/konfer-be/cliam/compare/v1.0.3...v1.0.4) +## [v1.0.5](https://github.com/konfer-be/cliam/compare/v1.0.4...v1.0.5) + +### Commits + +- Typing Cliam root instance [`2a988f5`](https://github.com/konfer-be/cliam/commit/2a988f5ab50630a0dadb0355474acdea9d4e97a8) + +## [v1.0.4](https://github.com/konfer-be/cliam/compare/v1.0.3...v1.0.4) - 2021-04-16 ### Commits - Typescript declarations [`7728d01`](https://github.com/konfer-be/cliam/commit/7728d011268c5ae896040ad0499a1b330d6d8900) +- Update changelog [`75d98e8`](https://github.com/konfer-be/cliam/commit/75d98e8bef3bb466ed824e424051b371e451fc3e) ## [v1.0.3](https://github.com/konfer-be/cliam/compare/v1.0.2...v1.0.3) - 2021-04-15 diff --git a/package.json b/package.json index 6d84045..5e6d0a5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cliam", - "version": "1.0.4", + "version": "1.0.5", "engines": { "node": ">=14.16" },