@goscribe/server 1.2.0 → 1.3.1

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 (126) hide show
  1. package/check-difficulty.cjs +14 -0
  2. package/check-questions.cjs +14 -0
  3. package/db-summary.cjs +22 -0
  4. package/dist/context.d.ts +5 -1
  5. package/dist/lib/activity_human_description.d.ts +13 -0
  6. package/dist/lib/activity_human_description.js +221 -0
  7. package/dist/lib/activity_human_description.test.d.ts +1 -0
  8. package/dist/lib/activity_human_description.test.js +16 -0
  9. package/dist/lib/activity_log_service.d.ts +87 -0
  10. package/dist/lib/activity_log_service.js +276 -0
  11. package/dist/lib/activity_log_service.test.d.ts +1 -0
  12. package/dist/lib/activity_log_service.test.js +27 -0
  13. package/dist/lib/ai-session.d.ts +15 -2
  14. package/dist/lib/ai-session.js +147 -85
  15. package/dist/lib/constants.d.ts +13 -0
  16. package/dist/lib/constants.js +12 -0
  17. package/dist/lib/email.d.ts +11 -0
  18. package/dist/lib/email.js +193 -0
  19. package/dist/lib/env.d.ts +13 -0
  20. package/dist/lib/env.js +16 -0
  21. package/dist/lib/inference.d.ts +4 -1
  22. package/dist/lib/inference.js +3 -3
  23. package/dist/lib/logger.d.ts +4 -4
  24. package/dist/lib/logger.js +30 -8
  25. package/dist/lib/notification-service.d.ts +152 -0
  26. package/dist/lib/notification-service.js +473 -0
  27. package/dist/lib/notification-service.test.d.ts +1 -0
  28. package/dist/lib/notification-service.test.js +87 -0
  29. package/dist/lib/prisma.d.ts +2 -1
  30. package/dist/lib/prisma.js +5 -1
  31. package/dist/lib/pusher.d.ts +23 -0
  32. package/dist/lib/pusher.js +69 -5
  33. package/dist/lib/retry.d.ts +15 -0
  34. package/dist/lib/retry.js +37 -0
  35. package/dist/lib/storage.js +2 -2
  36. package/dist/lib/stripe.d.ts +9 -0
  37. package/dist/lib/stripe.js +36 -0
  38. package/dist/lib/subscription_service.d.ts +37 -0
  39. package/dist/lib/subscription_service.js +654 -0
  40. package/dist/lib/usage_service.d.ts +26 -0
  41. package/dist/lib/usage_service.js +59 -0
  42. package/dist/lib/worksheet-generation.d.ts +91 -0
  43. package/dist/lib/worksheet-generation.js +95 -0
  44. package/dist/lib/worksheet-generation.test.d.ts +1 -0
  45. package/dist/lib/worksheet-generation.test.js +20 -0
  46. package/dist/lib/workspace-access.d.ts +18 -0
  47. package/dist/lib/workspace-access.js +13 -0
  48. package/dist/routers/_app.d.ts +1349 -253
  49. package/dist/routers/_app.js +10 -0
  50. package/dist/routers/admin.d.ts +361 -0
  51. package/dist/routers/admin.js +633 -0
  52. package/dist/routers/annotations.d.ts +219 -0
  53. package/dist/routers/annotations.js +187 -0
  54. package/dist/routers/auth.d.ts +88 -7
  55. package/dist/routers/auth.js +339 -19
  56. package/dist/routers/chat.d.ts +6 -12
  57. package/dist/routers/copilot.d.ts +199 -0
  58. package/dist/routers/copilot.js +571 -0
  59. package/dist/routers/flashcards.d.ts +47 -81
  60. package/dist/routers/flashcards.js +143 -27
  61. package/dist/routers/members.d.ts +36 -7
  62. package/dist/routers/members.js +200 -19
  63. package/dist/routers/notifications.d.ts +99 -0
  64. package/dist/routers/notifications.js +127 -0
  65. package/dist/routers/payment.d.ts +89 -0
  66. package/dist/routers/payment.js +403 -0
  67. package/dist/routers/podcast.d.ts +8 -13
  68. package/dist/routers/podcast.js +54 -31
  69. package/dist/routers/studyguide.d.ts +1 -29
  70. package/dist/routers/studyguide.js +80 -71
  71. package/dist/routers/worksheets.d.ts +105 -38
  72. package/dist/routers/worksheets.js +258 -68
  73. package/dist/routers/workspace.d.ts +139 -60
  74. package/dist/routers/workspace.js +455 -315
  75. package/dist/scripts/purge-deleted-users.d.ts +1 -0
  76. package/dist/scripts/purge-deleted-users.js +149 -0
  77. package/dist/server.js +130 -10
  78. package/dist/services/flashcard-progress.service.d.ts +18 -66
  79. package/dist/services/flashcard-progress.service.js +51 -42
  80. package/dist/trpc.d.ts +20 -21
  81. package/dist/trpc.js +150 -1
  82. package/mcq-test.cjs +36 -0
  83. package/package.json +9 -2
  84. package/prisma/migrations/20260413143206_init/migration.sql +873 -0
  85. package/prisma/schema.prisma +471 -324
  86. package/src/context.ts +4 -1
  87. package/src/lib/activity_human_description.test.ts +28 -0
  88. package/src/lib/activity_human_description.ts +239 -0
  89. package/src/lib/activity_log_service.test.ts +37 -0
  90. package/src/lib/activity_log_service.ts +353 -0
  91. package/src/lib/ai-session.ts +79 -51
  92. package/src/lib/email.ts +213 -29
  93. package/src/lib/env.ts +23 -6
  94. package/src/lib/inference.ts +2 -2
  95. package/src/lib/notification-service.test.ts +106 -0
  96. package/src/lib/notification-service.ts +677 -0
  97. package/src/lib/prisma.ts +6 -1
  98. package/src/lib/pusher.ts +86 -2
  99. package/src/lib/stripe.ts +39 -0
  100. package/src/lib/subscription_service.ts +722 -0
  101. package/src/lib/usage_service.ts +74 -0
  102. package/src/lib/worksheet-generation.test.ts +31 -0
  103. package/src/lib/worksheet-generation.ts +139 -0
  104. package/src/routers/_app.ts +9 -0
  105. package/src/routers/admin.ts +710 -0
  106. package/src/routers/annotations.ts +41 -0
  107. package/src/routers/auth.ts +338 -28
  108. package/src/routers/copilot.ts +719 -0
  109. package/src/routers/flashcards.ts +201 -68
  110. package/src/routers/members.ts +280 -80
  111. package/src/routers/notifications.ts +142 -0
  112. package/src/routers/payment.ts +448 -0
  113. package/src/routers/podcast.ts +112 -83
  114. package/src/routers/studyguide.ts +12 -0
  115. package/src/routers/worksheets.ts +289 -66
  116. package/src/routers/workspace.ts +329 -122
  117. package/src/scripts/purge-deleted-users.ts +167 -0
  118. package/src/server.ts +137 -11
  119. package/src/services/flashcard-progress.service.ts +49 -37
  120. package/src/trpc.ts +184 -5
  121. package/test-generate.js +30 -0
  122. package/test-ratio.cjs +9 -0
  123. package/zod-test.cjs +22 -0
  124. package/prisma/migrations/20250826124819_add_worksheet_difficulty_and_estimated_time/migration.sql +0 -213
  125. package/prisma/migrations/20250826133236_add_worksheet_question_progress/migration.sql +0 -31
  126. package/prisma/seed.mjs +0 -135
