Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,971 changes: 108 additions & 1,863 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "lambda-framework",
"version": "1.0.0",
"version": "1.0.16",
"description": "Framework to create web apps in AWS Lambda",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down Expand Up @@ -32,9 +32,7 @@
"@types/node": "^8.0.28",
"chai": "^4.1.2",
"coveralls": "^3.0.0",
"istanbul": "^0.4.5",
"mocha": "^3.5.3",
"nyc": "^11.2.1",
"tslint": "^5.7.0",
"tslint-microsoft-contrib": "^5.0.1",
"typescript": "^2.5.2"
Expand All @@ -43,6 +41,7 @@
"@types/aws-lambda": "0.0.16",
"@types/sinon": "^2.3.7",
"accepts": "^1.3.4",
"aws-sdk": "^2.141.0",
"bytes": "^3.0.0",
"content-type": "^1.0.4",
"cookie": "^0.3.1",
Expand All @@ -52,6 +51,7 @@
"fresh": "^0.5.2",
"logger": "0.0.1",
"mime-types": "^2.1.17",
"node-cache": "^4.1.1",
"npm-auto-version": "^1.0.0",
"path-to-regexp": "^2.0.0",
"qs": "^6.5.1",
Expand Down
6 changes: 6 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@ export { default as IBodyParser } from "./lib/types/http/IBodyParser";
export { default as JsonParser } from "./lib/http/bodyParsers/JsonParser";
export { default as MultipartParser } from "./lib/http/bodyParsers/MultipartParser";
export { default as UrlEncodedParser } from "./lib/http/bodyParsers/UrlEncodedParser";

