forked from slackapi/node-slack-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.ts
149 lines (133 loc) · 5.42 KB
/
util.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import * as util from 'util';
import * as os from 'os';
import { Agent } from 'http';
import objectEntries = require('object.entries'); // tslint:disable-line:no-require-imports
const pkg = require('../package.json'); // tslint:disable-line:no-require-imports no-var-requires
/**
* For when you need a function that does nothing
*/
export function noop(): void { } // tslint:disable-line:no-empty
/**
* Replaces occurences of '/' with ':' in a string, since '/' is meaningful inside User-Agent strings as a separator.
* @param s
*/
function replaceSlashes(s: string): string {
return s.replace('/', ':');
}
const baseUserAgent = `${replaceSlashes(pkg.name)}/${pkg.version} ` +
`node/${process.version.replace('v', '')} ` +
`${os.platform()}/${os.release()}`;
const appMetadata: { [key: string]: string } = {};
/**
* Appends the app metadata into the User-Agent value
* @param appMetadata
* @param appMetadata.name name of tool to be counted in instrumentation
* @param appMetadata.version version of tool to be counted in instrumentation
*/
export function addAppMetadata({ name, version }: { name: string, version: string }): void {
appMetadata[replaceSlashes(name)] = version;
}
/**
* Returns the current User-Agent value for instrumentation
*/
export function getUserAgent(): string {
const appIdentifier = objectEntries(appMetadata).map(([name, version]) => `${name}/${version}`).join(' ');
// only prepend the appIdentifier when its not empty
return ((appIdentifier.length > 0) ? `${appIdentifier} ` : '') + baseUserAgent;
}
/**
* The following is a polyfill of Node >= 8.2.0's util.callbackify method. The source is copied (with some
* modification) from:
* https://github.com/nodejs/node/blob/bff5d5b8f0c462880ef63a396d8912d5188bbd31/lib/util.js#L1095-L1140
* The modified parts are denoted using comments starting with `original` and ending with `modified`
* This could really be made an independent module. It was suggested here: https://github.com/js-n/callbackify/issues/5
*/
// tslint:disable-next-line:typedef
export const callbackify = util.callbackify !== undefined ? util.callbackify : (function () {
// Need polyfill of Object.getOwnPropertyDescriptors
// tslint:disable
require('object.getownpropertydescriptors').shim();
// This function is a shallow stub of what the real function does, but we cannot import from `internal/errors`
// @ts-ignore
function makeNodeError(type, code) {
const e = new type();
e.code = code;
return e;
}
// @ts-ignore
function callbackifyOnRejected(reason, cb) {
// `!reason` guard inspired by bluebird (Ref: https://goo.gl/t5IS6M).
// Because `null` is a special error value in callbacks which means "no error
// occurred", we error-wrap so the callback consumer can distinguish between
// "the promise rejected with null" or "the promise fulfilled with undefined".
if (!reason) {
// original
// const newReason = new errors.Error('FALSY_VALUE_REJECTION');
// modified
const newReason = makeNodeError(Error, 'FALSY_VALUE_REJECTION');
newReason.reason = reason;
reason = newReason;
Error.captureStackTrace(reason, callbackifyOnRejected);
}
return cb(reason);
}
// @ts-ignore
function callbackify(original) {
if (typeof original !== 'function') {
// original
// throw new TypeError(
// 'ERR_INVALID_ARG_TYPE',
// 'original',
// 'function');
// modified
throw makeNodeError(TypeError, 'ERR_INVALID_ARG_TYPE');
}
// We DO NOT return the promise as it gives the user a false sense that
// the promise is actually somehow related to the callback's execution
// and that the callback throwing will reject the promise.
// @ts-ignore
function callbackified(...args) {
const maybeCb = args.pop();
if (typeof maybeCb !== 'function') {
// original
// throw new errors.TypeError(
// 'ERR_INVALID_ARG_TYPE',
// 'last argument',
// 'function');
// modified
throw makeNodeError(TypeError, 'ERR_INVALID_ARG_TYPE');
}
// @ts-ignore
const cb = (...args) => { Reflect.apply(maybeCb, this, args); };
// In true node style we process the callback on `nextTick` with all the
// implications (stack, `uncaughtException`, `async_hooks`)
// @ts-ignore
Reflect.apply(original, this, args)
// @ts-ignore
.then((ret) => process.nextTick(cb, null, ret),
// @ts-ignore
(rej) => process.nextTick(callbackifyOnRejected, rej, cb));
}
Object.setPrototypeOf(callbackified, Object.getPrototypeOf(original));
Object.defineProperties(callbackified,
// @ts-ignore (installed with polyfill)
Object.getOwnPropertyDescriptors(original));
return callbackified;
}
// tslint:enable
return callbackify;
}() as typeof util.callbackify);
export type AgentOption = Agent | {
http?: Agent,
https?: Agent,
} | boolean;
// This interface is a subset of the options in SecureContextOptions from the node lib
// tslint:disable:prefer-array-literal
export interface TLSOptions {
pfx?: string | Buffer | Array<string | Buffer | Object>;
key?: string | Buffer | Array<Buffer | Object>;
passphrase?: string;
cert?: string | Buffer | Array<string | Buffer>;
ca?: string | Buffer | Array<string | Buffer>;
}
// tslint:enable:prefer-array-literal