electrodb
Advanced tools
Comparing version 0.9.13 to 0.9.14
{ | ||
"name": "electrodb", | ||
"version": "0.9.13", | ||
"version": "0.9.14", | ||
"description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -9,24 +9,2 @@ "use strict"; | ||
const utilities = { | ||
structureFacets: function ( | ||
structure, | ||
{ index, type, name }, | ||
i, | ||
attributes, | ||
indexSlot, | ||
) { | ||
let next = attributes[i + 1] !== undefined ? attributes[i + 1].name : ""; | ||
let facet = { index, name, type, next }; | ||
structure.byAttr[name] = structure.byAttr[name] || []; | ||
structure.byAttr[name].push(facet); | ||
structure.byType[type] = structure.byType[type] || []; | ||
structure.byType[type].push(facet); | ||
structure.byFacet[name] = structure.byFacet[name] || []; | ||
structure.byFacet[name][i] = structure.byFacet[name][i] || []; | ||
structure.byFacet[name][i].push(facet); | ||
structure.bySlot[i] = structure.bySlot[i] || []; | ||
structure.bySlot[i][indexSlot] = facet; | ||
} | ||
}; | ||
class Entity { | ||
@@ -61,2 +39,3 @@ constructor(model, config = {}) { | ||
} | ||
this.modelAttributeIdentifier = "__edb_e__" | ||
} | ||
@@ -210,3 +189,3 @@ | ||
formatResponse(response, config = {}) { | ||
formatResponse(index, response, config = {}) { | ||
let stackTrace = new Error(); | ||
@@ -242,5 +221,9 @@ try { | ||
} | ||
if (config.pager) { | ||
let nextPage = response.LastEvaluatedKey || null; | ||
if (!config.raw && !config.lastEvaluatedKeyRaw) { | ||
nextPage = this._formatReturnPager(index, nextPage, results[results.length - 1]); | ||
} | ||
results = [nextPage, results]; | ||
@@ -261,2 +244,101 @@ } | ||
_regexpEscape(string) { | ||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); | ||
} | ||
_deconstructKeys(index, keyType, key, backupFacets = {}) { | ||
if (typeof key !== "string" || key.length === 0) { | ||
return null; | ||
} | ||
// let index = ""; | ||
let accessPattern = this.model.translations.indexes.fromIndexToAccessPattern[index]; | ||
let {prefix, isCustom} = this.model.prefixes[index][keyType]; | ||
let {facets} = this.model.indexes[accessPattern][keyType]; | ||
let names = []; | ||
let pattern = `^${this._regexpEscape(prefix)}`; | ||
for (let facet of facets) { | ||
let { label, name } = this.model.schema.attributes[facet]; | ||
if (isCustom) { | ||
pattern += `${this._regexpEscape(label === undefined ? "" : label)}(.+)`; | ||
} else { | ||
pattern += `#${this._regexpEscape(label === undefined ? name : label)}_(.+)`; | ||
} | ||
names.push(name); | ||
} | ||
pattern += "$"; | ||
let regex = RegExp(pattern); | ||
let match = key.match(regex); | ||
let results = {} | ||
if (!match) { | ||
if (Object.keys(backupFacets || {}).length === 0) { | ||
// this can occur when a scan is performed but returns no results given the current filters or record timing | ||
return {}; | ||
} | ||
for (let facet of facets) { | ||
if (backupFacets[facet] === undefined) { | ||
throw new Error("Warning: LastEvaluatedKey contains entity that does not match the entity used to query. Use {lastEvaulatedKeyRaw: true} option."); | ||
} else { | ||
results[facet] = backupFacets[facet]; | ||
} | ||
} | ||
} else { | ||
for (let i = 0; i < names.length; i++) { | ||
results[names[i]] = match[i+1]; | ||
} | ||
} | ||
return results; | ||
} | ||
_deconstructIndex(index = "", lastEvaluated, lastReturned) { | ||
let pkName = this.model.translations.keys[index].pk; | ||
let skName = this.model.translations.keys[index].sk; | ||
let pkFacets = this._deconstructKeys(index, KeyTypes.pk, lastEvaluated[pkName], lastReturned); | ||
let skFacets = this._deconstructKeys(index, KeyTypes.sk, lastEvaluated[skName], lastReturned); | ||
let facets = {...pkFacets}; | ||
if (skFacets && Object.keys(skFacets).length) { | ||
facets = {...skFacets, ...pkFacets}; | ||
} | ||
return facets; | ||
} | ||
_formatReturnPager(index = "", lastEvaluated, lastReturned) { | ||
if (lastEvaluated === null || typeof lastEvaluated !== "object" || Object.keys(lastEvaluated).length === 0) { | ||
return lastEvaluated; | ||
} | ||
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 | ||
if (index !== tableIndex) { | ||
pager = {...pager, ...this._deconstructIndex(tableIndex, lastEvaluated, lastReturned)}; | ||
} | ||
if (Object.keys(pager).length === 0) { | ||
// In this case no suitable record could be found be the deconstructed pager. | ||
// This can be valid in cases where a scan is performed but returns no results. | ||
return null; | ||
} | ||
return pager; | ||
} | ||
_constructPagerIndex(index = "", item) { | ||
let pk = this._expectFacets(item, this.model.facets.byIndex[index].pk) | ||
let sk = this._expectFacets(item, this.model.facets.byIndex[index].sk) | ||
let keys = this._makeIndexKeys(index, pk, sk); | ||
return this._makeParameterKey(index, keys.pk, ...keys.sk); | ||
} | ||
_formatSuppliedPager(index = "", item) { | ||
if (typeof item !== "object" || Object.keys(item).length === 0) { | ||
return item; | ||
} | ||
let tableIndex = ""; | ||
let pager = this._constructPagerIndex(index, item); | ||
if (index !== tableIndex) { | ||
pager = {...pager, ...this._constructPagerIndex(tableIndex, item)} | ||
} | ||
return pager | ||
} | ||
_applyParameterOptions(params, ...options) { | ||
@@ -277,2 +359,3 @@ let config = { | ||
if (option.pager) config.pager = true; | ||
if (option.lastEvaluatedKeyRaw === true) config.lastEvaluatedKeyRaw = true; | ||
config.page = Object.assign({}, config.page, option.page); | ||
@@ -292,3 +375,7 @@ config.params = Object.assign({}, config.params, option.params); | ||
if (Object.keys(config.page || {}).length) { | ||
parameters.ExclusiveStartKey = config.page; | ||
if (config.raw || config.lastEvaluatedKeyRaw) { | ||
parameters.ExclusiveStartKey = config.page; | ||
} else { | ||
parameters.ExclusiveStartKey = this._formatSuppliedPager(params.IndexName, config.page); | ||
} | ||
} | ||
@@ -306,3 +393,4 @@ | ||
page: options.page, | ||
pager: !!options.pager | ||
pager: !!options.pager, | ||
lastEvaluatedKeyRaw: !!options.lastEvaluatedKeyRaw | ||
}; | ||
@@ -315,5 +403,5 @@ let parameters = Object.assign({}, params); | ||
// a VERY hacky way to deal with PUTs | ||
return this.formatResponse(parameters, config); | ||
return this.formatResponse(parameters.IndexName, parameters, config); | ||
} else { | ||
return this.formatResponse(response, config); | ||
return this.formatResponse(parameters.IndexName, response, config); | ||
} | ||
@@ -414,3 +502,3 @@ } catch (err) { | ||
let hasSortKey = this.model.lookup.indexHasSortKeys[indexBase]; | ||
let facets = this.model.facets.byIndex[indexBase]; | ||
// let facets = this.model.facets.byIndex[indexBase]; | ||
let {pk, sk} = this._makeIndexKeys(indexBase); | ||
@@ -428,3 +516,3 @@ let keys = this._makeParameterKey( | ||
filter.ExpressionAttributeNames, | ||
keyExpressions.ExpressionAttributeNames, | ||
keyExpressions.ExpressionAttributeNames | ||
), | ||
@@ -437,2 +525,5 @@ ExpressionAttributeValues: this._mergeExpressionsAttributes( | ||
}; | ||
params.ExpressionAttributeNames["#" + this.modelAttributeIdentifier] = this.modelAttributeIdentifier; | ||
params.ExpressionAttributeValues[":" + this.modelAttributeIdentifier] = this.model.entity; | ||
params.FilterExpression = `${params.FilterExpression} AND #${this.modelAttributeIdentifier} = :${this.modelAttributeIdentifier}` | ||
if (hasSortKey) { | ||
@@ -490,3 +581,3 @@ params.FilterExpression = `${params.FilterExpression} AND begins_with(#sk, :sk))`; | ||
...updatedKeys, | ||
__edb_e__: this.model.entity, | ||
[this.modelAttributeIdentifier]: this.model.entity, | ||
}, | ||
@@ -751,7 +842,7 @@ TableName: this.model.table, | ||
throw new Error( | ||
`Incomplete facets: Without the facets ${incomplete | ||
`Incomplete facets: Without the facets '${incomplete | ||
.filter((val) => val !== undefined) | ||
.join( | ||
", ", | ||
)} the following access patterns ${incompleteAccessPatterns | ||
)}' the following access patterns ${incompleteAccessPatterns | ||
.filter((val) => val !== undefined) | ||
@@ -930,7 +1021,46 @@ .join(", ")}cannot be updated.`, | ||
_makeKeyPrefixes(service, entity, version = "1") { | ||
return { | ||
pk: `$${service}_${version}`, | ||
sk: `$${entity}`, | ||
}; | ||
_makeKeyPrefixes(service, entity, version = "1", tableIndex) { | ||
/* | ||
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: tableIndex.customFacets.pk | ||
}, | ||
sk: { | ||
prefix: "", | ||
isCustom: tableIndex.customFacets.sk | ||
} | ||
} | ||
let pk = `$${service}_${version}`; | ||
let sk = ""; | ||
// If the index is in a collections, prepend the sk; | ||
if (tableIndex.collection) { | ||
sk = `$${tableIndex.collection}#${entity}` | ||
} else { | ||
sk = `$${entity}` | ||
} | ||
// If no sk, append the sk properties to the pk | ||
if (Object.keys(tableIndex.sk).length === 0) { | ||
pk += sk; | ||
} | ||
// If keys arent custom, set the prefixes | ||
if (!keys.pk.isCustom) { | ||
keys.pk.prefix = pk.toLowerCase(); | ||
} | ||
if (!keys.sk.isCustom) { | ||
keys.sk.prefix = sk.toLowerCase(); | ||
} | ||
return keys; | ||
} | ||
@@ -1005,4 +1135,6 @@ | ||
let facets = this.model.facets.byIndex[index]; | ||
let prefixes = this._getPrefixes(facets); | ||
// let sk = []; | ||
let prefixes = this.model.prefixes[index]; | ||
if (!prefixes) { | ||
throw new Error(`Invalid index: ${index}`); | ||
} | ||
let pk = this._makeKey( | ||
@@ -1032,5 +1164,5 @@ prefixes.pk.prefix, | ||
if (isCustom) { | ||
key = `${key}${label}`; | ||
key = `${key}${label === undefined ? "" : label}`; | ||
} else { | ||
key = `${key}#${label || name}_`; | ||
key = `${key}#${label === undefined ? name : label}_`; | ||
} | ||
@@ -1188,3 +1320,5 @@ if (supplied[name] !== undefined) { | ||
customFacets.pk = parsedPKFacets.isCustom; | ||
// labels can be set via the attribute definiton or as part of the facetTemplate. | ||
facets.labels = Object.assign({}, facets.labels, facetLabels); | ||
let pk = { | ||
@@ -1197,9 +1331,10 @@ accessPattern, | ||
facets: [...facetArray], | ||
isCustom: parsedPKFacets.isCustom | ||
}; | ||
let sk = {}; | ||
let parsedSKFacets = {} | ||
if (hasSk) { | ||
let parseSKFacets = this._parseFacets(index.sk.facets); | ||
let { facetArray, facetLabels } = parseSKFacets; | ||
customFacets.sk = parseSKFacets.isCustom; | ||
parsedSKFacets = this._parseFacets(index.sk.facets); | ||
let { facetArray, facetLabels } = parsedSKFacets; | ||
customFacets.sk = parsedSKFacets.isCustom; | ||
facets.labels = Object.assign({}, facets.labels, facetLabels); | ||
@@ -1213,2 +1348,3 @@ sk = { | ||
facets: [...facetArray], | ||
isCustom: parsedSKFacets.isCustom | ||
}; | ||
@@ -1280,6 +1416,17 @@ facets.fields.push(sk.field); | ||
}; | ||
attributes.forEach((facet, j) => | ||
utilities.structureFacets(facets, facet, j, attributes, i), | ||
); | ||
attributes.forEach(({index, type, name}, j) => { | ||
let next = attributes[j + 1] !== undefined ? attributes[j + 1].name : ""; | ||
let facet = { index, name, type, next }; | ||
facets.byAttr[name] = facets.byAttr[name] || []; | ||
facets.byAttr[name].push(facet); | ||
facets.byType[type] = facets.byType[type] || []; | ||
facets.byType[type].push(facet); | ||
facets.byFacet[name] = facets.byFacet[name] || []; | ||
facets.byFacet[name][j] = facets.byFacet[name][j] || []; | ||
facets.byFacet[name][j].push(facet); | ||
facets.bySlot[j] = facets.bySlot[j] || []; | ||
facets.bySlot[j][i] = facet; | ||
}); | ||
} | ||
@@ -1290,3 +1437,3 @@ | ||
} | ||
return { | ||
@@ -1320,5 +1467,14 @@ facets, | ||
_normalizePrefixes(service, entity, version, indexes) { | ||
let prefixes = {}; | ||
for (let accessPattern of Object.keys(indexes)) { | ||
let item = indexes[accessPattern]; | ||
prefixes[item.index] = this._makeKeyPrefixes(service, entity, version, item); | ||
} | ||
return prefixes; | ||
} | ||
_parseModel(model) { | ||
let { service, entity, table, version = "1" } = model; | ||
let prefixes = this._makeKeyPrefixes(service, entity, version); | ||
let { | ||
@@ -1335,2 +1491,3 @@ facets, | ||
let filters = this._normalizeFilters(model.filters); | ||
let prefixes = this._normalizePrefixes(service, entity, version, indexes); | ||
return { | ||
@@ -1337,0 +1494,0 @@ service, |
@@ -8,3 +8,3 @@ const { KeyTypes, CastTypes, AttributeTypes } = require("./types"); | ||
this.field = definition.field || definition.name; | ||
this.label = definition.label || ""; | ||
this.label = definition.label; | ||
this.readOnly = !!definition.readOnly; | ||
@@ -11,0 +11,0 @@ this.required = !!definition.required; |
@@ -62,7 +62,7 @@ const __is_clause__ = Symbol("IsWhereClause"); | ||
return expression.trim(); | ||
} else if (typeof property === "string") { | ||
// todo: parse string | ||
// } else if (typeof property === "string") { | ||
// // todo: parse string | ||
} else { | ||
// todo: proper error logging. | ||
throw new Error("INVALID PROPERTY") | ||
throw new Error(`Invalid Attribute in where clause passed to operation '${type}'. Use injected attributes only.`); | ||
} | ||
@@ -121,3 +121,3 @@ } | ||
if (typeof expression !== "string") { | ||
throw new Error("Invalid filter response. Expected result to be of type string"); | ||
throw new Error("Invalid response from where clause callback. Expected return result to be of type string"); | ||
} | ||
@@ -124,0 +124,0 @@ state.query.filter[expressionType] = this._concatFilterExpression( |
@@ -0,1 +1,3 @@ | ||
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); | ||
process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1; | ||
@@ -12,7 +14,2 @@ const { Entity } = require("../src/entity"); | ||
const ENTITY = "TEST_ENTITY" | ||
function sleep(ms) { | ||
return new Promise((resolve) => { | ||
setTimeout(resolve, ms); | ||
}); | ||
} | ||
let model = { | ||
@@ -143,2 +140,3 @@ service: SERVICE, | ||
describe("Entity", async () => { | ||
before(async () => sleep(1000)) | ||
let MallStores = new Entity(model, { client }); | ||
@@ -344,3 +342,23 @@ describe("Simple crud", async () => { | ||
expect(patchResultsTwo).to.be.null | ||
}) | ||
}); | ||
it("Should pass back the original dynamodb error when originalErr is set to true", async () => { | ||
let id = uuidv4(); | ||
let sector = "A1"; | ||
let [electroSuccess, electroErr] = await MallStores.get({sector, id}) | ||
.go({params: {TableName: "blahblah"}}) | ||
.then(() => [true, null]) | ||
.catch(err => [false, err]); | ||
let [originalSuccess, originalErr] = await MallStores.get({sector, id}) | ||
.go({originalErr: true, params: {TableName: "blahblah"}}) | ||
.then(() => [true, null]) | ||
.catch(err => [false, err]); | ||
expect(electroSuccess).to.be.false; | ||
expect(electroErr.stack.split(/\r?\n/)[1].includes("aws-sdk")).to.be.false; | ||
expect(originalSuccess).to.be.false; | ||
expect(originalErr.stack.split(/\r?\n/)[1].includes("aws-sdk")).to.be.true; | ||
}); | ||
}); | ||
@@ -392,47 +410,2 @@ | ||
// describe("scan", async () => { | ||
// it ("Should scan for created records", async () => { | ||
// let entity = uuidv4(); | ||
// let db = new Entity({ | ||
// service: "testing", | ||
// entity: entity, | ||
// table: "electro", | ||
// version: "1", | ||
// attributes: { | ||
// id: { | ||
// type: "string" | ||
// }, | ||
// bb: { | ||
// type: "string" | ||
// } | ||
// }, | ||
// indexes: { | ||
// main: { | ||
// pk: { | ||
// field: "pk", | ||
// facets: ["id"] | ||
// }, | ||
// sk: { | ||
// field: "sk", | ||
// facets: ["id"] | ||
// } | ||
// } | ||
// } | ||
// }, {client}); | ||
// let puts = []; | ||
// for (let i = 0; i < 5; i++) { | ||
// console.log("putz", db.put({id: `${i}`, bb: `${i}`}).params()); | ||
// puts.push(db.put({id: `${i}`, bb: `${i}`}).go({})); | ||
// } | ||
// await Promise.all(puts); | ||
// await sleep(250); | ||
// let recordparams = db.scan.filter(({id}) => id.gte("3")).params(); | ||
// let records = await db.scan.filter(({id}) => id.gte("3")).go(); | ||
// if (!records.length) { | ||
// console.log("ENTITYz", recordparams); | ||
// } | ||
// expect(records).to.be.an("array").and.to.have.lengthOf(3); | ||
// }) | ||
// }) | ||
describe("Getters/Setters", async () => { | ||
@@ -794,12 +767,14 @@ let db = new Entity( | ||
let [index, stores] = results; | ||
if (stores.length) { | ||
expect(index).to.have.a.property('pk').and.to.have.a.property('sk'); | ||
if (stores && stores.Items.length) { | ||
expect(index).to.have.a.property('pk'); | ||
expect(index).to.have.a.property('sk') | ||
expect(stores.Items).to.be.an("array") | ||
expect(stores.Items[0]).to.have.a.property('pk').and.to.have.a.property('sk'); | ||
let [nextIndex, nextStores] = await MallStores.scan.page(index); | ||
expect(stores).to.be.an("array").and.have.length(2); | ||
expect(stores.Items[0]).to.have.a.property('pk') | ||
expect(stores.Items[0]).to.have.a.property('sk'); | ||
let [nextIndex, nextStores] = await MallStores.scan.page(index, {raw: true}); | ||
expect(nextIndex).to.not.deep.equal(index); | ||
expect(nextStores).to.be.an("array"); | ||
if (nextStores.length) { | ||
expect(nextStores[0]).to.not.have.a.property('pk').and.to.not.have.a.property('sk'); | ||
expect(nextStores.Items).to.be.an("array"); | ||
if (nextStores.Items.length) { | ||
expect(nextStores.Items[0]).to.have.a.property('pk'); | ||
expect(nextStores.Items[0]).to.have.a.property('sk'); | ||
} | ||
@@ -806,0 +781,0 @@ } |
@@ -0,1 +1,2 @@ | ||
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); | ||
process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1; | ||
@@ -13,2 +14,3 @@ const { Entity, clauses } = require("../src/entity"); | ||
describe("General", async () => { | ||
before(async () => sleep(1000)) | ||
let FilterTests = new Entity({ | ||
@@ -15,0 +17,0 @@ service: "tests", |
@@ -0,1 +1,2 @@ | ||
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); | ||
process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1; | ||
@@ -272,2 +273,3 @@ const { Entity, clauses } = require("../src/entity"); | ||
describe("Put and query", async () => { | ||
before(async () => sleep(1000)) | ||
it("Should add three records and retrieve correct records based on collections", async () => { | ||
@@ -274,0 +276,0 @@ let recordOne = { |
@@ -0,1 +1,2 @@ | ||
const sleep = async (ms) => new Promise((resolve) => setTimeout(resolve, ms)); | ||
process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1; | ||
@@ -13,2 +14,3 @@ const { Entity, clauses } = require("../src/entity"); | ||
describe("General", async () => { | ||
before(async () => sleep(1000)) | ||
let WhereTests = new Entity({ | ||
@@ -36,2 +38,5 @@ service: "tests", | ||
type: "boolean" | ||
}, | ||
complex: { | ||
type: "any" | ||
} | ||
@@ -241,6 +246,2 @@ }, | ||
.go(); | ||
console.log("WHERE", WhereTests.query | ||
.farm({pen}) | ||
.where(({animal, dangerous}, {value, name, between}) => `${name(animal)} = ${value(animal, "Pig")} AND ${between(dangerous, "2020-09-25", "2020-09-28")}`) | ||
.params()) | ||
expect(animals) | ||
@@ -345,3 +346,59 @@ .to.be.an("array") | ||
.params()).to.throw("notReal is not a function") | ||
}) | ||
}); | ||
it("Should allow for complex types in where clause", () => { | ||
let params = WhereTests.query.farm({pen}) | ||
.where(({complex}, {gte}) => ` | ||
${gte(complex[0].coordinates.y, -56.0344)} | ||
`) | ||
.params(); | ||
expect(params).to.deep.equal({ | ||
KeyConditionExpression: '#pk = :pk and begins_with(#sk1, :sk1)', | ||
TableName: 'electro', | ||
ExpressionAttributeNames: { | ||
'#complex': 'complex', | ||
'#coordinates': 'coordinates', | ||
'#y': 'y', | ||
'#pk': 'pk', | ||
'#sk1': 'sk' | ||
}, | ||
ExpressionAttributeValues: { | ||
':complex_w1': -56.0344, | ||
':pk': `$tests_1#pen_${pen}`, | ||
':sk1': '$filters#row_' | ||
}, | ||
FilterExpression: '\n\t\t\t\t#complex[0].#coordinates.#y >= :complex_w1\n\t\t\t' | ||
}) | ||
}); | ||
it("Should not allow random values to passed to where operations", () => { | ||
let query = () => WhereTests.query.farm({pen}).where((attr, op) => op.eq({}, "invalid")).params(); | ||
expect(query).to.throw(`Invalid Attribute in where clause passed to operation 'eq'. Use injected attributes only.`); | ||
}); | ||
it("Must validate the response of a where clause callback is a string", () => { | ||
let query = () => WhereTests.query.farm({pen}).where((attr, op) => null).params(); | ||
expect(query).to.throw("Invalid response from where clause callback. Expected return result to be of type string"); | ||
}); | ||
it("Where clause should be able to be used more than once, which will cause an implicit 'and'", () => { | ||
let params = WhereTests.query.farm({pen}).where(({animal}, {eq}) => eq(animal, "Chicken")).where(({dangerous}, {eq}) => eq(dangerous, true)).params(); | ||
expect(params).to.deep.equal({ | ||
KeyConditionExpression: '#pk = :pk and begins_with(#sk1, :sk1)', | ||
TableName: 'electro', | ||
ExpressionAttributeNames: { | ||
'#animal': 'animal', | ||
'#dangerous': 'dangerous', | ||
'#pk': 'pk', | ||
'#sk1': 'sk' | ||
}, | ||
ExpressionAttributeValues: { | ||
':animal_w1': 'Chicken', | ||
':dangerous_w1': true, | ||
':pk': `$tests_1#pen_${pen}`, | ||
':sk1': '$filters#row_' | ||
}, | ||
FilterExpression: '(#animal = :animal_w1) AND #dangerous = :dangerous_w1' | ||
}); | ||
}); | ||
}) |
@@ -755,2 +755,3 @@ const { Entity, clauses } = require("../src/entity"); | ||
"ExpressionAttributeNames": { | ||
"#__edb_e__": "__edb_e__", | ||
"#pk": "pk", | ||
@@ -760,6 +761,7 @@ "#store": "storeId" | ||
"ExpressionAttributeValues": { | ||
":__edb_e__": "MallStores", | ||
":pk": "$mallstoredirectory_1$mallstores#id_", | ||
":store1": "Starblix" | ||
}, | ||
"FilterExpression": "(begins_with(#pk, :pk) AND #store = :store1", | ||
"FilterExpression": "(begins_with(#pk, :pk) AND #__edb_e__ = :__edb_e__ AND #store = :store1", | ||
"TableName": "StoreDirectory" | ||
@@ -1862,8 +1864,9 @@ }) | ||
TableName: 'StoreDirectory', | ||
ExpressionAttributeNames: { '#leaseEnd': 'leaseEnd', '#pk': 'pk' }, | ||
ExpressionAttributeNames: { "#__edb_e__": "__edb_e__", '#leaseEnd': 'leaseEnd', '#pk': 'pk' }, | ||
ExpressionAttributeValues: { | ||
":__edb_e__": "MallStores", | ||
':leaseEnd1': '123', | ||
':pk': '$mallstoredirectory_1$mallstores#id_' | ||
}, | ||
FilterExpression: '(begins_with(#pk, :pk) AND #leaseEnd = :leaseEnd1' | ||
FilterExpression: "(begins_with(#pk, :pk) AND #__edb_e__ = :__edb_e__ AND #leaseEnd = :leaseEnd1" | ||
}); | ||
@@ -1885,3 +1888,3 @@ expect(shouldScan).to.be.true; | ||
KeyConditionExpression: '#pk = :pk', | ||
FilterExpression: '#id = :id1' | ||
FilterExpression: "#id = :id1" | ||
}); | ||
@@ -1888,0 +1891,0 @@ expect(keys).to.be.deep.equal([{ name: "id", type: "pk" }]); |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
393765
25
8526
2265
6