Skip to content
Draft
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
12 changes: 12 additions & 0 deletions express-basic/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
109 changes: 109 additions & 0 deletions express-basic/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Project specific ignores
bin/
temp/
*.sqlite
21 changes: 21 additions & 0 deletions express-basic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Express Basic

This is a basic express application. It provides a solid starting point to build most small-scale apps.

## Features

- Sequelize ORM *(for SQL based databases)*
- Promise based router *(for full async/await support)*
- Ready to be expanded with tests and whatever else you might need.

## Usage

To develop:

```sh
npm run dev
```

## License

MIT: <https://nicholai.mit-license.org>
25 changes: 25 additions & 0 deletions express-basic/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const express = require('express')
const Router = require('express-promise-router')

function load (routes) {
const app = express()
const router = Router()

router.use('/api', routes)
router.use((error, req, res, next) => {
res.status(500).send({
message: 'An unexpected error has occurred',
error: {
message: error.message
}
})
})

app.use(router)

return app
}

module.exports = {
load
}
49 changes: 49 additions & 0 deletions express-basic/database.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
const { Sequelize } = require('sequelize')

/**
* Create in-memory SQLite Database.
* This is useful when running tests.
*
* @returns Promise<SequelizeZ
*/
async function createMemoryDatabase () {
return createAndConnect('sqlite::memory:')
}

/**
* Create file backed SQLite database.
* This is useful during development.
*
* @param {string} storage File path for database storage
* @returns Promise<Sequelize>
*/
async function createSQLiteDatabase (storage = 'database.sqlite') {
return createAndConnect({
dialect: 'sqlite',
storage
})
}

/**
* Connect to database.
* This is used for production deploys.
*
* @param {string} uri Connection string for MariaDB, MySQL or Postgres database.
* @returns
*/
function createSQLDatabase (uri) {
return createAndConnect(uri)
}

async function createAndConnect (opts) {
const sequelize = new Sequelize(opts)
await sequelize.authenticate()

return sequelize
}

module.exports = {
createMemoryDatabase,
createSQLiteDatabase,
createSQLDatabase
}
60 changes: 60 additions & 0 deletions express-basic/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/usr/bin/env node
'use strict'

require('dotenv').config()

const app = require('./app')
const routes = require('./routes')
const db = require('./database')

const port = process.env.PORT ?? 8000

async function main () {
console.log('Application starting')
const database = await initialiseDatabase(process.env.NODE_ENV, process.env.DB_URI)

app.load(routes(database))
.listen(port, () => {
console.info(`Application listening on port ${port}`)
})
.on('error', error => {
console.error(error)
})

await synchroniseDatabase(process.env.NODE_ENV, database)
}

/**
* Initialise database for this application.
* @param {'production'|'test'|'development'} env Node environment
* @param {string?} dbUri Database uri
* @returns
*/
function initialiseDatabase (env, dbUri) {
if (env === 'production') return db.createSQLDatabase(dbUri)
if (env === 'test') return db.createMemoryDatabase()
return db.createSQLiteDatabase()
}

/**
* Synchronise tables in database
* @param {'production'|'test'|'development'} env Node environment
* @param {import('sequelize').Sequelize} db Sequelize instance
* @return {Promise}
*/
function synchroniseDatabase (env, db) {
if (env === 'production') return db.sync()
if (env === 'test') return db.sync({ force: true })
return db.sync({ alter: true })
}

if (process.env.NODE_ENV !== 'test') main()
.then(() => console.info('Application running'))
.catch(error => {
console.error(error)
process.exit(1)
})

module.exports = {
main
}
Loading