Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

electrodb

Package Overview
Dependencies
Maintainers
1
Versions
163
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

electrodb - npm Package Compare versions

Comparing version 0.9.7 to 0.9.8

2

package.json
{
"name": "electrodb",
"version": "0.9.7",
"version": "0.9.8",
"description": "A library to more easily create and interact with multiple entities and heretical relationships in dynamodb",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -11,3 +11,3 @@ const { QueryTypes, MethodTypes } = require("./types");

// },
children: ["get", "delete", "update", "query", "put", "scan", "collection"],
children: ["get", "delete", "update", "query", "put", "scan", "collection", "create", "patch"],

@@ -17,3 +17,4 @@ },

name: "collection",
action(entity, state, collection /* istanbul ignore next */ = "", facets /* istanbul ignore next */ = {}) {
/* istanbul ignore next */
action(entity, state, collection = "", facets /* istanbul ignore next */ = {}) {
state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);

@@ -38,2 +39,3 @@ entity._expectFacets(facets, Object.keys(facets), `"query" facets`);

name: "get",
/* istanbul ignore next */
action(entity, state, facets = {}) {

@@ -59,2 +61,3 @@ state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);

name: "delete",
/* istanbul ignore next */
action(entity, state, facets = {}) {

@@ -80,3 +83,4 @@ state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);

name: "put",
action(entity, state, payload = {}) {
/* istanbul ignore next */
action(entity, state, payload) {
let record = entity.model.schema.checkCreate({ ...payload });

@@ -102,5 +106,47 @@ state.query.keys.pk = entity._expectFacets(record, state.query.facets.pk);

},
create: {
name: "create",
action(entity, state, payload) {
let record = entity.model.schema.checkCreate({ ...payload });
state.query.keys.pk = entity._expectFacets(record, state.query.facets.pk);
state.query.method = MethodTypes.put;
state.query.type = QueryTypes.eq;
if (state.hasSortKey) {
let queryFacets = entity._buildQueryFacets(
record,
state.query.facets.sk,
);
state.query.keys.sk.push({
type: state.query.type,
facets: queryFacets,
});
}
state.query.put.data = Object.assign({}, record);
return state;
},
children: ["params", "go"],
},
patch: {
name: "patch",
action(entity, state, facets) {
state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);
state.query.method = MethodTypes.update;
state.query.type = QueryTypes.eq;
if (state.hasSortKey) {
let queryFacets = entity._buildQueryFacets(
facets,
state.query.facets.sk,
);
state.query.keys.sk.push({
type: state.query.type,
facets: queryFacets,
});
}
return state;
},
children: ["set"],
},
update: {
name: "update",
action(entity, state, facets = {}) {
action(entity, state, facets) {
state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);

@@ -138,3 +184,3 @@ state.query.method = MethodTypes.update;

name: "query",
action(entity, state, facets = {}, options = {}) {
action(entity, state, facets, options = {}) {
state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);

@@ -144,7 +190,9 @@ entity._expectFacets(facets, Object.keys(facets), `"query" facets`);

state.query.type = QueryTypes.begins;
let queryFacets = entity._buildQueryFacets(facets, state.query.facets.sk);
state.query.keys.sk.push({
type: state.query.type,
facets: queryFacets,
});
if (state.query.facets.sk) {
let queryFacets = entity._buildQueryFacets(facets, state.query.facets.sk);
state.query.keys.sk.push({
type: state.query.type,
facets: queryFacets,
});
}
return state;

@@ -151,0 +199,0 @@ },

@@ -11,3 +11,3 @@ "use strict";

structure,
{ index, type, name } = {},
{ index, type, name },
i,

@@ -28,14 +28,2 @@ attributes,

structure.bySlot[i][indexSlot] = facet;
},
safeParse(str = "") {
try {
if (typeof str === "string") {
}
} catch(err) {
}
},
safeStringify() {
}

@@ -45,3 +33,3 @@ };

class Entity {
constructor(model = {}, config = {}) {
constructor(model, config = {}) {
this._validateModel(model);

@@ -54,19 +42,12 @@ this.client = config.client;

);
this.query = {};
let clausesWithFilters = this._filterBuilder.injectFilterClauses(
this._clausesWithFilters = this._filterBuilder.injectFilterClauses(
clauses,
this.model.filters,
);
// this.find = (facets = {}) => {
// let index = this._findBestIndexKeyMatch(facets);
// return this._makeChain(index, clausesWithFilters, clauses.index).query(
// facets,
// );
// };
this.scan = this._makeChain("", clausesWithFilters, clauses.index).scan();
this.scan = this._makeChain("", this._clausesWithFilters, clauses.index).scan();
this.query = {};
for (let accessPattern in this.model.indexes) {
let index = this.model.indexes[accessPattern].index;
this.query[accessPattern] = (...values) => {
return this._makeChain(index, clausesWithFilters, clauses.index).query(
return this._makeChain(index, this._clausesWithFilters, clauses.index).query(
...values,

@@ -78,2 +59,29 @@ );

find(facets = {}) {
let match = this._findBestIndexKeyMatch(facets);
if (match.shouldScan) {
return this._makeChain("", this._clausesWithFilters, clauses.index).scan().filter(attr => {
let eqFilters = [];
for (let facet of Object.keys(facets)) {
if (attr[facet]) {
eqFilters.push(attr[facet].eq(facets[facet]));
}
}
return eqFilters.join(" AND");
})
} else {
return this._makeChain(match.index, this._clausesWithFilters, clauses.index).query(
facets,
).filter(attr => {
let eqFilters = [];
for (let facet of Object.keys(facets)) {
if (attr[facet]) {
eqFilters.push(attr[facet].eq(facets[facet]));
}
}
return eqFilters.join(" AND");
});
}
}
collection(collection = "", clauses = {}, facets = {}) {

@@ -83,2 +91,5 @@ let index = this.model.translations.collections.fromCollectionToIndex[

];
if (index === undefined) {
throw new Error(`Invalid collection: ${collection}`);
}
return this._makeChain(index, clauses, clauses.index).collection(

@@ -90,6 +101,6 @@ collection,

_validateModel(model = {}) {
_validateModel(model) {
return validations.model(model);
}
get(facets = {}) {

@@ -110,2 +121,12 @@ let index = "";

create(attributes = {}) {
let index = "";
let options = {
params: {
ConditionExpression: this._makeCreateConditions(index)
}
}
return this._makeChain(index, clauses, clauses.index, options).create(attributes);
}
update(facets = {}) {

@@ -116,3 +137,13 @@ let index = "";

_chain(state = {}, clauses, clause = {}) {
patch(facets = {}) {
let index = "";
let options = {
params: {
ConditionExpression: this._makePatchConditions(index)
}
}
return this._makeChain(index, clauses, clauses.index, options).patch(facets);
}
_chain(state, clauses, clause) {
let current = {};

@@ -133,3 +164,3 @@ for (let child of clause.children) {

}
/* istanbul ignore next */
_makeChain(index = "", clauses, rootClause, options = {}) {

@@ -154,4 +185,4 @@ let facets = this.model.facets.byIndex[index];

filter: {},
options,
},
collectionOnly: !!options.collectionOnly,
hasSortKey: this.model.lookup.indexHasSortKeys[index],

@@ -226,12 +257,24 @@ };

_applyParameterOptions(params = {}, options = {}) {
_applyParameterOptions(params, ...options) {
let config = {
includeKeys: options.includeKeys,
originalErr: options.originalErr,
raw: options.raw,
params: options.params || {},
page: options.page,
pager: !!options.pager
includeKeys: false,
originalErr: false,
raw: false,
params: {},
page: {},
pager: false
};
config = options.reduce((config, option) => {
if (option.includeKeys) config.includeKeys = true;
if (option.originalErr) config.originalErr = true;
if (option.raw) config.raw = true;
if (option.pager) config.pager = true;
config.page = Object.assign({}, config.page, option.page);
config.params = Object.assign({}, config.params, option.params);
return config;
}, config);
let parameters = Object.assign({}, params);
for (let customParameter of Object.keys(config.params)) {

@@ -242,5 +285,7 @@ if (config.params[customParameter] !== undefined) {

}
if (Object.keys(config.page || {}).length) {
parameters.ExclusiveStartKey = config.page;
}
return parameters;

@@ -263,3 +308,3 @@ }

let response = await this.client[method](parameters).promise();
if (method === "put") {
if (method === "put" || method === "create") {
// a VERY hacky way to deal with PUTs

@@ -280,5 +325,21 @@ return this.formatResponse(parameters, config);

_params({ keys = {}, method = "", put = {}, update = {}, filter = {} } = {}, options = {}) {
_makeCreateConditions(index) {
let filter = [`attribute_not_exists(pk)`]
if (this.model.lookup.indexHasSortKeys[index]) {
filter.push(`attribute_not_exists(sk)`);
}
return filter.join(" AND ");
}
_makePatchConditions(index) {
let filter = [`attribute_exists(pk)`]
if (this.model.lookup.indexHasSortKeys[index]) {
filter.push(`attribute_exists(sk)`);
}
return filter.join(" AND ");
}
/* istanbul ignore next */
_params({ keys = {}, method = "", put = {}, update = {}, filter = {}, options = {} }, config = {}) {
let conlidatedQueryFacets = this._consolidateQueryFacets(keys.sk);
let params = {}
let params = {};
switch (method) {

@@ -290,5 +351,7 @@ case MethodTypes.get:

case MethodTypes.put:
case MethodTypes.create:
params = this._makePutParams(put, keys.pk, ...keys.sk);
break;
case MethodTypes.update:
case MethodTypes.patch:
params = this._makeUpdateParams(

@@ -300,9 +363,17 @@ update,

break;
case MethodTypes.patch:
params = this._makeUpdateParams(
update,
keys.pk,
...conlidatedQueryFacets,
);
break;
case MethodTypes.scan:
params = this._makeScanParam(filter);
break;
/* istanbul ignore next */
default:
throw new Error(`Invalid method: ${method}`);
}
return this._applyParameterOptions(params, options);
return this._applyParameterOptions(params, options, config);
}

@@ -322,6 +393,5 @@

}
/* istanbul ignore next */
_makeScanParam(filter = {}) {
// let _makeKey
// let { pk, sk } = this._makeIndexKeys();
let indexBase = "";

@@ -368,2 +438,3 @@ let hasSortKey = this.model.lookup.indexHasSortKeys[indexBase];

/* istanbul ignore next */
_makeUpdateParams({ set } = {}, pk = {}, sk = {}) {

@@ -393,2 +464,3 @@ let setAttributes = this.model.schema.applyAttributeSetters(set);

/* istanbul ignore next */
_makePutParams({ data } = {}, pk, sk) {

@@ -409,3 +481,3 @@ let setAttributes = this.model.schema.applyAttributeSetters(data);

_updateExpressionBuilder(data = {}) {
_updateExpressionBuilder(data) {
let skip = [

@@ -418,6 +490,7 @@ ...this.model.schema.getReadOnly(),

_queryKeyExpressionAttributeBuilder(index = "", pk, ...sks) {
_queryKeyExpressionAttributeBuilder(index, pk, ...sks) {
let translate = { ...this.model.translations.keys[index] };
let restrict = ["pk"];
let keys = { pk };
sks = sks.filter(sk => sk !== undefined);
for (let i = 0; i < sks.length; i++) {

@@ -435,18 +508,9 @@ let id = `sk${i + 1}`;

return {
ExpressionAttributeNames: Object.assign(
{},
keyExpressions.ExpressionAttributeNames,
),
ExpressionAttributeValues: Object.assign(
{},
keyExpressions.ExpressionAttributeValues,
),
ExpressionAttributeNames: Object.assign({}, keyExpressions.ExpressionAttributeNames),
ExpressionAttributeValues: Object.assign({}, keyExpressions.ExpressionAttributeValues),
};
}
_expressionAttributeBuilder(
item = {},
options = {},
{ noDuplicateNames } = {},
) {
/* istanbul ignore next */
_expressionAttributeBuilder(item = {}, options = {}, {noDuplicateNames} = {}) {
let {

@@ -512,3 +576,4 @@ require = [],

}
/* istanbul ignore next */
_queryParams(chainState = {}, options = {}) {

@@ -567,3 +632,3 @@ let conlidatedQueryFacets = this._consolidateQueryFacets(

_makeBetweenQueryParams(index = "", filter = {}, pk = {}, ...sk) {
_makeBetweenQueryParams(index, filter, pk, ...sk) {
let keyExpressions = this._queryKeyExpressionAttributeBuilder(

@@ -596,19 +661,13 @@ index,

_makeBeginsWithQueryParams(index = "", filter = {}, pk = {}, sk = {}) {
let keyExpressions = this._queryKeyExpressionAttributeBuilder(
index,
pk,
sk,
);
_makeBeginsWithQueryParams(index, filter, pk, sk) {
let keyExpressions = this._queryKeyExpressionAttributeBuilder(index, pk, sk);
let KeyConditionExpression = "#pk = :pk";
if (this.model.lookup.indexHasSortKeys[index]) {
KeyConditionExpression = `${KeyConditionExpression} and begins_with(#sk1, :sk1)`;
}
let params = {
KeyConditionExpression,
TableName: this.model.table,
ExpressionAttributeNames: this._mergeExpressionsAttributes(
filter.ExpressionAttributeNames,
keyExpressions.ExpressionAttributeNames,
),
ExpressionAttributeValues: this._mergeExpressionsAttributes(
filter.ExpressionAttributeValues,
keyExpressions.ExpressionAttributeValues,
),
KeyConditionExpression: `#pk = :pk and begins_with(#sk1, :sk1)`,
ExpressionAttributeNames: this._mergeExpressionsAttributes(filter.ExpressionAttributeNames, keyExpressions.ExpressionAttributeNames),
ExpressionAttributeValues: this._mergeExpressionsAttributes(filter.ExpressionAttributeValues, keyExpressions.ExpressionAttributeValues),
};

@@ -633,10 +692,5 @@ if (index) {

}
_makeComparisonQueryParams(
index = "",
comparison = "",
filter = {},
pk = {},
sk = {},
) {
/* istanbul ignore next */
_makeComparisonQueryParams(index = "", comparison = "", filter = {}, pk = {}, sk = {}) {
let operator = Comparisons[comparison];

@@ -676,3 +730,3 @@ if (!operator) {

_expectIndexFacets(attributes = {}, facets = {}) {
_expectIndexFacets(attributes, facets) {
let [isIncomplete, { incomplete, complete }] = this._getIndexImpact(

@@ -700,3 +754,3 @@ attributes,

_makeKeysFromAttributes(indexes, attributes = {}) {
_makeKeysFromAttributes(indexes, attributes) {
let indexKeys = {};

@@ -709,3 +763,3 @@ for (let index of indexes) {

_getUpdatedKeys(pk = {}, sk = {}, set = {}) {
_getUpdatedKeys(pk, sk, set) {
let updateIndex = "";

@@ -743,3 +797,4 @@ let keyTranslations = this.model.translations.keys;

}
/* istanbul ignore next */
_getIndexImpact(attributes = {}, included = {}) {

@@ -833,3 +888,4 @@ let includedFacets = Object.keys(included);

}
/* istanbul ignore next */
_expectFacets(obj = {}, properties = [], type = "key facets") {

@@ -851,7 +907,7 @@ let [incompletePk, missing, matching] = this._expectProperties(

_findProperties(obj = {}, properties = []) {
_findProperties(obj, properties) {
return properties.map((name) => [name, obj[name]]);
}
_expectProperties(obj = {}, properties = []) {
_expectProperties(obj, properties) {
let missing = [];

@@ -869,3 +925,3 @@ let matching = {};

_makeKeyPrefixes(service = "", entity = "", version = "1") {
_makeKeyPrefixes(service, entity, version = "1") {
return {

@@ -877,3 +933,3 @@ pk: `$${service}_${version}`,

_validateIndex(index = "") {
_validateIndex(index) {
if (!this.model.facets.byIndex[index]) {

@@ -884,3 +940,3 @@ throw new Error(`Invalid index: ${index}`);

_getCollectionSk(collection = "") {
_getCollectionSk(collection) {
if (typeof collection && collection.length) {

@@ -892,3 +948,4 @@ return `$${collection}`.toLowerCase();

}
/* istanbul ignore next */
_getPrefixes({ collection = "", customFacets = {} } = {}) {

@@ -934,3 +991,4 @@ /*

}
/* istanbul ignore next */
_makeIndexKeys(index = "", pkFacets = {}, ...skFacets) {

@@ -957,2 +1015,3 @@ this._validateIndex(index);

/* istanbul ignore next */
_makeKey(prefix = "", facets = [], supplied = {}, { isCustom } = {}) {

@@ -977,6 +1036,6 @@ let key = prefix;

_findBestIndexKeyMatch(attributes = {}) {
_findBestIndexKeyMatch(attributes) {
let candidates = this.model.facets.bySlot.map((val, i) => i);
let facets = this.model.facets.bySlot;
let match = "";
let match;
let keys = {};

@@ -1015,3 +1074,2 @@ for (let i = 0; i < facets.length; i++) {

} else if (i === 0) {
match = "";
break;

@@ -1027,5 +1085,7 @@ } else {

index: match || "",
shouldScan: match === undefined
};
}
/* istanbul ignore next */
_parseComposedKey(key = "") {

@@ -1068,3 +1128,3 @@ let facets = {};

_normalizeIndexes(indexes = {}) {
_normalizeIndexes(indexes) {
let normalized = {};

@@ -1233,3 +1293,3 @@ let indexFieldTranslation = {};

}
_normalizeFilters(filters = {}) {

@@ -1252,3 +1312,3 @@ let normalized = {};

_parseModel(model = {}) {
_parseModel(model) {
let { service, entity, table, version = "1" } = model;

@@ -1255,0 +1315,0 @@ let prefixes = this._makeKeyPrefixes(service, entity, version);

@@ -145,5 +145,5 @@ let queryChildren = [

}
if (newNeedsParens) {
newExpression = `(${newExpression})`;
}
// if (newNeedsParens) {
// newExpression = `(${newExpression})`;
// }
return `${existingExpression} AND ${newExpression}`;

@@ -203,3 +203,3 @@ } else {

action: this.buildClause(filter),
children: ["params", "go", "filter", ...modelFilters],
children: ["params", "go", "page", "filter", ...modelFilters],
};

@@ -212,3 +212,3 @@ }

},
children: ["params", "go", "filter", ...modelFilters],
children: ["params", "go", "page", "filter", ...modelFilters],
};

@@ -215,0 +215,0 @@ for (let parent of filterParents) {

@@ -26,2 +26,4 @@ const KeyTypes = {

scan: "scan",
patch: "patch",
create: "create"
};

@@ -28,0 +30,0 @@

@@ -278,4 +278,70 @@ process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1;

}).timeout(20000);
it("Should not create a overwrite existing record", async () => {
let id = uuidv4();
let mall = "EastPointe";
let store = "LatteLarrys";
let sector = "A1";
let category = "food/coffee";
let leaseEnd = "2020-01-20";
let rent = "0.00";
let building = "BuildingZ";
let unit = "G1";
let record = {
id,
mall,
store,
sector,
category,
leaseEnd,
rent,
building,
unit
};
let recordOne = await MallStores.create(record).go();
expect(recordOne).to.deep.equal(record);
let recordTwo = null;
try {
recordTwo = await MallStores.create(record).go();
} catch(err) {
expect(err.message).to.be.equal("The conditional request failed");
}
expect(recordTwo).to.be.null
});
it("Should only update a record if it already exists", async () => {
let id = uuidv4();
let mall = "EastPointe";
let store = "LatteLarrys";
let sector = "A1";
let category = "food/coffee";
let leaseEnd = "2020-01-20";
let rent = "0.00";
let building = "BuildingZ";
let unit = "G1";
let record = {
id,
mall,
store,
sector,
category,
leaseEnd,
rent,
building,
unit
};
let recordOne = await MallStores.create(record).go();
expect(recordOne).to.deep.equal(record);
let patchResultsOne = await MallStores.patch({sector, id}).set({rent: "100.00"}).go();
let patchResultsTwo = null;
try {
patchResultsTwo = await MallStores.patch({sector, id: `${id}-2`}).set({rent: "200.00"}).go();
} catch(err) {
expect(err.message).to.be.equal("The conditional request failed");
}
expect(patchResultsTwo).to.be.null
})
});
describe("Delete records", async () => {

@@ -282,0 +348,0 @@ it("Should create then delete a record", async () => {

@@ -1086,2 +1086,14 @@ const { Entity, clauses } = require("../src/entity");

let { index, keys } = MallStores._findBestIndexKeyMatch({ id });
let params = MallStores.find({id}).params();
console.log("params", params);
expect(params).to.be.deep.equal({
TableName: 'StoreDirectory',
ExpressionAttributeNames: { '#id': 'storeLocationId', '#pk': 'pk'},
ExpressionAttributeValues: {
':id1': '123',
':pk': '$mallstoredirectory_1#id_123',
},
KeyConditionExpression: '#pk = :pk',
FilterExpression: '#id = :id1'
});
expect(keys).to.be.deep.equal([{ name: "id", type: "pk" }]);

@@ -1096,2 +1108,23 @@ expect(index).to.be.equal("");

});
let params = MallStores.find({mall, building, unit}).params();
expect(params).to.be.deep.equal({
KeyConditionExpression: '#pk = :pk and begins_with(#sk1, :sk1)',
TableName: 'StoreDirectory',
ExpressionAttributeNames: {
'#mall': 'mall',
'#building': 'buildingId',
'#unit': 'unitId',
'#pk': 'gsi1pk',
'#sk1': 'gsi1sk'
},
ExpressionAttributeValues: {
':mall1': '123',
':building1': '123',
':unit1': '123',
':pk': '$mallstoredirectory_1#mall_123',
':sk1': '$mallstores#building_123#unit_123#store_'
},
IndexName: 'gsi1pk-gsi1sk-index',
FilterExpression: '#mall = :mall1 AND#building = :building1 AND#unit = :unit1'
});
expect(keys).to.be.deep.equal([

@@ -1098,0 +1131,0 @@ { name: "mall", type: "pk" },

@@ -511,2 +511,67 @@ const { Service } = require("../src/service");

});
it("Should validate that attributes with the same have the same field also listed", () => {
let entityOne = {
entity: "entityOne",
attributes: {
prop1: {
type: "string",
field: "abc"
},
prop2: {
type: "string"
},
prop3: {
type: "string"
}
},
indexes: {
index1: {
pk: {
field: "pk",
facets: ["prop1"],
},
sk: {
field: "sk",
facets: ["prop2", "prop3"],
},
collection: "collectionA",
}
}
}
let entityTwo = {
entity: "entityOne",
attributes: {
prop1: {
type: "string",
field: "def"
},
prop4: {
type: "string"
},
prop5: {
type: "string"
}
},
indexes: {
index1: {
pk: {
field: "pk",
facets: ["prop1"],
},
sk: {
field: "sk",
facets: ["prop1", "prop5"],
},
collection: "collectionA",
},
}
}
let database = new Service({
version: "1",
table: "electro",
service: "electrotest",
});
database.join(entityOne);
expect(() => database.join(entityTwo)).to.throw(`Attribute provided "prop1" with Table Field "def" does not match established Table Field "abc"`);
});
it("Should validate the PK field matches on all added schemas", () => {

@@ -513,0 +578,0 @@ let entityOne = {

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc