@forklaunch/implementation-billing-stripe 0.2.7 → 0.3.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.
@@ -1,19 +1,12 @@
1
- import { IdDto, IdsDto, InstanceTypeRecord } from '@forklaunch/common';
1
+ import { IdDto, IdsDto } from '@forklaunch/common';
2
2
  import {
3
3
  MetricsDefinition,
4
4
  OpenTelemetryCollector,
5
5
  TelemetryOptions
6
6
  } from '@forklaunch/core/http';
7
7
  import { BaseSubscriptionService } from '@forklaunch/implementation-billing-base/services';
8
+ import { SubscriptionMappers } from '@forklaunch/implementation-billing-base/types';
8
9
  import { SubscriptionService } from '@forklaunch/interfaces-billing/interfaces';
9
- import {
10
- IdentityRequestMapper,
11
- IdentityResponseMapper,
12
- InternalMapper,
13
- RequestMapperConstructor,
14
- ResponseMapperConstructor,
15
- transformIntoInternalMapper
16
- } from '@forklaunch/internal';
17
10
  import { AnySchemaValidator } from '@forklaunch/validator';
18
11
  import { EntityManager } from '@mikro-orm/core';
19
12
  import Stripe from 'stripe';
@@ -25,6 +18,7 @@ import {
25
18
  StripeUpdateSubscriptionDto
26
19
  } from '../domain/types/stripe.dto.types';
27
20
  import { StripeSubscriptionEntities } from '../domain/types/stripe.entity.types';
21
+ import { StripeSubscriptionMappers } from '../domain/types/subscription.mapper.types';
28
22
 
29
23
  export class StripeSubscriptionService<
30
24
  SchemaValidator extends AnySchemaValidator,
@@ -48,110 +42,55 @@ export class StripeSubscriptionService<
48
42
  baseSubscriptionService: BaseSubscriptionService<
49
43
  SchemaValidator,
50
44
  PartyType,
51
- typeof BillingProviderEnum,
45
+ BillingProviderEnum,
52
46
  Entities,
53
- Entities
47
+ Dto
54
48
  >;
55
- protected _mappers: InternalMapper<InstanceTypeRecord<typeof this.mappers>>;
56
- protected readonly stripe: Stripe;
49
+ protected readonly stripeClient: Stripe;
57
50
  protected readonly em: EntityManager;
58
51
  protected readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>;
59
52
  protected readonly schemaValidator: SchemaValidator;
60
- protected readonly mappers: {
61
- SubscriptionMapper: ResponseMapperConstructor<
62
- SchemaValidator,
63
- Dto['SubscriptionMapper'],
64
- Entities['SubscriptionMapper']
65
- >;
66
- CreateSubscriptionMapper: RequestMapperConstructor<
67
- SchemaValidator,
68
- Dto['CreateSubscriptionMapper'],
69
- Entities['CreateSubscriptionMapper'],
70
- (
71
- dto: Dto['CreateSubscriptionMapper'],
72
- em: EntityManager,
73
- subscription: Stripe.Subscription
74
- ) => Promise<Entities['CreateSubscriptionMapper']>
75
- >;
76
- UpdateSubscriptionMapper: RequestMapperConstructor<
77
- SchemaValidator,
78
- Dto['UpdateSubscriptionMapper'],
79
- Entities['UpdateSubscriptionMapper'],
80
- (
81
- dto: Dto['UpdateSubscriptionMapper'],
82
- em: EntityManager,
83
- subscription: Stripe.Subscription
84
- ) => Promise<Entities['UpdateSubscriptionMapper']>
85
- >;
86
- };
53
+ protected readonly mappers: StripeSubscriptionMappers<
54
+ PartyType,
55
+ Entities,
56
+ Dto
57
+ >;
87
58
 
