@classroomio/mcp 0.0.3 → 0.0.5
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/README.md +104 -6
- package/dist/index.js +922 -252
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -40,12 +40,61 @@ var ClassroomIoApiClient = class {
|
|
|
40
40
|
method: "GET"
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
+
async listOrganizationCourses(query = {}) {
|
|
44
|
+
const searchParams = new URLSearchParams();
|
|
45
|
+
if (query.tags) searchParams.set("tags", query.tags);
|
|
46
|
+
const querySuffix = searchParams.toString() ? `?${searchParams.toString()}` : "";
|
|
47
|
+
return this.request(`/organization/courses${querySuffix}`, {
|
|
48
|
+
method: "GET"
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
async listCourseExercises(courseId, query = {}) {
|
|
52
|
+
const searchParams = new URLSearchParams();
|
|
53
|
+
if (query.lessonId) searchParams.set("lessonId", query.lessonId);
|
|
54
|
+
if (query.sectionId) searchParams.set("sectionId", query.sectionId);
|
|
55
|
+
const querySuffix = searchParams.toString() ? `?${searchParams.toString()}` : "";
|
|
56
|
+
return this.request(`/course/${courseId}/exercise${querySuffix}`, {
|
|
57
|
+
method: "GET"
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async getCourseExercise(courseId, exerciseId) {
|
|
61
|
+
return this.request(`/course/${courseId}/exercise/${exerciseId}`, {
|
|
62
|
+
method: "GET"
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
async createCourseExercise(courseId, payload) {
|
|
66
|
+
return this.request(`/course/${courseId}/exercise`, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
body: {
|
|
69
|
+
...payload,
|
|
70
|
+
courseId
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async createCourseExerciseFromTemplate(courseId, payload) {
|
|
75
|
+
return this.request(`/course/${courseId}/exercise/from-template`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: payload
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async updateCourseExercise(courseId, exerciseId, payload) {
|
|
81
|
+
return this.request(`/course/${courseId}/exercise/${exerciseId}`, {
|
|
82
|
+
method: "PUT",
|
|
83
|
+
body: payload
|
|
84
|
+
});
|
|
85
|
+
}
|
|
43
86
|
async updateCourseDraft(draftId, payload) {
|
|
44
87
|
return this.request(`/organization/course-import/drafts/${draftId}`, {
|
|
45
88
|
method: "PUT",
|
|
46
89
|
body: payload
|
|
47
90
|
});
|
|
48
91
|
}
|
|
92
|
+
async tagCourseDraft(draftId, payload) {
|
|
93
|
+
return this.request(`/organization/course-import/drafts/${draftId}/tags`, {
|
|
94
|
+
method: "PUT",
|
|
95
|
+
body: payload
|
|
96
|
+
});
|
|
97
|
+
}
|
|
49
98
|
async publishCourseDraft(draftId, payload) {
|
|
50
99
|
return this.request(`/organization/course-import/drafts/${draftId}/publish`, {
|
|
51
100
|
method: "POST",
|
|
@@ -58,6 +107,15 @@ var ClassroomIoApiClient = class {
|
|
|
58
107
|
body: payload
|
|
59
108
|
});
|
|
60
109
|
}
|
|
110
|
+
async tagCourses(payload) {
|
|
111
|
+
return this.request(
|
|
112
|
+
"/organization/tags/courses/assign",
|
|
113
|
+
{
|
|
114
|
+
method: "PUT",
|
|
115
|
+
body: payload
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
61
119
|
async request(path, options) {
|
|
62
120
|
const response = await fetch(new URL(path, this.config.CLASSROOMIO_API_URL), {
|
|
63
121
|
method: options.method,
|
|
@@ -96,11 +154,318 @@ function getConfig(env = process.env) {
|
|
|
96
154
|
return ZConfig.parse(env);
|
|
97
155
|
}
|
|
98
156
|
|
|
99
|
-
// ../utils/dist/validation/
|
|
157
|
+
// ../utils/dist/validation/tag/tag.js
|
|
158
|
+
import * as z2 from "zod";
|
|
159
|
+
var TAG_COLOR_OPTIONS = [
|
|
160
|
+
"#EF4444",
|
|
161
|
+
"#F97316",
|
|
162
|
+
"#F59E0B",
|
|
163
|
+
"#84CC16",
|
|
164
|
+
"#22C55E",
|
|
165
|
+
"#14B8A6",
|
|
166
|
+
"#06B6D4",
|
|
167
|
+
"#3B82F6",
|
|
168
|
+
"#8B5CF6",
|
|
169
|
+
"#EC4899"
|
|
170
|
+
];
|
|
171
|
+
var ZTagColor = z2.enum(TAG_COLOR_OPTIONS);
|
|
172
|
+
var ZTagGroupParam = z2.object({
|
|
173
|
+
groupId: z2.uuid()
|
|
174
|
+
});
|
|
175
|
+
var ZTagGroupCreate = z2.object({
|
|
176
|
+
name: z2.string().min(1).max(80),
|
|
177
|
+
description: z2.string().max(240).optional(),
|
|
178
|
+
order: z2.number().int().min(0).optional()
|
|
179
|
+
});
|
|
180
|
+
var ZTagGroupUpdate = ZTagGroupCreate.partial().refine((value) => Object.keys(value).length > 0, {
|
|
181
|
+
message: "At least one field is required"
|
|
182
|
+
});
|
|
183
|
+
var ZTagParam = z2.object({
|
|
184
|
+
tagId: z2.uuid()
|
|
185
|
+
});
|
|
186
|
+
var ZTagCreate = z2.object({
|
|
187
|
+
name: z2.string().min(1).max(80),
|
|
188
|
+
description: z2.string().max(240).optional(),
|
|
189
|
+
groupId: z2.uuid(),
|
|
190
|
+
color: ZTagColor
|
|
191
|
+
});
|
|
192
|
+
var ZTagUpdate = z2.object({
|
|
193
|
+
name: z2.string().min(1).max(80).optional(),
|
|
194
|
+
description: z2.string().max(240).optional(),
|
|
195
|
+
groupId: z2.uuid().optional(),
|
|
196
|
+
color: ZTagColor.optional()
|
|
197
|
+
}).refine((value) => Object.keys(value).length > 0, {
|
|
198
|
+
message: "At least one field is required"
|
|
199
|
+
});
|
|
200
|
+
var ZCourseTagParam = z2.object({
|
|
201
|
+
courseId: z2.uuid()
|
|
202
|
+
});
|
|
203
|
+
var ZCourseTagAssignment = z2.object({
|
|
204
|
+
tagIds: z2.array(z2.uuid()).max(100).default([])
|
|
205
|
+
});
|
|
206
|
+
var ZAutomationTagMode = z2.enum(["merge", "replace"]).default("merge");
|
|
207
|
+
var ZAutomationTagName = z2.string().trim().min(1).max(80);
|
|
208
|
+
var ZAutomationDraftTagParam = z2.object({
|
|
209
|
+
draftId: z2.string().uuid()
|
|
210
|
+
});
|
|
211
|
+
var ZAutomationDraftTagAssignment = z2.object({
|
|
212
|
+
tagNames: z2.array(ZAutomationTagName).min(1).max(100),
|
|
213
|
+
mode: ZAutomationTagMode,
|
|
214
|
+
groupName: z2.string().trim().min(1).max(80).optional()
|
|
215
|
+
});
|
|
216
|
+
var ZAutomationCourseTagAssignment = ZAutomationDraftTagAssignment.extend({
|
|
217
|
+
courseIds: z2.array(z2.string().uuid()).min(1).max(100)
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// ../utils/dist/validation/organization/organization.js
|
|
100
221
|
import * as z3 from "zod";
|
|
101
222
|
|
|
102
|
-
// ../utils/dist/
|
|
103
|
-
|
|
223
|
+
// ../utils/dist/constants/org.js
|
|
224
|
+
var blockedSubdomain = [
|
|
225
|
+
"academy",
|
|
226
|
+
"app",
|
|
227
|
+
"apps",
|
|
228
|
+
"blog",
|
|
229
|
+
"build",
|
|
230
|
+
"campaign",
|
|
231
|
+
"church",
|
|
232
|
+
"cloud",
|
|
233
|
+
"community",
|
|
234
|
+
"conference",
|
|
235
|
+
"course",
|
|
236
|
+
"courses",
|
|
237
|
+
"demo",
|
|
238
|
+
"dev",
|
|
239
|
+
"forum",
|
|
240
|
+
"group",
|
|
241
|
+
"groups",
|
|
242
|
+
"help",
|
|
243
|
+
"launch",
|
|
244
|
+
"launchweek",
|
|
245
|
+
"mobile",
|
|
246
|
+
"play",
|
|
247
|
+
"prod",
|
|
248
|
+
"production",
|
|
249
|
+
"schools",
|
|
250
|
+
"stage",
|
|
251
|
+
"staging",
|
|
252
|
+
"support",
|
|
253
|
+
"teacher",
|
|
254
|
+
"teachers",
|
|
255
|
+
"tech",
|
|
256
|
+
"training"
|
|
257
|
+
];
|
|
258
|
+
|
|
259
|
+
// ../utils/dist/constants/content.js
|
|
260
|
+
var ContentType;
|
|
261
|
+
(function(ContentType2) {
|
|
262
|
+
ContentType2["Section"] = "SECTION";
|
|
263
|
+
ContentType2["Lesson"] = "LESSON";
|
|
264
|
+
ContentType2["Exercise"] = "EXERCISE";
|
|
265
|
+
})(ContentType || (ContentType = {}));
|
|
266
|
+
|
|
267
|
+
// ../utils/dist/validation/organization/organization.js
|
|
268
|
+
var ZGetOrganizations = z3.object({
|
|
269
|
+
siteName: z3.string().min(1).optional(),
|
|
270
|
+
customDomain: z3.string().min(1).optional(),
|
|
271
|
+
isCustomDomainVerified: z3.boolean().optional()
|
|
272
|
+
});
|
|
273
|
+
var ZGetCoursesBySiteName = z3.object({
|
|
274
|
+
siteName: z3.string().min(1),
|
|
275
|
+
tags: z3.string().optional()
|
|
276
|
+
});
|
|
277
|
+
var ZGetOrganizationCoursesQuery = z3.object({
|
|
278
|
+
tags: z3.string().optional()
|
|
279
|
+
});
|
|
280
|
+
var ZGetOrgSetup = z3.object({
|
|
281
|
+
siteName: z3.string().min(1)
|
|
282
|
+
});
|
|
283
|
+
var ZCreateOrgPlan = z3.object({
|
|
284
|
+
orgId: z3.uuid(),
|
|
285
|
+
planName: z3.enum(["EARLY_ADOPTER", "ENTERPRISE", "BASIC"]),
|
|
286
|
+
subscriptionId: z3.string().min(1),
|
|
287
|
+
triggeredBy: z3.number().int().positive(),
|
|
288
|
+
payload: z3.record(z3.string(), z3.unknown())
|
|
289
|
+
});
|
|
290
|
+
var ZUpdateOrgPlan = z3.object({
|
|
291
|
+
subscriptionId: z3.string().min(1),
|
|
292
|
+
payload: z3.record(z3.string(), z3.unknown())
|
|
293
|
+
});
|
|
294
|
+
var ZCancelOrgPlan = z3.object({
|
|
295
|
+
subscriptionId: z3.string().min(1),
|
|
296
|
+
payload: z3.record(z3.string(), z3.unknown())
|
|
297
|
+
});
|
|
298
|
+
var ZCreateOrganization = z3.object({
|
|
299
|
+
name: z3.string().min(5).refine((val) => !/^[-]|[-]$/.test(val), {
|
|
300
|
+
message: "Organization name cannot start or end with a hyphen"
|
|
301
|
+
}),
|
|
302
|
+
siteName: z3.string().min(5).refine((val) => !/^[-]|[-]$/.test(val), {
|
|
303
|
+
message: "Site name cannot start or end with a hyphen"
|
|
304
|
+
}).refine((val) => !blockedSubdomain.includes(val), {
|
|
305
|
+
message: "Sitename already exists."
|
|
306
|
+
})
|
|
307
|
+
});
|
|
308
|
+
var ZUpdateOrganization = z3.object({
|
|
309
|
+
name: z3.string().min(5).refine((val) => !/^[-]|[-]$/.test(val), {
|
|
310
|
+
message: "Organization name cannot start or end with a hyphen"
|
|
311
|
+
}).optional(),
|
|
312
|
+
avatarUrl: z3.url().optional(),
|
|
313
|
+
theme: z3.string().optional(),
|
|
314
|
+
landingpage: z3.record(z3.string(), z3.unknown()).optional(),
|
|
315
|
+
siteName: z3.string().min(1).optional(),
|
|
316
|
+
customDomain: z3.string().nullable().optional(),
|
|
317
|
+
isCustomDomainVerified: z3.boolean().optional(),
|
|
318
|
+
customization: z3.record(z3.string(), z3.unknown()).optional(),
|
|
319
|
+
disableSignup: z3.boolean().optional(),
|
|
320
|
+
disableSignupMessage: z3.string().optional(),
|
|
321
|
+
disableEmailPassword: z3.boolean().optional(),
|
|
322
|
+
disableGoogleAuth: z3.boolean().optional(),
|
|
323
|
+
/** Nested settings (stored in organization.settings JSONB). signup.inviteOnly = true means invite-only signup. */
|
|
324
|
+
settings: z3.object({
|
|
325
|
+
signup: z3.object({
|
|
326
|
+
inviteOnly: z3.boolean().optional()
|
|
327
|
+
}).optional()
|
|
328
|
+
}).optional()
|
|
329
|
+
});
|
|
330
|
+
var ZInviteTeamMembers = z3.object({
|
|
331
|
+
emails: z3.array(z3.string().email()).min(1).max(50),
|
|
332
|
+
roleId: z3.number().int().positive()
|
|
333
|
+
});
|
|
334
|
+
var ZRemoveTeamMember = z3.object({
|
|
335
|
+
memberId: z3.coerce.number().int().positive()
|
|
336
|
+
});
|
|
337
|
+
var ZGetUserAnalytics = z3.object({
|
|
338
|
+
userId: z3.uuid()
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
// ../utils/dist/validation/organization/quiz.js
|
|
342
|
+
import * as z4 from "zod";
|
|
343
|
+
var ZQuizGetParam = z4.object({
|
|
344
|
+
orgId: z4.uuid(),
|
|
345
|
+
quizId: z4.uuid()
|
|
346
|
+
});
|
|
347
|
+
var ZQuizListParam = z4.object({
|
|
348
|
+
orgId: z4.uuid()
|
|
349
|
+
});
|
|
350
|
+
var ZQuizCreate = z4.object({
|
|
351
|
+
title: z4.string().min(1),
|
|
352
|
+
questions: z4.array(z4.any()).optional(),
|
|
353
|
+
timelimit: z4.string().optional(),
|
|
354
|
+
theme: z4.string().optional()
|
|
355
|
+
});
|
|
356
|
+
var ZQuizUpdate = z4.object({
|
|
357
|
+
title: z4.string().min(1).optional(),
|
|
358
|
+
questions: z4.array(z4.any()).optional(),
|
|
359
|
+
timelimit: z4.string().optional(),
|
|
360
|
+
theme: z4.string().optional()
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
// ../utils/dist/validation/organization/exercise.js
|
|
364
|
+
import * as z5 from "zod";
|
|
365
|
+
var ZLMSExercisesParam = z5.object({
|
|
366
|
+
orgId: z5.uuid()
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
// ../utils/dist/validation/organization/invite.js
|
|
370
|
+
import * as z6 from "zod";
|
|
371
|
+
var ZOrganizationInviteTokenParam = z6.object({
|
|
372
|
+
token: z6.string().min(10).max(512)
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
// ../utils/dist/validation/organization/sso.js
|
|
376
|
+
import * as z7 from "zod";
|
|
377
|
+
var SSO_PROVIDERS = ["OKTA", "GOOGLE_WORKSPACE", "AUTH0"];
|
|
378
|
+
var ZCreateSsoConnection = z7.object({
|
|
379
|
+
provider: z7.enum(SSO_PROVIDERS),
|
|
380
|
+
displayName: z7.string().min(1, "Display name is required"),
|
|
381
|
+
issuer: z7.url("Must be a valid URL"),
|
|
382
|
+
domain: z7.string().min(1, "Domain is required").regex(/^[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\.[a-zA-Z]{2,}$/, "Invalid domain format"),
|
|
383
|
+
clientId: z7.string().min(1, "Client ID is required"),
|
|
384
|
+
clientSecret: z7.string().min(1, "Client secret is required"),
|
|
385
|
+
scopes: z7.string().default("openid profile email")
|
|
386
|
+
});
|
|
387
|
+
var ZUpdateSsoConnection = z7.object({
|
|
388
|
+
displayName: z7.string().min(1).optional(),
|
|
389
|
+
issuer: z7.url().optional(),
|
|
390
|
+
domain: z7.string().optional(),
|
|
391
|
+
clientId: z7.string().optional(),
|
|
392
|
+
clientSecret: z7.string().optional(),
|
|
393
|
+
scopes: z7.string().optional(),
|
|
394
|
+
isActive: z7.boolean().optional()
|
|
395
|
+
});
|
|
396
|
+
var ZUpdateSsoPolicy = z7.object({
|
|
397
|
+
forceSso: z7.boolean().optional(),
|
|
398
|
+
autoJoinSsoDomains: z7.boolean().optional(),
|
|
399
|
+
breakGlassEnabled: z7.boolean().optional(),
|
|
400
|
+
defaultRoleId: z7.number().int().positive().optional(),
|
|
401
|
+
roleMapping: z7.record(z7.string(), z7.number()).optional()
|
|
402
|
+
});
|
|
403
|
+
var ZSsoDiscoveryQuery = z7.object({
|
|
404
|
+
email: z7.email("Valid email is required")
|
|
405
|
+
});
|
|
406
|
+
var ZGetSsoConfig = z7.object({
|
|
407
|
+
orgId: z7.uuid()
|
|
408
|
+
});
|
|
409
|
+
|
|
410
|
+
// ../utils/dist/validation/organization/login-link.js
|
|
411
|
+
import { z as z8 } from "zod";
|
|
412
|
+
var ZLoginLinkQuery = z8.object({
|
|
413
|
+
token: z8.string().min(1),
|
|
414
|
+
redirect: z8.string().optional()
|
|
415
|
+
});
|
|
416
|
+
var ZLoginLinkPayload = z8.object({
|
|
417
|
+
sub: z8.uuid(),
|
|
418
|
+
email: z8.email(),
|
|
419
|
+
type: z8.literal("login-link")
|
|
420
|
+
});
|
|
421
|
+
|
|
422
|
+
// ../utils/dist/validation/organization/token-auth.js
|
|
423
|
+
import { z as z9 } from "zod";
|
|
424
|
+
var ZTokenExchangeQuery = z9.object({
|
|
425
|
+
token: z9.string().min(1),
|
|
426
|
+
redirect: z9.string().optional()
|
|
427
|
+
});
|
|
428
|
+
var ZTokenExchangePayload = z9.object({
|
|
429
|
+
sub: z9.string(),
|
|
430
|
+
email: z9.email(),
|
|
431
|
+
name: z9.string().optional(),
|
|
432
|
+
avatar: z9.url().optional(),
|
|
433
|
+
iat: z9.number(),
|
|
434
|
+
exp: z9.number()
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// ../utils/dist/validation/organization/automation-key.js
|
|
438
|
+
import { z as z10 } from "zod";
|
|
439
|
+
var ZOrganizationApiKeyType = z10.enum(["mcp", "api", "zapier"]);
|
|
440
|
+
var ZOrganizationApiKeyScope = z10.enum([
|
|
441
|
+
"course_import:draft:create",
|
|
442
|
+
"course_import:draft:read",
|
|
443
|
+
"course_import:draft:update",
|
|
444
|
+
"course_import:draft:publish",
|
|
445
|
+
"course:read",
|
|
446
|
+
"course:tag:write",
|
|
447
|
+
"course:exercise:read",
|
|
448
|
+
"course:exercise:write",
|
|
449
|
+
"public_api:*"
|
|
450
|
+
]);
|
|
451
|
+
var ZListOrganizationApiKeysQuery = z10.object({
|
|
452
|
+
type: ZOrganizationApiKeyType.optional()
|
|
453
|
+
});
|
|
454
|
+
var ZOrganizationAutomationUsageQuery = z10.object({
|
|
455
|
+
type: ZOrganizationApiKeyType.default("mcp")
|
|
456
|
+
});
|
|
457
|
+
var ZCreateOrganizationApiKey = z10.object({
|
|
458
|
+
type: ZOrganizationApiKeyType,
|
|
459
|
+
label: z10.string().min(1).max(120).optional(),
|
|
460
|
+
expiresAt: z10.string().datetime().optional(),
|
|
461
|
+
scopes: z10.array(ZOrganizationApiKeyScope).min(1).optional()
|
|
462
|
+
});
|
|
463
|
+
var ZOrganizationApiKeyParam = z10.object({
|
|
464
|
+
keyId: z10.string().uuid()
|
|
465
|
+
});
|
|
466
|
+
|
|
467
|
+
// ../utils/dist/validation/exercise/exercise.js
|
|
468
|
+
import * as z11 from "zod";
|
|
104
469
|
|
|
105
470
|
// ../question-types/dist/question-type-keys.js
|
|
106
471
|
var QUESTION_TYPE_KEY = {
|
|
@@ -444,226 +809,384 @@ var ALLOWED_DOCUMENT_TYPES = [
|
|
|
444
809
|
"application/msword"
|
|
445
810
|
// .doc
|
|
446
811
|
];
|
|
812
|
+
var QUESTION_TYPE = QUESTION_TYPE_IDS;
|
|
813
|
+
|
|
814
|
+
// ../utils/dist/validation/exercise/exercise.js
|
|
815
|
+
var QUESTION_VALIDATION_RULES = {
|
|
816
|
+
[QUESTION_TYPE.RADIO]: [
|
|
817
|
+
(question) => {
|
|
818
|
+
const options = question.options || [];
|
|
819
|
+
if (options.length > 0 && options.length < 2) {
|
|
820
|
+
return "Options must have at least 2 items for RADIO/CHECKBOX questions";
|
|
821
|
+
}
|
|
822
|
+
return null;
|
|
823
|
+
},
|
|
824
|
+
(question) => {
|
|
825
|
+
const options = question.options || [];
|
|
826
|
+
if (options.length > 0 && !options.some((opt) => opt.isCorrect === true)) {
|
|
827
|
+
return "Please mark an option as the correct answer";
|
|
828
|
+
}
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
],
|
|
832
|
+
[QUESTION_TYPE.CHECKBOX]: [
|
|
833
|
+
(question) => {
|
|
834
|
+
const options = question.options || [];
|
|
835
|
+
if (options.length > 0 && options.length < 2) {
|
|
836
|
+
return "Options must have at least 2 items for RADIO/CHECKBOX questions";
|
|
837
|
+
}
|
|
838
|
+
return null;
|
|
839
|
+
},
|
|
840
|
+
(question) => {
|
|
841
|
+
const options = question.options || [];
|
|
842
|
+
if (options.length > 0 && !options.some((opt) => opt.isCorrect === true)) {
|
|
843
|
+
return "Please mark an option as the correct answer";
|
|
844
|
+
}
|
|
845
|
+
return null;
|
|
846
|
+
}
|
|
847
|
+
],
|
|
848
|
+
[QUESTION_TYPE.TRUE_FALSE]: [
|
|
849
|
+
(question) => {
|
|
850
|
+
const options = question.options || [];
|
|
851
|
+
if (options.length > 0 && options.length < 2) {
|
|
852
|
+
return "True/False questions need both True and False options";
|
|
853
|
+
}
|
|
854
|
+
return null;
|
|
855
|
+
},
|
|
856
|
+
(question) => {
|
|
857
|
+
const options = question.options || [];
|
|
858
|
+
if (options.length > 0 && !options.some((opt) => opt.isCorrect === true)) {
|
|
859
|
+
return "Please mark an option as the correct answer";
|
|
860
|
+
}
|
|
861
|
+
return null;
|
|
862
|
+
}
|
|
863
|
+
],
|
|
864
|
+
[QUESTION_TYPE.TEXTAREA]: []
|
|
865
|
+
};
|
|
866
|
+
var ZExerciseUpdateQuestionBase = z11.object({
|
|
867
|
+
id: z11.number().int().optional(),
|
|
868
|
+
question: z11.string().min(1),
|
|
869
|
+
questionTypeId: z11.number().int().min(1).optional(),
|
|
870
|
+
// Added to support question type updates
|
|
871
|
+
points: z11.number().int().min(0).optional(),
|
|
872
|
+
order: z11.number().int().min(0).optional(),
|
|
873
|
+
settings: z11.record(z11.string(), z11.unknown()).optional(),
|
|
874
|
+
deletedAt: z11.string().optional(),
|
|
875
|
+
// Marks question as deleted
|
|
876
|
+
options: z11.array(z11.object({
|
|
877
|
+
id: z11.number().int().optional(),
|
|
878
|
+
label: z11.string().min(1),
|
|
879
|
+
isCorrect: z11.boolean(),
|
|
880
|
+
settings: z11.record(z11.string(), z11.unknown()).optional(),
|
|
881
|
+
deletedAt: z11.string().optional()
|
|
882
|
+
// Marks option as deleted
|
|
883
|
+
})).optional()
|
|
884
|
+
});
|
|
885
|
+
function validateQuestionOptions(question, ctx) {
|
|
886
|
+
if (question.deletedAt)
|
|
887
|
+
return;
|
|
888
|
+
const rules = QUESTION_VALIDATION_RULES[question.questionTypeId ?? -1] ?? [];
|
|
889
|
+
for (const rule of rules) {
|
|
890
|
+
const message = rule(question);
|
|
891
|
+
if (!message)
|
|
892
|
+
continue;
|
|
893
|
+
ctx.addIssue({
|
|
894
|
+
code: "custom",
|
|
895
|
+
message,
|
|
896
|
+
path: ["options"]
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
var ZExerciseUpdateQuestion = ZExerciseUpdateQuestionBase.superRefine(validateQuestionOptions);
|
|
901
|
+
var ZExerciseCreate = z11.object({
|
|
902
|
+
title: z11.string().min(1),
|
|
903
|
+
description: z11.string().optional(),
|
|
904
|
+
lessonId: z11.string().optional(),
|
|
905
|
+
sectionId: z11.string().optional(),
|
|
906
|
+
order: z11.number().int().optional(),
|
|
907
|
+
courseId: z11.string().min(1),
|
|
908
|
+
dueBy: z11.string().optional(),
|
|
909
|
+
questions: z11.array(z11.object({
|
|
910
|
+
question: z11.string().min(1),
|
|
911
|
+
questionTypeId: z11.number().int().min(1).optional(),
|
|
912
|
+
points: z11.number().int().min(0).optional(),
|
|
913
|
+
settings: z11.record(z11.string(), z11.unknown()).optional(),
|
|
914
|
+
options: z11.array(z11.object({
|
|
915
|
+
label: z11.string().min(1),
|
|
916
|
+
isCorrect: z11.boolean(),
|
|
917
|
+
settings: z11.record(z11.string(), z11.unknown()).optional()
|
|
918
|
+
})).min(2)
|
|
919
|
+
})).optional()
|
|
920
|
+
});
|
|
921
|
+
var ZExerciseUpdate = z11.object({
|
|
922
|
+
title: z11.string().min(1).optional(),
|
|
923
|
+
description: z11.string().optional(),
|
|
924
|
+
lessonId: z11.string().optional(),
|
|
925
|
+
sectionId: z11.string().optional(),
|
|
926
|
+
order: z11.number().int().optional(),
|
|
927
|
+
isUnlocked: z11.boolean().optional(),
|
|
928
|
+
dueBy: z11.string().optional(),
|
|
929
|
+
// Changed from iso.datetime() to string to match frontend format
|
|
930
|
+
questions: z11.array(ZExerciseUpdateQuestion).optional()
|
|
931
|
+
});
|
|
932
|
+
var ZExerciseGetParam = z11.object({
|
|
933
|
+
exerciseId: z11.string().min(1)
|
|
934
|
+
});
|
|
935
|
+
var ZExerciseListQuery = z11.object({
|
|
936
|
+
lessonId: z11.string().optional(),
|
|
937
|
+
sectionId: z11.string().optional()
|
|
938
|
+
});
|
|
939
|
+
var ZExerciseSubmissionCreate = z11.object({
|
|
940
|
+
exerciseId: z11.string().min(1),
|
|
941
|
+
answers: z11.array(z11.object({
|
|
942
|
+
questionId: z11.number().int(),
|
|
943
|
+
optionId: z11.number().int().optional(),
|
|
944
|
+
answer: z11.string().optional()
|
|
945
|
+
})).min(1)
|
|
946
|
+
});
|
|
947
|
+
var ZExerciseFromTemplate = z11.object({
|
|
948
|
+
lessonId: z11.string().optional(),
|
|
949
|
+
sectionId: z11.string().optional(),
|
|
950
|
+
order: z11.number().int().optional(),
|
|
951
|
+
templateId: z11.number().int().min(1)
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
// ../utils/dist/validation/course-import/course-import.js
|
|
955
|
+
import * as z13 from "zod";
|
|
447
956
|
|
|
448
957
|
// ../utils/dist/validation/course/course.js
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
958
|
+
import * as z12 from "zod";
|
|
959
|
+
var ZCourseClone = z12.object({
|
|
960
|
+
title: z12.string().min(1),
|
|
961
|
+
description: z12.string().optional(),
|
|
962
|
+
slug: z12.string().min(1),
|
|
963
|
+
organizationId: z12.string().min(1)
|
|
964
|
+
});
|
|
965
|
+
var ZCourseCloneParam = z12.object({
|
|
966
|
+
courseId: z12.string().min(1)
|
|
967
|
+
});
|
|
968
|
+
var ZCourseGetParam = z12.object({
|
|
969
|
+
courseId: z12.string().min(1)
|
|
970
|
+
});
|
|
971
|
+
var ZCourseGetQuery = z12.object({
|
|
972
|
+
slug: z12.string().optional()
|
|
973
|
+
});
|
|
974
|
+
var ZCourseGetBySlugParam = z12.object({
|
|
975
|
+
slug: z12.string().min(1)
|
|
976
|
+
});
|
|
977
|
+
var ZCourseEnrollParam = z12.object({
|
|
978
|
+
courseId: z12.string().min(1)
|
|
979
|
+
});
|
|
980
|
+
var ZCourseEnrollBody = z12.object({
|
|
981
|
+
inviteToken: z12.string().min(1).optional()
|
|
982
|
+
});
|
|
983
|
+
var ZCourseDownloadParam = z12.object({
|
|
984
|
+
courseId: z12.string().min(1)
|
|
985
|
+
});
|
|
986
|
+
var ZCertificateDownload = z12.object({
|
|
987
|
+
theme: z12.string().min(1),
|
|
988
|
+
studentName: z12.string().min(1),
|
|
989
|
+
courseName: z12.string().min(1),
|
|
990
|
+
courseDescription: z12.string().min(1),
|
|
991
|
+
orgName: z12.string().min(1),
|
|
992
|
+
orgLogoUrl: z12.string().url().optional(),
|
|
993
|
+
facilitator: z12.string().optional()
|
|
994
|
+
});
|
|
995
|
+
var ZCourseDownloadContent = z12.object({
|
|
996
|
+
courseTitle: z12.string().min(1),
|
|
997
|
+
orgName: z12.string().min(1),
|
|
998
|
+
orgTheme: z12.string().min(1),
|
|
999
|
+
lessons: z12.array(z12.object({
|
|
1000
|
+
lessonTitle: z12.string().min(1),
|
|
1001
|
+
lessonNumber: z12.string().min(1),
|
|
1002
|
+
lessonNote: z12.string(),
|
|
1003
|
+
slideUrl: z12.string().url().optional(),
|
|
1004
|
+
video: z12.array(z12.string().url()).optional()
|
|
495
1005
|
}))
|
|
496
1006
|
});
|
|
497
|
-
var ZLessonDownloadContent =
|
|
498
|
-
title:
|
|
499
|
-
number:
|
|
500
|
-
orgName:
|
|
501
|
-
note:
|
|
502
|
-
slideUrl:
|
|
503
|
-
video:
|
|
504
|
-
courseTitle:
|
|
505
|
-
});
|
|
506
|
-
var ZCoursePresignUrlUpload =
|
|
507
|
-
fileName:
|
|
508
|
-
fileType:
|
|
509
|
-
});
|
|
510
|
-
var ZCourseDocumentPresignUrlUpload =
|
|
511
|
-
fileName:
|
|
512
|
-
fileType:
|
|
513
|
-
});
|
|
514
|
-
var ZCourseDownloadPresignedUrl =
|
|
515
|
-
keys:
|
|
516
|
-
});
|
|
517
|
-
var ZCourseContentUpdateItem =
|
|
518
|
-
id:
|
|
519
|
-
type:
|
|
520
|
-
isUnlocked:
|
|
521
|
-
order:
|
|
522
|
-
sectionId:
|
|
523
|
-
});
|
|
524
|
-
var ZCourseContentUpdate =
|
|
525
|
-
items:
|
|
526
|
-
});
|
|
527
|
-
var ZCourseContentDeleteItem =
|
|
528
|
-
id:
|
|
529
|
-
type:
|
|
530
|
-
});
|
|
531
|
-
var ZCourseContentDelete =
|
|
532
|
-
sectionId:
|
|
533
|
-
items:
|
|
1007
|
+
var ZLessonDownloadContent = z12.object({
|
|
1008
|
+
title: z12.string().min(1),
|
|
1009
|
+
number: z12.string().min(1),
|
|
1010
|
+
orgName: z12.string().min(1),
|
|
1011
|
+
note: z12.string(),
|
|
1012
|
+
slideUrl: z12.string().url().optional(),
|
|
1013
|
+
video: z12.array(z12.string().url()).optional(),
|
|
1014
|
+
courseTitle: z12.string().min(1)
|
|
1015
|
+
});
|
|
1016
|
+
var ZCoursePresignUrlUpload = z12.object({
|
|
1017
|
+
fileName: z12.string().min(1),
|
|
1018
|
+
fileType: z12.enum(ALLOWED_CONTENT_TYPES)
|
|
1019
|
+
});
|
|
1020
|
+
var ZCourseDocumentPresignUrlUpload = z12.object({
|
|
1021
|
+
fileName: z12.string().min(1),
|
|
1022
|
+
fileType: z12.enum(ALLOWED_DOCUMENT_TYPES)
|
|
1023
|
+
});
|
|
1024
|
+
var ZCourseDownloadPresignedUrl = z12.object({
|
|
1025
|
+
keys: z12.array(z12.string().min(1)).min(1)
|
|
1026
|
+
});
|
|
1027
|
+
var ZCourseContentUpdateItem = z12.object({
|
|
1028
|
+
id: z12.string().min(1),
|
|
1029
|
+
type: z12.enum(["LESSON", "EXERCISE"]),
|
|
1030
|
+
isUnlocked: z12.boolean().optional(),
|
|
1031
|
+
order: z12.number().int().min(0).optional(),
|
|
1032
|
+
sectionId: z12.string().nullable().optional()
|
|
1033
|
+
});
|
|
1034
|
+
var ZCourseContentUpdate = z12.object({
|
|
1035
|
+
items: z12.array(ZCourseContentUpdateItem).min(1)
|
|
1036
|
+
});
|
|
1037
|
+
var ZCourseContentDeleteItem = z12.object({
|
|
1038
|
+
id: z12.string().min(1),
|
|
1039
|
+
type: z12.enum(["LESSON", "EXERCISE"])
|
|
1040
|
+
});
|
|
1041
|
+
var ZCourseContentDelete = z12.object({
|
|
1042
|
+
sectionId: z12.string().min(1).optional(),
|
|
1043
|
+
items: z12.array(ZCourseContentDeleteItem).min(1).optional()
|
|
534
1044
|
}).refine((data) => Boolean(data.sectionId) !== Boolean(data.items), {
|
|
535
1045
|
message: "Provide either sectionId or items",
|
|
536
1046
|
path: ["sectionId"]
|
|
537
1047
|
});
|
|
538
|
-
var ZCourseCreate =
|
|
539
|
-
title:
|
|
540
|
-
description:
|
|
541
|
-
type:
|
|
542
|
-
organizationId:
|
|
543
|
-
});
|
|
544
|
-
var ZCourseMetadata =
|
|
545
|
-
requirements:
|
|
546
|
-
description:
|
|
547
|
-
goals:
|
|
548
|
-
videoUrl:
|
|
549
|
-
showDiscount:
|
|
550
|
-
discount:
|
|
551
|
-
paymentLink:
|
|
552
|
-
reward:
|
|
553
|
-
show:
|
|
554
|
-
description:
|
|
1048
|
+
var ZCourseCreate = z12.object({
|
|
1049
|
+
title: z12.string().min(1),
|
|
1050
|
+
description: z12.string().min(1),
|
|
1051
|
+
type: z12.enum(["LIVE_CLASS", "SELF_PACED"]),
|
|
1052
|
+
organizationId: z12.string().min(1)
|
|
1053
|
+
});
|
|
1054
|
+
var ZCourseMetadata = z12.object({
|
|
1055
|
+
requirements: z12.string().optional(),
|
|
1056
|
+
description: z12.string().optional(),
|
|
1057
|
+
goals: z12.string().optional(),
|
|
1058
|
+
videoUrl: z12.string().optional(),
|
|
1059
|
+
showDiscount: z12.boolean().optional(),
|
|
1060
|
+
discount: z12.number().optional(),
|
|
1061
|
+
paymentLink: z12.string().optional(),
|
|
1062
|
+
reward: z12.object({
|
|
1063
|
+
show: z12.boolean(),
|
|
1064
|
+
description: z12.string()
|
|
555
1065
|
}).optional(),
|
|
556
|
-
instructor:
|
|
557
|
-
name:
|
|
558
|
-
role:
|
|
559
|
-
coursesNo:
|
|
560
|
-
description:
|
|
561
|
-
imgUrl:
|
|
1066
|
+
instructor: z12.object({
|
|
1067
|
+
name: z12.string(),
|
|
1068
|
+
role: z12.string(),
|
|
1069
|
+
coursesNo: z12.number(),
|
|
1070
|
+
description: z12.string(),
|
|
1071
|
+
imgUrl: z12.string()
|
|
562
1072
|
}).optional(),
|
|
563
|
-
certificate:
|
|
564
|
-
templateUrl:
|
|
1073
|
+
certificate: z12.object({
|
|
1074
|
+
templateUrl: z12.string()
|
|
565
1075
|
}).optional(),
|
|
566
|
-
reviews:
|
|
567
|
-
id:
|
|
568
|
-
hide:
|
|
569
|
-
name:
|
|
570
|
-
avatar_url:
|
|
571
|
-
rating:
|
|
572
|
-
created_at:
|
|
573
|
-
description:
|
|
1076
|
+
reviews: z12.array(z12.object({
|
|
1077
|
+
id: z12.number(),
|
|
1078
|
+
hide: z12.boolean(),
|
|
1079
|
+
name: z12.string(),
|
|
1080
|
+
avatar_url: z12.string(),
|
|
1081
|
+
rating: z12.number(),
|
|
1082
|
+
created_at: z12.number(),
|
|
1083
|
+
description: z12.string()
|
|
574
1084
|
})).optional(),
|
|
575
|
-
lessonTabsOrder:
|
|
576
|
-
id:
|
|
577
|
-
name:
|
|
1085
|
+
lessonTabsOrder: z12.array(z12.object({
|
|
1086
|
+
id: z12.union([z12.literal(1), z12.literal(2), z12.literal(3), z12.literal(4)]),
|
|
1087
|
+
name: z12.string()
|
|
578
1088
|
})).optional(),
|
|
579
|
-
grading:
|
|
580
|
-
lessonDownload:
|
|
581
|
-
allowNewStudent:
|
|
582
|
-
sectionDisplay:
|
|
583
|
-
isContentGroupingEnabled:
|
|
584
|
-
});
|
|
585
|
-
var ZCourseUpdate =
|
|
586
|
-
title:
|
|
587
|
-
description:
|
|
588
|
-
type:
|
|
589
|
-
logo:
|
|
590
|
-
slug:
|
|
591
|
-
isPublished:
|
|
592
|
-
overview:
|
|
1089
|
+
grading: z12.boolean().optional(),
|
|
1090
|
+
lessonDownload: z12.boolean().optional(),
|
|
1091
|
+
allowNewStudent: z12.boolean(),
|
|
1092
|
+
sectionDisplay: z12.record(z12.string(), z12.boolean()).optional(),
|
|
1093
|
+
isContentGroupingEnabled: z12.boolean().optional()
|
|
1094
|
+
});
|
|
1095
|
+
var ZCourseUpdate = z12.object({
|
|
1096
|
+
title: z12.string().min(1).optional(),
|
|
1097
|
+
description: z12.string().min(1).optional(),
|
|
1098
|
+
type: z12.enum(["LIVE_CLASS", "SELF_PACED"]).optional(),
|
|
1099
|
+
logo: z12.string().optional(),
|
|
1100
|
+
slug: z12.string().optional(),
|
|
1101
|
+
isPublished: z12.boolean().optional(),
|
|
1102
|
+
overview: z12.string().optional(),
|
|
593
1103
|
metadata: ZCourseMetadata.optional(),
|
|
594
|
-
isCertificateDownloadable:
|
|
595
|
-
certificateTheme:
|
|
596
|
-
tagIds:
|
|
1104
|
+
isCertificateDownloadable: z12.boolean().optional(),
|
|
1105
|
+
certificateTheme: z12.string().optional(),
|
|
1106
|
+
tagIds: z12.array(z12.uuid()).max(100).optional()
|
|
597
1107
|
});
|
|
598
|
-
var ZCourseUpdateParam =
|
|
599
|
-
courseId:
|
|
1108
|
+
var ZCourseUpdateParam = z12.object({
|
|
1109
|
+
courseId: z12.string().min(1)
|
|
600
1110
|
});
|
|
601
|
-
var ZCourseDeleteParam =
|
|
602
|
-
courseId:
|
|
1111
|
+
var ZCourseDeleteParam = z12.object({
|
|
1112
|
+
courseId: z12.string().min(1)
|
|
603
1113
|
});
|
|
604
|
-
var ZCourseProgressParam =
|
|
605
|
-
courseId:
|
|
1114
|
+
var ZCourseProgressParam = z12.object({
|
|
1115
|
+
courseId: z12.string().min(1)
|
|
606
1116
|
});
|
|
607
|
-
var ZCourseProgressQuery =
|
|
608
|
-
profileId:
|
|
1117
|
+
var ZCourseProgressQuery = z12.object({
|
|
1118
|
+
profileId: z12.string().uuid()
|
|
609
1119
|
});
|
|
610
|
-
var ZCourseUserAnalyticsParam =
|
|
611
|
-
courseId:
|
|
612
|
-
userId:
|
|
1120
|
+
var ZCourseUserAnalyticsParam = z12.object({
|
|
1121
|
+
courseId: z12.string().min(1),
|
|
1122
|
+
userId: z12.string().uuid()
|
|
613
1123
|
});
|
|
614
1124
|
|
|
615
1125
|
// ../utils/dist/validation/course-import/course-import.js
|
|
616
|
-
var ZSupportedLocale =
|
|
617
|
-
var ZCourseImportWarning =
|
|
618
|
-
code:
|
|
619
|
-
message:
|
|
620
|
-
severity:
|
|
621
|
-
});
|
|
622
|
-
var ZCourseImportSourceReference =
|
|
623
|
-
type:
|
|
624
|
-
label:
|
|
625
|
-
pageStart:
|
|
626
|
-
pageEnd:
|
|
627
|
-
});
|
|
628
|
-
var ZCourseImportDraftCourse =
|
|
629
|
-
title:
|
|
630
|
-
description:
|
|
631
|
-
type:
|
|
1126
|
+
var ZSupportedLocale = z13.enum(["en", "hi", "fr", "pt", "de", "vi", "ru", "es", "pl", "da"]);
|
|
1127
|
+
var ZCourseImportWarning = z13.object({
|
|
1128
|
+
code: z13.string().min(1),
|
|
1129
|
+
message: z13.string().min(1),
|
|
1130
|
+
severity: z13.enum(["info", "warning", "error"])
|
|
1131
|
+
});
|
|
1132
|
+
var ZCourseImportSourceReference = z13.object({
|
|
1133
|
+
type: z13.enum(["prompt", "pdf", "course"]),
|
|
1134
|
+
label: z13.string().min(1),
|
|
1135
|
+
pageStart: z13.number().int().min(1).optional(),
|
|
1136
|
+
pageEnd: z13.number().int().min(1).optional()
|
|
1137
|
+
});
|
|
1138
|
+
var ZCourseImportDraftCourse = z13.object({
|
|
1139
|
+
title: z13.string().min(1),
|
|
1140
|
+
description: z13.string().min(1),
|
|
1141
|
+
type: z13.enum(["LIVE_CLASS", "SELF_PACED"]),
|
|
632
1142
|
locale: ZSupportedLocale.default("en"),
|
|
633
1143
|
metadata: ZCourseMetadata.optional()
|
|
634
1144
|
});
|
|
635
|
-
var ZCourseImportDraftSection =
|
|
636
|
-
externalId:
|
|
637
|
-
title:
|
|
638
|
-
order:
|
|
639
|
-
});
|
|
640
|
-
var ZCourseImportDraftLesson =
|
|
641
|
-
externalId:
|
|
642
|
-
sectionExternalId:
|
|
643
|
-
title:
|
|
644
|
-
order:
|
|
645
|
-
isUnlocked:
|
|
646
|
-
public:
|
|
647
|
-
});
|
|
648
|
-
var ZCourseImportDraftLessonLanguage =
|
|
649
|
-
lessonExternalId:
|
|
1145
|
+
var ZCourseImportDraftSection = z13.object({
|
|
1146
|
+
externalId: z13.string().min(1),
|
|
1147
|
+
title: z13.string().min(1),
|
|
1148
|
+
order: z13.number().int().min(0)
|
|
1149
|
+
});
|
|
1150
|
+
var ZCourseImportDraftLesson = z13.object({
|
|
1151
|
+
externalId: z13.string().min(1),
|
|
1152
|
+
sectionExternalId: z13.string().min(1),
|
|
1153
|
+
title: z13.string().min(1),
|
|
1154
|
+
order: z13.number().int().min(0),
|
|
1155
|
+
isUnlocked: z13.boolean().optional(),
|
|
1156
|
+
public: z13.boolean().optional()
|
|
1157
|
+
});
|
|
1158
|
+
var ZCourseImportDraftLessonLanguage = z13.object({
|
|
1159
|
+
lessonExternalId: z13.string().min(1),
|
|
650
1160
|
locale: ZSupportedLocale,
|
|
651
|
-
content:
|
|
1161
|
+
content: z13.string().min(1)
|
|
652
1162
|
});
|
|
653
|
-
var ZCourseImportDraftPayload =
|
|
1163
|
+
var ZCourseImportDraftPayload = z13.object({
|
|
654
1164
|
course: ZCourseImportDraftCourse,
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
1165
|
+
tags: z13.array(z13.string().trim().min(1).max(80)).max(100).default([]),
|
|
1166
|
+
sections: z13.array(ZCourseImportDraftSection).min(1),
|
|
1167
|
+
lessons: z13.array(ZCourseImportDraftLesson).min(1),
|
|
1168
|
+
lessonLanguages: z13.array(ZCourseImportDraftLessonLanguage).min(1),
|
|
1169
|
+
exercises: z13.array(z13.record(z13.string(), z13.unknown())).optional(),
|
|
1170
|
+
sourceReferences: z13.array(ZCourseImportSourceReference).optional(),
|
|
1171
|
+
warnings: z13.array(ZCourseImportWarning).default([])
|
|
661
1172
|
}).superRefine((value, ctx) => {
|
|
1173
|
+
const normalizedTags = /* @__PURE__ */ new Set();
|
|
1174
|
+
value.tags.forEach((tag, index) => {
|
|
1175
|
+
const tagKey = tag.trim().toLowerCase();
|
|
1176
|
+
if (normalizedTags.has(tagKey)) {
|
|
1177
|
+
ctx.addIssue({
|
|
1178
|
+
code: z13.ZodIssueCode.custom,
|
|
1179
|
+
path: ["tags", index],
|
|
1180
|
+
message: "Draft tags must be unique"
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
normalizedTags.add(tagKey);
|
|
1184
|
+
});
|
|
662
1185
|
const sectionIds = /* @__PURE__ */ new Set();
|
|
663
1186
|
value.sections.forEach((section, index) => {
|
|
664
1187
|
if (sectionIds.has(section.externalId)) {
|
|
665
1188
|
ctx.addIssue({
|
|
666
|
-
code:
|
|
1189
|
+
code: z13.ZodIssueCode.custom,
|
|
667
1190
|
path: ["sections", index, "externalId"],
|
|
668
1191
|
message: "Section externalId must be unique"
|
|
669
1192
|
});
|
|
@@ -674,7 +1197,7 @@ var ZCourseImportDraftPayload = z3.object({
|
|
|
674
1197
|
value.lessons.forEach((lesson, index) => {
|
|
675
1198
|
if (lessonIds.has(lesson.externalId)) {
|
|
676
1199
|
ctx.addIssue({
|
|
677
|
-
code:
|
|
1200
|
+
code: z13.ZodIssueCode.custom,
|
|
678
1201
|
path: ["lessons", index, "externalId"],
|
|
679
1202
|
message: "Lesson externalId must be unique"
|
|
680
1203
|
});
|
|
@@ -682,7 +1205,7 @@ var ZCourseImportDraftPayload = z3.object({
|
|
|
682
1205
|
lessonIds.add(lesson.externalId);
|
|
683
1206
|
if (!sectionIds.has(lesson.sectionExternalId)) {
|
|
684
1207
|
ctx.addIssue({
|
|
685
|
-
code:
|
|
1208
|
+
code: z13.ZodIssueCode.custom,
|
|
686
1209
|
path: ["lessons", index, "sectionExternalId"],
|
|
687
1210
|
message: "Lesson sectionExternalId must reference an existing section"
|
|
688
1211
|
});
|
|
@@ -691,52 +1214,76 @@ var ZCourseImportDraftPayload = z3.object({
|
|
|
691
1214
|
value.lessonLanguages.forEach((lessonLanguage, index) => {
|
|
692
1215
|
if (!lessonIds.has(lessonLanguage.lessonExternalId)) {
|
|
693
1216
|
ctx.addIssue({
|
|
694
|
-
code:
|
|
1217
|
+
code: z13.ZodIssueCode.custom,
|
|
695
1218
|
path: ["lessonLanguages", index, "lessonExternalId"],
|
|
696
1219
|
message: "Lesson language must reference an existing lesson"
|
|
697
1220
|
});
|
|
698
1221
|
}
|
|
699
1222
|
});
|
|
700
1223
|
});
|
|
701
|
-
var ZCourseImportDraftCreate =
|
|
702
|
-
sourceType:
|
|
703
|
-
idempotencyKey:
|
|
704
|
-
summary:
|
|
705
|
-
sourceArtifacts:
|
|
1224
|
+
var ZCourseImportDraftCreate = z13.object({
|
|
1225
|
+
sourceType: z13.enum(["prompt", "pdf", "course"]),
|
|
1226
|
+
idempotencyKey: z13.string().min(1).optional(),
|
|
1227
|
+
summary: z13.record(z13.string(), z13.unknown()).optional(),
|
|
1228
|
+
sourceArtifacts: z13.array(z13.record(z13.string(), z13.unknown())).optional(),
|
|
706
1229
|
draft: ZCourseImportDraftPayload
|
|
707
1230
|
});
|
|
708
|
-
var ZCourseImportCourseParam =
|
|
709
|
-
courseId:
|
|
1231
|
+
var ZCourseImportCourseParam = z13.object({
|
|
1232
|
+
courseId: z13.string().min(1)
|
|
710
1233
|
});
|
|
711
|
-
var ZCourseImportDraftCreateFromCourse =
|
|
712
|
-
courseId:
|
|
713
|
-
idempotencyKey:
|
|
714
|
-
summary:
|
|
715
|
-
sourceArtifacts:
|
|
1234
|
+
var ZCourseImportDraftCreateFromCourse = z13.object({
|
|
1235
|
+
courseId: z13.string().min(1),
|
|
1236
|
+
idempotencyKey: z13.string().min(1).optional(),
|
|
1237
|
+
summary: z13.record(z13.string(), z13.unknown()).optional(),
|
|
1238
|
+
sourceArtifacts: z13.array(z13.record(z13.string(), z13.unknown())).optional()
|
|
716
1239
|
});
|
|
717
|
-
var ZCourseImportDraftGetParam =
|
|
718
|
-
draftId:
|
|
1240
|
+
var ZCourseImportDraftGetParam = z13.object({
|
|
1241
|
+
draftId: z13.string().uuid()
|
|
719
1242
|
});
|
|
720
|
-
var ZCourseImportDraftUpdate =
|
|
721
|
-
summary:
|
|
722
|
-
sourceArtifacts:
|
|
723
|
-
warnings:
|
|
1243
|
+
var ZCourseImportDraftUpdate = z13.object({
|
|
1244
|
+
summary: z13.record(z13.string(), z13.unknown()).optional(),
|
|
1245
|
+
sourceArtifacts: z13.array(z13.record(z13.string(), z13.unknown())).optional(),
|
|
1246
|
+
warnings: z13.array(ZCourseImportWarning).optional(),
|
|
724
1247
|
draft: ZCourseImportDraftPayload.optional()
|
|
725
1248
|
});
|
|
726
|
-
var ZCourseImportDraftPublish =
|
|
727
|
-
title:
|
|
728
|
-
description:
|
|
729
|
-
type:
|
|
730
|
-
metadata: ZCourseMetadata.optional()
|
|
1249
|
+
var ZCourseImportDraftPublish = z13.object({
|
|
1250
|
+
title: z13.string().min(1).optional(),
|
|
1251
|
+
description: z13.string().min(1).optional(),
|
|
1252
|
+
type: z13.enum(["LIVE_CLASS", "SELF_PACED"]).optional(),
|
|
1253
|
+
metadata: ZCourseMetadata.optional(),
|
|
1254
|
+
bannerImageUrl: z13.string().url().optional(),
|
|
1255
|
+
bannerImageQuery: z13.string().min(1).max(120).optional(),
|
|
1256
|
+
generateBannerImage: z13.boolean().optional()
|
|
731
1257
|
});
|
|
732
1258
|
var ZCourseImportDraftPublishToCourse = ZCourseImportDraftPublish.extend({
|
|
733
|
-
courseId:
|
|
1259
|
+
courseId: z13.string().min(1)
|
|
734
1260
|
});
|
|
735
1261
|
|
|
736
1262
|
// src/tools/course-drafts.ts
|
|
737
1263
|
var ZUpdateCourseDraftToolInput = ZCourseImportDraftUpdate.extend({
|
|
738
1264
|
draftId: ZCourseImportDraftGetParam.shape.draftId
|
|
739
1265
|
});
|
|
1266
|
+
var ZTagCourseDraftToolInput = ZAutomationDraftTagAssignment.extend({
|
|
1267
|
+
draftId: ZAutomationDraftTagParam.shape.draftId
|
|
1268
|
+
});
|
|
1269
|
+
var ZListCourseExercisesToolInput = ZExerciseListQuery.extend({
|
|
1270
|
+
courseId: ZCourseImportCourseParam.shape.courseId
|
|
1271
|
+
});
|
|
1272
|
+
var ZGetCourseExerciseToolInput = ZExerciseGetParam.extend({
|
|
1273
|
+
courseId: ZCourseImportCourseParam.shape.courseId
|
|
1274
|
+
});
|
|
1275
|
+
var ZCreateCourseExerciseToolInput = ZExerciseCreate.omit({
|
|
1276
|
+
courseId: true
|
|
1277
|
+
}).extend({
|
|
1278
|
+
courseId: ZCourseImportCourseParam.shape.courseId
|
|
1279
|
+
});
|
|
1280
|
+
var ZCreateCourseExerciseFromTemplateToolInput = ZExerciseFromTemplate.extend({
|
|
1281
|
+
courseId: ZCourseImportCourseParam.shape.courseId
|
|
1282
|
+
});
|
|
1283
|
+
var ZUpdateCourseExerciseToolInput = ZExerciseUpdate.extend({
|
|
1284
|
+
courseId: ZCourseImportCourseParam.shape.courseId,
|
|
1285
|
+
exerciseId: ZExerciseGetParam.shape.exerciseId
|
|
1286
|
+
});
|
|
740
1287
|
var ZPublishCourseDraftToolInput = ZCourseImportDraftPublish.extend({
|
|
741
1288
|
draftId: ZCourseImportDraftGetParam.shape.draftId
|
|
742
1289
|
});
|
|
@@ -745,47 +1292,170 @@ var ZPublishCourseDraftToExistingCourseToolInput = ZCourseImportDraftPublishToCo
|
|
|
745
1292
|
});
|
|
746
1293
|
var createCourseDraftShape = ZCourseImportDraftCreate.shape;
|
|
747
1294
|
var createCourseDraftFromCourseShape = ZCourseImportDraftCreateFromCourse.shape;
|
|
1295
|
+
var listOrganizationCoursesShape = ZGetOrganizationCoursesQuery.shape;
|
|
748
1296
|
var getCourseStructureShape = ZCourseImportCourseParam.shape;
|
|
749
1297
|
var getCourseDraftShape = ZCourseImportDraftGetParam.shape;
|
|
750
1298
|
var updateCourseDraftShape = ZUpdateCourseDraftToolInput.shape;
|
|
1299
|
+
var tagCourseDraftShape = ZTagCourseDraftToolInput.shape;
|
|
1300
|
+
var listCourseExercisesShape = ZListCourseExercisesToolInput.shape;
|
|
1301
|
+
var getCourseExerciseShape = ZGetCourseExerciseToolInput.shape;
|
|
1302
|
+
var createCourseExerciseShape = ZCreateCourseExerciseToolInput.shape;
|
|
1303
|
+
var createCourseExerciseFromTemplateShape = ZCreateCourseExerciseFromTemplateToolInput.shape;
|
|
1304
|
+
var updateCourseExerciseShape = ZUpdateCourseExerciseToolInput.shape;
|
|
751
1305
|
var publishCourseDraftShape = ZPublishCourseDraftToolInput.shape;
|
|
752
1306
|
var publishCourseDraftToExistingCourseShape = ZPublishCourseDraftToExistingCourseToolInput.shape;
|
|
1307
|
+
var tagCoursesShape = ZAutomationCourseTagAssignment.shape;
|
|
753
1308
|
function registerCourseDraftTools(server, apiClient) {
|
|
754
|
-
server.tool(
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
server.tool(
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
server.tool(
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
server.tool(
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1309
|
+
server.tool(
|
|
1310
|
+
"list_org_courses",
|
|
1311
|
+
"List all courses in the authenticated organization. Use this when the user refers to a course by name and you need to discover the available course IDs first.",
|
|
1312
|
+
listOrganizationCoursesShape,
|
|
1313
|
+
async (args) => {
|
|
1314
|
+
const query = ZGetOrganizationCoursesQuery.parse(args);
|
|
1315
|
+
const result = await apiClient.listOrganizationCourses(query);
|
|
1316
|
+
return jsonContent(result);
|
|
1317
|
+
}
|
|
1318
|
+
);
|
|
1319
|
+
server.tool(
|
|
1320
|
+
"get_course_structure",
|
|
1321
|
+
"Read the current live course structure. Use this before creating a fresh draft for post-publish edits.",
|
|
1322
|
+
getCourseStructureShape,
|
|
1323
|
+
async (args) => {
|
|
1324
|
+
const { courseId } = ZCourseImportCourseParam.parse(args);
|
|
1325
|
+
const result = await apiClient.getCourseStructure(courseId);
|
|
1326
|
+
return jsonContent(result);
|
|
1327
|
+
}
|
|
1328
|
+
);
|
|
1329
|
+
server.tool(
|
|
1330
|
+
"create_course_draft",
|
|
1331
|
+
"Create a new unpublished course draft from structured course JSON. Use this before the first publish.",
|
|
1332
|
+
createCourseDraftShape,
|
|
1333
|
+
async (args) => {
|
|
1334
|
+
const payload = ZCourseImportDraftCreate.parse(args);
|
|
1335
|
+
const result = await apiClient.createCourseDraft(payload);
|
|
1336
|
+
return jsonContent(result);
|
|
1337
|
+
}
|
|
1338
|
+
);
|
|
1339
|
+
server.tool(
|
|
1340
|
+
"create_course_draft_from_course",
|
|
1341
|
+
"Create a fresh draft from an existing live course. Use this after a course has already been published and the user wants more changes.",
|
|
1342
|
+
createCourseDraftFromCourseShape,
|
|
1343
|
+
async (args) => {
|
|
1344
|
+
const payload = ZCourseImportDraftCreateFromCourse.parse(args);
|
|
1345
|
+
const result = await apiClient.createCourseDraftFromCourse(payload);
|
|
1346
|
+
return jsonContent(result);
|
|
1347
|
+
}
|
|
1348
|
+
);
|
|
1349
|
+
server.tool(
|
|
1350
|
+
"get_course_draft",
|
|
1351
|
+
"Fetch an existing draft. Draft responses include status and publishedCourseId so you can decide whether to keep editing the draft or seed a fresh one from the live course.",
|
|
1352
|
+
getCourseDraftShape,
|
|
1353
|
+
async (args) => {
|
|
1354
|
+
const { draftId } = ZCourseImportDraftGetParam.parse(args);
|
|
1355
|
+
const result = await apiClient.getCourseDraft(draftId);
|
|
1356
|
+
return jsonContent(result);
|
|
1357
|
+
}
|
|
1358
|
+
);
|
|
1359
|
+
server.tool(
|
|
1360
|
+
"list_course_exercises",
|
|
1361
|
+
"List exercises for a live course, optionally filtered by lessonId or sectionId.",
|
|
1362
|
+
listCourseExercisesShape,
|
|
1363
|
+
async (args) => {
|
|
1364
|
+
const { courseId, ...query } = ZListCourseExercisesToolInput.parse(args);
|
|
1365
|
+
const result = await apiClient.listCourseExercises(courseId, query);
|
|
1366
|
+
return jsonContent(result);
|
|
1367
|
+
}
|
|
1368
|
+
);
|
|
1369
|
+
server.tool(
|
|
1370
|
+
"get_course_exercise",
|
|
1371
|
+
"Fetch a single exercise from a live course, including its questions and options.",
|
|
1372
|
+
getCourseExerciseShape,
|
|
1373
|
+
async (args) => {
|
|
1374
|
+
const { courseId, exerciseId } = ZGetCourseExerciseToolInput.parse(args);
|
|
1375
|
+
const result = await apiClient.getCourseExercise(courseId, exerciseId);
|
|
1376
|
+
return jsonContent(result);
|
|
1377
|
+
}
|
|
1378
|
+
);
|
|
1379
|
+
server.tool(
|
|
1380
|
+
"create_course_exercise",
|
|
1381
|
+
"Create a new exercise directly on a live course. Use this for adding exercises after a course has already been published.",
|
|
1382
|
+
createCourseExerciseShape,
|
|
1383
|
+
async (args) => {
|
|
1384
|
+
const { courseId, ...payload } = ZCreateCourseExerciseToolInput.parse(args);
|
|
1385
|
+
const result = await apiClient.createCourseExercise(courseId, payload);
|
|
1386
|
+
return jsonContent(result);
|
|
1387
|
+
}
|
|
1388
|
+
);
|
|
1389
|
+
server.tool(
|
|
1390
|
+
"create_course_exercise_from_template",
|
|
1391
|
+
"Create a new exercise on a live course from an existing template.",
|
|
1392
|
+
createCourseExerciseFromTemplateShape,
|
|
1393
|
+
async (args) => {
|
|
1394
|
+
const { courseId, ...payload } = ZCreateCourseExerciseFromTemplateToolInput.parse(args);
|
|
1395
|
+
const result = await apiClient.createCourseExerciseFromTemplate(courseId, payload);
|
|
1396
|
+
return jsonContent(result);
|
|
1397
|
+
}
|
|
1398
|
+
);
|
|
1399
|
+
server.tool(
|
|
1400
|
+
"update_course_exercise",
|
|
1401
|
+
"Update an existing exercise on a live course, including questions and options.",
|
|
1402
|
+
updateCourseExerciseShape,
|
|
1403
|
+
async (args) => {
|
|
1404
|
+
const { courseId, exerciseId, ...payload } = ZUpdateCourseExerciseToolInput.parse(args);
|
|
1405
|
+
const result = await apiClient.updateCourseExercise(courseId, exerciseId, payload);
|
|
1406
|
+
return jsonContent(result);
|
|
1407
|
+
}
|
|
1408
|
+
);
|
|
1409
|
+
server.tool(
|
|
1410
|
+
"update_course_draft",
|
|
1411
|
+
"Update an unpublished draft. If the draft is already published, do not keep editing it blindly; create a fresh draft from the live course first.",
|
|
1412
|
+
updateCourseDraftShape,
|
|
1413
|
+
async (args) => {
|
|
1414
|
+
const { draftId, ...payload } = ZUpdateCourseDraftToolInput.parse(args);
|
|
1415
|
+
const result = await apiClient.updateCourseDraft(draftId, payload);
|
|
1416
|
+
return jsonContent(result);
|
|
1417
|
+
}
|
|
1418
|
+
);
|
|
1419
|
+
server.tool(
|
|
1420
|
+
"tag_course_draft",
|
|
1421
|
+
"Attach human-readable tags to a draft before publish. The tags are stored on the draft and applied during publish.",
|
|
1422
|
+
tagCourseDraftShape,
|
|
1423
|
+
async (args) => {
|
|
1424
|
+
const { draftId, ...payload } = ZTagCourseDraftToolInput.parse(args);
|
|
1425
|
+
const result = await apiClient.tagCourseDraft(draftId, payload);
|
|
1426
|
+
return jsonContent(result);
|
|
1427
|
+
}
|
|
1428
|
+
);
|
|
1429
|
+
server.tool(
|
|
1430
|
+
"publish_course_draft",
|
|
1431
|
+
"Publish an unpublished draft as a new live course. The result includes courseId and courseUrl. After publish, future major edits should usually start from a fresh draft created from the live course.",
|
|
1432
|
+
publishCourseDraftShape,
|
|
1433
|
+
async (args) => {
|
|
1434
|
+
const { draftId, ...payload } = ZPublishCourseDraftToolInput.parse(args);
|
|
1435
|
+
const result = await apiClient.publishCourseDraft(draftId, payload);
|
|
1436
|
+
return jsonContent(result);
|
|
1437
|
+
}
|
|
1438
|
+
);
|
|
1439
|
+
server.tool(
|
|
1440
|
+
"publish_course_draft_to_existing_course",
|
|
1441
|
+
"Apply a fresh draft back onto an existing live course. Use this after reading the live course and creating a new draft from it.",
|
|
1442
|
+
publishCourseDraftToExistingCourseShape,
|
|
1443
|
+
async (args) => {
|
|
1444
|
+
const { draftId, ...payload } = ZPublishCourseDraftToExistingCourseToolInput.parse(args);
|
|
1445
|
+
const result = await apiClient.publishCourseDraftToExistingCourse(draftId, payload);
|
|
1446
|
+
return jsonContent(result);
|
|
1447
|
+
}
|
|
1448
|
+
);
|
|
1449
|
+
server.tool(
|
|
1450
|
+
"tag_courses",
|
|
1451
|
+
"Assign tags directly to one or more live courses by name. Default mode is merge, so existing tags are preserved unless replace is requested.",
|
|
1452
|
+
tagCoursesShape,
|
|
1453
|
+
async (args) => {
|
|
1454
|
+
const payload = ZAutomationCourseTagAssignment.parse(args);
|
|
1455
|
+
const result = await apiClient.tagCourses(payload);
|
|
1456
|
+
return jsonContent(result);
|
|
1457
|
+
}
|
|
1458
|
+
);
|
|
789
1459
|
}
|
|
790
1460
|
function jsonContent(data) {
|
|
791
1461
|
return {
|