
Product
Rust Support Now in Beta
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
dynamo-easy
Advanced tools
Use the power of typescript to define your object mapping when using dynamodb. This library also provides a fluent api for easy interaction with dynamodb.
Abstracts away the complexity of the low level aws dynamosdk. Provides an easy to use fluent api to for requests and supports typescript decorators, to define some metadata for your models. You don't need to care about the mapping of javascript types to their dynamo types any more. We got you covered.
Checkout the full technical api documentation here.
Built with :heart: by shiftcode.
@Model()
class Person{
@PartitionKeyUUID()
id: string
name: string
}
const dynamoStore = new DynamoStore(Person)
// add a new item
dynamoStore.put({name: 'peter'})
.exec().subscribe(()=>{
console.log('peter was saved')
})
// search for all persons which start with the character 'p'
dynamoStore.query()
.where('name').startsWith('p')
.exec()
.subscribe((persons: Person[])=>{
console.log('got persons')
})
// returns all persons
dynamoStore.scan()
.exec()
.subscribe((persons: Person[]) => {
console.log('all persons')
})
Want to use this library with Angular (>4) checkout our angular-service.
Decorators are used to add some metadata to our model classes, relevant to our javascript-to-dynamo mapper.
This is an experimental feature and requires to set the following typescript compiler options:
Additionally we rely on the reflect-metadata (https://www.npmjs.com/package/reflect-metadata) library for reflection api.
To get started with decorators just add a @Model() Decorator to any typescript class.
If you need to read the metadata by hand for some purpose, use the MetadataHelper to read the informations.
We make heavy usage of compile time informations about our models and the property types. Here is a list of the types that can be retrieved from compile time information for the key design:type. (The metadata will only be added if at least one decorator is present on a property)
Generic information is never available due to some serialization limitations at the time of writing.
Here is the rule how a table name is built ${kebabCase(modelName)}s
so for a model called Product the table will be named products, this is a default implementation.
There are two possibilities to change the name:
We do the mapping from javascript objects to dynamodb types for you in requests and responses
Simple Type (no decorators required to work)
Complex Types (properties with these types need some decorators to work properly)
TS Type | Dynamo Type |
---|---|
String | S |
Number | N |
Boolean | BOOL |
moment.Moment | S (ISO-8601 formatted) |
null | NULL |
Array | L, (S,N,B)S |
ES6 Set | L, (S,N,B)S |
Object | M |
--- | --- |
Binary | Not Supported |
ES6 Map | Not Supported |
Date | Not Supported |
It is always possible to define a custom mapping strategy, just implement the MapperForType class.
Javascript Arrays with a items of type String, Number or Binary will be mapped to a S(et) type, by default all other types are mapped to L(ist) type. If the items have a complex type it will be mapped to a L(ist).
An instance of ES6 Set type will be mapped to a S(et) type if the type of the items is supported (String, Number, Binary), otherwise it is mapped to a L(ist).
When one of the following decorators is present, the value is always mapped to a L(ist).
Right now we only support MomentJS Dates.
If you want to explicitly mark a property to be a Date use the @Date() decorator. If we find a moment value we automatically map it to a String (using ISO-8601 format). When coming from db we do a regex test for ISO-8601 format and map it back to a moment object.
Enum values are persisted as Numbers (index of enum).
To start making requests create an instance of DynamoStore and execute the desired operation using the provided api. We support the following dynamodb operations with a fluent api:
There is always the possibility to access the Params object directly to add values which are not covered with our api.
In a real world scenario you'll have some kind of authentication to protect your dynamodb ressources. You can customize on how to authenticate when providing a custom SessionValidityEnsurer function to the DynamoStore when creating a new instance. The default implementation is a no-op function.
Here is an example of an implementation using amazon cognito
function sessionValidityEnsurer(): Observable<boolean> {
return Observable.of(this.isLoggedIn())
.switchMap(isLoggedIn => {
if (isLoggedIn) {
this.logger.debug('withValidSession :: cognitoService.isLoggedIn() -> we have a valid session -> proceed')
return Observable.of(true)
} else {
this.logger.debug('withValidSession :: cognitoService.isLoggedIn() -> user is not logged in or token expired, try to get a new session')
return this.getUser()
.catch((err, caught): Observable<boolean> => {
this.logger.error('withValidSession :: there was an error when refreshing the session', err)
throw new AuthError('SC_UNAUTHENTICATED', 'Could not refresh the token' + JSON.stringify(err))
})
.do(user => this.logger.debug('withValidSession :: we got new valid session', user))
}
})
.map((value: boolean | CognitoUser) => {
return
})
}
By default we create a substitution placeholder for all the attributes, just to not implement a blacklist with reserved words in the context of aws dynamodb.
attributename: age
expression: '#age = :age'
attributeExpressionNames: {'#age': 'age'}
attributeExpressionValues: {':age': {N: '10'}}
this works seemlesly for top level attribtues, but if we wanna build an expression for where the attribute needs to be accessed with a document path, we need some special logic nested attribute: person.age
attributeExpressionNames: {'#person':'person', '#age': 'age'}
attributeExpressionValues: {':age': {N: '10'}}
expression: '#person.#age = :age'
we can't use #personAge as a placeholder for 'person.age' because if the dot is part of an attribute name it is not treated as a metacharacter compared to when using directly in expression, so the above solution needs to be used
these are the accessor rules for nested attribute types
TODO
There are two scenarios for a batch get item request. One is requesting multiple items from one table by id and the other is requesting multiple items by id from multiple tables. The first scenario is support using DynamoStore.batchGet() the second one must be implemented using the BatchGetItem class.
const request = new BatchRequest()
// table with simple primary key
request.forModel(MyModelClass, ['idValue', 'idValue2'])
// table with composite primary key (sortkey is optional)
request.forModel(MyOtherModelClass, [{partitionKey: 'id', sortKey: 'sortKeyValue'}])
request.exec().subscribe(response => {
// an object where the items are mapped to the table name
})
npm t
: Run test suitenpm start
: Runs npm run build
in watch modenpm run test:watch
: Run test suite in interactive watch modenpm run test:prod
: Run linting and generate coveragenpm run build
: Generage bundles and typings, create docsnpm run lint
: Lints codenpm run commit
: Commit using conventional commit style (husky will tell you to use it if you haven't :wink:)Use the npm comand npm run commit
, which is a convenient way to create conventional commits. Those messages are used to run semantic releases,
which publishes our code automatically on github and npm, plus generates automatically a changelog. This setup is highly influenced by Kent C. Dodds course on egghead.io
We use 2 git hooks:
precommit
prepush
npm run build
Made with :heart: by @michaelwittwer and all these wonderful contributors (emoji key):
Michael Wittwer 💻 📖 ⚠️ |
---|
This project follows the all-contributors specification. Contributions of any kind welcome!
FAQs
Use the power of typescript to define your object mapping when using dynamodb. This library also provides a fluent api for easy interaction with dynamodb.
The npm package dynamo-easy receives a total of 83 weekly downloads. As such, dynamo-easy popularity was classified as not popular.
We found that dynamo-easy demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket's Rust support is moving to Beta: all users can scan Cargo projects and generate SBOMs, including Cargo.toml-only crates, with Rust-aware supply chain checks.
Product
Socket Fix 2.0 brings targeted CVE remediation, smarter upgrade planning, and broader ecosystem support to help developers get to zero alerts.
Security News
Socket CEO Feross Aboukhadijeh joins Risky Business Weekly to unpack recent npm phishing attacks, their limited impact, and the risks if attackers get smarter.