@m5kdev/backend 0.1.1 → 0.1.2

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.
Files changed (113) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/CHANGELOG.md +9 -0
  3. package/dist/src/lib/posthog.js +7 -0
  4. package/dist/src/lib/sentry.js +9 -0
  5. package/dist/src/modules/access/access.repository.js +32 -0
  6. package/dist/src/modules/access/access.service.js +51 -0
  7. package/dist/src/modules/access/access.test.js +182 -0
  8. package/dist/src/modules/access/access.utils.js +20 -0
  9. package/dist/src/modules/ai/ai.db.js +39 -0
  10. package/dist/src/modules/ai/ai.prompt.js +30 -0
  11. package/dist/src/modules/ai/ai.repository.js +26 -0
  12. package/dist/src/modules/ai/ai.router.js +132 -0
  13. package/dist/src/modules/ai/ai.service.js +207 -0
  14. package/dist/src/modules/ai/ai.trpc.d.ts +5 -5
  15. package/dist/src/modules/ai/ai.trpc.js +20 -0
  16. package/dist/src/modules/ai/ideogram/ideogram.constants.js +167 -0
  17. package/dist/src/modules/ai/ideogram/ideogram.dto.js +49 -0
  18. package/dist/src/modules/ai/ideogram/ideogram.prompt.js +860 -0
  19. package/dist/src/modules/ai/ideogram/ideogram.repository.js +46 -0
  20. package/dist/src/modules/ai/ideogram/ideogram.service.js +11 -0
  21. package/dist/src/modules/auth/auth.db.js +215 -0
  22. package/dist/src/modules/auth/auth.dto.js +38 -0
  23. package/dist/src/modules/auth/auth.lib.d.ts +4 -4
  24. package/dist/src/modules/auth/auth.lib.js +284 -0
  25. package/dist/src/modules/auth/auth.middleware.js +52 -0
  26. package/dist/src/modules/auth/auth.repository.js +541 -0
  27. package/dist/src/modules/auth/auth.service.js +201 -0
  28. package/dist/src/modules/auth/auth.trpc.d.ts +18 -18
  29. package/dist/src/modules/auth/auth.trpc.js +157 -0
  30. package/dist/src/modules/auth/auth.utils.js +97 -0
  31. package/dist/src/modules/base/base.abstract.js +53 -0
  32. package/dist/src/modules/base/base.dto.js +112 -0
  33. package/dist/src/modules/base/base.grants.js +123 -0
  34. package/dist/src/modules/base/base.grants.test.js +668 -0
  35. package/dist/src/modules/base/base.repository.js +307 -0
  36. package/dist/src/modules/base/base.service.js +109 -0
  37. package/dist/src/modules/base/base.types.js +2 -0
  38. package/dist/src/modules/billing/billing.db.js +29 -0
  39. package/dist/src/modules/billing/billing.repository.js +235 -0
  40. package/dist/src/modules/billing/billing.router.js +56 -0
  41. package/dist/src/modules/billing/billing.service.js +147 -0
  42. package/dist/src/modules/billing/billing.trpc.d.ts +5 -5
  43. package/dist/src/modules/billing/billing.trpc.js +17 -0
  44. package/dist/src/modules/clay/clay.repository.js +26 -0
  45. package/dist/src/modules/clay/clay.service.js +24 -0
  46. package/dist/src/modules/connect/connect.db.js +30 -0
  47. package/dist/src/modules/connect/connect.dto.js +36 -0
  48. package/dist/src/modules/connect/connect.linkedin.js +53 -0
  49. package/dist/src/modules/connect/connect.oauth.js +198 -0
  50. package/dist/src/modules/connect/connect.repository.d.ts +7 -7
  51. package/dist/src/modules/connect/connect.repository.js +54 -0
  52. package/dist/src/modules/connect/connect.router.js +54 -0
  53. package/dist/src/modules/connect/connect.service.d.ts +14 -14
  54. package/dist/src/modules/connect/connect.service.js +114 -0
  55. package/dist/src/modules/connect/connect.trpc.d.ts +10 -10
  56. package/dist/src/modules/connect/connect.trpc.js +21 -0
  57. package/dist/src/modules/connect/connect.types.js +2 -0
  58. package/dist/src/modules/crypto/crypto.db.js +17 -0
  59. package/dist/src/modules/crypto/crypto.repository.js +10 -0
  60. package/dist/src/modules/crypto/crypto.service.js +52 -0
  61. package/dist/src/modules/email/email.service.js +107 -0
  62. package/dist/src/modules/file/file.repository.js +79 -0
  63. package/dist/src/modules/file/file.router.js +99 -0
  64. package/dist/src/modules/file/file.service.js +150 -0
  65. package/dist/src/modules/recurrence/recurrence.db.js +66 -0
  66. package/dist/src/modules/recurrence/recurrence.repository.js +39 -0
  67. package/dist/src/modules/recurrence/recurrence.service.js +70 -0
  68. package/dist/src/modules/recurrence/recurrence.trpc.d.ts +15 -15
  69. package/dist/src/modules/recurrence/recurrence.trpc.js +65 -0
  70. package/dist/src/modules/social/social.dto.js +18 -0
  71. package/dist/src/modules/social/social.linkedin.js +427 -0
  72. package/dist/src/modules/social/social.linkedin.test.js +235 -0
  73. package/dist/src/modules/social/social.service.js +76 -0
  74. package/dist/src/modules/social/social.types.js +2 -0
  75. package/dist/src/modules/tag/tag.db.js +42 -0
  76. package/dist/src/modules/tag/tag.dto.js +9 -0
  77. package/dist/src/modules/tag/tag.repository.js +154 -0
  78. package/dist/src/modules/tag/tag.service.js +31 -0
  79. package/dist/src/modules/tag/tag.trpc.d.ts +5 -5
  80. package/dist/src/modules/tag/tag.trpc.js +47 -0
  81. package/dist/src/modules/utils/applyPagination.js +16 -0
  82. package/dist/src/modules/utils/applySorting.js +18 -0
  83. package/dist/src/modules/utils/getConditionsFromFilters.js +200 -0
  84. package/dist/src/modules/video/video.service.js +84 -0
  85. package/dist/src/modules/webhook/webhook.constants.js +10 -0
  86. package/dist/src/modules/webhook/webhook.db.js +17 -0
  87. package/dist/src/modules/webhook/webhook.dto.js +7 -0
  88. package/dist/src/modules/webhook/webhook.repository.js +56 -0
  89. package/dist/src/modules/webhook/webhook.router.js +30 -0
  90. package/dist/src/modules/webhook/webhook.service.js +68 -0
  91. package/dist/src/modules/workflow/workflow.db.js +30 -0
  92. package/dist/src/modules/workflow/workflow.repository.js +105 -0
  93. package/dist/src/modules/workflow/workflow.service.js +37 -0
  94. package/dist/src/modules/workflow/workflow.trpc.d.ts +5 -5
  95. package/dist/src/modules/workflow/workflow.trpc.js +21 -0
  96. package/dist/src/modules/workflow/workflow.types.js +2 -0
  97. package/dist/src/modules/workflow/workflow.utils.js +173 -0
  98. package/dist/src/test/stubs/utils.js +5 -0
  99. package/dist/src/trpc/context.d.ts +5 -5
  100. package/dist/src/trpc/context.js +17 -0
  101. package/dist/src/trpc/index.js +6 -0
  102. package/dist/src/trpc/procedures.d.ts +56 -56
  103. package/dist/src/trpc/procedures.js +32 -0
  104. package/dist/src/trpc/utils.js +20 -0
  105. package/dist/src/types.d.ts +33 -33
  106. package/dist/src/types.js +13 -0
  107. package/dist/src/utils/errors.js +104 -0
  108. package/dist/src/utils/logger.js +11 -0
  109. package/dist/src/utils/posthog.js +31 -0
  110. package/dist/src/utils/types.js +2 -0
  111. package/dist/tsconfig.tsbuildinfo +1 -1
  112. package/package.json +3 -3
  113. 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
- url: string;
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
- url: string;
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;