88
59
  constructor(
89
- stripe: Stripe,
60
+ stripeClient: Stripe,
90
61
  em: EntityManager,
91
62
  openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,
92
63
  schemaValidator: SchemaValidator,
93
- mappers: {
94
- SubscriptionMapper: ResponseMapperConstructor<
95
- SchemaValidator,
96
- Dto['SubscriptionMapper'],
97
- Entities['SubscriptionMapper']
98
- >;
99
- CreateSubscriptionMapper: RequestMapperConstructor<
100
- SchemaValidator,
101
- Dto['CreateSubscriptionMapper'],
102
- Entities['CreateSubscriptionMapper'],
103
- (
104
- dto: Dto['CreateSubscriptionMapper'],
105
- em: EntityManager,
106
- subscription: Stripe.Subscription
107
- ) => Promise<Entities['CreateSubscriptionMapper']>
108
- >;
109
- UpdateSubscriptionMapper: RequestMapperConstructor<
110
- SchemaValidator,
111
- Dto['UpdateSubscriptionMapper'],
112
- Entities['UpdateSubscriptionMapper'],
113
- (
114
- dto: Dto['UpdateSubscriptionMapper'],
115
- em: EntityManager,
116
- subscription: Stripe.Subscription
117
- ) => Promise<Entities['UpdateSubscriptionMapper']>
118
- >;
119
- },
64
+ mappers: StripeSubscriptionMappers<PartyType, Entities, Dto>,
120
65
  readonly options?: {
121
66
  telemetry?: TelemetryOptions;
122
67
  databaseTableName?: string;
123
68
  }
124
69
  ) {
125
- this.stripe = stripe;
70
+ this.stripeClient = stripeClient;
126
71
  this.em = em;
127
72
  this.openTelemetryCollector = openTelemetryCollector;
128
73
  this.schemaValidator = schemaValidator;
129
74
  this.mappers = mappers;
130
- this._mappers = transformIntoInternalMapper(mappers, schemaValidator);
131
75
  this.baseSubscriptionService = new BaseSubscriptionService(
132
76
  em,
133
77
  openTelemetryCollector,
134
78
  schemaValidator,
135
- {
136
- SubscriptionMapper: IdentityResponseMapper<
137
- Entities['SubscriptionMapper']
138
- >,
139
- CreateSubscriptionMapper: IdentityRequestMapper<
140
- Entities['CreateSubscriptionMapper']
141
- >,
142
- UpdateSubscriptionMapper: IdentityRequestMapper<
143
- Entities['UpdateSubscriptionMapper']
144
- >
145
- },
79
+ mappers as SubscriptionMappers<
80
+ PartyType,
81
+ BillingProviderEnum,
82
+ Entities,
83
+ Dto
84
+ >,
146
85
  options
147
86
  );
148
87
  }
149
88
 
