import { defaults } from "./utils/lodash" ; import Command from "./command" ; import Script from "./script" ; import * as PromiseContainer from "./promiseContainer" ; import asCallback from "standard-as-callback" ; import { executeWithAutoPipelining , shouldUseAutoPipelining , } from "./autoPipelining" ; export interface ICommanderOptions { showFriendlyErrorStack ? : boolean ; } const DROP_BUFFER_SUPPORT_ERROR = "*Buffer methods are not available " + 'because "dropBufferSupport" option is enabled.' + "Refer to https://github.com/luin/ioredis/wiki/Improve-Performance for more details." ; param { boolean } options . showFriendlyErrorStack constructor export default function Commander ( ) { this . options = defaults ( { } , this . options || { } , { showFriendlyErrorStack : false , } ) ; this . scriptsSet = { } ; this . addedBuiltinSet = new Set ( ) ; } const commands = require ( "redis-commands" ) . list . filter ( function ( command ) { return command !== "monitor" ; } ) ; commands . push ( "sentinel" ) ; return { string [ ] } public Commander . prototype . getBuiltinCommands = function ( ) { return commands . slice ( 0 ) ; } ; param { string } commandName return { object } public Commander . prototype . createBuiltinCommand = function ( commandName ) { return { string : generateFunction ( null , commandName , "utf8" ) , buffer : generateFunction ( null , commandName , null ) , } ; } ; param { string } commandName return { object } public Commander . prototype . addBuiltinCommand = function ( commandName ) { this . addedBuiltinSet . add ( commandName ) ; this [ commandName ] = generateFunction ( commandName , commandName , "utf8" ) ; this [ commandName + "Buffer" ] = generateFunction ( commandName + "Buffer" , commandName , null ) ; } ; commands . forEach ( function ( commandName ) { Commander . prototype [ commandName ] = generateFunction ( commandName , commandName , "utf8" ) ; Commander . prototype [ commandName + "Buffer" ] = generateFunction ( commandName + "Buffer" , commandName , null ) ; } ) ; Commander . prototype . call = generateFunction ( "call" , "utf8" ) ; Commander . prototype . callBuffer = generateFunction ( "callBuffer" , null ) ; Commander . prototype . send_command = Commander . prototype . call ; param { string } name param definition param { string } definition . lua param { number } definition . numberOfKeys param { boolean } definition . readOnly Commander . prototype . defineCommand = function ( name , definition ) { const script = new Script ( definition . lua , definition . numberOfKeys , this . options . keyPrefix , definition . readOnly ) ; this . scriptsSet [ name ] = script ; this [ name ] = generateScriptingFunction ( name , name , script , "utf8" ) ; this [ name + "Buffer" ] = generateScriptingFunction ( name + "Buffer" , name , script , null ) ; } ; abstract public Commander . prototype . sendCommand = function ( ) { } ; function generateFunction ( functionName , _encoding ) ; function generateFunction ( functionName , _commandName , _encoding ) ; function generateFunction ( functionName , _commandName ? , _encoding ? ) { if ( typeof _encoding === "undefined" ) { _encoding = _commandName ; _commandName = null ; } return function ( ... args ) { const commandName = _commandName || args . shift ( ) ; let callback = args [ args . length - 1 ] ; if ( typeof callback === "function" ) { args . pop ( ) ; } else { callback = undefined ; } const options = { errorStack : this . options . showFriendlyErrorStack ? new Error ( ) : undefined , keyPrefix : this . options . keyPrefix , replyEncoding : _encoding , } ; if ( this . options . dropBufferSupport && ! _encoding ) { return asCallback ( PromiseContainer . get ( ) . reject ( new Error ( DROP_BUFFER_SUPPORT_ERROR ) ) , callback ) ; } if ( ! shouldUseAutoPipelining ( this , functionName , commandName ) ) { return this . sendCommand ( new Command ( commandName , args , options , callback ) ) ; } return executeWithAutoPipelining ( this , functionName , commandName , args , callback ) ; } ; } function generateScriptingFunction ( functionName , commandName , script , encoding ) { return function ( ) { let length = arguments . length ; const lastArgIndex = length - 1 ; let callback = arguments [ lastArgIndex ] ; if ( typeof callback !== "function" ) { callback = undefined ; } else { length = lastArgIndex ; } const args = new Array ( length ) ; for ( let i = 0 ; i < length ; i ++ ) { args [ i ] = arguments [ i ] ; } let options ; if ( this . options . dropBufferSupport ) { if ( ! encoding ) { return asCallback ( PromiseContainer . get ( ) . reject ( new Error ( DROP_BUFFER_SUPPORT_ERROR ) ) , callback ) ; } options = { replyEncoding : null } ; } else { options = { replyEncoding : encoding } ; } if ( this . options . showFriendlyErrorStack ) { options . errorStack = new Error ( ) ; } if ( ! shouldUseAutoPipelining ( this , functionName , commandName ) ) { return script . execute ( this , args , options , callback ) ; } return executeWithAutoPipelining ( this , functionName , commandName , args , callback ) ; } ; }