electrodb
Advanced tools
Comparing version 2.8.2 to 2.9.0
{ | ||
"name": "electrodb", | ||
"version": "2.8.2", | ||
"version": "2.9.0", | ||
"description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb", | ||
@@ -34,4 +34,4 @@ "main": "index.js", | ||
"devDependencies": { | ||
"@aws-sdk/client-dynamodb": "^3.54.1", | ||
"@aws-sdk/lib-dynamodb": "^3.54.1", | ||
"@aws-sdk/client-dynamodb": "^3.395.0", | ||
"@aws-sdk/lib-dynamodb": "^3.395.0", | ||
"@istanbuljs/nyc-config-typescript": "^1.0.2", | ||
@@ -54,4 +54,4 @@ "@types/chai": "^4.2.12", | ||
"ts-node": "^10.9.1", | ||
"tsd": "^0.21.0", | ||
"typescript": "^4.9.5", | ||
"tsd": "^0.28.1", | ||
"typescript": "^5.1.6", | ||
"uuid": "7.0.1" | ||
@@ -72,5 +72,4 @@ }, | ||
"dependencies": { | ||
"@aws-sdk/lib-dynamodb": "^3.54.1", | ||
"jsonschema": "1.2.7" | ||
} | ||
} |
const { QueryTypes, MethodTypes, ItemOperations, ExpressionTypes, TransactionCommitSymbol, TransactionOperations, TerminalOperation, KeyTypes, IndexTypes } = require("./types"); | ||
const {AttributeOperationProxy, UpdateOperations, FilterOperationNames} = require("./operations"); | ||
const {AttributeOperationProxy, UpdateOperations, FilterOperationNames, UpdateOperationNames} = require("./operations"); | ||
const {UpdateExpression} = require("./update"); | ||
@@ -369,3 +369,3 @@ const {FilterExpression} = require("./where"); | ||
}, | ||
children: ["set", "append","updateRemove", "updateDelete", "add", "subtract", "data", "commit"], | ||
children: ["set", "append","updateRemove", "updateDelete", "add", "subtract", "data", "composite", "commit"], | ||
}, | ||
@@ -397,3 +397,3 @@ update: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -428,3 +428,3 @@ data: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -446,4 +446,29 @@ set: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
composite: { | ||
name: "composite", | ||
action(entity, state, composites = {}) { | ||
if (state.getError() !== null) { | ||
return state; | ||
} | ||
try { | ||
for (const attrName in composites) { | ||
// todo: validate attrName is facet | ||
if (entity.model.facets.byAttr[attrName]) { | ||
const wasSet = state.query.update.addComposite(attrName, composites[attrName]); | ||
if (!wasSet) { | ||
throw new e.ElectroError(e.ErrorCodes.DuplicateUpdateCompositesProvided, `The composite attribute ${attrName} has been provided more than once with different values. Remove the duplication before running again`); | ||
} | ||
state.applyCondition(FilterOperationNames.eq, attrName, composites[attrName]); | ||
} | ||
} | ||
return state; | ||
} catch(err) { | ||
state.setError(err); | ||
return state; | ||
} | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
append: { | ||
@@ -464,3 +489,3 @@ name: "append", | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -485,3 +510,3 @@ updateRemove: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -503,3 +528,3 @@ updateDelete: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -521,3 +546,3 @@ add: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -539,3 +564,3 @@ subtract: { | ||
}, | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit"], | ||
children: ["data", "set", "append", "add", "updateRemove", "updateDelete", "go", "params", "subtract", "commit", "composite"], | ||
}, | ||
@@ -977,2 +1002,13 @@ query: { | ||
applyCondition(operation, name, ...values) { | ||
if (FilterOperationNames[operation] !== undefined && name !== undefined && values.length > 0) { | ||
const attribute = this.attributes[name]; | ||
if (attribute !== undefined) { | ||
const filter = this.query.filter[ExpressionTypes.ConditionExpression]; | ||
filter.unsafeSet(operation, attribute.field, ...values); | ||
} | ||
} | ||
return this; | ||
} | ||
unsafeApplyFilter(operation, name, ...values) { | ||
@@ -979,0 +1015,0 @@ if (FilterOperationNames[operation] !== undefined & name !== undefined && values.length > 0) { |
@@ -208,2 +208,8 @@ // # Errors: | ||
}, | ||
DuplicateUpdateCompositesProvided: { | ||
code: 2010, | ||
section: "duplicate-update-composites-provided", | ||
name: "DuplicateUpdateCompositesProvided", | ||
sym: ErrorCode, | ||
}, | ||
InvalidAttribute: { | ||
@@ -210,0 +216,0 @@ code: 3001, |
@@ -555,2 +555,7 @@ const {AttributeTypes, ItemOperations, AttributeProxySymbol, BuilderTypes, DynamoDBAttributeTypes} = require("./types"); | ||
module.exports = {UpdateOperations, FilterOperations, FilterOperationNames, ExpressionState, AttributeOperationProxy}; | ||
const UpdateOperationNames = Object.keys(UpdateOperations).reduce((ops, name) => { | ||
ops[name] = name; | ||
return ops; | ||
}, {}); | ||
module.exports = {UpdateOperations, UpdateOperationNames, FilterOperations, FilterOperationNames, ExpressionState, AttributeOperationProxy}; |
@@ -1174,3 +1174,3 @@ const { CastTypes, ValueTypes, KeyCasing, AttributeTypes, AttributeMutationMethods, AttributeWildCard, PathTypes, TableIndex, ItemOperations } = require("./types"); | ||
let assignedIndexes = facets.byAttr[name].map(assigned => assigned.index === "" ? "Table Index" : assigned.index); | ||
throw new e.ElectroError(e.ErrorCodes.InvalidAttributeDefinition, `Invalid composite attribute definition: Composite attributes must be one of the following: ${ValidFacetTypes.join(", ")}. The attribute "${name}" is defined as being type "${attribute.type}" but is a composite attribute of the the following indexes: ${assignedIndexes.join(", ")}`); | ||
throw new e.ElectroError(e.ErrorCodes.InvalidAttributeDefinition, `Invalid composite attribute definition: Composite attributes must be one of the following: ${ValidFacetTypes.join(", ")}. The attribute "${name}" is defined as being type "${attribute.type}" but is a composite attribute of the following indexes: ${assignedIndexes.join(", ")}`); | ||
} | ||
@@ -1442,5 +1442,5 @@ | ||
let record = {}; | ||
for (let [path, attribute] of this.traverser.getAll()) { | ||
let value = payload[path]; | ||
if (value === undefined) { | ||
for (let [path, value] of Object.entries(payload)) { | ||
let attribute = this.traverser.paths.get(path); | ||
if (attribute === undefined) { | ||
continue; | ||
@@ -1447,0 +1447,0 @@ } |
@@ -521,2 +521,4 @@ const { Entity, getEntityIdentifiers, matchToEntityAlias } = require("./entity"); | ||
_validateCollectionDefinition(definition = {}, providedIndex = {}) { | ||
let isCustomMatchPK = definition.pk.isCustom === providedIndex.pk.isCustom; | ||
let isCustomMatchSK = !!(definition.sk && definition.sk.isCustom) === !!(providedIndex.sk && providedIndex.sk.isCustom); | ||
let indexMatch = definition.index === providedIndex.index; | ||
@@ -530,28 +532,64 @@ let pkFieldMatch = definition.pk.field === providedIndex.pk.field; | ||
let matchingKeyCasing = this._validateIndexCasingMatch(definition, providedIndex); | ||
if (pkFacetLengthMatch) { | ||
for (let i = 0; i < definition.pk.labels.length; i++) { | ||
let definitionFacet = definition.pk.labels[i].name; | ||
let definitionLabel = definition.pk.labels[i].label; | ||
let providedFacet = providedIndex.pk.labels[i].name; | ||
let providedLabel = providedIndex.pk.labels[i].label; | ||
let noLabels = definition.pk.labels[i].label === definition.pk.labels[i].name && providedIndex.pk.labels[i].label === providedIndex.pk.labels[i].name; | ||
if (definitionLabel !== providedLabel) { | ||
mismatchedFacetLabels.push({ | ||
definitionFacet, | ||
definitionLabel, | ||
providedFacet, | ||
providedLabel, | ||
type: noLabels ? "facet" : "label" | ||
}); | ||
} else if (definitionFacet !== providedFacet) { | ||
mismatchedFacetLabels.push({ | ||
definitionFacet, | ||
definitionLabel, | ||
providedFacet, | ||
providedLabel, | ||
type: "facet" | ||
}); | ||
for (let i = 0; i < Math.max(definition.pk.labels.length, providedIndex.pk.labels.length); i++) { | ||
let definitionFacet = definition.pk.labels[i] && definition.pk.labels[i].name; | ||
let definitionLabel = definition.pk.labels[i] && definition.pk.labels[i].label; | ||
let providedFacet = providedIndex.pk.labels[i] && providedIndex.pk.labels[i].name; | ||
let providedLabel = providedIndex.pk.labels[i] && providedIndex.pk.labels[i].label; | ||
let noLabels = definitionLabel === definitionFacet && providedLabel === providedFacet; | ||
if (definitionLabel !== providedLabel) { | ||
mismatchedFacetLabels.push({ | ||
definitionFacet, | ||
definitionLabel, | ||
providedFacet, | ||
providedLabel, | ||
kind: "Partition", | ||
type: noLabels ? "facet" : "label" | ||
}); | ||
break; | ||
} else if (definitionFacet !== providedFacet) { | ||
mismatchedFacetLabels.push({ | ||
definitionFacet, | ||
definitionLabel, | ||
providedFacet, | ||
providedLabel, | ||
kind: "Partition", | ||
type: "facet" | ||
}); | ||
break; | ||
} | ||
} | ||
if (!isCustomMatchPK) { | ||
collectionDifferences.push(`The usage of key templates the partition key on index ${definitionIndexName} must be consistent across all Entities, some entities provided use template while others do not`); | ||
} | ||
if (!isCustomMatchSK) { | ||
collectionDifferences.push(`The usage of key templates the sort key on index ${definitionIndexName} must be consistent across all Entities, some entities provided use template while others do not`); | ||
} | ||
if (definition.type === "clustered") { | ||
for (let i = 0; i < Math.min(definition.sk.labels.length, providedIndex.sk.labels.length); i++) { | ||
let definitionFacet = definition.sk.labels[i] && definition.sk.labels[i].name; | ||
let definitionLabel = definition.sk.labels[i] && definition.sk.labels[i].label; | ||
let providedFacet = providedIndex.sk.labels[i] && providedIndex.sk.labels[i].name; | ||
let providedLabel = providedIndex.sk.labels[i] && providedIndex.sk.labels[i].label; | ||
let noLabels = definitionLabel === definitionFacet && providedLabel === providedFacet; | ||
if (definitionFacet === providedFacet) { | ||
if (definitionLabel !== providedLabel) { | ||
mismatchedFacetLabels.push({ | ||
definitionFacet, | ||
definitionLabel, | ||
providedFacet, | ||
providedLabel, | ||
kind: "Sort", | ||
type: noLabels ? "facet" : "label" | ||
}); | ||
} | ||
} else { | ||
break; | ||
} | ||
} | ||
} | ||
if (!matchingKeyCasing.pk) { | ||
@@ -562,2 +600,3 @@ collectionDifferences.push( | ||
} | ||
if (!matchingKeyCasing.sk) { | ||
@@ -570,2 +609,3 @@ const definedSk = definition.sk || {}; | ||
} | ||
if (!indexMatch) { | ||
@@ -580,2 +620,3 @@ collectionDifferences.push( | ||
} | ||
if (!pkFacetLengthMatch) { | ||
@@ -591,7 +632,7 @@ collectionDifferences.push( | ||
collectionDifferences.push( | ||
`Partition Key composite attributes provided for index "${providedIndexName}" do not match established composite attribute "${mismatch.definitionFacet}" on established index "${definitionIndexName}": "${mismatch.definitionLabel}" != "${mismatch.providedLabel}"; Composite attribute definitions must match between all members of a collection to ensure key structures will resolve to identical Partition Keys. Please ensure these composite attribute definitions are identical for all entities associated with this service.` | ||
`${mismatch.kind} Key composite attributes provided for index "${providedIndexName}" do not match established composite attribute "${mismatch.definitionFacet}" on established index "${definitionIndexName}": "${mismatch.definitionLabel}" != "${mismatch.providedLabel}"; Composite attribute definitions must match between all members of a collection to ensure key structures will resolve to identical Partition Keys. Please ensure these composite attribute definitions are identical for all entities associated with this service.` | ||
); | ||
} else { | ||
collectionDifferences.push( | ||
`Partition Key composite attributes provided for index "${providedIndexName}" contain conflicting composite attribute labels for established composite attribute "${mismatch.definitionFacet}" on established index "${definitionIndexName}". Established composite attribute "${mismatch.definitionFacet}" on established index "${definitionIndexName}" was defined with label "${mismatch.definitionLabel}" while provided composite attribute "${mismatch.providedFacet}" on provided index "${providedIndexName}" is defined with label "${mismatch.providedLabel}". Composite attribute labels definitions must match between all members of a collection to ensure key structures will resolve to identical Partition Keys. Please ensure these labels definitions are identical for all entities associated with this service.` | ||
`${mismatch.kind} Key composite attributes provided for index "${providedIndexName}" contain conflicting composite attribute labels for established composite attribute "${mismatch.definitionFacet || ""}" on established index "${definitionIndexName}". Established composite attribute "${mismatch.definitionFacet || ""}" on established index "${definitionIndexName}" was defined with label "${mismatch.definitionLabel}" while provided composite attribute "${mismatch.providedFacet || ""}" on provided index "${providedIndexName}" is defined with label "${mismatch.providedLabel}". Composite attribute labels definitions must match between all members of a collection to ensure key structures will resolve to identical Partition Keys. Please ensure these labels definitions are identical for all entities associated with this service.` | ||
); | ||
@@ -653,3 +694,3 @@ } | ||
if (invalidDefinition) { | ||
throw new e.ElectroError(e.ErrorCodes.InvalidJoin, `Validation Error while joining entity, "${name}". ${invalidIndexMessages.join(", ")}`); | ||
throw new e.ElectroError(e.ErrorCodes.InvalidJoin, `Validation Error while joining entity, "${name}". ${invalidIndexMessages.join("; ")}`); | ||
} | ||
@@ -656,0 +697,0 @@ const sharedSortKeyAttributes = []; |
@@ -14,5 +14,15 @@ const {AttributeOperationProxy, ExpressionState} = require("./operations"); | ||
}; | ||
this.composites = {}; | ||
this.seen = new Map(); | ||
this.type = BuilderTypes.update; | ||
} | ||
addComposite(attrName, value) { | ||
if (value !== undefined) { | ||
if (this.composites[attrName] === undefined || this.composites[attrName] === value) { | ||
this.composites[attrName] = value; | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
@@ -19,0 +29,0 @@ add(type, expression) { |
@@ -50,3 +50,3 @@ const {MethodTypes, ExpressionTypes, BuilderTypes} = require("./types"); | ||
if (template === undefined) { | ||
throw new Error(`Invalid operation: "${operation}". Please report`); | ||
throw new Error(`Invalid operation: "${operation}". Please report this issue via a bug ticket.`); | ||
} | ||
@@ -53,0 +53,0 @@ const names = this.setName({}, name, name); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
464309
1
11840
- Removed@aws-sdk/lib-dynamodb@^3.54.1
- Removed@aws-crypto/sha256-browser@5.2.0(transitive)
- Removed@aws-crypto/sha256-js@5.2.0(transitive)
- Removed@aws-crypto/supports-web-crypto@5.2.0(transitive)
- Removed@aws-crypto/util@5.2.0(transitive)
- Removed@aws-sdk/client-dynamodb@3.758.0(transitive)
- Removed@aws-sdk/client-sso@3.758.0(transitive)
- Removed@aws-sdk/core@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-env@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-http@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-ini@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-node@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-process@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-sso@3.758.0(transitive)
- Removed@aws-sdk/credential-provider-web-identity@3.758.0(transitive)
- Removed@aws-sdk/endpoint-cache@3.723.0(transitive)
- Removed@aws-sdk/lib-dynamodb@3.758.0(transitive)
- Removed@aws-sdk/middleware-endpoint-discovery@3.734.0(transitive)
- Removed@aws-sdk/middleware-host-header@3.734.0(transitive)
- Removed@aws-sdk/middleware-logger@3.734.0(transitive)
- Removed@aws-sdk/middleware-recursion-detection@3.734.0(transitive)
- Removed@aws-sdk/middleware-user-agent@3.758.0(transitive)
- Removed@aws-sdk/nested-clients@3.758.0(transitive)
- Removed@aws-sdk/region-config-resolver@3.734.0(transitive)
- Removed@aws-sdk/token-providers@3.758.0(transitive)
- Removed@aws-sdk/types@3.734.0(transitive)
- Removed@aws-sdk/util-dynamodb@3.758.0(transitive)
- Removed@aws-sdk/util-endpoints@3.743.0(transitive)
- Removed@aws-sdk/util-locate-window@3.723.0(transitive)
- Removed@aws-sdk/util-user-agent-browser@3.734.0(transitive)
- Removed@aws-sdk/util-user-agent-node@3.758.0(transitive)
- Removed@smithy/abort-controller@4.0.1(transitive)
- Removed@smithy/config-resolver@4.0.1(transitive)
- Removed@smithy/core@3.1.5(transitive)
- Removed@smithy/credential-provider-imds@4.0.1(transitive)
- Removed@smithy/fetch-http-handler@5.0.1(transitive)
- Removed@smithy/hash-node@4.0.1(transitive)
- Removed@smithy/invalid-dependency@4.0.1(transitive)
- Removed@smithy/is-array-buffer@2.2.04.0.0(transitive)
- Removed@smithy/middleware-content-length@4.0.1(transitive)
- Removed@smithy/middleware-endpoint@4.0.6(transitive)
- Removed@smithy/middleware-retry@4.0.7(transitive)
- Removed@smithy/middleware-serde@4.0.2(transitive)
- Removed@smithy/middleware-stack@4.0.1(transitive)
- Removed@smithy/node-config-provider@4.0.1(transitive)
- Removed@smithy/node-http-handler@4.0.3(transitive)
- Removed@smithy/property-provider@4.0.1(transitive)
- Removed@smithy/protocol-http@5.0.1(transitive)
- Removed@smithy/querystring-builder@4.0.1(transitive)
- Removed@smithy/querystring-parser@4.0.1(transitive)
- Removed@smithy/service-error-classification@4.0.1(transitive)
- Removed@smithy/shared-ini-file-loader@4.0.1(transitive)
- Removed@smithy/signature-v4@5.0.1(transitive)
- Removed@smithy/smithy-client@4.1.6(transitive)
- Removed@smithy/types@4.1.0(transitive)
- Removed@smithy/url-parser@4.0.1(transitive)
- Removed@smithy/util-base64@4.0.0(transitive)
- Removed@smithy/util-body-length-browser@4.0.0(transitive)
- Removed@smithy/util-body-length-node@4.0.0(transitive)
- Removed@smithy/util-buffer-from@2.2.04.0.0(transitive)
- Removed@smithy/util-config-provider@4.0.0(transitive)
- Removed@smithy/util-defaults-mode-browser@4.0.7(transitive)
- Removed@smithy/util-defaults-mode-node@4.0.7(transitive)
- Removed@smithy/util-endpoints@3.0.1(transitive)
- Removed@smithy/util-hex-encoding@4.0.0(transitive)
- Removed@smithy/util-middleware@4.0.1(transitive)
- Removed@smithy/util-retry@4.0.1(transitive)
- Removed@smithy/util-stream@4.1.2(transitive)
- Removed@smithy/util-uri-escape@4.0.0(transitive)
- Removed@smithy/util-utf8@2.3.04.0.0(transitive)
- Removed@smithy/util-waiter@4.0.2(transitive)
- Removed@types/uuid@9.0.8(transitive)
- Removedbowser@2.11.0(transitive)
- Removedfast-xml-parser@4.4.1(transitive)
- Removedmnemonist@0.38.3(transitive)
- Removedobliterator@1.6.1(transitive)
- Removedstrnum@1.1.2(transitive)
- Removedtslib@2.8.1(transitive)
- Removeduuid@9.0.1(transitive)