@@ -9,6 +9,7 @@ import { buildAsync } from './compiler.js'
9
9
import omitUndefined from './utilities/omitUndefined.js'
10
10
import { optimize } from './async_optimizer.js'
11
11
import { applyPatches } from './compatibility.js'
12
+ import { coerceArray } from './utilities/coerceArray.js'
12
13
13
14
/**
14
15
* An engine capable of running asynchronous JSON Logic.
@@ -75,16 +76,15 @@ class AsyncLogicEngine {
75
76
if ( ! this . methods [ func ] ) throw new Error ( `Method '${ func } ' was not found in the Logic Engine.` )
76
77
77
78
if ( typeof this . methods [ func ] === 'function' ) {
78
- const input = await this . run ( data , context , { above } )
79
- const result = await this . methods [ func ] ( input , context , above , this )
79
+ const input = ( ! data || typeof data !== 'object' ) ? [ data ] : await this . run ( data , context , { above } )
80
+ const result = await this . methods [ func ] ( coerceArray ( input ) , context , above , this )
80
81
return Array . isArray ( result ) ? Promise . all ( result ) : result
81
82
}
82
83
83
84
if ( typeof this . methods [ func ] === 'object' ) {
84
85
const { asyncMethod, method, traverse } = this . methods [ func ]
85
86
const shouldTraverse = typeof traverse === 'undefined' ? true : traverse
86
- const parsedData = shouldTraverse ? await this . run ( data , context , { above } ) : data
87
-
87
+ const parsedData = shouldTraverse ? ( ( ! data || typeof data !== 'object' ) ? [ data ] : coerceArray ( await this . run ( data , context , { above } ) ) ) : data
88
88
const result = await ( asyncMethod || method ) ( parsedData , context , above , this )
89
89
return Array . isArray ( result ) ? Promise . all ( result ) : result
90
90
}
@@ -96,12 +96,12 @@ class AsyncLogicEngine {
96
96
*
97
97
* @param {String } name The name of the method being added.
98
98
* @param {((args: any, context: any, above: any[], engine: AsyncLogicEngine) => any) | { traverse?: Boolean, method?: (args: any, context: any, above: any[], engine: AsyncLogicEngine) => any, asyncMethod?: (args: any, context: any, above: any[], engine: AsyncLogicEngine) => Promise<any>, deterministic?: Function | Boolean } } method
99
- * @param {{ deterministic?: Boolean, async?: Boolean, sync?: Boolean } } annotations This is used by the compiler to help determine if it can optimize the function being generated.
99
+ * @param {{ deterministic?: Boolean, async?: Boolean, sync?: Boolean, optimizeUnary?: boolean } } annotations This is used by the compiler to help determine if it can optimize the function being generated.
100
100
*/
101
101
addMethod (
102
102
name ,
103
103
method ,
104
- { deterministic, async, sync } = { }
104
+ { deterministic, async, sync, optimizeUnary } = { }
105
105
) {
106
106
if ( typeof async === 'undefined' && typeof sync === 'undefined' ) sync = false
107
107
if ( typeof sync !== 'undefined' ) async = ! sync
@@ -112,7 +112,7 @@ class AsyncLogicEngine {
112
112
else method = { method, traverse : true }
113
113
} else method = { ...method }
114
114
115
- Object . assign ( method , omitUndefined ( { deterministic } ) )
115
+ Object . assign ( method , omitUndefined ( { deterministic, optimizeUnary } ) )
116
116
// @ts -ignore
117
117
this . fallback . addMethod ( name , method , { deterministic } )
118
118
this . methods [ name ] = declareSync ( method , sync )
@@ -188,6 +188,8 @@ class AsyncLogicEngine {
188
188
async build ( logic , options = { } ) {
189
189
const { above = [ ] , top = true } = options
190
190
this . fallback . truthy = this . truthy
191
+ // @ts -ignore
192
+ this . fallback . allowFunctions = this . allowFunctions
191
193
if ( top ) {
192
194
const constructedFunction = await buildAsync ( logic , { engine : this , above, async : true , state : { } } )
193
195
0 commit comments