@m5kdev/backend 0.1.1 → 0.1.3
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +18 -0
- package/dist/src/lib/posthog.js +7 -0
- package/dist/src/lib/sentry.js +9 -0
- package/dist/src/modules/access/access.repository.js +32 -0
- package/dist/src/modules/access/access.service.js +51 -0
- package/dist/src/modules/access/access.test.js +182 -0
- package/dist/src/modules/access/access.utils.js +20 -0
- package/dist/src/modules/ai/ai.db.js +39 -0
- package/dist/src/modules/ai/ai.prompt.js +30 -0
- package/dist/src/modules/ai/ai.repository.js +26 -0
- package/dist/src/modules/ai/ai.router.js +132 -0
- package/dist/src/modules/ai/ai.service.js +207 -0
- package/dist/src/modules/ai/ai.trpc.d.ts +5 -5
- package/dist/src/modules/ai/ai.trpc.js +20 -0
- package/dist/src/modules/ai/ideogram/ideogram.constants.js +167 -0
- package/dist/src/modules/ai/ideogram/ideogram.dto.js +49 -0
- package/dist/src/modules/ai/ideogram/ideogram.prompt.js +860 -0
- package/dist/src/modules/ai/ideogram/ideogram.repository.js +46 -0
- package/dist/src/modules/ai/ideogram/ideogram.service.js +11 -0
- package/dist/src/modules/auth/auth.db.js +215 -0
- package/dist/src/modules/auth/auth.dto.js +38 -0
- package/dist/src/modules/auth/auth.lib.d.ts +4 -4
- package/dist/src/modules/auth/auth.lib.js +284 -0
- package/dist/src/modules/auth/auth.middleware.js +52 -0
- package/dist/src/modules/auth/auth.repository.js +541 -0
- package/dist/src/modules/auth/auth.service.js +201 -0
- package/dist/src/modules/auth/auth.trpc.d.ts +18 -18
- package/dist/src/modules/auth/auth.trpc.js +157 -0
- package/dist/src/modules/auth/auth.utils.js +97 -0
- package/dist/src/modules/base/base.abstract.js +53 -0
- package/dist/src/modules/base/base.dto.js +112 -0
- package/dist/src/modules/base/base.grants.js +123 -0
- package/dist/src/modules/base/base.grants.test.js +668 -0
- package/dist/src/modules/base/base.repository.js +307 -0
- package/dist/src/modules/base/base.service.js +109 -0
- package/dist/src/modules/base/base.types.js +2 -0
- package/dist/src/modules/billing/billing.db.js +29 -0
- package/dist/src/modules/billing/billing.repository.js +235 -0
- package/dist/src/modules/billing/billing.router.js +56 -0
- package/dist/src/modules/billing/billing.service.js +147 -0
- package/dist/src/modules/billing/billing.trpc.d.ts +5 -5
- package/dist/src/modules/billing/billing.trpc.js +17 -0
- package/dist/src/modules/clay/clay.repository.js +26 -0
- package/dist/src/modules/clay/clay.service.js +24 -0
- package/dist/src/modules/connect/connect.db.js +30 -0
- package/dist/src/modules/connect/connect.dto.js +36 -0
- package/dist/src/modules/connect/connect.linkedin.js +53 -0
- package/dist/src/modules/connect/connect.oauth.js +198 -0
- package/dist/src/modules/connect/connect.repository.d.ts +7 -7
- package/dist/src/modules/connect/connect.repository.js +54 -0
- package/dist/src/modules/connect/connect.router.js +54 -0
- package/dist/src/modules/connect/connect.service.d.ts +14 -14
- package/dist/src/modules/connect/connect.service.js +114 -0
- package/dist/src/modules/connect/connect.trpc.d.ts +10 -10
- package/dist/src/modules/connect/connect.trpc.js +21 -0
- package/dist/src/modules/connect/connect.types.js +2 -0
- package/dist/src/modules/crypto/crypto.db.js +17 -0
- package/dist/src/modules/crypto/crypto.repository.js +10 -0
- package/dist/src/modules/crypto/crypto.service.js +52 -0
- package/dist/src/modules/email/email.service.js +107 -0
- package/dist/src/modules/file/file.repository.js +79 -0
- package/dist/src/modules/file/file.router.js +99 -0
- package/dist/src/modules/file/file.service.js +150 -0
- package/dist/src/modules/recurrence/recurrence.db.js +66 -0
- package/dist/src/modules/recurrence/recurrence.repository.js +39 -0
- package/dist/src/modules/recurrence/recurrence.service.js +70 -0
- package/dist/src/modules/recurrence/recurrence.trpc.d.ts +15 -15
- package/dist/src/modules/recurrence/recurrence.trpc.js +65 -0
- package/dist/src/modules/social/social.dto.js +18 -0
- package/dist/src/modules/social/social.linkedin.js +427 -0
- package/dist/src/modules/social/social.linkedin.test.js +235 -0
- package/dist/src/modules/social/social.service.js +76 -0
- package/dist/src/modules/social/social.types.js +2 -0
- package/dist/src/modules/tag/tag.db.js +42 -0
- package/dist/src/modules/tag/tag.dto.js +9 -0
- package/dist/src/modules/tag/tag.repository.js +154 -0
- package/dist/src/modules/tag/tag.service.js +31 -0
- package/dist/src/modules/tag/tag.trpc.d.ts +5 -5
- package/dist/src/modules/tag/tag.trpc.js +47 -0
- package/dist/src/modules/utils/applyPagination.js +16 -0
- package/dist/src/modules/utils/applySorting.js +18 -0
- package/dist/src/modules/utils/getConditionsFromFilters.js +200 -0
- package/dist/src/modules/video/video.service.js +84 -0
- package/dist/src/modules/webhook/webhook.constants.js +10 -0
- package/dist/src/modules/webhook/webhook.db.js +17 -0
- package/dist/src/modules/webhook/webhook.dto.js +7 -0
- package/dist/src/modules/webhook/webhook.repository.js +56 -0
- package/dist/src/modules/webhook/webhook.router.js +30 -0
- package/dist/src/modules/webhook/webhook.service.js +68 -0
- package/dist/src/modules/workflow/workflow.db.js +30 -0
- package/dist/src/modules/workflow/workflow.repository.js +105 -0
- package/dist/src/modules/workflow/workflow.service.js +37 -0
- package/dist/src/modules/workflow/workflow.trpc.d.ts +5 -5
- package/dist/src/modules/workflow/workflow.trpc.js +21 -0
- package/dist/src/modules/workflow/workflow.types.js +2 -0
- package/dist/src/modules/workflow/workflow.utils.js +173 -0
- package/dist/src/test/stubs/utils.js +5 -0
- package/dist/src/trpc/context.d.ts +5 -5
- package/dist/src/trpc/context.js +17 -0
- package/dist/src/trpc/index.js +6 -0
- package/dist/src/trpc/procedures.d.ts +56 -56
- package/dist/src/trpc/procedures.js +32 -0
- package/dist/src/trpc/utils.js +20 -0
- package/dist/src/types.d.ts +33 -33
- package/dist/src/types.js +13 -0
- package/dist/src/utils/errors.js +104 -0
- package/dist/src/utils/logger.js +11 -0
- package/dist/src/utils/posthog.js +31 -0
- package/dist/src/utils/types.js +2 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/tsconfig.json +2 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthService = void 0;
|
|
4
|
+
const neverthrow_1 = require("neverthrow");
|
|
5
|
+
const base_service_1 = require("#modules/base/base.service");
|
|
6
|
+
const posthog_1 = require("#utils/posthog");
|
|
7
|
+
class AuthService extends base_service_1.BaseService {
|
|
8
|
+
getBillingService() {
|
|
9
|
+
if (!("billing" in this.service))
|
|
10
|
+
return null;
|
|
11
|
+
return this.service.billing;
|
|
12
|
+
}
|
|
13
|
+
async getUserWaitlistCount({ user }) {
|
|
14
|
+
if (user.role === "admin")
|
|
15
|
+
return (0, neverthrow_1.ok)(0);
|
|
16
|
+
return this.repository.auth.getUserWaitlistCount(user.id);
|
|
17
|
+
}
|
|
18
|
+
async getOnboarding({ user }) {
|
|
19
|
+
return this.repository.auth.getOnboarding(user.id);
|
|
20
|
+
}
|
|
21
|
+
async setOnboarding(onboarding, { user }) {
|
|
22
|
+
(0, posthog_1.posthogCapture)({
|
|
23
|
+
distinctId: user.id,
|
|
24
|
+
event: "onboarding_set",
|
|
25
|
+
properties: {
|
|
26
|
+
onboarding,
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
return this.repository.auth.setOnboarding(user.id, onboarding);
|
|
30
|
+
}
|
|
31
|
+
async getPreferences({ user }) {
|
|
32
|
+
return this.repository.auth.getPreferences(user.id);
|
|
33
|
+
}
|
|
34
|
+
async setPreferences(preferences, { user }) {
|
|
35
|
+
(0, posthog_1.posthogCapture)({
|
|
36
|
+
distinctId: user.id,
|
|
37
|
+
event: "preferences_set",
|
|
38
|
+
});
|
|
39
|
+
return this.repository.auth.setPreferences(user.id, preferences);
|
|
40
|
+
}
|
|
41
|
+
async getMetadata({ user }) {
|
|
42
|
+
return this.repository.auth.getMetadata(user.id);
|
|
43
|
+
}
|
|
44
|
+
async setMetadata(metadata, { user }) {
|
|
45
|
+
(0, posthog_1.posthogCapture)({
|
|
46
|
+
distinctId: user.id,
|
|
47
|
+
event: "metadata_set",
|
|
48
|
+
});
|
|
49
|
+
return this.repository.auth.setMetadata(user.id, metadata);
|
|
50
|
+
}
|
|
51
|
+
async getFlags({ user }) {
|
|
52
|
+
return this.repository.auth.getFlags(user.id);
|
|
53
|
+
}
|
|
54
|
+
async setFlags(flags, { user }) {
|
|
55
|
+
(0, posthog_1.posthogCapture)({
|
|
56
|
+
distinctId: user.id,
|
|
57
|
+
event: "flags_set",
|
|
58
|
+
});
|
|
59
|
+
return this.repository.auth.setFlags(user.id, flags);
|
|
60
|
+
}
|
|
61
|
+
async listAdminWaitlist() {
|
|
62
|
+
return this.repository.auth.listAdminWaitlist();
|
|
63
|
+
}
|
|
64
|
+
async listWaitlist({ user }) {
|
|
65
|
+
return this.repository.auth.listWaitlist(user.id);
|
|
66
|
+
}
|
|
67
|
+
async addToWaitlist({ email }) {
|
|
68
|
+
return this.repository.auth.addToWaitlist(email);
|
|
69
|
+
}
|
|
70
|
+
async inviteFromWaitlist({ id }) {
|
|
71
|
+
const waitlist = await this.repository.auth.inviteFromWaitlist(id);
|
|
72
|
+
if (waitlist.isErr())
|
|
73
|
+
return (0, neverthrow_1.err)(waitlist.error);
|
|
74
|
+
if (!waitlist.value.code)
|
|
75
|
+
return this.repository.auth.error("BAD_REQUEST");
|
|
76
|
+
if (!waitlist.value.email)
|
|
77
|
+
return this.repository.auth.error("BAD_REQUEST");
|
|
78
|
+
await this.service.email.sendWaitlistInvite(waitlist.value.email, waitlist.value.code);
|
|
79
|
+
return (0, neverthrow_1.ok)(waitlist.value);
|
|
80
|
+
}
|
|
81
|
+
async inviteToWaitlist({ email, name }, { user }) {
|
|
82
|
+
const count = await this.repository.auth.getUserWaitlistCount(user.id);
|
|
83
|
+
if (count.isErr())
|
|
84
|
+
return (0, neverthrow_1.err)(count.error);
|
|
85
|
+
if (count.value >= 3)
|
|
86
|
+
return this.repository.auth.error("BAD_REQUEST", "Run out of invites");
|
|
87
|
+
const waitlist = await this.repository.auth.inviteToWaitlist({ email, userId: user.id, name });
|
|
88
|
+
if (waitlist.isErr())
|
|
89
|
+
return (0, neverthrow_1.err)(waitlist.error);
|
|
90
|
+
if (!waitlist.value.code)
|
|
91
|
+
return this.repository.auth.error("BAD_REQUEST");
|
|
92
|
+
await this.service.email.sendWaitlistUserInvite(email, waitlist.value.code, user.name, name);
|
|
93
|
+
(0, posthog_1.posthogCapture)({
|
|
94
|
+
distinctId: user.id,
|
|
95
|
+
event: "waitlist_invite_sent",
|
|
96
|
+
properties: {
|
|
97
|
+
email,
|
|
98
|
+
name,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
return (0, neverthrow_1.ok)(waitlist.value);
|
|
102
|
+
}
|
|
103
|
+
async createInvitationCode({ name }, { user }) {
|
|
104
|
+
(0, posthog_1.posthogCapture)({
|
|
105
|
+
distinctId: user.id,
|
|
106
|
+
event: "waitlist_invitation_code_created",
|
|
107
|
+
properties: {
|
|
108
|
+
name,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
return this.repository.auth.createInvitationCode({ userId: user.id, name });
|
|
112
|
+
}
|
|
113
|
+
async joinWaitlist({ email }) {
|
|
114
|
+
const waitlist = await this.repository.auth.joinWaitlist(email);
|
|
115
|
+
if (waitlist.isErr())
|
|
116
|
+
return (0, neverthrow_1.err)(waitlist.error);
|
|
117
|
+
await this.service.email.sendWaitlistConfirmation(email);
|
|
118
|
+
return (0, neverthrow_1.ok)(waitlist.value);
|
|
119
|
+
}
|
|
120
|
+
async removeFromWaitlist({ id }) {
|
|
121
|
+
return this.repository.auth.removeFromWaitlist(id);
|
|
122
|
+
}
|
|
123
|
+
async validateWaitlistCode(code) {
|
|
124
|
+
return this.repository.auth.validateWaitlistCode(code);
|
|
125
|
+
}
|
|
126
|
+
async createAccountClaimCode({ userId, expiresInHours, }) {
|
|
127
|
+
return this.repository.auth.createAccountClaimCode({ userId, expiresInHours });
|
|
128
|
+
}
|
|
129
|
+
async listAccountClaims() {
|
|
130
|
+
return this.repository.auth.listAccountClaims();
|
|
131
|
+
}
|
|
132
|
+
async getMyAccountClaimStatus({ user }) {
|
|
133
|
+
return this.repository.auth.findPendingAccountClaimForUser(user.id);
|
|
134
|
+
}
|
|
135
|
+
async setMyAccountClaimEmail({ email }, { user }) {
|
|
136
|
+
return this.repository.auth.setAccountClaimEmail({ userId: user.id, email });
|
|
137
|
+
}
|
|
138
|
+
async acceptMyAccountClaim({ user }) {
|
|
139
|
+
const pendingClaim = await this.repository.auth.findPendingAccountClaimForUser(user.id);
|
|
140
|
+
if (pendingClaim.isErr())
|
|
141
|
+
return (0, neverthrow_1.err)(pendingClaim.error);
|
|
142
|
+
const accepted = await this.repository.auth.acceptAccountClaim(user.id);
|
|
143
|
+
if (accepted.isErr())
|
|
144
|
+
return (0, neverthrow_1.err)(accepted.error);
|
|
145
|
+
if (pendingClaim.value) {
|
|
146
|
+
const billingService = this.getBillingService();
|
|
147
|
+
if (billingService) {
|
|
148
|
+
await billingService.createUserHook({ user });
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return (0, neverthrow_1.ok)(accepted.value);
|
|
152
|
+
}
|
|
153
|
+
async generateAccountClaimMagicLink({ claimId, email, }) {
|
|
154
|
+
const claim = await this.repository.auth.findAccountClaimById(claimId);
|
|
155
|
+
if (claim.isErr())
|
|
156
|
+
return (0, neverthrow_1.err)(claim.error);
|
|
157
|
+
if (!claim.value)
|
|
158
|
+
return this.repository.auth.error("NOT_FOUND", "Claim not found");
|
|
159
|
+
if (!claim.value.claimUserId)
|
|
160
|
+
return this.repository.auth.error("BAD_REQUEST", "Claim has no user");
|
|
161
|
+
if (claim.value.status !== "INVITED") {
|
|
162
|
+
return this.repository.auth.error("BAD_REQUEST", "Claim is not pending");
|
|
163
|
+
}
|
|
164
|
+
if (claim.value.expiresAt && claim.value.expiresAt < new Date()) {
|
|
165
|
+
return this.repository.auth.error("BAD_REQUEST", "Claim is expired");
|
|
166
|
+
}
|
|
167
|
+
const targetEmail = email ?? claim.value.claimedEmail ?? undefined;
|
|
168
|
+
if (!targetEmail) {
|
|
169
|
+
return this.repository.auth.error("BAD_REQUEST", "Email required to generate magic link");
|
|
170
|
+
}
|
|
171
|
+
const setEmail = await this.repository.auth.setAccountClaimEmail({
|
|
172
|
+
userId: claim.value.claimUserId,
|
|
173
|
+
email: targetEmail,
|
|
174
|
+
});
|
|
175
|
+
if (setEmail.isErr())
|
|
176
|
+
return (0, neverthrow_1.err)(setEmail.error);
|
|
177
|
+
const response = await fetch(`${process.env.VITE_SERVER_URL}/api/auth/sign-in/magic-link`, {
|
|
178
|
+
method: "POST",
|
|
179
|
+
headers: {
|
|
180
|
+
"content-type": "application/json",
|
|
181
|
+
},
|
|
182
|
+
body: JSON.stringify({
|
|
183
|
+
email: targetEmail.toLowerCase(),
|
|
184
|
+
callbackURL: `${process.env.VITE_APP_URL}/claim-account?claim=${claimId}`,
|
|
185
|
+
}),
|
|
186
|
+
});
|
|
187
|
+
if (!response.ok) {
|
|
188
|
+
return this.repository.auth.error("INTERNAL_SERVER_ERROR", "Failed to generate magic link");
|
|
189
|
+
}
|
|
190
|
+
const latest = await this.repository.auth.latestAccountClaimMagicLink(claimId);
|
|
191
|
+
if (latest.isErr())
|
|
192
|
+
return (0, neverthrow_1.err)(latest.error);
|
|
193
|
+
if (!latest.value)
|
|
194
|
+
return this.repository.auth.error("INTERNAL_SERVER_ERROR");
|
|
195
|
+
return (0, neverthrow_1.ok)(latest.value);
|
|
196
|
+
}
|
|
197
|
+
async listAccountClaimMagicLinks({ claimId, }) {
|
|
198
|
+
return this.repository.auth.listAccountClaimMagicLinks(claimId);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
exports.AuthService = AuthService;
|
|
@@ -4,9 +4,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
4
4
|
session: {
|
|
5
5
|
id: string;
|
|
6
6
|
userId: string;
|
|
7
|
-
expiresAt: Date;
|
|
8
|
-
createdAt: Date;
|
|
9
7
|
updatedAt: Date;
|
|
8
|
+
createdAt: Date;
|
|
9
|
+
expiresAt: Date;
|
|
10
10
|
token: string;
|
|
11
11
|
ipAddress: string | null;
|
|
12
12
|
userAgent: string | null;
|
|
@@ -18,13 +18,12 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
18
18
|
};
|
|
19
19
|
user: {
|
|
20
20
|
name: string;
|
|
21
|
-
image: string | null;
|
|
22
21
|
id: string;
|
|
23
|
-
createdAt: Date;
|
|
24
22
|
updatedAt: Date;
|
|
25
23
|
email: string;
|
|
26
|
-
metadata: Record<string, unknown>;
|
|
27
24
|
emailVerified: boolean;
|
|
25
|
+
image: string | null;
|
|
26
|
+
createdAt: Date;
|
|
28
27
|
role: string | null;
|
|
29
28
|
banned: boolean | null;
|
|
30
29
|
banReason: string | null;
|
|
@@ -34,6 +33,7 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
34
33
|
paymentPlanTier: string | null;
|
|
35
34
|
paymentPlanExpiresAt: Date | null;
|
|
36
35
|
preferences: string | null;
|
|
36
|
+
metadata: Record<string, unknown>;
|
|
37
37
|
onboarding: number | null;
|
|
38
38
|
flags: string | null;
|
|
39
39
|
};
|
|
@@ -85,9 +85,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
85
85
|
input: void;
|
|
86
86
|
output: {
|
|
87
87
|
id: string;
|
|
88
|
-
expiresAt: Date | null;
|
|
89
|
-
createdAt: Date;
|
|
90
88
|
updatedAt: Date | null;
|
|
89
|
+
createdAt: Date;
|
|
90
|
+
expiresAt: Date | null;
|
|
91
91
|
status: string;
|
|
92
92
|
claimUserId: string | null;
|
|
93
93
|
claimedAt: Date | null;
|
|
@@ -103,11 +103,11 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
103
103
|
output: {
|
|
104
104
|
id: string;
|
|
105
105
|
userId: string;
|
|
106
|
-
expiresAt: Date | null;
|
|
107
|
-
createdAt: Date;
|
|
108
106
|
email: string;
|
|
109
|
-
|
|
107
|
+
createdAt: Date;
|
|
108
|
+
expiresAt: Date | null;
|
|
110
109
|
claimId: string;
|
|
110
|
+
url: string;
|
|
111
111
|
};
|
|
112
112
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
113
113
|
}>;
|
|
@@ -118,11 +118,11 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
118
118
|
output: {
|
|
119
119
|
id: string;
|
|
120
120
|
userId: string;
|
|
121
|
-
expiresAt: Date | null;
|
|
122
|
-
createdAt: Date;
|
|
123
121
|
email: string;
|
|
124
|
-
|
|
122
|
+
createdAt: Date;
|
|
123
|
+
expiresAt: Date | null;
|
|
125
124
|
claimId: string;
|
|
125
|
+
url: string;
|
|
126
126
|
}[];
|
|
127
127
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
128
128
|
}>;
|
|
@@ -176,9 +176,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
176
176
|
output: {
|
|
177
177
|
name: string | null;
|
|
178
178
|
id: string;
|
|
179
|
-
createdAt: Date;
|
|
180
179
|
updatedAt: Date | null;
|
|
181
180
|
email: string | null;
|
|
181
|
+
createdAt: Date;
|
|
182
182
|
status: string;
|
|
183
183
|
}[];
|
|
184
184
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
@@ -190,9 +190,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
190
190
|
output: {
|
|
191
191
|
name: string | null;
|
|
192
192
|
id: string;
|
|
193
|
-
createdAt: Date;
|
|
194
193
|
updatedAt: Date | null;
|
|
195
194
|
email: string | null;
|
|
195
|
+
createdAt: Date;
|
|
196
196
|
status: string;
|
|
197
197
|
};
|
|
198
198
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
@@ -221,9 +221,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
221
221
|
output: {
|
|
222
222
|
name: string | null;
|
|
223
223
|
id: string;
|
|
224
|
-
createdAt: Date;
|
|
225
224
|
updatedAt: Date | null;
|
|
226
225
|
email: string | null;
|
|
226
|
+
createdAt: Date;
|
|
227
227
|
status: string;
|
|
228
228
|
};
|
|
229
229
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
@@ -235,9 +235,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
235
235
|
output: {
|
|
236
236
|
name: string | null;
|
|
237
237
|
id: string;
|
|
238
|
-
createdAt: Date;
|
|
239
238
|
updatedAt: Date | null;
|
|
240
239
|
email: string | null;
|
|
240
|
+
createdAt: Date;
|
|
241
241
|
status: string;
|
|
242
242
|
};
|
|
243
243
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
@@ -249,9 +249,9 @@ export declare function createAuthTRPC(authService: AuthService): import("@trpc/
|
|
|
249
249
|
output: {
|
|
250
250
|
name: string | null;
|
|
251
251
|
id: string;
|
|
252
|
-
createdAt: Date;
|
|
253
252
|
updatedAt: Date | null;
|
|
254
253
|
email: string | null;
|
|
254
|
+
createdAt: Date;
|
|
255
255
|
status: string;
|
|
256
256
|
};
|
|
257
257
|
meta: import("trpc-to-openapi").OpenApiMeta;
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthTRPC = createAuthTRPC;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const auth_dto_1 = require("#modules/auth/auth.dto");
|
|
6
|
+
const _trpc_1 = require("#trpc");
|
|
7
|
+
function createAuthTRPC(authService) {
|
|
8
|
+
return (0, _trpc_1.router)({
|
|
9
|
+
getUserWaitlistCount: _trpc_1.procedure.output(zod_1.z.number()).query(async ({ ctx }) => {
|
|
10
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.getUserWaitlistCount(ctx));
|
|
11
|
+
}),
|
|
12
|
+
createInvitationCode: _trpc_1.procedure
|
|
13
|
+
.input(zod_1.z.object({ name: zod_1.z.string().optional() }))
|
|
14
|
+
.output(auth_dto_1.waitlistSchema)
|
|
15
|
+
.mutation(async ({ input, ctx }) => {
|
|
16
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.createInvitationCode(input, ctx));
|
|
17
|
+
}),
|
|
18
|
+
createAccountClaimCode: _trpc_1.adminProcedure
|
|
19
|
+
.input(zod_1.z.object({
|
|
20
|
+
userId: zod_1.z.string(),
|
|
21
|
+
expiresInHours: zod_1.z.number().optional(),
|
|
22
|
+
}))
|
|
23
|
+
.output(auth_dto_1.accountClaimSchema)
|
|
24
|
+
.mutation(async ({ input }) => {
|
|
25
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.createAccountClaimCode(input));
|
|
26
|
+
}),
|
|
27
|
+
listAccountClaims: _trpc_1.adminProcedure.output(zod_1.z.array(auth_dto_1.accountClaimOutputSchema)).query(async () => {
|
|
28
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.listAccountClaims());
|
|
29
|
+
}),
|
|
30
|
+
generateAccountClaimMagicLink: _trpc_1.adminProcedure
|
|
31
|
+
.input(zod_1.z.object({
|
|
32
|
+
claimId: zod_1.z.string(),
|
|
33
|
+
email: zod_1.z.string().email().optional(),
|
|
34
|
+
}))
|
|
35
|
+
.output(auth_dto_1.accountClaimMagicLinkOutputSchema)
|
|
36
|
+
.mutation(async ({ input }) => {
|
|
37
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.generateAccountClaimMagicLink(input));
|
|
38
|
+
}),
|
|
39
|
+
listAccountClaimMagicLinks: _trpc_1.adminProcedure
|
|
40
|
+
.input(zod_1.z.object({
|
|
41
|
+
claimId: zod_1.z.string(),
|
|
42
|
+
}))
|
|
43
|
+
.output(zod_1.z.array(auth_dto_1.accountClaimMagicLinkOutputSchema))
|
|
44
|
+
.query(async ({ input }) => {
|
|
45
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.listAccountClaimMagicLinks(input));
|
|
46
|
+
}),
|
|
47
|
+
getMyAccountClaimStatus: _trpc_1.procedure.output(auth_dto_1.accountClaimSchema.nullable()).query(async ({ ctx }) => {
|
|
48
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.getMyAccountClaimStatus(ctx));
|
|
49
|
+
}),
|
|
50
|
+
setMyAccountClaimEmail: _trpc_1.procedure
|
|
51
|
+
.input(zod_1.z.object({
|
|
52
|
+
email: zod_1.z.string().email(),
|
|
53
|
+
}))
|
|
54
|
+
.output(zod_1.z.object({ status: zod_1.z.boolean() }))
|
|
55
|
+
.mutation(async ({ input, ctx }) => {
|
|
56
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.setMyAccountClaimEmail(input, ctx));
|
|
57
|
+
}),
|
|
58
|
+
acceptMyAccountClaim: _trpc_1.procedure
|
|
59
|
+
.output(zod_1.z.object({ status: zod_1.z.boolean() }))
|
|
60
|
+
.mutation(async ({ ctx }) => {
|
|
61
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.acceptMyAccountClaim(ctx));
|
|
62
|
+
}),
|
|
63
|
+
listWaitlist: _trpc_1.procedure.output(zod_1.z.array(auth_dto_1.waitlistSchema)).query(async ({ ctx }) => {
|
|
64
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.listWaitlist(ctx));
|
|
65
|
+
}),
|
|
66
|
+
listAdminWaitlist: _trpc_1.adminProcedure.output(zod_1.z.array(auth_dto_1.waitlistOutputSchema)).query(async () => {
|
|
67
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.listAdminWaitlist());
|
|
68
|
+
}),
|
|
69
|
+
addToWaitlist: _trpc_1.adminProcedure
|
|
70
|
+
.input(zod_1.z.object({
|
|
71
|
+
email: zod_1.z.string(),
|
|
72
|
+
}))
|
|
73
|
+
.output(auth_dto_1.waitlistOutputSchema)
|
|
74
|
+
.mutation(async ({ input }) => {
|
|
75
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.addToWaitlist(input));
|
|
76
|
+
}),
|
|
77
|
+
inviteToWaitlist: _trpc_1.procedure
|
|
78
|
+
.input(zod_1.z.object({
|
|
79
|
+
email: zod_1.z.string(),
|
|
80
|
+
name: zod_1.z.string().optional(),
|
|
81
|
+
}))
|
|
82
|
+
.output(auth_dto_1.waitlistSchema)
|
|
83
|
+
.mutation(async ({ input, ctx }) => {
|
|
84
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.inviteToWaitlist(input, ctx));
|
|
85
|
+
}),
|
|
86
|
+
inviteFromWaitlist: _trpc_1.adminProcedure
|
|
87
|
+
.input(zod_1.z.object({
|
|
88
|
+
id: zod_1.z.string(),
|
|
89
|
+
}))
|
|
90
|
+
.output(auth_dto_1.waitlistOutputSchema)
|
|
91
|
+
.mutation(async ({ input }) => {
|
|
92
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.inviteFromWaitlist(input));
|
|
93
|
+
}),
|
|
94
|
+
removeFromWaitlist: _trpc_1.adminProcedure
|
|
95
|
+
.input(zod_1.z.object({
|
|
96
|
+
id: zod_1.z.string(),
|
|
97
|
+
}))
|
|
98
|
+
.output(auth_dto_1.waitlistOutputSchema)
|
|
99
|
+
.mutation(async ({ input }) => {
|
|
100
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.removeFromWaitlist(input));
|
|
101
|
+
}),
|
|
102
|
+
joinWaitlist: _trpc_1.publicProcedure
|
|
103
|
+
.input(zod_1.z.object({
|
|
104
|
+
email: zod_1.z.string(),
|
|
105
|
+
}))
|
|
106
|
+
.output(auth_dto_1.waitlistOutputSchema)
|
|
107
|
+
.mutation(async ({ input }) => {
|
|
108
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.joinWaitlist(input));
|
|
109
|
+
}),
|
|
110
|
+
getOnboarding: _trpc_1.procedure.output(zod_1.z.number()).query(async ({ ctx }) => {
|
|
111
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.getOnboarding(ctx));
|
|
112
|
+
}),
|
|
113
|
+
setOnboarding: _trpc_1.procedure
|
|
114
|
+
.input(zod_1.z.number())
|
|
115
|
+
.output(zod_1.z.number())
|
|
116
|
+
.mutation(async ({ ctx, input }) => {
|
|
117
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.setOnboarding(input, ctx));
|
|
118
|
+
}),
|
|
119
|
+
getPreferences: _trpc_1.procedure.output(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown())).query(async ({ ctx }) => {
|
|
120
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.getPreferences(ctx));
|
|
121
|
+
}),
|
|
122
|
+
setPreferences: _trpc_1.procedure
|
|
123
|
+
.input(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()))
|
|
124
|
+
.output(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()))
|
|
125
|
+
.mutation(async ({ ctx, input }) => {
|
|
126
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.setPreferences(input, ctx));
|
|
127
|
+
}),
|
|
128
|
+
getMetadata: _trpc_1.procedure.output(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown())).query(async ({ ctx }) => {
|
|
129
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.getMetadata(ctx));
|
|
130
|
+
}),
|
|
131
|
+
setMetadata: _trpc_1.procedure
|
|
132
|
+
.input(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()))
|
|
133
|
+
.output(zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()))
|
|
134
|
+
.mutation(async ({ ctx, input }) => {
|
|
135
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.setMetadata(input, ctx));
|
|
136
|
+
}),
|
|
137
|
+
getFlags: _trpc_1.procedure.output(zod_1.z.array(zod_1.z.string())).query(async ({ ctx }) => {
|
|
138
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.getFlags(ctx));
|
|
139
|
+
}),
|
|
140
|
+
setFlags: _trpc_1.procedure
|
|
141
|
+
.input(zod_1.z.array(zod_1.z.string()))
|
|
142
|
+
.output(zod_1.z.array(zod_1.z.string()))
|
|
143
|
+
.mutation(async ({ ctx, input }) => {
|
|
144
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.setFlags(input, ctx));
|
|
145
|
+
}),
|
|
146
|
+
validateWaitlistCode: _trpc_1.publicProcedure
|
|
147
|
+
.input(zod_1.z.object({
|
|
148
|
+
code: zod_1.z.string(),
|
|
149
|
+
}))
|
|
150
|
+
.output(zod_1.z.object({
|
|
151
|
+
status: zod_1.z.string(),
|
|
152
|
+
}))
|
|
153
|
+
.query(async ({ input }) => {
|
|
154
|
+
return (0, _trpc_1.handleTRPCResult)(await authService.validateWaitlistCode(input.code));
|
|
155
|
+
}),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getActiveOrganizationAndTeam = getActiveOrganizationAndTeam;
|
|
4
|
+
exports.createOrganizationAndTeam = createOrganizationAndTeam;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const drizzle_orm_1 = require("drizzle-orm");
|
|
7
|
+
const uuid_1 = require("uuid");
|
|
8
|
+
const auth = tslib_1.__importStar(require("#modules/auth/auth.db"));
|
|
9
|
+
const schema = { ...auth };
|
|
10
|
+
async function getActiveOrganizationAndTeam(orm, schema, userId) {
|
|
11
|
+
let organizationId;
|
|
12
|
+
let teamId;
|
|
13
|
+
let organizationRole;
|
|
14
|
+
let teamRole;
|
|
15
|
+
const [lastSession] = await orm
|
|
16
|
+
.select({
|
|
17
|
+
activeOrganizationId: schema.sessions.activeOrganizationId,
|
|
18
|
+
activeTeamId: schema.sessions.activeTeamId,
|
|
19
|
+
activeOrganizationRole: schema.sessions.activeOrganizationRole,
|
|
20
|
+
activeTeamRole: schema.sessions.activeTeamRole,
|
|
21
|
+
})
|
|
22
|
+
.from(schema.sessions)
|
|
23
|
+
.where((0, drizzle_orm_1.eq)(schema.sessions.userId, userId))
|
|
24
|
+
.orderBy((0, drizzle_orm_1.desc)(schema.sessions.createdAt))
|
|
25
|
+
.limit(1);
|
|
26
|
+
if (lastSession) {
|
|
27
|
+
organizationId = lastSession.activeOrganizationId ?? undefined;
|
|
28
|
+
teamId = lastSession.activeTeamId ?? undefined;
|
|
29
|
+
organizationRole = lastSession.activeOrganizationRole ?? undefined;
|
|
30
|
+
teamRole = lastSession.activeTeamRole ?? undefined;
|
|
31
|
+
}
|
|
32
|
+
if (!organizationId || !organizationRole) {
|
|
33
|
+
const [member] = await orm
|
|
34
|
+
.select({ organizationId: schema.members.organizationId, role: schema.members.role })
|
|
35
|
+
.from(schema.members)
|
|
36
|
+
.orderBy((0, drizzle_orm_1.desc)(schema.members.createdAt))
|
|
37
|
+
.where((0, drizzle_orm_1.eq)(schema.members.userId, userId))
|
|
38
|
+
.limit(1);
|
|
39
|
+
organizationId = member?.organizationId;
|
|
40
|
+
organizationRole = member?.role;
|
|
41
|
+
}
|
|
42
|
+
if (!teamId || !teamRole) {
|
|
43
|
+
const [teamMember] = await orm
|
|
44
|
+
.select({ teamId: schema.teamMembers.teamId, role: schema.teamMembers.role })
|
|
45
|
+
.from(schema.teamMembers)
|
|
46
|
+
.orderBy((0, drizzle_orm_1.desc)(schema.teamMembers.createdAt))
|
|
47
|
+
.where((0, drizzle_orm_1.eq)(schema.teamMembers.userId, userId))
|
|
48
|
+
.limit(1);
|
|
49
|
+
teamId = teamMember?.teamId;
|
|
50
|
+
teamRole = teamMember?.role;
|
|
51
|
+
}
|
|
52
|
+
return { organizationId, teamId, organizationRole, teamRole };
|
|
53
|
+
}
|
|
54
|
+
async function createOrganizationAndTeam(orm, schema, user) {
|
|
55
|
+
const organizationId = (0, uuid_1.v4)();
|
|
56
|
+
await orm.transaction(async (tx) => {
|
|
57
|
+
const [organization] = await tx
|
|
58
|
+
.insert(schema.organizations)
|
|
59
|
+
.values({
|
|
60
|
+
id: organizationId,
|
|
61
|
+
name: organizationId,
|
|
62
|
+
slug: organizationId,
|
|
63
|
+
})
|
|
64
|
+
.returning();
|
|
65
|
+
if (!organization)
|
|
66
|
+
throw new Error("createOrganizationAndTeam: Failed to create organization");
|
|
67
|
+
const [member] = await tx
|
|
68
|
+
.insert(schema.members)
|
|
69
|
+
.values({
|
|
70
|
+
userId: user.id,
|
|
71
|
+
organizationId: organization.id,
|
|
72
|
+
role: "owner",
|
|
73
|
+
})
|
|
74
|
+
.returning();
|
|
75
|
+
if (!member)
|
|
76
|
+
throw new Error("createOrganizationAndTeam: Failed to create member");
|
|
77
|
+
const [team] = await tx
|
|
78
|
+
.insert(schema.teams)
|
|
79
|
+
.values({
|
|
80
|
+
name: organization.id,
|
|
81
|
+
organizationId: organization.id,
|
|
82
|
+
})
|
|
83
|
+
.returning();
|
|
84
|
+
if (!team)
|
|
85
|
+
throw new Error("createOrganizationAndTeam: Failed to create team");
|
|
86
|
+
const [teamMember] = await tx
|
|
87
|
+
.insert(schema.teamMembers)
|
|
88
|
+
.values({
|
|
89
|
+
userId: user.id,
|
|
90
|
+
teamId: team.id,
|
|
91
|
+
role: "owner",
|
|
92
|
+
})
|
|
93
|
+
.returning();
|
|
94
|
+
if (!teamMember)
|
|
95
|
+
throw new Error("createOrganizationAndTeam: Failed to create team member");
|
|
96
|
+
});
|
|
97
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Base = void 0;
|
|
4
|
+
const neverthrow_1 = require("neverthrow");
|
|
5
|
+
const errors_1 = require("#utils/errors");
|
|
6
|
+
const logger_1 = require("#utils/logger");
|
|
7
|
+
class Base {
|
|
8
|
+
layer;
|
|
9
|
+
logger;
|
|
10
|
+
constructor(layer) {
|
|
11
|
+
this.layer = layer;
|
|
12
|
+
this.logger = logger_1.logger.child({ layer: this.layer, layerName: this.constructor.name });
|
|
13
|
+
}
|
|
14
|
+
error(code, message, { cause, clientMessage, log = process.env.NODE_ENV === "development", } = {}) {
|
|
15
|
+
const serverError = new errors_1.ServerError({
|
|
16
|
+
code,
|
|
17
|
+
layer: this.layer,
|
|
18
|
+
layerName: this.constructor.name,
|
|
19
|
+
message,
|
|
20
|
+
clientMessage,
|
|
21
|
+
cause,
|
|
22
|
+
captureBoundary: true,
|
|
23
|
+
});
|
|
24
|
+
if (serverError.is5xxError())
|
|
25
|
+
(0, errors_1.reportError)(serverError);
|
|
26
|
+
if (log)
|
|
27
|
+
logger_1.logger.error(serverError);
|
|
28
|
+
return (0, neverthrow_1.err)(serverError);
|
|
29
|
+
}
|
|
30
|
+
handleUnknownError(error) {
|
|
31
|
+
return errors_1.ServerError.fromUnknown("INTERNAL_SERVER_ERROR", error, {
|
|
32
|
+
layer: this.layer,
|
|
33
|
+
layerName: this.constructor.name,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
throwable(fn) {
|
|
37
|
+
try {
|
|
38
|
+
return fn();
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
return (0, neverthrow_1.err)(this.handleUnknownError(error));
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async throwableAsync(fn) {
|
|
45
|
+
try {
|
|
46
|
+
return fn();
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
return (0, neverthrow_1.err)(this.handleUnknownError(error));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
exports.Base = Base;
|