Comparing version 0.39.0 to 0.40.0
@@ -1,3 +0,3 @@ | ||
import { parser, trackVariables, normalizeContext } from 'lezer-feel'; | ||
import { Duration, DateTime, Info, FixedOffsetZone } from 'luxon'; | ||
import { normalizeContextKey, parser, trackVariables } from 'lezer-feel'; | ||
@@ -22,2 +22,25 @@ function parseParameterNames(fn) { | ||
} | ||
/** | ||
* @param {string} name | ||
* @param {Record<string, any>} context | ||
* | ||
* @return {any} | ||
*/ | ||
function getFromContext(name, context) { | ||
if (['nil', 'boolean', 'number', 'string'].includes(getType(context))) { | ||
return null; | ||
} | ||
if (name in context) { | ||
return context[name]; | ||
} | ||
const normalizedName = normalizeContextKey(name); | ||
if (normalizedName in context) { | ||
return context[normalizedName]; | ||
} | ||
const entry = Object.entries(context).find(([key]) => normalizedName === normalizeContextKey(key)); | ||
if (entry) { | ||
return entry[1]; | ||
} | ||
return null; | ||
} | ||
@@ -115,2 +138,5 @@ function isDateTime(obj) { | ||
} | ||
if (e instanceof FunctionWrapper) { | ||
return 'function'; | ||
} | ||
return 'literal'; | ||
@@ -141,25 +167,4 @@ } | ||
constructor(props) { | ||
this.props = props; | ||
Object.assign(this, props); | ||
} | ||
map(fn) { | ||
return this.props.map(fn); | ||
} | ||
includes(val) { | ||
if (val === null) { | ||
return null; | ||
} | ||
return this.props.includes(val); | ||
} | ||
get start() { | ||
return this.props.start; | ||
} | ||
get 'start included'() { | ||
return this.props['start included']; | ||
} | ||
get end() { | ||
return this.props.end; | ||
} | ||
get 'end included'() { | ||
return this.props['end included']; | ||
} | ||
} | ||
@@ -231,2 +236,18 @@ function isNumber(obj) { | ||
} | ||
class FunctionWrapper { | ||
constructor(fn, parameterNames) { | ||
this.fn = fn; | ||
this.parameterNames = parameterNames; | ||
} | ||
invoke(contextOrArgs) { | ||
let params; | ||
if (isArray(contextOrArgs)) { | ||
params = contextOrArgs; | ||
} | ||
else { | ||
params = this.parameterNames.map(n => contextOrArgs[n]); | ||
} | ||
return this.fn.call(null, ...params); | ||
} | ||
} | ||
@@ -386,5 +407,5 @@ // 10.3.4 Built-in functions | ||
}, ['string', 'string']), | ||
'replace': fn(function (input, pattern, replacement, flags = '') { | ||
return input.replace(new RegExp(pattern, 'ug' + flags.replace(/[x]/g, '')), replacement.replace(/\$0/g, '$$&')); | ||
}, ['string', 'string', 'string']), | ||
'replace': fn(function (input, pattern, replacement, flags) { | ||
return input.replace(new RegExp(pattern, 'ug' + (flags || '').replace(/[x]/g, '')), replacement.replace(/\$0/g, '$$&')); | ||
}, ['string', 'string', 'string', 'string?']), | ||
'contains': fn(function (string, match) { | ||
@@ -630,9 +651,3 @@ return string.includes(match); | ||
'get value': fn(function (m, key) { | ||
if (arguments.length !== 2) { | ||
return null; | ||
} | ||
if (!m) { | ||
return null; | ||
} | ||
return key in m ? m[key] : null; | ||
return getFromContext(key, m); | ||
}, ['context', 'string']), | ||
@@ -829,2 +844,5 @@ 'get entries': fn(function (m) { | ||
} | ||
if (type === 'range') { | ||
return '<range>'; | ||
} | ||
if (type === 'time') { | ||
@@ -836,2 +854,5 @@ if ((_c = obj.zone) === null || _c === void 0 ? void 0 : _c.zoneName) { | ||
} | ||
if (type === 'function') { | ||
return '<function>'; | ||
} | ||
throw notImplemented('string(' + type + ')'); | ||
@@ -952,3 +973,3 @@ } | ||
// root = fn(ctx) => test(val) | ||
const test = root(normalizeContext(context)); | ||
const test = root(context); | ||
return test(value); | ||
@@ -959,3 +980,3 @@ } | ||
// root = [ fn(ctx) ] | ||
const results = root(normalizeContext(context)); | ||
const results = root(context); | ||
if (results.length === 1) { | ||
@@ -1077,3 +1098,5 @@ return results[0]; | ||
case 'SpecialFunctionName': return (context) => getBuiltin(input); | ||
case 'Name': return args.join(' '); | ||
// preserve spaces in name, but compact multiple | ||
// spaces into one (token) | ||
case 'Name': return input.replace(/\s{2,}/g, ' '); | ||
case 'VariableName': return (context) => { | ||
@@ -1262,3 +1285,3 @@ const name = args.join(' '); | ||
if (isArray(pathTarget)) { | ||
return pathTarget.map(pathProp); | ||
return coerceSingleton(pathTarget.map(pathProp)); | ||
} | ||
@@ -1364,13 +1387,4 @@ else { | ||
function getBuiltin(name, _context) { | ||
return builtins[name]; | ||
return getFromContext(name, builtins); | ||
} | ||
function getFromContext(name, context) { | ||
if (['nil', 'boolean', 'number', 'string'].includes(getType(context))) { | ||
return null; | ||
} | ||
if (name in context) { | ||
return context[name]; | ||
} | ||
return null; | ||
} | ||
function extractValue(context, prop, _target) { | ||
@@ -1585,3 +1599,3 @@ const target = _target(context); | ||
* | ||
* @return {WrappedFn} | ||
* @return {FunctionWrapper} | ||
*/ | ||
@@ -1592,21 +1606,17 @@ function wrapFunction(fn, parameterNames = null) { | ||
} | ||
if (fn instanceof WrappedFn) { | ||
if (fn instanceof FunctionWrapper) { | ||
return fn; | ||
} | ||
if (fn instanceof Range) { | ||
return new WrappedFn((value) => fn.includes(value), ['value']); | ||
return new FunctionWrapper((value) => fn.includes(value), ['value']); | ||
} | ||
return new WrappedFn(fn, parameterNames || parseParameterNames(fn)); | ||
return new FunctionWrapper(fn, parameterNames || parseParameterNames(fn)); | ||
} | ||
function WrappedFn(fn, parameterNames) { | ||
this.invoke = function (contextOrArgs) { | ||
let params; | ||
if (isArray(contextOrArgs)) { | ||
params = contextOrArgs; | ||
} | ||
else { | ||
params = parameterNames.map(n => contextOrArgs[n]); | ||
} | ||
return fn.call(null, ...params); | ||
}; | ||
function coerceSingleton(values) { | ||
if (Array.isArray(values) && values.length === 1) { | ||
return values[0]; | ||
} | ||
else { | ||
return values; | ||
} | ||
} | ||
@@ -1613,0 +1623,0 @@ function parseString(str) { |
@@ -5,4 +5,4 @@ 'use strict'; | ||
var luxon = require('luxon'); | ||
var lezerFeel = require('lezer-feel'); | ||
var luxon = require('luxon'); | ||
@@ -27,2 +27,25 @@ function parseParameterNames(fn) { | ||
} | ||
/** | ||
* @param {string} name | ||
* @param {Record<string, any>} context | ||
* | ||
* @return {any} | ||
*/ | ||
function getFromContext(name, context) { | ||
if (['nil', 'boolean', 'number', 'string'].includes(getType(context))) { | ||
return null; | ||
} | ||
if (name in context) { | ||
return context[name]; | ||
} | ||
const normalizedName = lezerFeel.normalizeContextKey(name); | ||
if (normalizedName in context) { | ||
return context[normalizedName]; | ||
} | ||
const entry = Object.entries(context).find(([key]) => normalizedName === lezerFeel.normalizeContextKey(key)); | ||
if (entry) { | ||
return entry[1]; | ||
} | ||
return null; | ||
} | ||
@@ -120,2 +143,5 @@ function isDateTime(obj) { | ||
} | ||
if (e instanceof FunctionWrapper) { | ||
return 'function'; | ||
} | ||
return 'literal'; | ||
@@ -146,25 +172,4 @@ } | ||
constructor(props) { | ||
this.props = props; | ||
Object.assign(this, props); | ||
} | ||
map(fn) { | ||
return this.props.map(fn); | ||
} | ||
includes(val) { | ||
if (val === null) { | ||
return null; | ||
} | ||
return this.props.includes(val); | ||
} | ||
get start() { | ||
return this.props.start; | ||
} | ||
get 'start included'() { | ||
return this.props['start included']; | ||
} | ||
get end() { | ||
return this.props.end; | ||
} | ||
get 'end included'() { | ||
return this.props['end included']; | ||
} | ||
} | ||
@@ -236,2 +241,18 @@ function isNumber(obj) { | ||
} | ||
class FunctionWrapper { | ||
constructor(fn, parameterNames) { | ||
this.fn = fn; | ||
this.parameterNames = parameterNames; | ||
} | ||
invoke(contextOrArgs) { | ||
let params; | ||
if (isArray(contextOrArgs)) { | ||
params = contextOrArgs; | ||
} | ||
else { | ||
params = this.parameterNames.map(n => contextOrArgs[n]); | ||
} | ||
return this.fn.call(null, ...params); | ||
} | ||
} | ||
@@ -391,5 +412,5 @@ // 10.3.4 Built-in functions | ||
}, ['string', 'string']), | ||
'replace': fn(function (input, pattern, replacement, flags = '') { | ||
return input.replace(new RegExp(pattern, 'ug' + flags.replace(/[x]/g, '')), replacement.replace(/\$0/g, '$$&')); | ||
}, ['string', 'string', 'string']), | ||
'replace': fn(function (input, pattern, replacement, flags) { | ||
return input.replace(new RegExp(pattern, 'ug' + (flags || '').replace(/[x]/g, '')), replacement.replace(/\$0/g, '$$&')); | ||
}, ['string', 'string', 'string', 'string?']), | ||
'contains': fn(function (string, match) { | ||
@@ -635,9 +656,3 @@ return string.includes(match); | ||
'get value': fn(function (m, key) { | ||
if (arguments.length !== 2) { | ||
return null; | ||
} | ||
if (!m) { | ||
return null; | ||
} | ||
return key in m ? m[key] : null; | ||
return getFromContext(key, m); | ||
}, ['context', 'string']), | ||
@@ -834,2 +849,5 @@ 'get entries': fn(function (m) { | ||
} | ||
if (type === 'range') { | ||
return '<range>'; | ||
} | ||
if (type === 'time') { | ||
@@ -841,2 +859,5 @@ if ((_c = obj.zone) === null || _c === void 0 ? void 0 : _c.zoneName) { | ||
} | ||
if (type === 'function') { | ||
return '<function>'; | ||
} | ||
throw notImplemented('string(' + type + ')'); | ||
@@ -957,3 +978,3 @@ } | ||
// root = fn(ctx) => test(val) | ||
const test = root(lezerFeel.normalizeContext(context)); | ||
const test = root(context); | ||
return test(value); | ||
@@ -964,3 +985,3 @@ } | ||
// root = [ fn(ctx) ] | ||
const results = root(lezerFeel.normalizeContext(context)); | ||
const results = root(context); | ||
if (results.length === 1) { | ||
@@ -1082,3 +1103,5 @@ return results[0]; | ||
case 'SpecialFunctionName': return (context) => getBuiltin(input); | ||
case 'Name': return args.join(' '); | ||
// preserve spaces in name, but compact multiple | ||
// spaces into one (token) | ||
case 'Name': return input.replace(/\s{2,}/g, ' '); | ||
case 'VariableName': return (context) => { | ||
@@ -1267,3 +1290,3 @@ const name = args.join(' '); | ||
if (isArray(pathTarget)) { | ||
return pathTarget.map(pathProp); | ||
return coerceSingleton(pathTarget.map(pathProp)); | ||
} | ||
@@ -1369,13 +1392,4 @@ else { | ||
function getBuiltin(name, _context) { | ||
return builtins[name]; | ||
return getFromContext(name, builtins); | ||
} | ||
function getFromContext(name, context) { | ||
if (['nil', 'boolean', 'number', 'string'].includes(getType(context))) { | ||
return null; | ||
} | ||
if (name in context) { | ||
return context[name]; | ||
} | ||
return null; | ||
} | ||
function extractValue(context, prop, _target) { | ||
@@ -1590,3 +1604,3 @@ const target = _target(context); | ||
* | ||
* @return {WrappedFn} | ||
* @return {FunctionWrapper} | ||
*/ | ||
@@ -1597,21 +1611,17 @@ function wrapFunction(fn, parameterNames = null) { | ||
} | ||
if (fn instanceof WrappedFn) { | ||
if (fn instanceof FunctionWrapper) { | ||
return fn; | ||
} | ||
if (fn instanceof Range) { | ||
return new WrappedFn((value) => fn.includes(value), ['value']); | ||
return new FunctionWrapper((value) => fn.includes(value), ['value']); | ||
} | ||
return new WrappedFn(fn, parameterNames || parseParameterNames(fn)); | ||
return new FunctionWrapper(fn, parameterNames || parseParameterNames(fn)); | ||
} | ||
function WrappedFn(fn, parameterNames) { | ||
this.invoke = function (contextOrArgs) { | ||
let params; | ||
if (isArray(contextOrArgs)) { | ||
params = contextOrArgs; | ||
} | ||
else { | ||
params = parameterNames.map(n => contextOrArgs[n]); | ||
} | ||
return fn.call(null, ...params); | ||
}; | ||
function coerceSingleton(values) { | ||
if (Array.isArray(values) && values.length === 1) { | ||
return values[0]; | ||
} | ||
else { | ||
return values; | ||
} | ||
} | ||
@@ -1618,0 +1628,0 @@ function parseString(str) { |
@@ -6,3 +6,3 @@ import { isDateTime, isDuration } from './temporal'; | ||
export declare function isBoolean(e: any): boolean; | ||
export declare function getType(e: any): "string" | "number" | "literal" | "boolean" | "nil" | "context" | "list" | "duration" | "time" | "date" | "date time" | "range"; | ||
export declare function getType(e: any): "string" | "number" | "literal" | "nil" | "boolean" | "context" | "list" | "duration" | "time" | "date" | "date time" | "range" | "function"; | ||
export declare function isType(el: string, type: string): boolean; | ||
@@ -15,14 +15,13 @@ export declare function typeCast(obj: any, type: string): import("luxon").DateTime; | ||
end: string | number | null; | ||
map<T>(fn: (val: any) => T): T[]; | ||
includes(val: any): boolean; | ||
map: <T>(fn: (val: any) => T) => T[]; | ||
includes: (val: any) => boolean; | ||
}; | ||
export declare class Range { | ||
props: RangeProps; | ||
'start included': boolean; | ||
'end included': boolean; | ||
start: string | number | null; | ||
end: string | number | null; | ||
map: <T>(fn: (val: any) => T) => T[]; | ||
includes: (val: any) => boolean; | ||
constructor(props: RangeProps); | ||
map<T>(fn: (any: any) => T): T[]; | ||
includes(val: any): boolean; | ||
get start(): string | number; | ||
get 'start included'(): boolean; | ||
get end(): string | number; | ||
get 'end included'(): boolean; | ||
} | ||
@@ -32,1 +31,7 @@ export declare function isNumber(obj: any): obj is number; | ||
export declare function equals(a: any, b: any): any; | ||
export declare class FunctionWrapper { | ||
fn: (...args: any[]) => any; | ||
parameterNames: string[]; | ||
constructor(fn: (...args: any[]) => any, parameterNames: string[]); | ||
invoke(contextOrArgs: any): any; | ||
} |
export declare function parseParameterNames(fn: any): any; | ||
export declare function notImplemented(thing: any): Error; | ||
/** | ||
* @param {string} name | ||
* @param {Record<string, any>} context | ||
* | ||
* @return {any} | ||
*/ | ||
export declare function getFromContext(name: any, context: any): any; |
{ | ||
"name": "feelin", | ||
"version": "0.39.0", | ||
"version": "0.40.0", | ||
"description": "A FEEL parser and interpreter", | ||
@@ -37,3 +37,3 @@ "main": "dist/index.js", | ||
"@lezer/lr": "^1.2.0", | ||
"lezer-feel": "^0.11.1", | ||
"lezer-feel": "^0.12.1", | ||
"luxon": "^3.0.1" | ||
@@ -40,0 +40,0 @@ }, |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
339795
3645
+ Addedlezer-feel@0.12.1(transitive)
- Removedlezer-feel@0.11.4(transitive)
Updatedlezer-feel@^0.12.1