@intlayer/backend 3.1.0 → 3.2.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/dist/cjs/controllers/dictionary.controller.cjs +41 -0
- package/dist/cjs/controllers/dictionary.controller.cjs.map +1 -1
- package/dist/cjs/controllers/organization.controller.cjs +73 -4
- package/dist/cjs/controllers/organization.controller.cjs.map +1 -1
- package/dist/cjs/controllers/project.controller.cjs +71 -7
- package/dist/cjs/controllers/project.controller.cjs.map +1 -1
- package/dist/cjs/controllers/projectAccessKey.controller.cjs +31 -0
- package/dist/cjs/controllers/projectAccessKey.controller.cjs.map +1 -1
- package/dist/cjs/controllers/sessionAuth.controller.cjs +277 -57
- package/dist/cjs/controllers/sessionAuth.controller.cjs.map +1 -1
- package/dist/cjs/controllers/stripe.controller.cjs +84 -0
- package/dist/cjs/controllers/stripe.controller.cjs.map +1 -0
- package/dist/cjs/controllers/user.controller.cjs +40 -3
- package/dist/cjs/controllers/user.controller.cjs.map +1 -1
- package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs +182 -0
- package/dist/cjs/emails/SubscriptionPaymentCancellation.cjs.map +1 -0
- package/dist/cjs/emails/SubscriptionPaymentError.cjs +182 -0
- package/dist/cjs/emails/SubscriptionPaymentError.cjs.map +1 -0
- package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs +188 -0
- package/dist/cjs/emails/SubscriptionPaymentSuccess.cjs.map +1 -0
- package/dist/cjs/export.cjs.map +1 -1
- package/dist/cjs/index.cjs +15 -5
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs +4 -6
- package/dist/cjs/middlewares/sessionAuth.middleware.cjs.map +1 -1
- package/dist/cjs/routes/dictionary.routes.cjs +2 -62
- package/dist/cjs/routes/dictionary.routes.cjs.map +1 -1
- package/dist/cjs/routes/organization.routes.cjs +1 -25
- package/dist/cjs/routes/organization.routes.cjs.map +1 -1
- package/dist/cjs/routes/project.routes.cjs +10 -85
- package/dist/cjs/routes/project.routes.cjs.map +1 -1
- package/dist/cjs/routes/sessionAuth.routes.cjs +26 -25
- package/dist/cjs/routes/sessionAuth.routes.cjs.map +1 -1
- package/dist/cjs/{models/plan.moddel.cjs → routes/stripe.routes.cjs} +20 -9
- package/dist/cjs/routes/stripe.routes.cjs.map +1 -0
- package/dist/cjs/routes/user.routes.cjs +6 -27
- package/dist/cjs/routes/user.routes.cjs.map +1 -1
- package/dist/cjs/schemas/organization.schema.cjs +5 -0
- package/dist/cjs/schemas/organization.schema.cjs.map +1 -1
- package/dist/cjs/schemas/plans.schema.cjs +2 -8
- package/dist/cjs/schemas/plans.schema.cjs.map +1 -1
- package/dist/cjs/schemas/user.schema.cjs +1 -1
- package/dist/cjs/schemas/user.schema.cjs.map +1 -1
- package/dist/cjs/services/email.service.cjs +113 -43
- package/dist/cjs/services/email.service.cjs.map +1 -1
- package/dist/cjs/services/organization.service.cjs +55 -8
- package/dist/cjs/services/organization.service.cjs.map +1 -1
- package/dist/cjs/services/project.service.cjs +1 -3
- package/dist/cjs/services/project.service.cjs.map +1 -1
- package/dist/cjs/services/sessionAuth.service.cjs +9 -11
- package/dist/cjs/services/sessionAuth.service.cjs.map +1 -1
- package/dist/cjs/services/subscription.service.cjs +134 -51
- package/dist/cjs/services/subscription.service.cjs.map +1 -1
- package/dist/cjs/services/user.service.cjs +1 -3
- package/dist/cjs/services/user.service.cjs.map +1 -1
- package/dist/cjs/types/organization.types.cjs.map +1 -1
- package/dist/cjs/types/plan.types.cjs.map +1 -1
- package/dist/cjs/types/session.types.cjs.map +1 -1
- package/dist/cjs/utils/errors/ErrorHandler.cjs +29 -9
- package/dist/cjs/utils/errors/ErrorHandler.cjs.map +1 -1
- package/dist/cjs/utils/errors/ErrorsClass.cjs +17 -3
- package/dist/cjs/utils/errors/ErrorsClass.cjs.map +1 -1
- package/dist/cjs/utils/errors/errorCodes.cjs +99 -8
- package/dist/cjs/utils/errors/errorCodes.cjs.map +1 -1
- package/dist/cjs/utils/mapper/project.cjs +1 -1
- package/dist/cjs/utils/mapper/project.cjs.map +1 -1
- package/dist/cjs/utils/plan.cjs +7 -2
- package/dist/cjs/utils/plan.cjs.map +1 -1
- package/dist/cjs/utils/responseData.cjs +8 -0
- package/dist/cjs/utils/responseData.cjs.map +1 -1
- package/dist/cjs/webhooks/stripe.webhook.cjs +133 -0
- package/dist/cjs/webhooks/stripe.webhook.cjs.map +1 -0
- package/dist/esm/controllers/dictionary.controller.mjs +41 -0
- package/dist/esm/controllers/dictionary.controller.mjs.map +1 -1
- package/dist/esm/controllers/organization.controller.mjs +73 -4
- package/dist/esm/controllers/organization.controller.mjs.map +1 -1
- package/dist/esm/controllers/project.controller.mjs +71 -7
- package/dist/esm/controllers/project.controller.mjs.map +1 -1
- package/dist/esm/controllers/projectAccessKey.controller.mjs +31 -0
- package/dist/esm/controllers/projectAccessKey.controller.mjs.map +1 -1
- package/dist/esm/controllers/sessionAuth.controller.mjs +273 -56
- package/dist/esm/controllers/sessionAuth.controller.mjs.map +1 -1
- package/dist/esm/controllers/stripe.controller.mjs +60 -0
- package/dist/esm/controllers/stripe.controller.mjs.map +1 -0
- package/dist/esm/controllers/user.controller.mjs +40 -3
- package/dist/esm/controllers/user.controller.mjs.map +1 -1
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs +168 -0
- package/dist/esm/emails/SubscriptionPaymentCancellation.mjs.map +1 -0
- package/dist/esm/emails/SubscriptionPaymentError.mjs +168 -0
- package/dist/esm/emails/SubscriptionPaymentError.mjs.map +1 -0
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs +174 -0
- package/dist/esm/emails/SubscriptionPaymentSuccess.mjs.map +1 -0
- package/dist/esm/export.mjs.map +1 -1
- package/dist/esm/index.mjs +15 -5
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/middlewares/sessionAuth.middleware.mjs +4 -6
- package/dist/esm/middlewares/sessionAuth.middleware.mjs.map +1 -1
- package/dist/esm/routes/dictionary.routes.mjs +2 -62
- package/dist/esm/routes/dictionary.routes.mjs.map +1 -1
- package/dist/esm/routes/organization.routes.mjs +1 -25
- package/dist/esm/routes/organization.routes.mjs.map +1 -1
- package/dist/esm/routes/project.routes.mjs +10 -85
- package/dist/esm/routes/project.routes.mjs.map +1 -1
- package/dist/esm/routes/sessionAuth.routes.mjs +29 -26
- package/dist/esm/routes/sessionAuth.routes.mjs.map +1 -1
- package/dist/esm/routes/stripe.routes.mjs +17 -0
- package/dist/esm/routes/stripe.routes.mjs.map +1 -0
- package/dist/esm/routes/user.routes.mjs +6 -27
- package/dist/esm/routes/user.routes.mjs.map +1 -1
- package/dist/esm/schemas/organization.schema.mjs +5 -0
- package/dist/esm/schemas/organization.schema.mjs.map +1 -1
- package/dist/esm/schemas/plans.schema.mjs +2 -8
- package/dist/esm/schemas/plans.schema.mjs.map +1 -1
- package/dist/esm/schemas/user.schema.mjs +1 -1
- package/dist/esm/schemas/user.schema.mjs.map +1 -1
- package/dist/esm/services/email.service.mjs +125 -43
- package/dist/esm/services/email.service.mjs.map +1 -1
- package/dist/esm/services/organization.service.mjs +51 -7
- package/dist/esm/services/organization.service.mjs.map +1 -1
- package/dist/esm/services/project.service.mjs +1 -3
- package/dist/esm/services/project.service.mjs.map +1 -1
- package/dist/esm/services/sessionAuth.service.mjs +9 -10
- package/dist/esm/services/sessionAuth.service.mjs.map +1 -1
- package/dist/esm/services/subscription.service.mjs +136 -53
- package/dist/esm/services/subscription.service.mjs.map +1 -1
- package/dist/esm/services/user.service.mjs +1 -3
- package/dist/esm/services/user.service.mjs.map +1 -1
- package/dist/esm/utils/errors/ErrorHandler.mjs +29 -9
- package/dist/esm/utils/errors/ErrorHandler.mjs.map +1 -1
- package/dist/esm/utils/errors/ErrorsClass.mjs +17 -3
- package/dist/esm/utils/errors/ErrorsClass.mjs.map +1 -1
- package/dist/esm/utils/errors/errorCodes.mjs +99 -8
- package/dist/esm/utils/errors/errorCodes.mjs.map +1 -1
- package/dist/esm/utils/mapper/project.mjs +1 -1
- package/dist/esm/utils/mapper/project.mjs.map +1 -1
- package/dist/esm/utils/plan.mjs +7 -2
- package/dist/esm/utils/plan.mjs.map +1 -1
- package/dist/esm/utils/responseData.mjs +8 -0
- package/dist/esm/utils/responseData.mjs.map +1 -1
- package/dist/esm/webhooks/stripe.webhook.mjs +113 -0
- package/dist/esm/webhooks/stripe.webhook.mjs.map +1 -0
- package/dist/types/controllers/dictionary.controller.d.ts.map +1 -1
- package/dist/types/controllers/organization.controller.d.ts.map +1 -1
- package/dist/types/controllers/project.controller.d.ts.map +1 -1
- package/dist/types/controllers/projectAccessKey.controller.d.ts.map +1 -1
- package/dist/types/controllers/sessionAuth.controller.d.ts +24 -5
- package/dist/types/controllers/sessionAuth.controller.d.ts.map +1 -1
- package/dist/types/controllers/stripe.controller.d.ts +17 -0
- package/dist/types/controllers/stripe.controller.d.ts.map +1 -0
- package/dist/types/controllers/user.controller.d.ts.map +1 -1
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts +20 -0
- package/dist/types/emails/SubscriptionPaymentCancellation.d.ts.map +1 -0
- package/dist/types/emails/SubscriptionPaymentError.d.ts +20 -0
- package/dist/types/emails/SubscriptionPaymentError.d.ts.map +1 -0
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts +20 -0
- package/dist/types/emails/SubscriptionPaymentSuccess.d.ts.map +1 -0
- package/dist/types/export.d.ts +1 -0
- package/dist/types/export.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/middlewares/sessionAuth.middleware.d.ts.map +1 -1
- package/dist/types/models/organization.model.d.ts +1 -0
- package/dist/types/models/organization.model.d.ts.map +1 -1
- package/dist/types/routes/dictionary.routes.d.ts.map +1 -1
- package/dist/types/routes/organization.routes.d.ts.map +1 -1
- package/dist/types/routes/project.routes.d.ts.map +1 -1
- package/dist/types/routes/sessionAuth.routes.d.ts +15 -2
- package/dist/types/routes/sessionAuth.routes.d.ts.map +1 -1
- package/dist/types/routes/stripe.routes.d.ts +10 -0
- package/dist/types/routes/stripe.routes.d.ts.map +1 -0
- package/dist/types/routes/user.routes.d.ts.map +1 -1
- package/dist/types/schemas/organization.schema.d.ts +1 -0
- package/dist/types/schemas/organization.schema.d.ts.map +1 -1
- package/dist/types/schemas/plans.schema.d.ts.map +1 -1
- package/dist/types/services/email.service.d.ts +33 -4
- package/dist/types/services/email.service.d.ts.map +1 -1
- package/dist/types/services/organization.service.d.ts +15 -0
- package/dist/types/services/organization.service.d.ts.map +1 -1
- package/dist/types/services/project.service.d.ts.map +1 -1
- package/dist/types/services/sessionAuth.service.d.ts +1 -8
- package/dist/types/services/sessionAuth.service.d.ts.map +1 -1
- package/dist/types/services/subscription.service.d.ts +20 -5
- package/dist/types/services/subscription.service.d.ts.map +1 -1
- package/dist/types/services/user.service.d.ts.map +1 -1
- package/dist/types/types/organization.types.d.ts +2 -0
- package/dist/types/types/organization.types.d.ts.map +1 -1
- package/dist/types/types/plan.types.d.ts +2 -3
- package/dist/types/types/plan.types.d.ts.map +1 -1
- package/dist/types/types/session.types.d.ts +6 -6
- package/dist/types/types/session.types.d.ts.map +1 -1
- package/dist/types/utils/errors/ErrorHandler.d.ts +5 -3
- package/dist/types/utils/errors/ErrorHandler.d.ts.map +1 -1
- package/dist/types/utils/errors/ErrorsClass.d.ts +4 -1
- package/dist/types/utils/errors/ErrorsClass.d.ts.map +1 -1
- package/dist/types/utils/errors/errorCodes.d.ts +92 -1
- package/dist/types/utils/errors/errorCodes.d.ts.map +1 -1
- package/dist/types/utils/mapper/project.d.ts +1 -1
- package/dist/types/utils/mapper/project.d.ts.map +1 -1
- package/dist/types/utils/plan.d.ts +1 -1
- package/dist/types/utils/plan.d.ts.map +1 -1
- package/dist/types/utils/responseData.d.ts +13 -2
- package/dist/types/utils/responseData.d.ts.map +1 -1
- package/dist/types/webhooks/stripe.d.ts.map +1 -1
- package/dist/types/webhooks/stripe.webhook.d.ts +3 -0
- package/dist/types/webhooks/stripe.webhook.d.ts.map +1 -0
- package/package.json +6 -5
- package/dist/cjs/models/plan.moddel.cjs.map +0 -1
- package/dist/cjs/services/plans.service.cjs +0 -72
- package/dist/cjs/services/plans.service.cjs.map +0 -1
- package/dist/cjs/webhooks/stripe.cjs +0 -94
- package/dist/cjs/webhooks/stripe.cjs.map +0 -1
- package/dist/esm/models/plan.moddel.mjs +0 -7
- package/dist/esm/models/plan.moddel.mjs.map +0 -1
- package/dist/esm/services/plans.service.mjs +0 -44
- package/dist/esm/services/plans.service.mjs.map +0 -1
- package/dist/esm/webhooks/stripe.mjs +0 -70
- package/dist/esm/webhooks/stripe.mjs.map +0 -1
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { logger } from './../logger/index.mjs';
|
|
2
2
|
import { GenericError } from './../utils/errors/index.mjs';
|
|
3
3
|
import { retrievePlanInformation } from './../utils/plan.mjs';
|
|
4
|
+
import { Locales } from "intlayer";
|
|
5
|
+
import { Stripe } from "stripe";
|
|
6
|
+
import { sendEmail } from './email.service.mjs';
|
|
4
7
|
import {
|
|
5
|
-
|
|
6
|
-
|
|
8
|
+
getOrganizationByCustomerId,
|
|
9
|
+
updatePlan
|
|
7
10
|
} from './organization.service.mjs';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
const addSubscription = async (priceId, customerId, email, organizationId) => {
|
|
11
|
+
import { getUserByEmail, createUser, getUserById } from './user.service.mjs';
|
|
12
|
+
const addSubscription = async (priceId, customerId, email, locale = Locales.ENGLISH) => {
|
|
11
13
|
let user = await getUserByEmail(email);
|
|
14
|
+
const organization = await getOrganizationByCustomerId(customerId);
|
|
15
|
+
if (!organization) {
|
|
16
|
+
throw new GenericError("ORGANIZATION_NOT_FOUND", {
|
|
17
|
+
customerId
|
|
18
|
+
});
|
|
19
|
+
}
|
|
12
20
|
if (!user) {
|
|
13
21
|
user = await createUser({
|
|
14
22
|
email
|
|
@@ -23,73 +31,148 @@ const addSubscription = async (priceId, customerId, email, organizationId) => {
|
|
|
23
31
|
user.customerId = customerId;
|
|
24
32
|
await user.save();
|
|
25
33
|
}
|
|
26
|
-
let organization = null;
|
|
27
|
-
if (organizationId) {
|
|
28
|
-
organization = await getOrganizationById(organizationId);
|
|
29
|
-
}
|
|
30
|
-
const organizations = await getOrganizationsByOwner(user._id);
|
|
31
|
-
if (organizations && organizations.length === 1) {
|
|
32
|
-
organization = organizations[0];
|
|
33
|
-
}
|
|
34
34
|
const planType = retrievePlanInformation(priceId);
|
|
35
|
-
if (
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
let plan = await getPlan({
|
|
41
|
-
organizationId: organization._id
|
|
42
|
-
});
|
|
43
|
-
if (plan) {
|
|
44
|
-
plan.type = planType.type;
|
|
45
|
-
plan.period = planType.period;
|
|
46
|
-
plan.status = "ACTIVE";
|
|
47
|
-
await plan.save();
|
|
48
|
-
logger.info(
|
|
49
|
-
`Updated plan for organization ${organization._id} - ${planType.type} - ${planType.period}`
|
|
50
|
-
);
|
|
51
|
-
} else {
|
|
52
|
-
plan = await createNewPlan({
|
|
53
|
-
userId: user._id,
|
|
54
|
-
organizationId: organization._id,
|
|
35
|
+
if (organization.plan) {
|
|
36
|
+
await cancelSubscription(organization.plan.customerId);
|
|
37
|
+
const editedOrganization2 = await updatePlan(organization, {
|
|
38
|
+
...organization.plan,
|
|
39
|
+
creatorId: user._id,
|
|
55
40
|
priceId,
|
|
56
41
|
type: planType.type,
|
|
57
42
|
period: planType.period,
|
|
58
43
|
status: "ACTIVE"
|
|
59
44
|
});
|
|
45
|
+
if (!editedOrganization2) {
|
|
46
|
+
throw new GenericError("ORGANIZATION_UPDATE_FAILED", {
|
|
47
|
+
organizationId: organization._id
|
|
48
|
+
});
|
|
49
|
+
}
|
|
60
50
|
logger.info(
|
|
61
|
-
`
|
|
51
|
+
`Updated plan for organization ${organization._id} - ${planType.type} - ${planType.period}`
|
|
62
52
|
);
|
|
53
|
+
return editedOrganization2.plan;
|
|
54
|
+
}
|
|
55
|
+
const editedOrganization = await updatePlan(organization, {
|
|
56
|
+
creatorId: user._id,
|
|
57
|
+
priceId,
|
|
58
|
+
type: planType.type,
|
|
59
|
+
period: planType.period,
|
|
60
|
+
status: "ACTIVE"
|
|
61
|
+
});
|
|
62
|
+
if (!editedOrganization) {
|
|
63
|
+
throw new GenericError("ORGANIZATION_UPDATE_FAILED", {
|
|
64
|
+
organizationId: organization._id
|
|
65
|
+
});
|
|
63
66
|
}
|
|
64
|
-
|
|
67
|
+
const { type } = retrievePlanInformation(priceId);
|
|
68
|
+
await sendEmail({
|
|
69
|
+
type: "subscriptionPaymentSuccess",
|
|
70
|
+
to: user.email,
|
|
71
|
+
username: user.name,
|
|
72
|
+
planName: type,
|
|
73
|
+
subscriptionStartDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
|
|
74
|
+
email,
|
|
75
|
+
manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`,
|
|
76
|
+
locale
|
|
77
|
+
});
|
|
78
|
+
logger.info(
|
|
79
|
+
`Created plan for organization ${organization._id} - ${planType.type} - ${planType.period}`
|
|
80
|
+
);
|
|
81
|
+
return editedOrganization.plan;
|
|
65
82
|
};
|
|
66
|
-
const
|
|
67
|
-
const
|
|
68
|
-
|
|
83
|
+
const getActiveSubscriptions = async (customerId) => {
|
|
84
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
85
|
+
const subscriptions = await stripe.subscriptions.list({
|
|
86
|
+
customer: customerId,
|
|
87
|
+
status: "active"
|
|
69
88
|
});
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
89
|
+
return subscriptions.data;
|
|
90
|
+
};
|
|
91
|
+
const cancelSubscription = async (customerId) => {
|
|
92
|
+
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
93
|
+
const organization = await getOrganizationByCustomerId(customerId);
|
|
94
|
+
if (!organization) {
|
|
95
|
+
throw new GenericError("ORGANIZATION_NOT_FOUND", {
|
|
96
|
+
customerId
|
|
73
97
|
});
|
|
74
98
|
}
|
|
75
|
-
plan
|
|
76
|
-
|
|
77
|
-
|
|
99
|
+
if (!organization.plan) {
|
|
100
|
+
throw new GenericError("ORGANIZATION_PLAN_NOT_FOUND", {
|
|
101
|
+
customerId
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const activeSubscriptions = await getActiveSubscriptions(customerId);
|
|
105
|
+
for (const sub of activeSubscriptions) {
|
|
106
|
+
await stripe.subscriptions.cancel(sub.id);
|
|
107
|
+
}
|
|
108
|
+
logger.info(
|
|
109
|
+
`Cancelled plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period}`
|
|
110
|
+
);
|
|
111
|
+
return organization.plan;
|
|
78
112
|
};
|
|
79
|
-
const
|
|
80
|
-
const
|
|
81
|
-
if (!
|
|
82
|
-
throw new GenericError("
|
|
83
|
-
|
|
113
|
+
const changeSubscriptionStatus = async (customerId, status, locale = Locales.ENGLISH) => {
|
|
114
|
+
const organization = await getOrganizationByCustomerId(customerId);
|
|
115
|
+
if (!organization) {
|
|
116
|
+
throw new GenericError("ORGANIZATION_NOT_FOUND", {
|
|
117
|
+
customerId
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (!organization.plan) {
|
|
121
|
+
throw new GenericError("ORGANIZATION_PLAN_NOT_FOUND", {
|
|
122
|
+
customerId
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
const editedOrganization = await updatePlan(organization, {
|
|
126
|
+
status
|
|
127
|
+
});
|
|
128
|
+
if (!editedOrganization) {
|
|
129
|
+
throw new GenericError("ORGANIZATION_UPDATE_FAILED", {
|
|
130
|
+
organizationId: organization._id
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
const user = await getUserById(organization.plan.creatorId);
|
|
134
|
+
logger.info(
|
|
135
|
+
`Updated plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period} - ${status}`
|
|
136
|
+
);
|
|
137
|
+
if (status === "ACTIVE") {
|
|
138
|
+
await sendEmail({
|
|
139
|
+
type: "subscriptionPaymentSuccess",
|
|
140
|
+
to: user.email,
|
|
141
|
+
username: user.name,
|
|
142
|
+
email: user.email,
|
|
143
|
+
planName: organization.plan.type,
|
|
144
|
+
subscriptionStartDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
|
|
145
|
+
manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`,
|
|
146
|
+
locale
|
|
147
|
+
});
|
|
148
|
+
} else if (status === "CANCELLED") {
|
|
149
|
+
await sendEmail({
|
|
150
|
+
type: "subscriptionPaymentCancellation",
|
|
151
|
+
to: user.email,
|
|
152
|
+
username: user.name,
|
|
153
|
+
email: user.email,
|
|
154
|
+
planName: organization.plan.type,
|
|
155
|
+
cancellationDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
|
|
156
|
+
reactivateLink: `${process.env.CLIENT_URL}/dashboard`,
|
|
157
|
+
locale
|
|
158
|
+
});
|
|
159
|
+
} else if (status === "ERROR") {
|
|
160
|
+
await sendEmail({
|
|
161
|
+
type: "subscriptionPaymentError",
|
|
162
|
+
to: user.email,
|
|
163
|
+
username: user.name,
|
|
164
|
+
email: user.email,
|
|
165
|
+
planName: organization.plan.type,
|
|
166
|
+
errorDate: (/* @__PURE__ */ new Date()).toLocaleDateString(),
|
|
167
|
+
retryPaymentLink: `${process.env.CLIENT_URL}/dashboard`,
|
|
168
|
+
locale
|
|
84
169
|
});
|
|
85
170
|
}
|
|
86
|
-
plan
|
|
87
|
-
await plan.save();
|
|
88
|
-
return plan;
|
|
171
|
+
return editedOrganization.plan;
|
|
89
172
|
};
|
|
90
173
|
export {
|
|
91
174
|
addSubscription,
|
|
92
175
|
cancelSubscription,
|
|
93
|
-
|
|
176
|
+
changeSubscriptionStatus
|
|
94
177
|
};
|
|
95
178
|
//# sourceMappingURL=subscription.service.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/services/subscription.service.ts"],"sourcesContent":["import { logger } from '@logger';\nimport { GenericError } from '@utils/errors';\nimport { retrievePlanInformation } from '@utils/plan';\nimport { ObjectId } from 'mongoose';\nimport {\n getOrganizationById,\n getOrganizationsByOwner,\n} from './organization.service';\nimport { getPlan, createNewPlan, PlanSelector } from './plans.service';\nimport { getUserByEmail, createUser } from './user.service';\nimport { Organization } from '@/export';\nimport { Plan } from '@/types/plan.types';\n\nexport const addSubscription = async (\n priceId: string,\n customerId: string,\n email: string,\n organizationId?: string | ObjectId\n): Promise<Plan | null> => {\n let user = await getUserByEmail(email);\n\n if (!user) {\n user = await createUser({\n email,\n });\n }\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', {\n email,\n });\n }\n\n if (user.customerId !== customerId) {\n user.customerId = customerId as string;\n await user.save();\n }\n\n let organization: Organization | null = null;\n\n if (organizationId) {\n organization = await getOrganizationById(organizationId);\n }\n\n const organizations = await getOrganizationsByOwner(user._id);\n\n if (organizations && organizations.length === 1) {\n organization = organizations[0];\n }\n\n const planType = retrievePlanInformation(priceId!);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n organizationId,\n });\n }\n\n let plan = await getPlan({\n organizationId: organization._id,\n });\n\n if (plan) {\n plan.type = planType.type;\n plan.period = planType.period;\n plan.status = 'ACTIVE';\n await plan.save();\n\n logger.info(\n `Updated plan for organization ${organization._id} - ${planType.type} - ${planType.period}`\n );\n } else {\n plan = await createNewPlan({\n userId: user._id,\n organizationId: organization._id,\n priceId: priceId!,\n type: planType.type,\n period: planType.period,\n status: 'ACTIVE',\n });\n\n logger.info(\n `Created plan for organization ${organization._id} - ${planType.type} - ${planType.period}`\n );\n }\n\n return plan;\n};\n\nexport const cancelSubscription = async (\n organizationId: string | ObjectId\n): Promise<Plan | null> => {\n const plan = await getPlan({\n organizationId: organizationId as ObjectId,\n });\n\n if (!plan) {\n throw new GenericError('PLAN_NOT_FOUND', {\n organizationId,\n });\n }\n\n plan.status = 'CANCELLED';\n\n await plan.save();\n\n return plan;\n};\n\nexport const cancelUserSubscription = async (\n planData: PlanSelector\n): Promise<Plan | null> => {\n const plan = await getPlan(planData);\n\n if (!plan) {\n throw new GenericError('PLAN_NOT_FOUND', {\n planData,\n });\n }\n\n plan.status = 'CANCELLED';\n\n await plan.save();\n\n return plan;\n};\n"],"mappings":"AAAA,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAC7B,SAAS,+BAA+B;AAExC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP,SAAS,SAAS,qBAAmC;AACrD,SAAS,gBAAgB,kBAAkB;AAIpC,MAAM,kBAAkB,OAC7B,SACA,YACA,OACA,mBACyB;AACzB,MAAI,OAAO,MAAM,eAAe,KAAK;AAErC,MAAI,CAAC,MAAM;AACT,WAAO,MAAM,WAAW;AAAA,MACtB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,aAAa,kBAAkB;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,KAAK,eAAe,YAAY;AAClC,SAAK,aAAa;AAClB,UAAM,KAAK,KAAK;AAAA,EAClB;AAEA,MAAI,eAAoC;AAExC,MAAI,gBAAgB;AAClB,mBAAe,MAAM,oBAAoB,cAAc;AAAA,EACzD;AAEA,QAAM,gBAAgB,MAAM,wBAAwB,KAAK,GAAG;AAE5D,MAAI,iBAAiB,cAAc,WAAW,GAAG;AAC/C,mBAAe,cAAc,CAAC;AAAA,EAChC;AAEA,QAAM,WAAW,wBAAwB,OAAQ;AAEjD,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,aAAa,0BAA0B;AAAA,MAC/C;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,OAAO,MAAM,QAAQ;AAAA,IACvB,gBAAgB,aAAa;AAAA,EAC/B,CAAC;AAED,MAAI,MAAM;AACR,SAAK,OAAO,SAAS;AACrB,SAAK,SAAS,SAAS;AACvB,SAAK,SAAS;AACd,UAAM,KAAK,KAAK;AAEhB,WAAO;AAAA,MACL,iCAAiC,aAAa,GAAG,MAAM,SAAS,IAAI,MAAM,SAAS,MAAM;AAAA,IAC3F;AAAA,EACF,OAAO;AACL,WAAO,MAAM,cAAc;AAAA,MACzB,QAAQ,KAAK;AAAA,MACb,gBAAgB,aAAa;AAAA,MAC7B;AAAA,MACA,MAAM,SAAS;AAAA,MACf,QAAQ,SAAS;AAAA,MACjB,QAAQ;AAAA,IACV,CAAC;AAED,WAAO;AAAA,MACL,iCAAiC,aAAa,GAAG,MAAM,SAAS,IAAI,MAAM,SAAS,MAAM;AAAA,IAC3F;AAAA,EACF;AAEA,SAAO;AACT;AAEO,MAAM,qBAAqB,OAChC,mBACyB;AACzB,QAAM,OAAO,MAAM,QAAQ;AAAA,IACzB;AAAA,EACF,CAAC;AAED,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,aAAa,kBAAkB;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,OAAK,SAAS;AAEd,QAAM,KAAK,KAAK;AAEhB,SAAO;AACT;AAEO,MAAM,yBAAyB,OACpC,aACyB;AACzB,QAAM,OAAO,MAAM,QAAQ,QAAQ;AAEnC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,aAAa,kBAAkB;AAAA,MACvC;AAAA,IACF,CAAC;AAAA,EACH;AAEA,OAAK,SAAS;AAEd,QAAM,KAAK,KAAK;AAEhB,SAAO;AACT;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/services/subscription.service.ts"],"sourcesContent":["import { logger } from '@logger';\nimport { GenericError } from '@utils/errors';\nimport { retrievePlanInformation } from '@utils/plan';\nimport { Locales } from 'intlayer';\nimport { Stripe } from 'stripe';\nimport { sendEmail } from './email.service';\nimport {\n getOrganizationByCustomerId,\n updatePlan,\n} from './organization.service';\nimport { getUserByEmail, createUser, getUserById } from './user.service';\nimport { Plan } from '@/types/plan.types';\n\n/**\n * Adds a subscription to an organization.\n * @param priceId - The ID of the price to add.\n * @param customerId - The ID of the customer to add.\n * @param email - The email of the user to add.\n * @param locale - The locale of the user to add.\n * @returns The added plan.\n */\nexport const addSubscription = async (\n priceId: string,\n customerId: string,\n email: string,\n locale: Locales = Locales.ENGLISH\n): Promise<Plan | null> => {\n let user = await getUserByEmail(email);\n const organization = await getOrganizationByCustomerId(customerId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n customerId,\n });\n }\n\n if (!user) {\n user = await createUser({\n email,\n });\n }\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', {\n email,\n });\n }\n\n if (user.customerId !== customerId) {\n user.customerId = customerId as string;\n await user.save();\n }\n const planType = retrievePlanInformation(priceId!);\n\n if (organization.plan) {\n // Cancel the current plan\n await cancelSubscription(organization.plan.customerId!);\n\n const editedOrganization = await updatePlan(organization, {\n ...organization.plan,\n creatorId: user._id,\n priceId: priceId!,\n type: planType.type,\n period: planType.period,\n status: 'ACTIVE',\n });\n\n if (!editedOrganization) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization._id,\n });\n }\n\n logger.info(\n `Updated plan for organization ${organization._id} - ${planType.type} - ${planType.period}`\n );\n\n return editedOrganization.plan;\n }\n\n const editedOrganization = await updatePlan(organization, {\n creatorId: user._id,\n priceId: priceId!,\n type: planType.type,\n period: planType.period,\n status: 'ACTIVE',\n });\n\n if (!editedOrganization) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization._id,\n });\n }\n\n const { type } = retrievePlanInformation(priceId!);\n\n await sendEmail({\n type: 'subscriptionPaymentSuccess',\n to: user.email,\n username: user.name,\n planName: type,\n subscriptionStartDate: new Date().toLocaleDateString(),\n email,\n manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n\n logger.info(\n `Created plan for organization ${organization._id} - ${planType.type} - ${planType.period}`\n );\n\n return editedOrganization.plan;\n};\n\n/* Function to retrieve active subscriptions for a customer\n * Returns an array of Stripe.Subscription objects\n */\nconst getActiveSubscriptions = async (\n customerId: string\n): Promise<Stripe.Subscription[]> => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n\n const subscriptions = await stripe.subscriptions.list({\n customer: customerId,\n status: 'active',\n });\n return subscriptions.data;\n};\n\nexport const cancelSubscription = async (customerId: string) => {\n const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);\n const organization = await getOrganizationByCustomerId(customerId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n customerId,\n });\n }\n\n if (!organization.plan) {\n throw new GenericError('ORGANIZATION_PLAN_NOT_FOUND', {\n customerId,\n });\n }\n\n // Retrieve and cancel existing subscriptions\n const activeSubscriptions = await getActiveSubscriptions(customerId);\n for (const sub of activeSubscriptions) {\n await stripe.subscriptions.cancel(sub.id);\n }\n\n logger.info(\n `Cancelled plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period}`\n );\n\n return organization.plan;\n};\n\n/**\n * Changes the subscription status of an organization.\n *\n * @param customerId - The ID of the customer to change the subscription status for.\n * @param status - The new status of the subscription.\n * @param locale - The locale of the user to change the subscription status for.\n * @returns The updated plan.\n */\nexport const changeSubscriptionStatus = async (\n customerId: string,\n status: Plan['status'],\n locale: Locales = Locales.ENGLISH\n) => {\n const organization = await getOrganizationByCustomerId(customerId);\n\n if (!organization) {\n throw new GenericError('ORGANIZATION_NOT_FOUND', {\n customerId,\n });\n }\n\n if (!organization.plan) {\n throw new GenericError('ORGANIZATION_PLAN_NOT_FOUND', {\n customerId,\n });\n }\n\n const editedOrganization = await updatePlan(organization, {\n status,\n });\n\n if (!editedOrganization) {\n throw new GenericError('ORGANIZATION_UPDATE_FAILED', {\n organizationId: organization._id,\n });\n }\n\n const user = await getUserById(organization.plan.creatorId!);\n\n logger.info(\n `Updated plan for organization ${organization._id} - ${organization.plan.type} - ${organization.plan.period} - ${status}`\n );\n\n if (status === 'ACTIVE') {\n await sendEmail({\n type: 'subscriptionPaymentSuccess',\n to: user!.email,\n username: user!.name,\n email: user!.email,\n planName: organization.plan.type,\n subscriptionStartDate: new Date().toLocaleDateString(),\n manageSubscriptionLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n } else if (status === 'CANCELLED') {\n await sendEmail({\n type: 'subscriptionPaymentCancellation',\n to: user!.email,\n username: user!.name,\n email: user!.email,\n planName: organization.plan.type,\n cancellationDate: new Date().toLocaleDateString(),\n reactivateLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n } else if (status === 'ERROR') {\n await sendEmail({\n type: 'subscriptionPaymentError',\n to: user!.email,\n username: user!.name,\n email: user!.email,\n planName: organization.plan.type,\n errorDate: new Date().toLocaleDateString(),\n retryPaymentLink: `${process.env.CLIENT_URL}/dashboard`!,\n locale,\n });\n }\n\n return editedOrganization.plan;\n};\n"],"mappings":"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","names":["editedOrganization"]}
|
|
@@ -35,9 +35,7 @@ const checkUserExists = async (email) => {
|
|
|
35
35
|
const user = await UserModel.exists({ email });
|
|
36
36
|
return user !== null;
|
|
37
37
|
};
|
|
38
|
-
const getUserById = async (userId) =>
|
|
39
|
-
return await UserModel.findById(userId);
|
|
40
|
-
};
|
|
38
|
+
const getUserById = async (userId) => await UserModel.findById(userId);
|
|
41
39
|
const getUsersByIds = async (userIds) => {
|
|
42
40
|
return await UserModel.find({ _id: { $in: userIds } });
|
|
43
41
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/services/user.service.ts"],"sourcesContent":["import { UserModel } from '@models/user.model';\nimport { GenericError } from '@utils/errors';\nimport type { UserFilters } from '@utils/filtersAndPagination/getUserFiltersAndPagination';\nimport {\n type FieldsToCheck,\n type UserFields,\n validateUser,\n} from '@utils/validation/validateUser';\nimport type { ObjectId } from 'mongoose';\n// eslint-disable-next-line import/no-cycle\nimport { hashUserPassword } from './sessionAuth.service';\nimport type { SessionProviders } from '@/types/session.types';\nimport type {\n User,\n
|
|
1
|
+
{"version":3,"sources":["../../../src/services/user.service.ts"],"sourcesContent":["import { UserModel } from '@models/user.model';\nimport { GenericError } from '@utils/errors';\nimport type { UserFilters } from '@utils/filtersAndPagination/getUserFiltersAndPagination';\nimport {\n type FieldsToCheck,\n type UserFields,\n validateUser,\n} from '@utils/validation/validateUser';\nimport type { ObjectId } from 'mongoose';\n// eslint-disable-next-line import/no-cycle\nimport { hashUserPassword } from './sessionAuth.service';\nimport type { SessionProviders } from '@/types/session.types';\nimport type {\n User,\n UserDocument,\n UserWithPasswordNotHashed,\n} from '@/types/user.types';\n\n/**\n * Creates a new user with password in the database and hashes the password.\n * @param user - User object with password not hashed.\n * @returns Created user object.\n */\nexport const createUser = async (\n user: UserWithPasswordNotHashed\n): Promise<UserDocument> => {\n const fieldsToCheck: FieldsToCheck[] = ['email'];\n\n const errors = validateUser(user, fieldsToCheck);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('USER_INVALID_FIELDS', {\n userEmail: user.email,\n errors,\n });\n }\n\n let newUser: UserDocument;\n\n if (user.password) {\n const userWithHashedPassword = await hashUserPassword(user);\n\n newUser = await UserModel.create(userWithHashedPassword);\n } else {\n newUser = await UserModel.create(user);\n }\n\n if (!newUser) {\n throw new GenericError('USER_CREATION_FAILED', { userEmail: user.email });\n }\n\n return newUser;\n};\n\n/**\n * Retrieves a user by email.\n * @param email - User's email.\n * @returns User object or null if no user was found.\n */\nexport const getUserByEmail = async (\n email: string\n): Promise<UserDocument | null> => {\n return await UserModel.findOne({ email });\n};\n\n/**\n * Retrieves users list by email.\n * @param emails - Users email.\n * @returns User object or null if no user was found.\n */\nexport const getUsersByEmails = async (\n emails: string[]\n): Promise<UserDocument[] | null> => {\n return await UserModel.find({ email: { $in: emails } });\n};\n\n/**\n * Checks if a user exists by email.\n * @param email - User's email.\n * @returns True if the user exists, false otherwise.\n */\nexport const checkUserExists = async (email: string): Promise<boolean> => {\n const user = await UserModel.exists({ email });\n return user !== null;\n};\n\n/**\n * Retrieves a user by ID.\n * @param userId - User's ID.\n * @returns User object or null if no user was found.\n */\nexport const getUserById = async (\n userId: string | ObjectId\n): Promise<UserDocument | null> => await UserModel.findById(userId);\n\n/**\n * Retrieves a user by ID.\n * @param userId - User's ID.\n * @returns User object or null if no user was found.\n */\nexport const getUsersByIds = async (\n userIds: (string | ObjectId)[]\n): Promise<UserDocument[] | null> => {\n return await UserModel.find({ _id: { $in: userIds } });\n};\n\n/**\n * Retrieves a user by session token.\n * @param sessionToken - The session token.\n * @returns User object or null if no user was found.\n */\nexport const getUserBySession = async (\n sessionToken: string\n): Promise<UserDocument> => {\n // Get an user by session token and check if it expired\n const user = await UserModel.findOne({\n 'session.sessionToken': sessionToken,\n });\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { sessionToken });\n }\n\n if (user.session?.expires && user.session.expires < new Date()) {\n throw new GenericError('USER_SESSION_EXPIRED', {\n sessionToken,\n userId: user.id,\n });\n }\n\n return user;\n};\n\n/**\n * Retrieves a user by account.\n * @param provider - The provider of the account.\n * @param providerAccountId - The provider account ID.\n * @returns User object or null if no user was found.\n */\nexport const getUserByAccount = async (\n provider: SessionProviders['provider'],\n providerAccountId: string\n): Promise<UserDocument> => {\n const user = await UserModel.findOne({\n provider: [{ provider, providerAccountId }],\n });\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', {\n provider,\n providerAccountId,\n });\n }\n\n return user;\n};\n\n/**\n * Finds users based on filters and pagination options.\n * @param filters - MongoDB filter query.\n * @param skip - Number of documents to skip.\n * @param limit - Number of documents to limit.\n * @returns List of users matching the filters.\n */\nexport const findUsers = async (\n filters: UserFilters,\n skip: number,\n limit: number\n): Promise<UserDocument[]> => {\n return await UserModel.find(filters).skip(skip).limit(limit);\n};\n\n/**\n * Counts the total number of users that match the filters.\n * @param filters - MongoDB filter query.\n * @returns Total number of users.\n */\nexport const countUsers = async (filters: UserFilters): Promise<number> => {\n const count = await UserModel.countDocuments(filters);\n\n if (typeof count === 'undefined') {\n throw new GenericError('USER_COUNT_FAILED');\n }\n\n return count;\n};\n\n/**\n * Updates a user's information.\n * @param user - The user object.\n * @param updates - The updates to apply to the user.\n * @returns The updated user.\n */\nexport const updateUserById = async (\n userId: string | ObjectId,\n updates: Partial<User>\n): Promise<UserDocument> => {\n const keyToValidate = Object.keys(updates) as UserFields;\n const errors = validateUser(updates, keyToValidate);\n\n if (Object.keys(errors).length > 0) {\n throw new GenericError('USER_INVALID_FIELDS', {\n userId,\n errors,\n });\n }\n\n const result = await UserModel.updateOne({ _id: userId }, { $set: updates });\n\n if (result.matchedCount === 0) {\n throw new GenericError('USER_UPDATE_FAILED', { userId });\n }\n\n const updatedUser = await UserModel.findById(userId);\n\n if (!updatedUser) {\n throw new GenericError('USER_UPDATED_USER_NOT_FOUND', { userId });\n }\n\n return updatedUser;\n};\n\n/**\n * Deletes a user from the database.\n * @param userId - The user object.\n * @returns\n */\nexport const deleteUser = async (\n userId: string | ObjectId\n): Promise<UserDocument> => {\n await getUserById(userId);\n\n const user = await UserModel.findByIdAndDelete(userId);\n\n if (!user) {\n throw new GenericError('USER_NOT_FOUND', { userId });\n }\n\n return user;\n};\n"],"mappings":"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","names":[]}
|
|
@@ -3,6 +3,7 @@ import { formatPaginatedResponse, formatResponse } from './../../utils/responseD
|
|
|
3
3
|
import { t } from "express-intlayer";
|
|
4
4
|
import { errorData } from './errorCodes.mjs';
|
|
5
5
|
import { HttpStatusCodes } from './../../export.mjs';
|
|
6
|
+
import { Locales } from "intlayer";
|
|
6
7
|
class ErrorHandler {
|
|
7
8
|
/**
|
|
8
9
|
* Handles generic error responses by formatting and sending a JSON response.
|
|
@@ -17,6 +18,7 @@ class ErrorHandler {
|
|
|
17
18
|
this.handleCustomErrorResponse(
|
|
18
19
|
res,
|
|
19
20
|
errorKey,
|
|
21
|
+
error.title,
|
|
20
22
|
error.message,
|
|
21
23
|
errorDetails,
|
|
22
24
|
status,
|
|
@@ -27,15 +29,28 @@ class ErrorHandler {
|
|
|
27
29
|
* Handles application-specific error responses by formatting and sending a JSON response.
|
|
28
30
|
* @param res - The response object provided by Express.js.
|
|
29
31
|
* @param error - The error object.
|
|
30
|
-
* @param
|
|
32
|
+
* @param messageDetails - (Optional) Additional message details to include in the response.
|
|
33
|
+
* @param isPaginatedResponse - (Optional) Flag to determine if the response should be paginated.
|
|
31
34
|
*/
|
|
32
|
-
static handleAppErrorResponse(res, error,
|
|
35
|
+
static handleAppErrorResponse(res, error, messageDetails, isPaginatedResponse = false) {
|
|
36
|
+
if (!error.isAppError) {
|
|
37
|
+
this.handleCustomErrorResponse(
|
|
38
|
+
res,
|
|
39
|
+
error.errorKey ?? "UNKNOWN_ERROR",
|
|
40
|
+
"Error",
|
|
41
|
+
error.message ?? JSON.stringify(error),
|
|
42
|
+
void 0,
|
|
43
|
+
error.httpStatusCode ?? HttpStatusCodes.INTERNAL_SERVER_ERROR_500,
|
|
44
|
+
isPaginatedResponse
|
|
45
|
+
);
|
|
46
|
+
}
|
|
33
47
|
const isMultilingual = error.isMultilingual ?? false;
|
|
34
48
|
this.handleCustomErrorResponse(
|
|
35
49
|
res,
|
|
36
50
|
error.errorKey,
|
|
37
|
-
isMultilingual ? error.
|
|
38
|
-
|
|
51
|
+
isMultilingual ? error.multilingualTitle : error.title,
|
|
52
|
+
isMultilingual ? error.multilingualMessage : error.multilingualMessage,
|
|
53
|
+
error.messageDetails ?? messageDetails,
|
|
39
54
|
error.httpStatusCode,
|
|
40
55
|
isPaginatedResponse
|
|
41
56
|
);
|
|
@@ -45,17 +60,21 @@ class ErrorHandler {
|
|
|
45
60
|
* @param res - The response object.
|
|
46
61
|
* @param errorKey - Error code key used to fetch the corresponding message and default status.
|
|
47
62
|
* @param message - The localized error message object.
|
|
63
|
+
* @param messageDetails - (Optional) Additional message details to include in the response.
|
|
48
64
|
* @param statusCode - (Optional) HTTP status code, defaults to 500 if not specified.
|
|
49
65
|
* @param isPaginatedResponse - Determines if the error should be part of a paginated response.
|
|
50
66
|
*/
|
|
51
|
-
static handleCustomErrorResponse(res, errorKey, message,
|
|
52
|
-
|
|
67
|
+
static handleCustomErrorResponse(res, errorKey, title, message, messageDetails, statusCode, isPaginatedResponse = false) {
|
|
68
|
+
const errorTitle = t(title, Locales.ENGLISH);
|
|
69
|
+
const errorMessage = t(message, Locales.ENGLISH);
|
|
70
|
+
logger.error(errorMessage, messageDetails);
|
|
53
71
|
const status = statusCode ?? HttpStatusCodes.INTERNAL_SERVER_ERROR_500;
|
|
54
72
|
if (isPaginatedResponse) {
|
|
55
73
|
const responseData2 = formatPaginatedResponse({
|
|
56
74
|
error: {
|
|
57
75
|
code: errorKey,
|
|
58
|
-
|
|
76
|
+
title: errorTitle,
|
|
77
|
+
message: errorMessage
|
|
59
78
|
},
|
|
60
79
|
status
|
|
61
80
|
});
|
|
@@ -65,8 +84,9 @@ class ErrorHandler {
|
|
|
65
84
|
const responseData = formatResponse({
|
|
66
85
|
error: {
|
|
67
86
|
code: errorKey,
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
title: errorTitle,
|
|
88
|
+
message: errorMessage,
|
|
89
|
+
...messageDetails
|
|
70
90
|
},
|
|
71
91
|
status
|
|
72
92
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/errors/ErrorHandler.ts"],"sourcesContent":["// Import required modules and types from their respective locations.\nimport { logger } from '@logger';\nimport { formatPaginatedResponse, formatResponse } from '@utils/responseData';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t, LanguageContent } from 'express-intlayer';\nimport { ErrorCodes, errorData } from './errorCodes';\nimport { AppError } from './ErrorsClass';\nimport { HttpStatusCodes, UserAPI } from '@/export';\n\n// Define a class named 'ErrorHandler' to encapsulate error handling logic.\nexport class ErrorHandler {\n /**\n * Handles generic error responses by formatting and sending a JSON response.\n * @param res - The response object provided by Express.js.\n * @param errorKey - A key representing the specific error.\n * @param statusCode - (Optional) A specific HTTP status code to use for the response.\n * @param isPaginatedResponse - Flag to determine if the response should be paginated.\n */\n static handleGenericErrorResponse(\n res: Response,\n errorKey: ErrorCodes,\n errorDetails?: object,\n statusCode?: HttpStatusCodes,\n isPaginatedResponse: boolean = false\n ) {\n const error = errorData[errorKey];\n const status = statusCode ?? error.statusCode; // Use the provided status code or default to the one in errorData.\n\n // Delegate to a more customizable error response handler.\n this.handleCustomErrorResponse(\n res,\n errorKey,\n error.message,\n errorDetails,\n status,\n isPaginatedResponse\n );\n }\n\n /**\n * Handles application-specific error responses by formatting and sending a JSON response.\n * @param res - The response object provided by Express.js.\n * @param error - The error object.\n * @param isPaginatedResponse - Flag to determine if the response should be paginated.\n */\n static handleAppErrorResponse(\n res: Response,\n error: AppError,\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/errors/ErrorHandler.ts"],"sourcesContent":["// Import required modules and types from their respective locations.\nimport { logger } from '@logger';\nimport { formatPaginatedResponse, formatResponse } from '@utils/responseData';\nimport type { Response } from 'express';\n// @ts-ignore express-intlayer not build yet\nimport { t, LanguageContent } from 'express-intlayer';\nimport { ErrorCodes, errorData } from './errorCodes';\nimport { AppError } from './ErrorsClass';\nimport { HttpStatusCodes, UserAPI } from '@/export';\nimport { Locales } from 'intlayer';\n\n// Define a class named 'ErrorHandler' to encapsulate error handling logic.\nexport class ErrorHandler {\n /**\n * Handles generic error responses by formatting and sending a JSON response.\n * @param res - The response object provided by Express.js.\n * @param errorKey - A key representing the specific error.\n * @param statusCode - (Optional) A specific HTTP status code to use for the response.\n * @param isPaginatedResponse - Flag to determine if the response should be paginated.\n */\n static handleGenericErrorResponse(\n res: Response,\n errorKey: ErrorCodes,\n errorDetails?: object,\n statusCode?: HttpStatusCodes,\n isPaginatedResponse: boolean = false\n ) {\n const error = errorData[errorKey];\n const status = statusCode ?? error.statusCode; // Use the provided status code or default to the one in errorData.\n\n // Delegate to a more customizable error response handler.\n this.handleCustomErrorResponse(\n res,\n errorKey,\n error.title,\n error.message,\n errorDetails,\n status,\n isPaginatedResponse\n );\n }\n\n /**\n * Handles application-specific error responses by formatting and sending a JSON response.\n * @param res - The response object provided by Express.js.\n * @param error - The error object.\n * @param messageDetails - (Optional) Additional message details to include in the response.\n * @param isPaginatedResponse - (Optional) Flag to determine if the response should be paginated.\n */\n static handleAppErrorResponse(\n res: Response,\n error: AppError,\n messageDetails?: object,\n isPaginatedResponse: boolean = false\n ) {\n if (!error.isAppError) {\n this.handleCustomErrorResponse(\n res,\n error.errorKey ?? 'UNKNOWN_ERROR',\n 'Error',\n error.message ?? JSON.stringify(error),\n undefined,\n error.httpStatusCode ?? HttpStatusCodes.INTERNAL_SERVER_ERROR_500,\n isPaginatedResponse\n );\n }\n\n const isMultilingual = error.isMultilingual ?? false;\n // Delegate to a more customizable error response handler.\n this.handleCustomErrorResponse(\n res,\n error.errorKey,\n isMultilingual ? error.multilingualTitle : error.title,\n isMultilingual ? error.multilingualMessage : error.multilingualMessage,\n error.messageDetails ?? messageDetails,\n error.httpStatusCode,\n isPaginatedResponse\n );\n }\n\n /**\n * Handles more customizable error responses with detailed error messages and codes.\n * @param res - The response object.\n * @param errorKey - Error code key used to fetch the corresponding message and default status.\n * @param message - The localized error message object.\n * @param messageDetails - (Optional) Additional message details to include in the response.\n * @param statusCode - (Optional) HTTP status code, defaults to 500 if not specified.\n * @param isPaginatedResponse - Determines if the error should be part of a paginated response.\n */\n static handleCustomErrorResponse<T>(\n res: Response,\n errorKey: ErrorCodes | string,\n title: LanguageContent<string> | string,\n message: LanguageContent<string> | string,\n messageDetails?: object,\n statusCode?: HttpStatusCodes,\n isPaginatedResponse: boolean = false\n ) {\n const errorTitle = t(title as LanguageContent<string>, Locales.ENGLISH);\n const errorMessage = t(message as LanguageContent<string>, Locales.ENGLISH);\n logger.error(errorMessage, messageDetails); // Log the English version of the error message.\n const status = statusCode ?? HttpStatusCodes.INTERNAL_SERVER_ERROR_500; // Default to 500 if no status code is provided.\n\n if (isPaginatedResponse) {\n // Format the response as a paginated error response if requested.\n const responseData = formatPaginatedResponse<T>({\n error: {\n code: errorKey,\n title: errorTitle,\n message: errorMessage,\n },\n status,\n });\n res.status(status).json(responseData);\n return;\n }\n\n // Format the response as a standard non-paginated error response.\n const responseData = formatResponse<UserAPI>({\n error: {\n code: errorKey,\n title: errorTitle,\n message: errorMessage,\n ...messageDetails,\n },\n status,\n });\n\n res.status(status).json(responseData);\n }\n}\n"],"mappings":"AACA,SAAS,cAAc;AACvB,SAAS,yBAAyB,sBAAsB;AAGxD,SAAS,SAA0B;AACnC,SAAqB,iBAAiB;AAEtC,SAAS,uBAAgC;AACzC,SAAS,eAAe;AAGjB,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxB,OAAO,2BACL,KACA,UACA,cACA,YACA,sBAA+B,OAC/B;AACA,UAAM,QAAQ,UAAU,QAAQ;AAChC,UAAM,SAAS,cAAc,MAAM;AAGnC,SAAK;AAAA,MACH;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,OAAO,uBACL,KACA,OACA,gBACA,sBAA+B,OAC/B;AACA,QAAI,CAAC,MAAM,YAAY;AACrB,WAAK;AAAA,QACH;AAAA,QACA,MAAM,YAAY;AAAA,QAClB;AAAA,QACA,MAAM,WAAW,KAAK,UAAU,KAAK;AAAA,QACrC;AAAA,QACA,MAAM,kBAAkB,gBAAgB;AAAA,QACxC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,iBAAiB,MAAM,kBAAkB;AAE/C,SAAK;AAAA,MACH;AAAA,MACA,MAAM;AAAA,MACN,iBAAiB,MAAM,oBAAoB,MAAM;AAAA,MACjD,iBAAiB,MAAM,sBAAsB,MAAM;AAAA,MACnD,MAAM,kBAAkB;AAAA,MACxB,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAO,0BACL,KACA,UACA,OACA,SACA,gBACA,YACA,sBAA+B,OAC/B;AACA,UAAM,aAAa,EAAE,OAAkC,QAAQ,OAAO;AACtE,UAAM,eAAe,EAAE,SAAoC,QAAQ,OAAO;AAC1E,WAAO,MAAM,cAAc,cAAc;AACzC,UAAM,SAAS,cAAc,gBAAgB;AAE7C,QAAI,qBAAqB;AAEvB,YAAMA,gBAAe,wBAA2B;AAAA,QAC9C,OAAO;AAAA,UACL,MAAM;AAAA,UACN,OAAO;AAAA,UACP,SAAS;AAAA,QACX;AAAA,QACA;AAAA,MACF,CAAC;AACD,UAAI,OAAO,MAAM,EAAE,KAAKA,aAAY;AACpC;AAAA,IACF;AAGA,UAAM,eAAe,eAAwB;AAAA,MAC3C,OAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,QACP,SAAS;AAAA,QACT,GAAG;AAAA,MACL;AAAA,MACA;AAAA,IACF,CAAC;AAED,QAAI,OAAO,MAAM,EAAE,KAAK,YAAY;AAAA,EACtC;AACF;","names":["responseData"]}
|
|
@@ -2,9 +2,13 @@ import { HttpStatusCodes } from './../../utils/httpStatusCodes.mjs';
|
|
|
2
2
|
import { t } from "express-intlayer";
|
|
3
3
|
import { errorData } from './errorCodes.mjs';
|
|
4
4
|
class AppError extends Error {
|
|
5
|
+
isAppError = true;
|
|
6
|
+
// Flag to identify AppError instances.
|
|
5
7
|
name;
|
|
6
8
|
isMultilingual = true;
|
|
7
9
|
errorKey;
|
|
10
|
+
title;
|
|
11
|
+
multilingualTitle;
|
|
8
12
|
message;
|
|
9
13
|
multilingualMessage;
|
|
10
14
|
httpStatusCode;
|
|
@@ -14,13 +18,16 @@ class AppError extends Error {
|
|
|
14
18
|
* @param multilingualMessage - The error message which can be a simple string or a multilingual object.
|
|
15
19
|
* @param httpStatusCode - Optional HTTP status code, defaults to 500 Internal Server Error.
|
|
16
20
|
*/
|
|
17
|
-
constructor(multilingualMessage, errorKey, httpStatusCode = HttpStatusCodes.INTERNAL_SERVER_ERROR_500, messageDetails) {
|
|
21
|
+
constructor(multilingualTitle, multilingualMessage, errorKey, httpStatusCode = HttpStatusCodes.INTERNAL_SERVER_ERROR_500, messageDetails) {
|
|
22
|
+
const title = t(multilingualTitle);
|
|
18
23
|
const message = t(multilingualMessage);
|
|
19
24
|
super(message);
|
|
25
|
+
this.title = title;
|
|
26
|
+
this.multilingualTitle = multilingualTitle;
|
|
20
27
|
this.message = message;
|
|
28
|
+
this.multilingualMessage = multilingualMessage;
|
|
21
29
|
this.name = "AppError";
|
|
22
30
|
this.errorKey = errorKey;
|
|
23
|
-
this.multilingualMessage = multilingualMessage;
|
|
24
31
|
this.httpStatusCode = httpStatusCode;
|
|
25
32
|
this.messageDetails = messageDetails;
|
|
26
33
|
Error.captureStackTrace(this, this.constructor);
|
|
@@ -28,9 +35,16 @@ class AppError extends Error {
|
|
|
28
35
|
}
|
|
29
36
|
class GenericError extends AppError {
|
|
30
37
|
constructor(errorKey, messageDetails) {
|
|
38
|
+
const multilingualTitle = errorData[errorKey].title;
|
|
31
39
|
const multilingualMessage = errorData[errorKey].message;
|
|
32
40
|
const httpStatusCode = errorData[errorKey].statusCode;
|
|
33
|
-
super(
|
|
41
|
+
super(
|
|
42
|
+
multilingualTitle,
|
|
43
|
+
multilingualMessage,
|
|
44
|
+
errorKey,
|
|
45
|
+
httpStatusCode,
|
|
46
|
+
messageDetails
|
|
47
|
+
);
|
|
34
48
|
}
|
|
35
49
|
}
|
|
36
50
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/errors/ErrorsClass.ts"],"sourcesContent":["import { HttpStatusCodes } from '@utils/httpStatusCodes';\n// @ts-ignore express-intlayer not build yet\nimport { t, type LanguageContent } from 'express-intlayer';\nimport { ErrorCodes, errorData } from './errorCodes';\n\n/**\n * Custom error class that extends the native JavaScript Error class.\n * This class supports multilingual error messages and HTTP status codes.\n */\nexport class AppError extends Error {\n public name: string;\n public isMultilingual: boolean = true;\n public errorKey: string;\n public message: string;\n public multilingualMessage: LanguageContent<string>;\n public httpStatusCode: HttpStatusCodes;\n public messageDetails?: object;\n\n /**\n * Constructor for the custom error class.\n * @param multilingualMessage - The error message which can be a simple string or a multilingual object.\n * @param httpStatusCode - Optional HTTP status code, defaults to 500 Internal Server Error.\n */\n constructor(\n multilingualMessage: LanguageContent<string>,\n errorKey: string,\n httpStatusCode: HttpStatusCodes = HttpStatusCodes.INTERNAL_SERVER_ERROR_500,\n messageDetails?: object\n ) {\n const message = t(multilingualMessage); // Translate message based on current locale.\n\n super(message); // Use translated message for the superclass constructor.\n this.
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/errors/ErrorsClass.ts"],"sourcesContent":["import { HttpStatusCodes } from '@utils/httpStatusCodes';\n// @ts-ignore express-intlayer not build yet\nimport { t, type LanguageContent } from 'express-intlayer';\nimport { ErrorCodes, errorData } from './errorCodes';\n\n/**\n * Custom error class that extends the native JavaScript Error class.\n * This class supports multilingual error messages and HTTP status codes.\n */\nexport class AppError extends Error {\n public isAppError: boolean = true; // Flag to identify AppError instances.\n public name: string;\n public isMultilingual: boolean = true;\n public errorKey: string;\n public title: string;\n public multilingualTitle: LanguageContent<string>;\n public message: string;\n public multilingualMessage: LanguageContent<string>;\n public httpStatusCode: HttpStatusCodes;\n public messageDetails?: object;\n\n /**\n * Constructor for the custom error class.\n * @param multilingualMessage - The error message which can be a simple string or a multilingual object.\n * @param httpStatusCode - Optional HTTP status code, defaults to 500 Internal Server Error.\n */\n constructor(\n multilingualTitle: LanguageContent<string>,\n multilingualMessage: LanguageContent<string>,\n errorKey: string,\n httpStatusCode: HttpStatusCodes = HttpStatusCodes.INTERNAL_SERVER_ERROR_500,\n messageDetails?: object\n ) {\n const title = t(multilingualTitle); // Translate title based on current locale\n const message = t(multilingualMessage); // Translate message based on current locale.\n\n super(message); // Use translated message for the superclass constructor.\n this.title = title;\n this.multilingualTitle = multilingualTitle;\n this.message = message;\n this.multilingualMessage = multilingualMessage; // Store original message format for potential use.\n this.name = 'AppError';\n this.errorKey = errorKey;\n this.httpStatusCode = httpStatusCode; // Set the HTTP status code.\n this.messageDetails = messageDetails; // Store any additional message details.\n\n // Capture the stack trace to exclude the constructor call.\n Error.captureStackTrace(this, this.constructor);\n }\n}\n\nexport class GenericError extends AppError {\n constructor(errorKey: ErrorCodes, messageDetails?: object) {\n const multilingualTitle = errorData[errorKey].title;\n const multilingualMessage = errorData[errorKey].message;\n const httpStatusCode = errorData[errorKey].statusCode;\n\n super(\n multilingualTitle,\n multilingualMessage,\n errorKey,\n httpStatusCode,\n messageDetails\n );\n }\n}\n"],"mappings":"AAAA,SAAS,uBAAuB;AAEhC,SAAS,SAA+B;AACxC,SAAqB,iBAAiB;AAM/B,MAAM,iBAAiB,MAAM;AAAA,EAC3B,aAAsB;AAAA;AAAA,EACtB;AAAA,EACA,iBAA0B;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOP,YACE,mBACA,qBACA,UACA,iBAAkC,gBAAgB,2BAClD,gBACA;AACA,UAAM,QAAQ,EAAE,iBAAiB;AACjC,UAAM,UAAU,EAAE,mBAAmB;AAErC,UAAM,OAAO;AACb,SAAK,QAAQ;AACb,SAAK,oBAAoB;AACzB,SAAK,UAAU;AACf,SAAK,sBAAsB;AAC3B,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AAGtB,UAAM,kBAAkB,MAAM,KAAK,WAAW;AAAA,EAChD;AACF;AAEO,MAAM,qBAAqB,SAAS;AAAA,EACzC,YAAY,UAAsB,gBAAyB;AACzD,UAAM,oBAAoB,UAAU,QAAQ,EAAE;AAC9C,UAAM,sBAAsB,UAAU,QAAQ,EAAE;AAChD,UAAM,iBAAiB,UAAU,QAAQ,EAAE;AAE3C;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|