@sugarcoated/fondant-query
Version:
Query parser.
316 lines (279 loc) • 7.76 kB
JavaScript
/**
* Declaration of the Query class. Query makes parsing query strings manageable
* without manipulating strings manually.
*
* @fileoverview Query. Manageable query strings.
* @author Joshua Crowe, Junior Web Developer.
* @copyright Joshua Crowe, 2017.
*/
/**
* Query makes query strings manageable.
*
* @class Query
* @classdesc Query string manager.
*/
class Query extends Actionable {
/**
* @property pointer
* @description Indicator of a query string.
* @type {String}
*/
set pointer (pointerChange) {
this._queryPointer = pointerChange
return this._queryPointer
}
/**
* @property pointer
* @description Indicator of a query string.
* @type {String}
*/
get pointer () {
return this._queryPointer
}
/**
* @property seperator
* @description Seperator between KVP.
* @type {String}
*/
set seperator (seperatorChange) {
this._querySeperator = seperatorChange
return this._querySeperator
}
/**
* @property seperator
* @description Seperator between KVP.
* @type {String}
*/
get seperator () {
return this._querySeperator
}
/**
* @property items
* @description KVP.
* @type {Collection}
*/
get items () {
return this._queryItems
}
/**
* Create a new Query.
*
* @name Query#constructor
* @example new Query('&&', '?')
* @param {String} [querySeperator] Seperator of each KVP.
* @param {String} [queryPointer] Identifer for the query.
* @returns {Query}
*/
constructor (querySeperator = '&&', queryPointer = '?') {
super(['Insertion', 'Extraction', 'Parsed', 'Stringification'])
/**
* @property _queryPointer
* @description Identifier for the query.
* @type {String}
* @private
*/
this._queryPointer = queryPointer
/**
* @property _querySeperator
* @description Seperator of each KVP.
* @type {String}
* @private
*/
this._querySeperator = querySeperator
/**
* @property _queryItems
* @description KVPs.
* @type {Collection}
* @private
*/
this._queryItems = new Collection()
}
/**
* Insert a new item into the Query.
*
* @name Query#insert
* @example myQuery.insert(myKey)
* @param {Key} insertKey Key to insert.
* @param {String} insertKey.keyName Name of the Key.
* @param {String} insertKey.keyValue Value of the Key.
* @param {Date} insertKey.keyCreated Creation date of the Key.
* @returns {Key}
*/
insert ({keyName, keyValue, keyCreated}) {
/**
* @const insertItems
* @description Object reference to the items.
* @type {Collection}
*/
const insertItems = this._queryItems
insertItems.add(keyName, keyValue)
/**
* @const insertKey
* @description Key mirror.
* @type {Key}
*/
const insertKey = new Key(keyName, keyValue, keyCreated)
this.run('Insertion', insertKey)
return insertKey
}
/**
* Handle the insertion event.
*
* @name Query#insertion
* @example myQuery.insertion(() => {})
* @param {Function} insertionHandler Handler for the insertion event.
* @returns {Void}
*/
insertion (insertionHandler) {
this.on('Insertion', insertionHandler, this)
}
/**
* Extract a Key from the Query.
*
* @name Query#extract
* @example myQuery.extract('myKey')
* @param {String} extractName Name of the Key to extract.
* @returns {Key}
*/
extract (extractName) {
/**
* @const extractItems
* @description Object reference to the items of the Query.
* @type {Collection}
*/
const extractItems = this._queryItems
/**
* @const extractFound
* @description Found value inside the items Collection.
* @type {String}
*/
const extractFound = extractItems.get(extractName)
/**
* @const extractKey
* @description Key to represent that found.
* @type {Key}
*/
const extractKey = new Key(extractName, extractFound)
extractItems.delete(extractName)
this.run('Extraction', extractKey)
return extractKey
}
/**
* Handle the extraction event.
*
* @name Query#extraction
* @example myQuery.extraction(() => {})
* @param {Function} extractionHandler Handler for the extraction event.
* @returns {Void}
*/
extraction (extractionHandler) {
this.on('Extraction', extractionHandler, this)
}
/**
* Parse a query string.
*
* @name Query#parse
* @example myQuery.parse('?x=1&&y=2')
* @param {String} parseString Query string to parse.
* @returns {Collection}
*/
parse (parseString) {
/**
* @const parsePointer
* @description Pointer of the Query.
* @type {String}
*/
const parsePointer = this._queryPointer
if (parseString.startsWith(parsePointer)) {
parseString = parseString.substring(1)
}
/**
* @const parseSeperator
* @description Seperator of the Query.
* @type {String}
*/
const parseSeperator = this._querySeperator
/**
* @const parseSplit
* @description Split of the string into KVP as Strings.
* @type {Array.<String>}
*/
const parseSplit = parseString.split(parseSeperator)
/**
* @const parseMap
* @description Splitting String KVP into literal KVP.
* @type {Array.<Array.<String, String>>}
*/
const parseMap = parseSplit.map(s => s.split('='))
this._queryItems = new Collection(parseMap)
this.run('Parsed', this._queryItems)
return this._queryItems
}
/**
* Handle the parsed event.
*
* @name Query#parsed
* @example myQuery.parsed(() => {})
* @param {Function} parsedHandler Handler for the parsed event.
* @returns {Void}
*/
parsed (parsedHandler) {
this.on('Parsed', parsedHandler, this)
}
/**
* Stringify the query.
*
* @name Query#stringify
* @example myQuery.stringify()
* @param {Void}
* @returns {String}
*/
stringify () {
/**
* @const stringifyItems
* @description Object reference to the items Collection.
* @type {Collection}
*/
const stringifyItems = this._queryItems
/**
* @const stringifySeperator
* @description Seperator of the Query.
* @type {String}
*/
const stringifySeperator = this._querySeperator
/**
* @const stringifyPointer
* @description Pointer of the Query.
* @type {String}
*/
const stringifyPointer = this._queryPointer
/**
* @const stringifyReduction
* @description Concatenation of full query string.
* @type {String}
*/
const stringifyReduction = stringifyItems.items.reduce(stringifyItem => {
return `${stringifyItem[0]}=${stringifyItem[1]}${stringifySeperator}`
})
/**
* @const stringifyConcatenation
* @description Concatenation with the Pointer.
* @type {String}
*/
const stringifyConcatenation = `${stringifyPointer}${stringifyReduction}`
this.run('Stringified', stringifyConcatenation)
return stringifyConcatenation
}
/**
* Handle the stringified event.
*
* @name Query#stringified
* @example myQuery.stringified(() => {})
* @param {Function} stringifiedHandler Handler for the stringified event.
* @returns {Void}
*/
stringified (stringifiedHandler) {
this.on('Stringified', stringifiedHandler, this)
}
}
module.exports = Query;