This project created as a technical challenge for an interview and completed relatively small amount of time. It's not recommended to use this in real life projects. I open sourced this to help others and get and idea of how something like this can be done.
Compose is a very simple email sending tool. It's written for a technical challenge for Frontend Engineer position. You can think it like a simple Sent
box of an email client.
Here is the screencast, it may take some time to load and it may cut in half because of GitHub proxy. Better Cmd+click here and open in a new tab.
- NodeJS
- MongoLab
- Mongoose
- Express
- MailgunJS
- Nodemailer
- CoffeeScript
- Grunt
- Bower
- Karma
- Stylus
- jQuery
- Handlebars
- Jasmine
The challenge was expecting me to implement an email sending service with a failover mechanism. If one of the services goes down it should immediately switch to another service.
This projects depends NodeJS
, npm
, grunt
and bower
. I assume you already have them on your own machine. Remember that you will need Mongo and mailgun credentials to send and recieve emails.
- bower install
- npm install
- grunt client
- grunt server
- Open http://localhost:8888 on your browser
I implemented Karma Test Runner with Jasmine and PhantomJS and added a few tests which you can see in test_AppController.coffee
. To run tests you need to run grunt karma
. It has its own file watcher so tests will run on background when you change a code.
-
App uses an implementation of Express server. In
routes.coffee
it adds pre-defined routes to Express Router.*
will serve theindex.html
. For mail APIget
andpost
request are handled and wired toMailModel
. -
App uses a free sandbox MongoDB instance from MongoLab and uses
Mongoose
to make it easy to working with Mongo. Incompose.coffee
a MongoDB connection is established. InMailModel.coffee
a Mongoose schema is created and it's ready to handle Mongo operations. -
There are two different mail services to send mails which are
MailgunService
andNodeMailerService
. Both of them is an implementation ofAbstractMailService
to provide the same public API. -
There is a
MailSender
implementation. Basically you write your services and register them toMailSender
in priority then you useMailSender
to send mails. It will use registered services and failover between them. -
When a mail is composed,
MailSender
will send it thenMailModel
will save it to MongoDB so then we can fetch and list composed mails in UI after refreshing the page.
-
There is an
AppController
which will createRouter
andAppView
.AppController
is responsible to handle app state and it listens route changes to update views by telling toAppView
which is responsible from drawing UI widgets and binding required events. -
All views are extending from a
BaseView
which provides some useful methods likerender
,attach
anddetach
. For example, you can say a view class to render into an element by adding arenderTo
option to your view class. -
All classes are extending from
EventEmitter
to be all event driven. -
A few words view management,
BaseView
expectstemplate
andrenderTo
options to work with.template
is basically aHandlebars
compiled function which will return a string markup.BaseView
converts string markup into a DOM element using jQuery and append/prepend it to render target which is therenderTo
option. Also we can useattach
to add thetemplate
element into any other element anddetach
to remove it from DOM. -
Third party scripts are bundled in a file named
compose.third_party.min.js
and app scripts are bundled into a file namedcompose.min.js
. There are several Grunt tasks inbuild
folder which will transpileCoffeeScript
's toJavaScript
and minify and concat them usingUglifyJS
. -
Stylus files are transpiled into CSS with Grunt Stylus task and all of them will be placed in a file named
compose.min.css
. -
App will only download
compose.third_party.min.js
,compose.min.js
andcompose.min.css
. -
A footnote here,
Browserify
andWebPack
would more easy to manage the dependencies and bundle them so I can get rid of the file arrays onuglify.coffee
task.