@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/dist/lib/env.js CHANGED
@@ -27,11 +27,27 @@ const envSchema = z.object({
27
27
  INFERENCE_API_URL: z.string().url().optional(),
28
28
  // CORS
29
29
  FRONTEND_URL: z.string().url().default('http://localhost:3000'),
30
+ // Email
31
+ SMTP_HOST: z.string(),
32
+ SMTP_PORT: z.string().regex(/^\d+$/).default('587').transform(Number),
33
+ SMTP_USER: z.string().optional(),
34
+ SMTP_PASSWORD: z.string().optional(),
35
+ SMTP_SECURE: z.enum(['true', 'false']).default('false').transform((v) => v === 'true'),
36
+ EMAIL_FROM: z.string().default('Scribe <noreply@goscribe.app>'),
37
+ // Stripe
38
+ STRIPE_SECRET_KEY: z.string().startsWith('sk_').optional(),
39
+ STRIPE_SUCCESS_URL: z.string().url().default('http://localhost:3000/payment-success'),
40
+ STRIPE_CANCEL_URL: z.string().url().default('http://localhost:3000/payment-cancel'),
41
+ STRIPE_PRICE_SUB_BASIC: z.string().startsWith('price_').optional(),
42
+ STRIPE_PRICE_SUB_PRO: z.string().startsWith('price_').optional(),
43
+ STRIPE_PRICE_CREDITS_1000: z.string().startsWith('price_').optional(),
44
+ STRIPE_WEBHOOK_SECRET: z.string().startsWith('whsec_').optional(),
30
45
  });
31
46
  /**
32
47
  * Parsed and validated environment variables
33
48
  */
34
49
  export const env = envSchema.parse(process.env);
50
+ // console.log('DEBUG: SMTP_HOST loaded:', env.SMTP_HOST ? 'Yes' : 'No');
35
51
  /**
36
52
  * Check if running in production
37
53
  */
@@ -1,5 +1,8 @@
1
1
  import OpenAI from 'openai';
