electrodb
Advanced tools
Comparing version 0.9.34 to 0.9.35
{ | ||
"name": "electrodb", | ||
"version": "0.9.34", | ||
"version": "0.9.35", | ||
"description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb", | ||
@@ -24,12 +24,12 @@ "main": "index.js", | ||
"devDependencies": { | ||
"aws-sdk": "^2.630.0", | ||
"chai": "^4.2.0", | ||
"coveralls": "^3.0.13", | ||
"istanbul": "^0.4.5", | ||
"jest": "^25.4.0", | ||
"aws-sdk": "2.630.0", | ||
"chai": "4.2.0", | ||
"coveralls": "3.0.13", | ||
"istanbul": "0.4.5", | ||
"jest": "25.4.0", | ||
"mocha": "7.1.1", | ||
"mocha-lcov-reporter": "^1.3.0", | ||
"moment": "^2.24.0", | ||
"nyc": "^15.0.0", | ||
"uuid": "^7.0.1" | ||
"mocha-lcov-reporter": "1.3.0", | ||
"moment": "2.24.0", | ||
"nyc": "15.0.0", | ||
"uuid": "7.0.1" | ||
}, | ||
@@ -36,0 +36,0 @@ "keywords": [ |
@@ -14,6 +14,7 @@ "use strict"; | ||
this._validateModel(model); | ||
this.config = config; | ||
this.client = config.client; | ||
this.model = this._parseModel(model, config); | ||
/** start beta/v1 condition **/ | ||
this.model.table = config.table || model.table; | ||
this.config.table = config.table || model.table; | ||
/** end beta/v1 condition **/ | ||
@@ -32,6 +33,6 @@ this._filterBuilder = new FilterFactory(this.model.schema.attributes, FilterTypes); | ||
} | ||
config.identifiers = config.identifiers || {}; | ||
this.config.identifiers = config.identifiers || {}; | ||
this.identifiers = { | ||
entity: config.identifiers.entity || "__edb_e__", | ||
version: config.identifiers.version || "__edb_v__", | ||
entity: this.config.identifiers.entity || "__edb_e__", | ||
version: this.config.identifiers.version || "__edb_v__", | ||
}; | ||
@@ -150,24 +151,44 @@ this._instance = ElectroInstance.entity; | ||
_chain(state, clauses, clause) { | ||
let current = {}; | ||
for (let child of clause.children) { | ||
current[child] = (...args) => { | ||
state.prev = state.self; | ||
state.self = child; | ||
let results = clauses[child].action(this, state, ...args); | ||
if (clauses[child].children.length) { | ||
return this._chain(results, clauses, clauses[child]); | ||
async go(method, params = {}, options = {}) { | ||
let config = { | ||
includeKeys: options.includeKeys, | ||
originalErr: options.originalErr, | ||
raw: options.raw, | ||
params: options.params || {}, | ||
page: options.page, | ||
pager: !!options.pager, | ||
lastEvaluatedKeyRaw: !!options.lastEvaluatedKeyRaw | ||
}; | ||
let parameters = Object.assign({}, params); | ||
let stackTrace = new e.ElectroError(e.ErrorCodes.AWSError); | ||
try { | ||
let response = await this.client[method](parameters).promise().catch(err => { | ||
err.__isAWSError = true; | ||
throw err; | ||
}); | ||
switch (method) { | ||
case MethodTypes.put: | ||
case MethodTypes.create: | ||
return this.formatResponse(parameters.IndexName, parameters, config); | ||
case MethodTypes.batchWrite: | ||
return this.formatBulkResponse(parameters.IndexName, response, config); | ||
default: | ||
return this.formatResponse(parameters.IndexName, response, config); | ||
} | ||
} catch (err) { | ||
if (config.originalErr) { | ||
return Promise.reject(err); | ||
} else { | ||
if (err.__isAWSError) { | ||
stackTrace.message = new e.ElectroError(e.ErrorCodes.AWSError, err.message).message; | ||
return Promise.reject(stackTrace); | ||
} else if (err.isElectroError) { | ||
return Promise.reject(err); | ||
} else { | ||
return results; | ||
stackTrace.message = new e.ElectroError(e.ErrorCodes.UnknownError, err.message).message; | ||
return Promise.reject(stackTrace); | ||
} | ||
}; | ||
} | ||
} | ||
return current; | ||
} | ||
/* istanbul ignore next */ | ||
_makeChain(index = "", clauses, rootClause, options = {}) { | ||
let facets = this.model.facets.byIndex[index]; | ||
let state = initChainState(index, facets, this.model.lookup.indexHasSortKeys[index], options); | ||
return this._chain(state, clauses, rootClause); | ||
} | ||
@@ -193,3 +214,4 @@ cleanseRetrievedData(item = {}, options = {}) { | ||
} | ||
let unProcessed = response.UnprocessedItems[this.model.table]; | ||
let table = this._getTableName(); | ||
let unProcessed = response.UnprocessedItems[table]; | ||
if (Array.isArray(unProcessed) && unProcessed.length) { | ||
@@ -264,4 +286,31 @@ return unProcessed.map(request => { | ||
_getTableName() { | ||
return this.config.table; | ||
} | ||
_chain(state, clauses, clause) { | ||
let current = {}; | ||
for (let child of clause.children) { | ||
current[child] = (...args) => { | ||
state.prev = state.self; | ||
state.self = child; | ||
let results = clauses[child].action(this, state, ...args); | ||
if (clauses[child].children.length) { | ||
return this._chain(results, clauses, clauses[child]); | ||
} else { | ||
return results; | ||
} | ||
}; | ||
} | ||
return current; | ||
} | ||
/* istanbul ignore next */ | ||
_makeChain(index = "", clauses, rootClause, options = {}) { | ||
let facets = this.model.facets.byIndex[index]; | ||
let state = initChainState(index, facets, this.model.lookup.indexHasSortKeys[index], options); | ||
return this._chain(state, clauses, rootClause); | ||
} | ||
_regexpEscape(string) { | ||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); | ||
} | ||
@@ -279,4 +328,6 @@ | ||
let pattern = `^${this._regexpEscape(prefix)}`; | ||
let labels = this.model.facets.labels[index]; | ||
for (let facet of facets) { | ||
let { label, name } = this.model.schema.attributes[facet]; | ||
let { name } = this.model.schema.attributes[facet]; | ||
let label = labels[facet]; | ||
if (isCustom) { | ||
@@ -307,3 +358,3 @@ pattern += `${this._regexpEscape(label === undefined ? "" : label)}(.+)`; | ||
for (let i = 0; i < names.length; i++) { | ||
results[names[i]] = match[i+1]; | ||
results[names[i]] = match[i+1]; | ||
} | ||
@@ -314,2 +365,4 @@ } | ||
_deconstructIndex(index = "", lastEvaluated, lastReturned) { | ||
@@ -331,5 +384,4 @@ let pkName = this.model.translations.keys[index].pk; | ||
} | ||
let tableIndex = ""; | ||
let pager = this._deconstructIndex(index, lastEvaluated, lastReturned); | ||
let tableIndex = ""; | ||
// lastEvaluatedKeys from query calls include the index pk/sk as well as the table index's pk/sk | ||
@@ -339,4 +391,5 @@ if (index !== tableIndex) { | ||
} | ||
if (Object.keys(pager).length === 0) { | ||
let pagerIsEmpty = Object.keys(pager).length === 0; | ||
let pagerIsIncomplete = this.model.facets.byIndex[tableIndex].all.find(facet => pager[facet.name] === undefined); | ||
if (pagerIsEmpty || pagerIsIncomplete) { | ||
// In this case no suitable record could be found be the deconstructed pager. | ||
@@ -385,2 +438,4 @@ // This can be valid in cases where a scan is performed but returns no results. | ||
if (option.lastEvaluatedKeyRaw === true) config.lastEvaluatedKeyRaw = true; | ||
if (option.limit) config.params.Limit = option.limit; | ||
if (option.table) config.params.Limit = option.table; | ||
config.page = Object.assign({}, config.page, option.page); | ||
@@ -410,46 +465,2 @@ config.params = Object.assign({}, config.params, option.params); | ||
async go(method, params = {}, options = {}) { | ||
let config = { | ||
includeKeys: options.includeKeys, | ||
originalErr: options.originalErr, | ||
raw: options.raw, | ||
params: options.params || {}, | ||
page: options.page, | ||
pager: !!options.pager, | ||
lastEvaluatedKeyRaw: !!options.lastEvaluatedKeyRaw | ||
}; | ||
let parameters = Object.assign({}, params); | ||
let stackTrace = new e.ElectroError(e.ErrorCodes.AWSError); | ||
try { | ||
let response = await this.client[method](parameters).promise().catch(err => { | ||
err.__isAWSError = true; | ||
throw err; | ||
}); | ||
switch (method) { | ||
case MethodTypes.put: | ||
case MethodTypes.create: | ||
return this.formatResponse(parameters.IndexName, parameters, config); | ||
case MethodTypes.batchWrite: | ||
return this.formatBulkResponse(parameters.IndexName, response, config); | ||
default: | ||
return this.formatResponse(parameters.IndexName, response, config); | ||
} | ||
} catch (err) { | ||
if (config.originalErr) { | ||
return Promise.reject(err); | ||
} else { | ||
if (err.__isAWSError) { | ||
stackTrace.message = new e.ElectroError(e.ErrorCodes.AWSError, err.message).message; | ||
return Promise.reject(stackTrace); | ||
} else if (err.isElectroError) { | ||
return Promise.reject(err); | ||
} else { | ||
stackTrace.message = new e.ElectroError(e.ErrorCodes.UnknownError, err.message).message; | ||
return Promise.reject(stackTrace); | ||
} | ||
} | ||
} | ||
} | ||
_makeCreateConditions(index) { | ||
@@ -523,2 +534,3 @@ let filter = [`attribute_not_exists(pk)`]; | ||
_batchWriteParams(state, config = {}) { | ||
let table = this._getTableName(); | ||
let batch = []; | ||
@@ -544,3 +556,3 @@ for (let itemState of state.batch.items) { | ||
RequestItems: { | ||
[this.model.table]: batch | ||
[table]: batch | ||
} | ||
@@ -587,3 +599,3 @@ } | ||
let params = { | ||
TableName: this.model.table, | ||
TableName: this._getTableName(), | ||
ExpressionAttributeNames: this._mergeExpressionsAttributes( | ||
@@ -617,3 +629,3 @@ filter.ExpressionAttributeNames, | ||
let Key = this._makeParameterKey(index, keys.pk, ...keys.sk); | ||
let TableName = this.model.table; | ||
let TableName = this._getTableName(); | ||
return {Key, TableName}; | ||
@@ -643,3 +655,3 @@ } | ||
ExpressionAttributeValues, | ||
TableName: this.model.table, | ||
TableName: this._getTableName(), | ||
Key: indexKey, | ||
@@ -662,3 +674,3 @@ }; | ||
}, | ||
TableName: this.model.table, | ||
TableName: this._getTableName(), | ||
}; | ||
@@ -822,3 +834,3 @@ } | ||
let params = { | ||
TableName: this.model.table, | ||
TableName: this._getTableName(), | ||
ExpressionAttributeNames: this._mergeExpressionsAttributes( | ||
@@ -856,3 +868,3 @@ filter.ExpressionAttributeNames, | ||
KeyConditionExpression, | ||
TableName: this.model.table, | ||
TableName: this._getTableName(), | ||
ExpressionAttributeNames: this._mergeExpressionsAttributes(filter.ExpressionAttributeNames, keyExpressions.ExpressionAttributeNames, customExpressions.names), | ||
@@ -893,3 +905,3 @@ ExpressionAttributeValues: this._mergeExpressionsAttributes(filter.ExpressionAttributeValues, keyExpressions.ExpressionAttributeValues, customExpressions.values), | ||
let params = { | ||
TableName: this.model.table, | ||
TableName: this._getTableName(), | ||
ExpressionAttributeNames: this._mergeExpressionsAttributes( | ||
@@ -1159,48 +1171,2 @@ filter.ExpressionAttributeNames, | ||
/* istanbul ignore next */ | ||
// _getPrefixes({ collection = "", customFacets = {}, sk } = {}) { | ||
// /* | ||
// Collections will prefix the sort key so they can be queried with | ||
// a "begins_with" operator when crossing entities. It is also possible | ||
// that the user defined a custom key on either the PK or SK. In the case | ||
// of a customKey AND a collection, the collection is ignored to favor | ||
// the custom key. | ||
// */ | ||
// | ||
// let keys = { | ||
// pk: { | ||
// prefix: "", | ||
// isCustom: false, | ||
// }, | ||
// sk: { | ||
// prefix: "", | ||
// isCustom: false, | ||
// }, | ||
// }; | ||
// | ||
// if (collection) { | ||
// keys.pk.prefix = this.model.prefixes.pk; | ||
// keys.sk.prefix = `$${collection}#${this.model.entity}`; | ||
// } else { | ||
// keys.pk.prefix = this.model.prefixes.pk; | ||
// keys.sk.prefix = this.model.prefixes.sk; | ||
// } | ||
// | ||
// if (sk === undefined) { | ||
// keys.pk.prefix += keys.sk.prefix; | ||
// } | ||
// | ||
// if (customFacets.pk) { | ||
// keys.pk.prefix = ""; | ||
// keys.pk.isCustom = customFacets.pk; | ||
// } | ||
// | ||
// if (customFacets.sk) { | ||
// keys.sk.prefix = ""; | ||
// keys.sk.isCustom = customFacets.sk; | ||
// } | ||
// | ||
// return keys; | ||
// } | ||
/* istanbul ignore next */ | ||
_makeIndexKeys(index = "", pkFacets = {}, ...skFacets) { | ||
@@ -1505,3 +1471,2 @@ this._validateIndex(index); | ||
attributes.forEach(({index, type, name}, j) => { | ||
@@ -1508,0 +1473,0 @@ let next = attributes[j + 1] !== undefined ? attributes[j + 1].name : ""; |
@@ -245,2 +245,3 @@ const { KeyTypes, CastTypes, AttributeTypes } = require("./types"); | ||
}; | ||
if (facets.byAttr[definition.name] !== undefined && (!ValidFacetTypes.includes(definition.type) && !Array.isArray(definition.type))) { | ||
@@ -250,2 +251,3 @@ let assignedIndexes = facets.byAttr[name].map(assigned => assigned.index === "" ? "Table Index" : assigned.index); | ||
} | ||
if (usedAttrs[definition.field] || usedAttrs[name]) { | ||
@@ -263,2 +265,3 @@ invalidProperties.push({ | ||
} | ||
translationForTable[definition.name] = definition.field; | ||
@@ -265,0 +268,0 @@ translationForRetrieval[definition.field] = definition.name; |
Sorry, the diff of this file is too big to display
2848
246703
3452