Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate other Stripe infrastructure to TS #1563

Merged
merged 13 commits into from
Sep 28, 2022
Merged
10 changes: 8 additions & 2 deletions lib/Webhooks.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions lib/apiVersion.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/crypto/SubtleCryptoProvider.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions lib/multipart.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/net/FetchHttpClient.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lib/net/NodeHttpClient.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 16 additions & 8 deletions lib/utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"node-fetch": "^2.6.2",
"nyc": "^15.1.0",
"prettier": "^1.16.4",
"typescript": "^3.7.2"
"typescript": "^4.8.3"
},
"resolutions": {
"ansi-regex": "5.0.1",
Expand Down
2 changes: 0 additions & 2 deletions src/ResourceNamespace.js → src/ResourceNamespace.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'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`.

Expand Down
16 changes: 10 additions & 6 deletions src/Webhooks.js → src/Webhooks.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict';

const utils = require('./utils');
const {StripeError, StripeSignatureVerificationError} = require('./Error');
import utils = require('./utils');
import _Error = require('./Error');
const {StripeError, StripeSignatureVerificationError} = _Error;

const Webhook = {
DEFAULT_TOLERANCE: 300, // 5 minutes
signature: null,
anniel-stripe marked this conversation as resolved.
Show resolved Hide resolved

constructEvent(payload, header, secret, tolerance, cryptoProvider) {
this.signature.verifyHeader(
Expand Down Expand Up @@ -169,6 +169,7 @@ function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) {
if (!details || details.timestamp === -1) {
throw new StripeSignatureVerificationError({
message: 'Unable to extract timestamp and signatures from header',
// @ts-expect-error Type '{ decodedHeader: any; decodedPayload: any; }' is not assignable to type 'string'.
anniel-stripe marked this conversation as resolved.
Show resolved Hide resolved
detail: {
decodedHeader,
decodedPayload,
Expand All @@ -179,6 +180,7 @@ function parseEventDetails(encodedPayload, encodedHeader, expectedScheme) {
if (!details.signatures.length) {
throw new StripeSignatureVerificationError({
message: 'No signatures found with expected scheme',
// @ts-expect-error Type '{ decodedHeader: any; decodedPayload: any; }' is not assignable to type 'string'.
detail: {
decodedHeader,
decodedPayload,
Expand Down Expand Up @@ -210,6 +212,7 @@ function validateComputedSignature(
'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',
// @ts-expect-error Type '{ header: any; payload: any; }' is not assignable to type 'string'.
detail: {
header,
payload,
Expand All @@ -222,6 +225,7 @@ function validateComputedSignature(
if (tolerance > 0 && timestampAge > tolerance) {
throw new StripeSignatureVerificationError({
message: 'Timestamp outside the tolerance zone',
// @ts-expect-error Type '{ header: any; payload: any; }' is not assignable to type 'string'.
detail: {
header,
payload,
Expand All @@ -242,7 +246,7 @@ function parseHeader(header, scheme) {
const kv = item.split('=');

if (kv[0] === 't') {
accum.timestamp = kv[1];
accum.timestamp = parseInt(kv[1], 10);
}

if (kv[0] === scheme) {
Expand Down Expand Up @@ -274,4 +278,4 @@ function getNodeCryptoProvider() {

Webhook.signature = signature;

module.exports = Webhook;
export = Webhook;
8 changes: 3 additions & 5 deletions src/crypto/CryptoProvider.js → src/crypto/CryptoProvider.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use strict';

/**
* Interface encapsulating the various crypto computations used by the library,
* allowing pluggable underlying crypto implementations.
Expand All @@ -13,7 +11,7 @@ class CryptoProvider {
* - computeHMACSignature('', 'test_secret') => 'f7f9bd47fb987337b5796fdc1fdb9ba221d0d5396814bfcaf9521f43fd8927fd'
* - computeHMACSignature('\ud83d\ude00', 'test_secret') => '837da296d05c4fe31f61d5d7ead035099d9585a5bcde87de952012a78f0b0c43
*/
computeHMACSignature(payload, secret) {
computeHMACSignature(payload: string, secret: string): string {
throw new Error('computeHMACSignature not implemented.');
}

Expand All @@ -28,9 +26,9 @@ class CryptoProvider {
* - computeHMACSignature('', 'test_secret') => 'f7f9bd47fb987337b5796fdc1fdb9ba221d0d5396814bfcaf9521f43fd8927fd'
* - computeHMACSignature('\ud83d\ude00', 'test_secret') => '837da296d05c4fe31f61d5d7ead035099d9585a5bcde87de952012a78f0b0c43
*/
computeHMACSignatureAsync(payload, secret) {
computeHMACSignatureAsync(payload: string, secret: string): Promise<string> {
throw new Error('computeHMACSignatureAsync not implemented.');
}
}

module.exports = CryptoProvider;
export = CryptoProvider;
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
'use strict';
import crypto = require('crypto');

const crypto = require('crypto');

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

/**
* `CryptoProvider which uses the Node `crypto` package for its computations.
*/
class NodeCryptoProvider extends CryptoProvider {
/** @override */
computeHMACSignature(payload, secret) {
computeHMACSignature(payload: string, secret: string): string {
return crypto
.createHmac('sha256', secret)
.update(payload, 'utf8')
.digest('hex');
}

/** @override */
async computeHMACSignatureAsync(payload, secret) {
async computeHMACSignatureAsync(
payload: string,
secret: string
): Promise<string> {
const signature = await this.computeHMACSignature(payload, secret);
return signature;
}
}

module.exports = NodeCryptoProvider;
export = NodeCryptoProvider;
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
'use strict';

const CryptoProvider = require('./CryptoProvider');
import 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) {
subtleCrypto: SubtleCrypto;

constructor(subtleCrypto: SubtleCrypto) {
super();

// If no subtle crypto is interface, default to the global namespace. This
Expand All @@ -18,15 +18,18 @@ class SubtleCryptoProvider extends CryptoProvider {
}

/** @override */
computeHMACSignature(payload, secret) {
computeHMACSignature(payload: string, secret: string): string {
throw new Error(
'SubtleCryptoProvider cannot be used in a synchronous context.'
);
}

/** @override */
async computeHMACSignatureAsync(payload, secret) {
const encoder = new TextEncoder('utf-8');
async computeHMACSignatureAsync(
payload: string,
secret: string
): Promise<string> {
const encoder = new TextEncoder();
anniel-stripe marked this conversation as resolved.
Show resolved Hide resolved

const key = await this.subtleCrypto.importKey(
'raw',
Expand Down Expand Up @@ -66,4 +69,4 @@ for (let i = 0; i < byteHexMapping.length; i++) {
byteHexMapping[i] = i.toString(16).padStart(2, '0');
}

module.exports = SubtleCryptoProvider;
export = SubtleCryptoProvider;
13 changes: 7 additions & 6 deletions src/multipart.js → src/multipart.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use strict';

const utils = require('./utils');
const {StripeError} = require('./Error');
import utils = require('./utils');
import _Error = require('./Error');
const {StripeError} = _Error;

class StreamProcessingError extends StripeError {}

Expand Down Expand Up @@ -33,7 +32,7 @@ const multipartDataGenerator = (method, data, headers) => {
for (const k in flattenedData) {
const v = flattenedData[k];
push(`--${segno}`);
if (v.hasOwnProperty('data')) {
if (Object.prototype.hasOwnProperty.call(v, 'data')) {
push(
`Content-Disposition: form-data; name=${q(k)}; filename=${q(
v.name || 'blob'
Expand Down Expand Up @@ -93,4 +92,6 @@ const multipartRequestDataProcessor = (method, data, headers, callback) => {
return callback(null, buffer);
};

module.exports.multipartRequestDataProcessor = multipartRequestDataProcessor;
export = {
multipartRequestDataProcessor: multipartRequestDataProcessor,
};