electrodb 1.4.6 → 1.4.7

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
@@ -104,4 +104,11 @@ All notable changes to this project will be documented in this file. Breaking ch
104
104
 
105
105
  ## [1.4.6] = 2021-10-20
106
106
  ### Added, Fixed
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.
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
+
109
+ ## [1.4.7] = 2021-10-20
110
+ ### Changed
111
+ - Using `add()` update mutation now resolves to `ADD #prop :prop` update expression instead of a `SET #prop = #prop + :prop`
112
+
113
+ ### Fixed
114
+ - Fixed param naming conflict during updates, when map attribute shares a name with another (separate) attribute.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electrodb",
3
- "version": "1.4.6",
3
+ "version": "1.4.7",
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": {
@@ -11,7 +11,8 @@
11
11
  "test-types": "node ./node_modules/tsd/dist/cli.js",
12
12
  "coverage": "nyc npm run test-all && nyc report --reporter=text-lcov | coveralls",
13
13
  "coverage-coveralls-local": "nyc npm run test-all-local && nyc report --reporter=text-lcov | coveralls",
14
- "coverage-html-local": "nyc npm run test-all-local && nyc report --reporter=html"
14
+ "coverage-html-local": "nyc npm run test-all-local && nyc report --reporter=html",
15
+ "build:browser": "browserify playground/browser.js -o playground/bundle.js"
15
16
  },
16
17
  "repository": {
17
18
  "type": "git",
@@ -30,6 +31,7 @@
30
31
  "@types/node": "^15.6.0",
31
32
  "@types/uuid": "^8.3.0",
32
33
  "aws-sdk": "2.630.0",
34
+ "browserify": "^17.0.0",
33
35
  "chai": "4.2.0",
34
36
  "coveralls": "^3.1.0",
35
37
  "istanbul": "0.4.5",
package/src/filters.js CHANGED
@@ -39,7 +39,7 @@ class FilterFactory {
39
39
  );
40
40
  }
41
41
  }
42
- let expression = template(attribute, prop, ...attrValues);
42
+ let expression = template({}, attribute, prop, ...attrValues);
43
43
  return expression.trim();
44
44
  };
45
45
  },
package/src/operations.js CHANGED
@@ -4,7 +4,7 @@ const v = require("./util");
4
4
 
5
5
  const deleteOperations = {
6
6
  canNest: false,
7
- template: function del(attr, path, value) {
7
+ template: function del(options, attr, path, value) {
8
8
  let operation = "";
9
9
  let expression = "";
10
10
  switch(attr.type) {
@@ -23,19 +23,19 @@ const deleteOperations = {
23
23
  const UpdateOperations = {
24
24
  name: {
25
25
  canNest: true,
26
- template: function name(attr, path) {
26
+ template: function name(options, attr, path) {
27
27
  return path;
28
28
  }
29
29
  },
30
30
  value: {
31
31
  canNest: true,
32
- template: function value(attr, path, value) {
32
+ template: function value(options, attr, path, value) {
33
33
  return value;
34
34
  }
35
35
  },
36
36
  append: {
37
37
  canNest: false,
38
- template: function append(attr, path, value) {
38
+ template: function append(options, attr, path, value) {
39
39
  let operation = "";
40
40
  let expression = "";
41
41
  switch(attr.type) {
@@ -52,7 +52,7 @@ const UpdateOperations = {
52
52
  },
53
53
  add: {
54
54
  canNest: false,
55
- template: function add(attr, path, value) {
55
+ template: function add(options, attr, path, value) {
56
56
  let operation = "";
57
57
  let expression = "";
58
58
  switch(attr.type) {
@@ -62,8 +62,13 @@ const UpdateOperations = {
62
62
  expression = `${path} ${value}`;
63
63
  break;
64
64
  case AttributeTypes.number:
65
- operation = ItemOperations.set;
66
- expression = `${path} = ${path} + ${value}`;
65
+ if (options.nestedValue) {
66
+ operation = ItemOperations.set;
67
+ expression = `${path} = ${path} + ${value}`;
68
+ } else {
69
+ operation = ItemOperations.add;
70
+ expression = `${path} ${value}`;
71
+ }
67
72
  break;
68
73
  default:
69
74
  throw new Error(`Invalid Update Attribute Operation: "ADD" Operation can only be performed on attributes with type "number", "set", or "any".`);
@@ -73,7 +78,7 @@ const UpdateOperations = {
73
78
  },
74
79
  subtract: {
75
80
  canNest: false,
76
- template: function subtract(attr, path, value) {
81
+ template: function subtract(options, attr, path, value) {
77
82
  let operation = "";
78
83
  let expression = "";
79
84
  switch(attr.type) {
@@ -91,7 +96,7 @@ const UpdateOperations = {
91
96
  },
92
97
  set: {
93
98
  canNest: false,
94
- template: function set(attr, path, value) {
99
+ template: function set(options, attr, path, value) {
95
100
  let operation = "";
96
101
  let expression = "";
97
102
  switch(attr.type) {
@@ -114,7 +119,7 @@ const UpdateOperations = {
114
119
  },
115
120
  remove: {
116
121
  canNest: false,
117
- template: function remove(attr, ...paths) {
122
+ template: function remove(options, attr, ...paths) {
118
123
  let operation = "";
119
124
  let expression = "";
120
125
  switch(attr.type) {
@@ -142,86 +147,86 @@ const UpdateOperations = {
142
147
 
143
148
  const FilterOperations = {
144
149
  ne: {
145
- template: function eq(attr, name, value) {
150
+ template: function eq(options, attr, name, value) {
146
151
  return `${name} <> ${value}`;
147
152
  },
148
153
  strict: false,
149
154
  },
150
155
  eq: {
151
- template: function eq(attr, name, value) {
156
+ template: function eq(options, attr, name, value) {
152
157
  return `${name} = ${value}`;
153
158
  },
154
159
  strict: false,
155
160
  },
156
161
  gt: {
157
- template: function gt(attr, name, value) {
162
+ template: function gt(options, attr, name, value) {
158
163
  return `${name} > ${value}`;
159
164
  },
160
165
  strict: false
161
166
  },
162
167
  lt: {
163
- template: function lt(attr, name, value) {
168
+ template: function lt(options, attr, name, value) {
164
169
  return `${name} < ${value}`;
165
170
  },
166
171
  strict: false
167
172
  },
168
173
  gte: {
169
- template: function gte(attr, name, value) {
174
+ template: function gte(options, attr, name, value) {
170
175
  return `${name} >= ${value}`;
171
176
  },
172
177
  strict: false
173
178
  },
174
179
  lte: {
175
- template: function lte(attr, name, value) {
180
+ template: function lte(options, attr, name, value) {
176
181
  return `${name} <= ${value}`;
177
182
  },
178
183
  strict: false
179
184
  },
180
185
  between: {
181
- template: function between(attr, name, value1, value2) {
186
+ template: function between(options, attr, name, value1, value2) {
182
187
  return `(${name} between ${value1} and ${value2})`;
183
188
  },
184
189
  strict: false
185
190
  },
186
191
  begins: {
187
- template: function begins(attr, name, value) {
192
+ template: function begins(options, attr, name, value) {
188
193
  return `begins_with(${name}, ${value})`;
189
194
  },
190
195
  strict: false
191
196
  },
192
197
  exists: {
193
- template: function exists(attr, name) {
198
+ template: function exists(options, attr, name) {
194
199
  return `attribute_exists(${name})`;
195
200
  },
196
201
  strict: false
197
202
  },
198
203
  notExists: {
199
- template: function notExists(attr, name) {
204
+ template: function notExists(options, attr, name) {
200
205
  return `attribute_not_exists(${name})`;
201
206
  },
202
207
  strict: false
203
208
  },
204
209
  contains: {
205
- template: function contains(attr, name, value) {
210
+ template: function contains(options, attr, name, value) {
206
211
  return `contains(${name}, ${value})`;
207
212
  },
208
213
  strict: false
209
214
  },
210
215
  notContains: {
211
- template: function notContains(attr, name, value) {
216
+ template: function notContains(options, attr, name, value) {
212
217
  return `not contains(${name}, ${value})`;
213
218
  },
214
219
  strict: false
215
220
  },
216
221
  value: {
217
- template: function(attr, name, value) {
222
+ template: function(options, attr, name, value) {
218
223
  return value;
219
224
  },
220
225
  strict: false,
221
226
  canNest: true,
222
227
  },
223
228
  name: {
224
- template: function(attr, name) {
229
+ template: function(options, attr, name) {
225
230
  return name;
226
231
  },
227
232
  strict: false,
@@ -230,7 +235,7 @@ const FilterOperations = {
230
235
  };
231
236
 
232
237
  class ExpressionState {
233
- constructor({prefix, singleOccurrence} = {}) {
238
+ constructor({prefix} = {}) {
234
239
  this.names = {};
235
240
  this.values = {};
236
241
  this.paths = {};
@@ -238,13 +243,9 @@ class ExpressionState {
238
243
  this.impacted = {};
239
244
  this.expression = "";
240
245
  this.prefix = prefix || "";
241
- this.singleOccurrence = singleOccurrence;
242
246
  }
243
247
 
244
248
  incrementName(name) {
245
- if (this.singleOccurrence) {
246
- return `${this.prefix}${0}`
247
- }
248
249
  if (this.counts[name] === undefined) {
249
250
  this.counts[name] = 0;
250
251
  }
@@ -372,12 +373,14 @@ class AttributeOperationProxy {
372
373
  if (property.__is_clause__ === AttributeProxySymbol) {
373
374
  const {paths, root, target} = property();
374
375
  const attributeValues = [];
376
+ let hasNestedValue = false;
375
377
  for (let value of values) {
376
378
  value = target.format(value);
377
379
  // template.length is to see if function takes value argument
378
- if (template.length > 2) {
380
+ if (template.length > 3) {
379
381
  if (seen.has(value)) {
380
382
  attributeValues.push(value);
383
+ hasNestedValue = true;
381
384
  } else {
382
385
  let attributeValueName = builder.setValue(target.name, value);
383
386
  builder.setPath(paths.json, {value, name: attributeValueName});
@@ -386,7 +389,11 @@ class AttributeOperationProxy {
386
389
  }
387
390
  }
388
391
 
389
- const formatted = template(target, paths.expression, ...attributeValues);
392
+ const options = {
393
+ nestedValue: hasNestedValue
394
+ }
395
+
396
+ const formatted = template(options, target, paths.expression, ...attributeValues);
390
397
  builder.setImpacted(operation, paths.json);
391
398
  if (canNest) {
392
399
  seen.add(paths.expression);
package/src/update.js CHANGED
@@ -3,7 +3,7 @@ const {ItemOperations, BuilderTypes} = require("./types");
3
3
 
4
4
  class UpdateExpression extends ExpressionState {
5
5
  constructor(props = {}) {
6
- super({...props, singleOccurrence: true});
6
+ super({...props});
7
7
  this.operations = {
8
8
  set: new Set(),
9
9
  remove: new Set(),