UNPKG

5.59 kBJavaScriptView Raw
1"use strict";
2/* eslint-disable prefer-rest-params */
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.callbackifyAll = exports.callbackify = exports.promisifyAll = exports.promisify = void 0;
5/**
6 * Wraps a callback style function to conditionally return a promise.
7 *
8 * @param {function} originalMethod - The method to promisify.
9 * @param {object=} options - Promise options.
10 * @param {boolean} options.singular - Resolve the promise with single arg instead of an array.
11 * @return {function} wrapped
12 */
13function promisify(originalMethod, options) {
14 if (originalMethod.promisified_) {
15 return originalMethod;
16 }
17 options = options || {};
18 const slice = Array.prototype.slice;
19 // tslint:disable-next-line:no-any
20 const wrapper = function () {
21 let last;
22 for (last = arguments.length - 1; last >= 0; last--) {
23 const arg = arguments[last];
24 if (typeof arg === 'undefined') {
25 continue; // skip trailing undefined.
26 }
27 if (typeof arg !== 'function') {
28 break; // non-callback last argument found.
29 }
30 return originalMethod.apply(this, arguments);
31 }
32 // peel trailing undefined.
33 const args = slice.call(arguments, 0, last + 1);
34 // tslint:disable-next-line:variable-name
35 let PromiseCtor = Promise;
36 // Because dedupe will likely create a single install of
37 // @google-cloud/common to be shared amongst all modules, we need to
38 // localize it at the Service level.
39 if (this && this.Promise) {
40 PromiseCtor = this.Promise;
41 }
42 return new PromiseCtor((resolve, reject) => {
43 // tslint:disable-next-line:no-any
44 args.push((...args) => {
45 const callbackArgs = slice.call(args);
46 const err = callbackArgs.shift();
47 if (err) {
48 return reject(err);
49 }
50 if (options.singular && callbackArgs.length === 1) {
51 resolve(callbackArgs[0]);
52 }
53 else {
54 resolve(callbackArgs);
55 }
56 });
57 originalMethod.apply(this, args);
58 });
59 };
60 wrapper.promisified_ = true;
61 return wrapper;
62}
63exports.promisify = promisify;
64/**
65 * Promisifies certain Class methods. This will not promisify private or
66 * streaming methods.
67 *
68 * @param {module:common/service} Class - Service class.
69 * @param {object=} options - Configuration object.
70 */
71// tslint:disable-next-line:variable-name
72function promisifyAll(Class, options) {
73 const exclude = (options && options.exclude) || [];
74 const ownPropertyNames = Object.getOwnPropertyNames(Class.prototype);
75 const methods = ownPropertyNames.filter(methodName => {
76 // clang-format off
77 return (!exclude.includes(methodName) &&
78 typeof Class.prototype[methodName] === 'function' && // is it a function?
79 !/(^_|(Stream|_)|promise$)|^constructor$/.test(methodName) // is it promisable?
80 );
81 // clang-format on
82 });
83 methods.forEach(methodName => {
84 const originalMethod = Class.prototype[methodName];
85 if (!originalMethod.promisified_) {
86 Class.prototype[methodName] = exports.promisify(originalMethod, options);
87 }
88 });
89}
90exports.promisifyAll = promisifyAll;
91/**
92 * Wraps a promisy type function to conditionally call a callback function.
93 *
94 * @param {function} originalMethod - The method to callbackify.
95 * @param {object=} options - Callback options.
96 * @param {boolean} options.singular - Pass to the callback a single arg instead of an array.
97 * @return {function} wrapped
98 */
99function callbackify(originalMethod) {
100 if (originalMethod.callbackified_) {
101 return originalMethod;
102 }
103 // tslint:disable-next-line:no-any
104 const wrapper = function () {
105 if (typeof arguments[arguments.length - 1] !== 'function') {
106 return originalMethod.apply(this, arguments);
107 }
108 const cb = Array.prototype.pop.call(arguments);
109 originalMethod.apply(this, arguments).then(
110 // tslint:disable-next-line:no-any
111 (res) => {
112 res = Array.isArray(res) ? res : [res];
113 cb(null, ...res);
114 }, (err) => cb(err));
115 };
116 wrapper.callbackified_ = true;
117 return wrapper;
118}
119exports.callbackify = callbackify;
120/**
121 * Callbackifies certain Class methods. This will not callbackify private or
122 * streaming methods.
123 *
124 * @param {module:common/service} Class - Service class.
125 * @param {object=} options - Configuration object.
126 */
127function callbackifyAll(
128// tslint:disable-next-line:variable-name
129Class, options) {
130 const exclude = (options && options.exclude) || [];
131 const ownPropertyNames = Object.getOwnPropertyNames(Class.prototype);
132 const methods = ownPropertyNames.filter(methodName => {
133 // clang-format off
134 return (!exclude.includes(methodName) &&
135 typeof Class.prototype[methodName] === 'function' && // is it a function?
136 !/^_|(Stream|_)|^constructor$/.test(methodName) // is it callbackifyable?
137 );
138 // clang-format on
139 });
140 methods.forEach(methodName => {
141 const originalMethod = Class.prototype[methodName];
142 if (!originalMethod.callbackified_) {
143 Class.prototype[methodName] = exports.callbackify(originalMethod);
144 }
145 });
146}
147exports.callbackifyAll = callbackifyAll;
148//# sourceMappingURL=index.js.map
\No newline at end of file