indicative-parser
Advanced tools
Comparing version 7.0.0 to 7.0.1
export { rulesParser, messagesParser } from './src/main'; | ||
export { Schema, ParsedSchema, ParsedRule, SchemaNodeLiteral, SchemaNodeArray, SchemaNodeObject, ParsedFieldsMessages, ParsedMessages, Message, Messages, ParsedRulesMessages, } from './src/contracts'; | ||
export { ParsedRule, ParsedMessages, ParsedSchema, ParsedFieldsMessages, ParsedRulesMessages, Schema, SchemaNodeArray, SchemaNodeLiteral, SchemaNodeObject, Message, Messages, } from './src/contracts'; |
@@ -1,1 +0,5 @@ | ||
!function(e,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports["indicative.parser"]=r():e["indicative.parser"]=r()}(this,function(){return function(e){var r={};function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:n})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,r){if(1&r&&(e=t(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(t.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var o in e)t.d(n,o,function(r){return e[r]}.bind(null,o));return n},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.p="",t(t.s=0)}([function(e,r,t){"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n=t(1);r.rulesParser=n.rulesParser,r.messagesParser=n.messagesParser},function(e,r,t){"use strict";Object.defineProperty(r,"__esModule",{value:!0});const n=t(2),o=t(3);function u(e,r,t,n=0){const o=e[n++],s=e.length===n,i=/^\d+$/.test(e[n]),c="*"===e[n]||i;if("*"===o||/^\d+$/.test(o))return s?void(t.each[o].rules=r):u(e,r,t.each[o].children,n);if(!s){if(c){return u(e,r,function(e,r,t){if(e[r]&&"object"===e[r].type)throw new Error(`cannot reshape ${r} object to an array`);const n=e[r]||{rules:[]};return n.each=n.each||{},n.each[t]=n.each[t]||{children:{},rules:[]},n.type="array",e[r]=n,n}(t,o,i?e[n]:"*"),n)}return u(e,r,function(e,r){if(e[r]&&"array"===e[r].type)throw new Error(`cannot reshape ${r} array to an object`);const t=e[r]||{rules:[]};return t.type="object",t.children=t.children||{},e[r]=t,t}(t,o).children,n)}!function(e,r,t){const n=e[r]||{type:"literal"};n.rules=t,e[r]=n}(t,o,r)}r.rulesParser=function(e){return Object.keys(e).reduce((r,t)=>{const s=e[t];let i=[];if(!s)throw new Error(`make sure to define rules for ${t}`);return i="string"==typeof s?new n(s,new o):s,u(t.split("."),i,r),r},{})},r.messagesParser=function(e){return Object.keys(e).reduce((r,t)=>{const n=e[t],o=t.split("."),u=o.pop();if(!o.length)return r.rules={[u]:n},r;const s=o.join(".");return r.fields[s]=r.fields[s]||{},r.fields[s][u]=n,r},{fields:{},rules:{}})}},function(e,r,t){"use strict";e.exports=function(e,r){r.add();for(var t=e.length,n=0,o="name";n<t;){var u=e[n++],s=u.charCodeAt(0);58===s||44===s?(o="arg",r.shiftValue()):124===s?(o="name",r.add()):"arg"===o?r.appendValue(u):r.appendKey(u,s)}return r.toJSON()}},function(e,r,t){"use strict";e.exports=function(){return{nodes:[],currentNode:null,add:function(){this.currentNode={name:"",args:[]},this.nodes.push(this.currentNode)},appendKey:function(e,r){32!==r&&(this.currentNode.name+=e)},appendValue:function(e){this.currentNode.args[this.currentNode.args.length-1]+=e},shiftValue:function(){this.currentNode.args.push("")},toJSON:function(){return this.nodes}}}}])}); | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var main_1 = require("./src/main"); | ||
exports.rulesParser = main_1.rulesParser; | ||
exports.messagesParser = main_1.messagesParser; |
# The MIT License | ||
Copyright 2018 thetutlage, contributors | ||
Copyright 2019 Harminder virk, contributors | ||
@@ -5,0 +5,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
{ | ||
"name": "indicative-parser", | ||
"version": "7.0.0", | ||
"description": "Rules and messages schema parser for Indicative", | ||
"version": "7.0.1", | ||
"description": "Schema parser for Indicative", | ||
"main": "build/index.js", | ||
"files": [ | ||
"build/src", | ||
"build/index.js", | ||
"build/index.d.ts" | ||
"build/index.d.ts", | ||
"build/index.js" | ||
], | ||
"scripts": { | ||
"mrm": "mrm --preset=@adonisjs/mrm-preset", | ||
"pretest": "npm run lint", | ||
"test": "nyc node japaFile.js", | ||
"test": "node japaFile.js", | ||
"lint": "tslint --project tsconfig.json", | ||
"clean": "del build", | ||
"compile": "npm run lint && npm run clean && webpack", | ||
"build": "npm run compile", | ||
"coverage": "nyc report --reporter=text-lcov | coveralls" | ||
"compile": "npm run lint && npm run clean && tsc", | ||
"build": "npm run compile && typedoc --excludePrivate && git add docs", | ||
"commit": "git-cz", | ||
"release": "np", | ||
"version": "npm run build" | ||
}, | ||
"keywords": [ | ||
"parser", | ||
"indicative" | ||
], | ||
"author": "virk", | ||
"homepage": "https://indicative.adonisjs.com", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/poppinss/indicative/tree/master/packages/parser.git" | ||
"url": "git+ssh://git@github.com/poppinss/indicative-parser.git" | ||
}, | ||
"keywords": [ | ||
"indicative", | ||
"validator", | ||
"parser" | ||
], | ||
"author": "virk,poppinss", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/poppinss/indicative-parser/issues" | ||
}, | ||
"homepage": "https://github.com/poppinss/indicative-parser#readme", | ||
"devDependencies": { | ||
"@adonisjs/mrm-preset": "^2.0.3", | ||
"@types/node": "^12.0.12", | ||
"commitizen": "^3.1.1", | ||
"cz-conventional-changelog": "^2.1.0", | ||
"del-cli": "^2.0.0", | ||
"doctoc": "^1.4.0", | ||
"husky": "^3.0.0", | ||
"japa": "^2.0.10", | ||
"mrm": "^1.2.2", | ||
"np": "^5.0.3", | ||
"ts-node": "^8.3.0", | ||
"tslint": "^5.18.0", | ||
"tslint-eslint-rules": "^5.4.0", | ||
"typedoc": "^0.14.2", | ||
"typedoc-plugin-external-module-name": "^2.1.0", | ||
"typescript": "^3.5.2" | ||
}, | ||
"nyc": { | ||
@@ -39,2 +64,17 @@ "exclude": [ | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "doctoc README.md --title='## Table of contents' && git add README.md", | ||
"commit-msg": "node ./node_modules/@adonisjs/mrm-preset/validateCommit/conventional/validate.js" | ||
} | ||
}, | ||
"config": { | ||
"commitizen": { | ||
"path": "cz-conventional-changelog" | ||
} | ||
}, | ||
"np": { | ||
"contents": ".", | ||
"anyBranch": false | ||
}, | ||
"publishConfig": { | ||
@@ -44,9 +84,5 @@ "access": "public", | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/poppinss/indicative/issues" | ||
}, | ||
"devDependencies": { | ||
"dependencies": { | ||
"haye": "^2.0.2" | ||
}, | ||
"gitHead": "ec4b9e65401b74657beab116d08dfb8f8b109551" | ||
} | ||
} |
218
README.md
@@ -1,175 +0,113 @@ | ||
<p align="center"> | ||
<a href="#"> | ||
<img src="https://res.cloudinary.com/adonisjs/image/upload/v1553759989/indicative-banner_lh27zs.png" width="600px;" /> | ||
</a> | ||
</p> | ||
<div align="center"> | ||
<img src="https://res.cloudinary.com/adonisjs/image/upload/q_100/v1557762307/poppinss_iftxlt.jpg" width="600px"> | ||
</div> | ||
<p align="center"> | ||
<a href="https://indicative.adonisjs.com/quick-start">Usage</a> • | ||
<a href="https://indicative.adonisjs.com/why">Why?</a> • | ||
<a href="https://indicative.adonisjs.com/features">Features</a> • | ||
<a href="https://indicative.adonisjs.com/examples">Examples</a> • | ||
<a href="https://indicative.adonisjs.com/docs">Documentation</a> | ||
</p> | ||
# Indicative Parser | ||
> Converts indicative rules and messages schema to a tree | ||
<br/> | ||
[![circleci-image]][circleci-url] [![npm-image]][npm-url] ![][typescript-image] [![license-image]][license-url] | ||
<p align="center"> | ||
<a href="https://travis-ci.org/poppinss/indicative"> | ||
<img src="https://img.shields.io/travis/poppinss/indicative.svg?style=flat-square" alt=""> | ||
</a> | ||
Indicative parser pre-compiles the Indicative schema to a recursive tree of nodes. Each node is given one of the following types. | ||
<a href="https://www.typescriptlang.org/"> | ||
<img src="https://img.shields.io/badge/uses-typescript-blue.svg?style=flat-square" alt=""> | ||
</a> | ||
</p> | ||
- `object`: Node with one or more nested children. | ||
- `array`: Node with one or more index or wildcard based nested children. | ||
- `literal`: The leaf nodes. | ||
## Parser | ||
Indicative parser parses the user defined **schema object** to a **tree of nodes**. Using this, the end user can always define their rules as a flat object and it's the job of the parser to expand it to a nested object. | ||
Do note, that the `literal` **type is not equal to literal values in Javascript**. For parser, the literal nodes are nodes with no leaf. | ||
## Usage | ||
Install the package from npm | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
## Table of contents | ||
```sh | ||
npm i indicative-parser | ||
- [Why Indicative needs a parser?](#why-indicative-needs-a-parser) | ||
- [Usage](#usage) | ||
- [Maintainers](#maintainers) | ||
# yarn user | ||
yarn add indicative-parser | ||
``` | ||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
and then usage it as follows | ||
## Why Indicative needs a parser? | ||
If you look at the Indicative schema, it is very concise and developer friendly. However, the same schema needs to be parsed to execute the validation rules. | ||
```js | ||
const { rulesParser, messagesParser } = require('indicative-parser') | ||
console.log(rulesParser({ | ||
'client_id': 'required', | ||
'settings.key': 'required', | ||
'users.*.email': 'required|email' | ||
})) | ||
// messages parser | ||
console.log(messagesParser({ | ||
'users.*.email.required': 'Email is required', | ||
'users.*.email.email': 'Invalid email address' | ||
})) | ||
``` | ||
The parser tree emits three types of nodes, which are explained below: | ||
## Literal type | ||
The `literal` type is the reference to the final property or leaf in the tree. A literal node doesn't have any children. | ||
```js | ||
{ | ||
username: 'required' | ||
username: 'required', | ||
'account.type': 'required|in:email,social' | ||
} | ||
``` | ||
Output | ||
One way is to loop over the schema object keys, split them by `.` and then inline execute the validations for each field. This process is very straight forward, but will have performance issues. | ||
```js | ||
{ | ||
username: { | ||
type: 'literal', | ||
rules: [{ | ||
name: 'required', | ||
args: [], | ||
}], | ||
}, | ||
} | ||
``` | ||
Instead, we pre-compile the schema (later cache it) and generate a tree, which is easier to reason about and then generated optimized functions from the parsed tree. | ||
| Property | Description | | ||
|----------|-------------| | ||
| `type` | The type of the node | | ||
| `rules` | An array of parsed rules | | ||
## Usage | ||
Install the package from npm registry as follows: | ||
## Object type | ||
The `object` type defines an object, which will always have one or more children. | ||
```sh | ||
npm i indicative-parser@alpha | ||
Following is an example of `object` node. | ||
```js | ||
{ | ||
'user.profile': 'required' | ||
} | ||
# yarn | ||
yarn add indicative-parser@alpha | ||
``` | ||
Output | ||
and then use it as follows: | ||
```js | ||
{ | ||
user: { | ||
type: 'object', | ||
rules: [], | ||
children: { | ||
profile: { | ||
rules: [ | ||
{ | ||
name: 'required', | ||
args: [], | ||
}, | ||
], | ||
type: 'literal', | ||
}, | ||
}, | ||
}, | ||
} | ||
``` | ||
import { rulesParser } from 'indicative-parser' | ||
In the above code example, you can see that the properties before the dot `.` notation is marked as `type = object` and last property `username` is considered a literal. There is no limit to the depth of the object. | ||
| Property | Description | | ||
|----------|-------------| | ||
| `type` | The type of the node | | ||
| `rules` | An array of parsed rules on the object node itself | | ||
| `children` | An object of nested named children | | ||
## Array type | ||
The `array` type detects the array expressions as shown below. | ||
```js | ||
{ | ||
'users.*.username': 'required' | ||
} | ||
rulesParser({ | ||
username: 'required', | ||
'account.type': 'required|in:email,social' | ||
}) | ||
``` | ||
Output | ||
Above code outputs the following tree. | ||
```js | ||
```json | ||
{ | ||
users: { | ||
type: 'array', | ||
rules: [], | ||
each: { | ||
'*': { | ||
rules: [], | ||
children: { | ||
username: { | ||
type: 'literal', | ||
rules: [ | ||
{ | ||
name: 'required', | ||
args: [], | ||
}, | ||
], | ||
"username": { | ||
"type": "literal", | ||
"rules": [ | ||
{ | ||
"name": "required", | ||
"args": [] | ||
} | ||
] | ||
}, | ||
"account": { | ||
"rules": [], | ||
"type": "object", | ||
"children": { | ||
"type": { | ||
"type": "literal", | ||
"rules": [ | ||
{ | ||
"name": "required", | ||
"args": [] | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ | ||
"name": "in", | ||
"args": [ | ||
"email", | ||
"social" | ||
] | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
A node is considered as an array when it has `*` or `numeric` expressions. The `each` property contains a sub object for each defined `index` with nested children. | ||
## Maintainers | ||
[Harminder virk](https://github.com/thetutlage) | ||
| Property | Description | | ||
|----------|-------------| | ||
| `type` | The type of the node | | ||
| `rules` | An array of parsed rules on the object node itself | | ||
| `each` | Set of children for each defined index. | | ||
[circleci-image]: https://img.shields.io/circleci/project/github/poppinss/indicative-parser/master.svg?style=for-the-badge&logo=circleci | ||
[circleci-url]: https://circleci.com/gh/poppinss/indicative-parser "circleci" | ||
[npm-image]: https://img.shields.io/npm/v/indicative-parser.svg?style=for-the-badge&logo=npm | ||
[npm-url]: https://npmjs.org/package/indicative-parser "npm" | ||
## What's next? | ||
The output of `parser` is used by [compiler](https://github.com/poppinss/indicative/tree/master/packages/compiler.git) to create a top level function, which executes the validations on runtime data object. | ||
[typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript | ||
[license-url]: LICENSE.md | ||
[license-image]: https://img.shields.io/aur/license/pac.svg?style=for-the-badge |
9
152
11714
1
16
114
+ Addedhaye@^2.0.2
+ Addedhaye@2.0.2(transitive)