From ce6ed3d10c3cdf723b57d76ea253feed1c62164f Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 11 Nov 2022 10:25:08 -0800 Subject: [PATCH 1/4] Remove unused method --- src/StripeResource.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/StripeResource.ts b/src/StripeResource.ts index b4392c0d57..696fc31938 100644 --- a/src/StripeResource.ts +++ b/src/StripeResource.ts @@ -120,21 +120,6 @@ StripeResource.prototype = { // DEPRECATED: Here for backcompat in case users relied on this. wrapTimeout: utils.callbackifyPromiseWithTimeout, - // eslint-disable-next-line no-warning-comments - // TODO: Unused? - _timeoutHandler( - timeout: number, - req: any, - callback: RequestCallback - ): () => void { - return (): void => { - const timeoutErr = new TypeError('ETIMEDOUT'); - (timeoutErr as any).code = 'ETIMEDOUT'; - - req.destroy(timeoutErr); - }; - }, - _addHeadersDirectlyToObject( obj: Record, headers: RequestHeaders From a633adee051d19d4aa440e395150334121d5aa66 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 11 Nov 2022 10:32:38 -0800 Subject: [PATCH 2/4] build --- lib/StripeResource.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/StripeResource.js b/lib/StripeResource.js index 9a11b7d1c3..414d5217e2 100644 --- a/lib/StripeResource.js +++ b/lib/StripeResource.js @@ -95,15 +95,6 @@ StripeResource.prototype = { }, // DEPRECATED: Here for backcompat in case users relied on this. wrapTimeout: utils.callbackifyPromiseWithTimeout, - // eslint-disable-next-line no-warning-comments - // TODO: Unused? - _timeoutHandler(timeout, req, callback) { - return () => { - const timeoutErr = new TypeError('ETIMEDOUT'); - timeoutErr.code = 'ETIMEDOUT'; - req.destroy(timeoutErr); - }; - }, _addHeadersDirectlyToObject(obj, headers) { // For convenience, make some headers easily accessible on // lastResponse. From e1d1f3a721c69ffa93a78091f261984d8ab099ac Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 11 Nov 2022 14:35:06 -0800 Subject: [PATCH 3/4] Annotate prototypes with types --- lib/StripeResource.js | 18 ++------- lib/stripe.js | 14 +++++++ src/StripeResource.ts | 42 ++++++-------------- src/Types.d.ts | 92 ++++++++++++++++++++++++++++++++++++++++--- src/stripe.ts | 34 +++++++++++++--- tsconfig.json | 1 + 6 files changed, 146 insertions(+), 55 deletions(-) diff --git a/lib/StripeResource.js b/lib/StripeResource.js index 414d5217e2..4d8731932e 100644 --- a/lib/StripeResource.js +++ b/lib/StripeResource.js @@ -47,7 +47,9 @@ function StripeResource(stripe, deprecatedUrlData) { } StripeResource.prototype = { _stripe: null, + // @ts-ignore the type of path changes in ctor path: '', + resourcePath: '', // Methods that don't use the API's default '/v1' path can override it with this setting. basePath: null, initialize() {}, @@ -232,18 +234,6 @@ StripeResource.prototype = { requestRetries > 0 ? ` Request was retried ${requestRetries} times.` : '' }`; }, - _errorHandler(res, requestRetries, callback) { - return (message, detail) => { - callback.call( - this, - new StripeConnectionError({ - message: this._generateConnectionErrorMessage(requestRetries), - detail, - }), - null - ); - }; - }, // For more on when and how to retry API requests, see https://stripe.com/docs/error-handling#safely-retrying-requests-with-idempotency _shouldRetry(res, numRetries, maxRetries, error) { if ( @@ -459,7 +449,7 @@ StripeResource.prototype = { request_start_time: requestStartTime, }); const requestRetries = numRetries || 0; - const maxRetries = this._getMaxNetworkRetries(options.settings); + const maxRetries = this._getMaxNetworkRetries(options.settings || {}); this._stripe._emitter.emit('request', requestEvent); req .then((res) => { @@ -507,7 +497,7 @@ StripeResource.prototype = { if (error) { return callback(error); } - requestData = data; + const requestData = data; this._stripe.getClientUserAgent((clientUserAgent) => { const apiVersion = this._stripe.getApiField('version'); const headers = this._makeHeaders( diff --git a/lib/stripe.js b/lib/stripe.js index 97a78644cb..c4341c1b82 100644 --- a/lib/stripe.js +++ b/lib/stripe.js @@ -149,6 +149,19 @@ Stripe.createSubtleCryptoProvider = (subtleCrypto) => { return new SubtleCryptoProvider(subtleCrypto); }; Stripe.prototype = { + // Properties are set in the constructor above + _appInfo: null, + on: null, + off: null, + once: null, + VERSION: null, + StripeResource: null, + webhooks: null, + errors: null, + _api: null, + _prevRequestMetrics: null, + _emitter: null, + _enableTelemetry: null, /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -488,6 +501,7 @@ Stripe.prototype = { */ _prepResources() { for (const name in resources) { + // @ts-ignore this[utils.pascalToCamelCase(name)] = new resources[name](this); } }, diff --git a/src/StripeResource.ts b/src/StripeResource.ts index 696fc31938..c93293f6b8 100644 --- a/src/StripeResource.ts +++ b/src/StripeResource.ts @@ -58,10 +58,12 @@ function StripeResource( StripeResource.prototype = { _stripe: null as StripeObject | null, - path: '', + // @ts-ignore the type of path changes in ctor + path: '' as UrlInterpolator, + resourcePath: '', // Methods that don't use the API's default '/v1' path can override it with this setting. - basePath: null, + basePath: null!, initialize(): void {}, @@ -120,10 +122,7 @@ StripeResource.prototype = { // DEPRECATED: Here for backcompat in case users relied on this. wrapTimeout: utils.callbackifyPromiseWithTimeout, - _addHeadersDirectlyToObject( - obj: Record, - headers: RequestHeaders - ): void { + _addHeadersDirectlyToObject(obj: any, headers: RequestHeaders): void { // For convenience, make some headers easily accessible on // lastResponse. @@ -288,29 +287,12 @@ StripeResource.prototype = { }`; }, - _errorHandler( - res: never, - requestRetries: number, - callback: RequestCallback - ): (message: string, detail: string) => void { - return (message: string, detail: string): void => { - callback.call( - this, - new StripeConnectionError({ - message: this._generateConnectionErrorMessage(requestRetries), - detail, - }), - null - ); - }; - }, - // For more on when and how to retry API requests, see https://stripe.com/docs/error-handling#safely-retrying-requests-with-idempotency _shouldRetry( - res: HttpClientResponseInterface, + res: null | HttpClientResponseInterface, numRetries: number, maxRetries: number, - error?: {code: number} + error?: HttpClientResponseError ): boolean { if ( error && @@ -510,12 +492,12 @@ StripeResource.prototype = { method: string, host: string, path: string, - data: string, + data: RequestData, auth: string, options: RequestOptions = {}, callback: RequestCallback ): void { - let requestData: string; + let requestData: RequestData; const retryRequest = ( requestFn: typeof makeRequest, @@ -574,7 +556,7 @@ StripeResource.prototype = { const requestRetries = numRetries || 0; - const maxRetries = this._getMaxNetworkRetries(options.settings); + const maxRetries = this._getMaxNetworkRetries(options.settings || {}); this._stripe._emitter.emit('request', requestEvent); @@ -627,7 +609,7 @@ StripeResource.prototype = { return callback(error); } - requestData = data; + const requestData = data; this._stripe.getClientUserAgent((clientUserAgent: string) => { const apiVersion = this._stripe.getApiField('version'); @@ -656,6 +638,6 @@ StripeResource.prototype = { prepareAndMakeRequest(null, utils.stringifyRequestData(data || {})); } }, -}; +} as StripeResourceObject; export = StripeResource; diff --git a/src/Types.d.ts b/src/Types.d.ts index c785e6f3d0..b1cc7e9e59 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -107,6 +107,29 @@ interface HttpClientInterface { ) => Promise; } type StripeObject = { + getClientUserAgentSeeded: ( + seed: Record, + callback: (userAgent: string) => void + ) => void; + getUname: (callback: (uname: string) => void) => void; + setProtocol: (protocol: string) => void; + setPort: (port: number) => void; + getClientUserAgent: (callback: (clientUserAgent: string) => void) => void; + getTelemetryEnabled: () => boolean; + getAppInfoAsString: () => string; + getInitialNetworkRetryDelay: () => number; + getMaxNetworkRetryDelay: () => number; + getMaxNetworkRetries: () => number; + getConstant: (name: string) => T; + _setApiField: ( + name: K, + value: StripeObject['_api'][K] + ) => void; + getApiField: ( + key: K + ) => StripeObject['_api'][K]; + _setApiNumberField: (name: string, value: number) => unknown; + _appInfo: any; on: any; off: any; once: any; @@ -114,11 +137,13 @@ type StripeObject = { StripeResource: typeof StripeResource; errors: any; webhooks: any; - getApiField: (name: string) => T; _prepResources: () => void; _setAppInfo: (appInfo: AppInfo) => void; _setApiKey: (apiKey: string) => void; - _prevRequestMetrics: number[]; + _prevRequestMetrics: Array<{ + request_id: string; + request_duration_ms: number; + }>; _api: { auth: string | null; host: string; @@ -126,7 +151,7 @@ type StripeObject = { protocol: string; basePath: string; version: string; - timeout: string; + timeout: number; maxNetworkRetries: number; agent: string; httpClient: any; @@ -136,6 +161,7 @@ type StripeObject = { _emitter: import('events').EventEmitter; _enableTelemetry: boolean; _getPropsFromConfig: (config: Record) => UserProvidedConfig; + _clientId?: string; }; type StripeRawError = { message?: string; @@ -169,13 +195,13 @@ type StripeResourceObject = { basePath: UrlInterpolator; path: UrlInterpolator; resourcePath: string; - includeBasic: Array; + includeBasic?: Array; createResourcePathWithSymbols: (path: string | null | undefined) => string; createFullPath: ( interpolator: UrlInterpolator, urlData: RequestData ) => string; - _request: ( + _request( method: string, host: string, path: string, @@ -183,8 +209,62 @@ type StripeResourceObject = { auth: string, options: RequestOptions, callback: RequestCallback - ) => void; + ): void; initialize: (...args: Array) => void; + _joinUrlParts: (urlParts: string[]) => string; + _getRequestId: (headers: RequestHeaders) => string; + _makeResponseEvent: ( + requestEvent: RequestEvent, + statusCode: number, + headers: ResponseHeaders + ) => ResponseEvent; + _getUserAgentString: () => string; + _getTelemetryHeader: () => string; + requestDataProcessor: + | null + | (( + method: string, + data: RequestData, + headers: RequestHeaders | undefined, + prepareAndMakeRequest: (error: Error | null, data: string) => void + ) => void); + _recordRequestMetrics: (requestId: string, elapsed?: number) => void; + _addHeadersDirectlyToObject: (obj: any, headers: ResponseHeaders) => void; + _getMaxNetworkRetries: (settings: RequestSettings) => number; + _defaultIdempotencyKey: ( + method: string, + userSuppliedSettings: RequestSettings + ) => string | number | string[]; + _getSleepTimeInMS: ( + requestRetries: number, + retryAfter: number | null + ) => number | undefined; + _shouldRetry: ( + res: HttpClientResponseInterface | null, + requestRetries: number, + maxRetries: number, + error?: HttpClientResponseError + ) => boolean | undefined; + _jsonResponseHandler: ( + requestEvent: RequestEvent, + callback: RequestCallback + ) => (res: HttpClientResponseInterface) => void; + _streamingResponseHandler: ( + requestEvent: RequestEvent, + callback: RequestCallback + ) => (res: HttpClientResponseInterface) => RequestCallbackReturn; + _generateConnectionErrorMessage: ( + requestRetries: number + ) => string | undefined; + _makeHeaders: ( + auth: string, + length: number, + apiVersion: string, + clientUserAgent: string, + method: string, + headers: RequestHeaders | undefined, + settings: RequestSettings | undefined + ) => RequestHeaders; }; type UrlInterpolator = (params: Record) => string; type UserProvidedConfig = { diff --git a/src/stripe.ts b/src/stripe.ts index 6e684e19c7..b53719fa77 100644 --- a/src/stripe.ts +++ b/src/stripe.ts @@ -185,6 +185,20 @@ Stripe.createSubtleCryptoProvider = ( }; Stripe.prototype = { + // Properties are set in the constructor above + _appInfo: null!, + on: null!, + off: null!, + once: null!, + VERSION: null!, + StripeResource: null!, + webhooks: null!, + errors: null!, + _api: null!, + _prevRequestMetrics: null!, + _emitter: null!, + _enableTelemetry: null!, + /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -369,7 +383,10 @@ Stripe.prototype = { * @private * This may be removed in the future. */ - _setApiField(key: string, value: unknown): void { + _setApiField( + key: K, + value: StripeObject['_api'][K] + ): void { this._api[key] = value; }, @@ -380,7 +397,9 @@ Stripe.prototype = { * * It may be deprecated and removed in the future. */ - getApiField(key: string): T { + getApiField( + key: K + ): StripeObject['_api'][K] { return this._api[key]; }, @@ -388,7 +407,7 @@ Stripe.prototype = { this._clientId = clientId; }, - getClientId(): string { + getClientId(): string | undefined { return this._clientId; }, @@ -439,7 +458,11 @@ Stripe.prototype = { * @private * This may be removed in the future. */ - _setApiNumberField(prop: string, n: number, defaultVal?: number): void { + _setApiNumberField( + prop: keyof StripeObject['_api'], + n: number, + defaultVal?: number + ): void { const val = utils.validateInteger(prop, n, defaultVal); this._setApiField(prop, val); @@ -567,6 +590,7 @@ Stripe.prototype = { */ _prepResources(): void { for (const name in resources) { + // @ts-ignore this[utils.pascalToCamelCase(name)] = new resources[name](this); } }, @@ -611,7 +635,7 @@ Stripe.prototype = { return config; }, -}; +} as StripeObject; module.exports = Stripe; diff --git a/tsconfig.json b/tsconfig.json index b0e175f4d9..441cce9364 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "noImplicitAny": true, "noImplicitThis": true, "strict": true, + "strictFunctionTypes": true, }, "include": ["./src/**/*"] } From 6d4378b35269f7c511622fa3e7d55f00e5d337d4 Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Fri, 11 Nov 2022 14:54:42 -0800 Subject: [PATCH 4/4] revert bad change --- lib/StripeResource.js | 2 +- src/StripeResource.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/StripeResource.js b/lib/StripeResource.js index 4d8731932e..4ca71e7517 100644 --- a/lib/StripeResource.js +++ b/lib/StripeResource.js @@ -497,7 +497,7 @@ StripeResource.prototype = { if (error) { return callback(error); } - const requestData = data; + requestData = data; this._stripe.getClientUserAgent((clientUserAgent) => { const apiVersion = this._stripe.getApiField('version'); const headers = this._makeHeaders( diff --git a/src/StripeResource.ts b/src/StripeResource.ts index c93293f6b8..b273a9ae77 100644 --- a/src/StripeResource.ts +++ b/src/StripeResource.ts @@ -497,7 +497,7 @@ StripeResource.prototype = { options: RequestOptions = {}, callback: RequestCallback ): void { - let requestData: RequestData; + let requestData: string; const retryRequest = ( requestFn: typeof makeRequest, @@ -609,7 +609,7 @@ StripeResource.prototype = { return callback(error); } - const requestData = data; + requestData = data; this._stripe.getClientUserAgent((clientUserAgent: string) => { const apiVersion = this._stripe.getApiField('version');