@jsforce/jsforce-node 0.0.1 → 3.0.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +54 -0
  3. package/index.d.ts +4 -0
  4. package/index.js +1 -0
  5. package/lib/VERSION.d.ts +2 -0
  6. package/lib/VERSION.js +3 -0
  7. package/lib/api/analytics/types.d.ts +509 -0
  8. package/lib/api/analytics/types.js +2 -0
  9. package/lib/api/analytics.d.ts +163 -0
  10. package/lib/api/analytics.js +342 -0
  11. package/lib/api/apex.d.ts +44 -0
  12. package/lib/api/apex.js +86 -0
  13. package/lib/api/bulk.d.ts +253 -0
  14. package/lib/api/bulk.js +678 -0
  15. package/lib/api/bulk2.d.ts +324 -0
  16. package/lib/api/bulk2.js +800 -0
  17. package/lib/api/chatter.d.ts +133 -0
  18. package/lib/api/chatter.js +248 -0
  19. package/lib/api/metadata/schema.d.ts +16117 -0
  20. package/lib/api/metadata/schema.js +9094 -0
  21. package/lib/api/metadata.d.ts +189 -0
  22. package/lib/api/metadata.js +406 -0
  23. package/lib/api/soap/schema.d.ts +3167 -0
  24. package/lib/api/soap/schema.js +1787 -0
  25. package/lib/api/soap.d.ts +76 -0
  26. package/lib/api/soap.js +155 -0
  27. package/lib/api/streaming/extension.d.ts +94 -0
  28. package/lib/api/streaming/extension.js +151 -0
  29. package/lib/api/streaming.d.ts +160 -0
  30. package/lib/api/streaming.js +252 -0
  31. package/lib/api/tooling.d.ts +284 -0
  32. package/lib/api/tooling.js +202 -0
  33. package/lib/api/wsdl/wsdl2schema.d.ts +1 -0
  34. package/lib/api/wsdl/wsdl2schema.js +354 -0
  35. package/lib/browser/canvas.d.ts +12 -0
  36. package/lib/browser/canvas.js +77 -0
  37. package/lib/browser/client.d.ts +82 -0
  38. package/lib/browser/client.js +244 -0
  39. package/lib/browser/jsonp.d.ts +12 -0
  40. package/lib/browser/jsonp.js +69 -0
  41. package/lib/browser/registry.d.ts +3 -0
  42. package/lib/browser/registry.js +5 -0
  43. package/lib/browser/request.d.ts +10 -0
  44. package/lib/browser/request.js +202 -0
  45. package/lib/cache.d.ts +74 -0
  46. package/lib/cache.js +159 -0
  47. package/lib/connection.d.ts +356 -0
  48. package/lib/connection.js +1153 -0
  49. package/lib/core.d.ts +17 -0
  50. package/lib/core.js +55 -0
  51. package/lib/csv.d.ts +23 -0
  52. package/lib/csv.js +35 -0
  53. package/lib/date.d.ts +82 -0
  54. package/lib/date.js +201 -0
  55. package/lib/http-api.d.ts +75 -0
  56. package/lib/http-api.js +295 -0
  57. package/lib/index.d.ts +13 -0
  58. package/lib/index.js +32 -0
  59. package/lib/jsforce.d.ts +26 -0
  60. package/lib/jsforce.js +67 -0
  61. package/lib/jwtOAuth2.d.ts +8 -0
  62. package/lib/jwtOAuth2.js +23 -0
  63. package/lib/oauth2.d.ts +92 -0
  64. package/lib/oauth2.js +245 -0
  65. package/lib/process.d.ts +157 -0
  66. package/lib/process.js +143 -0
  67. package/lib/query.d.ts +341 -0
  68. package/lib/query.js +817 -0
  69. package/lib/quick-action.d.ts +44 -0
  70. package/lib/quick-action.js +46 -0
  71. package/lib/record-reference.d.ts +46 -0
  72. package/lib/record-reference.js +65 -0
  73. package/lib/record-stream.d.ts +83 -0
  74. package/lib/record-stream.js +233 -0
  75. package/lib/registry/base.d.ts +43 -0
  76. package/lib/registry/base.js +96 -0
  77. package/lib/registry/empty.d.ts +7 -0
  78. package/lib/registry/empty.js +13 -0
  79. package/lib/registry/file.d.ts +11 -0
  80. package/lib/registry/file.js +51 -0
  81. package/lib/registry/index.d.ts +8 -0
  82. package/lib/registry/index.js +21 -0
  83. package/lib/registry/sfdx.d.ts +56 -0
  84. package/lib/registry/sfdx.js +133 -0
  85. package/lib/registry/types.d.ts +47 -0
  86. package/lib/registry/types.js +2 -0
  87. package/lib/request-helper.d.ts +23 -0
  88. package/lib/request-helper.js +102 -0
  89. package/lib/request.d.ts +11 -0
  90. package/lib/request.js +75 -0
  91. package/lib/session-refresh-delegate.d.ts +31 -0
  92. package/lib/session-refresh-delegate.js +69 -0
  93. package/lib/soap.d.ts +60 -0
  94. package/lib/soap.js +257 -0
  95. package/lib/sobject.d.ts +258 -0
  96. package/lib/sobject.js +376 -0
  97. package/lib/soql-builder.d.ts +25 -0
  98. package/lib/soql-builder.js +226 -0
  99. package/lib/transport.d.ts +63 -0
  100. package/lib/transport.js +175 -0
  101. package/lib/types/common.d.ts +560 -0
  102. package/lib/types/common.js +2 -0
  103. package/lib/types/index.d.ts +7 -0
  104. package/lib/types/index.js +23 -0
  105. package/lib/types/projection.d.ts +26 -0
  106. package/lib/types/projection.js +2 -0
  107. package/lib/types/record.d.ts +44 -0
  108. package/lib/types/record.js +2 -0
  109. package/lib/types/schema.d.ts +50 -0
  110. package/lib/types/schema.js +2 -0
  111. package/lib/types/soap.d.ts +43 -0
  112. package/lib/types/soap.js +2 -0
  113. package/lib/types/standard-schema.d.ts +16199 -0
  114. package/lib/types/standard-schema.js +2 -0
  115. package/lib/types/util.d.ts +7 -0
  116. package/lib/types/util.js +2 -0
  117. package/lib/util/formatter.d.ts +8 -0
  118. package/lib/util/formatter.js +24 -0
  119. package/lib/util/function.d.ts +32 -0
  120. package/lib/util/function.js +52 -0
  121. package/lib/util/get-body-size.d.ts +4 -0
  122. package/lib/util/get-body-size.js +39 -0
  123. package/lib/util/logger.d.ts +29 -0
  124. package/lib/util/logger.js +102 -0
  125. package/lib/util/promise.d.ts +19 -0
  126. package/lib/util/promise.js +25 -0
  127. package/lib/util/stream.d.ts +12 -0
  128. package/lib/util/stream.js +88 -0
  129. package/package.json +262 -6
  130. package/typings/faye/index.d.ts +16 -0
  131. package/typings/index.d.ts +1 -0
