@forklaunch/implementation-billing-base 0.2.3 → 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.
- package/lib/schemas/index.d.mts +402 -0
- package/lib/schemas/index.d.ts +402 -6
- package/lib/schemas/index.js +498 -5
- package/lib/schemas/index.mjs +547 -0
- package/lib/services/index.d.mts +255 -0
- package/lib/services/index.d.ts +255 -6
- package/lib/services/index.js +610 -5
- package/lib/services/index.mjs +599 -0
- package/package.json +6 -5
- package/lib/__test__/schemaEquality.test.d.ts +0 -2
- package/lib/__test__/schemaEquality.test.d.ts.map +0 -1
- package/lib/__test__/schemaEquality.test.js +0 -430
- package/lib/jest.config.d.ts +0 -4
- package/lib/jest.config.d.ts.map +0 -1
- package/lib/jest.config.js +0 -19
- package/lib/schemas/billingPortal.schema.d.ts +0 -119
- package/lib/schemas/billingPortal.schema.d.ts.map +0 -1
- package/lib/schemas/billingPortal.schema.js +0 -7
- package/lib/schemas/checkoutSession.schema.d.ts +0 -265
- package/lib/schemas/checkoutSession.schema.d.ts.map +0 -1
- package/lib/schemas/checkoutSession.schema.js +0 -7
- package/lib/schemas/index.d.ts.map +0 -1
- package/lib/schemas/paymentLink.schema.d.ts +0 -319
- package/lib/schemas/paymentLink.schema.d.ts.map +0 -1
- package/lib/schemas/paymentLink.schema.js +0 -7
- package/lib/schemas/plan.schema.d.ts +0 -338
- package/lib/schemas/plan.schema.d.ts.map +0 -1
- package/lib/schemas/plan.schema.js +0 -7
- package/lib/schemas/subscription.schema.d.ts +0 -366
- package/lib/schemas/subscription.schema.d.ts.map +0 -1
- package/lib/schemas/subscription.schema.js +0 -7
- package/lib/schemas/typebox/billingPortal.schema.d.ts +0 -161
- package/lib/schemas/typebox/billingPortal.schema.d.ts.map +0 -1
- package/lib/schemas/typebox/billingPortal.schema.js +0 -31
- package/lib/schemas/typebox/checkoutSession.schema.d.ts +0 -316
- package/lib/schemas/typebox/checkoutSession.schema.d.ts.map +0 -1
- package/lib/schemas/typebox/checkoutSession.schema.js +0 -50
- package/lib/schemas/typebox/paymentLink.schema.d.ts +0 -406
- package/lib/schemas/typebox/paymentLink.schema.d.ts.map +0 -1
- package/lib/schemas/typebox/paymentLink.schema.js +0 -55
- package/lib/schemas/typebox/plan.schema.d.ts +0 -408
- package/lib/schemas/typebox/plan.schema.d.ts.map +0 -1
- package/lib/schemas/typebox/plan.schema.js +0 -57
- package/lib/schemas/typebox/subscription.schema.d.ts +0 -456
- package/lib/schemas/typebox/subscription.schema.d.ts.map +0 -1
- package/lib/schemas/typebox/subscription.schema.js +0 -61
- package/lib/schemas/zod/billingPortal.schema.d.ts +0 -63
- package/lib/schemas/zod/billingPortal.schema.d.ts.map +0 -1
- package/lib/schemas/zod/billingPortal.schema.js +0 -31
- package/lib/schemas/zod/checkoutSession.schema.d.ts +0 -176
- package/lib/schemas/zod/checkoutSession.schema.d.ts.map +0 -1
- package/lib/schemas/zod/checkoutSession.schema.js +0 -50
- package/lib/schemas/zod/paymentLink.schema.d.ts +0 -172
- package/lib/schemas/zod/paymentLink.schema.d.ts.map +0 -1
- package/lib/schemas/zod/paymentLink.schema.js +0 -55
- package/lib/schemas/zod/plan.schema.d.ts +0 -196
- package/lib/schemas/zod/plan.schema.d.ts.map +0 -1
- package/lib/schemas/zod/plan.schema.js +0 -57
- package/lib/schemas/zod/subscription.schema.d.ts +0 -204
- package/lib/schemas/zod/subscription.schema.d.ts.map +0 -1
- package/lib/schemas/zod/subscription.schema.js +0 -61
- package/lib/services/billingPortal.service.d.ts +0 -112
- package/lib/services/billingPortal.service.d.ts.map +0 -1
- package/lib/services/billingPortal.service.js +0 -128
- package/lib/services/checkoutSession.service.d.ts +0 -137
- package/lib/services/checkoutSession.service.d.ts.map +0 -1
- package/lib/services/checkoutSession.service.js +0 -111
- package/lib/services/index.d.ts.map +0 -1
- package/lib/services/paymentLink.service.d.ts +0 -118
- package/lib/services/paymentLink.service.d.ts.map +0 -1
- package/lib/services/paymentLink.service.js +0 -154
- package/lib/services/plan.service.d.ts +0 -102
- package/lib/services/plan.service.d.ts.map +0 -1
- package/lib/services/plan.service.js +0 -80
- package/lib/services/subscription.service.d.ts +0 -159
- package/lib/services/subscription.service.d.ts.map +0 -1
- package/lib/services/subscription.service.js +0 -169
- package/lib/tsconfig.tsbuildinfo +0 -1
- package/lib/vitest.config.d.ts +0 -3
- package/lib/vitest.config.d.ts.map +0 -1
- package/lib/vitest.config.js +0 -7
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
// services/billingPortal.service.ts
|
|
2
|
+
import { createCacheKey } from "@forklaunch/core/cache";
|
|
3
|
+
import {
|
|
4
|
+
evaluateTelemetryOptions
|
|
5
|
+
} from "@forklaunch/core/http";
|
|
6
|
+
import {
|
|
7
|
+
transformIntoInternalDtoMapper
|
|
8
|
+
} from "@forklaunch/core/mappers";
|
|
9
|
+
var BaseBillingPortalService = class {
|
|
10
|
+
constructor(em, cache, openTelemetryCollector, schemaValidator, mappers, options) {
|
|
11
|
+
this.em = em;
|
|
12
|
+
this.cache = cache;
|
|
13
|
+
this.openTelemetryCollector = openTelemetryCollector;
|
|
14
|
+
this.schemaValidator = schemaValidator;
|
|
15
|
+
this.mappers = mappers;
|
|
16
|
+
this.options = options;
|
|
17
|
+
this.#mappers = transformIntoInternalDtoMapper(mappers, schemaValidator);
|
|
18
|
+
this.enableDatabaseBackup = options?.enableDatabaseBackup ?? false;
|
|
19
|
+
this.evaluatedTelemetryOptions = options?.telemetry ? evaluateTelemetryOptions(options.telemetry).enabled : {
|
|
20
|
+
logging: false,
|
|
21
|
+
metrics: false,
|
|
22
|
+
tracing: false
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
#mappers;
|
|
26
|
+
evaluatedTelemetryOptions;
|
|
27
|
+
enableDatabaseBackup;
|
|
28
|
+
createCacheKey = createCacheKey("billing_portal_session");
|
|
29
|
+
async createBillingPortalSession(billingPortalDto) {
|
|
30
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
31
|
+
this.openTelemetryCollector.info(
|
|
32
|
+
"Creating billing portal session",
|
|
33
|
+
billingPortalDto
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
const billingPortal = await this.#mappers.CreateBillingPortalDtoMapper.deserializeDtoToEntity(
|
|
37
|
+
billingPortalDto,
|
|
38
|
+
this.em
|
|
39
|
+
);
|
|
40
|
+
if (this.enableDatabaseBackup) {
|
|
41
|
+
await this.em.persistAndFlush(billingPortal);
|
|
42
|
+
}
|
|
43
|
+
const createdBillingPortalDto = await this.#mappers.BillingPortalDtoMapper.serializeEntityToDto(
|
|
44
|
+
billingPortal
|
|
45
|
+
);
|
|
46
|
+
await this.cache.putRecord({
|
|
47
|
+
key: this.createCacheKey(createdBillingPortalDto.id),
|
|
48
|
+
value: createdBillingPortalDto,
|
|
49
|
+
ttlMilliseconds: this.cache.getTtlMilliseconds()
|
|
50
|
+
});
|
|
51
|
+
return createdBillingPortalDto;
|
|
52
|
+
}
|
|
53
|
+
async getBillingPortalSession(idDto) {
|
|
54
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
55
|
+
this.openTelemetryCollector.info("Getting billing portal session", idDto);
|
|
56
|
+
}
|
|
57
|
+
const billingPortalDetails = await this.cache.readRecord(this.createCacheKey(idDto.id));
|
|
58
|
+
if (!billingPortalDetails) {
|
|
59
|
+
throw new Error("Session not found");
|
|
60
|
+
}
|
|
61
|
+
return billingPortalDetails.value;
|
|
62
|
+
}
|
|
63
|
+
async updateBillingPortalSession(billingPortalDto) {
|
|
64
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
65
|
+
this.openTelemetryCollector.info(
|
|
66
|
+
"Updating billing portal session",
|
|
67
|
+
billingPortalDto
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
const existingBillingPortal = (await this.cache.readRecord(
|
|
71
|
+
this.createCacheKey(billingPortalDto.id)
|
|
72
|
+
))?.value;
|
|
73
|
+
if (!existingBillingPortal) {
|
|
74
|
+
throw new Error("Session not found");
|
|
75
|
+
}
|
|
76
|
+
const billingPortal = await this.#mappers.UpdateBillingPortalDtoMapper.deserializeDtoToEntity(
|
|
77
|
+
billingPortalDto,
|
|
78
|
+
this.em
|
|
79
|
+
);
|
|
80
|
+
if (this.enableDatabaseBackup) {
|
|
81
|
+
await this.em.persistAndFlush({
|
|
82
|
+
billingPortal
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const updatedBillingPortalDto = {
|
|
86
|
+
...existingBillingPortal,
|
|
87
|
+
...await this.#mappers.BillingPortalDtoMapper.serializeEntityToDto(
|
|
88
|
+
billingPortal
|
|
89
|
+
)
|
|
90
|
+
};
|
|
91
|
+
await this.cache.putRecord({
|
|
92
|
+
key: this.createCacheKey(updatedBillingPortalDto.id),
|
|
93
|
+
value: updatedBillingPortalDto,
|
|
94
|
+
ttlMilliseconds: this.cache.getTtlMilliseconds()
|
|
95
|
+
});
|
|
96
|
+
return updatedBillingPortalDto;
|
|
97
|
+
}
|
|
98
|
+
async expireBillingPortalSession(idDto) {
|
|
99
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
100
|
+
this.openTelemetryCollector.info(
|
|
101
|
+
"Expiring billing portal session",
|
|
102
|
+
idDto
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
const sessionExists = await this.cache.readRecord(
|
|
106
|
+
this.createCacheKey(idDto.id)
|
|
107
|
+
);
|
|
108
|
+
if (!sessionExists) {
|
|
109
|
+
throw new Error("Session not found");
|
|
110
|
+
}
|
|
111
|
+
await this.cache.deleteRecord(this.createCacheKey(idDto.id));
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// services/checkoutSession.service.ts
|
|
116
|
+
import { createCacheKey as createCacheKey2 } from "@forklaunch/core/cache";
|
|
117
|
+
import {
|
|
118
|
+
evaluateTelemetryOptions as evaluateTelemetryOptions2
|
|
119
|
+
} from "@forklaunch/core/http";
|
|
120
|
+
import {
|
|
121
|
+
transformIntoInternalDtoMapper as transformIntoInternalDtoMapper2
|
|
122
|
+
} from "@forklaunch/core/mappers";
|
|
123
|
+
var BaseCheckoutSessionService = class {
|
|
124
|
+
constructor(em, cache, openTelemetryCollector, schemaValidator, mappers, options) {
|
|
125
|
+
this.em = em;
|
|
126
|
+
this.cache = cache;
|
|
127
|
+
this.openTelemetryCollector = openTelemetryCollector;
|
|
128
|
+
this.schemaValidator = schemaValidator;
|
|
129
|
+
this.mappers = mappers;
|
|
130
|
+
this.options = options;
|
|
131
|
+
this.#mappers = transformIntoInternalDtoMapper2(mappers, schemaValidator);
|
|
132
|
+
this.enableDatabaseBackup = options?.enableDatabaseBackup ?? false;
|
|
133
|
+
this.evaluatedTelemetryOptions = options?.telemetry ? evaluateTelemetryOptions2(options.telemetry).enabled : {
|
|
134
|
+
logging: false,
|
|
135
|
+
metrics: false,
|
|
136
|
+
tracing: false
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
#mappers;
|
|
140
|
+
evaluatedTelemetryOptions;
|
|
141
|
+
enableDatabaseBackup;
|
|
142
|
+
createCacheKey = createCacheKey2("checkout_session");
|
|
143
|
+
async createCheckoutSession(checkoutSessionDto) {
|
|
144
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
145
|
+
this.openTelemetryCollector.info(
|
|
146
|
+
"Creating checkout session",
|
|
147
|
+
checkoutSessionDto
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
const checkoutSession = await this.#mappers.CreateCheckoutSessionDtoMapper.deserializeDtoToEntity(
|
|
151
|
+
checkoutSessionDto,
|
|
152
|
+
this.em
|
|
153
|
+
);
|
|
154
|
+
const createdCheckoutSessionDto = await this.#mappers.CheckoutSessionDtoMapper.serializeEntityToDto(
|
|
155
|
+
checkoutSession
|
|
156
|
+
);
|
|
157
|
+
if (this.enableDatabaseBackup) {
|
|
158
|
+
await this.em.persistAndFlush(checkoutSession);
|
|
159
|
+
}
|
|
160
|
+
await this.cache.putRecord({
|
|
161
|
+
key: this.createCacheKey(createdCheckoutSessionDto.id),
|
|
162
|
+
value: createdCheckoutSessionDto,
|
|
163
|
+
ttlMilliseconds: this.cache.getTtlMilliseconds()
|
|
164
|
+
});
|
|
165
|
+
return createdCheckoutSessionDto;
|
|
166
|
+
}
|
|
167
|
+
async getCheckoutSession({
|
|
168
|
+
id
|
|
169
|
+
}) {
|
|
170
|
+
const checkoutSessionDetails = await this.cache.readRecord(this.createCacheKey(id));
|
|
171
|
+
if (!checkoutSessionDetails) {
|
|
172
|
+
throw new Error("Session not found");
|
|
173
|
+
}
|
|
174
|
+
return this.#mappers.CheckoutSessionDtoMapper.serializeEntityToDto(
|
|
175
|
+
checkoutSessionDetails.value
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
async expireCheckoutSession({ id }) {
|
|
179
|
+
const checkoutSessionDetails = await this.cache.readRecord(
|
|
180
|
+
this.createCacheKey(id)
|
|
181
|
+
);
|
|
182
|
+
if (!checkoutSessionDetails) {
|
|
183
|
+
throw new Error("Session not found");
|
|
184
|
+
}
|
|
185
|
+
await this.cache.deleteRecord(this.createCacheKey(id));
|
|
186
|
+
}
|
|
187
|
+
async handleCheckoutSuccess({ id }) {
|
|
188
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
189
|
+
this.openTelemetryCollector.info("Checkout success", { id });
|
|
190
|
+
}
|
|
191
|
+
if (this.enableDatabaseBackup) {
|
|
192
|
+
const checkoutSession = await this.em.upsert("CheckoutSession", {
|
|
193
|
+
id,
|
|
194
|
+
status: "SUCCESS"
|
|
195
|
+
});
|
|
196
|
+
await this.em.persistAndFlush(checkoutSession);
|
|
197
|
+
}
|
|
198
|
+
await this.cache.deleteRecord(this.createCacheKey(id));
|
|
199
|
+
}
|
|
200
|
+
async handleCheckoutFailure({ id }) {
|
|
201
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
202
|
+
this.openTelemetryCollector.info("Checkout failure", { id });
|
|
203
|
+
}
|
|
204
|
+
if (this.enableDatabaseBackup) {
|
|
205
|
+
const checkoutSession = await this.em.upsert("CheckoutSession", {
|
|
206
|
+
id,
|
|
207
|
+
status: "FAILED"
|
|
208
|
+
});
|
|
209
|
+
await this.em.persistAndFlush(checkoutSession);
|
|
210
|
+
}
|
|
211
|
+
await this.cache.deleteRecord(this.createCacheKey(id));
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
// services/paymentLink.service.ts
|
|
216
|
+
import { createCacheKey as createCacheKey3 } from "@forklaunch/core/cache";
|
|
217
|
+
import {
|
|
218
|
+
evaluateTelemetryOptions as evaluateTelemetryOptions3
|
|
219
|
+
} from "@forklaunch/core/http";
|
|
220
|
+
import {
|
|
221
|
+
transformIntoInternalDtoMapper as transformIntoInternalDtoMapper3
|
|
222
|
+
} from "@forklaunch/core/mappers";
|
|
223
|
+
var BasePaymentLinkService = class {
|
|
224
|
+
constructor(em, cache, openTelemetryCollector, schemaValidator, mappers, options) {
|
|
225
|
+
this.em = em;
|
|
226
|
+
this.cache = cache;
|
|
227
|
+
this.openTelemetryCollector = openTelemetryCollector;
|
|
228
|
+
this.schemaValidator = schemaValidator;
|
|
229
|
+
this.mappers = mappers;
|
|
230
|
+
this.options = options;
|
|
231
|
+
this.#mappers = transformIntoInternalDtoMapper3(mappers, schemaValidator);
|
|
232
|
+
this.enableDatabaseBackup = options?.enableDatabaseBackup ?? false;
|
|
233
|
+
this.evaluatedTelemetryOptions = options?.telemetry ? evaluateTelemetryOptions3(options.telemetry).enabled : {
|
|
234
|
+
logging: false,
|
|
235
|
+
metrics: false,
|
|
236
|
+
tracing: false
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
#mappers;
|
|
240
|
+
evaluatedTelemetryOptions;
|
|
241
|
+
enableDatabaseBackup;
|
|
242
|
+
cacheKeyPrefix = "payment_link";
|
|
243
|
+
createCacheKey = createCacheKey3(this.cacheKeyPrefix);
|
|
244
|
+
async createPaymentLink(paymentLinkDto) {
|
|
245
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
246
|
+
this.openTelemetryCollector.info("Creating payment link", paymentLinkDto);
|
|
247
|
+
}
|
|
248
|
+
const paymentLink = await this.#mappers.CreatePaymentLinkDtoMapper.deserializeDtoToEntity(
|
|
249
|
+
paymentLinkDto,
|
|
250
|
+
this.em
|
|
251
|
+
);
|
|
252
|
+
if (this.enableDatabaseBackup) {
|
|
253
|
+
await this.em.persistAndFlush(paymentLink);
|
|
254
|
+
}
|
|
255
|
+
const createdPaymentLinkDto = await this.#mappers.PaymentLinkDtoMapper.serializeEntityToDto(
|
|
256
|
+
paymentLink
|
|
257
|
+
);
|
|
258
|
+
await this.cache.putRecord({
|
|
259
|
+
key: this.createCacheKey(createdPaymentLinkDto.id),
|
|
260
|
+
value: createdPaymentLinkDto,
|
|
261
|
+
ttlMilliseconds: this.cache.getTtlMilliseconds()
|
|
262
|
+
});
|
|
263
|
+
return createdPaymentLinkDto;
|
|
264
|
+
}
|
|
265
|
+
async updatePaymentLink(paymentLinkDto) {
|
|
266
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
267
|
+
this.openTelemetryCollector.info("Updating payment link", paymentLinkDto);
|
|
268
|
+
}
|
|
269
|
+
const cacheKey = this.createCacheKey(paymentLinkDto.id);
|
|
270
|
+
const existingLink = (await this.cache.readRecord(cacheKey))?.value;
|
|
271
|
+
if (!existingLink) {
|
|
272
|
+
throw new Error("Payment link not found");
|
|
273
|
+
}
|
|
274
|
+
const paymentLink = await this.#mappers.UpdatePaymentLinkDtoMapper.deserializeDtoToEntity(
|
|
275
|
+
paymentLinkDto,
|
|
276
|
+
this.em
|
|
277
|
+
);
|
|
278
|
+
if (this.enableDatabaseBackup) {
|
|
279
|
+
await this.em.persistAndFlush(paymentLink);
|
|
280
|
+
}
|
|
281
|
+
const updatedLinkDto = {
|
|
282
|
+
...existingLink,
|
|
283
|
+
...await this.#mappers.PaymentLinkDtoMapper.serializeEntityToDto(
|
|
284
|
+
paymentLink
|
|
285
|
+
)
|
|
286
|
+
};
|
|
287
|
+
await this.cache.putRecord({
|
|
288
|
+
key: cacheKey,
|
|
289
|
+
value: updatedLinkDto,
|
|
290
|
+
ttlMilliseconds: this.cache.getTtlMilliseconds()
|
|
291
|
+
});
|
|
292
|
+
return updatedLinkDto;
|
|
293
|
+
}
|
|
294
|
+
async getPaymentLink({ id }) {
|
|
295
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
296
|
+
this.openTelemetryCollector.info("Getting payment link", { id });
|
|
297
|
+
}
|
|
298
|
+
const cacheKey = this.createCacheKey(id);
|
|
299
|
+
const paymentLink = await this.cache.readRecord(cacheKey);
|
|
300
|
+
if (!paymentLink) {
|
|
301
|
+
throw new Error("Payment link not found");
|
|
302
|
+
}
|
|
303
|
+
return this.#mappers.PaymentLinkDtoMapper.serializeEntityToDto(
|
|
304
|
+
paymentLink.value
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
async expirePaymentLink({ id }) {
|
|
308
|
+
this.openTelemetryCollector.info("Payment link expired", { id });
|
|
309
|
+
if (this.enableDatabaseBackup) {
|
|
310
|
+
const paymentLink = await this.em.upsert("PaymentLink", {
|
|
311
|
+
id,
|
|
312
|
+
status: "EXPIRED"
|
|
313
|
+
});
|
|
314
|
+
await this.em.removeAndFlush(paymentLink);
|
|
315
|
+
}
|
|
316
|
+
await this.cache.deleteRecord(this.createCacheKey(id));
|
|
317
|
+
}
|
|
318
|
+
async handlePaymentSuccess({ id }) {
|
|
319
|
+
this.openTelemetryCollector.info("Payment link success", { id });
|
|
320
|
+
if (this.enableDatabaseBackup) {
|
|
321
|
+
const paymentLink = await this.em.upsert("PaymentLink", {
|
|
322
|
+
id,
|
|
323
|
+
status: "COMPLETED"
|
|
324
|
+
});
|
|
325
|
+
await this.em.removeAndFlush(paymentLink);
|
|
326
|
+
}
|
|
327
|
+
await this.cache.deleteRecord(this.createCacheKey(id));
|
|
328
|
+
}
|
|
329
|
+
async handlePaymentFailure({ id }) {
|
|
330
|
+
this.openTelemetryCollector.info("Payment link failure", { id });
|
|
331
|
+
if (this.enableDatabaseBackup) {
|
|
332
|
+
const paymentLink = await this.em.upsert("PaymentLink", {
|
|
333
|
+
id,
|
|
334
|
+
status: "FAILED"
|
|
335
|
+
});
|
|
336
|
+
await this.em.removeAndFlush(paymentLink);
|
|
337
|
+
}
|
|
338
|
+
await this.cache.deleteRecord(this.createCacheKey(id));
|
|
339
|
+
}
|
|
340
|
+
async listPaymentLinks(idsDto) {
|
|
341
|
+
const keys = idsDto?.ids.map((id) => this.createCacheKey(id)) ?? await this.cache.listKeys(this.cacheKeyPrefix);
|
|
342
|
+
return Promise.all(
|
|
343
|
+
keys.map(async (key) => {
|
|
344
|
+
const paymentLink = await this.cache.readRecord(key);
|
|
345
|
+
const paymentLinkDto = this.#mappers.PaymentLinkDtoMapper.serializeEntityToDto(
|
|
346
|
+
paymentLink.value
|
|
347
|
+
);
|
|
348
|
+
return paymentLinkDto;
|
|
349
|
+
})
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
// services/plan.service.ts
|
|
355
|
+
import {
|
|
356
|
+
evaluateTelemetryOptions as evaluateTelemetryOptions4
|
|
357
|
+
} from "@forklaunch/core/http";
|
|
358
|
+
import {
|
|
359
|
+
transformIntoInternalDtoMapper as transformIntoInternalDtoMapper4
|
|
360
|
+
} from "@forklaunch/core/mappers";
|
|
361
|
+
var BasePlanService = class {
|
|
362
|
+
constructor(em, openTelemetryCollector, schemaValidator, mappers, options) {
|
|
363
|
+
this.em = em;
|
|
364
|
+
this.openTelemetryCollector = openTelemetryCollector;
|
|
365
|
+
this.schemaValidator = schemaValidator;
|
|
366
|
+
this.mappers = mappers;
|
|
367
|
+
this.options = options;
|
|
368
|
+
this.#mappers = transformIntoInternalDtoMapper4(mappers, schemaValidator);
|
|
369
|
+
this.evaluatedTelemetryOptions = options?.telemetry ? evaluateTelemetryOptions4(options.telemetry).enabled : {
|
|
370
|
+
logging: false,
|
|
371
|
+
metrics: false,
|
|
372
|
+
tracing: false
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
#mappers;
|
|
376
|
+
evaluatedTelemetryOptions;
|
|
377
|
+
async listPlans(idsDto, em) {
|
|
378
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
379
|
+
this.openTelemetryCollector.info("Listing plans", idsDto);
|
|
380
|
+
}
|
|
381
|
+
return Promise.all(
|
|
382
|
+
(await (em ?? this.em).findAll("Plan", {
|
|
383
|
+
filters: idsDto?.ids ? { id: { $in: idsDto.ids } } : void 0
|
|
384
|
+
})).map(
|
|
385
|
+
(plan) => this.#mappers.PlanDtoMapper.serializeEntityToDto(
|
|
386
|
+
plan
|
|
387
|
+
)
|
|
388
|
+
)
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
async createPlan(planDto, em) {
|
|
392
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
393
|
+
this.openTelemetryCollector.info("Creating plan", planDto);
|
|
394
|
+
}
|
|
395
|
+
const plan = await this.#mappers.CreatePlanDtoMapper.deserializeDtoToEntity(
|
|
396
|
+
planDto,
|
|
397
|
+
em ?? this.em
|
|
398
|
+
);
|
|
399
|
+
await (em ?? this.em).transactional(async (innerEm) => {
|
|
400
|
+
await innerEm.persist(plan);
|
|
401
|
+
});
|
|
402
|
+
return this.#mappers.PlanDtoMapper.serializeEntityToDto(plan);
|
|
403
|
+
}
|
|
404
|
+
async getPlan(idDto, em) {
|
|
405
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
406
|
+
this.openTelemetryCollector.info("Getting plan", idDto);
|
|
407
|
+
}
|
|
408
|
+
const plan = await (em ?? this.em).findOneOrFail("Plan", idDto);
|
|
409
|
+
return this.#mappers.PlanDtoMapper.serializeEntityToDto(
|
|
410
|
+
plan
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
async updatePlan(planDto, em) {
|
|
414
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
415
|
+
this.openTelemetryCollector.info("Updating plan", planDto);
|
|
416
|
+
}
|
|
417
|
+
const plan = await this.#mappers.UpdatePlanDtoMapper.deserializeDtoToEntity(
|
|
418
|
+
planDto,
|
|
419
|
+
em ?? this.em
|
|
420
|
+
);
|
|
421
|
+
const updatedPlan = await (em ?? this.em).upsert(plan);
|
|
422
|
+
await (em ?? this.em).transactional(async (innerEm) => {
|
|
423
|
+
await innerEm.persist(plan);
|
|
424
|
+
});
|
|
425
|
+
const updatedPlanDto = await this.#mappers.PlanDtoMapper.serializeEntityToDto(updatedPlan);
|
|
426
|
+
return updatedPlanDto;
|
|
427
|
+
}
|
|
428
|
+
async deletePlan(idDto, em) {
|
|
429
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
430
|
+
this.openTelemetryCollector.info("Deleting plan", idDto);
|
|
431
|
+
}
|
|
432
|
+
await (em ?? this.em).nativeDelete("Plan", idDto);
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// services/subscription.service.ts
|
|
437
|
+
import {
|
|
438
|
+
evaluateTelemetryOptions as evaluateTelemetryOptions5
|
|
439
|
+
} from "@forklaunch/core/http";
|
|
440
|
+
import {
|
|
441
|
+
transformIntoInternalDtoMapper as transformIntoInternalDtoMapper5
|
|
442
|
+
} from "@forklaunch/core/mappers";
|
|
443
|
+
var BaseSubscriptionService = class {
|
|
444
|
+
constructor(em, openTelemetryCollector, schemaValidator, mappers, options) {
|
|
445
|
+
this.em = em;
|
|
446
|
+
this.openTelemetryCollector = openTelemetryCollector;
|
|
447
|
+
this.schemaValidator = schemaValidator;
|
|
448
|
+
this.mappers = mappers;
|
|
449
|
+
this.options = options;
|
|
450
|
+
this.#mappers = transformIntoInternalDtoMapper5(mappers, this.schemaValidator);
|
|
451
|
+
this.evaluatedTelemetryOptions = options?.telemetry ? evaluateTelemetryOptions5(options.telemetry).enabled : {
|
|
452
|
+
logging: false,
|
|
453
|
+
metrics: false,
|
|
454
|
+
tracing: false
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
#mappers;
|
|
458
|
+
evaluatedTelemetryOptions;
|
|
459
|
+
async createSubscription(subscriptionDto, em) {
|
|
460
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
461
|
+
this.openTelemetryCollector.info(
|
|
462
|
+
"Creating subscription",
|
|
463
|
+
subscriptionDto
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
const subscription = await this.#mappers.CreateSubscriptionDtoMapper.deserializeDtoToEntity(
|
|
467
|
+
subscriptionDto,
|
|
468
|
+
em ?? this.em
|
|
469
|
+
);
|
|
470
|
+
await (em ?? this.em).transactional(async (innerEm) => {
|
|
471
|
+
await innerEm.persist(subscription);
|
|
472
|
+
});
|
|
473
|
+
const createdSubscriptionDto = await this.#mappers.SubscriptionDtoMapper.serializeEntityToDto(
|
|
474
|
+
subscription
|
|
475
|
+
);
|
|
476
|
+
return createdSubscriptionDto;
|
|
477
|
+
}
|
|
478
|
+
async getSubscription(idDto, em) {
|
|
479
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
480
|
+
this.openTelemetryCollector.info("Getting subscription", idDto);
|
|
481
|
+
}
|
|
482
|
+
const subscription = await (em ?? this.em).findOneOrFail(
|
|
483
|
+
"Subscription",
|
|
484
|
+
idDto
|
|
485
|
+
);
|
|
486
|
+
return this.#mappers.SubscriptionDtoMapper.serializeEntityToDto(
|
|
487
|
+
subscription
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
async getUserSubscription({ id }, em) {
|
|
491
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
492
|
+
this.openTelemetryCollector.info("Getting user subscription", id);
|
|
493
|
+
}
|
|
494
|
+
const subscription = await (em ?? this.em).findOneOrFail("Subscription", {
|
|
495
|
+
partyId: id,
|
|
496
|
+
partyType: "USER",
|
|
497
|
+
active: true
|
|
498
|
+
});
|
|
499
|
+
return this.#mappers.SubscriptionDtoMapper.serializeEntityToDto(
|
|
500
|
+
subscription
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
async getOrganizationSubscription({ id }, em) {
|
|
504
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
505
|
+
this.openTelemetryCollector.info("Getting organization subscription", id);
|
|
506
|
+
}
|
|
507
|
+
const subscription = await (em ?? this.em).findOneOrFail("Subscription", {
|
|
508
|
+
partyId: id,
|
|
509
|
+
partyType: "ORGANIZATION",
|
|
510
|
+
active: true
|
|
511
|
+
});
|
|
512
|
+
return this.#mappers.SubscriptionDtoMapper.serializeEntityToDto(
|
|
513
|
+
subscription
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
async updateSubscription(subscriptionDto, em) {
|
|
517
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
518
|
+
this.openTelemetryCollector.info(
|
|
519
|
+
"Updating subscription",
|
|
520
|
+
subscriptionDto
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
const subscription = this.#mappers.UpdateSubscriptionDtoMapper.deserializeDtoToEntity(
|
|
524
|
+
subscriptionDto,
|
|
525
|
+
em ?? this.em
|
|
526
|
+
);
|
|
527
|
+
const updatedSubscription = await (em ?? this.em).upsert(subscription);
|
|
528
|
+
await (em ?? this.em).transactional(async (innerEm) => {
|
|
529
|
+
await innerEm.persist(updatedSubscription);
|
|
530
|
+
});
|
|
531
|
+
const updatedSubscriptionDto = await this.#mappers.SubscriptionDtoMapper.serializeEntityToDto(
|
|
532
|
+
updatedSubscription
|
|
533
|
+
);
|
|
534
|
+
return updatedSubscriptionDto;
|
|
535
|
+
}
|
|
536
|
+
async deleteSubscription(idDto, em) {
|
|
537
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
538
|
+
this.openTelemetryCollector.info("Deleting subscription", idDto);
|
|
539
|
+
}
|
|
540
|
+
const subscription = await (em ?? this.em).findOne("Subscription", idDto);
|
|
541
|
+
if (!subscription) {
|
|
542
|
+
throw new Error("Subscription not found");
|
|
543
|
+
}
|
|
544
|
+
await (em ?? this.em).removeAndFlush(subscription);
|
|
545
|
+
}
|
|
546
|
+
async listSubscriptions(idsDto, em) {
|
|
547
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
548
|
+
this.openTelemetryCollector.info("Listing subscriptions", idsDto);
|
|
549
|
+
}
|
|
550
|
+
const subscriptions = await (em ?? this.em).findAll("Subscription", {
|
|
551
|
+
where: idsDto.ids ? {
|
|
552
|
+
id: {
|
|
553
|
+
$in: idsDto.ids
|
|
554
|
+
}
|
|
555
|
+
} : void 0
|
|
556
|
+
});
|
|
557
|
+
return Promise.all(
|
|
558
|
+
subscriptions.map((subscription) => {
|
|
559
|
+
const subscriptionDto = this.#mappers.SubscriptionDtoMapper.serializeEntityToDto(
|
|
560
|
+
subscription
|
|
561
|
+
);
|
|
562
|
+
return subscriptionDto;
|
|
563
|
+
})
|
|
564
|
+
);
|
|
565
|
+
}
|
|
566
|
+
async cancelSubscription(idDto, em) {
|
|
567
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
568
|
+
this.openTelemetryCollector.info("Canceling subscription", idDto);
|
|
569
|
+
}
|
|
570
|
+
const subscription = await (em ?? this.em).findOne("Subscription", idDto);
|
|
571
|
+
if (!subscription) {
|
|
572
|
+
throw new Error("Subscription not found");
|
|
573
|
+
}
|
|
574
|
+
subscription.active = false;
|
|
575
|
+
await (em ?? this.em).transactional(async (innerEm) => {
|
|
576
|
+
await innerEm.persist(subscription);
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
async resumeSubscription(idDto, em) {
|
|
580
|
+
if (this.evaluatedTelemetryOptions.logging) {
|
|
581
|
+
this.openTelemetryCollector.info("Resuming subscription", idDto);
|
|
582
|
+
}
|
|
583
|
+
const subscription = await (em ?? this.em).findOne("Subscription", idDto);
|
|
584
|
+
if (!subscription) {
|
|
585
|
+
throw new Error("Subscription not found");
|
|
586
|
+
}
|
|
587
|
+
subscription.active = true;
|
|
588
|
+
await (em ?? this.em).transactional(async (innerEm) => {
|
|
589
|
+
await innerEm.persist(subscription);
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
};
|
|
593
|
+
export {
|
|
594
|
+
BaseBillingPortalService,
|
|
595
|
+
BaseCheckoutSessionService,
|
|
596
|
+
BasePaymentLinkService,
|
|
597
|
+
BasePlanService,
|
|
598
|
+
BaseSubscriptionService
|
|
599
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forklaunch/implementation-billing-base",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Billing basic implementation for forklaunch",
|
|
5
5
|
"homepage": "https://github.com/forklaunch/forklaunch-js#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -29,21 +29,22 @@
|
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@forklaunch/common": "^0.3.11",
|
|
32
|
-
"@forklaunch/core": "^0.9.
|
|
33
|
-
"@forklaunch/validator": "^0.6.
|
|
32
|
+
"@forklaunch/core": "^0.9.13",
|
|
33
|
+
"@forklaunch/validator": "^0.6.12",
|
|
34
34
|
"@mikro-orm/core": "^6.4.16",
|
|
35
35
|
"@sinclair/typebox": "^0.34.33",
|
|
36
36
|
"ajv": "^8.17.1",
|
|
37
37
|
"zod": "^3.25.62",
|
|
38
|
-
"@forklaunch/interfaces-billing": "0.
|
|
38
|
+
"@forklaunch/interfaces-billing": "0.3.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
+
"@typescript/native-preview": "7.0.0-dev.20250611.1",
|
|
41
42
|
"depcheck": "^1.4.7",
|
|
42
43
|
"prettier": "^3.5.3",
|
|
43
44
|
"typedoc": "^0.28.5"
|
|
44
45
|
},
|
|
45
46
|
"scripts": {
|
|
46
|
-
"build": "tsc && if [ -f eject-package.bash ]; then pnpm package:eject; fi",
|
|
47
|
+
"build": "tsc --noEmit && tsup schemas/index.ts services/index.ts --format cjs,esm --no-splitting --dts --tsconfig tsconfig.json --out-dir lib --clean && if [ -f eject-package.bash ]; then pnpm package:eject; fi",
|
|
47
48
|
"clean": "rm -rf lib pnpm.lock.yaml node_modules",
|
|
48
49
|
"docs": "typedoc --out docs *",
|
|
49
50
|
"format": "prettier --ignore-path=.prettierignore --config .prettierrc '**/*.{ts,tsx,json}' --write",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"schemaEquality.test.d.ts","sourceRoot":"","sources":["../../__test__/schemaEquality.test.ts"],"names":[],"mappings":""}
|