@goscribe/server 1.1.2 → 1.1.4
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/lib/ai-session.d.ts +13 -3
- package/dist/lib/ai-session.js +66 -146
- package/dist/lib/pusher.js +1 -1
- package/dist/routers/_app.d.ts +114 -7
- package/dist/routers/chat.js +2 -23
- package/dist/routers/flashcards.d.ts +25 -1
- package/dist/routers/flashcards.js +0 -14
- package/dist/routers/members.d.ts +18 -0
- package/dist/routers/members.js +14 -1
- package/dist/routers/worksheets.js +5 -4
- package/dist/routers/workspace.d.ts +89 -6
- package/dist/routers/workspace.js +389 -259
- package/dist/services/flashcard-progress.service.d.ts +25 -1
- package/dist/services/flashcard-progress.service.js +70 -31
- package/package.json +3 -2
- package/prisma/schema.prisma +196 -184
- package/src/lib/ai-session.ts +3 -21
- package/src/routers/auth.ts +50 -2
- package/src/routers/flashcards.ts +0 -16
- package/src/routers/members.ts +27 -6
- package/src/routers/workspace.ts +468 -439
- package/src/server.ts +13 -0
- package/ANALYSIS_PROGRESS_SPEC.md +0 -463
- package/PROGRESS_QUICK_REFERENCE.md +0 -239
- package/dist/lib/podcast-prompts.d.ts +0 -43
- package/dist/lib/podcast-prompts.js +0 -135
- package/dist/routers/ai-session.d.ts +0 -0
- package/dist/routers/ai-session.js +0 -1
- package/dist/services/flashcard.service.d.ts +0 -183
- package/dist/services/flashcard.service.js +0 -224
- package/dist/services/podcast-segment-reorder.d.ts +0 -0
- package/dist/services/podcast-segment-reorder.js +0 -107
- package/dist/services/podcast.service.d.ts +0 -0
- package/dist/services/podcast.service.js +0 -326
- package/dist/services/worksheet.service.d.ts +0 -0
- package/dist/services/worksheet.service.js +0 -295
package/src/routers/auth.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { router, publicProcedure, authedProcedure } from '../trpc.js';
|
|
|
3
3
|
import bcrypt from 'bcryptjs';
|
|
4
4
|
import { serialize } from 'cookie';
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
|
+
import { TRPCError } from '@trpc/server';
|
|
7
|
+
import { supabaseClient } from 'src/lib/storage.js';
|
|
6
8
|
|
|
7
9
|
// Helper to create custom auth token
|
|
8
10
|
function createCustomAuthToken(userId: string): string {
|
|
@@ -19,6 +21,54 @@ function createCustomAuthToken(userId: string): string {
|
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
export const auth = router({
|
|
24
|
+
updateProfile: publicProcedure
|
|
25
|
+
.input(z.object({
|
|
26
|
+
name: z.string().min(1),
|
|
27
|
+
}))
|
|
28
|
+
.mutation(async ({ctx, input}) => {
|
|
29
|
+
const { name } = input;
|
|
30
|
+
|
|
31
|
+
await ctx.db.user.update({
|
|
32
|
+
where: {
|
|
33
|
+
id: ctx.session.user.id,
|
|
34
|
+
},
|
|
35
|
+
data: {
|
|
36
|
+
name: name,
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
message: 'Profile updated successfully',
|
|
43
|
+
};
|
|
44
|
+
}),
|
|
45
|
+
uploadProfilePicture: publicProcedure
|
|
46
|
+
.mutation(async ({ctx, input}) => {
|
|
47
|
+
const objectKey = `profile_picture_${ctx.session.user.id}`;
|
|
48
|
+
const { data: signedUrlData, error: signedUrlError } = await supabaseClient.storage
|
|
49
|
+
.from('media')
|
|
50
|
+
.createSignedUploadUrl(objectKey); // 5 minutes
|
|
51
|
+
if (signedUrlError) {
|
|
52
|
+
throw new TRPCError({ code: 'INTERNAL_SERVER_ERROR', message: `Failed to generate upload URL: ${signedUrlError.message}` });
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
await ctx.db.fileAsset.create({
|
|
56
|
+
data: {
|
|
57
|
+
userId: ctx.session.user.id,
|
|
58
|
+
name: 'Profile Picture',
|
|
59
|
+
mimeType: 'image/jpeg',
|
|
60
|
+
size: 0,
|
|
61
|
+
bucket: 'media',
|
|
62
|
+
objectKey: objectKey,
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
return {
|
|
67
|
+
success: true,
|
|
68
|
+
message: 'Profile picture uploaded successfully',
|
|
69
|
+
signedUrl: signedUrlData.signedUrl,
|
|
70
|
+
};
|
|
71
|
+
}),
|
|
22
72
|
signup: publicProcedure
|
|
23
73
|
.input(z.object({
|
|
24
74
|
name: z.string().min(1),
|
|
@@ -85,7 +135,6 @@ export const auth = router({
|
|
|
85
135
|
id: user.id,
|
|
86
136
|
email: user.email,
|
|
87
137
|
name: user.name,
|
|
88
|
-
image: user.image,
|
|
89
138
|
token: authToken
|
|
90
139
|
};
|
|
91
140
|
}),
|
|
@@ -108,7 +157,6 @@ export const auth = router({
|
|
|
108
157
|
id: user.id,
|
|
109
158
|
email: user.email,
|
|
110
159
|
name: user.name,
|
|
111
|
-
image: user.image
|
|
112
160
|
}
|
|
113
161
|
};
|
|
114
162
|
}),
|
|
@@ -177,22 +177,6 @@ export const flashcards = router({
|
|
|
177
177
|
|
|
178
178
|
await PusherService.emitTaskComplete(input.workspaceId, 'flash_card_info', { status: 'generating', numCards: input.numCards, difficulty: input.difficulty });
|
|
179
179
|
|
|
180
|
-
const formattedPreviousCards = flashcardCurrent?.flashcards.map((card) => ({
|
|
181
|
-
front: card.front,
|
|
182
|
-
back: card.back,
|
|
183
|
-
}));
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
const partialPrompt = `
|
|
187
|
-
This is the users previous flashcards, avoid repeating any existing cards.
|
|
188
|
-
Please generate ${input.numCards} new cards,
|
|
189
|
-
Of a ${input.difficulty} difficulty,
|
|
190
|
-
Of a ${input.tags?.join(', ')} tag,
|
|
191
|
-
Of a ${input.title} title.
|
|
192
|
-
${formattedPreviousCards?.map((card) => `Front: ${card.front}\nBack: ${card.back}`).join('\n')}
|
|
193
|
-
|
|
194
|
-
The user has also left you this prompt: ${input.prompt}
|
|
195
|
-
`
|
|
196
180
|
const artifact = await ctx.db.artifact.create({
|
|
197
181
|
data: {
|
|
198
182
|
workspaceId: input.workspaceId,
|
package/src/routers/members.ts
CHANGED
|
@@ -38,7 +38,13 @@ export const members = router({
|
|
|
38
38
|
id: true,
|
|
39
39
|
name: true,
|
|
40
40
|
email: true,
|
|
41
|
-
|
|
41
|
+
profilePicture: {
|
|
42
|
+
select: {
|
|
43
|
+
id: true,
|
|
44
|
+
name: true,
|
|
45
|
+
url: true,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
42
48
|
}
|
|
43
49
|
},
|
|
44
50
|
members: {
|
|
@@ -48,7 +54,13 @@ export const members = router({
|
|
|
48
54
|
id: true,
|
|
49
55
|
name: true,
|
|
50
56
|
email: true,
|
|
51
|
-
|
|
57
|
+
profilePicture: {
|
|
58
|
+
select: {
|
|
59
|
+
id: true,
|
|
60
|
+
name: true,
|
|
61
|
+
url: true,
|
|
62
|
+
}
|
|
63
|
+
}
|
|
52
64
|
}
|
|
53
65
|
}
|
|
54
66
|
}
|
|
@@ -69,7 +81,6 @@ export const members = router({
|
|
|
69
81
|
id: workspace.owner.id,
|
|
70
82
|
name: workspace.owner.name || 'Unknown',
|
|
71
83
|
email: workspace.owner.email || '',
|
|
72
|
-
image: workspace.owner.image,
|
|
73
84
|
role: 'owner' as const,
|
|
74
85
|
joinedAt: workspace.createdAt,
|
|
75
86
|
},
|
|
@@ -77,7 +88,6 @@ export const members = router({
|
|
|
77
88
|
id: membership.user.id,
|
|
78
89
|
name: membership.user.name || 'Unknown',
|
|
79
90
|
email: membership.user.email || '',
|
|
80
|
-
image: membership.user.image,
|
|
81
91
|
role: membership.role as 'admin' | 'member',
|
|
82
92
|
joinedAt: membership.joinedAt,
|
|
83
93
|
}))
|
|
@@ -230,7 +240,16 @@ export const members = router({
|
|
|
230
240
|
invitedByName: invitation.workspace.owner.name || invitation.workspace.owner.email,
|
|
231
241
|
};
|
|
232
242
|
}),
|
|
233
|
-
|
|
243
|
+
getInvitations: authedProcedure
|
|
244
|
+
.input(z.object({
|
|
245
|
+
workspaceId: z.string(),
|
|
246
|
+
}))
|
|
247
|
+
.query(async ({ ctx, input }) => {
|
|
248
|
+
const invitations = await ctx.db.workspaceInvitation.findMany({
|
|
249
|
+
where: { workspaceId: input.workspaceId },
|
|
250
|
+
});
|
|
251
|
+
return invitations;
|
|
252
|
+
}),
|
|
234
253
|
/**
|
|
235
254
|
* Accept an invitation (public endpoint)
|
|
236
255
|
*/
|
|
@@ -277,8 +296,10 @@ export const members = router({
|
|
|
277
296
|
});
|
|
278
297
|
}
|
|
279
298
|
|
|
299
|
+
const user = await ctx.db.user.findFirst({ where: { id: ctx.session.user.id } });
|
|
300
|
+
if (!user || !user.email) throw new TRPCError({ code: 'NOT_FOUND' });
|
|
280
301
|
// Check if the email matches the user's email
|
|
281
|
-
if (
|
|
302
|
+
if (user.email !== invitation.email) {
|
|
282
303
|
throw new TRPCError({
|
|
283
304
|
code: 'BAD_REQUEST',
|
|
284
305
|
message: 'This invitation was sent to a different email address'
|