electrodb 2.2.3 → 2.2.4

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/README.md CHANGED
@@ -3419,6 +3419,8 @@ operation | example | result
3419
3419
  `value` | `value(rent, amount)` | `:rent1` | Create a reference to a particular value, can be passed to other operation that allows leveraging existing attribute values in calculating new values
3420
3420
  `ifNotExists` | `ifNotExists(rent, amount)` | `#rent = if_not_exists(#rent, :rent0)` | Update a property's value only if that property doesn't yet exist on the record
3421
3421
 
3422
+ > _NOTE: Usage of `name` and `value` operations allow for some escape hatching in the case that a custom operation needs to be expressed. When used however, ElectroDB loses the context necessary to validate the expression created by the user. In practical terms, this means the `validation` function/regex on the impacted attribute will not be called._
3423
+
3422
3424
  Example:
3423
3425
  ```javascript
3424
3426
  await StoreLocations
@@ -5688,6 +5690,8 @@ const person = new Entity({
5688
5690
  }, { table });
5689
5691
  ```
5690
5692
 
5693
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=3&ssc=29&pln=37&pc=2#code/JYWwDg9gTgLgBAbzgUQHY2DAngGjgYQFcBnGCEAQRhimACNCYBTAFSzCbgF84AzKcnADkTADZMAxjQgATOkIDcAKCUSIqUnACqqYAEdCTANJMsAZSwg6EUQC44hXQc7FL10XAC8cC1ZsAKAEplbA4UcFEILCYmAEkAES84UlpUAHM4ADJEAG0dfUMTczcbAF17AENULC5lVXVNfOcKNKZfd3tHApcSj292gOClUM4AWXUYAAsk1EIrJigs3KbDFrbe8rgqmrqRuAAFBeJ1VDEAJRtObwQlODu4EfsRCKiYxVv70grYeIrmexSwHSynucCYqBkv2YAH4ATQgWllDwAD6ID53R7CNToKAVKTQd6g7E0PEwMwwb4wKFMOGpRHouDE3FSNCQv405Lw4FKWoqbGaCl0cRJIQAd2gAGswKI8UwAPqC8TveoaeAcKDHVAzJiilDoTBYfw3UEgWRiezG0H3cEYbBPdWa06iIQ4Bmg4gLABuwAkHLFkulspdbvunqOwHUTwAjEIGVxXaC-vCGMxiBaQ3cmC9onEZOmrQWHuwOURSOQqMnGKxiwAeZDZmIJAB8-iEgPSQkCGe4CcLWelrwW+cLoMxba5aVjI-j3d4wA1MAAchUQBzLSOMcWnu3J72N3AoEwDPOmHmHlBDHurTORzLSMvV8P92Od8H93dD8fD2eaJfuzfCwqVonw3MdZnmKAp0LACCyAuJUHGdBJjTNF3zgUU-gkSZ7ByIQ4KEUorxHTFSzIShqFoFNqw4GtEKmFshHAugFk7IjCw9GB7CCLwm0QGCNxkJheAqQhRE4uBuM8XiEH4kdWnE-w5XsOjJjwBA4K4C04PsJiFi4QIeNQtD7kPGBCCgLVRj+SYADpeEiaB-DguAAHo4CjAAmIY0K4f82I-S4QOIrcCBIMiK0oqs2Bow4NROc5LgY7ZWP-OMryBQSAA8mBQ9crUPNQoDPPKRzACUgvfOcxDPIQyrfYy7jUcAIGITAOVw-tIhzSDSm7UFZPY8qjIaqrRBq4gJXqhqmsgVr-jgDqG1zAj-OvVL+p5NSHgqIVOH0up+XgCRD3ZWIZCSIJ7HrAccwSQy8tM8ytQAAwAEgQakbNQCBRSCLhnq2Yhwhuxt4iRFQHXUBkbOOph2SNbsXLc4gOAkYAKg8CAwAqZw4GAc6Rm7TrBzO+xYdOmQglW4nuqefYqkICQ0aB-ZgAALzZiopqtOcFwfP19kmYBRGAMBudBO8lxXP0ADEoCwcX7m0uAPIAVlWgRxAqgsxxpt5VvdCkfnZaMAE5TYAdgAWgABg8q2PNNxWC3BNl5qEKNzdNq3PKtgBmGNVt8-qu1BGy0ggIJoamcF-EPYhRPgKThqtJGDyYMyLKLDggYx448fAUlT27ePE5smQ-gqGy4NiBCJmQuNAiAA)
5694
+
5691
5695
  ### Opaque Keys