150
89
  async createSubscription(
151
- subscriptionDto: Dto['CreateSubscriptionMapper'],
90
+ subscriptionDto: StripeCreateSubscriptionDto<PartyType>,
152
91
  em?: EntityManager
153
92
  ): Promise<Dto['SubscriptionMapper']> {
154
- const subscription = await this.stripe.subscriptions.create({
93
+ const subscription = await this.stripeClient.subscriptions.create({
155
94
  ...subscriptionDto.stripeFields,
156
95
  customer: subscriptionDto.partyId,
157
96
  items: [
@@ -161,22 +100,14 @@ export class StripeSubscriptionService<
161
100
  ]
162
101
  });
163
102
 
164
- const subscriptionEntity =
165
- await this.baseSubscriptionService.createSubscription(
166
- await this._mappers.CreateSubscriptionMapper.deserializeDtoToEntity(
167
- {
168
- ...subscriptionDto,
169
- externalId: subscription.id,
170
- billingProvider: 'stripe'
171
- },
172
- em ?? this.em,
173
- subscription
174
- ),
175
- em
176
- );
177
-
178
- return this._mappers.SubscriptionMapper.serializeEntityToDto(
179
- subscriptionEntity
103
+ return await this.baseSubscriptionService.createSubscription(
104
+ {
105
+ ...subscriptionDto,
106
+ externalId: subscription.id,
107
+ billingProvider: 'stripe'
108
+ },
109
+ em ?? this.em,
110
+ subscription
180
111
  );
181
112
  }
182
113
 
@@ -184,24 +115,26 @@ export class StripeSubscriptionService<
184
115
  idDto: IdDto,
185
116
  em?: EntityManager
186
117
  ): Promise<Dto['SubscriptionMapper']> {
187
- return {
188
- ...(await this._mappers.SubscriptionMapper.serializeEntityToDto(
189
- await this.baseSubscriptionService.getSubscription(idDto, em)
190
- )),
191
- stripeFields: await this.stripe.subscriptions.retrieve(idDto.id)
192
- };
118
+ const subscriptionEntity =
119
+ await this.baseSubscriptionService.getSubscription(idDto, em);
120
+ const stripeSubscription = await this.stripeClient.subscriptions.retrieve(
121
+ idDto.id
122
+ );
123
+ subscriptionEntity.stripeFields = stripeSubscription;
124
+ return subscriptionEntity;
193
125
  }
194
126
 
195
127
  async getUserSubscription(
196
128
  idDto: IdDto,
197
129
  em?: EntityManager
198
130
  ): Promise<Dto['SubscriptionMapper']> {
199
- return {
200
- ...(await this._mappers.SubscriptionMapper.serializeEntityToDto(
201
- await this.baseSubscriptionService.getUserSubscription(idDto, em)
202
- )),
203
- stripeFields: await this.stripe.subscriptions.retrieve(idDto.id)
204
- };
131
+ const subscriptionEntity =
132
+ await this.baseSubscriptionService.getUserSubscription(idDto, em);
133
+ const stripeSubscription = await this.stripeClient.subscriptions.retrieve(
134
+ idDto.id
135
+ );
136
+ subscriptionEntity.stripeFields = stripeSubscription;
137
+ return subscriptionEntity;
205
138
  }
206
139
 
207
140
  async getOrganizationSubscription(
@@ -217,22 +150,23 @@ export class StripeSubscriptionService<
217
150
  if (!id) {
218
151
  throw new Error('Subscription not found');
219
152
  }
220
- return {
221
- ...(await this._mappers.SubscriptionMapper.serializeEntityToDto(
222
- await this.baseSubscriptionService.getOrganizationSubscription(
223
- { id },
224
- em
225
- )
226
- )),
227
- stripeFields: await this.stripe.subscriptions.retrieve(idDto.id)
228
- };
153
+ const subscriptionEntity =
154
+ await this.baseSubscriptionService.getOrganizationSubscription(
155
+ { id },
156
+ em
157
+ );
158
+ const stripeSubscription = await this.stripeClient.subscriptions.retrieve(
159
+ idDto.id
160
+ );
161
+ subscriptionEntity.stripeFields = stripeSubscription;
162
+ return subscriptionEntity;
229
163
  }
230
164
 
231
165
  async updateSubscription(
232
- subscriptionDto: Dto['UpdateSubscriptionMapper'],
166
+ subscriptionDto: StripeUpdateSubscriptionDto<PartyType>,
233
167
  em?: EntityManager
234
168
  ): Promise<Dto['SubscriptionMapper']> {
235
- const subscription = await this.stripe.subscriptions.update(
169
+ const subscription = await this.stripeClient.subscriptions.update(
236
170
  subscriptionDto.id,
237
171
  {
238
172
  ...subscriptionDto.stripeFields,
@@ -244,23 +178,15 @@ export class StripeSubscriptionService<
244
178
  }
245
179
  );
246
180
 
247
- const subscriptionEntity =
248
- await this.baseSubscriptionService.updateSubscription(
249
- await this._mappers.UpdateSubscriptionMapper.deserializeDtoToEntity(
250
- {
251
- ...subscriptionDto,
252
- externalId: subscription.id,
253
- billingProvider: 'stripe',
254
- providerFields: subscription
255
- },
256
- em ?? this.em,
257
- subscription
258
- ),
259
- em
260
- );
261
-
262
- return this._mappers.SubscriptionMapper.serializeEntityToDto(
263
- subscriptionEntity
181
+ return await this.baseSubscriptionService.updateSubscription(
182
+ {
183
+ ...subscriptionDto,
184
+ externalId: subscription.id,
185
+ billingProvider: 'stripe',
186
+ providerFields: subscription
187
+ },
188
+ em ?? this.em,
189
+ subscription
264
190
  );
265
191
  }
266
192
 
@@ -268,7 +194,7 @@ export class StripeSubscriptionService<
268
194
  idDto: { id: string },
269
195
  em?: EntityManager
270
196
  ): Promise<void> {
271
- await this.stripe.subscriptions.cancel(idDto.id);
197
+ await this.stripeClient.subscriptions.cancel(idDto.id);
272
198
  await this.baseSubscriptionService.deleteSubscription(idDto, em);
273
199
  }
274
200
 
@@ -277,7 +203,7 @@ export class StripeSubscriptionService<
277
203
  em?: EntityManager
278
204
  ): Promise<Dto['SubscriptionMapper'][]> {
279
205
  const subscriptions = (
280
- await this.stripe.subscriptions.list({
206
+ await this.stripeClient.subscriptions.list({
281
207
  status: 'active'
282
208
  })
283
209
  ).data.filter((s) => idsDto.ids?.includes(s.id));
@@ -296,26 +222,23 @@ export class StripeSubscriptionService<
296
222
  return await Promise.all(
297
223
  (await this.baseSubscriptionService.listSubscriptions({ ids }, em)).map(
298
224
  async (subscription) => {
299
- return {
300
- ...(await this._mappers.SubscriptionMapper.serializeEntityToDto(
301
- subscription
302
- )),
303
- stripeFields: subscriptions.find(
304
- (s) => s.id === subscription.externalId
305
- )
306
- };
225
+ const stripeSubscription = subscriptions.find(
226
+ (s) => s.id === subscription.externalId
227
+ )!;
228
+ subscription.stripeFields = stripeSubscription;
229
+ return subscription;
307
230
  }
308
231
  )
309
232
  );
310
233
  }
311
234
 
312
235
  async cancelSubscription(idDto: IdDto, em?: EntityManager): Promise<void> {
313
- await this.stripe.subscriptions.cancel(idDto.id);
236
+ await this.stripeClient.subscriptions.cancel(idDto.id);
314
237
  await this.baseSubscriptionService.cancelSubscription(idDto, em);
315
238
  }
316
239
 
317
240
  async resumeSubscription(idDto: IdDto, em?: EntityManager): Promise<void> {
318
- await this.stripe.subscriptions.resume(idDto.id);
241
+ await this.stripeClient.subscriptions.resume(idDto.id);
319
242
  await this.baseSubscriptionService.resumeSubscription(idDto, em);
320
243
  }
321
244
  }
@@ -114,8 +114,7 @@ export class StripeWebhookService<
114
114
  id: event.data.object.id,
115
115
  customerId: event.data.object.customer,
116
116
  expiresAt: new Date(event.data.object.created + 5 * 60 * 1000),
117
- uri: event.data.object.url,
118
- providerFields: event.data.object
117
+ uri: event.data.object.url
119
118
  }
120
119
  );
121
120
  break;
@@ -147,8 +146,7 @@ export class StripeWebhookService<
147
146
  paymentMethods: event.data.object
148
147
  .payment_method_types as PaymentMethodEnum[],
149
148
  status: 'CREATED' as StatusEnum[keyof StatusEnum],
150
- currency: event.data.object.currency as CurrencyEnum,
151
- providerFields: event.data.object
149
+ currency: event.data.object.currency as CurrencyEnum
152
150
  });
