diff --git a/package.json b/package.json index bf11797..9c8f111 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "@efstajas/tela", - "version": "0.3.0", + "version": "0.3.2", "description": "A framework for building Intercom Canvas Kit applications.", "main": "lib/index.js", "scripts": { "build": "tsc" }, - "keywords": ["intercom", "canvas kit", "custom apps", "express"], + "keywords": ["intercom", "canvas kit", "custom apps", "express", "typescript"], "repository": { "type" : "git", "url" : "https://github.com/efstajas/tela.git" diff --git a/src/methods/appValidator/errorTemplates/handlerNotFunction.ts b/src/methods/appValidator/errorTemplates/handlerNotFunction.ts new file mode 100644 index 0000000..95857a1 --- /dev/null +++ b/src/methods/appValidator/errorTemplates/handlerNotFunction.ts @@ -0,0 +1,2 @@ +export default (appName: string, methodName: string) => + `Expected handler ${methodName} of app ${appName} to be function that returns Promise or Component[]` diff --git a/src/methods/appValidator/errorTemplates/hookNotFunction.ts b/src/methods/appValidator/errorTemplates/hookNotFunction.ts new file mode 100644 index 0000000..1a806c0 --- /dev/null +++ b/src/methods/appValidator/errorTemplates/hookNotFunction.ts @@ -0,0 +1,2 @@ +export default (appName: string, hookName: string) => + `Expected hook ${hookName} of app ${appName} to be function like (req, res, next, context) => void` diff --git a/src/methods/appValidator/errorTemplates/hooksNotObject.ts b/src/methods/appValidator/errorTemplates/hooksNotObject.ts new file mode 100644 index 0000000..ef4895a --- /dev/null +++ b/src/methods/appValidator/errorTemplates/hooksNotObject.ts @@ -0,0 +1,2 @@ +export default (appName: string) => + `Expected 'hooks' member of app ${appName} to be object of shape { [key: string]: (req, res, next, context) => void }` diff --git a/src/methods/appValidator/errorTemplates/missingMethod.ts b/src/methods/appValidator/errorTemplates/missingMethod.ts new file mode 100644 index 0000000..70cc596 --- /dev/null +++ b/src/methods/appValidator/errorTemplates/missingMethod.ts @@ -0,0 +1,2 @@ +export default (appName: string, methodName: string) => + `App ${appName} is missing required method ${methodName}` diff --git a/src/methods/appValidator/validateApp.ts b/src/methods/appValidator/validateApp.ts new file mode 100644 index 0000000..c00d749 --- /dev/null +++ b/src/methods/appValidator/validateApp.ts @@ -0,0 +1,50 @@ +import { App } from '../../app.types' +import missingMethodTemplate from './errorTemplates/missingMethod' +import hooksNotObjectTemplate from './errorTemplates/hooksNotObject' +import handlerNotFunctionTemplate from './errorTemplates/handlerNotFunction' +import hookNotFunctionTemplate from './errorTemplates/hookNotFunction' + +export default (appName: string, app: App) => { + const requiredMembers = ['initialize'] + const optionalMembers = ['submit', 'configure', 'hooks'] + const possibleMembers = requiredMembers.concat(optionalMembers) + + const appMethods = Object.keys(app) + + // check if all required methods are present + + requiredMembers.forEach((key: string) => { + if (!appMethods.includes(key)) { + throw new Error(missingMethodTemplate(appName, key)) + } + }) + + // Check if members are of expected type + + const appAsAny = (app as any) + + possibleMembers.forEach((key: string) => { + const memberType = typeof appAsAny[key] + + if (appAsAny[key]) { + switch (key) { + case 'hooks': + if (memberType !== 'object') { + throw new Error(hooksNotObjectTemplate(appName)) + } + + Object.keys(appAsAny.hooks).forEach((h: string) => { + if (typeof appAsAny.hooks[h] !== 'function') { + throw new Error(hookNotFunctionTemplate(appName, h)) + } + }) + break + default: + if (memberType !== 'function') { + throw new Error(handlerNotFunctionTemplate(appName, key)) + } + break + } + } + }) +} diff --git a/src/tela.class.ts b/src/tela.class.ts index c9fd454..92ce5ef 100644 --- a/src/tela.class.ts +++ b/src/tela.class.ts @@ -4,11 +4,14 @@ import * as bodyParser from 'body-parser' import { App } from './app.types' import constructHandlerContext from './methods/construct-handler-context' import constructRouter from './methods/construct-router' +import validateApp from './methods/appValidator/validateApp' export default class Tela { private server = express().use(bodyParser.json()); public registerApp = async (appName: string, app: App) => { + validateApp(appName, app) + const router = constructRouter(appName, app) const path = `/${appName.toLowerCase()}`