5692
5696
  If you use Opaque Keys for identifiers or other primitive types, you can use the function `CustomAttributeType` and pass it the primitive base type of your key ('string', 'number', 'boolean'). This can be useful to gain more precise control over which properties can be used as entity identifiers, create unique unit types, etc.
5693
5697
 
@@ -5739,6 +5743,8 @@ const person = new Entity({
5739
5743
  }, { table });
5740
5744
  ```
5741
5745
 
5746
+ [![Try it out!](https://img.shields.io/badge/electrodb-try_out_this_example_›-%23f9bd00?style=for-the-badge&logo=amazondynamodb&labelColor=1a212a)](https://electrodb.fun/?ssl=3&ssc=29&pln=37&pc=2#code/JYWwDg9gTgLgBAbzgUQHY2DAngGjgYQFcBnGCEAQRhimACNCYBTAFSzCbgF84AzKcnADkTADZMAxjQgATOkIDcAKCUSIqUnACqqYAEdCTANJMsAZSwg6EUQC44hXQc7FL10XAC8cC1ZsAKAEplbA4UcFEILCYmAEkAES84UlpUAHM4ADJEAG0dfUMTczcbAF17AENULC5lVXVNfOcKNKZfd3tHApcSj292gOClUM4AWXUYAAsk1EIrJigs3KbDFrbe8rgqmrqRuAAFBeJ1VDEAJRtObwQlODu4EfsRCKiYxVv70grYeIrmexSwHSynucCYqBkv2YAH4ATQgWllDwAD6ID53R7CNToKAVKTQd6g7E0PEwMwwb4wKFMOGpRHouDE3FSNCQv405Lw4FKWoqbGaCl0cRJIQAd2gAGswKI8UwAPqC8TveoaeAcKDHVAzJiilDoTBYfw3UEgWRiezG0H3cEYbBPdWa06iIQ4Bmg4gLABuwAkHLFkulspdbvunqOwHUTwAjEIGVxXaC-vCGMxiBaQ3cmC9onEZOmrQWHuwOURSOQqMnGKxiwAeZDZmIJAB8-iEgPSQkCGe4CcLWelrwW+cLoMxba5aVjI-j3d4wA1MAAchUQBzLSOMcWnu3J72N3AoEwDPOmHmHlBDHurTORzLSMvV8P92Od8H93dD8fD2eaJfuzfCwqVonw3MdZnmKAp0LACCyAuJUHGdBJjTNF3zgUU-gkSZ7ByIQ4KEUorxHTFSzIShqFoFNqw4GtEKmFshHAugFk7IjCw9GB7CCLwm0QGCNxkJheAqQhRE4uBuM8XiEH4kdWnE-w5XsOjJjwBA4K4C04PsJiFi4QIeNQtD7kPGBCCgLVRj+SYADpeEiaB-DguAAHo4CjAAmIY0K4f82I-S4QOIrcCBIMiK0oqs2Bow4NROc5LgY7ZWP-OMryBQSAA8mBQ9crUPNQoDPPKRzACUgvfOcxDPIQyrfYy7jUcAIGITAOVw-tIhzSDSm7UFZPY8qjIaqrRBq4gJXqhqmsgVr-jgDqG1zAj-OvVL+p5NSHgqIVOH0up+XgCRD3ZWIZCSIJ7HrAccwSQy8tM8ytQAAwAEgQakbNQCBRSCLhnq2Yhwhuxt4iRFQHXUBkbOOph2SNbsXLc4gOAkYAKg8CAwAqZw4GAc6Rm7TrBzO+xYdOmQglW4nuqefYqkICQ0aB-ZgAALzZiopqtOcFwfP19kmYBRGAMBudBO8lxXP0ADEoCwcX7m0uAPIAVlWgRxAqgsxxpt5VvdCkfnZaMAE5TYAdgAWgABg8q2PNNxWC3BNl5qEKNzdNq3PKtgBmGNVt8-qu1BGy0ggIJoamcF-EPYhRPgKThqtJGDyYMyLKLDggYx448fAUlT27ePE5smQ-gqGy4NiBCJmQuNAiAA)
5747
+
5742
5748
  ## Exported Types
5743
5749
 
5744
5750
  The following types are exported for easier use while using ElectroDB with TypeScript. The naming convention for the types include three different kinds:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrodb",
3
- "version": "2.2.3",
3
+ "version": "2.2.4",
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": {
package/src/clauses.js CHANGED
@@ -309,7 +309,16 @@ let clauses = {
309
309
  for (const path of Object.keys(state.query.update.refs)) {
310
310
  const operation = state.query.update.impacted[path];
311
311
  const attribute = state.query.update.refs[path];
312
- entity.model.schema.checkOperation(attribute, operation);
312
+ // note: keyValue will be empty if the user used `name`/`value` operations
313
+ // because it becomes hard to know how they are used and which attribute
314
+ // should validate the change. This is an edge case however, this change
315
+ // still improves on the existing implementation.
316
+ const keyValue = state.query.update.paths[path] || {};
317
+ if (!attribute) {
318
+ throw new e.ElectroAttributeValidationError(path, `Attribute "${path}" does not exist on model.`);
319
+ }
320
+
321
+ entity.model.schema.checkOperation(attribute, operation, keyValue.value);
313
322
  }
314
323
  return state;
315
324
  } catch(err) {
package/src/entity.js CHANGED
@@ -229,7 +229,7 @@ class Entity {
229
229
  if (Array.isArray(facets)) {
230
230
  return this._makeChain(index, this._clausesWithFilters, clauses.index).batchGet(facets);
231
231
  } else {
232
- return this._makeChain(index, clauses, clauses.index).get(facets);
232
+ return this._makeChain(index, this._clausesWithFilters, clauses.index).get(facets);
233
233
  }
234
234
  }
235
235
 
package/src/filters.js CHANGED
@@ -16,6 +16,7 @@ class FilterFactory {
16
16
  case MethodTypes.update:
17
17
  case MethodTypes.patch:
18
18
  case MethodTypes.delete:
19
+ case MethodTypes.get:
19
20
  return ExpressionTypes.ConditionExpression
20
21
  default:
21
22
  return ExpressionTypes.FilterExpression
package/src/schema.js CHANGED
@@ -1,4 +1,4 @@
1
- const { CastTypes, ValueTypes, KeyCasing, AttributeTypes, AttributeMutationMethods, AttributeWildCard, PathTypes, TableIndex } = require("./types");
1
+ const { CastTypes, ValueTypes, KeyCasing, AttributeTypes, AttributeMutationMethods, AttributeWildCard, PathTypes, TableIndex, ItemOperations } = require("./types");
2
2
  const AttributeTypeNames = Object.keys(AttributeTypes);
3
3
  const ValidFacetTypes = [AttributeTypes.string, AttributeTypes.number, AttributeTypes.boolean, AttributeTypes.enum];
4
4
  const e = require("./errors");
@@ -1389,16 +1389,6 @@ class Schema {
1389
1389
  return record;
1390
1390
  }
1391
1391
 
1392
- checkOperation(attribute, operation) {
1393
- if (!attribute) {
1394
- throw new e.ElectroAttributeValidationError(path, `Attribute "${path}" does not exist on model.`);
1395
- } else if (attribute.required && operation === 'remove') {
1396
- throw new e.ElectroAttributeValidationError(attribute.path, `Attribute "${attribute.path}" is Required and cannot be removed`);
1397
- } else if (attribute.readOnly) {
1398
- throw new e.ElectroAttributeValidationError(attribute.path, `Attribute "${attribute.path}" is Read-Only and cannot be updated`);
1399
- }
1400
- }
1401
-
1402
1392
  checkRemove(paths = []) {
1403
1393
  for (const path of paths) {
1404
1394
  const attribute = this.traverser.getPath(path);
@@ -1413,6 +1403,18 @@ class Schema {
1413
1403
  return paths;
1414
1404
  }
1415
1405
 
1406
+ checkOperation(attribute, operation, value) {
1407
+ if (attribute.required && operation === ItemOperations.remove) {
1408
+ throw new e.ElectroAttributeValidationError(attribute.path, `Attribute "${attribute.path}" is Required and cannot be removed`);
1409
+ } else if (attribute.readOnly) {
1410
+ throw new e.ElectroAttributeValidationError(attribute.path, `Attribute "${attribute.path}" is Read-Only and cannot be updated`);
1411
+ }
1412
+
1413
+ return value === undefined
1414
+ ? undefined
1415
+ : attribute.getValidate(value);
1416
+ }
1417
+
1416
1418
  checkUpdate(payload = {}) {
1417
1419
  let record = {};
1418
1420
  for (let [path, attribute] of this.traverser.getAll()) {
package/src/where.js CHANGED
@@ -74,6 +74,7 @@ class WhereFactory {
74
74
  case MethodTypes.patch:
75
75
  case MethodTypes.delete:
76
76
  case MethodTypes.remove:
77
+ case MethodTypes.get:
77
78
  return ExpressionTypes.ConditionExpression
78
79
  default:
79
80
  return ExpressionTypes.FilterExpression