// Require the core node modules. var chalk = require( "chalk" ); // Try calling the "database method" with various combinations of inputs. The key here // is to notice that falsey values, such as "0", neither include the associated // conditional SQL statements; and that the falsey value itself doesn't get included // in the result (since the "embed" tag will ignore values that aren't strings). header( "getUsers()", "Excluding all conditional statements." ); format( getUsers() ); header( "getUsers( 0 )", "Excluding all conditionals, but using a non-empty falsey." ); format( getUsers( 0 ) ); header( "getUsers( 4 )", "Including the user constraint." ); format( getUsers( 4 ) ); header( "getUsers( 4, 16, false )", "Including the user and team constraint, but not an active constraint." ); format( getUsers( 4, 16, false ) ); header( "getUsers( 4, 16, true )", "Including all conditional, nested statements." ); format( getUsers( 4, 16, true ) ); // ----------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------- // // I get the given users, filtered by the optional userID and teamID. // -- // NOTE: Obviously, this function doesn't actually perform any query - for the demo, // it is just constructing the SQL statement that would be used. function getUsers( userID, teamID, ensureActiveMembership ) { var statement = embed` SELECT u.id, u.name, u.email FROM user u ${ userID && teamID && embed` INNER JOIN team_membership tm ON ( tm.userID = :userID AND tm.teamID = :teamID ${ ensureActiveMembership && embed` AND tm.endedAt IS NULL `} ) `} ${ userID && ! teamID && embed` WHERE userID = :userID `} ; `; return( statement ); } // ----------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------- // // I construct the SQL statement by zipping the given template strings and values // together. Only string values with non-space characters will be included in the // result (so that falseys don't get included). // -- // CAUTION: This function is intended to be used with a TAGGED TEMPLATE literal. function embed() { var strings = arguments[ 0 ]; var values = Array.prototype.slice.call( arguments, 1 ); var results = []; for ( var i = 0 ; i < strings.length ; i++ ) { // Make sure the string part isn't just spaces and tabs. if ( isEmbeddable( strings[ i ] ) ) { results.push( strings[ i ] ); } // Make sure the value is a String and more than just spaces and tabs. // -- // NOTE: There may not be a value at this index; but, if we go beyond the bounds // of the value collection, the result will just be "undefined", which will be // omitted anyway by the isEmbeddable() check. if ( isEmbeddable( values[ i ] ) ) { results.push( values[ i ] ); } } return( results.join( "" ) ); } // I determine if the given value is a String that contains at least one non-space // character (that is worth embedding). function isEmbeddable( input ) { var isString = ( String( input ) === input ); var hasContent = /\S/.test( input ); return( isString && hasContent ); } // ----------------------------------------------------------------------------------- // // ----------------------------------------------------------------------------------- // // I output the logging header. function header( label, note ) { console.log( chalk.cyan.bold( label ) ); console.log( chalk.cyan.bold( "-".repeat( label.length ) ) ); console.log( chalk.dim( "Note:", note ) ); } // I output the logging body. function format( content ) { var formattedContent = content .replace( /^\t\t/gm, " " ) .replace( /\t/g, " " ) .replace( /(^[ \t]+)[\r\n]\s+/gm, "$1" ) ; console.log( formattedContent ); }