Proxy API

@inner
@param {Object} ctx the extra context information for the hook
@param {Function} rawApi the original API to call
@param {Object} apiOpts the API hook options
@param  {...any} args the arguments to call the API
@return {*}
function proxyAPI(ctx, rawApi, apiOpts, ...args) {
    let {init, done, sync} = apiOpts;

    // API init interception
    let initResult = hookAPIInit(init, args, ctx);

    if (isPromise(initResult)) {
        return initResult.then(
            () => {
                let hookInfo = hookAPIDone(done, sync, args, ctx);
                return executeAPI(hookInfo, rawApi, args);
            }
        );
    }
    else {
        let hookInfo = hookAPIDone(done, sync, args, ctx);
        return executeAPI(hookInfo, rawApi, args);
    }
}