Skip to content

Commit f2d376c

Browse files
committed
Add pipe operation to the engine, I believe this is fairly general purpose
1 parent 20b77fd commit f2d376c

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

compiler.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,16 @@ import asyncIterators from './async_iterators.js'
1919
*/
2020
function compileTemplate (strings, ...items) {
2121
let res = ''
22+
const buildState = this
2223
for (let i = 0; i < strings.length; i++) {
2324
res += strings[i]
2425
if (i < items.length) {
2526
if (typeof items[i] === 'function') {
2627
this.methods.push(items[i])
27-
res += 'methods[' + (this.methods.length - 1) + ']'
28+
if (!isSync(items[i])) buildState.asyncDetected = true
29+
res += (isSync(items[i]) ? '' : ' await ') + 'methods[' + (buildState.methods.length - 1) + ']'
2830
} else if (items[i] && typeof items[i][Compiled] !== 'undefined') res += items[i][Compiled]
29-
else res += buildString(items[i], this)
31+
else res += buildString(items[i], buildState)
3032
}
3133
}
3234
return { [Compiled]: res }

defaultMethods.js

+28-1
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,33 @@ const defaultMethods = {
393393
return res
394394
},
395395
keys: (obj) => typeof obj === 'object' ? Object.keys(obj) : [],
396+
pipe: {
397+
traverse: false,
398+
[Sync]: (data, buildState) => isSyncDeep(data, buildState.engine, buildState),
399+
method: (args, context, above, engine) => {
400+
if (!Array.isArray(args)) throw new Error('Data for pipe must be an array')
401+
let answer = (engine.fallback || engine).run(args[0], context, { above: [args, context, ...above] })
402+
for (let i = 1; i < args.length; i++) answer = (engine.fallback || engine).run(args[i], answer, { above: [args, context, ...above] })
403+
return answer
404+
},
405+
asyncMethod: async (args, context, above, engine) => {
406+
if (!Array.isArray(args)) throw new Error('Data for pipe must be an array')
407+
let answer = await engine.run(args[0], context, { above: [args, context, ...above] })
408+
for (let i = 1; i < args.length; i++) answer = await engine.run(args[i], answer, { above: [args, context, ...above] })
409+
return answer
410+
},
411+
compile: (args, buildState) => {
412+
let res = buildState.compile`${args[0]}`
413+
for (let i = 1; i < args.length; i++) res = buildState.compile`${build(args[i], { ...buildState, extraArguments: 'above' })}(${res}, [null, context, ...above])`
414+
return res
415+
},
416+
deterministic: (data, buildState) => {
417+
if (!Array.isArray(data)) return false
418+
data = [...data]
419+
const first = data.shift()
420+
return isDeterministic(first, buildState.engine, buildState) && isDeterministic(data, buildState.engine, { ...buildState, insideIterator: true })
421+
}
422+
},
396423
eachKey: {
397424
traverse: false,
398425
[Sync]: (data, buildState) => isSyncDeep(Object.values(data[Object.keys(data)[0]]), buildState.engine, buildState),
@@ -506,7 +533,7 @@ function createArrayIterativeMethod (name, useTruthy = false) {
506533
if (async) {
507534
if (!isSyncDeep(mapper, buildState.engine, buildState)) {
508535
buildState.detectAsync = true
509-
return buildState.compile`await asyncIterators[${name}](${selector} || [], (i, x) => ${build(mapper, mapState)}(i, x, [{ item: null }, context, ...above]))`
536+
return buildState.compile`await asyncIterators[${name}](${selector} || [], async (i, x) => ${build(mapper, mapState)}(i, x, [{ item: null }, context, ...above]))`
510537
}
511538
}
512539

general.test.js

+5
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,11 @@ describe('Various Test Cases', () => {
162162
for (const engine of [...normalEngines, ...permissiveEngines]) await testEngine(engine, { map: [[0, 1, 2, 3], { '+': [{ var: '' }, { var: '../index' }] }] }, {}, [0, 2, 4, 6])
163163
})
164164

165+
it('is able to use pipe', async () => {
166+
for (const engine of [...normalEngines, ...permissiveEngines]) await testEngine(engine, { pipe: ['Austin', { cat: ['Hello, ', { var: '' }, '!'] }] }, {}, 'Hello, Austin!')
167+
for (const engine of [...normalEngines, ...permissiveEngines]) await testEngine(engine, { pipe: [{ var: 'name' }, { cat: ['Hello, ', { var: '' }, '!'] }] }, { name: 'Austin' }, 'Hello, Austin!')
168+
})
169+
165170
it('disables interpreted optimization when it realizes it will not be faster', async () => {
166171
for (const engine of [...normalEngines, ...permissiveEngines]) {
167172
const disableInterpretedOptimization = engine.disableInterpretedOptimization

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "json-logic-engine",
3-
"version": "3.0.0",
3+
"version": "3.0.1",
44
"description": "Construct complex rules with JSON & process them.",
55
"main": "./dist/cjs/index.js",
66
"module": "./dist/esm/index.js",

0 commit comments

Comments
 (0)