ghost 5.115.0 → 5.116.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (341) hide show
  1. package/components/{tryghost-api-framework-5.115.0.tgz → tryghost-api-framework-5.116.0.tgz} +0 -0
  2. package/components/tryghost-constants-5.116.0.tgz +0 -0
  3. package/components/tryghost-custom-fonts-5.116.0.tgz +0 -0
  4. package/components/{tryghost-custom-theme-settings-service-5.115.0.tgz → tryghost-custom-theme-settings-service-5.116.0.tgz} +0 -0
  5. package/components/tryghost-domain-events-5.116.0.tgz +0 -0
  6. package/components/{tryghost-donations-5.115.0.tgz → tryghost-donations-5.116.0.tgz} +0 -0
  7. package/components/tryghost-email-addresses-5.116.0.tgz +0 -0
  8. package/components/tryghost-email-service-5.116.0.tgz +0 -0
  9. package/components/tryghost-email-suppression-list-5.116.0.tgz +0 -0
  10. package/components/tryghost-html-to-plaintext-5.116.0.tgz +0 -0
  11. package/components/tryghost-i18n-5.116.0.tgz +0 -0
  12. package/components/tryghost-job-manager-5.116.0.tgz +0 -0
  13. package/components/tryghost-link-replacer-5.116.0.tgz +0 -0
  14. package/components/tryghost-magic-link-5.116.0.tgz +0 -0
  15. package/components/tryghost-member-attribution-5.116.0.tgz +0 -0
  16. package/components/tryghost-member-events-5.116.0.tgz +0 -0
  17. package/components/tryghost-members-api-5.116.0.tgz +0 -0
  18. package/components/tryghost-members-csv-5.116.0.tgz +0 -0
  19. package/components/{tryghost-members-offers-5.115.0.tgz → tryghost-members-offers-5.116.0.tgz} +0 -0
  20. package/components/{tryghost-milestones-5.115.0.tgz → tryghost-milestones-5.116.0.tgz} +0 -0
  21. package/components/{tryghost-mw-error-handler-5.115.0.tgz → tryghost-mw-error-handler-5.116.0.tgz} +0 -0
  22. package/components/tryghost-mw-vhost-5.116.0.tgz +0 -0
  23. package/components/{tryghost-post-events-5.115.0.tgz → tryghost-post-events-5.116.0.tgz} +0 -0
  24. package/components/{tryghost-post-revisions-5.115.0.tgz → tryghost-post-revisions-5.116.0.tgz} +0 -0
  25. package/components/tryghost-posts-service-5.116.0.tgz +0 -0
  26. package/components/{tryghost-prometheus-metrics-5.115.0.tgz → tryghost-prometheus-metrics-5.116.0.tgz} +0 -0
  27. package/components/tryghost-security-5.116.0.tgz +0 -0
  28. package/components/{tryghost-tiers-5.115.0.tgz → tryghost-tiers-5.116.0.tgz} +0 -0
  29. package/components/tryghost-webmentions-5.116.0.tgz +0 -0
  30. package/content/themes/casper/LICENSE +1 -1
  31. package/content/themes/casper/README.md +1 -1
  32. package/content/themes/source/LICENSE +1 -1
  33. package/content/themes/source/README.md +1 -1
  34. package/content/themes/source/assets/built/screen.css +1 -1
  35. package/content/themes/source/assets/built/screen.css.map +1 -1
  36. package/content/themes/source/assets/css/screen.css +11 -6
  37. package/content/themes/source/partials/feature-image.hbs +2 -2
  38. package/core/boot.js +3 -43
  39. package/core/built/admin/assets/admin-x-activitypub/admin-x-activitypub.js +30494 -29403
  40. package/core/built/admin/assets/admin-x-demo/admin-x-demo.js +1 -1
  41. package/core/built/admin/assets/admin-x-demo/{index-0040480a.mjs → index-a9601514.mjs} +5 -4
  42. package/core/built/admin/assets/admin-x-demo/{modals-fb35c86c.mjs → modals-c1789d04.mjs} +67 -65
  43. package/core/built/admin/assets/admin-x-settings/{CodeEditorView-806ef39c.mjs → CodeEditorView-e9c9deb8.mjs} +2 -2
  44. package/core/built/admin/assets/admin-x-settings/admin-x-settings.js +2 -2
  45. package/core/built/admin/assets/admin-x-settings/{index-376f847c.mjs → index-84580c3a.mjs} +2 -2
  46. package/core/built/admin/assets/admin-x-settings/{index-8fa19303.mjs → index-f744cab7.mjs} +3147 -3123
  47. package/core/built/admin/assets/admin-x-settings/{modals-36775d71.mjs → modals-d9ca60c5.mjs} +1198 -1192
  48. package/core/built/admin/assets/chunk.524.8371443ef8f60db429d0.js +35 -0
  49. package/core/built/admin/assets/chunk.582.f90151775f2e53dd21d9.js +37 -0
  50. package/core/built/admin/assets/{chunk.874.461cb3cf5b6b36915f8c.js → chunk.713.e9027c0cc3c56110f5da.js} +125 -98
  51. package/core/built/admin/assets/{ghost-938b3d9c29e3564a53a22f8c8f82d351.js → ghost-03b64c086f3c60cabc85fe7a7e2b640a.js} +272 -251
  52. package/core/built/admin/assets/ghost-ba58e9822f7384461e926c7e23f04a75.css +1 -0
  53. package/core/built/admin/assets/ghost-dark-f1f29683b14ffa11615b3bba8b6ab92c.css +1 -0
  54. package/core/built/admin/assets/koenig-lexical/index.css +1 -1
  55. package/core/built/admin/assets/koenig-lexical/koenig-lexical.js +20563 -20891
  56. package/core/built/admin/assets/koenig-lexical/koenig-lexical.umd.js +139 -139
  57. package/core/built/admin/assets/posts/posts.js +5732 -5667
  58. package/core/built/admin/assets/stats/stats.js +75373 -0
  59. package/core/built/admin/assets/{vendor-68a4aa424a179a90f5bbc2b750def576.js → vendor-72026232b36d97babc6320917c16c321.js} +36 -34
  60. package/core/built/admin/index.html +6 -6
  61. package/core/cli/generate-data.js +1 -1
  62. package/core/frontend/helpers/ghost_head.js +8 -1
  63. package/core/frontend/public/ghost-stats.js +55 -2
  64. package/core/frontend/services/assets-minification/AdminAuthAssets.js +2 -1
  65. package/core/frontend/services/assets-minification/CardAssets.js +1 -1
  66. package/core/frontend/services/assets-minification/CommentCountsAssets.js +1 -1
  67. package/core/frontend/services/assets-minification/MemberAttributionAssets.js +1 -1
  68. package/core/frontend/services/assets-minification/Minifier.js +191 -0
  69. package/core/frontend/services/routing/controllers/previews.js +2 -1
  70. package/core/frontend/src/cards/css/cta.css +1 -1
  71. package/core/server/adapters/cache/Redis.js +1 -1
  72. package/core/server/adapters/lib/redis/AdapterCacheRedis.js +287 -0
  73. package/core/server/adapters/lib/redis/redis-store-factory.js +22 -0
  74. package/core/server/api/endpoints/posts.js +9 -3
  75. package/core/server/api/endpoints/previews.js +35 -1
  76. package/core/server/api/endpoints/slugs.js +6 -2
  77. package/core/server/api/endpoints/utils/serializers/output/utils/post-gating.js +6 -9
  78. package/core/server/api/endpoints/utils/validators/input/settings.js +1 -1
  79. package/core/server/data/db/connection.js +2 -0
  80. package/core/server/data/db/index.js +1 -0
  81. package/core/server/data/importer/handlers/ImporterContentFileHandler.js +90 -0
  82. package/core/server/data/importer/import-manager.js +3 -3
  83. package/core/server/data/importer/importers/importer-revue.js +128 -0
  84. package/core/server/data/importer/importers/json-to-html.js +107 -0
  85. package/core/server/data/migrations/utils/tables.js +2 -4
  86. package/core/server/data/seeders/DataGenerator.js +288 -0
  87. package/core/server/data/seeders/importers/BenefitsImporter.js +28 -0
  88. package/core/server/data/seeders/importers/CommentsImporter.js +73 -0
  89. package/core/server/data/seeders/importers/EmailBatchesImporter.js +38 -0
  90. package/core/server/data/seeders/importers/EmailRecipientFailuresImporter.js +67 -0
  91. package/core/server/data/seeders/importers/EmailRecipientsImporter.js +212 -0
  92. package/core/server/data/seeders/importers/EmailsImporter.js +99 -0
  93. package/core/server/data/seeders/importers/LabelsImporter.js +41 -0
  94. package/core/server/data/seeders/importers/MembersClickEventsImporter.js +69 -0
  95. package/core/server/data/seeders/importers/MembersCreatedEventsImporter.js +103 -0
  96. package/core/server/data/seeders/importers/MembersFeedbackImporter.js +45 -0
  97. package/core/server/data/seeders/importers/MembersImporter.js +111 -0
  98. package/core/server/data/seeders/importers/MembersLabelsImporter.js +39 -0
  99. package/core/server/data/seeders/importers/MembersLoginEventsImporter.js +69 -0
  100. package/core/server/data/seeders/importers/MembersNewslettersImporter.js +38 -0
  101. package/core/server/data/seeders/importers/MembersPaidSubscriptionEventsImporter.js +99 -0
  102. package/core/server/data/seeders/importers/MembersProductsImporter.js +42 -0
  103. package/core/server/data/seeders/importers/MembersStatusEventsImporter.js +58 -0
  104. package/core/server/data/seeders/importers/MembersStripeCustomersImporter.js +60 -0
  105. package/core/server/data/seeders/importers/MembersStripeCustomersSubscriptionsImporter.js +259 -0
  106. package/core/server/data/seeders/importers/MembersSubscribeEventsImporter.js +69 -0
  107. package/core/server/data/seeders/importers/MembersSubscriptionCreatedEventsImporter.js +95 -0
  108. package/core/server/data/seeders/importers/NewslettersImporter.js +40 -0
  109. package/core/server/data/seeders/importers/OffersImporter.js +70 -0
  110. package/core/server/data/seeders/importers/PostsAuthorsImporter.js +32 -0
  111. package/core/server/data/seeders/importers/PostsImporter.js +102 -0
  112. package/core/server/data/seeders/importers/PostsProductsImporter.js +35 -0
  113. package/core/server/data/seeders/importers/PostsTagsImporter.js +46 -0
  114. package/core/server/data/seeders/importers/ProductsBenefitsImporter.js +54 -0
  115. package/core/server/data/seeders/importers/ProductsImporter.js +90 -0
  116. package/core/server/data/seeders/importers/RecommendationClickEventsImporter.js +32 -0
  117. package/core/server/data/seeders/importers/RecommendationSubscribeEventsImporter.js +32 -0
  118. package/core/server/data/seeders/importers/RecommendationsImporter.js +34 -0
  119. package/core/server/data/seeders/importers/RedirectsImporter.js +49 -0
  120. package/core/server/data/seeders/importers/RolesUsersImporter.js +42 -0
  121. package/core/server/data/seeders/importers/StripePricesImporter.js +69 -0
  122. package/core/server/data/seeders/importers/StripeProductsImporter.js +34 -0
  123. package/core/server/data/seeders/importers/TableImporter.js +187 -0
  124. package/core/server/data/seeders/importers/TagsImporter.js +41 -0
  125. package/core/server/data/seeders/importers/UsersImporter.js +31 -0
  126. package/core/server/data/seeders/importers/WebMentionsImporter.js +42 -0
  127. package/core/server/data/seeders/importers/index.js +41 -0
  128. package/core/server/data/seeders/utils/JsonImporter.js +39 -0
  129. package/core/server/data/seeders/utils/blog-info.js +3 -0
  130. package/core/server/data/seeders/utils/database-date.js +7 -0
  131. package/core/server/data/seeders/utils/event-generator.js +48 -0
  132. package/core/server/data/seeders/utils/random.js +13 -0
  133. package/core/server/data/seeders/utils/topological-sort.js +33 -0
  134. package/core/server/lib/bootstrap-socket.js +87 -0
  135. package/core/server/lib/package-json/index.js +1 -0
  136. package/core/server/lib/package-json/package-json.js +160 -0
  137. package/core/server/lib/package-json/parse.js +57 -0
  138. package/core/server/models/base/plugins/actions.js +44 -31
  139. package/core/server/models/base/plugins/generate-slug.js +6 -0
  140. package/core/server/notify.js +1 -1
  141. package/core/server/services/activitypub/ActivityPubService.ts +1 -1
  142. package/core/server/services/adapter-manager/AdapterManager.js +161 -0
  143. package/core/server/services/adapter-manager/index.js +1 -1
  144. package/core/server/services/announcement-bar-service/AnnouncementBarSettings.js +54 -0
  145. package/core/server/services/announcement-bar-service/AnnouncementVisibilityValues.js +11 -0
  146. package/core/server/services/announcement-bar-service/index.js +1 -1
  147. package/core/server/services/api-version-compatibility/APIVersionCompatibilityService.js +99 -0
  148. package/core/server/services/api-version-compatibility/VersionNotificationsDataService.js +80 -0
  149. package/core/server/services/api-version-compatibility/extract-api-key.js +57 -0
  150. package/core/server/services/api-version-compatibility/index.js +2 -2
  151. package/core/server/services/api-version-compatibility/mw-api-version-mismatch.js +31 -0
  152. package/core/server/services/audience-feedback/AudienceFeedbackController.js +85 -0
  153. package/core/server/services/audience-feedback/AudienceFeedbackService.js +34 -0
  154. package/core/server/services/audience-feedback/Feedback.js +35 -0
  155. package/core/server/services/audience-feedback/index.js +4 -2
  156. package/core/server/services/auth/session/emails/signin.js +168 -0
  157. package/core/server/services/auth/session/index.js +2 -2
  158. package/core/server/services/auth/session/session-from-token.js +69 -0
  159. package/core/server/services/auth/session/session-service.js +374 -0
  160. package/core/server/services/custom-redirects/index.js +1 -1
  161. package/core/server/services/email-analytics/EmailAnalyticsProviderMailgun.js +62 -0
  162. package/core/server/services/email-analytics/EmailAnalyticsService.js +552 -0
  163. package/core/server/services/email-analytics/EmailAnalyticsServiceWrapper.js +3 -3
  164. package/core/server/services/email-analytics/EventProcessingResult.js +66 -0
  165. package/core/server/services/email-service/EmailServiceWrapper.js +4 -4
  166. package/core/server/services/email-suppression-list/MailgunEmailSuppressionList.js +1 -1
  167. package/core/server/services/email-suppression-list/service.js +1 -1
  168. package/core/server/services/explore-ping/ExplorePingService.js +106 -0
  169. package/core/server/services/explore-ping/index.js +31 -0
  170. package/core/server/services/identity-tokens/IdentityTokenService.js +30 -0
  171. package/core/server/services/identity-tokens/IdentityTokenService.ts +28 -0
  172. package/core/server/services/identity-tokens/IdentityTokenServiceWrapper.js +1 -1
  173. package/core/server/services/invitations/accept.js +5 -2
  174. package/core/server/services/lib/DynamicRedirectManager.js +156 -0
  175. package/core/server/services/lib/EmailContentGenerator.js +54 -0
  176. package/core/server/services/lib/InMemoryRepository.js +62 -0
  177. package/core/server/services/lib/InMemoryRepository.ts +80 -0
  178. package/core/server/services/lib/MailgunClient.js +364 -0
  179. package/core/server/services/link-redirection/LinkRedirect.js +26 -0
  180. package/core/server/services/link-redirection/LinkRedirectRepository.js +7 -7
  181. package/core/server/services/link-redirection/LinkRedirectsService.js +123 -0
  182. package/core/server/services/link-redirection/README.md +151 -0
  183. package/core/server/services/link-redirection/RedirectEvent.js +24 -0
  184. package/core/server/services/link-redirection/index.js +1 -1
  185. package/core/server/services/link-tracking/LinkClickTrackingService.js +1 -1
  186. package/core/server/services/mail/index.js +1 -1
  187. package/core/server/services/mail-events/BookshelfMailEventRepository.js +2 -2
  188. package/core/server/services/mail-events/InMemoryMailEventRepository.js +10 -0
  189. package/core/server/services/mail-events/InMemoryMailEventRepository.ts +8 -0
  190. package/core/server/services/mail-events/MailEvent.js +20 -0
  191. package/core/server/services/mail-events/MailEvent.ts +10 -0
  192. package/core/server/services/mail-events/MailEventRepository.js +2 -0
  193. package/core/server/services/mail-events/MailEventRepository.ts +5 -0
  194. package/core/server/services/mail-events/MailEventService.js +124 -0
  195. package/core/server/services/mail-events/MailEventService.ts +169 -0
  196. package/core/server/services/mail-events/index.js +1 -1
  197. package/core/server/services/mail-events/libraries.d.ts +2 -0
  198. package/core/server/services/members/CaptchaService.js +80 -0
  199. package/core/server/services/members/api.js +1 -1
  200. package/core/server/services/members/importer/MembersCSVImporter.js +464 -0
  201. package/core/server/services/members/importer/MembersCSVImporterStripeUtils.js +194 -0
  202. package/core/server/services/members/importer/email-template.js +182 -0
  203. package/core/server/services/members/importer/index.js +30 -0
  204. package/core/server/services/members/members-ssr.js +333 -0
  205. package/core/server/services/members/service.js +2 -2
  206. package/core/server/services/members-events/LastSeenAtUpdater.js +1 -1
  207. package/core/server/services/offers/service.js +1 -1
  208. package/core/server/services/posts/stats/PostStats.js +13 -0
  209. package/core/server/services/recommendations/RecommendationServiceWrapper.js +8 -8
  210. package/core/server/services/recommendations/service/BookshelfClickEventRepository.js +48 -0
  211. package/core/server/services/recommendations/service/BookshelfClickEventRepository.ts +49 -0
  212. package/core/server/services/recommendations/service/BookshelfRecommendationRepository.js +98 -0
  213. package/core/server/services/recommendations/service/BookshelfRecommendationRepository.ts +117 -0
  214. package/core/server/services/recommendations/service/BookshelfRepository.js +134 -0
  215. package/core/server/services/recommendations/service/BookshelfRepository.ts +196 -0
  216. package/core/server/services/recommendations/service/BookshelfSubscribeEventRepository.js +48 -0
  217. package/core/server/services/recommendations/service/BookshelfSubscribeEventRepository.ts +49 -0
  218. package/core/server/services/recommendations/service/ClickEvent.js +33 -0
  219. package/core/server/services/recommendations/service/ClickEvent.ts +32 -0
  220. package/core/server/services/recommendations/service/InMemoryRecommendationRepository.js +19 -0
  221. package/core/server/services/recommendations/service/InMemoryRecommendationRepository.ts +20 -0
  222. package/core/server/services/recommendations/service/IncomingRecommendationController.js +34 -0
  223. package/core/server/services/recommendations/service/IncomingRecommendationController.ts +51 -0
  224. package/core/server/services/recommendations/service/IncomingRecommendationEmailRenderer.js +25 -0
  225. package/core/server/services/recommendations/service/IncomingRecommendationEmailRenderer.ts +37 -0
  226. package/core/server/services/recommendations/service/IncomingRecommendationService.js +93 -0
  227. package/core/server/services/recommendations/service/IncomingRecommendationService.ts +160 -0
  228. package/core/server/services/recommendations/service/Recommendation.js +140 -0
  229. package/core/server/services/recommendations/service/Recommendation.ts +201 -0
  230. package/core/server/services/recommendations/service/RecommendationController.js +208 -0
  231. package/core/server/services/recommendations/service/RecommendationController.ts +258 -0
  232. package/core/server/services/recommendations/service/RecommendationMetadataService.js +86 -0
  233. package/core/server/services/recommendations/service/RecommendationMetadataService.ts +128 -0
  234. package/core/server/services/recommendations/service/RecommendationRepository.js +2 -0
  235. package/core/server/services/recommendations/service/RecommendationRepository.ts +13 -0
  236. package/core/server/services/recommendations/service/RecommendationService.js +228 -0
  237. package/core/server/services/recommendations/service/RecommendationService.ts +281 -0
  238. package/core/server/services/recommendations/service/SubscribeEvent.js +33 -0
  239. package/core/server/services/recommendations/service/SubscribeEvent.ts +32 -0
  240. package/core/server/services/recommendations/service/UnsafeData.js +183 -0
  241. package/core/server/services/recommendations/service/UnsafeData.ts +217 -0
  242. package/core/server/services/recommendations/service/WellknownService.js +36 -0
  243. package/core/server/services/recommendations/service/WellknownService.ts +47 -0
  244. package/core/server/services/recommendations/service/index.js +31 -0
  245. package/core/server/services/recommendations/service/index.ts +15 -0
  246. package/core/server/services/recommendations/service/libraries.d.ts +5 -0
  247. package/core/server/services/route-settings/SettingsPathManager.js +47 -0
  248. package/core/server/services/route-settings/index.js +1 -1
  249. package/core/server/services/slack-notifications/SlackNotifications.js +211 -0
  250. package/core/server/services/slack-notifications/SlackNotificationsService.js +90 -0
  251. package/core/server/services/slack-notifications/service.js +4 -6
  252. package/core/server/services/stripe/README.md +63 -0
  253. package/core/server/services/stripe/StripeAPI.js +931 -0
  254. package/core/server/services/stripe/StripeMigrations.js +613 -0
  255. package/core/server/services/stripe/StripeService.js +175 -0
  256. package/core/server/services/stripe/WebhookController.js +100 -0
  257. package/core/server/services/stripe/WebhookManager.js +175 -0
  258. package/core/server/services/stripe/events/StripeLiveDisabledEvent.js +23 -0
  259. package/core/server/services/stripe/events/StripeLiveEnabledEvent.js +23 -0
  260. package/core/server/services/stripe/events/index.js +4 -0
  261. package/core/server/services/stripe/service.js +1 -1
  262. package/core/server/services/stripe/services/webhook/CheckoutSessionEventService.js +255 -0
  263. package/core/server/services/stripe/services/webhook/InvoiceEventService.js +70 -0
  264. package/core/server/services/stripe/services/webhook/SubscriptionEventService.js +54 -0
  265. package/core/server/services/themes/loader.js +1 -1
  266. package/core/server/services/themes/to-json.js +1 -1
  267. package/core/server/web/api/endpoints/admin/app.js +1 -21
  268. package/core/server/web/api/endpoints/admin/routes.js +1 -0
  269. package/core/server/web/api/middleware/version-match.js +41 -0
  270. package/core/server/web/shared/middleware/cache-control.js +51 -0
  271. package/core/server/web/shared/middleware/index.js +1 -1
  272. package/core/server/web/well-known.js +1 -1
  273. package/core/shared/labs.js +5 -3
  274. package/core/shared/settings-cache/CacheManager.js +64 -6
  275. package/package.json +98 -146
  276. package/tsconfig.tsbuildinfo +1 -1
  277. package/yarn.lock +1478 -1634
  278. package/components/tryghost-adapter-cache-redis-5.115.0.tgz +0 -0
  279. package/components/tryghost-adapter-manager-5.115.0.tgz +0 -0
  280. package/components/tryghost-announcement-bar-settings-5.115.0.tgz +0 -0
  281. package/components/tryghost-api-version-compatibility-service-5.115.0.tgz +0 -0
  282. package/components/tryghost-audience-feedback-5.115.0.tgz +0 -0
  283. package/components/tryghost-bookshelf-repository-5.115.0.tgz +0 -0
  284. package/components/tryghost-bootstrap-socket-5.115.0.tgz +0 -0
  285. package/components/tryghost-captcha-service-5.115.0.tgz +0 -0
  286. package/components/tryghost-constants-5.115.0.tgz +0 -0
  287. package/components/tryghost-custom-fonts-5.115.0.tgz +0 -0
  288. package/components/tryghost-data-generator-5.115.0.tgz +0 -0
  289. package/components/tryghost-domain-events-5.115.0.tgz +0 -0
  290. package/components/tryghost-email-addresses-5.115.0.tgz +0 -0
  291. package/components/tryghost-email-analytics-provider-mailgun-5.115.0.tgz +0 -0
  292. package/components/tryghost-email-analytics-service-5.115.0.tgz +0 -0
  293. package/components/tryghost-email-content-generator-5.115.0.tgz +0 -0
  294. package/components/tryghost-email-events-5.115.0.tgz +0 -0
  295. package/components/tryghost-email-service-5.115.0.tgz +0 -0
  296. package/components/tryghost-email-suppression-list-5.115.0.tgz +0 -0
  297. package/components/tryghost-express-dynamic-redirects-5.115.0.tgz +0 -0
  298. package/components/tryghost-extract-api-key-5.115.0.tgz +0 -0
  299. package/components/tryghost-ghost-5.115.0.tgz +0 -0
  300. package/components/tryghost-html-to-plaintext-5.115.0.tgz +0 -0
  301. package/components/tryghost-i18n-5.115.0.tgz +0 -0
  302. package/components/tryghost-identity-token-service-5.115.0.tgz +0 -0
  303. package/components/tryghost-importer-handler-content-files-5.115.0.tgz +0 -0
  304. package/components/tryghost-importer-revue-5.115.0.tgz +0 -0
  305. package/components/tryghost-in-memory-repository-5.115.0.tgz +0 -0
  306. package/components/tryghost-job-manager-5.115.0.tgz +0 -0
  307. package/components/tryghost-link-redirects-5.115.0.tgz +0 -0
  308. package/components/tryghost-link-replacer-5.115.0.tgz +0 -0
  309. package/components/tryghost-magic-link-5.115.0.tgz +0 -0
  310. package/components/tryghost-mail-events-5.115.0.tgz +0 -0
  311. package/components/tryghost-mailgun-client-5.115.0.tgz +0 -0
  312. package/components/tryghost-member-attribution-5.115.0.tgz +0 -0
  313. package/components/tryghost-member-events-5.115.0.tgz +0 -0
  314. package/components/tryghost-members-api-5.115.0.tgz +0 -0
  315. package/components/tryghost-members-csv-5.115.0.tgz +0 -0
  316. package/components/tryghost-members-importer-5.115.0.tgz +0 -0
  317. package/components/tryghost-members-payments-5.115.0.tgz +0 -0
  318. package/components/tryghost-members-ssr-5.115.0.tgz +0 -0
  319. package/components/tryghost-members-stripe-service-5.115.0.tgz +0 -0
  320. package/components/tryghost-minifier-5.115.0.tgz +0 -0
  321. package/components/tryghost-mw-api-version-mismatch-5.115.0.tgz +0 -0
  322. package/components/tryghost-mw-cache-control-5.115.0.tgz +0 -0
  323. package/components/tryghost-mw-session-from-token-5.115.0.tgz +0 -0
  324. package/components/tryghost-mw-update-user-last-seen-5.115.0.tgz +0 -0
  325. package/components/tryghost-mw-version-match-5.115.0.tgz +0 -0
  326. package/components/tryghost-mw-vhost-5.115.0.tgz +0 -0
  327. package/components/tryghost-package-json-5.115.0.tgz +0 -0
  328. package/components/tryghost-posts-service-5.115.0.tgz +0 -0
  329. package/components/tryghost-recommendations-5.115.0.tgz +0 -0
  330. package/components/tryghost-referrers-5.115.0.tgz +0 -0
  331. package/components/tryghost-security-5.115.0.tgz +0 -0
  332. package/components/tryghost-session-service-5.115.0.tgz +0 -0
  333. package/components/tryghost-settings-path-manager-5.115.0.tgz +0 -0
  334. package/components/tryghost-slack-notifications-5.115.0.tgz +0 -0
  335. package/components/tryghost-version-notifications-data-service-5.115.0.tgz +0 -0
  336. package/components/tryghost-webmentions-5.115.0.tgz +0 -0
  337. package/core/built/admin/assets/chunk.524.31419fdf6fb3859ecc1e.js +0 -35
  338. package/core/built/admin/assets/chunk.582.08c816d5e4ab766486a7.js +0 -37
  339. package/core/built/admin/assets/ghost-c2a7c4a1b76550c4219adb2ed4124ce0.css +0 -1
  340. package/core/built/admin/assets/ghost-dark-f91e4a479c6d38d94d5d1b14727871dc.css +0 -1
  341. /package/core/built/admin/assets/{chunk.874.461cb3cf5b6b36915f8c.js.LICENSE.txt → chunk.713.e9027c0cc3c56110f5da.js.LICENSE.txt} +0 -0
