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 🙏

© 2024 – Pkg Stats / Ryan Hefner

fieldify

v2.1.5

Published

Fieldify object manipulation & validator

Downloads

148

Readme

Fieldify

NPM Codacy Badge

Fieldify is a multi-purpose schema manipulation library, data extractor, generic object and schema iterator. It allows to read, transform or verify a data schema. It is very useful for handling complex objects and schemas. Especially when designing CRUD or API input validator. But also define protocols or file format, the field of Fieldify is very wide.

Warning: On the current Git repository, you are on the "master" branch, which corresponds to the future version 2 of Fieldify. If you want to access the production code, please go to the "V1" branch.

Documentations

Installation

Using NPM :

npm install fieldify

Using Yarn :

yarn add fieldify

Including Fieldify

Using require()

const fieldify = require("fieldify")

Using import

import fieldify from "fieldify"

Portability

The package is independant from other in order to have a clean base.

Fieldify is known to be ran well on different Javascript plateforms such as :

  • NodeJS
  • In Browser (Chrome, Firefox, IE, Opera, ...)
  • Electron
  • ReactJS
  • React Native

Fieldify Schema

Fieldify embeds a schema and types mechanism allowing to manipulate input and output data based on a schema.

Design of the Schema

Schema Declaration

It is super simple to create a single schema using Fieldfy, the design is inspired from MongoDB but Fieldify works differently.

First you need to know that the $ sign before keys names are used to define special operation on the schema.

Let's say we just need to validate an email and a token, and after update the token can not be readed from the database.


const fieldify = require("fieldify")

const { types } = fieldify;

// here is the schema
const schema = {
    email: {
        $type: "Email",
        $write: true,
        $read: true,
    },
    token: {
        $type: "String",
        $write: true,
        $read: false,
    },
}

// here we create the schema context
const hdl = new fieldify.schema("test")

// here we compile the final schema
// you can update whenever you want using hdl.compile()
// or hdl.fusion() and hdl.compile()
hdl.compile(schema)

// define a user input
const input = {
    email: "[email protected]",
    token: "supertoken"
}

// run the verifier against the input
hdl.verify(input, (fieldified) => {
    if(fieldified.error === false) {
      console.log("Error in the input")
    }
})

// verify promise version call
const fieldified = await hdl.verify(input)
if(fieldified.error === false) {
  console.log("Error in the input")
}

// after verification you can store in 
// database after encoding
hdl.encode(input, (fieldified) => {
  console.log(fieldified.result)
})

// and getting data from the database 
hdl.decode(input, (fieldified) => {
  console.log(fieldified.result)
})

// and finally filter what is going out from the db
hdl.filter(input, (fieldified) => {
  console.log(fieldified.result)
})

// filter promise version
const fieldified = await hdl.filter(input)
console.log(fieldified.result)

Roles based Schema Declaration

Schema based on roles allows to define roles for some fields of the schema. This allows to limit the reading or writing of fields according to a role. Typically an administrator will be able to field a field when a user will not be able to do so.

Fieldify provides a role management method associated to the field directly. Depending on these roles, Fieldify will create different schemes per existing role. This makes data verification or filtering much easier.

Moreover, Fieldify allows to rewrite all 'leaf' fields starting with $. It is possible to change the values for $read or $write but also $encode or $decode. Here is how to declare a schema based on roles:


const fieldify = require("fieldify")

const { roles } = fieldify

const theSchema = {
  test: {
    $type: 'String',
    // this is default role schema where the field can not write or read.
    $write: false,
    $read: false,
    $roles: {
      admin: {
        // admin can read & write
        $read: true,
        $write: true
      },
      user: {
        // user can just read, not write
        $read: true
      }
    }
  }
}

const hdl = new roles('test', theSchema)

// here we have 3 instances of schema

// verify on default role
const fieldified = await hdl.default.verify(input)
if(fieldified.error === false) {
  console.log("Error in the input")
}

// verify on admin role
const fieldified = await hdl.admin.verify(input)
if(fieldified.error === false) {
  console.log("Error in the input")
}

// verify on user role
const fieldified = await hdl.user.verify(input)
if(fieldified.error === false) {
  console.log("Error in the input")
}

F2020.1 Official Types

| Type | Description | Class |-|-|- | String | Single string | Low | Number | Number Type | Low | Moment | Manage Date Picker | Low | Select | Item selector | Low | Name | Name type | Low | Checkbox | Single checkbox | Low | DatePickerRange | Date picking with range | Low | Color | HTML Color selector | Low | FieldName | Internal Field Name | Low | Hash | Hash | Low | KV | Single KV | Low | URL | Valid URL | Low | Email | E-mail address | Low | Radio | Radio button | Low | Country | List of Countries | Low | Hash | HASH type field | Low | Slug | Slug string | Low | TimePickerRange | Time picking with range | Low

Upcomming Official Types

| Type | Description | Class |-|-|- | Switch | Switch button | Low | Rate | Rate selector | Low | Address | IRL Address | Low | LocationGPS | GPS Position | Low

Schema Types

Each type has it own space in a schema, few methods are exposed to perform different operations on the field. Every type are derived from fieldifyType.

Actually Fieldify Types provides different access method :

  • verify(input, cb): Verify / Validate / Sanatize user input
  • filter(input, cb): Filtering Data Output generally from a database (prevent leak)
  • encode(input, cb): Before to write into the database - this is how to write
  • decode(input, cb): After data getting out from the database - this is how to read

