electrodb 2.9.3 → 2.10.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/src/errors.js CHANGED
@@ -65,31 +65,31 @@ const ErrorCodes = {
65
65
  code: 1009,
66
66
  section: "invalid-model",
67
67
  name: "InvalidModel",
68
- sym: ErrorCode
68
+ sym: ErrorCode,
69
69
  },
70
70
  InvalidOptions: {
71
71
  code: 1010,
72
72
  section: "invalid-options",
73
73
  name: "InvalidOptions",
74
- sym: ErrorCode
74
+ sym: ErrorCode,
75
75
  },
76
76
  InvalidFilter: {
77
77
  code: 1011,
78
78
  section: "filters",
79
79
  name: "InvalidFilter",
80
- sym: ErrorCode
80
+ sym: ErrorCode,
81
81
  },
82
82
  InvalidWhere: {
83
83
  code: 1012,
84
84
  section: "where",
85
85
  name: "InvalidWhere",
86
- sym: ErrorCode
86
+ sym: ErrorCode,
87
87
  },
88
88
  InvalidJoin: {
89
89
  code: 1013,
90
90
  section: "join",
91
91
  name: "InvalidJoin",
92
- sym: ErrorCode
92
+ sym: ErrorCode,
93
93
  },
94
94
  DuplicateIndexFields: {
95
95
  code: 1014,
@@ -107,7 +107,7 @@ const ErrorCodes = {
107
107
  code: 1016,
108
108
  section: "invalid-attribute-watch-definition",
109
109
  name: "InvalidAttributeWatchDefinition",
110
- sym: ErrorCode
110
+ sym: ErrorCode,
111
111
  },
112
112
  IncompatibleKeyCompositeAttributeTemplate: {
113
113
  code: 1017,
@@ -167,13 +167,13 @@ const ErrorCodes = {
167
167
  code: 2003,
168
168
  section: "missing-table",
169
169
  name: "MissingTable",
170
- sym: ErrorCode
170
+ sym: ErrorCode,
171
171
  },
172
172
  InvalidConcurrencyOption: {
173
173
  code: 2004,
174
174
  section: "invalid-concurrency-option",
175
175
  name: "InvalidConcurrencyOption",
176
- sym: ErrorCode
176
+ sym: ErrorCode,
177
177
  },
178
178
  InvalidPagesOption: {
179
179
  code: 2005,
@@ -215,7 +215,7 @@ const ErrorCodes = {
215
215
  code: 3001,
216
216
  section: "invalid-attribute",
217
217
  name: "InvalidAttribute",
218
- sym: ErrorCode
218
+ sym: ErrorCode,
219
219
  },
220
220
  AWSError: {
221
221
  code: 4001,
@@ -233,7 +233,7 @@ const ErrorCodes = {
233
233
  code: 5002,
234
234
  section: "",
235
235
  name: "GeneralError",
236
- sym: ErrorCode
236
+ sym: ErrorCode,
237
237
  },
238
238
  LastEvaluatedKey: {
239
239
  code: 5003,
@@ -258,19 +258,21 @@ const ErrorCodes = {
258
258
  section: "pager-not-unique",
259
259
  name: "NoOwnerForPager",
260
260
  sym: ErrorCode,
261
- }
261
+ },
262
262
  };
263
263
 
264
264
  function makeMessage(message, section) {
265
- return `${message} - For more detail on this error reference: ${getHelpLink(section)}`
265
+ return `${message} - For more detail on this error reference: ${getHelpLink(
266
+ section,
267
+ )}`;
266
268
  }
267
269
 
268
270
  class ElectroError extends Error {
269
- constructor(code, message) {
270
- super(message);
271
+ constructor(code, message, cause) {
272
+ super(message, { cause });
271
273
  let detail = ErrorCodes.UnknownError;
272
274
  if (code && code.sym === ErrorCode) {
273
- detail = code
275
+ detail = code;
274
276
  }
275
277
  this._message = message;
276
278
  // this.message = `${message} - For more detail on this error reference: ${getHelpLink(detail.section)}`;
@@ -279,7 +281,7 @@ class ElectroError extends Error {
279
281
  Error.captureStackTrace(this, ElectroError);
280
282
  }
281
283
 
282
- this.name = 'ElectroError';
284
+ this.name = "ElectroError";
283
285
  this.ref = code;
284
286
  this.code = detail.code;
285
287
  this.date = Date.now();
@@ -293,7 +295,7 @@ class ElectroValidationError extends ElectroError {
293
295
  const messages = [];
294
296
  for (let i = 0; i < errors.length; i++) {
295
297
  const error = errors[i];
296
- const message = error ? (error._message || error.message) : undefined;
298
+ const message = error ? error._message || error.message : undefined;
297
299
  messages.push(message);
298
300
  if (error instanceof ElectroUserValidationError) {
299
301
  fields.push({
@@ -301,7 +303,7 @@ class ElectroValidationError extends ElectroError {
301
303
  index: error.index,
302
304
  reason: message,
303
305
  cause: error.cause,
304
- type: 'validation'
306
+ type: "validation",
305
307
  });
306
308
  } else if (error instanceof ElectroAttributeValidationError) {
307
309
  fields.push({
@@ -309,22 +311,23 @@ class ElectroValidationError extends ElectroError {
309
311
  index: error.index,
310
312
  reason: message,
311
313
  cause: error.cause || error, // error | undefined
312
- type: 'validation'
314
+ type: "validation",
313
315
  });
314
316
  } else if (message) {
315
317
  fields.push({
316
- field: '',
318
+ field: "",
317
319
  index: error.index,
318
320
  reason: message,
319
321
  cause: error !== undefined ? error.cause || error : undefined,
320
- type: 'fatal'
322
+ type: "fatal",
321
323
  });
322
324
  }
323
325
  }
324
326
 
325
- const message = messages
326
- .filter(message => typeof message === "string" && message.length)
327
- .join(', ') || `Invalid value(s) provided`;
327
+ const message =
328
+ messages
329
+ .filter((message) => typeof message === "string" && message.length)
330
+ .join(", ") || `Invalid value(s) provided`;
328
331
 
329
332
  super(ErrorCodes.InvalidAttribute, message);
330
333
  this.fields = fields;
@@ -338,14 +341,22 @@ class ElectroUserValidationError extends ElectroError {
338
341
  let hasCause = false;
339
342
  if (typeof cause === "string") {
340
343
  message = cause;
341
- } else if (cause !== undefined && typeof cause._message === "string" && cause._message.length) {
344
+ } else if (
345
+ cause !== undefined &&
346
+ typeof cause._message === "string" &&
347
+ cause._message.length
348
+ ) {
342
349
  message = cause._message;
343
350
  hasCause = true;
344
- } else if (cause !== undefined && typeof cause.message === "string" && cause.message.length) {
351
+ } else if (
352
+ cause !== undefined &&
353
+ typeof cause.message === "string" &&
354
+ cause.message.length
355
+ ) {
345
356
  message = cause.message;
346
357
  hasCause = true;
347
358
  } else {
348
- message = "Invalid value provided";
359
+ message = "Invalid value provided";
349
360
  }
350
361
  super(ErrorCodes.InvalidAttribute, message);
351
362
  this.field = field;
@@ -368,5 +379,5 @@ module.exports = {
368
379
  ElectroError,
369
380
  ElectroValidationError,
370
381
  ElectroUserValidationError,
371
- ElectroAttributeValidationError
382
+ ElectroAttributeValidationError,
372
383
  };
package/src/events.js CHANGED
@@ -1,42 +1,52 @@
1
1
  const e = require("./errors");
2
- const v = require('./validations');
2
+ const v = require("./validations");
3
3
 
4
4
  class EventManager {
5
5
  static createSafeListener(listener) {
6
6
  if (listener === undefined) {
7
7
  return undefined;
8
- } if (!v.isFunction(listener)) {
9
- throw new e.ElectroError(e.ErrorCodes.InvalidListenerProvided, `Provided listener is not of type 'function'`);
8
+ }
9
+ if (!v.isFunction(listener)) {
10
+ throw new e.ElectroError(
11
+ e.ErrorCodes.InvalidListenerProvided,
12
+ `Provided listener is not of type 'function'`,
13
+ );
10
14
  } else {
11
15
  return (...params) => {
12
16
  try {
13
17
  listener(...params);
14
- } catch(err) {
18
+ } catch (err) {
15
19
  console.error(`Error invoking user supplied listener`, err);
16
20
  }
17
- }
21
+ };
18
22
  }
19
23
  }
20
24
 
21
25
  static normalizeListeners(listeners = []) {
22
26
  if (!Array.isArray(listeners)) {
23
- throw new e.ElectroError(e.ErrorCodes.InvalidListenerProvided, `Listeners must be provided as an array of functions`);
27
+ throw new e.ElectroError(
28
+ e.ErrorCodes.InvalidListenerProvided,
29
+ `Listeners must be provided as an array of functions`,
30
+ );
24
31
  }
25
32
  return listeners
26
- .map(listener => EventManager.createSafeListener(listener))
27
- .filter(listener => {
33
+ .map((listener) => EventManager.createSafeListener(listener))
34
+ .filter((listener) => {
28
35
  switch (typeof listener) {
29
- case 'function':
36
+ case "function":
30
37
  return true;
31
- case 'undefined':
38
+ case "undefined":
32
39
  return false;
33
40
  default:
34
- throw new e.ElectroError(e.ErrorCodes.InvalidListenerProvided, `Provided listener is not of type 'function`);
41
+ throw new e.ElectroError(
42
+ e.ErrorCodes.InvalidListenerProvided,
43
+ `Provided listener is not of type 'function`,
44
+ );
35
45
  }
36
46
  });
37
47
  }
38
48
 
39
- constructor({listeners = []} = {}) {
49
+ constructor({ listeners = [] } = {}) {
40
50
  this.listeners = EventManager.normalizeListeners(listeners);
41
51
  }
42
52
 
@@ -46,14 +56,14 @@ class EventManager {
46
56
  }
47
57
 
48
58
  this.listeners = this.listeners.concat(
49
- EventManager.normalizeListeners(listeners)
59
+ EventManager.normalizeListeners(listeners),
50
60
  );
51
61
  }
52
62
 
53
63
  trigger(event, adHocListeners = []) {
54
64
  const allListeners = [
55
65
  ...this.listeners,
56
- ...EventManager.normalizeListeners(adHocListeners)
66
+ ...EventManager.normalizeListeners(adHocListeners),
57
67
  ];
58
68
 
59
69
  for (const listener of allListeners) {
@@ -63,5 +73,5 @@ class EventManager {
63
73
  }
64
74
 
65
75
  module.exports = {
66
- EventManager
67
- };
76
+ EventManager,
77
+ };
@@ -0,0 +1,124 @@
1
+ const FilterOperations = {
2
+ escape: {
3
+ template: function escape(options, attr) {
4
+ return `${attr}`;
5
+ },
6
+ rawValue: true,
7
+ },
8
+ size: {
9
+ template: function size(options, attr, name) {
10
+ return `size(${name})`;
11
+ },
12
+ strict: false,
13
+ },
14
+ type: {
15
+ template: function attributeType(options, attr, name, value) {
16
+ return `attribute_type(${name}, ${value})`;
17
+ },
18
+ strict: false,
19
+ },
20
+ ne: {
21
+ template: function ne(options, attr, name, value) {
22
+ return `${name} <> ${value}`;
23
+ },
24
+ strict: false,
25
+ },
26
+ eq: {
27
+ template: function eq(options, attr, name, value) {
28
+ return `${name} = ${value}`;
29
+ },
30
+ strict: false,
31
+ },
32
+ gt: {
33
+ template: function gt(options, attr, name, value) {
34
+ return `${name} > ${value}`;
35
+ },
36
+ strict: false,
37
+ },
38
+ lt: {
39
+ template: function lt(options, attr, name, value) {
40
+ return `${name} < ${value}`;
41
+ },
42
+ strict: false,
43
+ },
44
+ gte: {
45
+ template: function gte(options, attr, name, value) {
46
+ return `${name} >= ${value}`;
47
+ },
48
+ strict: false,
49
+ },
50
+ lte: {
51
+ template: function lte(options, attr, name, value) {
52
+ return `${name} <= ${value}`;
53
+ },
54
+ strict: false,
55
+ },
56
+ between: {
57
+ template: function between(options, attr, name, value1, value2) {
58
+ return `(${name} between ${value1} and ${value2})`;
59
+ },
60
+ strict: false,
61
+ },
62
+ begins: {
63
+ template: function begins(options, attr, name, value) {
64
+ return `begins_with(${name}, ${value})`;
65
+ },
66
+ strict: false,
67
+ },
68
+ exists: {
69
+ template: function exists(options, attr, name) {
70
+ return `attribute_exists(${name})`;
71
+ },
72
+ strict: false,
73
+ },
74
+ notExists: {
75
+ template: function notExists(options, attr, name) {
76
+ return `attribute_not_exists(${name})`;
77
+ },
78
+ strict: false,
79
+ },
80
+ contains: {
81
+ template: function contains(options, attr, name, value) {
82
+ return `contains(${name}, ${value})`;
83
+ },
84
+ strict: false,
85
+ },
86
+ notContains: {
87
+ template: function notContains(options, attr, name, value) {
88
+ return `not contains(${name}, ${value})`;
89
+ },
90
+ strict: false,
91
+ },
92
+ value: {
93
+ template: function (options, attr, name, value) {
94
+ return value;
95
+ },
96
+ strict: false,
97
+ canNest: true,
98
+ },
99
+ name: {
100
+ template: function (options, attr, name) {
101
+ return name;
102
+ },
103
+ strict: false,
104
+ canNest: true,
105
+ },
106
+ eqOrNotExists: {
107
+ template: function eq(options, attr, name, value) {
108
+ return `(${name} = ${value} OR attribute_not_exists(${name}))`;
109
+ },
110
+ strict: false,
111
+ },
112
+ field: {
113
+ template: function (options, _, fieldName) {
114
+ return fieldName !== undefined ? `${fieldName}` : "";
115
+ },
116
+ strict: false,
117
+ canNest: true,
118
+ rawField: true,
119
+ },
120
+ };
121
+
122
+ module.exports = {
123
+ FilterOperations,
124
+ };
package/src/filters.js CHANGED
@@ -1,111 +1,109 @@
1
1
  const e = require("./errors");
2
- const {MethodTypes, ExpressionTypes} = require("./types");
2
+ const { MethodTypes, ExpressionTypes } = require("./types");
3
3
 
4
4
  class FilterFactory {
5
- constructor(attributes = {}, filterTypes = {}) {
6
- this.attributes = { ...attributes };
7
- this.filters = {
8
- ...filterTypes,
9
- };
10
- }
5
+ constructor(attributes = {}, filterTypes = {}) {
6
+ this.attributes = { ...attributes };
7
+ this.filters = {
8
+ ...filterTypes,
9
+ };
10
+ }
11
11
 
12
- getExpressionType(methodType) {
13
- switch (methodType) {
14
- case MethodTypes.put:
15
- case MethodTypes.create:
16
- case MethodTypes.update:
17
- case MethodTypes.patch:
18
- case MethodTypes.delete:
19
- case MethodTypes.get:
20
- case MethodTypes.upsert:
21
- return ExpressionTypes.ConditionExpression
22
- default:
23
- return ExpressionTypes.FilterExpression
24
- }
25
- }
12
+ getExpressionType(methodType) {
13
+ switch (methodType) {
14
+ case MethodTypes.put:
15
+ case MethodTypes.create:
16
+ case MethodTypes.update:
17
+ case MethodTypes.patch:
18
+ case MethodTypes.delete:
19
+ case MethodTypes.get:
20
+ case MethodTypes.upsert:
21
+ return ExpressionTypes.ConditionExpression;
22
+ default:
23
+ return ExpressionTypes.FilterExpression;
24
+ }
25
+ }
26
26
 
27
- _buildFilterAttributes(setName, setValue) {
28
- let attributes = {};
29
- for (let [name, attribute] of Object.entries(this.attributes)) {
30
- let filterAttribute = {};
31
- for (let [type, {template}] of Object.entries(this.filters)) {
32
- Object.defineProperty(filterAttribute, type, {
33
- get: () => {
34
- return (...values) => {
35
- let {prop} = setName({}, name, attribute.field);
36
- let attrValues = [];
37
- for (let value of values) {
38
- if (template.length > 1) {
39
- attrValues.push(
40
- setValue(name, value, name)
41
- );
42
- }
43
- }
44
- let expression = template({}, attribute, prop, ...attrValues);
45
- return expression.trim();
46
- };
47
- },
48
- });
49
- }
50
- attributes[name] = filterAttribute;
51
- }
52
- return attributes;
53
- }
27
+ _buildFilterAttributes(setName, setValue) {
28
+ let attributes = {};
29
+ for (let [name, attribute] of Object.entries(this.attributes)) {
30
+ let filterAttribute = {};
31
+ for (let [type, { template }] of Object.entries(this.filters)) {
32
+ Object.defineProperty(filterAttribute, type, {
33
+ get: () => {
34
+ return (...values) => {
35
+ let { prop } = setName({}, name, attribute.field);
36
+ let attrValues = [];
37
+ for (let value of values) {
38
+ if (template.length > 1) {
39
+ attrValues.push(setValue(name, value, name));
40
+ }
41
+ }
42
+ let expression = template({}, attribute, prop, ...attrValues);
43
+ return expression.trim();
44
+ };
45
+ },
46
+ });
47
+ }
48
+ attributes[name] = filterAttribute;
49
+ }
50
+ return attributes;
51
+ }
54
52
 
55
- buildClause(filterFn) {
56
- return (entity, state, ...params) => {
57
- const type = this.getExpressionType(state.query.method);
58
- const builder = state.query.filter[type];
59
- let setName = (paths, name, value) => builder.setName(paths, name, value);
60
- let setValue = (name, value, path) => builder.setValue(name, value, path);
61
- let attributes = this._buildFilterAttributes(
62
- setName,
63
- setValue,
64
- );
65
- const expression = filterFn(attributes, ...params);
66
- if (typeof expression !== "string") {
67
- throw new e.ElectroError(e.ErrorCodes.InvalidFilter, "Invalid filter response. Expected result to be of type string");
68
- }
69
- builder.add(expression);
70
- return state;
71
- };
72
- }
53
+ buildClause(filterFn) {
54
+ return (entity, state, ...params) => {
55
+ const type = this.getExpressionType(state.query.method);
56
+ const builder = state.query.filter[type];
57
+ let setName = (paths, name, value) => builder.setName(paths, name, value);
58
+ let setValue = (name, value, path) => builder.setValue(name, value, path);
59
+ let attributes = this._buildFilterAttributes(setName, setValue);
60
+ const expression = filterFn(attributes, ...params);
61
+ if (typeof expression !== "string") {
62
+ throw new e.ElectroError(
63
+ e.ErrorCodes.InvalidFilter,
64
+ "Invalid filter response. Expected result to be of type string",
65
+ );
66
+ }
67
+ builder.add(expression);
68
+ return state;
69
+ };
70
+ }
73
71
 
74
- injectFilterClauses(clauses = {}, filters = {}) {
75
- let injected = { ...clauses };
76
- let filterParents = Object.entries(injected)
77
- .filter(clause => {
78
- let [name, { children }] = clause;
79
- return children.find(child => ['go', 'commit'].includes(child));
80
- })
81
- .map(([name]) => name);
82
- let modelFilters = Object.keys(filters);
83
- let filterChildren = [];
84
- for (let [name, filter] of Object.entries(filters)) {
85
- filterChildren.push(name);
86
- injected[name] = {
87
- name: name,
88
- action: this.buildClause(filter),
89
- children: ["params", "go", "commit", "filter", ...modelFilters],
90
- };
91
- }
92
- filterChildren.push("filter");
93
- injected["filter"] = {
94
- name: "filter",
95
- action: (entity, state, fn) => {
96
- return this.buildClause(fn)(entity, state);
97
- },
98
- children: ["params", "go", "commit", "filter", ...modelFilters],
99
- };
100
- for (let parent of filterParents) {
101
- injected[parent] = { ...injected[parent] };
102
- injected[parent].children = [
103
- ...filterChildren,
104
- ...injected[parent].children,
105
- ];
106
- }
107
- return injected;
108
- }
72
+ injectFilterClauses(clauses = {}, filters = {}) {
73
+ let injected = { ...clauses };
74
+ let filterParents = Object.entries(injected)
75
+ .filter((clause) => {
76
+ let [name, { children }] = clause;
77
+ return children.find((child) => ["go", "commit"].includes(child));
78
+ })
79
+ .map(([name]) => name);
80
+ let modelFilters = Object.keys(filters);
81
+ let filterChildren = [];
82
+ for (let [name, filter] of Object.entries(filters)) {
83
+ filterChildren.push(name);
84
+ injected[name] = {
85
+ name: name,
86
+ action: this.buildClause(filter),
87
+ children: ["params", "go", "commit", "filter", ...modelFilters],
88
+ };
89
+ }
90
+ filterChildren.push("filter");
91
+ injected["filter"] = {
92
+ name: "filter",
93
+ action: (entity, state, fn) => {
94
+ return this.buildClause(fn)(entity, state);
95
+ },
96
+ children: ["params", "go", "commit", "filter", ...modelFilters],
97
+ };
98
+ for (let parent of filterParents) {
99
+ injected[parent] = { ...injected[parent] };
100
+ injected[parent].children = [
101
+ ...filterChildren,
102
+ ...injected[parent].children,
103
+ ];
104
+ }
105
+ return injected;
106
+ }
109
107
  }
110
108
 
111
109
  module.exports = { FilterFactory };