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 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] = 2021-10-17
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] = 2021-10-20
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] = 2021-10-20
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
- - [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)
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-watch-all)
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
- - [Sub-Collection Entities](#sub-collection-entities)
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
- + [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)
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-set)
181
- - [Update Method: Remove](#update-method-remove)
182
- - [Update Method: Add](#update-method-add)
183
- - [Update Method: Subtract](#update-method-subtract)
184
- - [Update Method: Append](#update-method-append)
185
- - [Update Method: Delete](#update-method-delete)
186
- - [Update Method: Data](#update-method-data)
187
- + [Update Method: Complex Data Types](#update-method-complex-data-types)
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
- + [No Client Defined On Model](#no-client-defined-on-model)
209
- + [Invalid Identifier](#invalid-identifier)
210
- + [Invalid Key Composite Attribute Template](#invalid-key-composite-attribute-template)
211
- + [Duplicate Indexes](#duplicate-indexes)
212
- + [Collection Without An SK](#collection-without-an-sk)
213
- + [Duplicate Collections](#duplicate-collections)
214
- + [Missing Primary Index](#missing-primary-index)
215
- + [Invalid Attribute Definition](#invalid-attribute-definition)
216
- + [Invalid Model](#invalid-model)
217
- + [Invalid Options](#invalid-options)
218
- + [Duplicate Index Fields](#duplicate-index-fields)
219
- + [Duplicate Index Composite Attributes](#duplicate-index-composite-attributes)
220
- + [Incompatible Key Composite Attribute Template](#incompatible-key-composite-attribute-template)
221
- + [Invalid Index With Attribute Name](#invalid-index-with-attribute-name)
222
- + [Invalid Collection on Index With Attribute Field Names](#invalid-collection-on-index-with-attribute-field-names)
223
- + [Missing Composite Attributes](#missing-composite-attributes)
224
- + [Missing Table](#missing-table)
225
- + [Invalid Concurrency Option](#invalid-concurrency-option)
226
- + [aws-error](#aws-error)
227
- + [Unknown Errors](#unknown-errors)
228
- + [Invalid Last Evaluated Key](#invalid-last-evaluated-key)
229
- + [No Owner For Pager](#no-owner-for-pager)
230
- + [Pager Not Unique](#pager-not-unique)
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: () => uuidv4(),
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 indendently undefined because either attribute could have triggered this callback
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 indendently undefined because either attribute could have triggered this callback.
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 indendently undefined because either attribute could have triggered this callback
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 indendently undefined because either attribute could have triggered this callback
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 genericly named index fields that are separate from your business attributes._
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
- > **Note**: A `collection` name should be unique to a single common index across entities.
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 "JExpotic"
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
- colleciton: "assignments"
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
- colleciton: ["assignments"]
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
- > As of September 29th 2020 the `.page()` now returns the composite attributes that make up the `ExclusiveStartKey` instead of the `ExclusiveStartKey` itself. To get back only the `ExclusiveStartKey`, add the [query option](#query-options) `{pager: "raw"}` to your query options. If you treated this value opaquely no changes are needed, or if you used the `raw` flag.
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 Feburary 2021
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 convenience option for the query parameter `Limit`, used to specify the number of records to retrieve while performing a query.
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 value. Double-check the value you are providing is the value you expect to be passing, and that the value passes the tests listed above.
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
- ### aws-error
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, [AllTableIndexCompositeAttributes<A,F,C,S>[], ResponseItem<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.4.7",
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.1",
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.0",
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": {