Skip to content

Commit

Permalink
Merge pull request #1543 from stripe/anniel-ts-infrastructure
Browse files Browse the repository at this point in the history
Migrate Stripe infrastructure to Typescript
  • Loading branch information
anniel-stripe authored Sep 6, 2022
2 parents 7d20c8e + aa07eb4 commit 6fb6573
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 65 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ module.exports = {
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/no-empty-function': 0,
'@typescript-eslint/camelcase': 0,
'@typescript-eslint/no-var-requires': 0,
'@typescript-eslint/no-explicit-any': 0,
'@typescript-eslint/explicit-function-return-type': 0,
'prefer-rest-params': 'off',
Expand Down
92 changes: 65 additions & 27 deletions src/Error.js → src/Error.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,63 @@
'use strict';

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 {
constructor(raw = {}) {
export 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;

Expand Down Expand Up @@ -60,83 +112,69 @@ class StripeError extends Error {
* CardError is raised when a user enters a card that can't be charged for
* some reason.
*/
class StripeCardError extends StripeError {}
export class StripeCardError extends StripeError {}

/**
* InvalidRequestError is raised when a request is initiated with invalid
* parameters.
*/
class StripeInvalidRequestError extends StripeError {}
export 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 {}
export class StripeAPIError extends StripeError {}

/**
* AuthenticationError is raised when invalid credentials are used to connect
* to Stripe's servers.
*/
class StripeAuthenticationError extends StripeError {}
export class StripeAuthenticationError extends StripeError {}

/**
* PermissionError is raised in cases where access was attempted on a resource
* that wasn't allowed.
*/
class StripePermissionError extends StripeError {}
export 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 {}
export 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 {}
export class StripeConnectionError extends StripeError {}

/**
* SignatureVerificationError is raised when the signature verification for a
* webhook fails
*/
class StripeSignatureVerificationError extends StripeError {}
export class StripeSignatureVerificationError extends StripeError {}

/**
* IdempotencyError is raised in cases where an idempotency key was used
* improperly.
*/
class StripeIdempotencyError extends StripeError {}
export 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 {}
export 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;
export class StripeUnknownError extends StripeError {}
9 changes: 4 additions & 5 deletions src/StripeMethod.js → src/StripeMethod.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use strict';

const utils = require('./utils');
const makeRequest = require('./makeRequest');
const makeAutoPaginationMethods = require('./autoPagination')
.makeAutoPaginationMethods;
import utils = require('./utils');
import makeRequest = require('./makeRequest');
import {makeAutoPaginationMethods} from './autoPagination';

/**
* Create an API method from the declared spec.
Expand Down Expand Up @@ -55,4 +54,4 @@ function stripeMethod(spec) {
};
}

module.exports = stripeMethod;
export = stripeMethod;
14 changes: 7 additions & 7 deletions src/StripeResource.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
'use strict';

const utils = require('./utils');
const {
StripeConnectionError,
import utils = require('./utils');
import {
StripeAPIError,
StripeAuthenticationError,
StripeConnectionError,
StripeError,
StripePermissionError,
StripeRateLimitError,
StripeError,
StripeAPIError,
} = require('./Error');
} from './Error';

const {HttpClient} = require('./net/HttpClient');
import {HttpClient} from './net/HttpClient';

type Settings = {
timeout?: number;
Expand Down
15 changes: 9 additions & 6 deletions src/autoPagination.js → src/autoPagination.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
'use strict';

const makeRequest = require('./makeRequest');
const utils = require('./utils');
import utils = require('./utils');
import makeRequest = require('./makeRequest');

function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) {
export function makeAutoPaginationMethods(
self,
requestArgs,
spec,
firstPagePromise
) {
const promiseCache = {currentPromise: null};
const reverseIteration = isReverseIteration(requestArgs);
let pagePromise = firstPagePromise;
Expand Down Expand Up @@ -94,8 +99,6 @@ function makeAutoPaginationMethods(self, requestArgs, spec, firstPagePromise) {
return autoPaginationMethods;
}

module.exports.makeAutoPaginationMethods = makeAutoPaginationMethods;

/**
* ----------------
* Private Helpers:
Expand Down Expand Up @@ -242,7 +245,7 @@ function makeAutoPagingToArray(autoPagingEach) {
}

function wrapAsyncIteratorWithCallback(asyncIteratorNext, onItem) {
return new Promise((resolve, reject) => {
return new Promise<void>((resolve, reject) => {
function handleIteration(iterResult) {
if (iterResult.done) {
resolve();
Expand Down
4 changes: 2 additions & 2 deletions src/makeRequest.js → src/makeRequest.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

const utils = require('./utils');
import utils = require('./utils');

function getRequestOpts(self, requestArgs, spec, overrideData) {
// Extract spec values with defaults.
Expand Down Expand Up @@ -119,4 +119,4 @@ function makeRequest(self, requestArgs, spec, overrideData) {
});
}

module.exports = makeRequest;
export = makeRequest;
39 changes: 22 additions & 17 deletions src/stripe.js → src/stripe.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
'use strict';

const resources = require('./resources');
import resources = require('./resources');
import utils = require('./utils');

import {HttpClient, HttpClientResponse} from './net/HttpClient';
import {FetchHttpClient} from './net/FetchHttpClient';
import {NodeHttpClient} from './net/NodeHttpClient';

import CryptoProvider = require('./crypto/CryptoProvider');
import NodeCryptoProvider = require('./crypto/NodeCryptoProvider');
import SubtleCryptoProvider = require('./crypto/SubtleCryptoProvider');

const DEFAULT_HOST = 'api.stripe.com';
const DEFAULT_PORT = '443';
Expand All @@ -11,7 +20,6 @@ const DEFAULT_TIMEOUT = 80000;

Stripe.PACKAGE_VERSION = require('../package.json').version;

const utils = require('./utils');
const {determineProcessUserAgentProperties, emitWarning} = utils;

Stripe.USER_AGENT = {
Expand Down Expand Up @@ -50,16 +58,14 @@ const EventEmitter = require('events').EventEmitter;
Stripe.StripeResource = require('./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);
return new (Stripe as any)(key, config);
}

const props = this._getPropsFromConfig(config);
Expand Down Expand Up @@ -138,7 +144,6 @@ Stripe.errors = require('./Error');
Stripe.webhooks = require('./Webhooks');

Stripe.createNodeHttpClient = (agent) => {
const {NodeHttpClient} = require('./net/NodeHttpClient');
return new NodeHttpClient(agent);
};

Expand All @@ -150,7 +155,6 @@ Stripe.createNodeHttpClient = (agent) => {
* passed, will default to the default `fetch` function in the global scope.
*/
Stripe.createFetchHttpClient = (fetchFn) => {
const {FetchHttpClient} = require('./net/FetchHttpClient');
return new FetchHttpClient(fetchFn);
};

Expand All @@ -159,7 +163,6 @@ Stripe.createFetchHttpClient = (fetchFn) => {
* its crypto operations.
*/
Stripe.createNodeCryptoProvider = () => {
const NodeCryptoProvider = require('./crypto/NodeCryptoProvider');
return new NodeCryptoProvider();
};

Expand All @@ -172,7 +175,6 @@ Stripe.createNodeCryptoProvider = () => {
* scope.
*/
Stripe.createSubtleCryptoProvider = (subtleCrypto) => {
const SubtleCryptoProvider = require('./crypto/SubtleCryptoProvider');
return new SubtleCryptoProvider(subtleCrypto);
};

Expand Down Expand Up @@ -326,15 +328,18 @@ Stripe.prototype = {

info = info || {};

const appInfo = APP_INFO_PROPERTIES.reduce((accum, prop) => {
if (typeof info[prop] == 'string') {
accum = accum || {};
const appInfo = APP_INFO_PROPERTIES.reduce(
(accum: Record<string, any>, prop) => {
if (typeof info[prop] == 'string') {
accum = accum || {};

accum[prop] = info[prop];
}
accum[prop] = info[prop];
}

return accum;
}, undefined);
return accum;
},
undefined
);

this._appInfo = appInfo;
},
Expand Down Expand Up @@ -483,7 +488,7 @@ Stripe.prototype = {
*/
getClientUserAgentSeeded(seed, cb) {
this.getUname((uname) => {
const userAgent = {};
const userAgent: any = {};
for (const field in seed) {
userAgent[field] = encodeURIComponent(seed[field]);
}
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"outDir": "./lib",
"allowJs": true,
"target": "es6",
"module": "commonjs",
"checkJs": false,
},
"include": ["./src/**/*"]
Expand Down

0 comments on commit 6fb6573

Please sign in to comment.