153
151
  }
154
152
  break;
@@ -164,8 +162,7 @@ export class StripeWebhookService<
164
162
  paymentMethods: event.data.object
165
163
  .payment_method_types as PaymentMethodEnum[],
166
164
  status: 'UPDATED' as StatusEnum[keyof StatusEnum],
167
- currency: event.data.object.currency as CurrencyEnum,
168
- providerFields: event.data.object
165
+ currency: event.data.object.currency as CurrencyEnum
169
166
  });
170
167
  break;
171
168
  }
@@ -187,8 +184,7 @@ export class StripeWebhookService<
187
184
  ? event.data.object.product
188
185
  : event.data.object.product?.id,
189
186
  price: event.data.object.amount,
190
- externalId: event.data.object.id,
191
- providerFields: event.data.object
187
+ externalId: event.data.object.id
192
188
  });
193
189
  } else {
194
190
  throw new Error('Invalid plan');
@@ -213,8 +209,7 @@ export class StripeWebhookService<
213
209
  ? event.data.object.product
214
210
  : event.data.object.product?.id,
215
211
  price: event.data.object.amount,
216
- externalId: event.data.object.id,
217
- providerFields: event.data.object
212
+ externalId: event.data.object.id
218
213
  });
219
214
  } else {
220
215
  throw new Error('Invalid plan');
@@ -240,7 +235,6 @@ export class StripeWebhookService<
240
235
  description: event.data.object.description ?? undefined,
241
236
  active: true,
242
237
  productId: event.data.object.items.data[0].plan.id,
243
- providerFields: event.data.object,
244
238
  externalId: event.data.object.id,
245
239
  billingProvider: BillingProviderEnum.STRIPE,
246
240
  startDate: new Date(event.data.object.created),
@@ -262,7 +256,6 @@ export class StripeWebhookService<
262
256
  partyType: 'USER' as PartyEnum[keyof PartyEnum],
263
257
  description: event.data.object.description ?? undefined,
264
258
  active: true,
265
- providerFields: event.data.object,
266
259
  externalId: event.data.object.id,
267
260
  billingProvider: BillingProviderEnum.STRIPE,
268
261
  startDate: new Date(event.data.object.created),