export { default as ITemplate } from "./lib/types/http/renderEngine/ITemplate";
export { default as ITemplateEngine } from "./lib/types/http/renderEngine/ITemplateEngine";
export { default as ITemplateLoader } from "./lib/types/http/renderEngine/ITemplateLoader";
export { default as ITemplateRenderer } from "./lib/types/http/renderEngine/ITemplateRenderer";
export { default as DefaultTemplateLoader } from "./lib/http/renderEngine/DefaultTemplateLoader";
18 changes: 17 additions & 1 deletion src/lib/App.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import HttpError from "./exceptions/HttpError";
import httpFinalHandler from "./http/httpFinalHandler";
import HttpRequest from "./http/HttpRequest";
import HttpResponse from "./http/HttpResponse";
import DefaultTemplateLoader from "./http/renderEngine/DefaultTemplateLoader";
import TemplateEngine from "./http/renderEngine/TemplateEngine";
import Router from "./Router";
import IEventHandler from "./types/event/IEventHandler";
import IEventRequest from "./types/event/IEventRequest";
Expand All @@ -16,6 +18,9 @@ import IHttpPlaceholderHandler from "./types/http/IHttpPlaceholderHandler";
import IHttpRequest from "./types/http/IHttpRequest";
import IHttpResponse from "./types/http/IHttpResponse";
import IHttpRoute from "./types/http/IHttpRoute";
import ITemplateEngine from "./types/http/renderEngine/ITemplateEngine";
import ITemplateLoader from "./types/http/renderEngine/ITemplateLoader";
import ITemplateRenderer from "./types/http/renderEngine/ITemplateRenderer";
import IApp from "./types/IApp";
import IRouter from "./types/IRouter";
import { getEventType } from "./utils/utils";
Expand All @@ -26,14 +31,18 @@ import { getEventType } from "./utils/utils";
export default class App implements IApp {

private _settings: object;

private _router: IRouter;
private _templateEngine: ITemplateEngine;

constructor() {
this._settings = {};
this._router = new Router();
}

get templateEngine(): ITemplateEngine {
return this._templateEngine;
}

public init(settings?: object): void {
this.initDefaultConfiguration(settings);
}
Expand Down Expand Up @@ -102,6 +111,13 @@ export default class App implements IApp {
return this;
}

public addTemplateEngine(bucket: string, renderer: ITemplateRenderer, ttl?: number): IApp {
const templateLoader: ITemplateLoader = new DefaultTemplateLoader(bucket, ttl);
this._templateEngine = new TemplateEngine(bucket, renderer, templateLoader);

return this;
}

private initDefaultConfiguration(settings: object): void {
this._settings = settings ? settings : defaultConfiguration;
}
Expand Down
4 changes: 1 addition & 3 deletions src/lib/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ const configuration = {
COOKIE_SECRET: "cookie_secret",
JSON_REPLACER: "json_replacer",
JSON_SPACES: "json_spaces",
JSON_ESCAPE: "json_escape",
TEMPLATE_RENDERER_FILES_BUCKET: "template_renderer_files_bucket",
TEMPLATE_RENDERER_FUNCTION: "template_renderer_function"
JSON_ESCAPE: "json_escape"
};

export default configuration;
31 changes: 19 additions & 12 deletions src/lib/http/HttpResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import IHttpError from "./../types/exceptions/IHttpError";
import IHttpHandler from "./../types/http/IHttpHandler";
import IHttpRequest from "./../types/http/IHttpRequest";
import IHttpResponse from "./../types/http/IHttpResponse";
import ITemplateEngine from "./../types/http/renderEngine/ITemplateEngine";
import IApp from "./../types/IApp";
import INext from "./../types/INext";
import { merge, normalizeType, setCharset, stringify } from "./../utils/utils";
import AbstractTemplateEngine from "./renderEngine/AbstractRenderEngine";

/**
* This class represents an HTTP response, with the helpers to be sent.
Expand Down Expand Up @@ -351,17 +351,24 @@ export default class HttpResponse implements IHttpResponse {
}
}

public render(view: string, params: {[name: string]: any}, callback?: (html: string) => void): void {
const templateEngine: AbstractTemplateEngine = new AbstractTemplateEngine(this._app);

templateEngine.render(view, params, (html) => {
if(callback) {
callback(html);
} else {
this.putHeader("Content-Type", "text/html");
this.send(html);
}
});
public render(view: string, params: {[name: string]: any}, callback?: (err: Error, html: string) => void): void {
const templateEngine: ITemplateEngine = this._app.templateEngine;
if (templateEngine == null) {
throw new Error("The template engine must to be added in `app.addTemplateEngine` if you want to use render.");
} else {
templateEngine.render(view, params, (err: Error, html: string) => {
if (callback) {
callback(err, html);
} else {
if (err) {
this._request.next(err);
} else {
this.putHeader("Content-Type", "text/html");
this.send(html);
}
}
});
}
}

public setError(error: IHttpError): IHttpResponse {
Expand Down
39 changes: 0 additions & 39 deletions src/lib/http/renderEngine/AbstractRenderEngine.ts

This file was deleted.

68 changes: 68 additions & 0 deletions src/lib/http/renderEngine/DefaultTemplateLoader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import * as S3 from "aws-sdk/clients/s3";
import * as NodeCache from "node-cache";
import ITemplateLoader from "./../../types/http/renderEngine/ITemplateLoader";

/**
* Loads the template from AWS S3 bucket.
*/
export default class DefaultTemplateLoader implements ITemplateLoader {

private _s3: S3;
private _bucket: string;
private _cache: NodeCache;

constructor(bucket: string, ttl: number) {
this._s3 = new S3();
this._bucket = bucket;
if (ttl) {
this._cache = new NodeCache({ stdTTL: ttl });
}
}

public load(fileName: string, callback: (err: Error, content: string) => void): void {
this.getFromCache(fileName, (cacheErr: Error, cacheValue: string) => {
if (cacheErr) {
callback(cacheErr, null);
} else {
if (cacheValue === undefined) {
this._s3.getObject(
{
Bucket: this._bucket,
Key: fileName
},
(err: Error, data: S3.Types.GetObjectOutput) => {
if (err) {
callback(err, null);
} else {
const content: string = data.Body.toString();
this.setToCache(fileName, content);
callback(null, content);
}
}
);
} else {
callback(null, cacheValue);
}
}
});
}

private getFromCache(fileName: string, callback: (cacheErr: Error, cacheValue: string) => void): void {
if (this._cache) {
this._cache.get(fileName, callback);
} else {
callback(null, undefined);
}
}

private setToCache(fileName: string, content: string): void {
if (this._cache) {
this._cache.set(fileName, (err: Error, success: boolean) => {
if (err || !success) {
console.error("Error saving template into cache: " + fileName, err);
}
});
}
}

}
39 changes: 24 additions & 15 deletions src/lib/http/renderEngine/Template.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,45 @@
import ITemplate from "./../../types/http/renderEngine/ITemplate";
import ITemplateLoader from "./../../types/http/renderEngine/ITemplateLoader";

const cachedTemplates: {[name: string]: string} = {};

/**
* Representation of a template file.
*/
export default class Template implements ITemplate {

private _fileName: string;
private _bucket: string;
private _content: string;
private _loaded: boolean;
private _templateLoader: ITemplateLoader;

constructor(fileName: string, bucket: string) {
constructor(fileName: string, templateLoader: ITemplateLoader) {
this._fileName = fileName;
this._bucket = bucket;
this._loaded = false;
this._templateLoader = templateLoader;
}

get content(): string {
if(!this._loaded) {
if (!this._loaded) {
throw new Error("The template " + this._fileName + " has not been loaded.");
}
return this._content;
}

public load(callback: () => void): void {
if(!this._loaded) {
if(cachedTemplates[this._fileName]) {
this._content = cachedTemplates[this._fileName];
} else {
// TODO load file from S3
cachedTemplates[this._fileName] = this._content;
this._loaded = true;
}
public load(callback: (err?: Error) => void): void {
if (!this._loaded) {
this._templateLoader.load(
this._fileName,
(err: Error, content: string) => {
if (err) {
callback(err);
} else {
this._content = content;
this._loaded = true;
callback();
}
}
);
} else {
callback();
}
}

Expand Down
34 changes: 34 additions & 0 deletions src/lib/http/renderEngine/TemplateEngine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import ITemplate from "./../../types/http/renderEngine/ITemplate";
import ITemplateEngine from "./../../types/http/renderEngine/ITemplateEngine";
import ITemplateLoader from "./../../types/http/renderEngine/ITemplateLoader";
import ITemplateRenderer from "./../../types/http/renderEngine/ITemplateRenderer";
import Template from "./Template";

/**
* A class that render a template with a template renderer.
*/
export default class TemplateEngine implements ITemplateEngine {

private _bucket: string;
private _templateRenderer: ITemplateRenderer;
private _templateLoader: ITemplateLoader;

constructor(bucket: string, templateRenderer: ITemplateRenderer, templateLoader: ITemplateLoader) {
this._bucket = bucket;
this._templateRenderer = templateRenderer;
this._templateLoader = templateLoader;
}

public render(fileName: string, params: {[name: string]: any}, callback: (err: Error, parsedHtml: string) => void): void {
const template: ITemplate = new Template(fileName, this._templateLoader);

template.load((err: Error) => {
if (err) {
callback(err, null);
} else {
this._templateRenderer(template, params, callback);
}
});
}

}
Loading