├── .editorconfig ├── .eslintrc ├── .github ├── FUNDING.yml ├── contributing.md ├── issue_template.md ├── pull_request_template.md ├── stale.yml └── workflows │ └── nodejs.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.config.ts ├── package-lock.json ├── package.json ├── src ├── index.ts ├── services │ ├── account-links.ts │ ├── account.ts │ ├── application-fee-refund.ts │ ├── balance-transactions.ts │ ├── balance.ts │ ├── bank-account.ts │ ├── base.ts │ ├── card.ts │ ├── charge.ts │ ├── coupon.ts │ ├── customer.ts │ ├── dispute.ts │ ├── event.ts │ ├── external-account.ts │ ├── index.ts │ ├── invoice-item.ts │ ├── invoice.ts │ ├── payment-intent.ts │ ├── payment-method.ts │ ├── payout.ts │ ├── plan.ts │ ├── price.ts │ ├── product.ts │ ├── refund.ts │ ├── setup-intent.ts │ ├── source.ts │ ├── subscription-item.ts │ ├── subscription.ts │ ├── token.ts │ ├── transaction.ts │ ├── transfer-reversal.ts │ ├── transfer.ts │ └── webhook.ts └── types.ts ├── test ├── error-handler.test.ts ├── filter-params.test.ts ├── index.test.ts └── tsconfig.json ├── tsconfig.json └── vite.config.mts /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "env": { 4 | "node": true 5 | }, 6 | "parser": "@typescript-eslint/parser", 7 | "plugins": ["@typescript-eslint", "prettier"], 8 | "extends": [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "prettier" 12 | ], 13 | "rules": { 14 | "quotes": ["warn", "double", "avoid-escape"], 15 | "indent": ["warn", 2, { "SwitchCase": 1 }], 16 | "semi": ["warn", "always"], 17 | "@typescript-eslint/no-unused-vars": "warn", 18 | "no-console": "off", 19 | "camelcase": "warn", 20 | "require-atomic-updates": "off", 21 | "prefer-destructuring": [ 22 | "warn", 23 | { 24 | "AssignmentExpression": { "object": false, "array": false }, 25 | "VariableDeclarator": { "object": true, "array": true } 26 | }, 27 | { 28 | "enforceForRenamedProperties": false 29 | } 30 | ], 31 | "object-curly-spacing": ["warn", "always"], 32 | "prefer-const": ["warn"], 33 | "@typescript-eslint/consistent-type-imports": [ 34 | "warn", 35 | { "prefer": "type-imports" } 36 | ] 37 | }, 38 | "overrides": [ 39 | { 40 | "files": ["test/**/*.ts"], 41 | "rules": { 42 | "@typescript-eslint/ban-ts-comment": ["off"], 43 | "@typescript-eslint/no-explicit-any": ["off"], 44 | "@typescript-eslint/no-unused-vars": ["off"] 45 | } 46 | } 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ daffl ] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing to Feathers 2 | 3 | Thank you for contributing to Feathers! :heart: :tada: 4 | 5 | This repo is the main core and where most issues are reported. Feathers embraces modularity and is broken up across many repos. To make this easier to manage we currently use [Zenhub](https://www.zenhub.com/) for issue triage and visibility. They have a free browser plugin you can install so that you can see what is in flight at any time, but of course you also always see current issues in Github. 6 | 7 | ## Report a bug 8 | 9 | Before creating an issue please make sure you have checked out the docs, specifically the [FAQ](https://docs.feathersjs.com/help/faq.html) section. You might want to also try searching Github. It's pretty likely someone has already asked a similar question. 10 | 11 | If you haven't found your answer please feel free to join our [slack channel](http://slack.feathersjs.com), create an issue on Github, or post on [Stackoverflow](http://stackoverflow.com) using the `feathers` or `feathersjs` tag. We try our best to monitor Stackoverflow but you're likely to get more immediate responses in Slack and Github. 12 | 13 | Issues can be reported in the [issue tracker](https://github.com/feathersjs/feathers/issues). Since feathers combines many modules it can be hard for us to assess the root cause without knowing which modules are being used and what your configuration looks like, so **it helps us immensely if you can link to a simple example that reproduces your issue**. 14 | 15 | ## Report a Security Concern 16 | 17 | We take security very seriously at Feathers. We welcome any peer review of our 100% open source code to ensure nobody's Feathers app is ever compromised or hacked. As a web application developer you are responsible for any security breaches. We do our very best to make sure Feathers is as secure as possible by default. 18 | 19 | In order to give the community time to respond and upgrade we strongly urge you report all security issues to us. Send one of the core team members a PM in [Slack](http://slack.feathersjs.com) or email us at hello@feathersjs.com with details and we will respond ASAP. 20 | 21 | For full details refer to our [Security docs](https://docs.feathersjs.com/SECURITY.html). 22 | 23 | ## Pull Requests 24 | 25 | We :heart: pull requests and we're continually working to make it as easy as possible for people to contribute, including a [Plugin Generator](https://github.com/feathersjs/generator-feathers-plugin) and a [common test suite](https://github.com/feathersjs/feathers-service-tests) for database adapters. 26 | 27 | We prefer small pull requests with minimal code changes. The smaller they are the easier they are to review and merge. A core team member will pick up your PR and review it as soon as they can. They may ask for changes or reject your pull request. This is not a reflection of you as an engineer or a person. Please accept feedback graciously as we will also try to be sensitive when providing it. 28 | 29 | Although we generally accept many PRs they can be rejected for many reasons. We will be as transparent as possible but it may simply be that you do not have the same context or information regarding the roadmap that the core team members have. We value the time you take to put together any contributions so we pledge to always be respectful of that time and will try to be as open as possible so that you don't waste it. :smile: 30 | 31 | **All PRs (except documentation) should be accompanied with tests and pass the linting rules.** 32 | 33 | ### Code style 34 | 35 | Before running the tests from the `test/` folder `npm test` will run ESlint. You can check your code changes individually by running `npm run lint`. 36 | 37 | ### Tests 38 | 39 | [Mocha](http://mochajs.org/) tests are located in the `test/` folder and can be run using the `npm run mocha` or `npm test` (with ESLint and code coverage) command. 40 | 41 | ### Documentation 42 | 43 | Feathers documentation is contained in Markdown files in the [feathers-docs](https://github.com/feathersjs/feathers-docs) repository. To change the documentation submit a pull request to that repo, referencing any other PR if applicable, and the docs will be updated with the next release. 44 | 45 | ## External Modules 46 | 47 | If you're written something awesome for Feathers, the Feathers ecosystem, or using Feathers please add it to the [showcase](https://docs.feathersjs.com/why/showcase.html). You also might want to check out the [Plugin Generator](https://github.com/feathersjs/generator-feathers-plugin) that can be used to scaffold plugins to be Feathers compliant from the start. 48 | 49 | If you think it would be a good core module then please contact one of the Feathers core team members in [Slack](http://slack.feathersjs.com) and we can discuss whether it belongs in core and how to get it there. :beers: 50 | 51 | ## Contributor Code of Conduct 52 | 53 | As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities. 54 | 55 | We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 56 | 57 | Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct. 58 | 59 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team. 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers. 62 | 63 | This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/) 64 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Steps to reproduce 2 | 3 | (First please check that this issue is not already solved as [described 4 | here](https://github.com/feathersjs/feathers/blob/master/.github/contributing.md#report-a-bug)) 5 | 6 | - [ ] Tell us what broke. The more detailed the better. 7 | - [ ] If you can, please create a simple example that reproduces the issue and link to a gist, jsbin, repo, etc. 8 | 9 | ### Expected behavior 10 | Tell us what should happen 11 | 12 | ### Actual behavior 13 | Tell us what happens instead 14 | 15 | ### System configuration 16 | 17 | Tell us about the applicable parts of your setup. 18 | 19 | **Module versions** (especially the part that's not working): 20 | 21 | **NodeJS version**: 22 | 23 | **Operating System**: 24 | 25 | **Browser Version**: 26 | 27 | **React Native Version**: 28 | 29 | **Module Loader**: -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ### Summary 2 | 3 | (If you have not already please refer to the contributing guideline as [described 4 | here](https://github.com/feathersjs/feathers/blob/master/.github/contributing.md#pull-requests)) 5 | 6 | - [ ] Tell us about the problem your pull request is solving. 7 | - [ ] Are there any open issues that are related to this? 8 | - [ ] Is this PR dependent on PRs in other repos? 9 | 10 | If so, please mention them to keep the conversations linked together. 11 | 12 | ### Other Information 13 | 14 | If there's anything else that's important and relevant to your pull 15 | request, mention that information here. This could include 16 | benchmarks, or other information. 17 | 18 | Your PR will be reviewed by a core team member and they will work with you to get your changes merged in a timely manner. If merged your PR will automatically be added to the changelog in the next release. 19 | 20 | If your changes involve documentation updates please mention that and link the appropriate PR in [feathers-docs](https://github.com/feathersjs/feathers-docs). 21 | 22 | Thanks for contributing to Feathers! :heart: -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 84 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - greenkeeper 8 | - bug 9 | - security 10 | - enhancement 11 | # Label to use when marking an issue as stale 12 | staleLabel: wontfix 13 | # Comment to post when marking an issue as stale. Set to `false` to disable 14 | markComment: > 15 | This issue has been automatically marked as stale because it has not had 16 | recent activity. It will be closed if no further activity occurs. 17 | Apologies if the issue could not be resolved. FeathersJS ecosystem 18 | modules are community maintained so there may be a chance that there isn't anybody 19 | available to address the issue at the moment. 20 | For other ways to get help [see here](https://docs.feathersjs.com/help/readme.html). 21 | # Comment to post when closing a stale issue. Set to `false` to disable 22 | closeComment: false 23 | # Only close stale issues 24 | only: issues 25 | -------------------------------------------------------------------------------- /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: [push, pull_request] 3 | jobs: 4 | test: 5 | runs-on: ubuntu-latest 6 | strategy: 7 | matrix: 8 | node-version: [16.x, 18.x] 9 | steps: 10 | - uses: actions/checkout@v3 11 | - name: Use Node.js ${{ matrix.node-version }} 12 | uses: actions/setup-node@v3 13 | with: 14 | node-version: ${{ matrix.node-version }} 15 | - run: npm install 16 | - run: npm run test 17 | 18 | build: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v3 22 | - uses: actions/setup-node@v3 23 | with: 24 | node-version: 18.x 25 | - run: npm install 26 | - run: npm run build 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Logs 4 | logs 5 | *.log 6 | 7 | # Runtime data 8 | pids 9 | *.pid 10 | *.seed 11 | 12 | # Directory for instrumented libs generated by jscoverage/JSCover 13 | lib-cov 14 | 15 | # Coverage directory used by tools like istanbul 16 | coverage 17 | 18 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 19 | .grunt 20 | 21 | # Compiled binary addons (http://nodejs.org/api/addons.html) 22 | build/Release 23 | 24 | # Dependency directory 25 | # Commenting this out is preferred by some people, see 26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 27 | node_modules 28 | 29 | # Users Environment Variables 30 | .lock-wscript 31 | 32 | dist/ 33 | 34 | *.env 35 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [Unreleased](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/HEAD) 4 | 5 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v3.1.0...HEAD) 6 | 7 | **Merged pull requests:** 8 | 9 | - feat: add balance transactions service [\#120](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/120) ([TheNoim](https://github.com/TheNoim)) 10 | 11 | ## [v3.1.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v3.1.0) (2024-07-17) 12 | 13 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v3.0.0...v3.1.0) 14 | 15 | ## [v3.0.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v3.0.0) (2024-02-02) 16 | 17 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v2.0.0...v3.0.0) 18 | 19 | **Merged pull requests:** 20 | 21 | - feat: search for customer and invoice [\#119](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/119) ([TheNoim](https://github.com/TheNoim)) 22 | 23 | ## [v2.0.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v2.0.0) (2023-08-31) 24 | 25 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v1.0.1...v2.0.0) 26 | 27 | **Merged pull requests:** 28 | 29 | - dove & typescript refactor [\#118](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/118) ([fratzinger](https://github.com/fratzinger)) 30 | 31 | ## [v1.0.1](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v1.0.1) (2022-03-23) 32 | 33 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v1.0.0...v1.0.1) 34 | 35 | ## [v1.0.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v1.0.0) (2022-03-23) 36 | 37 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.11.0...v1.0.0) 38 | 39 | **Merged pull requests:** 40 | 41 | - Add auto pagination support [\#115](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/115) ([DaddyWarbucks](https://github.com/DaddyWarbucks)) 42 | - Add generic options to service [\#109](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/109) ([DaddyWarbucks](https://github.com/DaddyWarbucks)) 43 | - Add Price service [\#108](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/108) ([DaddyWarbucks](https://github.com/DaddyWarbucks)) 44 | - Add underscored methods to services [\#107](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/107) ([DaddyWarbucks](https://github.com/DaddyWarbucks)) 45 | 46 | ## [v0.11.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.11.0) (2021-07-31) 47 | 48 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.10.1...v0.11.0) 49 | 50 | **Merged pull requests:** 51 | 52 | - Added stripe Application Fee Refunds feature [\#103](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/103) ([fazilvp](https://github.com/fazilvp)) 53 | - fix typing error [\#102](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/102) ([shakir-abdo](https://github.com/shakir-abdo)) 54 | - Fix Typo in README [\#101](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/101) ([ericirish](https://github.com/ericirish)) 55 | - Pass data forward on capture [\#97](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/97) ([mrfrase3](https://github.com/mrfrase3)) 56 | - Greenkeeper/stripe 8.28.1 [\#96](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/96) ([daffl](https://github.com/daffl)) 57 | - Fixes sample code for preventing external access [\#95](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/95) ([emmanuelgeoffray](https://github.com/emmanuelgeoffray)) 58 | - Add webhook [\#93](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/93) ([ydeshayes](https://github.com/ydeshayes)) 59 | - Greenkeeper/stripe 8.18.0 [\#91](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/91) ([daffl](https://github.com/daffl)) 60 | - adds account links service [\#89](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/89) ([regmish](https://github.com/regmish)) 61 | - Update all dependencies [\#85](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/85) ([daffl](https://github.com/daffl)) 62 | 63 | ## [v0.10.1](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.10.1) (2019-09-11) 64 | 65 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.10.0...v0.10.1) 66 | 67 | **Merged pull requests:** 68 | 69 | - Remove attach from payment method data [\#78](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/78) ([dottodot](https://github.com/dottodot)) 70 | - Update all dependencies and run tests [\#77](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/77) ([daffl](https://github.com/daffl)) 71 | - Update @feathersjs/feathers to the latest version 🚀 [\#74](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/74) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 72 | - Update @feathersjs/errors to the latest version 🚀 [\#73](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/73) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 73 | 74 | ## [v0.10.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.10.0) (2019-08-16) 75 | 76 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.9.1...v0.10.0) 77 | 78 | **Merged pull requests:** 79 | 80 | - Added stripe SetupIntent feature [\#71](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/71) ([fazilvp](https://github.com/fazilvp)) 81 | 82 | ## [v0.9.1](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.9.1) (2019-08-13) 83 | 84 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.9.0...v0.9.1) 85 | 86 | **Merged pull requests:** 87 | 88 | - Migration for stripe v7 balance transaction [\#70](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/70) ([fazilvp](https://github.com/fazilvp)) 89 | 90 | ## [v0.9.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.9.0) (2019-08-07) 91 | 92 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.8.0...v0.9.0) 93 | 94 | **Merged pull requests:** 95 | 96 | - Change Card Methods [\#69](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/69) ([jordan-mcrae](https://github.com/jordan-mcrae)) 97 | - Greenkeeper/stripe 7.5.2 [\#67](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/67) ([daffl](https://github.com/daffl)) 98 | 99 | ## [v0.8.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.8.0) (2019-07-03) 100 | 101 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.7.1...v0.8.0) 102 | 103 | **Merged pull requests:** 104 | 105 | - Greenkeeper/stripe 7.4.0 [\#66](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/66) ([daffl](https://github.com/daffl)) 106 | - \#64 Query Account Balances [\#65](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/65) ([DaddyWarbucks](https://github.com/DaddyWarbucks)) 107 | - Feature/62 charge remove [\#63](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/63) ([DaddyWarbucks](https://github.com/DaddyWarbucks)) 108 | - Greenkeeper/stripe 7.3.0 [\#61](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/61) ([daffl](https://github.com/daffl)) 109 | 110 | ## [v0.7.1](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.7.1) (2019-05-30) 111 | 112 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.7.0...v0.7.1) 113 | 114 | **Merged pull requests:** 115 | 116 | - Add paymentMethod Service [\#59](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/59) ([dottodot](https://github.com/dottodot)) 117 | - Update stripe to the latest version 🚀 [\#58](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/58) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 118 | - Greenkeeper/stripe 6.34.0 [\#57](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/57) ([daffl](https://github.com/daffl)) 119 | - Update mocha to the latest version 🚀 [\#55](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/55) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 120 | - Update README.md [\#54](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/54) ([fmoessle](https://github.com/fmoessle)) 121 | 122 | ## [v0.7.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.7.0) (2019-01-22) 123 | 124 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.6.0...v0.7.0) 125 | 126 | **Merged pull requests:** 127 | 128 | - External accounts [\#53](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/53) ([daffl](https://github.com/daffl)) 129 | - Add payment intent and source service [\#52](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/52) ([dottodot](https://github.com/dottodot)) 130 | 131 | ## [v0.6.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.6.0) (2018-12-19) 132 | 133 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.5.0...v0.6.0) 134 | 135 | **Merged pull requests:** 136 | 137 | - Update all dependencies [\#51](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/51) ([daffl](https://github.com/daffl)) 138 | - Update error handler so original error message is supplied in data [\#50](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/50) ([dottodot](https://github.com/dottodot)) 139 | - Update semistandard to the latest version 🚀 [\#46](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/46) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 140 | - Update debug to the latest version 🚀 [\#44](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/44) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 141 | 142 | ## [v0.5.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.5.0) (2018-08-21) 143 | 144 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.4.1...v0.5.0) 145 | 146 | **Merged pull requests:** 147 | 148 | - Add SubscriptionItem service [\#42](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/42) ([wdmtech](https://github.com/wdmtech)) 149 | - Add params to remove method for Subscriptions [\#41](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/41) ([wdmtech](https://github.com/wdmtech)) 150 | - Update stripe to the latest version 🚀 [\#39](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/39) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 151 | 152 | ## [v0.4.1](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.4.1) (2018-02-02) 153 | 154 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.4.0...v0.4.1) 155 | 156 | **Merged pull requests:** 157 | 158 | - Add a base service [\#37](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/37) ([daffl](https://github.com/daffl)) 159 | 160 | ## [v0.4.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.4.0) (2018-01-31) 161 | 162 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.3.3...v0.4.0) 163 | 164 | **Merged pull requests:** 165 | 166 | - Rename repository and generate initial changelog [\#36](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/36) ([daffl](https://github.com/daffl)) 167 | - Refactor to export service classes directly and update Readme [\#35](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/35) ([daffl](https://github.com/daffl)) 168 | - Update to new plugin infrastructure and Feathers 3 [\#34](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/34) ([daffl](https://github.com/daffl)) 169 | - Update mocha to the latest version 🚀 [\#33](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/33) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 170 | - Update semistandard to the latest version 🚀 [\#32](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/32) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 171 | - Payouts [\#31](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/31) ([adamvr](https://github.com/adamvr)) 172 | - Update mocha to the latest version 🚀 [\#29](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/29) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 173 | - Update stripe to the latest version 🚀 [\#28](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/28) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 174 | - Update debug to the latest version 🚀 [\#25](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/25) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 175 | - Update chai to the latest version 🚀 [\#18](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/18) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 176 | - Update feathers-socketio to the latest version 🚀 [\#16](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/16) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 177 | - Update semistandard to the latest version 🚀 [\#15](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/15) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 178 | - Update feathers-hooks to the latest version 🚀 [\#14](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/14) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 179 | 180 | ## [v0.3.3](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.3.3) (2017-09-27) 181 | 182 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.3.2...v0.3.3) 183 | 184 | ## [v0.3.2](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.3.2) (2017-09-07) 185 | 186 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.3.1...v0.3.2) 187 | 188 | ## [v0.3.1](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.3.1) (2017-04-14) 189 | 190 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.3.0...v0.3.1) 191 | 192 | **Merged pull requests:** 193 | 194 | - Update dependencies to enable Greenkeeper 🌴 [\#13](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/13) ([greenkeeper[bot]](https://github.com/apps/greenkeeper)) 195 | - apiKey -\> secretKey in README.md [\#11](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/11) ([bedeoverend](https://github.com/bedeoverend)) 196 | - jshint —\> semistandard [\#10](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/10) ([corymsmith](https://github.com/corymsmith)) 197 | 198 | ## [v0.3.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.3.0) (2016-09-20) 199 | 200 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.2.0...v0.3.0) 201 | 202 | **Merged pull requests:** 203 | 204 | - 0.3 [\#6](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/6) ([ekryski](https://github.com/ekryski)) 205 | - Updates the card service as per latest Stripe docs [\#4](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/4) ([bedeoverend](https://github.com/bedeoverend)) 206 | - Add subscription service [\#3](https://github.com/feathersjs-ecosystem/feathers-stripe/pull/3) ([bedeoverend](https://github.com/bedeoverend)) 207 | 208 | ## [v0.2.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.2.0) (2016-08-08) 209 | 210 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/v0.1.0...v0.2.0) 211 | 212 | ## [v0.1.0](https://github.com/feathersjs-ecosystem/feathers-stripe/tree/v0.1.0) (2016-03-22) 213 | 214 | [Full Changelog](https://github.com/feathersjs-ecosystem/feathers-stripe/compare/e1230dfedefb01ca41bfc2ca127ac7671f11164b...v0.1.0) 215 | 216 | 217 | 218 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 219 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2023 Feathers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # feathers-stripe 2 | 3 | [![CI](https://github.com/feathersjs-ecosystem/feathers-stripe/workflows/CI/badge.svg)](https://github.com/feathersjs-ecosystem/feathers-stripe/actions?query=workflow%3ACI) 4 | [![Dependency Status](https://img.shields.io/librariesio/release/npm/feathers-stripe)](https://libraries.io/npm/feathers-stripe) 5 | [![Download Status](https://img.shields.io/npm/dm/feathers-stripe.svg?style=flat-square)](https://www.npmjs.com/package/feathers-stripe) 6 | [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/qa8kez8QBx) 7 | 8 | > A Feathers service for Stripe 9 | 10 | ## Installation 11 | 12 | ``` 13 | npm install stripe@^13 feathers-stripe --save 14 | ``` 15 | 16 | ## Documentation 17 | 18 | Please refer to the [Stripe API Docs](https://stripe.com/docs/api/node) and the [stripe-node docs](https://github.com/stripe/stripe-node) for options that can be passed. Feathers service methods map to the following Stripe methods: 19 | 20 | - Feathers `find` -> Stripe `list` 21 | - Feathers `get` -> Stripe `retrieve` 22 | - Feathers `create` -> Stripe `create` 23 | - Feathers `update` -> Stripe `update` 24 | - Feathers `patch` -> Stripe `update` (in most cases). Some special cases include paying an invoice or an order when you pass `{pay: true}` as part of `context.data`. See each service's code for more info. 25 | - Feathers `remove` -> Stripe `del` (in most cases). Some special cases include transfers and charges create a reversal/refund. See each service's code for more info. 26 | 27 | If a method is not supported by Stripe for a given resource it is not supported here as well. 28 | 29 | Use `params.stripe` to pass additional parameters like `expand`, `idempotencyKey`, `apiVersion`, etc to the underlying Stripe methods. 30 | 31 | Many methods support/require passing special properties to `context.data` and `context.query` to better inform the underlying stripe methods. You are encouraged to read the source code for each service to better understand their usage. For example, the `Card` service requires a `customer` to be provided. 32 | 33 | ```ts 34 | const card = await app.service("stripe/cards").create({ 35 | customer: "cust_123", 36 | source: { token: "tok_123" } 37 | }); 38 | // stripe.customers.createSource(customer, { source: { ... } }); 39 | 40 | const card = await app.service("stripe/cards").get("card_123", { 41 | query: { customer: "cust_123" } 42 | }); 43 | // stripe.customers.retrieveSource(query.customer, id); 44 | ``` 45 | 46 | ### Available Services 47 | 48 | The following services are supported and map to the appropriate Stripe resource: 49 | 50 | - `AccountLinks` 51 | - `Account` 52 | - `ApplicationFeeRefund` 53 | - `Balance` 54 | - `BankAccount` 55 | - `Card` 56 | - `Charge` 57 | - `Coupon` 58 | - `Customer` 59 | - `Dispute` 60 | - `Event` 61 | - `ExternalAccount` 62 | - `InvoiceItem` 63 | - `Invoice` 64 | - `PaymentIntent` 65 | - `PaymentMethod` 66 | - `Payout` 67 | - `Plan` 68 | - `Price` 69 | - `Product` 70 | - `Recipient` 71 | - `Refund` 72 | - `SetupIntent` 73 | - `Source` 74 | - `SubscriptionItem` 75 | - `Subscription` 76 | - `Token` 77 | - `Transaction` 78 | - `TransferReversal` 79 | - `Transfer` 80 | - `Webhook` 81 | 82 | **This is pretty important!** Since this connects to your Stripe account you want to make sure that you don't expose these endpoints via your app unless the user has the appropriate permissions. You can prevent any external access by doing this: 83 | 84 | ```ts 85 | import { Forbidden } from "@feathersjs/errors"; 86 | 87 | app.service("stripe/cards").hooks({ 88 | before: { 89 | all: [ 90 | (context) => { 91 | if (context.params.provider) { 92 | throw new Forbidden("You are not allowed to access this"); 93 | } 94 | } 95 | ] 96 | } 97 | }); 98 | ``` 99 | 100 | **This is pretty important!** You are also encouraged to use some kind of rate limiter. Checkout the [Stripe Rate Limit Docs](https://stripe.com/docs/rate-limits) 101 | 102 | ```ts 103 | import Bottleneck from 'bottleneck'; 104 | 105 | // Configure 100 reqs/second for production, 25 for test mode 106 | const readLimiter = new Bottleneck({ minTime: 10 }); 107 | const writeLimiter = new Bottleneck({ minTime: 10 }); 108 | // const readLimiter = new Bottleneck({ minTime: 40 }); 109 | // const writeLimiter = new Bottleneck({ minTime: 40 }); 110 | 111 | const rateLimitHook = async (context) => { 112 | const limiter = context.method === 'find' || context.method === 'get' 113 | ? readLimiter 114 | : writeLimiter; 115 | 116 | context.result = await limiter.schedule(() => { 117 | // Use an underscored method to bypass hooks and not end 118 | // up in an infinite loop hitting this hook again. 119 | if (context.method === 'find') { 120 | return context.service._find(context.params); 121 | } 122 | if (context.method === 'get') { 123 | return context.service._get(context.id, context.params); 124 | } 125 | if (context.method === 'create') { 126 | return context.service._create(context.data, context.params); 127 | } 128 | if (context.method === 'update') { 129 | return context.service._update(context.id, context.data, context.params); 130 | } 131 | if (context.method === 'patch') { 132 | return context.service._patch(context.id, context.data, context.params); 133 | } 134 | if (context.method === 'remove') { 135 | return context.service._remove(context.id context.params); 136 | } 137 | }); 138 | 139 | return context; 140 | } 141 | 142 | // The rateLimitHook should be the last before hook for each method. 143 | app.service('stripe/cards').hooks({ 144 | before: { 145 | find: [ ...hooks, rateLimitHook], 146 | get: [ ...hooks, rateLimitHook], 147 | create: [ ...hooks, rateLimitHook], 148 | update: [ ...hooks, rateLimitHook], 149 | patch: [ ...hooks, rateLimitHook], 150 | remove: [ ...hooks, rateLimitHook], 151 | } 152 | }); 153 | ``` 154 | 155 | ## Complete Example 156 | 157 | Here's an example of a Feathers server that uses `feathers-authentication` for local auth. It includes a `users` service that uses `feathers-mongoose`. _Note that it does NOT implement any authorization._ 158 | 159 | ```ts 160 | import { feathers } from "@feathersjs/feathers"; 161 | import express from "@feathersjs/express"; 162 | import socketio from "@feathersjs/socketio"; 163 | import Stripe from 'stripe'; 164 | import { ChargeService } from "feathers-stripe"; 165 | 166 | // Initialize the application 167 | const app = feathers() 168 | .configure(express.rest()) 169 | .configure(socketio()) 170 | // Needed for parsing bodies (login) 171 | .use(express.json()) 172 | .use(express.urlencoded({ extended: true })) 173 | // A simple Message service that we can used for testing 174 | .use( 175 | "/stripe/charges", 176 | new ChargeService({ stripe: new Stripe('sk_test_...') }) 177 | ) 178 | .use("/", feathers.static(__dirname + "/public")) 179 | .use(express.errorHandler({ html: false })); 180 | 181 | const validateCharge = () => (hook) => { 182 | console.log("Validating charge code goes here"); 183 | }; 184 | 185 | const chargeService = app.service("stripe/charges"); 186 | 187 | chargeService.hooks({ 188 | before: { 189 | create: [validateCharge()] 190 | } 191 | }); 192 | 193 | const charge = { 194 | amount: 400, 195 | currency: "cad", 196 | source: "tok_87rau6axWXeqLq", // obtained with Stripe.js 197 | description: "Charge for test@example.com" 198 | }; 199 | 200 | chargeService 201 | .create(charge) 202 | .then((result) => { 203 | console.log("Charge created", result); 204 | }) 205 | .catch((error) => { 206 | console.log("Error creating charge", error); 207 | }); 208 | 209 | app.listen(3030); 210 | 211 | console.log("Feathers authentication app started on 127.0.0.1:3030"); 212 | ``` 213 | 214 | ## Webhook 215 | 216 | You can setup a webhook using the helper function `setupWebhook` in your service 217 | 218 | ```ts 219 | export default function (app) { 220 | setupWebhook(app, "/stripe-webhook", { 221 | endpointSecret: "whsec_ededqwdwqdqwdqwd778qwdwqdq", 222 | stripe: new Stripe("sk_test_..."), 223 | handlers: { 224 | customer: { 225 | subscription: { 226 | async created({ object, event, params, app }) { 227 | return {}; 228 | } 229 | } 230 | } 231 | } 232 | }); 233 | 234 | // Get our initialized service so that we can register hooks 235 | const service = app.service("stripe-webhook"); 236 | 237 | service.hooks(hooks); 238 | } 239 | ``` 240 | 241 | ## License 242 | 243 | Licensed under the [MIT license](LICENSE). 244 | -------------------------------------------------------------------------------- /build.config.ts: -------------------------------------------------------------------------------- 1 | import { defineBuildConfig } from "unbuild"; 2 | import pkg from "./package.json"; 3 | 4 | export default defineBuildConfig({ 5 | entries: ["./src/index"], 6 | outDir: "./dist", 7 | declaration: true, 8 | externals: [ 9 | ...Object.keys(pkg.dependencies), 10 | ...Object.keys(pkg.devDependencies) 11 | ], 12 | rollup: { 13 | emitCJS: true 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "feathers-stripe", 3 | "description": "A Feathers service for Stripe", 4 | "version": "3.1.0", 5 | "homepage": "https://github.com/feathersjs-ecosystem/feathers-stripe", 6 | "keywords": [ 7 | "stripe", 8 | "feathers", 9 | "feathers-plugin" 10 | ], 11 | "license": "MIT", 12 | "repository": { 13 | "type": "git", 14 | "url": "git://github.com/feathersjs-ecosystem/feathers-stripe.git" 15 | }, 16 | "author": { 17 | "name": "Feathers contributors", 18 | "email": "hello@feathersjs.com", 19 | "url": "https://feathersjs.com" 20 | }, 21 | "contributors": [], 22 | "bugs": { 23 | "url": "https://github.com/feathersjs-ecosystem/feathers-stripe/issues" 24 | }, 25 | "exports": { 26 | ".": { 27 | "types": "./dist/index.d.ts", 28 | "import": "./dist/index.mjs", 29 | "require": "./dist/index.cjs" 30 | } 31 | }, 32 | "main": "./dist/index.cjs", 33 | "module": "./dist/index.mjs", 34 | "types": "./dist/index.d.ts", 35 | "engines": { 36 | "node": ">= 16" 37 | }, 38 | "files": [ 39 | "CHANGELOG.md", 40 | "LICENSE", 41 | "README.md", 42 | "src/**", 43 | "dist/**" 44 | ], 45 | "scripts": { 46 | "build": "unbuild", 47 | "changelog": "github_changelog_generator --no-issues -p feathers-stripe -u feathersjs-ecosystem && git add CHANGELOG.md && git commit -am \"Updating changelog\"", 48 | "publish": "git push origin --tags && npm run changelog && git push origin", 49 | "preversion": "npm run lint && npm run test && npm run build", 50 | "release:patch": "npm version patch && npm publish", 51 | "release:minor": "npm version minor && npm publish", 52 | "release:major": "npm version major && npm publish", 53 | "lint": "eslint src/**/*.ts test/**/*.ts --fix", 54 | "vitest": "vitest --typecheck", 55 | "test": "vitest run --typecheck", 56 | "coverage": "vitest run --coverage" 57 | }, 58 | "dependencies": { 59 | "@feathersjs/adapter-commons": "^5.0.21", 60 | "@feathersjs/commons": "^5.0.21", 61 | "@feathersjs/errors": "^5.0.21", 62 | "@feathersjs/express": "^5.0.21", 63 | "@feathersjs/feathers": "^5.0.21", 64 | "debug": "^4.3.4", 65 | "stripe": "^14.14.0" 66 | }, 67 | "devDependencies": { 68 | "@types/debug": "^4.1.8", 69 | "@types/node": "^20.11.16", 70 | "@typescript-eslint/eslint-plugin": "^6.20.0", 71 | "@typescript-eslint/parser": "^6.20.0", 72 | "eslint": "^8.48.0", 73 | "eslint-config-prettier": "^9.0.0", 74 | "eslint-plugin-import": "^2.28.1", 75 | "eslint-plugin-prefer-arrow": "^1.2.3", 76 | "eslint-plugin-prettier": "^5.0.0", 77 | "prettier": "^3.0.3", 78 | "unbuild": "^2.0.0", 79 | "vite": "^5.0.12", 80 | "vitest": "^1.2.2" 81 | }, 82 | "peerDependencies": { 83 | "@feathersjs/feathers": "^5.0.0", 84 | "stripe": "^14.14.0" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./services"; 2 | 3 | export * from "./types"; 4 | -------------------------------------------------------------------------------- /src/services/account-links.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { ParamsWithStripe } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IAccountLinksService { 6 | _find: never; 7 | _get: never; 8 | _create( 9 | data: Stripe.AccountLinkCreateParams, 10 | params: ParamsWithStripe 11 | ): Promise; 12 | _update: never; 13 | _patch: never; 14 | _remove: never; 15 | } 16 | 17 | export class AccountLinkService 18 | extends BaseService 19 | implements IAccountLinksService 20 | { 21 | _create(data: Stripe.AccountLinkCreateParams, params: ParamsWithStripe) { 22 | const { stripe } = this.filterParams(params); 23 | 24 | return this.stripe.accountLinks.create(data, stripe); 25 | } 26 | 27 | _find: never; 28 | _get: never; 29 | _update: never; 30 | _patch: never; 31 | _remove: never; 32 | } 33 | -------------------------------------------------------------------------------- /src/services/account.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { 3 | FindMethod, 4 | ParamsWithStripe, 5 | ParamsWithStripeQuery 6 | } from "../types"; 7 | import { BaseService } from "./base"; 8 | 9 | export interface IAccountService { 10 | _find: FindMethod< 11 | ParamsWithStripeQuery, 12 | Stripe.Account 13 | >; 14 | _get: (id: string, params: ParamsWithStripe) => Promise; 15 | _create: ( 16 | data: Stripe.AccountCreateParams, 17 | params: ParamsWithStripe 18 | ) => Promise; 19 | _update: ( 20 | id: string, 21 | data: Stripe.AccountUpdateParams, 22 | params: ParamsWithStripe 23 | ) => Promise; 24 | _patch: ( 25 | id: string, 26 | data: Stripe.AccountUpdateParams, 27 | params: ParamsWithStripe 28 | ) => Promise; 29 | _remove: never; 30 | } 31 | 32 | export class AccountService 33 | extends BaseService 34 | implements IAccountService 35 | { 36 | _find(params: ParamsWithStripeQuery) { 37 | const filtered = this.filterParams(params); 38 | return this.handlePaginate( 39 | filtered, 40 | this.stripe.accounts.list(filtered.query, filtered.stripe) 41 | ); 42 | } 43 | 44 | async _get(id: string, params: ParamsWithStripe) { 45 | const { stripe } = this.filterParams(params); 46 | 47 | return this.stripe.accounts.retrieve(id, stripe); 48 | } 49 | 50 | _create(data: Stripe.AccountCreateParams, params: ParamsWithStripe) { 51 | const { stripe } = this.filterParams(params); 52 | return this.stripe.accounts.create(data, stripe); 53 | } 54 | 55 | _update( 56 | id: string, 57 | data: Stripe.AccountUpdateParams, 58 | params: ParamsWithStripe 59 | ) { 60 | const { stripe } = this.filterParams(params); 61 | return this.stripe.accounts.update(id, data, stripe); 62 | } 63 | 64 | _patch( 65 | id: string, 66 | data: Stripe.AccountUpdateParams, 67 | params: ParamsWithStripe 68 | ) { 69 | return this._update(id, data, params); 70 | } 71 | 72 | _remove: never; 73 | } 74 | -------------------------------------------------------------------------------- /src/services/application-fee-refund.ts: -------------------------------------------------------------------------------- 1 | import makeDebug from "debug"; 2 | import type Stripe from "stripe"; 3 | import type { 4 | FindMethod, 5 | ParamsWithStripeFee, 6 | ParamsWithStripeQuery 7 | } from "../types"; 8 | import { BaseService } from "./base"; 9 | 10 | const debug = makeDebug("feathers-stripe:application-fee-refund"); 11 | 12 | export interface IApplicationFeeRefundService { 13 | _find: FindMethod< 14 | ParamsWithStripeQuery, 15 | Stripe.FeeRefund 16 | >; 17 | _get: (id: string, params: ParamsWithStripeFee) => Promise; 18 | _create: ( 19 | data: Stripe.FeeRefundCreateParams, 20 | params: ParamsWithStripeFee 21 | ) => Promise; 22 | _update: ( 23 | id: string, 24 | data: Stripe.FeeRefundUpdateParams, 25 | params: ParamsWithStripeFee 26 | ) => Promise; 27 | _patch: ( 28 | id: string, 29 | data: Stripe.FeeRefundUpdateParams, 30 | params: ParamsWithStripeFee 31 | ) => Promise; 32 | _remove: never; 33 | } 34 | 35 | export class ApplicationFeeRefundService 36 | extends BaseService 37 | implements IApplicationFeeRefundService 38 | { 39 | _find( 40 | params: ParamsWithStripeQuery< 41 | Stripe.ApplicationFeeListParams & { fee: string } 42 | > 43 | ) { 44 | const filtered = this.filterParams(params); 45 | if (!filtered.query.fee) { 46 | debug("Missing Stripe fee id"); 47 | } 48 | const { fee, ...query } = filtered.query; 49 | return this.handlePaginate( 50 | filtered, 51 | this.stripe.applicationFees.listRefunds(fee, query, filtered.stripe) 52 | ); 53 | } 54 | 55 | _get(id: string, params: ParamsWithStripeFee) { 56 | const { stripe } = this.filterParams(params); 57 | if (!stripe.fee) { 58 | debug("Missing Stripe fee id"); 59 | } 60 | const { fee, ...rest } = stripe; 61 | return this.stripe.applicationFees.retrieveRefund(fee, id, rest); 62 | } 63 | 64 | _create(data: Stripe.FeeRefundCreateParams, params: ParamsWithStripeFee) { 65 | const { stripe } = this.filterParams(params); 66 | if (!stripe.fee) { 67 | debug("Missing Stripe fee id"); 68 | } 69 | const { fee, ...rest } = stripe; 70 | return this.stripe.applicationFees.createRefund(fee, data, rest); 71 | } 72 | 73 | _update( 74 | id: string, 75 | data: Stripe.FeeRefundUpdateParams, 76 | params: ParamsWithStripeFee 77 | ) { 78 | const { stripe } = this.filterParams(params); 79 | if (!stripe.fee) { 80 | debug("Missing Stripe fee id"); 81 | } 82 | const { fee, ...rest } = stripe; 83 | return this.stripe.applicationFees.updateRefund(fee, id, data, rest); 84 | } 85 | 86 | _patch( 87 | id: string, 88 | data: Stripe.FeeRefundUpdateParams, 89 | params: ParamsWithStripeFee 90 | ) { 91 | return this._update(id, data, params); 92 | } 93 | 94 | _remove: never; 95 | } 96 | -------------------------------------------------------------------------------- /src/services/balance-transactions.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IBalanceTransactionService { 6 | _find: FindMethod, Stripe.BalanceTransaction>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: never; 9 | _update: never; 10 | _patch: never; 11 | _remove: never; 12 | } 13 | 14 | export class BalanceTransactionService 15 | extends BaseService 16 | implements IBalanceTransactionService 17 | { 18 | _get(id: string, params: ParamsWithStripe) { 19 | let { stripe } = this.filterParams(params); 20 | stripe = Object.assign({}, stripe); 21 | if (id) { 22 | stripe.stripeAccount = id; 23 | } 24 | return this.stripe.balanceTransactions.retrieve(undefined, stripe); 25 | } 26 | 27 | _find (params: ParamsWithStripeQuery) { 28 | const filtered = this.filterParams(params); 29 | return this.handlePaginate( 30 | filtered, 31 | this.stripe.balanceTransactions.list(filtered.query, filtered.stripe) 32 | ); 33 | } 34 | 35 | _create: never; 36 | _update: never; 37 | _patch: never; 38 | _remove: never; 39 | } 40 | -------------------------------------------------------------------------------- /src/services/balance.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { ParamsWithStripe } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IBalanceService { 6 | _find: never; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: never; 9 | _update: never; 10 | _patch: never; 11 | _remove: never; 12 | } 13 | 14 | export class BalanceService 15 | extends BaseService 16 | implements IBalanceService 17 | { 18 | _get(id: string, params: ParamsWithStripe) { 19 | let { stripe } = this.filterParams(params); 20 | stripe = Object.assign({}, stripe); 21 | if (id) { 22 | stripe.stripeAccount = id; 23 | } 24 | return this.stripe.balance.retrieve(undefined, stripe); 25 | } 26 | 27 | _find: never; 28 | _create: never; 29 | _update: never; 30 | _patch: never; 31 | _remove: never; 32 | } 33 | -------------------------------------------------------------------------------- /src/services/bank-account.ts: -------------------------------------------------------------------------------- 1 | import makeDebug from "debug"; 2 | import type Stripe from "stripe"; 3 | import type { FindMethod, ParamsWithStripeQuery } from "../types"; 4 | import { BaseService } from "./base"; 5 | 6 | const debug = makeDebug("feathers-stripe:card"); 7 | 8 | export interface IBankAccountService { 9 | _find: FindMethod< 10 | ParamsWithStripeQuery< 11 | Stripe.CustomerSourceListParams & { customer: string } 12 | >, 13 | Stripe.CustomerSource 14 | >; 15 | _get: ( 16 | id: string, 17 | params: ParamsWithStripeQuery<{ customer: string }> 18 | ) => Promise; 19 | _create: ( 20 | data: Stripe.CustomerSourceCreateParams & { customer: string }, 21 | params: ParamsWithStripeQuery<{ customer: string }> 22 | ) => Promise; 23 | _update: ( 24 | id: string, 25 | data: Stripe.CustomerSourceUpdateParams, 26 | params: ParamsWithStripeQuery<{ customer: string }> 27 | ) => Promise; 28 | _patch: ( 29 | id: string, 30 | data: Stripe.CustomerSourceUpdateParams, 31 | params: ParamsWithStripeQuery<{ customer: string }> 32 | ) => Promise; 33 | _remove: ( 34 | id: string, 35 | params: ParamsWithStripeQuery<{ customer: string }> 36 | ) => Promise< 37 | Stripe.CustomerSource | Stripe.DeletedBankAccount | Stripe.DeletedCard 38 | >; 39 | } 40 | 41 | export class BankAccountService 42 | extends BaseService 43 | implements IBankAccountService 44 | { 45 | _find( 46 | params: ParamsWithStripeQuery< 47 | Stripe.CustomerSourceListParams & { customer: string } 48 | > 49 | ) { 50 | const filtered = this.filterParams(params); 51 | const { customer, ...query } = filtered.query; 52 | if (!customer) { 53 | debug("Missing Stripe customer id"); 54 | } 55 | 56 | return this.handlePaginate( 57 | filtered, 58 | this.stripe.customers.listSources(customer, query, filtered.stripe) 59 | ); 60 | } 61 | 62 | _get(id: string, params: ParamsWithStripeQuery<{ customer: string }>) { 63 | const { query, stripe } = this.filterParams(params); 64 | if (!query.customer) { 65 | debug("Missing Stripe customer id"); 66 | } 67 | return this.stripe.customers.retrieveSource(query.customer, id, stripe); 68 | } 69 | 70 | _create( 71 | data: Stripe.CustomerSourceCreateParams, 72 | params: ParamsWithStripeQuery<{ customer: string }> 73 | ) { 74 | const { query, stripe } = this.filterParams(params); 75 | if (!query.customer) { 76 | debug("Missing Stripe customer id"); 77 | } 78 | return this.stripe.customers.createSource(query.customer, data, stripe); 79 | } 80 | 81 | _update( 82 | id: string, 83 | data: Stripe.CustomerSourceUpdateParams, 84 | params: ParamsWithStripeQuery<{ customer: string }> 85 | ) { 86 | const { query, stripe } = this.filterParams(params); 87 | if (!query.customer) { 88 | debug("Missing Stripe customer id"); 89 | } 90 | return this.stripe.customers.updateSource(query.customer, id, data, stripe); 91 | } 92 | 93 | _patch( 94 | id: string, 95 | data: Stripe.CustomerSourceUpdateParams, 96 | params: ParamsWithStripeQuery<{ customer: string }> 97 | ) { 98 | return this._update(id, data, params); 99 | } 100 | 101 | _remove(id: string, params: ParamsWithStripeQuery<{ customer: string }>) { 102 | const { query, stripe } = this.filterParams(params); 103 | if (!query.customer) { 104 | debug("Missing Stripe customer id"); 105 | } 106 | return this.stripe.customers.deleteSource(query.customer, id, stripe); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/services/base.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | import type Stripe from "stripe"; 3 | import { 4 | BadRequest, 5 | NotImplemented, 6 | Unavailable, 7 | NotAuthenticated, 8 | TooManyRequests, 9 | GeneralError, 10 | PaymentError, 11 | MethodNotAllowed 12 | } from "@feathersjs/errors"; 13 | import { _ } from "@feathersjs/commons"; 14 | import type { 15 | IUnderScoreFunctions, 16 | ParamsWithStripe, 17 | StripeServiceOptions 18 | } from "../types"; 19 | import type { Params, Query } from "@feathersjs/feathers"; 20 | 21 | type FilteredParams = { 22 | query: Remove$QueryKeys; 23 | stripe: T["stripe"]; 24 | paginate: boolean; 25 | }; 26 | 27 | export interface BaseService { 36 | _search?(params: Parameters[0]): ReturnType; 37 | } 38 | 39 | type Remove$QueryKeys = T extends Array ? Remove$QueryKeys[] : T extends object ? { 40 | [K in keyof T as string extends K ? never : K extends `$${infer DollarlessKey}` ? DollarlessKey : K]: T[K] extends object ? Remove$QueryKeys : T[K] 41 | } : never; 42 | 43 | // eslint-disable-next-line @typescript-eslint/no-unsafe-declaration-merging 44 | export abstract class BaseService< 45 | I extends IUnderScoreFunctions, 46 | Find extends I["_find"] = I["_find"], 47 | Get extends I["_get"] = I["_get"], 48 | Create extends I["_create"] = I["_create"], 49 | Update extends I["_update"] = I["_update"], 50 | Patch extends I["_patch"] = I["_patch"], 51 | Remove extends I["_remove"] = I["_remove"], 52 | Search extends I["_search"] = I["_search"] 53 | > { 54 | stripe: Stripe; 55 | options: StripeServiceOptions; 56 | 57 | abstract _find(params: Parameters[0]): ReturnType; 58 | abstract _get(id: string, params: Parameters[1]): ReturnType; 59 | abstract _create( 60 | data: Parameters[0], 61 | params: Parameters[1] 62 | ): ReturnType; 63 | abstract _update( 64 | id: string, 65 | data: Parameters[1], 66 | params: Parameters[2] 67 | ): ReturnType; 68 | abstract _patch( 69 | id: string, 70 | data: Parameters[1], 71 | params: Parameters[2] 72 | ): ReturnType; 73 | abstract _remove( 74 | id: string, 75 | params: Parameters[1] 76 | ): ReturnType; 77 | 78 | constructor(options: StripeServiceOptions) { 79 | const opts = { 80 | // Stripe enforces 100 max and 10 default 81 | paginate: { 82 | default: 10, 83 | max: 100 84 | }, 85 | ...options 86 | }; 87 | if (!opts.stripe) { 88 | throw new Error("Stripe service option `stripe` needs to be provided"); 89 | } 90 | 91 | this.stripe = opts.stripe; 92 | } 93 | 94 | find(params: Parameters[0]): ReturnType { 95 | if (!(this as any)._find) { 96 | throw new NotImplemented("Find method not implemented"); 97 | } 98 | return (this as any)._find(params).catch(this.handleError); 99 | } 100 | 101 | get(id: Parameters[0], params: Parameters[1]): ReturnType { 102 | if (!(this as any)._get) { 103 | throw new NotImplemented("Get method not implemented"); 104 | } 105 | return (this as any)._get(id, params).catch(this.handleError); 106 | } 107 | 108 | create( 109 | data: Parameters[0], 110 | params: Parameters[1] 111 | ): ReturnType { 112 | if (!(this as any)._create) { 113 | throw new NotImplemented("Create method not implemented"); 114 | } 115 | return (this as any)._create(data, params).catch(this.handleError); 116 | } 117 | 118 | update( 119 | id: Parameters[0], 120 | data: Parameters[1], 121 | params: Parameters[2] 122 | ): ReturnType { 123 | if (!(this as any)._update) { 124 | throw new NotImplemented("Update method not implemented"); 125 | } 126 | return (this as any)._update(id, data, params).catch(this.handleError); 127 | } 128 | 129 | patch( 130 | id: Parameters[0], 131 | data: Parameters[1], 132 | params: Parameters[2] 133 | ): ReturnType { 134 | if (!(this as any)._patch) { 135 | throw new NotImplemented("Patch method not implemented"); 136 | } 137 | return (this as any)._patch(id, data, params).catch(this.handleError); 138 | } 139 | 140 | remove( 141 | id: Parameters[0], 142 | params: Parameters[1] 143 | ): ReturnType { 144 | if (!(this as any)._remove) { 145 | throw new NotImplemented("Remove method not implemented"); 146 | } 147 | return (this as any)._remove(id, params).catch(this.handleError); 148 | } 149 | 150 | search(params: Parameters[0]): ReturnType { 151 | if (!(this as any)._search) { 152 | throw new NotImplemented("Search method not implemented"); 153 | } 154 | return (this as any)._search(params).catch(this.handleError); 155 | } 156 | 157 | getLimit( 158 | limit: number | undefined, 159 | paramsPaginate: false | { max: number } | undefined 160 | ): number { 161 | if (paramsPaginate === false) { 162 | return limit; 163 | } 164 | const paginate = this.options?.paginate; 165 | if (paginate && (paginate.default || paginate.max)) { 166 | const base = paginate.default || 0; 167 | const lower = typeof limit === "number" && !isNaN(limit) ? limit : base; 168 | const upper = 169 | typeof paginate.max === "number" ? paginate.max : Number.MAX_VALUE; 170 | 171 | return Math.min(lower, upper); 172 | } 173 | return limit; 174 | } 175 | 176 | cleanQuery(query: Q): Remove$QueryKeys { 177 | if (Array.isArray(query)) { 178 | // @ts-expect-error TODO: fix this 179 | return query.map((item) => this.cleanQuery(item)); 180 | } 181 | if (_.isObject(query)) { 182 | const result = Object.assign({}, query); 183 | Object.entries(result).forEach(([key, value]) => { 184 | let cleanKey = key; 185 | if (key.startsWith("$")) { 186 | // @ts-expect-error TODO: fix this 187 | delete result[key]; 188 | cleanKey = key.replace("$", ""); 189 | } 190 | // @ts-expect-error TODO: fix this 191 | result[cleanKey] = this.cleanQuery(value); 192 | }); 193 | return result as unknown as Remove$QueryKeys; 194 | } 195 | return query as unknown as Remove$QueryKeys; 196 | } 197 | 198 | filterQuery< 199 | P extends ParamsWithStripe, 200 | Q = P extends Params ? T : Query 201 | >(params: P): Remove$QueryKeys { 202 | const query = Object.assign({}, params.query); 203 | const limit = query.$limit ?? query.limit; 204 | if (limit) { 205 | query.limit = this.getLimit(limit, params.paginate); 206 | delete query.$limit; 207 | } 208 | return this.cleanQuery(query); 209 | } 210 | 211 | filterParams( 212 | params: T 213 | ): FilteredParams { 214 | return { 215 | query: this.filterQuery(params), 216 | stripe: params.stripe, 217 | paginate: params.paginate !== false 218 | }; 219 | } 220 | 221 | async handlePaginate | Stripe.ApiSearchResultPromise = Stripe.ApiListPromise>( 222 | { paginate }: FilteredParams, 223 | stripeMethod: M 224 | ): Promise ? Stripe.ApiList : Stripe.ApiSearchResult)> { 225 | if (paginate) { 226 | return (await stripeMethod) as (M extends Stripe.ApiListPromise ? Stripe.ApiList : Stripe.ApiSearchResult); 227 | } 228 | if (stripeMethod.autoPagingEach) { 229 | // NOTE: This is similar to stripe's autoPagingToArray 230 | // but bypasses the 10,000 limit to better follow 231 | // feathers pagination standards. You get better 232 | // performance when using $limit because stripe 233 | // will use Math.min($limit, 100) as the "chunk" 234 | // size for each page of autoPagingEach. When 235 | // no $limit is provided, it falls back to a 236 | // page size of 10. 237 | const results: R[] = []; 238 | await stripeMethod.autoPagingEach((result) => { 239 | results.push(result); 240 | }); 241 | return results; 242 | } 243 | throw new MethodNotAllowed("Cannot use paginate: false on this method"); 244 | } 245 | 246 | handleError(error: Stripe.errors.StripeError) { 247 | if (!error.type) { 248 | throw new GeneralError("Unknown Payment Gateway Error", error); 249 | } 250 | 251 | switch (error.type) { 252 | case "StripeCardError": 253 | // A declined card error 254 | throw new PaymentError(error, error); 255 | case "StripeInvalidRequestError": 256 | // Invalid parameters were supplied to Stripe's API 257 | throw new BadRequest(error, error); 258 | case "StripeAPIError": 259 | // An error occurred internally with Stripe's API 260 | throw new Unavailable(error, error); 261 | case "StripeConnectionError": 262 | // Some kind of error occurred during the HTTPS communication 263 | throw new Unavailable(error, error); 264 | case "StripeAuthenticationError": 265 | // You probably used an incorrect API key 266 | throw new NotAuthenticated(error, error); 267 | case "StripeRateLimitError": 268 | // Too many requests 269 | throw new TooManyRequests(error, error); 270 | default: 271 | throw new GeneralError("Unknown Payment Gateway Error", error); 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /src/services/card.ts: -------------------------------------------------------------------------------- 1 | import makeDebug from "debug"; 2 | import type Stripe from "stripe"; 3 | import type { 4 | FindMethod, 5 | ParamsWithStripe, 6 | ParamsWithStripeQuery 7 | } from "../types"; 8 | import { BaseService } from "./base"; 9 | 10 | const debug = makeDebug("feathers-stripe:card"); 11 | 12 | export interface ICardService { 13 | _find: FindMethod< 14 | ParamsWithStripeQuery< 15 | Stripe.CustomerSourceListParams & { customer: string } 16 | >, 17 | Stripe.CustomerSource 18 | >; 19 | _get: ( 20 | id: string, 21 | params: ParamsWithStripeQuery<{ customer: string }> 22 | ) => Promise; 23 | _create: ( 24 | data: Stripe.CustomerSourceCreateParams & { customer: string }, 25 | params: ParamsWithStripe 26 | ) => Promise; 27 | _update: ( 28 | id: string, 29 | data: Stripe.CustomerSourceUpdateParams, 30 | params: ParamsWithStripeQuery<{ customer: string }> 31 | ) => Promise; 32 | _patch: ( 33 | id: string, 34 | data: Stripe.CustomerSourceUpdateParams, 35 | params: ParamsWithStripeQuery<{ customer: string }> 36 | ) => Promise; 37 | _remove: ( 38 | id: string, 39 | params: ParamsWithStripeQuery<{ customer: string }> 40 | ) => Promise< 41 | Stripe.CustomerSource | Stripe.DeletedBankAccount | Stripe.DeletedCard 42 | >; 43 | } 44 | 45 | export class CardService 46 | extends BaseService 47 | implements ICardService 48 | { 49 | _find( 50 | params: ParamsWithStripeQuery< 51 | Stripe.CustomerSourceListParams & { customer: string } 52 | > 53 | ) { 54 | const filtered = this.filterParams(params); 55 | const { customer, ...query } = filtered.query; 56 | if (!customer) { 57 | debug("Missing Stripe customer id"); 58 | } 59 | return this.handlePaginate( 60 | filtered, 61 | this.stripe.customers.listSources(customer, query, filtered.stripe) 62 | ); 63 | } 64 | 65 | _get(id: string, params: ParamsWithStripeQuery<{ customer: string }>) { 66 | const { query, stripe } = this.filterParams(params); 67 | if (!query.customer) { 68 | debug("Missing Stripe customer id"); 69 | } 70 | 71 | return this.stripe.customers.retrieveSource(query.customer, id, stripe); 72 | } 73 | 74 | _create( 75 | data: Stripe.CustomerSourceCreateParams & { customer: string }, 76 | params: ParamsWithStripe 77 | ) { 78 | const { stripe } = this.filterParams(params); 79 | const { customer, ...rest } = data; 80 | if (!customer) { 81 | debug("Missing Stripe customer id"); 82 | } 83 | return this.stripe.customers.createSource(customer, rest, stripe); 84 | } 85 | 86 | _update( 87 | id: string, 88 | data: Stripe.CustomerSourceUpdateParams, 89 | params: ParamsWithStripeQuery<{ customer: string }> 90 | ) { 91 | const { query, stripe } = this.filterParams(params); 92 | if (!query.customer) { 93 | debug("Missing Stripe customer id"); 94 | } 95 | return this.stripe.customers.updateSource(query.customer, id, data, stripe); 96 | } 97 | 98 | _patch( 99 | id: string, 100 | data: Stripe.CustomerSourceUpdateParams, 101 | params: ParamsWithStripeQuery<{ customer: string }> 102 | ) { 103 | return this._update(id, data, params); 104 | } 105 | 106 | _remove(id: string, params: ParamsWithStripeQuery<{ customer: string }>) { 107 | const { query, stripe } = this.filterParams(params); 108 | if (!query.customer) { 109 | debug("Missing Stripe customer id"); 110 | } 111 | return this.stripe.customers.deleteSource(query.customer, id, stripe); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/services/charge.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { 3 | FindMethod, 4 | ParamsWithStripe, 5 | ParamsWithStripeQuery 6 | } from "../types"; 7 | import { BaseService } from "./base"; 8 | 9 | export interface IChargeService { 10 | _find: FindMethod< 11 | ParamsWithStripeQuery, 12 | Stripe.Charge 13 | >; 14 | _get: (id: string, params: ParamsWithStripe) => Promise; 15 | _create: ( 16 | data: Stripe.ChargeCreateParams, 17 | params: ParamsWithStripe 18 | ) => Promise; 19 | _update: ( 20 | id: string, 21 | data: Stripe.ChargeUpdateParams, 22 | params: ParamsWithStripe 23 | ) => Promise; 24 | _patch: ( 25 | id: string, 26 | data: 27 | | ({ capture: boolean } & Stripe.ChargeCaptureParams) 28 | | Stripe.ChargeUpdateParams, 29 | params: ParamsWithStripe 30 | ) => Promise; 31 | _remove: (id: string, params: ParamsWithStripe) => Promise; 32 | } 33 | 34 | export class ChargeService 35 | extends BaseService 36 | implements IChargeService 37 | { 38 | _find(params: ParamsWithStripeQuery) { 39 | const filtered = this.filterParams(params); 40 | return this.handlePaginate( 41 | filtered, 42 | this.stripe.charges.list(filtered.query, filtered.stripe) 43 | ); 44 | } 45 | 46 | _get(id: string, params: ParamsWithStripe) { 47 | const { stripe } = this.filterParams(params); 48 | return this.stripe.charges.retrieve(id, stripe); 49 | } 50 | 51 | _create(data: Stripe.ChargeCreateParams, params: ParamsWithStripe) { 52 | const { stripe } = this.filterParams(params); 53 | return this.stripe.charges.create(data, stripe); 54 | } 55 | 56 | _update( 57 | id: string, 58 | data: Stripe.ChargeUpdateParams, 59 | params: ParamsWithStripe 60 | ) { 61 | const { stripe } = this.filterParams(params); 62 | return this.stripe.charges.update(id, data, stripe); 63 | } 64 | 65 | _patch( 66 | id: string, 67 | data: 68 | | ({ capture: boolean } & Stripe.ChargeCaptureParams) 69 | | Stripe.ChargeUpdateParams, 70 | params: ParamsWithStripe 71 | ): Promise { 72 | const { stripe } = this.filterParams(params); 73 | if ("capture" in data) { 74 | const { capture, ...rest } = data; 75 | if (capture) { 76 | return this.stripe.charges.capture(id, rest, stripe); 77 | } 78 | } 79 | return this._update(id, data, params); 80 | } 81 | 82 | _remove(id: string, params: ParamsWithStripe) { 83 | const { stripe } = this.filterParams(params); 84 | return this.stripe.refunds.create({ charge: id }, stripe); 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/services/coupon.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { 3 | FindMethod, 4 | ParamsWithStripe, 5 | ParamsWithStripeQuery 6 | } from "../types"; 7 | import { BaseService } from "./base"; 8 | 9 | export interface ICouponService { 10 | _find: FindMethod< 11 | ParamsWithStripeQuery, 12 | Stripe.Coupon 13 | >; 14 | _get: (id: string, params: ParamsWithStripe) => Promise; 15 | _create: ( 16 | data: Stripe.CouponCreateParams, 17 | params: ParamsWithStripe 18 | ) => Promise; 19 | _update: ( 20 | id: string, 21 | data: Stripe.CouponUpdateParams, 22 | params: ParamsWithStripe 23 | ) => Promise; 24 | _patch: ( 25 | id: string, 26 | data: Stripe.CouponUpdateParams, 27 | params: ParamsWithStripe 28 | ) => Promise; 29 | _remove: never; 30 | } 31 | 32 | export class CouponService 33 | extends BaseService 34 | implements ICouponService 35 | { 36 | _find(params: ParamsWithStripeQuery) { 37 | const filtered = this.filterParams(params); 38 | return this.handlePaginate( 39 | filtered, 40 | this.stripe.coupons.list(filtered.query, filtered.stripe) 41 | ); 42 | } 43 | 44 | _get(id: string, params: ParamsWithStripe) { 45 | const { stripe } = this.filterParams(params); 46 | return this.stripe.coupons.retrieve(id, stripe); 47 | } 48 | 49 | _create(data: Stripe.CouponCreateParams, params: ParamsWithStripe) { 50 | const { stripe } = this.filterParams(params); 51 | return this.stripe.coupons.create(data, stripe); 52 | } 53 | 54 | _update( 55 | id: string, 56 | data: Stripe.CouponUpdateParams, 57 | params: ParamsWithStripe 58 | ) { 59 | const { stripe } = this.filterParams(params); 60 | return this.stripe.coupons.update(id, data, stripe); 61 | } 62 | 63 | _patch( 64 | id: string, 65 | data: Stripe.CouponUpdateParams, 66 | params: ParamsWithStripe 67 | ) { 68 | return this._update(id, data, params); 69 | } 70 | 71 | _remove: never; 72 | } 73 | -------------------------------------------------------------------------------- /src/services/customer.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { 3 | FindMethod, 4 | ParamsWithStripe, 5 | ParamsWithStripeQuery 6 | } from "../types"; 7 | import { BaseService } from "./base"; 8 | 9 | export interface ICustomerService { 10 | _find: FindMethod< 11 | ParamsWithStripeQuery, 12 | Stripe.Customer 13 | >; 14 | _get: ( 15 | id: string, 16 | params: ParamsWithStripe 17 | ) => Promise; 18 | _create: ( 19 | data: Stripe.CustomerCreateParams, 20 | params: ParamsWithStripe 21 | ) => Promise; 22 | _update: ( 23 | id: string, 24 | data: Stripe.CustomerUpdateParams, 25 | params: ParamsWithStripe 26 | ) => Promise; 27 | _patch: ( 28 | id: string, 29 | data: Stripe.CustomerUpdateParams, 30 | params: ParamsWithStripe 31 | ) => Promise; 32 | _remove: ( 33 | id: string, 34 | params: ParamsWithStripe 35 | ) => Promise; 36 | _search: ( 37 | params: ParamsWithStripeQuery 38 | ) => Promise>; 39 | } 40 | 41 | export class CustomerService 42 | extends BaseService 43 | implements ICustomerService 44 | { 45 | _find(params: ParamsWithStripeQuery) { 46 | const filtered = this.filterParams(params); 47 | return this.handlePaginate( 48 | filtered, 49 | this.stripe.customers.list(filtered.query, filtered.stripe) 50 | ); 51 | } 52 | 53 | _get(id: string, params: ParamsWithStripe) { 54 | const { stripe } = this.filterParams(params); 55 | return this.stripe.customers.retrieve(id, stripe); 56 | } 57 | 58 | _create(data: Stripe.CustomerCreateParams, params: ParamsWithStripe) { 59 | const { stripe } = this.filterParams(params); 60 | return this.stripe.customers.create(data, stripe); 61 | } 62 | 63 | _update( 64 | id: string, 65 | data: Stripe.CustomerUpdateParams, 66 | params: ParamsWithStripe 67 | ) { 68 | const { stripe } = this.filterParams(params); 69 | return this.stripe.customers.update(id, data, stripe); 70 | } 71 | 72 | _patch( 73 | id: string, 74 | data: Stripe.CustomerUpdateParams, 75 | params: ParamsWithStripe 76 | ) { 77 | return this._update(id, data, params); 78 | } 79 | 80 | _remove(id: string, params: ParamsWithStripe) { 81 | const { stripe } = this.filterParams(params); 82 | return this.stripe.customers.del(id, stripe); 83 | } 84 | 85 | _search(params: ParamsWithStripeQuery) { 86 | const filtered = this.filterParams(params); 87 | return this.handlePaginate( 88 | filtered, 89 | this.stripe.customers.search(filtered.query, filtered.stripe) 90 | ); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/services/dispute.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IDisputeService { 6 | _find: FindMethod, Stripe.Dispute>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: never; 9 | _update: (id: string, data: Stripe.DisputeUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.DisputeUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: never; 12 | } 13 | 14 | export class DisputeService extends BaseService implements IDisputeService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.disputes.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.disputes.retrieve(id, stripe); 26 | } 27 | 28 | _update (id: string, data: Stripe.DisputeUpdateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.disputes.update(id, data, stripe); 31 | } 32 | 33 | _patch (id: string, data: Stripe.DisputeUpdateParams, params: ParamsWithStripe) { 34 | return this._update(id, data, params); 35 | } 36 | 37 | _create: never; 38 | _remove: never; 39 | } 40 | -------------------------------------------------------------------------------- /src/services/event.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IEventService { 6 | _find: FindMethod, Stripe.Event>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: never; 9 | _update: never; 10 | _patch: never; 11 | _remove: never; 12 | } 13 | 14 | export class EventService extends BaseService implements IEventService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.events.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.events.retrieve(id, stripe); 26 | } 27 | 28 | _create: never; 29 | _update: never; 30 | _patch: never; 31 | _remove: never; 32 | } 33 | -------------------------------------------------------------------------------- /src/services/external-account.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import { BaseService } from "./base"; 3 | import makeDebug from "debug"; 4 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 5 | 6 | const debug = makeDebug("feathers-stripe:external-account"); 7 | 8 | export interface IExternalAccountService { 9 | _find: FindMethod, Stripe.BankAccount | Stripe.Card>; 10 | _get: (id: string, params: ParamsWithStripeQuery<{ account: string }>) => Promise; 11 | _create: (data: Stripe.ExternalAccountCreateParams & { account: string }, params: ParamsWithStripe) => Promise; 12 | _update: (id: string, data: Stripe.ExternalAccountUpdateParams, params: ParamsWithStripeQuery<{ account: string }>) => Promise; 13 | _patch: (id: string, data: Stripe.ExternalAccountUpdateParams, params: ParamsWithStripeQuery<{ account: string }>) => Promise; 14 | _remove: (id: string, params: ParamsWithStripeQuery<{ account: string }>) => Promise; 15 | } 16 | 17 | export class ExternalAccountService extends BaseService implements IExternalAccountService { 18 | _find (params: ParamsWithStripeQuery) { 19 | const filtered = this.filterParams(params); 20 | const { account, ...query } = filtered.query; 21 | if (!account) { 22 | debug("Missing Stripe account id"); 23 | } 24 | return this.handlePaginate( 25 | filtered, 26 | this.stripe.accounts.listExternalAccounts(account, query, filtered.stripe) 27 | ); 28 | } 29 | 30 | _get (id: string, params: ParamsWithStripeQuery<{ account: string }>) { 31 | const { query, stripe } = this.filterParams(params); 32 | if (!query.account) { 33 | debug("Missing Stripe account id"); 34 | } 35 | return this.stripe.accounts.retrieveExternalAccount( 36 | query.account, 37 | id, 38 | stripe 39 | ); 40 | } 41 | 42 | // TODO: move 'account' to 'query'? 43 | _create (data: Stripe.ExternalAccountCreateParams & { account: string }, params: ParamsWithStripe) { 44 | const { stripe } = this.filterParams(params); 45 | const { account, ...rest } = data; 46 | if (!account) { 47 | debug("Missing Stripe account id"); 48 | } 49 | return this.stripe.accounts.createExternalAccount(account, rest, stripe); 50 | } 51 | 52 | _update (id: string, data: Stripe.ExternalAccountUpdateParams, params: ParamsWithStripeQuery<{ account: string }>) { 53 | const { query, stripe } = this.filterParams(params); 54 | if (!query.account) { 55 | debug("Missing Stripe account id"); 56 | } 57 | return this.stripe.accounts.updateExternalAccount( 58 | query.account, 59 | id, 60 | data, 61 | stripe 62 | ); 63 | } 64 | 65 | _patch (id: string, data: Stripe.ExternalAccountUpdateParams, params: ParamsWithStripeQuery<{ account: string }>) { 66 | return this._update(id, data, params); 67 | } 68 | 69 | _remove (id: string, params: ParamsWithStripeQuery<{ account: string }>) { 70 | const { query, stripe } = this.filterParams(params); 71 | if (!query.account) { 72 | debug("Missing Stripe account id"); 73 | } 74 | return this.stripe.accounts.deleteExternalAccount( 75 | query.account, 76 | id, 77 | stripe 78 | ); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/services/index.ts: -------------------------------------------------------------------------------- 1 | export { AccountService } from "./account"; 2 | export { AccountLinkService } from "./account-links"; 3 | export { ApplicationFeeRefundService } from "./application-fee-refund"; 4 | export { BalanceService } from "./balance"; 5 | export { BalanceTransactionService } from "./balance-transactions"; 6 | export { BankAccountService } from "./bank-account"; 7 | export { ExternalAccountService } from "./external-account"; 8 | export { CardService } from "./card"; 9 | export { ChargeService } from "./charge"; 10 | export { CouponService } from "./coupon"; 11 | export { CustomerService } from "./customer"; 12 | export { DisputeService } from "./dispute"; 13 | export { EventService } from "./event"; 14 | export { InvoiceService } from "./invoice"; 15 | export { InvoiceItemService } from "./invoice-item"; 16 | export { PayoutService } from "./payout"; 17 | export { PaymentIntentService } from "./payment-intent"; 18 | export { PaymentMethodService } from "./payment-method"; 19 | export { PlanService } from "./plan"; 20 | export { PriceService } from "./price"; 21 | export { ProductService } from "./product"; 22 | export { RefundService } from "./refund"; 23 | export { SetupIntentService } from "./setup-intent"; 24 | export { SourceService } from "./source"; 25 | export { SubscriptionService } from "./subscription"; 26 | export { SubscriptionItemService } from "./subscription-item"; 27 | export { TokenService } from "./token"; 28 | export { TransactionService } from "./transaction"; 29 | export { TransferService } from "./transfer"; 30 | export { TransferReversalService } from "./transfer-reversal"; 31 | export * from "./webhook"; 32 | -------------------------------------------------------------------------------- /src/services/invoice-item.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IInvoiceItemService { 6 | _find: FindMethod, Stripe.InvoiceItem>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create(data: Stripe.InvoiceItemCreateParams, params: ParamsWithStripe): Promise; 9 | _update: (id: string, data: Stripe.InvoiceItemUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.InvoiceItemUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class InvoiceItemService extends BaseService implements IInvoiceItemService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.invoiceItems.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.invoiceItems.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.InvoiceItemCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.invoiceItems.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.InvoiceUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.invoiceItems.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.InvoiceItemUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.invoiceItems.del(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/invoice.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IInvoiceService { 6 | _find: FindMethod, Stripe.Invoice>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.InvoiceCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.InvoiceUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: ({ pay: boolean } & Stripe.InvoicePayParams) | Stripe.InvoiceUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: never; 12 | _search: ( 13 | params: ParamsWithStripeQuery 14 | ) => Promise>; 15 | } 16 | 17 | export class InvoiceService extends BaseService implements IInvoiceService { 18 | _find (params: ParamsWithStripeQuery) { 19 | const filtered = this.filterParams(params); 20 | return this.handlePaginate( 21 | filtered, 22 | this.stripe.invoices.list(filtered.query, filtered.stripe) 23 | ); 24 | } 25 | 26 | // TODO (EK): Support upcoming invoices 27 | // TODO (EK): Support invoice line items 28 | _get (id: string, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.invoices.retrieve(id, stripe); 31 | } 32 | 33 | _create (data: Stripe.InvoiceCreateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.invoices.create(data, stripe); 36 | } 37 | 38 | _update (id: string, data: Stripe.InvoiceUpdateParams, params: ParamsWithStripe) { 39 | const { stripe } = this.filterParams(params); 40 | return this.stripe.invoices.update(id, data, stripe); 41 | } 42 | 43 | _patch (id: string, data: ({ pay: boolean } & Stripe.InvoicePayParams) | Stripe.InvoiceUpdateParams, params: ParamsWithStripe): Promise { 44 | const { stripe } = this.filterParams(params); 45 | if ("pay" in data) { 46 | const { pay } = data; 47 | if (pay) { 48 | return this.stripe.invoices.pay(id, stripe); 49 | } 50 | } 51 | 52 | return this._update(id, data, params); 53 | } 54 | 55 | _search(params: ParamsWithStripeQuery) { 56 | const filtered = this.filterParams(params); 57 | return this.handlePaginate( 58 | filtered, 59 | this.stripe.invoices.search(filtered.query, filtered.stripe) 60 | ); 61 | } 62 | 63 | _remove: never; 64 | } 65 | -------------------------------------------------------------------------------- /src/services/payment-intent.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IPaymentIntentService { 6 | _find: FindMethod, Stripe.PaymentIntent>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.PaymentIntentCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.PaymentIntentUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.PaymentIntentUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: never 12 | } 13 | 14 | export class PaymentIntentService extends BaseService implements IPaymentIntentService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.paymentIntents.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.paymentIntents.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.PaymentIntentCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.paymentIntents.create(data, stripe); 31 | } 32 | 33 | _patch (id: string, data: { capture: boolean } | Stripe.PaymentIntentUpdateParams, params: ParamsWithStripe): Promise { 34 | const { stripe } = this.filterParams(params); 35 | if ("capture" in data) { 36 | return this.stripe.paymentIntents.capture(id, stripe); 37 | } 38 | 39 | return this._update(id, data, params); 40 | } 41 | 42 | _update (id: string, data: Stripe.PaymentIntentUpdateParams, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.paymentIntents.update(id, data, stripe); 45 | } 46 | 47 | _remove: never; 48 | } 49 | -------------------------------------------------------------------------------- /src/services/payment-method.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IPaymentMethodService { 6 | _find: FindMethod, Stripe.PaymentMethod>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.PaymentMethodCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.PaymentMethodUpdateParams, params: ParamsWithStripe) => Promise; 10 | 11 | _patch: 12 | ((id: string, data: { attach: boolean } & Stripe.PaymentMethodAttachParams, params: ParamsWithStripe) => Promise) | 13 | ((id: string, data: Stripe.PaymentMethodUpdateParams, params: ParamsWithStripe) => Promise); 14 | 15 | _remove: (id: string, params: ParamsWithStripe) => Promise; 16 | } 17 | 18 | export class PaymentMethodService extends BaseService implements IPaymentMethodService { 19 | _find (params: ParamsWithStripeQuery) { 20 | const filtered = this.filterParams(params); 21 | return this.handlePaginate( 22 | filtered, 23 | this.stripe.paymentMethods.list(filtered.query, filtered.stripe) 24 | ); 25 | } 26 | 27 | _get (id: string, params: ParamsWithStripe) { 28 | const { stripe } = this.filterParams(params); 29 | return this.stripe.paymentMethods.retrieve(id, stripe); 30 | } 31 | 32 | _create (data: Stripe.PaymentMethodCreateParams, params: ParamsWithStripe) { 33 | const { stripe } = this.filterParams(params); 34 | return this.stripe.paymentMethods.create(data, stripe); 35 | } 36 | 37 | _update (id: string, data: Stripe.PaymentMethodUpdateParams, params: ParamsWithStripe) { 38 | const { stripe } = this.filterParams(params); 39 | return this.stripe.paymentMethods.update(id, data, stripe); 40 | } 41 | 42 | _patch (id: string, data: ({ attach: boolean } & Stripe.PaymentMethodAttachParams) | Stripe.PaymentMethodUpdateParams, params: ParamsWithStripe): Promise { 43 | const { stripe } = this.filterParams(params); 44 | 45 | if ("attach" in data) { 46 | const { attach, ...rest } = data; 47 | if (attach) { 48 | return this.stripe.paymentMethods.attach(id, rest, stripe); 49 | } 50 | } 51 | 52 | return this._update(id, data, params); 53 | } 54 | 55 | _remove (id: string, params: ParamsWithStripe) { 56 | const { stripe } = this.filterParams(params); 57 | return this.stripe.paymentMethods.detach(id, stripe); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/services/payout.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IPayoutService { 6 | _find: FindMethod, Stripe.Payout>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.PayoutCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.PayoutUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.PayoutUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class PayoutService extends BaseService implements IPayoutService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.payouts.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.payouts.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.PayoutCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.payouts.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.PayoutUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.payouts.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.PayoutUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.payouts.cancel(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/plan.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IPlanService { 6 | _find: FindMethod, Stripe.Plan>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.PlanCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.PlanUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.PlanUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class PlanService extends BaseService implements IPlanService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.plans.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.plans.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.PlanCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.plans.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.PlanUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.plans.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.PlanUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.plans.del(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/price.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IPriceService { 6 | _find: FindMethod, Stripe.Price>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.PriceCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.PriceUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.PriceUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: never 12 | } 13 | 14 | export class PriceService extends BaseService implements IPriceService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.prices.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.prices.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.PriceCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.prices.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.PriceUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.prices.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.PriceUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove: never; 43 | } 44 | -------------------------------------------------------------------------------- /src/services/product.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IProductService { 6 | _find: FindMethod, Stripe.Product>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.ProductCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.ProductUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.ProductUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class ProductService extends BaseService implements IProductService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.products.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.products.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.ProductCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.products.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.ProductUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.products.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.ProductUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.products.del(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/refund.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface IRefundService { 6 | _find: FindMethod, Stripe.Refund>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.RefundCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.RefundUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.RefundUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: never; 12 | } 13 | 14 | export class RefundService extends BaseService implements IRefundService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.refunds.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.refunds.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.RefundCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.refunds.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.RefundUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.refunds.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.RefundUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove: never; 43 | } 44 | -------------------------------------------------------------------------------- /src/services/setup-intent.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface ISetupIntentService { 6 | _find: FindMethod, Stripe.SetupIntent>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.SetupIntentCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.SetupIntentUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.SetupIntentUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: never; 12 | } 13 | 14 | export class SetupIntentService extends BaseService implements ISetupIntentService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.setupIntents.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.setupIntents.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.SetupIntentCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.setupIntents.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.SetupIntentUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.setupIntents.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.SetupIntentUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove: never; 43 | } 44 | -------------------------------------------------------------------------------- /src/services/source.ts: -------------------------------------------------------------------------------- 1 | import makeDebug from "debug"; 2 | import type Stripe from "stripe"; 3 | import type { ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 4 | import { BaseService } from "./base"; 5 | 6 | const debug = makeDebug("feathers-stripe:source"); 7 | 8 | export interface ISourceService { 9 | _find: never; 10 | _get: (id: string, params: ParamsWithStripe) => Promise; 11 | _create: 12 | ((data: { customer: string } & Stripe.CustomerSourceCreateParams, params: ParamsWithStripe) => Promise) | 13 | ((data: Stripe.SourceCreateParams, params: ParamsWithStripe) => Promise); 14 | _update: (id: string, data: Stripe.SourceUpdateParams, params: ParamsWithStripe) => Promise; 15 | _patch: (id: string, data: Stripe.SourceUpdateParams, params: ParamsWithStripe) => Promise; 16 | _remove: (id: string, params: ParamsWithStripeQuery<{ customer: string }>) => Promise; 17 | } 18 | 19 | export class SourceService extends BaseService implements ISourceService { 20 | _find: never; 21 | 22 | _get (id: string, params: ParamsWithStripe) { 23 | const { stripe } = this.filterParams(params); 24 | return this.stripe.sources.retrieve(id, stripe); 25 | } 26 | 27 | _create (data: { customer: string } & Stripe.CustomerSourceCreateParams, params: ParamsWithStripe): Promise; 28 | _create (data: Stripe.SourceCreateParams, params: ParamsWithStripe): Promise; 29 | _create (data: ({ customer: string } & Stripe.CustomerSourceCreateParams) | Stripe.SourceCreateParams, params: ParamsWithStripe): Promise { 30 | const { stripe } = this.filterParams(params); 31 | if ("customer" in data) { 32 | const { customer, ...rest } = data; 33 | if (customer) { 34 | return this.stripe.customers.createSource(customer, rest as Stripe.CustomerSourceCreateParams, stripe); 35 | } 36 | } 37 | return this.stripe.sources.create(data, stripe); 38 | } 39 | 40 | _update (id: string, data: Stripe.SourceUpdateParams, params: ParamsWithStripe) { 41 | const { stripe } = this.filterParams(params); 42 | return this.stripe.sources.update(id, data, stripe); 43 | } 44 | 45 | _patch (id: string, data: Stripe.SourceUpdateParams, params: ParamsWithStripe) { 46 | return this._update(id, data, params); 47 | } 48 | 49 | _remove (id: string, params: ParamsWithStripeQuery<{ customer: string }>) { 50 | const { query, stripe } = this.filterParams(params); 51 | if (!query.customer) { 52 | debug("Missing Stripe customer id"); 53 | } 54 | return this.stripe.customers.deleteSource(query.customer, id, stripe); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/services/subscription-item.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface ISubscriptionItemService { 6 | _find: FindMethod, Stripe.SubscriptionItem>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.SubscriptionItemCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.SubscriptionItemUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.SubscriptionItemUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class SubscriptionItemService extends BaseService implements ISubscriptionItemService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.subscriptionItems.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.subscriptionItems.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.SubscriptionItemCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.subscriptionItems.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.SubscriptionItemUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.subscriptionItems.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.SubscriptionItemUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.subscriptionItems.del(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/subscription.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface ISubscriptionService { 6 | _find: FindMethod, Stripe.Subscription>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.SubscriptionCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.SubscriptionUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.SubscriptionUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class SubscriptionService extends BaseService implements ISubscriptionService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.subscriptions.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.subscriptions.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.SubscriptionCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.subscriptions.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.SubscriptionUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.subscriptions.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.SubscriptionUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.subscriptions.cancel(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/token.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { ParamsWithStripe } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface ITokenService { 6 | _find: never; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.TokenCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: never; 10 | _patch: never; 11 | _remove: never; 12 | } 13 | 14 | export class TokenService extends BaseService implements ITokenService { 15 | _get (id: string, params: ParamsWithStripe) { 16 | const { stripe } = this.filterParams(params); 17 | return this.stripe.tokens.retrieve(id, stripe); 18 | } 19 | 20 | _create (data: Stripe.TokenCreateParams, params: ParamsWithStripe) { 21 | const { stripe } = this.filterParams(params); 22 | return this.stripe.tokens.create(data, stripe); 23 | } 24 | 25 | _find: never; 26 | _update: never; 27 | _patch: never; 28 | _remove: never; 29 | } 30 | -------------------------------------------------------------------------------- /src/services/transaction.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface ITransactionService { 6 | _find: FindMethod, Stripe.BalanceTransaction>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: never; 9 | _update: never; 10 | _patch: never; 11 | _remove: never; 12 | } 13 | 14 | export class TransactionService extends BaseService implements ITransactionService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.balanceTransactions.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.balanceTransactions.retrieve(id, stripe); 26 | } 27 | 28 | _create: never; 29 | _update: never; 30 | _patch: never; 31 | _remove: never; 32 | } 33 | -------------------------------------------------------------------------------- /src/services/transfer-reversal.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | import makeDebug from "debug"; 5 | 6 | const debug = makeDebug("feathers-stripe:transferReversal"); 7 | 8 | export interface ITransferReversalService { 9 | _find: FindMethod, Stripe.TransferReversal>; 10 | _get: (id: string, params: ParamsWithStripe & { query: { transfer: string } }) => Promise; 11 | _create: (data: Stripe.TransferReversalCreateParams & { transfer: string }, params: ParamsWithStripe) => Promise; 12 | _update: (id: string, data: Stripe.TransferReversalUpdateParams, params: ParamsWithStripeQuery<{ transfer: string }>) => Promise; 13 | _patch: (id: string, data: Stripe.TransferReversalUpdateParams, params: ParamsWithStripeQuery<{ transfer: string }>) => Promise; 14 | _remove: never; 15 | } 16 | 17 | export class TransferReversalService extends BaseService implements ITransferReversalService { 18 | _find (params: ParamsWithStripeQuery) { 19 | const filtered = this.filterParams(params); 20 | const { transfer, ...query } = filtered.query; 21 | if (!transfer) { 22 | debug("Missing Stripe transfer id"); 23 | } 24 | return this.handlePaginate( 25 | filtered, 26 | this.stripe.transfers.listReversals(transfer, query, filtered.stripe) 27 | ); 28 | } 29 | 30 | _get (id: string, params: ParamsWithStripe & { query: { transfer: string } }) { 31 | const { query, stripe } = this.filterParams(params); 32 | if (!query.transfer) { 33 | debug("Missing Stripe transfer id"); 34 | } 35 | return this.stripe.transfers.retrieveReversal(query.transfer, id, stripe); 36 | } 37 | 38 | _create (data: Stripe.TransferReversalCreateParams & { transfer: string }, params: ParamsWithStripe) { 39 | const { stripe } = this.filterParams(params); 40 | const { transfer, ...rest } = data; 41 | if (!transfer) { 42 | debug("Missing Stripe transfer id"); 43 | } 44 | return this.stripe.transfers.createReversal(transfer, rest, stripe); 45 | } 46 | 47 | _update (id: string, data: Stripe.TransferReversalUpdateParams, params: ParamsWithStripeQuery<{ transfer: string }>) { 48 | const { query, stripe } = this.filterParams(params); 49 | if (!query.transfer) { 50 | debug("Missing Stripe transfer id"); 51 | } 52 | return this.stripe.transfers.updateReversal( 53 | query.transfer, 54 | id, 55 | data, 56 | stripe 57 | ); 58 | } 59 | 60 | _patch (id: string, data: Stripe.TransferReversalUpdateParams, params: ParamsWithStripeQuery<{ transfer: string }>) { 61 | return this._update(id, data, params); 62 | } 63 | 64 | _remove: never; 65 | } 66 | -------------------------------------------------------------------------------- /src/services/transfer.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { FindMethod, ParamsWithStripe, ParamsWithStripeQuery } from "../types"; 3 | import { BaseService } from "./base"; 4 | 5 | export interface ITransferService { 6 | _find: FindMethod, Stripe.Transfer>; 7 | _get: (id: string, params: ParamsWithStripe) => Promise; 8 | _create: (data: Stripe.TransferCreateParams, params: ParamsWithStripe) => Promise; 9 | _update: (id: string, data: Stripe.TransferUpdateParams, params: ParamsWithStripe) => Promise; 10 | _patch: (id: string, data: Stripe.TransferUpdateParams, params: ParamsWithStripe) => Promise; 11 | _remove: (id: string, params: ParamsWithStripe) => Promise; 12 | } 13 | 14 | export class TransferService extends BaseService implements ITransferService { 15 | _find (params: ParamsWithStripeQuery) { 16 | const filtered = this.filterParams(params); 17 | return this.handlePaginate( 18 | filtered, 19 | this.stripe.transfers.list(filtered.query, filtered.stripe) 20 | ); 21 | } 22 | 23 | _get (id: string, params: ParamsWithStripe) { 24 | const { stripe } = this.filterParams(params); 25 | return this.stripe.transfers.retrieve(id, stripe); 26 | } 27 | 28 | _create (data: Stripe.TransferCreateParams, params: ParamsWithStripe) { 29 | const { stripe } = this.filterParams(params); 30 | return this.stripe.transfers.create(data, stripe); 31 | } 32 | 33 | _update (id: string, data: Stripe.TransferUpdateParams, params: ParamsWithStripe) { 34 | const { stripe } = this.filterParams(params); 35 | return this.stripe.transfers.update(id, data, stripe); 36 | } 37 | 38 | _patch (id: string, data: Stripe.TransferUpdateParams, params: ParamsWithStripe) { 39 | return this._update(id, data, params); 40 | } 41 | 42 | _remove (id: string, params: ParamsWithStripe) { 43 | const { stripe } = this.filterParams(params); 44 | return this.stripe.transfers.createReversal(id, stripe); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/services/webhook.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | // Heavily inspired from https://github.com/fixate/feathers-stripe-webhooks 3 | import { BaseService } from "./base"; 4 | 5 | import type { Application, Params } from "@feathersjs/feathers"; 6 | import type Stripe from "stripe"; 7 | import type { Application as ExpressApplication } from "@feathersjs/express"; 8 | import type { NextFunction, Request, Response } from "express"; 9 | 10 | export interface IWebhookService { 11 | _find: never; 12 | _get: never; 13 | _create: (data: any, params: any) => Promise; 14 | _update: never; 15 | _patch: never; 16 | _remove: never; 17 | } 18 | 19 | export type WebHookHandler = (options: { 20 | object: Stripe.Event.Data.Object; 21 | event: Stripe.Event; 22 | params: Params; 23 | app: Application; 24 | }) => any; 25 | 26 | export interface WebHookHandlers { 27 | [key: string]: { 28 | [key: string]: WebHookHandler; 29 | }; 30 | } 31 | 32 | export interface WebHookOptions { 33 | app: Application; 34 | handlers: WebHookHandlers; 35 | stripe: Stripe; 36 | } 37 | 38 | export class WebhookService 39 | extends BaseService 40 | implements IWebhookService 41 | { 42 | app: Application; 43 | handlers: WebHookHandlers; 44 | declare options: WebHookOptions; 45 | 46 | isExpressSetup = false; 47 | 48 | constructor(options: WebHookOptions) { 49 | super(options); 50 | 51 | if (!options.app) { 52 | throw new Error("options.app is required"); 53 | } 54 | 55 | this.app = options.app; 56 | this.handlers = options.handlers || {}; 57 | this.options = options; 58 | } 59 | 60 | /** 61 | * registers an express route 62 | * @param route 63 | * @param endpointSecret 64 | * @returns 65 | */ 66 | setupExpress(route: string, endpointSecret: string) { 67 | if (this.isExpressSetup) { 68 | return; 69 | } 70 | 71 | (this.app as ExpressApplication).post( 72 | route, 73 | (req: Request, res: Response, next: NextFunction) => { 74 | const signature = req.headers["stripe-signature"]; 75 | if (!signature) { 76 | res.status(400).end("Bad signature"); 77 | return; 78 | } 79 | 80 | try { 81 | this.stripe.webhooks.constructEvent( 82 | // @ts-expect-error - rawBody is not defined in express 83 | req.rawBody, 84 | signature, 85 | endpointSecret 86 | ); 87 | } catch (err) { 88 | res.status(400).end(err); 89 | return; 90 | } 91 | 92 | next(); 93 | } 94 | ); 95 | 96 | this.isExpressSetup = true; 97 | } 98 | 99 | getHandler(event: Stripe.Event): WebHookHandler | null { 100 | const parts = event.type.split("."); 101 | let node = this.handlers; 102 | 103 | for (const p of parts) { 104 | // @ts-expect-error - node is not a string 105 | node = node[parts[p]]; 106 | 107 | if (!node) { 108 | return null; 109 | } 110 | } 111 | 112 | return node as any as WebHookHandler; 113 | } 114 | 115 | _create(event: Stripe.Event, params: Params) { 116 | const handler = this.getHandler(event); 117 | if (!handler) { 118 | // No handler, nothing to do 119 | return Promise.resolve({}); 120 | } 121 | 122 | return handler({ object: event.data.object, event, params, app: this.app }); 123 | } 124 | 125 | _find: never; 126 | _get: never; 127 | _update: never; 128 | _patch: never; 129 | _remove: never; 130 | } 131 | 132 | export type SetupWebHookOptions = { 133 | endpointSecret: string; 134 | stripe: Stripe; 135 | handlers: WebHookHandlers; 136 | }; 137 | 138 | export function setupWebhook( 139 | app: Application, 140 | route: string, 141 | { endpointSecret, stripe, handlers }: SetupWebHookOptions 142 | ) { 143 | const service = new WebhookService({ 144 | handlers, 145 | stripe, 146 | app 147 | }); 148 | 149 | service.setupExpress(route, endpointSecret); 150 | 151 | return service; 152 | } 153 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import type Stripe from "stripe"; 2 | import type { PaginationOptions, Params } from "@feathersjs/feathers"; 3 | 4 | export type StripeServiceOptions = { 5 | paginate?: PaginationOptions; 6 | stripe: Stripe; 7 | }; 8 | 9 | export type ParamsWithStripe = { 10 | stripe?: Stripe.RequestOptions; 11 | [key: string]: any; 12 | }; 13 | 14 | export type ParamsWithStripeFee = { 15 | stripe: Partial & { fee: string }; 16 | [key: string]: any; 17 | }; 18 | 19 | export type ParamsWithStripeQuery = Params & { 20 | stripe?: Stripe.RequestOptions; 21 | [key: string]: any; 22 | }; 23 | 24 | export interface IUnderScoreFunctions { 25 | _find: never | ((...args: any) => any); 26 | _get: never | ((...args: any) => any); 27 | _create: never | ((data: any, params: any) => any); 28 | _update: never | ((id: string, data: any, params: any) => any); 29 | _patch: never | ((id: string, data: any, params: any) => any); 30 | _remove: never | ((id: string, params: any) => any); 31 | _search?: never | ((...args: any) => any); 32 | } 33 | 34 | export type FindMethod = (params: P) => Promise>; 35 | -------------------------------------------------------------------------------- /test/error-handler.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "vitest"; 2 | import { 3 | GeneralError, 4 | PaymentError, 5 | BadRequest, 6 | Unavailable, 7 | NotAuthenticated 8 | } from "@feathersjs/errors"; 9 | import Stripe from "stripe"; 10 | import { AccountLinkService } from "../src"; 11 | 12 | describe("handleError", () => { 13 | // @ts-expect-error - we don't need stripe for this test 14 | const service = new AccountLinkService({ stripe: {} }); 15 | 16 | describe("when it is a Stripe error", () => { 17 | let error: Stripe.errors.StripeError; 18 | 19 | it("handles StripeCardError", () => { 20 | error = Stripe.errors.StripeError.generate({ type: "card_error" }); 21 | 22 | expect(() => service.handleError(error)).to.throw(PaymentError); 23 | }); 24 | 25 | it("handles StripeInvalidRequestError", () => { 26 | error = Stripe.errors.StripeError.generate({ type: "invalid_request_error" }); 27 | 28 | expect(() => service.handleError(error)).to.throw(BadRequest); 29 | }); 30 | 31 | it("handles StripeAPIError", () => { 32 | error = Stripe.errors.StripeError.generate({ type: "api_error" }); 33 | 34 | expect(() => service.handleError(error)).to.throw(Unavailable); 35 | }); 36 | 37 | it("handles StripeConnectionError", () => { 38 | error = new Stripe.errors.StripeConnectionError({ type: "api_error" }); 39 | 40 | expect(() => service.handleError(error)).to.throw(Unavailable); 41 | }); 42 | 43 | it("handles StripeAuthenticationError", () => { 44 | error = Stripe.errors.StripeError.generate({ type: "authentication_error" }); 45 | 46 | expect(() => service.handleError(error)).to.throw(NotAuthenticated); 47 | }); 48 | 49 | it("handles unknown Stripe errors", () => { 50 | error = Stripe.errors.StripeError.generate({ type: "Unknown" as Stripe.RawErrorType }); 51 | 52 | expect(() => service.handleError(error)).to.throw(GeneralError); 53 | }); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /test/filter-params.test.ts: -------------------------------------------------------------------------------- 1 | import { expect, expectTypeOf } from "vitest"; 2 | import { AccountLinkService } from "../src"; 3 | import { BaseService } from "../src/services/base"; 4 | 5 | describe("filterQuery", () => { 6 | // @ts-expect-error - we don't need stripe for this test 7 | const service = new AccountLinkService({ stripe: {} }); 8 | 9 | describe("when $limit is present", () => { 10 | const params = { 11 | customer: 1, 12 | query: { 13 | $limit: 5, 14 | name: "bob" 15 | } 16 | }; 17 | 18 | it("replaces $limit with limit", () => { 19 | const query = service.filterQuery(params); 20 | expectTypeOf(query).toEqualTypeOf<{ limit: number; name: string }>(); 21 | expectTypeOf(query).not.toHaveProperty("$limit"); 22 | // @ts-expect-error $limit should not exits anymore on this type 23 | expect(query.$limit).to.equal(undefined); 24 | expect(query.limit).to.equal(5); 25 | }); 26 | 27 | it("does not modify original params", () => { 28 | const paramsCopy = Object.assign({}, params); 29 | service.filterQuery(params); 30 | expect(params).to.deep.equal(paramsCopy); 31 | }); 32 | 33 | it("returns original query object params", () => { 34 | const query = service.filterQuery(params); 35 | expectTypeOf(query).toEqualTypeOf<{ limit: number; name: string }>(); 36 | expect(query.name).to.equal("bob"); 37 | }); 38 | }); 39 | 40 | describe("when $limit is not present", () => { 41 | it("returns original query object", () => { 42 | const params = { 43 | customer: 1, 44 | query: { 45 | name: "bob" 46 | } 47 | }; 48 | const query = service.filterQuery(params); 49 | expectTypeOf(query).toEqualTypeOf<{ name: string }>(); 50 | expect(query).to.deep.equal({ name: "bob" }); 51 | }); 52 | }); 53 | }); 54 | 55 | describe("filterParams", () => { 56 | abstract class TestService extends BaseService { 57 | _create(data: any, params: any) { 58 | return this.filterParams(params); 59 | } 60 | } 61 | // @ts-expect-error - we don't need stripe for this test 62 | const service = new TestService({ stripe: {} }); 63 | 64 | describe("when params are not present", () => { 65 | const params: undefined = undefined; 66 | 67 | it("returns empty values", () => { 68 | expect(() => service.filterParams(params)).to.throw(); 69 | }); 70 | }); 71 | 72 | describe("when stripe is present", () => { 73 | const params = { 74 | stripe: { 75 | expand: ["customer"] 76 | } 77 | }; 78 | 79 | it("picks off stripe", () => { 80 | const { stripe } = service.filterParams(params as any); 81 | expect(stripe).to.deep.equal(params.stripe); 82 | }); 83 | }); 84 | 85 | describe("when stripe is not present", () => { 86 | it("returns empty object", () => { 87 | const params = {}; 88 | const { stripe } = service.filterParams(params); 89 | expect(stripe).to.deep.equal(undefined); 90 | }); 91 | }); 92 | }); 93 | 94 | describe("cleanQuery", () => { 95 | // @ts-expect-error - we don't need stripe for this test 96 | const service = new AccountLinkService({ stripe: {} }); 97 | 98 | describe("when $ keys are present", () => { 99 | const query = { 100 | prop: { $gt: Date.now() }, 101 | nested: { nested: { $gt: Date.now() } }, 102 | array: [{ $lt: Date.now() }] 103 | }; 104 | 105 | const expected = { 106 | prop: { gt: Date.now() }, 107 | nested: { nested: { gt: Date.now() } }, 108 | array: [{ lt: Date.now() }] 109 | }; 110 | 111 | it("strips keys that start with $", () => { 112 | const cleanQuery = service.cleanQuery(query); 113 | expectTypeOf(cleanQuery).toEqualTypeOf(); 114 | expect(cleanQuery).to.deep.equal(expected); 115 | }); 116 | }); 117 | 118 | describe("when $ keys are not present", () => { 119 | const query = { 120 | prop: { gt: Date.now() }, 121 | nested: { nested: { gt: Date.now() } }, 122 | array: [{ lt: Date.now() }] 123 | }; 124 | 125 | it("does not modify orignal keys", () => { 126 | const cleanQuery = service.cleanQuery(query); 127 | expectTypeOf(cleanQuery).toEqualTypeOf(); 128 | expect(cleanQuery).to.deep.equal(query); 129 | }); 130 | }); 131 | }); 132 | -------------------------------------------------------------------------------- /test/index.test.ts: -------------------------------------------------------------------------------- 1 | import { expect } from "vitest"; 2 | import { 3 | AccountService, 4 | AccountLinkService, 5 | ApplicationFeeRefundService, 6 | BalanceService, 7 | BalanceTransactionService, 8 | BankAccountService, 9 | ExternalAccountService, 10 | CardService, 11 | ChargeService, 12 | CouponService, 13 | CustomerService, 14 | DisputeService, 15 | EventService, 16 | PaymentIntentService, 17 | PaymentMethodService, 18 | InvoiceService, 19 | InvoiceItemService, 20 | PayoutService, 21 | PlanService, 22 | PriceService, 23 | ProductService, 24 | RefundService, 25 | SetupIntentService, 26 | SourceService, 27 | SubscriptionService, 28 | SubscriptionItemService, 29 | TokenService, 30 | TransactionService, 31 | TransferService, 32 | TransferReversalService, 33 | WebhookService 34 | } from "../src"; 35 | 36 | const services = [ 37 | AccountService, 38 | AccountLinkService, 39 | ApplicationFeeRefundService, 40 | BalanceService, 41 | BalanceTransactionService, 42 | BankAccountService, 43 | ExternalAccountService, 44 | CardService, 45 | ChargeService, 46 | CouponService, 47 | CustomerService, 48 | DisputeService, 49 | EventService, 50 | PaymentIntentService, 51 | PaymentMethodService, 52 | InvoiceService, 53 | InvoiceItemService, 54 | PayoutService, 55 | PlanService, 56 | PriceService, 57 | ProductService, 58 | RefundService, 59 | SetupIntentService, 60 | SourceService, 61 | SubscriptionService, 62 | SubscriptionItemService, 63 | TokenService, 64 | TransactionService, 65 | TransferService, 66 | TransferReversalService, 67 | WebhookService 68 | ]; 69 | 70 | describe("feathers-stripe", () => { 71 | it("exports expected classes", () => { 72 | services.forEach((Service) => { 73 | expect(Service).to.be.a("function"); 74 | }); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "include": ["./**.test.ts"], 4 | "exclude": [], 5 | "compilerOptions": { 6 | "types": ["vitest/globals"] 7 | } 8 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "include": ["src/**/*.ts"], 3 | "exclude": ["test/**/*.test.ts"], 4 | "compilerOptions": { 5 | "outDir": "dist", 6 | /* Basic Options */ 7 | "target": "es2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */, 8 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | "declaration": true /* Generates corresponding '.d.ts' file. */, 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | "sourceMap": true /* Generates corresponding '.map' file. */, 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | // "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 18 | // "composite": true, /* Enable project compilation */ 19 | // "removeComments": true, /* Do not emit comments to output. */ 20 | // "noEmit": true, /* Do not emit outputs. */ 21 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 22 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 23 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 24 | 25 | /* Strict Type-Checking Options */ 26 | "strict": true /* Enable all strict type-checking options. */, 27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 28 | "strictNullChecks": false /* Enable strict null checks. */, 29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 30 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 31 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 32 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 33 | 34 | /* Additional Checks */ 35 | "noUnusedLocals": true /* Report errors on unused locals. */, 36 | "noUnusedParameters": true /* Report errors on unused parameters. */, 37 | "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, 38 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 39 | 40 | /* Module Resolution Options */ 41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 45 | // "typeRoots": [], /* List of folders to include type definitions from. */ 46 | // "types": [], /* Type declaration files to be included in compilation. */ 47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 48 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 50 | 51 | /* Source Map Options */ 52 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 53 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 54 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 55 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 56 | 57 | /* Experimental Options */ 58 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 59 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 60 | "types": ["vitest/globals"] 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /vite.config.mts: -------------------------------------------------------------------------------- 1 | /// 2 | import path from "node:path"; 3 | import { defineConfig } from "vite"; 4 | import pkg from "./package.json"; 5 | 6 | export default defineConfig({ 7 | build: { 8 | minify: false, 9 | lib: { 10 | entry: path.resolve(__dirname, "src/index.ts"), 11 | name: "index", 12 | fileName: "index", 13 | formats: ["es", "cjs"] 14 | }, 15 | // outDir: path.resolve(__dirname, "dist"), 16 | sourcemap: true, 17 | rollupOptions: { 18 | // make sure to externalize deps that shouldn't be bundled 19 | // into your library 20 | external: [...Object.keys(pkg.dependencies), /^node:/], 21 | output: {} 22 | } 23 | }, 24 | test: { 25 | globals: true 26 | } 27 | }); 28 | --------------------------------------------------------------------------------