New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@entityjs/entityjs

Package Overview
Dependencies
Maintainers
2
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@entityjs/entityjs - npm Package Compare versions

Comparing version 0.0.5 to 0.0.6

2

package.json
{
"name": "@entityjs/entityjs",
"version": "0.0.5",
"version": "0.0.6",
"description": "entity framework for pure javascript",

@@ -5,0 +5,0 @@ "type": "module",

@@ -21,7 +21,4 @@ # entityJS

class Member extends Entity{
constructor(){
super();
stringValue(this, "name");
numberValue(this, "age");
}
name = stringValue();
age = numberValue();
}

@@ -54,7 +51,4 @@ ```

class Remember extends Entity{
constructor(){
super();
stringList(this, "friends");
numberMap(this, "lotto");
}
friends = stringList();
lotto = numberMap();
}

@@ -72,14 +66,8 @@

class Partner extends Entity{
constructor() {
super();
stringValue(this, "name");
}
name = stringValue();
}
class Member extends Entity{
constructor() {
super();
stringValue(this, "name");
numberValue(this, "age");
entityList(this, "partners", Partner);
}
name = stringValue();
age = numberValue();
partners = entityList(Partner);
}

@@ -96,2 +84,167 @@ const member = (new Member).parse({

### 4. default value
If there is a default value, the parsing will pass even if there is no corresponding property in the json.
Therefore, you can think of the default value as a kind of optional field declaration for parsing.
```js
class Member extends Entity{
name = stringValue().default("hika");
age = numberValue();
}
const member = (new Member).parse({ //There is no name field in json
age:18
}); // but parsing ok!
member.name == "hika"
member.age == 18
```
### 5. validator
Validation can be set precisely for each field, and it is applied when directly entering a value in a property or parsing from json.
```js
class Member extends Entity{
name = stringValue()
.default("hika")
.validation(name=> 3 < name.length && name.length < 20); //4 ~ 19 characters
age = numberValue().validation(age=> 9 < age && age < 20); //teenager
}
const member = (new Member).parse({
name:"ted", //invalid
age:9 //invalid
}); // throw exception
const member = (new Member).parse({
name:"teds", //valid
age:12 //valid
}); //parsing ok
```
### 6. decorator
Without changing the value of the actual field, you can do extra work when you get it with get.
```js
class Member extends Entity{
name = stringValue()
.default("hika")
.validation(name=> 3 < name.length && name.length < 20)
.decorator(name=>"**" + name + "**"); //set decorator
age = numberValue().validation(age=> 9 < age && age < 20);
}
const member = (new Member).parse({
name:"hika",
age:12
});
member.name == "**hika**" //decorated!
```
### 7. union type
In practice, json is often in the form of a or b. In particular, it is common for a and b to have shared fields. To handle this, define the abstract type of a and b to define a common field, and define a and b by inheriting it. This is called a union type.
```json
//backend developers
{
"name":"hika",
"age":18,
"part":"backend",
"languages":["java", "kotlin"],
"framework":"spring",
"database":"mysql"
}
//frontend developers
{
"name":"hika",
"age":18,
"part":"frontend",
"languages":["js", "ts"],
"view":"react",
"state":"redux"
}
```
In the example above, the developers has 'name', 'age', and 'languages' as shared fields.
However, backend developers have 'framework' and 'database', and front-end developers have 'view' and 'state'.
This can be effectively modeled as follows.
#### 1 'part' is determined as an enum.
```js
const PART = new Enum("backend", "frontend");
```
#### 2 Collect the shared fields to define the abstract type 'Developer'.
```js
class Developer extends Entity{
name = stringValue();
age = numberValue();
part = enumValue(PART);
languages = stringList();
}
```
#### 3 Define 'Backend' and 'Frontend' by extending 'Developer'.
```js
class Backend extends Developer{
framework = stringValue();
database = stringValue();
}
class Frontend extends Developer{
view = stringValue();
state = stringValue();
}
```
#### 4 Declare Union.
```js
Entity.union(Developer, Backend, Frontend)
```
* The first parameter becomes an abstract type, followed by concrete classes. According to the order of concrete classes, it is judged first when parsing.
#### 5 Parsing through static method of abstract class.
```js
const dev1 = Developer.parse({
"name":"hika",
"age":18,
"part":"backend",
"languages":["java", "kotlin"],
"framework":"spring",
"database":"mysql"
});
dev1 instanceof Backend == true
const dev2 = Developer.parse({
"name":"hika",
"age":18,
"part":"frontend",
"languages":["js", "ts"],
"view":"react",
"state":"redux"
});
dev2 instanceof Frontend == true
```
A cleaner implementation is possible because it can branch through exact type matching without understanding the shape of json based on the value or existence of a specific field.
```js
//other system - field level branch
if(entity.field === undefined)
if(entity.field === specialValue)
//entityJS - type level branch
switch(true){
case entity instanceof Frontend:{
...
}
case entity instanceof Backend:{
...
}
}
```
## addtional content

@@ -98,0 +251,0 @@ * NPM <a href="https://www.npmjs.com/package/@entityjs/entityjs" target="_blank">https://www.npmjs.com/package/@entityjs/entityjs</a>

@@ -7,14 +7,8 @@ import {Entity} from "../../src/entity/Entity.js";

class Partner extends Entity{
constructor() {
super();
stringValue(this, "name");
}
name = stringValue();
}
class Member extends Entity{
constructor() {
super();
stringValue(this, "name");
numberValue(this, "age");
entityList(this, "partners", Partner);
}
name = stringValue();
age = numberValue();
partners = entityList(Partner);
}

@@ -33,14 +27,8 @@

class Partner extends Entity{
constructor() {
super();
stringValue(this, "name");
}
name = stringValue();
}
class Member extends Entity{
constructor() {
super();
stringValue(this, "name");
numberValue(this, "age");
entityList(this, "partners", Partner);
}
name = stringValue();
age = numberValue();
partners = entityList();
}

@@ -47,0 +35,0 @@

import {Entity, stringValue, numberValue, dateValue, entityList, enumValue, Enum} from "../../src/index.js";
class Member extends Entity{
#name = stringValue(this, "name").validation(v=>2<v.length && v.length<=10);
#point = numberValue(this, "point").default(0);
name = stringValue().validation(v=>2<v.length && v.length<=10);
point = numberValue().default(0);
}
class VIP extends Member{
#freeParking = numberValue(this, "freeParking").validation(v=>v>=0);
#vipCoupons = entityList(this, "vipCoupons", Coupon);
#until = dateValue(this, "until");
freeParking = numberValue().validation(v=>v>=0);
vipCoupons = entityList(Coupon);
until = dateValue();
}

@@ -18,5 +18,5 @@ class Normal extends Member{}

class Coupon extends Entity{
#title = stringValue(this, "title");
#type = enumValue(this, "type", CouponType);
#value = numberValue(this, "value");
title = stringValue();
type = enumValue(CouponType);
value = numberValue();
}

@@ -38,12 +38,11 @@

});
const sourceCode = `
class Member extends Entity{
#name = stringValue(this, "name").validation(v => 2 < v.length && v.length<=10);
#point = numberValue(this, "point").default(0);
name = stringValue().validation(v=>2<v.length && v.length<=10);
point = numberValue().default(0);
}
class VIP extends Member{
#freeParking = numberValue(this, "freeParking").validation(v=>v>=0);
#vipCoupons = entityList(this, "vipCoupons", Coupon);
#until = dateValue(this, "until");
freeParking = numberValue().validation(v=>v>=0);
vipCoupons = entityList(Coupon);
until = dateValue();
}

@@ -59,5 +58,5 @@ class Normal extends Member{}

class Coupon extends Entity{
#title = stringValue(this, "title");
#type = enumValue(this, "type", CouponType);
#value = numberValue(this, "value");
title = stringValue();
type = enumValue(CouponType);
value = numberValue();
}

@@ -64,0 +63,0 @@

import {setProp} from "../util/util.js";
import {Field} from "../field/Field.js";
const handler = {
get(target, prop){
if(prop[0] === "#") return target[prop.substr(1)];
const field = target[prop];
return field instanceof Field ? field.get() : field;
},
set(target, prop, value){
const field = target[prop];
field instanceof Field ? field.set(value) : (target[prop] = value);
return true;
}
};
class Entity{

@@ -9,3 +21,4 @@ static union(base, ...sub){

let target;
if(!sub.some(cls=>Object.entries((target = new cls)._fields).every(([key, field])=>{
if(!sub.some(cls=>Object.keys(target = new cls).every(key=>{
const field = target["#" + key];
const jsonValue = json[key];

@@ -24,17 +37,17 @@ if(jsonValue === undefined && field.get() === undefined) return false;

constructor() {
setProp(this, '_fields', {});
return new Proxy(this, handler);
}
parse(json){
Object.entries(this._fields).forEach(([key, field])=>{
Object.keys(this).forEach(key=>{
const jsonValue = json[key];
const field = this["#" + key];
if(jsonValue === undefined && field.get() === undefined) throw 'no key in json:' + key;
this[key] = field.fromJSON(jsonValue);
field.set(field.fromJSON(jsonValue));
});
return this;
}
toJSON(){return this._fields;}
define(field, descriptor){
if(!(descriptor instanceof Field)) throw 'invalid descriptor(no Field type):' + descriptor
Object.defineProperty(this, field, this._fields[field] = descriptor);
return descriptor;
toJSON(){
const result = {};
Object.keys(this).forEach(key=>result[key] = this["#" + key]);
return result;
}

@@ -41,0 +54,0 @@ }

import {Field} from "../Field.js";
class BooleanField extends Field{
typeValidation(v){ return typeof newValue != "boolean";}
typeValidation(v){ return typeof v == "boolean";}
}
const booleanValue = (entity, key)=>entity.define(key, new BooleanField);
const booleanValue = _=>new BooleanField;
export {booleanValue};

@@ -7,3 +7,3 @@ import {Field} from "../Field.js";

}
const booleanList = (entity, key)=>entity.define(key, new BooleanListField);
const booleanList = _=>new BooleanListField;
export {booleanList};

@@ -7,3 +7,3 @@ import {Field} from "../Field.js";

}
const booleanMap = (entity, key)=>entity.define(key, new BooleanMapField);
const booleanMap = _=>new BooleanMapField;
export {booleanMap};

@@ -9,4 +9,4 @@ import {Field} from "../Field.js";

const dateValue = (entity, key)=>entity.define(key, new DateField);
const dateValue = _=>new DateField;
export {dateValue};

@@ -9,4 +9,4 @@ import {Field} from "../Field.js";

}
const dateList = (entity, key)=>entity.define(key, new DateListField);
const dateList = _=>new DateListField;
export {dateList};

@@ -9,3 +9,3 @@ import {Field} from "../Field.js";

}
const dateMap = (entity, key)=>entity.define(key, new DateMapField);
const dateMap = _=>new DateMapField;
export {dateMap};

@@ -11,4 +11,4 @@ import {Field} from "../Field.js";

}
const entityValue = (entity, key, cls)=>entity.define(key, new EntityField(cls));
const entityValue = cls=>new EntityField(cls);
export {entityValue};

@@ -12,4 +12,4 @@ import {Field} from "../Field.js";

}
const entityList = (entity, key, cls)=>entity.define(key, new EntityListField(cls));
const entityList = cls=>new EntityListField(cls);
export {entityList};

@@ -13,4 +13,4 @@ import {Field} from "../Field.js";

const entityMap = (entity, key, cls)=>entity.define(key, new EntityMapField(cls));
const entityMap = cls=>new EntityMapField(cls);
export {entityMap};

@@ -11,4 +11,4 @@ import {Field} from "../Field.js";

const enumValue = (entity, key, targetEnum)=>entity.define(key, new EnumField(targetEnum));
const enumValue = targetEnum=>new EnumField(targetEnum);
export {enumValue};

@@ -10,4 +10,4 @@ import {Field} from "../Field.js";

}
const enumList = (entity, key, targetEnum)=>entity.define(key, new EnumListField(targetEnum));
const enumList = targetEnum=>new EnumListField(targetEnum);
export {enumList};

@@ -12,4 +12,4 @@ import {Field} from "../Field.js";

const enumMap = (entity, key, targetEnum)=>entity.define(key, new EnumMapField(targetEnum));
const enumMap = targetEnum=>new EnumMapField(targetEnum);
export {enumMap};

@@ -16,4 +16,10 @@ class Field{

}
default(v){this.set(v);}
decorator(v){this._decorator = v;}
default(v){
this.set(v);
return this;
}
decorator(v){
this._decorator = v;
return this;
}
toJSON(){return this.v;}

@@ -20,0 +26,0 @@ fromJSON(v){return v;}

import {Field} from "../Field.js";
class NumberField extends Field{
typeValidation(v){ return typeof newValue != "number";}
typeValidation(v){ return typeof v == "number";}
}
const numberValue = (entity, key)=>entity.define(key, new NumberField);
const numberValue = _=>new NumberField();
export {numberValue};

@@ -7,4 +7,4 @@ import {Field} from "../Field.js";

}
const numberList = (entity, key)=>entity.define(key, new NumberListField);
const numberList = _=>new NumberListField;
export {numberList};

@@ -8,4 +8,4 @@ import {Field} from "../Field.js";

const numberMap = (entity, key)=>entity.define(key, new NumberMapField);
const numberMap = _=>new NumberMapField;
export {numberMap};
import {Field} from "../Field.js";
class StringField extends Field{
typeValidation(v){ return typeof newValue != "string";}
typeValidation(v){ return typeof v == "string";}
}
const stringValue = (entity, key)=>entity.define(key, new StringField);
const stringValue = ()=>new StringField;
export {stringValue};

@@ -7,4 +7,4 @@ import {Field} from "../Field.js";

}
const stringList = (entity, key)=>entity.define(key, new StringListField);
const stringList = _=>new StringListField;
export {stringList};

@@ -7,4 +7,4 @@ import {Field} from "../Field.js";

}
const stringMap = (entity, key)=>entity.define(key, new StringMapField);
const stringMap = _=>new StringMapField;
export {stringMap};
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