lucene-filter.js

Data filter for lucene queries
git clone git://git.finwo.net/lib/lucene-filter.js
Log | Files | Refs | README | LICENSE

commit 0a63b58834b32a1efc8006ddb96e16c0020d08e6
parent 7b85c8b74903b803136fc8d488e4faea546ecd74
Author: finwo <finwo@pm.me>
Date:   Tue, 11 Jun 2019 13:00:42 +0200

<implicit> operator now supported; main returns factory instead now

Diffstat:
Dsrc/has-module.js | 15---------------
Dsrc/has-module.test.js | 41-----------------------------------------
Msrc/index.js | 93++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/operators/index.js | 11++++++-----
4 files changed, 56 insertions(+), 104 deletions(-)

diff --git a/src/has-module.js b/src/has-module.js @@ -1,15 +0,0 @@ -module.exports = function hasModule( name ) { - if ( require.resolve ) { - try { - return !!require.resolve(name); - } catch(e) { - return false; - } - } - try { - require(name); - return true; - } catch(e) { - return false; - } -}; diff --git a/src/has-module.test.js b/src/has-module.test.js @@ -1,41 +0,0 @@ -import expect from 'expect'; - -// Setup environment -if ( 'object' !== typeof process ) process = {}; -if (!process.env) process.env = {}; -process.env.TEST = true; - -// Load extends -expect.extend(require('jest-isa')); - -// Load our module -let hasModule = require('./has-module'); - -test('Ensure hasModule is a function', async () => { - expect(hasModule).toBeDefined(); // Basics - expect(hasModule).isA(Function); -}); - -test('Verify some packages', async () => { - expect(hasModule('./has-module')).toBe(true); - expect(hasModule('./index')).toBe(true); - expect(hasModule('jest-isa')).toBe(true); - expect(hasModule('non-existent-module')).toBe(false); - expect(hasModule('pizza-courier')).toBe(false); -}); - -// TODO: fix this one -// test('Verify some packages without require.resolve', async () => { -// -// // Reload module -// process.env.NO_RESOLVE = true; -// console.log(process.env); -// delete require.cache[require.resolve('./has-module')]; -// hasModule = require('./has-module'); -// -// expect(hasModule('./has-module')).toBe(true); -// expect(hasModule('./index')).toBe(true); -// expect(hasModule('jest-isa')).toBe(true); -// expect(hasModule('non-existent-module')).toBe(false); -// expect(hasModule('pizza-courier')).toBe(false); -// }); diff --git a/src/index.js b/src/index.js @@ -1,59 +1,66 @@ -const hasModule = require('./has-module'), - parser = (function() { - if (hasModule('lucene')) return require('lucene'); - if (hasModule('lucene-queryparser')) return require('lucene-queryparser'); - if (hasModule('lucene-query-parser')) return require('lucene-query-parser'); - throw new Error("None of 'lucene', 'lucene-queryparser' or 'lucene-query-parser' are installed"); - })(); +// Factory +const lucene = module.exports = function factory( parser ) { -const lucene = module.exports = function compiler(query) { + // Parser must be given + if (!parser) { + throw new Error('No parser given. Must be one of \'lucene\',\'lucene-queryparser\',\'lucene-query-parser\''); + } + + // The given parser must be compatible + if (('object' !== typeof parser) || ('function' !== typeof parser.parse)) { + throw new Error('Incompatible parser given. Must be one of \'lucene\',\'lucene-queryparser\',\'lucene-query-parser\''); + } + + // Returns Function(Object):Number + function compile(query) { + if ('string' !== typeof query) return ()=>0; + if (!query) return ()=>0; - // Parse string query - if (!query) return () => 0; - if ('string' === typeof query) { + // Actually compile what was given try { query = parser.parse(query); - } catch (e) { - return () => 0; + } catch(e) { + return ()=>0; } - } - // Compile combined - if (query.operator) { - return lucene.operators[query.operator]( - lucene(query.left), - lucene(query.right), - ); - } + // Compile multi-query + if (query.operator) { + return lucene.operators[query.operator]( + compile(query.left), + compile(query.right), + ); + } - // Wrapped - if (query.left) { - return lucene(query.left); - } + // Wrapped + if (query.left) { + return compile(query.left); + } - // Ensure default boost - query.boost = query.boost || 1; + // Ensure default boost + query.boost = query.boost || 1; - // Return the first detected filter - for (const filter of lucene.filters) { - if (filter.detect(query)) { - return filter.compile(query); + // Return the first detected filter + for (const filter of lucene.filters) { + if (filter.detect(query)) { + return filter.compile(query); + } } - } - // Return no match - return () => 0; -}; + // Return no match + return ()=>0; + } -// Return the data when matching -// TODO: lucene() = { f() passthrough: f() } -lucene.passthrough = function(query) { - let match = lucene(query); - return function(data) { - if(match(data)) return data; - return undefined; + // Return the data when matching + compile.passthrough = function(parser, query) { + let match = compile(query); + return function(data) { + if(match(data)) return data; + return undefined; + }; }; -}; + + return compile; +} // Add filters & operators lucene.filters = require('./filters'); diff --git a/src/operators/index.js b/src/operators/index.js @@ -1,5 +1,6 @@ -const operators = module.exports = {}; -operators['OR'] = require('./or'); -operators['AND'] = require('./and'); -operators['OR NOT'] = require('./or-not')(operators); -operators['AND NOT'] = require('./and-not')(operators); +const operators = module.exports = {}; +operators['OR'] = require('./or'); +operators['AND'] = require('./and'); +operators['OR NOT'] = require('./or-not')(operators); +operators['AND NOT'] = require('./and-not')(operators); +operators['<implicit>'] = require('./and')(operators);