docs: function (args, onDone, extra) {
  		// if args are not provided then we shift the parameters
  		if (typeof args === 'function') {
  			extra = onDone;
  			onDone = args;
  			args = {};
  		}
  
  		// TODO: perform argument type check (currently there's none, so internal API calls won't do type checks)
  		// TODO: move checker to here
  
  		var onError = function(err) {
  			LOG.error('onError '+ err, l_name);
  			UTIL.safeCall(onDone, err);
  		}
  
  		function onExec() {
  			// make actual call to user-defined function
  			// NOTE: we also return values for direct function calls
  			return UTIL.safeCall(l_list[name], args, function (err, result, unsupported_return) {
  				if (err) {
  					LOG.error('[' + name + '] error:', l_name);
  					LOG.error(err, l_name);
  				}
  
  				if (unsupported_return) {
  					var errmsg = 'onDone() in SR.API does not support more than one return variable, please return everything inside a result object';
  					LOG.error(errmsg, l_name);
  					LOG.stack();
  					return UTIL.safeCall(onDone, errmsg);
  				}
  
  				// perform post-event actions, if any
  				if (l_afterActions.hasOwnProperty(name) === false) {
  					return UTIL.safeCall(onDone, err, result);
  				}
  
  				var posts = l_afterActions[name];
  				var promise = undefined;
  				for (var i=0; i < posts.length; i++) {
  					if (!promise) {
  						promise = post_action(args, { err: err, result: result }, posts[i], extra);
  					} else {
  						promise = promise.then(post_action(args, { err: err, result: result }, posts[i], extra));
  					}
  				}
  
  				// last action
  				promise.then(new SR.promise(function (resolve, reject) {
  					//LOG.warn('everything is done... call original onDone...', l_name);
  					UTIL.safeCall(onDone, err, result);
  					resolve();
  				}));
  
  			}, extra);
  		}
  
  		// perform pre-event actions, if any
  		if (l_beforeActions.hasOwnProperty(name) === false) {
  			return onExec();
  		}
  
  		const pres = l_beforeActions[name].map((callback) => pre_action(args, callback, extra));
  		pres.reduce((p, callback) => p.then(() => callback), Promise.resolve())
  			.then(onExec)
  			.catch((err) => {
  				LOG.error(err);
  				onDone(err);
  			});
  	}