package/src/lib/pusher.ts CHANGED
@@ -12,6 +12,16 @@ export const pusher = new Pusher({
12
12
 
13
13
  // Pusher service for managing notifications
14
14
  export class PusherService {
15
+ static async emitUserEvent(userId: string, eventName: string, data: any) {
16
+ try {
17
+ const channel = `user_${userId}`;
18
+ await pusher.trigger(channel, eventName, data);
19
+ logger.info(`📡 Pusher user event sent: ${eventName} to ${channel}`);
20
+ } catch (error) {
21
+ logger.error('Pusher user event error:', 'PUSHER', { error, userId, eventName });
22
+ }
23
+ }
24
+
15
25
  // Emit task completion notification
16
26
  static async emitTaskComplete(workspaceId: string, event: string, data: any) {
17
27
  try {
@@ -35,7 +45,7 @@ export class PusherService {
35
45
 
36
46
  // Emit study guide completion
37
47
  static async emitStudyGuideComplete(workspaceId: string, artifact: any) {
38
- await this.emitAnalysisComplete(workspaceId, 'studyguide', {
48
+ await this.emitTaskComplete(workspaceId, 'study_guide_generation_complete', {
39
49
  artifactId: artifact.id,
40
50
  title: artifact.title,
41
51
  status: 'completed'
@@ -60,6 +70,21 @@ export class PusherService {
60
70
  });
61
71
  }
62
72
 
73
+ // Emit worksheet generation start notification
74
+ static async emitWorksheetGenerationStart(workspaceId: string) {
75
+ await this.emitTaskComplete(workspaceId, 'worksheet_generation_start', {});
76
+ }
77
+
78
+ // Emit new worksheet notification
79
+ static async emitWorksheetNew(workspaceId: string, worksheet: any) {
80
+ await this.emitTaskComplete(workspaceId, 'worksheet_new', { worksheet });
81
+ }
82
+
83
+ // Emit worksheet generation completion notification
84
+ static async emitWorksheetGenerationComplete(workspaceId: string, worksheet: any) {
85
+ await this.emitTaskComplete(workspaceId, 'worksheet_generation_complete', { worksheet });
86
+ }
87
+
63
88
  // Emit podcast completion
64
89
  static async emitPodcastComplete(workspaceId: string, artifact: any) {
65
90
  await this.emitAnalysisComplete(workspaceId, 'podcast', {
@@ -81,7 +106,7 @@ export class PusherService {
81
106
  // Emit error notification
82
107
  static async emitError(workspaceId: string, error: string, analysisType?: string) {
83
108
  const event = analysisType ? `${analysisType}_error` : 'analysis_error';
84
-
109
+
85
110
  await this.emitTaskComplete(workspaceId, event, {
86
111
  error,
87
112
  analysisType,
@@ -111,6 +136,65 @@ export class PusherService {
111
136
  logger.error('Pusher channel notification error:', 'PUSHER', { error });
112
137
  }
113
138
  }
139
+
140
+ // Emit member joined notification
141
+ static async emitMemberJoined(workspaceId: string, member: any) {
142
+ await this.emitTaskComplete(workspaceId, 'member_joined', { member });
143
+ }
144
+
145
+ // Emit profile update notification
146
+ static async emitProfileUpdate(userId: string) {
147
+ await this.emitUserEvent(userId, 'profile_updated', {
148
+ userId,
149
+ timestamp: new Date().toISOString(),
150
+ });
151
+ }
152
+
153
+ // Emit library (folders/workspaces) update notification
154
+ static async emitLibraryUpdate(userId: string) {
155
+ await this.emitUserEvent(userId, 'library_updated', {
156
+ userId,
157
+ timestamp: new Date().toISOString(),
158
+ });
159
+ }
160
+
161
+ static async emitNotificationNew(
162
+ userId: string,
163
+ data: {
164
+ notificationId: string;
165
+ type: string;
166
+ title: string;
167
+ unreadCount: number;
168
+ createdAt: string;
169
+ },
170
+ ) {
171
+ await this.emitUserEvent(userId, 'notification_new', data);
172
+ }
173
+
174
+ static async emitNotificationReadState(
175
+ userId: string,
176
+ data: { unreadCount: number; timestamp?: string },
177
+ ) {
178
+ await this.emitUserEvent(userId, 'notification_read_state_changed', {
179
+ ...data,
180
+ timestamp: data.timestamp ?? new Date().toISOString(),
181
+ });
182
+ }
183
+
184
+ // Emit payment success (top-up or subscription)
185
+ static async emitPaymentSuccess(userId: string, data: { type: 'topup' | 'subscription', resourceType?: string, quantity?: string }) {
186
+ try {
187
+ const channel = `user_${userId}`;
188
+ const eventName = 'payment_success';
189
+ await pusher.trigger(channel, eventName, {
190
+ ...data,
191
+ timestamp: new Date().toISOString(),
192
+ });
193
+ logger.info(`📡 Pusher payment success sent: ${eventName} to ${channel}`);
194
+ } catch (error) {
195
+ logger.error('Pusher payment success error:', 'PUSHER', { error });
196
+ }
197
+ }
114
198
  }
115
199
 
116
200
  export default PusherService;
@@ -0,0 +1,39 @@
1
+ import Stripe from 'stripe';
2
+ import { env } from './env.js';
3
+ import { logger } from './logger.js';
4
+
5
+ if (!env.STRIPE_SECRET_KEY) {
6
+ logger.warn('STRIPE_SECRET_KEY is not set. Stripe functionality will be disabled.', 'STRIPE');
7
+ }
8
+
9
+ export const stripe = env.STRIPE_SECRET_KEY
10
+ ? new Stripe(env.STRIPE_SECRET_KEY, {
11
+ apiVersion: '2026-02-25.clover' as any,
12
+ })
13
+ : null;
14
+
15
+ /**
16
+ * Creates a Stripe customer for a user.
17
+ *
18
+ * @param email - User's email
19
+ * @param name - User's name
20
+ * @returns The Stripe customer ID
21
+ */
22
+ export async function createStripeCustomer(email: string, name?: string): Promise<string | null> {
23
+ if (!stripe) {
24
+ logger.error('Stripe is not initialized. Cannot create customer.', 'STRIPE');
25
+ return null;
26
+ }
27
+
28
+ try {
29
+ const customer = await stripe.customers.create({
30
+ email,
31
+ name,
32
+ });
33
+ logger.info(`Stripe customer created for ${email}: ${customer.id}`, 'STRIPE');
34
+ return customer.id;
35
+ } catch (error: any) {
36
+ logger.error(`Failed to create Stripe customer for ${email}: ${error.message}`, 'STRIPE');
37
+ return null;
38
+ }
39
+ }