rudder-json-template-engine
Advanced tools
Comparing version 0.2.1 to 0.2.2
@@ -0,7 +1,15 @@ | ||
import { Expression } from './types'; | ||
export declare class JsonTemplateEngine { | ||
private readonly fn; | ||
constructor(template: string); | ||
private constructor(); | ||
static create(templateOrExpr: string | Expression, compileTimeBindings?: any): JsonTemplateEngine; | ||
static createSync(templateOrExpr: string | Expression, compileTimeBindings?: any): JsonTemplateEngine; | ||
private static compileSync; | ||
private static compile; | ||
evaluate(data: any, bindings?: any): Promise<any>; | ||
static parse(template: string): Expression; | ||
static translate(templateOrExpr: string | Expression, compileTimeBindings?: any): string; | ||
private static translateTemplate; | ||
private static translateExpression; | ||
evaluate(data: any, bindings?: any): any; | ||
} | ||
//# sourceMappingURL=engine.d.ts.map |
@@ -10,12 +10,35 @@ "use strict"; | ||
class JsonTemplateEngine { | ||
constructor(template) { | ||
this.fn = JsonTemplateEngine.compile(template); | ||
constructor(fn) { | ||
this.fn = fn; | ||
} | ||
static compile(template) { | ||
static create(templateOrExpr, compileTimeBindings) { | ||
return new JsonTemplateEngine(this.compile(templateOrExpr, compileTimeBindings)); | ||
} | ||
static createSync(templateOrExpr, compileTimeBindings) { | ||
return new JsonTemplateEngine(this.compileSync(templateOrExpr, compileTimeBindings)); | ||
} | ||
static compileSync(templateOrExpr, compileTimeBindings) { | ||
return Function(constants_1.DATA_PARAM_KEY, constants_1.BINDINGS_PARAM_KEY, this.translate(templateOrExpr, compileTimeBindings)); | ||
} | ||
static compile(templateOrExpr, compileTimeBindings) { | ||
return utils_1.CommonUtils.CreateAsyncFunction(constants_1.DATA_PARAM_KEY, constants_1.BINDINGS_PARAM_KEY, this.translate(templateOrExpr, compileTimeBindings)); | ||
} | ||
static parse(template) { | ||
const lexer = new lexer_1.JsonTemplateLexer(template); | ||
const parser = new parser_1.JsonTemplateParser(lexer); | ||
const translator = new translator_1.JsonTemplateTranslator(parser.parse()); | ||
const code = translator.translate(); | ||
return utils_1.CommonUtils.CreateAsyncFunction(constants_1.DATA_PARAM_KEY, constants_1.BINDINGS_PARAM_KEY, code); | ||
return parser.parse(); | ||
} | ||
static translate(templateOrExpr, compileTimeBindings) { | ||
if (typeof templateOrExpr === 'string') { | ||
return this.translateTemplate(templateOrExpr, compileTimeBindings); | ||
} | ||
return this.translateExpression(templateOrExpr, compileTimeBindings); | ||
} | ||
static translateTemplate(template, compileTimeBindings) { | ||
return this.translateExpression(this.parse(template), compileTimeBindings); | ||
} | ||
static translateExpression(expr, compileTimeBindings) { | ||
const translator = new translator_1.JsonTemplateTranslator(expr, compileTimeBindings); | ||
return translator.translate(); | ||
} | ||
evaluate(data, bindings = {}) { | ||
@@ -22,0 +45,0 @@ return this.fn(data || {}, bindings); |
export declare class JsonTemplateLexerError extends Error { | ||
constructor(message: string); | ||
} | ||
export declare class JsosTemplateParserError extends Error { | ||
export declare class JsonTemplateParserError extends Error { | ||
constructor(message: string); | ||
@@ -6,0 +6,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.JsosTemplateTranslatorError = exports.JsosTemplateParserError = exports.JsonTemplateLexerError = void 0; | ||
exports.JsosTemplateTranslatorError = exports.JsonTemplateParserError = exports.JsonTemplateLexerError = void 0; | ||
class JsonTemplateLexerError extends Error { | ||
@@ -10,3 +10,3 @@ constructor(message) { | ||
exports.JsonTemplateLexerError = JsonTemplateLexerError; | ||
class JsosTemplateParserError extends Error { | ||
class JsonTemplateParserError extends Error { | ||
constructor(message) { | ||
@@ -16,3 +16,3 @@ super(message); | ||
} | ||
exports.JsosTemplateParserError = JsosTemplateParserError; | ||
exports.JsonTemplateParserError = JsonTemplateParserError; | ||
class JsosTemplateTranslatorError extends Error { | ||
@@ -19,0 +19,0 @@ constructor(message) { |
@@ -12,2 +12,4 @@ import { Token, TokenType } from './types'; | ||
matchLiteral(): boolean; | ||
matchINT(steps?: number): boolean; | ||
matchToArray(): boolean; | ||
matchPath(): boolean; | ||
@@ -21,3 +23,4 @@ matchSpread(): boolean; | ||
private static isOperator; | ||
matchKeyword(op: string): boolean; | ||
matchKeyword(): boolean; | ||
matchKeywordValue(val: string): boolean; | ||
matchIN(): boolean; | ||
@@ -28,5 +31,3 @@ matchFunction(): boolean; | ||
matchAwait(): boolean; | ||
matchAsync(): boolean; | ||
matchLambda(): boolean; | ||
matchDefinition(): boolean; | ||
expect(value: any): void; | ||
@@ -45,2 +46,3 @@ lookahead(steps?: number): Token; | ||
value(): any; | ||
ignoreTokens(numTokens: number): void; | ||
lex(): Token; | ||
@@ -57,3 +59,3 @@ static isLiteralToken(token: Token): boolean; | ||
private scanString; | ||
private scanNumeric; | ||
scanInteger(): Token | undefined; | ||
private scanPunctuatorForDots; | ||
@@ -60,0 +62,0 @@ private scanPunctuatorForEquality; |
@@ -39,2 +39,8 @@ "use strict"; | ||
} | ||
matchINT(steps = 0) { | ||
return this.matchTokenType(types_1.TokenType.INT, steps); | ||
} | ||
matchToArray() { | ||
return this.match('[') && this.match(']', 1); | ||
} | ||
matchPath() { | ||
@@ -49,4 +55,3 @@ return this.matchPathSelector() || this.matchID(); | ||
if (token.type === types_1.TokenType.PUNCT) { | ||
let value = token.value; | ||
return value === '.' || value === '..'; | ||
return token.value === '.' || token.value === '..'; | ||
} | ||
@@ -76,30 +81,27 @@ return false; | ||
} | ||
matchKeyword(op) { | ||
matchKeyword() { | ||
return this.matchTokenType(types_1.TokenType.KEYWORD); | ||
} | ||
matchKeywordValue(val) { | ||
let token = this.lookahead(); | ||
return token.type === types_1.TokenType.KEYWORD && token.value === op; | ||
return token.type === types_1.TokenType.KEYWORD && token.value === val; | ||
} | ||
matchIN() { | ||
return this.matchKeyword(types_1.Keyword.IN); | ||
return this.matchKeywordValue(types_1.Keyword.IN); | ||
} | ||
matchFunction() { | ||
return this.matchKeyword(types_1.Keyword.FUNCTION); | ||
return this.matchKeywordValue(types_1.Keyword.FUNCTION); | ||
} | ||
matchNew() { | ||
return this.matchKeyword(types_1.Keyword.NEW); | ||
return this.matchKeywordValue(types_1.Keyword.NEW); | ||
} | ||
matchTypeOf() { | ||
return this.matchKeyword(types_1.Keyword.TYPEOF); | ||
return this.matchKeywordValue(types_1.Keyword.TYPEOF); | ||
} | ||
matchAwait() { | ||
return this.matchKeyword(types_1.Keyword.AWAIT); | ||
return this.matchKeywordValue(types_1.Keyword.AWAIT); | ||
} | ||
matchAsync() { | ||
return this.matchKeyword(types_1.Keyword.ASYNC); | ||
} | ||
matchLambda() { | ||
return this.matchKeyword(types_1.Keyword.LAMBDA); | ||
return this.matchKeywordValue(types_1.Keyword.LAMBDA); | ||
} | ||
matchDefinition() { | ||
return this.matchKeyword(types_1.Keyword.LET) || this.matchKeyword(types_1.Keyword.CONST); | ||
} | ||
expect(value) { | ||
@@ -129,3 +131,3 @@ let token = this.lex(); | ||
isLineCommentEnd() { | ||
return this.codeChars[this.idx] === '\n'; | ||
return this.idx >= this.codeChars.length || this.codeChars[this.idx] === '\n'; | ||
} | ||
@@ -180,3 +182,3 @@ isBlockCommentStart() { | ||
} | ||
let token = this.scanPunctuator() || this.scanID() || this.scanString() || this.scanNumeric(); | ||
let token = this.scanPunctuator() || this.scanID() || this.scanString() || this.scanInteger(); | ||
if (token) { | ||
@@ -190,2 +192,7 @@ return token; | ||
} | ||
ignoreTokens(numTokens) { | ||
for (let i = 0; i < numTokens; i++) { | ||
this.lex(); | ||
} | ||
} | ||
lex() { | ||
@@ -203,3 +210,4 @@ let token; | ||
return (token.type === types_1.TokenType.BOOL || | ||
token.type === types_1.TokenType.NUM || | ||
token.type === types_1.TokenType.INT || | ||
token.type === types_1.TokenType.FLOAT || | ||
token.type === types_1.TokenType.STR || | ||
@@ -315,25 +323,21 @@ token.type === types_1.TokenType.NULL || | ||
} | ||
scanNumeric() { | ||
let start = this.idx, ch = this.codeChars[this.idx], isFloat = ch === '.'; | ||
if (isFloat || JsonTemplateLexer.isDigit(ch)) { | ||
let num = ch; | ||
while (++this.idx < this.codeChars.length) { | ||
ch = this.codeChars[this.idx]; | ||
if (ch === '.') { | ||
if (isFloat) { | ||
this.throwUnexpectedToken(); | ||
} | ||
isFloat = true; | ||
} | ||
else if (!JsonTemplateLexer.isDigit(ch)) { | ||
break; | ||
} | ||
num += ch; | ||
scanInteger() { | ||
let start = this.idx; | ||
let ch = this.codeChars[this.idx]; | ||
if (!JsonTemplateLexer.isDigit(ch)) { | ||
return; | ||
} | ||
let num = ch; | ||
while (++this.idx < this.codeChars.length) { | ||
ch = this.codeChars[this.idx]; | ||
if (!JsonTemplateLexer.isDigit(ch)) { | ||
break; | ||
} | ||
return { | ||
type: types_1.TokenType.NUM, | ||
value: isFloat ? parseFloat(num) : parseInt(num, 10), | ||
range: [start, this.idx], | ||
}; | ||
num += ch; | ||
} | ||
return { | ||
type: types_1.TokenType.INT, | ||
value: num, | ||
range: [start, this.idx], | ||
}; | ||
} | ||
@@ -345,6 +349,14 @@ scanPunctuatorForDots() { | ||
} | ||
if (ch2 === '.' && ch3 === '.') { | ||
if (ch2 === '(' && ch3 === ')') { | ||
this.idx = this.idx + 3; | ||
return { | ||
type: types_1.TokenType.PUNCT, | ||
value: '.()', | ||
range: [start, this.idx], | ||
}; | ||
} | ||
else if (ch2 === '.' && ch3 === '.') { | ||
this.idx = this.idx + 3; | ||
return { | ||
type: types_1.TokenType.PUNCT, | ||
value: '...', | ||
@@ -363,5 +375,2 @@ range: [start, this.idx], | ||
else { | ||
if (JsonTemplateLexer.isDigit(ch2)) { | ||
return; | ||
} | ||
return { | ||
@@ -368,0 +377,0 @@ type: types_1.TokenType.PUNCT, |
@@ -14,11 +14,11 @@ import { Expression } from './types'; | ||
private parseNextExpr; | ||
private parseToArrayExpr; | ||
private parsePathPart; | ||
private parsePathParts; | ||
private static prependFunctionID; | ||
private static combinePathParts; | ||
private static convertToFunctionCallExpr; | ||
private parseContextVariable; | ||
private parsePathOptions; | ||
private parsePathRoot; | ||
private updatePathExpr; | ||
private parsePath; | ||
private parseContextVariable; | ||
private createArrayIndexFilterExpr; | ||
private createArrayFilterExpr; | ||
private parseSelector; | ||
@@ -45,2 +45,3 @@ private parseRangeFilterExpr; | ||
private parsePathAfterExpr; | ||
private createLiteralExpr; | ||
private parseLiteralExpr; | ||
@@ -65,2 +66,6 @@ private parseIDPath; | ||
private parseLambdaExpr; | ||
private parseCompileTimeExpr; | ||
private parseNumber; | ||
private parseFloatingNumber; | ||
private parseKeywordBasedExpr; | ||
private parsePrimaryExpr; | ||
@@ -70,3 +75,7 @@ private static setSubpath; | ||
private static convertToBlockExpr; | ||
private static prependFunctionID; | ||
private static ignoreEmptySelectors; | ||
private static combinePathOptionParts; | ||
private static convertToFunctionCallExpr; | ||
} | ||
//# sourceMappingURL=parser.d.ts.map |
@@ -22,3 +22,3 @@ "use strict"; | ||
if (this.lexer.match(';')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
return; | ||
@@ -53,3 +53,3 @@ } | ||
if (expr.type === types_1.SyntaxType.PATH && this.lexer.match('=')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
return { | ||
@@ -96,10 +96,8 @@ type: types_1.SyntaxType.ASSIGNMENT_EXPR, | ||
} | ||
parseToArrayExpr() { | ||
this.lexer.lex(); | ||
this.lexer.lex(); | ||
return { type: types_1.SyntaxType.TO_ARRAY }; | ||
} | ||
parsePathPart() { | ||
if (this.lexer.match('.') && this.lexer.match('(', 1)) { | ||
this.lexer.lex(); | ||
if (this.lexer.match('.()')) { | ||
this.lexer.ignoreTokens(1); | ||
} | ||
else if (this.lexer.match('.') && this.lexer.match('(', 1)) { | ||
this.lexer.ignoreTokens(1); | ||
return this.parseBlockExpr(); | ||
@@ -113,4 +111,4 @@ } | ||
} | ||
else if (this.lexer.match('[') && this.lexer.match(']', 1)) { | ||
return this.parseToArrayExpr(); | ||
else if (this.lexer.matchToArray()) { | ||
return this.parsePathOptions(); | ||
} | ||
@@ -123,2 +121,5 @@ else if (this.lexer.match('[')) { | ||
} | ||
else if (this.lexer.match('@') || this.lexer.match('#')) { | ||
return this.parsePathOptions(); | ||
} | ||
} | ||
@@ -128,5 +129,4 @@ parsePathParts() { | ||
let newParts; | ||
while ((newParts = this.parsePathPart())) { | ||
newParts = utils_1.CommonUtils.toArray(newParts); | ||
parts.push(...newParts); | ||
while ((newParts = utils_1.CommonUtils.toArray(this.parsePathPart()))) { | ||
parts = parts.concat(newParts); | ||
if (newParts[0].type === types_1.SyntaxType.FUNCTION_CALL_EXPR) { | ||
@@ -136,51 +136,33 @@ break; | ||
} | ||
return JsonTemplateParser.combinePathParts(parts); | ||
return JsonTemplateParser.ignoreEmptySelectors(parts); | ||
} | ||
static prependFunctionID(prefix, id) { | ||
return id ? prefix + '.' + id : prefix; | ||
parseContextVariable() { | ||
this.lexer.ignoreTokens(1); | ||
if (!this.lexer.matchID()) { | ||
this.lexer.throwUnexpectedToken(); | ||
} | ||
return this.lexer.value(); | ||
} | ||
static combinePathParts(parts) { | ||
if (parts.length < 2) { | ||
return parts; | ||
} | ||
let newParts = []; | ||
for (let i = 0; i < parts.length; i++) { | ||
let expr = parts[i]; | ||
if (i !== parts.length - 1) { | ||
if (expr.type === types_1.SyntaxType.TO_ARRAY) { | ||
continue; | ||
} | ||
if (expr.type === types_1.SyntaxType.SELECTOR && expr.selector === '.') { | ||
const selectorExpr = expr; | ||
if (!selectorExpr.prop) { | ||
continue; | ||
} | ||
else if (!selectorExpr.contextVar && | ||
selectorExpr.prop?.type === types_1.TokenType.ID && | ||
parts[i + 1].type === types_1.SyntaxType.FUNCTION_CALL_EXPR) { | ||
expr = parts[i + 1]; | ||
expr.id = this.prependFunctionID(selectorExpr.prop.value, expr.id); | ||
expr.dot = true; | ||
i++; | ||
} | ||
} | ||
parsePathOptions() { | ||
const context = {}; | ||
while (this.lexer.match('@') || this.lexer.match('#') || this.lexer.matchToArray()) { | ||
if (this.lexer.match('@')) { | ||
context.item = this.parseContextVariable(); | ||
continue; | ||
} | ||
newParts.push(expr); | ||
if (this.lexer.match('#')) { | ||
context.index = this.parseContextVariable(); | ||
continue; | ||
} | ||
if (this.lexer.matchToArray()) { | ||
this.lexer.ignoreTokens(2); | ||
context.toArray = true; | ||
continue; | ||
} | ||
} | ||
if (newParts.length < parts.length) { | ||
newParts = this.combinePathParts(newParts); | ||
} | ||
return newParts; | ||
return { | ||
type: types_1.SyntaxType.PATH_OPTIONS, | ||
options: context, | ||
}; | ||
} | ||
static convertToFunctionCallExpr(expr) { | ||
const fnExpr = expr.parts.pop(); | ||
if (!expr.parts.length && expr.root && typeof expr.root !== 'object') { | ||
fnExpr.id = this.prependFunctionID(expr.root, fnExpr.id); | ||
fnExpr.dot = false; | ||
} | ||
else { | ||
fnExpr.object = expr; | ||
} | ||
return fnExpr; | ||
} | ||
parsePathRoot(root) { | ||
@@ -191,3 +173,3 @@ if (root) { | ||
if (this.lexer.match('^')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
return constants_1.DATA_PARAM_KEY; | ||
@@ -199,2 +181,29 @@ } | ||
} | ||
updatePathExpr(pathExpr) { | ||
if (pathExpr.parts.length > 1 && pathExpr.parts[0].type === types_1.SyntaxType.PATH_OPTIONS) { | ||
pathExpr.options = pathExpr.parts[0].options; | ||
pathExpr.parts.shift(); | ||
} | ||
JsonTemplateParser.setSubpath(pathExpr.parts); | ||
const shouldConvertAsBlock = JsonTemplateParser.pathContainsVariables(pathExpr.parts); | ||
let lastPart = utils_1.CommonUtils.getLastElement(pathExpr.parts); | ||
let fnExpr; | ||
if (lastPart?.type === types_1.SyntaxType.FUNCTION_CALL_EXPR) { | ||
fnExpr = pathExpr.parts.pop(); | ||
} | ||
lastPart = utils_1.CommonUtils.getLastElement(pathExpr.parts); | ||
if (lastPart?.type === types_1.SyntaxType.PATH_OPTIONS) { | ||
pathExpr.parts.pop(); | ||
pathExpr.returnAsArray = lastPart.options?.toArray; | ||
} | ||
pathExpr.parts = JsonTemplateParser.combinePathOptionParts(pathExpr.parts); | ||
let expr = pathExpr; | ||
if (fnExpr) { | ||
expr = JsonTemplateParser.convertToFunctionCallExpr(fnExpr, pathExpr); | ||
} | ||
if (shouldConvertAsBlock) { | ||
expr = JsonTemplateParser.convertToBlockExpr(expr); | ||
} | ||
return expr; | ||
} | ||
parsePath(root) { | ||
@@ -209,38 +218,28 @@ let expr = { | ||
} | ||
JsonTemplateParser.setSubpath(expr.parts); | ||
const shouldConvertAsBlock = JsonTemplateParser.pathContainsVariables(expr.parts); | ||
const lastPart = utils_1.CommonUtils.getLastElement(expr.parts); | ||
if (lastPart.type === types_1.SyntaxType.TO_ARRAY) { | ||
expr.parts.pop(); | ||
expr.toArray = true; | ||
} | ||
else if (lastPart.type === types_1.SyntaxType.FUNCTION_CALL_EXPR) { | ||
expr = JsonTemplateParser.convertToFunctionCallExpr(expr); | ||
} | ||
return shouldConvertAsBlock ? JsonTemplateParser.convertToBlockExpr(expr) : expr; | ||
return this.updatePathExpr(expr); | ||
} | ||
parseContextVariable(expected) { | ||
if (this.lexer.match(expected)) { | ||
this.lexer.lex(); | ||
if (!this.lexer.matchID()) { | ||
this.lexer.throwUnexpectedToken(); | ||
} | ||
return this.lexer.value(); | ||
} | ||
createArrayIndexFilterExpr(expr) { | ||
return { | ||
type: types_1.SyntaxType.ARRAY_INDEX_FILTER_EXPR, | ||
indexes: { | ||
type: types_1.SyntaxType.ARRAY_EXPR, | ||
elements: [expr], | ||
}, | ||
}; | ||
} | ||
createArrayFilterExpr(expr) { | ||
return { | ||
type: types_1.SyntaxType.ARRAY_FILTER_EXPR, | ||
filters: [expr], | ||
}; | ||
} | ||
parseSelector() { | ||
let selector = this.lexer.value(); | ||
if (this.lexer.matchINT()) { | ||
return this.createArrayFilterExpr(this.createArrayIndexFilterExpr(this.parseLiteralExpr())); | ||
} | ||
let prop; | ||
let context; | ||
if (this.lexer.match('*')) { | ||
if (this.lexer.match('*') || this.lexer.matchID() || this.lexer.matchTokenType(types_1.TokenType.STR)) { | ||
prop = this.lexer.lex(); | ||
} | ||
if (this.lexer.matchID() || this.lexer.matchTokenType(types_1.TokenType.STR)) { | ||
prop = this.lexer.lex(); | ||
while (this.lexer.match('@') || this.lexer.match('#')) { | ||
context = context || {}; | ||
context.item = context.item || this.parseContextVariable('@'); | ||
context.index = context.index || this.parseContextVariable('#'); | ||
} | ||
} | ||
return { | ||
@@ -250,3 +249,2 @@ type: types_1.SyntaxType.SELECTOR, | ||
prop, | ||
context, | ||
}; | ||
@@ -256,3 +254,3 @@ } | ||
if (this.lexer.match(':')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
return { | ||
@@ -265,3 +263,3 @@ type: types_1.SyntaxType.RANGE_FILTER_EXPR, | ||
if (this.lexer.match(':')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
if (this.lexer.match(']')) { | ||
@@ -313,3 +311,3 @@ return { | ||
if (this.lexer.match('~')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
exclude = true; | ||
@@ -361,3 +359,3 @@ } | ||
if (this.lexer.match('.') && this.lexer.match('{', 1)) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
} | ||
@@ -370,6 +368,6 @@ } | ||
if (this.lexer.match('?')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
const thenExpr = this.parseConditionalExpr(); | ||
if (this.lexer.match(':')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
const elseExpr = this.parseConditionalExpr(); | ||
@@ -398,7 +396,7 @@ return { | ||
while (this.lexer.match('[') && !this.lexer.match(']', 1)) { | ||
this.lexer.expect('['); | ||
this.lexer.ignoreTokens(1); | ||
filters.push(this.parseArrayFilterExpr()); | ||
this.lexer.expect(']'); | ||
if (this.lexer.match('.') && this.lexer.match('[', 1)) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
} | ||
@@ -575,4 +573,3 @@ } | ||
} | ||
parseLiteralExpr() { | ||
const token = this.lexer.lex(); | ||
createLiteralExpr(token) { | ||
return { | ||
@@ -584,2 +581,5 @@ type: types_1.SyntaxType.LITERAL, | ||
} | ||
parseLiteralExpr() { | ||
return this.createLiteralExpr(this.lexer.lex()); | ||
} | ||
parseIDPath() { | ||
@@ -590,3 +590,3 @@ const idParts = []; | ||
if (this.lexer.match('.') && this.lexer.matchID(1)) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
} | ||
@@ -604,3 +604,3 @@ } | ||
if (!this.lexer.matchID()) { | ||
throw new errors_1.JsosTemplateParserError('Invalid object vars at ' + this.lexer.getContext()); | ||
throw new errors_1.JsonTemplateParserError('Invalid object vars at ' + this.lexer.getContext()); | ||
} | ||
@@ -614,3 +614,3 @@ vars.push(this.lexer.value()); | ||
if (vars.length === 0) { | ||
throw new errors_1.JsosTemplateParserError('Empty object vars at ' + this.lexer.getContext()); | ||
throw new errors_1.JsonTemplateParserError('Empty object vars at ' + this.lexer.getContext()); | ||
} | ||
@@ -622,3 +622,3 @@ return vars; | ||
if (!this.lexer.matchID()) { | ||
throw new errors_1.JsosTemplateParserError('Invalid normal vars at ' + this.lexer.getContext()); | ||
throw new errors_1.JsonTemplateParserError('Invalid normal vars at ' + this.lexer.getContext()); | ||
} | ||
@@ -650,3 +650,3 @@ vars.push(this.lexer.value()); | ||
if (this.lexer.matchNew()) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
id = 'new ' + this.parseIDPath(); | ||
@@ -663,3 +663,3 @@ } | ||
if (this.lexer.matchSpread()) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
spread = '...'; | ||
@@ -683,3 +683,3 @@ // rest param should be last param. | ||
parseFunctionExpr(asyncFn = false) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
const params = this.parseFunctionDefinitionParams(); | ||
@@ -699,3 +699,3 @@ this.lexer.expect('{'); | ||
if (this.lexer.match('[')) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
key = this.parseBaseExpr(); | ||
@@ -749,3 +749,3 @@ this.lexer.expect(']'); | ||
if (this.lexer.matchSpread()) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
return { | ||
@@ -772,15 +772,11 @@ type: types_1.SyntaxType.SPREAD_EXPR, | ||
if (statements.length === 0) { | ||
return EMPTY_EXPR; | ||
throw new errors_1.JsonTemplateParserError('empty block is not allowed'); | ||
} | ||
else if (statements.length === 1) { | ||
return statements[0]; | ||
} | ||
return { | ||
type: types_1.SyntaxType.FUNCTION_EXPR, | ||
body: utils_1.CommonUtils.convertToStatementsExpr(...statements), | ||
block: true, | ||
type: types_1.SyntaxType.BLOCK_EXPR, | ||
statements, | ||
}; | ||
} | ||
parseAsyncFunctionExpr() { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
if (this.lexer.matchFunction()) { | ||
@@ -795,3 +791,3 @@ return this.parseFunctionExpr(true); | ||
parseLambdaExpr(asyncFn = false) { | ||
this.lexer.lex(); | ||
this.lexer.ignoreTokens(1); | ||
const expr = this.parseBaseExpr(); | ||
@@ -805,2 +801,55 @@ return { | ||
} | ||
parseCompileTimeExpr() { | ||
this.lexer.expect('{'); | ||
this.lexer.expect('{'); | ||
const expr = this.parseBaseExpr(); | ||
this.lexer.expect('}'); | ||
this.lexer.expect('}'); | ||
return { | ||
type: types_1.SyntaxType.COMPILE_TIME_EXPR, | ||
value: expr, | ||
}; | ||
} | ||
parseNumber() { | ||
let val = this.lexer.value(); | ||
if (this.lexer.match('.')) { | ||
val += this.lexer.value(); | ||
if (this.lexer.matchINT()) { | ||
val += this.lexer.value(); | ||
} | ||
return { | ||
type: types_1.SyntaxType.LITERAL, | ||
value: parseFloat(val), | ||
tokenType: types_1.TokenType.FLOAT, | ||
}; | ||
} | ||
return { | ||
type: types_1.SyntaxType.LITERAL, | ||
value: parseInt(val, 10), | ||
tokenType: types_1.TokenType.INT, | ||
}; | ||
} | ||
parseFloatingNumber() { | ||
const val = this.lexer.value() + this.lexer.value(); | ||
return { | ||
type: types_1.SyntaxType.LITERAL, | ||
value: parseFloat(val), | ||
tokenType: types_1.TokenType.FLOAT, | ||
}; | ||
} | ||
parseKeywordBasedExpr() { | ||
const token = this.lexer.lookahead(); | ||
switch (token.value) { | ||
case types_1.Keyword.NEW: | ||
return this.parseFunctionCallExpr(); | ||
case types_1.Keyword.LAMBDA: | ||
return this.parseLambdaExpr(); | ||
case types_1.Keyword.ASYNC: | ||
return this.parseAsyncFunctionExpr(); | ||
case types_1.Keyword.FUNCTION: | ||
return this.parseFunctionExpr(); | ||
default: | ||
return this.parseDefinitionExpr(); | ||
} | ||
} | ||
parsePrimaryExpr() { | ||
@@ -816,20 +865,17 @@ if (this.lexer.match(';')) { | ||
} | ||
if (this.lexer.matchNew()) { | ||
return this.parseFunctionCallExpr(); | ||
if (this.lexer.matchKeyword()) { | ||
return this.parseKeywordBasedExpr(); | ||
} | ||
if (this.lexer.matchDefinition()) { | ||
return this.parseDefinitionExpr(); | ||
if (this.lexer.matchINT()) { | ||
return this.parseNumber(); | ||
} | ||
if (this.lexer.matchLambda()) { | ||
return this.parseLambdaExpr(); | ||
if (this.lexer.match('.') && this.lexer.matchINT(1) && !this.lexer.match('.', 2)) { | ||
return this.parseFloatingNumber(); | ||
} | ||
if (this.lexer.matchFunction()) { | ||
return this.parseFunctionExpr(); | ||
} | ||
if (this.lexer.matchAsync()) { | ||
return this.parseAsyncFunctionExpr(); | ||
} | ||
if (this.lexer.matchLiteral()) { | ||
return this.parseLiteralExpr(); | ||
} | ||
if (this.lexer.match('{') && this.lexer.match('{', 1)) { | ||
return this.parseCompileTimeExpr(); | ||
} | ||
if (this.lexer.match('{')) { | ||
@@ -850,6 +896,6 @@ return this.parseObjectExpr(); | ||
static setSubpath(parts) { | ||
const remainingParts = parts.slice(); | ||
let remainingParts = parts.slice(); | ||
while (remainingParts.length) { | ||
const part = remainingParts.shift(); | ||
if (typeof part !== 'object') { | ||
if (!part || typeof part !== 'object') { | ||
continue; | ||
@@ -862,8 +908,3 @@ } | ||
for (let key in part) { | ||
if (Array.isArray(part[key])) { | ||
remainingParts.push(...part[key].flat()); | ||
} | ||
else if (typeof part[key] === 'object') { | ||
remainingParts.push(part[key]); | ||
} | ||
remainingParts = remainingParts.concat(utils_1.CommonUtils.toArray(part[key])); | ||
} | ||
@@ -875,5 +916,4 @@ } | ||
return parts | ||
.filter((part) => part.type === types_1.SyntaxType.SELECTOR) | ||
.map((part) => part) | ||
.some((part) => part.context?.index || part.context?.item); | ||
.filter((part) => part.type === types_1.SyntaxType.PATH_OPTIONS) | ||
.some((part) => part.options?.index || part.options?.item); | ||
} | ||
@@ -887,3 +927,43 @@ static convertToBlockExpr(expr) { | ||
} | ||
static prependFunctionID(prefix, id) { | ||
return id ? prefix + '.' + id : prefix; | ||
} | ||
static ignoreEmptySelectors(parts) { | ||
return parts.filter((part) => !(part.type === types_1.SyntaxType.SELECTOR && part.selector === '.' && !part.prop)); | ||
} | ||
static combinePathOptionParts(parts) { | ||
if (parts.length < 2) { | ||
return parts; | ||
} | ||
let newParts = []; | ||
for (let i = 0; i < parts.length; i++) { | ||
let currPart = parts[i]; | ||
if (i < parts.length - 1 && parts[i + 1].type === types_1.SyntaxType.PATH_OPTIONS) { | ||
currPart.options = parts[i + 1].options; | ||
i++; | ||
} | ||
newParts.push(currPart); | ||
} | ||
return newParts; | ||
} | ||
static convertToFunctionCallExpr(fnExpr, pathExpr) { | ||
let lastPart = utils_1.CommonUtils.getLastElement(pathExpr.parts); | ||
if (lastPart?.type === types_1.SyntaxType.SELECTOR) { | ||
const selectorExpr = lastPart; | ||
if (selectorExpr.selector === '.' && selectorExpr.prop?.type === types_1.TokenType.ID) { | ||
pathExpr.parts.pop(); | ||
fnExpr.id = selectorExpr.prop.value; | ||
fnExpr.dot = true; | ||
} | ||
} | ||
if (!pathExpr.parts.length && pathExpr.root && typeof pathExpr.root !== 'object') { | ||
fnExpr.id = this.prependFunctionID(pathExpr.root, fnExpr.id); | ||
fnExpr.dot = false; | ||
} | ||
else { | ||
fnExpr.object = pathExpr; | ||
} | ||
return fnExpr; | ||
} | ||
} | ||
exports.JsonTemplateParser = JsonTemplateParser; |
@@ -6,4 +6,5 @@ import { Expression } from './types'; | ||
private unusedVars; | ||
private expr; | ||
constructor(expr: Expression); | ||
private readonly expr; | ||
private readonly compileTimeBindings?; | ||
constructor(expr: Expression, compileTimeBindings?: any); | ||
private init; | ||
@@ -15,2 +16,3 @@ private acquireVar; | ||
private translateExpr; | ||
private translateCompileTimeExpr; | ||
private translateConditionalExpr; | ||
@@ -20,3 +22,3 @@ private translateLambdaArgExpr; | ||
private translatePathRoot; | ||
private translatePathContext; | ||
private translatePathContextVariables; | ||
private prepareDataForPathPart; | ||
@@ -28,2 +30,3 @@ private translatePathParts; | ||
private translateDescendantSelector; | ||
private translateBlockExpr; | ||
private translateFunctionExpr; | ||
@@ -48,9 +51,12 @@ private getFunctionName; | ||
private translateUnaryExpr; | ||
private static getPathOptions; | ||
private static isToArray; | ||
private static isArrayFilterExpr; | ||
private static isValidSelectorForAssignment; | ||
private static isSinglePropSelection; | ||
private static returnIsEmpty; | ||
private static returnIsNotEmpty; | ||
private static returnObjectValues; | ||
private static returnSingleValue; | ||
private static convertToSingleValue; | ||
private static returnSingleValueIfSafe; | ||
private static convertToSingleValueIfSafe; | ||
private static covertToArrayValue; | ||
@@ -57,0 +63,0 @@ private static generateAssignmentCode; |
@@ -5,2 +5,3 @@ "use strict"; | ||
const constants_1 = require("./constants"); | ||
const engine_1 = require("./engine"); | ||
const errors_1 = require("./errors"); | ||
@@ -11,3 +12,3 @@ const operators_1 = require("./operators"); | ||
class JsonTemplateTranslator { | ||
constructor(expr) { | ||
constructor(expr, compileTimeBindings) { | ||
this.vars = []; | ||
@@ -17,2 +18,3 @@ this.lastVarId = 0; | ||
this.expr = expr; | ||
this.compileTimeBindings = compileTimeBindings; | ||
} | ||
@@ -82,2 +84,4 @@ init() { | ||
return this.translateObjectExpr(expr, dest, ctx); | ||
case types_1.SyntaxType.BLOCK_EXPR: | ||
return this.translateBlockExpr(expr, dest, ctx); | ||
case types_1.SyntaxType.FUNCTION_EXPR: | ||
@@ -101,2 +105,4 @@ return this.translateFunctionExpr(expr, dest, ctx); | ||
return this.translateConditionalExpr(expr, dest, ctx); | ||
case types_1.SyntaxType.COMPILE_TIME_EXPR: | ||
return this.translateCompileTimeExpr(expr, dest, ctx); | ||
default: | ||
@@ -106,2 +112,6 @@ return ''; | ||
} | ||
translateCompileTimeExpr(expr, dest, _ctx) { | ||
const value = engine_1.JsonTemplateEngine.createSync(expr.value).evaluate({}, this.compileTimeBindings); | ||
return JsonTemplateTranslator.generateAssignmentCode(dest, JSON.stringify(value)); | ||
} | ||
translateConditionalExpr(expr, dest, ctx) { | ||
@@ -139,2 +149,3 @@ const code = []; | ||
const propStr = utils_1.CommonUtils.escapeStr(part.prop?.value); | ||
path.options = Object.assign({}, path.options, part.options); | ||
return `${dest} = ${ctx}[${propStr}];`; | ||
@@ -145,25 +156,20 @@ } | ||
} | ||
translatePathContext(context, item, idx) { | ||
translatePathContextVariables(expr, partNum, item, idx) { | ||
let options = JsonTemplateTranslator.getPathOptions(expr, partNum); | ||
const code = []; | ||
if (context.item) { | ||
code.push(`let ${context.item} = ${item};`); | ||
if (options.item) { | ||
code.push(`let ${options.item} = ${item};`); | ||
} | ||
if (context.index) { | ||
code.push(`let ${context.index} = ${idx};`); | ||
if (options.index) { | ||
code.push(`let ${options.index} = ${idx};`); | ||
} | ||
return code.join(''); | ||
} | ||
prepareDataForPathPart(part, data) { | ||
prepareDataForPathPart(expr, partNum, data) { | ||
const code = []; | ||
code.push(JsonTemplateTranslator.covertToArrayValue(data)); | ||
if (JsonTemplateTranslator.isSinglePropSelection(part)) { | ||
const selector = part; | ||
const propStr = utils_1.CommonUtils.escapeStr(selector.prop?.value); | ||
code.push(`if(Object.prototype.hasOwnProperty.call(${data}, ${propStr})){`); | ||
if (JsonTemplateTranslator.isArrayFilterExpr(expr.parts[partNum]) || | ||
JsonTemplateTranslator.isToArray(expr, partNum)) { | ||
code.push(`${data} = [${data}];`); | ||
code.push('}'); | ||
} | ||
else if (JsonTemplateTranslator.isArrayFilterExpr(part)) { | ||
code.push(`${data} = [${data}];`); | ||
} | ||
return code.join(''); | ||
@@ -185,14 +191,12 @@ } | ||
for (let i = 0; i < numParts; i++) { | ||
const part = parts[i]; | ||
let part = parts[i]; | ||
const idx = indexVars[i]; | ||
const item = itemVars[i]; | ||
const data = dataVars[i]; | ||
code.push(this.prepareDataForPathPart(part, data)); | ||
code.push(this.prepareDataForPathPart(expr, i, data)); | ||
code.push(`for(${idx}=0; ${idx}<${data}.length; ${idx}++) {`); | ||
code.push(`${item} = ${data}[${idx}];`); | ||
if (i > 0 && parts[i - 1].context) { | ||
code.push(this.translatePathContext(parts[i - 1].context, item, idx)); | ||
} | ||
code.push(this.translatePathContextVariables(expr, i, item, idx)); | ||
code.push(this.translateExpr(part, item, item)); | ||
code.push(`if(!${item}) { continue; }`); | ||
code.push(`if(${JsonTemplateTranslator.returnIsEmpty(item)}) { continue; }`); | ||
if (i < numParts - 1) { | ||
@@ -202,4 +206,3 @@ code.push(JsonTemplateTranslator.generateAssignmentCode(dataVars[i + 1], item)); | ||
else { | ||
code.push(JsonTemplateTranslator.covertToArrayValue(item)); | ||
code.push(`${result} = ${result}.concat(${item});`); | ||
code.push(`${result}.push(${item});`); | ||
} | ||
@@ -214,4 +217,4 @@ } | ||
this.releaseVars(result); | ||
if (!expr.toArray) { | ||
code.push(result, '=', JsonTemplateTranslator.returnSingleValueIfSafe(result), ';'); | ||
if (!expr.returnAsArray) { | ||
code.push(JsonTemplateTranslator.convertToSingleValueIfSafe(result)); | ||
} | ||
@@ -225,3 +228,3 @@ code.push(JsonTemplateTranslator.generateAssignmentCode(dest, result)); | ||
code.push(this.translatePathParts(expr, dest)); | ||
if (expr.toArray && !expr.parts.length) { | ||
if (expr.returnAsArray && expr.parts.length === 0) { | ||
code.push(JsonTemplateTranslator.covertToArrayValue(dest)); | ||
@@ -243,3 +246,3 @@ } | ||
code.push('} else {'); | ||
code.push(`${dest} = undefined`); | ||
code.push(`${dest} = undefined;`); | ||
code.push('}'); | ||
@@ -266,3 +269,3 @@ } | ||
code.push(`${currCtx} = ${ctxs}.shift();`); | ||
code.push(`if(!${currCtx}){continue;}`); | ||
code.push(`if(${JsonTemplateTranslator.returnIsEmpty(currCtx)}){continue;}`); | ||
code.push(`if(Array.isArray(${currCtx})){`); | ||
@@ -281,3 +284,3 @@ code.push(`${ctxs} = ${ctxs}.concat(${currCtx});`); | ||
code.push(`if(Object.prototype.hasOwnProperty.call(${currCtx}, ${propStr})){`); | ||
code.push(`${result}.push(${currCtx}[${propStr}]);`); | ||
code.push(`${result} = ${result}.concat(${currCtx}[${propStr}]);`); | ||
code.push('}'); | ||
@@ -294,2 +297,13 @@ } | ||
} | ||
translateBlockExpr(expr, dest, ctx) { | ||
if (expr.statements.length === 1) { | ||
return this.translateExpr(expr.statements[0], dest, ctx); | ||
} | ||
const fnExpr = { | ||
type: types_1.SyntaxType.FUNCTION_EXPR, | ||
body: utils_1.CommonUtils.convertToStatementsExpr(...expr.statements), | ||
block: true, | ||
}; | ||
return this.translateExpr(fnExpr, dest, ctx); | ||
} | ||
translateFunctionExpr(expr, dest, ctx) { | ||
@@ -318,7 +332,8 @@ let code = []; | ||
} | ||
if (!expr.id) { | ||
code.push(JsonTemplateTranslator.convertToSingleValue(result)); | ||
} | ||
code.push(`if(${JsonTemplateTranslator.returnIsNotEmpty(result)}){`); | ||
const functionArgsStr = this.translateSpreadableExpressions(expr.args, result, code); | ||
code.push(dest, '=', this.getFunctionName(expr, result), '(', functionArgsStr, ');'); | ||
code.push(result, '=', this.getFunctionName(expr, result), '(', functionArgsStr, ');'); | ||
code.push('}'); | ||
code.push(JsonTemplateTranslator.generateAssignmentCode(dest, result)); | ||
this.releaseVars(result); | ||
return code.join(''); | ||
@@ -509,2 +524,8 @@ } | ||
} | ||
static getPathOptions(expr, partNum) { | ||
return (partNum === 0 ? expr.options : expr.parts[partNum - 1]?.options) || {}; | ||
} | ||
static isToArray(expr, partNum) { | ||
return this.getPathOptions(expr, partNum).toArray === true; | ||
} | ||
static isArrayFilterExpr(expr) { | ||
@@ -524,2 +545,8 @@ return expr.type === types_1.SyntaxType.ARRAY_FILTER_EXPR; | ||
} | ||
static returnIsEmpty(varName) { | ||
return `${varName} === null || ${varName} === undefined`; | ||
} | ||
static returnIsNotEmpty(varName) { | ||
return `${varName} !== null && ${varName} !== undefined`; | ||
} | ||
static returnObjectValues(varName) { | ||
@@ -534,8 +561,5 @@ return `Object.values(${varName}).filter(v => v !== null && v !== undefined)`; | ||
} | ||
static convertToSingleValue(varName) { | ||
return `${varName} = Array.isArray(${varName}) ? ${varName}[0] : ${varName};`; | ||
static convertToSingleValueIfSafe(varName) { | ||
return `${varName} = ${varName}.length < 2 ? ${varName}[0] : ${varName};`; | ||
} | ||
static returnSingleValueIfSafe(varName) { | ||
return `(${varName}.length < 2 ? ${varName}[0] : ${varName})`; | ||
} | ||
static covertToArrayValue(varName) { | ||
@@ -557,2 +581,3 @@ return `${varName} = Array.isArray(${varName}) ? ${varName} : [${varName}];`; | ||
} | ||
code.push(`if(!${dest}){continue;}`); | ||
} | ||
@@ -559,0 +584,0 @@ return code.join(''); |
@@ -16,12 +16,13 @@ export type Dictionary<T> = Record<string, T>; | ||
ID = 1, | ||
NUM = 2, | ||
STR = 3, | ||
BOOL = 4, | ||
NULL = 5, | ||
UNDEFINED = 6, | ||
LAMBDA_ARG = 7, | ||
PUNCT = 8, | ||
THROW = 9, | ||
KEYWORD = 10, | ||
EOT = 11 | ||
INT = 2, | ||
FLOAT = 3, | ||
STR = 4, | ||
BOOL = 5, | ||
NULL = 6, | ||
UNDEFINED = 7, | ||
LAMBDA_ARG = 8, | ||
PUNCT = 9, | ||
THROW = 10, | ||
KEYWORD = 11, | ||
EOT = 12 | ||
} | ||
@@ -46,29 +47,31 @@ export declare enum OperatorType { | ||
PATH = 1, | ||
SELECTOR = 2, | ||
LAMBDA_ARG = 3, | ||
LITERAL = 4, | ||
LOGICAL_COALESCE_EXPR = 5, | ||
LOGICAL_OR_EXPR = 6, | ||
LOGICAL_AND_EXPR = 7, | ||
COMPARISON_EXPR = 8, | ||
IN_EXPR = 9, | ||
MATH_EXPR = 10, | ||
UNARY_EXPR = 11, | ||
SPREAD_EXPR = 12, | ||
ARRAY_INDEX_FILTER_EXPR = 13, | ||
OBJECT_INDEX_FILTER_EXPR = 14, | ||
RANGE_FILTER_EXPR = 15, | ||
OBJECT_FILTER_EXPR = 16, | ||
ARRAY_FILTER_EXPR = 17, | ||
DEFINTION_EXPR = 18, | ||
ASSIGNMENT_EXPR = 19, | ||
OBJECT_PROP_EXPR = 20, | ||
OBJECT_EXPR = 21, | ||
TO_ARRAY = 22, | ||
ARRAY_EXPR = 23, | ||
FUNCTION_EXPR = 24, | ||
FUNCTION_CALL_ARG = 25, | ||
FUNCTION_CALL_EXPR = 26, | ||
STATEMENTS_EXPR = 27, | ||
CONDITIONAL_EXPR = 28 | ||
PATH_OPTIONS = 2, | ||
SELECTOR = 3, | ||
LAMBDA_ARG = 4, | ||
LITERAL = 5, | ||
LOGICAL_COALESCE_EXPR = 6, | ||
LOGICAL_OR_EXPR = 7, | ||
LOGICAL_AND_EXPR = 8, | ||
COMPARISON_EXPR = 9, | ||
IN_EXPR = 10, | ||
MATH_EXPR = 11, | ||
UNARY_EXPR = 12, | ||
SPREAD_EXPR = 13, | ||
CONDITIONAL_EXPR = 14, | ||
ARRAY_INDEX_FILTER_EXPR = 15, | ||
OBJECT_INDEX_FILTER_EXPR = 16, | ||
RANGE_FILTER_EXPR = 17, | ||
OBJECT_FILTER_EXPR = 18, | ||
ARRAY_FILTER_EXPR = 19, | ||
DEFINTION_EXPR = 20, | ||
ASSIGNMENT_EXPR = 21, | ||
OBJECT_PROP_EXPR = 22, | ||
OBJECT_EXPR = 23, | ||
ARRAY_EXPR = 24, | ||
BLOCK_EXPR = 25, | ||
FUNCTION_EXPR = 26, | ||
FUNCTION_CALL_ARG = 27, | ||
FUNCTION_CALL_EXPR = 28, | ||
COMPILE_TIME_EXPR = 29, | ||
STATEMENTS_EXPR = 30 | ||
} | ||
@@ -80,4 +83,10 @@ export type Token = { | ||
}; | ||
export interface PathOptions { | ||
item?: string; | ||
index?: string; | ||
toArray?: boolean; | ||
} | ||
export interface Expression { | ||
type: SyntaxType; | ||
options?: PathOptions; | ||
[key: string]: any; | ||
@@ -94,2 +103,5 @@ } | ||
} | ||
export interface BlockExpression extends Expression { | ||
statements: Expression[]; | ||
} | ||
export interface ObjectPropExpression extends Expression { | ||
@@ -102,2 +114,5 @@ key?: Expression | string; | ||
} | ||
export interface CompileTimeExpression extends Expression { | ||
value: Expression; | ||
} | ||
export interface ArrayExpression extends Expression { | ||
@@ -151,13 +166,8 @@ elements: Expression[]; | ||
root?: Expression | string; | ||
toArray?: boolean; | ||
returnAsArray?: boolean; | ||
subPath?: boolean; | ||
} | ||
export interface ContextVariable { | ||
item?: string; | ||
index?: string; | ||
} | ||
export interface SelectorExpression extends Expression { | ||
selector: string; | ||
prop?: Token; | ||
context?: ContextVariable; | ||
} | ||
@@ -164,0 +174,0 @@ export interface SpreadExpression extends Expression { |
@@ -20,12 +20,13 @@ "use strict"; | ||
TokenType[TokenType["ID"] = 1] = "ID"; | ||
TokenType[TokenType["NUM"] = 2] = "NUM"; | ||
TokenType[TokenType["STR"] = 3] = "STR"; | ||
TokenType[TokenType["BOOL"] = 4] = "BOOL"; | ||
TokenType[TokenType["NULL"] = 5] = "NULL"; | ||
TokenType[TokenType["UNDEFINED"] = 6] = "UNDEFINED"; | ||
TokenType[TokenType["LAMBDA_ARG"] = 7] = "LAMBDA_ARG"; | ||
TokenType[TokenType["PUNCT"] = 8] = "PUNCT"; | ||
TokenType[TokenType["THROW"] = 9] = "THROW"; | ||
TokenType[TokenType["KEYWORD"] = 10] = "KEYWORD"; | ||
TokenType[TokenType["EOT"] = 11] = "EOT"; | ||
TokenType[TokenType["INT"] = 2] = "INT"; | ||
TokenType[TokenType["FLOAT"] = 3] = "FLOAT"; | ||
TokenType[TokenType["STR"] = 4] = "STR"; | ||
TokenType[TokenType["BOOL"] = 5] = "BOOL"; | ||
TokenType[TokenType["NULL"] = 6] = "NULL"; | ||
TokenType[TokenType["UNDEFINED"] = 7] = "UNDEFINED"; | ||
TokenType[TokenType["LAMBDA_ARG"] = 8] = "LAMBDA_ARG"; | ||
TokenType[TokenType["PUNCT"] = 9] = "PUNCT"; | ||
TokenType[TokenType["THROW"] = 10] = "THROW"; | ||
TokenType[TokenType["KEYWORD"] = 11] = "KEYWORD"; | ||
TokenType[TokenType["EOT"] = 12] = "EOT"; | ||
})(TokenType = exports.TokenType || (exports.TokenType = {})); | ||
@@ -53,29 +54,31 @@ // In the order of precedence | ||
SyntaxType[SyntaxType["PATH"] = 1] = "PATH"; | ||
SyntaxType[SyntaxType["SELECTOR"] = 2] = "SELECTOR"; | ||
SyntaxType[SyntaxType["LAMBDA_ARG"] = 3] = "LAMBDA_ARG"; | ||
SyntaxType[SyntaxType["LITERAL"] = 4] = "LITERAL"; | ||
SyntaxType[SyntaxType["LOGICAL_COALESCE_EXPR"] = 5] = "LOGICAL_COALESCE_EXPR"; | ||
SyntaxType[SyntaxType["LOGICAL_OR_EXPR"] = 6] = "LOGICAL_OR_EXPR"; | ||
SyntaxType[SyntaxType["LOGICAL_AND_EXPR"] = 7] = "LOGICAL_AND_EXPR"; | ||
SyntaxType[SyntaxType["COMPARISON_EXPR"] = 8] = "COMPARISON_EXPR"; | ||
SyntaxType[SyntaxType["IN_EXPR"] = 9] = "IN_EXPR"; | ||
SyntaxType[SyntaxType["MATH_EXPR"] = 10] = "MATH_EXPR"; | ||
SyntaxType[SyntaxType["UNARY_EXPR"] = 11] = "UNARY_EXPR"; | ||
SyntaxType[SyntaxType["SPREAD_EXPR"] = 12] = "SPREAD_EXPR"; | ||
SyntaxType[SyntaxType["ARRAY_INDEX_FILTER_EXPR"] = 13] = "ARRAY_INDEX_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_INDEX_FILTER_EXPR"] = 14] = "OBJECT_INDEX_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["RANGE_FILTER_EXPR"] = 15] = "RANGE_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_FILTER_EXPR"] = 16] = "OBJECT_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["ARRAY_FILTER_EXPR"] = 17] = "ARRAY_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["DEFINTION_EXPR"] = 18] = "DEFINTION_EXPR"; | ||
SyntaxType[SyntaxType["ASSIGNMENT_EXPR"] = 19] = "ASSIGNMENT_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_PROP_EXPR"] = 20] = "OBJECT_PROP_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_EXPR"] = 21] = "OBJECT_EXPR"; | ||
SyntaxType[SyntaxType["TO_ARRAY"] = 22] = "TO_ARRAY"; | ||
SyntaxType[SyntaxType["ARRAY_EXPR"] = 23] = "ARRAY_EXPR"; | ||
SyntaxType[SyntaxType["FUNCTION_EXPR"] = 24] = "FUNCTION_EXPR"; | ||
SyntaxType[SyntaxType["FUNCTION_CALL_ARG"] = 25] = "FUNCTION_CALL_ARG"; | ||
SyntaxType[SyntaxType["FUNCTION_CALL_EXPR"] = 26] = "FUNCTION_CALL_EXPR"; | ||
SyntaxType[SyntaxType["STATEMENTS_EXPR"] = 27] = "STATEMENTS_EXPR"; | ||
SyntaxType[SyntaxType["CONDITIONAL_EXPR"] = 28] = "CONDITIONAL_EXPR"; | ||
SyntaxType[SyntaxType["PATH_OPTIONS"] = 2] = "PATH_OPTIONS"; | ||
SyntaxType[SyntaxType["SELECTOR"] = 3] = "SELECTOR"; | ||
SyntaxType[SyntaxType["LAMBDA_ARG"] = 4] = "LAMBDA_ARG"; | ||
SyntaxType[SyntaxType["LITERAL"] = 5] = "LITERAL"; | ||
SyntaxType[SyntaxType["LOGICAL_COALESCE_EXPR"] = 6] = "LOGICAL_COALESCE_EXPR"; | ||
SyntaxType[SyntaxType["LOGICAL_OR_EXPR"] = 7] = "LOGICAL_OR_EXPR"; | ||
SyntaxType[SyntaxType["LOGICAL_AND_EXPR"] = 8] = "LOGICAL_AND_EXPR"; | ||
SyntaxType[SyntaxType["COMPARISON_EXPR"] = 9] = "COMPARISON_EXPR"; | ||
SyntaxType[SyntaxType["IN_EXPR"] = 10] = "IN_EXPR"; | ||
SyntaxType[SyntaxType["MATH_EXPR"] = 11] = "MATH_EXPR"; | ||
SyntaxType[SyntaxType["UNARY_EXPR"] = 12] = "UNARY_EXPR"; | ||
SyntaxType[SyntaxType["SPREAD_EXPR"] = 13] = "SPREAD_EXPR"; | ||
SyntaxType[SyntaxType["CONDITIONAL_EXPR"] = 14] = "CONDITIONAL_EXPR"; | ||
SyntaxType[SyntaxType["ARRAY_INDEX_FILTER_EXPR"] = 15] = "ARRAY_INDEX_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_INDEX_FILTER_EXPR"] = 16] = "OBJECT_INDEX_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["RANGE_FILTER_EXPR"] = 17] = "RANGE_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_FILTER_EXPR"] = 18] = "OBJECT_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["ARRAY_FILTER_EXPR"] = 19] = "ARRAY_FILTER_EXPR"; | ||
SyntaxType[SyntaxType["DEFINTION_EXPR"] = 20] = "DEFINTION_EXPR"; | ||
SyntaxType[SyntaxType["ASSIGNMENT_EXPR"] = 21] = "ASSIGNMENT_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_PROP_EXPR"] = 22] = "OBJECT_PROP_EXPR"; | ||
SyntaxType[SyntaxType["OBJECT_EXPR"] = 23] = "OBJECT_EXPR"; | ||
SyntaxType[SyntaxType["ARRAY_EXPR"] = 24] = "ARRAY_EXPR"; | ||
SyntaxType[SyntaxType["BLOCK_EXPR"] = 25] = "BLOCK_EXPR"; | ||
SyntaxType[SyntaxType["FUNCTION_EXPR"] = 26] = "FUNCTION_EXPR"; | ||
SyntaxType[SyntaxType["FUNCTION_CALL_ARG"] = 27] = "FUNCTION_CALL_ARG"; | ||
SyntaxType[SyntaxType["FUNCTION_CALL_EXPR"] = 28] = "FUNCTION_CALL_EXPR"; | ||
SyntaxType[SyntaxType["COMPILE_TIME_EXPR"] = 29] = "COMPILE_TIME_EXPR"; | ||
SyntaxType[SyntaxType["STATEMENTS_EXPR"] = 30] = "STATEMENTS_EXPR"; | ||
})(SyntaxType = exports.SyntaxType || (exports.SyntaxType = {})); |
import { Expression, StatementsExpression } from './types'; | ||
export declare class CommonUtils { | ||
static toArray(val: any): any[]; | ||
static toArray(val: any): any[] | undefined; | ||
static getLastElement<T>(arr: T[]): T | undefined; | ||
@@ -5,0 +5,0 @@ static convertToStatementsExpr(...expressions: Expression[]): StatementsExpression; |
@@ -7,5 +7,11 @@ "use strict"; | ||
static toArray(val) { | ||
if (val === undefined || val === null) { | ||
return undefined; | ||
} | ||
return Array.isArray(val) ? val : [val]; | ||
} | ||
static getLastElement(arr) { | ||
if (!arr.length) { | ||
return undefined; | ||
} | ||
return arr[arr.length - 1]; | ||
@@ -12,0 +18,0 @@ } |
# Changelog | ||
## [0.2.2](https://github.com/rudderlabs/rudder-json-template-engine/compare/v0.2.1...v0.2.2) (2022-11-30) | ||
### Features | ||
* add support for compile time expressions ([#12](https://github.com/rudderlabs/rudder-json-template-engine/issues/12)) ([4fc59c0](https://github.com/rudderlabs/rudder-json-template-engine/commit/4fc59c00289e1f10c0e22e4f80e7e72316e07091)) | ||
* add support for index selectors ([#13](https://github.com/rudderlabs/rudder-json-template-engine/issues/13)) ([db8a661](https://github.com/rudderlabs/rudder-json-template-engine/commit/db8a661decada7c9d6b4d1aab4cda3d25f8fe748)) | ||
* add support to use context variables any where in the path ([#11](https://github.com/rudderlabs/rudder-json-template-engine/issues/11)) ([5e8f75e](https://github.com/rudderlabs/rudder-json-template-engine/commit/5e8f75e2fe7d86f8b0409470f5a1385734a686af)) | ||
### Bug Fixes | ||
* add missing semi-colon ([dcee815](https://github.com/rudderlabs/rudder-json-template-engine/commit/dcee8151379f86f98699683e92168f29fdbbfac7)) | ||
* block expressions ([#10](https://github.com/rudderlabs/rudder-json-template-engine/issues/10)) ([509fccf](https://github.com/rudderlabs/rudder-json-template-engine/commit/509fccf90190da65b929c9c149fbdaed3e45a174)) | ||
## [0.2.1](https://github.com/rudderlabs/rudder-json-template-engine/compare/v0.2.0...v0.2.1) (2022-11-22) | ||
@@ -4,0 +19,0 @@ |
{ | ||
"name": "rudder-json-template-engine", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"homepage": "https://github.com/rudderlabs/rudder-workflow-engine", | ||
@@ -5,0 +5,0 @@ "description": "A library for evaluating JSON template expressions.", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
111385
2849
1