Node.js REST API boilerplate using TypeScript, restify, and mongodb.
- Server: Node.js with restify
- Language: TypeScript 2.3
- Database: mongodb with mongoose
- Task runner: gulp
- Features: Paging, sorting, filtering, field selection, soft deletes, HATEOAS.
- In the future: Testing
# Clone the repository
git clone https://github.com/jrollins9/typescript-restify-api.git myproject
cd myproject
# Install depenencies
npm install
# Build API
gulp build
# Start server
# Uses nodemon to watch for changes to Typescript source files
gulp start
The server will connect to a database: mongodb://localhost:27017/dev
.
This setting can be changed in the config.ts
file.
// default settings are for development environment
const config: Config = {
name: 'API Server',
env: env,
debug: process.env.DEBUG || true,
root: path.join(__dirname, '/'),
port: 8888,
db: 'mongodb://localhost:27017/dev',
version: '1.0.0',
};
Run the seed command
gulp seed
If the dev server was changed in the config.ts
file, make the corresponding change in gulpfile.js
.
seed = {
db: {
name: "mongodb://localhost:27017/dev",
options: {
server: {
socketOptions: {
keepAlive: 0
}
}
}
},
count: 50 // number of documents to seed
};
GET /api/widgets?limit=10&page=2
Status: 200 OK
Content-Type: application/json
{
"totalItems": 50,
"totalPages": 5,
"page": 2,
"limit": 10,
"links": {
"self": "/api/widgets?limit=10&page=2",
"next": "/api/widgets?limit=10&page=3",
"prev": "/api/widgets?limit=10&page=1",
"first": "/api/widgets?limit=10&page=1",
"last": "/api/widgets?limit=10&page=5"
},
"items": [
{
"_id": "592336c20fec061708156508",
"__v": 0,
"current": true,
"name": "Widget10",
"description": "description for widget10",
"rank": 5,
"createdAt": "2017-05-22T19:06:53.492Z",
"updatedAt": "2017-05-22T19:06:53.492Z",
"deleted": false,
"deletedAt": null
},
...
]
}
GET /api/widgets/{id}
Status: 200 OK
Content-Type: application/json
Link: <http://localhost:8888/api/widgets/592336c20fec061708156508>; rel="self"
{
"_id": "592336c20fec061708156508",
"__v": 0,
"current": true,
"name": "Widget10",
"description": "description for widget10",
"rank": 5,
"createdAt": "2017-05-22T19:06:53.492Z",
"updatedAt": "2017-05-22T19:06:53.492Z",
"deleted": false,
"deletedAt": null
}
POST /api/widgets
body
{
"current": true,
"name": "Widget999",
"description": "description for widget 999",
"rank": 1
}
The created resource
Status: 201 Created
Content-Type: application/json
Link: <http://localhost:8888/api/widgets/592336c20fec061708156508>; rel="self"
{
"__v": 0,
"updatedAt": "2017-05-22T21:14:04.628Z",
"createdAt": "2017-05-22T21:14:04.628Z",
"current": true,
"name": "Widget999",
"description": "description for widget 999",
"rank": 1,
"deleted": false,
"_id": "5923549c251f7c2cdc7b5bbd",
"deletedAt": null
}
PUT /api/widgets/{id}
body
{
"current": false,
"description": "widget 999 updated by user",
"rank": 4
}
The updated resource
Status: 200 OK
Content-Type: application/json
Link: <http://localhost:8888/api/widgets/592336c20fec061708156508>; rel="self"
{
"_id": "5923549c251f7c2cdc7b5bbd",
"updatedAt": "2017-05-22T21:16:44.880Z",
"createdAt": "2017-05-22T21:14:04.628Z",
"current": false,
"name": "Widget999",
"description": "widget 999 updated by user",
"rank": 4,
"__v": 0,
"deleted": false,
"deletedAt": null
}
DELETE /api/widgets/{id}
Status: 204 No Content
If using soft deletes, the response will be as follows
The 'deleted' resource, notice deleted
and deletedAt
fields
Status: 200 OK
Content-Type: application/json
Link: <http://localhost:8888/api/widgets/592336c20fec061708156508>; rel="self"
{
"_id": "5923549c251f7c2cdc7b5bbd",
"updatedAt": "2017-05-22T21:20:41.600Z",
"createdAt": "2017-05-22T21:14:04.628Z",
"current": false,
"name": "Widget999",
"description": "widget 999 updated by user",
"rank": 4,
"__v": 0,
"deleted": true,
"deletedAt": "2017-05-22T21:20:41.599Z"
}
To use sorting and filtering, the sortable
and filterable
properties must be set in the resource's controller.
// fields that results can be filtered by
public filterable = ['current', 'name', 'rank', 'deleted'];
// fields that results can be sorted by
public sortable = ['name', 'updatedAt', 'rank', 'deletedAt'];
# sort by update date ASC, then by rank DESC
GET /api/widgets?sort=updatedAt,-rank
# standard filtering
GET /api/widgets?current=true&rank=1
# advanced filtering, see mongoose documentation for formatting
GET /api/widgets?filter=[{"rank":{"$gt":1, "$lt":4}}]
# select only the name and description fields
GET /api/widgets?fields=name,description
GET /api/widgets?sort=-rank&filter=[{"rank":{"$gt":1, "$lt":4}}]&fields=id,name,rank,current¤t=false