Skip to content

Commit

Permalink
Merge pull request #777 from dynamoosejs/generalImprovements
Browse files Browse the repository at this point in the history
General improvements
  • Loading branch information
fishcharlie committed Apr 5, 2020
2 parents 87c0f54 + 92c23ee commit 0e58719
Show file tree
Hide file tree
Showing 18 changed files with 329 additions and 466 deletions.
7 changes: 6 additions & 1 deletion README.md
@@ -1,4 +1,4 @@
# Dynamoose [![Slack Chat](https://img.shields.io/badge/chat-on%20slack-informational.svg)](https://join.slack.com/t/dynamoose/shared_invite/enQtODM4OTI0MTc1NDc3LWI3MmNhMThmNmJmZDk5MmUxOTZmMGEwNGQzNTRkMjhjZGJlNGM5M2JmZjMzMzlkODRhMGY3MTQ5YjQ2Nzg3YTY) [![Twitter Follow](https://img.shields.io/twitter/follow/dynamoosejs?style=social)](https://twitter.com/DynamooseJS) [![CI](https://github.com/dynamoosejs/dynamoose/workflows/CI/badge.svg)](https://github.com/dynamoosejs/dynamoose/actions) [![Coverage Status](https://coveralls.io/repos/github/dynamoosejs/dynamoose/badge.svg?branch=master)](https://coveralls.io/github/dynamoosejs/dynamoose?branch=master)
# Dynamoose [![npm](https://img.shields.io/npm/v/dynamoose)](https://www.npmjs.com/package/dynamoose) [![npm (beta)](https://img.shields.io/npm/v/dynamoose/beta)](https://www.npmjs.com/package/dynamoose/v/beta) [![License](https://img.shields.io/github/license/dynamoosejs/dynamoose)](https://github.com/dynamoosejs/dynamoose/blob/master/LICENSE) [![npm Downloads](https://img.shields.io/npm/dw/dynamoose)](https://www.npmjs.com/package/dynamoose) [![CI](https://github.com/dynamoosejs/dynamoose/workflows/CI/badge.svg)](https://github.com/dynamoosejs/dynamoose/actions) [![Coverage Status](https://coveralls.io/repos/github/dynamoosejs/dynamoose/badge.svg?branch=master)](https://coveralls.io/github/dynamoosejs/dynamoose?branch=master) [![Slack Chat](https://img.shields.io/badge/chat-on%20slack-informational.svg)](https://join.slack.com/t/dynamoose/shared_invite/enQtODM4OTI0MTc1NDc3LWI3MmNhMThmNmJmZDk5MmUxOTZmMGEwNGQzNTRkMjhjZGJlNGM5M2JmZjMzMzlkODRhMGY3MTQ5YjQ2Nzg3YTY) [![Contact](https://img.shields.io/badge/contact-me-blue)](https://charlie.fish/contact) [![Twitter](https://img.shields.io/twitter/follow/dynamoosejs?style=social)](https://twitter.com/DynamooseJS)

# Dynamoose Version 2.0 is still In Development. Please [contact me](https://charlie.fish/contact) with any feedback or questions.

Expand All @@ -12,3 +12,8 @@ Dynamoose is a modeling tool for Amazon's DynamoDB (inspired by [Mongoose](http:
```sh
$ npm i dynamoose@beta
```

## Documentation

- [v2](https://github.com/dynamoosejs/dynamoose/tree/master/docs)
- [v1](https://dynamoosejs.com)
22 changes: 13 additions & 9 deletions docs/api/Condition.md
Expand Up @@ -35,18 +35,22 @@ new dynamoose.Condition().where("id").eq(1).or().where("name").eq("Bob"); // id

This function sets the condition to use the opposite comparison type for the given condition. You can find the list opposite comparison types below.

- equals (EQ) - not equals (NE)
- less than or equals (LE) - greater than (GT)
- less than (LT) - greater than or equals (GE)
- null (NULL) - not null (NOT_NULL)
- contains (CONTAINS) - not contains (NOT_CONTAINS)
- exists (EXISTS) - not exists (NOT_EXISTS)
| Original | Opposite |
|---|---|
| equals (EQ) | not equals (NE) |
| less than or equals (LE) | greater than (GT) |
| less than (LT) | greater than or equals (GE) |
| null (NULL) | not null (NOT_NULL) |
| contains (CONTAINS) | not contains (NOT_CONTAINS) |
| exists (EXISTS) | not exists (NOT_EXISTS) |

The following comparisons do not have an opposite comparison type, and will throw an error if you try to use condition.not() with them.

- in (IN)
- between (BETWEEN)
- begins with (BEGINS_WITH)
| Original |
|---|
| in (IN) |
| between (BETWEEN) |
| begins with (BEGINS_WITH) |

```js
new dynamoose.Condition().where("id").not().eq(1); // Retrieve all objects where id does NOT equal 1
Expand Down
6 changes: 4 additions & 2 deletions docs/api/Document.md
Expand Up @@ -24,8 +24,10 @@ This method returns a promise that will resolve when the operation is complete,

You can also pass a settings object in as the first parameter. The following options are available for settings are:

- `overwrite` (default: true) - If an existing document with the same hash key should be overwritten in the database. You can set this to false to not overwrite an existing document with the same hash key.
- `return` (default: `document`) - If the function should return the `document` or `request`. If you set this to `request` the request that would be made to DynamoDB will be returned, but no requests will be made to DynamoDB.
| Name | Type | Default | Notes |
|---|---|---|---|
| overwrite | boolean | true | If an existing document with the same hash key should be overwritten in the database. You can set this to false to not overwrite an existing document with the same hash key. |
| return | string | `document` | If the function should return the `document` or `request`. If you set this to `request` the request that would be made to DynamoDB will be returned, but no requests will be made to DynamoDB. |

Both `settings` and `callback` parameters are optional. You can pass in a `callback` without `settings`, just by passing in one argument and having that argument be the `callback`. You are not required to pass in `settings` if you just want to pass in a `callback`.

Expand Down
4 changes: 3 additions & 1 deletion docs/api/Model.md
Expand Up @@ -357,7 +357,9 @@ This method returns a promise that will resolve when the operation is complete,

You can also pass a settings object in as the second parameter. The following options are available for settings are:

- `return` (default: `response`) - If the function should return the `response` or `request`. If you set this to `request` the request that would be made to DynamoDB will be returned, but no requests will be made to DynamoDB.
| Name | Description | Type | Default |
|------|-------------|------|---------|
| return | If the function should return the `response` or `request`. If you set this to `request` the request that would be made to DynamoDB will be returned, but no requests will be made to DynamoDB. | String | `response` |

Both `settings` and `callback` parameters are optional. You can pass in a `callback` without `settings`, just by passing in your array of objects as the first parameter, and the second argument as the `callback` function. You are not required to pass in `settings` if you just want to pass in a `callback`.

Expand Down
59 changes: 52 additions & 7 deletions docs/api/Schema.md
Expand Up @@ -6,8 +6,10 @@ You can use this method to create a schema. The `schema` parameter is an object

The `options` parameter is an optional object with the following options:

- `saveUnknown` array | boolean (default: false) - This setting lets you specify if the schema should allow properties not defined in the schema. If you pass `true` in for this option all unknown properties will be allowed. If you pass in an array of strings, only properties that are included in that array will be allowed. If you pass in an array of strings, you can use `*` to indicate a wildcard nested property one level deep, or `**` to indicate a wildcard nested property infinite levels deep. If you retrieve items from DynamoDB with `saveUnknown` enabled, all custom Dynamoose types will be returned as the underlying DynamoDB type (ex. Dates will be returned as a Number representing number of milliseconds since Jan 1 1970).
- `timestamps` boolean | object (default: false) - This setting lets you indicate to Dynamoose that you would like it to handle storing timestamps in your documents for both creation and most recent update times. If you pass in an object for this setting you must specify two keys `createdAt` & `updatedAt`, each with a value of a string being the name of the attribute for each timestamp. If you pass in `null` for either of those keys that specific timestamp won't be added to the schema. If you set this option to `true` it will use the default attribute names of `createdAt` & `updatedAt`.
| Name | Type | Default | Information
|---|---|---|---|
| `saveUnknown` | array \| boolean | false | This setting lets you specify if the schema should allow properties not defined in the schema. If you pass `true` in for this option all unknown properties will be allowed. If you pass in an array of strings, only properties that are included in that array will be allowed. If you pass in an array of strings, you can use `*` to indicate a wildcard nested property one level deep, or `**` to indicate a wildcard nested property infinite levels deep. If you retrieve items from DynamoDB with `saveUnknown` enabled, all custom Dynamoose types will be returned as the underlying DynamoDB type (ex. Dates will be returned as a Number representing number of milliseconds since Jan 1 1970).
| `timestamps` | boolean \| object | false | This setting lets you indicate to Dynamoose that you would like it to handle storing timestamps in your documents for both creation and most recent update times. If you pass in an object for this setting you must specify two keys `createdAt` & `updatedAt`, each with a value of a string being the name of the attribute for each timestamp. If you pass in `null` for either of those keys that specific timestamp won't be added to the schema. If you set this option to `true` it will use the default attribute names of `createdAt` & `updatedAt`.

```js
const schema = new dynamoose.Schema({
Expand Down Expand Up @@ -317,11 +319,14 @@ You can define indexes on properties to be created or updated upon model initial

Your index object can contain the following properties:

- name: string - Name of index (default: `${attribute}${global ? "GlobalIndex" : "LocalIndex"}`)
- global: boolean - If the index should be a global secondary index or not. Attribute will be the hash key for the index. (default: `false`)
- rangeKey: string - The range key attribute name for a global secondary index. (default: undefined)
- project: boolean | [string] - Sets the attributes to be projected for the index. `true` projects all attributes, `false` projects only the key attributes, and an array of strings projects the attributes listed. (default: `true`)
- throughput: number | {read: number, write: number} - Sets the throughput for the global secondary index. (default: undefined)
| Name | Type | Default | Notes |
|---|---|---|---|
| name | string | `${attribute}${global ? "GlobalIndex" : "LocalIndex"}` | Name of index |
| global | boolean | false | If the index should be a global secondary index or not. Attribute will be the hash key for the index. |
| rangeKey | string | undefined | The range key attribute name for a global secondary index. |
| project | boolean \| [string] | true | Sets the attributes to be projected for the index. `true` projects all attributes, `false` projects only the key attributes, and an array of strings projects the attributes listed. |
| throughput | number \| {read: number, write: number} | undefined | Sets the throughput for the global secondary index. |


If you set `index` to `true`, it will create an index with all of the default settings.

Expand All @@ -336,3 +341,43 @@ If you set `index` to `true`, it will create an index with all of the default se
}
}
```

```js
{
"email": {
"type": String,
"index": {
"name": "emailIndex",
"throughput": {"read": 5, "write": 10}
} // creates a global index with the name `emailIndex`
}
}
```

### hashKey: boolean

You can set this to true to overwrite what the `hashKey` for the Model will be. By default the `hashKey` will be the first key in the Schema object.

```js
{
"id": String,
"key": {
"type": String,
"hashKey": true
}
}
```

### rangeKey: boolean

You can set this to true to overwrite what the `rangeKey` for the Model will be. By default the `rangeKey` won't exist.

```js
{
"id": String,
"email": {
"type": String,
"rangeKey": true
}
}
```
46 changes: 13 additions & 33 deletions lib/Condition.js
Expand Up @@ -30,36 +30,16 @@ class Condition {
}


const notComparisonTypes = (() => {
const obj = {
"EQ": "NE",
"IN": null,
"LE": "GT",
"LT": "GE",
"BETWEEN": null,
"CONTAINS": "NOT_CONTAINS",
"EXISTS": "NOT_EXISTS",
"BEGINS_WITH": null
};
Object.keys(obj).forEach((key) => {
const val = obj[key];
if (val) {
obj[val] = key;
} else {
obj[val] = null;
}
});
return obj;
})();

function finalizePending(instance) {
const pending = instance.settings.pending;

if (pending.not === true) {
if (notComparisonTypes[pending.type] === null) {
throw new Error.InvalidFilterComparison(`${pending.type} can not follow not()`);
if (!pending.type.not) {
throw new Error.InvalidFilterComparison(`${pending.type.typeName} can not follow not()`);
}
pending.type = notComparisonTypes[pending.type];
pending.type = pending.type.not;
} else {
pending.type = pending.type.typeName;
}

instance.settings.conditions.push([pending.key, {
Expand Down Expand Up @@ -89,21 +69,21 @@ Condition.prototype.where = Condition.prototype.filter = Condition.prototype.att
return this;
};
const types = [
{"name": "eq", "typeName": "EQ"},
{"name": "lt", "typeName": "LT"},
{"name": "le", "typeName": "LE"},
{"name": "gt", "typeName": "GT"},
{"name": "ge", "typeName": "GE"},
{"name": "eq", "typeName": "EQ", "not": "NE"},
{"name": "lt", "typeName": "LT", "not": "GE"},
{"name": "le", "typeName": "LE", "not": "GT"},
{"name": "gt", "typeName": "GT", "not": "LE"},
{"name": "ge", "typeName": "GE", "not": "LT"},
{"name": "beginsWith", "typeName": "BEGINS_WITH"},
{"name": "contains", "typeName": "CONTAINS"},
{"name": "exists", "typeName": "EXISTS"},
{"name": "contains", "typeName": "CONTAINS", "not": "NOT_CONTAINS"},
{"name": "exists", "typeName": "EXISTS", "not": "NOT_EXISTS"},
{"name": "in", "typeName": "IN"},
{"name": "between", "typeName": "BETWEEN", "multipleArguments": true}
];
types.forEach((type) => {
Condition.prototype[type.name] = function(value) {
this.settings.pending.value = type.value || (type.multipleArguments ? [...arguments] : value);
this.settings.pending.type = type.typeName;
this.settings.pending.type = type;
finalizePending(this);
return this;
};
Expand Down

0 comments on commit 0e58719

Please sign in to comment.