@@ -0,0 +1,931 @@
1
+ // @ts-ignore
2
+ const {VersionMismatchError} = require('@tryghost/errors');
3
+ // @ts-ignore
4
+ const debug = require('@tryghost/debug')('stripe');
5
+ const Stripe = require('stripe').Stripe;
6
+
7
+ /* Stripe has the following rate limits:
8
+ * - For most APIs, 100 read requests per second in live mode, 25 read requests per second in test mode
9
+ * - For search, 20 requests per second in both live and test modes
10
+ *
11
+ * For the testing environment, we increase these limits to 10,000 req/s to keep tests fast
12
+ */
13
+ const EXPECTED_API_EFFICIENCY = 0.95;
14
+ const EXPECTED_SEARCH_API_EFFICIENCY = 0.15;
15
+
16
+ // If we're running in a testing environment, we don't want to rate limit the Stripe API like we do in production
17
+ const isTesting = process.env.NODE_ENV?.includes('testing');
18
+ const TEST_MODE_RATE_LIMIT = isTesting ? 10_000 : 25;
19
+ const LIVE_MODE_RATE_LIMIT = isTesting ? 10_000 : 100;
20
+ const SEARCH_MODE_RATE_LIMIT = isTesting ? 10_000 : 100;
21
+
22
+ const STRIPE_API_VERSION = '2020-08-27';
23
+
24
+ /**
25
+ * @typedef {import('stripe').Stripe.Customer} ICustomer
26
+ * @typedef {import('stripe').Stripe.DeletedCustomer} IDeletedCustomer
27
+ * @typedef {import('stripe').Stripe.Product} IProduct
28
+ * @typedef {import('stripe').Stripe.Plan} IPlan
29
+ * @typedef {import('stripe').Stripe.Price} IPrice
30
+ * @typedef {import('stripe').Stripe.WebhookEndpoint} IWebhookEndpoint
31
+ * @typedef {import('stripe').Stripe.Coupon} ICoupon
32
+ * @typedef {import('stripe').Stripe.CouponCreateParams} ICouponCreateParams
33
+ * @typedef {import('stripe').Stripe.ProductCreateParams} IProductCreateParams
34
+ * @typedef {import('stripe').Stripe.CustomerRetrieveParams} ICustomerRetrieveParams
35
+ * @typedef {import('stripe').Stripe.Checkout.Session} ICheckoutSession
36
+ * @typedef {import('stripe').Stripe.Checkout.SessionCreateParams} ICheckoutSessionCreateParams
37
+ * @typedef {import('stripe').Stripe.SubscriptionRetrieveParams} ISubscriptionRetrieveParams
38
+ * @typedef {import('stripe').Stripe.Subscription} ISubscription
39
+ * @typedef {import('stripe').Stripe.Checkout.SessionCreateParams.PaymentMethodType} IPaymentMethodType
40
+ */
41
+
42
+ /**
43
+ * @typedef {object} IStripeAPIConfig
44
+ * @prop {string} secretKey
45
+ * @prop {string} publicKey
46
+ * @prop {boolean} enablePromoCodes
47
+ * @prop {boolean} enableAutomaticTax
48
+ * @prop {string} checkoutSessionSuccessUrl
49
+ * @prop {string} checkoutSessionCancelUrl
50
+ * @prop {string} checkoutSetupSessionSuccessUrl
51
+ * @prop {string} checkoutSetupSessionCancelUrl
52
+ * @prop {boolean} testEnv - indicates if the module is run in test environment (note, NOT the test mode)
53
+ */
54
+
55
+ module.exports = class StripeAPI {
56
+ /**
57
+ * StripeAPI
58
+ * @param {object} deps
59
+ * @param {object} deps.labs
60
+ */
61
+ constructor(deps) {
62
+ /** @type {Stripe} */
63
+ this._stripe = null;
64
+ this._configured = false;
65
+ this.labs = deps.labs;
66
+ }
67
+
68
+ /**
69
+ * @returns {IPaymentMethodType[]|undefined}
70
+ */
71
+ get PAYMENT_METHOD_TYPES() {
72
+ if (this.labs.isSet('additionalPaymentMethods')) {
73
+ return undefined;
74
+ } else {
75
+ return ['card'];
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Returns true if the Stripe API is configured.
81
+ * @returns {boolean}
82
+ */
83
+ get configured() {
84
+ return this._configured;
85
+ }
86
+
87
+ /**
88
+ * Returns true if this package is running in a test environment (i.e. browser tests).
89
+ *
90
+ * Note: This is not the same as the Stripe API's test mode.
91
+ * @returns {boolean}
92
+ */
93
+ get testEnv() {
94
+ return this._config.testEnv;
95
+ }
96
+
97
+ /**
98
+ * Returns the Stripe API mode (test or live).
99
+ *
100
+ * @returns {string}
101
+ */
102
+ get mode() {
103
+ return this._testMode ? 'test' : 'live';
104
+ }
105
+
106
+ /**
107
+ * Configure the Stripe API.
108
+ * - Instantiates the Stripe API client
109
+ * - Sets the Stripe API mode
110
+ * - Configures rate limiting buckets
111
+ *
112
+ * @param {IStripeAPIConfig} config
113
+ *
114
+ * @returns {void}
115
+ */
116
+ configure(config) {
117
+ if (!config) {
118
+ this._stripe = null;
119
+ this._configured = false;
120
+ return;
121
+ }
122
+
123
+ // Lazyloaded to protect sites without Stripe configured
124
+ const LeakyBucket = require('leaky-bucket');
125
+
126
+ this._stripe = new Stripe(config.secretKey, {
127
+ apiVersion: STRIPE_API_VERSION
128
+ });
129
+ this._config = config;
130
+ this._testMode = config.secretKey && config.secretKey.startsWith('sk_test_');
131
+ if (this._testMode) {
132
+ this._rateLimitBucket = new LeakyBucket(EXPECTED_API_EFFICIENCY * TEST_MODE_RATE_LIMIT, 1);
133
+ } else {
134
+ this._rateLimitBucket = new LeakyBucket(EXPECTED_API_EFFICIENCY * LIVE_MODE_RATE_LIMIT, 1);
135
+ }
136
+ this._searchRateLimitBucket = new LeakyBucket(EXPECTED_SEARCH_API_EFFICIENCY * SEARCH_MODE_RATE_LIMIT, 1);
137
+ this._configured = true;
138
+ }
139
+
140
+ /**
141
+ * Create a new Stripe Coupon.
142
+ *
143
+ * @param {ICouponCreateParams} options
144
+ *
145
+ * @returns {Promise<ICoupon>}
146
+ */
147
+ async createCoupon(options) {
148
+ await this._rateLimitBucket.throttle();
149
+ const coupon = await this._stripe.coupons.create(options);
150
+
151
+ return coupon;
152
+ }
153
+
154
+ /**
155
+ * Retrieve the Stripe Product object by ID.
156
+ * @param {string} id
157
+ *
158
+ * @returns {Promise<IProduct>}
159
+ */
160
+ async getProduct(id) {
161
+ await this._rateLimitBucket.throttle();
162
+ const product = await this._stripe.products.retrieve(id);
163
+
164
+ return product;
165
+ }
166
+
167
+ /**
168
+ * Create a new Stripe Product.
169
+ * @param {IProductCreateParams} options
170
+ *
171
+ * @returns {Promise<IProduct>}
172
+ */
173
+ async createProduct(options) {
174
+ await this._rateLimitBucket.throttle();
175
+ const product = await this._stripe.products.create(options);
176
+
177
+ return product;
178
+ }
179
+
180
+ /**
181
+ * Create a new Stripe Price.
182
+ *
183
+ * @param {object} options
184
+ * @param {string} options.product
185
+ * @param {boolean} options.active
186
+ * @param {string} options.nickname
187
+ * @param {string} options.currency
188
+ * @param {number} [options.amount]
189
+ * @param {{enabled: boolean;maximum?: number;minimum?: number;preset?: number;}} [options.custom_unit_amount]
190
+ * @param {'recurring'|'one-time'} options.type
191
+ * @param {Stripe.Price.Recurring.Interval|null} [options.interval]
192
+ *
193
+ * @returns {Promise<IPrice>}
194
+ */
195
+ async createPrice(options) {
196
+ await this._rateLimitBucket.throttle();
197
+ const price = await this._stripe.prices.create({
198
+ currency: options.currency,
199
+ product: options.product,
200
+ unit_amount: options.amount,
201
+ active: options.active,
202
+ nickname: options.nickname,
203
+ // @ts-ignore
204
+ custom_unit_amount: options.custom_unit_amount, // missing in .d.ts definitions in the Stripe node version we use, but should be supported in Stripe API at this version (:
205
+ recurring: options.type === 'recurring' && options.interval ? {
206
+ interval: options.interval
207
+ } : undefined
208
+ });
209
+
210
+ return price;
211
+ }
212
+
213
+ /**
214
+ * Update the Stripe Price object by ID.
215
+ *
216
+ * @param {string} id
217
+ * @param {object} options
218
+ * @param {boolean} [options.active]
219
+ * @param {string} [options.nickname]
220
+ *
221
+ * @returns {Promise<IPrice>}
222
+ */
223
+ async updatePrice(id, options) {
224
+ await this._rateLimitBucket.throttle();
225
+ const price = await this._stripe.prices.update(id, {
226
+ active: options.active,
227
+ nickname: options.nickname
228
+ });
229
+
230
+ return price;
231
+ }
232
+
233
+ /**
234
+ * Update the Stripe Product object by ID.
235
+ *
236
+ * @param {string} id
237
+ * @param {object} options
238
+ * @param {string} options.name
239
+ *
240
+ * @returns {Promise<IProduct>}
241
+ */
242
+ async updateProduct(id, options) {
243
+ await this._rateLimitBucket.throttle();
244
+ const product = await this._stripe.products.update(id, {
245
+ name: options.name
246
+ });
247
+
248
+ return product;
249
+ }
250
+
251
+ /**
252
+ * Retrieve the Stripe Customer object by ID.
253
+ *
254
+ * @param {string} id
255
+ * @param {ICustomerRetrieveParams} options
256
+ *
257
+ * @returns {Promise<ICustomer|IDeletedCustomer>}
258
+ * @throws {Error}
259
+ */
260
+ async getCustomer(id, options = {}) {
261
+ debug(`getCustomer(${id}, ${JSON.stringify(options)})`);
262
+ try {
263
+ await this._rateLimitBucket.throttle();
264
+ if (options.expand) {
265
+ options.expand.push('subscriptions');
266
+ } else {
267
+ options.expand = ['subscriptions'];
268
+ }
269
+ const customer = await this._stripe.customers.retrieve(id, options);
270
+ debug(`getCustomer(${id}, ${JSON.stringify(options)}) -> Success`);
271
+ return customer;
272
+ } catch (err) {
273
+ debug(`getCustomer(${id}, ${JSON.stringify(options)}) -> ${err.type}`);
274
+ throw err;
275
+ }
276
+ }
277
+
278
+ /**
279
+ * Finds or creates a Stripe Customer for a Member.
280
+ *
281
+ * @deprecated
282
+ * @param {any} member
283
+ *
284
+ * @returns {Promise<ICustomer>}
285
+ */
286
+ async getCustomerForMemberCheckoutSession(member) {
287
+ await member.related('stripeCustomers').fetch();
288
+ const customers = member.related('stripeCustomers');
289
+ for (const data of customers.models) {
290
+ try {
291
+ const customer = await this.getCustomer(data.get('customer_id'));
292
+ if (!customer.deleted) {
293
+ return /** @type {ICustomer} */(customer);
294
+ }
295
+ } catch (err) {
296
+ debug(`Ignoring Error getting customer for member ${err.message}`);
297
+ }
298
+ }
299
+
300
+ debug(`Creating customer for member ${member.get('email')}`);
301
+ const customer = await this.createCustomer({
302
+ email: member.get('email')
303
+ });
304
+
305
+ return customer;
306
+ }
307
+
308
+ /**
309
+ * Finds a Stripe Customer ID based on the provided email address. Returns null if no customer is found.
310
+ * @param {string} email
311
+ * @see https://stripe.com/docs/api/customers/search
312
+ *
313
+ * @returns {Promise<string|null>} Stripe Customer ID, if found
314
+ */
315
+ async getCustomerIdByEmail(email) {
316
+ await this._searchRateLimitBucket.throttle();
317
+ try {
318
+ const result = await this._stripe.customers.search({
319
+ query: `email:"${email}"`,
320
+ limit: 10,
321
+ expand: ['data.subscriptions']
322
+ });
323
+ const customers = result.data;
324
+
325
+ // No customer found, return null
326
+ if (customers.length === 0) {
327
+ return;
328
+ }
329
+
330
+ // Return the only customer found
331
+ if (customers.length === 1) {
332
+ return customers[0].id;
333
+ }
334
+
335
+ // Multiple customers found, return the one with the most recent subscription
336
+ if (customers.length > 1) {
337
+ let latestCustomer = customers[0];
338
+ let latestSubscriptionTime = 0;
339
+
340
+ for (let customer of customers) {
341
+ // skip customers with no subscriptions
342
+ if (!customer.subscriptions || !customer.subscriptions.data || customer.subscriptions.data.length === 0) {
343
+ continue;
344
+ }
345
+
346
+ // find the customer with the most recent subscription
347
+ for (let subscription of customer.subscriptions.data) {
348
+ if (subscription.current_period_end && subscription.current_period_end > latestSubscriptionTime) {
349
+ latestSubscriptionTime = subscription.current_period_end;
350
+ latestCustomer = customer;
351
+ }
352
+ }
353
+ }
354
+
355
+ return latestCustomer.id;
356
+ }
357
+ } catch (err) {
358
+ debug(`getCustomerByEmail(${email}) -> ${err.type}:${err.message}`);
359
+ }
360
+ }
361
+
362
+ /**
363
+ * Create a new Stripe Customer.
364
+ *
365
+ * @param {import('stripe').Stripe.CustomerCreateParams} options
366
+ *
367
+ * @returns {Promise<ICustomer>}
368
+ */
369
+ async createCustomer(options = {}) {
370
+ debug(`createCustomer(${JSON.stringify(options)})`);
371
+ try {
372
+ await this._rateLimitBucket.throttle();
373
+ const customer = await this._stripe.customers.create(options);
374
+ debug(`createCustomer(${JSON.stringify(options)}) -> Success`);
375
+ return customer;
376
+ } catch (err) {
377
+ debug(`createCustomer(${JSON.stringify(options)}) -> ${err.type}`);
378
+ throw err;
379
+ }
380
+ }
381
+
382
+ /**
383
+ * Update the email address for a Stripe Customer.
384
+ *
385
+ * @param {string} id
386
+ * @param {string} email
387
+ *
388
+ * @returns {Promise<ICustomer>}
389
+ */
390
+ async updateCustomerEmail(id, email) {
391
+ debug(`updateCustomerEmail(${id}, ${email})`);
392
+ try {
393
+ await this._rateLimitBucket.throttle();
394
+ const customer = await this._stripe.customers.update(id, {email});
395
+ debug(`updateCustomerEmail(${id}, ${email}) -> Success`);
396
+ return customer;
397
+ } catch (err) {
398
+ debug(`updateCustomerEmail(${id}, ${email}) -> ${err.type}`);
399
+ throw err;
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Create a new Stripe Webhook Endpoint.
405
+ *
406
+ * @param {string} url
407
+ * @param {import('stripe').Stripe.WebhookEndpointUpdateParams.EnabledEvent[]} events
408
+ *
409
+ * @returns {Promise<IWebhookEndpoint>}
410
+ */
411
+ async createWebhookEndpoint(url, events) {
412
+ debug(`createWebhook(${url})`);
413
+ try {
414
+ await this._rateLimitBucket.throttle();
415
+ const webhook = await this._stripe.webhookEndpoints.create({
416
+ url,
417
+ enabled_events: events,
418
+ api_version: STRIPE_API_VERSION
419
+ });
420
+ debug(`createWebhook(${url}) -> Success`);
421
+ return webhook;
422
+ } catch (err) {
423
+ debug(`createWebhook(${url}) -> ${err.type}`);
424
+ throw err;
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Delete a Stripe Webhook Endpoint by ID.
430
+ *
431
+ * @param {string} id
432
+ *
433
+ * @returns {Promise<void>}
434
+ */
435
+ async deleteWebhookEndpoint(id) {
436
+ debug(`deleteWebhook(${id})`);
437
+ try {
438
+ await this._rateLimitBucket.throttle();
439
+ await this._stripe.webhookEndpoints.del(id);
440
+ debug(`deleteWebhook(${id}) -> Success`);
441
+ return;
442
+ } catch (err) {
443
+ debug(`deleteWebhook(${id}) -> ${err.type}`);
444
+ throw err;
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Update a Stripe Webhook Endpoint by ID and URL.
450
+ *
451
+ * @param {string} id
452
+ * @param {string} url
453
+ * @param {import('stripe').Stripe.WebhookEndpointUpdateParams.EnabledEvent[]} events
454
+ *
455
+ * @returns {Promise<IWebhookEndpoint>}
456
+ */
457
+ async updateWebhookEndpoint(id, url, events) {
458
+ debug(`updateWebhook(${id}, ${url})`);
459
+ try {
460
+ await this._rateLimitBucket.throttle();
461
+ const webhook = await this._stripe.webhookEndpoints.update(id, {
462
+ url,
463
+ enabled_events: events
464
+ });
465
+ if (webhook.api_version !== STRIPE_API_VERSION) {
466
+ throw new VersionMismatchError({message: 'Webhook has incorrect api_version'});
467
+ }
468
+ debug(`updateWebhook(${id}, ${url}) -> Success`);
469
+ return webhook;
470
+ } catch (err) {
471
+ debug(`updateWebhook(${id}, ${url}) -> ${err.type}`);
472
+ throw err;
473
+ }
474
+ }
475
+
476
+ /**
477
+ * Parse a Stripe Webhook event.
478
+ *
479
+ * @param {string} body
480
+ * @param {string} signature
481
+ * @param {string} secret
482
+ *
483
+ * @returns {import('stripe').Stripe.Event}
484
+ */
485
+ parseWebhook(body, signature, secret) {
486
+ debug(`parseWebhook(${body}, ${signature}, ${secret})`);
487
+ try {
488
+ const event = this._stripe.webhooks.constructEvent(body, signature, secret);
489
+ debug(`parseWebhook(${body}, ${signature}, ${secret}) -> Success ${event.type}`);
490
+ return event;
491
+ } catch (err) {
492
+ debug(`parseWebhook(${body}, ${signature}, ${secret}) -> ${err.type}`);
493
+ throw err;
494
+ }
495
+ }
496
+
497
+ /**
498
+ * Create a new Stripe Checkout Session for a new subscription.
499
+ *
500
+ * @param {string} priceId
501
+ * @param {ICustomer} customer
502
+ *
503
+ * @param {object} options
504
+ * @param {Object.<String, any>} options.metadata
505
+ * @param {string} options.successUrl
506
+ * @param {string} options.cancelUrl
507
+ * @param {string} options.customerEmail
508
+ * @param {number} options.trialDays
509
+ * @param {string} [options.coupon]
510
+ *
511
+ * @returns {Promise<ICheckoutSession>}
512
+ */
513
+ async createCheckoutSession(priceId, customer, options) {
514
+ const metadata = options.metadata || undefined; // https://docs.stripe.com/api/metadata some limits to how much can be passed
515
+ const customerId = customer ? customer.id : undefined;
516
+ const customerEmail = customer ? customer.email : options.customerEmail;
517
+
518
+ await this._rateLimitBucket.throttle();
519
+ let discounts;
520
+ if (options.coupon) {
521
+ discounts = [{coupon: options.coupon}];
522
+ }
523
+
524
+ const subscriptionData = {
525
+ trial_from_plan: true,
526
+ items: [{
527
+ plan: priceId
528
+ }],
529
+ metadata: {
530
+ attribution_id: metadata?.attribution_id,
531
+ attribution_url: metadata?.attribution_url,
532
+ attribution_type: metadata?.attribution_type,
533
+ referrer_source: metadata?.referrer_source,
534
+ referrer_medium: metadata?.referrer_medium,
535
+ referrer_url: metadata?.referrer_url
536
+ }
537
+ };
538
+
539
+ /**
540
+ * `trial_from_plan` is deprecated.
541
+ * Replaces it in favor of custom trial period days stored in Ghost
542
+ */
543
+ if (typeof options.trialDays === 'number' && options.trialDays > 0) {
544
+ delete subscriptionData.trial_from_plan;
545
+ subscriptionData.trial_period_days = options.trialDays;
546
+ }
547
+
548
+ let stripeSessionOptions = {
549
+ payment_method_types: this.PAYMENT_METHOD_TYPES,
550
+ success_url: options.successUrl || this._config.checkoutSessionSuccessUrl,
551
+ cancel_url: options.cancelUrl || this._config.checkoutSessionCancelUrl,
552
+ // @ts-ignore - we need to update to latest stripe library to correctly use newer features
553
+ allow_promotion_codes: discounts ? undefined : this._config.enablePromoCodes,
554
+ automatic_tax: {
555
+ enabled: this._config.enableAutomaticTax
556
+ },
557
+ metadata,
558
+ discounts,
559
+ /*
560
+ line_items: [{
561
+ price: priceId
562
+ }]
563
+ */
564
+ // This is deprecated and using the old way of doing things with Plans.
565
+ // It should be replaced with the line_items entry above when possible,
566
+ // however, this would lose the "trial from plan" feature which has also
567
+ // been deprecated by Stripe
568
+ subscription_data: subscriptionData
569
+ };
570
+
571
+ /* We are only allowed to specify one of these; email will be pulled from
572
+ customer object on Stripe side if that object already exists. */
573
+ if (customerId) {
574
+ stripeSessionOptions.customer = customerId;
575
+ } else {
576
+ stripeSessionOptions.customer_email = customerEmail;
577
+ }
578
+
579
+ if (customerId && this._config.enableAutomaticTax) {
580
+ stripeSessionOptions.customer_update = {address: 'auto'};
581
+ }
582
+
583
+ // @ts-ignore
584
+ const session = await this._stripe.checkout.sessions.create(stripeSessionOptions);
585
+
586
+ return session;
587
+ }
588
+
589
+ /**
590
+ * Create a new Stripe Checkout Session for a donation.
591
+ *
592
+ * @param {object} options
593
+ * @param {string} options.priceId
594
+ * @param {string} options.successUrl
595
+ * @param {string} options.cancelUrl
596
+ * @param {Object.<String, any>} options.metadata
597
+ * @param {ICustomer} [options.customer]
598
+ * @param {string} [options.customerEmail]
599
+ * @param {string} [options.personalNote]
600
+ *
601
+ * @returns {Promise<ICheckoutSession>}
602
+ */
603
+ async createDonationCheckoutSession({priceId, successUrl, cancelUrl, metadata, customer, customerEmail, personalNote}) {
604
+ await this._rateLimitBucket.throttle();
605
+
606
+ /**
607
+ * @type {Stripe.Checkout.SessionCreateParams}
608
+ */
609
+
610
+ // TODO - add it higher up the stack to the metadata object.
611
+ // add ghost_donation key to metadata object
612
+ metadata = {
613
+ ghost_donation: true,
614
+ ...metadata
615
+ };
616
+
617
+ const stripeSessionOptions = {
618
+ mode: 'payment',
619
+ success_url: successUrl || this._config.checkoutSessionSuccessUrl,
620
+ cancel_url: cancelUrl || this._config.checkoutSessionCancelUrl,
621
+ automatic_tax: {
622
+ enabled: this._config.enableAutomaticTax
623
+ },
624
+ metadata,
625
+ customer: customer ? customer.id : undefined,
626
+ customer_email: !customer && customerEmail ? customerEmail : undefined,
627
+ submit_type: 'pay',
628
+ invoice_creation: {
629
+ enabled: true,
630
+ invoice_data: {
631
+ // Make sure we pass the data through to the invoice
632
+ metadata: {
633
+ ghost_donation: true,
634
+ ...metadata
635
+ }
636
+ }
637
+ },
638
+ line_items: [{
639
+ price: priceId,
640
+ quantity: 1
641
+ }],
642
+ custom_fields: [
643
+ {
644
+ key: 'donation_message',
645
+ label: {
646
+ type: 'custom',
647
+ custom: personalNote || 'Add a personal note'
648
+ },
649
+ type: 'text',
650
+ optional: true
651
+ }
652
+ ]
653
+ };
654
+
655
+ if (customer && this._config.enableAutomaticTax) {
656
+ stripeSessionOptions.customer_update = {address: 'auto'};
657
+ }
658
+
659
+ // @ts-ignore
660
+ const session = await this._stripe.checkout.sessions.create(stripeSessionOptions);
661
+ return session;
662
+ }
663
+
664
+ /**
665
+ * Create a new Stripe Checkout Setup Session.
666
+ *
667
+ * @param {ICustomer} customer
668
+ * @param {object} options
669
+ * @param {string} options.successUrl
670
+ * @param {string} options.cancelUrl
671
+ * @param {string} options.currency - 3-letter ISO code in lowercase, e.g. `usd`
672
+ * @returns {Promise<ICheckoutSession>}
673
+ */
674
+ async createCheckoutSetupSession(customer, options) {
675
+ await this._rateLimitBucket.throttle();
676
+ const session = await this._stripe.checkout.sessions.create({
677
+ mode: 'setup',
678
+ payment_method_types: this.PAYMENT_METHOD_TYPES,
679
+ success_url: options.successUrl || this._config.checkoutSetupSessionSuccessUrl,
680
+ cancel_url: options.cancelUrl || this._config.checkoutSetupSessionCancelUrl,
681
+ customer_email: customer.email,
682
+ setup_intent_data: {
683
+ metadata: {
684
+ customer_id: customer.id
685
+ }
686
+ },
687
+
688
+ // Note: this is required for dynamic payment methods
689
+ // https://docs.stripe.com/api/checkout/sessions/create#create_checkout_session-currency
690
+ // @ts-ignore
691
+ currency: this.labs.isSet('additionalPaymentMethods') ? options.currency : undefined
692
+ });
693
+
694
+ return session;
695
+ }
696
+
697
+ /**
698
+ * Get the Stripe public key.
699
+ *
700
+ * @returns {string}
701
+ */
702
+ getPublicKey() {
703
+ return this._config.publicKey;
704
+ }
705
+
706
+ /**
707
+ * Retrieve the Stripe Price object by ID.
708
+ *
709
+ * @param {string} id
710
+ * @param {object} options
711
+ *
712
+ * @returns {Promise<IPrice>}
713
+ */
714
+ async getPrice(id, options = {}) {
715
+ debug(`getPrice(${id}, ${JSON.stringify(options)})`);
716
+
717
+ return await this._stripe.prices.retrieve(id, options);
718
+ }
719
+
720
+ /**
721
+ * Retrieve the Stripe Subscription object by ID.
722
+ *
723
+ * @param {string} id
724
+ * @param {ISubscriptionRetrieveParams} options
725
+ *
726
+ * @returns {Promise<ISubscription>}
727
+ */
728
+ async getSubscription(id, options = {}) {
729
+ debug(`getSubscription(${id}, ${JSON.stringify(options)})`);
730
+ try {
731
+ await this._rateLimitBucket.throttle();
732
+ const subscription = await this._stripe.subscriptions.retrieve(id, options);
733
+ debug(`getSubscription(${id}, ${JSON.stringify(options)}) -> Success`);
734
+ return subscription;
735
+ } catch (err) {
736
+ debug(`getSubscription(${id}, ${JSON.stringify(options)}) -> ${err.type}`);
737
+ throw err;
738
+ }
739
+ }
740
+
741
+ /**
742
+ * Cancel the Stripe Subscription by ID.
743
+ *
744
+ * @param {string} id
745
+ *
746
+ * @returns {Promise<ISubscription>}
747
+ */
748
+ async cancelSubscription(id) {
749
+ debug(`cancelSubscription(${id})`);
750
+ try {
751
+ await this._rateLimitBucket.throttle();
752
+ const subscription = await this._stripe.subscriptions.del(id);
753
+ debug(`cancelSubscription(${id}) -> Success`);
754
+ return subscription;
755
+ } catch (err) {
756
+ debug(`cancelSubscription(${id}) -> ${err.type}`);
757
+ throw err;
758
+ }
759
+ }
760
+
761
+ /**
762
+ * Cancel the Stripe Subscription at the end of the current period by ID.
763
+ *
764
+ * @param {string} id - The ID of the Subscription to modify
765
+ * @param {string} [reason=''] - The user defined cancellation reason
766
+ *
767
+ * @returns {Promise<ISubscription>}
768
+ */
769
+ async cancelSubscriptionAtPeriodEnd(id, reason = '') {
770
+ await this._rateLimitBucket.throttle();
771
+ const subscription = await this._stripe.subscriptions.update(id, {
772
+ cancel_at_period_end: true,
773
+ metadata: {
774
+ cancellation_reason: reason
775
+ }
776
+ });
777
+ return subscription;
778
+ }
779
+
780
+ /**
781
+ * Continue the Stripe Subscription at the end of the current period by ID.
782
+ *
783
+ * @param {string} id - The ID of the Subscription to modify
784
+ *
785
+ * @returns {Promise<ISubscription>}
786
+ */
787
+ async continueSubscriptionAtPeriodEnd(id) {
788
+ await this._rateLimitBucket.throttle();
789
+ const subscription = await this._stripe.subscriptions.update(id, {
790
+ cancel_at_period_end: false,
791
+ metadata: {
792
+ cancellation_reason: null
793
+ }
794
+ });
795
+ return subscription;
796
+ }
797
+
798
+ /**
799
+ * Remove the coupon from the Stripe Subscription by ID.
800
+ *
801
+ * @param {string} id - The ID of the subscription to remove coupon from
802
+ *
803
+ * @returns {Promise<ISubscription>}
804
+ */
805
+ async removeCouponFromSubscription(id) {
806
+ await this._rateLimitBucket.throttle();
807
+ const subscription = await this._stripe.subscriptions.update(id, {
808
+ coupon: ''
809
+ });
810
+ return subscription;
811
+ }
812
+
813
+ /**
814
+ * Update the price of the Stripe SubscriptionItem by Subscription ID,
815
+ * SubscriptionItem ID, and Price ID.
816
+ *
817
+ * @param {string} subscriptionId - The ID of the Subscription to modify
818
+ * @param {string} id - The ID of the SubscriptionItem
819
+ * @param {string} price - The ID of the new Price
820
+ * @param {object} [options={}] - Additional data to set on the subscription object
821
+ * @param {('always_invoice'|'create_prorations'|'none')} [options.prorationBehavior='always_invoice'] - The proration behavior to use. See [Stripe docs](https://docs.stripe.com/api/subscriptions/update#update_subscription-proration_behavior) for more info
822
+ * @param {string} [options.cancellationReason=null] - The user defined cancellation reason
823
+ *
824
+ * @returns {Promise<ISubscription>}
825
+ */
826
+ async updateSubscriptionItemPrice(subscriptionId, id, price, options = {}) {
827
+ await this._rateLimitBucket.throttle();
828
+ const subscription = await this._stripe.subscriptions.update(subscriptionId, {
829
+ proration_behavior: options.prorationBehavior || 'always_invoice',
830
+ items: [{
831
+ id,
832
+ price
833
+ }],
834
+ cancel_at_period_end: false,
835
+ metadata: {
836
+ cancellation_reason: options.cancellationReason ?? null
837
+ }
838
+ });
839
+ return subscription;
840
+ }
841
+
842
+ /**
843
+ * Create a new Stripe Subscription for a Customer by ID and Price ID.
844
+ *
845
+ * @param {string} customer - The ID of the Customer to create the subscription for
846
+ * @param {string} price - The ID of the new Price
847
+ *
848
+ * @returns {Promise<ISubscription>}
849
+ */
850
+ async createSubscription(customer, price) {
851
+ await this._rateLimitBucket.throttle();
852
+ const subscription = await this._stripe.subscriptions.create({
853
+ customer,
854
+ items: [{price}]
855
+ });
856
+ return subscription;
857
+ }
858
+
859
+ /**
860
+ * Retrieve the Stripe SetupIntent object by ID.
861
+ *
862
+ * @param {string} id
863
+ * @param {import('stripe').Stripe.SetupIntentRetrieveParams} options
864
+ *
865
+ * @returns {Promise<import('stripe').Stripe.SetupIntent>}
866
+ */
867
+ async getSetupIntent(id, options = {}) {
868
+ await this._rateLimitBucket.throttle();
869
+ return await this._stripe.setupIntents.retrieve(id, options);
870
+ }
871
+
872
+ /**
873
+ * Attach a PaymentMethod to a Customer
874
+ *
875
+ * @param {string} customer
876
+ * @param {string} paymentMethod
877
+ *
878
+ * @returns {Promise<void>}
879
+ */
880
+ async attachPaymentMethodToCustomer(customer, paymentMethod) {
881
+ await this._rateLimitBucket.throttle();
882
+ await this._stripe.paymentMethods.attach(paymentMethod, {customer});
883
+ return;
884
+ }
885
+
886
+ /**
887
+ * Retrieve the Stripe PaymentMethod object by ID.
888
+ *
889
+ * @param {string} id
890
+ *
891
+ * @returns {Promise<import('stripe').Stripe.PaymentMethod|null>}
892
+ */
893
+ async getCardPaymentMethod(id) {
894
+ await this._rateLimitBucket.throttle();
895
+ const paymentMethod = await this._stripe.paymentMethods.retrieve(id);
896
+ if (paymentMethod.type !== 'card') {
897
+ return null;
898
+ }
899
+
900
+ return paymentMethod;
901
+ }
902
+
903
+ /**
904
+ * Update the default PaymentMethod for a Subscription.
905
+ *
906
+ * @param {string} subscription
907
+ * @param {string} paymentMethod
908
+ *
909
+ * @returns {Promise<ISubscription>}
910
+ */
911
+ async updateSubscriptionDefaultPaymentMethod(subscription, paymentMethod) {
912
+ await this._rateLimitBucket.throttle();
913
+ return await this._stripe.subscriptions.update(subscription, {
914
+ default_payment_method: paymentMethod
915
+ });
916
+ }
917
+
918
+ /**
919
+ * Cancel the trial for a Stripe Subscription by ID.
920
+ *
921
+ * @param {string} id - The ID of the subscription to cancel the trial for
922
+ *
923
+ * @returns {Promise<ISubscription>}
924
+ */
925
+ async cancelSubscriptionTrial(id) {
926
+ await this._rateLimitBucket.throttle();
927
+ return this._stripe.subscriptions.update(id, {
928
+ trial_end: 'now'
929
+ });
930
+ }
931
+ };