@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,4 +1,4 @@
1
- import { IdDto, IdsDto, InstanceTypeRecord } from '@forklaunch/common';
1
+ import { IdDto, IdsDto } from '@forklaunch/common';
2
2
  import { TtlCache } from '@forklaunch/core/cache';
3
3
  import {
4
4
  MetricsDefinition,
@@ -6,19 +6,13 @@ import {
6
6
  TelemetryOptions
7
7
  } from '@forklaunch/core/http';
8
8
  import { BasePaymentLinkService } from '@forklaunch/implementation-billing-base/services';
9
+ import { PaymentLinkMappers } from '@forklaunch/implementation-billing-base/types';
9
10
  import { PaymentLinkService } from '@forklaunch/interfaces-billing/interfaces';
10
- import {
11
- IdentityRequestMapper,
12
- IdentityResponseMapper,
13
- InternalMapper,
14
- RequestMapperConstructor,
15
- ResponseMapperConstructor,
16
- transformIntoInternalMapper
17
- } from '@forklaunch/internal';
18
11
  import { AnySchemaValidator } from '@forklaunch/validator';
19
12
  import { EntityManager } from '@mikro-orm/core';
20
13
  import Stripe from 'stripe';
21
14
  import { CurrencyEnum, PaymentMethodEnum } from '../domain/enum';
15
+ import { StripePaymentLinkMappers } from '../domain/types/paymentLink.mapper.types';
22
16
  import {
23
17
  StripeCreatePaymentLinkDto,
24
18
  StripePaymentLinkDto,
@@ -49,45 +43,22 @@ export class StripePaymentLinkService<
49
43
  {
50
44
  basePaymentLinkService: BasePaymentLinkService<
51
45
  SchemaValidator,
52
- typeof PaymentMethodEnum,
53
- typeof CurrencyEnum,
46
+ PaymentMethodEnum,
47
+ CurrencyEnum,
54
48
  StatusEnum,
55
49
  Entities,
56
- Entities
50
+ Dto
57
51
  >;
58
- protected _mappers: InternalMapper<InstanceTypeRecord<typeof this.mappers>>;
59
52
  protected readonly stripeClient: Stripe;
60
53
  protected readonly em: EntityManager;
61
54
  protected readonly cache: TtlCache;
62
55
  protected readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>;
63
56
  protected readonly schemaValidator: SchemaValidator;
64
- protected readonly mappers: {
65
- PaymentLinkMapper: ResponseMapperConstructor<
66
- SchemaValidator,
67
- Dto['PaymentLinkMapper'],
68
- Entities['PaymentLinkMapper']
69
- >;
70
- CreatePaymentLinkMapper: RequestMapperConstructor<
71
- SchemaValidator,
72
- Dto['CreatePaymentLinkMapper'],
73
- Entities['CreatePaymentLinkMapper'],
74
- (
75
- dto: Dto['CreatePaymentLinkMapper'],
76
- em: EntityManager,
77
- paymentLink: Stripe.PaymentLink
78
- ) => Promise<Entities['CreatePaymentLinkMapper']>
79
- >;
80
- UpdatePaymentLinkMapper: RequestMapperConstructor<
81
- SchemaValidator,
82
- Dto['UpdatePaymentLinkMapper'],
83
- Entities['UpdatePaymentLinkMapper'],
84
- (
85
- dto: Dto['UpdatePaymentLinkMapper'],
86
- em: EntityManager,
87
- paymentLink: Stripe.PaymentLink
88
- ) => Promise<Entities['UpdatePaymentLinkMapper']>
89
- >;
90
- };
57
+ protected readonly mappers: StripePaymentLinkMappers<
58
+ StatusEnum,
59
+ Entities,
60
+ Dto
61
+ >;
91
62
 
92
63
  constructor(
93
64
  stripeClient: Stripe,
@@ -95,33 +66,7 @@ export class StripePaymentLinkService<
95
66
  cache: TtlCache,
96
67
  openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,
97
68
  schemaValidator: SchemaValidator,
98
- mappers: {
99
- PaymentLinkMapper: ResponseMapperConstructor<
100
- SchemaValidator,
101
- Dto['PaymentLinkMapper'],
102
- Entities['PaymentLinkMapper']
103
- >;
104
- CreatePaymentLinkMapper: RequestMapperConstructor<
105
- SchemaValidator,
106
- Dto['CreatePaymentLinkMapper'],
107
- Entities['CreatePaymentLinkMapper'],
108
- (
109
- dto: Dto['CreatePaymentLinkMapper'],
110
- em: EntityManager,
111
- paymentLink: Stripe.PaymentLink
112
- ) => Promise<Entities['CreatePaymentLinkMapper']>
113
- >;
114
- UpdatePaymentLinkMapper: RequestMapperConstructor<
115
- SchemaValidator,
116
- Dto['UpdatePaymentLinkMapper'],
117
- Entities['UpdatePaymentLinkMapper'],
118
- (
119
- dto: Dto['UpdatePaymentLinkMapper'],
120
- em: EntityManager,
121
- paymentLink: Stripe.PaymentLink
122
- ) => Promise<Entities['UpdatePaymentLinkMapper']>
123
- >;
124
- },
69
+ mappers: StripePaymentLinkMappers<StatusEnum, Entities, Dto>,
125
70
  readonly options?: {
126
71
  enableDatabaseBackup?: boolean;
127
72
  telemetry?: TelemetryOptions;
@@ -133,29 +78,25 @@ export class StripePaymentLinkService<
133
78
  this.openTelemetryCollector = openTelemetryCollector;
134
79
  this.schemaValidator = schemaValidator;
135
80
  this.mappers = mappers;
136
- this._mappers = transformIntoInternalMapper(mappers, schemaValidator);
137
81
  this.basePaymentLinkService = new BasePaymentLinkService(
138
82
  em,
139
83
  cache,
140
84
  openTelemetryCollector,
141
85
  schemaValidator,
142
- {
143
- PaymentLinkMapper: IdentityResponseMapper<
144
- Entities['PaymentLinkMapper']
145
- >,
146
- CreatePaymentLinkMapper: IdentityRequestMapper<
147
- Entities['CreatePaymentLinkMapper']
148
- >,
149
- UpdatePaymentLinkMapper: IdentityRequestMapper<
150
- Entities['UpdatePaymentLinkMapper']
151
- >
152
- },
86
+ mappers as PaymentLinkMappers<
87
+ PaymentMethodEnum,
88
+ CurrencyEnum,
89
+ StatusEnum,
90
+ Entities,
91
+ Dto
92
+ >,
153
93
  options
154
94
  );
155
95
  }
156
96
 
157
97
  async createPaymentLink(
158
- paymentLinkDto: Dto['CreatePaymentLinkMapper']
98
+ paymentLinkDto: StripeCreatePaymentLinkDto<StatusEnum>,
99
+ ...args: unknown[]
159
100
  ): Promise<Dto['PaymentLinkMapper']> {
160
101
  const session = await this.stripeClient.paymentLinks.create({
161
102
  ...paymentLinkDto.stripeFields,
@@ -163,30 +104,29 @@ export class StripePaymentLinkService<
163
104
  currency: paymentLinkDto.currency as string
164
105
  });
165
106
 
166
- const paymentLinkEntity =
167
- await this.basePaymentLinkService.createPaymentLink(
168
- await this._mappers.CreatePaymentLinkMapper.deserializeDtoToEntity(
169
- {
170
- ...paymentLinkDto,
171
- id: session.id,
172
- amount:
173
- session.line_items?.data.reduce<number>(
174
- (total, item) => total + item.amount_total,
175
- 0
176
- ) ?? 0
177
- },
178
- this.em,
179
- session
180
- )
181
- );
182
-
183
- return this._mappers.PaymentLinkMapper.serializeEntityToDto(
184
- paymentLinkEntity
107
+ const paymentLink = await this.basePaymentLinkService.createPaymentLink(
108
+ {
109
+ ...paymentLinkDto,
110
+ id: session.id,
111
+ amount:
112
+ session.line_items?.data.reduce<number>(
113
+ (total, item) => total + item.amount_total,
114
+ 0
115
+ ) ?? 0
116
+ },
117
+ this.em,
118
+ session,
119
+ ...args
185
120
  );
121
+
122
+ paymentLink.stripeFields = session;
123
+
124
+ return paymentLink;
186
125
  }
187
126
 
188
127
  async updatePaymentLink(
189
- paymentLinkDto: Dto['UpdatePaymentLinkMapper']
128
+ paymentLinkDto: StripeUpdatePaymentLinkDto<StatusEnum>,
129
+ ...args: unknown[]
190
130
  ): Promise<Dto['PaymentLinkMapper']> {
191
131
  const session = await this.stripeClient.paymentLinks.update(
192
132
  paymentLinkDto.id,
@@ -196,37 +136,37 @@ export class StripePaymentLinkService<
196
136
  }
197
137
  );
198
138
 
199
- const paymentLinkEntity =
200
- await this.basePaymentLinkService.updatePaymentLink(
201
- await this._mappers.UpdatePaymentLinkMapper.deserializeDtoToEntity(
202
- {
203
- ...paymentLinkDto,
204
- id: session.id,
205
- amount:
206
- session.line_items?.data.reduce<number>(
207
- (total, item) => total + item.amount_total,
208
- 0
209
- ) ?? 0
210
- },
211
- this.em,
212
- session
213
- )
214
- );
215
-
216
- return this._mappers.PaymentLinkMapper.serializeEntityToDto(
217
- paymentLinkEntity
139
+ const paymentLink = await this.basePaymentLinkService.updatePaymentLink(
140
+ await this.mappers.UpdatePaymentLinkMapper.toEntity(
141
+ {
142
+ ...paymentLinkDto,
143
+ id: session.id,
144
+ amount:
145
+ session.line_items?.data.reduce<number>(
146
+ (total, item) => total + item.amount_total,
147
+ 0
148
+ ) ?? 0
149
+ },
150
+ this.em,
151
+ session
152
+ ),
153
+ ...args
218
154
  );
155
+
156
+ paymentLink.stripeFields = session;
157
+
158
+ return paymentLink;
219
159
  }
220
160
 
221
161
  async getPaymentLink({ id }: IdDto): Promise<Dto['PaymentLinkMapper']> {
162
+ const stripePaymentLink = await this.stripeClient.paymentLinks.retrieve(id);
163
+
222
164
  const databasePaymentLink =
223
165
  await this.basePaymentLinkService.getPaymentLink({ id });
224
- return {
225
- ...this._mappers.PaymentLinkMapper.serializeEntityToDto(
226
- databasePaymentLink
227
- ),
228
- stripeFields: await this.stripeClient.paymentLinks.retrieve(id)
229
- };
166
+
167
+ databasePaymentLink.stripeFields = stripePaymentLink;
168
+
169
+ return databasePaymentLink;
230
170
  }
231
171
 
232
172
  async expirePaymentLink({ id }: IdDto): Promise<void> {
@@ -257,20 +197,26 @@ export class StripePaymentLinkService<
257
197
  }
258
198
 
259
199
  async listPaymentLinks(idsDto?: IdsDto): Promise<Dto['PaymentLinkMapper'][]> {
260
- const paymentLinks = await this.stripeClient.paymentLinks.list({
200
+ const stripePaymentLinks = await this.stripeClient.paymentLinks.list({
261
201
  active: true
262
202
  });
203
+
204
+ const databasePaymentLinks =
205
+ await this.basePaymentLinkService.listPaymentLinks(idsDto);
206
+
263
207
  return await Promise.all(
264
- (await this.basePaymentLinkService.listPaymentLinks(idsDto)).map(
265
- async (paymentLink) => ({
266
- ...(await this._mappers.PaymentLinkMapper.serializeEntityToDto(
267
- paymentLink
268
- )),
269
- stripeFields: paymentLinks.data.find(
270
- (paymentLink) => paymentLink.id === paymentLink.id
271
- )
272
- })
273
- )
208
+ databasePaymentLinks.map(async (paymentLink) => {
209
+ const stripePaymentLink = stripePaymentLinks.data.find(
210
+ (sp) => sp.id === paymentLink.id
211
+ );
212
+ if (!stripePaymentLink) {
213
+ throw new Error(
214
+ `Stripe payment link not found for id: ${paymentLink.id}`
215
+ );
216
+ }
217
+ paymentLink.stripeFields = stripePaymentLink;
218
+ return paymentLink;
219
+ })
274
220
  );
275
221
  }
276
222
  }
@@ -1,25 +1,19 @@
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 { BasePlanService } from '@forklaunch/implementation-billing-base/services';
8
+ import { PlanMappers } from '@forklaunch/implementation-billing-base/types';
8
9
  import { PlanService } 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';
20
13
  import { BillingProviderEnum } from '../domain/enum/billingProvider.enum';
21
14
  import { CurrencyEnum } from '../domain/enum/currency.enum';
22
15
  import { PlanCadenceEnum } from '../domain/enum/planCadence.enum';
16
+ import { StripePlanMappers } from '../domain/types/plan.mapper.types';
23
17
  import {
24
18
  StripeCreatePlanDto,
25
19
  StripePlanDto,
@@ -48,77 +42,24 @@ export class StripePlanService<
48
42
  {
49
43
  basePlanService: BasePlanService<
50
44
  SchemaValidator,
51
- typeof PlanCadenceEnum,
52
- typeof CurrencyEnum,
53
- typeof BillingProviderEnum,
45
+ PlanCadenceEnum,
46
+ CurrencyEnum,
47
+ BillingProviderEnum,
54
48
  Entities,
55
- Entities
49
+ Dto
56
50
  >;
57
- protected _mappers: InternalMapper<InstanceTypeRecord<typeof this.mappers>>;
58
51
  protected readonly stripeClient: Stripe;
59
52
  protected readonly em: EntityManager;
60
53
  protected readonly openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>;
61
54
  protected readonly schemaValidator: SchemaValidator;
62
- protected readonly mappers: {
63
- PlanMapper: ResponseMapperConstructor<
64
- SchemaValidator,
65
- Dto['PlanMapper'],
66
- Entities['PlanMapper']
67
- >;
68
- CreatePlanMapper: RequestMapperConstructor<
69
- SchemaValidator,
70
- Dto['CreatePlanMapper'],
71
- Entities['CreatePlanMapper'],
72
- (
73
- dto: Dto['CreatePlanMapper'],
74
- em: EntityManager,
75
- plan: Stripe.Plan
76
- ) => Promise<Entities['CreatePlanMapper']>
77
- >;
78
- UpdatePlanMapper: RequestMapperConstructor<
79
- SchemaValidator,
80
- Dto['UpdatePlanMapper'],
81
- Entities['UpdatePlanMapper'],
82
- (
83
- dto: Dto['UpdatePlanMapper'],
84
- em: EntityManager,
85
- plan: Stripe.Plan
86
- ) => Promise<Entities['UpdatePlanMapper']>
87
- >;
88
- };
55
+ protected readonly mappers: StripePlanMappers<Entities, Dto>;
89
56
 
90
57
  constructor(
91
58
  stripeClient: Stripe,
92
59
  em: EntityManager,
93
60
  openTelemetryCollector: OpenTelemetryCollector<MetricsDefinition>,
94
61
  schemaValidator: SchemaValidator,
95
- mappers: {
96
- PlanMapper: ResponseMapperConstructor<
97
- SchemaValidator,
98
- Dto['PlanMapper'],
99
- Entities['PlanMapper']
100
- >;
101
- CreatePlanMapper: RequestMapperConstructor<
102
- SchemaValidator,
103
- Dto['CreatePlanMapper'],
104
- Entities['CreatePlanMapper'],
105
- (
106
- dto: Dto['CreatePlanMapper'],
107
- em: EntityManager,
108
- plan: Stripe.Plan
109
- ) => Promise<Entities['CreatePlanMapper']>
110
- >;
111
- UpdatePlanMapper: RequestMapperConstructor<
112
- SchemaValidator,
113
- Dto['UpdatePlanMapper'],
114
- Entities['UpdatePlanMapper'],
115
- (
116
- dto: Dto['UpdatePlanMapper'],
117
- em: EntityManager,
118
- plan: Stripe.Plan
119
- ) => Promise<Entities['UpdatePlanMapper']>
120
- >;
121
- },
62
+ mappers: StripePlanMappers<Entities, Dto>,
122
63
  readonly options?: {
123
64
  telemetry?: TelemetryOptions;
124
65
  databaseTableName?: string;
@@ -129,45 +70,43 @@ export class StripePlanService<
129
70
  this.openTelemetryCollector = openTelemetryCollector;
130
71
  this.schemaValidator = schemaValidator;
131
72
  this.mappers = mappers;
132
- this._mappers = transformIntoInternalMapper(mappers, schemaValidator);
133
73
  this.basePlanService = new BasePlanService(
134
74
  em,
135
75
  openTelemetryCollector,
136
76
  schemaValidator,
137
- {
138
- PlanMapper: IdentityResponseMapper<Entities['PlanMapper']>,
139
- CreatePlanMapper: IdentityRequestMapper<Entities['CreatePlanMapper']>,
140
- UpdatePlanMapper: IdentityRequestMapper<Entities['UpdatePlanMapper']>
141
- },
77
+ mappers as PlanMappers<
78
+ PlanCadenceEnum,
79
+ CurrencyEnum,
80
+ BillingProviderEnum,
81
+ Entities,
82
+ Dto
83
+ >,
142
84
  options
143
85
  );
144
86
  }
145
87
 
146
88
  async createPlan(
147
- planDto: Dto['CreatePlanMapper'],
89
+ planDto: StripeCreatePlanDto,
148
90
  em?: EntityManager
149
91
  ): Promise<Dto['PlanMapper']> {
150
- const plan = await this.stripeClient.plans.create({
92
+ const stripePlan = await this.stripeClient.plans.create({
151
93
  ...planDto.stripeFields,
152
94
  interval: planDto.cadence,
153
95
  product: planDto.name,
154
96
  currency: planDto.currency as string
155
97
  });
156
98
 
157
- const planEntity = await this.basePlanService.createPlan(
158
- await this._mappers.CreatePlanMapper.deserializeDtoToEntity(
159
- {
160
- ...planDto,
161
- externalId: plan.id,
162
- billingProvider: 'stripe'
163
- },
164
- em ?? this.em,
165
- plan
166
- ),
167
- em
99
+ const plan = await this.basePlanService.createPlan(
100
+ {
101
+ ...planDto,
102
+ externalId: stripePlan.id,
103
+ billingProvider: 'stripe'
104
+ },
105
+ em ?? this.em,
106
+ stripePlan
168
107
  );
169
108
 
170
- return this._mappers.PlanMapper.serializeEntityToDto(planEntity);
109
+ return plan;
171
110
  }
172
111
 
173
112
  async getPlan(idDto: IdDto, em?: EntityManager): Promise<Dto['PlanMapper']> {
@@ -181,16 +120,13 @@ export class StripePlanService<
181
120
  if (!id) {
182
121
  throw new Error('Plan not found');
183
122
  }
184
- return {
185
- ...(await this._mappers.PlanMapper.serializeEntityToDto(
186
- await this.basePlanService.getPlan({ id }, em)
187
- )),
188
- stripeFields: plan
189
- };
123
+ const planEntity = await this.basePlanService.getPlan({ id }, em);
124
+ planEntity.stripeFields = plan;
125
+ return planEntity;
190
126
  }
191
127
 
192
128
  async updatePlan(
193
- planDto: Dto['UpdatePlanMapper'],
129
+ planDto: StripeUpdatePlanDto,
194
130
  em?: EntityManager
195
131
  ): Promise<Dto['PlanMapper']> {
196
132
  const existingPlan = await this.stripeClient.plans.retrieve(planDto.id);
@@ -204,7 +140,7 @@ export class StripePlanService<
204
140
  );
205
141
 
206
142
  const planEntity = await this.basePlanService.updatePlan(
207
- await this._mappers.UpdatePlanMapper.deserializeDtoToEntity(
143
+ await this.mappers.UpdatePlanMapper.toEntity(
208
144
  {
209
145
  ...planDto,
210
146
  externalId: plan.id,
@@ -215,8 +151,9 @@ export class StripePlanService<
215
151
  ),
216
152
  em
217
153
  );
154
+ planEntity.stripeFields = plan;
218
155
 
219
- return this._mappers.PlanMapper.serializeEntityToDto(planEntity);
156
+ return planEntity;
220
157
  }
221
158
 
222
159
  async deletePlan(idDto: { id: string }, em?: EntityManager): Promise<void> {
@@ -231,7 +168,7 @@ export class StripePlanService<
231
168
  const plans = await this.stripeClient.plans.list({
232
169
  active: true
233
170
  });
234
- const ids = (
171
+ const planIds = (
235
172
  await em?.findAll<{ id: string; externalId: string }>(
236
173
  this.options?.databaseTableName ?? 'plan',
237
174
  { where: { externalId: { $in: plans.data.map((plan) => plan.id) } } }
@@ -240,16 +177,18 @@ export class StripePlanService<
240
177
  ?.filter((s) => idsDto?.ids?.includes(s.id))
241
178
  ?.map((s) => s.id);
242
179
 
243
- if (!ids) {
180
+ if (!planIds) {
244
181
  throw new Error('Plans not found');
245
182
  }
246
183
  return await Promise.all(
247
- (await this.basePlanService.listPlans({ ids }, em)).map(async (plan) => ({
248
- ...(await this._mappers.PlanMapper.serializeEntityToDto(plan)),
249
- stripeFields: plans.data.find(
250
- (stripePlan) => stripePlan.id === plan.externalId
251
- )
252
- }))
184
+ (await this.basePlanService.listPlans({ ids: planIds }, em)).map(
185
+ async (plan) => ({
186
+ ...plan,
187
+ stripeFields: plans.data.find(
188
+ (stripePlan) => stripePlan.id === plan.externalId
189
+ )
190
+ })
191
+ )
253
192
  );
254
193
  }
255
194
  }