@goscribe/server 1.0.6 → 1.0.8

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.
@@ -12,7 +12,7 @@ const ArtifactType = {
12
12
 
13
13
  export const flashcards = router({
14
14
  listSets: authedProcedure
15
- .input(z.object({ workspaceId: z.string().uuid() }))
15
+ .input(z.object({ workspaceId: z.string() }))
16
16
  .query(async ({ ctx, input }) => {
17
17
  const workspace = await ctx.db.workspace.findFirst({
18
18
  where: { id: input.workspaceId, ownerId: ctx.session.user.id },
@@ -20,45 +20,31 @@ export const flashcards = router({
20
20
  if (!workspace) throw new TRPCError({ code: 'NOT_FOUND' });
21
21
  return ctx.db.artifact.findMany({
22
22
  where: { workspaceId: input.workspaceId, type: ArtifactType.FLASHCARD_SET },
23
- orderBy: { updatedAt: 'desc' },
24
- });
25
- }),
26
-
27
- createSet: authedProcedure
28
- .input(z.object({ workspaceId: z.string().uuid(), title: z.string().min(1).max(120) }))
29
- .mutation(async ({ ctx, input }) => {
30
- const workspace = await ctx.db.workspace.findFirst({
31
- where: { id: input.workspaceId, ownerId: ctx.session.user.id },
32
- });
33
- if (!workspace) throw new TRPCError({ code: 'NOT_FOUND' });
34
- return ctx.db.artifact.create({
35
- data: {
36
- workspaceId: input.workspaceId,
37
- type: ArtifactType.FLASHCARD_SET,
38
- title: input.title,
39
- createdById: ctx.session.user.id,
23
+ include: {
24
+ versions: {
25
+ orderBy: { version: 'desc' },
26
+ take: 1, // Get only the latest version
27
+ },
40
28
  },
29
+ orderBy: { updatedAt: 'desc' },
41
30
  });
42
31
  }),
43
-
44
- getSet: authedProcedure
45
- .input(z.object({ setId: z.string().uuid() }))
32
+ listCards: authedProcedure
33
+ .input(z.object({ workspaceId: z.string() }))
46
34
  .query(async ({ ctx, input }) => {
47
35
  const set = await ctx.db.artifact.findFirst({
48
- where: {
49
- id: input.setId,
50
- type: ArtifactType.FLASHCARD_SET,
51
- workspace: { ownerId: ctx.session.user.id },
36
+ where: { workspaceId: input.workspaceId, type: ArtifactType.FLASHCARD_SET, workspace: { ownerId: ctx.session.user.id } },
37
+ include: {
38
+ flashcards: true,
52
39
  },
53
- include: { flashcards: true },
40
+ orderBy: { updatedAt: 'desc' },
54
41
  });
55
42
  if (!set) throw new TRPCError({ code: 'NOT_FOUND' });
56
- return set;
43
+ return set.flashcards;
57
44
  }),
58
-
59
45
  createCard: authedProcedure
60
46
  .input(z.object({
61
- setId: z.string().uuid(),
47
+ workspaceId: z.string(),
62
48
  front: z.string().min(1),
63
49
  back: z.string().min(1),
64
50
  tags: z.array(z.string()).optional(),
@@ -66,12 +52,18 @@ export const flashcards = router({
66
52
  }))
67
53
  .mutation(async ({ ctx, input }) => {
68
54
  const set = await ctx.db.artifact.findFirst({
69
- where: { id: input.setId, type: ArtifactType.FLASHCARD_SET, workspace: { ownerId: ctx.session.user.id } },
55
+ where: { type: ArtifactType.FLASHCARD_SET, workspace: {
56
+ id: input.workspaceId,
57
+ } },
58
+ include: {
59
+ flashcards: true,
60
+ },
61
+ orderBy: { updatedAt: 'desc' },
70
62
  });
71
63
  if (!set) throw new TRPCError({ code: 'NOT_FOUND' });
72
64
  return ctx.db.flashcard.create({
73
65
  data: {
74
- artifactId: input.setId,
66
+ artifactId: set.id,
75
67
  front: input.front,
76
68
  back: input.back,
77
69
  tags: input.tags ?? [],
@@ -82,7 +74,7 @@ export const flashcards = router({
82
74
 
83
75
  updateCard: authedProcedure
84
76
  .input(z.object({
85
- cardId: z.string().uuid(),
77
+ cardId: z.string(),
86
78
  front: z.string().optional(),
87
79
  back: z.string().optional(),
88
80
  tags: z.array(z.string()).optional(),
@@ -105,7 +97,7 @@ export const flashcards = router({
105
97
  }),
106
98
 
107
99
  deleteCard: authedProcedure
108
- .input(z.object({ cardId: z.string().uuid() }))
100
+ .input(z.object({ cardId: z.string() }))
109
101
  .mutation(async ({ ctx, input }) => {
110
102
  const card = await ctx.db.flashcard.findFirst({
111
103
  where: { id: input.cardId, artifact: { workspace: { ownerId: ctx.session.user.id } } },
@@ -114,16 +106,6 @@ export const flashcards = router({
114
106
  await ctx.db.flashcard.delete({ where: { id: input.cardId } });
115
107
  return true;
116
108
  }),
117
-
118
- deleteSet: authedProcedure
119
- .input(z.object({ setId: z.string().uuid() }))
120
- .mutation(async ({ ctx, input }) => {
121
- const deleted = await ctx.db.artifact.deleteMany({
122
- where: { id: input.setId, type: ArtifactType.FLASHCARD_SET, workspace: { ownerId: ctx.session.user.id } },
123
- });
124
- if (deleted.count === 0) throw new TRPCError({ code: 'NOT_FOUND' });
125
- return true;
126
- }),
127
109
  });
128
110
 
129
111
 
@@ -15,22 +15,27 @@ const Difficulty = {
15
15
 
16
16
  export const worksheets = router({
17
17
  // List all worksheet artifacts for a workspace
18
- listSets: authedProcedure
19
- .input(z.object({ workspaceId: z.string().uuid() }))
18
+ list: authedProcedure
19
+ .input(z.object({ workspaceId: z.string() }))
20
20
  .query(async ({ ctx, input }) => {
21
- const workspace = await ctx.db.workspace.findFirst({
22
- where: { id: input.workspaceId, ownerId: ctx.session.user.id },
23
- });
24
- if (!workspace) throw new TRPCError({ code: 'NOT_FOUND' });
25
- return ctx.db.artifact.findMany({
21
+ const worksheets = await ctx.db.artifact.findMany({
26
22
  where: { workspaceId: input.workspaceId, type: ArtifactType.WORKSHEET },
23
+ include: {
24
+ versions: {
25
+ orderBy: { version: 'desc' },
26
+ take: 1, // Get only the latest version
27
+ },
28
+ questions: true,
29
+ },
27
30
  orderBy: { updatedAt: 'desc' },
28
31
  });
32
+ if (!worksheets) throw new TRPCError({ code: 'NOT_FOUND' });
33
+ return worksheets;
29
34
  }),
30
35
 
31
36
  // Create a worksheet set
32
- createSet: authedProcedure
33
- .input(z.object({ workspaceId: z.string().uuid(), title: z.string().min(1).max(120) }))
37
+ createWorksheet: authedProcedure
38
+ .input(z.object({ workspaceId: z.string(), title: z.string().min(1).max(120) }))
34
39
  .mutation(async ({ ctx, input }) => {
35
40
  const workspace = await ctx.db.workspace.findFirst({
36
41
  where: { id: input.workspaceId, ownerId: ctx.session.user.id },
@@ -47,25 +52,25 @@ export const worksheets = router({
47
52
  }),
48
53
 
49
54
  // Get a worksheet with its questions
50
- getSet: authedProcedure
51
- .input(z.object({ setId: z.string().uuid() }))
55
+ get: authedProcedure
56
+ .input(z.object({ worksheetId: z.string() }))
52
57
  .query(async ({ ctx, input }) => {
53
- const set = await ctx.db.artifact.findFirst({
58
+ const worksheet = await ctx.db.artifact.findFirst({
54
59
  where: {
55
- id: input.setId,
60
+ id: input.worksheetId,
56
61
  type: ArtifactType.WORKSHEET,
57
62
  workspace: { ownerId: ctx.session.user.id },
58
63
  },
59
64
  include: { questions: true },
60
65
  });
61
- if (!set) throw new TRPCError({ code: 'NOT_FOUND' });
62
- return set;
66
+ if (!worksheet) throw new TRPCError({ code: 'NOT_FOUND' });
67
+ return worksheet;
63
68
  }),
64
69
 
65
70
  // Add a question to a worksheet
66
- createQuestion: authedProcedure
71
+ createWorksheetQuestion: authedProcedure
67
72
  .input(z.object({
68
- setId: z.string().uuid(),
73
+ worksheetId: z.string(),
69
74
  prompt: z.string().min(1),
70
75
  answer: z.string().optional(),
71
76
  difficulty: z.enum(['EASY', 'MEDIUM', 'HARD']).optional(),
@@ -73,13 +78,13 @@ export const worksheets = router({
73
78
  meta: z.record(z.string(), z.unknown()).optional(),
74
79
  }))
75
80
  .mutation(async ({ ctx, input }) => {
76
- const set = await ctx.db.artifact.findFirst({
77
- where: { id: input.setId, type: ArtifactType.WORKSHEET, workspace: { ownerId: ctx.session.user.id } },
81
+ const worksheet = await ctx.db.artifact.findFirst({
82
+ where: { id: input.worksheetId, type: ArtifactType.WORKSHEET, workspace: { ownerId: ctx.session.user.id } },
78
83
  });
79
- if (!set) throw new TRPCError({ code: 'NOT_FOUND' });
84
+ if (!worksheet) throw new TRPCError({ code: 'NOT_FOUND' });
80
85
  return ctx.db.worksheetQuestion.create({
81
86
  data: {
82
- artifactId: input.setId,
87
+ artifactId: input.worksheetId,
83
88
  prompt: input.prompt,
84
89
  answer: input.answer,
85
90
  difficulty: (input.difficulty ?? Difficulty.MEDIUM) as any,
@@ -90,9 +95,9 @@ export const worksheets = router({
90
95
  }),
91
96
 
92
97
  // Update a question
93
- updateQuestion: authedProcedure
98
+ updateWorksheetQuestion: authedProcedure
94
99
  .input(z.object({
95
- questionId: z.string().uuid(),
100
+ worksheetQuestionId: z.string(),
96
101
  prompt: z.string().optional(),
97
102
  answer: z.string().optional(),
98
103
  difficulty: z.enum(['EASY', 'MEDIUM', 'HARD']).optional(),
@@ -101,11 +106,11 @@ export const worksheets = router({
101
106
  }))
102
107
  .mutation(async ({ ctx, input }) => {
103
108
  const q = await ctx.db.worksheetQuestion.findFirst({
104
- where: { id: input.questionId, artifact: { type: ArtifactType.WORKSHEET, workspace: { ownerId: ctx.session.user.id } } },
109
+ where: { id: input.worksheetQuestionId, artifact: { type: ArtifactType.WORKSHEET, workspace: { ownerId: ctx.session.user.id } } },
105
110
  });
106
111
  if (!q) throw new TRPCError({ code: 'NOT_FOUND' });
107
112
  return ctx.db.worksheetQuestion.update({
108
- where: { id: input.questionId },
113
+ where: { id: input.worksheetQuestionId },
109
114
  data: {
110
115
  prompt: input.prompt ?? q.prompt,
111
116
  answer: input.answer ?? q.answer,
@@ -117,23 +122,23 @@ export const worksheets = router({
117
122
  }),
118
123
 
119
124
  // Delete a question
120
- deleteQuestion: authedProcedure
121
- .input(z.object({ questionId: z.string().uuid() }))
125
+ deleteWorksheetQuestion: authedProcedure
126
+ .input(z.object({ worksheetQuestionId: z.string() }))
122
127
  .mutation(async ({ ctx, input }) => {
123
128
  const q = await ctx.db.worksheetQuestion.findFirst({
124
- where: { id: input.questionId, artifact: { workspace: { ownerId: ctx.session.user.id } } },
129
+ where: { id: input.worksheetQuestionId, artifact: { workspace: { ownerId: ctx.session.user.id } } },
125
130
  });
126
131
  if (!q) throw new TRPCError({ code: 'NOT_FOUND' });
127
- await ctx.db.worksheetQuestion.delete({ where: { id: input.questionId } });
132
+ await ctx.db.worksheetQuestion.delete({ where: { id: input.worksheetQuestionId } });
128
133
  return true;
129
134
  }),
130
135
 
131
136
  // Delete a worksheet set and its questions
132
- deleteSet: authedProcedure
133
- .input(z.object({ setId: z.string().uuid() }))
137
+ deleteWorksheet: authedProcedure
138
+ .input(z.object({ worksheetId: z.string() }))
134
139
  .mutation(async ({ ctx, input }) => {
135
140
  const deleted = await ctx.db.artifact.deleteMany({
136
- where: { id: input.setId, type: ArtifactType.WORKSHEET, workspace: { ownerId: ctx.session.user.id } },
141
+ where: { id: input.worksheetId, type: ArtifactType.WORKSHEET, workspace: { ownerId: ctx.session.user.id } },
137
142
  });
138
143
  if (deleted.count === 0) throw new TRPCError({ code: 'NOT_FOUND' });
139
144
  return true;
@@ -2,6 +2,7 @@ import { z } from 'zod';
2
2
  import { TRPCError } from '@trpc/server';
3
3
  import { router, publicProcedure, authedProcedure } from '../trpc.js';
4
4
  import { bucket } from '../lib/storage.js';
5
+ import { ArtifactType } from '@prisma/client';
5
6
 
6
7
  export const workspace = router({
7
8
  // List current user's workspaces
@@ -27,6 +28,18 @@ export const workspace = router({
27
28
  title: input.name,
28
29
  description: input.description,
29
30
  ownerId: ctx.session.user.id,
31
+ artifacts: {
32
+ create: {
33
+ type: ArtifactType.FLASHCARD_SET,
34
+ title: "New Flashcard Set",
35
+ },
36
+ createMany: {
37
+ data: [
38
+ { type: ArtifactType.WORKSHEET, title: "Worksheet 1" },
39
+ { type: ArtifactType.WORKSHEET, title: "Worksheet 2" },
40
+ ],
41
+ },
42
+ },
30
43
  },
31
44
  });
32
45
  return ws;
package/src/server.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import 'dotenv/config';
1
2
  import express from 'express';
2
3
  import cors from 'cors';
3
4
  import helmet from 'helmet';
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAGjF,wBAAsB,aAAa,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,2BAA2B;;;;;GAI5E;AAED,MAAM,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,UAAU,0HA0BnB,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"file.d.ts","sourceRoot":"","sources":["../../src/lib/file.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../../src/lib/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAI9C,eAAO,MAAM,MAAM,gIAIf,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,eAAO,MAAM,OAAO,SAMlB,CAAC;AAEH,eAAO,MAAM,MAAM,wCAA0C,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"_app.d.ts","sourceRoot":"","sources":["../../src/routers/_app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAKrE,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAGpB,CAAC;AAGH,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC;AACzC,MAAM,MAAM,YAAY,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AACxD,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC,SAAS,CAAC,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/routers/auth.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;GA4Bf,CAAC"}
@@ -1,21 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.sampleRouter = void 0;
4
- const zod_1 = require("zod");
5
- const trpc_1 = require("../trpc");
6
- exports.sampleRouter = (0, trpc_1.router)({
7
- // GET-like: query without input
8
- hello: trpc_1.publicProcedure.query(() => {
9
- return { message: 'Hello from tRPC + Express 👋' };
10
- }),
11
- // Mutation with Zod input
12
- echo: trpc_1.publicProcedure
13
- .input(zod_1.z.object({ text: zod_1.z.string().min(1) }))
14
- .mutation(({ input }) => {
15
- return { echoed: input.text };
16
- }),
17
- // Authed query
18
- me: trpc_1.authedProcedure.query(({ ctx }) => {
19
- return { userId: ctx.user.id, role: ctx.user.role };
20
- }),
21
- });
@@ -1 +0,0 @@
1
- {"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/routers/workspace.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuJpB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"file":"trpc.d.ts","sourceRoot":"","sources":["../src/trpc.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,MAAM;;;;;;;;;;EAAW,CAAC;AAC/B,eAAO,MAAM,UAAU;;;;;;;;;;sCAAe,CAAC;AACvC,eAAO,MAAM,eAAe;;;;;yLAAc,CAAC;AAsB3C,gCAAgC;AAChC,eAAO,MAAM,eAAe;;;;;;;;;;yKAAgC,CAAC"}