@jsonjoy.com/json-expression
Version:
High-performance JSON Pointer implementation
147 lines (146 loc) • 5.12 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.stringOperators = void 0;
const tslib_1 = require("tslib");
const codegen_steps_1 = require("../codegen-steps");
const util = tslib_1.__importStar(require("../util"));
const binaryOperands = (expr, ctx) => {
const left = ctx.eval(expr[1], ctx);
const right = ctx.eval(expr[2], ctx);
return [left, right];
};
const createValidationOperator = (name, validate) => {
return [
name + '?',
[],
1,
(expr, ctx) => {
const email = ctx.eval(expr[1], ctx);
return validate(email);
},
(ctx) => {
ctx.link(validate, 'is_' + name);
return new codegen_steps_1.Expression(`is_${name}(${ctx.operands[0]})`);
},
];
};
exports.stringOperators = [
[
'.',
['cat'],
-1,
(expr, ctx) => {
return expr.slice(1).reduce((acc, e) => acc + util.str(ctx.eval(e, ctx)), '');
},
(ctx) => {
ctx.link(util.str, 'str');
const parts = [];
for (const operand of ctx.operands) {
if (operand instanceof codegen_steps_1.Literal) {
parts.push(JSON.stringify(util.str(operand.val)));
}
else if (operand instanceof codegen_steps_1.Expression) {
parts.push(`str(${operand})`);
}
}
return new codegen_steps_1.Expression(parts.join('+'));
},
],
[
'contains',
[],
2,
(expr, ctx) => {
const [outer, inner] = binaryOperands(expr, ctx);
return util.contains(outer, inner);
},
(ctx) => {
ctx.link(util.contains, 'contains');
const js = `contains(${ctx.operands[0]},${ctx.operands[1]})`;
return new codegen_steps_1.Expression(js);
},
],
[
'starts',
[],
2,
(expr, ctx) => {
const [outer, inner] = binaryOperands(expr, ctx);
return util.starts(outer, inner);
},
(ctx) => {
ctx.link(util.starts, 'starts');
const js = `starts(${ctx.operands[0]},${ctx.operands[1]})`;
return new codegen_steps_1.Expression(js);
},
],
[
'ends',
[],
2,
(expr, ctx) => {
const [outer, inner] = binaryOperands(expr, ctx);
return util.ends(outer, inner);
},
(ctx) => {
ctx.link(util.ends, 'ends');
const js = `ends(${ctx.operands[0]},${ctx.operands[1]})`;
return new codegen_steps_1.Expression(js);
},
],
[
'substr',
[],
3,
(expr, ctx) => {
const str = ctx.eval(expr[1], ctx);
const start = ctx.eval(expr[2], ctx);
const end = ctx.eval(expr[3], ctx);
return util.substr(str, start, end);
},
(ctx) => {
ctx.link(util.substr, 'substr');
const js = `substr(${ctx.operands[0]},${ctx.operands[1]},${ctx.operands[2]})`;
return new codegen_steps_1.Expression(js);
},
],
[
'matches',
[],
2,
(expr, ctx) => {
let pattern = expr[2];
if (pattern instanceof Array && pattern.length === 1)
pattern = pattern[0];
if (typeof pattern !== 'string')
throw new Error('"matches" second argument should be a regular expression string.');
if (!ctx.createPattern)
throw new Error('"matches" operator requires ".createPattern()" option to be implemented.');
const fn = ctx.createPattern(pattern);
const outer = ctx.eval(expr[1], ctx);
return fn(util.str(outer));
},
(ctx) => {
const pattern = ctx.operands[1];
if (!(pattern instanceof codegen_steps_1.Literal) || typeof pattern.val !== 'string')
throw new Error('"matches" second argument should be a regular expression string.');
if (!ctx.createPattern)
throw new Error('"matches" operator requires ".createPattern()" option to be implemented.');
const fn = ctx.createPattern(pattern.val);
const d = ctx.link(fn);
ctx.link(util.str, 'str');
const subject = ctx.operands[0];
return new codegen_steps_1.Expression(`${d}(str(${subject}))`);
},
],
createValidationOperator('email', util.isEmail),
createValidationOperator('hostname', util.isHostname),
createValidationOperator('ip4', util.isIp4),
createValidationOperator('ip6', util.isIp6),
createValidationOperator('uuid', util.isUuid),
createValidationOperator('uri', util.isUri),
createValidationOperator('duration', util.isDuration),
createValidationOperator('date', util.isDate),
createValidationOperator('time', util.isTime),
createValidationOperator('dateTime', util.isDateTime),
];
;