In the last example you may have noticed that the hasStoreKeys property, which is defined as a BIT in the database, is serialized as a Buffer. Usually, however, it's nice to convert BIT fields to booleans. node-data-mapper allows developers to attach converters to selected columns on the fly. (Note that there's also a way to attach converters at initialization time, which allows developers to, for example, convert all bit-type columns to booleans. This is convered in the Schema tutorials.)
node-data-mapper has some built-in converters in the converter directory. Let's take a look at the pre-defined BooleanConverter object:
'use strict'; /** A converter that converts buffers and numbers to booleans and back. */ class BooleanConverter { /** * Convert the "bit" to a boolean. * @param {number|Buffer} bit - Either an instance of a Buffer containing a 1 * or a 0, or a number. * @return {boolean} The bit's representation as a boolean. */ onRetrieve(bit) { if (bit === null || bit === undefined || bit === '') return null; if (Buffer.isBuffer(bit)) return bit[0] === 1; return bit === '1' || bit === 1; } /** * Convert a boolean to a bit. * @param {boolean} bool - A boolean value. * @return {number} The boolean's representation as a number (1 or 0), * or null if bool is null or undefined. */ onSave(bool) { if (bool === null || bool === undefined || bool === '') return null; return bool ? 1 : 0; } }A converter is an object with two functions: onRetrieve and onSave. Each function takes in a value and transforms it. The former transforms for serialization, and the latter transforms for saving (INSERT or UPDATE). In the above code, the BooleanConverter#onRetrieve method takes a Buffer or Number instance and converts it to a boolean (or null).
The following code snippet gives an example of using the BooleanConverter#onRetrieve converter on the fly. It also uses a simple in-line converter to convert firstName to uppercase.
'use strict'; const booleanConverter = require('node-data-mapper').booleanConverter; const MySQLDriver = require('node-data-mapper-mysql').MySQLDriver; const driver = new MySQLDriver(require('../bikeShopConOpts.json')); driver .initialize() .then(runQuery) .then(printResult) .catch(console.error) .finally(() => driver.end()); function runQuery(dataContext) { const query = dataContext .from('staff s') .select( 's.staffID', // Convert "hasStoreKeys" to boolean. {column: 's.hasStoreKeys', convert: booleanConverter.onRetrieve}, // Convert "firstName" to upper case. {column: 's.firstName', convert: fName => fName.toUpperCase()} ); console.log('Query:'); console.log(query.toString(), '\n'); return query .execute(); } function printResult(result) { console.log('Result:'); console.log(result); }
And here is the result ($ node example/retrieve/adHocConverter.js):
Query: SELECT `s`.`staffID` AS `s.staffID`, `s`.`hasStoreKeys` AS `s.hasStoreKeys`, `s`.`firstName` AS `s.firstName` FROM `staff` AS `s` Result: { staff: [ { staffID: 1, hasStoreKeys: false, firstName: 'RANDY' }, { staffID: 2, hasStoreKeys: true, firstName: 'JOHN' }, { staffID: 3, hasStoreKeys: false, firstName: 'TINA' }, { staffID: 4, hasStoreKeys: true, firstName: 'ABE' }, { staffID: 5, hasStoreKeys: true, firstName: 'SAL' }, { staffID: 6, hasStoreKeys: true, firstName: 'VALERIE' }, { staffID: 7, hasStoreKeys: false, firstName: 'KIMBERLY' }, { staffID: 8, hasStoreKeys: false, firstName: 'MICHAEL' } ] }