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.0 to 0.9.1

.travis.yml

9

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

@@ -8,3 +8,4 @@ "main": "index.js",

"test": "mocha ./test/offline**.spec.js",
"test-all": "mocha ./test/**.spec.js"
"test-all": "mocha ./test/**.spec.js",
"coverage": "nyc npm run test-all && nyc report --reporter=text-lcov | coveralls"
},

@@ -24,3 +25,7 @@ "repository": {

"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",

@@ -27,0 +32,0 @@ "nyc": "^15.0.0",

@@ -15,3 +15,3 @@

- **Simple Filter Composition**: Easily create complex readable filters for Dynamo queries without worrying about the implementation of `ExpressionAttributeNames`, `ExpressionAttributeValues`.
- **Easily Cross Entity Queries**: Define "collections" to create powerful/peformant queries that return multiple entities in a single request.
- **Easily Query Across Entities**: Define "collections" to create powerful/peformant queries that return multiple entities in a single request.

@@ -159,3 +159,3 @@ Turn this:

```javascript
const {Entity, Service} = require("electrodb");
const {Entity} = require("electrodb");
```

@@ -166,2 +166,8 @@

Require or import `Service` from `electrodb`:
```javascript
const {Service} = require("electrodb");
```
## Model

@@ -168,0 +174,0 @@

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

index: {
action(entity, state = {}, facets = {}) {
// todo: maybe all key info is passed on the subsequent query identifiers?
// todo: look for article/list of all dynamodb query limitations
return state;
},
// action(entity, state, facets = {}) {
// // todo: maybe all key info is passed on the subsequent query identifiers?
// // todo: look for article/list of all dynamodb query limitations
// // return state;
// },
children: ["get", "delete", "update", "query", "put", "scan", "collection"],
},
collection: {
action(entity, state = {}, collection = "", facets = {}) {
action(entity, state, collection /* istanbul ignore next */ = "", facets /* istanbul ignore next */ = {}) {
state.query.keys.pk = entity._expectFacets(facets, state.query.facets.pk);

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

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

@@ -52,3 +52,3 @@ state.query.method = MethodTypes.get;

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

@@ -72,3 +72,3 @@ state.query.method = MethodTypes.delete;

put: {
action(entity, state = {}, payload = {}) {
action(entity, state, payload = {}) {
let record = entity.model.schema.checkCreate({ ...payload });

@@ -95,3 +95,3 @@ state.query.keys.pk = entity._expectFacets(record, state.query.facets.pk);

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

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

set: {
action(entity, state = {}, data) {
action(entity, state, data) {
let record = entity.model.schema.checkUpdate({ ...data });

@@ -128,3 +128,3 @@ state.query.update.set = Object.assign(

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

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

between: {
action(entity, state = {}, startingFacets = {}, endingFacets = {}) {
action(entity, state, startingFacets = {}, endingFacets = {}) {
entity._expectFacets(

@@ -178,3 +178,3 @@ startingFacets,

gt: {
action(entity, state = {}, facets = {}) {
action(entity, state, facets = {}) {
entity._expectFacets(facets, Object.keys(facets), `"gt" facets`);

@@ -192,3 +192,3 @@ state.query.type = QueryTypes.gt;

gte: {
action(entity, state = {}, facets = {}) {
action(entity, state, facets = {}) {
entity._expectFacets(facets, Object.keys(facets), `"gte" facets`);

@@ -206,3 +206,3 @@ state.query.type = QueryTypes.gte;

lt: {
action(entity, state = {}, facets = {}) {
action(entity, state, facets = {}) {
entity._expectFacets(facets, Object.keys(facets), `"lt" facets`);

@@ -220,3 +220,3 @@ state.query.type = QueryTypes.lt;

lte: {
action(entity, state = {}, facets = {}) {
action(entity, state, facets = {}) {
entity._expectFacets(facets, Object.keys(facets), `"lte" facets`);

@@ -234,3 +234,3 @@ state.query.type = QueryTypes.lte;

params: {
action(entity, state = {}, options) {
action(entity, state, options) {
if (state.query.method === MethodTypes.query) {

@@ -245,3 +245,3 @@ return entity._queryParams(state.query, options);

go: {
action(entity, state = {}, options) {
action(entity, state, options) {
if (entity.client === undefined) {

@@ -263,3 +263,3 @@ throw new Error("No client defined on model");

module.exports = {
clauses
};
clauses,
};

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

structure,
{ index, type, name } = {},
{ index, type, name } /* istanbul ignore next */ = {},
i,

@@ -32,3 +32,3 @@ attributes,

class Entity {
constructor(model = {}, config = {}) {
constructor(model /* istanbul ignore next */ = {}, config /* istanbul ignore next */ = {}) {
this._validateModel(model);

@@ -47,8 +47,8 @@ this.client = config.client;

);
this.find = (facets = {}) => {
let index = this._findBestIndexKeyMatch(facets);
return this._makeChain(index, clausesWithFilters, clauses.index).query(
facets,
);
};
// 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();

@@ -65,28 +65,3 @@ for (let accessPattern in this.model.indexes) {

// _rearrangeModel(model = {}, config = {}) {
// model.client = model.client || {};
// model.service = model.service || {};
// if (model.table) {
// console.log(`Warning: Defining the "table" directly on the model will be depricated in version 1.0. Please see the README for additional direction.`)
// model.client.table = model.table;
// }
// if (config.client) {
// console.log(`Warning: Defining the "version" directly on the model will be depricated in version 1.0. Please see the README for additional direction.`)
// model.client.docClient = config.client;
// }
// if (model.service) {
// console.log(`Warning: Defining the "service" directly on the model will be depricated in version 1.0. Please see the README for additional direction.`)
// model.service.name = model.service;
// }
// if (model.version) {
// console.log(`Warning: Defining the "version" directly on the model will be depricated in version 1.0. Please see the README for additional direction.`)
// model.service.version = model.version;
// }
// }
collection(collection = "", clauses = {}, facets = {}) {
collection(collection /* istanbul ignore next */ = "", clauses /* istanbul ignore next */ = {}, facets /* istanbul ignore next */ = {}) {
let index = this.model.translations.collections.fromCollectionToIndex[

@@ -197,3 +172,3 @@ collection

if (response.Item) {
data = this.cleanseRetrievedData(response.Item);
data = this.cleanseRetrievedData(response.Item, config);
} else if (response.Items) {

@@ -295,2 +270,3 @@ data = response.Items.map((item) =>

let indexBase = "";
let hasSortKey = this.model.lookup.indexHasSortKeys[indexBase];
let facets = this.model.facets.byIndex[indexBase];

@@ -313,4 +289,7 @@ let keys = this._makeParameterKey(

),
FilterExpression: `(begins_with(#pk, :pk) AND begins_with(#sk, :sk))`,
FilterExpression: `(begins_with(#pk, :pk)`,
};
if (hasSortKey) {
params.FilterExpression = `${params.FilterExpression} AND begins_with(#sk, :sk))`;
}
if (filter.FilterExpression) {

@@ -317,0 +296,0 @@ params.FilterExpression = `${params.FilterExpression} AND ${filter.FilterExpression}`;

@@ -103,9 +103,2 @@ let queryChildren = [

for (let value of values) {
if (strict) {
let [isValid, errMessage] = attribute.isValid(value);
if (!isValid) {
throw new Error(errMessage);
}
}
let valueCount = getValueCount(name);

@@ -119,9 +112,3 @@ let attrValue = `:${name}${valueCount}`;

let expression = template(attrName, ...attrValues);
if (typeof expression !== "string") {
throw new Error(
"Invalid filter response. Expected result to be of type string",
);
} else {
return expression.trim();
}
};

@@ -180,2 +167,5 @@ },

let expression = filterFn(attributes, ...params);
if (typeof expression !== "string") {
throw new Error("Invalid filter response. Expected result to be of type string");
}
state.query.filter.FilterExpression = this._concatFilterExpression(

@@ -182,0 +172,0 @@ state.query.filter.FilterExpression,

@@ -1,4 +0,3 @@

const { KeyTypes } = require("./types");
const { KeyTypes, CastTypes } = require("./types");
const AttributeTypes = ["string", "number", "boolean", "enum"];
const CastTypes = ["string", "number"];

@@ -27,3 +26,3 @@ class Attribute {

} else if (get === undefined) {
return attr => attr;
return (attr) => attr;
} else {

@@ -40,3 +39,3 @@ throw new Error(

} else if (set === undefined) {
return attr => attr;
return (attr) => attr;
} else {

@@ -57,3 +56,3 @@ throw new Error(

} else if (cast === "string") {
return val => {
return (val) => {
if (val === undefined) {

@@ -70,3 +69,3 @@ throw new Error(

} else if (cast === "number") {
return val => {
return (val) => {
if (val === undefined) {

@@ -90,3 +89,3 @@ throw new Error(

} else {
return val => val;
return (val) => val;
}

@@ -97,3 +96,3 @@ }

if (typeof definition === "function") {
return val => {
return (val) => {
let reason = definition(val);

@@ -103,3 +102,3 @@ return [!reason, reason || ""];

} else if (definition instanceof RegExp) {
return val => {
return (val) => {
let isValid = definition.test(val);

@@ -110,3 +109,3 @@ let reason = isValid ? "" : "Failed user defined regex";

} else {
return val => [true, ""];
return (val) => [true, ""];
}

@@ -223,3 +222,3 @@ }

}
let isKey = !!facets.byIndex[""].all.find(facet => facet.name === name);
let isKey = !!facets.byIndex[""].all.find((facet) => facet.name === name);
let definition = {

@@ -259,3 +258,3 @@ name,

})
.map(facet => `"${facet.type}: ${facet.name}"`);
.map((facet) => `"${facet.type}: ${facet.name}"`);
if (missingFacetAttributes.length) {

@@ -270,3 +269,3 @@ throw new Error(

let message = invalidProperties.map(
prop =>
(prop) =>
`Schema Validation Error: Attribute "${prop.name}" property "${prop.property}". Received: "${prop.value}", Expected: "${prop.expected}"`,

@@ -285,10 +284,2 @@ );

getValidate(payload = {}) {
let record = {};
for (let [name, value] of Object.entries(payload)) {
record[name] = this.attributes[name].getValidate(value);
}
return record;
}
applyAttributeGetters(payload = {}) {

@@ -356,4 +347,4 @@ let attributes = { ...payload };

return Object.values(this.attributes)
.filter(attribute => attribute.readOnly)
.map(attribute => attribute.name);
.filter((attribute) => attribute.readOnly)
.map((attribute) => attribute.name);
}

@@ -365,2 +356,3 @@ }

Attribute,
CastTypes,
};

@@ -80,4 +80,2 @@ const { Entity } = require("./entity");

);
} else {
results.push(record);
}

@@ -84,0 +82,0 @@ }

@@ -15,3 +15,3 @@ const KeyTypes = {

between: "between",
collection: "collection"
collection: "collection",
};

@@ -36,2 +36,4 @@

const CastTypes = ["string", "number"];
module.exports = {

@@ -41,3 +43,4 @@ KeyTypes,

MethodTypes,
CastTypes,
Comparisons,
};

@@ -0,1 +1,2 @@

process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1;
const { Entity } = require("../src/entity");

@@ -277,2 +278,90 @@ const { expect } = require("chai");

describe("Delete records", async () => {
it("Should create then delete a record", async () => {
let record = new Entity(
{
service: "testservice",
entity: "testentity",
table: "electro",
version: "1",
attributes: {
prop1: {
type: "string",
},
prop2: {
type: "string",
},
},
indexes: {
main: {
pk: {
field: "pk",
facets: ["prop1"],
},
sk: {
field: "sk",
facets: ["prop2"],
},
},
},
},
{ client },
);
let prop1 = uuidv4();
let prop2 = uuidv4();
await record.put({ prop1, prop2 }).go();
let recordExists = await record.get({ prop1, prop2 }).go();
await record.delete({ prop1, prop2 }).go();
await sleep(150);
let recordNoLongerExists = await record.get({ prop1, prop2 }).go();
expect(!!Object.keys(recordExists).length).to.be.true;
expect(!!Object.keys(recordNoLongerExists).length).to.be.false;
});
});
// 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 () => {

@@ -436,2 +525,11 @@ let db = new Entity(

});
let recordWithKeys = await db.get({id, date}).go({includeKeys: true});
expect(recordWithKeys).to.deep.equal({
id,
date,
someValue: "ABDEF wham bam",
__edb_e__: entity,
sk: `$${entity}#id_${id}`.toLowerCase(),
pk: `$testing_1#date_${date}`.toLowerCase(),
})
}).timeout(10000);

@@ -438,0 +536,0 @@ });

@@ -0,1 +1,2 @@

process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1;
const { Entity, clauses } = require("../src/entity");

@@ -71,3 +72,2 @@ const { expect } = require("chai");

})
it("Should filter 'eq'", async () => {

@@ -74,0 +74,0 @@ let animals = await FilterTests.query

@@ -0,1 +1,2 @@

process.env.AWS_NODEJS_CONNECTION_REUSE_ENABLED = 1;
const { Entity, clauses } = require("../src/entity");

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

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

});
it("should recognize when an attribute's field property is duplicated", () => {
let schema = {
service: "MallStoreDirectory",
entity: "MallStores",
table: "StoreDirectory",
version: "1",
attributes: {
id: {
type: "string",
field: "id",
},
duplicateFieldName: {
type: "string",
field: "id",
},
},
indexes: {
main: {
pk: {
field: "pk",
facets: ["id"],
},
},
},
};
expect(() => new Entity(schema)).to.throw(
`Schema Validation Error: Attribute "duplicateFieldName" property "field". Received: "id", Expected: "Unique field property, already used by attribute id"`,
);
});
it("Should validate regex", () => {

@@ -375,2 +404,20 @@ let Test = new Entity({

});
it("Should make scan parameters", () => {
let scan = MallStores.scan.filter(({store}) => store.eq("Starblix")).params();
expect(scan).to.deep.equal({
"ExpressionAttributeNames": {
"#pk": "pk",
"#store": "storeId"
},
"ExpressionAttributeValues": {
":pk": "$mallstoredirectory_1#id_",
":store1": "Starblix"
},
"FilterExpression": "(begins_with(#pk, :pk) AND #store = :store1",
"TableName": "StoreDirectory"
})
})
it("Should check if filter returns string", () => {
expect(() => MallStores.scan.filter(() => 1234)).to.throw("Invalid filter response. Expected result to be of type string");
})
it("Should create parameters for a given chain", () => {

@@ -377,0 +424,0 @@ let mall = "EastPointe";

@@ -166,18 +166,2 @@ const moment = require("moment");

});
// it("Should validate the attributes passed when strict", () => {
// function byCategory(attr, { category }) {
// return attr.category.eq(category);
// }
// let filter = new FilterFactory(
// MallStores.model.schema.attributes,
// FilterTypes,
// );
// let clause = filter.buildClause(byCategory);
// let category = "BAD_CATEGORY";
// let results = () =>
// clause(MallStores, { query: { filter: {} } }, { category });
// expect(results).to.throw(
// "Value not found in set of acceptable values: food/coffee, food/meal, clothing, electronics, department, misc",
// );
// });
it("Shouldnt validate the attributes passed when not strict", () => {

@@ -184,0 +168,0 @@ function byCategory(attr, { category }) {

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