electrodb 1.4.7 → 1.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -4
- package/README.md +151 -61
- package/index.d.ts +41 -1
- package/package.json +6 -3
- package/src/entity.js +177 -47
- package/src/errors.js +104 -8
- package/src/schema.js +101 -50
- package/tsconfig.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -98,17 +98,44 @@ All notable changes to this project will be documented in this file. Breaking ch
|
|
|
98
98
|
### Patched
|
|
99
99
|
- Updates did not include composite attributes involved in primary index. Though these values cannot be changed, they should be `set` on update method calls in case the update results in an item insert. [[read more]](./README.md#updates-to-composite-attributes)
|
|
100
100
|
|
|
101
|
-
## [1.4.5]
|
|
101
|
+
## [1.4.5] - 2021-10-17
|
|
102
102
|
### Fixed
|
|
103
103
|
- Improved .npmignore to remove playground oriented files, and created official directory to keep playground in sync with library changes.
|
|
104
104
|
|
|
105
|
-
## [1.4.6]
|
|
105
|
+
## [1.4.6] - 2021-10-20
|
|
106
106
|
### Added, Fixed
|
|
107
107
|
- Adding Entity identifiers to all update operations. When primary index composite attributes were added in 1.4.4, entities were written properly but did not include the identifiers. This resulted in entities being written but not being readable without the query option `ignoreOwnership` being used.
|
|
108
108
|
|
|
109
|
-
## [1.4.7]
|
|
109
|
+
## [1.4.7] - 2021-10-20
|
|
110
110
|
### Changed
|
|
111
111
|
- Using `add()` update mutation now resolves to `ADD #prop :prop` update expression instead of a `SET #prop = #prop + :prop`
|
|
112
112
|
|
|
113
113
|
### Fixed
|
|
114
|
-
- Fixed param naming conflict during updates, when map attribute shares a name with another (separate) attribute.
|
|
114
|
+
- Fixed param naming conflict during updates, when map attribute shares a name with another (separate) attribute.
|
|
115
|
+
|
|
116
|
+
## [1.4.8] - 2021-11-01
|
|
117
|
+
### Fixed
|
|
118
|
+
- Addressed issue#90 to flip batchGet's response tuple type definition.
|
|
119
|
+
|
|
120
|
+
## [1.5.0] - 2021-11-07
|
|
121
|
+
### Changed
|
|
122
|
+
- Queries will now fully paginate all responses. Prior to this change, ElectroDB would only return items from a single ElectroDB query result. Now ElectroDB will paginate through all query results. This will impact both uses of entity queries and service collections. [[read more](./README.md#query-method)]
|
|
123
|
+
- The query option `limit` has an extended meaning with the change to automatically paginate records on query. The option `limit` now represents a target for the number of items to return from DynamoDB. If this option is passed, Queries on entities and through collections will paginate DynamoDB until this limit is reached or all items for that query have been returned. [[read more](./README.md#query-options)]
|
|
124
|
+
|
|
125
|
+
### Added
|
|
126
|
+
- A new query option `pages` has been added to coincide with the change to automatically paginate all records when queried. The `pages` option sets a max number of pagination iterations ElectroDB will perform on a query. When this option is paired with `limit`, ElectroDB will respect the first condition reached. [[read more](./README.md#query-options)]
|
|
127
|
+
|
|
128
|
+
## [1.6.0] - 2021-11-21
|
|
129
|
+
### Added
|
|
130
|
+
- Exporting TypeScript interfaces for `ElectroError` and `ElectroValidationError`
|
|
131
|
+
- Errors thrown within an attribute's validate callback are now wrapped and accessible after being thrown. Prior to this change, only the `message` of the error thrown by a validation function was persisted back through to the user, now the error itself is also accessible. Reference the exported interface typedef for `ElectroValidationError` [here](./index.d.ts) to see the new properties available on a thrown validation error.
|
|
132
|
+
|
|
133
|
+
### Changed
|
|
134
|
+
- As a byproduct of enhancing validation errors, the format of message text on a validation error has changed. This could be breaking if your app had a hardcoded dependency on the exact text of a thrown validation error.
|
|
135
|
+
|
|
136
|
+
### Fixed
|
|
137
|
+
- For Set attributes, the callback functions `get`, `set`, and `validate` are now consistently given an Array of values. These functions would sometimes (incorrectly) be called with a DynamoDB DocClient Set.
|
|
138
|
+
|
|
139
|
+
## [1.6.1] - 2021-12-05
|
|
140
|
+
### Fixed
|
|
141
|
+
- In some cases the `find()` and `match()` methods would incorrectly select an index without a complete partition key. This would result in validation exceptions preventing the user from querying if an index definition and provided attribute object aligned improperly. This was fixed and a slightly more robust mechanism for ranking indexes was made.
|
package/README.md
CHANGED
|
@@ -107,11 +107,11 @@ tasks
|
|
|
107
107
|
* [TypeScript Support](#typescript-support)
|
|
108
108
|
+ [TypeScript Services](#typescript-services)
|
|
109
109
|
* [Join](#join)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
110
|
+
- [Independent Models](#independent-models)
|
|
111
|
+
- [Joining Entity instances to a Service](#joining-entity-instances-to-a-service)
|
|
112
|
+
- [Joining models to a Service](#joining-models-to-a-service)
|
|
113
|
+
- [Joining Entities or Models with an alias](#joining-entities-or-models-with-an-alias)
|
|
114
|
+
- [Joining Entities at Service construction for TypeScript](#joining-entities-at-service-construction-for-typescript)
|
|
115
115
|
* [Model](#model)
|
|
116
116
|
+ [Model Properties](#model-properties)
|
|
117
117
|
+ [Service Options](#service-options)
|
|
@@ -125,7 +125,7 @@ tasks
|
|
|
125
125
|
- [Set Attributes](#set-attributes)
|
|
126
126
|
- [Attribute Getters and Setters](#attribute-getters-and-setters)
|
|
127
127
|
- [Attribute Watching](#attribute-watching)
|
|
128
|
-
* [Attribute Watching: Watch All](#attribute-watching
|
|
128
|
+
* [Attribute Watching: Watch All](#attribute-watching--watch-all)
|
|
129
129
|
* [Attribute Watching Examples](#attribute-watching-examples)
|
|
130
130
|
- [Calculated Attributes](#calculated-attributes)
|
|
131
131
|
- [Virtual Attributes](#virtual-attributes)
|
|
@@ -147,7 +147,7 @@ tasks
|
|
|
147
147
|
+ [Collection Queries vs Entity Queries](#collection-queries-vs-entity-queries)
|
|
148
148
|
+ [Collection Response Structure](#collection-response-structure)
|
|
149
149
|
* [Sub-Collections](#sub-collections)
|
|
150
|
-
|
|
150
|
+
- [Sub-Collection Entities](#sub-collection-entities)
|
|
151
151
|
* [Index and Collection Naming Conventions](#index-and-collection-naming-conventions)
|
|
152
152
|
+ [Index Naming Conventions](#index-naming-conventions)
|
|
153
153
|
* [Collection Naming Conventions](#collection-naming-conventions)
|
|
@@ -163,12 +163,13 @@ tasks
|
|
|
163
163
|
+ [Multiple Where Clauses](#multiple-where-clauses)
|
|
164
164
|
* [Parse](#parse)
|
|
165
165
|
- [Building Queries](#building-queries)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
166
|
+
+ [Using composite attributes to make hierarchical keys](#using-composite-attributes-to-make-hierarchical-keys)
|
|
167
|
+
- [Shopping Mall Stores](#shopping-mall-stores)
|
|
168
|
+
+ [Query App Records](#query-app-records)
|
|
169
|
+
- [Partition Key Composite Attributes](#partition-key-composite-attributes)
|
|
170
|
+
+ [Sort Key Operations](#sort-key-operations)
|
|
171
171
|
* [Query Chains](#query-chains)
|
|
172
|
+
+ [Query Method](#query-method)
|
|
172
173
|
+ [Get Method](#get-method)
|
|
173
174
|
+ [Batch Get](#batch-get)
|
|
174
175
|
+ [Delete Method](#delete-method)
|
|
@@ -177,14 +178,14 @@ tasks
|
|
|
177
178
|
+ [Batch Write Put Records](#batch-write-put-records)
|
|
178
179
|
+ [Update Record](#update-record)
|
|
179
180
|
- [Updates to Composite Attributes](#updates-to-composite-attributes)
|
|
180
|
-
- [Update Method: Set](#update-method
|
|
181
|
-
- [Update Method: Remove](#update-method
|
|
182
|
-
- [Update Method: Add](#update-method
|
|
183
|
-
- [Update Method: Subtract](#update-method
|
|
184
|
-
- [Update Method: Append](#update-method
|
|
185
|
-
- [Update Method: Delete](#update-method
|
|
186
|
-
- [Update Method: Data](#update-method
|
|
187
|
-
+ [Update Method: Complex Data Types](#update-method
|
|
181
|
+
- [Update Method: Set](#update-method--set)
|
|
182
|
+
- [Update Method: Remove](#update-method--remove)
|
|
183
|
+
- [Update Method: Add](#update-method--add)
|
|
184
|
+
- [Update Method: Subtract](#update-method--subtract)
|
|
185
|
+
- [Update Method: Append](#update-method--append)
|
|
186
|
+
- [Update Method: Delete](#update-method--delete)
|
|
187
|
+
- [Update Method: Data](#update-method--data)
|
|
188
|
+
+ [Update Method: Complex Data Types](#update-method--complex-data-types)
|
|
188
189
|
+ [Scan Records](#scan-records)
|
|
189
190
|
+ [Remove Method](#remove-method)
|
|
190
191
|
+ [Patch Record](#patch-record)
|
|
@@ -204,30 +205,33 @@ tasks
|
|
|
204
205
|
* [Pagination Example](#pagination-example)
|
|
205
206
|
* [Query Examples](#query-examples)
|
|
206
207
|
* [Query Options](#query-options)
|
|
207
|
-
- [Errors:](#errors)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
208
|
+
- [Errors:](#errors-)
|
|
209
|
+
+ [No Client Defined On Model](#no-client-defined-on-model)
|
|
210
|
+
+ [Invalid Identifier](#invalid-identifier)
|
|
211
|
+
+ [Invalid Key Composite Attribute Template](#invalid-key-composite-attribute-template)
|
|
212
|
+
+ [Duplicate Indexes](#duplicate-indexes)
|
|
213
|
+
+ [Collection Without An SK](#collection-without-an-sk)
|
|
214
|
+
+ [Duplicate Collections](#duplicate-collections)
|
|
215
|
+
+ [Missing Primary Index](#missing-primary-index)
|
|
216
|
+
+ [Invalid Attribute Definition](#invalid-attribute-definition)
|
|
217
|
+
+ [Invalid Model](#invalid-model)
|
|
218
|
+
+ [Invalid Options](#invalid-options)
|
|
219
|
+
+ [Duplicate Index Fields](#duplicate-index-fields)
|
|
220
|
+
+ [Duplicate Index Composite Attributes](#duplicate-index-composite-attributes)
|
|
221
|
+
+ [Incompatible Key Composite Attribute Template](#incompatible-key-composite-attribute-template)
|
|
222
|
+
+ [Invalid Index With Attribute Name](#invalid-index-with-attribute-name)
|
|
223
|
+
+ [Invalid Collection on Index With Attribute Field Names](#invalid-collection-on-index-with-attribute-field-names)
|
|
224
|
+
+ [Missing Composite Attributes](#missing-composite-attributes)
|
|
225
|
+
+ [Missing Table](#missing-table)
|
|
226
|
+
+ [Invalid Concurrency Option](#invalid-concurrency-option)
|
|
227
|
+
+ [Invalid Pages Option](#invalid-pages-option)
|
|
228
|
+
+ [Invalid Limit Option](#invalid-limit-option)
|
|
229
|
+
+ [Invalid Attribute](#invalid-attribute)
|
|
230
|
+
+ [AWS Error](#aws-error)
|
|
231
|
+
+ [Unknown Errors](#unknown-errors)
|
|
232
|
+
+ [Invalid Last Evaluated Key](#invalid-last-evaluated-key)
|
|
233
|
+
+ [No Owner For Pager](#no-owner-for-pager)
|
|
234
|
+
+ [Pager Not Unique](#pager-not-unique)
|
|
231
235
|
- [Examples](#examples)
|
|
232
236
|
* [Employee App](#employee-app)
|
|
233
237
|
+ [Employee App Requirements](#employee-app-requirements)
|
|
@@ -565,7 +569,7 @@ const TasksModel = {
|
|
|
565
569
|
attributes: {
|
|
566
570
|
task: {
|
|
567
571
|
type: "string",
|
|
568
|
-
default: () =>
|
|
572
|
+
default: () => uuid(),
|
|
569
573
|
},
|
|
570
574
|
project: {
|
|
571
575
|
type: "string",
|
|
@@ -815,11 +819,11 @@ myAttr: {
|
|
|
815
819
|
watch: ["otherAttr"],
|
|
816
820
|
set: (myAttr, {otherAttr}) => {
|
|
817
821
|
// Whenever "myAttr" or "otherAttr" are updated from an `update` or `patch` operation, this callback will be fired.
|
|
818
|
-
// Note: myAttr or otherAttr could be
|
|
822
|
+
// Note: myAttr or otherAttr could be independently undefined because either attribute could have triggered this callback
|
|
819
823
|
},
|
|
820
824
|
get: (myAttr, {otherAttr}) => {
|
|
821
825
|
// Whenever "myAttr" or "otherAttr" are retrieved from a `query` or `get` operation, this callback will be fired.
|
|
822
|
-
// Note: myAttr or otherAttr could be
|
|
826
|
+
// Note: myAttr or otherAttr could be independently undefined because either attribute could have triggered this callback.
|
|
823
827
|
}
|
|
824
828
|
}
|
|
825
829
|
```
|
|
@@ -833,11 +837,11 @@ myAttr: {
|
|
|
833
837
|
watch: "*", // "watch all"
|
|
834
838
|
set: (myAttr, allAttributes) => {
|
|
835
839
|
// Whenever an `update` or `patch` operation is performed, this callback will be fired.
|
|
836
|
-
// Note: myAttr or the attributes under `allAttributes` could be
|
|
840
|
+
// Note: myAttr or the attributes under `allAttributes` could be independently undefined because either attribute could have triggered this callback
|
|
837
841
|
},
|
|
838
842
|
get: (myAttr, allAttributes) => {
|
|
839
843
|
// Whenever a `query` or `get` operation is performed, this callback will be fired.
|
|
840
|
-
// Note: myAttr or the attributes under `allAttributes` could be
|
|
844
|
+
// Note: myAttr or the attributes under `allAttributes` could be independently undefined because either attribute could have triggered this callback
|
|
841
845
|
}
|
|
842
846
|
}
|
|
843
847
|
```
|
|
@@ -1417,7 +1421,7 @@ As described in the above two sections ([Composite Attributes](#composite-attrib
|
|
|
1417
1421
|
|
|
1418
1422
|
It may be the case that an index field is also an attribute. For example, if a table was created with a Primary Index partition key of `accountId`, and that same field is used to store the `accountId` value used by the application. The following are a few examples of how to model that schema with ElectroDB:
|
|
1419
1423
|
|
|
1420
|
-
> _NOTE: If you have the unique opportunity to use ElectroDB with a new project, it is strongly recommended to use
|
|
1424
|
+
> _NOTE: If you have the unique opportunity to use ElectroDB with a new project, it is strongly recommended to use generically named index fields that are separate from your business attributes._
|
|
1421
1425
|
|
|
1422
1426
|
**Using `composite`**
|
|
1423
1427
|
|
|
@@ -1564,9 +1568,11 @@ name: "your_item_name"
|
|
|
1564
1568
|
## Collections
|
|
1565
1569
|
A Collection is a grouping of Entities with the same Partition Key and allows you to make efficient query across multiple entities. If your background is SQL, imagine Partition Keys as Foreign Keys, a Collection represents a View with multiple joined Entities.
|
|
1566
1570
|
|
|
1571
|
+
> _NOTE: ElectroDB Collections use DynamoDB queries to retrieve results. One query is made to retrieve results for all Entities (the benefits of single table design), however like the [query method](#query-method), ElectroDB will paginate through all results for a given query._
|
|
1572
|
+
|
|
1567
1573
|
Collections are defined on an Index, and the name of the collection should represent what the query would return as a pseudo `Entity`. Additionally, Collection names must be unique across a `Service`.
|
|
1568
1574
|
|
|
1569
|
-
>
|
|
1575
|
+
> _NOTE: A `collection` name should be unique to a single common index across entities._
|
|
1570
1576
|
|
|
1571
1577
|
```javascript
|
|
1572
1578
|
const DynamoDB = require("aws-sdk/clients/dynamodb");
|
|
@@ -1756,7 +1762,7 @@ let results = await TaskApp.collections
|
|
|
1756
1762
|
|
|
1757
1763
|
{
|
|
1758
1764
|
tasks: [...], // tasks for employeeId "JExotic"
|
|
1759
|
-
employees: [...] // employee record(s) with employeeId "
|
|
1765
|
+
employees: [...] // employee record(s) with employeeId "JExotic"
|
|
1760
1766
|
}
|
|
1761
1767
|
```
|
|
1762
1768
|
|
|
@@ -1771,7 +1777,7 @@ The following is an example of functionally identical collections, implemented a
|
|
|
1771
1777
|
**As a string (collection):**
|
|
1772
1778
|
```typescript
|
|
1773
1779
|
{
|
|
1774
|
-
|
|
1780
|
+
collection: "assignments"
|
|
1775
1781
|
pk: {
|
|
1776
1782
|
field: "pk",
|
|
1777
1783
|
composite: ["employeeId"]
|
|
@@ -1786,7 +1792,7 @@ The following is an example of functionally identical collections, implemented a
|
|
|
1786
1792
|
**As a string array (sub-collections):**
|
|
1787
1793
|
```typescript
|
|
1788
1794
|
{
|
|
1789
|
-
|
|
1795
|
+
collection: ["assignments"]
|
|
1790
1796
|
pk: {
|
|
1791
1797
|
field: "pk",
|
|
1792
1798
|
composite: ["employeeId"]
|
|
@@ -2600,6 +2606,10 @@ Option | Default | Notes
|
|
|
2600
2606
|
# Building Queries
|
|
2601
2607
|
> For hands-on learners: the following example can be followed along with **and** executed on runkit: https://runkit.com/tywalch/electrodb-building-queries
|
|
2602
2608
|
|
|
2609
|
+
ElectroDB queries use DynamoDB's `query` method to find records based on your table's indexes.
|
|
2610
|
+
|
|
2611
|
+
> _NOTE: By default, ElectroDB will paginate through all items that match your query. To limit the number of items ElectroDB will retrieve, read more about the [Query Options](#query-options) `pages` and `limit`, or use the ElectroDB [Pagination API](#page) for fine-grain pagination support._
|
|
2612
|
+
|
|
2603
2613
|
Forming a composite **Partition Key** and **Sort Key** is a critical step in planning **Access Patterns** in **DynamoDB**. When planning composite keys, it is crucial to consider the order in which they are *composed*. As of the time of writing this documentation, **DynamoDB** has the following constraints that should be taken into account when planning your **Access Patterns**:
|
|
2604
2614
|
1. You must always supply the **Partition Key** in full for all queries to **DynamoDB**.
|
|
2605
2615
|
2. You currently only have the following operators available on a **Sort Key**: `begins_with`, `between`, `>`, `>=`, `<`, `<=`, and `Equals`.
|
|
@@ -2806,6 +2816,12 @@ Queries in ***ElectroDB*** are built around the **Access Patterns** defined in t
|
|
|
2806
2816
|
|
|
2807
2817
|
The methods: Get (`get`), Create (`put`), Update (`update`), and Delete (`delete`) **require* all composite attributes described in the Entities' primary `PK` and `SK`.
|
|
2808
2818
|
|
|
2819
|
+
### Query Method
|
|
2820
|
+
|
|
2821
|
+
ElectroDB queries use DynamoDB's `query` method to find records based on your table's indexes. To read more about queries checkout the section [Building Queries](#building-queries)
|
|
2822
|
+
|
|
2823
|
+
> _NOTE: By default, ElectroDB will paginate through all items that match your query. To limit the number of items ElectroDB will retrieve, read more about the [Query Options](#query-options) `pages` and `limit`, or use the ElectroDB [Pagination API](#page) for fine-grain pagination support._
|
|
2824
|
+
|
|
2809
2825
|
### Get Method
|
|
2810
2826
|
Provide all Table Index composite attributes in an object to the `get` method. In the event no record is found, a value of `null` will be returned.
|
|
2811
2827
|
|
|
@@ -3704,6 +3720,8 @@ DynamoDB offers three methods to query records: `get`, `query`, and `scan`. In *
|
|
|
3704
3720
|
|
|
3705
3721
|
> _NOTE: The Find method is similar to the Match method with one exception: The attributes you supply directly to the `.find()` method will only be used to identify and fulfill your index access patterns. Any values supplied that do not contribute to a composite key will not be applied as query filters. Furthermore, if the values you provide do not resolve to an index access pattern, then a table scan will be performed. Use the `where()` chain method to further filter beyond keys, or use [Match](#match-records) for the convenience of automatic filtering based on the values given directly to that method._
|
|
3706
3722
|
|
|
3723
|
+
The Find method is useful when the index chosen does not matter or is not known. If your secondary indexes do not contain all attributes then this method might not be right for you. The mechanism that picks the best index for a given payload is subject to improvement and change without triggering a breaking change release version.
|
|
3724
|
+
|
|
3707
3725
|
```javascript
|
|
3708
3726
|
await StoreLocations.find({
|
|
3709
3727
|
mallId: "EastPointe",
|
|
@@ -3734,8 +3752,11 @@ await StoreLocations.find({
|
|
|
3734
3752
|
|
|
3735
3753
|
Match is a convenience method based off of ElectroDB's [find](#find-records) method. Similar to Find, Match does not require you to provide keys, but under the covers it will leverage the attributes provided to choose the best index to query on.
|
|
3736
3754
|
|
|
3755
|
+
> _NOTE: The Math method is useful when the index chosen does not matter or is not known. If your secondary indexes do not contain all attributes then this method might not be right for you. The mechanism that picks the best index for a given payload is subject to improvement and change without triggering a breaking change release version.
|
|
3756
|
+
|
|
3737
3757
|
Match differs from [Find](#find-records) in that it will also include all supplied values into a query filter.
|
|
3738
3758
|
|
|
3759
|
+
|
|
3739
3760
|
```javascript
|
|
3740
3761
|
await StoreLocations.find({
|
|
3741
3762
|
mallId: "EastPointe",
|
|
@@ -4032,7 +4053,7 @@ let stores = MallStores.query
|
|
|
4032
4053
|
|
|
4033
4054
|
### Page
|
|
4034
4055
|
|
|
4035
|
-
>
|
|
4056
|
+
> _NOTE: By Default, ElectroDB queries will paginate through all results with the [`go()`](#building-queries) method. ElectroDB's `page()` method can be used to manually iterate through DynamoDB query results._
|
|
4036
4057
|
|
|
4037
4058
|
The `page` method _ends_ a query chain, and asynchronously queries DynamoDB with the `client` provided in the model. Unlike the `.go()`, the `.page()` method returns a tuple.
|
|
4038
4059
|
|
|
@@ -4093,6 +4114,9 @@ let [pageTwo, moreStores] = await MallStores.query
|
|
|
4093
4114
|
```
|
|
4094
4115
|
|
|
4095
4116
|
#### Service Pagination
|
|
4117
|
+
|
|
4118
|
+
> _NOTE: By Default, ElectroDB will paginate through all results with the [`query()`](#building-queries) method. ElectroDB's `page()` method can be used to manually iterate through DynamoDB query results._
|
|
4119
|
+
|
|
4096
4120
|
Pagination with services is also possible. Similar to [Entity Pagination](#entity-pagination), calling the `.page()` method returns a `[pager, results]` tuple. Also, similar to pagination on Entities, the pager object returned by default is a deconstruction of the returned LastEvaluatedKey.
|
|
4097
4121
|
|
|
4098
4122
|
#### Pager Query Options
|
|
@@ -4209,7 +4233,7 @@ await StoreLocations.query.leases({storeId}).gte({leaseEndDate: "2020-03"}).go()
|
|
|
4209
4233
|
// Lease Agreements by StoreId before 2021
|
|
4210
4234
|
await StoreLocations.query.leases({storeId}).lt({leaseEndDate: "2021-01"}).go()
|
|
4211
4235
|
|
|
4212
|
-
// Lease Agreements by StoreId before
|
|
4236
|
+
// Lease Agreements by StoreId before February 2021
|
|
4213
4237
|
await StoreLocations.query.leases({storeId}).lte({leaseEndDate: "2021-02"}).go()
|
|
4214
4238
|
|
|
4215
4239
|
// Lease Agreements by StoreId between 2010 and 2020
|
|
@@ -4261,6 +4285,7 @@ By default, **ElectroDB** enables you to work with records as the names and prop
|
|
|
4261
4285
|
response?: "default" | "none" | "all_old" | "updated_old" | "all_new" | "updated_new";
|
|
4262
4286
|
ignoreOwnership?: boolean;
|
|
4263
4287
|
limit?: number;
|
|
4288
|
+
pages?: number;
|
|
4264
4289
|
};
|
|
4265
4290
|
```
|
|
4266
4291
|
|
|
@@ -4276,7 +4301,8 @@ concurrent | `1` | When performing batch operations, how m
|
|
|
4276
4301
|
unprocessed | `"item"` | Used in batch processing to override ElectroDBs default behaviour to break apart DynamoDBs `Unprocessed` records into composite attributes. See more detail about this in the sections for [BatchGet](#batch-get), [BatchDelete](#batch-write-delete-records), and [BatchPut](#batch-write-put-records).
|
|
4277
4302
|
response | `"default"` | Used as a convenience for applying the DynamoDB parameter `ReturnValues`. The options here are the same as the parameter values for the DocumentClient except lowercase. The `"none"` option will cause the method to return null and will bypass ElectroDB's response formatting -- useful if formatting performance is a concern.
|
|
4278
4303
|
ignoreOwnership | `false` | By default, **ElectroDB** interrogates items returned from a query for the presence of matching entity "identifiers". This helps to ensure other entities, or other versions of an entity, are filtered from your results. If you are using ElectroDB with an existing table/dataset you can turn off this feature by setting this property to `true`.
|
|
4279
|
-
limit | _none_ | A
|
|
4304
|
+
limit | _none_ | A target for the number of items to return from DynamoDB. If this option is passed, Queries on entities and through collections will paginate DynamoDB until this limit is reached or all items for that query have been returned.
|
|
4305
|
+
pages | ∞ | How many DynamoDB pages should a query iterate through before stopping. By default ElectroDB paginate through all results for your query.
|
|
4280
4306
|
|
|
4281
4307
|
# Errors:
|
|
4282
4308
|
|
|
@@ -4531,12 +4557,77 @@ Tables can be defined on the [Service Options](#service-options) object when you
|
|
|
4531
4557
|
*Code: 2004*
|
|
4532
4558
|
|
|
4533
4559
|
*Why this occurred:*
|
|
4534
|
-
When performing a bulk operation ([Batch Get](#batch-get), [Batch Delete Records](#batch-write-delete-records), [Batch Put Records](#batch-write-put-records)) you can pass a [Query Options](#query-options) called `concurrent`, which impacts how many batch requests can occur at the same time. Your value pass the test of both, `!isNaN(parseInt(value))` and `parseInt(value) > 0`.
|
|
4560
|
+
When performing a bulk operation ([Batch Get](#batch-get), [Batch Delete Records](#batch-write-delete-records), [Batch Put Records](#batch-write-put-records)) you can pass a [Query Options](#query-options) called `concurrent`, which impacts how many batch requests can occur at the same time. Your value should pass the test of both, `!isNaN(parseInt(value))` and `parseInt(value) > 0`.
|
|
4535
4561
|
|
|
4536
4562
|
*What to do about it:*
|
|
4537
|
-
Expect this error only if you're providing a concurrency
|
|
4563
|
+
Expect this error only if you're providing a `concurrency` option. Double-check the value you are providing is the value you expect to be passing, and that the value passes the tests listed above.
|
|
4564
|
+
|
|
4565
|
+
### Invalid Pages Option
|
|
4566
|
+
*Code: 2005*
|
|
4567
|
+
|
|
4568
|
+
*Why this occurred:*
|
|
4569
|
+
When performing a query [Query](#building-queries) you can pass a [Query Options](#query-options) called `pages`, which impacts how many DynamoDB pages a query should iterate through. Your value should pass the test of both, `!isNaN(parseInt(value))` and `parseInt(value) > 0`.
|
|
4570
|
+
|
|
4571
|
+
*What to do about it:*
|
|
4572
|
+
Expect this error only if you're providing a `pages` option. Double-check the value you are providing is the value you expect to be passing, and that the value passes the tests listed above.
|
|
4573
|
+
|
|
4574
|
+
### Invalid Limit Option
|
|
4575
|
+
*Code: 2006*
|
|
4576
|
+
|
|
4577
|
+
*Why this occurred:*
|
|
4578
|
+
When performing a query [Query](#building-queries) you can pass a [Query Options](#query-options) called `limit`, which impacts how many DynamoDB items a query should return. Your value should pass the test of both, `!isNaN(parseInt(value))` and `parseInt(value) > 0`.
|
|
4579
|
+
|
|
4580
|
+
*What to do about it:*
|
|
4581
|
+
Expect this error only if you're providing a `limit` option. Double-check the value you are providing is the value you expect to be passing, and that the value passes the tests listed above.
|
|
4582
|
+
|
|
4583
|
+
### Invalid Attribute
|
|
4584
|
+
*Code: 3001*
|
|
4585
|
+
|
|
4586
|
+
*Why this occurred:*
|
|
4587
|
+
The value received for a validation either failed type expectations (e.g. a "number" instead of a "string"), or the user provided "validate" callback on an attribute rejected a value.
|
|
4588
|
+
|
|
4589
|
+
*What to do about it:*
|
|
4590
|
+
Examine the error itself for more precise detail on why the failure occurred. The error object itself should have a property called "fields" which contains an array of every attribute that failed validation, and a reason for each. If the failure originated from a "validate" callback, the originally thrown error will be accessible via the `cause` property the corresponding element within the fields array.1
|
|
4591
|
+
|
|
4592
|
+
Below is the type definition for an ElectroValidationError:
|
|
4593
|
+
|
|
4594
|
+
```typescript
|
|
4595
|
+
ElectroValidationError<T extends Error = Error> extends ElectroError {
|
|
4596
|
+
readonly name: "ElectroValidationError"
|
|
4597
|
+
readonly code: number;
|
|
4598
|
+
readonly date: number;
|
|
4599
|
+
readonly isElectroError: boolean;
|
|
4600
|
+
ref: {
|
|
4601
|
+
readonly code: number;
|
|
4602
|
+
readonly section: string;
|
|
4603
|
+
readonly name: string;
|
|
4604
|
+
readonly sym: unique symbol;
|
|
4605
|
+
}
|
|
4606
|
+
readonly fields: ReadonlyArray<{
|
|
4607
|
+
/**
|
|
4608
|
+
* The json path to the attribute that had a validation error
|
|
4609
|
+
*/
|
|
4610
|
+
readonly field: string;
|
|
4611
|
+
|
|
4612
|
+
/**
|
|
4613
|
+
* A description of the validation error for that attribute
|
|
4614
|
+
*/
|
|
4615
|
+
readonly reason: string;
|
|
4616
|
+
|
|
4617
|
+
/**
|
|
4618
|
+
* Index of the value passed (present only in List attribute validation errors)
|
|
4619
|
+
*/
|
|
4620
|
+
readonly index: number | undefined;
|
|
4621
|
+
|
|
4622
|
+
/**
|
|
4623
|
+
* The error thrown from the attribute's validate callback (if applicable)
|
|
4624
|
+
*/
|
|
4625
|
+
readonly cause: T | undefined;
|
|
4626
|
+
}>
|
|
4627
|
+
}
|
|
4628
|
+
```
|
|
4538
4629
|
|
|
4539
|
-
###
|
|
4630
|
+
### AWS Error
|
|
4540
4631
|
*Code: 4001*
|
|
4541
4632
|
|
|
4542
4633
|
*Why this occurred:*
|
|
@@ -5462,4 +5553,3 @@ This change stems from the fact the `facets` is already a defined term in the Dy
|
|
|
5462
5553
|
|
|
5463
5554
|
# Coming Soon
|
|
5464
5555
|
- Default query options defined on the `model` to give more general control of interactions with the Entity.
|
|
5465
|
-
- Complex attributes (list, map, set)
|
package/index.d.ts
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
declare const WhereSymbol: unique symbol;
|
|
2
2
|
declare const UpdateDataSymbol: unique symbol;
|
|
3
3
|
|
|
4
|
+
export interface ElectroError extends Error {
|
|
5
|
+
readonly name: 'ElectroError';
|
|
6
|
+
readonly code: number;
|
|
7
|
+
readonly date: number;
|
|
8
|
+
readonly isElectroError: boolean;
|
|
9
|
+
ref: {
|
|
10
|
+
readonly code: number;
|
|
11
|
+
readonly section: string;
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly sym: unique symbol;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
interface ElectroValidationErrorFieldReference<T extends Error = Error> {
|
|
18
|
+
/**
|
|
19
|
+
* The json path to the attribute that had a validation error
|
|
20
|
+
*/
|
|
21
|
+
readonly field: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A description of the validation error for that attribute
|
|
25
|
+
*/
|
|
26
|
+
readonly reason: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Index of the value passed (present only in List attribute validation errors)
|
|
30
|
+
*/
|
|
31
|
+
readonly index: number | undefined;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The error thrown from the attribute's validate callback (if applicable)
|
|
35
|
+
*/
|
|
36
|
+
readonly cause: T | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface ElectroValidationError<T extends Error = Error> extends ElectroError {
|
|
40
|
+
readonly fields: ReadonlyArray<ElectroValidationErrorFieldReference<T>>;
|
|
41
|
+
}
|
|
42
|
+
|
|
4
43
|
interface ReadOnlyAttribute {
|
|
5
44
|
readonly readOnly: true;
|
|
6
45
|
}
|
|
@@ -933,6 +972,7 @@ interface QueryOptions {
|
|
|
933
972
|
includeKeys?: boolean;
|
|
934
973
|
originalErr?: boolean;
|
|
935
974
|
ignoreOwnership?: boolean;
|
|
975
|
+
pages?: number;
|
|
936
976
|
}
|
|
937
977
|
|
|
938
978
|
// subset of QueryOptions
|
|
@@ -1103,7 +1143,7 @@ export class Entity<A extends string, F extends A, C extends string, S extends S
|
|
|
1103
1143
|
readonly schema: S;
|
|
1104
1144
|
constructor(schema: S, config?: EntityConfiguration);
|
|
1105
1145
|
get(key: AllTableIndexCompositeAttributes<A,F,C,S>): SingleRecordOperationOptions<A,F,C,S, ResponseItem<A,F,C,S> | null>;
|
|
1106
|
-
get(key: AllTableIndexCompositeAttributes<A,F,C,S>[]): BulkRecordOperationOptions<A,F,C,S, [
|
|
1146
|
+
get(key: AllTableIndexCompositeAttributes<A,F,C,S>[]): BulkRecordOperationOptions<A,F,C,S, [Array<ResponseItem<A,F,C,S>>, Array<AllTableIndexCompositeAttributes<A,F,C,S>>]>;
|
|
1107
1147
|
delete(key: AllTableIndexCompositeAttributes<A,F,C,S>): DeleteRecordOperationOptions<A,F,C,S, ResponseItem<A,F,C,S>>;
|
|
1108
1148
|
delete(key: AllTableIndexCompositeAttributes<A,F,C,S>[]): BulkRecordOperationOptions<A,F,C,S, AllTableIndexCompositeAttributes<A,F,C,S>[]>;
|
|
1109
1149
|
remove(key: AllTableIndexCompositeAttributes<A,F,C,S>): DeleteRecordOperationOptions<A,F,C,S, ResponseItem<A,F,C,S>>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electrodb",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"homepage": "https://github.com/tywalch/electrodb#readme",
|
|
27
27
|
"devDependencies": {
|
|
28
|
-
"@istanbuljs/nyc-config-typescript": "^1.0.
|
|
28
|
+
"@istanbuljs/nyc-config-typescript": "^1.0.2",
|
|
29
29
|
"@types/chai": "^4.2.12",
|
|
30
30
|
"@types/mocha": "^8.0.3",
|
|
31
31
|
"@types/node": "^15.6.0",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"aws-sdk": "2.630.0",
|
|
34
34
|
"browserify": "^17.0.0",
|
|
35
35
|
"chai": "4.2.0",
|
|
36
|
-
"coveralls": "^3.1.
|
|
36
|
+
"coveralls": "^3.1.1",
|
|
37
37
|
"istanbul": "0.4.5",
|
|
38
38
|
"jest": "25.4.0",
|
|
39
39
|
"mocha": "7.1.1",
|
|
@@ -50,6 +50,9 @@
|
|
|
50
50
|
"electrodb",
|
|
51
51
|
"dynamo",
|
|
52
52
|
"dynamodb",
|
|
53
|
+
"nosql",
|
|
54
|
+
"single table design",
|
|
55
|
+
"typescript",
|
|
53
56
|
"aws"
|
|
54
57
|
],
|
|
55
58
|
"tsd": {
|