Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
@jsonlang/core
Advanced tools
It is a Typescript package that provides a simple JSON Programming Language, allowing you to execute a safe logic in Frontend or Backend (NodeJS). Furthermore, it can be stored in the database and rendered to the Frontend-Side to execute/run some business logic.
JsonLang is designed to be extendable. You can define new rules with sync/async handlers.
npm install @jsonlang/core
{"$R": "R1", "$I": ["value1", "value2", {"$R": "R2", "$I": [...] }, ...] }
.JsonLang have three main parameters:
String
) is the rule name itself. i.e. and
, or
, ==
, >
.any[]
) is an array of inputs which will be passed to the Rule
handler/function, their type depends on the Rule
handler, or it can be a nested ruleSymbol [Optional]
), is an optional field, it accept a name of variable which used to save the Rule result in a variable and can be called in any other rule by { "$R": "Var": "$I": ["variableX"] }
. The output value should be unique. If you define the same value more than once, the last one will override the value of the previous one.
async execute(jsonLang: IJsonLangParams, data?: {}, options?: { sync: false }): Promise<RuleResult>
Execute is used to run the JsonLang and takes two parameters.
sync
if it false the execute will be async for async rules, else it will be syncExecute is the Async
version of JsonLang, use it to run all builtin rules and any extended Sync
or Async
Rules
execute(jsonLang: IJsonLangParams, data: {} | undefined, options: { sync: true }): RuleResult
Execute is the Sync
version of JsonLang, use it to run all builtin rules and any extended Sync
Rules
registerOne(ruleDefinition: RuleDefinition, ruleHandler: RuleHandler): void
Extend JsonLang by adding 2 params
{ name: string, shortcut?: string, group?: string }
, name
(required) is the Rule
name, shortcut
(optional) is the shortcut. i.e Sum
is the name
, and +
is the shortcut
, and group
a name of group to categorize/group set of rule under group.(...inputs: RuleInput[]) => RuleResult)
, inputs
(required) is array of all inputs needs for the handler check Input in Structure, and data
is the schemaless data check Data in the Execute Section registerMany(rules: Rules): void
registerMany allows registering a Map()
of rules. The Map key
is RuleDefinition
, and the Map value
is the RuleHandler
This way is the best practice way to extend JSONLang using decorators and import
import { JsonLang } from '@jsonlang/core';
import { MathRules } from '@jsonlang/math';
import { LogicRules } from '@jsonlang/logic';
import { ArrayRules } from '@jsonlang/array';
import { ObjectRules } from '@jsonlang/object';
const jsonLang = new JsonLang();
jsonLang.import(MathRules, LogicRules, ArrayRules, ObjectRules);
Example
import { JsonLang } from '@jsonlang/core';
const jsonLang = new JsonLang();
@JsonLangExtension('Test') // here pass the groupName
export class TestRules {
@RuleExtension({
/* rule name and shortcut */
identifier: { name: 'RuleOne', shortcut: 'R' },
/* key-value pair <variableName, jsonschema> for rule's inputs */
inputs: { inputOne: {type: 'string', enum: ['TP', 'RF']}, inputTwo: {type: 'number'} },
/* jsonschema object for rule's output */
output: { type: 'boolean', default: false }
})
RuleOne(
inputOne: string,
inputTwo: number
): boolean {
// do the implementation here
}
@RuleExtension({
identifier: { name: 'RuleTwo' },
inputs: { type: 'array', items: { type: 'string' } },
output: { type: 'number' }
})
RuleTwo(...inputs: string[]): number {
// do the implementation here
}
}
jsonLang.import(TestRules);
import { JsonLang } from '@jsonlang/core';
Data
["External"]
it will return the schemaless data object which you pass it to the execute method, else if the input is ["Internal"]
, it will return the value of any Output
from any rules, Check the Output part or the value passed from the parent rule like filter in array rules.import { JsonLang } from '@jsonlang/core';
import { LogicRules } from '@jsonlang/logic';
const jsonLang = new JsonLang();
jsonLang.import(LogicRules);
And or &&
Anding
operation, if any value in Input[]
has a value of (null, 0, false), it will return false
, else it will return true
.Or or ||
Oring
operation, if all values in Input[]
has a value of (null, 0, false), it will return false
, else it will return true
.Equal or ==
Equal
element two or not.NotEqual or =
Not Equal
to element two or not.Not or !
true
it will return false
and vice versa.GreaterThan or >
Greater Than
element two or not.LessThan or <
Less Than
element two or not.GreaterThanOrEqual or >=
Greater Than or Equal
element two or not.LessThanOrEqual or <=
Less Than or Equal
element two or not.import { JsonLang } from '@jsonlang/core';
import { MathRules } from '@jsonlang/math';
const jsonLang = new JsonLang();
jsonLang.import(MathRules);
IsNumber
Sum or +
Input1 + Input2 + .... + InputN
.Subtract or -
Input1 - Input2 - .... - InputN
.Multiply or *
Input1 * Input2 * .... * InputN
.Divide or /
Input1 / Input2 / .... / InputN
.import { JsonLang } from '@jsonlang/core';
import { ArrayRules } from '@jsonlang/array';
const jsonLang = new JsonLang();
jsonLang.import(ArrayRules);
All
nested Rules
.Filter
Internal
, to access it by the inner rules, you will need to use Data Rule with scope local, check this example.Map
Internal
, to access it by the inner rules, you will need to use Data Rule with scope local.Foreach
Internal
, to access it by the inner rules, you will need to use Data Rule with scope local.Flatten
import { JsonLang } from '@jsonlang/core';
import { ObjectRules } from '@jsonlang/object';
const jsonLang = new JsonLang();
jsonLang.import(ObjectRules);
Get [In Progress]
path
must follow the dotted style var1.var2
for nested fields and brackets with number for arrays var1.var2[3].var3
Set [In Progress]
path
must follow the dotted style var1.var2
for nested fields and brackets with number for arrays var1.var2[3].var3
. If the path
does not exist, the Set
Rule will create it.Update [In Progress]
path
must follow the dotted style var1.var2
for nested fields and brackets with number for arrays var1.var2[3].var3
. If the path
does not exist, the Update
rule won't do anything.Delete [In Progress]
path
must follow the dotted style var1.var2
for nested fields and brackets with number for arrays var1.var2[3].var3
. If the path
does not exist, the Delete
rule won't do anything.import { JsonLang } from '@jsonlang/core';
import { LogicRules } from '@jsonlang/logic';
const jsonLang = new JsonLang();
jsonLang.import(LogicRules);
jsonLang.execute( { "$R": "LessThan" , "$I": [10, 20] }, undefined, { sync: true } ); // true
// or for short
jsonLang.execute( { "$R": "<" , "$I": [10, 20] }, undefined, { sync: true } ); // true
// or use the async function
jsonLang.execute( { "$R": "<" , "$I": [10, 20] } )
.then(result => {
console.log(result); // true
});
import { JsonLang } from '@jsonlang/core';
import { MathRules } from '@jsonlang/math';
import { ObjectRules } from '@jsonlang/object';
const jsonLang = new JsonLang();
jsonLang.import(MathRules, ObjectRules);
const result = jsonLang.execute({
$R: '+',
$I: [
{
$R: '+',
$I: [
1,
{ $R: '*', $I: [2, 3] },
5
]
},
{
$R: '+',
$I: [
1,
{ $R: '*', $I: [3, 3], $O: 'x' },
5
]
},
{ $R: 'Var', $I: ['x'] },
{ $R: 'Get', $I: ['user.age', null, { $R: 'Data', $I: ['External'] }] }
]
}, { user: { name: 'test', age: 100 } }, { sync: true });
console.log(result);
// 136
import { JsonLang } from '@jsonlang/core';
import { LogicRules } from '@jsonlang/logic';
import { ArrayRules } from '@jsonlang/array';
import { ObjectRules } from '@jsonlang/object';
const jsonLang = new JsonLang();
jsonLang.import(LogicRules, ArrayRules, ObjectRules);
const result = jsonLang.execute({ $R: 'All', $I: [
{
$R: 'Filter',
$I: [[1, 3, 5], 'i', { $R: '>', $I: [{ $R: 'Data', $I: ['Internal'] }, 2] }],
},
{
$R: 'Filter',
$I: [
{ $R: 'Get', $I: ['data.test', null, { $R: 'Data', $I: ['External'] }] },
'j',
{ $R: '<', $I: [{ $R: 'Data', $I: ['Internal'] }, 500] }
]
}
] }, { data: { id: 'test', test: [100, 300, 700] } }, { sync: true });
console.log(result);
// [ [ 3, 5 ], [ 100, 300 ] ]
import { JsonLang } from '@jsonlang/core';
import { ObjectRules } from '@jsonlang/object';
const jsonLang = new JsonLang();
jsonLang.import(ObjectRules);
jsonLang.registerOne({ name: 'Test', shortcut: 't' }, {
sync: (input: any) => { return `${input} Test` },
async: async (input: any) => { return `${input} Test` }
});
const result = await jsonLang.execute({
$R: 'Test',
$I: [
{ $R: 'Get', $I: ['user.age', null, { $R: 'Data' }] }
]
}, { user: { name: 'test', age: 100 } }, { sync: true });
console.log(result);
// 100 Test
You can extend JsonLang and add any logic you want from well-known sync/async packages like lodash, moment, ajv, axios, mysql, mongoose, ...etc.
Just use the register functions and follow its structure to add whatever you want.
JsonLang can be extended with any function, and you can override the existing rules, but make sure that any method you will add won't:
This library uses Array.map
and Array.reduce
, so it's not exactly Internet Explorer 8 friendly.
JsonLang is MIT licensed
FAQs
Json Programming Language Core
The npm package @jsonlang/core receives a total of 3,107 weekly downloads. As such, @jsonlang/core popularity was classified as popular.
We found that @jsonlang/core demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.