Each type in a schema as it owns configuration. Fieldify supports 4 mains options on the field:

  • $required: Is the field is required ? true = yes, default true
  • $read: Is it allowed to read the field using filter(), true = yes, default false
  • $write: Is it allowed to write the field using verify(), true = yes, default false
  • $type: The field type declaration

Types

Internal Design

There are a few basic points in Fieldify. In particular the management of arrays and the use of $ in front of certain fields.

Fieldify is a recursive object iterator which allows :

  • Read or transform a schema - assignator
  • Extract and verify the input data following a schema - iterator

It is essential to understand the use of $. When a field in a schema is preceded by $ this means that the iterator will not enter processing in this field, this allows options to be given to the parent field and this recursively.

So you can give any options you want to define the properties of a field.

const schema = {
  name: {
    first: {
      $options: "string",
      $max: 30,
      $onCheck: (data, next) => {}
    },
    last: {
      $options: "string"
    }
  }
};

Nested Object and Array

The last important point in Fieldify is the notion of Array and Nested object. The great ability of Fieldify is to support Nested Objects and Array. In a Fieldify schema the definition of an Array makes it possible to define the type of the field. One cannot thus define several element in an array of schema however to define one of them will allow Fieldify to authorize elements in time as source/input in the iterator.

In a schema the assign _ or the _fusion* * will only take the first element of an Array to compose the output.

It's a bit complex like that but very useful every day:

// a Fieldify schema
const schema = {
  name: {
    // define an array field
    first: [
      {
        fieldOne: {
          $opt: true
        },
        fieldTwo: {
          $opt: true
        }
      }
    ]
  }
};

// an input
const input = {
  name: {
    first: [
      {
        fieldOne: 32,
        fieldTwo: 43
      },
      {
        fieldOne: 1,
        fieldTwo: 4
      }
    ]
  }
};

Schema Assignation

The assigner allows you to extract fields (those that are not prefixed with $) from a schema in a desired format. This is particularly useful for transforming a Fieldify schema into another schema format.

Example: Transforming a Fieldify schema into a Mongo (mongoose) schema

Info: The assigner works in blocking mode. It is not recommended to let users control the schema without validation.

Below is an example of a Fieldify schema

const schema = {
  entry: {
    $read: false,

    subEntry1: {
      $read: true
    },

    subEntry2: {
      $read: true,

      subEntry22: {
        $read: true
      }
    }
  }
};

In the example below we transform an assigner into another format. Even if $read _ is _false* * we continue to follow the tree.

const extract = fieldify.assign(schema, (user, dst, object, source) => {
  dst["_read"] = object.$read;
});

/  * Will return

{
	"entry": {
		"_read": false,
		"subEntry1": {
			"_read": true
		},
		"subEntry2": {
			"_read": true,
			"subEntry22": {
				"_read": true
			}
		}
	}
}
*/

Extract a schema and prohibit the iterator from going further in its floor if $read _ is false. This is _return(false)* * which indicates the iterator to return to a lower floor.

const extract = fieldify.assign(schema, (user, dst, object, source) => {
  dst["_read"] = object.$read;

  // do not follow the rest in any case
  if (object.$read === false) return false;
});

/* Will return
{
	"entry": {
		"_read": false
	}
}
*/

There is an example that shows how to merge 2 fields into one in examples/assignator-rw.js.

Input Iterator

Once the schema is defined and modeled it is necessary to compile it in order to optimize the traversing of the tree.

const fieldify = require("fieldify");
const crypto = require("crypto");

const schema = {
  $write: false,

  name: {
    $read: false,
    $write: true,

    first: { $read: true },
    last: { $read: true }
  },
  password: {
    $write: true
  }
};
const handler = fieldify.compile(schema);

The handler * corresponds to the compiled instance of the schema which will be used later for the iteration.

The iterator is a means of extracting data from an entry according to the defined Fieldify scheme. This is very useful for validating or verifying input data.

This is how things start to get interesting, in the example below we are going to check some input data and assignment.

Considering the following entry:

const input = {
  name: {
    first: "Michael",
    last: "Vergoz"
  },
  password: "My super password"
};

We will create 2 assignators, one to extract the data that is readable and the other for the data that can be written. Thus the password field cannot be read.

function isReadable(current, next) {
  if (current.access.$read === true) {
    current.result[current.key] = current.input;
  }
  next();
}

function isWritable(current, next) {
  if (current.access.$write === true) {
    current.result[current.key] = current.input;
  }
  next();
}

It is important to note that the extraction functions are asynchronous and so the next() callback must be executed on each pass. It is thus possible to question a third party service for a field without blocking the iteration.

const opts = {
  handler: handler,
  input: input,
  onAssign: isReadable,
  onEnd: iterator => {
    console.log(iterator.result);
  }
};
fieldify.iterator(opts);

In the example above, we retrieve the input data according to the Fieldify schema compiled handler with the onAssign() assignment function which will extract only the fields inheriting from a $read flag to true. In this example, the password field will not be rendered when the iteration has finished and executed the onEnd() callback

This type of iteration is very useful when presenting data to the user (database > user)

const opts = {
  handler: handler,
  input: input,
  onAssign: isWritable,
  onEnd: iterator => {
    console.log(iterator.result);
  }
};
fieldify.iterator(opts);

In the example above the password field will be returned in the result. This case arises when we want to insert the data in a database (user > database)