diff --git a/.eslintignore b/.eslintignore index a6de844ce0..331241cae0 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,4 @@ *.node*.js -node_modules \ No newline at end of file +node_modules +lib +testProjects diff --git a/.eslintrc.js b/.eslintrc.js index 5111f4c6da..7eecf96137 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -249,4 +249,30 @@ module.exports = { }, plugins: ['prettier'], extends: ['plugin:prettier/recommended'], + overrides: [ + { + files: ["**/*.ts"], + parser: "@typescript-eslint/parser", + plugins: ['@typescript-eslint', 'prettier'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + rules: { + '@typescript-eslint/no-use-before-define': 0, + '@typescript-eslint/no-empty-interface': 0, + '@typescript-eslint/no-unused-vars': 0, + '@typescript-eslint/triple-slash-reference': 0, + '@typescript-eslint/ban-ts-ignore': 0, + '@typescript-eslint/no-empty-function': 0, + '@typescript-eslint/camelcase': 0, + '@typescript-eslint/no-explicit-any': 0, + '@typescript-eslint/explicit-function-return-type': 0, + '@typescript-eslint/no-var-requires': 0, + 'prefer-rest-params': 'off', + }, + }, + ], }; diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..ab0463350b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +lib/** linguist-generated diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 61f9d08d3e..6240f246fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,11 +41,21 @@ jobs: restore-keys: | ${{ runner.os }}-yarn- - - name: Node check - run: find . -name "*.js" -type f -not -path "./node_modules/*" -not -path "./\.*" -exec node --check {} \; + - name: Build Typescript + run: yarn && yarn build + + - name: Check for changes + run: | + if [[ `git status --porcelain` ]]; then + git diff + >&2 echo "Changes detected after compiling TypeScript. Please run yarn build and check in all compiled files in lib/." + exit 1 + else + exit 0 + fi - name: Lint - run: yarn && yarn lint + run: yarn lint test: name: Test (${{ matrix.node }}) diff --git a/.gitignore b/.gitignore index ee483f2f9d..9bc0539f53 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ tags .nyc_output coverage .idea +testProjects/**/node_modules +testProjects/**/package-lock.json diff --git a/lib/Error.js b/lib/Error.js index 2ad52c931a..a50ccab948 100644 --- a/lib/Error.js +++ b/lib/Error.js @@ -1,5 +1,4 @@ 'use strict'; - /** * StripeError is the base error from which all other more specific Stripe errors derive. * Specifically for errors returned from Stripe's REST API. @@ -8,7 +7,6 @@ class StripeError extends Error { constructor(raw = {}) { super(raw.message); this.type = this.constructor.name; - this.raw = raw; this.rawType = raw.type; this.code = raw.code; @@ -19,7 +17,6 @@ class StripeError extends Error { this.requestId = raw.requestId; this.statusCode = raw.statusCode; this.message = raw.message; - this.charge = raw.charge; this.decline_code = raw.decline_code; this.payment_intent = raw.payment_intent; @@ -28,7 +25,6 @@ class StripeError extends Error { this.setup_intent = raw.setup_intent; this.source = raw.source; } - /** * Helper factory which takes raw stripe errors and outputs wrapping instances */ @@ -53,21 +49,17 @@ class StripeError extends Error { } } } - // Specific Stripe Error types: - /** * CardError is raised when a user enters a card that can't be charged for * some reason. */ class StripeCardError extends StripeError {} - /** * InvalidRequestError is raised when a request is initiated with invalid * parameters. */ class StripeInvalidRequestError extends StripeError {} - /** * APIError is a generic error that may be raised in cases where none of the * other named errors cover the problem. It could also be raised in the case @@ -75,45 +67,38 @@ class StripeInvalidRequestError extends StripeError {} * Node.JS SDK doesn't know how to handle it. */ class StripeAPIError extends StripeError {} - /** * AuthenticationError is raised when invalid credentials are used to connect * to Stripe's servers. */ class StripeAuthenticationError extends StripeError {} - /** * PermissionError is raised in cases where access was attempted on a resource * that wasn't allowed. */ class StripePermissionError extends StripeError {} - /** * RateLimitError is raised in cases where an account is putting too much load * on Stripe's API servers (usually by performing too many requests). Please * back off on request rate. */ class StripeRateLimitError extends StripeError {} - /** * StripeConnectionError is raised in the event that the SDK can't connect to * Stripe's servers. That can be for a variety of different reasons from a * downed network to a bad TLS certificate. */ class StripeConnectionError extends StripeError {} - /** * SignatureVerificationError is raised when the signature verification for a * webhook fails */ class StripeSignatureVerificationError extends StripeError {} - /** * IdempotencyError is raised in cases where an idempotency key was used * improperly. */ class StripeIdempotencyError extends StripeError {} - /** * InvalidGrantError is raised when a specified code doesn't exist, is * expired, has been used, or doesn't belong to you; a refresh token doesn't @@ -121,22 +106,22 @@ class StripeIdempotencyError extends StripeError {} * doesn't match the mode of a code or refresh token. */ class StripeInvalidGrantError extends StripeError {} - /** * Any other error from Stripe not specifically captured above */ class StripeUnknownError extends StripeError {} - -module.exports.generate = StripeError.generate; -module.exports.StripeError = StripeError; -module.exports.StripeCardError = StripeCardError; -module.exports.StripeInvalidRequestError = StripeInvalidRequestError; -module.exports.StripeAPIError = StripeAPIError; -module.exports.StripeAuthenticationError = StripeAuthenticationError; -module.exports.StripePermissionError = StripePermissionError; -module.exports.StripeRateLimitError = StripeRateLimitError; -module.exports.StripeConnectionError = StripeConnectionError; -module.exports.StripeSignatureVerificationError = StripeSignatureVerificationError; -module.exports.StripeIdempotencyError = StripeIdempotencyError; -module.exports.StripeInvalidGrantError = StripeInvalidGrantError; -module.exports.StripeUnknownError = StripeUnknownError; +module.exports = { + generate: StripeError.generate, + StripeError: StripeError, + StripeCardError: StripeCardError, + StripeInvalidRequestError: StripeInvalidRequestError, + StripeAPIError: StripeAPIError, + StripeAuthenticationError: StripeAuthenticationError, + StripePermissionError: StripePermissionError, + StripeRateLimitError: StripeRateLimitError, + StripeConnectionError: StripeConnectionError, + StripeSignatureVerificationError: StripeSignatureVerificationError, + StripeIdempotencyError: StripeIdempotencyError, + StripeInvalidGrantError: StripeInvalidGrantError, + StripeUnknownError: StripeUnknownError, +}; diff --git a/lib/ResourceNamespace.js b/lib/ResourceNamespace.js index 0d76787d81..8267a0fa8b 100644 --- a/lib/ResourceNamespace.js +++ b/lib/ResourceNamespace.js @@ -1,22 +1,16 @@ 'use strict'; - // ResourceNamespace allows you to create nested resources, i.e. `stripe.issuing.cards`. // It also works recursively, so you could do i.e. `stripe.billing.invoicing.pay`. - function ResourceNamespace(stripe, resources) { for (const name in resources) { const camelCaseName = name[0].toLowerCase() + name.substring(1); - const resource = new resources[name](stripe); - this[camelCaseName] = resource; } } - module.exports = function(namespace, resources) { return function(stripe) { return new ResourceNamespace(stripe, resources); }; }; - module.exports.ResourceNamespace = ResourceNamespace; diff --git a/lib/StripeMethod.basic.js b/lib/StripeMethod.basic.js index b9be5302e4..1949b543c9 100644 --- a/lib/StripeMethod.basic.js +++ b/lib/StripeMethod.basic.js @@ -1,29 +1,23 @@ 'use strict'; - const stripeMethod = require('./StripeMethod'); - // DEPRECATED: These were kept for backwards compatibility in case users were // using this, but basic methods are now explicitly defined on a resource. module.exports = { create: stripeMethod({ method: 'POST', }), - list: stripeMethod({ method: 'GET', methodType: 'list', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - update: stripeMethod({ method: 'POST', path: '{id}', }), - // Avoid 'delete' keyword in JS del: stripeMethod({ method: 'DELETE', diff --git a/lib/StripeMethod.js b/lib/StripeMethod.js index 78018da23a..f4e9ada721 100644 --- a/lib/StripeMethod.js +++ b/lib/StripeMethod.js @@ -1,10 +1,8 @@ 'use strict'; - const utils = require('./utils'); const makeRequest = require('./makeRequest'); -const makeAutoPaginationMethods = require('./autoPagination') - .makeAutoPaginationMethods; - +const autoPagination = require('./autoPagination'); +const makeAutoPaginationMethods = autoPagination.makeAutoPaginationMethods; /** * Create an API method from the declared spec. * @@ -29,16 +27,13 @@ function stripeMethod(spec) { } return function(...args) { const callback = typeof args[args.length - 1] == 'function' && args.pop(); - spec.urlParams = utils.extractUrlParams( spec.fullPath || this.createResourcePathWithSymbols(spec.path || '') ); - const requestPromise = utils.callbackifyPromiseWithTimeout( makeRequest(this, args, spec, {}), callback ); - // Please note `spec.methodType === 'search'` is beta functionality and this // interface is subject to change/removal at any time. if (spec.methodType === 'list' || spec.methodType === 'search') { @@ -50,9 +45,7 @@ function stripeMethod(spec) { ); Object.assign(requestPromise, autoPaginationMethods); } - return requestPromise; }; } - module.exports = stripeMethod; diff --git a/lib/StripeResource.js b/lib/StripeResource.js index f56bb9bc72..bfced38996 100644 --- a/lib/StripeResource.js +++ b/lib/StripeResource.js @@ -1,27 +1,22 @@ 'use strict'; - const utils = require('./utils'); +const _Error = require('./Error'); const { - StripeConnectionError, + StripeAPIError, StripeAuthenticationError, + StripeConnectionError, + StripeError, StripePermissionError, StripeRateLimitError, - StripeError, - StripeAPIError, -} = require('./Error'); - +} = _Error; const {HttpClient} = require('./net/HttpClient'); - // Provide extension mechanism for Stripe Resource Sub-Classes StripeResource.extend = utils.protoExtend; - // Expose method-creator & prepared (basic) methods StripeResource.method = require('./StripeMethod'); StripeResource.BASIC_METHODS = require('./StripeMethod.basic'); - StripeResource.MAX_BUFFERED_REQUEST_METRICS = 100; const MAX_RETRY_AFTER_WAIT = 60; - /** * Encapsulates request logic for a Stripe Resource */ @@ -32,13 +27,11 @@ function StripeResource(stripe, deprecatedUrlData) { 'Support for curried url params was dropped in stripe-node v7.0.0. Instead, pass two ids.' ); } - this.basePath = utils.makeURLInterpolator( this.basePath || stripe.getApiField('basePath') ); this.resourcePath = this.path; this.path = utils.makeURLInterpolator(this.path); - // DEPRECATED: This was kept for backwards compatibility in case users were // using this, but basic methods are now explicitly defined on a resource. if (this.includeBasic) { @@ -46,31 +39,23 @@ function StripeResource(stripe, deprecatedUrlData) { this[methodName] = StripeResource.BASIC_METHODS[methodName]; }, this); } - this.initialize(...arguments); } - StripeResource.prototype = { path: '', - // Methods that don't use the API's default '/v1' path can override it with this setting. basePath: null, - initialize() {}, - // Function to override the default data processor. This allows full control // over how a StripeResource's request data will get converted into an HTTP // body. This is useful for non-standard HTTP requests. The function should // take method name, data, and headers as arguments. requestDataProcessor: null, - // Function to add a validation checks before sending the request, errors should // be thrown, and they will be passed to the callback/promise. validateRequest: null, - createFullPath(commandPath, urlData) { const urlParts = [this.basePath(urlData), this.path(urlData)]; - if (typeof commandPath === 'function') { const computedCommandPath = commandPath(urlData); // If we have no actual command path, we just omit it to avoid adding a @@ -82,10 +67,8 @@ StripeResource.prototype = { } else { urlParts.push(commandPath); } - return this._joinUrlParts(urlParts); }, - // Creates a relative resource path with symbols left in (unlike // createFullPath which takes some data to replace them with). For example it // might produce: /invoices/{id} @@ -98,7 +81,6 @@ StripeResource.prototype = { return `/${this.resourcePath}`; } }, - _joinUrlParts(parts) { // Replace any accidentally doubled up slashes. This previously used // path.join, which would do this as well. Unfortunately we need to do this @@ -106,34 +88,27 @@ StripeResource.prototype = { // interface and so we need to preserve backwards compatibility. return parts.join('/').replace(/\/{2,}/g, '/'); }, - // DEPRECATED: Here for backcompat in case users relied on this. wrapTimeout: utils.callbackifyPromiseWithTimeout, - _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. - // NOTE: Stripe responds with lowercase header names/keys. obj.requestId = headers['request-id']; obj.stripeAccount = obj.stripeAccount || headers['stripe-account']; obj.apiVersion = obj.apiVersion || headers['stripe-version']; obj.idempotencyKey = obj.idempotencyKey || headers['idempotency-key']; }, - _makeResponseEvent(requestEvent, statusCode, headers) { const requestEndTime = Date.now(); const requestDurationMs = requestEndTime - requestEvent.request_start_time; - return utils.removeNullish({ api_version: headers['stripe-version'], account: headers['stripe-account'], @@ -147,11 +122,9 @@ StripeResource.prototype = { request_end_time: requestEndTime, }); }, - _getRequestId(headers) { return headers['request-id']; }, - /** * Used by methods with spec.streaming === true. For these methods, we do not * buffer successful responses into memory or do parse them into stripe @@ -165,7 +138,6 @@ StripeResource.prototype = { _streamingResponseHandler(requestEvent, callback) { return (res) => { const headers = res.getHeaders(); - const streamCompleteCallback = () => { const responseEvent = this._makeResponseEvent( requestEvent, @@ -178,18 +150,14 @@ StripeResource.prototype = { responseEvent.elapsed ); }; - const stream = res.toStream(streamCompleteCallback); - // This is here for backwards compatibility, as the stream is a raw // HTTP response in Node and the legacy behavior was to mutate this // response. this._addHeadersDirectlyToObject(stream, headers); - return callback(null, stream); }; }, - /** * Default handler for Stripe responses. Buffers the response into memory, * parses the JSON and returns it (i.e. passes it to the callback) if there @@ -200,21 +168,18 @@ StripeResource.prototype = { const headers = res.getHeaders(); const requestId = this._getRequestId(headers); const statusCode = res.getStatusCode(); - const responseEvent = this._makeResponseEvent( requestEvent, statusCode, headers ); this._stripe._emitter.emit('response', responseEvent); - res .toJSON() .then( (jsonResponse) => { if (jsonResponse.error) { let err; - // Convert OAuth error responses into a standard format // so that the rest of the error logic can be shared if (typeof jsonResponse.error === 'string') { @@ -223,11 +188,9 @@ StripeResource.prototype = { message: jsonResponse.error_description, }; } - jsonResponse.error.headers = headers; jsonResponse.error.statusCode = statusCode; jsonResponse.error.requestId = requestId; - if (statusCode === 401) { err = new StripeAuthenticationError(jsonResponse.error); } else if (statusCode === 403) { @@ -237,10 +200,8 @@ StripeResource.prototype = { } else { err = StripeError.generate(jsonResponse.error); } - throw err; } - return jsonResponse; }, (e) => { @@ -254,7 +215,6 @@ StripeResource.prototype = { .then( (jsonResponse) => { this._recordRequestMetrics(requestId, responseEvent.elapsed); - // Expose raw response object. const rawResponse = res.getRawResponse(); this._addHeadersDirectlyToObject(rawResponse, headers); @@ -263,33 +223,29 @@ StripeResource.prototype = { writable: false, value: rawResponse, }); - callback.call(this, null, jsonResponse); }, (e) => callback.call(this, e, null) ); }; }, - _generateConnectionErrorMessage(requestRetries) { return `An error occurred with our connection to Stripe.${ requestRetries > 0 ? ` Request was retried ${requestRetries} times.` : '' }`; }, - _errorHandler(req, requestRetries, callback) { return (message, detail) => { callback.call( this, new StripeConnectionError({ message: this._generateConnectionErrorMessage(requestRetries), - detail: error, + 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 ( @@ -299,17 +255,14 @@ StripeResource.prototype = { ) { return true; } - // Do not retry if we are out of retries. if (numRetries >= maxRetries) { return false; } - // Retry on connection error. if (!res) { return true; } - // The API may ask us not to retry (e.g., if doing so would be a no-op) // or advise us to retry (e.g., in cases of lock timeouts); we defer to that. if (res.getHeaders()['stripe-should-retry'] === 'false') { @@ -318,12 +271,10 @@ StripeResource.prototype = { if (res.getHeaders()['stripe-should-retry'] === 'true') { return true; } - // Retry on conflict errors. if (res.getStatusCode() === 409) { return true; } - // Retry on 500, 503, and other internal errors. // // Note that we expect the stripe-should-retry header to be false @@ -332,14 +283,11 @@ StripeResource.prototype = { if (res.getStatusCode() >= 500) { return true; } - return false; }, - _getSleepTimeInMS(numRetries, retryAfter = null) { const initialNetworkRetryDelay = this._stripe.getInitialNetworkRetryDelay(); const maxNetworkRetryDelay = this._stripe.getMaxNetworkRetryDelay(); - // Apply exponential backoff with initialNetworkRetryDelay on the // number of numRetries so far as inputs. Do not allow the number to exceed // maxNetworkRetryDelay. @@ -347,22 +295,17 @@ StripeResource.prototype = { initialNetworkRetryDelay * Math.pow(numRetries - 1, 2), maxNetworkRetryDelay ); - // Apply some jitter by randomizing the value in the range of // (sleepSeconds / 2) to (sleepSeconds). sleepSeconds *= 0.5 * (1 + Math.random()); - // But never sleep less than the base sleep seconds. sleepSeconds = Math.max(initialNetworkRetryDelay, sleepSeconds); - // And never sleep less than the time the API asks us to wait, assuming it's a reasonable ask. if (Number.isInteger(retryAfter) && retryAfter <= MAX_RETRY_AFTER_WAIT) { sleepSeconds = Math.max(sleepSeconds, retryAfter); } - return sleepSeconds * 1000; }, - // Max retries can be set on a per request basis. Favor those over the global setting _getMaxNetworkRetries(settings = {}) { return settings.maxNetworkRetries && @@ -370,17 +313,14 @@ StripeResource.prototype = { ? settings.maxNetworkRetries : this._stripe.getMaxNetworkRetries(); }, - _defaultIdempotencyKey(method, settings) { // If this is a POST and we allow multiple retries, ensure an idempotency key. const maxRetries = this._getMaxNetworkRetries(settings); - if (method === 'POST' && maxRetries > 0) { return `stripe-node-retry-${utils.uuid4()}`; } return null; }, - _makeHeaders( auth, contentLength, @@ -405,7 +345,6 @@ StripeResource.prototype = { userSuppliedSettings ), }; - // As per https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2: // A user agent SHOULD send a Content-Length in a request message when // no Transfer-Encoding is sent and the request method defines a meaning @@ -420,7 +359,6 @@ StripeResource.prototype = { // include a Content-Length. const methodHasPayload = method == 'POST' || method == 'PUT' || method == 'PATCH'; - // If a content length was specified, we always include it regardless of // whether the method semantics anticipate such a body. This keeps us // consistent with historical behavior. We do however want to warn on this @@ -433,23 +371,19 @@ StripeResource.prototype = { } defaultHeaders['Content-Length'] = contentLength; } - return Object.assign( utils.removeNullish(defaultHeaders), // If the user supplied, say 'idempotency-key', override instead of appending by ensuring caps are the same. utils.normalizeHeaders(userSuppliedHeaders) ); }, - _getUserAgentString() { const packageVersion = this._stripe.getConstant('PACKAGE_VERSION'); const appInfo = this._stripe._appInfo ? this._stripe.getAppInfoAsString() : ''; - return `Stripe/v1 NodeBindings/${packageVersion} ${appInfo}`.trim(); }, - _getTelemetryHeader() { if ( this._stripe.getTelemetryEnabled() && @@ -461,7 +395,6 @@ StripeResource.prototype = { }); } }, - _recordRequestMetrics(requestId, requestDurationMs) { if (this._stripe.getTelemetryEnabled() && requestId) { if ( @@ -479,10 +412,8 @@ StripeResource.prototype = { } } }, - _request(method, host, path, data, auth, options = {}, callback) { let requestData; - const retryRequest = ( requestFn, apiVersion, @@ -498,16 +429,15 @@ StripeResource.prototype = { requestRetries + 1 ); }; - const makeRequest = (apiVersion, headers, numRetries) => { // timeout can be set on a per-request basis. Favor that over the global setting const timeout = options.settings && + options.settings.timeout && Number.isInteger(options.settings.timeout) && options.settings.timeout >= 0 ? options.settings.timeout : this._stripe.getApiField('timeout'); - const req = this._stripe .getApiField('httpClient') .makeRequest( @@ -520,9 +450,7 @@ StripeResource.prototype = { this._stripe.getApiField('protocol'), timeout ); - const requestStartTime = Date.now(); - const requestEvent = utils.removeNullish({ api_version: apiVersion, account: headers['Stripe-Account'], @@ -531,13 +459,9 @@ StripeResource.prototype = { path, request_start_time: requestStartTime, }); - const requestRetries = numRetries || 0; - const maxRetries = this._getMaxNetworkRetries(options.settings); - this._stripe._emitter.emit('request', requestEvent); - req .then((res) => { if (this._shouldRetry(res, requestRetries, maxRetries)) { @@ -566,7 +490,6 @@ StripeResource.prototype = { } else { const isTimeoutError = error.code && error.code === HttpClient.TIMEOUT_ERROR_CODE; - return callback.call( this, new StripeConnectionError({ @@ -579,14 +502,11 @@ StripeResource.prototype = { } }); }; - const prepareAndMakeRequest = (error, data) => { if (error) { return callback(error); } - requestData = data; - this._stripe.getClientUserAgent((clientUserAgent) => { const apiVersion = this._stripe.getApiField('version'); const headers = this._makeHeaders( @@ -598,11 +518,9 @@ StripeResource.prototype = { options.headers, options.settings ); - - makeRequest(apiVersion, headers); + makeRequest(apiVersion, headers, 0); }); }; - if (this.requestDataProcessor) { this.requestDataProcessor( method, @@ -615,5 +533,4 @@ StripeResource.prototype = { } }, }; - module.exports = StripeResource; diff --git a/lib/Webhooks.js b/lib/Webhooks.js index ffbe2004a9..cfd9232527 100644 --- a/lib/Webhooks.js +++ b/lib/Webhooks.js @@ -1,11 +1,8 @@ 'use strict'; - const utils = require('./utils'); const {StripeError, StripeSignatureVerificationError} = require('./Error'); - const Webhook = { - DEFAULT_TOLERANCE: 300, // 5 minutes - + DEFAULT_TOLERANCE: 300, constructEvent(payload, header, secret, tolerance, cryptoProvider) { this.signature.verifyHeader( payload, @@ -14,11 +11,9 @@ const Webhook = { tolerance || Webhook.DEFAULT_TOLERANCE, cryptoProvider ); - const jsonPayload = JSON.parse(payload); return jsonPayload; }, - async constructEventAsync( payload, header, @@ -33,11 +28,9 @@ const Webhook = { tolerance || Webhook.DEFAULT_TOLERANCE, cryptoProvider ); - const jsonPayload = JSON.parse(payload); return jsonPayload; }, - /** * Generates a header to be used for webhook mocking * @@ -55,32 +48,25 @@ const Webhook = { message: 'Options are required', }); } - opts.timestamp = Math.floor(opts.timestamp) || Math.floor(Date.now() / 1000); opts.scheme = opts.scheme || signature.EXPECTED_SCHEME; - opts.cryptoProvider = opts.cryptoProvider || getNodeCryptoProvider(); - opts.signature = opts.signature || opts.cryptoProvider.computeHMACSignature( opts.timestamp + '.' + opts.payload, opts.secret ); - const generatedHeader = [ 't=' + opts.timestamp, opts.scheme + '=' + opts.signature, ].join(','); - return generatedHeader; }, }; - const signature = { EXPECTED_SCHEME: 'v1', - verifyHeader( encodedPayload, encodedHeader, @@ -93,13 +79,11 @@ const signature = { decodedPayload: payload, details, } = parseEventDetails(encodedPayload, encodedHeader, this.EXPECTED_SCHEME); - cryptoProvider = cryptoProvider || getNodeCryptoProvider(); const expectedSignature = cryptoProvider.computeHMACSignature( makeHMACContent(payload, details), secret ); - validateComputedSignature( payload, header, @@ -107,10 +91,8 @@ const signature = { expectedSignature, tolerance ); - return true; }, - async verifyHeaderAsync( encodedPayload, encodedHeader, @@ -123,14 +105,11 @@ const signature = { decodedPayload: payload, details, } = parseEventDetails(encodedPayload, encodedHeader, this.EXPECTED_SCHEME); - cryptoProvider = cryptoProvider || getNodeCryptoProvider(); - const expectedSignature = await cryptoProvider.computeHMACSignatureAsync( makeHMACContent(payload, details), secret ); - return validateComputedSignature( payload, header, @@ -140,16 +119,13 @@ const signature = { ); }, }; - function makeHMACContent(payload, details) { return `${details.timestamp}.${payload}`; } - function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) { const decodedPayload = Buffer.isBuffer(encodedPayload) ? encodedPayload.toString('utf8') : encodedPayload; - // Express's type for `Request#headers` is `string | []string` // which is because the `set-cookie` header is an array, // but no other headers are an array (docs: https://nodejs.org/api/http.html#http_message_headers) @@ -159,13 +135,10 @@ function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) { 'Unexpected: An array was passed as a header, which should not be possible for the stripe-signature header.' ); } - const decodedHeader = Buffer.isBuffer(encodedHeader) ? encodedHeader.toString('utf8') : encodedHeader; - const details = parseHeader(decodedHeader, expectedScheme); - if (!details || details.timestamp === -1) { throw new StripeSignatureVerificationError({ message: 'Unable to extract timestamp and signatures from header', @@ -175,7 +148,6 @@ function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) { }, }); } - if (!details.signatures.length) { throw new StripeSignatureVerificationError({ message: 'No signatures found with expected scheme', @@ -185,14 +157,12 @@ function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) { }, }); } - return { decodedPayload, decodedHeader, details, }; } - function validateComputedSignature( payload, header, @@ -203,7 +173,6 @@ function validateComputedSignature( const signatureFound = !!details.signatures.filter( utils.secureCompare.bind(utils, expectedSignature) ).length; - if (!signatureFound) { throw new StripeSignatureVerificationError({ message: @@ -216,9 +185,7 @@ function validateComputedSignature( }, }); } - const timestampAge = Math.floor(Date.now() / 1000) - details.timestamp; - if (tolerance > 0 && timestampAge > tolerance) { throw new StripeSignatureVerificationError({ message: 'Timestamp outside the tolerance zone', @@ -228,27 +195,21 @@ function validateComputedSignature( }, }); } - return true; } - function parseHeader(header, scheme) { if (typeof header !== 'string') { return null; } - return header.split(',').reduce( (accum, item) => { const kv = item.split('='); - if (kv[0] === 't') { accum.timestamp = kv[1]; } - if (kv[0] === scheme) { accum.signatures.push(kv[1]); } - return accum; }, { @@ -257,9 +218,7 @@ function parseHeader(header, scheme) { } ); } - let webhooksNodeCryptoProviderInstance = null; - /** * Lazily instantiate a NodeCryptoProvider instance. This is a stateless object * so a singleton can be used here. @@ -271,7 +230,5 @@ function getNodeCryptoProvider() { } return webhooksNodeCryptoProviderInstance; } - Webhook.signature = signature; - module.exports = Webhook; diff --git a/lib/apiVersion.js b/lib/apiVersion.js index 704a3619eb..9c1e0e38d1 100644 --- a/lib/apiVersion.js +++ b/lib/apiVersion.js @@ -1,3 +1,2 @@ // File generated from our OpenAPI spec - module.exports = {ApiVersion: '2022-08-01'}; diff --git a/lib/autoPagination.js b/lib/autoPagination.js index fe6f1f15b6..141afdeb49 100644 --- a/lib/autoPagination.js +++ b/lib/autoPagination.js @@ -1,14 +1,11 @@ 'use strict'; - const makeRequest = require('./makeRequest'); const utils = require('./utils'); - function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { const promiseCache = {currentPromise: null}; const reverseIteration = isReverseIteration(requestArgs); let pagePromise = firstPagePromise; let i = 0; - // Search and List methods iterate differently. // Search relies on a `next_page` token and can only iterate in one direction. // List relies on either an `ending_before` or `starting_after` field with @@ -36,7 +33,6 @@ function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { }); }; } - function iterate(pageResult) { if ( !( @@ -49,12 +45,10 @@ function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { 'Unexpected: Stripe API response does not have a well-formed `data` array.' ); } - if (i < pageResult.data.length) { const idx = reverseIteration ? pageResult.data.length - 1 - i : i; const value = pageResult.data[idx]; i += 1; - return {value, done: false}; } else if (pageResult.has_more) { // Reset counter, request next page, and recurse. @@ -64,7 +58,6 @@ function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { } return {value: undefined, done: true}; } - function asyncIteratorNext() { return memoizedPromise(promiseCache, (resolve, reject) => { return pagePromise @@ -73,14 +66,11 @@ function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { .catch(reject); }); } - const autoPagingEach = makeAutoPagingEach(asyncIteratorNext); const autoPagingToArray = makeAutoPagingToArray(autoPagingEach); - const autoPaginationMethods = { autoPagingEach, autoPagingToArray, - // Async iterator functions: next: asyncIteratorNext, return: () => { @@ -93,15 +83,11 @@ function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { }; return autoPaginationMethods; } - -module.exports.makeAutoPaginationMethods = makeAutoPaginationMethods; - /** * ---------------- * Private Helpers: * ---------------- */ - function getAsyncIteratorSymbol() { if (typeof Symbol !== 'undefined' && Symbol.asyncIterator) { return Symbol.asyncIterator; @@ -109,7 +95,6 @@ function getAsyncIteratorSymbol() { // Follow the convention from libraries like iterall: https://github.com/leebyron/iterall#asynciterator-1 return '@@asyncIterator'; } - function getDoneCallback(args) { if (args.length < 2) { return undefined; @@ -122,7 +107,6 @@ function getDoneCallback(args) { } return onDone; } - /** * We allow four forms of the `onItem` callback (the middle two being equivalent), * @@ -144,18 +128,15 @@ function getItemCallback(args) { `The first argument to autoPagingEach, if present, must be a callback function; received ${typeof onItem}` ); } - // 4. `.autoPagingEach((item, next) => { doSomething(item); next(false); });` if (onItem.length === 2) { return onItem; } - if (onItem.length > 2) { throw Error( `The \`onItem\` callback function passed to autoPagingEach must accept at most two arguments; got ${onItem}` ); } - // This magically handles all three of these usecases (the latter two being functionally identical): // 1. `.autoPagingEach((item) => { doSomething(item); return false; });` // 2. `.autoPagingEach(async (item) => { await doSomething(item); return false; });` @@ -165,7 +146,6 @@ function getItemCallback(args) { next(shouldContinue); }; } - function getLastId(listResult, reverseIteration) { const lastIdx = reverseIteration ? 0 : listResult.data.length - 1; const lastItem = listResult.data[lastIdx]; @@ -177,7 +157,6 @@ function getLastId(listResult, reverseIteration) { } return lastId; } - /** * If a user calls `.next()` multiple times in parallel, * return the same result until something has resolved @@ -193,7 +172,6 @@ function memoizedPromise(promiseCache, cb) { }); return promiseCache.currentPromise; } - function makeAutoPagingEach(asyncIteratorNext) { return function autoPagingEach(/* onItem?, onDone? */) { const args = [].slice.call(arguments); @@ -202,7 +180,6 @@ function makeAutoPagingEach(asyncIteratorNext) { if (args.length > 2) { throw Error(`autoPagingEach takes up to two arguments; received ${args}`); } - const autoPagePromise = wrapAsyncIteratorWithCallback( asyncIteratorNext, onItem @@ -210,7 +187,6 @@ function makeAutoPagingEach(asyncIteratorNext) { return utils.callbackifyPromiseWithTimeout(autoPagePromise, onDone); }; } - function makeAutoPagingToArray(autoPagingEach) { return function autoPagingToArray(opts, onDone) { const limit = opts && opts.limit; @@ -240,7 +216,6 @@ function makeAutoPagingToArray(autoPagingEach) { return utils.callbackifyPromiseWithTimeout(promise, onDone); }; } - function wrapAsyncIteratorWithCallback(asyncIteratorNext, onItem) { return new Promise((resolve, reject) => { function handleIteration(iterResult) { @@ -248,7 +223,6 @@ function wrapAsyncIteratorWithCallback(asyncIteratorNext, onItem) { resolve(); return; } - const item = iterResult.value; return new Promise((next) => { // Bit confusing, perhaps; we pass a `resolve` fn @@ -263,16 +237,16 @@ function wrapAsyncIteratorWithCallback(asyncIteratorNext, onItem) { } }); } - asyncIteratorNext() .then(handleIteration) .catch(reject); }); } - function isReverseIteration(requestArgs) { const args = [].slice.call(requestArgs); const dataFromArgs = utils.getDataFromArgs(args); - return !!dataFromArgs.ending_before; } +module.exports = { + makeAutoPaginationMethods: makeAutoPaginationMethods, +}; diff --git a/lib/crypto/CryptoProvider.js b/lib/crypto/CryptoProvider.js index 8f038d06ca..015a339447 100644 --- a/lib/crypto/CryptoProvider.js +++ b/lib/crypto/CryptoProvider.js @@ -1,5 +1,4 @@ 'use strict'; - /** * Interface encapsulating the various crypto computations used by the library, * allowing pluggable underlying crypto implementations. @@ -16,7 +15,6 @@ class CryptoProvider { computeHMACSignature(payload, secret) { throw new Error('computeHMACSignature not implemented.'); } - /** * Asynchronous version of `computeHMACSignature`. Some implementations may * only allow support async signature computation. @@ -32,5 +30,4 @@ class CryptoProvider { throw new Error('computeHMACSignatureAsync not implemented.'); } } - module.exports = CryptoProvider; diff --git a/lib/crypto/NodeCryptoProvider.js b/lib/crypto/NodeCryptoProvider.js index 83c2037ea2..4cdeb521fc 100644 --- a/lib/crypto/NodeCryptoProvider.js +++ b/lib/crypto/NodeCryptoProvider.js @@ -1,9 +1,6 @@ 'use strict'; - const crypto = require('crypto'); - const CryptoProvider = require('./CryptoProvider'); - /** * `CryptoProvider which uses the Node `crypto` package for its computations. */ @@ -15,12 +12,10 @@ class NodeCryptoProvider extends CryptoProvider { .update(payload, 'utf8') .digest('hex'); } - /** @override */ async computeHMACSignatureAsync(payload, secret) { const signature = await this.computeHMACSignature(payload, secret); return signature; } } - module.exports = NodeCryptoProvider; diff --git a/lib/crypto/SubtleCryptoProvider.js b/lib/crypto/SubtleCryptoProvider.js index 45aa40dd46..6ff0e2b3c2 100644 --- a/lib/crypto/SubtleCryptoProvider.js +++ b/lib/crypto/SubtleCryptoProvider.js @@ -1,7 +1,5 @@ 'use strict'; - const CryptoProvider = require('./CryptoProvider'); - /** * `CryptoProvider which uses the SubtleCrypto interface of the Web Crypto API. * @@ -10,24 +8,20 @@ const CryptoProvider = require('./CryptoProvider'); class SubtleCryptoProvider extends CryptoProvider { constructor(subtleCrypto) { super(); - // If no subtle crypto is interface, default to the global namespace. This // is to allow custom interfaces (eg. using the Node webcrypto interface in // tests). this.subtleCrypto = subtleCrypto || crypto.subtle; } - /** @override */ computeHMACSignature(payload, secret) { throw new Error( 'SubtleCryptoProvider cannot be used in a synchronous context.' ); } - /** @override */ async computeHMACSignatureAsync(payload, secret) { const encoder = new TextEncoder('utf-8'); - const key = await this.subtleCrypto.importKey( 'raw', encoder.encode(secret), @@ -38,32 +32,26 @@ class SubtleCryptoProvider extends CryptoProvider { false, ['sign'] ); - const signatureBuffer = await this.subtleCrypto.sign( 'hmac', key, encoder.encode(payload) ); - // crypto.subtle returns the signature in base64 format. This must be // encoded in hex to match the CryptoProvider contract. We map each byte in // the buffer to its corresponding hex octet and then combine into a string. const signatureBytes = new Uint8Array(signatureBuffer); const signatureHexCodes = new Array(signatureBytes.length); - for (let i = 0; i < signatureBytes.length; i++) { signatureHexCodes[i] = byteHexMapping[signatureBytes[i]]; } - return signatureHexCodes.join(''); } } - // Cached mapping of byte to hex representation. We do this once to avoid re- // computing every time we need to convert the result of a signature to hex. const byteHexMapping = new Array(256); for (let i = 0; i < byteHexMapping.length; i++) { byteHexMapping[i] = i.toString(16).padStart(2, '0'); } - module.exports = SubtleCryptoProvider; diff --git a/lib/makeRequest.js b/lib/makeRequest.js index 7ea0737b73..fc591f3245 100644 --- a/lib/makeRequest.js +++ b/lib/makeRequest.js @@ -1,13 +1,10 @@ 'use strict'; - const utils = require('./utils'); - function getRequestOpts(self, requestArgs, spec, overrideData) { // Extract spec values with defaults. const requestMethod = (spec.method || 'GET').toUpperCase(); const urlParams = spec.urlParams || []; const encode = spec.encode || ((data) => data); - const isUsingFullPath = !!spec.fullPath; const commandPath = utils.makeURLInterpolator( isUsingFullPath ? spec.fullPath : spec.path || '' @@ -17,10 +14,8 @@ function getRequestOpts(self, requestArgs, spec, overrideData) { const path = isUsingFullPath ? spec.fullPath : self.createResourcePathWithSymbols(spec.path); - // Don't mutate args externally. const args = [].slice.call(requestArgs); - // Generate and validate url params. const urlData = urlParams.reduce((urlData, param) => { const arg = args.shift(); @@ -29,11 +24,9 @@ function getRequestOpts(self, requestArgs, spec, overrideData) { `Stripe: Argument "${param}" must be a string, but got: ${arg} (on API request to \`${requestMethod} ${path}\`)` ); } - urlData[param] = arg; return urlData; }, {}); - // Pull request data and options (headers, auth) from args. const dataFromArgs = utils.getDataFromArgs(args); const data = encode(Object.assign({}, dataFromArgs, overrideData)); @@ -46,23 +39,18 @@ function getRequestOpts(self, requestArgs, spec, overrideData) { `Stripe: Unknown arguments (${args}). Did you mean to pass an options object? See https://github.com/stripe/stripe-node/wiki/Passing-Options. (on API request to ${requestMethod} \`${path}\`)` ); } - // When using full path, we can just invoke the URL interpolator directly // as we don't need to use the resource to create a full path. const requestPath = isUsingFullPath ? commandPath(urlData) : self.createFullPath(commandPath, urlData); - const headers = Object.assign(options.headers, spec.headers); - if (spec.validator) { spec.validator(data, {headers}); } - const dataInQuery = spec.method === 'GET' || spec.method === 'DELETE'; const bodyData = dataInQuery ? {} : data; const queryData = dataInQuery ? data : {}; - return { requestMethod, requestPath, @@ -75,7 +63,6 @@ function getRequestOpts(self, requestArgs, spec, overrideData) { settings: options.settings, }; } - function makeRequest(self, requestArgs, spec, overrideData) { return new Promise((resolve, reject) => { let opts; @@ -85,7 +72,6 @@ function makeRequest(self, requestArgs, spec, overrideData) { reject(err); return; } - function requestCallback(err, response) { if (err) { reject(err); @@ -97,16 +83,13 @@ function makeRequest(self, requestArgs, spec, overrideData) { ); } } - const emptyQuery = Object.keys(opts.queryData).length === 0; const path = [ opts.requestPath, emptyQuery ? '' : '?', utils.stringifyRequestData(opts.queryData), ].join(''); - const {headers, settings} = opts; - self._request( opts.requestMethod, opts.host, @@ -118,5 +101,4 @@ function makeRequest(self, requestArgs, spec, overrideData) { ); }); } - module.exports = makeRequest; diff --git a/lib/multipart.js b/lib/multipart.js index 90682aedda..bb186e00db 100644 --- a/lib/multipart.js +++ b/lib/multipart.js @@ -1,10 +1,7 @@ 'use strict'; - const utils = require('./utils'); const {StripeError} = require('./Error'); - class StreamProcessingError extends StripeError {} - // Method for formatting HTTP body for the multipart/form-data specification // Mostly taken from Fermata.js // https://github.com/natevw/fermata/blob/5d9732a33d776ce925013a265935facd1626cc88/fermata.js#L315-L343 @@ -14,7 +11,6 @@ const multipartDataGenerator = (method, data, headers) => { ).toString(); headers['Content-Type'] = `multipart/form-data; boundary=${segno}`; let buffer = Buffer.alloc(0); - function push(l) { const prevBuffer = buffer; const newBuffer = l instanceof Buffer ? l : Buffer.from(l); @@ -23,13 +19,10 @@ const multipartDataGenerator = (method, data, headers) => { newBuffer.copy(buffer, prevBuffer.length); buffer.write('\r\n', buffer.length - 2); } - function q(s) { return `"${s.replace(/"|"/g, '%22').replace(/\r\n|\r|\n/g, ' ')}"`; } - const flattenedData = utils.flattenAndStringify(data); - for (const k in flattenedData) { const v = flattenedData[k]; push(`--${segno}`); @@ -49,10 +42,8 @@ const multipartDataGenerator = (method, data, headers) => { } } push(`--${segno}--`); - return buffer; }; - const streamProcessor = (method, data, headers, callback) => { const bufferArray = []; data.file.data @@ -76,21 +67,16 @@ const streamProcessor = (method, data, headers, callback) => { ); }); }; - const multipartRequestDataProcessor = (method, data, headers, callback) => { data = data || {}; - if (method !== 'POST') { return callback(null, utils.stringifyRequestData(data)); } - const isStream = utils.checkForStream(data); if (isStream) { return streamProcessor(method, data, headers, callback); } - const buffer = multipartDataGenerator(method, data, headers); return callback(null, buffer); }; - module.exports.multipartRequestDataProcessor = multipartRequestDataProcessor; diff --git a/lib/net/FetchHttpClient.js b/lib/net/FetchHttpClient.js index 431282cd19..e57891b8cd 100644 --- a/lib/net/FetchHttpClient.js +++ b/lib/net/FetchHttpClient.js @@ -1,7 +1,5 @@ 'use strict'; - const {HttpClient, HttpClientResponse} = require('./HttpClient'); - /** * HTTP client which uses a `fetch` function to issue requests. * @@ -15,12 +13,10 @@ class FetchHttpClient extends HttpClient { super(); this._fetchFn = fetchFn; } - /** @override. */ getClientName() { return 'fetch'; } - makeRequest( host, port, @@ -32,13 +28,11 @@ class FetchHttpClient extends HttpClient { timeout ) { const isInsecureConnection = protocol === 'http'; - const url = new URL( path, `${isInsecureConnection ? 'http' : 'https'}://${host}` ); url.port = port; - // For methods which expect payloads, we should always pass a body value // even when it is empty. Without this, some JS runtimes (eg. Deno) will // inject a second Content-Length header. See https://github.com/stripe/stripe-node/issues/1519 @@ -46,14 +40,12 @@ class FetchHttpClient extends HttpClient { const methodHasPayload = method == 'POST' || method == 'PUT' || method == 'PATCH'; const body = requestData || (methodHasPayload ? '' : undefined); - const fetchFn = this._fetchFn || fetch; const fetchPromise = fetchFn(url.toString(), { method, headers, body, }); - // The Fetch API does not support passing in a timeout natively, so a // timeout promise is constructed to race against the fetch and preempt the // request, simulating a timeout. @@ -74,7 +66,6 @@ class FetchHttpClient extends HttpClient { reject(HttpClient.makeTimeoutError()); }, timeout); }); - return Promise.race([fetchPromise, timeoutPromise]) .then((res) => { return new FetchHttpClientResponse(res); @@ -86,7 +77,6 @@ class FetchHttpClient extends HttpClient { }); } } - class FetchHttpClientResponse extends HttpClientResponse { constructor(res) { super( @@ -95,11 +85,9 @@ class FetchHttpClientResponse extends HttpClientResponse { ); this._res = res; } - getRawResponse() { return this._res; } - toStream(streamCompleteCallback) { // Unfortunately `fetch` does not have event handlers for when the stream is // completely read. We therefore invoke the streamCompleteCallback right @@ -107,32 +95,25 @@ class FetchHttpClientResponse extends HttpClientResponse { // metrics, so it's ok to do this without waiting for the stream to be // completely read. streamCompleteCallback(); - // Fetch's `body` property is expected to be a readable stream of the body. return this._res.body; } - toJSON() { return this._res.json(); } - static _transformHeadersToObject(headers) { // Fetch uses a Headers instance so this must be converted to a barebones // JS object to meet the HttpClient interface. const headersObj = {}; - for (const entry of headers) { if (!Array.isArray(entry) || entry.length != 2) { throw new Error( 'Response objects produced by the fetch function given to FetchHttpClient do not have an iterable headers map. Response#headers should be an iterable object.' ); } - headersObj[entry[0]] = entry[1]; } - return headersObj; } } - module.exports = {FetchHttpClient, FetchHttpClientResponse}; diff --git a/lib/net/HttpClient.js b/lib/net/HttpClient.js index b309ce7d9d..88f9f31f1b 100644 --- a/lib/net/HttpClient.js +++ b/lib/net/HttpClient.js @@ -1,5 +1,4 @@ 'use strict'; - /** * Encapsulates the logic for issuing a request to the Stripe API. * @@ -14,7 +13,6 @@ class HttpClient { getClientName() { throw new Error('getClientName not implemented.'); } - makeRequest( host, port, @@ -27,7 +25,6 @@ class HttpClient { ) { throw new Error('makeRequest not implemented.'); } - /** Helper to make a consistent timeout error across implementations. */ static makeTimeoutError() { const timeoutErr = new TypeError(HttpClient.TIMEOUT_ERROR_CODE); @@ -35,35 +32,27 @@ class HttpClient { return timeoutErr; } } - HttpClient.CONNECTION_CLOSED_ERROR_CODES = ['ECONNRESET', 'EPIPE']; HttpClient.TIMEOUT_ERROR_CODE = 'ETIMEDOUT'; - class HttpClientResponse { constructor(statusCode, headers) { this._statusCode = statusCode; this._headers = headers; } - getStatusCode() { return this._statusCode; } - getHeaders() { return this._headers; } - getRawResponse() { throw new Error('getRawResponse not implemented.'); } - toStream(streamCompleteCallback) { throw new Error('toStream not implemented.'); } - toJSON() { throw new Error('toJSON not implemented.'); } } - module.exports = {HttpClient, HttpClientResponse}; diff --git a/lib/net/NodeHttpClient.js b/lib/net/NodeHttpClient.js index 222a446ce7..1f9d12c4d8 100644 --- a/lib/net/NodeHttpClient.js +++ b/lib/net/NodeHttpClient.js @@ -1,13 +1,9 @@ 'use strict'; - const http = require('http'); const https = require('https'); - const {HttpClient, HttpClientResponse} = require('./HttpClient'); - const defaultHttpAgent = new http.Agent({keepAlive: true}); const defaultHttpsAgent = new https.Agent({keepAlive: true}); - /** * HTTP client which uses the Node `http` and `https` packages to issue * requests.` @@ -17,12 +13,10 @@ class NodeHttpClient extends HttpClient { super(); this._agent = agent; } - /** @override. */ getClientName() { return 'node'; } - makeRequest( host, port, @@ -34,12 +28,10 @@ class NodeHttpClient extends HttpClient { timeout ) { const isInsecureConnection = protocol === 'http'; - let agent = this._agent; if (!agent) { agent = isInsecureConnection ? defaultHttpAgent : defaultHttpsAgent; } - const requestPromise = new Promise((resolve, reject) => { const req = (isInsecureConnection ? http : https).request({ host: host, @@ -50,19 +42,15 @@ class NodeHttpClient extends HttpClient { headers, ciphers: 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:!MD5', }); - req.setTimeout(timeout, () => { req.destroy(HttpClient.makeTimeoutError()); }); - req.on('response', (res) => { resolve(new NodeHttpClientResponse(res)); }); - req.on('error', (error) => { reject(error); }); - req.once('socket', (socket) => { if (socket.connecting) { socket.once( @@ -80,21 +68,17 @@ class NodeHttpClient extends HttpClient { } }); }); - return requestPromise; } } - class NodeHttpClientResponse extends HttpClientResponse { constructor(res) { super(res.statusCode, res.headers || {}); this._res = res; } - getRawResponse() { return this._res; } - toStream(streamCompleteCallback) { // The raw response is itself the stream, so we just return that. To be // backwards compatible, we should invoke the streamCompleteCallback only @@ -102,11 +86,9 @@ class NodeHttpClientResponse extends HttpClientResponse { this._res.once('end', () => streamCompleteCallback()); return this._res; } - toJSON() { return new Promise((resolve, reject) => { let response = ''; - this._res.setEncoding('utf8'); this._res.on('data', (chunk) => { response += chunk; @@ -121,5 +103,4 @@ class NodeHttpClientResponse extends HttpClientResponse { }); } } - module.exports = {NodeHttpClient, NodeHttpClientResponse}; diff --git a/lib/resources.js b/lib/resources.js index 825c8f1d9d..60e5444aad 100644 --- a/lib/resources.js +++ b/lib/resources.js @@ -1,9 +1,6 @@ // File generated from our OpenAPI spec - 'use strict'; - const resourceNamespace = require('./ResourceNamespace'); - module.exports = { Accounts: require('./resources/Accounts'), // Support Accounts for consistency, Account for backwards compatibility diff --git a/lib/resources/AccountLinks.js b/lib/resources/AccountLinks.js index 41e02b1ec5..2e8453e200 100644 --- a/lib/resources/AccountLinks.js +++ b/lib/resources/AccountLinks.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'account_links', - create: stripeMethod({ method: 'POST', path: '', diff --git a/lib/resources/Accounts.js b/lib/resources/Accounts.js index 351c055f23..44d78baf59 100644 --- a/lib/resources/Accounts.js +++ b/lib/resources/Accounts.js @@ -1,19 +1,14 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - // Since path can either be `account` or `accounts`, support both through stripeMethod path; module.exports = StripeResource.extend({ path: '', - create: stripeMethod({ method: 'POST', path: 'accounts', }), - retrieve(id) { // No longer allow an api key to be passed as the first string to this function due to ambiguity between // old account ids and api keys. To request the account for an api key, send null as the id @@ -33,96 +28,78 @@ module.exports = StripeResource.extend({ }).apply(this, arguments); } }, - update: stripeMethod({ method: 'POST', path: 'accounts/{account}', }), - list: stripeMethod({ method: 'GET', path: 'accounts', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: 'accounts/{account}', }), - reject: stripeMethod({ method: 'POST', path: 'accounts/{account}/reject', }), - retrieveCapability: stripeMethod({ method: 'GET', path: 'accounts/{account}/capabilities/{capability}', }), - updateCapability: stripeMethod({ method: 'POST', path: 'accounts/{account}/capabilities/{capability}', }), - listCapabilities: stripeMethod({ method: 'GET', path: 'accounts/{account}/capabilities', methodType: 'list', }), - createExternalAccount: stripeMethod({ method: 'POST', path: 'accounts/{account}/external_accounts', }), - retrieveExternalAccount: stripeMethod({ method: 'GET', path: 'accounts/{account}/external_accounts/{id}', }), - updateExternalAccount: stripeMethod({ method: 'POST', path: 'accounts/{account}/external_accounts/{id}', }), - listExternalAccounts: stripeMethod({ method: 'GET', path: 'accounts/{account}/external_accounts', methodType: 'list', }), - deleteExternalAccount: stripeMethod({ method: 'DELETE', path: 'accounts/{account}/external_accounts/{id}', }), - createLoginLink: stripeMethod({ method: 'POST', path: 'accounts/{account}/login_links', }), - createPerson: stripeMethod({ method: 'POST', path: 'accounts/{account}/persons', }), - retrievePerson: stripeMethod({ method: 'GET', path: 'accounts/{account}/persons/{person}', }), - updatePerson: stripeMethod({ method: 'POST', path: 'accounts/{account}/persons/{person}', }), - listPersons: stripeMethod({ method: 'GET', path: 'accounts/{account}/persons', methodType: 'list', }), - deletePerson: stripeMethod({ method: 'DELETE', path: 'accounts/{account}/persons/{person}', diff --git a/lib/resources/ApplePayDomains.js b/lib/resources/ApplePayDomains.js index 76a8c59585..e9a24f3638 100644 --- a/lib/resources/ApplePayDomains.js +++ b/lib/resources/ApplePayDomains.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'apple_pay/domains', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{domain}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{domain}', diff --git a/lib/resources/ApplicationFees.js b/lib/resources/ApplicationFees.js index ebd6372aca..c2e524df7a 100644 --- a/lib/resources/ApplicationFees.js +++ b/lib/resources/ApplicationFees.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'application_fees', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - createRefund: stripeMethod({ method: 'POST', path: '/{id}/refunds', }), - retrieveRefund: stripeMethod({ method: 'GET', path: '/{fee}/refunds/{id}', }), - updateRefund: stripeMethod({ method: 'POST', path: '/{fee}/refunds/{id}', }), - listRefunds: stripeMethod({ method: 'GET', path: '/{id}/refunds', diff --git a/lib/resources/Apps/Secrets.js b/lib/resources/Apps/Secrets.js index 238037508f..d5a0831a6f 100644 --- a/lib/resources/Apps/Secrets.js +++ b/lib/resources/Apps/Secrets.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'apps/secrets', - create: stripeMethod({ method: 'POST', path: '', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - deleteWhere: stripeMethod({ method: 'POST', path: '/delete', }), - find: stripeMethod({ method: 'GET', path: '/find', diff --git a/lib/resources/Balance.js b/lib/resources/Balance.js index ac7a9ae459..9b6f692d86 100644 --- a/lib/resources/Balance.js +++ b/lib/resources/Balance.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'balance', - retrieve: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/BalanceTransactions.js b/lib/resources/BalanceTransactions.js index adbe3d41f9..00438d0dc0 100644 --- a/lib/resources/BalanceTransactions.js +++ b/lib/resources/BalanceTransactions.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'balance_transactions', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/BillingPortal/Configurations.js b/lib/resources/BillingPortal/Configurations.js index ff3200160a..624852cb04 100644 --- a/lib/resources/BillingPortal/Configurations.js +++ b/lib/resources/BillingPortal/Configurations.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'billing_portal/configurations', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{configuration}', }), - update: stripeMethod({ method: 'POST', path: '/{configuration}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/BillingPortal/Sessions.js b/lib/resources/BillingPortal/Sessions.js index 04f0ef6805..909b3e077e 100644 --- a/lib/resources/BillingPortal/Sessions.js +++ b/lib/resources/BillingPortal/Sessions.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'billing_portal/sessions', - create: stripeMethod({ method: 'POST', path: '', diff --git a/lib/resources/Charges.js b/lib/resources/Charges.js index f4546063f7..ebe6b16a76 100644 --- a/lib/resources/Charges.js +++ b/lib/resources/Charges.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'charges', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{charge}', }), - update: stripeMethod({ method: 'POST', path: '/{charge}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - capture: stripeMethod({ method: 'POST', path: '/{charge}/capture', }), - search: stripeMethod({ method: 'GET', path: '/search', diff --git a/lib/resources/Checkout/Sessions.js b/lib/resources/Checkout/Sessions.js index 1cef4d65d7..9e3e61f000 100644 --- a/lib/resources/Checkout/Sessions.js +++ b/lib/resources/Checkout/Sessions.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'checkout/sessions', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{session}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - expire: stripeMethod({ method: 'POST', path: '/{session}/expire', }), - listLineItems: stripeMethod({ method: 'GET', path: '/{session}/line_items', diff --git a/lib/resources/CountrySpecs.js b/lib/resources/CountrySpecs.js index 789f99054a..5f76abfdcd 100644 --- a/lib/resources/CountrySpecs.js +++ b/lib/resources/CountrySpecs.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'country_specs', - retrieve: stripeMethod({ method: 'GET', path: '/{country}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Coupons.js b/lib/resources/Coupons.js index 11bed027fe..0e3d7c8acb 100644 --- a/lib/resources/Coupons.js +++ b/lib/resources/Coupons.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'coupons', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{coupon}', }), - update: stripeMethod({ method: 'POST', path: '/{coupon}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{coupon}', diff --git a/lib/resources/CreditNotes.js b/lib/resources/CreditNotes.js index e435282d00..94865f45e6 100644 --- a/lib/resources/CreditNotes.js +++ b/lib/resources/CreditNotes.js @@ -1,50 +1,39 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'credit_notes', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - update: stripeMethod({ method: 'POST', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - listPreviewLineItems: stripeMethod({ method: 'GET', path: '/preview/lines', methodType: 'list', }), - preview: stripeMethod({ method: 'GET', path: '/preview', }), - voidCreditNote: stripeMethod({ method: 'POST', path: '/{id}/void', }), - listLineItems: stripeMethod({ method: 'GET', path: '/{creditNote}/lines', diff --git a/lib/resources/Customers.js b/lib/resources/Customers.js index e3b8e8fab8..d0236d5444 100644 --- a/lib/resources/Customers.js +++ b/lib/resources/Customers.js @@ -1,155 +1,124 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'customers', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{customer}', }), - update: stripeMethod({ method: 'POST', path: '/{customer}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{customer}', }), - createFundingInstructions: stripeMethod({ method: 'POST', path: '/{customer}/funding_instructions', }), - deleteDiscount: stripeMethod({ method: 'DELETE', path: '/{customer}/discount', }), - listPaymentMethods: stripeMethod({ method: 'GET', path: '/{customer}/payment_methods', methodType: 'list', }), - retrievePaymentMethod: stripeMethod({ method: 'GET', path: '/{customer}/payment_methods/{paymentMethod}', }), - search: stripeMethod({ method: 'GET', path: '/search', methodType: 'search', }), - retrieveCashBalance: stripeMethod({ method: 'GET', path: '/{customer}/cash_balance', }), - updateCashBalance: stripeMethod({ method: 'POST', path: '/{customer}/cash_balance', }), - createBalanceTransaction: stripeMethod({ method: 'POST', path: '/{customer}/balance_transactions', }), - retrieveBalanceTransaction: stripeMethod({ method: 'GET', path: '/{customer}/balance_transactions/{transaction}', }), - updateBalanceTransaction: stripeMethod({ method: 'POST', path: '/{customer}/balance_transactions/{transaction}', }), - listBalanceTransactions: stripeMethod({ method: 'GET', path: '/{customer}/balance_transactions', methodType: 'list', }), - retrieveCashBalanceTransaction: stripeMethod({ method: 'GET', path: '/{customer}/cash_balance_transactions/{transaction}', }), - listCashBalanceTransactions: stripeMethod({ method: 'GET', path: '/{customer}/cash_balance_transactions', methodType: 'list', }), - createSource: stripeMethod({ method: 'POST', path: '/{customer}/sources', }), - retrieveSource: stripeMethod({ method: 'GET', path: '/{customer}/sources/{id}', }), - updateSource: stripeMethod({ method: 'POST', path: '/{customer}/sources/{id}', }), - listSources: stripeMethod({ method: 'GET', path: '/{customer}/sources', methodType: 'list', }), - deleteSource: stripeMethod({ method: 'DELETE', path: '/{customer}/sources/{id}', }), - verifySource: stripeMethod({ method: 'POST', path: '/{customer}/sources/{id}/verify', }), - createTaxId: stripeMethod({ method: 'POST', path: '/{customer}/tax_ids', }), - retrieveTaxId: stripeMethod({ method: 'GET', path: '/{customer}/tax_ids/{id}', }), - listTaxIds: stripeMethod({ method: 'GET', path: '/{customer}/tax_ids', methodType: 'list', }), - deleteTaxId: stripeMethod({ method: 'DELETE', path: '/{customer}/tax_ids/{id}', diff --git a/lib/resources/Disputes.js b/lib/resources/Disputes.js index 1318758949..6ca079cd87 100644 --- a/lib/resources/Disputes.js +++ b/lib/resources/Disputes.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'disputes', - retrieve: stripeMethod({ method: 'GET', path: '/{dispute}', }), - update: stripeMethod({ method: 'POST', path: '/{dispute}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - close: stripeMethod({ method: 'POST', path: '/{dispute}/close', diff --git a/lib/resources/EphemeralKeys.js b/lib/resources/EphemeralKeys.js index 2f9b02694c..962d341761 100644 --- a/lib/resources/EphemeralKeys.js +++ b/lib/resources/EphemeralKeys.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'ephemeral_keys', - create: stripeMethod({ method: 'POST', path: '', @@ -19,7 +15,6 @@ module.exports = StripeResource.extend({ } }, }), - del: stripeMethod({ method: 'DELETE', path: '/{key}', diff --git a/lib/resources/Events.js b/lib/resources/Events.js index 79ee31d45a..5c2c8ceb86 100644 --- a/lib/resources/Events.js +++ b/lib/resources/Events.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'events', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/ExchangeRates.js b/lib/resources/ExchangeRates.js index 021e972336..3c1464a3ae 100644 --- a/lib/resources/ExchangeRates.js +++ b/lib/resources/ExchangeRates.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'exchange_rates', - retrieve: stripeMethod({ method: 'GET', path: '/{rateId}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/FileLinks.js b/lib/resources/FileLinks.js index 7c7a6e117d..805e37ee5d 100644 --- a/lib/resources/FileLinks.js +++ b/lib/resources/FileLinks.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'file_links', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{link}', }), - update: stripeMethod({ method: 'POST', path: '/{link}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Files.js b/lib/resources/Files.js index 5dee82d1d2..b436f465d9 100644 --- a/lib/resources/Files.js +++ b/lib/resources/Files.js @@ -1,14 +1,10 @@ // File generated from our OpenAPI spec - 'use strict'; - const {multipartRequestDataProcessor} = require('../multipart'); const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'files', - create: stripeMethod({ method: 'POST', headers: { @@ -16,17 +12,14 @@ module.exports = StripeResource.extend({ }, host: 'files.stripe.com', }), - retrieve: stripeMethod({ method: 'GET', path: '/{file}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - requestDataProcessor: multipartRequestDataProcessor, }); diff --git a/lib/resources/FinancialConnections/Accounts.js b/lib/resources/FinancialConnections/Accounts.js index 674f42ec48..2a85a3b0d8 100644 --- a/lib/resources/FinancialConnections/Accounts.js +++ b/lib/resources/FinancialConnections/Accounts.js @@ -1,35 +1,27 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'financial_connections/accounts', - retrieve: stripeMethod({ method: 'GET', path: '/{account}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - disconnect: stripeMethod({ method: 'POST', path: '/{account}/disconnect', }), - listOwners: stripeMethod({ method: 'GET', path: '/{account}/owners', methodType: 'list', }), - refresh: stripeMethod({ method: 'POST', path: '/{account}/refresh', diff --git a/lib/resources/FinancialConnections/Sessions.js b/lib/resources/FinancialConnections/Sessions.js index 0e968a437b..0508a13fc3 100644 --- a/lib/resources/FinancialConnections/Sessions.js +++ b/lib/resources/FinancialConnections/Sessions.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'financial_connections/sessions', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{session}', diff --git a/lib/resources/Identity/VerificationReports.js b/lib/resources/Identity/VerificationReports.js index 6d78faa7a0..058451119b 100644 --- a/lib/resources/Identity/VerificationReports.js +++ b/lib/resources/Identity/VerificationReports.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'identity/verification_reports', - retrieve: stripeMethod({ method: 'GET', path: '/{report}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Identity/VerificationSessions.js b/lib/resources/Identity/VerificationSessions.js index 02345e1210..4f9ae5d151 100644 --- a/lib/resources/Identity/VerificationSessions.js +++ b/lib/resources/Identity/VerificationSessions.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'identity/verification_sessions', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{session}', }), - update: stripeMethod({ method: 'POST', path: '/{session}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{session}/cancel', }), - redact: stripeMethod({ method: 'POST', path: '/{session}/redact', diff --git a/lib/resources/InvoiceItems.js b/lib/resources/InvoiceItems.js index c7cb5586be..58ed3d88fd 100644 --- a/lib/resources/InvoiceItems.js +++ b/lib/resources/InvoiceItems.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'invoiceitems', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{invoiceitem}', }), - update: stripeMethod({ method: 'POST', path: '/{invoiceitem}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{invoiceitem}', diff --git a/lib/resources/Invoices.js b/lib/resources/Invoices.js index 21543c1f3a..67237d020d 100644 --- a/lib/resources/Invoices.js +++ b/lib/resources/Invoices.js @@ -1,81 +1,64 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'invoices', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{invoice}', }), - update: stripeMethod({ method: 'POST', path: '/{invoice}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{invoice}', }), - finalizeInvoice: stripeMethod({ method: 'POST', path: '/{invoice}/finalize', }), - listUpcomingLines: stripeMethod({ method: 'GET', path: '/upcoming/lines', methodType: 'list', }), - markUncollectible: stripeMethod({ method: 'POST', path: '/{invoice}/mark_uncollectible', }), - pay: stripeMethod({ method: 'POST', path: '/{invoice}/pay', }), - retrieveUpcoming: stripeMethod({ method: 'GET', path: '/upcoming', }), - search: stripeMethod({ method: 'GET', path: '/search', methodType: 'search', }), - sendInvoice: stripeMethod({ method: 'POST', path: '/{invoice}/send', }), - voidInvoice: stripeMethod({ method: 'POST', path: '/{invoice}/void', }), - listLineItems: stripeMethod({ method: 'GET', path: '/{invoice}/lines', diff --git a/lib/resources/Issuing/Authorizations.js b/lib/resources/Issuing/Authorizations.js index 5310d0ea8b..649d2b0595 100644 --- a/lib/resources/Issuing/Authorizations.js +++ b/lib/resources/Issuing/Authorizations.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'issuing/authorizations', - retrieve: stripeMethod({ method: 'GET', path: '/{authorization}', }), - update: stripeMethod({ method: 'POST', path: '/{authorization}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - approve: stripeMethod({ method: 'POST', path: '/{authorization}/approve', }), - decline: stripeMethod({ method: 'POST', path: '/{authorization}/decline', diff --git a/lib/resources/Issuing/Cardholders.js b/lib/resources/Issuing/Cardholders.js index 7b340e6912..20f17017b3 100644 --- a/lib/resources/Issuing/Cardholders.js +++ b/lib/resources/Issuing/Cardholders.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'issuing/cardholders', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{cardholder}', }), - update: stripeMethod({ method: 'POST', path: '/{cardholder}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Issuing/Cards.js b/lib/resources/Issuing/Cards.js index efc2cbc10f..35d66cd465 100644 --- a/lib/resources/Issuing/Cards.js +++ b/lib/resources/Issuing/Cards.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'issuing/cards', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{card}', }), - update: stripeMethod({ method: 'POST', path: '/{card}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Issuing/Disputes.js b/lib/resources/Issuing/Disputes.js index f62a2be96d..4d14d03db2 100644 --- a/lib/resources/Issuing/Disputes.js +++ b/lib/resources/Issuing/Disputes.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'issuing/disputes', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{dispute}', }), - update: stripeMethod({ method: 'POST', path: '/{dispute}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - submit: stripeMethod({ method: 'POST', path: '/{dispute}/submit', diff --git a/lib/resources/Issuing/Transactions.js b/lib/resources/Issuing/Transactions.js index 22b438429d..23a8e4f41e 100644 --- a/lib/resources/Issuing/Transactions.js +++ b/lib/resources/Issuing/Transactions.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'issuing/transactions', - retrieve: stripeMethod({ method: 'GET', path: '/{transaction}', }), - update: stripeMethod({ method: 'POST', path: '/{transaction}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Mandates.js b/lib/resources/Mandates.js index 6d9ced9f82..37bc7fae45 100644 --- a/lib/resources/Mandates.js +++ b/lib/resources/Mandates.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'mandates', - retrieve: stripeMethod({ method: 'GET', path: '/{mandate}', diff --git a/lib/resources/OAuth.js b/lib/resources/OAuth.js index 70ce4a2358..2c04c5fb7b 100644 --- a/lib/resources/OAuth.js +++ b/lib/resources/OAuth.js @@ -1,51 +1,38 @@ 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; const utils = require('../utils'); - const oAuthHost = 'connect.stripe.com'; - module.exports = StripeResource.extend({ basePath: '/', - authorizeUrl(params, options) { params = params || {}; options = options || {}; - let path = 'oauth/authorize'; - // For Express accounts, the path changes if (options.express) { path = `express/${path}`; } - if (!params.response_type) { params.response_type = 'code'; } - if (!params.client_id) { params.client_id = this._stripe.getClientId(); } - if (!params.scope) { params.scope = 'read_write'; } - return `https://${oAuthHost}/${path}?${utils.stringifyRequestData(params)}`; }, - token: stripeMethod({ method: 'POST', path: 'oauth/token', host: oAuthHost, }), - deauthorize(spec) { if (!spec.client_id) { spec.client_id = this._stripe.getClientId(); } - return stripeMethod({ method: 'POST', path: 'oauth/deauthorize', diff --git a/lib/resources/Orders.js b/lib/resources/Orders.js index a216b32fc7..61697d6a14 100644 --- a/lib/resources/Orders.js +++ b/lib/resources/Orders.js @@ -1,50 +1,39 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'orders', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - update: stripeMethod({ method: 'POST', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{id}/cancel', }), - listLineItems: stripeMethod({ method: 'GET', path: '/{id}/line_items', methodType: 'list', }), - reopen: stripeMethod({ method: 'POST', path: '/{id}/reopen', }), - submit: stripeMethod({ method: 'POST', path: '/{id}/submit', diff --git a/lib/resources/PaymentIntents.js b/lib/resources/PaymentIntents.js index d6addba0d3..b79f5aa6f5 100644 --- a/lib/resources/PaymentIntents.js +++ b/lib/resources/PaymentIntents.js @@ -1,65 +1,51 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'payment_intents', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{intent}', }), - update: stripeMethod({ method: 'POST', path: '/{intent}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - applyCustomerBalance: stripeMethod({ method: 'POST', path: '/{intent}/apply_customer_balance', }), - cancel: stripeMethod({ method: 'POST', path: '/{intent}/cancel', }), - capture: stripeMethod({ method: 'POST', path: '/{intent}/capture', }), - confirm: stripeMethod({ method: 'POST', path: '/{intent}/confirm', }), - incrementAuthorization: stripeMethod({ method: 'POST', path: '/{intent}/increment_authorization', }), - search: stripeMethod({ method: 'GET', path: '/search', methodType: 'search', }), - verifyMicrodeposits: stripeMethod({ method: 'POST', path: '/{intent}/verify_microdeposits', diff --git a/lib/resources/PaymentLinks.js b/lib/resources/PaymentLinks.js index a357cedd89..b2e76d285f 100644 --- a/lib/resources/PaymentLinks.js +++ b/lib/resources/PaymentLinks.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'payment_links', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{paymentLink}', }), - update: stripeMethod({ method: 'POST', path: '/{paymentLink}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - listLineItems: stripeMethod({ method: 'GET', path: '/{paymentLink}/line_items', diff --git a/lib/resources/PaymentMethods.js b/lib/resources/PaymentMethods.js index bd74b2ee5f..dff07ab37e 100644 --- a/lib/resources/PaymentMethods.js +++ b/lib/resources/PaymentMethods.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'payment_methods', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{paymentMethod}', }), - update: stripeMethod({ method: 'POST', path: '/{paymentMethod}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - attach: stripeMethod({ method: 'POST', path: '/{paymentMethod}/attach', }), - detach: stripeMethod({ method: 'POST', path: '/{paymentMethod}/detach', diff --git a/lib/resources/Payouts.js b/lib/resources/Payouts.js index a3b8e0cd66..3ba5176ffc 100644 --- a/lib/resources/Payouts.js +++ b/lib/resources/Payouts.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'payouts', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{payout}', }), - update: stripeMethod({ method: 'POST', path: '/{payout}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{payout}/cancel', }), - reverse: stripeMethod({ method: 'POST', path: '/{payout}/reverse', diff --git a/lib/resources/Plans.js b/lib/resources/Plans.js index bd55a157da..ade0a6cab4 100644 --- a/lib/resources/Plans.js +++ b/lib/resources/Plans.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'plans', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{plan}', }), - update: stripeMethod({ method: 'POST', path: '/{plan}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{plan}', diff --git a/lib/resources/Prices.js b/lib/resources/Prices.js index c509fdcbc0..f48b5b9981 100644 --- a/lib/resources/Prices.js +++ b/lib/resources/Prices.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'prices', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{price}', }), - update: stripeMethod({ method: 'POST', path: '/{price}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - search: stripeMethod({ method: 'GET', path: '/search', diff --git a/lib/resources/Products.js b/lib/resources/Products.js index 3886020cf8..fdb03d6a30 100644 --- a/lib/resources/Products.js +++ b/lib/resources/Products.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'products', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - update: stripeMethod({ method: 'POST', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{id}', }), - search: stripeMethod({ method: 'GET', path: '/search', diff --git a/lib/resources/PromotionCodes.js b/lib/resources/PromotionCodes.js index c8afa0e478..77d3ac71bd 100644 --- a/lib/resources/PromotionCodes.js +++ b/lib/resources/PromotionCodes.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'promotion_codes', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{promotionCode}', }), - update: stripeMethod({ method: 'POST', path: '/{promotionCode}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Quotes.js b/lib/resources/Quotes.js index 62aebb65a9..ca6073104d 100644 --- a/lib/resources/Quotes.js +++ b/lib/resources/Quotes.js @@ -1,61 +1,48 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'quotes', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{quote}', }), - update: stripeMethod({ method: 'POST', path: '/{quote}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - accept: stripeMethod({ method: 'POST', path: '/{quote}/accept', }), - cancel: stripeMethod({ method: 'POST', path: '/{quote}/cancel', }), - finalizeQuote: stripeMethod({ method: 'POST', path: '/{quote}/finalize', }), - listComputedUpfrontLineItems: stripeMethod({ method: 'GET', path: '/{quote}/computed_upfront_line_items', methodType: 'list', }), - listLineItems: stripeMethod({ method: 'GET', path: '/{quote}/line_items', methodType: 'list', }), - pdf: stripeMethod({ host: 'files.stripe.com', method: 'GET', diff --git a/lib/resources/Radar/EarlyFraudWarnings.js b/lib/resources/Radar/EarlyFraudWarnings.js index 9282648d86..3b32b7aee5 100644 --- a/lib/resources/Radar/EarlyFraudWarnings.js +++ b/lib/resources/Radar/EarlyFraudWarnings.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'radar/early_fraud_warnings', - retrieve: stripeMethod({ method: 'GET', path: '/{earlyFraudWarning}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Radar/ValueListItems.js b/lib/resources/Radar/ValueListItems.js index 75bcb8947c..2555807345 100644 --- a/lib/resources/Radar/ValueListItems.js +++ b/lib/resources/Radar/ValueListItems.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'radar/value_list_items', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{item}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{item}', diff --git a/lib/resources/Radar/ValueLists.js b/lib/resources/Radar/ValueLists.js index ace1edaa2d..8f3b6f9648 100644 --- a/lib/resources/Radar/ValueLists.js +++ b/lib/resources/Radar/ValueLists.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'radar/value_lists', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{valueList}', }), - update: stripeMethod({ method: 'POST', path: '/{valueList}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{valueList}', diff --git a/lib/resources/Refunds.js b/lib/resources/Refunds.js index c859fc577c..698646e681 100644 --- a/lib/resources/Refunds.js +++ b/lib/resources/Refunds.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'refunds', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{refund}', }), - update: stripeMethod({ method: 'POST', path: '/{refund}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{refund}/cancel', diff --git a/lib/resources/Reporting/ReportRuns.js b/lib/resources/Reporting/ReportRuns.js index 84eb179f90..0d0055f6da 100644 --- a/lib/resources/Reporting/ReportRuns.js +++ b/lib/resources/Reporting/ReportRuns.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'reporting/report_runs', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{reportRun}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Reporting/ReportTypes.js b/lib/resources/Reporting/ReportTypes.js index b4b25f8043..7a1f1bb67c 100644 --- a/lib/resources/Reporting/ReportTypes.js +++ b/lib/resources/Reporting/ReportTypes.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'reporting/report_types', - retrieve: stripeMethod({ method: 'GET', path: '/{reportType}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Reviews.js b/lib/resources/Reviews.js index 9400e8b89a..f4426b2703 100644 --- a/lib/resources/Reviews.js +++ b/lib/resources/Reviews.js @@ -1,24 +1,18 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'reviews', - retrieve: stripeMethod({ method: 'GET', path: '/{review}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - approve: stripeMethod({ method: 'POST', path: '/{review}/approve', diff --git a/lib/resources/SKUs.js b/lib/resources/SKUs.js index 26812405ff..9347fb54e0 100644 --- a/lib/resources/SKUs.js +++ b/lib/resources/SKUs.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'skus', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - update: stripeMethod({ method: 'POST', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{id}', diff --git a/lib/resources/SetupAttempts.js b/lib/resources/SetupAttempts.js index 9bb8c1d3e3..c8144bf284 100644 --- a/lib/resources/SetupAttempts.js +++ b/lib/resources/SetupAttempts.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'setup_attempts', - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/SetupIntents.js b/lib/resources/SetupIntents.js index 7aea8dcf75..adbf79a340 100644 --- a/lib/resources/SetupIntents.js +++ b/lib/resources/SetupIntents.js @@ -1,44 +1,34 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'setup_intents', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{intent}', }), - update: stripeMethod({ method: 'POST', path: '/{intent}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{intent}/cancel', }), - confirm: stripeMethod({ method: 'POST', path: '/{intent}/confirm', }), - verifyMicrodeposits: stripeMethod({ method: 'POST', path: '/{intent}/verify_microdeposits', diff --git a/lib/resources/ShippingRates.js b/lib/resources/ShippingRates.js index d7eb52ac16..859f07772d 100644 --- a/lib/resources/ShippingRates.js +++ b/lib/resources/ShippingRates.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'shipping_rates', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{shippingRateToken}', }), - update: stripeMethod({ method: 'POST', path: '/{shippingRateToken}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Sigma/ScheduledQueryRuns.js b/lib/resources/Sigma/ScheduledQueryRuns.js index a8cb8e60a6..e518c11a46 100644 --- a/lib/resources/Sigma/ScheduledQueryRuns.js +++ b/lib/resources/Sigma/ScheduledQueryRuns.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'sigma/scheduled_query_runs', - retrieve: stripeMethod({ method: 'GET', path: '/{scheduledQueryRun}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Sources.js b/lib/resources/Sources.js index 5008001c5c..8dc06c4df6 100644 --- a/lib/resources/Sources.js +++ b/lib/resources/Sources.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'sources', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{source}', }), - update: stripeMethod({ method: 'POST', path: '/{source}', }), - listSourceTransactions: stripeMethod({ method: 'GET', path: '/{source}/source_transactions', methodType: 'list', }), - verify: stripeMethod({ method: 'POST', path: '/{source}/verify', diff --git a/lib/resources/SubscriptionItems.js b/lib/resources/SubscriptionItems.js index 62423a22cb..8d05380657 100644 --- a/lib/resources/SubscriptionItems.js +++ b/lib/resources/SubscriptionItems.js @@ -1,44 +1,34 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'subscription_items', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{item}', }), - update: stripeMethod({ method: 'POST', path: '/{item}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{item}', }), - createUsageRecord: stripeMethod({ method: 'POST', path: '/{subscriptionItem}/usage_records', }), - listUsageRecordSummaries: stripeMethod({ method: 'GET', path: '/{subscriptionItem}/usage_record_summaries', diff --git a/lib/resources/SubscriptionSchedules.js b/lib/resources/SubscriptionSchedules.js index 9c9249e3d9..4bb9916c21 100644 --- a/lib/resources/SubscriptionSchedules.js +++ b/lib/resources/SubscriptionSchedules.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'subscription_schedules', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{schedule}', }), - update: stripeMethod({ method: 'POST', path: '/{schedule}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{schedule}/cancel', }), - release: stripeMethod({ method: 'POST', path: '/{schedule}/release', diff --git a/lib/resources/Subscriptions.js b/lib/resources/Subscriptions.js index bd0dc644c7..14494398b8 100644 --- a/lib/resources/Subscriptions.js +++ b/lib/resources/Subscriptions.js @@ -1,49 +1,38 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'subscriptions', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{subscriptionExposedId}', }), - update: stripeMethod({ method: 'POST', path: '/{subscriptionExposedId}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'DELETE', path: '/{subscriptionExposedId}', }), - del: stripeMethod({ method: 'DELETE', path: '/{subscriptionExposedId}', }), - deleteDiscount: stripeMethod({ method: 'DELETE', path: '/{subscriptionExposedId}/discount', }), - search: stripeMethod({ method: 'GET', path: '/search', diff --git a/lib/resources/TaxCodes.js b/lib/resources/TaxCodes.js index 57bf52ff3e..37c76cfb2d 100644 --- a/lib/resources/TaxCodes.js +++ b/lib/resources/TaxCodes.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'tax_codes', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/TaxRates.js b/lib/resources/TaxRates.js index e429895f7b..2d2242c80d 100644 --- a/lib/resources/TaxRates.js +++ b/lib/resources/TaxRates.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'tax_rates', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{taxRate}', }), - update: stripeMethod({ method: 'POST', path: '/{taxRate}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Terminal/Configurations.js b/lib/resources/Terminal/Configurations.js index 4a7d069a8e..c040bbc9f7 100644 --- a/lib/resources/Terminal/Configurations.js +++ b/lib/resources/Terminal/Configurations.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'terminal/configurations', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{configuration}', }), - update: stripeMethod({ method: 'POST', path: '/{configuration}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{configuration}', diff --git a/lib/resources/Terminal/ConnectionTokens.js b/lib/resources/Terminal/ConnectionTokens.js index 2e1a1b5155..fc16a45e17 100644 --- a/lib/resources/Terminal/ConnectionTokens.js +++ b/lib/resources/Terminal/ConnectionTokens.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'terminal/connection_tokens', - create: stripeMethod({ method: 'POST', path: '', diff --git a/lib/resources/Terminal/Locations.js b/lib/resources/Terminal/Locations.js index 161e0dd014..e89ac4c4d7 100644 --- a/lib/resources/Terminal/Locations.js +++ b/lib/resources/Terminal/Locations.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'terminal/locations', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{location}', }), - update: stripeMethod({ method: 'POST', path: '/{location}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{location}', diff --git a/lib/resources/Terminal/Readers.js b/lib/resources/Terminal/Readers.js index 05a8a53ef5..ec5cbae9a0 100644 --- a/lib/resources/Terminal/Readers.js +++ b/lib/resources/Terminal/Readers.js @@ -1,54 +1,42 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'terminal/readers', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{reader}', }), - update: stripeMethod({ method: 'POST', path: '/{reader}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{reader}', }), - cancelAction: stripeMethod({ method: 'POST', path: '/{reader}/cancel_action', }), - processPaymentIntent: stripeMethod({ method: 'POST', path: '/{reader}/process_payment_intent', }), - processSetupIntent: stripeMethod({ method: 'POST', path: '/{reader}/process_setup_intent', }), - setReaderDisplay: stripeMethod({ method: 'POST', path: '/{reader}/set_reader_display', diff --git a/lib/resources/TestHelpers/Customers.js b/lib/resources/TestHelpers/Customers.js index 64796a11da..418ac2b91b 100644 --- a/lib/resources/TestHelpers/Customers.js +++ b/lib/resources/TestHelpers/Customers.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/customers', - fundCashBalance: stripeMethod({ method: 'POST', path: '/{customer}/fund_cash_balance', diff --git a/lib/resources/TestHelpers/Issuing/Cards.js b/lib/resources/TestHelpers/Issuing/Cards.js index 0f8c50f7d0..67d2ae6841 100644 --- a/lib/resources/TestHelpers/Issuing/Cards.js +++ b/lib/resources/TestHelpers/Issuing/Cards.js @@ -1,28 +1,21 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/issuing/cards', - deliverCard: stripeMethod({ method: 'POST', path: '/{card}/shipping/deliver', }), - failCard: stripeMethod({ method: 'POST', path: '/{card}/shipping/fail', }), - returnCard: stripeMethod({ method: 'POST', path: '/{card}/shipping/return', }), - shipCard: stripeMethod({ method: 'POST', path: '/{card}/shipping/ship', diff --git a/lib/resources/TestHelpers/Refunds.js b/lib/resources/TestHelpers/Refunds.js index 7aac415e77..23c6e4a536 100644 --- a/lib/resources/TestHelpers/Refunds.js +++ b/lib/resources/TestHelpers/Refunds.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/refunds', - expire: stripeMethod({ method: 'POST', path: '/{refund}/expire', diff --git a/lib/resources/TestHelpers/Terminal/Readers.js b/lib/resources/TestHelpers/Terminal/Readers.js index ab660b0f95..9e1b961009 100644 --- a/lib/resources/TestHelpers/Terminal/Readers.js +++ b/lib/resources/TestHelpers/Terminal/Readers.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/terminal/readers', - presentPaymentMethod: stripeMethod({ method: 'POST', path: '/{reader}/present_payment_method', diff --git a/lib/resources/TestHelpers/TestClocks.js b/lib/resources/TestHelpers/TestClocks.js index adae9ae446..23e443c940 100644 --- a/lib/resources/TestHelpers/TestClocks.js +++ b/lib/resources/TestHelpers/TestClocks.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/test_clocks', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{testClock}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{testClock}', }), - advance: stripeMethod({ method: 'POST', path: '/{testClock}/advance', diff --git a/lib/resources/TestHelpers/Treasury/InboundTransfers.js b/lib/resources/TestHelpers/Treasury/InboundTransfers.js index 178816ad58..a565bdb064 100644 --- a/lib/resources/TestHelpers/Treasury/InboundTransfers.js +++ b/lib/resources/TestHelpers/Treasury/InboundTransfers.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/treasury/inbound_transfers', - fail: stripeMethod({ method: 'POST', path: '/{id}/fail', }), - returnInboundTransfer: stripeMethod({ method: 'POST', path: '/{id}/return', }), - succeed: stripeMethod({ method: 'POST', path: '/{id}/succeed', diff --git a/lib/resources/TestHelpers/Treasury/OutboundPayments.js b/lib/resources/TestHelpers/Treasury/OutboundPayments.js index 3a1b4d6516..3b0e9c0b28 100644 --- a/lib/resources/TestHelpers/Treasury/OutboundPayments.js +++ b/lib/resources/TestHelpers/Treasury/OutboundPayments.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/treasury/outbound_payments', - fail: stripeMethod({ method: 'POST', path: '/{id}/fail', }), - post: stripeMethod({ method: 'POST', path: '/{id}/post', }), - returnOutboundPayment: stripeMethod({ method: 'POST', path: '/{id}/return', diff --git a/lib/resources/TestHelpers/Treasury/OutboundTransfers.js b/lib/resources/TestHelpers/Treasury/OutboundTransfers.js index 90d7d6236b..70c4282770 100644 --- a/lib/resources/TestHelpers/Treasury/OutboundTransfers.js +++ b/lib/resources/TestHelpers/Treasury/OutboundTransfers.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/treasury/outbound_transfers', - fail: stripeMethod({ method: 'POST', path: '/{outboundTransfer}/fail', }), - post: stripeMethod({ method: 'POST', path: '/{outboundTransfer}/post', }), - returnOutboundTransfer: stripeMethod({ method: 'POST', path: '/{outboundTransfer}/return', diff --git a/lib/resources/TestHelpers/Treasury/ReceivedCredits.js b/lib/resources/TestHelpers/Treasury/ReceivedCredits.js index 8c3e5f0286..c13b41e601 100644 --- a/lib/resources/TestHelpers/Treasury/ReceivedCredits.js +++ b/lib/resources/TestHelpers/Treasury/ReceivedCredits.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/treasury/received_credits', - create: stripeMethod({ method: 'POST', path: '', diff --git a/lib/resources/TestHelpers/Treasury/ReceivedDebits.js b/lib/resources/TestHelpers/Treasury/ReceivedDebits.js index e25dc03bd2..245ff75520 100644 --- a/lib/resources/TestHelpers/Treasury/ReceivedDebits.js +++ b/lib/resources/TestHelpers/Treasury/ReceivedDebits.js @@ -1,13 +1,9 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'test_helpers/treasury/received_debits', - create: stripeMethod({ method: 'POST', path: '', diff --git a/lib/resources/Tokens.js b/lib/resources/Tokens.js index 76e4d33774..d840debbf9 100644 --- a/lib/resources/Tokens.js +++ b/lib/resources/Tokens.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'tokens', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{token}', diff --git a/lib/resources/Topups.js b/lib/resources/Topups.js index e65fe5d14a..e894b6f6b6 100644 --- a/lib/resources/Topups.js +++ b/lib/resources/Topups.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'topups', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{topup}', }), - update: stripeMethod({ method: 'POST', path: '/{topup}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{topup}/cancel', diff --git a/lib/resources/Transfers.js b/lib/resources/Transfers.js index 656128c392..c45b376bd4 100644 --- a/lib/resources/Transfers.js +++ b/lib/resources/Transfers.js @@ -1,49 +1,38 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'transfers', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{transfer}', }), - update: stripeMethod({ method: 'POST', path: '/{transfer}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - createReversal: stripeMethod({ method: 'POST', path: '/{id}/reversals', }), - retrieveReversal: stripeMethod({ method: 'GET', path: '/{transfer}/reversals/{id}', }), - updateReversal: stripeMethod({ method: 'POST', path: '/{transfer}/reversals/{id}', }), - listReversals: stripeMethod({ method: 'GET', path: '/{id}/reversals', diff --git a/lib/resources/Treasury/CreditReversals.js b/lib/resources/Treasury/CreditReversals.js index 9039b816a2..58139a528d 100644 --- a/lib/resources/Treasury/CreditReversals.js +++ b/lib/resources/Treasury/CreditReversals.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/credit_reversals', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{creditReversal}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Treasury/DebitReversals.js b/lib/resources/Treasury/DebitReversals.js index f95bfe5372..4e1e252504 100644 --- a/lib/resources/Treasury/DebitReversals.js +++ b/lib/resources/Treasury/DebitReversals.js @@ -1,23 +1,17 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/debit_reversals', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{debitReversal}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Treasury/FinancialAccounts.js b/lib/resources/Treasury/FinancialAccounts.js index a30b1273b6..d52bbea9f1 100644 --- a/lib/resources/Treasury/FinancialAccounts.js +++ b/lib/resources/Treasury/FinancialAccounts.js @@ -1,39 +1,30 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/financial_accounts', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{financialAccount}', }), - update: stripeMethod({ method: 'POST', path: '/{financialAccount}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - retrieveFeatures: stripeMethod({ method: 'GET', path: '/{financialAccount}/features', }), - updateFeatures: stripeMethod({ method: 'POST', path: '/{financialAccount}/features', diff --git a/lib/resources/Treasury/InboundTransfers.js b/lib/resources/Treasury/InboundTransfers.js index 468adba0e7..ecb36ecf31 100644 --- a/lib/resources/Treasury/InboundTransfers.js +++ b/lib/resources/Treasury/InboundTransfers.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/inbound_transfers', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{inboundTransfer}/cancel', diff --git a/lib/resources/Treasury/OutboundPayments.js b/lib/resources/Treasury/OutboundPayments.js index 5d08eaad0d..9e707e38ec 100644 --- a/lib/resources/Treasury/OutboundPayments.js +++ b/lib/resources/Treasury/OutboundPayments.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/outbound_payments', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{id}/cancel', diff --git a/lib/resources/Treasury/OutboundTransfers.js b/lib/resources/Treasury/OutboundTransfers.js index 40d72465dd..b7f024445c 100644 --- a/lib/resources/Treasury/OutboundTransfers.js +++ b/lib/resources/Treasury/OutboundTransfers.js @@ -1,29 +1,22 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/outbound_transfers', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{outboundTransfer}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - cancel: stripeMethod({ method: 'POST', path: '/{outboundTransfer}/cancel', diff --git a/lib/resources/Treasury/ReceivedCredits.js b/lib/resources/Treasury/ReceivedCredits.js index 98b11b1699..23abb51d70 100644 --- a/lib/resources/Treasury/ReceivedCredits.js +++ b/lib/resources/Treasury/ReceivedCredits.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/received_credits', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Treasury/ReceivedDebits.js b/lib/resources/Treasury/ReceivedDebits.js index c472144aa9..38e197bee3 100644 --- a/lib/resources/Treasury/ReceivedDebits.js +++ b/lib/resources/Treasury/ReceivedDebits.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/received_debits', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Treasury/TransactionEntries.js b/lib/resources/Treasury/TransactionEntries.js index a52c432d68..8b64e41a80 100644 --- a/lib/resources/Treasury/TransactionEntries.js +++ b/lib/resources/Treasury/TransactionEntries.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/transaction_entries', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/Treasury/Transactions.js b/lib/resources/Treasury/Transactions.js index a810413116..bcf4143114 100644 --- a/lib/resources/Treasury/Transactions.js +++ b/lib/resources/Treasury/Transactions.js @@ -1,18 +1,13 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'treasury/transactions', - retrieve: stripeMethod({ method: 'GET', path: '/{id}', }), - list: stripeMethod({ method: 'GET', path: '', diff --git a/lib/resources/WebhookEndpoints.js b/lib/resources/WebhookEndpoints.js index 2f73d65031..3027842505 100644 --- a/lib/resources/WebhookEndpoints.js +++ b/lib/resources/WebhookEndpoints.js @@ -1,34 +1,26 @@ // File generated from our OpenAPI spec - 'use strict'; - const StripeResource = require('../StripeResource'); const stripeMethod = StripeResource.method; - module.exports = StripeResource.extend({ path: 'webhook_endpoints', - create: stripeMethod({ method: 'POST', path: '', }), - retrieve: stripeMethod({ method: 'GET', path: '/{webhookEndpoint}', }), - update: stripeMethod({ method: 'POST', path: '/{webhookEndpoint}', }), - list: stripeMethod({ method: 'GET', path: '', methodType: 'list', }), - del: stripeMethod({ method: 'DELETE', path: '/{webhookEndpoint}', diff --git a/lib/stripe.js b/lib/stripe.js index f928ee5a51..60b82e7312 100644 --- a/lib/stripe.js +++ b/lib/stripe.js @@ -1,34 +1,28 @@ 'use strict'; - +const _Error = require('./Error'); const resources = require('./resources'); - const DEFAULT_HOST = 'api.stripe.com'; const DEFAULT_PORT = '443'; const DEFAULT_BASE_PATH = '/v1/'; const DEFAULT_API_VERSION = null; - const DEFAULT_TIMEOUT = 80000; - Stripe.PACKAGE_VERSION = require('../package.json').version; - const utils = require('./utils'); const {determineProcessUserAgentProperties, emitWarning} = utils; - -Stripe.USER_AGENT = { - bindings_version: Stripe.PACKAGE_VERSION, - lang: 'node', - publisher: 'stripe', - uname: null, - typescript: false, - ...determineProcessUserAgentProperties(), -}; - +Stripe.USER_AGENT = Object.assign( + { + bindings_version: Stripe.PACKAGE_VERSION, + lang: 'node', + publisher: 'stripe', + uname: null, + typescript: false, + }, + determineProcessUserAgentProperties() +); /** @private */ Stripe._UNAME_CACHE = null; - const MAX_NETWORK_RETRY_DELAY_SEC = 2; const INITIAL_NETWORK_RETRY_DELAY_SEC = 0.5; - const APP_INFO_PROPERTIES = ['name', 'version', 'url', 'partner_id']; const ALLOWED_CONFIG_PROPERTIES = [ 'apiVersion', @@ -44,39 +38,30 @@ const ALLOWED_CONFIG_PROPERTIES = [ 'appInfo', 'stripeAccount', ]; - const EventEmitter = require('events').EventEmitter; - -Stripe.StripeResource = require('./StripeResource'); +const StripeResource = require('./StripeResource'); +Stripe.StripeResource = StripeResource; Stripe.resources = resources; - const {HttpClient, HttpClientResponse} = require('./net/HttpClient'); Stripe.HttpClient = HttpClient; Stripe.HttpClientResponse = HttpClientResponse; - const CryptoProvider = require('./crypto/CryptoProvider'); Stripe.CryptoProvider = CryptoProvider; - function Stripe(key, config = {}) { if (!(this instanceof Stripe)) { return new Stripe(key, config); } - const props = this._getPropsFromConfig(config); - Object.defineProperty(this, '_emitter', { value: new EventEmitter(), enumerable: false, configurable: false, writable: false, }); - this.VERSION = Stripe.PACKAGE_VERSION; - this.on = this._emitter.on.bind(this._emitter); this.once = this._emitter.once.bind(this._emitter); this.off = this._emitter.removeListener.bind(this._emitter); - if ( props.protocol && props.protocol !== 'https' && @@ -86,9 +71,7 @@ function Stripe(key, config = {}) { 'The `https` protocol must be used when sending requests to `*.stripe.com`' ); } - const agent = props.httpAgent || null; - this._api = { auth: null, host: props.host || DEFAULT_HOST, @@ -107,7 +90,6 @@ function Stripe(key, config = {}) { dev: false, stripeAccount: props.stripeAccount || null, }; - const typescript = props.typescript || false; if (typescript !== Stripe.USER_AGENT.typescript) { // The mutation here is uncomfortable, but likely fastest; @@ -116,32 +98,24 @@ function Stripe(key, config = {}) { // we only want to incur the performance hit when that actually happens. Stripe.USER_AGENT.typescript = typescript; } - if (props.appInfo) { this._setAppInfo(props.appInfo); } - this._prepResources(); this._setApiKey(key); - - this.errors = require('./Error'); + this.errors = _Error; this.webhooks = require('./Webhooks'); - this._prevRequestMetrics = []; this._enableTelemetry = props.telemetry !== false; - // Expose StripeResource on the instance too this.StripeResource = Stripe.StripeResource; } - -Stripe.errors = require('./Error'); +Stripe.errors = _Error; Stripe.webhooks = require('./Webhooks'); - Stripe.createNodeHttpClient = (agent) => { const {NodeHttpClient} = require('./net/NodeHttpClient'); return new NodeHttpClient(agent); }; - /** * Creates an HTTP client for issuing Stripe API requests which uses the Web * Fetch API. @@ -153,7 +127,6 @@ Stripe.createFetchHttpClient = (fetchFn) => { const {FetchHttpClient} = require('./net/FetchHttpClient'); return new FetchHttpClient(fetchFn); }; - /** * Create a CryptoProvider which uses the built-in Node crypto libraries for * its crypto operations. @@ -162,7 +135,6 @@ Stripe.createNodeCryptoProvider = () => { const NodeCryptoProvider = require('./crypto/NodeCryptoProvider'); return new NodeCryptoProvider(); }; - /** * Creates a CryptoProvider which uses the Subtle Crypto API from the Web * Crypto API spec for its crypto operations. @@ -175,7 +147,6 @@ Stripe.createSubtleCryptoProvider = (subtleCrypto) => { const SubtleCryptoProvider = require('./crypto/SubtleCryptoProvider'); return new SubtleCryptoProvider(subtleCrypto); }; - Stripe.prototype = { /** * @deprecated will be removed in a future major version. Use the config object instead: @@ -199,7 +170,6 @@ Stripe.prototype = { this.setProtocol(protocol); } }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -214,7 +184,6 @@ Stripe.prototype = { ); this._setApiField('protocol', protocol.toLowerCase()); }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -229,7 +198,6 @@ Stripe.prototype = { ); this._setApiField('port', port); }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -246,7 +214,6 @@ Stripe.prototype = { this._setApiField('version', version); } }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -268,7 +235,6 @@ Stripe.prototype = { ); this._setApiKey(key); }, - /** * @private */ @@ -277,7 +243,6 @@ Stripe.prototype = { this._setApiField('auth', `Bearer ${key}`); } }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -291,7 +256,6 @@ Stripe.prototype = { ); this._setApiField('timeout', timeout == null ? DEFAULT_TIMEOUT : timeout); }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -310,7 +274,6 @@ Stripe.prototype = { ); this._setAppInfo(info); }, - /** * @private * This may be removed in the future. @@ -319,26 +282,19 @@ Stripe.prototype = { if (info && typeof info !== 'object') { throw new Error('AppInfo must be an object.'); } - if (info && !info.name) { throw new Error('AppInfo.name is required'); } - info = info || {}; - const appInfo = APP_INFO_PROPERTIES.reduce((accum, prop) => { if (typeof info[prop] == 'string') { accum = accum || {}; - accum[prop] = info[prop]; } - return accum; }, undefined); - this._appInfo = appInfo; }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -354,7 +310,6 @@ Stripe.prototype = { ); this._setApiField('agent', agent); }, - /** * @private * This may be removed in the future. @@ -362,7 +317,6 @@ Stripe.prototype = { _setApiField(key, value) { this._api[key] = value; }, - /** * @private * Please open or upvote an issue at github.com/stripe/stripe-node @@ -373,15 +327,12 @@ Stripe.prototype = { getApiField(key) { return this._api[key]; }, - setClientId(clientId) { this._clientId = clientId; }, - getClientId() { return this._clientId; }, - /** * @private * Please open or upvote an issue at github.com/stripe/stripe-node @@ -408,11 +359,9 @@ Stripe.prototype = { } return Stripe[c]; }, - getMaxNetworkRetries() { return this.getApiField('maxNetworkRetries'); }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -424,25 +373,20 @@ Stripe.prototype = { setMaxNetworkRetries(maxNetworkRetries) { this._setApiNumberField('maxNetworkRetries', maxNetworkRetries); }, - /** * @private * This may be removed in the future. */ _setApiNumberField(prop, n, defaultVal) { const val = utils.validateInteger(prop, n, defaultVal); - this._setApiField(prop, val); }, - getMaxNetworkRetryDelay() { return MAX_NETWORK_RETRY_DELAY_SEC; }, - getInitialNetworkRetryDelay() { return INITIAL_NETWORK_RETRY_DELAY_SEC; }, - /** * @private */ @@ -456,7 +400,6 @@ Stripe.prototype = { } Stripe._UNAME_CACHE.then((uname) => cb(uname)); }, - /** * @private * Please open or upvote an issue at github.com/stripe/stripe-node @@ -470,7 +413,6 @@ Stripe.prototype = { getClientUserAgent(cb) { return this.getClientUserAgentSeeded(Stripe.USER_AGENT, cb); }, - /** * @private * Please open or upvote an issue at github.com/stripe/stripe-node @@ -487,23 +429,18 @@ Stripe.prototype = { for (const field in seed) { userAgent[field] = encodeURIComponent(seed[field]); } - // URI-encode in case there are unusual characters in the system's uname. userAgent.uname = encodeURIComponent(uname || 'UNKNOWN'); - const client = this.getApiField('httpClient'); if (client) { userAgent.httplib = encodeURIComponent(client.getClientName()); } - if (this._appInfo) { userAgent.application = this._appInfo; } - cb(JSON.stringify(userAgent)); }); }, - /** * @private * Please open or upvote an issue at github.com/stripe/stripe-node @@ -515,20 +452,15 @@ Stripe.prototype = { if (!this._appInfo) { return ''; } - let formatted = this._appInfo.name; - if (this._appInfo.version) { formatted += `/${this._appInfo.version}`; } - if (this._appInfo.url) { formatted += ` (${this._appInfo.url})`; } - return formatted; }, - /** * @deprecated will be removed in a future major version. Use the config object instead: * @@ -543,11 +475,9 @@ Stripe.prototype = { ); this._enableTelemetry = enableTelemetry; }, - getTelemetryEnabled() { return this._enableTelemetry; }, - /** * @private * This may be removed in the future. @@ -557,7 +487,6 @@ Stripe.prototype = { this[utils.pascalToCamelCase(name)] = new resources[name](this); } }, - /** * @private * This may be removed in the future. @@ -567,27 +496,22 @@ Stripe.prototype = { if (!config) { return {}; } - // config can be an object or a string const isString = typeof config === 'string'; const isObject = config === Object(config) && !Array.isArray(config); - if (!isObject && !isString) { throw new Error('Config must either be an object or a string'); } - // If config is a string, we assume the old behavior of passing in a string representation of the api version if (isString) { return { apiVersion: config, }; } - // If config is an object, we assume the new behavior and make sure it doesn't contain any unexpected values const values = Object.keys(config).filter( (value) => !ALLOWED_CONFIG_PROPERTIES.includes(value) ); - if (values.length > 0) { throw new Error( `Config object may only contain the following: ${ALLOWED_CONFIG_PROPERTIES.join( @@ -595,16 +519,12 @@ Stripe.prototype = { )}` ); } - return config; }, }; - module.exports = Stripe; - // expose constructor as a named property to enable mocking with Sinon.JS module.exports.Stripe = Stripe; - // Allow use with the TypeScript compiler without `esModuleInterop`. // We may also want to add `Object.defineProperty(exports, "__esModule", {value: true});` in the future, so that Babel users will use the `default` version. module.exports.default = Stripe; diff --git a/lib/utils.js b/lib/utils.js index 7eed41defd..9efd90fd63 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,11 +1,8 @@ 'use strict'; - const EventEmitter = require('events').EventEmitter; const qs = require('qs'); const crypto = require('crypto'); - const hasOwn = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); - // Certain sandboxed environments (our known example right now are CloudFlare // Workers) may make `child_process` unavailable. Because `exec` isn't critical // to the operation of stripe-node, we handle this unavailability gracefully. @@ -17,7 +14,6 @@ try { throw e; } } - const OPTIONS_KEYS = [ 'apiKey', 'idempotencyKey', @@ -27,7 +23,6 @@ const OPTIONS_KEYS = [ 'timeout', 'host', ]; - const DEPRECATED_OPTIONS = { api_key: 'apiKey', idempotency_key: 'idempotencyKey', @@ -36,7 +31,6 @@ const DEPRECATED_OPTIONS = { stripeVersion: 'apiVersion', }; const DEPRECATED_OPTIONS_KEYS = Object.keys(DEPRECATED_OPTIONS); - const utils = (module.exports = { isOptionsHash(o) { return ( @@ -46,7 +40,6 @@ const utils = (module.exports = { DEPRECATED_OPTIONS_KEYS.some((prop) => hasOwn(o, prop))) ); }, - /** * Stringifies an Object, accommodating nested objects * (forming the conventional key 'parent[child]=value') @@ -64,7 +57,6 @@ const utils = (module.exports = { .replace(/%5D/g, ']') ); }, - /** * Outputs a new function with interpolated object property values. * Use like so: @@ -87,16 +79,13 @@ const utils = (module.exports = { }; }; })(), - extractUrlParams: (path) => { const params = path.match(/\{\w+\}/g); if (!params) { return []; } - return params.map((param) => param.replace(/[{}]/g, '')); }, - /** * Return the data argument from a list of arguments * @@ -107,17 +96,13 @@ const utils = (module.exports = { if (!Array.isArray(args) || !args[0] || typeof args[0] !== 'object') { return {}; } - if (!utils.isOptionsHash(args[0])) { return args.shift(); } - const argKeys = Object.keys(args[0]); - const optionKeysInArgs = argKeys.filter((key) => OPTIONS_KEYS.includes(key) ); - // In some cases options may be the provided as the first argument. // Here we're detecting a case where there are two distinct arguments // (the first being args and the second options) and with known @@ -132,10 +117,8 @@ const utils = (module.exports = { )}). Did you mean to pass an options object? See https://github.com/stripe/stripe-node/wiki/Passing-Options.` ); } - return {}; }, - /** * Return the options hash from a list of arguments */ @@ -150,12 +133,10 @@ const utils = (module.exports = { if (typeof arg === 'string') { opts.auth = args.pop(); } else if (utils.isOptionsHash(arg)) { - const params = {...args.pop()}; - + const params = Object.assign({}, args.pop()); const extraKeys = Object.keys(params).filter( (key) => !OPTIONS_KEYS.includes(key) ); - if (extraKeys.length) { const nonDeprecated = extraKeys.filter((key) => { if (!DEPRECATED_OPTIONS[key]) { @@ -179,7 +160,6 @@ const utils = (module.exports = { ); } } - if (params.apiKey) { opts.auth = params.apiKey; } @@ -205,7 +185,6 @@ const utils = (module.exports = { } return opts; }, - /** * Provide simple "Class" extension mechanism */ @@ -216,7 +195,6 @@ const utils = (module.exports = { : function(...args) { Super.apply(this, args); }; - // This initialization logic is somewhat sensitive to be compatible with // divergent JS implementations like the one found in Qt. See here for more // context: @@ -225,38 +203,31 @@ const utils = (module.exports = { Object.assign(Constructor, Super); Constructor.prototype = Object.create(Super.prototype); Object.assign(Constructor.prototype, sub); - return Constructor; }, - /** * Secure compare, from https://github.com/freewil/scmp */ secureCompare: (a, b) => { a = Buffer.from(a); b = Buffer.from(b); - // return early here if buffer lengths are not equal since timingSafeEqual // will throw if buffer lengths are not equal if (a.length !== b.length) { return false; } - // use crypto.timingSafeEqual if available (since Node.js v6.6.0), // otherwise use our own scmp-internal function. if (crypto.timingSafeEqual) { return crypto.timingSafeEqual(a, b); } - const len = a.length; let result = 0; - for (let i = 0; i < len; ++i) { result |= a[i] ^ b[i]; } return result === 0; }, - /** * Remove empty values from an object */ @@ -264,7 +235,6 @@ const utils = (module.exports = { if (typeof obj !== 'object') { throw new Error('Argument must be an object'); } - return Object.keys(obj).reduce((result, key) => { if (obj[key] != null) { result[key] = obj[key]; @@ -272,7 +242,6 @@ const utils = (module.exports = { return result; }, {}); }, - /** * Normalize standard HTTP Headers: * {'foo-bar': 'hi'} @@ -283,13 +252,11 @@ const utils = (module.exports = { if (!(obj && typeof obj === 'object')) { return obj; } - return Object.keys(obj).reduce((result, header) => { result[utils.normalizeHeader(header)] = obj[header]; return result; }, {}); }, - /** * Stolen from https://github.com/marten-de-vries/header-case-normalizer/blob/master/index.js#L36-L41 * without the exceptions which are irrelevant to us. @@ -302,7 +269,6 @@ const utils = (module.exports = { ) .join('-'); }, - /** * Determine if file data is a derivative of EventEmitter class. * https://nodejs.org/api/events.html#events_events @@ -313,7 +279,6 @@ const utils = (module.exports = { } return false; }, - callbackifyPromiseWithTimeout: (promise, callback) => { if (callback) { // Ensure callback is called outside of promise stack. @@ -330,10 +295,8 @@ const utils = (module.exports = { } ); } - return promise; }, - /** * Allow for special capitalization cases (such as OAuth) */ @@ -344,9 +307,7 @@ const utils = (module.exports = { return name[0].toLowerCase() + name.substring(1); } }, - emitWarning, - /** * Node's built in `exec` function sometimes throws outright, * and sometimes has a callback with an error, @@ -361,32 +322,25 @@ const utils = (module.exports = { cb(new Error('exec not available'), null); return; } - try { utils._exec(cmd, cb); } catch (e) { cb(e, null); } }, - // For mocking in tests. _exec: exec, - isObject: (obj) => { const type = typeof obj; return (type === 'function' || type === 'object') && !!obj; }, - // For use in multipart requests flattenAndStringify: (data) => { const result = {}; - const step = (obj, prevKey) => { Object.keys(obj).forEach((key) => { const value = obj[key]; - const newKey = prevKey ? `${prevKey}[${key}]` : key; - if (utils.isObject(value)) { if (!Buffer.isBuffer(value) && !value.hasOwnProperty('data')) { // Non-buffer non-file Objects are recursively flattened @@ -401,12 +355,9 @@ const utils = (module.exports = { } }); }; - step(data); - return result; }, - /** * https://stackoverflow.com/a/2117523 */ @@ -417,7 +368,6 @@ const utils = (module.exports = { return v.toString(16); }); }, - validateInteger: (name, n, defaultVal) => { if (!Number.isInteger(n)) { if (defaultVal !== undefined) { @@ -426,10 +376,8 @@ const utils = (module.exports = { throw new Error(`${name} must be an integer`); } } - return n; }, - determineProcessUserAgentProperties: () => { return typeof process === 'undefined' ? {} @@ -439,13 +387,11 @@ const utils = (module.exports = { }; }, }); - function emitWarning(warning) { if (typeof process.emitWarning !== 'function') { return console.warn( `Stripe: ${warning}` ); /* eslint-disable-line no-console */ } - return process.emitWarning(warning, 'Stripe'); } diff --git a/package.json b/package.json index a48dd125f7..ba4f71cf36 100644 --- a/package.json +++ b/package.json @@ -55,14 +55,18 @@ }, "license": "MIT", "scripts": { - "clean": "rm -rf ./.nyc_output ./node_modules/.cache ./coverage", + "build": "tsc -p tsconfig.json && yarn remove-exports-line && yarn prettier-format", + "remove-exports-line": "sed -i.bak '/Object.defineProperty(exports, \"__esModule\", { value: true });/d' ./lib/stripe.js; rm ./lib/stripe.js.bak", + "clean": "rm -rf ./.nyc_output ./node_modules/.cache ./coverage ./lib", + "prepack": "yarn install && yarn build", "mocha": "nyc mocha --config=test/.mocharc.js", "mocha-only": "mocha --config=test/.mocharc.js", - "test": "yarn test-typescript && yarn mocha", + "test": "yarn build && yarn test-typescript && yarn mocha", "test-typescript": "tsc --build types/test", "lint": "eslint --ext .js,.jsx,.ts .", "fix": "yarn lint --fix && ./scripts/updateAPIVersion.js", "report": "nyc -r text -r lcov report", - "coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js" - } + "coveralls": "cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js", + "prettier-format": "prettier --config .prettierrc 'lib/**/*.js' --write" +} } diff --git a/src/Error.ts b/src/Error.ts new file mode 100644 index 0000000000..c5de62ea0c --- /dev/null +++ b/src/Error.ts @@ -0,0 +1,194 @@ +type RawErrorType = + | 'card_error' + | 'invalid_request_error' + | 'api_error' + | 'idempotency_error' + | 'rate_limit_error' + | 'authentication_error' + | 'invalid_grant'; + +type StripeRawError = { + message?: string; + type?: RawErrorType; + + headers?: {[header: string]: string}; + statusCode?: number; + requestId?: string; + code?: string; + doc_url?: string; + decline_code?: string; + param?: string; + detail?: string; + charge?: string; + payment_method_type?: string; + + payment_intent?: any; + payment_method?: any; + setup_intent?: any; + source?: any; + exception?: any; +}; + +/** + * StripeError is the base error from which all other more specific Stripe errors derive. + * Specifically for errors returned from Stripe's REST API. + */ +class StripeError extends Error { + readonly message: string; + readonly type: string; + readonly raw: unknown; + readonly rawType: RawErrorType; + readonly headers: {[header: string]: string}; + readonly requestId: string; + + readonly code?: string; + readonly doc_url?: string; + readonly param?: string; + readonly detail?: string; + readonly statusCode?: number; + readonly charge?: string; + readonly decline_code?: string; + readonly payment_method_type?: string; + + readonly payment_intent?: any; + readonly payment_method?: any; + readonly setup_intent?: any; + readonly source?: any; + + constructor(raw: StripeRawError = {}) { + super(raw.message); + this.type = this.constructor.name; + + this.raw = raw; + this.rawType = raw.type; + this.code = raw.code; + this.doc_url = raw.doc_url; + this.param = raw.param; + this.detail = raw.detail; + this.headers = raw.headers; + this.requestId = raw.requestId; + this.statusCode = raw.statusCode; + this.message = raw.message; + + this.charge = raw.charge; + this.decline_code = raw.decline_code; + this.payment_intent = raw.payment_intent; + this.payment_method = raw.payment_method; + this.payment_method_type = raw.payment_method_type; + this.setup_intent = raw.setup_intent; + this.source = raw.source; + } + + /** + * Helper factory which takes raw stripe errors and outputs wrapping instances + */ + static generate(rawStripeError) { + switch (rawStripeError.type) { + case 'card_error': + return new StripeCardError(rawStripeError); + case 'invalid_request_error': + return new StripeInvalidRequestError(rawStripeError); + case 'api_error': + return new StripeAPIError(rawStripeError); + case 'authentication_error': + return new StripeAuthenticationError(rawStripeError); + case 'rate_limit_error': + return new StripeRateLimitError(rawStripeError); + case 'idempotency_error': + return new StripeIdempotencyError(rawStripeError); + case 'invalid_grant': + return new StripeInvalidGrantError(rawStripeError); + default: + return new StripeUnknownError(rawStripeError); + } + } +} + +// Specific Stripe Error types: + +/** + * CardError is raised when a user enters a card that can't be charged for + * some reason. + */ +class StripeCardError extends StripeError {} + +/** + * InvalidRequestError is raised when a request is initiated with invalid + * parameters. + */ +class StripeInvalidRequestError extends StripeError {} + +/** + * APIError is a generic error that may be raised in cases where none of the + * other named errors cover the problem. It could also be raised in the case + * that a new error has been introduced in the API, but this version of the + * Node.JS SDK doesn't know how to handle it. + */ +class StripeAPIError extends StripeError {} + +/** + * AuthenticationError is raised when invalid credentials are used to connect + * to Stripe's servers. + */ +class StripeAuthenticationError extends StripeError {} + +/** + * PermissionError is raised in cases where access was attempted on a resource + * that wasn't allowed. + */ +class StripePermissionError extends StripeError {} + +/** + * RateLimitError is raised in cases where an account is putting too much load + * on Stripe's API servers (usually by performing too many requests). Please + * back off on request rate. + */ +class StripeRateLimitError extends StripeError {} + +/** + * StripeConnectionError is raised in the event that the SDK can't connect to + * Stripe's servers. That can be for a variety of different reasons from a + * downed network to a bad TLS certificate. + */ +class StripeConnectionError extends StripeError {} + +/** + * SignatureVerificationError is raised when the signature verification for a + * webhook fails + */ +class StripeSignatureVerificationError extends StripeError {} + +/** + * IdempotencyError is raised in cases where an idempotency key was used + * improperly. + */ +class StripeIdempotencyError extends StripeError {} + +/** + * InvalidGrantError is raised when a specified code doesn't exist, is + * expired, has been used, or doesn't belong to you; a refresh token doesn't + * exist, or doesn't belong to you; or if an API key's mode (live or test) + * doesn't match the mode of a code or refresh token. + */ +class StripeInvalidGrantError extends StripeError {} + +/** + * Any other error from Stripe not specifically captured above + */ +class StripeUnknownError extends StripeError {} + +export = { + generate: StripeError.generate, + StripeError: StripeError, + StripeCardError: StripeCardError, + StripeInvalidRequestError: StripeInvalidRequestError, + StripeAPIError: StripeAPIError, + StripeAuthenticationError: StripeAuthenticationError, + StripePermissionError: StripePermissionError, + StripeRateLimitError: StripeRateLimitError, + StripeConnectionError: StripeConnectionError, + StripeSignatureVerificationError: StripeSignatureVerificationError, + StripeIdempotencyError: StripeIdempotencyError, + StripeInvalidGrantError: StripeInvalidGrantError, + StripeUnknownError: StripeUnknownError, +}; diff --git a/src/ResourceNamespace.js b/src/ResourceNamespace.js new file mode 100644 index 0000000000..0d76787d81 --- /dev/null +++ b/src/ResourceNamespace.js @@ -0,0 +1,22 @@ +'use strict'; + +// ResourceNamespace allows you to create nested resources, i.e. `stripe.issuing.cards`. +// It also works recursively, so you could do i.e. `stripe.billing.invoicing.pay`. + +function ResourceNamespace(stripe, resources) { + for (const name in resources) { + const camelCaseName = name[0].toLowerCase() + name.substring(1); + + const resource = new resources[name](stripe); + + this[camelCaseName] = resource; + } +} + +module.exports = function(namespace, resources) { + return function(stripe) { + return new ResourceNamespace(stripe, resources); + }; +}; + +module.exports.ResourceNamespace = ResourceNamespace; diff --git a/src/StripeMethod.basic.js b/src/StripeMethod.basic.js new file mode 100644 index 0000000000..b9be5302e4 --- /dev/null +++ b/src/StripeMethod.basic.js @@ -0,0 +1,32 @@ +'use strict'; + +const stripeMethod = require('./StripeMethod'); + +// DEPRECATED: These were kept for backwards compatibility in case users were +// using this, but basic methods are now explicitly defined on a resource. +module.exports = { + create: stripeMethod({ + method: 'POST', + }), + + list: stripeMethod({ + method: 'GET', + methodType: 'list', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + update: stripeMethod({ + method: 'POST', + path: '{id}', + }), + + // Avoid 'delete' keyword in JS + del: stripeMethod({ + method: 'DELETE', + path: '{id}', + }), +}; diff --git a/src/StripeMethod.ts b/src/StripeMethod.ts new file mode 100644 index 0000000000..f2c0595988 --- /dev/null +++ b/src/StripeMethod.ts @@ -0,0 +1,56 @@ +const utils = require('./utils'); +import makeRequest = require('./makeRequest'); +import autoPagination = require('./autoPagination'); +const makeAutoPaginationMethods = autoPagination.makeAutoPaginationMethods; + +/** + * Create an API method from the declared spec. + * + * @param [spec.method='GET'] Request Method (POST, GET, DELETE, PUT) + * @param [spec.path=''] Path to be appended to the API BASE_PATH, joined with + * the instance's path (e.g. 'charges' or 'customers') + * @param [spec.fullPath=''] Fully qualified path to the method (eg. /v1/a/b/c). + * If this is specified, path should not be specified. + * @param [spec.urlParams=[]] Array of required arguments in the order that they + * must be passed by the consumer of the API. Subsequent optional arguments are + * optionally passed through a hash (Object) as the penultimate argument + * (preceding the also-optional callback argument + * @param [spec.encode] Function for mutating input parameters to a method. + * Usefully for applying transforms to data on a per-method basis. + * @param [spec.host] Hostname for the request. + */ +function stripeMethod(spec) { + if (spec.path !== undefined && spec.fullPath !== undefined) { + throw new Error( + `Method spec specified both a 'path' (${spec.path}) and a 'fullPath' (${spec.fullPath}).` + ); + } + return function(...args) { + const callback = typeof args[args.length - 1] == 'function' && args.pop(); + + spec.urlParams = utils.extractUrlParams( + spec.fullPath || this.createResourcePathWithSymbols(spec.path || '') + ); + + const requestPromise = utils.callbackifyPromiseWithTimeout( + makeRequest(this, args, spec, {}), + callback + ); + + // Please note `spec.methodType === 'search'` is beta functionality and this + // interface is subject to change/removal at any time. + if (spec.methodType === 'list' || spec.methodType === 'search') { + const autoPaginationMethods = makeAutoPaginationMethods( + this, + args, + spec, + requestPromise + ); + Object.assign(requestPromise, autoPaginationMethods); + } + + return requestPromise; + }; +} + +export = stripeMethod; diff --git a/src/StripeResource.ts b/src/StripeResource.ts new file mode 100644 index 0000000000..e8f85599fe --- /dev/null +++ b/src/StripeResource.ts @@ -0,0 +1,630 @@ +import * as utils from './utils'; + +import _Error = require('./Error'); +const { + StripeAPIError, + StripeAuthenticationError, + StripeConnectionError, + StripeError, + StripePermissionError, + StripeRateLimitError, +} = _Error; + +const {HttpClient} = require('./net/HttpClient'); + +type Settings = { + timeout?: number; +}; + +type Options = { + settings?: Settings; + streaming?: boolean; + headers?: Record; +}; + +// Provide extension mechanism for Stripe Resource Sub-Classes +StripeResource.extend = utils.protoExtend; + +// Expose method-creator & prepared (basic) methods +StripeResource.method = require('./StripeMethod'); +StripeResource.BASIC_METHODS = require('./StripeMethod.basic'); + +StripeResource.MAX_BUFFERED_REQUEST_METRICS = 100; +const MAX_RETRY_AFTER_WAIT = 60; + +/** + * Encapsulates request logic for a Stripe Resource + */ +function StripeResource(stripe, deprecatedUrlData) { + this._stripe = stripe; + if (deprecatedUrlData) { + throw new Error( + 'Support for curried url params was dropped in stripe-node v7.0.0. Instead, pass two ids.' + ); + } + + this.basePath = utils.makeURLInterpolator( + this.basePath || stripe.getApiField('basePath') + ); + this.resourcePath = this.path; + this.path = utils.makeURLInterpolator(this.path); + + // DEPRECATED: This was kept for backwards compatibility in case users were + // using this, but basic methods are now explicitly defined on a resource. + if (this.includeBasic) { + this.includeBasic.forEach(function(methodName) { + this[methodName] = StripeResource.BASIC_METHODS[methodName]; + }, this); + } + + this.initialize(...arguments); +} + +StripeResource.prototype = { + path: '', + + // Methods that don't use the API's default '/v1' path can override it with this setting. + basePath: null, + + initialize() {}, + + // Function to override the default data processor. This allows full control + // over how a StripeResource's request data will get converted into an HTTP + // body. This is useful for non-standard HTTP requests. The function should + // take method name, data, and headers as arguments. + requestDataProcessor: null, + + // Function to add a validation checks before sending the request, errors should + // be thrown, and they will be passed to the callback/promise. + validateRequest: null, + + createFullPath(commandPath, urlData) { + const urlParts = [this.basePath(urlData), this.path(urlData)]; + + if (typeof commandPath === 'function') { + const computedCommandPath = commandPath(urlData); + // If we have no actual command path, we just omit it to avoid adding a + // trailing slash. This is important for top-level listing requests, which + // do not have a command path. + if (computedCommandPath) { + urlParts.push(computedCommandPath); + } + } else { + urlParts.push(commandPath); + } + + return this._joinUrlParts(urlParts); + }, + + // Creates a relative resource path with symbols left in (unlike + // createFullPath which takes some data to replace them with). For example it + // might produce: /invoices/{id} + createResourcePathWithSymbols(pathWithSymbols) { + // If there is no path beyond the resource path, we want to produce just + // / rather than //. + if (pathWithSymbols) { + return `/${this._joinUrlParts([this.resourcePath, pathWithSymbols])}`; + } else { + return `/${this.resourcePath}`; + } + }, + + _joinUrlParts(parts) { + // Replace any accidentally doubled up slashes. This previously used + // path.join, which would do this as well. Unfortunately we need to do this + // as the functions for creating paths are technically part of the public + // interface and so we need to preserve backwards compatibility. + return parts.join('/').replace(/\/{2,}/g, '/'); + }, + + // DEPRECATED: Here for backcompat in case users relied on this. + wrapTimeout: utils.callbackifyPromiseWithTimeout, + + _timeoutHandler(timeout, req, callback) { + return () => { + const timeoutErr = new TypeError('ETIMEDOUT'); + (timeoutErr as any).code = 'ETIMEDOUT'; + + req.destroy(timeoutErr); + }; + }, + + _addHeadersDirectlyToObject(obj, headers) { + // For convenience, make some headers easily accessible on + // lastResponse. + + // NOTE: Stripe responds with lowercase header names/keys. + obj.requestId = headers['request-id']; + obj.stripeAccount = obj.stripeAccount || headers['stripe-account']; + obj.apiVersion = obj.apiVersion || headers['stripe-version']; + obj.idempotencyKey = obj.idempotencyKey || headers['idempotency-key']; + }, + + _makeResponseEvent(requestEvent, statusCode, headers) { + const requestEndTime = Date.now(); + const requestDurationMs = requestEndTime - requestEvent.request_start_time; + + return utils.removeNullish({ + api_version: headers['stripe-version'], + account: headers['stripe-account'], + idempotency_key: headers['idempotency-key'], + method: requestEvent.method, + path: requestEvent.path, + status: statusCode, + request_id: this._getRequestId(headers), + elapsed: requestDurationMs, + request_start_time: requestEvent.request_start_time, + request_end_time: requestEndTime, + }); + }, + + _getRequestId(headers) { + return headers['request-id']; + }, + + /** + * Used by methods with spec.streaming === true. For these methods, we do not + * buffer successful responses into memory or do parse them into stripe + * objects, we delegate that all of that to the user and pass back the raw + * http.Response object to the callback. + * + * (Unsuccessful responses shouldn't make it here, they should + * still be buffered/parsed and handled by _jsonResponseHandler -- see + * makeRequest) + */ + _streamingResponseHandler(requestEvent, callback) { + return (res) => { + const headers = res.getHeaders(); + + const streamCompleteCallback = () => { + const responseEvent = this._makeResponseEvent( + requestEvent, + res.getStatusCode(), + headers + ); + this._stripe._emitter.emit('response', responseEvent); + this._recordRequestMetrics( + this._getRequestId(headers), + responseEvent.elapsed + ); + }; + + const stream = res.toStream(streamCompleteCallback); + + // This is here for backwards compatibility, as the stream is a raw + // HTTP response in Node and the legacy behavior was to mutate this + // response. + this._addHeadersDirectlyToObject(stream, headers); + + return callback(null, stream); + }; + }, + + /** + * Default handler for Stripe responses. Buffers the response into memory, + * parses the JSON and returns it (i.e. passes it to the callback) if there + * is no "error" field. Otherwise constructs/passes an appropriate Error. + */ + _jsonResponseHandler(requestEvent, callback) { + return (res) => { + const headers = res.getHeaders(); + const requestId = this._getRequestId(headers); + const statusCode = res.getStatusCode(); + + const responseEvent = this._makeResponseEvent( + requestEvent, + statusCode, + headers + ); + this._stripe._emitter.emit('response', responseEvent); + + res + .toJSON() + .then( + (jsonResponse) => { + if (jsonResponse.error) { + let err; + + // Convert OAuth error responses into a standard format + // so that the rest of the error logic can be shared + if (typeof jsonResponse.error === 'string') { + jsonResponse.error = { + type: jsonResponse.error, + message: jsonResponse.error_description, + }; + } + + jsonResponse.error.headers = headers; + jsonResponse.error.statusCode = statusCode; + jsonResponse.error.requestId = requestId; + + if (statusCode === 401) { + err = new StripeAuthenticationError(jsonResponse.error); + } else if (statusCode === 403) { + err = new StripePermissionError(jsonResponse.error); + } else if (statusCode === 429) { + err = new StripeRateLimitError(jsonResponse.error); + } else { + err = StripeError.generate(jsonResponse.error); + } + + throw err; + } + + return jsonResponse; + }, + (e) => { + throw new StripeAPIError({ + message: 'Invalid JSON received from the Stripe API', + exception: e, + requestId: headers['request-id'], + }); + } + ) + .then( + (jsonResponse) => { + this._recordRequestMetrics(requestId, responseEvent.elapsed); + + // Expose raw response object. + const rawResponse = res.getRawResponse(); + this._addHeadersDirectlyToObject(rawResponse, headers); + Object.defineProperty(jsonResponse, 'lastResponse', { + enumerable: false, + writable: false, + value: rawResponse, + }); + + callback.call(this, null, jsonResponse); + }, + (e) => callback.call(this, e, null) + ); + }; + }, + + _generateConnectionErrorMessage(requestRetries) { + return `An error occurred with our connection to Stripe.${ + requestRetries > 0 ? ` Request was retried ${requestRetries} times.` : '' + }`; + }, + + _errorHandler(req, 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 ( + error && + numRetries === 0 && + HttpClient.CONNECTION_CLOSED_ERROR_CODES.includes(error.code) + ) { + return true; + } + + // Do not retry if we are out of retries. + if (numRetries >= maxRetries) { + return false; + } + + // Retry on connection error. + if (!res) { + return true; + } + + // The API may ask us not to retry (e.g., if doing so would be a no-op) + // or advise us to retry (e.g., in cases of lock timeouts); we defer to that. + if (res.getHeaders()['stripe-should-retry'] === 'false') { + return false; + } + if (res.getHeaders()['stripe-should-retry'] === 'true') { + return true; + } + + // Retry on conflict errors. + if (res.getStatusCode() === 409) { + return true; + } + + // Retry on 500, 503, and other internal errors. + // + // Note that we expect the stripe-should-retry header to be false + // in most cases when a 500 is returned, since our idempotency framework + // would typically replay it anyway. + if (res.getStatusCode() >= 500) { + return true; + } + + return false; + }, + + _getSleepTimeInMS(numRetries, retryAfter = null) { + const initialNetworkRetryDelay = this._stripe.getInitialNetworkRetryDelay(); + const maxNetworkRetryDelay = this._stripe.getMaxNetworkRetryDelay(); + + // Apply exponential backoff with initialNetworkRetryDelay on the + // number of numRetries so far as inputs. Do not allow the number to exceed + // maxNetworkRetryDelay. + let sleepSeconds = Math.min( + initialNetworkRetryDelay * Math.pow(numRetries - 1, 2), + maxNetworkRetryDelay + ); + + // Apply some jitter by randomizing the value in the range of + // (sleepSeconds / 2) to (sleepSeconds). + sleepSeconds *= 0.5 * (1 + Math.random()); + + // But never sleep less than the base sleep seconds. + sleepSeconds = Math.max(initialNetworkRetryDelay, sleepSeconds); + + // And never sleep less than the time the API asks us to wait, assuming it's a reasonable ask. + if (Number.isInteger(retryAfter) && retryAfter <= MAX_RETRY_AFTER_WAIT) { + sleepSeconds = Math.max(sleepSeconds, retryAfter); + } + + return sleepSeconds * 1000; + }, + + // Max retries can be set on a per request basis. Favor those over the global setting + _getMaxNetworkRetries(settings: {maxNetworkRetries?: number} = {}) { + return settings.maxNetworkRetries && + Number.isInteger(settings.maxNetworkRetries) + ? settings.maxNetworkRetries + : this._stripe.getMaxNetworkRetries(); + }, + + _defaultIdempotencyKey(method, settings) { + // If this is a POST and we allow multiple retries, ensure an idempotency key. + const maxRetries = this._getMaxNetworkRetries(settings); + + if (method === 'POST' && maxRetries > 0) { + return `stripe-node-retry-${utils.uuid4()}`; + } + return null; + }, + + _makeHeaders( + auth, + contentLength, + apiVersion, + clientUserAgent, + method, + userSuppliedHeaders, + userSuppliedSettings + ) { + const defaultHeaders = { + // Use specified auth token or use default from this stripe instance: + Authorization: auth ? `Bearer ${auth}` : this._stripe.getApiField('auth'), + Accept: 'application/json', + 'Content-Type': 'application/x-www-form-urlencoded', + 'User-Agent': this._getUserAgentString(), + 'X-Stripe-Client-User-Agent': clientUserAgent, + 'X-Stripe-Client-Telemetry': this._getTelemetryHeader(), + 'Stripe-Version': apiVersion, + 'Stripe-Account': this._stripe.getApiField('stripeAccount'), + 'Idempotency-Key': this._defaultIdempotencyKey( + method, + userSuppliedSettings + ), + }; + + // As per https://datatracker.ietf.org/doc/html/rfc7230#section-3.3.2: + // A user agent SHOULD send a Content-Length in a request message when + // no Transfer-Encoding is sent and the request method defines a meaning + // for an enclosed payload body. For example, a Content-Length header + // field is normally sent in a POST request even when the value is 0 + // (indicating an empty payload body). A user agent SHOULD NOT send a + // Content-Length header field when the request message does not contain + // a payload body and the method semantics do not anticipate such a + // body. + // + // These method types are expected to have bodies and so we should always + // include a Content-Length. + const methodHasPayload = + method == 'POST' || method == 'PUT' || method == 'PATCH'; + + // If a content length was specified, we always include it regardless of + // whether the method semantics anticipate such a body. This keeps us + // consistent with historical behavior. We do however want to warn on this + // and fix these cases as they are semantically incorrect. + if (methodHasPayload || contentLength) { + if (!methodHasPayload) { + utils.emitWarning( + `${method} method had non-zero contentLength but no payload is expected for this verb` + ); + } + defaultHeaders['Content-Length'] = contentLength; + } + + return Object.assign( + utils.removeNullish(defaultHeaders), + // If the user supplied, say 'idempotency-key', override instead of appending by ensuring caps are the same. + utils.normalizeHeaders(userSuppliedHeaders) + ); + }, + + _getUserAgentString() { + const packageVersion = this._stripe.getConstant('PACKAGE_VERSION'); + const appInfo = this._stripe._appInfo + ? this._stripe.getAppInfoAsString() + : ''; + + return `Stripe/v1 NodeBindings/${packageVersion} ${appInfo}`.trim(); + }, + + _getTelemetryHeader() { + if ( + this._stripe.getTelemetryEnabled() && + this._stripe._prevRequestMetrics.length > 0 + ) { + const metrics = this._stripe._prevRequestMetrics.shift(); + return JSON.stringify({ + last_request_metrics: metrics, + }); + } + }, + + _recordRequestMetrics(requestId, requestDurationMs) { + if (this._stripe.getTelemetryEnabled() && requestId) { + if ( + this._stripe._prevRequestMetrics.length > + StripeResource.MAX_BUFFERED_REQUEST_METRICS + ) { + utils.emitWarning( + 'Request metrics buffer is full, dropping telemetry message.' + ); + } else { + this._stripe._prevRequestMetrics.push({ + request_id: requestId, + request_duration_ms: requestDurationMs, + }); + } + } + }, + + _request(method, host, path, data, auth, options: Options = {}, callback) { + let requestData; + + const retryRequest = ( + requestFn, + apiVersion, + headers, + requestRetries, + retryAfter + ) => { + return setTimeout( + requestFn, + this._getSleepTimeInMS(requestRetries, retryAfter), + apiVersion, + headers, + requestRetries + 1 + ); + }; + + const makeRequest = (apiVersion, headers, numRetries) => { + // timeout can be set on a per-request basis. Favor that over the global setting + const timeout = + options.settings && + options.settings.timeout && + Number.isInteger(options.settings.timeout) && + options.settings.timeout >= 0 + ? options.settings.timeout + : this._stripe.getApiField('timeout'); + + const req = this._stripe + .getApiField('httpClient') + .makeRequest( + host || this._stripe.getApiField('host'), + this._stripe.getApiField('port'), + path, + method, + headers, + requestData, + this._stripe.getApiField('protocol'), + timeout + ); + + const requestStartTime = Date.now(); + + const requestEvent = utils.removeNullish({ + api_version: apiVersion, + account: headers['Stripe-Account'], + idempotency_key: headers['Idempotency-Key'], + method, + path, + request_start_time: requestStartTime, + }); + + const requestRetries = numRetries || 0; + + const maxRetries = this._getMaxNetworkRetries(options.settings); + + this._stripe._emitter.emit('request', requestEvent); + + req + .then((res) => { + if (this._shouldRetry(res, requestRetries, maxRetries)) { + return retryRequest( + makeRequest, + apiVersion, + headers, + requestRetries, + res.getHeaders()['retry-after'] + ); + } else if (options.streaming && res.getStatusCode() < 400) { + return this._streamingResponseHandler(requestEvent, callback)(res); + } else { + return this._jsonResponseHandler(requestEvent, callback)(res); + } + }) + .catch((error) => { + if (this._shouldRetry(null, requestRetries, maxRetries, error)) { + return retryRequest( + makeRequest, + apiVersion, + headers, + requestRetries, + null + ); + } else { + const isTimeoutError = + error.code && error.code === HttpClient.TIMEOUT_ERROR_CODE; + + return callback.call( + this, + new StripeConnectionError({ + message: isTimeoutError + ? `Request aborted due to timeout being reached (${timeout}ms)` + : this._generateConnectionErrorMessage(requestRetries), + detail: error, + }) + ); + } + }); + }; + + const prepareAndMakeRequest = (error, data) => { + if (error) { + return callback(error); + } + + requestData = data; + + this._stripe.getClientUserAgent((clientUserAgent) => { + const apiVersion = this._stripe.getApiField('version'); + const headers = this._makeHeaders( + auth, + requestData.length, + apiVersion, + clientUserAgent, + method, + options.headers, + options.settings + ); + + makeRequest(apiVersion, headers, 0); + }); + }; + + if (this.requestDataProcessor) { + this.requestDataProcessor( + method, + data, + options.headers, + prepareAndMakeRequest + ); + } else { + prepareAndMakeRequest(null, utils.stringifyRequestData(data || {})); + } + }, +}; + +export = StripeResource; diff --git a/src/Webhooks.js b/src/Webhooks.js new file mode 100644 index 0000000000..ffbe2004a9 --- /dev/null +++ b/src/Webhooks.js @@ -0,0 +1,277 @@ +'use strict'; + +const utils = require('./utils'); +const {StripeError, StripeSignatureVerificationError} = require('./Error'); + +const Webhook = { + DEFAULT_TOLERANCE: 300, // 5 minutes + + constructEvent(payload, header, secret, tolerance, cryptoProvider) { + this.signature.verifyHeader( + payload, + header, + secret, + tolerance || Webhook.DEFAULT_TOLERANCE, + cryptoProvider + ); + + const jsonPayload = JSON.parse(payload); + return jsonPayload; + }, + + async constructEventAsync( + payload, + header, + secret, + tolerance, + cryptoProvider + ) { + await this.signature.verifyHeaderAsync( + payload, + header, + secret, + tolerance || Webhook.DEFAULT_TOLERANCE, + cryptoProvider + ); + + const jsonPayload = JSON.parse(payload); + return jsonPayload; + }, + + /** + * Generates a header to be used for webhook mocking + * + * @typedef {object} opts + * @property {number} timestamp - Timestamp of the header. Defaults to Date.now() + * @property {string} payload - JSON stringified payload object, containing the 'id' and 'object' parameters + * @property {string} secret - Stripe webhook secret 'whsec_...' + * @property {string} scheme - Version of API to hit. Defaults to 'v1'. + * @property {string} signature - Computed webhook signature + * @property {CryptoProvider} cryptoProvider - Crypto provider to use for computing the signature if none was provided. Defaults to NodeCryptoProvider. + */ + generateTestHeaderString: function(opts) { + if (!opts) { + throw new StripeError({ + message: 'Options are required', + }); + } + + opts.timestamp = + Math.floor(opts.timestamp) || Math.floor(Date.now() / 1000); + opts.scheme = opts.scheme || signature.EXPECTED_SCHEME; + + opts.cryptoProvider = opts.cryptoProvider || getNodeCryptoProvider(); + + opts.signature = + opts.signature || + opts.cryptoProvider.computeHMACSignature( + opts.timestamp + '.' + opts.payload, + opts.secret + ); + + const generatedHeader = [ + 't=' + opts.timestamp, + opts.scheme + '=' + opts.signature, + ].join(','); + + return generatedHeader; + }, +}; + +const signature = { + EXPECTED_SCHEME: 'v1', + + verifyHeader( + encodedPayload, + encodedHeader, + secret, + tolerance, + cryptoProvider + ) { + const { + decodedHeader: header, + decodedPayload: payload, + details, + } = parseEventDetails(encodedPayload, encodedHeader, this.EXPECTED_SCHEME); + + cryptoProvider = cryptoProvider || getNodeCryptoProvider(); + const expectedSignature = cryptoProvider.computeHMACSignature( + makeHMACContent(payload, details), + secret + ); + + validateComputedSignature( + payload, + header, + details, + expectedSignature, + tolerance + ); + + return true; + }, + + async verifyHeaderAsync( + encodedPayload, + encodedHeader, + secret, + tolerance, + cryptoProvider + ) { + const { + decodedHeader: header, + decodedPayload: payload, + details, + } = parseEventDetails(encodedPayload, encodedHeader, this.EXPECTED_SCHEME); + + cryptoProvider = cryptoProvider || getNodeCryptoProvider(); + + const expectedSignature = await cryptoProvider.computeHMACSignatureAsync( + makeHMACContent(payload, details), + secret + ); + + return validateComputedSignature( + payload, + header, + details, + expectedSignature, + tolerance + ); + }, +}; + +function makeHMACContent(payload, details) { + return `${details.timestamp}.${payload}`; +} + +function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) { + const decodedPayload = Buffer.isBuffer(encodedPayload) + ? encodedPayload.toString('utf8') + : encodedPayload; + + // Express's type for `Request#headers` is `string | []string` + // which is because the `set-cookie` header is an array, + // but no other headers are an array (docs: https://nodejs.org/api/http.html#http_message_headers) + // (Express's Request class is an extension of http.IncomingMessage, and doesn't appear to be relevantly modified: https://github.com/expressjs/express/blob/master/lib/request.js#L31) + if (Array.isArray(encodedHeader)) { + throw new Error( + 'Unexpected: An array was passed as a header, which should not be possible for the stripe-signature header.' + ); + } + + const decodedHeader = Buffer.isBuffer(encodedHeader) + ? encodedHeader.toString('utf8') + : encodedHeader; + + const details = parseHeader(decodedHeader, expectedScheme); + + if (!details || details.timestamp === -1) { + throw new StripeSignatureVerificationError({ + message: 'Unable to extract timestamp and signatures from header', + detail: { + decodedHeader, + decodedPayload, + }, + }); + } + + if (!details.signatures.length) { + throw new StripeSignatureVerificationError({ + message: 'No signatures found with expected scheme', + detail: { + decodedHeader, + decodedPayload, + }, + }); + } + + return { + decodedPayload, + decodedHeader, + details, + }; +} + +function validateComputedSignature( + payload, + header, + details, + expectedSignature, + tolerance +) { + const signatureFound = !!details.signatures.filter( + utils.secureCompare.bind(utils, expectedSignature) + ).length; + + if (!signatureFound) { + throw new StripeSignatureVerificationError({ + message: + 'No signatures found matching the expected signature for payload.' + + ' Are you passing the raw request body you received from Stripe?' + + ' https://github.com/stripe/stripe-node#webhook-signing', + detail: { + header, + payload, + }, + }); + } + + const timestampAge = Math.floor(Date.now() / 1000) - details.timestamp; + + if (tolerance > 0 && timestampAge > tolerance) { + throw new StripeSignatureVerificationError({ + message: 'Timestamp outside the tolerance zone', + detail: { + header, + payload, + }, + }); + } + + return true; +} + +function parseHeader(header, scheme) { + if (typeof header !== 'string') { + return null; + } + + return header.split(',').reduce( + (accum, item) => { + const kv = item.split('='); + + if (kv[0] === 't') { + accum.timestamp = kv[1]; + } + + if (kv[0] === scheme) { + accum.signatures.push(kv[1]); + } + + return accum; + }, + { + timestamp: -1, + signatures: [], + } + ); +} + +let webhooksNodeCryptoProviderInstance = null; + +/** + * Lazily instantiate a NodeCryptoProvider instance. This is a stateless object + * so a singleton can be used here. + */ +function getNodeCryptoProvider() { + if (!webhooksNodeCryptoProviderInstance) { + const NodeCryptoProvider = require('./crypto/NodeCryptoProvider'); + webhooksNodeCryptoProviderInstance = new NodeCryptoProvider(); + } + return webhooksNodeCryptoProviderInstance; +} + +Webhook.signature = signature; + +module.exports = Webhook; diff --git a/src/apiVersion.js b/src/apiVersion.js new file mode 100644 index 0000000000..704a3619eb --- /dev/null +++ b/src/apiVersion.js @@ -0,0 +1,3 @@ +// File generated from our OpenAPI spec + +module.exports = {ApiVersion: '2022-08-01'}; diff --git a/src/autoPagination.ts b/src/autoPagination.ts new file mode 100644 index 0000000000..b98f44d122 --- /dev/null +++ b/src/autoPagination.ts @@ -0,0 +1,278 @@ +import makeRequest = require('./makeRequest'); +const utils = require('./utils'); + +function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) { + const promiseCache = {currentPromise: null}; + const reverseIteration = isReverseIteration(requestArgs); + let pagePromise = firstPagePromise; + let i = 0; + + // Search and List methods iterate differently. + // Search relies on a `next_page` token and can only iterate in one direction. + // List relies on either an `ending_before` or `starting_after` field with + // an item ID to paginate and is bi-directional. + // + // Please note: spec.methodType === 'search' is beta functionality and is + // subject to change/removal at any time. + let getNextPagePromise; + if (spec.methodType === 'search') { + getNextPagePromise = (pageResult) => { + if (!pageResult.next_page) { + throw Error( + 'Unexpected: Stripe API response does not have a well-formed `next_page` field, but `has_more` was true.' + ); + } + return makeRequest(self, requestArgs, spec, { + page: pageResult.next_page, + }); + }; + } else { + getNextPagePromise = (pageResult) => { + const lastId = getLastId(pageResult, reverseIteration); + return makeRequest(self, requestArgs, spec, { + [reverseIteration ? 'ending_before' : 'starting_after']: lastId, + }); + }; + } + + function iterate(pageResult) { + if ( + !( + pageResult && + pageResult.data && + typeof pageResult.data.length === 'number' + ) + ) { + throw Error( + 'Unexpected: Stripe API response does not have a well-formed `data` array.' + ); + } + + if (i < pageResult.data.length) { + const idx = reverseIteration ? pageResult.data.length - 1 - i : i; + const value = pageResult.data[idx]; + i += 1; + + return {value, done: false}; + } else if (pageResult.has_more) { + // Reset counter, request next page, and recurse. + i = 0; + pagePromise = getNextPagePromise(pageResult); + return pagePromise.then(iterate); + } + return {value: undefined, done: true}; + } + + function asyncIteratorNext() { + return memoizedPromise(promiseCache, (resolve, reject) => { + return pagePromise + .then(iterate) + .then(resolve) + .catch(reject); + }); + } + + const autoPagingEach = makeAutoPagingEach(asyncIteratorNext); + const autoPagingToArray = makeAutoPagingToArray(autoPagingEach); + + const autoPaginationMethods = { + autoPagingEach, + autoPagingToArray, + + // Async iterator functions: + next: asyncIteratorNext, + return: () => { + // This is required for `break`. + return {}; + }, + [getAsyncIteratorSymbol()]: () => { + return autoPaginationMethods; + }, + }; + return autoPaginationMethods; +} + +export = { + makeAutoPaginationMethods: makeAutoPaginationMethods, +}; + +/** + * ---------------- + * Private Helpers: + * ---------------- + */ + +function getAsyncIteratorSymbol() { + if (typeof Symbol !== 'undefined' && Symbol.asyncIterator) { + return Symbol.asyncIterator; + } + // Follow the convention from libraries like iterall: https://github.com/leebyron/iterall#asynciterator-1 + return '@@asyncIterator'; +} + +function getDoneCallback(args) { + if (args.length < 2) { + return undefined; + } + const onDone = args[1]; + if (typeof onDone !== 'function') { + throw Error( + `The second argument to autoPagingEach, if present, must be a callback function; received ${typeof onDone}` + ); + } + return onDone; +} + +/** + * We allow four forms of the `onItem` callback (the middle two being equivalent), + * + * 1. `.autoPagingEach((item) => { doSomething(item); return false; });` + * 2. `.autoPagingEach(async (item) => { await doSomething(item); return false; });` + * 3. `.autoPagingEach((item) => doSomething(item).then(() => false));` + * 4. `.autoPagingEach((item, next) => { doSomething(item); next(false); });` + * + * In addition to standard validation, this helper + * coalesces the former forms into the latter form. + */ +function getItemCallback(args) { + if (args.length === 0) { + return undefined; + } + const onItem = args[0]; + if (typeof onItem !== 'function') { + throw Error( + `The first argument to autoPagingEach, if present, must be a callback function; received ${typeof onItem}` + ); + } + + // 4. `.autoPagingEach((item, next) => { doSomething(item); next(false); });` + if (onItem.length === 2) { + return onItem; + } + + if (onItem.length > 2) { + throw Error( + `The \`onItem\` callback function passed to autoPagingEach must accept at most two arguments; got ${onItem}` + ); + } + + // This magically handles all three of these usecases (the latter two being functionally identical): + // 1. `.autoPagingEach((item) => { doSomething(item); return false; });` + // 2. `.autoPagingEach(async (item) => { await doSomething(item); return false; });` + // 3. `.autoPagingEach((item) => doSomething(item).then(() => false));` + return function _onItem(item, next) { + const shouldContinue = onItem(item); + next(shouldContinue); + }; +} + +function getLastId(listResult, reverseIteration) { + const lastIdx = reverseIteration ? 0 : listResult.data.length - 1; + const lastItem = listResult.data[lastIdx]; + const lastId = lastItem && lastItem.id; + if (!lastId) { + throw Error( + 'Unexpected: No `id` found on the last item while auto-paging a list.' + ); + } + return lastId; +} + +/** + * If a user calls `.next()` multiple times in parallel, + * return the same result until something has resolved + * to prevent page-turning race conditions. + */ +function memoizedPromise(promiseCache, cb) { + if (promiseCache.currentPromise) { + return promiseCache.currentPromise; + } + promiseCache.currentPromise = new Promise(cb).then((ret) => { + promiseCache.currentPromise = undefined; + return ret; + }); + return promiseCache.currentPromise; +} + +function makeAutoPagingEach(asyncIteratorNext) { + return function autoPagingEach(/* onItem?, onDone? */) { + const args = [].slice.call(arguments); + const onItem = getItemCallback(args); + const onDone = getDoneCallback(args); + if (args.length > 2) { + throw Error(`autoPagingEach takes up to two arguments; received ${args}`); + } + + const autoPagePromise = wrapAsyncIteratorWithCallback( + asyncIteratorNext, + onItem + ); + return utils.callbackifyPromiseWithTimeout(autoPagePromise, onDone); + }; +} + +function makeAutoPagingToArray(autoPagingEach) { + return function autoPagingToArray(opts, onDone) { + const limit = opts && opts.limit; + if (!limit) { + throw Error( + 'You must pass a `limit` option to autoPagingToArray, e.g., `autoPagingToArray({limit: 1000});`.' + ); + } + if (limit > 10000) { + throw Error( + 'You cannot specify a limit of more than 10,000 items to fetch in `autoPagingToArray`; use `autoPagingEach` to iterate through longer lists.' + ); + } + const promise = new Promise((resolve, reject) => { + const items = []; + autoPagingEach((item) => { + items.push(item); + if (items.length >= limit) { + return false; + } + }) + .then(() => { + resolve(items); + }) + .catch(reject); + }); + return utils.callbackifyPromiseWithTimeout(promise, onDone); + }; +} + +function wrapAsyncIteratorWithCallback(asyncIteratorNext, onItem) { + return new Promise((resolve, reject) => { + function handleIteration(iterResult) { + if (iterResult.done) { + resolve(); + return; + } + + const item = iterResult.value; + return new Promise((next) => { + // Bit confusing, perhaps; we pass a `resolve` fn + // to the user, so they can decide when and if to continue. + // They can return false, or a promise which resolves to false, to break. + onItem(item, next); + }).then((shouldContinue) => { + if (shouldContinue === false) { + return handleIteration({done: true}); + } else { + return asyncIteratorNext().then(handleIteration); + } + }); + } + + asyncIteratorNext() + .then(handleIteration) + .catch(reject); + }); +} + +function isReverseIteration(requestArgs) { + const args = [].slice.call(requestArgs); + const dataFromArgs = utils.getDataFromArgs(args); + + return !!dataFromArgs.ending_before; +} diff --git a/src/crypto/CryptoProvider.js b/src/crypto/CryptoProvider.js new file mode 100644 index 0000000000..8f038d06ca --- /dev/null +++ b/src/crypto/CryptoProvider.js @@ -0,0 +1,36 @@ +'use strict'; + +/** + * Interface encapsulating the various crypto computations used by the library, + * allowing pluggable underlying crypto implementations. + */ +class CryptoProvider { + /** + * Computes a SHA-256 HMAC given a secret and a payload (encoded in UTF-8). + * The output HMAC should be encoded in hexadecimal. + * + * Sample values for implementations: + * - computeHMACSignature('', 'test_secret') => 'f7f9bd47fb987337b5796fdc1fdb9ba221d0d5396814bfcaf9521f43fd8927fd' + * - computeHMACSignature('\ud83d\ude00', 'test_secret') => '837da296d05c4fe31f61d5d7ead035099d9585a5bcde87de952012a78f0b0c43 + */ + computeHMACSignature(payload, secret) { + throw new Error('computeHMACSignature not implemented.'); + } + + /** + * Asynchronous version of `computeHMACSignature`. Some implementations may + * only allow support async signature computation. + * + * Computes a SHA-256 HMAC given a secret and a payload (encoded in UTF-8). + * The output HMAC should be encoded in hexadecimal. + * + * Sample values for implementations: + * - computeHMACSignature('', 'test_secret') => 'f7f9bd47fb987337b5796fdc1fdb9ba221d0d5396814bfcaf9521f43fd8927fd' + * - computeHMACSignature('\ud83d\ude00', 'test_secret') => '837da296d05c4fe31f61d5d7ead035099d9585a5bcde87de952012a78f0b0c43 + */ + computeHMACSignatureAsync(payload, secret) { + throw new Error('computeHMACSignatureAsync not implemented.'); + } +} + +module.exports = CryptoProvider; diff --git a/src/crypto/NodeCryptoProvider.js b/src/crypto/NodeCryptoProvider.js new file mode 100644 index 0000000000..83c2037ea2 --- /dev/null +++ b/src/crypto/NodeCryptoProvider.js @@ -0,0 +1,26 @@ +'use strict'; + +const crypto = require('crypto'); + +const CryptoProvider = require('./CryptoProvider'); + +/** + * `CryptoProvider which uses the Node `crypto` package for its computations. + */ +class NodeCryptoProvider extends CryptoProvider { + /** @override */ + computeHMACSignature(payload, secret) { + return crypto + .createHmac('sha256', secret) + .update(payload, 'utf8') + .digest('hex'); + } + + /** @override */ + async computeHMACSignatureAsync(payload, secret) { + const signature = await this.computeHMACSignature(payload, secret); + return signature; + } +} + +module.exports = NodeCryptoProvider; diff --git a/src/crypto/SubtleCryptoProvider.js b/src/crypto/SubtleCryptoProvider.js new file mode 100644 index 0000000000..45aa40dd46 --- /dev/null +++ b/src/crypto/SubtleCryptoProvider.js @@ -0,0 +1,69 @@ +'use strict'; + +const CryptoProvider = require('./CryptoProvider'); + +/** + * `CryptoProvider which uses the SubtleCrypto interface of the Web Crypto API. + * + * This only supports asynchronous operations. + */ +class SubtleCryptoProvider extends CryptoProvider { + constructor(subtleCrypto) { + super(); + + // If no subtle crypto is interface, default to the global namespace. This + // is to allow custom interfaces (eg. using the Node webcrypto interface in + // tests). + this.subtleCrypto = subtleCrypto || crypto.subtle; + } + + /** @override */ + computeHMACSignature(payload, secret) { + throw new Error( + 'SubtleCryptoProvider cannot be used in a synchronous context.' + ); + } + + /** @override */ + async computeHMACSignatureAsync(payload, secret) { + const encoder = new TextEncoder('utf-8'); + + const key = await this.subtleCrypto.importKey( + 'raw', + encoder.encode(secret), + { + name: 'HMAC', + hash: {name: 'SHA-256'}, + }, + false, + ['sign'] + ); + + const signatureBuffer = await this.subtleCrypto.sign( + 'hmac', + key, + encoder.encode(payload) + ); + + // crypto.subtle returns the signature in base64 format. This must be + // encoded in hex to match the CryptoProvider contract. We map each byte in + // the buffer to its corresponding hex octet and then combine into a string. + const signatureBytes = new Uint8Array(signatureBuffer); + const signatureHexCodes = new Array(signatureBytes.length); + + for (let i = 0; i < signatureBytes.length; i++) { + signatureHexCodes[i] = byteHexMapping[signatureBytes[i]]; + } + + return signatureHexCodes.join(''); + } +} + +// Cached mapping of byte to hex representation. We do this once to avoid re- +// computing every time we need to convert the result of a signature to hex. +const byteHexMapping = new Array(256); +for (let i = 0; i < byteHexMapping.length; i++) { + byteHexMapping[i] = i.toString(16).padStart(2, '0'); +} + +module.exports = SubtleCryptoProvider; diff --git a/src/makeRequest.ts b/src/makeRequest.ts new file mode 100644 index 0000000000..57737cfd25 --- /dev/null +++ b/src/makeRequest.ts @@ -0,0 +1,120 @@ +const utils = require('./utils'); + +function getRequestOpts(self, requestArgs, spec, overrideData) { + // Extract spec values with defaults. + const requestMethod = (spec.method || 'GET').toUpperCase(); + const urlParams = spec.urlParams || []; + const encode = spec.encode || ((data) => data); + + const isUsingFullPath = !!spec.fullPath; + const commandPath = utils.makeURLInterpolator( + isUsingFullPath ? spec.fullPath : spec.path || '' + ); + // When using fullPath, we ignore the resource path as it should already be + // fully qualified. + const path = isUsingFullPath + ? spec.fullPath + : self.createResourcePathWithSymbols(spec.path); + + // Don't mutate args externally. + const args = [].slice.call(requestArgs); + + // Generate and validate url params. + const urlData = urlParams.reduce((urlData, param) => { + const arg = args.shift(); + if (typeof arg !== 'string') { + throw new Error( + `Stripe: Argument "${param}" must be a string, but got: ${arg} (on API request to \`${requestMethod} ${path}\`)` + ); + } + + urlData[param] = arg; + return urlData; + }, {}); + + // Pull request data and options (headers, auth) from args. + const dataFromArgs = utils.getDataFromArgs(args); + const data = encode(Object.assign({}, dataFromArgs, overrideData)); + const options = utils.getOptionsFromArgs(args); + const host = options.host || spec.host; + const streaming = !!spec.streaming; + // Validate that there are no more args. + if (args.filter((x) => x != null).length) { + throw new Error( + `Stripe: Unknown arguments (${args}). Did you mean to pass an options object? See https://github.com/stripe/stripe-node/wiki/Passing-Options. (on API request to ${requestMethod} \`${path}\`)` + ); + } + + // When using full path, we can just invoke the URL interpolator directly + // as we don't need to use the resource to create a full path. + const requestPath = isUsingFullPath + ? commandPath(urlData) + : self.createFullPath(commandPath, urlData); + + const headers = Object.assign(options.headers, spec.headers); + + if (spec.validator) { + spec.validator(data, {headers}); + } + + const dataInQuery = spec.method === 'GET' || spec.method === 'DELETE'; + const bodyData = dataInQuery ? {} : data; + const queryData = dataInQuery ? data : {}; + + return { + requestMethod, + requestPath, + bodyData, + queryData, + auth: options.auth, + headers, + host, + streaming, + settings: options.settings, + }; +} + +function makeRequest(self, requestArgs, spec, overrideData) { + return new Promise((resolve, reject) => { + let opts; + try { + opts = getRequestOpts(self, requestArgs, spec, overrideData); + } catch (err) { + reject(err); + return; + } + + function requestCallback(err, response) { + if (err) { + reject(err); + } else { + resolve( + spec.transformResponseData + ? spec.transformResponseData(response) + : response + ); + } + } + + const emptyQuery = Object.keys(opts.queryData).length === 0; + const path = [ + opts.requestPath, + emptyQuery ? '' : '?', + utils.stringifyRequestData(opts.queryData), + ].join(''); + + const {headers, settings} = opts; + + self._request( + opts.requestMethod, + opts.host, + path, + opts.bodyData, + opts.auth, + {headers, settings, streaming: opts.streaming}, + requestCallback + ); + }); +} + +export = makeRequest; diff --git a/src/multipart.js b/src/multipart.js new file mode 100644 index 0000000000..90682aedda --- /dev/null +++ b/src/multipart.js @@ -0,0 +1,96 @@ +'use strict'; + +const utils = require('./utils'); +const {StripeError} = require('./Error'); + +class StreamProcessingError extends StripeError {} + +// Method for formatting HTTP body for the multipart/form-data specification +// Mostly taken from Fermata.js +// https://github.com/natevw/fermata/blob/5d9732a33d776ce925013a265935facd1626cc88/fermata.js#L315-L343 +const multipartDataGenerator = (method, data, headers) => { + const segno = ( + Math.round(Math.random() * 1e16) + Math.round(Math.random() * 1e16) + ).toString(); + headers['Content-Type'] = `multipart/form-data; boundary=${segno}`; + let buffer = Buffer.alloc(0); + + function push(l) { + const prevBuffer = buffer; + const newBuffer = l instanceof Buffer ? l : Buffer.from(l); + buffer = Buffer.alloc(prevBuffer.length + newBuffer.length + 2); + prevBuffer.copy(buffer); + newBuffer.copy(buffer, prevBuffer.length); + buffer.write('\r\n', buffer.length - 2); + } + + function q(s) { + return `"${s.replace(/"|"/g, '%22').replace(/\r\n|\r|\n/g, ' ')}"`; + } + + const flattenedData = utils.flattenAndStringify(data); + + for (const k in flattenedData) { + const v = flattenedData[k]; + push(`--${segno}`); + if (v.hasOwnProperty('data')) { + push( + `Content-Disposition: form-data; name=${q(k)}; filename=${q( + v.name || 'blob' + )}` + ); + push(`Content-Type: ${v.type || 'application/octet-stream'}`); + push(''); + push(v.data); + } else { + push(`Content-Disposition: form-data; name=${q(k)}`); + push(''); + push(v); + } + } + push(`--${segno}--`); + + return buffer; +}; + +const streamProcessor = (method, data, headers, callback) => { + const bufferArray = []; + data.file.data + .on('data', (line) => { + bufferArray.push(line); + }) + .once('end', () => { + const bufferData = Object.assign({}, data); + bufferData.file.data = Buffer.concat(bufferArray); + const buffer = multipartDataGenerator(method, bufferData, headers); + callback(null, buffer); + }) + .on('error', (err) => { + callback( + new StreamProcessingError({ + message: + 'An error occurred while attempting to process the file for upload.', + detail: err, + }), + null + ); + }); +}; + +const multipartRequestDataProcessor = (method, data, headers, callback) => { + data = data || {}; + + if (method !== 'POST') { + return callback(null, utils.stringifyRequestData(data)); + } + + const isStream = utils.checkForStream(data); + if (isStream) { + return streamProcessor(method, data, headers, callback); + } + + const buffer = multipartDataGenerator(method, data, headers); + return callback(null, buffer); +}; + +module.exports.multipartRequestDataProcessor = multipartRequestDataProcessor; diff --git a/src/net/FetchHttpClient.js b/src/net/FetchHttpClient.js new file mode 100644 index 0000000000..431282cd19 --- /dev/null +++ b/src/net/FetchHttpClient.js @@ -0,0 +1,138 @@ +'use strict'; + +const {HttpClient, HttpClientResponse} = require('./HttpClient'); + +/** + * HTTP client which uses a `fetch` function to issue requests. + * + * By default relies on the global `fetch` function, but an optional function + * can be passed in. If passing in a function, it is expected to match the Web + * Fetch API. As an example, this could be the function provided by the + * node-fetch package (https://github.com/node-fetch/node-fetch). + */ +class FetchHttpClient extends HttpClient { + constructor(fetchFn) { + super(); + this._fetchFn = fetchFn; + } + + /** @override. */ + getClientName() { + return 'fetch'; + } + + makeRequest( + host, + port, + path, + method, + headers, + requestData, + protocol, + timeout + ) { + const isInsecureConnection = protocol === 'http'; + + const url = new URL( + path, + `${isInsecureConnection ? 'http' : 'https'}://${host}` + ); + url.port = port; + + // For methods which expect payloads, we should always pass a body value + // even when it is empty. Without this, some JS runtimes (eg. Deno) will + // inject a second Content-Length header. See https://github.com/stripe/stripe-node/issues/1519 + // for more details. + const methodHasPayload = + method == 'POST' || method == 'PUT' || method == 'PATCH'; + const body = requestData || (methodHasPayload ? '' : undefined); + + const fetchFn = this._fetchFn || fetch; + const fetchPromise = fetchFn(url.toString(), { + method, + headers, + body, + }); + + // The Fetch API does not support passing in a timeout natively, so a + // timeout promise is constructed to race against the fetch and preempt the + // request, simulating a timeout. + // + // This timeout behavior differs from Node: + // - Fetch uses a single timeout for the entire length of the request. + // - Node is more fine-grained and resets the timeout after each stage of + // the request. + // + // As an example, if the timeout is set to 30s and the connection takes 20s + // to be established followed by 20s for the body, Fetch would timeout but + // Node would not. The more fine-grained timeout cannot be implemented with + // fetch. + let pendingTimeoutId; + const timeoutPromise = new Promise((_, reject) => { + pendingTimeoutId = setTimeout(() => { + pendingTimeoutId = null; + reject(HttpClient.makeTimeoutError()); + }, timeout); + }); + + return Promise.race([fetchPromise, timeoutPromise]) + .then((res) => { + return new FetchHttpClientResponse(res); + }) + .finally(() => { + if (pendingTimeoutId) { + clearTimeout(pendingTimeoutId); + } + }); + } +} + +class FetchHttpClientResponse extends HttpClientResponse { + constructor(res) { + super( + res.status, + FetchHttpClientResponse._transformHeadersToObject(res.headers) + ); + this._res = res; + } + + getRawResponse() { + return this._res; + } + + toStream(streamCompleteCallback) { + // Unfortunately `fetch` does not have event handlers for when the stream is + // completely read. We therefore invoke the streamCompleteCallback right + // away. This callback emits a response event with metadata and completes + // metrics, so it's ok to do this without waiting for the stream to be + // completely read. + streamCompleteCallback(); + + // Fetch's `body` property is expected to be a readable stream of the body. + return this._res.body; + } + + toJSON() { + return this._res.json(); + } + + static _transformHeadersToObject(headers) { + // Fetch uses a Headers instance so this must be converted to a barebones + // JS object to meet the HttpClient interface. + const headersObj = {}; + + for (const entry of headers) { + if (!Array.isArray(entry) || entry.length != 2) { + throw new Error( + 'Response objects produced by the fetch function given to FetchHttpClient do not have an iterable headers map. Response#headers should be an iterable object.' + ); + } + + headersObj[entry[0]] = entry[1]; + } + + return headersObj; + } +} + +module.exports = {FetchHttpClient, FetchHttpClientResponse}; diff --git a/src/net/HttpClient.js b/src/net/HttpClient.js new file mode 100644 index 0000000000..b309ce7d9d --- /dev/null +++ b/src/net/HttpClient.js @@ -0,0 +1,69 @@ +'use strict'; + +/** + * Encapsulates the logic for issuing a request to the Stripe API. + * + * A custom HTTP client should should implement: + * 1. A response class which extends HttpClientResponse and wraps around their + * own internal representation of a response. + * 2. A client class which extends HttpClient and implements all methods, + * returning their own response class when making requests. + */ +class HttpClient { + /** The client name used for diagnostics. */ + getClientName() { + throw new Error('getClientName not implemented.'); + } + + makeRequest( + host, + port, + path, + method, + headers, + requestData, + protocol, + timeout + ) { + throw new Error('makeRequest not implemented.'); + } + + /** Helper to make a consistent timeout error across implementations. */ + static makeTimeoutError() { + const timeoutErr = new TypeError(HttpClient.TIMEOUT_ERROR_CODE); + timeoutErr.code = HttpClient.TIMEOUT_ERROR_CODE; + return timeoutErr; + } +} + +HttpClient.CONNECTION_CLOSED_ERROR_CODES = ['ECONNRESET', 'EPIPE']; +HttpClient.TIMEOUT_ERROR_CODE = 'ETIMEDOUT'; + +class HttpClientResponse { + constructor(statusCode, headers) { + this._statusCode = statusCode; + this._headers = headers; + } + + getStatusCode() { + return this._statusCode; + } + + getHeaders() { + return this._headers; + } + + getRawResponse() { + throw new Error('getRawResponse not implemented.'); + } + + toStream(streamCompleteCallback) { + throw new Error('toStream not implemented.'); + } + + toJSON() { + throw new Error('toJSON not implemented.'); + } +} + +module.exports = {HttpClient, HttpClientResponse}; diff --git a/src/net/NodeHttpClient.js b/src/net/NodeHttpClient.js new file mode 100644 index 0000000000..222a446ce7 --- /dev/null +++ b/src/net/NodeHttpClient.js @@ -0,0 +1,125 @@ +'use strict'; + +const http = require('http'); +const https = require('https'); + +const {HttpClient, HttpClientResponse} = require('./HttpClient'); + +const defaultHttpAgent = new http.Agent({keepAlive: true}); +const defaultHttpsAgent = new https.Agent({keepAlive: true}); + +/** + * HTTP client which uses the Node `http` and `https` packages to issue + * requests.` + */ +class NodeHttpClient extends HttpClient { + constructor(agent) { + super(); + this._agent = agent; + } + + /** @override. */ + getClientName() { + return 'node'; + } + + makeRequest( + host, + port, + path, + method, + headers, + requestData, + protocol, + timeout + ) { + const isInsecureConnection = protocol === 'http'; + + let agent = this._agent; + if (!agent) { + agent = isInsecureConnection ? defaultHttpAgent : defaultHttpsAgent; + } + + const requestPromise = new Promise((resolve, reject) => { + const req = (isInsecureConnection ? http : https).request({ + host: host, + port: port, + path, + method, + agent, + headers, + ciphers: 'DEFAULT:!aNULL:!eNULL:!LOW:!EXPORT:!SSLv2:!MD5', + }); + + req.setTimeout(timeout, () => { + req.destroy(HttpClient.makeTimeoutError()); + }); + + req.on('response', (res) => { + resolve(new NodeHttpClientResponse(res)); + }); + + req.on('error', (error) => { + reject(error); + }); + + req.once('socket', (socket) => { + if (socket.connecting) { + socket.once( + isInsecureConnection ? 'connect' : 'secureConnect', + () => { + // Send payload; we're safe: + req.write(requestData); + req.end(); + } + ); + } else { + // we're already connected + req.write(requestData); + req.end(); + } + }); + }); + + return requestPromise; + } +} + +class NodeHttpClientResponse extends HttpClientResponse { + constructor(res) { + super(res.statusCode, res.headers || {}); + this._res = res; + } + + getRawResponse() { + return this._res; + } + + toStream(streamCompleteCallback) { + // The raw response is itself the stream, so we just return that. To be + // backwards compatible, we should invoke the streamCompleteCallback only + // once the stream has been fully consumed. + this._res.once('end', () => streamCompleteCallback()); + return this._res; + } + + toJSON() { + return new Promise((resolve, reject) => { + let response = ''; + + this._res.setEncoding('utf8'); + this._res.on('data', (chunk) => { + response += chunk; + }); + this._res.once('end', () => { + try { + resolve(JSON.parse(response)); + } catch (e) { + reject(e); + } + }); + }); + } +} + +module.exports = {NodeHttpClient, NodeHttpClientResponse}; diff --git a/src/resources.js b/src/resources.js new file mode 100644 index 0000000000..825c8f1d9d --- /dev/null +++ b/src/resources.js @@ -0,0 +1,130 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const resourceNamespace = require('./ResourceNamespace'); + +module.exports = { + Accounts: require('./resources/Accounts'), + // Support Accounts for consistency, Account for backwards compatibility + Account: require('./resources/Accounts'), + AccountLinks: require('./resources/AccountLinks'), + ApplePayDomains: require('./resources/ApplePayDomains'), + ApplicationFees: require('./resources/ApplicationFees'), + Balance: require('./resources/Balance'), + BalanceTransactions: require('./resources/BalanceTransactions'), + Charges: require('./resources/Charges'), + CountrySpecs: require('./resources/CountrySpecs'), + Coupons: require('./resources/Coupons'), + CreditNotes: require('./resources/CreditNotes'), + Customers: require('./resources/Customers'), + Disputes: require('./resources/Disputes'), + EphemeralKeys: require('./resources/EphemeralKeys'), + Events: require('./resources/Events'), + ExchangeRates: require('./resources/ExchangeRates'), + Files: require('./resources/Files'), + FileLinks: require('./resources/FileLinks'), + Invoices: require('./resources/Invoices'), + InvoiceItems: require('./resources/InvoiceItems'), + Mandates: require('./resources/Mandates'), + OAuth: require('./resources/OAuth'), + Orders: require('./resources/Orders'), + PaymentIntents: require('./resources/PaymentIntents'), + PaymentLinks: require('./resources/PaymentLinks'), + PaymentMethods: require('./resources/PaymentMethods'), + Payouts: require('./resources/Payouts'), + Plans: require('./resources/Plans'), + Prices: require('./resources/Prices'), + Products: require('./resources/Products'), + PromotionCodes: require('./resources/PromotionCodes'), + Quotes: require('./resources/Quotes'), + Refunds: require('./resources/Refunds'), + Reviews: require('./resources/Reviews'), + SetupAttempts: require('./resources/SetupAttempts'), + SetupIntents: require('./resources/SetupIntents'), + ShippingRates: require('./resources/ShippingRates'), + Skus: require('./resources/SKUs'), + Sources: require('./resources/Sources'), + Subscriptions: require('./resources/Subscriptions'), + SubscriptionItems: require('./resources/SubscriptionItems'), + SubscriptionSchedules: require('./resources/SubscriptionSchedules'), + TaxCodes: require('./resources/TaxCodes'), + TaxRates: require('./resources/TaxRates'), + Tokens: require('./resources/Tokens'), + Topups: require('./resources/Topups'), + Transfers: require('./resources/Transfers'), + WebhookEndpoints: require('./resources/WebhookEndpoints'), + Apps: resourceNamespace('apps', { + Secrets: require('./resources/Apps/Secrets'), + }), + BillingPortal: resourceNamespace('billingPortal', { + Configurations: require('./resources/BillingPortal/Configurations'), + Sessions: require('./resources/BillingPortal/Sessions'), + }), + Checkout: resourceNamespace('checkout', { + Sessions: require('./resources/Checkout/Sessions'), + }), + FinancialConnections: resourceNamespace('financialConnections', { + Accounts: require('./resources/FinancialConnections/Accounts'), + Sessions: require('./resources/FinancialConnections/Sessions'), + }), + Identity: resourceNamespace('identity', { + VerificationReports: require('./resources/Identity/VerificationReports'), + VerificationSessions: require('./resources/Identity/VerificationSessions'), + }), + Issuing: resourceNamespace('issuing', { + Authorizations: require('./resources/Issuing/Authorizations'), + Cards: require('./resources/Issuing/Cards'), + Cardholders: require('./resources/Issuing/Cardholders'), + Disputes: require('./resources/Issuing/Disputes'), + Transactions: require('./resources/Issuing/Transactions'), + }), + Radar: resourceNamespace('radar', { + EarlyFraudWarnings: require('./resources/Radar/EarlyFraudWarnings'), + ValueLists: require('./resources/Radar/ValueLists'), + ValueListItems: require('./resources/Radar/ValueListItems'), + }), + Reporting: resourceNamespace('reporting', { + ReportRuns: require('./resources/Reporting/ReportRuns'), + ReportTypes: require('./resources/Reporting/ReportTypes'), + }), + Sigma: resourceNamespace('sigma', { + ScheduledQueryRuns: require('./resources/Sigma/ScheduledQueryRuns'), + }), + Terminal: resourceNamespace('terminal', { + Configurations: require('./resources/Terminal/Configurations'), + ConnectionTokens: require('./resources/Terminal/ConnectionTokens'), + Locations: require('./resources/Terminal/Locations'), + Readers: require('./resources/Terminal/Readers'), + }), + TestHelpers: resourceNamespace('testHelpers', { + Customers: require('./resources/TestHelpers/Customers'), + Refunds: require('./resources/TestHelpers/Refunds'), + TestClocks: require('./resources/TestHelpers/TestClocks'), + Issuing: resourceNamespace('issuing', { + Cards: require('./resources/TestHelpers/Issuing/Cards'), + }), + Terminal: resourceNamespace('terminal', { + Readers: require('./resources/TestHelpers/Terminal/Readers'), + }), + Treasury: resourceNamespace('treasury', { + InboundTransfers: require('./resources/TestHelpers/Treasury/InboundTransfers'), + OutboundPayments: require('./resources/TestHelpers/Treasury/OutboundPayments'), + OutboundTransfers: require('./resources/TestHelpers/Treasury/OutboundTransfers'), + ReceivedCredits: require('./resources/TestHelpers/Treasury/ReceivedCredits'), + ReceivedDebits: require('./resources/TestHelpers/Treasury/ReceivedDebits'), + }), + }), + Treasury: resourceNamespace('treasury', { + CreditReversals: require('./resources/Treasury/CreditReversals'), + DebitReversals: require('./resources/Treasury/DebitReversals'), + FinancialAccounts: require('./resources/Treasury/FinancialAccounts'), + InboundTransfers: require('./resources/Treasury/InboundTransfers'), + OutboundPayments: require('./resources/Treasury/OutboundPayments'), + OutboundTransfers: require('./resources/Treasury/OutboundTransfers'), + ReceivedCredits: require('./resources/Treasury/ReceivedCredits'), + ReceivedDebits: require('./resources/Treasury/ReceivedDebits'), + Transactions: require('./resources/Treasury/Transactions'), + TransactionEntries: require('./resources/Treasury/TransactionEntries'), + }), +}; diff --git a/src/resources/AccountLinks.js b/src/resources/AccountLinks.js new file mode 100644 index 0000000000..41e02b1ec5 --- /dev/null +++ b/src/resources/AccountLinks.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'account_links', + + create: stripeMethod({ + method: 'POST', + path: '', + }), +}); diff --git a/src/resources/Accounts.js b/src/resources/Accounts.js new file mode 100644 index 0000000000..351c055f23 --- /dev/null +++ b/src/resources/Accounts.js @@ -0,0 +1,130 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +// Since path can either be `account` or `accounts`, support both through stripeMethod path; +module.exports = StripeResource.extend({ + path: '', + + create: stripeMethod({ + method: 'POST', + path: 'accounts', + }), + + retrieve(id) { + // No longer allow an api key to be passed as the first string to this function due to ambiguity between + // old account ids and api keys. To request the account for an api key, send null as the id + if (typeof id === 'string') { + return stripeMethod({ + method: 'GET', + path: 'accounts/{id}', + }).apply(this, arguments); + } else { + if (id === null || id === undefined) { + // Remove id as stripeMethod would complain of unexpected argument + [].shift.apply(arguments); + } + return stripeMethod({ + method: 'GET', + path: 'account', + }).apply(this, arguments); + } + }, + + update: stripeMethod({ + method: 'POST', + path: 'accounts/{account}', + }), + + list: stripeMethod({ + method: 'GET', + path: 'accounts', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: 'accounts/{account}', + }), + + reject: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/reject', + }), + + retrieveCapability: stripeMethod({ + method: 'GET', + path: 'accounts/{account}/capabilities/{capability}', + }), + + updateCapability: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/capabilities/{capability}', + }), + + listCapabilities: stripeMethod({ + method: 'GET', + path: 'accounts/{account}/capabilities', + methodType: 'list', + }), + + createExternalAccount: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/external_accounts', + }), + + retrieveExternalAccount: stripeMethod({ + method: 'GET', + path: 'accounts/{account}/external_accounts/{id}', + }), + + updateExternalAccount: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/external_accounts/{id}', + }), + + listExternalAccounts: stripeMethod({ + method: 'GET', + path: 'accounts/{account}/external_accounts', + methodType: 'list', + }), + + deleteExternalAccount: stripeMethod({ + method: 'DELETE', + path: 'accounts/{account}/external_accounts/{id}', + }), + + createLoginLink: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/login_links', + }), + + createPerson: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/persons', + }), + + retrievePerson: stripeMethod({ + method: 'GET', + path: 'accounts/{account}/persons/{person}', + }), + + updatePerson: stripeMethod({ + method: 'POST', + path: 'accounts/{account}/persons/{person}', + }), + + listPersons: stripeMethod({ + method: 'GET', + path: 'accounts/{account}/persons', + methodType: 'list', + }), + + deletePerson: stripeMethod({ + method: 'DELETE', + path: 'accounts/{account}/persons/{person}', + }), +}); diff --git a/src/resources/ApplePayDomains.js b/src/resources/ApplePayDomains.js new file mode 100644 index 0000000000..76a8c59585 --- /dev/null +++ b/src/resources/ApplePayDomains.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'apple_pay/domains', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{domain}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{domain}', + }), +}); diff --git a/src/resources/ApplicationFees.js b/src/resources/ApplicationFees.js new file mode 100644 index 0000000000..ebd6372aca --- /dev/null +++ b/src/resources/ApplicationFees.js @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'application_fees', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + createRefund: stripeMethod({ + method: 'POST', + path: '/{id}/refunds', + }), + + retrieveRefund: stripeMethod({ + method: 'GET', + path: '/{fee}/refunds/{id}', + }), + + updateRefund: stripeMethod({ + method: 'POST', + path: '/{fee}/refunds/{id}', + }), + + listRefunds: stripeMethod({ + method: 'GET', + path: '/{id}/refunds', + methodType: 'list', + }), +}); diff --git a/src/resources/Apps/Secrets.js b/src/resources/Apps/Secrets.js new file mode 100644 index 0000000000..238037508f --- /dev/null +++ b/src/resources/Apps/Secrets.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'apps/secrets', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + deleteWhere: stripeMethod({ + method: 'POST', + path: '/delete', + }), + + find: stripeMethod({ + method: 'GET', + path: '/find', + }), +}); diff --git a/src/resources/Balance.js b/src/resources/Balance.js new file mode 100644 index 0000000000..ac7a9ae459 --- /dev/null +++ b/src/resources/Balance.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'balance', + + retrieve: stripeMethod({ + method: 'GET', + path: '', + }), +}); diff --git a/src/resources/BalanceTransactions.js b/src/resources/BalanceTransactions.js new file mode 100644 index 0000000000..adbe3d41f9 --- /dev/null +++ b/src/resources/BalanceTransactions.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'balance_transactions', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/BillingPortal/Configurations.js b/src/resources/BillingPortal/Configurations.js new file mode 100644 index 0000000000..ff3200160a --- /dev/null +++ b/src/resources/BillingPortal/Configurations.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'billing_portal/configurations', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{configuration}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{configuration}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/BillingPortal/Sessions.js b/src/resources/BillingPortal/Sessions.js new file mode 100644 index 0000000000..04f0ef6805 --- /dev/null +++ b/src/resources/BillingPortal/Sessions.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'billing_portal/sessions', + + create: stripeMethod({ + method: 'POST', + path: '', + }), +}); diff --git a/src/resources/Charges.js b/src/resources/Charges.js new file mode 100644 index 0000000000..f4546063f7 --- /dev/null +++ b/src/resources/Charges.js @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'charges', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{charge}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{charge}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + capture: stripeMethod({ + method: 'POST', + path: '/{charge}/capture', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), +}); diff --git a/src/resources/Checkout/Sessions.js b/src/resources/Checkout/Sessions.js new file mode 100644 index 0000000000..1cef4d65d7 --- /dev/null +++ b/src/resources/Checkout/Sessions.js @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'checkout/sessions', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{session}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + expire: stripeMethod({ + method: 'POST', + path: '/{session}/expire', + }), + + listLineItems: stripeMethod({ + method: 'GET', + path: '/{session}/line_items', + methodType: 'list', + }), +}); diff --git a/src/resources/CountrySpecs.js b/src/resources/CountrySpecs.js new file mode 100644 index 0000000000..789f99054a --- /dev/null +++ b/src/resources/CountrySpecs.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'country_specs', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{country}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Coupons.js b/src/resources/Coupons.js new file mode 100644 index 0000000000..11bed027fe --- /dev/null +++ b/src/resources/Coupons.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'coupons', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{coupon}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{coupon}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{coupon}', + }), +}); diff --git a/src/resources/CreditNotes.js b/src/resources/CreditNotes.js new file mode 100644 index 0000000000..e435282d00 --- /dev/null +++ b/src/resources/CreditNotes.js @@ -0,0 +1,53 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'credit_notes', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + listPreviewLineItems: stripeMethod({ + method: 'GET', + path: '/preview/lines', + methodType: 'list', + }), + + preview: stripeMethod({ + method: 'GET', + path: '/preview', + }), + + voidCreditNote: stripeMethod({ + method: 'POST', + path: '/{id}/void', + }), + + listLineItems: stripeMethod({ + method: 'GET', + path: '/{creditNote}/lines', + methodType: 'list', + }), +}); diff --git a/src/resources/Customers.js b/src/resources/Customers.js new file mode 100644 index 0000000000..e3b8e8fab8 --- /dev/null +++ b/src/resources/Customers.js @@ -0,0 +1,157 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'customers', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{customer}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{customer}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{customer}', + }), + + createFundingInstructions: stripeMethod({ + method: 'POST', + path: '/{customer}/funding_instructions', + }), + + deleteDiscount: stripeMethod({ + method: 'DELETE', + path: '/{customer}/discount', + }), + + listPaymentMethods: stripeMethod({ + method: 'GET', + path: '/{customer}/payment_methods', + methodType: 'list', + }), + + retrievePaymentMethod: stripeMethod({ + method: 'GET', + path: '/{customer}/payment_methods/{paymentMethod}', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), + + retrieveCashBalance: stripeMethod({ + method: 'GET', + path: '/{customer}/cash_balance', + }), + + updateCashBalance: stripeMethod({ + method: 'POST', + path: '/{customer}/cash_balance', + }), + + createBalanceTransaction: stripeMethod({ + method: 'POST', + path: '/{customer}/balance_transactions', + }), + + retrieveBalanceTransaction: stripeMethod({ + method: 'GET', + path: '/{customer}/balance_transactions/{transaction}', + }), + + updateBalanceTransaction: stripeMethod({ + method: 'POST', + path: '/{customer}/balance_transactions/{transaction}', + }), + + listBalanceTransactions: stripeMethod({ + method: 'GET', + path: '/{customer}/balance_transactions', + methodType: 'list', + }), + + retrieveCashBalanceTransaction: stripeMethod({ + method: 'GET', + path: '/{customer}/cash_balance_transactions/{transaction}', + }), + + listCashBalanceTransactions: stripeMethod({ + method: 'GET', + path: '/{customer}/cash_balance_transactions', + methodType: 'list', + }), + + createSource: stripeMethod({ + method: 'POST', + path: '/{customer}/sources', + }), + + retrieveSource: stripeMethod({ + method: 'GET', + path: '/{customer}/sources/{id}', + }), + + updateSource: stripeMethod({ + method: 'POST', + path: '/{customer}/sources/{id}', + }), + + listSources: stripeMethod({ + method: 'GET', + path: '/{customer}/sources', + methodType: 'list', + }), + + deleteSource: stripeMethod({ + method: 'DELETE', + path: '/{customer}/sources/{id}', + }), + + verifySource: stripeMethod({ + method: 'POST', + path: '/{customer}/sources/{id}/verify', + }), + + createTaxId: stripeMethod({ + method: 'POST', + path: '/{customer}/tax_ids', + }), + + retrieveTaxId: stripeMethod({ + method: 'GET', + path: '/{customer}/tax_ids/{id}', + }), + + listTaxIds: stripeMethod({ + method: 'GET', + path: '/{customer}/tax_ids', + methodType: 'list', + }), + + deleteTaxId: stripeMethod({ + method: 'DELETE', + path: '/{customer}/tax_ids/{id}', + }), +}); diff --git a/src/resources/Disputes.js b/src/resources/Disputes.js new file mode 100644 index 0000000000..1318758949 --- /dev/null +++ b/src/resources/Disputes.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'disputes', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{dispute}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{dispute}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + close: stripeMethod({ + method: 'POST', + path: '/{dispute}/close', + }), +}); diff --git a/src/resources/EphemeralKeys.js b/src/resources/EphemeralKeys.js new file mode 100644 index 0000000000..2f9b02694c --- /dev/null +++ b/src/resources/EphemeralKeys.js @@ -0,0 +1,27 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'ephemeral_keys', + + create: stripeMethod({ + method: 'POST', + path: '', + validator: (data, options) => { + if (!options.headers || !options.headers['Stripe-Version']) { + throw new Error( + 'Passing apiVersion in a separate options hash is required to create an ephemeral key. See https://stripe.com/docs/api/versioning?lang=node' + ); + } + }, + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{key}', + }), +}); diff --git a/src/resources/Events.js b/src/resources/Events.js new file mode 100644 index 0000000000..79ee31d45a --- /dev/null +++ b/src/resources/Events.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'events', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/ExchangeRates.js b/src/resources/ExchangeRates.js new file mode 100644 index 0000000000..021e972336 --- /dev/null +++ b/src/resources/ExchangeRates.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'exchange_rates', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{rateId}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/FileLinks.js b/src/resources/FileLinks.js new file mode 100644 index 0000000000..7c7a6e117d --- /dev/null +++ b/src/resources/FileLinks.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'file_links', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{link}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{link}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Files.js b/src/resources/Files.js new file mode 100644 index 0000000000..5dee82d1d2 --- /dev/null +++ b/src/resources/Files.js @@ -0,0 +1,32 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const {multipartRequestDataProcessor} = require('../multipart'); +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'files', + + create: stripeMethod({ + method: 'POST', + headers: { + 'Content-Type': 'multipart/form-data', + }, + host: 'files.stripe.com', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{file}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + requestDataProcessor: multipartRequestDataProcessor, +}); diff --git a/src/resources/FinancialConnections/Accounts.js b/src/resources/FinancialConnections/Accounts.js new file mode 100644 index 0000000000..674f42ec48 --- /dev/null +++ b/src/resources/FinancialConnections/Accounts.js @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'financial_connections/accounts', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{account}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + disconnect: stripeMethod({ + method: 'POST', + path: '/{account}/disconnect', + }), + + listOwners: stripeMethod({ + method: 'GET', + path: '/{account}/owners', + methodType: 'list', + }), + + refresh: stripeMethod({ + method: 'POST', + path: '/{account}/refresh', + }), +}); diff --git a/src/resources/FinancialConnections/Sessions.js b/src/resources/FinancialConnections/Sessions.js new file mode 100644 index 0000000000..0e968a437b --- /dev/null +++ b/src/resources/FinancialConnections/Sessions.js @@ -0,0 +1,20 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'financial_connections/sessions', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{session}', + }), +}); diff --git a/src/resources/Identity/VerificationReports.js b/src/resources/Identity/VerificationReports.js new file mode 100644 index 0000000000..6d78faa7a0 --- /dev/null +++ b/src/resources/Identity/VerificationReports.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'identity/verification_reports', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{report}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Identity/VerificationSessions.js b/src/resources/Identity/VerificationSessions.js new file mode 100644 index 0000000000..02345e1210 --- /dev/null +++ b/src/resources/Identity/VerificationSessions.js @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'identity/verification_sessions', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{session}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{session}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{session}/cancel', + }), + + redact: stripeMethod({ + method: 'POST', + path: '/{session}/redact', + }), +}); diff --git a/src/resources/InvoiceItems.js b/src/resources/InvoiceItems.js new file mode 100644 index 0000000000..c7cb5586be --- /dev/null +++ b/src/resources/InvoiceItems.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'invoiceitems', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{invoiceitem}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{invoiceitem}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{invoiceitem}', + }), +}); diff --git a/src/resources/Invoices.js b/src/resources/Invoices.js new file mode 100644 index 0000000000..21543c1f3a --- /dev/null +++ b/src/resources/Invoices.js @@ -0,0 +1,84 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'invoices', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{invoice}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{invoice}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{invoice}', + }), + + finalizeInvoice: stripeMethod({ + method: 'POST', + path: '/{invoice}/finalize', + }), + + listUpcomingLines: stripeMethod({ + method: 'GET', + path: '/upcoming/lines', + methodType: 'list', + }), + + markUncollectible: stripeMethod({ + method: 'POST', + path: '/{invoice}/mark_uncollectible', + }), + + pay: stripeMethod({ + method: 'POST', + path: '/{invoice}/pay', + }), + + retrieveUpcoming: stripeMethod({ + method: 'GET', + path: '/upcoming', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), + + sendInvoice: stripeMethod({ + method: 'POST', + path: '/{invoice}/send', + }), + + voidInvoice: stripeMethod({ + method: 'POST', + path: '/{invoice}/void', + }), + + listLineItems: stripeMethod({ + method: 'GET', + path: '/{invoice}/lines', + methodType: 'list', + }), +}); diff --git a/src/resources/Issuing/Authorizations.js b/src/resources/Issuing/Authorizations.js new file mode 100644 index 0000000000..5310d0ea8b --- /dev/null +++ b/src/resources/Issuing/Authorizations.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'issuing/authorizations', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{authorization}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{authorization}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + approve: stripeMethod({ + method: 'POST', + path: '/{authorization}/approve', + }), + + decline: stripeMethod({ + method: 'POST', + path: '/{authorization}/decline', + }), +}); diff --git a/src/resources/Issuing/Cardholders.js b/src/resources/Issuing/Cardholders.js new file mode 100644 index 0000000000..7b340e6912 --- /dev/null +++ b/src/resources/Issuing/Cardholders.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'issuing/cardholders', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{cardholder}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{cardholder}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Issuing/Cards.js b/src/resources/Issuing/Cards.js new file mode 100644 index 0000000000..efc2cbc10f --- /dev/null +++ b/src/resources/Issuing/Cards.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'issuing/cards', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{card}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{card}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Issuing/Disputes.js b/src/resources/Issuing/Disputes.js new file mode 100644 index 0000000000..f62a2be96d --- /dev/null +++ b/src/resources/Issuing/Disputes.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'issuing/disputes', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{dispute}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{dispute}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + submit: stripeMethod({ + method: 'POST', + path: '/{dispute}/submit', + }), +}); diff --git a/src/resources/Issuing/Transactions.js b/src/resources/Issuing/Transactions.js new file mode 100644 index 0000000000..22b438429d --- /dev/null +++ b/src/resources/Issuing/Transactions.js @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'issuing/transactions', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{transaction}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{transaction}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Mandates.js b/src/resources/Mandates.js new file mode 100644 index 0000000000..6d9ced9f82 --- /dev/null +++ b/src/resources/Mandates.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'mandates', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{mandate}', + }), +}); diff --git a/src/resources/OAuth.js b/src/resources/OAuth.js new file mode 100644 index 0000000000..70ce4a2358 --- /dev/null +++ b/src/resources/OAuth.js @@ -0,0 +1,55 @@ +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; +const utils = require('../utils'); + +const oAuthHost = 'connect.stripe.com'; + +module.exports = StripeResource.extend({ + basePath: '/', + + authorizeUrl(params, options) { + params = params || {}; + options = options || {}; + + let path = 'oauth/authorize'; + + // For Express accounts, the path changes + if (options.express) { + path = `express/${path}`; + } + + if (!params.response_type) { + params.response_type = 'code'; + } + + if (!params.client_id) { + params.client_id = this._stripe.getClientId(); + } + + if (!params.scope) { + params.scope = 'read_write'; + } + + return `https://${oAuthHost}/${path}?${utils.stringifyRequestData(params)}`; + }, + + token: stripeMethod({ + method: 'POST', + path: 'oauth/token', + host: oAuthHost, + }), + + deauthorize(spec) { + if (!spec.client_id) { + spec.client_id = this._stripe.getClientId(); + } + + return stripeMethod({ + method: 'POST', + path: 'oauth/deauthorize', + host: oAuthHost, + }).apply(this, arguments); + }, +}); diff --git a/src/resources/Orders.js b/src/resources/Orders.js new file mode 100644 index 0000000000..a216b32fc7 --- /dev/null +++ b/src/resources/Orders.js @@ -0,0 +1,52 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'orders', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{id}/cancel', + }), + + listLineItems: stripeMethod({ + method: 'GET', + path: '/{id}/line_items', + methodType: 'list', + }), + + reopen: stripeMethod({ + method: 'POST', + path: '/{id}/reopen', + }), + + submit: stripeMethod({ + method: 'POST', + path: '/{id}/submit', + }), +}); diff --git a/src/resources/PaymentIntents.js b/src/resources/PaymentIntents.js new file mode 100644 index 0000000000..d6addba0d3 --- /dev/null +++ b/src/resources/PaymentIntents.js @@ -0,0 +1,67 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'payment_intents', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{intent}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{intent}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + applyCustomerBalance: stripeMethod({ + method: 'POST', + path: '/{intent}/apply_customer_balance', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{intent}/cancel', + }), + + capture: stripeMethod({ + method: 'POST', + path: '/{intent}/capture', + }), + + confirm: stripeMethod({ + method: 'POST', + path: '/{intent}/confirm', + }), + + incrementAuthorization: stripeMethod({ + method: 'POST', + path: '/{intent}/increment_authorization', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), + + verifyMicrodeposits: stripeMethod({ + method: 'POST', + path: '/{intent}/verify_microdeposits', + }), +}); diff --git a/src/resources/PaymentLinks.js b/src/resources/PaymentLinks.js new file mode 100644 index 0000000000..a357cedd89 --- /dev/null +++ b/src/resources/PaymentLinks.js @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'payment_links', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{paymentLink}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{paymentLink}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + listLineItems: stripeMethod({ + method: 'GET', + path: '/{paymentLink}/line_items', + methodType: 'list', + }), +}); diff --git a/src/resources/PaymentMethods.js b/src/resources/PaymentMethods.js new file mode 100644 index 0000000000..bd74b2ee5f --- /dev/null +++ b/src/resources/PaymentMethods.js @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'payment_methods', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{paymentMethod}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{paymentMethod}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + attach: stripeMethod({ + method: 'POST', + path: '/{paymentMethod}/attach', + }), + + detach: stripeMethod({ + method: 'POST', + path: '/{paymentMethod}/detach', + }), +}); diff --git a/src/resources/Payouts.js b/src/resources/Payouts.js new file mode 100644 index 0000000000..a3b8e0cd66 --- /dev/null +++ b/src/resources/Payouts.js @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'payouts', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{payout}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{payout}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{payout}/cancel', + }), + + reverse: stripeMethod({ + method: 'POST', + path: '/{payout}/reverse', + }), +}); diff --git a/src/resources/Plans.js b/src/resources/Plans.js new file mode 100644 index 0000000000..bd55a157da --- /dev/null +++ b/src/resources/Plans.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'plans', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{plan}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{plan}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{plan}', + }), +}); diff --git a/src/resources/Prices.js b/src/resources/Prices.js new file mode 100644 index 0000000000..c509fdcbc0 --- /dev/null +++ b/src/resources/Prices.js @@ -0,0 +1,37 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'prices', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{price}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{price}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), +}); diff --git a/src/resources/Products.js b/src/resources/Products.js new file mode 100644 index 0000000000..3886020cf8 --- /dev/null +++ b/src/resources/Products.js @@ -0,0 +1,42 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'products', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{id}', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), +}); diff --git a/src/resources/PromotionCodes.js b/src/resources/PromotionCodes.js new file mode 100644 index 0000000000..c8afa0e478 --- /dev/null +++ b/src/resources/PromotionCodes.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'promotion_codes', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{promotionCode}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{promotionCode}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Quotes.js b/src/resources/Quotes.js new file mode 100644 index 0000000000..62aebb65a9 --- /dev/null +++ b/src/resources/Quotes.js @@ -0,0 +1,65 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'quotes', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{quote}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{quote}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + accept: stripeMethod({ + method: 'POST', + path: '/{quote}/accept', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{quote}/cancel', + }), + + finalizeQuote: stripeMethod({ + method: 'POST', + path: '/{quote}/finalize', + }), + + listComputedUpfrontLineItems: stripeMethod({ + method: 'GET', + path: '/{quote}/computed_upfront_line_items', + methodType: 'list', + }), + + listLineItems: stripeMethod({ + method: 'GET', + path: '/{quote}/line_items', + methodType: 'list', + }), + + pdf: stripeMethod({ + host: 'files.stripe.com', + method: 'GET', + path: '/{quote}/pdf', + streaming: true, + }), +}); diff --git a/src/resources/Radar/EarlyFraudWarnings.js b/src/resources/Radar/EarlyFraudWarnings.js new file mode 100644 index 0000000000..9282648d86 --- /dev/null +++ b/src/resources/Radar/EarlyFraudWarnings.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'radar/early_fraud_warnings', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{earlyFraudWarning}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Radar/ValueListItems.js b/src/resources/Radar/ValueListItems.js new file mode 100644 index 0000000000..75bcb8947c --- /dev/null +++ b/src/resources/Radar/ValueListItems.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'radar/value_list_items', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{item}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{item}', + }), +}); diff --git a/src/resources/Radar/ValueLists.js b/src/resources/Radar/ValueLists.js new file mode 100644 index 0000000000..ace1edaa2d --- /dev/null +++ b/src/resources/Radar/ValueLists.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'radar/value_lists', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{valueList}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{valueList}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{valueList}', + }), +}); diff --git a/src/resources/Refunds.js b/src/resources/Refunds.js new file mode 100644 index 0000000000..c859fc577c --- /dev/null +++ b/src/resources/Refunds.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'refunds', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{refund}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{refund}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{refund}/cancel', + }), +}); diff --git a/src/resources/Reporting/ReportRuns.js b/src/resources/Reporting/ReportRuns.js new file mode 100644 index 0000000000..84eb179f90 --- /dev/null +++ b/src/resources/Reporting/ReportRuns.js @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'reporting/report_runs', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{reportRun}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Reporting/ReportTypes.js b/src/resources/Reporting/ReportTypes.js new file mode 100644 index 0000000000..b4b25f8043 --- /dev/null +++ b/src/resources/Reporting/ReportTypes.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'reporting/report_types', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{reportType}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Reviews.js b/src/resources/Reviews.js new file mode 100644 index 0000000000..9400e8b89a --- /dev/null +++ b/src/resources/Reviews.js @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'reviews', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{review}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + approve: stripeMethod({ + method: 'POST', + path: '/{review}/approve', + }), +}); diff --git a/src/resources/SKUs.js b/src/resources/SKUs.js new file mode 100644 index 0000000000..26812405ff --- /dev/null +++ b/src/resources/SKUs.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'skus', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{id}', + }), +}); diff --git a/src/resources/SetupAttempts.js b/src/resources/SetupAttempts.js new file mode 100644 index 0000000000..9bb8c1d3e3 --- /dev/null +++ b/src/resources/SetupAttempts.js @@ -0,0 +1,16 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'setup_attempts', + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/SetupIntents.js b/src/resources/SetupIntents.js new file mode 100644 index 0000000000..7aea8dcf75 --- /dev/null +++ b/src/resources/SetupIntents.js @@ -0,0 +1,46 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'setup_intents', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{intent}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{intent}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{intent}/cancel', + }), + + confirm: stripeMethod({ + method: 'POST', + path: '/{intent}/confirm', + }), + + verifyMicrodeposits: stripeMethod({ + method: 'POST', + path: '/{intent}/verify_microdeposits', + }), +}); diff --git a/src/resources/ShippingRates.js b/src/resources/ShippingRates.js new file mode 100644 index 0000000000..d7eb52ac16 --- /dev/null +++ b/src/resources/ShippingRates.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'shipping_rates', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{shippingRateToken}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{shippingRateToken}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Sigma/ScheduledQueryRuns.js b/src/resources/Sigma/ScheduledQueryRuns.js new file mode 100644 index 0000000000..a8cb8e60a6 --- /dev/null +++ b/src/resources/Sigma/ScheduledQueryRuns.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'sigma/scheduled_query_runs', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{scheduledQueryRun}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Sources.js b/src/resources/Sources.js new file mode 100644 index 0000000000..5008001c5c --- /dev/null +++ b/src/resources/Sources.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'sources', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{source}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{source}', + }), + + listSourceTransactions: stripeMethod({ + method: 'GET', + path: '/{source}/source_transactions', + methodType: 'list', + }), + + verify: stripeMethod({ + method: 'POST', + path: '/{source}/verify', + }), +}); diff --git a/src/resources/SubscriptionItems.js b/src/resources/SubscriptionItems.js new file mode 100644 index 0000000000..62423a22cb --- /dev/null +++ b/src/resources/SubscriptionItems.js @@ -0,0 +1,47 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'subscription_items', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{item}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{item}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{item}', + }), + + createUsageRecord: stripeMethod({ + method: 'POST', + path: '/{subscriptionItem}/usage_records', + }), + + listUsageRecordSummaries: stripeMethod({ + method: 'GET', + path: '/{subscriptionItem}/usage_record_summaries', + methodType: 'list', + }), +}); diff --git a/src/resources/SubscriptionSchedules.js b/src/resources/SubscriptionSchedules.js new file mode 100644 index 0000000000..9c9249e3d9 --- /dev/null +++ b/src/resources/SubscriptionSchedules.js @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'subscription_schedules', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{schedule}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{schedule}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{schedule}/cancel', + }), + + release: stripeMethod({ + method: 'POST', + path: '/{schedule}/release', + }), +}); diff --git a/src/resources/Subscriptions.js b/src/resources/Subscriptions.js new file mode 100644 index 0000000000..bd0dc644c7 --- /dev/null +++ b/src/resources/Subscriptions.js @@ -0,0 +1,52 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'subscriptions', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{subscriptionExposedId}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{subscriptionExposedId}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'DELETE', + path: '/{subscriptionExposedId}', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{subscriptionExposedId}', + }), + + deleteDiscount: stripeMethod({ + method: 'DELETE', + path: '/{subscriptionExposedId}/discount', + }), + + search: stripeMethod({ + method: 'GET', + path: '/search', + methodType: 'search', + }), +}); diff --git a/src/resources/TaxCodes.js b/src/resources/TaxCodes.js new file mode 100644 index 0000000000..57bf52ff3e --- /dev/null +++ b/src/resources/TaxCodes.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'tax_codes', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/TaxRates.js b/src/resources/TaxRates.js new file mode 100644 index 0000000000..e429895f7b --- /dev/null +++ b/src/resources/TaxRates.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'tax_rates', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{taxRate}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{taxRate}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Terminal/Configurations.js b/src/resources/Terminal/Configurations.js new file mode 100644 index 0000000000..4a7d069a8e --- /dev/null +++ b/src/resources/Terminal/Configurations.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'terminal/configurations', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{configuration}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{configuration}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{configuration}', + }), +}); diff --git a/src/resources/Terminal/ConnectionTokens.js b/src/resources/Terminal/ConnectionTokens.js new file mode 100644 index 0000000000..2e1a1b5155 --- /dev/null +++ b/src/resources/Terminal/ConnectionTokens.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'terminal/connection_tokens', + + create: stripeMethod({ + method: 'POST', + path: '', + }), +}); diff --git a/src/resources/Terminal/Locations.js b/src/resources/Terminal/Locations.js new file mode 100644 index 0000000000..161e0dd014 --- /dev/null +++ b/src/resources/Terminal/Locations.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'terminal/locations', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{location}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{location}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{location}', + }), +}); diff --git a/src/resources/Terminal/Readers.js b/src/resources/Terminal/Readers.js new file mode 100644 index 0000000000..05a8a53ef5 --- /dev/null +++ b/src/resources/Terminal/Readers.js @@ -0,0 +1,56 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'terminal/readers', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{reader}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{reader}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{reader}', + }), + + cancelAction: stripeMethod({ + method: 'POST', + path: '/{reader}/cancel_action', + }), + + processPaymentIntent: stripeMethod({ + method: 'POST', + path: '/{reader}/process_payment_intent', + }), + + processSetupIntent: stripeMethod({ + method: 'POST', + path: '/{reader}/process_setup_intent', + }), + + setReaderDisplay: stripeMethod({ + method: 'POST', + path: '/{reader}/set_reader_display', + }), +}); diff --git a/src/resources/TestHelpers/Customers.js b/src/resources/TestHelpers/Customers.js new file mode 100644 index 0000000000..64796a11da --- /dev/null +++ b/src/resources/TestHelpers/Customers.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/customers', + + fundCashBalance: stripeMethod({ + method: 'POST', + path: '/{customer}/fund_cash_balance', + }), +}); diff --git a/src/resources/TestHelpers/Issuing/Cards.js b/src/resources/TestHelpers/Issuing/Cards.js new file mode 100644 index 0000000000..0f8c50f7d0 --- /dev/null +++ b/src/resources/TestHelpers/Issuing/Cards.js @@ -0,0 +1,30 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/issuing/cards', + + deliverCard: stripeMethod({ + method: 'POST', + path: '/{card}/shipping/deliver', + }), + + failCard: stripeMethod({ + method: 'POST', + path: '/{card}/shipping/fail', + }), + + returnCard: stripeMethod({ + method: 'POST', + path: '/{card}/shipping/return', + }), + + shipCard: stripeMethod({ + method: 'POST', + path: '/{card}/shipping/ship', + }), +}); diff --git a/src/resources/TestHelpers/Refunds.js b/src/resources/TestHelpers/Refunds.js new file mode 100644 index 0000000000..7aac415e77 --- /dev/null +++ b/src/resources/TestHelpers/Refunds.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/refunds', + + expire: stripeMethod({ + method: 'POST', + path: '/{refund}/expire', + }), +}); diff --git a/src/resources/TestHelpers/Terminal/Readers.js b/src/resources/TestHelpers/Terminal/Readers.js new file mode 100644 index 0000000000..ab660b0f95 --- /dev/null +++ b/src/resources/TestHelpers/Terminal/Readers.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/terminal/readers', + + presentPaymentMethod: stripeMethod({ + method: 'POST', + path: '/{reader}/present_payment_method', + }), +}); diff --git a/src/resources/TestHelpers/TestClocks.js b/src/resources/TestHelpers/TestClocks.js new file mode 100644 index 0000000000..adae9ae446 --- /dev/null +++ b/src/resources/TestHelpers/TestClocks.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/test_clocks', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{testClock}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{testClock}', + }), + + advance: stripeMethod({ + method: 'POST', + path: '/{testClock}/advance', + }), +}); diff --git a/src/resources/TestHelpers/Treasury/InboundTransfers.js b/src/resources/TestHelpers/Treasury/InboundTransfers.js new file mode 100644 index 0000000000..178816ad58 --- /dev/null +++ b/src/resources/TestHelpers/Treasury/InboundTransfers.js @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/treasury/inbound_transfers', + + fail: stripeMethod({ + method: 'POST', + path: '/{id}/fail', + }), + + returnInboundTransfer: stripeMethod({ + method: 'POST', + path: '/{id}/return', + }), + + succeed: stripeMethod({ + method: 'POST', + path: '/{id}/succeed', + }), +}); diff --git a/src/resources/TestHelpers/Treasury/OutboundPayments.js b/src/resources/TestHelpers/Treasury/OutboundPayments.js new file mode 100644 index 0000000000..3a1b4d6516 --- /dev/null +++ b/src/resources/TestHelpers/Treasury/OutboundPayments.js @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/treasury/outbound_payments', + + fail: stripeMethod({ + method: 'POST', + path: '/{id}/fail', + }), + + post: stripeMethod({ + method: 'POST', + path: '/{id}/post', + }), + + returnOutboundPayment: stripeMethod({ + method: 'POST', + path: '/{id}/return', + }), +}); diff --git a/src/resources/TestHelpers/Treasury/OutboundTransfers.js b/src/resources/TestHelpers/Treasury/OutboundTransfers.js new file mode 100644 index 0000000000..90d7d6236b --- /dev/null +++ b/src/resources/TestHelpers/Treasury/OutboundTransfers.js @@ -0,0 +1,25 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/treasury/outbound_transfers', + + fail: stripeMethod({ + method: 'POST', + path: '/{outboundTransfer}/fail', + }), + + post: stripeMethod({ + method: 'POST', + path: '/{outboundTransfer}/post', + }), + + returnOutboundTransfer: stripeMethod({ + method: 'POST', + path: '/{outboundTransfer}/return', + }), +}); diff --git a/src/resources/TestHelpers/Treasury/ReceivedCredits.js b/src/resources/TestHelpers/Treasury/ReceivedCredits.js new file mode 100644 index 0000000000..8c3e5f0286 --- /dev/null +++ b/src/resources/TestHelpers/Treasury/ReceivedCredits.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/treasury/received_credits', + + create: stripeMethod({ + method: 'POST', + path: '', + }), +}); diff --git a/src/resources/TestHelpers/Treasury/ReceivedDebits.js b/src/resources/TestHelpers/Treasury/ReceivedDebits.js new file mode 100644 index 0000000000..e25dc03bd2 --- /dev/null +++ b/src/resources/TestHelpers/Treasury/ReceivedDebits.js @@ -0,0 +1,15 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'test_helpers/treasury/received_debits', + + create: stripeMethod({ + method: 'POST', + path: '', + }), +}); diff --git a/src/resources/Tokens.js b/src/resources/Tokens.js new file mode 100644 index 0000000000..76e4d33774 --- /dev/null +++ b/src/resources/Tokens.js @@ -0,0 +1,20 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'tokens', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{token}', + }), +}); diff --git a/src/resources/Topups.js b/src/resources/Topups.js new file mode 100644 index 0000000000..e65fe5d14a --- /dev/null +++ b/src/resources/Topups.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'topups', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{topup}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{topup}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{topup}/cancel', + }), +}); diff --git a/src/resources/Transfers.js b/src/resources/Transfers.js new file mode 100644 index 0000000000..656128c392 --- /dev/null +++ b/src/resources/Transfers.js @@ -0,0 +1,52 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'transfers', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{transfer}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{transfer}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + createReversal: stripeMethod({ + method: 'POST', + path: '/{id}/reversals', + }), + + retrieveReversal: stripeMethod({ + method: 'GET', + path: '/{transfer}/reversals/{id}', + }), + + updateReversal: stripeMethod({ + method: 'POST', + path: '/{transfer}/reversals/{id}', + }), + + listReversals: stripeMethod({ + method: 'GET', + path: '/{id}/reversals', + methodType: 'list', + }), +}); diff --git a/src/resources/Treasury/CreditReversals.js b/src/resources/Treasury/CreditReversals.js new file mode 100644 index 0000000000..9039b816a2 --- /dev/null +++ b/src/resources/Treasury/CreditReversals.js @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/credit_reversals', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{creditReversal}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Treasury/DebitReversals.js b/src/resources/Treasury/DebitReversals.js new file mode 100644 index 0000000000..f95bfe5372 --- /dev/null +++ b/src/resources/Treasury/DebitReversals.js @@ -0,0 +1,26 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/debit_reversals', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{debitReversal}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Treasury/FinancialAccounts.js b/src/resources/Treasury/FinancialAccounts.js new file mode 100644 index 0000000000..a30b1273b6 --- /dev/null +++ b/src/resources/Treasury/FinancialAccounts.js @@ -0,0 +1,41 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/financial_accounts', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{financialAccount}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{financialAccount}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + retrieveFeatures: stripeMethod({ + method: 'GET', + path: '/{financialAccount}/features', + }), + + updateFeatures: stripeMethod({ + method: 'POST', + path: '/{financialAccount}/features', + }), +}); diff --git a/src/resources/Treasury/InboundTransfers.js b/src/resources/Treasury/InboundTransfers.js new file mode 100644 index 0000000000..468adba0e7 --- /dev/null +++ b/src/resources/Treasury/InboundTransfers.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/inbound_transfers', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{inboundTransfer}/cancel', + }), +}); diff --git a/src/resources/Treasury/OutboundPayments.js b/src/resources/Treasury/OutboundPayments.js new file mode 100644 index 0000000000..5d08eaad0d --- /dev/null +++ b/src/resources/Treasury/OutboundPayments.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/outbound_payments', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{id}/cancel', + }), +}); diff --git a/src/resources/Treasury/OutboundTransfers.js b/src/resources/Treasury/OutboundTransfers.js new file mode 100644 index 0000000000..40d72465dd --- /dev/null +++ b/src/resources/Treasury/OutboundTransfers.js @@ -0,0 +1,31 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/outbound_transfers', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{outboundTransfer}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + cancel: stripeMethod({ + method: 'POST', + path: '/{outboundTransfer}/cancel', + }), +}); diff --git a/src/resources/Treasury/ReceivedCredits.js b/src/resources/Treasury/ReceivedCredits.js new file mode 100644 index 0000000000..98b11b1699 --- /dev/null +++ b/src/resources/Treasury/ReceivedCredits.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/received_credits', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Treasury/ReceivedDebits.js b/src/resources/Treasury/ReceivedDebits.js new file mode 100644 index 0000000000..c472144aa9 --- /dev/null +++ b/src/resources/Treasury/ReceivedDebits.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/received_debits', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Treasury/TransactionEntries.js b/src/resources/Treasury/TransactionEntries.js new file mode 100644 index 0000000000..a52c432d68 --- /dev/null +++ b/src/resources/Treasury/TransactionEntries.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/transaction_entries', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/Treasury/Transactions.js b/src/resources/Treasury/Transactions.js new file mode 100644 index 0000000000..a810413116 --- /dev/null +++ b/src/resources/Treasury/Transactions.js @@ -0,0 +1,21 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'treasury/transactions', + + retrieve: stripeMethod({ + method: 'GET', + path: '/{id}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), +}); diff --git a/src/resources/WebhookEndpoints.js b/src/resources/WebhookEndpoints.js new file mode 100644 index 0000000000..2f73d65031 --- /dev/null +++ b/src/resources/WebhookEndpoints.js @@ -0,0 +1,36 @@ +// File generated from our OpenAPI spec + +'use strict'; + +const StripeResource = require('../StripeResource'); +const stripeMethod = StripeResource.method; + +module.exports = StripeResource.extend({ + path: 'webhook_endpoints', + + create: stripeMethod({ + method: 'POST', + path: '', + }), + + retrieve: stripeMethod({ + method: 'GET', + path: '/{webhookEndpoint}', + }), + + update: stripeMethod({ + method: 'POST', + path: '/{webhookEndpoint}', + }), + + list: stripeMethod({ + method: 'GET', + path: '', + methodType: 'list', + }), + + del: stripeMethod({ + method: 'DELETE', + path: '/{webhookEndpoint}', + }), +}); diff --git a/src/stripe.ts b/src/stripe.ts new file mode 100644 index 0000000000..5d6cb7e377 --- /dev/null +++ b/src/stripe.ts @@ -0,0 +1,614 @@ +import _Error = require('./Error'); + +const resources = require('./resources'); + +const DEFAULT_HOST = 'api.stripe.com'; +const DEFAULT_PORT = '443'; +const DEFAULT_BASE_PATH = '/v1/'; +const DEFAULT_API_VERSION = null; + +const DEFAULT_TIMEOUT = 80000; + +Stripe.PACKAGE_VERSION = require('../package.json').version; + +const utils = require('./utils'); +const {determineProcessUserAgentProperties, emitWarning} = utils; + +Stripe.USER_AGENT = { + bindings_version: Stripe.PACKAGE_VERSION, + lang: 'node', + publisher: 'stripe', + uname: null, + typescript: false, + ...determineProcessUserAgentProperties(), +}; + +/** @private */ +Stripe._UNAME_CACHE = null; + +const MAX_NETWORK_RETRY_DELAY_SEC = 2; +const INITIAL_NETWORK_RETRY_DELAY_SEC = 0.5; + +const APP_INFO_PROPERTIES = ['name', 'version', 'url', 'partner_id']; +const ALLOWED_CONFIG_PROPERTIES = [ + 'apiVersion', + 'typescript', + 'maxNetworkRetries', + 'httpAgent', + 'httpClient', + 'timeout', + 'host', + 'port', + 'protocol', + 'telemetry', + 'appInfo', + 'stripeAccount', +]; + +const EventEmitter = require('events').EventEmitter; + +import StripeResource = require('./StripeResource'); +Stripe.StripeResource = StripeResource; +Stripe.resources = resources; + +const {HttpClient, HttpClientResponse} = require('./net/HttpClient'); +Stripe.HttpClient = HttpClient; +Stripe.HttpClientResponse = HttpClientResponse; + +const CryptoProvider = require('./crypto/CryptoProvider'); +Stripe.CryptoProvider = CryptoProvider; + +function Stripe(key, config = {}) { + if (!(this instanceof Stripe)) { + return new (Stripe as any)(key, config); + } + + const props = this._getPropsFromConfig(config); + + Object.defineProperty(this, '_emitter', { + value: new EventEmitter(), + enumerable: false, + configurable: false, + writable: false, + }); + + this.VERSION = Stripe.PACKAGE_VERSION; + + this.on = this._emitter.on.bind(this._emitter); + this.once = this._emitter.once.bind(this._emitter); + this.off = this._emitter.removeListener.bind(this._emitter); + + if ( + props.protocol && + props.protocol !== 'https' && + (!props.host || /\.stripe\.com$/.test(props.host)) + ) { + throw new Error( + 'The `https` protocol must be used when sending requests to `*.stripe.com`' + ); + } + + const agent = props.httpAgent || null; + + this._api = { + auth: null, + host: props.host || DEFAULT_HOST, + port: props.port || DEFAULT_PORT, + protocol: props.protocol || 'https', + basePath: DEFAULT_BASE_PATH, + version: props.apiVersion || DEFAULT_API_VERSION, + timeout: utils.validateInteger('timeout', props.timeout, DEFAULT_TIMEOUT), + maxNetworkRetries: utils.validateInteger( + 'maxNetworkRetries', + props.maxNetworkRetries, + 0 + ), + agent: agent, + httpClient: props.httpClient || Stripe.createNodeHttpClient(agent), + dev: false, + stripeAccount: props.stripeAccount || null, + }; + + const typescript = props.typescript || false; + if (typescript !== Stripe.USER_AGENT.typescript) { + // The mutation here is uncomfortable, but likely fastest; + // serializing the user agent involves shelling out to the system, + // and given some users may instantiate the library many times without switching between TS and non-TS, + // we only want to incur the performance hit when that actually happens. + Stripe.USER_AGENT.typescript = typescript; + } + + if (props.appInfo) { + this._setAppInfo(props.appInfo); + } + + this._prepResources(); + this._setApiKey(key); + + this.errors = _Error; + this.webhooks = require('./Webhooks'); + + this._prevRequestMetrics = []; + this._enableTelemetry = props.telemetry !== false; + + // Expose StripeResource on the instance too + this.StripeResource = Stripe.StripeResource; +} + +Stripe.errors = _Error; +Stripe.webhooks = require('./Webhooks'); + +Stripe.createNodeHttpClient = (agent) => { + const {NodeHttpClient} = require('./net/NodeHttpClient'); + return new NodeHttpClient(agent); +}; + +/** + * Creates an HTTP client for issuing Stripe API requests which uses the Web + * Fetch API. + * + * A fetch function can optionally be passed in as a parameter. If none is + * passed, will default to the default `fetch` function in the global scope. + */ +Stripe.createFetchHttpClient = (fetchFn) => { + const {FetchHttpClient} = require('./net/FetchHttpClient'); + return new FetchHttpClient(fetchFn); +}; + +/** + * Create a CryptoProvider which uses the built-in Node crypto libraries for + * its crypto operations. + */ +Stripe.createNodeCryptoProvider = () => { + const NodeCryptoProvider = require('./crypto/NodeCryptoProvider'); + return new NodeCryptoProvider(); +}; + +/** + * Creates a CryptoProvider which uses the Subtle Crypto API from the Web + * Crypto API spec for its crypto operations. + * + * A SubtleCrypto interface can optionally be passed in as a parameter. If none + * is passed, will default to the default `crypto.subtle` object in the global + * scope. + */ +Stripe.createSubtleCryptoProvider = (subtleCrypto) => { + const SubtleCryptoProvider = require('./crypto/SubtleCryptoProvider'); + return new SubtleCryptoProvider(subtleCrypto); +}; + +Stripe.prototype = { + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * host: 'example.com', + * port: '8080', + * protocol: 'http', + * }); + * + */ + setHost(host, port, protocol) { + emitWarning( + '`setHost` is deprecated. Use the `host` config option instead.' + ); + this._setApiField('host', host); + if (port) { + this.setPort(port); + } + if (protocol) { + this.setProtocol(protocol); + } + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * protocol: 'http', + * }); + * + */ + setProtocol(protocol) { + emitWarning( + '`setProtocol` is deprecated. Use the `protocol` config option instead.' + ); + this._setApiField('protocol', protocol.toLowerCase()); + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * port: 3000, + * }); + * + */ + setPort(port) { + emitWarning( + '`setPort` is deprecated. Use the `port` config option instead.' + ); + this._setApiField('port', port); + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * apiVersion: API_VERSION, + * }); + * + */ + setApiVersion(version) { + emitWarning( + '`setApiVersion` is deprecated. Use the `apiVersion` config or request option instead.' + ); + if (version) { + this._setApiField('version', version); + } + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY); + * + * Or, for Stripe Connect, use `stripeAccount` instead: + * + * const stripe = new Stripe(API_KEY, { + * stripeAccount: 'acct_...', + * }); + * + * Or, to use a different apiKey on a given request: + * + * stripe.customers.create(params, {apiKey: 'sk_test_...'}); + */ + setApiKey(key) { + emitWarning( + '`setApiKey` is deprecated. Use the `apiKey` request option instead.' + ); + this._setApiKey(key); + }, + + /** + * @private + */ + _setApiKey(key) { + if (key) { + this._setApiField('auth', `Bearer ${key}`); + } + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * timeout: TIMEOUT_MS, + * }); + */ + setTimeout(timeout) { + emitWarning( + '`setTimeout` is deprecated. Use the `timeout` config or request option instead.' + ); + this._setApiField('timeout', timeout == null ? DEFAULT_TIMEOUT : timeout); + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * appInfo: { + * name: 'MyPlugin', + * version: '1.4.2', + * url: 'https://myplugin.com', + * partner_id: '1234', + * }, + * }); + */ + setAppInfo(info) { + emitWarning( + '`setAppInfo` is deprecated. Use the `appInfo` config option instead.' + ); + this._setAppInfo(info); + }, + + /** + * @private + * This may be removed in the future. + */ + _setAppInfo(info) { + if (info && typeof info !== 'object') { + throw new Error('AppInfo must be an object.'); + } + + if (info && !info.name) { + throw new Error('AppInfo.name is required'); + } + + info = info || {}; + + const appInfo = APP_INFO_PROPERTIES.reduce( + (accum: Record, prop) => { + if (typeof info[prop] == 'string') { + accum = accum || {}; + + accum[prop] = info[prop]; + } + + return accum; + }, + undefined + ); + + this._appInfo = appInfo; + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const ProxyAgent = require('https-proxy-agent'); + * const stripe = new Stripe(API_KEY, { + * httpAgent: new ProxyAgent(process.env.http_proxy), + * }); + * + */ + setHttpAgent(agent) { + emitWarning( + '`setHttpAgent` is deprecated. Use the `httpAgent` config option instead.' + ); + this._setApiField('agent', agent); + }, + + /** + * @private + * This may be removed in the future. + */ + _setApiField(key, value) { + this._api[key] = value; + }, + + /** + * @private + * Please open or upvote an issue at github.com/stripe/stripe-node + * if you use this, detailing your use-case. + * + * It may be deprecated and removed in the future. + */ + getApiField(key) { + return this._api[key]; + }, + + setClientId(clientId) { + this._clientId = clientId; + }, + + getClientId() { + return this._clientId; + }, + + /** + * @private + * Please open or upvote an issue at github.com/stripe/stripe-node + * if you use this, detailing your use-case. + * + * It may be deprecated and removed in the future. + */ + getConstant: (c) => { + switch (c) { + case 'DEFAULT_HOST': + return DEFAULT_HOST; + case 'DEFAULT_PORT': + return DEFAULT_PORT; + case 'DEFAULT_BASE_PATH': + return DEFAULT_BASE_PATH; + case 'DEFAULT_API_VERSION': + return DEFAULT_API_VERSION; + case 'DEFAULT_TIMEOUT': + return DEFAULT_TIMEOUT; + case 'MAX_NETWORK_RETRY_DELAY_SEC': + return MAX_NETWORK_RETRY_DELAY_SEC; + case 'INITIAL_NETWORK_RETRY_DELAY_SEC': + return INITIAL_NETWORK_RETRY_DELAY_SEC; + } + return Stripe[c]; + }, + + getMaxNetworkRetries() { + return this.getApiField('maxNetworkRetries'); + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * maxNetworkRetries: 2, + * }); + * + */ + setMaxNetworkRetries(maxNetworkRetries) { + this._setApiNumberField('maxNetworkRetries', maxNetworkRetries); + }, + + /** + * @private + * This may be removed in the future. + */ + _setApiNumberField(prop, n, defaultVal) { + const val = utils.validateInteger(prop, n, defaultVal); + + this._setApiField(prop, val); + }, + + getMaxNetworkRetryDelay() { + return MAX_NETWORK_RETRY_DELAY_SEC; + }, + + getInitialNetworkRetryDelay() { + return INITIAL_NETWORK_RETRY_DELAY_SEC; + }, + + /** + * @private + */ + getUname(cb) { + if (!Stripe._UNAME_CACHE) { + Stripe._UNAME_CACHE = new Promise((resolve) => { + utils.safeExec('uname -a', (err, uname) => { + resolve(uname); + }); + }); + } + Stripe._UNAME_CACHE.then((uname) => cb(uname)); + }, + + /** + * @private + * Please open or upvote an issue at github.com/stripe/stripe-node + * if you use this, detailing your use-case. + * + * It may be deprecated and removed in the future. + * + * Gets a JSON version of a User-Agent and uses a cached version for a slight + * speed advantage. + */ + getClientUserAgent(cb) { + return this.getClientUserAgentSeeded(Stripe.USER_AGENT, cb); + }, + + /** + * @private + * Please open or upvote an issue at github.com/stripe/stripe-node + * if you use this, detailing your use-case. + * + * It may be deprecated and removed in the future. + * + * Gets a JSON version of a User-Agent by encoding a seeded object and + * fetching a uname from the system. + */ + getClientUserAgentSeeded(seed, cb) { + this.getUname((uname) => { + const userAgent: Record = {}; + for (const field in seed) { + userAgent[field] = encodeURIComponent(seed[field]); + } + + // URI-encode in case there are unusual characters in the system's uname. + userAgent.uname = encodeURIComponent(uname || 'UNKNOWN'); + + const client = this.getApiField('httpClient'); + if (client) { + userAgent.httplib = encodeURIComponent(client.getClientName()); + } + + if (this._appInfo) { + userAgent.application = this._appInfo; + } + + cb(JSON.stringify(userAgent)); + }); + }, + + /** + * @private + * Please open or upvote an issue at github.com/stripe/stripe-node + * if you use this, detailing your use-case. + * + * It may be deprecated and removed in the future. + */ + getAppInfoAsString() { + if (!this._appInfo) { + return ''; + } + + let formatted = this._appInfo.name; + + if (this._appInfo.version) { + formatted += `/${this._appInfo.version}`; + } + + if (this._appInfo.url) { + formatted += ` (${this._appInfo.url})`; + } + + return formatted; + }, + + /** + * @deprecated will be removed in a future major version. Use the config object instead: + * + * const stripe = new Stripe(API_KEY, { + * telemetry: false, + * }); + * + */ + setTelemetryEnabled(enableTelemetry) { + emitWarning( + '`setTelemetryEnabled` is deprecated. Use the `telemetry` config option instead.' + ); + this._enableTelemetry = enableTelemetry; + }, + + getTelemetryEnabled() { + return this._enableTelemetry; + }, + + /** + * @private + * This may be removed in the future. + */ + _prepResources() { + for (const name in resources) { + this[utils.pascalToCamelCase(name)] = new resources[name](this); + } + }, + + /** + * @private + * This may be removed in the future. + */ + _getPropsFromConfig(config) { + // If config is null or undefined, just bail early with no props + if (!config) { + return {}; + } + + // config can be an object or a string + const isString = typeof config === 'string'; + const isObject = config === Object(config) && !Array.isArray(config); + + if (!isObject && !isString) { + throw new Error('Config must either be an object or a string'); + } + + // If config is a string, we assume the old behavior of passing in a string representation of the api version + if (isString) { + return { + apiVersion: config, + }; + } + + // If config is an object, we assume the new behavior and make sure it doesn't contain any unexpected values + const values = Object.keys(config).filter( + (value) => !ALLOWED_CONFIG_PROPERTIES.includes(value) + ); + + if (values.length > 0) { + throw new Error( + `Config object may only contain the following: ${ALLOWED_CONFIG_PROPERTIES.join( + ', ' + )}` + ); + } + + return config; + }, +}; + +module.exports = Stripe; + +// expose constructor as a named property to enable mocking with Sinon.JS +module.exports.Stripe = Stripe; + +// Allow use with the TypeScript compiler without `esModuleInterop`. +// We may also want to add `Object.defineProperty(exports, "__esModule", {value: true});` in the future, so that Babel users will use the `default` version. +module.exports.default = Stripe; diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000000..7eed41defd --- /dev/null +++ b/src/utils.js @@ -0,0 +1,451 @@ +'use strict'; + +const EventEmitter = require('events').EventEmitter; +const qs = require('qs'); +const crypto = require('crypto'); + +const hasOwn = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop); + +// Certain sandboxed environments (our known example right now are CloudFlare +// Workers) may make `child_process` unavailable. Because `exec` isn't critical +// to the operation of stripe-node, we handle this unavailability gracefully. +let exec = null; +try { + exec = require('child_process').exec; +} catch (e) { + if (e.code !== 'MODULE_NOT_FOUND') { + throw e; + } +} + +const OPTIONS_KEYS = [ + 'apiKey', + 'idempotencyKey', + 'stripeAccount', + 'apiVersion', + 'maxNetworkRetries', + 'timeout', + 'host', +]; + +const DEPRECATED_OPTIONS = { + api_key: 'apiKey', + idempotency_key: 'idempotencyKey', + stripe_account: 'stripeAccount', + stripe_version: 'apiVersion', + stripeVersion: 'apiVersion', +}; +const DEPRECATED_OPTIONS_KEYS = Object.keys(DEPRECATED_OPTIONS); + +const utils = (module.exports = { + isOptionsHash(o) { + return ( + o && + typeof o === 'object' && + (OPTIONS_KEYS.some((prop) => hasOwn(o, prop)) || + DEPRECATED_OPTIONS_KEYS.some((prop) => hasOwn(o, prop))) + ); + }, + + /** + * Stringifies an Object, accommodating nested objects + * (forming the conventional key 'parent[child]=value') + */ + stringifyRequestData: (data) => { + return ( + qs + .stringify(data, { + serializeDate: (d) => Math.floor(d.getTime() / 1000), + }) + // Don't use strict form encoding by changing the square bracket control + // characters back to their literals. This is fine by the server, and + // makes these parameter strings easier to read. + .replace(/%5B/g, '[') + .replace(/%5D/g, ']') + ); + }, + + /** + * Outputs a new function with interpolated object property values. + * Use like so: + * const fn = makeURLInterpolator('some/url/{param1}/{param2}'); + * fn({ param1: 123, param2: 456 }); // => 'some/url/123/456' + */ + makeURLInterpolator: (() => { + const rc = { + '\n': '\\n', + '"': '\\"', + '\u2028': '\\u2028', + '\u2029': '\\u2029', + }; + return (str) => { + const cleanString = str.replace(/["\n\r\u2028\u2029]/g, ($0) => rc[$0]); + return (outputs) => { + return cleanString.replace(/\{([\s\S]+?)\}/g, ($0, $1) => + encodeURIComponent(outputs[$1] || '') + ); + }; + }; + })(), + + extractUrlParams: (path) => { + const params = path.match(/\{\w+\}/g); + if (!params) { + return []; + } + + return params.map((param) => param.replace(/[{}]/g, '')); + }, + + /** + * Return the data argument from a list of arguments + * + * @param {object[]} args + * @returns {object} + */ + getDataFromArgs(args) { + if (!Array.isArray(args) || !args[0] || typeof args[0] !== 'object') { + return {}; + } + + if (!utils.isOptionsHash(args[0])) { + return args.shift(); + } + + const argKeys = Object.keys(args[0]); + + const optionKeysInArgs = argKeys.filter((key) => + OPTIONS_KEYS.includes(key) + ); + + // In some cases options may be the provided as the first argument. + // Here we're detecting a case where there are two distinct arguments + // (the first being args and the second options) and with known + // option keys in the first so that we can warn the user about it. + if ( + optionKeysInArgs.length > 0 && + optionKeysInArgs.length !== argKeys.length + ) { + emitWarning( + `Options found in arguments (${optionKeysInArgs.join( + ', ' + )}). Did you mean to pass an options object? See https://github.com/stripe/stripe-node/wiki/Passing-Options.` + ); + } + + return {}; + }, + + /** + * Return the options hash from a list of arguments + */ + getOptionsFromArgs: (args) => { + const opts = { + auth: null, + headers: {}, + settings: {}, + }; + if (args.length > 0) { + const arg = args[args.length - 1]; + if (typeof arg === 'string') { + opts.auth = args.pop(); + } else if (utils.isOptionsHash(arg)) { + const params = {...args.pop()}; + + const extraKeys = Object.keys(params).filter( + (key) => !OPTIONS_KEYS.includes(key) + ); + + if (extraKeys.length) { + const nonDeprecated = extraKeys.filter((key) => { + if (!DEPRECATED_OPTIONS[key]) { + return true; + } + const newParam = DEPRECATED_OPTIONS[key]; + if (params[newParam]) { + throw Error( + `Both '${newParam}' and '${key}' were provided; please remove '${key}', which is deprecated.` + ); + } + /** + * TODO turn this into a hard error in a future major version (once we have fixed our docs). + */ + emitWarning(`'${key}' is deprecated; use '${newParam}' instead.`); + params[newParam] = params[key]; + }); + if (nonDeprecated.length) { + emitWarning( + `Invalid options found (${extraKeys.join(', ')}); ignoring.` + ); + } + } + + if (params.apiKey) { + opts.auth = params.apiKey; + } + if (params.idempotencyKey) { + opts.headers['Idempotency-Key'] = params.idempotencyKey; + } + if (params.stripeAccount) { + opts.headers['Stripe-Account'] = params.stripeAccount; + } + if (params.apiVersion) { + opts.headers['Stripe-Version'] = params.apiVersion; + } + if (Number.isInteger(params.maxNetworkRetries)) { + opts.settings.maxNetworkRetries = params.maxNetworkRetries; + } + if (Number.isInteger(params.timeout)) { + opts.settings.timeout = params.timeout; + } + if (params.host) { + opts.host = params.host; + } + } + } + return opts; + }, + + /** + * Provide simple "Class" extension mechanism + */ + protoExtend(sub) { + const Super = this; + const Constructor = hasOwn(sub, 'constructor') + ? sub.constructor + : function(...args) { + Super.apply(this, args); + }; + + // This initialization logic is somewhat sensitive to be compatible with + // divergent JS implementations like the one found in Qt. See here for more + // context: + // + // https://github.com/stripe/stripe-node/pull/334 + Object.assign(Constructor, Super); + Constructor.prototype = Object.create(Super.prototype); + Object.assign(Constructor.prototype, sub); + + return Constructor; + }, + + /** + * Secure compare, from https://github.com/freewil/scmp + */ + secureCompare: (a, b) => { + a = Buffer.from(a); + b = Buffer.from(b); + + // return early here if buffer lengths are not equal since timingSafeEqual + // will throw if buffer lengths are not equal + if (a.length !== b.length) { + return false; + } + + // use crypto.timingSafeEqual if available (since Node.js v6.6.0), + // otherwise use our own scmp-internal function. + if (crypto.timingSafeEqual) { + return crypto.timingSafeEqual(a, b); + } + + const len = a.length; + let result = 0; + + for (let i = 0; i < len; ++i) { + result |= a[i] ^ b[i]; + } + return result === 0; + }, + + /** + * Remove empty values from an object + */ + removeNullish: (obj) => { + if (typeof obj !== 'object') { + throw new Error('Argument must be an object'); + } + + return Object.keys(obj).reduce((result, key) => { + if (obj[key] != null) { + result[key] = obj[key]; + } + return result; + }, {}); + }, + + /** + * Normalize standard HTTP Headers: + * {'foo-bar': 'hi'} + * becomes + * {'Foo-Bar': 'hi'} + */ + normalizeHeaders: (obj) => { + if (!(obj && typeof obj === 'object')) { + return obj; + } + + return Object.keys(obj).reduce((result, header) => { + result[utils.normalizeHeader(header)] = obj[header]; + return result; + }, {}); + }, + + /** + * Stolen from https://github.com/marten-de-vries/header-case-normalizer/blob/master/index.js#L36-L41 + * without the exceptions which are irrelevant to us. + */ + normalizeHeader: (header) => { + return header + .split('-') + .map( + (text) => text.charAt(0).toUpperCase() + text.substr(1).toLowerCase() + ) + .join('-'); + }, + + /** + * Determine if file data is a derivative of EventEmitter class. + * https://nodejs.org/api/events.html#events_events + */ + checkForStream: (obj) => { + if (obj.file && obj.file.data) { + return obj.file.data instanceof EventEmitter; + } + return false; + }, + + callbackifyPromiseWithTimeout: (promise, callback) => { + if (callback) { + // Ensure callback is called outside of promise stack. + return promise.then( + (res) => { + setTimeout(() => { + callback(null, res); + }, 0); + }, + (err) => { + setTimeout(() => { + callback(err, null); + }, 0); + } + ); + } + + return promise; + }, + + /** + * Allow for special capitalization cases (such as OAuth) + */ + pascalToCamelCase: (name) => { + if (name === 'OAuth') { + return 'oauth'; + } else { + return name[0].toLowerCase() + name.substring(1); + } + }, + + emitWarning, + + /** + * Node's built in `exec` function sometimes throws outright, + * and sometimes has a callback with an error, + * depending on the type of error. + * + * This unifies that interface. + */ + safeExec: (cmd, cb) => { + // Occurs if we couldn't load the `child_process` module, which might + // happen in certain sandboxed environments like a CloudFlare Worker. + if (utils._exec === null) { + cb(new Error('exec not available'), null); + return; + } + + try { + utils._exec(cmd, cb); + } catch (e) { + cb(e, null); + } + }, + + // For mocking in tests. + _exec: exec, + + isObject: (obj) => { + const type = typeof obj; + return (type === 'function' || type === 'object') && !!obj; + }, + + // For use in multipart requests + flattenAndStringify: (data) => { + const result = {}; + + const step = (obj, prevKey) => { + Object.keys(obj).forEach((key) => { + const value = obj[key]; + + const newKey = prevKey ? `${prevKey}[${key}]` : key; + + if (utils.isObject(value)) { + if (!Buffer.isBuffer(value) && !value.hasOwnProperty('data')) { + // Non-buffer non-file Objects are recursively flattened + return step(value, newKey); + } else { + // Buffers and file objects are stored without modification + result[newKey] = value; + } + } else { + // Primitives are converted to strings + result[newKey] = String(value); + } + }); + }; + + step(data); + + return result; + }, + + /** + * https://stackoverflow.com/a/2117523 + */ + uuid4: () => { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { + const r = (Math.random() * 16) | 0; + const v = c === 'x' ? r : (r & 0x3) | 0x8; + return v.toString(16); + }); + }, + + validateInteger: (name, n, defaultVal) => { + if (!Number.isInteger(n)) { + if (defaultVal !== undefined) { + return defaultVal; + } else { + throw new Error(`${name} must be an integer`); + } + } + + return n; + }, + + determineProcessUserAgentProperties: () => { + return typeof process === 'undefined' + ? {} + : { + lang_version: process.version, + platform: process.platform, + }; + }, +}); + +function emitWarning(warning) { + if (typeof process.emitWarning !== 'function') { + return console.warn( + `Stripe: ${warning}` + ); /* eslint-disable-line no-console */ + } + + return process.emitWarning(warning, 'Stripe'); +} diff --git a/test/stripe.spec.js b/test/stripe.spec.js index 5751a8b692..c2111b39b1 100644 --- a/test/stripe.spec.js +++ b/test/stripe.spec.js @@ -613,4 +613,28 @@ describe('Stripe Module', function() { expect(newStripe.VERSION).to.equal(Stripe.PACKAGE_VERSION); }); }); + + describe('imports', function() { + const runTestProject = (projectName) => { + const script = ` + cd testProjects/${projectName} + npm install + node index.js ${testUtils.getUserStripeKey()} + `; + require('child_process').execSync(script); + }; + + it('should work with CommonJS imports', () => { + expect(runTestProject.bind(null, 'cjs')).to.not.throw(); + }); + + it('should work with ESModule imports', function() { + // Node supports ES Modules starting at v12 + if (parseInt(process.versions.node.split('.')[0], 10) <= 12) { + this.skip(); + } + + expect(runTestProject.bind(null, 'mjs')).to.not.throw(); + }); + }); }); diff --git a/testProjects/cjs/index.js b/testProjects/cjs/index.js new file mode 100644 index 0000000000..eeead7ec23 --- /dev/null +++ b/testProjects/cjs/index.js @@ -0,0 +1,33 @@ +const stripe = require('stripe')(process.argv[2]); + +try { + throw new stripe.errors.StripeError({ + charge: 'foo', + unknown_prop: 'bar', + }); +} catch (e) { + if (e instanceof stripe.errors.StripeError) { + console.log("Caught StripeError"); + } else { + throw e; + } +} + +async function exampleFunction(args) { + try { + await stripe.paymentIntents.create(args); + } catch (e) { + if (e instanceof stripe.errors.StripeInvalidRequestError) { + console.log("Caught StripeInvalidRequestError"); + } else { + throw e; + } + } +} + +exampleFunction({ + // The required parameter currency is missing + amount: 2000, + confirm: true, + payment_method: 'pm_card_visa', +}); diff --git a/testProjects/cjs/package.json b/testProjects/cjs/package.json new file mode 100644 index 0000000000..0415d9242f --- /dev/null +++ b/testProjects/cjs/package.json @@ -0,0 +1,13 @@ +{ + "name": "cjs", + "type": "commonjs", + "version": "1.0.0", + "description": "", + "main": "index.js", + "dependencies": { + "stripe": "file:../../" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +} diff --git a/testProjects/mjs/index.js b/testProjects/mjs/index.js new file mode 100644 index 0000000000..7489b17c16 --- /dev/null +++ b/testProjects/mjs/index.js @@ -0,0 +1,37 @@ +import {Stripe} from 'stripe'; +import DefaultStripe from 'stripe'; + +const stripe = new Stripe(process.argv[2]); +const defaultStripe = new DefaultStripe(process.argv[2]); + +try { + throw new stripe.errors.StripeError({ + charge: 'foo', + unknown_prop: 'bar', + }); +} catch (e) { + if (e instanceof stripe.errors.StripeError) { + console.log("Caught StripeError"); + } else { + throw e; + } +} + +async function exampleFunction(args) { + try { + await stripe.paymentIntents.create(args); + } catch (e) { + if (e instanceof stripe.errors.StripeInvalidRequestError) { + console.log("Caught StripeInvalidRequestError"); + } else { + throw e; + } + } +} + +exampleFunction({ + // The required parameter currency is missing + amount: 2000, + confirm: true, + payment_method: 'pm_card_visa', +}); diff --git a/testProjects/mjs/package.json b/testProjects/mjs/package.json new file mode 100644 index 0000000000..0a66a1509b --- /dev/null +++ b/testProjects/mjs/package.json @@ -0,0 +1,13 @@ +{ + "name": "mjs", + "type": "module", + "version": "1.0.0", + "description": "", + "main": "index.js", + "dependencies": { + "stripe": "file:../../" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..f5cc13096a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "outDir": "./lib", + "allowJs": true, + "target": "es2017", + "module": "commonjs", + "checkJs": false, + }, + "include": ["./src/**/*"] +}