2
- declare function inference(prompt: string): Promise<OpenAI.Chat.Completions.ChatCompletion & {
2
+ declare function inference(messages: {
3
+ role: 'system' | 'user' | 'assistant';
4
+ content: string;
5
+ }[]): Promise<OpenAI.Chat.Completions.ChatCompletion & {
3
6
  _request_id?: string | null;
4
7
  }>;
5
8
  export default inference;
@@ -3,16 +3,16 @@ const openai = new OpenAI({
3
3
  apiKey: process.env.INFERENCE_API_KEY,
4
4
  baseURL: process.env.INFERENCE_BASE_URL,
5
5
  });
6
- async function inference(prompt) {
6
+ async function inference(messages) {
7
7
  try {
8
8
  const response = await openai.chat.completions.create({
9
9
  model: "command-a-03-2025",
10
- messages: [{ role: "user", content: prompt }],
10
+ messages: messages,
11
11
  });
12
12
  return response;
13
13
  }
14
14
  catch (error) {
15
- console.error('Inference error:', error);
15
+ // Inference error logged at call site
16
16
  throw error;
17
17
  }
18
18
  }
@@ -40,10 +40,10 @@ declare class Logger {
40
40
  private formatValue;
41
41
  private formatError;
42
42
  private log;
43
- error(message: string, context?: string, metadata?: Record<string, any>, error?: Error): void;
44
- warn(message: string, context?: string, metadata?: Record<string, any>): void;
45
- info(message: string, context?: string, metadata?: Record<string, any>): void;
46
- debug(message: string, context?: string, metadata?: Record<string, any>): void;
43
+ error(message: string, contextOrError?: string | Error | unknown, metadata?: Record<string, any>, error?: Error): void;
44
+ warn(message: string, contextOrMeta?: string | Record<string, any>, metadata?: Record<string, any>): void;
45
+ info(message: string, contextOrMeta?: string | Record<string, any>, metadata?: Record<string, any>): void;
46
+ debug(message: string, contextOrMeta?: string | Record<string, any>, metadata?: Record<string, any>): void;
47
47
  trace(message: string, context?: string, metadata?: Record<string, any>): void;
48
48
  http(method: string, url: string, statusCode: number, responseTime?: number, context?: string): void;
49
49
  private getHttpStatusIcon;
@@ -125,6 +125,8 @@ class Logger {
125
125
  return `\x1b[90m${time}\x1b[0m`; // Gray color
126
126
  }
127
127
  formatContext(context) {
128
+ if (typeof context !== 'string')
129
+ return '';
128
130
  const icon = CONTEXT_ICONS[context.toUpperCase()] || '📦';
129
131
  return `\x1b[94m${icon}${context}\x1b[0m `; // Blue color
130
132
  }
@@ -201,17 +203,37 @@ class Logger {
201
203
  this.logStream.write(formattedLog + '\n');
202
204
  }
203
205
  }
204
- error(message, context, metadata, error) {
205
- this.log(LogLevel.ERROR, message, context, metadata, error);
206
+ error(message, contextOrError, metadata, error) {
207
+ if (contextOrError instanceof Error) {
208
+ this.log(LogLevel.ERROR, message, undefined, metadata, contextOrError);
209
+ }
210
+ else {
211
+ this.log(LogLevel.ERROR, message, contextOrError, metadata, error);
212
+ }
206
213
  }
207
- warn(message, context, metadata) {
208
- this.log(LogLevel.WARN, message, context, metadata);
214
+ warn(message, contextOrMeta, metadata) {
215
+ if (typeof contextOrMeta === 'object' && contextOrMeta !== null) {
216
+ this.log(LogLevel.WARN, message, undefined, contextOrMeta);
217
+ }
218
+ else {
219
+ this.log(LogLevel.WARN, message, contextOrMeta, metadata);
220
+ }
209
221
  }
210
- info(message, context, metadata) {
211
- this.log(LogLevel.INFO, message, context, metadata);
222
+ info(message, contextOrMeta, metadata) {
223
+ if (typeof contextOrMeta === 'object' && contextOrMeta !== null) {
224
+ this.log(LogLevel.INFO, message, undefined, contextOrMeta);
225
+ }
226
+ else {
227
+ this.log(LogLevel.INFO, message, contextOrMeta, metadata);
228
+ }
212
229
  }
213
- debug(message, context, metadata) {
214
- this.log(LogLevel.DEBUG, message, context, metadata);
230
+ debug(message, contextOrMeta, metadata) {
231
+ if (typeof contextOrMeta === 'object' && contextOrMeta !== null) {
232
+ this.log(LogLevel.DEBUG, message, undefined, contextOrMeta);
233
+ }
234
+ else {
235
+ this.log(LogLevel.DEBUG, message, contextOrMeta, metadata);
236
+ }
215
237
  }
216
238
  trace(message, context, metadata) {
217
239
  this.log(LogLevel.TRACE, message, context, metadata);
@@ -0,0 +1,152 @@
1
+ type NotificationPriority = 'LOW' | 'NORMAL' | 'HIGH';
2
+ export declare const NotificationType: {
3
+ readonly GENERAL: "GENERAL";
4
+ readonly USER_SIGNED_UP: "USER_SIGNED_UP";
5
+ readonly ACCOUNT_DELETION_SCHEDULED: "ACCOUNT_DELETION_SCHEDULED";
6
+ readonly ACCOUNT_PERMANENTLY_DELETED: "ACCOUNT_PERMANENTLY_DELETED";
7
+ readonly WORKSPACE_INVITE_RECEIVED: "WORKSPACE_INVITE_RECEIVED";
8
+ readonly WORKSPACE_INVITE_ACCEPTED: "WORKSPACE_INVITE_ACCEPTED";
9
+ readonly WORKSPACE_DELETED: "WORKSPACE_DELETED";
10
+ readonly PAYMENT_SUCCEEDED: "PAYMENT_SUCCEEDED";
11
+ readonly SUBSCRIPTION_ACTIVATED: "SUBSCRIPTION_ACTIVATED";
12
+ readonly SUBSCRIPTION_PAYMENT_SUCCEEDED: "SUBSCRIPTION_PAYMENT_SUCCEEDED";
13
+ readonly SUBSCRIPTION_CANCELED: "SUBSCRIPTION_CANCELED";
14
+ readonly PAYMENT_FAILED: "PAYMENT_FAILED";
15
+ readonly WORKSPACE_ROLE_CHANGED: "WORKSPACE_ROLE_CHANGED";
16
+ readonly WORKSPACE_MEMBERSHIP_REMOVED: "WORKSPACE_MEMBERSHIP_REMOVED";
17
+ readonly STUDY_GUIDE_COMMENT_ADDED: "STUDY_GUIDE_COMMENT_ADDED";
18
+ readonly ARTIFACT_READY: "ARTIFACT_READY";
19
+ readonly ARTIFACT_FAILED: "ARTIFACT_FAILED";
20
+ };
21
+ export declare function artifactTypeLabel(artifactType: string): string;
22
+ export declare function buildArtifactActionUrl(workspaceId: string, artifactId: string | undefined, artifactType: string): string;
23
+ type CreateNotificationInput = {
24
+ userId: string;
25
+ type: string;
26
+ title: string;
27
+ body: string;
28
+ actorUserId?: string;
29
+ workspaceId?: string;
30
+ actionUrl?: string;
31
+ metadata?: Record<string, unknown>;
32
+ priority?: NotificationPriority;
33
+ sourceId?: string;
34
+ };
35
+ export declare function createNotification(db: any, input: CreateNotificationInput): Promise<any>;
36
+ export declare function createManyNotifications(db: any, inputs: CreateNotificationInput[]): Promise<any[]>;
37
+ export declare function getSystemAdminIds(db: any): Promise<any>;
38
+ export declare function notifyAdminsOnSignup(db: any, user: {
39
+ id: string;
40
+ name?: string | null;
41
+ email?: string | null;
42
+ }): Promise<void>;
43
+ export declare function notifyAdminsAccountDeletionScheduled(db: any, user: {
44
+ id: string;
45
+ name?: string | null;
46
+ email?: string | null;
47
+ }): Promise<void>;
48
+ export declare function notifyAdminsAccountPermanentlyDeleted(db: any, user: {
49
+ id: string;
50
+ name?: string | null;
51
+ email?: string | null;
52
+ }): Promise<void>;
53
+ export declare function notifyInviteRecipient(db: any, input: {
54
+ invitedUserId: string;
55
+ inviterUserId: string;
56
+ workspaceId: string;
57
+ workspaceTitle: string;
58
+ invitationId: string;
59
+ invitationToken: string;
60
+ inviterName?: string | null;
61
+ }): Promise<void>;
62
+ export declare function notifyInviteAccepted(db: any, input: {
63
+ recipientUserIds: string[];
64
+ actorUserId: string;
65
+ workspaceId: string;
66
+ workspaceTitle: string;
67
+ memberName?: string | null;
68
+ invitationId: string;
69
+ }): Promise<void>;
70
+ export declare function notifyWorkspaceDeleted(db: any, input: {
71
+ recipientUserIds: string[];
72
+ actorUserId: string;
73
+ actorName: string;
74
+ workspaceId: string;
75
+ workspaceTitle: string;
76
+ }): Promise<void>;
77
+ export declare function notifyPaymentSucceeded(db: any, input: {
78
+ userId: string;
79
+ planId?: string;
80
+ planName?: string;
81
+ stripeSessionId?: string;
82
+ amountPaid?: number;
83
+ }): Promise<void>;
84
+ export declare function notifySubscriptionActivated(db: any, input: {
85
+ userId: string;
86
+ planId?: string;
87
+ planName?: string;
88
+ stripeSubscriptionId: string;
89
+ }): Promise<void>;
90
+ export declare function notifySubscriptionPaymentSucceeded(db: any, input: {
91
+ userId: string;
92
+ planId?: string;
93
+ planName?: string;
94
+ stripeInvoiceId: string;
95
+ amountPaid?: number;
96
+ }): Promise<void>;
97
+ export declare function notifySubscriptionCanceled(db: any, input: {
98
+ userId: string;
99
+ planId?: string;
100
+ planName?: string;
101
+ stripeSubscriptionId: string;
102
+ }): Promise<void>;
103
+ export declare function notifyPaymentFailed(db: any, input: {
104
+ userId: string;
105
+ planId?: string;
106
+ planName?: string;
107
+ stripeInvoiceId?: string;
108
+ stripePaymentIntentId?: string;
109
+ }): Promise<void>;
110
+ export declare function notifyWorkspaceRoleChanged(db: any, input: {
111
+ memberUserId: string;
112
+ workspaceId: string;
113
+ workspaceTitle: string;
114
+ newRole: string;
115
+ oldRole: string;
116
+ actorUserId: string;
117
+ actorName: string;
118
+ }): Promise<void>;
119
+ export declare function notifyWorkspaceMembershipRemoved(db: any, input: {
120
+ memberUserId: string;
121
+ workspaceId: string;
122
+ workspaceTitle: string;
123
+ actorUserId: string;
124
+ actorName: string;
125
+ }): Promise<void>;
126
+ export declare function notifyStudyGuideCommentAdded(db: any, input: {
127
+ authorUserId: string;
128
+ authorName: string;
129
+ content: string;
130
+ highlightId: string;
131
+ commentId: string;
132
+ workspaceId: string;
133
+ artifactId: string;
134
+ artifactTitle: string;
135
+ recipientUserIds: string[];
136
+ }): Promise<void>;
137
+ export declare function notifyArtifactReady(db: any, input: {
138
+ userId: string;
139
+ workspaceId: string;
140
+ artifactId: string;
141
+ artifactType: string;
142
+ title: string;
143
+ }): Promise<void>;
144
+ export declare function notifyArtifactFailed(db: any, input: {
145
+ userId: string;
146
+ workspaceId: string;
147
+ artifactType: string;
148
+ title?: string;
149
+ artifactId?: string;
150
+ message: string;
151
+ }): Promise<void>;
152
+ export {};