README
dynamodb-loader-model
This module integrates the following modules:
- AWS-SDK
- DataLoader
- ElasticSearch
DynamoDB without the hassle.
Getting Started
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.
Installing
Install it via npm.
npm install dynamodb-loader-model
You can find an example in the examples folder, or a boilerplate at this repo
Usage
Configuration
It all starts with the configuration object, this declares the keys of the DynamoDB table and the fields it has. Once set the configuration, the only thing that remains is extending the base Model class, passing the table name and the configuration object.
const { Model } = require('dynamodb-loader-model')
const modelConfig = {
hashKey: 'id',
rangeKey: 'second_id',
fields: {
id: { type: 'uuid' },
second_id: { type: 'string', required: true },
name: { type: 'string', default: 'no name' },
},
elastic: 'https://elastic.endpoint'
}
class MyModel extends Model {
constructor () {
super('your_table_name', modelConfig)
}
}
Configuration object
- hashKey - string - required: Hash Key of the table.
- rangeKey - string: Range Key of the table.
- fields - object - required: Information about the attributes of the table. Each of them with the following options:
- type - string - required: Type of the attribute, if set to
uuidand no value is passed when creating it, it gets defaulted to a generated uuuid (v4). - required - boolean: Whether it's a required attribute or not.
- default - any: Default value for that attribute.
- type - string - required: Type of the attribute, if set to
- elastic - string: ElasticSearch endpoint.
Extending the model
The base model is intended to be extended, for example, you can add checks before you create an element. You can extend a Model like you would extend any Class.
class MyModel extends Model {
constructor () {
super('your_table_name', yourConfig)
this.create = this.create.bind(this)
}
create (raw) {
if (!raw.name || raw.name === '') {
throw new Error('Name is a required field')
}
if (raw.name.length >= 50) {
throw new Error('Name can only be 50 characters max')
}
return super.create(raw)
}
}
psst: remember to bind this to the method, otherwise some unwanted side effects might rise.
Methods
The module exposes the following methods:
- create: Creates an item and returns it.
remove: Removes an item.Promise<Object> create (<Object> data)
fetch: Fetches an item, if true is passed as the second parameter, DataLoader is skipped and the object is fetched directly from DynamoDB.Promise<Boolean> remove (<String|Object> key)
batchFetch: Fetches many items, calling the fetch method.Promise<Object> fetch (<String|Object> key, <Boolean> fresh)
update: Updates an item.Promise<Object> batchFetch (<List<String|Object>> key, <Boolean> fresh)
search: Executes a query on the ElasticSearch endpoint.Promise<Boolean> update (<String|Object> key, <Object> data)Promise<Boolean> remove (<Object> query)
Model Manager
It is good practice not to share the same dataloader instance across different users, so, in order to do that there's a helper model.
Configuration
The manager receives the model that you want to manage and a timeout to destroy old instances.
const { Model, ModelManager } = require('dynamodb-loader-model')
// ...
class MyModel extends Model {
constructor () {
super('your_table_name', yourConfig)
this.create = this.create.bind(this)
}
}
module.exports = new ModelManager(MyModel, 30000)
Usage
const Model = require('./route/to/manager')
const instance = Model.getInstance('unique_id')
getInstance returns an instance of your Model.
If you want to destroy it before the timeout you can call destroyInstance with the same id you got the instance.
Use case
If you are using apollo-server-lambda, when creating the context you could get an instance of the model and attach it to the context, so you can call it from the schema. The unique_id could be the request id from aws.
This way you could have a dataloader instance for every request, enforcing good practices.
Running the tests
Prerequisites
In order to run the tests you need to have Serverless Framework installed.
npm install -g serverless
Clone the repository and install dependencies.
git clone https://gitlab.com/gotoar/graphql-acl-service.git
npm install
Run the tests.
npm run test
This will get you a copy of dynamodb-local, run it, run the tests and then kill the dynamodb-local process.
And coding style tests
You can check linting with this command.
npm run lint
Dependencies
- aws-sdk
- dataloader
- dynamo-update-expression
- elasticsearch
- uuid
Contributing
Please read CONTRIBUTING.MD for details on our code of conduct, and the process for submitting merge requests to us.
Versioning
We use SemVer for versioning. For the versions available, see the tags on this repository.
Authors
- Tomas Gorkin - Initial work
See also the list of contributors who participated in this project.
License
This project is licensed under the MIT License - see the LICENSE.md file for details
Acknowledgments
- Hat tip to anyone whose code was used
- Inspiration
- etc