npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@entityjs/entityjs

v0.0.6

Published

entity framework for pure javascript

Downloads

17

Readme

entityJS

what is

entityJS is data modeling framework for JSON.

usage

1. simple sample

JSON

{
  "name":"hika",
  "age":18
}

Model Simple value model using value series function.

class Member extends Entity{
  name = stringValue();
  age = numberValue();
}

Use

const member = new Member();
member.parse({
  "name":"hika",
  "age":18
});

//or

const member = (new Member()).parse({
  "name":"hika",
  "age":18
});

//------------------
console.log(member.name); //hika
console.log(member.age); //18

2. array and object

using List, Map series Function

class Remember extends Entity{
  friends = stringList();
  lotto = numberMap();
}

const remember = (new Remember).parse({
  "friends":["hika", "easy"],
  "lotto":{"num1":1, "num2":2, "num3":3, "num4":4, "num5":5, "num6":6}
});

3. composited strcuture

using entity, entityList, entityMap

class Partner extends Entity{
  name = stringValue();
}
class Member extends Entity{
  name = stringValue();
  age = numberValue();
  partners = entityList(Partner);
}
const member = (new Member).parse({
    name:"hika",
    age:18,
    partners:[
        {name:"jidolstar"},
        {name:"easy"}
    ]
});

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.

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.

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.

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.

//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.

const PART = new Enum("backend", "frontend");

2 Collect the shared fields to define the abstract type 'Developer'.

class Developer extends Entity{
  name = stringValue();
  age = numberValue();
  part = enumValue(PART);
  languages = stringList();
}

3 Define 'Backend' and 'Frontend' by extending 'Developer'.

class Backend extends Developer{
  framework = stringValue();
  database = stringValue();
}
class Frontend extends Developer{
  view = stringValue();
  state = stringValue();
}

4 Declare Union.

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.

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.

//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

  • NPM https://www.npmjs.com/package/@entityjs/entityjs

Blog Post(Korean)

  • entityJS 1
  • entityJS 2
  • entityJS 3

license

MIT