@@ -0,0 +1,82 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * @file Browser client connection management class
4
+ * @author Shinichi Tomita <shinichi.tomita@gmail.com>
5
+ */
6
+ import { EventEmitter } from 'events';
7
+ import Connection, { ConnectionConfig } from '../connection';
8
+ import { TokenResponse } from '../oauth2';
9
+ /**
10
+ *
11
+ */
12
+ export type LoginOptions = {
13
+ scope?: string;
14
+ size?: {
15
+ width: number;
16
+ height: number;
17
+ };
18
+ };
19
+ /**
20
+ *
21
+ */
22
+ export declare class BrowserClient extends EventEmitter {
23
+ _prefix: string;
24
+ _config: ConnectionConfig | undefined;
25
+ _connection: Connection | undefined;
26
+ /**
27
+ *
28
+ */
29
+ constructor(prefix?: string);
30
+ get connection(): Connection;
31
+ /**
32
+ *
33
+ */
34
+ init(config: ConnectionConfig): void;
35
+ /**
36
+ *
37
+ */
38
+ login(options?: LoginOptions): Promise<{
39
+ status: string;
40
+ }>;
41
+ /**
42
+ *
43
+ */
44
+ isLoggedIn(): boolean;
45
+ /**
46
+ *
47
+ */
48
+ logout(): void;
49
+ /**
50
+ * @private
51
+ */
52
+ _getTokens(): {
53
+ accessToken: string | null;
54
+ instanceUrl: string | null;
55
+ userInfo: {
56
+ id: string;
57
+ organizationId: string;
58
+ url: string;
59
+ } | undefined;
60
+ } | null;
61
+ /**
62
+ * @private
63
+ */
64
+ _storeTokens(params: TokenResponse): void;
65
+ /**
66
+ * @private
67
+ */
68
+ _removeTokens(): void;
69
+ /**
70
+ * @private
71
+ */
72
+ _getError(): any;
73
+ /**
74
+ * @private
75
+ */
76
+ _storeError(err: any): void;
77
+ }
78
+ /**
79
+ *
80
+ */
81
+ declare const client: BrowserClient;
82
+ export default client;
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BrowserClient = void 0;
7
+ /**
8
+ * @file Browser client connection management class
9
+ * @author Shinichi Tomita <shinichi.tomita@gmail.com>
10
+ */
11
+ const events_1 = require("events");
12
+ const connection_1 = __importDefault(require("../connection"));
13
+ const oauth2_1 = __importDefault(require("../oauth2"));
14
+ /**
15
+ * @private
16
+ */
17
+ function popupWin(url, w, h) {
18
+ const left = screen.width / 2 - w / 2;
19
+ const top = screen.height / 2 - h / 2;
20
+ return window.open(url, undefined, `location=yes,toolbar=no,status=no,menubar=no,width=${w},height=${h},top=${top},left=${left}`);
21
+ }
22
+ /**
23
+ * @private
24
+ */
25
+ function handleCallbackResponse() {
26
+ const res = checkCallbackResponse();
27
+ const state = localStorage.getItem('jsforce_state');
28
+ if (res && state && res.body.get('state') === state) {
29
+ localStorage.removeItem('jsforce_state');
30
+ const [prefix, promptType] = state.split('.');
31
+ const cli = new BrowserClient(prefix);
32
+ if (res.success) {
33
+ cli._storeTokens(Object.fromEntries(res.body));
34
+ location.hash = '';
35
+ }
36
+ else {
37
+ cli._storeError(res.body);
38
+ }
39
+ if (promptType === 'popup') {
40
+ window.close();
41
+ }
42
+ return true;
43
+ }
44
+ }
45
+ /**
46
+ * @private
47
+ */
48
+ function checkCallbackResponse() {
49
+ let params;
50
+ if (window.location.hash) {
51
+ params = new URLSearchParams(window.location.hash.substring(1));
52
+ if (params.get('access_token')) {
53
+ return { success: true, body: params };
54
+ }
55
+ }
56
+ else if (window.location.search) {
57
+ params = new URLSearchParams(window.location.search.substring(1));
58
+ if (params.get('error')) {
59
+ return { success: false, body: params };
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ *
65
+ */
66
+ const DEFAULT_POPUP_WIN_WIDTH = 912;
67
+ const DEFAULT_POPUP_WIN_HEIGHT = 513;
68
+ /** @private **/
69
+ let clientIdx = 0;
70
+ /**
71
+ *
72
+ */
73
+ class BrowserClient extends events_1.EventEmitter {
74
+ _prefix;
75
+ _config;
76
+ _connection;
77
+ /**
78
+ *
79
+ */
80
+ constructor(prefix) {
81
+ super();
82
+ this._prefix = prefix || 'jsforce' + clientIdx++;
83
+ }
84
+ get connection() {
85
+ if (!this._connection) {
86
+ this._connection = new connection_1.default(this._config);
87
+ }
88
+ return this._connection;
89
+ }
90
+ /**
91
+ *
92
+ */
93
+ init(config) {
94
+ if (handleCallbackResponse()) {
95
+ return;
96
+ }
97
+ this._config = config;
98
+ const tokens = this._getTokens();
99
+ if (tokens) {
100
+ this.connection._establish(tokens);
101
+ setTimeout(() => {
102
+ this.emit('connect', this.connection);
103
+ }, 10);
104
+ }
105
+ }
106
+ /**
107
+ *
108
+ */
109
+ login(options = {}) {
110
+ const { scope, size } = options;
111
+ const oauth2 = new oauth2_1.default(this._config ?? {});
112
+ const rand = Math.random().toString(36).substring(2);
113
+ const state = [this._prefix, 'popup', rand].join('.');
114
+ localStorage.setItem('jsforce_state', state);
115
+ const authzUrl = oauth2.getAuthorizationUrl({
116
+ response_type: 'token',
117
+ state,
118
+ ...(scope ? { scope } : {}),
119
+ });
120
+ const pw = popupWin(authzUrl, size?.width ?? DEFAULT_POPUP_WIN_WIDTH, size?.height ?? DEFAULT_POPUP_WIN_HEIGHT);
121
+ return new Promise((resolve, reject) => {
122
+ if (!pw) {
123
+ const state = [this._prefix, 'redirect', rand].join('.');
124
+ localStorage.setItem('jsforce_state', state);
125
+ const authzUrl = oauth2.getAuthorizationUrl({
126
+ response_type: 'token',
127
+ state,
128
+ ...(scope ? { scope } : {}),
129
+ });
130
+ location.href = authzUrl;
131
+ return;
132
+ }
133
+ this._removeTokens();
134
+ const pid = setInterval(() => {
135
+ try {
136
+ if (!pw || pw.closed) {
137
+ clearInterval(pid);
138
+ const tokens = this._getTokens();
139
+ if (tokens) {
140
+ this.connection._establish(tokens);
141
+ this.emit('connect', this.connection);
142
+ resolve({ status: 'connect' });
143
+ }
144
+ else {
145
+ const err = this._getError();
146
+ if (err) {
147
+ reject(new Error(err.error + ': ' + err.error_description));
148
+ }
149
+ else {
150
+ resolve({ status: 'cancel' });
151
+ }
152
+ }
153
+ }
154
+ }
155
+ catch (e) {
156
+ //
157
+ }
158
+ }, 1000);
159
+ });
160
+ }
161
+ /**
162
+ *
163
+ */
164
+ isLoggedIn() {
165
+ return !!this.connection.accessToken;
166
+ }
167
+ /**
168
+ *
169
+ */
170
+ logout() {
171
+ this.connection.logout();
172
+ this._removeTokens();
173
+ this.emit('disconnect');
174
+ }
175
+ /**
176
+ * @private
177
+ */
178
+ _getTokens() {
179
+ const regexp = new RegExp('(^|;\\s*)' + this._prefix + '_loggedin=true(;|$)');
180
+ if (document.cookie.match(regexp)) {
181
+ const issuedAt = Number(localStorage.getItem(this._prefix + '_issued_at'));
182
+ // 2 hours
183
+ if (Date.now() < issuedAt + 2 * 60 * 60 * 1000) {
184
+ let userInfo;
185
+ const idUrl = localStorage.getItem(this._prefix + '_id');
186
+ if (idUrl) {
187
+ const [id, organizationId] = idUrl.split('/').reverse();
188
+ userInfo = { id, organizationId, url: idUrl };
189
+ }
190
+ return {
191
+ accessToken: localStorage.getItem(this._prefix + '_access_token'),
192
+ instanceUrl: localStorage.getItem(this._prefix + '_instance_url'),
193
+ userInfo,
194
+ };
195
+ }
196
+ }
197
+ return null;
198
+ }
199
+ /**
200
+ * @private
201
+ */
202
+ _storeTokens(params) {
203
+ localStorage.setItem(this._prefix + '_access_token', params.access_token);
204
+ localStorage.setItem(this._prefix + '_instance_url', params.instance_url);
205
+ localStorage.setItem(this._prefix + '_issued_at', params.issued_at);
206
+ localStorage.setItem(this._prefix + '_id', params.id);
207
+ document.cookie = this._prefix + '_loggedin=true;';
208
+ }
209
+ /**
210
+ * @private
211
+ */
212
+ _removeTokens() {
213
+ localStorage.removeItem(this._prefix + '_access_token');
214
+ localStorage.removeItem(this._prefix + '_instance_url');
215
+ localStorage.removeItem(this._prefix + '_issued_at');
216
+ localStorage.removeItem(this._prefix + '_id');
217
+ document.cookie = this._prefix + '_loggedin=';
218
+ }
219
+ /**
220
+ * @private
221
+ */
222
+ _getError() {
223
+ try {
224
+ const err = JSON.parse(localStorage.getItem(this._prefix + '_error') ?? '');
225
+ localStorage.removeItem(this._prefix + '_error');
226
+ return err;
227
+ }
228
+ catch (e) {
229
+ //
230
+ }
231
+ }
232
+ /**
233
+ * @private
234
+ */
235
+ _storeError(err) {
236
+ localStorage.setItem(this._prefix + '_error', JSON.stringify(err));
237
+ }
238
+ }
239
+ exports.BrowserClient = BrowserClient;
240
+ /**
241
+ *
242
+ */
243
+ const client = new BrowserClient();
244
+ exports.default = client;
@@ -0,0 +1,12 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ *
4
+ */
5
+ import { Transform } from 'stream';
6
+ import { HttpRequest } from '../types';
7
+ declare function createRequest(jsonpParam?: string, timeout?: number): (params: HttpRequest) => Transform;
8
+ declare const _default: {
9
+ supported: boolean;
10
+ createRequest: typeof createRequest;
11
+ };
12
+ export default _default;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ *
5
+ */
6
+ const stream_1 = require("stream");
7
+ let _index = 0;
8
+ async function processJsonpRequest(params, jsonpParam, timeout) {
9
+ if (params.method.toUpperCase() !== 'GET') {
10
+ throw new Error('JSONP only supports GET request.');
11
+ }
12
+ _index += 1;
13
+ const cbFuncName = `_jsforce_jsonpCallback_${_index}`;
14
+ const callbacks = window;
15
+ let url = params.url;
16
+ url += url.indexOf('?') > 0 ? '&' : '?';
17
+ url += `${jsonpParam}=${cbFuncName}`;
18
+ const script = document.createElement('script');
19
+ script.type = 'text/javascript';
20
+ script.src = url;
21
+ if (document.documentElement) {
22
+ document.documentElement.appendChild(script);
23
+ }
24
+ let pid;
25
+ try {
26
+ const res = await new Promise((resolve, reject) => {
27
+ pid = setTimeout(() => {
28
+ reject(new Error('JSONP call time out.'));
29
+ }, timeout);
30
+ callbacks[cbFuncName] = resolve;
31
+ });
32
+ return {
33
+ statusCode: 200,
34
+ headers: { 'content-type': 'application/json' },
35
+ body: JSON.stringify(res),
36
+ };
37
+ }
38
+ finally {
39
+ clearTimeout(pid);
40
+ if (document.documentElement) {
41
+ document.documentElement.removeChild(script);
42
+ }
43
+ delete callbacks[cbFuncName];
44
+ }
45
+ }
46
+ function createRequest(jsonpParam = 'callback', timeout = 10000) {
47
+ return (params) => {
48
+ const stream = new stream_1.Transform({
49
+ transform(chunk, encoding, callback) {
50
+ callback();
51
+ },
52
+ flush() {
53
+ (async () => {
54
+ const response = await processJsonpRequest(params, jsonpParam, timeout);
55
+ stream.emit('response', response);
56
+ stream.emit('complete', response);
57
+ stream.push(response.body);
58
+ stream.push(null);
59
+ })();
60
+ },
61
+ });
62
+ stream.end();
63
+ return stream;
64
+ };
65
+ }
66
+ exports.default = {
67
+ supported: typeof window !== 'undefined' && typeof document !== 'undefined',
68
+ createRequest,
69
+ };
@@ -0,0 +1,3 @@
1
+ import { EmptyRegistry } from '../registry/empty';
2
+ declare const registry: EmptyRegistry;
3
+ export default registry;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const empty_1 = require("../registry/empty");
4
+ const registry = new empty_1.EmptyRegistry();
5
+ exports.default = registry;
@@ -0,0 +1,10 @@
1
+ /// <reference types="node" />
2
+ import { HttpRequest, HttpRequestOptions } from '../types';
3
+ /**
4
+ *
5
+ */
6
+ export declare function setDefaults(defaults_: HttpRequestOptions): void;
7
+ /**
8
+ *
9
+ */
10
+ export default function request(req: HttpRequest, options_?: HttpRequestOptions): import("stream").Duplex;
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setDefaults = void 0;
4
+ const request_helper_1 = require("../request-helper");
5
+ const stream_1 = require("../util/stream");
6
+ /**
7
+ * As the request streming is not yet supported on major browsers,
8
+ * it is set to false for now.
9
+ */
10
+ const supportsReadableStream = false;
11
+ /*
12
+ (async () => {
13
+ try {
14
+ if (
15
+ typeof fetch === 'function' &&
16
+ typeof Request === 'function' &&
17
+ typeof ReadableStream === 'function'
18
+ ) {
19
+ // this feature detection requires dummy POST request
20
+ const req = new Request('data:text/plain,', {
21
+ method: 'POST',
22
+ body: new ReadableStream(),
23
+ });
24
+ // if it has content-type header it doesn't regard body as stream
25
+ if (req.headers.has('Content-Type')) {
26
+ return false;
27
+ }
28
+ await (await fetch(req)).text();
29
+ return true;
30
+ }
31
+ } catch (e) {
32
+ // error might occur in env with CSP without connect-src data:
33
+ return false;
34
+ }
35
+ return false;
36
+ })();
37
+ */
38
+ /**
39
+ *
40
+ */
41
+ function toWhatwgReadableStream(ins) {
42
+ return new ReadableStream({
43
+ start(controller) {
44
+ ins.on('data', (chunk) => controller.enqueue(chunk));
45
+ ins.on('end', () => controller.close());
46
+ },
47
+ });
48
+ }
49
+ /**
50
+ *
51
+ */
52
+ async function readWhatwgReadableStream(rs, outs) {
53
+ const reader = rs.getReader();
54
+ async function readAndWrite() {
55
+ const { done, value } = await reader.read();
56
+ if (done) {
57
+ outs.end();
58
+ return false;
59
+ }
60
+ outs.write(value);
61
+ return true;
62
+ }
63
+ while (await readAndWrite())
64
+ ;
65
+ }
66
+ /**
67
+ *
68
+ */
69
+ async function startFetchRequest(request, options, input, output, emitter, counter = 0) {
70
+ const { followRedirect } = options;
71
+ const { url, body: reqBody, ...rreq } = request;
72
+ const body = input && /^(post|put|patch)$/i.test(request.method)
73
+ ? supportsReadableStream
74
+ ? toWhatwgReadableStream(input)
75
+ : await (0, stream_1.readAll)(input)
76
+ : undefined;
77
+ const controller = typeof AbortController !== 'undefined' ? new AbortController() : undefined;
78
+ const res = await (0, request_helper_1.executeWithTimeout)(() => fetch(url, {
79
+ ...rreq,
80
+ ...(body ? { body } : {}),
81
+ redirect: 'manual',
82
+ ...(controller ? { signal: controller.signal } : {}),
83
+ ...{ allowHTTP1ForStreamingUpload: true }, // Chrome allows request stream only in HTTP2/QUIC unless this opt-in flag
84
+ }), options.timeout, () => controller?.abort());
85
+ const headers = {};
86
+ // @ts-expect-error
87
+ for (const headerName of res.headers.keys()) {
88
+ headers[headerName.toLowerCase()] = res.headers.get(headerName);
89
+ }
90
+ const response = {
91
+ statusCode: res.status,
92
+ headers,
93
+ };
94
+ if (followRedirect && (0, request_helper_1.isRedirect)(response.statusCode)) {
95
+ try {
96
+ (0, request_helper_1.performRedirectRequest)(request, response, followRedirect, counter, (req) => startFetchRequest(req, options, undefined, output, emitter, counter + 1));
97
+ }
98
+ catch (err) {
99
+ emitter.emit('error', err);
100
+ }
101
+ return;
102
+ }
103
+ emitter.emit('response', response);
104
+ if (res.body) {
105
+ readWhatwgReadableStream(res.body, output);
106
+ }
107
+ else {
108
+ output.end();
109
+ }
110
+ }
111
+ /**
112
+ *
113
+ */
114
+ function getResponseHeaderNames(xhr) {
115
+ const headerLines = (xhr.getAllResponseHeaders() || '')
116
+ .split(/[\r\n]+/)
117
+ .filter((l) => l.trim() !== '');
118
+ return headerLines.map((headerLine) => headerLine.split(/\s*:/)[0].toLowerCase());
119
+ }
120
+ /**
121
+ *
122
+ */
123
+ async function startXmlHttpRequest(request, options, input, output, emitter, counter = 0) {
124
+ const { method, url, headers: reqHeaders } = request;
125
+ const { followRedirect } = options;
126
+ const reqBody = input && /^(post|put|patch)$/i.test(method) ? await (0, stream_1.readAll)(input) : null;
127
+ const xhr = new XMLHttpRequest();
128
+ await (0, request_helper_1.executeWithTimeout)(() => {
129
+ xhr.open(method, url);
130
+ if (reqHeaders) {
131
+ for (const header in reqHeaders) {
132
+ xhr.setRequestHeader(header, reqHeaders[header]);
133
+ }
134
+ }
135
+ if (options.timeout) {
136
+ xhr.timeout = options.timeout;
137
+ }
138
+ xhr.responseType = 'arraybuffer';
139
+ xhr.send(reqBody);
140
+ return new Promise((resolve, reject) => {
141
+ xhr.onload = () => resolve();
142
+ xhr.onerror = reject;
143
+ xhr.ontimeout = reject;
144
+ xhr.onabort = reject;
145
+ });
146
+ }, options.timeout, () => xhr.abort());
147
+ const headerNames = getResponseHeaderNames(xhr);
148
+ const headers = headerNames.reduce((headers, headerName) => ({
149
+ ...headers,
150
+ [headerName]: xhr.getResponseHeader(headerName) || '',
151
+ }), {});
152
+ const response = {
153
+ statusCode: xhr.status,
154
+ headers: headers,
155
+ };
156
+ if (followRedirect && (0, request_helper_1.isRedirect)(response.statusCode)) {
157
+ try {
158
+ (0, request_helper_1.performRedirectRequest)(request, response, followRedirect, counter, (req) => startXmlHttpRequest(req, options, undefined, output, emitter, counter + 1));
159
+ }
160
+ catch (err) {
161
+ emitter.emit('error', err);
162
+ }
163
+ return;
164
+ }
165
+ let body;
166
+ if (!response.statusCode) {
167
+ response.statusCode = 400;
168
+ body = Buffer.from('Access Declined');
169
+ }
170
+ else {
171
+ body = Buffer.from(xhr.response);
172
+ }
173
+ emitter.emit('response', response);
174
+ output.write(body);
175
+ output.end();
176
+ }
177
+ /**
178
+ *
179
+ */
180
+ let defaults = {};
181
+ /**
182
+ *
183
+ */
184
+ function setDefaults(defaults_) {
185
+ defaults = defaults_;
186
+ }
187
+ exports.setDefaults = setDefaults;
188
+ /**
189
+ *
190
+ */
191
+ function request(req, options_ = {}) {
192
+ const options = { ...defaults, ...options_ };
193
+ const { input, output, stream } = (0, request_helper_1.createHttpRequestHandlerStreams)(req, options);
194
+ if (typeof window !== 'undefined' && typeof window.fetch === 'function') {
195
+ startFetchRequest(req, options, input, output, stream);
196
+ }
197
+ else {
198
+ startXmlHttpRequest(req, options, input, output, stream);
199
+ }
200
+ return stream;
201
+ }
202
+ exports.default = request;
package/lib/cache.d.ts ADDED
@@ -0,0 +1,74 @@
1
+ /// <reference types="node" />
2
+ /**
3
+ * @file Manages asynchronous method response cache
4
+ * @author Shinichi Tomita <shinichi.tomita@gmail.com>
5
+ */
6
+ import { EventEmitter } from 'events';
7
+ /**
8
+ * type def
9
+ */
10
+ export type CachingOptions = {
11
+ key?: string | ((...args: any[]) => string);
12
+ namespace?: string;
13
+ strategy: 'NOCACHE' | 'HIT' | 'IMMEDIATE';
14
+ };
15
+ type CacheValue<T> = {
16
+ error?: Error;
17
+ result: T;
18
+ };
19
+ export type CachedFunction<Fn> = Fn & {
20
+ clear: (...args: any[]) => void;
21
+ };
22
+ /**
23
+ * Class for managing cache entry
24
+ *
25
+ * @private
26
+ * @class
27
+ * @constructor
28
+ * @template T
29
+ */
30
+ declare class CacheEntry<T> extends EventEmitter {
31
+ _fetching: boolean;
32
+ _value: CacheValue<T> | void;
33
+ /**
34
+ * Get value in the cache entry
35
+ *
36
+ * @param {() => Promise<T>} [callback] - Callback function callbacked the cache entry updated
37
+ * @returns {T|undefined}
38
+ */
39
+ get(callback?: (v: T) => any): CacheValue<T> | void;
40
+ /**
41
+ * Set value in the cache entry
42
+ */
43
+ set(value: CacheValue<T>): void;
44
+ /**
45
+ * Clear cached value
46
+ */
47
+ clear(): void;
48
+ }
49
+ /**
50
+ * Caching manager for async methods
51
+ *
52
+ * @class
53
+ * @constructor
54
+ */
55
+ export declare class Cache {
56
+ private _entries;
57
+ /**
58
+ * retrive cache entry, or create if not exists.
59
+ *
60
+ * @param {String} [key] - Key of cache entry
61
+ * @returns {CacheEntry}
62
+ */
63
+ get(key: string): CacheEntry<any>;
64
+ /**
65
+ * clear cache entries prefix matching given key
66
+ */
67
+ clear(key?: string): void;
68
+ /**
69
+ * Enable caching for async call fn to lookup the response cache first,
70
+ * then invoke original if no cached value.
71
+ */
72
+ createCachedFunction<Fn extends Function>(fn: Fn, scope: any, options?: CachingOptions): CachedFunction<Fn>;
73
+ }
74
+ export default Cache;