├── templates
├── common
│ ├── mainbrand
│ │ ├── brand_header.html
│ │ └── brand_footer.html
│ ├── subbrand
│ │ ├── brand_header.html
│ │ └── brand_footer.html
│ ├── footer.html
│ └── header.html
└── emails
│ └── ice_cream.html
├── .gitignore
├── lambda
├── example-invoked-lambda
│ ├── index.js
│ └── package.json
├── template-engine
│ ├── Cache.js
│ ├── package.json
│ └── index.js
└── campaign-hook
│ ├── package.json
│ └── index.js
└── README.md
/templates/common/mainbrand/brand_header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Big MAIN BRAND Header
6 | |
7 |
8 |
9 | |
10 |
--------------------------------------------------------------------------------
/templates/common/mainbrand/brand_footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | |
5 | © My Main Brand. All Rights Reserved
6 | |
7 |
8 |
9 | |
10 |
--------------------------------------------------------------------------------
/templates/common/subbrand/brand_header.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Big SUB BRAND Header
6 | |
7 |
8 |
9 | |
10 |
--------------------------------------------------------------------------------
/templates/common/subbrand/brand_footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | |
5 | © My Sub Brand. All Rights Reserved
6 | |
7 |
8 |
9 | |
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # compiled output
2 | **/dist
3 | **/.zip
4 | **/tmp
5 | **/out-tsc
6 |
7 | # dependencies
8 | **/node_modules
9 |
10 | # e2e
11 | **/e2e/*.js
12 | **/e2e/*.map
13 |
14 | # misc
15 | **/npm-debug.log
16 | **/testem.log
17 | **/package-lock.json
18 | **/.vscode/settings.json
19 |
20 | # System Files
21 | **/.DS_Store
22 | **/.vscode
23 |
24 | example-import.csv
25 |
--------------------------------------------------------------------------------
/lambda/example-invoked-lambda/index.js:
--------------------------------------------------------------------------------
1 | exports.handler = async (event) => {
2 | // Imagine this is a database call, or a webservice call, or anything!
3 | // event.Endpoint would contain the full Endpoint object as stored in Pinpoint
4 | return {
5 | "image": "https://images.unsplash.com/photo-1580750603266-cae8b4b9f72a",
6 | "name": "Bananas",
7 | "price": "$12.00",
8 | "link": "http://www.amazon.com"
9 | };
10 | };
11 |
--------------------------------------------------------------------------------
/lambda/template-engine/Cache.js:
--------------------------------------------------------------------------------
1 | const Cache = function(){
2 |
3 | this.items = [];
4 |
5 | };
6 |
7 |
8 | Cache.prototype.put = function(key, value, timeout = null) {
9 |
10 | if (value !== undefined && value !== null) {
11 | const item = {
12 | key: key,
13 | value: value,
14 | expiredWhen: timeout ? Date.now() + timeout : null
15 | };
16 | this.items[key] = item;
17 | }
18 |
19 | };
20 |
21 | Cache.prototype.get = function(key) {
22 |
23 | const item = this.items[key];
24 | if (item) {
25 | if (item.expiredWhen === null || Date.now() <= item.expiredWhen) {
26 | return item.value;
27 | }
28 | }
29 | return null;
30 | };
31 |
32 |
33 | module.exports = new Cache();
34 |
--------------------------------------------------------------------------------
/lambda/campaign-hook/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "lambda",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": {
10 | "name": "Ryan Lowe"
11 | },
12 | "license": "Apache 2.0",
13 | "scripts": {
14 | "pretest": "npm install",
15 | "build:init": "rm -rf package-lock.json && rm -rf dist && rm -rf node_modules",
16 | "build:zip": "rm -rf package-lock.json && zip -rq --exclude=*tests* --exclude=*template.yml campaign-hook.zip .",
17 | "build:dist": "mkdir dist && mv campaign-hook.zip dist/",
18 | "build": "npm run build:init && npm install --production && npm run build:zip && npm run build:dist",
19 | "coverage": "nyc npm test"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lambda/example-invoked-lambda/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example-invoked-lambda",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": {
10 | "name": "Ryan Lowe"
11 | },
12 | "license": "Apache 2.0",
13 | "scripts": {
14 | "pretest": "npm install",
15 | "build:init": "rm -rf package-lock.json && rm -rf dist && rm -rf node_modules",
16 | "build:zip": "rm -rf package-lock.json && zip -rq --exclude=*tests* --exclude=*template.yml campaign-hook.zip .",
17 | "build:dist": "mkdir dist && mv campaign-hook.zip dist/",
18 | "build": "npm run build:init && npm install --production && npm run build:zip && npm run build:dist",
19 | "coverage": "nyc npm test"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lambda/template-engine/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "template-engine",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "pretest": "npm install",
8 | "build:init": "rm -rf package-lock.json && rm -rf dist && rm -rf node_modules",
9 | "build:zip": "rm -rf package-lock.json && zip -rq --exclude=*tests* --exclude=*template.yml template-engine.zip .",
10 | "build:dist": "mkdir dist && mv template-engine.zip dist/",
11 | "build": "npm run build:init && npm install --production && npm run build:zip && npm run build:dist",
12 | "coverage": "nyc npm test"
13 | },
14 | "author": {
15 | "name": "Ryan Lowe"
16 | },
17 | "license": "Apache 2.0",
18 | "dependencies": {
19 | "dateformat": "^3.0.3",
20 | "handlebars": "^4.7.3",
21 | "promised-handlebars": "^2.0.1",
22 | "q": "^1.5.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/templates/emails/ice_cream.html:
--------------------------------------------------------------------------------
1 |
2 | {{content-block "common/header.html"}}
3 |
4 | Here is my Ice Cream promotion email. I am so happy you are here {{properCase Attributes.FirstName}}
5 |
6 | Your price is {{currencyFormat Attributes.Price Attributes.Locale Attributes.Currency}}
7 |
8 |
Your Deal expires {{dateFormat Attributes.ExpireDate "dddd, mmmm d, yyyy"}}
9 |
10 |
11 | {{#invokeLambda "example-invoked-lambda"}}
12 |
13 |
14 | | Product Image from Lambda: |
15 |  |
16 |
17 |
18 | | Product Name |
19 | {{{name}}} |
20 |
21 |
22 | | Price: |
23 | {{{price}}} |
24 |
25 |
26 | {{/invokeLambda}}
27 |
28 |
29 |
30 | {{#translate-text "en" Attributes.PreferredLanguage.[0]}}
31 | This is English that will be translated into the preferred language of the current user by Amazon Translate.
32 | {{/translate-text}}
33 |
34 |
35 | {{content-block "common/footer.html"}}
36 |
--------------------------------------------------------------------------------
/templates/common/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{#ifEquals Attributes.brand "mainbrand"}}
10 | {{content-block "common/mainbrand/brand_footer.html"}}
11 | {{/ifEquals}}
12 | {{#ifEquals Attributes.brand "subbrand"}}
13 | {{content-block "common/subbrand/brand_footer.html"}}
14 | {{/ifEquals}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |