electrodb 2.14.3 → 3.0.0
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 +7 -3
- package/index.d.ts +69 -163
- package/index.js +9 -0
- package/package.json +5 -4
- package/src/clauses.js +163 -56
- package/src/client.js +15 -6
- package/src/conversions.js +68 -0
- package/src/entity.js +332 -212
- package/src/errors.js +2 -2
- package/src/operations.js +7 -4
- package/src/schema.js +14 -22
- package/src/service.js +8 -8
- package/src/transaction.js +4 -4
- package/src/types.js +17 -2
- package/src/validations.js +2 -2
- package/src/where.js +14 -7
package/src/errors.js
CHANGED
|
@@ -219,8 +219,8 @@ const ErrorCodes = {
|
|
|
219
219
|
},
|
|
220
220
|
IncompleteIndexCompositesAttributesProvided: {
|
|
221
221
|
code: 2012,
|
|
222
|
-
section:
|
|
223
|
-
name:
|
|
222
|
+
section: "invalid-index-composite-attributes-provided",
|
|
223
|
+
name: "IncompleteIndexCompositesAttributesProvided",
|
|
224
224
|
sym: ErrorCode,
|
|
225
225
|
},
|
|
226
226
|
InvalidAttribute: {
|
package/src/operations.js
CHANGED
|
@@ -313,12 +313,15 @@ class AttributeOperationProxy {
|
|
|
313
313
|
return AttributeOperationProxy.pathProxy(() => {
|
|
314
314
|
const { commit, root, target, builder } = build();
|
|
315
315
|
const attribute = target.getChild(prop);
|
|
316
|
-
const nestedAny =
|
|
317
|
-
|
|
318
|
-
|
|
316
|
+
const nestedAny =
|
|
317
|
+
attribute.type === AttributeTypes.any &&
|
|
318
|
+
// if the name doesn't match that's because we are nested under 'any'
|
|
319
|
+
attribute.name !== prop;
|
|
319
320
|
let field;
|
|
320
321
|
if (attribute === undefined) {
|
|
321
|
-
throw new Error(
|
|
322
|
+
throw new Error(
|
|
323
|
+
`Invalid attribute "${prop}" at path "${target.path}.${prop}"`,
|
|
324
|
+
);
|
|
322
325
|
} else if (nestedAny) {
|
|
323
326
|
field = prop;
|
|
324
327
|
} else {
|
package/src/schema.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
PathTypes,
|
|
9
9
|
TableIndex,
|
|
10
10
|
ItemOperations,
|
|
11
|
+
DataOptions,
|
|
11
12
|
} = require("./types");
|
|
12
13
|
const AttributeTypeNames = Object.keys(AttributeTypes);
|
|
13
14
|
const ValidFacetTypes = [
|
|
@@ -466,26 +467,18 @@ class Attribute {
|
|
|
466
467
|
if (typeof definition === "function") {
|
|
467
468
|
return (val) => {
|
|
468
469
|
try {
|
|
469
|
-
let
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
],
|
|
482
|
-
];
|
|
483
|
-
} else {
|
|
484
|
-
return [
|
|
485
|
-
isValid,
|
|
486
|
-
[new e.ElectroUserValidationError(this.path, reason)],
|
|
487
|
-
];
|
|
488
|
-
}
|
|
470
|
+
let isValid = !!definition(val);
|
|
471
|
+
return [
|
|
472
|
+
isValid,
|
|
473
|
+
isValid
|
|
474
|
+
? []
|
|
475
|
+
: [
|
|
476
|
+
new e.ElectroUserValidationError(
|
|
477
|
+
this.path,
|
|
478
|
+
"Invalid value provided",
|
|
479
|
+
),
|
|
480
|
+
],
|
|
481
|
+
];
|
|
489
482
|
} catch (err) {
|
|
490
483
|
return [false, [new e.ElectroUserValidationError(this.path, err)]];
|
|
491
484
|
}
|
|
@@ -1687,14 +1680,13 @@ class Schema {
|
|
|
1687
1680
|
}
|
|
1688
1681
|
|
|
1689
1682
|
translateFromFields(item = {}, options = {}) {
|
|
1690
|
-
let { includeKeys } = options;
|
|
1691
1683
|
let data = {};
|
|
1692
1684
|
let names = this.translationForRetrieval;
|
|
1693
1685
|
for (let [attr, value] of Object.entries(item)) {
|
|
1694
1686
|
let name = names[attr];
|
|
1695
1687
|
if (name) {
|
|
1696
1688
|
data[name] = value;
|
|
1697
|
-
} else if (includeKeys) {
|
|
1689
|
+
} else if (options.data === DataOptions.includeKeys) {
|
|
1698
1690
|
data[attr] = value;
|
|
1699
1691
|
}
|
|
1700
1692
|
}
|
package/src/service.js
CHANGED
|
@@ -9,11 +9,11 @@ const {
|
|
|
9
9
|
TransactionMethods,
|
|
10
10
|
KeyCasing,
|
|
11
11
|
ServiceVersions,
|
|
12
|
-
Pager,
|
|
13
12
|
ElectroInstance,
|
|
14
13
|
ElectroInstanceTypes,
|
|
15
14
|
ModelVersions,
|
|
16
15
|
IndexTypes,
|
|
16
|
+
DataOptions,
|
|
17
17
|
} = require("./types");
|
|
18
18
|
const { FilterFactory } = require("./filters");
|
|
19
19
|
const { FilterOperations } = require("./operations");
|
|
@@ -345,7 +345,7 @@ class Service {
|
|
|
345
345
|
}
|
|
346
346
|
|
|
347
347
|
cleanseRetrievedData(index = TableIndex, entities, data = {}, config = {}) {
|
|
348
|
-
if (config.raw) {
|
|
348
|
+
if (config.data === DataOptions.raw) {
|
|
349
349
|
return data;
|
|
350
350
|
}
|
|
351
351
|
const identifiers = getEntityIdentifiers(entities);
|
|
@@ -462,7 +462,7 @@ class Service {
|
|
|
462
462
|
let options = {
|
|
463
463
|
// expressions, // DynamoDB doesnt return what I expect it would when provided with these entity filters
|
|
464
464
|
parse: (options, data) => {
|
|
465
|
-
if (options.raw) {
|
|
465
|
+
if (options.data === DataOptions.raw) {
|
|
466
466
|
return data;
|
|
467
467
|
}
|
|
468
468
|
return this.cleanseRetrievedData(index, entities, data, options);
|
|
@@ -634,11 +634,11 @@ class Service {
|
|
|
634
634
|
|
|
635
635
|
if (!scopeMatch) {
|
|
636
636
|
collectionDifferences.push(
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
637
|
+
`The index scope value provided "${
|
|
638
|
+
providedIndex.scope || "undefined"
|
|
639
|
+
}" does not match established index scope value "${
|
|
640
|
+
definition.scope || "undefined"
|
|
641
|
+
}" on index "${providedIndexName}". Index scope options must match across all entities participating in a collection`,
|
|
642
642
|
);
|
|
643
643
|
}
|
|
644
644
|
|
package/src/transaction.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { TableIndex, TransactionMethods } = require("./types");
|
|
1
|
+
const { TableIndex, TransactionMethods, DataOptions } = require("./types");
|
|
2
2
|
const { getEntityIdentifiers, matchToEntityAlias } = require("./entity");
|
|
3
3
|
|
|
4
4
|
function cleanseCanceledData(
|
|
@@ -7,7 +7,7 @@ function cleanseCanceledData(
|
|
|
7
7
|
data = {},
|
|
8
8
|
config = {},
|
|
9
9
|
) {
|
|
10
|
-
if (config.raw) {
|
|
10
|
+
if (config.data === DataOptions.raw) {
|
|
11
11
|
return data;
|
|
12
12
|
}
|
|
13
13
|
const identifiers = getEntityIdentifiers(entities);
|
|
@@ -52,7 +52,7 @@ function cleanseTransactionData(
|
|
|
52
52
|
data = {},
|
|
53
53
|
config = {},
|
|
54
54
|
) {
|
|
55
|
-
if (config.raw) {
|
|
55
|
+
if (config.data === DataOptions.raw) {
|
|
56
56
|
return data;
|
|
57
57
|
}
|
|
58
58
|
const identifiers = getEntityIdentifiers(entities);
|
|
@@ -139,7 +139,7 @@ function createTransaction(options) {
|
|
|
139
139
|
const response = await driver.go(method, params, {
|
|
140
140
|
...options,
|
|
141
141
|
parse: (options, data) => {
|
|
142
|
-
if (options.raw) {
|
|
142
|
+
if (options.data === DataOptions.raw) {
|
|
143
143
|
return data;
|
|
144
144
|
} else if (data.canceled) {
|
|
145
145
|
canceled = true;
|
package/src/types.js
CHANGED
|
@@ -3,11 +3,23 @@ const KeyTypes = {
|
|
|
3
3
|
sk: "sk",
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
+
const DataOptions = {
|
|
7
|
+
raw: "raw",
|
|
8
|
+
includeKeys: "includeKeys",
|
|
9
|
+
attributes: "attributes",
|
|
10
|
+
};
|
|
11
|
+
|
|
6
12
|
const BatchWriteTypes = {
|
|
7
13
|
batch: "batch",
|
|
8
14
|
concurrent: "concurrent",
|
|
9
15
|
};
|
|
10
16
|
|
|
17
|
+
const ComparisonTypes = {
|
|
18
|
+
keys: "keys",
|
|
19
|
+
attributes: "attributes",
|
|
20
|
+
v2: "v2",
|
|
21
|
+
};
|
|
22
|
+
|
|
11
23
|
const QueryTypes = {
|
|
12
24
|
and: "and",
|
|
13
25
|
gte: "gte",
|
|
@@ -86,7 +98,7 @@ const Comparisons = {
|
|
|
86
98
|
gt: ">",
|
|
87
99
|
};
|
|
88
100
|
|
|
89
|
-
const
|
|
101
|
+
const KeyAttributesComparisons = {
|
|
90
102
|
lt: "<",
|
|
91
103
|
gte: ">=",
|
|
92
104
|
|
|
@@ -332,6 +344,7 @@ module.exports = {
|
|
|
332
344
|
ValueTypes,
|
|
333
345
|
TableIndex,
|
|
334
346
|
MethodTypes,
|
|
347
|
+
DataOptions,
|
|
335
348
|
Comparisons,
|
|
336
349
|
BuilderTypes,
|
|
337
350
|
ReturnValues,
|
|
@@ -341,6 +354,7 @@ module.exports = {
|
|
|
341
354
|
AttributeTypes,
|
|
342
355
|
EntityVersions,
|
|
343
356
|
CastKeyOptions,
|
|
357
|
+
ComparisonTypes,
|
|
344
358
|
ServiceVersions,
|
|
345
359
|
ExpressionTypes,
|
|
346
360
|
ElectroInstance,
|
|
@@ -348,13 +362,13 @@ module.exports = {
|
|
|
348
362
|
UnprocessedTypes,
|
|
349
363
|
AttributeWildCard,
|
|
350
364
|
TerminalOperation,
|
|
351
|
-
PartialComparisons,
|
|
352
365
|
FormatToReturnValues,
|
|
353
366
|
AttributeProxySymbol,
|
|
354
367
|
ElectroInstanceTypes,
|
|
355
368
|
MethodTypeTranslation,
|
|
356
369
|
EventSubscriptionTypes,
|
|
357
370
|
DynamoDBAttributeTypes,
|
|
371
|
+
KeyAttributesComparisons,
|
|
358
372
|
AttributeMutationMethods,
|
|
359
373
|
AllPages,
|
|
360
374
|
ResultOrderOption,
|
|
@@ -363,4 +377,5 @@ module.exports = {
|
|
|
363
377
|
TransactionOperations,
|
|
364
378
|
TransactionMethods,
|
|
365
379
|
UpsertOperations,
|
|
380
|
+
BatchWriteTypes,
|
|
366
381
|
};
|
package/src/validations.js
CHANGED
|
@@ -122,7 +122,7 @@ const Index = {
|
|
|
122
122
|
scope: {
|
|
123
123
|
type: "string",
|
|
124
124
|
required: false,
|
|
125
|
-
}
|
|
125
|
+
},
|
|
126
126
|
},
|
|
127
127
|
},
|
|
128
128
|
sk: {
|
|
@@ -178,7 +178,7 @@ const Index = {
|
|
|
178
178
|
type: "any",
|
|
179
179
|
required: false,
|
|
180
180
|
format: "isFunction",
|
|
181
|
-
}
|
|
181
|
+
},
|
|
182
182
|
},
|
|
183
183
|
};
|
|
184
184
|
|
package/src/where.js
CHANGED
|
@@ -27,7 +27,8 @@ class FilterExpression extends ExpressionState {
|
|
|
27
27
|
return !expression.replace(/\n|\r|\w/g, "").trim();
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
add(newExpression) {
|
|
30
|
+
add(newExpression, filterOptions = {}) {
|
|
31
|
+
const asPrefix = !!filterOptions.asPrefix;
|
|
31
32
|
let expression = "";
|
|
32
33
|
let existingExpression = this.expression;
|
|
33
34
|
if (
|
|
@@ -39,13 +40,19 @@ class FilterExpression extends ExpressionState {
|
|
|
39
40
|
if (isEmpty) {
|
|
40
41
|
return existingExpression;
|
|
41
42
|
}
|
|
42
|
-
|
|
43
|
+
|
|
44
|
+
if (
|
|
45
|
+
!asPrefix &&
|
|
43
46
|
!existingExpression.startsWith("(") &&
|
|
44
|
-
!existingExpression.endsWith(")")
|
|
45
|
-
|
|
47
|
+
!existingExpression.endsWith(")")
|
|
48
|
+
) {
|
|
46
49
|
existingExpression = `(${existingExpression})`;
|
|
47
50
|
}
|
|
48
|
-
|
|
51
|
+
if (asPrefix) {
|
|
52
|
+
expression = `(${newExpression}) AND ${existingExpression}`;
|
|
53
|
+
} else {
|
|
54
|
+
expression = `${existingExpression} AND ${newExpression}`;
|
|
55
|
+
}
|
|
49
56
|
} else {
|
|
50
57
|
expression = this._trim(newExpression);
|
|
51
58
|
}
|
|
@@ -53,7 +60,7 @@ class FilterExpression extends ExpressionState {
|
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
// applies operations without verifying them against known attributes. Used internally for key conditions.
|
|
56
|
-
unsafeSet(operation, name, ...values) {
|
|
63
|
+
unsafeSet(filterOptions, operation, name, ...values) {
|
|
57
64
|
const { template } = FilterOperations[operation] || {};
|
|
58
65
|
if (template === undefined) {
|
|
59
66
|
throw new Error(
|
|
@@ -68,7 +75,7 @@ class FilterExpression extends ExpressionState {
|
|
|
68
75
|
names.prop,
|
|
69
76
|
...valueExpressions,
|
|
70
77
|
);
|
|
71
|
-
this.add(condition);
|
|
78
|
+
this.add(condition, filterOptions);
|
|
72
79
|
}
|
|
73
80
|
|
|
74
81
|
build() {
|