@timeback/core 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts +4 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/errors.js +30 -8
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +645 -355
- package/dist/utils.js +119 -68
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -699,7 +699,17 @@ class TimebackProvider {
|
|
|
699
699
|
}
|
|
700
700
|
function getEnv(key) {
|
|
701
701
|
try {
|
|
702
|
-
|
|
702
|
+
if (typeof process === "undefined")
|
|
703
|
+
return;
|
|
704
|
+
if (typeof key === "string") {
|
|
705
|
+
return process.env[key];
|
|
706
|
+
}
|
|
707
|
+
for (const k of key) {
|
|
708
|
+
const value = process.env[k];
|
|
709
|
+
if (value !== undefined)
|
|
710
|
+
return value;
|
|
711
|
+
}
|
|
712
|
+
return;
|
|
703
713
|
} catch {
|
|
704
714
|
return;
|
|
705
715
|
}
|
|
@@ -730,6 +740,18 @@ var DEFAULT_PROVIDER_REGISTRY = {
|
|
|
730
740
|
}
|
|
731
741
|
}
|
|
732
742
|
};
|
|
743
|
+
function primaryEnvVar(key) {
|
|
744
|
+
if (typeof key === "string") {
|
|
745
|
+
return key;
|
|
746
|
+
}
|
|
747
|
+
if (key.length === 0) {
|
|
748
|
+
throw new Error(`Missing env var key: ${key}`);
|
|
749
|
+
}
|
|
750
|
+
return key[0];
|
|
751
|
+
}
|
|
752
|
+
function formatEnvVarKey(key) {
|
|
753
|
+
return primaryEnvVar(key);
|
|
754
|
+
}
|
|
733
755
|
function validateEnv(env) {
|
|
734
756
|
if (env !== "staging" && env !== "production") {
|
|
735
757
|
throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
|
|
@@ -740,10 +762,10 @@ function validateAuth(auth, envVars) {
|
|
|
740
762
|
const clientId = auth?.clientId ?? getEnv(envVars.clientId);
|
|
741
763
|
const clientSecret = auth?.clientSecret ?? getEnv(envVars.clientSecret);
|
|
742
764
|
if (!clientId) {
|
|
743
|
-
throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
|
|
765
|
+
throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey(envVars.clientId)}`);
|
|
744
766
|
}
|
|
745
767
|
if (!clientSecret) {
|
|
746
|
-
throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
|
|
768
|
+
throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey(envVars.clientSecret)}`);
|
|
747
769
|
}
|
|
748
770
|
return { clientId, clientSecret };
|
|
749
771
|
}
|
|
@@ -759,21 +781,21 @@ function buildMissingEnvError(envVars) {
|
|
|
759
781
|
const clientId = getEnv(envVars.clientId);
|
|
760
782
|
const clientSecret = getEnv(envVars.clientSecret);
|
|
761
783
|
if (baseUrl === undefined && clientId === undefined) {
|
|
762
|
-
const hint = envVars.env ?? envVars.baseUrl;
|
|
784
|
+
const hint = formatEnvVarKey(envVars.env ?? envVars.baseUrl);
|
|
763
785
|
return `Missing env: provide in config or set ${hint}`;
|
|
764
786
|
}
|
|
765
787
|
const missing = [];
|
|
766
788
|
if (baseUrl === undefined) {
|
|
767
|
-
missing.push(envVars.env ?? envVars.baseUrl);
|
|
789
|
+
missing.push(formatEnvVarKey(envVars.env ?? envVars.baseUrl));
|
|
768
790
|
}
|
|
769
791
|
if (baseUrl !== undefined && authUrl === undefined) {
|
|
770
|
-
missing.push(envVars.authUrl);
|
|
792
|
+
missing.push(formatEnvVarKey(envVars.authUrl));
|
|
771
793
|
}
|
|
772
794
|
if (clientId === undefined) {
|
|
773
|
-
missing.push(envVars.clientId);
|
|
795
|
+
missing.push(formatEnvVarKey(envVars.clientId));
|
|
774
796
|
}
|
|
775
797
|
if (clientSecret === undefined) {
|
|
776
|
-
missing.push(envVars.clientSecret);
|
|
798
|
+
missing.push(formatEnvVarKey(envVars.clientSecret));
|
|
777
799
|
}
|
|
778
800
|
return `Missing environment variables: ${missing.join(", ")}`;
|
|
779
801
|
}
|
|
@@ -1473,10 +1495,10 @@ function validateOffsetListParams(params) {
|
|
|
1473
1495
|
}
|
|
1474
1496
|
}
|
|
1475
1497
|
var CALIPER_ENV_VARS = {
|
|
1476
|
-
baseUrl: "CALIPER_BASE_URL",
|
|
1477
|
-
authUrl: "CALIPER_TOKEN_URL",
|
|
1478
|
-
clientId: "CALIPER_CLIENT_ID",
|
|
1479
|
-
clientSecret: "CALIPER_CLIENT_SECRET"
|
|
1498
|
+
baseUrl: ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "CALIPER_BASE_URL"],
|
|
1499
|
+
authUrl: ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL", "CALIPER_TOKEN_URL"],
|
|
1500
|
+
clientId: ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID", "CALIPER_CLIENT_ID"],
|
|
1501
|
+
clientSecret: ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET", "CALIPER_CLIENT_SECRET"]
|
|
1480
1502
|
};
|
|
1481
1503
|
var CALIPER_DATA_VERSION = "http://purl.imsglobal.org/ctx/caliper/v1p2";
|
|
1482
1504
|
function resolveToProvider2(config, registry = DEFAULT_PROVIDER_REGISTRY) {
|
|
@@ -3725,7 +3747,7 @@ class Doc {
|
|
|
3725
3747
|
var version = {
|
|
3726
3748
|
major: 4,
|
|
3727
3749
|
minor: 3,
|
|
3728
|
-
patch:
|
|
3750
|
+
patch: 6
|
|
3729
3751
|
};
|
|
3730
3752
|
var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
3731
3753
|
var _a;
|
|
@@ -5009,7 +5031,7 @@ var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
5009
5031
|
if (keyResult instanceof Promise) {
|
|
5010
5032
|
throw new Error("Async schemas not supported in object keys currently");
|
|
5011
5033
|
}
|
|
5012
|
-
const checkNumericKey = typeof key === "string" && number.test(key) && keyResult.issues.length
|
|
5034
|
+
const checkNumericKey = typeof key === "string" && number.test(key) && keyResult.issues.length;
|
|
5013
5035
|
if (checkNumericKey) {
|
|
5014
5036
|
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
5015
5037
|
if (retryResult instanceof Promise) {
|
|
@@ -12326,7 +12348,7 @@ function finalize(ctx, schema) {
|
|
|
12326
12348
|
}
|
|
12327
12349
|
}
|
|
12328
12350
|
}
|
|
12329
|
-
if (refSchema.$ref) {
|
|
12351
|
+
if (refSchema.$ref && refSeen.def) {
|
|
12330
12352
|
for (const key in schema2) {
|
|
12331
12353
|
if (key === "$ref" || key === "allOf")
|
|
12332
12354
|
continue;
|
|
@@ -14958,7 +14980,7 @@ var TimebackSubject = exports_external.enum([
|
|
|
14958
14980
|
"Math",
|
|
14959
14981
|
"None",
|
|
14960
14982
|
"Other"
|
|
14961
|
-
]);
|
|
14983
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
14962
14984
|
var TimebackGrade = exports_external.union([
|
|
14963
14985
|
exports_external.literal(-1),
|
|
14964
14986
|
exports_external.literal(0),
|
|
@@ -14975,7 +14997,10 @@ var TimebackGrade = exports_external.union([
|
|
|
14975
14997
|
exports_external.literal(11),
|
|
14976
14998
|
exports_external.literal(12),
|
|
14977
14999
|
exports_external.literal(13)
|
|
14978
|
-
])
|
|
15000
|
+
]).meta({
|
|
15001
|
+
id: "TimebackGrade",
|
|
15002
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
15003
|
+
});
|
|
14979
15004
|
var ScoreStatus = exports_external.enum([
|
|
14980
15005
|
"exempt",
|
|
14981
15006
|
"fully graded",
|
|
@@ -15205,62 +15230,84 @@ var CaliperListEventsParams = exports_external.object({
|
|
|
15205
15230
|
actorEmail: exports_external.email().optional()
|
|
15206
15231
|
}).strict();
|
|
15207
15232
|
var CourseIds = exports_external.object({
|
|
15208
|
-
staging: exports_external.string().optional(),
|
|
15209
|
-
production: exports_external.string().optional()
|
|
15210
|
-
});
|
|
15211
|
-
var CourseType = exports_external.enum(["base", "hole-filling", "optional"]);
|
|
15212
|
-
var PublishStatus = exports_external.enum(["draft", "testing", "published", "deactivated"]);
|
|
15233
|
+
staging: exports_external.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
15234
|
+
production: exports_external.string().meta({ description: "Course ID in production environment" }).optional()
|
|
15235
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
15236
|
+
var CourseType = exports_external.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
15237
|
+
var PublishStatus = exports_external.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
15213
15238
|
var CourseGoals = exports_external.object({
|
|
15214
|
-
dailyXp: exports_external.number().int().positive().optional(),
|
|
15215
|
-
dailyLessons: exports_external.number().int().positive().optional(),
|
|
15216
|
-
dailyActiveMinutes: exports_external.number().int().positive().optional(),
|
|
15217
|
-
dailyAccuracy: exports_external.number().int().min(0).max(100).optional(),
|
|
15218
|
-
dailyMasteredUnits: exports_external.number().int().positive().optional()
|
|
15219
|
-
});
|
|
15239
|
+
dailyXp: exports_external.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
15240
|
+
dailyLessons: exports_external.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
15241
|
+
dailyActiveMinutes: exports_external.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
15242
|
+
dailyAccuracy: exports_external.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
15243
|
+
dailyMasteredUnits: exports_external.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
15244
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
15220
15245
|
var CourseMetrics = exports_external.object({
|
|
15221
|
-
totalXp: exports_external.number().int().positive().optional(),
|
|
15222
|
-
totalLessons: exports_external.number().int().positive().optional(),
|
|
15223
|
-
totalGrades: exports_external.number().int().positive().optional()
|
|
15224
|
-
});
|
|
15246
|
+
totalXp: exports_external.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
15247
|
+
totalLessons: exports_external.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
15248
|
+
totalGrades: exports_external.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
15249
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
15225
15250
|
var CourseMetadata = exports_external.object({
|
|
15226
15251
|
courseType: CourseType.optional(),
|
|
15227
|
-
isSupplemental: exports_external.boolean().optional(),
|
|
15228
|
-
isCustom: exports_external.boolean().optional(),
|
|
15252
|
+
isSupplemental: exports_external.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
15253
|
+
isCustom: exports_external.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
15229
15254
|
publishStatus: PublishStatus.optional(),
|
|
15230
|
-
contactEmail: exports_external.email().optional(),
|
|
15231
|
-
primaryApp: exports_external.string().optional(),
|
|
15255
|
+
contactEmail: exports_external.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
15256
|
+
primaryApp: exports_external.string().meta({ description: "Primary application identifier" }).optional(),
|
|
15232
15257
|
goals: CourseGoals.optional(),
|
|
15233
15258
|
metrics: CourseMetrics.optional()
|
|
15234
|
-
});
|
|
15259
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
15235
15260
|
var CourseDefaults = exports_external.object({
|
|
15236
|
-
courseCode: exports_external.string().optional(),
|
|
15237
|
-
level: exports_external.string().optional(),
|
|
15261
|
+
courseCode: exports_external.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
15262
|
+
level: exports_external.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
15238
15263
|
metadata: CourseMetadata.optional()
|
|
15264
|
+
}).meta({
|
|
15265
|
+
id: "CourseDefaults",
|
|
15266
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
15239
15267
|
});
|
|
15240
15268
|
var CourseEnvOverrides = exports_external.object({
|
|
15241
|
-
level: exports_external.string().optional(),
|
|
15242
|
-
sensor: exports_external.
|
|
15243
|
-
launchUrl: exports_external.
|
|
15269
|
+
level: exports_external.string().meta({ description: "Course level for this environment" }).optional(),
|
|
15270
|
+
sensor: exports_external.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
15271
|
+
launchUrl: exports_external.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
15244
15272
|
metadata: CourseMetadata.optional()
|
|
15273
|
+
}).meta({
|
|
15274
|
+
id: "CourseEnvOverrides",
|
|
15275
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
15245
15276
|
});
|
|
15246
15277
|
var CourseOverrides = exports_external.object({
|
|
15247
|
-
staging: CourseEnvOverrides.
|
|
15248
|
-
|
|
15249
|
-
})
|
|
15278
|
+
staging: CourseEnvOverrides.meta({
|
|
15279
|
+
description: "Overrides for staging environment"
|
|
15280
|
+
}).optional(),
|
|
15281
|
+
production: CourseEnvOverrides.meta({
|
|
15282
|
+
description: "Overrides for production environment"
|
|
15283
|
+
}).optional()
|
|
15284
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
15250
15285
|
var CourseConfig = CourseDefaults.extend({
|
|
15251
|
-
subject: TimebackSubject,
|
|
15252
|
-
grade: TimebackGrade.
|
|
15286
|
+
subject: TimebackSubject.meta({ description: "Subject area for this course" }),
|
|
15287
|
+
grade: TimebackGrade.meta({
|
|
15288
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
15289
|
+
}).optional(),
|
|
15253
15290
|
ids: CourseIds.nullable().optional(),
|
|
15254
|
-
sensor: exports_external.
|
|
15255
|
-
launchUrl: exports_external.
|
|
15291
|
+
sensor: exports_external.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
15292
|
+
launchUrl: exports_external.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
15256
15293
|
overrides: CourseOverrides.optional()
|
|
15294
|
+
}).meta({
|
|
15295
|
+
id: "CourseConfig",
|
|
15296
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
15257
15297
|
});
|
|
15258
15298
|
var TimebackConfig = exports_external.object({
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15299
|
+
$schema: exports_external.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
15300
|
+
name: exports_external.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
15301
|
+
defaults: CourseDefaults.meta({
|
|
15302
|
+
description: "Default properties applied to all courses"
|
|
15303
|
+
}).optional(),
|
|
15304
|
+
courses: exports_external.array(CourseConfig).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
15305
|
+
sensor: exports_external.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
15306
|
+
launchUrl: exports_external.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
15307
|
+
}).meta({
|
|
15308
|
+
id: "TimebackConfig",
|
|
15309
|
+
title: "Timeback Config",
|
|
15310
|
+
description: "Configuration schema for timeback.config.json files"
|
|
15264
15311
|
}).refine((config2) => {
|
|
15265
15312
|
return config2.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
15266
15313
|
}, {
|
|
@@ -15281,17 +15328,23 @@ var TimebackConfig = exports_external.object({
|
|
|
15281
15328
|
message: "Duplicate courseCode found; each must be unique",
|
|
15282
15329
|
path: ["courses"]
|
|
15283
15330
|
}).refine((config2) => {
|
|
15284
|
-
return config2.courses.every((c) =>
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
|
|
15289
|
-
|
|
15331
|
+
return config2.courses.every((c) => {
|
|
15332
|
+
if (c.sensor !== undefined || config2.sensor !== undefined) {
|
|
15333
|
+
return true;
|
|
15334
|
+
}
|
|
15335
|
+
const launchUrls = [
|
|
15336
|
+
c.launchUrl,
|
|
15337
|
+
config2.launchUrl,
|
|
15338
|
+
c.overrides?.staging?.launchUrl,
|
|
15339
|
+
c.overrides?.production?.launchUrl
|
|
15340
|
+
].filter(Boolean);
|
|
15341
|
+
return launchUrls.length > 0;
|
|
15342
|
+
});
|
|
15290
15343
|
}, {
|
|
15291
|
-
message: "Each course must have an effective
|
|
15344
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
15292
15345
|
path: ["courses"]
|
|
15293
15346
|
});
|
|
15294
|
-
var EdubridgeDateString =
|
|
15347
|
+
var EdubridgeDateString = IsoDateTimeString;
|
|
15295
15348
|
var EduBridgeEnrollment = exports_external.object({
|
|
15296
15349
|
id: exports_external.string(),
|
|
15297
15350
|
role: exports_external.string(),
|
|
@@ -15355,12 +15408,9 @@ var EmailOrStudentId = exports_external.object({
|
|
|
15355
15408
|
});
|
|
15356
15409
|
var SubjectTrackInput = exports_external.object({
|
|
15357
15410
|
subject: NonEmptyString,
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
15361
|
-
});
|
|
15362
|
-
var SubjectTrackUpsertInput = SubjectTrackInput.extend({
|
|
15363
|
-
id: NonEmptyString
|
|
15411
|
+
grade: NonEmptyString,
|
|
15412
|
+
courseId: NonEmptyString,
|
|
15413
|
+
orgSourcedId: NonEmptyString.optional()
|
|
15364
15414
|
});
|
|
15365
15415
|
var EdubridgeListEnrollmentsParams = exports_external.object({
|
|
15366
15416
|
userId: NonEmptyString
|
|
@@ -17244,7 +17294,17 @@ class TimebackProvider2 {
|
|
|
17244
17294
|
}
|
|
17245
17295
|
function getEnv2(key) {
|
|
17246
17296
|
try {
|
|
17247
|
-
|
|
17297
|
+
if (typeof process === "undefined")
|
|
17298
|
+
return;
|
|
17299
|
+
if (typeof key === "string") {
|
|
17300
|
+
return process.env[key];
|
|
17301
|
+
}
|
|
17302
|
+
for (const k of key) {
|
|
17303
|
+
const value = process.env[k];
|
|
17304
|
+
if (value !== undefined)
|
|
17305
|
+
return value;
|
|
17306
|
+
}
|
|
17307
|
+
return;
|
|
17248
17308
|
} catch {
|
|
17249
17309
|
return;
|
|
17250
17310
|
}
|
|
@@ -17275,6 +17335,18 @@ var DEFAULT_PROVIDER_REGISTRY2 = {
|
|
|
17275
17335
|
}
|
|
17276
17336
|
}
|
|
17277
17337
|
};
|
|
17338
|
+
function primaryEnvVar2(key) {
|
|
17339
|
+
if (typeof key === "string") {
|
|
17340
|
+
return key;
|
|
17341
|
+
}
|
|
17342
|
+
if (key.length === 0) {
|
|
17343
|
+
throw new Error(`Missing env var key: ${key}`);
|
|
17344
|
+
}
|
|
17345
|
+
return key[0];
|
|
17346
|
+
}
|
|
17347
|
+
function formatEnvVarKey2(key) {
|
|
17348
|
+
return primaryEnvVar2(key);
|
|
17349
|
+
}
|
|
17278
17350
|
function validateEnv2(env) {
|
|
17279
17351
|
if (env !== "staging" && env !== "production") {
|
|
17280
17352
|
throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
|
|
@@ -17285,10 +17357,10 @@ function validateAuth2(auth, envVars) {
|
|
|
17285
17357
|
const clientId = auth?.clientId ?? getEnv2(envVars.clientId);
|
|
17286
17358
|
const clientSecret = auth?.clientSecret ?? getEnv2(envVars.clientSecret);
|
|
17287
17359
|
if (!clientId) {
|
|
17288
|
-
throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
|
|
17360
|
+
throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey2(envVars.clientId)}`);
|
|
17289
17361
|
}
|
|
17290
17362
|
if (!clientSecret) {
|
|
17291
|
-
throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
|
|
17363
|
+
throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey2(envVars.clientSecret)}`);
|
|
17292
17364
|
}
|
|
17293
17365
|
return { clientId, clientSecret };
|
|
17294
17366
|
}
|
|
@@ -17304,21 +17376,21 @@ function buildMissingEnvError2(envVars) {
|
|
|
17304
17376
|
const clientId = getEnv2(envVars.clientId);
|
|
17305
17377
|
const clientSecret = getEnv2(envVars.clientSecret);
|
|
17306
17378
|
if (baseUrl === undefined && clientId === undefined) {
|
|
17307
|
-
const hint = envVars.env ?? envVars.baseUrl;
|
|
17379
|
+
const hint = formatEnvVarKey2(envVars.env ?? envVars.baseUrl);
|
|
17308
17380
|
return `Missing env: provide in config or set ${hint}`;
|
|
17309
17381
|
}
|
|
17310
17382
|
const missing = [];
|
|
17311
17383
|
if (baseUrl === undefined) {
|
|
17312
|
-
missing.push(envVars.env ?? envVars.baseUrl);
|
|
17384
|
+
missing.push(formatEnvVarKey2(envVars.env ?? envVars.baseUrl));
|
|
17313
17385
|
}
|
|
17314
17386
|
if (baseUrl !== undefined && authUrl === undefined) {
|
|
17315
|
-
missing.push(envVars.authUrl);
|
|
17387
|
+
missing.push(formatEnvVarKey2(envVars.authUrl));
|
|
17316
17388
|
}
|
|
17317
17389
|
if (clientId === undefined) {
|
|
17318
|
-
missing.push(envVars.clientId);
|
|
17390
|
+
missing.push(formatEnvVarKey2(envVars.clientId));
|
|
17319
17391
|
}
|
|
17320
17392
|
if (clientSecret === undefined) {
|
|
17321
|
-
missing.push(envVars.clientSecret);
|
|
17393
|
+
missing.push(formatEnvVarKey2(envVars.clientSecret));
|
|
17322
17394
|
}
|
|
17323
17395
|
return `Missing environment variables: ${missing.join(", ")}`;
|
|
17324
17396
|
}
|
|
@@ -17809,10 +17881,10 @@ function validateNonEmptyString2(value, name) {
|
|
|
17809
17881
|
}
|
|
17810
17882
|
}
|
|
17811
17883
|
var EDUBRIDGE_ENV_VARS = {
|
|
17812
|
-
baseUrl: "EDUBRIDGE_BASE_URL",
|
|
17813
|
-
clientId: "EDUBRIDGE_CLIENT_ID",
|
|
17814
|
-
clientSecret: "EDUBRIDGE_CLIENT_SECRET",
|
|
17815
|
-
authUrl: "EDUBRIDGE_TOKEN_URL"
|
|
17884
|
+
baseUrl: ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "EDUBRIDGE_BASE_URL"],
|
|
17885
|
+
clientId: ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID", "EDUBRIDGE_CLIENT_ID"],
|
|
17886
|
+
clientSecret: ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET", "EDUBRIDGE_CLIENT_SECRET"],
|
|
17887
|
+
authUrl: ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL", "EDUBRIDGE_TOKEN_URL"]
|
|
17816
17888
|
};
|
|
17817
17889
|
function resolveToProvider22(config2, registry2 = DEFAULT_PROVIDER_REGISTRY2) {
|
|
17818
17890
|
return resolveToProvider3(config2, EDUBRIDGE_ENV_VARS, registry2);
|
|
@@ -20140,7 +20212,7 @@ class Doc2 {
|
|
|
20140
20212
|
var version2 = {
|
|
20141
20213
|
major: 4,
|
|
20142
20214
|
minor: 3,
|
|
20143
|
-
patch:
|
|
20215
|
+
patch: 6
|
|
20144
20216
|
};
|
|
20145
20217
|
var $ZodType2 = /* @__PURE__ */ $constructor2("$ZodType", (inst, def) => {
|
|
20146
20218
|
var _a2;
|
|
@@ -21424,7 +21496,7 @@ var $ZodRecord2 = /* @__PURE__ */ $constructor2("$ZodRecord", (inst, def) => {
|
|
|
21424
21496
|
if (keyResult instanceof Promise) {
|
|
21425
21497
|
throw new Error("Async schemas not supported in object keys currently");
|
|
21426
21498
|
}
|
|
21427
|
-
const checkNumericKey = typeof key === "string" && number4.test(key) && keyResult.issues.length
|
|
21499
|
+
const checkNumericKey = typeof key === "string" && number4.test(key) && keyResult.issues.length;
|
|
21428
21500
|
if (checkNumericKey) {
|
|
21429
21501
|
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
21430
21502
|
if (retryResult instanceof Promise) {
|
|
@@ -28741,7 +28813,7 @@ function finalize2(ctx, schema) {
|
|
|
28741
28813
|
}
|
|
28742
28814
|
}
|
|
28743
28815
|
}
|
|
28744
|
-
if (refSchema.$ref) {
|
|
28816
|
+
if (refSchema.$ref && refSeen.def) {
|
|
28745
28817
|
for (const key in schema2) {
|
|
28746
28818
|
if (key === "$ref" || key === "allOf")
|
|
28747
28819
|
continue;
|
|
@@ -31373,7 +31445,7 @@ var TimebackSubject2 = exports_external2.enum([
|
|
|
31373
31445
|
"Math",
|
|
31374
31446
|
"None",
|
|
31375
31447
|
"Other"
|
|
31376
|
-
]);
|
|
31448
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
31377
31449
|
var TimebackGrade2 = exports_external2.union([
|
|
31378
31450
|
exports_external2.literal(-1),
|
|
31379
31451
|
exports_external2.literal(0),
|
|
@@ -31390,7 +31462,10 @@ var TimebackGrade2 = exports_external2.union([
|
|
|
31390
31462
|
exports_external2.literal(11),
|
|
31391
31463
|
exports_external2.literal(12),
|
|
31392
31464
|
exports_external2.literal(13)
|
|
31393
|
-
])
|
|
31465
|
+
]).meta({
|
|
31466
|
+
id: "TimebackGrade",
|
|
31467
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
31468
|
+
});
|
|
31394
31469
|
var ScoreStatus2 = exports_external2.enum([
|
|
31395
31470
|
"exempt",
|
|
31396
31471
|
"fully graded",
|
|
@@ -31620,62 +31695,84 @@ var CaliperListEventsParams2 = exports_external2.object({
|
|
|
31620
31695
|
actorEmail: exports_external2.email().optional()
|
|
31621
31696
|
}).strict();
|
|
31622
31697
|
var CourseIds2 = exports_external2.object({
|
|
31623
|
-
staging: exports_external2.string().optional(),
|
|
31624
|
-
production: exports_external2.string().optional()
|
|
31625
|
-
});
|
|
31626
|
-
var CourseType2 = exports_external2.enum(["base", "hole-filling", "optional"]);
|
|
31627
|
-
var PublishStatus2 = exports_external2.enum(["draft", "testing", "published", "deactivated"]);
|
|
31698
|
+
staging: exports_external2.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
31699
|
+
production: exports_external2.string().meta({ description: "Course ID in production environment" }).optional()
|
|
31700
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
31701
|
+
var CourseType2 = exports_external2.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
31702
|
+
var PublishStatus2 = exports_external2.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
31628
31703
|
var CourseGoals2 = exports_external2.object({
|
|
31629
|
-
dailyXp: exports_external2.number().int().positive().optional(),
|
|
31630
|
-
dailyLessons: exports_external2.number().int().positive().optional(),
|
|
31631
|
-
dailyActiveMinutes: exports_external2.number().int().positive().optional(),
|
|
31632
|
-
dailyAccuracy: exports_external2.number().int().min(0).max(100).optional(),
|
|
31633
|
-
dailyMasteredUnits: exports_external2.number().int().positive().optional()
|
|
31634
|
-
});
|
|
31704
|
+
dailyXp: exports_external2.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
31705
|
+
dailyLessons: exports_external2.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
31706
|
+
dailyActiveMinutes: exports_external2.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
31707
|
+
dailyAccuracy: exports_external2.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
31708
|
+
dailyMasteredUnits: exports_external2.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
31709
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
31635
31710
|
var CourseMetrics2 = exports_external2.object({
|
|
31636
|
-
totalXp: exports_external2.number().int().positive().optional(),
|
|
31637
|
-
totalLessons: exports_external2.number().int().positive().optional(),
|
|
31638
|
-
totalGrades: exports_external2.number().int().positive().optional()
|
|
31639
|
-
});
|
|
31711
|
+
totalXp: exports_external2.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
31712
|
+
totalLessons: exports_external2.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
31713
|
+
totalGrades: exports_external2.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
31714
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
31640
31715
|
var CourseMetadata2 = exports_external2.object({
|
|
31641
31716
|
courseType: CourseType2.optional(),
|
|
31642
|
-
isSupplemental: exports_external2.boolean().optional(),
|
|
31643
|
-
isCustom: exports_external2.boolean().optional(),
|
|
31717
|
+
isSupplemental: exports_external2.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
31718
|
+
isCustom: exports_external2.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
31644
31719
|
publishStatus: PublishStatus2.optional(),
|
|
31645
|
-
contactEmail: exports_external2.email().optional(),
|
|
31646
|
-
primaryApp: exports_external2.string().optional(),
|
|
31720
|
+
contactEmail: exports_external2.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
31721
|
+
primaryApp: exports_external2.string().meta({ description: "Primary application identifier" }).optional(),
|
|
31647
31722
|
goals: CourseGoals2.optional(),
|
|
31648
31723
|
metrics: CourseMetrics2.optional()
|
|
31649
|
-
});
|
|
31724
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
31650
31725
|
var CourseDefaults2 = exports_external2.object({
|
|
31651
|
-
courseCode: exports_external2.string().optional(),
|
|
31652
|
-
level: exports_external2.string().optional(),
|
|
31726
|
+
courseCode: exports_external2.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
31727
|
+
level: exports_external2.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
31653
31728
|
metadata: CourseMetadata2.optional()
|
|
31729
|
+
}).meta({
|
|
31730
|
+
id: "CourseDefaults",
|
|
31731
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
31654
31732
|
});
|
|
31655
31733
|
var CourseEnvOverrides2 = exports_external2.object({
|
|
31656
|
-
level: exports_external2.string().optional(),
|
|
31657
|
-
sensor: exports_external2.
|
|
31658
|
-
launchUrl: exports_external2.
|
|
31734
|
+
level: exports_external2.string().meta({ description: "Course level for this environment" }).optional(),
|
|
31735
|
+
sensor: exports_external2.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
31736
|
+
launchUrl: exports_external2.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
31659
31737
|
metadata: CourseMetadata2.optional()
|
|
31738
|
+
}).meta({
|
|
31739
|
+
id: "CourseEnvOverrides",
|
|
31740
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
31660
31741
|
});
|
|
31661
31742
|
var CourseOverrides2 = exports_external2.object({
|
|
31662
|
-
staging: CourseEnvOverrides2.
|
|
31663
|
-
|
|
31664
|
-
})
|
|
31743
|
+
staging: CourseEnvOverrides2.meta({
|
|
31744
|
+
description: "Overrides for staging environment"
|
|
31745
|
+
}).optional(),
|
|
31746
|
+
production: CourseEnvOverrides2.meta({
|
|
31747
|
+
description: "Overrides for production environment"
|
|
31748
|
+
}).optional()
|
|
31749
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
31665
31750
|
var CourseConfig2 = CourseDefaults2.extend({
|
|
31666
|
-
subject: TimebackSubject2,
|
|
31667
|
-
grade: TimebackGrade2.
|
|
31751
|
+
subject: TimebackSubject2.meta({ description: "Subject area for this course" }),
|
|
31752
|
+
grade: TimebackGrade2.meta({
|
|
31753
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
31754
|
+
}).optional(),
|
|
31668
31755
|
ids: CourseIds2.nullable().optional(),
|
|
31669
|
-
sensor: exports_external2.
|
|
31670
|
-
launchUrl: exports_external2.
|
|
31756
|
+
sensor: exports_external2.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
31757
|
+
launchUrl: exports_external2.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
31671
31758
|
overrides: CourseOverrides2.optional()
|
|
31759
|
+
}).meta({
|
|
31760
|
+
id: "CourseConfig",
|
|
31761
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
31672
31762
|
});
|
|
31673
31763
|
var TimebackConfig2 = exports_external2.object({
|
|
31674
|
-
|
|
31675
|
-
|
|
31676
|
-
|
|
31677
|
-
|
|
31678
|
-
|
|
31764
|
+
$schema: exports_external2.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
31765
|
+
name: exports_external2.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
31766
|
+
defaults: CourseDefaults2.meta({
|
|
31767
|
+
description: "Default properties applied to all courses"
|
|
31768
|
+
}).optional(),
|
|
31769
|
+
courses: exports_external2.array(CourseConfig2).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
31770
|
+
sensor: exports_external2.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
31771
|
+
launchUrl: exports_external2.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
31772
|
+
}).meta({
|
|
31773
|
+
id: "TimebackConfig",
|
|
31774
|
+
title: "Timeback Config",
|
|
31775
|
+
description: "Configuration schema for timeback.config.json files"
|
|
31679
31776
|
}).refine((config22) => {
|
|
31680
31777
|
return config22.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
31681
31778
|
}, {
|
|
@@ -31696,17 +31793,23 @@ var TimebackConfig2 = exports_external2.object({
|
|
|
31696
31793
|
message: "Duplicate courseCode found; each must be unique",
|
|
31697
31794
|
path: ["courses"]
|
|
31698
31795
|
}).refine((config22) => {
|
|
31699
|
-
return config22.courses.every((c) =>
|
|
31700
|
-
|
|
31701
|
-
|
|
31702
|
-
|
|
31703
|
-
|
|
31704
|
-
|
|
31796
|
+
return config22.courses.every((c) => {
|
|
31797
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
31798
|
+
return true;
|
|
31799
|
+
}
|
|
31800
|
+
const launchUrls = [
|
|
31801
|
+
c.launchUrl,
|
|
31802
|
+
config22.launchUrl,
|
|
31803
|
+
c.overrides?.staging?.launchUrl,
|
|
31804
|
+
c.overrides?.production?.launchUrl
|
|
31805
|
+
].filter(Boolean);
|
|
31806
|
+
return launchUrls.length > 0;
|
|
31807
|
+
});
|
|
31705
31808
|
}, {
|
|
31706
|
-
message: "Each course must have an effective
|
|
31809
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
31707
31810
|
path: ["courses"]
|
|
31708
31811
|
});
|
|
31709
|
-
var EdubridgeDateString2 =
|
|
31812
|
+
var EdubridgeDateString2 = IsoDateTimeString2;
|
|
31710
31813
|
var EduBridgeEnrollment2 = exports_external2.object({
|
|
31711
31814
|
id: exports_external2.string(),
|
|
31712
31815
|
role: exports_external2.string(),
|
|
@@ -31770,13 +31873,11 @@ var EmailOrStudentId2 = exports_external2.object({
|
|
|
31770
31873
|
});
|
|
31771
31874
|
var SubjectTrackInput2 = exports_external2.object({
|
|
31772
31875
|
subject: NonEmptyString4,
|
|
31773
|
-
|
|
31774
|
-
|
|
31775
|
-
|
|
31776
|
-
});
|
|
31777
|
-
var SubjectTrackUpsertInput2 = SubjectTrackInput2.extend({
|
|
31778
|
-
id: NonEmptyString4
|
|
31876
|
+
grade: NonEmptyString4,
|
|
31877
|
+
courseId: NonEmptyString4,
|
|
31878
|
+
orgSourcedId: NonEmptyString4.optional()
|
|
31779
31879
|
});
|
|
31880
|
+
var SubjectTrackUpsertInput = SubjectTrackInput2;
|
|
31780
31881
|
var EdubridgeListEnrollmentsParams2 = exports_external2.object({
|
|
31781
31882
|
userId: NonEmptyString4
|
|
31782
31883
|
});
|
|
@@ -32834,7 +32935,7 @@ class SubjectTrackResource {
|
|
|
32834
32935
|
return response.subjectTrack;
|
|
32835
32936
|
}
|
|
32836
32937
|
async upsert(data) {
|
|
32837
|
-
validateWithSchema2(
|
|
32938
|
+
validateWithSchema2(SubjectTrackUpsertInput, data, "subject track");
|
|
32838
32939
|
const response = await this.transport.request(`${this.transport.paths.base}/subject-track/`, { method: "PUT", body: data });
|
|
32839
32940
|
return response.subjectTrack;
|
|
32840
32941
|
}
|
|
@@ -33625,7 +33726,17 @@ class TimebackProvider3 {
|
|
|
33625
33726
|
// ../../internal/client-infra/src/utils/utils.ts
|
|
33626
33727
|
function getEnv3(key) {
|
|
33627
33728
|
try {
|
|
33628
|
-
|
|
33729
|
+
if (typeof process === "undefined")
|
|
33730
|
+
return;
|
|
33731
|
+
if (typeof key === "string") {
|
|
33732
|
+
return process.env[key];
|
|
33733
|
+
}
|
|
33734
|
+
for (const k of key) {
|
|
33735
|
+
const value = process.env[k];
|
|
33736
|
+
if (value !== undefined)
|
|
33737
|
+
return value;
|
|
33738
|
+
}
|
|
33739
|
+
return;
|
|
33629
33740
|
} catch {
|
|
33630
33741
|
return;
|
|
33631
33742
|
}
|
|
@@ -33646,6 +33757,18 @@ var DEFAULT_PROVIDER_REGISTRY3 = {
|
|
|
33646
33757
|
};
|
|
33647
33758
|
|
|
33648
33759
|
// ../../internal/client-infra/src/config/resolve.ts
|
|
33760
|
+
function primaryEnvVar3(key) {
|
|
33761
|
+
if (typeof key === "string") {
|
|
33762
|
+
return key;
|
|
33763
|
+
}
|
|
33764
|
+
if (key.length === 0) {
|
|
33765
|
+
throw new Error(`Missing env var key: ${key}`);
|
|
33766
|
+
}
|
|
33767
|
+
return key[0];
|
|
33768
|
+
}
|
|
33769
|
+
function formatEnvVarKey3(key) {
|
|
33770
|
+
return primaryEnvVar3(key);
|
|
33771
|
+
}
|
|
33649
33772
|
function validateEnv3(env) {
|
|
33650
33773
|
if (env !== "staging" && env !== "production") {
|
|
33651
33774
|
throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
|
|
@@ -33656,10 +33779,10 @@ function validateAuth3(auth, envVars) {
|
|
|
33656
33779
|
const clientId = auth?.clientId ?? getEnv3(envVars.clientId);
|
|
33657
33780
|
const clientSecret = auth?.clientSecret ?? getEnv3(envVars.clientSecret);
|
|
33658
33781
|
if (!clientId) {
|
|
33659
|
-
throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
|
|
33782
|
+
throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey3(envVars.clientId)}`);
|
|
33660
33783
|
}
|
|
33661
33784
|
if (!clientSecret) {
|
|
33662
|
-
throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
|
|
33785
|
+
throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey3(envVars.clientSecret)}`);
|
|
33663
33786
|
}
|
|
33664
33787
|
return { clientId, clientSecret };
|
|
33665
33788
|
}
|
|
@@ -33675,21 +33798,21 @@ function buildMissingEnvError3(envVars) {
|
|
|
33675
33798
|
const clientId = getEnv3(envVars.clientId);
|
|
33676
33799
|
const clientSecret = getEnv3(envVars.clientSecret);
|
|
33677
33800
|
if (baseUrl === undefined && clientId === undefined) {
|
|
33678
|
-
const hint = envVars.env ?? envVars.baseUrl;
|
|
33801
|
+
const hint = formatEnvVarKey3(envVars.env ?? envVars.baseUrl);
|
|
33679
33802
|
return `Missing env: provide in config or set ${hint}`;
|
|
33680
33803
|
}
|
|
33681
33804
|
const missing = [];
|
|
33682
33805
|
if (baseUrl === undefined) {
|
|
33683
|
-
missing.push(envVars.env ?? envVars.baseUrl);
|
|
33806
|
+
missing.push(formatEnvVarKey3(envVars.env ?? envVars.baseUrl));
|
|
33684
33807
|
}
|
|
33685
33808
|
if (baseUrl !== undefined && authUrl === undefined) {
|
|
33686
|
-
missing.push(envVars.authUrl);
|
|
33809
|
+
missing.push(formatEnvVarKey3(envVars.authUrl));
|
|
33687
33810
|
}
|
|
33688
33811
|
if (clientId === undefined) {
|
|
33689
|
-
missing.push(envVars.clientId);
|
|
33812
|
+
missing.push(formatEnvVarKey3(envVars.clientId));
|
|
33690
33813
|
}
|
|
33691
33814
|
if (clientSecret === undefined) {
|
|
33692
|
-
missing.push(envVars.clientSecret);
|
|
33815
|
+
missing.push(formatEnvVarKey3(envVars.clientSecret));
|
|
33693
33816
|
}
|
|
33694
33817
|
return `Missing environment variables: ${missing.join(", ")}`;
|
|
33695
33818
|
}
|
|
@@ -34651,7 +34774,17 @@ class TimebackProvider4 {
|
|
|
34651
34774
|
}
|
|
34652
34775
|
function getEnv4(key) {
|
|
34653
34776
|
try {
|
|
34654
|
-
|
|
34777
|
+
if (typeof process === "undefined")
|
|
34778
|
+
return;
|
|
34779
|
+
if (typeof key === "string") {
|
|
34780
|
+
return process.env[key];
|
|
34781
|
+
}
|
|
34782
|
+
for (const k of key) {
|
|
34783
|
+
const value = process.env[k];
|
|
34784
|
+
if (value !== undefined)
|
|
34785
|
+
return value;
|
|
34786
|
+
}
|
|
34787
|
+
return;
|
|
34655
34788
|
} catch {
|
|
34656
34789
|
return;
|
|
34657
34790
|
}
|
|
@@ -34682,6 +34815,18 @@ var DEFAULT_PROVIDER_REGISTRY4 = {
|
|
|
34682
34815
|
}
|
|
34683
34816
|
}
|
|
34684
34817
|
};
|
|
34818
|
+
function primaryEnvVar4(key) {
|
|
34819
|
+
if (typeof key === "string") {
|
|
34820
|
+
return key;
|
|
34821
|
+
}
|
|
34822
|
+
if (key.length === 0) {
|
|
34823
|
+
throw new Error(`Missing env var key: ${key}`);
|
|
34824
|
+
}
|
|
34825
|
+
return key[0];
|
|
34826
|
+
}
|
|
34827
|
+
function formatEnvVarKey4(key) {
|
|
34828
|
+
return primaryEnvVar4(key);
|
|
34829
|
+
}
|
|
34685
34830
|
function validateEnv4(env) {
|
|
34686
34831
|
if (env !== "staging" && env !== "production") {
|
|
34687
34832
|
throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
|
|
@@ -34692,10 +34837,10 @@ function validateAuth4(auth, envVars) {
|
|
|
34692
34837
|
const clientId = auth?.clientId ?? getEnv4(envVars.clientId);
|
|
34693
34838
|
const clientSecret = auth?.clientSecret ?? getEnv4(envVars.clientSecret);
|
|
34694
34839
|
if (!clientId) {
|
|
34695
|
-
throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
|
|
34840
|
+
throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey4(envVars.clientId)}`);
|
|
34696
34841
|
}
|
|
34697
34842
|
if (!clientSecret) {
|
|
34698
|
-
throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
|
|
34843
|
+
throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey4(envVars.clientSecret)}`);
|
|
34699
34844
|
}
|
|
34700
34845
|
return { clientId, clientSecret };
|
|
34701
34846
|
}
|
|
@@ -34711,21 +34856,21 @@ function buildMissingEnvError4(envVars) {
|
|
|
34711
34856
|
const clientId = getEnv4(envVars.clientId);
|
|
34712
34857
|
const clientSecret = getEnv4(envVars.clientSecret);
|
|
34713
34858
|
if (baseUrl === undefined && clientId === undefined) {
|
|
34714
|
-
const hint = envVars.env ?? envVars.baseUrl;
|
|
34859
|
+
const hint = formatEnvVarKey4(envVars.env ?? envVars.baseUrl);
|
|
34715
34860
|
return `Missing env: provide in config or set ${hint}`;
|
|
34716
34861
|
}
|
|
34717
34862
|
const missing = [];
|
|
34718
34863
|
if (baseUrl === undefined) {
|
|
34719
|
-
missing.push(envVars.env ?? envVars.baseUrl);
|
|
34864
|
+
missing.push(formatEnvVarKey4(envVars.env ?? envVars.baseUrl));
|
|
34720
34865
|
}
|
|
34721
34866
|
if (baseUrl !== undefined && authUrl === undefined) {
|
|
34722
|
-
missing.push(envVars.authUrl);
|
|
34867
|
+
missing.push(formatEnvVarKey4(envVars.authUrl));
|
|
34723
34868
|
}
|
|
34724
34869
|
if (clientId === undefined) {
|
|
34725
|
-
missing.push(envVars.clientId);
|
|
34870
|
+
missing.push(formatEnvVarKey4(envVars.clientId));
|
|
34726
34871
|
}
|
|
34727
34872
|
if (clientSecret === undefined) {
|
|
34728
|
-
missing.push(envVars.clientSecret);
|
|
34873
|
+
missing.push(formatEnvVarKey4(envVars.clientSecret));
|
|
34729
34874
|
}
|
|
34730
34875
|
return `Missing environment variables: ${missing.join(", ")}`;
|
|
34731
34876
|
}
|
|
@@ -35441,10 +35586,10 @@ function validateSourcedId2(sourcedId, context) {
|
|
|
35441
35586
|
}
|
|
35442
35587
|
}
|
|
35443
35588
|
var ONEROSTER_ENV_VARS = {
|
|
35444
|
-
baseUrl: "ONEROSTER_BASE_URL",
|
|
35445
|
-
clientId: "ONEROSTER_CLIENT_ID",
|
|
35446
|
-
clientSecret: "ONEROSTER_CLIENT_SECRET",
|
|
35447
|
-
authUrl: "ONEROSTER_TOKEN_URL"
|
|
35589
|
+
baseUrl: ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "ONEROSTER_BASE_URL"],
|
|
35590
|
+
clientId: ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID", "ONEROSTER_CLIENT_ID"],
|
|
35591
|
+
clientSecret: ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET", "ONEROSTER_CLIENT_SECRET"],
|
|
35592
|
+
authUrl: ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL", "ONEROSTER_TOKEN_URL"]
|
|
35448
35593
|
};
|
|
35449
35594
|
function resolveToProvider23(config3, registry3 = DEFAULT_PROVIDER_REGISTRY4) {
|
|
35450
35595
|
return resolveToProvider6(config3, ONEROSTER_ENV_VARS, registry3);
|
|
@@ -37699,7 +37844,7 @@ class Doc3 {
|
|
|
37699
37844
|
var version3 = {
|
|
37700
37845
|
major: 4,
|
|
37701
37846
|
minor: 3,
|
|
37702
|
-
patch:
|
|
37847
|
+
patch: 6
|
|
37703
37848
|
};
|
|
37704
37849
|
var $ZodType3 = /* @__PURE__ */ $constructor3("$ZodType", (inst, def) => {
|
|
37705
37850
|
var _a3;
|
|
@@ -38983,7 +39128,7 @@ var $ZodRecord3 = /* @__PURE__ */ $constructor3("$ZodRecord", (inst, def) => {
|
|
|
38983
39128
|
if (keyResult instanceof Promise) {
|
|
38984
39129
|
throw new Error("Async schemas not supported in object keys currently");
|
|
38985
39130
|
}
|
|
38986
|
-
const checkNumericKey = typeof key === "string" && number6.test(key) && keyResult.issues.length
|
|
39131
|
+
const checkNumericKey = typeof key === "string" && number6.test(key) && keyResult.issues.length;
|
|
38987
39132
|
if (checkNumericKey) {
|
|
38988
39133
|
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
38989
39134
|
if (retryResult instanceof Promise) {
|
|
@@ -46300,7 +46445,7 @@ function finalize3(ctx, schema) {
|
|
|
46300
46445
|
}
|
|
46301
46446
|
}
|
|
46302
46447
|
}
|
|
46303
|
-
if (refSchema.$ref) {
|
|
46448
|
+
if (refSchema.$ref && refSeen.def) {
|
|
46304
46449
|
for (const key in schema2) {
|
|
46305
46450
|
if (key === "$ref" || key === "allOf")
|
|
46306
46451
|
continue;
|
|
@@ -48932,7 +49077,7 @@ var TimebackSubject3 = exports_external3.enum([
|
|
|
48932
49077
|
"Math",
|
|
48933
49078
|
"None",
|
|
48934
49079
|
"Other"
|
|
48935
|
-
]);
|
|
49080
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
48936
49081
|
var TimebackGrade3 = exports_external3.union([
|
|
48937
49082
|
exports_external3.literal(-1),
|
|
48938
49083
|
exports_external3.literal(0),
|
|
@@ -48949,7 +49094,10 @@ var TimebackGrade3 = exports_external3.union([
|
|
|
48949
49094
|
exports_external3.literal(11),
|
|
48950
49095
|
exports_external3.literal(12),
|
|
48951
49096
|
exports_external3.literal(13)
|
|
48952
|
-
])
|
|
49097
|
+
]).meta({
|
|
49098
|
+
id: "TimebackGrade",
|
|
49099
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
49100
|
+
});
|
|
48953
49101
|
var ScoreStatus3 = exports_external3.enum([
|
|
48954
49102
|
"exempt",
|
|
48955
49103
|
"fully graded",
|
|
@@ -49179,62 +49327,84 @@ var CaliperListEventsParams3 = exports_external3.object({
|
|
|
49179
49327
|
actorEmail: exports_external3.email().optional()
|
|
49180
49328
|
}).strict();
|
|
49181
49329
|
var CourseIds3 = exports_external3.object({
|
|
49182
|
-
staging: exports_external3.string().optional(),
|
|
49183
|
-
production: exports_external3.string().optional()
|
|
49184
|
-
});
|
|
49185
|
-
var CourseType3 = exports_external3.enum(["base", "hole-filling", "optional"]);
|
|
49186
|
-
var PublishStatus3 = exports_external3.enum(["draft", "testing", "published", "deactivated"]);
|
|
49330
|
+
staging: exports_external3.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
49331
|
+
production: exports_external3.string().meta({ description: "Course ID in production environment" }).optional()
|
|
49332
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
49333
|
+
var CourseType3 = exports_external3.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
49334
|
+
var PublishStatus3 = exports_external3.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
49187
49335
|
var CourseGoals3 = exports_external3.object({
|
|
49188
|
-
dailyXp: exports_external3.number().int().positive().optional(),
|
|
49189
|
-
dailyLessons: exports_external3.number().int().positive().optional(),
|
|
49190
|
-
dailyActiveMinutes: exports_external3.number().int().positive().optional(),
|
|
49191
|
-
dailyAccuracy: exports_external3.number().int().min(0).max(100).optional(),
|
|
49192
|
-
dailyMasteredUnits: exports_external3.number().int().positive().optional()
|
|
49193
|
-
});
|
|
49336
|
+
dailyXp: exports_external3.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
49337
|
+
dailyLessons: exports_external3.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
49338
|
+
dailyActiveMinutes: exports_external3.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
49339
|
+
dailyAccuracy: exports_external3.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
49340
|
+
dailyMasteredUnits: exports_external3.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
49341
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
49194
49342
|
var CourseMetrics3 = exports_external3.object({
|
|
49195
|
-
totalXp: exports_external3.number().int().positive().optional(),
|
|
49196
|
-
totalLessons: exports_external3.number().int().positive().optional(),
|
|
49197
|
-
totalGrades: exports_external3.number().int().positive().optional()
|
|
49198
|
-
});
|
|
49343
|
+
totalXp: exports_external3.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
49344
|
+
totalLessons: exports_external3.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
49345
|
+
totalGrades: exports_external3.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
49346
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
49199
49347
|
var CourseMetadata3 = exports_external3.object({
|
|
49200
49348
|
courseType: CourseType3.optional(),
|
|
49201
|
-
isSupplemental: exports_external3.boolean().optional(),
|
|
49202
|
-
isCustom: exports_external3.boolean().optional(),
|
|
49349
|
+
isSupplemental: exports_external3.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
49350
|
+
isCustom: exports_external3.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
49203
49351
|
publishStatus: PublishStatus3.optional(),
|
|
49204
|
-
contactEmail: exports_external3.email().optional(),
|
|
49205
|
-
primaryApp: exports_external3.string().optional(),
|
|
49352
|
+
contactEmail: exports_external3.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
49353
|
+
primaryApp: exports_external3.string().meta({ description: "Primary application identifier" }).optional(),
|
|
49206
49354
|
goals: CourseGoals3.optional(),
|
|
49207
49355
|
metrics: CourseMetrics3.optional()
|
|
49208
|
-
});
|
|
49356
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
49209
49357
|
var CourseDefaults3 = exports_external3.object({
|
|
49210
|
-
courseCode: exports_external3.string().optional(),
|
|
49211
|
-
level: exports_external3.string().optional(),
|
|
49358
|
+
courseCode: exports_external3.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
49359
|
+
level: exports_external3.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
49212
49360
|
metadata: CourseMetadata3.optional()
|
|
49361
|
+
}).meta({
|
|
49362
|
+
id: "CourseDefaults",
|
|
49363
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
49213
49364
|
});
|
|
49214
49365
|
var CourseEnvOverrides3 = exports_external3.object({
|
|
49215
|
-
level: exports_external3.string().optional(),
|
|
49216
|
-
sensor: exports_external3.
|
|
49217
|
-
launchUrl: exports_external3.
|
|
49366
|
+
level: exports_external3.string().meta({ description: "Course level for this environment" }).optional(),
|
|
49367
|
+
sensor: exports_external3.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
49368
|
+
launchUrl: exports_external3.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
49218
49369
|
metadata: CourseMetadata3.optional()
|
|
49370
|
+
}).meta({
|
|
49371
|
+
id: "CourseEnvOverrides",
|
|
49372
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
49219
49373
|
});
|
|
49220
49374
|
var CourseOverrides3 = exports_external3.object({
|
|
49221
|
-
staging: CourseEnvOverrides3.
|
|
49222
|
-
|
|
49223
|
-
})
|
|
49375
|
+
staging: CourseEnvOverrides3.meta({
|
|
49376
|
+
description: "Overrides for staging environment"
|
|
49377
|
+
}).optional(),
|
|
49378
|
+
production: CourseEnvOverrides3.meta({
|
|
49379
|
+
description: "Overrides for production environment"
|
|
49380
|
+
}).optional()
|
|
49381
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
49224
49382
|
var CourseConfig3 = CourseDefaults3.extend({
|
|
49225
|
-
subject: TimebackSubject3,
|
|
49226
|
-
grade: TimebackGrade3.
|
|
49383
|
+
subject: TimebackSubject3.meta({ description: "Subject area for this course" }),
|
|
49384
|
+
grade: TimebackGrade3.meta({
|
|
49385
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
49386
|
+
}).optional(),
|
|
49227
49387
|
ids: CourseIds3.nullable().optional(),
|
|
49228
|
-
sensor: exports_external3.
|
|
49229
|
-
launchUrl: exports_external3.
|
|
49388
|
+
sensor: exports_external3.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
49389
|
+
launchUrl: exports_external3.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
49230
49390
|
overrides: CourseOverrides3.optional()
|
|
49391
|
+
}).meta({
|
|
49392
|
+
id: "CourseConfig",
|
|
49393
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
49231
49394
|
});
|
|
49232
49395
|
var TimebackConfig3 = exports_external3.object({
|
|
49233
|
-
|
|
49234
|
-
|
|
49235
|
-
|
|
49236
|
-
|
|
49237
|
-
|
|
49396
|
+
$schema: exports_external3.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
49397
|
+
name: exports_external3.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
49398
|
+
defaults: CourseDefaults3.meta({
|
|
49399
|
+
description: "Default properties applied to all courses"
|
|
49400
|
+
}).optional(),
|
|
49401
|
+
courses: exports_external3.array(CourseConfig3).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
49402
|
+
sensor: exports_external3.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
49403
|
+
launchUrl: exports_external3.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
49404
|
+
}).meta({
|
|
49405
|
+
id: "TimebackConfig",
|
|
49406
|
+
title: "Timeback Config",
|
|
49407
|
+
description: "Configuration schema for timeback.config.json files"
|
|
49238
49408
|
}).refine((config22) => {
|
|
49239
49409
|
return config22.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
49240
49410
|
}, {
|
|
@@ -49255,17 +49425,23 @@ var TimebackConfig3 = exports_external3.object({
|
|
|
49255
49425
|
message: "Duplicate courseCode found; each must be unique",
|
|
49256
49426
|
path: ["courses"]
|
|
49257
49427
|
}).refine((config22) => {
|
|
49258
|
-
return config22.courses.every((c) =>
|
|
49259
|
-
|
|
49260
|
-
|
|
49261
|
-
|
|
49262
|
-
|
|
49263
|
-
|
|
49428
|
+
return config22.courses.every((c) => {
|
|
49429
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
49430
|
+
return true;
|
|
49431
|
+
}
|
|
49432
|
+
const launchUrls = [
|
|
49433
|
+
c.launchUrl,
|
|
49434
|
+
config22.launchUrl,
|
|
49435
|
+
c.overrides?.staging?.launchUrl,
|
|
49436
|
+
c.overrides?.production?.launchUrl
|
|
49437
|
+
].filter(Boolean);
|
|
49438
|
+
return launchUrls.length > 0;
|
|
49439
|
+
});
|
|
49264
49440
|
}, {
|
|
49265
|
-
message: "Each course must have an effective
|
|
49441
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
49266
49442
|
path: ["courses"]
|
|
49267
49443
|
});
|
|
49268
|
-
var EdubridgeDateString3 =
|
|
49444
|
+
var EdubridgeDateString3 = IsoDateTimeString3;
|
|
49269
49445
|
var EduBridgeEnrollment3 = exports_external3.object({
|
|
49270
49446
|
id: exports_external3.string(),
|
|
49271
49447
|
role: exports_external3.string(),
|
|
@@ -49329,12 +49505,9 @@ var EmailOrStudentId3 = exports_external3.object({
|
|
|
49329
49505
|
});
|
|
49330
49506
|
var SubjectTrackInput3 = exports_external3.object({
|
|
49331
49507
|
subject: NonEmptyString6,
|
|
49332
|
-
|
|
49333
|
-
|
|
49334
|
-
|
|
49335
|
-
});
|
|
49336
|
-
var SubjectTrackUpsertInput3 = SubjectTrackInput3.extend({
|
|
49337
|
-
id: NonEmptyString6
|
|
49508
|
+
grade: NonEmptyString6,
|
|
49509
|
+
courseId: NonEmptyString6,
|
|
49510
|
+
orgSourcedId: NonEmptyString6.optional()
|
|
49338
49511
|
});
|
|
49339
49512
|
var EdubridgeListEnrollmentsParams3 = exports_external3.object({
|
|
49340
49513
|
userId: NonEmptyString6
|
|
@@ -50303,7 +50476,8 @@ class BaseResource {
|
|
|
50303
50476
|
return this.stream(params).toArray();
|
|
50304
50477
|
}
|
|
50305
50478
|
async first(params) {
|
|
50306
|
-
const
|
|
50479
|
+
const limitedParams = { ...params ?? {}, limit: 1 };
|
|
50480
|
+
const result = await new Paginator22(this.transport, this.basePath, limitedParams, this.unwrapKey, this.transform.bind(this)).firstPage();
|
|
50307
50481
|
return result.data[0];
|
|
50308
50482
|
}
|
|
50309
50483
|
stream(params) {
|
|
@@ -50386,7 +50560,8 @@ class ReadOnlyResource {
|
|
|
50386
50560
|
return this.stream(params).toArray();
|
|
50387
50561
|
}
|
|
50388
50562
|
async first(params) {
|
|
50389
|
-
const
|
|
50563
|
+
const limitedParams = { ...params ?? {}, limit: 1 };
|
|
50564
|
+
const result = await new Paginator22(this.transport, this.basePath, limitedParams, this.unwrapKey, this.transform.bind(this)).firstPage();
|
|
50390
50565
|
return result.data[0];
|
|
50391
50566
|
}
|
|
50392
50567
|
stream(params) {
|
|
@@ -52305,7 +52480,17 @@ class TimebackProvider5 {
|
|
|
52305
52480
|
}
|
|
52306
52481
|
function getEnv5(key) {
|
|
52307
52482
|
try {
|
|
52308
|
-
|
|
52483
|
+
if (typeof process === "undefined")
|
|
52484
|
+
return;
|
|
52485
|
+
if (typeof key === "string") {
|
|
52486
|
+
return process.env[key];
|
|
52487
|
+
}
|
|
52488
|
+
for (const k of key) {
|
|
52489
|
+
const value = process.env[k];
|
|
52490
|
+
if (value !== undefined)
|
|
52491
|
+
return value;
|
|
52492
|
+
}
|
|
52493
|
+
return;
|
|
52309
52494
|
} catch {
|
|
52310
52495
|
return;
|
|
52311
52496
|
}
|
|
@@ -52336,6 +52521,18 @@ var DEFAULT_PROVIDER_REGISTRY5 = {
|
|
|
52336
52521
|
}
|
|
52337
52522
|
}
|
|
52338
52523
|
};
|
|
52524
|
+
function primaryEnvVar5(key) {
|
|
52525
|
+
if (typeof key === "string") {
|
|
52526
|
+
return key;
|
|
52527
|
+
}
|
|
52528
|
+
if (key.length === 0) {
|
|
52529
|
+
throw new Error(`Missing env var key: ${key}`);
|
|
52530
|
+
}
|
|
52531
|
+
return key[0];
|
|
52532
|
+
}
|
|
52533
|
+
function formatEnvVarKey5(key) {
|
|
52534
|
+
return primaryEnvVar5(key);
|
|
52535
|
+
}
|
|
52339
52536
|
function validateEnv5(env) {
|
|
52340
52537
|
if (env !== "staging" && env !== "production") {
|
|
52341
52538
|
throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
|
|
@@ -52346,10 +52543,10 @@ function validateAuth5(auth, envVars) {
|
|
|
52346
52543
|
const clientId = auth?.clientId ?? getEnv5(envVars.clientId);
|
|
52347
52544
|
const clientSecret = auth?.clientSecret ?? getEnv5(envVars.clientSecret);
|
|
52348
52545
|
if (!clientId) {
|
|
52349
|
-
throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
|
|
52546
|
+
throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey5(envVars.clientId)}`);
|
|
52350
52547
|
}
|
|
52351
52548
|
if (!clientSecret) {
|
|
52352
|
-
throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
|
|
52549
|
+
throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey5(envVars.clientSecret)}`);
|
|
52353
52550
|
}
|
|
52354
52551
|
return { clientId, clientSecret };
|
|
52355
52552
|
}
|
|
@@ -52365,21 +52562,21 @@ function buildMissingEnvError5(envVars) {
|
|
|
52365
52562
|
const clientId = getEnv5(envVars.clientId);
|
|
52366
52563
|
const clientSecret = getEnv5(envVars.clientSecret);
|
|
52367
52564
|
if (baseUrl === undefined && clientId === undefined) {
|
|
52368
|
-
const hint = envVars.env ?? envVars.baseUrl;
|
|
52565
|
+
const hint = formatEnvVarKey5(envVars.env ?? envVars.baseUrl);
|
|
52369
52566
|
return `Missing env: provide in config or set ${hint}`;
|
|
52370
52567
|
}
|
|
52371
52568
|
const missing = [];
|
|
52372
52569
|
if (baseUrl === undefined) {
|
|
52373
|
-
missing.push(envVars.env ?? envVars.baseUrl);
|
|
52570
|
+
missing.push(formatEnvVarKey5(envVars.env ?? envVars.baseUrl));
|
|
52374
52571
|
}
|
|
52375
52572
|
if (baseUrl !== undefined && authUrl === undefined) {
|
|
52376
|
-
missing.push(envVars.authUrl);
|
|
52573
|
+
missing.push(formatEnvVarKey5(envVars.authUrl));
|
|
52377
52574
|
}
|
|
52378
52575
|
if (clientId === undefined) {
|
|
52379
|
-
missing.push(envVars.clientId);
|
|
52576
|
+
missing.push(formatEnvVarKey5(envVars.clientId));
|
|
52380
52577
|
}
|
|
52381
52578
|
if (clientSecret === undefined) {
|
|
52382
|
-
missing.push(envVars.clientSecret);
|
|
52579
|
+
missing.push(formatEnvVarKey5(envVars.clientSecret));
|
|
52383
52580
|
}
|
|
52384
52581
|
return `Missing environment variables: ${missing.join(", ")}`;
|
|
52385
52582
|
}
|
|
@@ -53063,10 +53260,14 @@ function validateNonEmptyString4(value, name) {
|
|
|
53063
53260
|
}
|
|
53064
53261
|
}
|
|
53065
53262
|
var POWERPATH_ENV_VARS = {
|
|
53066
|
-
baseUrl: "POWERPATH_BASE_URL",
|
|
53067
|
-
clientId: "POWERPATH_CLIENT_ID",
|
|
53068
|
-
clientSecret:
|
|
53069
|
-
|
|
53263
|
+
baseUrl: ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "POWERPATH_BASE_URL"],
|
|
53264
|
+
clientId: ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID", "POWERPATH_CLIENT_ID"],
|
|
53265
|
+
clientSecret: [
|
|
53266
|
+
"TIMEBACK_API_CLIENT_SECRET",
|
|
53267
|
+
"TIMEBACK_CLIENT_SECRET",
|
|
53268
|
+
"POWERPATH_CLIENT_SECRET"
|
|
53269
|
+
],
|
|
53270
|
+
authUrl: ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL", "POWERPATH_TOKEN_URL"]
|
|
53070
53271
|
};
|
|
53071
53272
|
function resolveToProvider24(config4, registry4 = DEFAULT_PROVIDER_REGISTRY5) {
|
|
53072
53273
|
return resolveToProvider7(config4, POWERPATH_ENV_VARS, registry4);
|
|
@@ -55308,7 +55509,7 @@ class Doc4 {
|
|
|
55308
55509
|
var version4 = {
|
|
55309
55510
|
major: 4,
|
|
55310
55511
|
minor: 3,
|
|
55311
|
-
patch:
|
|
55512
|
+
patch: 6
|
|
55312
55513
|
};
|
|
55313
55514
|
var $ZodType4 = /* @__PURE__ */ $constructor4("$ZodType", (inst, def) => {
|
|
55314
55515
|
var _a4;
|
|
@@ -56592,7 +56793,7 @@ var $ZodRecord4 = /* @__PURE__ */ $constructor4("$ZodRecord", (inst, def) => {
|
|
|
56592
56793
|
if (keyResult instanceof Promise) {
|
|
56593
56794
|
throw new Error("Async schemas not supported in object keys currently");
|
|
56594
56795
|
}
|
|
56595
|
-
const checkNumericKey = typeof key === "string" && number7.test(key) && keyResult.issues.length
|
|
56796
|
+
const checkNumericKey = typeof key === "string" && number7.test(key) && keyResult.issues.length;
|
|
56596
56797
|
if (checkNumericKey) {
|
|
56597
56798
|
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
56598
56799
|
if (retryResult instanceof Promise) {
|
|
@@ -63909,7 +64110,7 @@ function finalize4(ctx, schema) {
|
|
|
63909
64110
|
}
|
|
63910
64111
|
}
|
|
63911
64112
|
}
|
|
63912
|
-
if (refSchema.$ref) {
|
|
64113
|
+
if (refSchema.$ref && refSeen.def) {
|
|
63913
64114
|
for (const key in schema2) {
|
|
63914
64115
|
if (key === "$ref" || key === "allOf")
|
|
63915
64116
|
continue;
|
|
@@ -66541,7 +66742,7 @@ var TimebackSubject4 = exports_external4.enum([
|
|
|
66541
66742
|
"Math",
|
|
66542
66743
|
"None",
|
|
66543
66744
|
"Other"
|
|
66544
|
-
]);
|
|
66745
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
66545
66746
|
var TimebackGrade4 = exports_external4.union([
|
|
66546
66747
|
exports_external4.literal(-1),
|
|
66547
66748
|
exports_external4.literal(0),
|
|
@@ -66558,7 +66759,10 @@ var TimebackGrade4 = exports_external4.union([
|
|
|
66558
66759
|
exports_external4.literal(11),
|
|
66559
66760
|
exports_external4.literal(12),
|
|
66560
66761
|
exports_external4.literal(13)
|
|
66561
|
-
])
|
|
66762
|
+
]).meta({
|
|
66763
|
+
id: "TimebackGrade",
|
|
66764
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
66765
|
+
});
|
|
66562
66766
|
var ScoreStatus4 = exports_external4.enum([
|
|
66563
66767
|
"exempt",
|
|
66564
66768
|
"fully graded",
|
|
@@ -66788,62 +66992,84 @@ var CaliperListEventsParams4 = exports_external4.object({
|
|
|
66788
66992
|
actorEmail: exports_external4.email().optional()
|
|
66789
66993
|
}).strict();
|
|
66790
66994
|
var CourseIds4 = exports_external4.object({
|
|
66791
|
-
staging: exports_external4.string().optional(),
|
|
66792
|
-
production: exports_external4.string().optional()
|
|
66793
|
-
});
|
|
66794
|
-
var CourseType4 = exports_external4.enum(["base", "hole-filling", "optional"]);
|
|
66795
|
-
var PublishStatus4 = exports_external4.enum(["draft", "testing", "published", "deactivated"]);
|
|
66995
|
+
staging: exports_external4.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
66996
|
+
production: exports_external4.string().meta({ description: "Course ID in production environment" }).optional()
|
|
66997
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
66998
|
+
var CourseType4 = exports_external4.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
66999
|
+
var PublishStatus4 = exports_external4.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
66796
67000
|
var CourseGoals4 = exports_external4.object({
|
|
66797
|
-
dailyXp: exports_external4.number().int().positive().optional(),
|
|
66798
|
-
dailyLessons: exports_external4.number().int().positive().optional(),
|
|
66799
|
-
dailyActiveMinutes: exports_external4.number().int().positive().optional(),
|
|
66800
|
-
dailyAccuracy: exports_external4.number().int().min(0).max(100).optional(),
|
|
66801
|
-
dailyMasteredUnits: exports_external4.number().int().positive().optional()
|
|
66802
|
-
});
|
|
67001
|
+
dailyXp: exports_external4.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
67002
|
+
dailyLessons: exports_external4.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
67003
|
+
dailyActiveMinutes: exports_external4.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
67004
|
+
dailyAccuracy: exports_external4.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
67005
|
+
dailyMasteredUnits: exports_external4.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
67006
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
66803
67007
|
var CourseMetrics4 = exports_external4.object({
|
|
66804
|
-
totalXp: exports_external4.number().int().positive().optional(),
|
|
66805
|
-
totalLessons: exports_external4.number().int().positive().optional(),
|
|
66806
|
-
totalGrades: exports_external4.number().int().positive().optional()
|
|
66807
|
-
});
|
|
67008
|
+
totalXp: exports_external4.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
67009
|
+
totalLessons: exports_external4.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
67010
|
+
totalGrades: exports_external4.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
67011
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
66808
67012
|
var CourseMetadata4 = exports_external4.object({
|
|
66809
67013
|
courseType: CourseType4.optional(),
|
|
66810
|
-
isSupplemental: exports_external4.boolean().optional(),
|
|
66811
|
-
isCustom: exports_external4.boolean().optional(),
|
|
67014
|
+
isSupplemental: exports_external4.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
67015
|
+
isCustom: exports_external4.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
66812
67016
|
publishStatus: PublishStatus4.optional(),
|
|
66813
|
-
contactEmail: exports_external4.email().optional(),
|
|
66814
|
-
primaryApp: exports_external4.string().optional(),
|
|
67017
|
+
contactEmail: exports_external4.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
67018
|
+
primaryApp: exports_external4.string().meta({ description: "Primary application identifier" }).optional(),
|
|
66815
67019
|
goals: CourseGoals4.optional(),
|
|
66816
67020
|
metrics: CourseMetrics4.optional()
|
|
66817
|
-
});
|
|
67021
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
66818
67022
|
var CourseDefaults4 = exports_external4.object({
|
|
66819
|
-
courseCode: exports_external4.string().optional(),
|
|
66820
|
-
level: exports_external4.string().optional(),
|
|
67023
|
+
courseCode: exports_external4.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
67024
|
+
level: exports_external4.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
66821
67025
|
metadata: CourseMetadata4.optional()
|
|
67026
|
+
}).meta({
|
|
67027
|
+
id: "CourseDefaults",
|
|
67028
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
66822
67029
|
});
|
|
66823
67030
|
var CourseEnvOverrides4 = exports_external4.object({
|
|
66824
|
-
level: exports_external4.string().optional(),
|
|
66825
|
-
sensor: exports_external4.
|
|
66826
|
-
launchUrl: exports_external4.
|
|
67031
|
+
level: exports_external4.string().meta({ description: "Course level for this environment" }).optional(),
|
|
67032
|
+
sensor: exports_external4.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
67033
|
+
launchUrl: exports_external4.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
66827
67034
|
metadata: CourseMetadata4.optional()
|
|
67035
|
+
}).meta({
|
|
67036
|
+
id: "CourseEnvOverrides",
|
|
67037
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
66828
67038
|
});
|
|
66829
67039
|
var CourseOverrides4 = exports_external4.object({
|
|
66830
|
-
staging: CourseEnvOverrides4.
|
|
66831
|
-
|
|
66832
|
-
})
|
|
67040
|
+
staging: CourseEnvOverrides4.meta({
|
|
67041
|
+
description: "Overrides for staging environment"
|
|
67042
|
+
}).optional(),
|
|
67043
|
+
production: CourseEnvOverrides4.meta({
|
|
67044
|
+
description: "Overrides for production environment"
|
|
67045
|
+
}).optional()
|
|
67046
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
66833
67047
|
var CourseConfig4 = CourseDefaults4.extend({
|
|
66834
|
-
subject: TimebackSubject4,
|
|
66835
|
-
grade: TimebackGrade4.
|
|
67048
|
+
subject: TimebackSubject4.meta({ description: "Subject area for this course" }),
|
|
67049
|
+
grade: TimebackGrade4.meta({
|
|
67050
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
67051
|
+
}).optional(),
|
|
66836
67052
|
ids: CourseIds4.nullable().optional(),
|
|
66837
|
-
sensor: exports_external4.
|
|
66838
|
-
launchUrl: exports_external4.
|
|
67053
|
+
sensor: exports_external4.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
67054
|
+
launchUrl: exports_external4.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
66839
67055
|
overrides: CourseOverrides4.optional()
|
|
67056
|
+
}).meta({
|
|
67057
|
+
id: "CourseConfig",
|
|
67058
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
66840
67059
|
});
|
|
66841
67060
|
var TimebackConfig4 = exports_external4.object({
|
|
66842
|
-
|
|
66843
|
-
|
|
66844
|
-
|
|
66845
|
-
|
|
66846
|
-
|
|
67061
|
+
$schema: exports_external4.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
67062
|
+
name: exports_external4.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
67063
|
+
defaults: CourseDefaults4.meta({
|
|
67064
|
+
description: "Default properties applied to all courses"
|
|
67065
|
+
}).optional(),
|
|
67066
|
+
courses: exports_external4.array(CourseConfig4).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
67067
|
+
sensor: exports_external4.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
67068
|
+
launchUrl: exports_external4.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
67069
|
+
}).meta({
|
|
67070
|
+
id: "TimebackConfig",
|
|
67071
|
+
title: "Timeback Config",
|
|
67072
|
+
description: "Configuration schema for timeback.config.json files"
|
|
66847
67073
|
}).refine((config22) => {
|
|
66848
67074
|
return config22.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
66849
67075
|
}, {
|
|
@@ -66864,17 +67090,23 @@ var TimebackConfig4 = exports_external4.object({
|
|
|
66864
67090
|
message: "Duplicate courseCode found; each must be unique",
|
|
66865
67091
|
path: ["courses"]
|
|
66866
67092
|
}).refine((config22) => {
|
|
66867
|
-
return config22.courses.every((c) =>
|
|
66868
|
-
|
|
66869
|
-
|
|
66870
|
-
|
|
66871
|
-
|
|
66872
|
-
|
|
67093
|
+
return config22.courses.every((c) => {
|
|
67094
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
67095
|
+
return true;
|
|
67096
|
+
}
|
|
67097
|
+
const launchUrls = [
|
|
67098
|
+
c.launchUrl,
|
|
67099
|
+
config22.launchUrl,
|
|
67100
|
+
c.overrides?.staging?.launchUrl,
|
|
67101
|
+
c.overrides?.production?.launchUrl
|
|
67102
|
+
].filter(Boolean);
|
|
67103
|
+
return launchUrls.length > 0;
|
|
67104
|
+
});
|
|
66873
67105
|
}, {
|
|
66874
|
-
message: "Each course must have an effective
|
|
67106
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
66875
67107
|
path: ["courses"]
|
|
66876
67108
|
});
|
|
66877
|
-
var EdubridgeDateString4 =
|
|
67109
|
+
var EdubridgeDateString4 = IsoDateTimeString4;
|
|
66878
67110
|
var EduBridgeEnrollment4 = exports_external4.object({
|
|
66879
67111
|
id: exports_external4.string(),
|
|
66880
67112
|
role: exports_external4.string(),
|
|
@@ -66938,12 +67170,9 @@ var EmailOrStudentId4 = exports_external4.object({
|
|
|
66938
67170
|
});
|
|
66939
67171
|
var SubjectTrackInput4 = exports_external4.object({
|
|
66940
67172
|
subject: NonEmptyString7,
|
|
66941
|
-
|
|
66942
|
-
|
|
66943
|
-
|
|
66944
|
-
});
|
|
66945
|
-
var SubjectTrackUpsertInput4 = SubjectTrackInput4.extend({
|
|
66946
|
-
id: NonEmptyString7
|
|
67173
|
+
grade: NonEmptyString7,
|
|
67174
|
+
courseId: NonEmptyString7,
|
|
67175
|
+
orgSourcedId: NonEmptyString7.optional()
|
|
66947
67176
|
});
|
|
66948
67177
|
var EdubridgeListEnrollmentsParams4 = exports_external4.object({
|
|
66949
67178
|
userId: NonEmptyString7
|
|
@@ -68924,7 +69153,17 @@ class TimebackProvider6 {
|
|
|
68924
69153
|
}
|
|
68925
69154
|
function getEnv6(key) {
|
|
68926
69155
|
try {
|
|
68927
|
-
|
|
69156
|
+
if (typeof process === "undefined")
|
|
69157
|
+
return;
|
|
69158
|
+
if (typeof key === "string") {
|
|
69159
|
+
return process.env[key];
|
|
69160
|
+
}
|
|
69161
|
+
for (const k of key) {
|
|
69162
|
+
const value = process.env[k];
|
|
69163
|
+
if (value !== undefined)
|
|
69164
|
+
return value;
|
|
69165
|
+
}
|
|
69166
|
+
return;
|
|
68928
69167
|
} catch {
|
|
68929
69168
|
return;
|
|
68930
69169
|
}
|
|
@@ -68955,6 +69194,18 @@ var DEFAULT_PROVIDER_REGISTRY6 = {
|
|
|
68955
69194
|
}
|
|
68956
69195
|
}
|
|
68957
69196
|
};
|
|
69197
|
+
function primaryEnvVar6(key) {
|
|
69198
|
+
if (typeof key === "string") {
|
|
69199
|
+
return key;
|
|
69200
|
+
}
|
|
69201
|
+
if (key.length === 0) {
|
|
69202
|
+
throw new Error(`Missing env var key: ${key}`);
|
|
69203
|
+
}
|
|
69204
|
+
return key[0];
|
|
69205
|
+
}
|
|
69206
|
+
function formatEnvVarKey6(key) {
|
|
69207
|
+
return primaryEnvVar6(key);
|
|
69208
|
+
}
|
|
68958
69209
|
function validateEnv6(env) {
|
|
68959
69210
|
if (env !== "staging" && env !== "production") {
|
|
68960
69211
|
throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
|
|
@@ -68965,10 +69216,10 @@ function validateAuth6(auth, envVars) {
|
|
|
68965
69216
|
const clientId = auth?.clientId ?? getEnv6(envVars.clientId);
|
|
68966
69217
|
const clientSecret = auth?.clientSecret ?? getEnv6(envVars.clientSecret);
|
|
68967
69218
|
if (!clientId) {
|
|
68968
|
-
throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
|
|
69219
|
+
throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey6(envVars.clientId)}`);
|
|
68969
69220
|
}
|
|
68970
69221
|
if (!clientSecret) {
|
|
68971
|
-
throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
|
|
69222
|
+
throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey6(envVars.clientSecret)}`);
|
|
68972
69223
|
}
|
|
68973
69224
|
return { clientId, clientSecret };
|
|
68974
69225
|
}
|
|
@@ -68984,21 +69235,21 @@ function buildMissingEnvError6(envVars) {
|
|
|
68984
69235
|
const clientId = getEnv6(envVars.clientId);
|
|
68985
69236
|
const clientSecret = getEnv6(envVars.clientSecret);
|
|
68986
69237
|
if (baseUrl === undefined && clientId === undefined) {
|
|
68987
|
-
const hint = envVars.env ?? envVars.baseUrl;
|
|
69238
|
+
const hint = formatEnvVarKey6(envVars.env ?? envVars.baseUrl);
|
|
68988
69239
|
return `Missing env: provide in config or set ${hint}`;
|
|
68989
69240
|
}
|
|
68990
69241
|
const missing = [];
|
|
68991
69242
|
if (baseUrl === undefined) {
|
|
68992
|
-
missing.push(envVars.env ?? envVars.baseUrl);
|
|
69243
|
+
missing.push(formatEnvVarKey6(envVars.env ?? envVars.baseUrl));
|
|
68993
69244
|
}
|
|
68994
69245
|
if (baseUrl !== undefined && authUrl === undefined) {
|
|
68995
|
-
missing.push(envVars.authUrl);
|
|
69246
|
+
missing.push(formatEnvVarKey6(envVars.authUrl));
|
|
68996
69247
|
}
|
|
68997
69248
|
if (clientId === undefined) {
|
|
68998
|
-
missing.push(envVars.clientId);
|
|
69249
|
+
missing.push(formatEnvVarKey6(envVars.clientId));
|
|
68999
69250
|
}
|
|
69000
69251
|
if (clientSecret === undefined) {
|
|
69001
|
-
missing.push(envVars.clientSecret);
|
|
69252
|
+
missing.push(formatEnvVarKey6(envVars.clientSecret));
|
|
69002
69253
|
}
|
|
69003
69254
|
return `Missing environment variables: ${missing.join(", ")}`;
|
|
69004
69255
|
}
|
|
@@ -69698,10 +69949,10 @@ function validatePageListParams2(params) {
|
|
|
69698
69949
|
}
|
|
69699
69950
|
}
|
|
69700
69951
|
var QTI_ENV_VARS = {
|
|
69701
|
-
baseUrl: "QTI_BASE_URL",
|
|
69702
|
-
clientId: "QTI_CLIENT_ID",
|
|
69703
|
-
clientSecret: "QTI_CLIENT_SECRET",
|
|
69704
|
-
authUrl: "QTI_TOKEN_URL"
|
|
69952
|
+
baseUrl: ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "QTI_BASE_URL"],
|
|
69953
|
+
clientId: ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID", "QTI_CLIENT_ID"],
|
|
69954
|
+
clientSecret: ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET", "QTI_CLIENT_SECRET"],
|
|
69955
|
+
authUrl: ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL", "QTI_TOKEN_URL"]
|
|
69705
69956
|
};
|
|
69706
69957
|
function resolveToProvider25(config5, registry5 = DEFAULT_PROVIDER_REGISTRY6) {
|
|
69707
69958
|
return resolveToProvider8(config5, QTI_ENV_VARS, registry5);
|
|
@@ -71947,7 +72198,7 @@ class Doc5 {
|
|
|
71947
72198
|
var version5 = {
|
|
71948
72199
|
major: 4,
|
|
71949
72200
|
minor: 3,
|
|
71950
|
-
patch:
|
|
72201
|
+
patch: 6
|
|
71951
72202
|
};
|
|
71952
72203
|
var $ZodType5 = /* @__PURE__ */ $constructor5("$ZodType", (inst, def) => {
|
|
71953
72204
|
var _a5;
|
|
@@ -73231,7 +73482,7 @@ var $ZodRecord5 = /* @__PURE__ */ $constructor5("$ZodRecord", (inst, def) => {
|
|
|
73231
73482
|
if (keyResult instanceof Promise) {
|
|
73232
73483
|
throw new Error("Async schemas not supported in object keys currently");
|
|
73233
73484
|
}
|
|
73234
|
-
const checkNumericKey = typeof key === "string" && number8.test(key) && keyResult.issues.length
|
|
73485
|
+
const checkNumericKey = typeof key === "string" && number8.test(key) && keyResult.issues.length;
|
|
73235
73486
|
if (checkNumericKey) {
|
|
73236
73487
|
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
73237
73488
|
if (retryResult instanceof Promise) {
|
|
@@ -80548,7 +80799,7 @@ function finalize5(ctx, schema) {
|
|
|
80548
80799
|
}
|
|
80549
80800
|
}
|
|
80550
80801
|
}
|
|
80551
|
-
if (refSchema.$ref) {
|
|
80802
|
+
if (refSchema.$ref && refSeen.def) {
|
|
80552
80803
|
for (const key in schema2) {
|
|
80553
80804
|
if (key === "$ref" || key === "allOf")
|
|
80554
80805
|
continue;
|
|
@@ -83180,7 +83431,7 @@ var TimebackSubject5 = exports_external5.enum([
|
|
|
83180
83431
|
"Math",
|
|
83181
83432
|
"None",
|
|
83182
83433
|
"Other"
|
|
83183
|
-
]);
|
|
83434
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
83184
83435
|
var TimebackGrade5 = exports_external5.union([
|
|
83185
83436
|
exports_external5.literal(-1),
|
|
83186
83437
|
exports_external5.literal(0),
|
|
@@ -83197,7 +83448,10 @@ var TimebackGrade5 = exports_external5.union([
|
|
|
83197
83448
|
exports_external5.literal(11),
|
|
83198
83449
|
exports_external5.literal(12),
|
|
83199
83450
|
exports_external5.literal(13)
|
|
83200
|
-
])
|
|
83451
|
+
]).meta({
|
|
83452
|
+
id: "TimebackGrade",
|
|
83453
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
83454
|
+
});
|
|
83201
83455
|
var ScoreStatus5 = exports_external5.enum([
|
|
83202
83456
|
"exempt",
|
|
83203
83457
|
"fully graded",
|
|
@@ -83427,62 +83681,84 @@ var CaliperListEventsParams5 = exports_external5.object({
|
|
|
83427
83681
|
actorEmail: exports_external5.email().optional()
|
|
83428
83682
|
}).strict();
|
|
83429
83683
|
var CourseIds5 = exports_external5.object({
|
|
83430
|
-
staging: exports_external5.string().optional(),
|
|
83431
|
-
production: exports_external5.string().optional()
|
|
83432
|
-
});
|
|
83433
|
-
var CourseType5 = exports_external5.enum(["base", "hole-filling", "optional"]);
|
|
83434
|
-
var PublishStatus5 = exports_external5.enum(["draft", "testing", "published", "deactivated"]);
|
|
83684
|
+
staging: exports_external5.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
83685
|
+
production: exports_external5.string().meta({ description: "Course ID in production environment" }).optional()
|
|
83686
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
83687
|
+
var CourseType5 = exports_external5.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
83688
|
+
var PublishStatus5 = exports_external5.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
83435
83689
|
var CourseGoals5 = exports_external5.object({
|
|
83436
|
-
dailyXp: exports_external5.number().int().positive().optional(),
|
|
83437
|
-
dailyLessons: exports_external5.number().int().positive().optional(),
|
|
83438
|
-
dailyActiveMinutes: exports_external5.number().int().positive().optional(),
|
|
83439
|
-
dailyAccuracy: exports_external5.number().int().min(0).max(100).optional(),
|
|
83440
|
-
dailyMasteredUnits: exports_external5.number().int().positive().optional()
|
|
83441
|
-
});
|
|
83690
|
+
dailyXp: exports_external5.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
83691
|
+
dailyLessons: exports_external5.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
83692
|
+
dailyActiveMinutes: exports_external5.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
83693
|
+
dailyAccuracy: exports_external5.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
83694
|
+
dailyMasteredUnits: exports_external5.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
83695
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
83442
83696
|
var CourseMetrics5 = exports_external5.object({
|
|
83443
|
-
totalXp: exports_external5.number().int().positive().optional(),
|
|
83444
|
-
totalLessons: exports_external5.number().int().positive().optional(),
|
|
83445
|
-
totalGrades: exports_external5.number().int().positive().optional()
|
|
83446
|
-
});
|
|
83697
|
+
totalXp: exports_external5.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
83698
|
+
totalLessons: exports_external5.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
83699
|
+
totalGrades: exports_external5.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
83700
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
83447
83701
|
var CourseMetadata5 = exports_external5.object({
|
|
83448
83702
|
courseType: CourseType5.optional(),
|
|
83449
|
-
isSupplemental: exports_external5.boolean().optional(),
|
|
83450
|
-
isCustom: exports_external5.boolean().optional(),
|
|
83703
|
+
isSupplemental: exports_external5.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
83704
|
+
isCustom: exports_external5.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
83451
83705
|
publishStatus: PublishStatus5.optional(),
|
|
83452
|
-
contactEmail: exports_external5.email().optional(),
|
|
83453
|
-
primaryApp: exports_external5.string().optional(),
|
|
83706
|
+
contactEmail: exports_external5.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
83707
|
+
primaryApp: exports_external5.string().meta({ description: "Primary application identifier" }).optional(),
|
|
83454
83708
|
goals: CourseGoals5.optional(),
|
|
83455
83709
|
metrics: CourseMetrics5.optional()
|
|
83456
|
-
});
|
|
83710
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
83457
83711
|
var CourseDefaults5 = exports_external5.object({
|
|
83458
|
-
courseCode: exports_external5.string().optional(),
|
|
83459
|
-
level: exports_external5.string().optional(),
|
|
83712
|
+
courseCode: exports_external5.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
83713
|
+
level: exports_external5.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
83460
83714
|
metadata: CourseMetadata5.optional()
|
|
83715
|
+
}).meta({
|
|
83716
|
+
id: "CourseDefaults",
|
|
83717
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
83461
83718
|
});
|
|
83462
83719
|
var CourseEnvOverrides5 = exports_external5.object({
|
|
83463
|
-
level: exports_external5.string().optional(),
|
|
83464
|
-
sensor: exports_external5.
|
|
83465
|
-
launchUrl: exports_external5.
|
|
83720
|
+
level: exports_external5.string().meta({ description: "Course level for this environment" }).optional(),
|
|
83721
|
+
sensor: exports_external5.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
83722
|
+
launchUrl: exports_external5.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
83466
83723
|
metadata: CourseMetadata5.optional()
|
|
83724
|
+
}).meta({
|
|
83725
|
+
id: "CourseEnvOverrides",
|
|
83726
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
83467
83727
|
});
|
|
83468
83728
|
var CourseOverrides5 = exports_external5.object({
|
|
83469
|
-
staging: CourseEnvOverrides5.
|
|
83470
|
-
|
|
83471
|
-
})
|
|
83729
|
+
staging: CourseEnvOverrides5.meta({
|
|
83730
|
+
description: "Overrides for staging environment"
|
|
83731
|
+
}).optional(),
|
|
83732
|
+
production: CourseEnvOverrides5.meta({
|
|
83733
|
+
description: "Overrides for production environment"
|
|
83734
|
+
}).optional()
|
|
83735
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
83472
83736
|
var CourseConfig5 = CourseDefaults5.extend({
|
|
83473
|
-
subject: TimebackSubject5,
|
|
83474
|
-
grade: TimebackGrade5.
|
|
83737
|
+
subject: TimebackSubject5.meta({ description: "Subject area for this course" }),
|
|
83738
|
+
grade: TimebackGrade5.meta({
|
|
83739
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
83740
|
+
}).optional(),
|
|
83475
83741
|
ids: CourseIds5.nullable().optional(),
|
|
83476
|
-
sensor: exports_external5.
|
|
83477
|
-
launchUrl: exports_external5.
|
|
83742
|
+
sensor: exports_external5.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
83743
|
+
launchUrl: exports_external5.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
83478
83744
|
overrides: CourseOverrides5.optional()
|
|
83745
|
+
}).meta({
|
|
83746
|
+
id: "CourseConfig",
|
|
83747
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
83479
83748
|
});
|
|
83480
83749
|
var TimebackConfig5 = exports_external5.object({
|
|
83481
|
-
|
|
83482
|
-
|
|
83483
|
-
|
|
83484
|
-
|
|
83485
|
-
|
|
83750
|
+
$schema: exports_external5.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
83751
|
+
name: exports_external5.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
83752
|
+
defaults: CourseDefaults5.meta({
|
|
83753
|
+
description: "Default properties applied to all courses"
|
|
83754
|
+
}).optional(),
|
|
83755
|
+
courses: exports_external5.array(CourseConfig5).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
83756
|
+
sensor: exports_external5.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
83757
|
+
launchUrl: exports_external5.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
83758
|
+
}).meta({
|
|
83759
|
+
id: "TimebackConfig",
|
|
83760
|
+
title: "Timeback Config",
|
|
83761
|
+
description: "Configuration schema for timeback.config.json files"
|
|
83486
83762
|
}).refine((config22) => {
|
|
83487
83763
|
return config22.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
83488
83764
|
}, {
|
|
@@ -83503,17 +83779,23 @@ var TimebackConfig5 = exports_external5.object({
|
|
|
83503
83779
|
message: "Duplicate courseCode found; each must be unique",
|
|
83504
83780
|
path: ["courses"]
|
|
83505
83781
|
}).refine((config22) => {
|
|
83506
|
-
return config22.courses.every((c) =>
|
|
83507
|
-
|
|
83508
|
-
|
|
83509
|
-
|
|
83510
|
-
|
|
83511
|
-
|
|
83782
|
+
return config22.courses.every((c) => {
|
|
83783
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
83784
|
+
return true;
|
|
83785
|
+
}
|
|
83786
|
+
const launchUrls = [
|
|
83787
|
+
c.launchUrl,
|
|
83788
|
+
config22.launchUrl,
|
|
83789
|
+
c.overrides?.staging?.launchUrl,
|
|
83790
|
+
c.overrides?.production?.launchUrl
|
|
83791
|
+
].filter(Boolean);
|
|
83792
|
+
return launchUrls.length > 0;
|
|
83793
|
+
});
|
|
83512
83794
|
}, {
|
|
83513
|
-
message: "Each course must have an effective
|
|
83795
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
83514
83796
|
path: ["courses"]
|
|
83515
83797
|
});
|
|
83516
|
-
var EdubridgeDateString5 =
|
|
83798
|
+
var EdubridgeDateString5 = IsoDateTimeString5;
|
|
83517
83799
|
var EduBridgeEnrollment5 = exports_external5.object({
|
|
83518
83800
|
id: exports_external5.string(),
|
|
83519
83801
|
role: exports_external5.string(),
|
|
@@ -83577,12 +83859,9 @@ var EmailOrStudentId5 = exports_external5.object({
|
|
|
83577
83859
|
});
|
|
83578
83860
|
var SubjectTrackInput5 = exports_external5.object({
|
|
83579
83861
|
subject: NonEmptyString8,
|
|
83580
|
-
|
|
83581
|
-
|
|
83582
|
-
|
|
83583
|
-
});
|
|
83584
|
-
var SubjectTrackUpsertInput5 = SubjectTrackInput5.extend({
|
|
83585
|
-
id: NonEmptyString8
|
|
83862
|
+
grade: NonEmptyString8,
|
|
83863
|
+
courseId: NonEmptyString8,
|
|
83864
|
+
orgSourcedId: NonEmptyString8.optional()
|
|
83586
83865
|
});
|
|
83587
83866
|
var EdubridgeListEnrollmentsParams5 = exports_external5.object({
|
|
83588
83867
|
userId: NonEmptyString8
|
|
@@ -84978,11 +85257,21 @@ var QtiClient = createQtiClient();
|
|
|
84978
85257
|
// src/constants.ts
|
|
84979
85258
|
var TIMEBACK_ENV_VARS = {
|
|
84980
85259
|
env: "TIMEBACK_ENV",
|
|
84981
|
-
baseUrl: "TIMEBACK_BASE_URL",
|
|
84982
|
-
authUrl: "
|
|
84983
|
-
clientId: "TIMEBACK_CLIENT_ID",
|
|
84984
|
-
clientSecret: "TIMEBACK_CLIENT_SECRET"
|
|
85260
|
+
baseUrl: ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL"],
|
|
85261
|
+
authUrl: ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL"],
|
|
85262
|
+
clientId: ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID"],
|
|
85263
|
+
clientSecret: ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET"]
|
|
84985
85264
|
};
|
|
85265
|
+
function getServiceUrlsForEnv(env, platform = DEFAULT_PLATFORM3) {
|
|
85266
|
+
const endpoints = PLATFORM_ENDPOINTS3[platform];
|
|
85267
|
+
return {
|
|
85268
|
+
oneroster: endpoints.api[env],
|
|
85269
|
+
caliper: endpoints.caliper[env],
|
|
85270
|
+
edubridge: endpoints.api[env],
|
|
85271
|
+
qti: endpoints.qti[env],
|
|
85272
|
+
authUrl: endpoints.token[env]
|
|
85273
|
+
};
|
|
85274
|
+
}
|
|
84986
85275
|
|
|
84987
85276
|
// src/client.ts
|
|
84988
85277
|
class TimebackClient {
|
|
@@ -85160,6 +85449,7 @@ class TimebackManager {
|
|
|
85160
85449
|
export {
|
|
85161
85450
|
whereToFilter2 as whereToFilter,
|
|
85162
85451
|
isApiError,
|
|
85452
|
+
getServiceUrlsForEnv,
|
|
85163
85453
|
ValidationError3 as ValidationError,
|
|
85164
85454
|
UnauthorizedError3 as UnauthorizedError,
|
|
85165
85455
|
TimebackManager,
|