Skip to content

Commit

Permalink
TypeScript definitions [beta] (#736)
Browse files Browse the repository at this point in the history
* First pass

* wip

* More changes

* Split resources by file

* Move to api version folder

* Remove tsconfig, add prettierignore

* Properly generate nested and no-method resources

* Document new TypeScript usage in README

* Add a basic test for typescript correctness

* Better formatting for export of Stripe

* Break out subtypes

* Separate out Address

* Pull empty strings out of enums

* Use all named subresources from openapi

* Rough draft of using shared subresources

* Revert "Rough draft of using shared subresources"

This reverts commit eb9a4d8.

* Fix some bugs I think

* Okay actually go back to normal

* Actually use all shared subresources from openapi

* Revert "Actually use all shared subresources from openapi"

This reverts commit 52136ae.

* Add webhooks.d.ts

* Add and test ApiListPromise for async iteration of lists

* Add better types for ApiList and HeaderOptions

* Rename HeaderOptions to RequestOptions

* Add docs and tests for expanding objects

* Add in reference to webhooks.d.ts

* Update snapshots to reflect reordering

* Add multiple dispatch for optional params

* Add TS tests for multiple dispatch, config, etc

* Move types for setAppInfo

* Add errors

* Fix some formatting

* Remove (Customer) Source and ExternalAccount

* Move metadata back up, add deleted?: void, add eg DeletedCustomer to the union for expandable deletable objects

* Reorder nested methods, rename nested & delete param types, move nested model & param types into their own files

* Remove docstrings from param types since they exist on method definitions

* Reorder required params to be first

* Minor method reorder

* Describe why you have to explicitly reference the types

* Move from vYYYY-MM-DD to YYYY-MM-DD, upgrade api version to 2019-12-03

* Update future version

* Fix param type name and mention esModuleInterop in docs

* Add docstring and test for ApiList

* Add docstrings for errors

* Fix accidentally optional fields

* Add missing values to RawErrorType

* Fix many non-optional fields

* Remove whitespace typo

* Add signature for retrieving a specific account

* Add types for OAuth

* Openapi updates

* Rename Webhooks in git

* Use export default instead of export = so that users dont need to do esModuleInterop

* Add a default export to the runtime

* Also export Stripe as a named export, and as a static property on itself

* Collapse types for setHost

* Require the user to specify the latest API version, use types by default.

* Fix a type error

* Reorganize test, use strictNullChecks etc

* Fix readme

* Unexport error classes to avoid instanceof confusion

* Clarify how to use old api versions with TS

* Fix typo params -> param

* Updates from openapi

* Mark the args to several setters as required

* More accurate handling of deleted resources and required/optional fields

* Erroneous handling of deleted

* Revert "Erroneous handling of deleted"

This reverts commit ad64e33.

* Add comment about deprecated total_count.

* Add shared types for Addresses and Metadata, and update openapi

* Use null intead of empty string

* Fix invoice upcoming lines

* Update openapi

* More empty-string to null translation

* Stop polluting the global namespace by scoping everything under module stripe

* Run eslint & prettier on TS files

* Continue to have poor types for HttpAgent, but with more claity as to why

* Clean up explicit any lint warnings

* Remove constants intended for internal use only

* Extract CustomerSource to a standalone type

* Remove unnecessary export

* Better types for account debit sources

* Use shared RangeQueryParam and PaginationParam

* Add expand param to SubscriptionDeleteParams

* Bring business_type back

* Add docstrings to config options

* Add mandatory `typescript: true` config prop

* Use await in TS readme

* Wrap await in async function

* Many readme updates

* Remove docs on non-public fields/params (we should revert this if it comes up a lot)

* Clarify async/await a bit

* TypeScriptify docstrings for Webhooks

* Add @types/node as a dependency, use it for typing Buffer and http.Agent

* Remove a TODO

Co-authored-by: jlomas-stripe <[email protected]>
  • Loading branch information
rattrayalex-stripe and jlomas-stripe authored Dec 24, 2019
1 parent 09bb044 commit d96a741
Show file tree
Hide file tree
Showing 107 changed files with 34,194 additions and 267 deletions.
204 changes: 105 additions & 99 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,20 @@
The Stripe Node library provides convenient access to the Stripe API from
applications written in server-side JavaScript.

Please keep in mind that this package is for use with server-side Node that
uses Stripe secret keys. To maintain PCI compliance, tokenization of credit
card information should always be done with [Stripe.js][stripe-js] on the
client side. This package should not be used for that purpose.
For collecting customer and payment information in the browser, use [Stripe.js][stripe-js].

## Documentation

See the [`stripe-node` API docs](https://stripe.com/docs/api/node#intro) for Node.js.
See the [`stripe-node` API docs](https://stripe.com/docs/api?lang=node) for Node.js.

## Installation

Install the package with:

```sh
npm install stripe --save
# or
yarn add stripe
```

## Usage
Expand All @@ -32,73 +31,83 @@ The package needs to be configured with your account's secret key which is
available in your [Stripe Dashboard][api-keys]. Require it with the key's
value:

<!-- prettier-ignore -->
```js
const stripe = require('stripe')('sk_test_...');

const customer = await stripe.customers.create({
stripe.customers.create({
email: '[email protected]',
});
})
.then(customer => console.log(customer.id))
.catch(error => console.error(error));
```

Or using ES modules, this looks more like:
Or using ES modules and `async`/`await`:

```js
import Stripe from 'stripe';
const stripe = Stripe('sk_test_...');
//
const stripe = new Stripe('sk_test_...');

(async () => {
const customer = await stripe.customers.create({
email: '[email protected]',
});

console.log(customer.id);
})();
```

## Initialize with config object
### Usage with TypeScript

The package can be initialized with several options:
As of 8.0.0, Stripe maintains types for the latest [API version][api-versions].

```js
import ProxyAgent from 'https-proxy-agent';
Import Stripe as a default import (not `* as Stripe`, unlike the DefinitelyTyped version)
and instantiate it as `new Stripe()` with the latest API version.

const stripe = Stripe('sk_test_...', {
apiVersion: '2019-08-08',
maxNetworkRetries: 1,
httpAgent: new ProxyAgent(process.env.http_proxy),
timeout: 1000,
host: 'api.example.com',
port: 123,
telemetry: true,
```ts
import Stripe from 'stripe';
const stripe = new Stripe('sk_test_...', {
apiVersion: '2019-12-03',
typescript: true,
});
```

| Option | Default | Description |
| ------------------- | ----------------------------- | ------------------------------------------------------------------------------------- |
| `apiVersion` | `null` | Stripe API version to be used. If not set the account's default version will be used. |
| `maxNetworkRetries` | 0 | The amount of times a request should be [retried](#network-retries). |
| `httpAgent` | `null` | [Proxy](#configuring-a-proxy) agent to be used by the library. |
| `timeout` | 120000 (Node default timeout) | [Maximum time each request can take in ms.](#configuring-timeout) |
| `host` | `'api.stripe.com'` | Host that requests are made to. |
| `port` | 443 | Port that requests are made to. |
| `telemetry` | `true` | Allow Stripe to send latency [telemetry](#request-latency-telemetry) |
const createCustomer = async () => {
const params: Stripe.CustomerCreateParams = {
description: 'test customer',
};

Note: Both `maxNetworkRetries` and `timeout` can be overridden on a per-request basis. `timeout` can be updated at any time with [`stripe.setTimeout`](#configuring-timeout).
const customer: Stripe.Customer = await stripe.customers.create(params);

### Usage with TypeScript
console.log(customer.id);
};
createCustomer();
```

Stripe does not currently maintain typings for this package, but there are
community typings available from DefinitelyTyped.
#### Using old API versions with TypeScript

To install:
Types can change between API versions (eg; Stripe may have changed a field from a string to a hash),
so our types only reflect the latest API version.

```sh
npm install --dev @types/stripe
```
We therefore encourage [upgrading your API version][api-version-upgrading]
if you would like to take advantage of Stripe's TypeScript definitions.

To use:
If you are on an older API version (eg; `2019-10-17`) and not able to upgrade,
you may pass another version or `apiVersion: null` to use your account's default API version,
and use a comment like `// @ts-ignore stripe-version-2019-10-17` to silence type errors here
and anywhere the types differ between your API version and the latest.
When you upgrade, you should remove these comments.

```ts
// Note `* as` and `new Stripe` for TypeScript:
import * as Stripe from 'stripe';
const stripe = new Stripe('sk_test_...');
#### Using `expand` with TypeScript

const customer: Promise<
Stripe.customers.ICustomer
> = stripe.customers.create(/* ... */);
[Expandable][expanding_objects] fields are typed as `string | Foo`,
so you must cast them appropriately, eg;

```ts
const charge: Stripe.Charge = await stripe.charges.retrieve('ch_123', {
expand: ['customer'],
});
const customerEmail: string = (charge.customer as Stripe.Customer).email;
const btId: string = charge.balance_transaction as string;
```

### Using Promises
Expand Down Expand Up @@ -132,62 +141,81 @@ stripe.customers
});
```

### Configuring Timeout
## Configuration

### Initialize with config object

Request timeout is configurable (the default is Node's default of 120 seconds):
The package can be initialized with several options:

```js
stripe.setTimeout(20000); // in ms (this is 20 seconds)
import ProxyAgent from 'https-proxy-agent';

const stripe = Stripe('sk_test_...', {
apiVersion: '2019-08-08',
maxNetworkRetries: 1,
httpAgent: new ProxyAgent(process.env.http_proxy),
timeout: 1000,
host: 'api.example.com',
port: 123,
telemetry: true,
});
```

Timeout can also be set globally via the config object:
| Option | Default | Description |
| ------------------- | ----------------------------- | ------------------------------------------------------------------------------------- |
| `apiVersion` | `null` | Stripe API version to be used. If not set the account's default version will be used. |
| `maxNetworkRetries` | 0 | The amount of times a request should be [retried](#network-retries). |
| `httpAgent` | `null` | [Proxy](#configuring-a-proxy) agent to be used by the library. |
| `timeout` | 120000 (Node default timeout) | [Maximum time each request can take in ms.](#configuring-timeout) |
| `host` | `'api.stripe.com'` | Host that requests are made to. |
| `port` | 443 | Port that requests are made to. |
| `telemetry` | `true` | Allow Stripe to send latency [telemetry](#request-latency-telemetry) |

Note: Both `maxNetworkRetries` and `timeout` can be overridden on a per-request basis.

### Configuring Timeout

Timeout can be set globally via the config object:

```js
const stripe = Stripe('sk_test_...', {
timeout: 2000,
timeout: 20 * 1000, // 20 seconds
});
```

And on a per-request basis:
And overridden on a per-request basis:

```js
stripe.customers.create(
{
email: '[email protected]',
},
{
timeout: 1000,
timeout: 1000, // 1 second
}
);
```

If `timeout` is set globally via the config object, the value set in a per-request basis will be favored.

### Configuring For Connect

A per-request `Stripe-Account` header for use with [Stripe Connect][connect]
can be added to any method:

```js
// Retrieve the balance for a connected account:
stripe.balance
.retrieve({
// List the balance transactions for a connected account:
stripe.balanceTransactions.list(
{
limit: 10,
},
{
stripeAccount: 'acct_foo',
})
.then((balance) => {
// The balance object for the connected account
})
.catch((err) => {
// Error
});
}
);
```

### Configuring a Proxy

An [https-proxy-agent][https-proxy-agent] can be configured with
`setHttpAgent`.

To use stripe behind a proxy you can pass to sdk on initialization:
To use stripe behind a proxy you can pass an [https-proxy-agent][https-proxy-agent] on initialization:

```js
if (process.env.http_proxy) {
Expand Down Expand Up @@ -338,7 +366,6 @@ This information is passed along when the library makes calls to the Stripe API.

### Auto-pagination

As of stripe-node 6.11.0, you may auto-paginate list methods.
We provide a few different APIs for this to aid with a variety of node versions and styles.

#### Async iterators (`for-await-of`)
Expand Down Expand Up @@ -389,32 +416,6 @@ stripe.customers
.catch(handleError);
```

If you prefer callbacks to promises, you may also use a `next` callback and a second `onDone` callback:

```js
stripe.customers.list().autoPagingEach(
function onItem(customer, next) {
doSomething(customer, function(err, result) {
if (shouldStop(result)) {
next(false); // Passing `false` breaks out of the loop.
} else {
next();
}
});
},
function onDone(err) {
if (err) {
console.error(err);
} else {
console.log('Done iterating.');
}
}
);
```

If your `onItem` function does not accept a `next` callback parameter _or_ return a Promise,
the return value is used to decide whether to continue (`false` breaks, anything else continues).

#### `autoPagingToArray`

This is a convenience for cases where you expect the number of items
Expand All @@ -437,7 +438,9 @@ numbers help Stripe improve the overall latency of its API for all users.
You can disable this behavior if you prefer:

```js
stripe.setTelemetryEnabled(false);
const stripe = new Stripe('sk_test_...', {
telemetry: false,
});
```

## More Information
Expand Down Expand Up @@ -487,7 +490,10 @@ $ yarn fix
```

[api-keys]: https://dashboard.stripe.com/account/apikeys
[api-versions]: https://stripe.com/docs/api/versioning
[api-version-upgrading]: https://stripe.com/docs/upgrades#how-can-i-upgrade-my-api
[connect]: https://stripe.com/connect
[expanding_objects]: https://stripe.com/docs/api/expanding_objects
[https-proxy-agent]: https://github.com/TooTallNate/node-https-proxy-agent
[stripe-js]: https://stripe.com/docs/stripe.js

Expand Down
29 changes: 14 additions & 15 deletions lib/resources/Accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,25 @@ const stripeMethod = StripeResource.method;
module.exports = StripeResource.extend({
path: '',

reject: stripeMethod({
method: 'POST',
path: 'accounts/{account}/reject',
}),

create: stripeMethod({
method: 'POST',
path: 'accounts',
}),

del: stripeMethod({
method: 'DELETE',
path: 'accounts/{account}',
}),

list: stripeMethod({
method: 'GET',
path: 'accounts',
methodType: 'list',
}),

update: stripeMethod({
reject: stripeMethod({
method: 'POST',
path: 'accounts/{id}',
}),

// Avoid 'delete' keyword in JS
del: stripeMethod({
method: 'DELETE',
path: 'accounts/{id}',
path: 'accounts/{account}/reject',
}),

retrieve(id) {
Expand All @@ -54,9 +48,9 @@ module.exports = StripeResource.extend({
}
},

createLoginLink: stripeMethod({
update: stripeMethod({
method: 'POST',
path: 'accounts/{account}/login_links',
path: 'accounts/{account}',
}),

listCapabilities: stripeMethod({
Expand Down Expand Up @@ -101,6 +95,11 @@ module.exports = StripeResource.extend({
path: 'accounts/{account}/external_accounts/{id}',
}),

createLoginLink: stripeMethod({
method: 'POST',
path: 'accounts/{account}/login_links',
}),

createPerson: stripeMethod({
method: 'POST',
path: 'accounts/{account}/persons',
Expand Down
1 change: 1 addition & 0 deletions lib/resources/Balance.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ module.exports = StripeResource.extend({

retrieve: stripeMethod({
method: 'GET',
path: '',
}),
});
Loading

0 comments on commit d96a741

Please sign in to comment.