diff --git a/src/services/search/expressions/order_by_and_limit.js b/src/services/search/expressions/order_by_and_limit.ts similarity index 65% rename from src/services/search/expressions/order_by_and_limit.js rename to src/services/search/expressions/order_by_and_limit.ts index 2de6547ed..cc7512303 100644 --- a/src/services/search/expressions/order_by_and_limit.js +++ b/src/services/search/expressions/order_by_and_limit.ts @@ -1,13 +1,33 @@ "use strict"; -const Expression = require('./expression'); -const NoteSet = require('../note_set'); +import BNote = require("../../../becca/entities/bnote"); +import NoteSet = require("../note_set"); +import SearchContext = require("../search_context"); +import Expression = require("./expression"); + +type Direction = "asc"; + +interface ValueExtractor { + extract: (note: BNote) => number | string | null; +} + +interface OrderDefinition { + direction: Direction; + smaller: number; + larger: number; + valueExtractor: ValueExtractor; +} class OrderByAndLimitExp extends Expression { - constructor(orderDefinitions, limit) { + + private orderDefinitions: OrderDefinition[]; + private limit: number; + private subExpression: Expression | null; + + constructor(orderDefinitions: Pick[], limit: number) { super(); - this.orderDefinitions = orderDefinitions; + this.orderDefinitions = orderDefinitions as unknown as OrderDefinition[]; for (const od of this.orderDefinitions) { od.smaller = od.direction === "asc" ? -1 : 1; @@ -16,11 +36,15 @@ class OrderByAndLimitExp extends Expression { this.limit = limit || 0; - /** @type {Expression} */ this.subExpression = null; // it's expected to be set after construction } - execute(inputNoteSet, executionContext, searchContext) { + execute(inputNoteSet: NoteSet, executionContext: {}, searchContext: SearchContext) { + if (!this.subExpression) { + // FIXME: who is setting the subexpression? + throw new Error("Missing subexpression"); + } + let {notes} = this.subExpression.execute(inputNoteSet, executionContext, searchContext); notes.sort((a, b) => { @@ -48,7 +72,8 @@ class OrderByAndLimitExp extends Expression { } // if both are numbers, then parse them for numerical comparison - if (this.isNumber(valA) && this.isNumber(valB)) { + if (typeof valA === "string" && this.isNumber(valA) && + typeof valB === "string" && this.isNumber(valB)) { valA = parseFloat(valA); valB = parseFloat(valB); } @@ -77,16 +102,16 @@ class OrderByAndLimitExp extends Expression { return noteSet; } - isNumber(x) { + isNumber(x: number | string) { if (typeof x === 'number') { return true; } else if (typeof x === 'string') { // isNaN will return false for blank string - return x.trim() !== "" && !isNaN(x); + return x.trim() !== "" && !isNaN(parseInt(x, 10)); } else { return false; } } } -module.exports = OrderByAndLimitExp; +export = OrderByAndLimitExp; diff --git a/src/services/search/services/parse.js b/src/services/search/services/parse.js index c60595de6..eb6c03000 100644 --- a/src/services/search/services/parse.js +++ b/src/services/search/services/parse.js @@ -13,7 +13,7 @@ const AttributeExistsExp = require('../expressions/attribute_exists'); const LabelComparisonExp = require('../expressions/label_comparison'); const NoteFlatTextExp = require('../expressions/note_flat_text'); const NoteContentFulltextExp = require('../expressions/note_content_fulltext'); -const OrderByAndLimitExp = require('../expressions/order_by_and_limit.js'); +const OrderByAndLimitExp = require('../expressions/order_by_and_limit'); const AncestorExp = require('../expressions/ancestor'); const buildComparator = require('./build_comparator.js'); const ValueExtractor = require('../value_extractor');