timeback 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -26
- package/dist/cli.js +766 -695
- package/package.json +3 -11
- package/schema.json +523 -133
- package/dist/cli/src/config.d.ts +0 -8
- package/dist/types/src/config.d.ts +0 -186
- package/dist/types/src/index.d.ts +0 -5
- package/dist/types/src/primitives.d.ts +0 -53
package/dist/cli.js
CHANGED
|
@@ -31623,7 +31623,7 @@ var TimebackSubject = exports_external2.enum([
|
|
|
31623
31623
|
"Math",
|
|
31624
31624
|
"None",
|
|
31625
31625
|
"Other"
|
|
31626
|
-
]);
|
|
31626
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
31627
31627
|
var TimebackGrade = exports_external2.union([
|
|
31628
31628
|
exports_external2.literal(-1),
|
|
31629
31629
|
exports_external2.literal(0),
|
|
@@ -31640,7 +31640,10 @@ var TimebackGrade = exports_external2.union([
|
|
|
31640
31640
|
exports_external2.literal(11),
|
|
31641
31641
|
exports_external2.literal(12),
|
|
31642
31642
|
exports_external2.literal(13)
|
|
31643
|
-
])
|
|
31643
|
+
]).meta({
|
|
31644
|
+
id: "TimebackGrade",
|
|
31645
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
31646
|
+
});
|
|
31644
31647
|
var ScoreStatus = exports_external2.enum([
|
|
31645
31648
|
"exempt",
|
|
31646
31649
|
"fully graded",
|
|
@@ -31870,62 +31873,84 @@ var CaliperListEventsParams = exports_external2.object({
|
|
|
31870
31873
|
actorEmail: exports_external2.email().optional()
|
|
31871
31874
|
}).strict();
|
|
31872
31875
|
var CourseIds = exports_external2.object({
|
|
31873
|
-
staging: exports_external2.string().optional(),
|
|
31874
|
-
production: exports_external2.string().optional()
|
|
31875
|
-
});
|
|
31876
|
-
var CourseType = exports_external2.enum(["base", "hole-filling", "optional"]);
|
|
31877
|
-
var PublishStatus = exports_external2.enum(["draft", "testing", "published", "deactivated"]);
|
|
31876
|
+
staging: exports_external2.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
31877
|
+
production: exports_external2.string().meta({ description: "Course ID in production environment" }).optional()
|
|
31878
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
31879
|
+
var CourseType = exports_external2.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
31880
|
+
var PublishStatus = exports_external2.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
31878
31881
|
var CourseGoals = exports_external2.object({
|
|
31879
|
-
dailyXp: exports_external2.number().int().positive().optional(),
|
|
31880
|
-
dailyLessons: exports_external2.number().int().positive().optional(),
|
|
31881
|
-
dailyActiveMinutes: exports_external2.number().int().positive().optional(),
|
|
31882
|
-
dailyAccuracy: exports_external2.number().int().min(0).max(100).optional(),
|
|
31883
|
-
dailyMasteredUnits: exports_external2.number().int().positive().optional()
|
|
31884
|
-
});
|
|
31882
|
+
dailyXp: exports_external2.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
31883
|
+
dailyLessons: exports_external2.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
31884
|
+
dailyActiveMinutes: exports_external2.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
31885
|
+
dailyAccuracy: exports_external2.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
31886
|
+
dailyMasteredUnits: exports_external2.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
31887
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
31885
31888
|
var CourseMetrics = exports_external2.object({
|
|
31886
|
-
totalXp: exports_external2.number().int().positive().optional(),
|
|
31887
|
-
totalLessons: exports_external2.number().int().positive().optional(),
|
|
31888
|
-
totalGrades: exports_external2.number().int().positive().optional()
|
|
31889
|
-
});
|
|
31889
|
+
totalXp: exports_external2.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
31890
|
+
totalLessons: exports_external2.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
31891
|
+
totalGrades: exports_external2.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
31892
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
31890
31893
|
var CourseMetadata = exports_external2.object({
|
|
31891
31894
|
courseType: CourseType.optional(),
|
|
31892
|
-
isSupplemental: exports_external2.boolean().optional(),
|
|
31893
|
-
isCustom: exports_external2.boolean().optional(),
|
|
31895
|
+
isSupplemental: exports_external2.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
31896
|
+
isCustom: exports_external2.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
31894
31897
|
publishStatus: PublishStatus.optional(),
|
|
31895
|
-
contactEmail: exports_external2.email().optional(),
|
|
31896
|
-
primaryApp: exports_external2.string().optional(),
|
|
31898
|
+
contactEmail: exports_external2.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
31899
|
+
primaryApp: exports_external2.string().meta({ description: "Primary application identifier" }).optional(),
|
|
31897
31900
|
goals: CourseGoals.optional(),
|
|
31898
31901
|
metrics: CourseMetrics.optional()
|
|
31899
|
-
});
|
|
31902
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
31900
31903
|
var CourseDefaults = exports_external2.object({
|
|
31901
|
-
courseCode: exports_external2.string().optional(),
|
|
31902
|
-
level: exports_external2.string().optional(),
|
|
31904
|
+
courseCode: exports_external2.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
31905
|
+
level: exports_external2.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
31903
31906
|
metadata: CourseMetadata.optional()
|
|
31907
|
+
}).meta({
|
|
31908
|
+
id: "CourseDefaults",
|
|
31909
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
31904
31910
|
});
|
|
31905
31911
|
var CourseEnvOverrides = exports_external2.object({
|
|
31906
|
-
level: exports_external2.string().optional(),
|
|
31907
|
-
sensor: exports_external2.
|
|
31908
|
-
launchUrl: exports_external2.
|
|
31912
|
+
level: exports_external2.string().meta({ description: "Course level for this environment" }).optional(),
|
|
31913
|
+
sensor: exports_external2.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
31914
|
+
launchUrl: exports_external2.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
31909
31915
|
metadata: CourseMetadata.optional()
|
|
31916
|
+
}).meta({
|
|
31917
|
+
id: "CourseEnvOverrides",
|
|
31918
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
31910
31919
|
});
|
|
31911
31920
|
var CourseOverrides = exports_external2.object({
|
|
31912
|
-
staging: CourseEnvOverrides.
|
|
31913
|
-
|
|
31914
|
-
})
|
|
31921
|
+
staging: CourseEnvOverrides.meta({
|
|
31922
|
+
description: "Overrides for staging environment"
|
|
31923
|
+
}).optional(),
|
|
31924
|
+
production: CourseEnvOverrides.meta({
|
|
31925
|
+
description: "Overrides for production environment"
|
|
31926
|
+
}).optional()
|
|
31927
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
31915
31928
|
var CourseConfig = CourseDefaults.extend({
|
|
31916
|
-
subject: TimebackSubject,
|
|
31917
|
-
grade: TimebackGrade.
|
|
31929
|
+
subject: TimebackSubject.meta({ description: "Subject area for this course" }),
|
|
31930
|
+
grade: TimebackGrade.meta({
|
|
31931
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
31932
|
+
}).optional(),
|
|
31918
31933
|
ids: CourseIds.nullable().optional(),
|
|
31919
|
-
sensor: exports_external2.
|
|
31920
|
-
launchUrl: exports_external2.
|
|
31934
|
+
sensor: exports_external2.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
31935
|
+
launchUrl: exports_external2.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
31921
31936
|
overrides: CourseOverrides.optional()
|
|
31937
|
+
}).meta({
|
|
31938
|
+
id: "CourseConfig",
|
|
31939
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
31922
31940
|
});
|
|
31923
31941
|
var TimebackConfig = exports_external2.object({
|
|
31924
|
-
|
|
31925
|
-
|
|
31926
|
-
|
|
31927
|
-
|
|
31928
|
-
|
|
31942
|
+
$schema: exports_external2.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
31943
|
+
name: exports_external2.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
31944
|
+
defaults: CourseDefaults.meta({
|
|
31945
|
+
description: "Default properties applied to all courses"
|
|
31946
|
+
}).optional(),
|
|
31947
|
+
courses: exports_external2.array(CourseConfig).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
31948
|
+
sensor: exports_external2.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
31949
|
+
launchUrl: exports_external2.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
31950
|
+
}).meta({
|
|
31951
|
+
id: "TimebackConfig",
|
|
31952
|
+
title: "Timeback Config",
|
|
31953
|
+
description: "Configuration schema for timeback.config.json files"
|
|
31929
31954
|
}).refine((config22) => {
|
|
31930
31955
|
return config22.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
31931
31956
|
}, {
|
|
@@ -48001,7 +48026,7 @@ var TimebackSubject2 = exports_external22.enum([
|
|
|
48001
48026
|
"Math",
|
|
48002
48027
|
"None",
|
|
48003
48028
|
"Other"
|
|
48004
|
-
]);
|
|
48029
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
48005
48030
|
var TimebackGrade2 = exports_external22.union([
|
|
48006
48031
|
exports_external22.literal(-1),
|
|
48007
48032
|
exports_external22.literal(0),
|
|
@@ -48018,7 +48043,10 @@ var TimebackGrade2 = exports_external22.union([
|
|
|
48018
48043
|
exports_external22.literal(11),
|
|
48019
48044
|
exports_external22.literal(12),
|
|
48020
48045
|
exports_external22.literal(13)
|
|
48021
|
-
])
|
|
48046
|
+
]).meta({
|
|
48047
|
+
id: "TimebackGrade",
|
|
48048
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
48049
|
+
});
|
|
48022
48050
|
var ScoreStatus2 = exports_external22.enum([
|
|
48023
48051
|
"exempt",
|
|
48024
48052
|
"fully graded",
|
|
@@ -48248,62 +48276,84 @@ var CaliperListEventsParams2 = exports_external22.object({
|
|
|
48248
48276
|
actorEmail: exports_external22.email().optional()
|
|
48249
48277
|
}).strict();
|
|
48250
48278
|
var CourseIds2 = exports_external22.object({
|
|
48251
|
-
staging: exports_external22.string().optional(),
|
|
48252
|
-
production: exports_external22.string().optional()
|
|
48253
|
-
});
|
|
48254
|
-
var CourseType2 = exports_external22.enum(["base", "hole-filling", "optional"]);
|
|
48255
|
-
var PublishStatus2 = exports_external22.enum(["draft", "testing", "published", "deactivated"]);
|
|
48279
|
+
staging: exports_external22.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
48280
|
+
production: exports_external22.string().meta({ description: "Course ID in production environment" }).optional()
|
|
48281
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
48282
|
+
var CourseType2 = exports_external22.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
48283
|
+
var PublishStatus2 = exports_external22.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
48256
48284
|
var CourseGoals2 = exports_external22.object({
|
|
48257
|
-
dailyXp: exports_external22.number().int().positive().optional(),
|
|
48258
|
-
dailyLessons: exports_external22.number().int().positive().optional(),
|
|
48259
|
-
dailyActiveMinutes: exports_external22.number().int().positive().optional(),
|
|
48260
|
-
dailyAccuracy: exports_external22.number().int().min(0).max(100).optional(),
|
|
48261
|
-
dailyMasteredUnits: exports_external22.number().int().positive().optional()
|
|
48262
|
-
});
|
|
48285
|
+
dailyXp: exports_external22.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
48286
|
+
dailyLessons: exports_external22.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
48287
|
+
dailyActiveMinutes: exports_external22.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
48288
|
+
dailyAccuracy: exports_external22.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
48289
|
+
dailyMasteredUnits: exports_external22.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
48290
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
48263
48291
|
var CourseMetrics2 = exports_external22.object({
|
|
48264
|
-
totalXp: exports_external22.number().int().positive().optional(),
|
|
48265
|
-
totalLessons: exports_external22.number().int().positive().optional(),
|
|
48266
|
-
totalGrades: exports_external22.number().int().positive().optional()
|
|
48267
|
-
});
|
|
48292
|
+
totalXp: exports_external22.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
48293
|
+
totalLessons: exports_external22.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
48294
|
+
totalGrades: exports_external22.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
48295
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
48268
48296
|
var CourseMetadata2 = exports_external22.object({
|
|
48269
48297
|
courseType: CourseType2.optional(),
|
|
48270
|
-
isSupplemental: exports_external22.boolean().optional(),
|
|
48271
|
-
isCustom: exports_external22.boolean().optional(),
|
|
48298
|
+
isSupplemental: exports_external22.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
48299
|
+
isCustom: exports_external22.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
48272
48300
|
publishStatus: PublishStatus2.optional(),
|
|
48273
|
-
contactEmail: exports_external22.email().optional(),
|
|
48274
|
-
primaryApp: exports_external22.string().optional(),
|
|
48301
|
+
contactEmail: exports_external22.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
48302
|
+
primaryApp: exports_external22.string().meta({ description: "Primary application identifier" }).optional(),
|
|
48275
48303
|
goals: CourseGoals2.optional(),
|
|
48276
48304
|
metrics: CourseMetrics2.optional()
|
|
48277
|
-
});
|
|
48305
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
48278
48306
|
var CourseDefaults2 = exports_external22.object({
|
|
48279
|
-
courseCode: exports_external22.string().optional(),
|
|
48280
|
-
level: exports_external22.string().optional(),
|
|
48307
|
+
courseCode: exports_external22.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
48308
|
+
level: exports_external22.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
48281
48309
|
metadata: CourseMetadata2.optional()
|
|
48310
|
+
}).meta({
|
|
48311
|
+
id: "CourseDefaults",
|
|
48312
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
48282
48313
|
});
|
|
48283
48314
|
var CourseEnvOverrides2 = exports_external22.object({
|
|
48284
|
-
level: exports_external22.string().optional(),
|
|
48285
|
-
sensor: exports_external22.
|
|
48286
|
-
launchUrl: exports_external22.
|
|
48315
|
+
level: exports_external22.string().meta({ description: "Course level for this environment" }).optional(),
|
|
48316
|
+
sensor: exports_external22.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
48317
|
+
launchUrl: exports_external22.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
48287
48318
|
metadata: CourseMetadata2.optional()
|
|
48319
|
+
}).meta({
|
|
48320
|
+
id: "CourseEnvOverrides",
|
|
48321
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
48288
48322
|
});
|
|
48289
48323
|
var CourseOverrides2 = exports_external22.object({
|
|
48290
|
-
staging: CourseEnvOverrides2.
|
|
48291
|
-
|
|
48292
|
-
})
|
|
48324
|
+
staging: CourseEnvOverrides2.meta({
|
|
48325
|
+
description: "Overrides for staging environment"
|
|
48326
|
+
}).optional(),
|
|
48327
|
+
production: CourseEnvOverrides2.meta({
|
|
48328
|
+
description: "Overrides for production environment"
|
|
48329
|
+
}).optional()
|
|
48330
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
48293
48331
|
var CourseConfig2 = CourseDefaults2.extend({
|
|
48294
|
-
subject: TimebackSubject2,
|
|
48295
|
-
grade: TimebackGrade2.
|
|
48332
|
+
subject: TimebackSubject2.meta({ description: "Subject area for this course" }),
|
|
48333
|
+
grade: TimebackGrade2.meta({
|
|
48334
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
48335
|
+
}).optional(),
|
|
48296
48336
|
ids: CourseIds2.nullable().optional(),
|
|
48297
|
-
sensor: exports_external22.
|
|
48298
|
-
launchUrl: exports_external22.
|
|
48337
|
+
sensor: exports_external22.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
48338
|
+
launchUrl: exports_external22.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
48299
48339
|
overrides: CourseOverrides2.optional()
|
|
48340
|
+
}).meta({
|
|
48341
|
+
id: "CourseConfig",
|
|
48342
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
48300
48343
|
});
|
|
48301
48344
|
var TimebackConfig2 = exports_external22.object({
|
|
48302
|
-
|
|
48303
|
-
|
|
48304
|
-
|
|
48305
|
-
|
|
48306
|
-
|
|
48345
|
+
$schema: exports_external22.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
48346
|
+
name: exports_external22.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
48347
|
+
defaults: CourseDefaults2.meta({
|
|
48348
|
+
description: "Default properties applied to all courses"
|
|
48349
|
+
}).optional(),
|
|
48350
|
+
courses: exports_external22.array(CourseConfig2).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
48351
|
+
sensor: exports_external22.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
48352
|
+
launchUrl: exports_external22.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
48353
|
+
}).meta({
|
|
48354
|
+
id: "TimebackConfig",
|
|
48355
|
+
title: "Timeback Config",
|
|
48356
|
+
description: "Configuration schema for timeback.config.json files"
|
|
48307
48357
|
}).refine((config222) => {
|
|
48308
48358
|
return config222.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
48309
48359
|
}, {
|
|
@@ -65414,7 +65464,7 @@ var TimebackSubject3 = exports_external3.enum([
|
|
|
65414
65464
|
"Math",
|
|
65415
65465
|
"None",
|
|
65416
65466
|
"Other"
|
|
65417
|
-
]);
|
|
65467
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
65418
65468
|
var TimebackGrade3 = exports_external3.union([
|
|
65419
65469
|
exports_external3.literal(-1),
|
|
65420
65470
|
exports_external3.literal(0),
|
|
@@ -65431,7 +65481,10 @@ var TimebackGrade3 = exports_external3.union([
|
|
|
65431
65481
|
exports_external3.literal(11),
|
|
65432
65482
|
exports_external3.literal(12),
|
|
65433
65483
|
exports_external3.literal(13)
|
|
65434
|
-
])
|
|
65484
|
+
]).meta({
|
|
65485
|
+
id: "TimebackGrade",
|
|
65486
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
65487
|
+
});
|
|
65435
65488
|
var ScoreStatus3 = exports_external3.enum([
|
|
65436
65489
|
"exempt",
|
|
65437
65490
|
"fully graded",
|
|
@@ -65661,62 +65714,84 @@ var CaliperListEventsParams3 = exports_external3.object({
|
|
|
65661
65714
|
actorEmail: exports_external3.email().optional()
|
|
65662
65715
|
}).strict();
|
|
65663
65716
|
var CourseIds3 = exports_external3.object({
|
|
65664
|
-
staging: exports_external3.string().optional(),
|
|
65665
|
-
production: exports_external3.string().optional()
|
|
65666
|
-
});
|
|
65667
|
-
var CourseType3 = exports_external3.enum(["base", "hole-filling", "optional"]);
|
|
65668
|
-
var PublishStatus3 = exports_external3.enum(["draft", "testing", "published", "deactivated"]);
|
|
65717
|
+
staging: exports_external3.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
65718
|
+
production: exports_external3.string().meta({ description: "Course ID in production environment" }).optional()
|
|
65719
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
65720
|
+
var CourseType3 = exports_external3.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
65721
|
+
var PublishStatus3 = exports_external3.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
65669
65722
|
var CourseGoals3 = exports_external3.object({
|
|
65670
|
-
dailyXp: exports_external3.number().int().positive().optional(),
|
|
65671
|
-
dailyLessons: exports_external3.number().int().positive().optional(),
|
|
65672
|
-
dailyActiveMinutes: exports_external3.number().int().positive().optional(),
|
|
65673
|
-
dailyAccuracy: exports_external3.number().int().min(0).max(100).optional(),
|
|
65674
|
-
dailyMasteredUnits: exports_external3.number().int().positive().optional()
|
|
65675
|
-
});
|
|
65723
|
+
dailyXp: exports_external3.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
65724
|
+
dailyLessons: exports_external3.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
65725
|
+
dailyActiveMinutes: exports_external3.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
65726
|
+
dailyAccuracy: exports_external3.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
65727
|
+
dailyMasteredUnits: exports_external3.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
65728
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
65676
65729
|
var CourseMetrics3 = exports_external3.object({
|
|
65677
|
-
totalXp: exports_external3.number().int().positive().optional(),
|
|
65678
|
-
totalLessons: exports_external3.number().int().positive().optional(),
|
|
65679
|
-
totalGrades: exports_external3.number().int().positive().optional()
|
|
65680
|
-
});
|
|
65730
|
+
totalXp: exports_external3.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
65731
|
+
totalLessons: exports_external3.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
65732
|
+
totalGrades: exports_external3.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
65733
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
65681
65734
|
var CourseMetadata3 = exports_external3.object({
|
|
65682
65735
|
courseType: CourseType3.optional(),
|
|
65683
|
-
isSupplemental: exports_external3.boolean().optional(),
|
|
65684
|
-
isCustom: exports_external3.boolean().optional(),
|
|
65736
|
+
isSupplemental: exports_external3.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
65737
|
+
isCustom: exports_external3.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
65685
65738
|
publishStatus: PublishStatus3.optional(),
|
|
65686
|
-
contactEmail: exports_external3.email().optional(),
|
|
65687
|
-
primaryApp: exports_external3.string().optional(),
|
|
65739
|
+
contactEmail: exports_external3.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
65740
|
+
primaryApp: exports_external3.string().meta({ description: "Primary application identifier" }).optional(),
|
|
65688
65741
|
goals: CourseGoals3.optional(),
|
|
65689
65742
|
metrics: CourseMetrics3.optional()
|
|
65690
|
-
});
|
|
65743
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
65691
65744
|
var CourseDefaults3 = exports_external3.object({
|
|
65692
|
-
courseCode: exports_external3.string().optional(),
|
|
65693
|
-
level: exports_external3.string().optional(),
|
|
65745
|
+
courseCode: exports_external3.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
65746
|
+
level: exports_external3.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
65694
65747
|
metadata: CourseMetadata3.optional()
|
|
65748
|
+
}).meta({
|
|
65749
|
+
id: "CourseDefaults",
|
|
65750
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
65695
65751
|
});
|
|
65696
65752
|
var CourseEnvOverrides3 = exports_external3.object({
|
|
65697
|
-
level: exports_external3.string().optional(),
|
|
65698
|
-
sensor: exports_external3.
|
|
65699
|
-
launchUrl: exports_external3.
|
|
65753
|
+
level: exports_external3.string().meta({ description: "Course level for this environment" }).optional(),
|
|
65754
|
+
sensor: exports_external3.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
65755
|
+
launchUrl: exports_external3.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
65700
65756
|
metadata: CourseMetadata3.optional()
|
|
65757
|
+
}).meta({
|
|
65758
|
+
id: "CourseEnvOverrides",
|
|
65759
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
65701
65760
|
});
|
|
65702
65761
|
var CourseOverrides3 = exports_external3.object({
|
|
65703
|
-
staging: CourseEnvOverrides3.
|
|
65704
|
-
|
|
65705
|
-
})
|
|
65762
|
+
staging: CourseEnvOverrides3.meta({
|
|
65763
|
+
description: "Overrides for staging environment"
|
|
65764
|
+
}).optional(),
|
|
65765
|
+
production: CourseEnvOverrides3.meta({
|
|
65766
|
+
description: "Overrides for production environment"
|
|
65767
|
+
}).optional()
|
|
65768
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
65706
65769
|
var CourseConfig3 = CourseDefaults3.extend({
|
|
65707
|
-
subject: TimebackSubject3,
|
|
65708
|
-
grade: TimebackGrade3.
|
|
65770
|
+
subject: TimebackSubject3.meta({ description: "Subject area for this course" }),
|
|
65771
|
+
grade: TimebackGrade3.meta({
|
|
65772
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
65773
|
+
}).optional(),
|
|
65709
65774
|
ids: CourseIds3.nullable().optional(),
|
|
65710
|
-
sensor: exports_external3.
|
|
65711
|
-
launchUrl: exports_external3.
|
|
65775
|
+
sensor: exports_external3.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
65776
|
+
launchUrl: exports_external3.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
65712
65777
|
overrides: CourseOverrides3.optional()
|
|
65778
|
+
}).meta({
|
|
65779
|
+
id: "CourseConfig",
|
|
65780
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
65713
65781
|
});
|
|
65714
65782
|
var TimebackConfig3 = exports_external3.object({
|
|
65715
|
-
|
|
65716
|
-
|
|
65717
|
-
|
|
65718
|
-
|
|
65719
|
-
|
|
65783
|
+
$schema: exports_external3.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
65784
|
+
name: exports_external3.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
65785
|
+
defaults: CourseDefaults3.meta({
|
|
65786
|
+
description: "Default properties applied to all courses"
|
|
65787
|
+
}).optional(),
|
|
65788
|
+
courses: exports_external3.array(CourseConfig3).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
65789
|
+
sensor: exports_external3.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
65790
|
+
launchUrl: exports_external3.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
65791
|
+
}).meta({
|
|
65792
|
+
id: "TimebackConfig",
|
|
65793
|
+
title: "Timeback Config",
|
|
65794
|
+
description: "Configuration schema for timeback.config.json files"
|
|
65720
65795
|
}).refine((config222) => {
|
|
65721
65796
|
return config222.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
65722
65797
|
}, {
|
|
@@ -83021,7 +83096,7 @@ var TimebackSubject4 = exports_external4.enum([
|
|
|
83021
83096
|
"Math",
|
|
83022
83097
|
"None",
|
|
83023
83098
|
"Other"
|
|
83024
|
-
]);
|
|
83099
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
83025
83100
|
var TimebackGrade4 = exports_external4.union([
|
|
83026
83101
|
exports_external4.literal(-1),
|
|
83027
83102
|
exports_external4.literal(0),
|
|
@@ -83038,7 +83113,10 @@ var TimebackGrade4 = exports_external4.union([
|
|
|
83038
83113
|
exports_external4.literal(11),
|
|
83039
83114
|
exports_external4.literal(12),
|
|
83040
83115
|
exports_external4.literal(13)
|
|
83041
|
-
])
|
|
83116
|
+
]).meta({
|
|
83117
|
+
id: "TimebackGrade",
|
|
83118
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
83119
|
+
});
|
|
83042
83120
|
var ScoreStatus4 = exports_external4.enum([
|
|
83043
83121
|
"exempt",
|
|
83044
83122
|
"fully graded",
|
|
@@ -83268,62 +83346,84 @@ var CaliperListEventsParams4 = exports_external4.object({
|
|
|
83268
83346
|
actorEmail: exports_external4.email().optional()
|
|
83269
83347
|
}).strict();
|
|
83270
83348
|
var CourseIds4 = exports_external4.object({
|
|
83271
|
-
staging: exports_external4.string().optional(),
|
|
83272
|
-
production: exports_external4.string().optional()
|
|
83273
|
-
});
|
|
83274
|
-
var CourseType4 = exports_external4.enum(["base", "hole-filling", "optional"]);
|
|
83275
|
-
var PublishStatus4 = exports_external4.enum(["draft", "testing", "published", "deactivated"]);
|
|
83349
|
+
staging: exports_external4.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
83350
|
+
production: exports_external4.string().meta({ description: "Course ID in production environment" }).optional()
|
|
83351
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
83352
|
+
var CourseType4 = exports_external4.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
83353
|
+
var PublishStatus4 = exports_external4.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
83276
83354
|
var CourseGoals4 = exports_external4.object({
|
|
83277
|
-
dailyXp: exports_external4.number().int().positive().optional(),
|
|
83278
|
-
dailyLessons: exports_external4.number().int().positive().optional(),
|
|
83279
|
-
dailyActiveMinutes: exports_external4.number().int().positive().optional(),
|
|
83280
|
-
dailyAccuracy: exports_external4.number().int().min(0).max(100).optional(),
|
|
83281
|
-
dailyMasteredUnits: exports_external4.number().int().positive().optional()
|
|
83282
|
-
});
|
|
83355
|
+
dailyXp: exports_external4.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
83356
|
+
dailyLessons: exports_external4.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
83357
|
+
dailyActiveMinutes: exports_external4.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
83358
|
+
dailyAccuracy: exports_external4.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
83359
|
+
dailyMasteredUnits: exports_external4.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
83360
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
83283
83361
|
var CourseMetrics4 = exports_external4.object({
|
|
83284
|
-
totalXp: exports_external4.number().int().positive().optional(),
|
|
83285
|
-
totalLessons: exports_external4.number().int().positive().optional(),
|
|
83286
|
-
totalGrades: exports_external4.number().int().positive().optional()
|
|
83287
|
-
});
|
|
83362
|
+
totalXp: exports_external4.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
83363
|
+
totalLessons: exports_external4.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
83364
|
+
totalGrades: exports_external4.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
83365
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
83288
83366
|
var CourseMetadata4 = exports_external4.object({
|
|
83289
83367
|
courseType: CourseType4.optional(),
|
|
83290
|
-
isSupplemental: exports_external4.boolean().optional(),
|
|
83291
|
-
isCustom: exports_external4.boolean().optional(),
|
|
83368
|
+
isSupplemental: exports_external4.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
83369
|
+
isCustom: exports_external4.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
83292
83370
|
publishStatus: PublishStatus4.optional(),
|
|
83293
|
-
contactEmail: exports_external4.email().optional(),
|
|
83294
|
-
primaryApp: exports_external4.string().optional(),
|
|
83371
|
+
contactEmail: exports_external4.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
83372
|
+
primaryApp: exports_external4.string().meta({ description: "Primary application identifier" }).optional(),
|
|
83295
83373
|
goals: CourseGoals4.optional(),
|
|
83296
83374
|
metrics: CourseMetrics4.optional()
|
|
83297
|
-
});
|
|
83375
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
83298
83376
|
var CourseDefaults4 = exports_external4.object({
|
|
83299
|
-
courseCode: exports_external4.string().optional(),
|
|
83300
|
-
level: exports_external4.string().optional(),
|
|
83377
|
+
courseCode: exports_external4.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
83378
|
+
level: exports_external4.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
83301
83379
|
metadata: CourseMetadata4.optional()
|
|
83380
|
+
}).meta({
|
|
83381
|
+
id: "CourseDefaults",
|
|
83382
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
83302
83383
|
});
|
|
83303
83384
|
var CourseEnvOverrides4 = exports_external4.object({
|
|
83304
|
-
level: exports_external4.string().optional(),
|
|
83305
|
-
sensor: exports_external4.
|
|
83306
|
-
launchUrl: exports_external4.
|
|
83385
|
+
level: exports_external4.string().meta({ description: "Course level for this environment" }).optional(),
|
|
83386
|
+
sensor: exports_external4.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
83387
|
+
launchUrl: exports_external4.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
83307
83388
|
metadata: CourseMetadata4.optional()
|
|
83389
|
+
}).meta({
|
|
83390
|
+
id: "CourseEnvOverrides",
|
|
83391
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
83308
83392
|
});
|
|
83309
83393
|
var CourseOverrides4 = exports_external4.object({
|
|
83310
|
-
staging: CourseEnvOverrides4.
|
|
83311
|
-
|
|
83312
|
-
})
|
|
83394
|
+
staging: CourseEnvOverrides4.meta({
|
|
83395
|
+
description: "Overrides for staging environment"
|
|
83396
|
+
}).optional(),
|
|
83397
|
+
production: CourseEnvOverrides4.meta({
|
|
83398
|
+
description: "Overrides for production environment"
|
|
83399
|
+
}).optional()
|
|
83400
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
83313
83401
|
var CourseConfig4 = CourseDefaults4.extend({
|
|
83314
|
-
subject: TimebackSubject4,
|
|
83315
|
-
grade: TimebackGrade4.
|
|
83402
|
+
subject: TimebackSubject4.meta({ description: "Subject area for this course" }),
|
|
83403
|
+
grade: TimebackGrade4.meta({
|
|
83404
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
83405
|
+
}).optional(),
|
|
83316
83406
|
ids: CourseIds4.nullable().optional(),
|
|
83317
|
-
sensor: exports_external4.
|
|
83318
|
-
launchUrl: exports_external4.
|
|
83407
|
+
sensor: exports_external4.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
83408
|
+
launchUrl: exports_external4.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
83319
83409
|
overrides: CourseOverrides4.optional()
|
|
83410
|
+
}).meta({
|
|
83411
|
+
id: "CourseConfig",
|
|
83412
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
83320
83413
|
});
|
|
83321
83414
|
var TimebackConfig4 = exports_external4.object({
|
|
83322
|
-
|
|
83323
|
-
|
|
83324
|
-
|
|
83325
|
-
|
|
83326
|
-
|
|
83415
|
+
$schema: exports_external4.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
83416
|
+
name: exports_external4.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
83417
|
+
defaults: CourseDefaults4.meta({
|
|
83418
|
+
description: "Default properties applied to all courses"
|
|
83419
|
+
}).optional(),
|
|
83420
|
+
courses: exports_external4.array(CourseConfig4).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
83421
|
+
sensor: exports_external4.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
83422
|
+
launchUrl: exports_external4.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
83423
|
+
}).meta({
|
|
83424
|
+
id: "TimebackConfig",
|
|
83425
|
+
title: "Timeback Config",
|
|
83426
|
+
description: "Configuration schema for timeback.config.json files"
|
|
83327
83427
|
}).refine((config222) => {
|
|
83328
83428
|
return config222.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
83329
83429
|
}, {
|
|
@@ -99658,7 +99758,7 @@ var TimebackSubject5 = exports_external5.enum([
|
|
|
99658
99758
|
"Math",
|
|
99659
99759
|
"None",
|
|
99660
99760
|
"Other"
|
|
99661
|
-
]);
|
|
99761
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
99662
99762
|
var TimebackGrade5 = exports_external5.union([
|
|
99663
99763
|
exports_external5.literal(-1),
|
|
99664
99764
|
exports_external5.literal(0),
|
|
@@ -99675,7 +99775,10 @@ var TimebackGrade5 = exports_external5.union([
|
|
|
99675
99775
|
exports_external5.literal(11),
|
|
99676
99776
|
exports_external5.literal(12),
|
|
99677
99777
|
exports_external5.literal(13)
|
|
99678
|
-
])
|
|
99778
|
+
]).meta({
|
|
99779
|
+
id: "TimebackGrade",
|
|
99780
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
99781
|
+
});
|
|
99679
99782
|
var ScoreStatus5 = exports_external5.enum([
|
|
99680
99783
|
"exempt",
|
|
99681
99784
|
"fully graded",
|
|
@@ -99905,62 +100008,84 @@ var CaliperListEventsParams5 = exports_external5.object({
|
|
|
99905
100008
|
actorEmail: exports_external5.email().optional()
|
|
99906
100009
|
}).strict();
|
|
99907
100010
|
var CourseIds5 = exports_external5.object({
|
|
99908
|
-
staging: exports_external5.string().optional(),
|
|
99909
|
-
production: exports_external5.string().optional()
|
|
99910
|
-
});
|
|
99911
|
-
var CourseType5 = exports_external5.enum(["base", "hole-filling", "optional"]);
|
|
99912
|
-
var PublishStatus5 = exports_external5.enum(["draft", "testing", "published", "deactivated"]);
|
|
100011
|
+
staging: exports_external5.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
100012
|
+
production: exports_external5.string().meta({ description: "Course ID in production environment" }).optional()
|
|
100013
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
100014
|
+
var CourseType5 = exports_external5.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
100015
|
+
var PublishStatus5 = exports_external5.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
99913
100016
|
var CourseGoals5 = exports_external5.object({
|
|
99914
|
-
dailyXp: exports_external5.number().int().positive().optional(),
|
|
99915
|
-
dailyLessons: exports_external5.number().int().positive().optional(),
|
|
99916
|
-
dailyActiveMinutes: exports_external5.number().int().positive().optional(),
|
|
99917
|
-
dailyAccuracy: exports_external5.number().int().min(0).max(100).optional(),
|
|
99918
|
-
dailyMasteredUnits: exports_external5.number().int().positive().optional()
|
|
99919
|
-
});
|
|
100017
|
+
dailyXp: exports_external5.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
100018
|
+
dailyLessons: exports_external5.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
100019
|
+
dailyActiveMinutes: exports_external5.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
100020
|
+
dailyAccuracy: exports_external5.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
100021
|
+
dailyMasteredUnits: exports_external5.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
100022
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
99920
100023
|
var CourseMetrics5 = exports_external5.object({
|
|
99921
|
-
totalXp: exports_external5.number().int().positive().optional(),
|
|
99922
|
-
totalLessons: exports_external5.number().int().positive().optional(),
|
|
99923
|
-
totalGrades: exports_external5.number().int().positive().optional()
|
|
99924
|
-
});
|
|
100024
|
+
totalXp: exports_external5.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
100025
|
+
totalLessons: exports_external5.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
100026
|
+
totalGrades: exports_external5.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
100027
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
99925
100028
|
var CourseMetadata5 = exports_external5.object({
|
|
99926
100029
|
courseType: CourseType5.optional(),
|
|
99927
|
-
isSupplemental: exports_external5.boolean().optional(),
|
|
99928
|
-
isCustom: exports_external5.boolean().optional(),
|
|
100030
|
+
isSupplemental: exports_external5.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
100031
|
+
isCustom: exports_external5.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
99929
100032
|
publishStatus: PublishStatus5.optional(),
|
|
99930
|
-
contactEmail: exports_external5.email().optional(),
|
|
99931
|
-
primaryApp: exports_external5.string().optional(),
|
|
100033
|
+
contactEmail: exports_external5.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
100034
|
+
primaryApp: exports_external5.string().meta({ description: "Primary application identifier" }).optional(),
|
|
99932
100035
|
goals: CourseGoals5.optional(),
|
|
99933
100036
|
metrics: CourseMetrics5.optional()
|
|
99934
|
-
});
|
|
100037
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
99935
100038
|
var CourseDefaults5 = exports_external5.object({
|
|
99936
|
-
courseCode: exports_external5.string().optional(),
|
|
99937
|
-
level: exports_external5.string().optional(),
|
|
100039
|
+
courseCode: exports_external5.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
100040
|
+
level: exports_external5.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
99938
100041
|
metadata: CourseMetadata5.optional()
|
|
100042
|
+
}).meta({
|
|
100043
|
+
id: "CourseDefaults",
|
|
100044
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
99939
100045
|
});
|
|
99940
100046
|
var CourseEnvOverrides5 = exports_external5.object({
|
|
99941
|
-
level: exports_external5.string().optional(),
|
|
99942
|
-
sensor: exports_external5.
|
|
99943
|
-
launchUrl: exports_external5.
|
|
100047
|
+
level: exports_external5.string().meta({ description: "Course level for this environment" }).optional(),
|
|
100048
|
+
sensor: exports_external5.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
100049
|
+
launchUrl: exports_external5.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
99944
100050
|
metadata: CourseMetadata5.optional()
|
|
100051
|
+
}).meta({
|
|
100052
|
+
id: "CourseEnvOverrides",
|
|
100053
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
99945
100054
|
});
|
|
99946
100055
|
var CourseOverrides5 = exports_external5.object({
|
|
99947
|
-
staging: CourseEnvOverrides5.
|
|
99948
|
-
|
|
99949
|
-
})
|
|
100056
|
+
staging: CourseEnvOverrides5.meta({
|
|
100057
|
+
description: "Overrides for staging environment"
|
|
100058
|
+
}).optional(),
|
|
100059
|
+
production: CourseEnvOverrides5.meta({
|
|
100060
|
+
description: "Overrides for production environment"
|
|
100061
|
+
}).optional()
|
|
100062
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
99950
100063
|
var CourseConfig5 = CourseDefaults5.extend({
|
|
99951
|
-
subject: TimebackSubject5,
|
|
99952
|
-
grade: TimebackGrade5.
|
|
100064
|
+
subject: TimebackSubject5.meta({ description: "Subject area for this course" }),
|
|
100065
|
+
grade: TimebackGrade5.meta({
|
|
100066
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
100067
|
+
}).optional(),
|
|
99953
100068
|
ids: CourseIds5.nullable().optional(),
|
|
99954
|
-
sensor: exports_external5.
|
|
99955
|
-
launchUrl: exports_external5.
|
|
100069
|
+
sensor: exports_external5.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
100070
|
+
launchUrl: exports_external5.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
99956
100071
|
overrides: CourseOverrides5.optional()
|
|
100072
|
+
}).meta({
|
|
100073
|
+
id: "CourseConfig",
|
|
100074
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
99957
100075
|
});
|
|
99958
100076
|
var TimebackConfig5 = exports_external5.object({
|
|
99959
|
-
|
|
99960
|
-
|
|
99961
|
-
|
|
99962
|
-
|
|
99963
|
-
|
|
100077
|
+
$schema: exports_external5.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
100078
|
+
name: exports_external5.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
100079
|
+
defaults: CourseDefaults5.meta({
|
|
100080
|
+
description: "Default properties applied to all courses"
|
|
100081
|
+
}).optional(),
|
|
100082
|
+
courses: exports_external5.array(CourseConfig5).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
100083
|
+
sensor: exports_external5.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
100084
|
+
launchUrl: exports_external5.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
100085
|
+
}).meta({
|
|
100086
|
+
id: "TimebackConfig",
|
|
100087
|
+
title: "Timeback Config",
|
|
100088
|
+
description: "Configuration schema for timeback.config.json files"
|
|
99964
100089
|
}).refine((config222) => {
|
|
99965
100090
|
return config222.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
99966
100091
|
}, {
|
|
@@ -101840,8 +101965,8 @@ var outro = {
|
|
|
101840
101965
|
};
|
|
101841
101966
|
// ../internal/cli-infra/src/config/timeback.ts
|
|
101842
101967
|
import { existsSync } from "node:fs";
|
|
101843
|
-
import { basename, relative, resolve } from "node:path";
|
|
101844
|
-
import {
|
|
101968
|
+
import { basename, extname, relative, resolve } from "node:path";
|
|
101969
|
+
import { loadConfig as c12LoadConfig } from "c12";
|
|
101845
101970
|
// ../types/src/zod/primitives.ts
|
|
101846
101971
|
var IsoDateTimeRegex6 = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
101847
101972
|
var IsoDateTimeString6 = exports_external.string().min(1).regex(IsoDateTimeRegex6, "must be a valid ISO 8601 datetime");
|
|
@@ -101857,7 +101982,7 @@ var TimebackSubject6 = exports_external.enum([
|
|
|
101857
101982
|
"Math",
|
|
101858
101983
|
"None",
|
|
101859
101984
|
"Other"
|
|
101860
|
-
]);
|
|
101985
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
101861
101986
|
var TimebackGrade6 = exports_external.union([
|
|
101862
101987
|
exports_external.literal(-1),
|
|
101863
101988
|
exports_external.literal(0),
|
|
@@ -101874,7 +101999,10 @@ var TimebackGrade6 = exports_external.union([
|
|
|
101874
101999
|
exports_external.literal(11),
|
|
101875
102000
|
exports_external.literal(12),
|
|
101876
102001
|
exports_external.literal(13)
|
|
101877
|
-
])
|
|
102002
|
+
]).meta({
|
|
102003
|
+
id: "TimebackGrade",
|
|
102004
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
102005
|
+
});
|
|
101878
102006
|
var ScoreStatus6 = exports_external.enum([
|
|
101879
102007
|
"exempt",
|
|
101880
102008
|
"fully graded",
|
|
@@ -102106,62 +102234,84 @@ var CaliperListEventsParams6 = exports_external.object({
|
|
|
102106
102234
|
}).strict();
|
|
102107
102235
|
// ../types/src/zod/config.ts
|
|
102108
102236
|
var CourseIds6 = exports_external.object({
|
|
102109
|
-
staging: exports_external.string().optional(),
|
|
102110
|
-
production: exports_external.string().optional()
|
|
102111
|
-
});
|
|
102112
|
-
var CourseType6 = exports_external.enum(["base", "hole-filling", "optional"]);
|
|
102113
|
-
var PublishStatus6 = exports_external.enum(["draft", "testing", "published", "deactivated"]);
|
|
102237
|
+
staging: exports_external.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
102238
|
+
production: exports_external.string().meta({ description: "Course ID in production environment" }).optional()
|
|
102239
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
102240
|
+
var CourseType6 = exports_external.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
102241
|
+
var PublishStatus6 = exports_external.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
102114
102242
|
var CourseGoals6 = exports_external.object({
|
|
102115
|
-
dailyXp: exports_external.number().int().positive().optional(),
|
|
102116
|
-
dailyLessons: exports_external.number().int().positive().optional(),
|
|
102117
|
-
dailyActiveMinutes: exports_external.number().int().positive().optional(),
|
|
102118
|
-
dailyAccuracy: exports_external.number().int().min(0).max(100).optional(),
|
|
102119
|
-
dailyMasteredUnits: exports_external.number().int().positive().optional()
|
|
102120
|
-
});
|
|
102243
|
+
dailyXp: exports_external.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
102244
|
+
dailyLessons: exports_external.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
102245
|
+
dailyActiveMinutes: exports_external.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
102246
|
+
dailyAccuracy: exports_external.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
102247
|
+
dailyMasteredUnits: exports_external.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
102248
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
102121
102249
|
var CourseMetrics6 = exports_external.object({
|
|
102122
|
-
totalXp: exports_external.number().int().positive().optional(),
|
|
102123
|
-
totalLessons: exports_external.number().int().positive().optional(),
|
|
102124
|
-
totalGrades: exports_external.number().int().positive().optional()
|
|
102125
|
-
});
|
|
102250
|
+
totalXp: exports_external.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
102251
|
+
totalLessons: exports_external.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
102252
|
+
totalGrades: exports_external.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
102253
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
102126
102254
|
var CourseMetadata6 = exports_external.object({
|
|
102127
102255
|
courseType: CourseType6.optional(),
|
|
102128
|
-
isSupplemental: exports_external.boolean().optional(),
|
|
102129
|
-
isCustom: exports_external.boolean().optional(),
|
|
102256
|
+
isSupplemental: exports_external.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
102257
|
+
isCustom: exports_external.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
102130
102258
|
publishStatus: PublishStatus6.optional(),
|
|
102131
|
-
contactEmail: exports_external.email().optional(),
|
|
102132
|
-
primaryApp: exports_external.string().optional(),
|
|
102259
|
+
contactEmail: exports_external.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
102260
|
+
primaryApp: exports_external.string().meta({ description: "Primary application identifier" }).optional(),
|
|
102133
102261
|
goals: CourseGoals6.optional(),
|
|
102134
102262
|
metrics: CourseMetrics6.optional()
|
|
102135
|
-
});
|
|
102263
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
102136
102264
|
var CourseDefaults6 = exports_external.object({
|
|
102137
|
-
courseCode: exports_external.string().optional(),
|
|
102138
|
-
level: exports_external.string().optional(),
|
|
102265
|
+
courseCode: exports_external.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
102266
|
+
level: exports_external.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
102139
102267
|
metadata: CourseMetadata6.optional()
|
|
102268
|
+
}).meta({
|
|
102269
|
+
id: "CourseDefaults",
|
|
102270
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
102140
102271
|
});
|
|
102141
102272
|
var CourseEnvOverrides6 = exports_external.object({
|
|
102142
|
-
level: exports_external.string().optional(),
|
|
102143
|
-
sensor: exports_external.
|
|
102144
|
-
launchUrl: exports_external.
|
|
102273
|
+
level: exports_external.string().meta({ description: "Course level for this environment" }).optional(),
|
|
102274
|
+
sensor: exports_external.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
102275
|
+
launchUrl: exports_external.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
102145
102276
|
metadata: CourseMetadata6.optional()
|
|
102277
|
+
}).meta({
|
|
102278
|
+
id: "CourseEnvOverrides",
|
|
102279
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
102146
102280
|
});
|
|
102147
102281
|
var CourseOverrides6 = exports_external.object({
|
|
102148
|
-
staging: CourseEnvOverrides6.
|
|
102149
|
-
|
|
102150
|
-
})
|
|
102282
|
+
staging: CourseEnvOverrides6.meta({
|
|
102283
|
+
description: "Overrides for staging environment"
|
|
102284
|
+
}).optional(),
|
|
102285
|
+
production: CourseEnvOverrides6.meta({
|
|
102286
|
+
description: "Overrides for production environment"
|
|
102287
|
+
}).optional()
|
|
102288
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
102151
102289
|
var CourseConfig6 = CourseDefaults6.extend({
|
|
102152
|
-
subject: TimebackSubject6,
|
|
102153
|
-
grade: TimebackGrade6.
|
|
102290
|
+
subject: TimebackSubject6.meta({ description: "Subject area for this course" }),
|
|
102291
|
+
grade: TimebackGrade6.meta({
|
|
102292
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
102293
|
+
}).optional(),
|
|
102154
102294
|
ids: CourseIds6.nullable().optional(),
|
|
102155
|
-
sensor: exports_external.
|
|
102156
|
-
launchUrl: exports_external.
|
|
102295
|
+
sensor: exports_external.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
102296
|
+
launchUrl: exports_external.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
102157
102297
|
overrides: CourseOverrides6.optional()
|
|
102298
|
+
}).meta({
|
|
102299
|
+
id: "CourseConfig",
|
|
102300
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
102158
102301
|
});
|
|
102159
102302
|
var TimebackConfig6 = exports_external.object({
|
|
102160
|
-
|
|
102161
|
-
|
|
102162
|
-
|
|
102163
|
-
|
|
102164
|
-
|
|
102303
|
+
$schema: exports_external.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
102304
|
+
name: exports_external.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
102305
|
+
defaults: CourseDefaults6.meta({
|
|
102306
|
+
description: "Default properties applied to all courses"
|
|
102307
|
+
}).optional(),
|
|
102308
|
+
courses: exports_external.array(CourseConfig6).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
102309
|
+
sensor: exports_external.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
102310
|
+
launchUrl: exports_external.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
102311
|
+
}).meta({
|
|
102312
|
+
id: "TimebackConfig",
|
|
102313
|
+
title: "Timeback Config",
|
|
102314
|
+
description: "Configuration schema for timeback.config.json files"
|
|
102165
102315
|
}).refine((config6) => {
|
|
102166
102316
|
return config6.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
102167
102317
|
}, {
|
|
@@ -103178,94 +103328,88 @@ var QtiLessonFeedbackInput6 = exports_external.object({
|
|
|
103178
103328
|
humanApproved: exports_external.boolean().optional()
|
|
103179
103329
|
}).strict();
|
|
103180
103330
|
// ../internal/cli-infra/src/config/timeback.ts
|
|
103181
|
-
var
|
|
103182
|
-
|
|
103183
|
-
|
|
103184
|
-
|
|
103185
|
-
|
|
103186
|
-
|
|
103187
|
-
|
|
103188
|
-
|
|
103189
|
-
|
|
103190
|
-
|
|
103191
|
-
|
|
103192
|
-
|
|
103193
|
-
|
|
103194
|
-
|
|
103195
|
-
|
|
103196
|
-
|
|
103197
|
-
|
|
103198
|
-
|
|
103331
|
+
var CONFIG_FILENAME = "timeback.config.json";
|
|
103332
|
+
function isJsonConfigPath(configPath) {
|
|
103333
|
+
return extname(configPath).toLowerCase() === ".json";
|
|
103334
|
+
}
|
|
103335
|
+
async function loadWithC12(cwd, configPath) {
|
|
103336
|
+
if (configPath && !isJsonConfigPath(configPath)) {
|
|
103337
|
+
throw new Error(`Config file must be JSON (.json): ${configPath}`);
|
|
103338
|
+
}
|
|
103339
|
+
const result = await c12LoadConfig({
|
|
103340
|
+
cwd,
|
|
103341
|
+
name: "timeback",
|
|
103342
|
+
configFile: configPath ?? CONFIG_FILENAME,
|
|
103343
|
+
rcFile: false,
|
|
103344
|
+
packageJson: false,
|
|
103345
|
+
dotenv: false,
|
|
103346
|
+
envName: false,
|
|
103347
|
+
extend: false,
|
|
103348
|
+
omit$Keys: true,
|
|
103349
|
+
defaults: {},
|
|
103350
|
+
overrides: {}
|
|
103351
|
+
});
|
|
103352
|
+
if (!result.config || Object.keys(result.config).length === 0) {
|
|
103353
|
+
return null;
|
|
103199
103354
|
}
|
|
103200
|
-
|
|
103355
|
+
const rawConfig = result.config;
|
|
103356
|
+
if ("extends" in rawConfig) {
|
|
103357
|
+
throw new Error("The 'extends' feature is not supported in timeback.config.json. " + "Please inline all configuration.");
|
|
103358
|
+
}
|
|
103359
|
+
const { $schema: _schema, ...configWithoutSchema } = rawConfig;
|
|
103360
|
+
return {
|
|
103361
|
+
config: configWithoutSchema,
|
|
103362
|
+
configFile: result.configFile ?? resolve(cwd, configPath ?? CONFIG_FILENAME)
|
|
103363
|
+
};
|
|
103201
103364
|
}
|
|
103202
103365
|
async function loadConfig(opts = {}) {
|
|
103203
103366
|
const cwd = process.cwd();
|
|
103204
|
-
|
|
103205
|
-
|
|
103206
|
-
let loadError = null;
|
|
103207
|
-
if (opts.configPath) {
|
|
103208
|
-
const fullPath = resolve(cwd, opts.configPath);
|
|
103209
|
-
if (!existsSync(fullPath)) {
|
|
103367
|
+
try {
|
|
103368
|
+
if (opts.configPath && !isJsonConfigPath(opts.configPath)) {
|
|
103210
103369
|
return {
|
|
103211
103370
|
success: false,
|
|
103212
|
-
error: `Config file
|
|
103371
|
+
error: `Config file must be JSON (.json): ${opts.configPath}`
|
|
103213
103372
|
};
|
|
103214
103373
|
}
|
|
103215
|
-
|
|
103216
|
-
|
|
103217
|
-
|
|
103218
|
-
|
|
103374
|
+
if (opts.configPath) {
|
|
103375
|
+
const fullPath = resolve(cwd, opts.configPath);
|
|
103376
|
+
if (!existsSync(fullPath)) {
|
|
103377
|
+
return {
|
|
103378
|
+
success: false,
|
|
103379
|
+
error: `Config file not found: ${opts.configPath}`
|
|
103380
|
+
};
|
|
103381
|
+
}
|
|
103382
|
+
}
|
|
103383
|
+
const loaded = await loadWithC12(cwd, opts.configPath);
|
|
103384
|
+
if (!loaded) {
|
|
103219
103385
|
return {
|
|
103220
103386
|
success: false,
|
|
103221
|
-
error: `
|
|
103222
|
-
${err instanceof Error ? err.message : String(err)}`
|
|
103387
|
+
error: `No timeback config found. Run ${greenBright("timeback init")} to create one.`
|
|
103223
103388
|
};
|
|
103224
103389
|
}
|
|
103225
|
-
|
|
103226
|
-
|
|
103227
|
-
const
|
|
103228
|
-
|
|
103229
|
-
|
|
103230
|
-
|
|
103231
|
-
|
|
103232
|
-
|
|
103233
|
-
|
|
103234
|
-
} catch (err) {
|
|
103235
|
-
loadError = err instanceof Error ? err : new Error(String(err));
|
|
103236
|
-
foundPath = fullPath;
|
|
103237
|
-
break;
|
|
103238
|
-
}
|
|
103390
|
+
const result = TimebackConfig6.safeParse(loaded.config);
|
|
103391
|
+
if (!result.success) {
|
|
103392
|
+
const issues = result.error.issues.map((issue4) => ` - ${issue4.path.join(".")}: ${issue4.message}`).join(`
|
|
103393
|
+
`);
|
|
103394
|
+
return {
|
|
103395
|
+
success: false,
|
|
103396
|
+
error: `Invalid config in ${basename(loaded.configFile)}:
|
|
103397
|
+
${issues}`
|
|
103398
|
+
};
|
|
103239
103399
|
}
|
|
103240
|
-
}
|
|
103241
|
-
if (loadError && foundPath) {
|
|
103242
103400
|
return {
|
|
103243
|
-
success:
|
|
103244
|
-
|
|
103245
|
-
|
|
103246
|
-
};
|
|
103247
|
-
}
|
|
103248
|
-
if (!rawConfig || !foundPath) {
|
|
103249
|
-
return {
|
|
103250
|
-
success: false,
|
|
103251
|
-
error: `No timeback config found. Run ${greenBright("timeback init")} to create one.`
|
|
103401
|
+
success: true,
|
|
103402
|
+
config: result.data,
|
|
103403
|
+
configPath: loaded.configFile
|
|
103252
103404
|
};
|
|
103253
|
-
}
|
|
103254
|
-
|
|
103255
|
-
if (!result.success) {
|
|
103256
|
-
const issues = result.error.issues.map((issue4) => ` - ${issue4.path.join(".")}: ${issue4.message}`).join(`
|
|
103257
|
-
`);
|
|
103405
|
+
} catch (err) {
|
|
103406
|
+
const filename = opts.configPath ? basename(opts.configPath) : CONFIG_FILENAME;
|
|
103258
103407
|
return {
|
|
103259
103408
|
success: false,
|
|
103260
|
-
error: `
|
|
103261
|
-
${
|
|
103409
|
+
error: `Failed to load ${filename}:
|
|
103410
|
+
${err instanceof Error ? err.message : String(err)}`
|
|
103262
103411
|
};
|
|
103263
103412
|
}
|
|
103264
|
-
return {
|
|
103265
|
-
success: true,
|
|
103266
|
-
config: result.data,
|
|
103267
|
-
configPath: foundPath
|
|
103268
|
-
};
|
|
103269
103413
|
}
|
|
103270
103414
|
function getRelativeConfigPath(configPath) {
|
|
103271
103415
|
return relative(process.cwd(), configPath);
|
|
@@ -103530,42 +103674,9 @@ async function promptLaunchUrl() {
|
|
|
103530
103674
|
}
|
|
103531
103675
|
return input.trim();
|
|
103532
103676
|
}
|
|
103533
|
-
// ../internal/cli-infra/src/project/package-
|
|
103677
|
+
// ../internal/cli-infra/src/project/package-manager.ts
|
|
103534
103678
|
import { existsSync as existsSync2 } from "node:fs";
|
|
103535
|
-
import { readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
103536
103679
|
import { resolve as resolve2 } from "node:path";
|
|
103537
|
-
function hasWorkspaceSpec(record6) {
|
|
103538
|
-
if (!record6)
|
|
103539
|
-
return false;
|
|
103540
|
-
return Object.values(record6).some((v2) => v2.startsWith("workspace:"));
|
|
103541
|
-
}
|
|
103542
|
-
function isWorkspaceProject(pkg) {
|
|
103543
|
-
if (!pkg || typeof pkg !== "object")
|
|
103544
|
-
return false;
|
|
103545
|
-
const maybePkg = pkg;
|
|
103546
|
-
return !!maybePkg.workspaces || hasWorkspaceSpec(maybePkg.dependencies) || hasWorkspaceSpec(maybePkg.devDependencies) || hasWorkspaceSpec(maybePkg.peerDependencies);
|
|
103547
|
-
}
|
|
103548
|
-
async function ensureDependency(options) {
|
|
103549
|
-
const { cwd = process.cwd(), packageName, section, version: version6 } = options;
|
|
103550
|
-
const packageJsonPath = resolve2(cwd, "package.json");
|
|
103551
|
-
if (!existsSync2(packageJsonPath)) {
|
|
103552
|
-
return { updated: false, reason: "no_package_json" };
|
|
103553
|
-
}
|
|
103554
|
-
const raw = await readFile2(packageJsonPath, "utf-8");
|
|
103555
|
-
const pkg = JSON.parse(raw);
|
|
103556
|
-
if (pkg.dependencies?.[packageName] || pkg.devDependencies?.[packageName]) {
|
|
103557
|
-
return { updated: false, reason: "already_present" };
|
|
103558
|
-
}
|
|
103559
|
-
const chosen = version6 ?? (isWorkspaceProject(pkg) ? "workspace:*" : "*");
|
|
103560
|
-
pkg[section] ??= {};
|
|
103561
|
-
pkg[section][packageName] = chosen;
|
|
103562
|
-
await writeFile2(packageJsonPath, JSON.stringify(pkg, null, 2) + `
|
|
103563
|
-
`, "utf-8");
|
|
103564
|
-
return { updated: true, reason: "updated", version: chosen };
|
|
103565
|
-
}
|
|
103566
|
-
// ../internal/cli-infra/src/project/package-manager.ts
|
|
103567
|
-
import { existsSync as existsSync3 } from "node:fs";
|
|
103568
|
-
import { resolve as resolve3 } from "node:path";
|
|
103569
103680
|
function detectPackageManager(cwd) {
|
|
103570
103681
|
const candidates = [
|
|
103571
103682
|
{ pm: "bun", file: "bun.lockb" },
|
|
@@ -103575,25 +103686,12 @@ function detectPackageManager(cwd) {
|
|
|
103575
103686
|
{ pm: "npm", file: "package-lock.json" }
|
|
103576
103687
|
];
|
|
103577
103688
|
for (const { pm, file: file6 } of candidates) {
|
|
103578
|
-
if (
|
|
103689
|
+
if (existsSync2(resolve2(cwd, file6))) {
|
|
103579
103690
|
return { packageManager: pm, reason: "lockfile", lockfile: file6 };
|
|
103580
103691
|
}
|
|
103581
103692
|
}
|
|
103582
103693
|
return { packageManager: "npm", reason: "default" };
|
|
103583
103694
|
}
|
|
103584
|
-
function getInstallCommand(pm) {
|
|
103585
|
-
switch (pm) {
|
|
103586
|
-
case "bun":
|
|
103587
|
-
return { cmd: "bun", args: ["install"] };
|
|
103588
|
-
case "pnpm":
|
|
103589
|
-
return { cmd: "pnpm", args: ["install"] };
|
|
103590
|
-
case "yarn":
|
|
103591
|
-
return { cmd: "yarn", args: ["install"] };
|
|
103592
|
-
case "npm":
|
|
103593
|
-
default:
|
|
103594
|
-
return { cmd: "npm", args: ["install"] };
|
|
103595
|
-
}
|
|
103596
|
-
}
|
|
103597
103695
|
function getDlxCommand(pm, tool) {
|
|
103598
103696
|
switch (pm) {
|
|
103599
103697
|
case "bun":
|
|
@@ -103674,7 +103772,7 @@ function getAuthContext(env2) {
|
|
|
103674
103772
|
};
|
|
103675
103773
|
}
|
|
103676
103774
|
// src/lib/common.ts
|
|
103677
|
-
import { readFile as
|
|
103775
|
+
import { readFile as readFile2 } from "node:fs/promises";
|
|
103678
103776
|
|
|
103679
103777
|
// ../internal/constants/src/endpoints.ts
|
|
103680
103778
|
var DEFAULT_PLATFORM7 = "BEYOND_AI";
|
|
@@ -104460,7 +104558,7 @@ async function parseInputData(opts) {
|
|
|
104460
104558
|
}
|
|
104461
104559
|
if (opts.file) {
|
|
104462
104560
|
try {
|
|
104463
|
-
const content = await
|
|
104561
|
+
const content = await readFile2(opts.file, "utf-8");
|
|
104464
104562
|
const parsed = JSON.parse(content);
|
|
104465
104563
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
104466
104564
|
throw new Error(`File ${opts.file} must contain a JSON object, not an array or primitive`);
|
|
@@ -104532,32 +104630,10 @@ function getSyncedCourses(course) {
|
|
|
104532
104630
|
return [];
|
|
104533
104631
|
return Object.keys(course.ids).filter((env2) => course.ids?.[env2]).map((env2) => ({ env: env2, courseId: course.ids[env2] }));
|
|
104534
104632
|
}
|
|
104535
|
-
// src/lib/config/dependencies.ts
|
|
104536
|
-
async function ensureSdkDependency(options) {
|
|
104537
|
-
const result = await ensureDependency({
|
|
104538
|
-
cwd: options.cwd,
|
|
104539
|
-
packageName: "@timeback/sdk",
|
|
104540
|
-
section: "dependencies"
|
|
104541
|
-
});
|
|
104542
|
-
if (result.reason === "updated") {
|
|
104543
|
-
options.logger.success(`Added @timeback/sdk@${result.version} to package.json`);
|
|
104544
|
-
return { updated: true, reason: "updated" };
|
|
104545
|
-
}
|
|
104546
|
-
if (result.reason === "no_package_json") {
|
|
104547
|
-
options.logger.warn(`No package.json found`);
|
|
104548
|
-
return { updated: false, reason: "no_package_json" };
|
|
104549
|
-
}
|
|
104550
|
-
return { updated: false, reason: "already_present" };
|
|
104551
|
-
}
|
|
104552
104633
|
// src/lib/config/project.ts
|
|
104553
104634
|
import { spawn } from "node:child_process";
|
|
104554
|
-
import { existsSync as
|
|
104555
|
-
import { resolve as
|
|
104556
|
-
function isPackageInstalled(options) {
|
|
104557
|
-
const { cwd, packageName } = options;
|
|
104558
|
-
const parts = packageName.split("/");
|
|
104559
|
-
return existsSync4(resolve4(cwd, "node_modules", ...parts, "package.json"));
|
|
104560
|
-
}
|
|
104635
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
104636
|
+
import { resolve as resolve3 } from "node:path";
|
|
104561
104637
|
function run(cmd, args, cwd, silent = false) {
|
|
104562
104638
|
return new Promise((resolvePromise) => {
|
|
104563
104639
|
const child = spawn(cmd, args, {
|
|
@@ -104569,24 +104645,11 @@ function run(cmd, args, cwd, silent = false) {
|
|
|
104569
104645
|
child.on("error", () => resolvePromise(1));
|
|
104570
104646
|
});
|
|
104571
104647
|
}
|
|
104572
|
-
async function runInstall(options) {
|
|
104573
|
-
const { cwd, logger } = options;
|
|
104574
|
-
const { packageManager } = detectPackageManager(cwd);
|
|
104575
|
-
const { cmd, args } = getInstallCommand(packageManager);
|
|
104576
|
-
logger.info(`Running ${cmd} ${args.join(" ")}...`);
|
|
104577
|
-
const code = await run(cmd, args, cwd);
|
|
104578
|
-
if (code === 0) {
|
|
104579
|
-
logger.success("Dependencies installed");
|
|
104580
|
-
return true;
|
|
104581
|
-
}
|
|
104582
|
-
logger.warn(`Install failed (exit ${code}). You may need to run install manually.`);
|
|
104583
|
-
return false;
|
|
104584
|
-
}
|
|
104585
104648
|
async function formatWithPrettier(options) {
|
|
104586
104649
|
const { cwd, filePath, logger, silent = false } = options;
|
|
104587
|
-
const prettierBin =
|
|
104650
|
+
const prettierBin = resolve3(cwd, "node_modules", ".bin", process.platform === "win32" ? "prettier.cmd" : "prettier");
|
|
104588
104651
|
const args = ["--write", filePath];
|
|
104589
|
-
if (
|
|
104652
|
+
if (existsSync3(prettierBin)) {
|
|
104590
104653
|
if (!silent)
|
|
104591
104654
|
logger.info(`Formatting ${filePath} with prettier...`);
|
|
104592
104655
|
const code2 = await run(prettierBin, args, cwd, silent);
|
|
@@ -104608,186 +104671,186 @@ async function formatWithPrettier(options) {
|
|
|
104608
104671
|
return false;
|
|
104609
104672
|
}
|
|
104610
104673
|
// src/lib/config/generate.ts
|
|
104611
|
-
|
|
104612
|
-
|
|
104613
|
-
|
|
104614
|
-
|
|
104615
|
-
|
|
104616
|
-
|
|
104617
|
-
|
|
104618
|
-
|
|
104619
|
-
|
|
104620
|
-
|
|
104621
|
-
|
|
104674
|
+
var SCHEMA_URL = "https://timeback.dev/schema.json";
|
|
104675
|
+
var TOP_LEVEL_KEY_ORDER = ["$schema", "name", "launchUrl", "sensor", "defaults", "courses"];
|
|
104676
|
+
var COURSE_KEY_ORDER = [
|
|
104677
|
+
"subject",
|
|
104678
|
+
"grade",
|
|
104679
|
+
"courseCode",
|
|
104680
|
+
"level",
|
|
104681
|
+
"sensor",
|
|
104682
|
+
"launchUrl",
|
|
104683
|
+
"ids",
|
|
104684
|
+
"metadata",
|
|
104685
|
+
"overrides"
|
|
104686
|
+
];
|
|
104687
|
+
var IDS_KEY_ORDER = ["staging", "production"];
|
|
104688
|
+
var METADATA_KEY_ORDER = [
|
|
104689
|
+
"courseType",
|
|
104690
|
+
"isSupplemental",
|
|
104691
|
+
"isCustom",
|
|
104692
|
+
"publishStatus",
|
|
104693
|
+
"contactEmail",
|
|
104694
|
+
"primaryApp",
|
|
104695
|
+
"goals",
|
|
104696
|
+
"metrics"
|
|
104697
|
+
];
|
|
104698
|
+
var DEFAULTS_KEY_ORDER = ["courseCode", "level", "metadata"];
|
|
104699
|
+
var OVERRIDES_KEY_ORDER = ["staging", "production"];
|
|
104700
|
+
var ENV_OVERRIDES_KEY_ORDER = ["level", "sensor", "launchUrl", "metadata"];
|
|
104701
|
+
function orderKeys(obj, keyOrder) {
|
|
104702
|
+
const result = {};
|
|
104703
|
+
const objKeys = Object.keys(obj);
|
|
104704
|
+
const source = obj;
|
|
104705
|
+
for (const key of keyOrder) {
|
|
104706
|
+
if (key in source && source[key] !== undefined) {
|
|
104707
|
+
result[key] = source[key];
|
|
104708
|
+
}
|
|
104622
104709
|
}
|
|
104623
|
-
|
|
104624
|
-
|
|
104625
|
-
|
|
104626
|
-
|
|
104627
|
-
const inner = entries.map(([k3, v2]) => `${k3}: ${formatValue6(v2)}`).join(", ");
|
|
104628
|
-
return `{ ${inner} }`;
|
|
104710
|
+
for (const key of objKeys) {
|
|
104711
|
+
if (!(key in result) && source[key] !== undefined) {
|
|
104712
|
+
result[key] = source[key];
|
|
104713
|
+
}
|
|
104629
104714
|
}
|
|
104630
|
-
return
|
|
104715
|
+
return result;
|
|
104716
|
+
}
|
|
104717
|
+
function filterUndefined(obj) {
|
|
104718
|
+
const result = {};
|
|
104719
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
104720
|
+
if (value !== undefined) {
|
|
104721
|
+
result[key] = value;
|
|
104722
|
+
}
|
|
104723
|
+
}
|
|
104724
|
+
return result;
|
|
104631
104725
|
}
|
|
104632
104726
|
function formatCourseIds(ids) {
|
|
104633
104727
|
if (!ids)
|
|
104634
|
-
return
|
|
104635
|
-
const
|
|
104636
|
-
if (
|
|
104637
|
-
return
|
|
104638
|
-
|
|
104639
|
-
return `{ ${inner} }`;
|
|
104728
|
+
return;
|
|
104729
|
+
const filtered = filterUndefined(ids);
|
|
104730
|
+
if (Object.keys(filtered).length === 0)
|
|
104731
|
+
return;
|
|
104732
|
+
return orderKeys(filtered, IDS_KEY_ORDER);
|
|
104640
104733
|
}
|
|
104641
|
-
function formatMetadata(metadata
|
|
104734
|
+
function formatMetadata(metadata) {
|
|
104642
104735
|
if (!metadata)
|
|
104643
|
-
return
|
|
104644
|
-
const
|
|
104645
|
-
if (
|
|
104646
|
-
return
|
|
104647
|
-
|
|
104648
|
-
if (metadata.courseType)
|
|
104649
|
-
parts.push(`courseType: '${metadata.courseType}'`);
|
|
104650
|
-
if (metadata.isSupplemental !== undefined)
|
|
104651
|
-
parts.push(`isSupplemental: ${metadata.isSupplemental}`);
|
|
104652
|
-
if (metadata.isCustom !== undefined)
|
|
104653
|
-
parts.push(`isCustom: ${metadata.isCustom}`);
|
|
104654
|
-
if (metadata.publishStatus)
|
|
104655
|
-
parts.push(`publishStatus: '${metadata.publishStatus}'`);
|
|
104656
|
-
if (metadata.contactEmail)
|
|
104657
|
-
parts.push(`contactEmail: '${metadata.contactEmail}'`);
|
|
104658
|
-
if (metadata.primaryApp)
|
|
104659
|
-
parts.push(`primaryApp: '${metadata.primaryApp}'`);
|
|
104660
|
-
if (metadata.goals)
|
|
104661
|
-
parts.push(`goals: ${formatValue6(metadata.goals)}`);
|
|
104662
|
-
if (metadata.metrics)
|
|
104663
|
-
parts.push(`metrics: ${formatValue6(metadata.metrics)}`);
|
|
104664
|
-
if (parts.length === 0)
|
|
104665
|
-
return null;
|
|
104666
|
-
return `{
|
|
104667
|
-
${indent} ${parts.join(`,
|
|
104668
|
-
${indent} `)},
|
|
104669
|
-
${indent}}`;
|
|
104736
|
+
return;
|
|
104737
|
+
const filtered = filterUndefined(metadata);
|
|
104738
|
+
if (Object.keys(filtered).length === 0)
|
|
104739
|
+
return;
|
|
104740
|
+
return orderKeys(filtered, METADATA_KEY_ORDER);
|
|
104670
104741
|
}
|
|
104671
104742
|
function formatDefaults(defaults) {
|
|
104672
104743
|
if (!defaults)
|
|
104673
|
-
return
|
|
104674
|
-
const
|
|
104675
|
-
if (entries.length === 0)
|
|
104676
|
-
return null;
|
|
104677
|
-
const parts = [];
|
|
104744
|
+
return;
|
|
104745
|
+
const result = {};
|
|
104678
104746
|
if (defaults.courseCode)
|
|
104679
|
-
|
|
104747
|
+
result.courseCode = defaults.courseCode;
|
|
104680
104748
|
if (defaults.level)
|
|
104681
|
-
|
|
104682
|
-
|
|
104683
|
-
|
|
104684
|
-
|
|
104685
|
-
|
|
104686
|
-
|
|
104687
|
-
|
|
104688
|
-
|
|
104689
|
-
|
|
104690
|
-
}`;
|
|
104749
|
+
result.level = defaults.level;
|
|
104750
|
+
if (defaults.metadata) {
|
|
104751
|
+
const meta4 = formatMetadata(defaults.metadata);
|
|
104752
|
+
if (meta4)
|
|
104753
|
+
result.metadata = meta4;
|
|
104754
|
+
}
|
|
104755
|
+
if (Object.keys(result).length === 0)
|
|
104756
|
+
return;
|
|
104757
|
+
return orderKeys(result, DEFAULTS_KEY_ORDER);
|
|
104691
104758
|
}
|
|
104692
|
-
function formatEnvOverrides(overrides
|
|
104759
|
+
function formatEnvOverrides(overrides) {
|
|
104693
104760
|
if (!overrides)
|
|
104694
|
-
return
|
|
104695
|
-
const
|
|
104696
|
-
if (entries.length === 0)
|
|
104697
|
-
return null;
|
|
104698
|
-
const parts = [];
|
|
104761
|
+
return;
|
|
104762
|
+
const result = {};
|
|
104699
104763
|
if (overrides.level)
|
|
104700
|
-
|
|
104764
|
+
result.level = overrides.level;
|
|
104701
104765
|
if (overrides.sensor)
|
|
104702
|
-
|
|
104766
|
+
result.sensor = overrides.sensor;
|
|
104703
104767
|
if (overrides.launchUrl)
|
|
104704
|
-
|
|
104705
|
-
|
|
104706
|
-
|
|
104707
|
-
|
|
104708
|
-
|
|
104709
|
-
|
|
104710
|
-
|
|
104711
|
-
|
|
104712
|
-
|
|
104713
|
-
${indent}}`;
|
|
104768
|
+
result.launchUrl = overrides.launchUrl;
|
|
104769
|
+
if (overrides.metadata) {
|
|
104770
|
+
const meta4 = formatMetadata(overrides.metadata);
|
|
104771
|
+
if (meta4)
|
|
104772
|
+
result.metadata = meta4;
|
|
104773
|
+
}
|
|
104774
|
+
if (Object.keys(result).length === 0)
|
|
104775
|
+
return;
|
|
104776
|
+
return orderKeys(result, ENV_OVERRIDES_KEY_ORDER);
|
|
104714
104777
|
}
|
|
104715
|
-
function formatOverrides(overrides
|
|
104778
|
+
function formatOverrides(overrides) {
|
|
104716
104779
|
if (!overrides)
|
|
104717
|
-
return
|
|
104718
|
-
const
|
|
104719
|
-
|
|
104720
|
-
|
|
104721
|
-
|
|
104722
|
-
|
|
104723
|
-
|
|
104724
|
-
|
|
104725
|
-
|
|
104726
|
-
|
|
104727
|
-
|
|
104728
|
-
|
|
104729
|
-
|
|
104730
|
-
|
|
104780
|
+
return;
|
|
104781
|
+
const result = {};
|
|
104782
|
+
if (overrides.staging) {
|
|
104783
|
+
const staging = formatEnvOverrides(overrides.staging);
|
|
104784
|
+
if (staging)
|
|
104785
|
+
result.staging = staging;
|
|
104786
|
+
}
|
|
104787
|
+
if (overrides.production) {
|
|
104788
|
+
const production = formatEnvOverrides(overrides.production);
|
|
104789
|
+
if (production)
|
|
104790
|
+
result.production = production;
|
|
104791
|
+
}
|
|
104792
|
+
if (Object.keys(result).length === 0)
|
|
104793
|
+
return;
|
|
104794
|
+
return orderKeys(result, OVERRIDES_KEY_ORDER);
|
|
104731
104795
|
}
|
|
104732
|
-
function formatCourse(
|
|
104733
|
-
const
|
|
104734
|
-
|
|
104735
|
-
|
|
104796
|
+
function formatCourse(course) {
|
|
104797
|
+
const result = {
|
|
104798
|
+
subject: course.subject
|
|
104799
|
+
};
|
|
104800
|
+
if (course.grade !== undefined) {
|
|
104801
|
+
result.grade = course.grade;
|
|
104802
|
+
}
|
|
104803
|
+
if (course.courseCode) {
|
|
104804
|
+
result.courseCode = course.courseCode;
|
|
104805
|
+
}
|
|
104806
|
+
if (course.level) {
|
|
104807
|
+
result.level = course.level;
|
|
104736
104808
|
}
|
|
104737
|
-
if (
|
|
104738
|
-
|
|
104809
|
+
if (course.sensor) {
|
|
104810
|
+
result.sensor = course.sensor;
|
|
104739
104811
|
}
|
|
104740
|
-
if (
|
|
104741
|
-
|
|
104742
|
-
if (c.sensor) {
|
|
104743
|
-
parts.push(`sensor: '${c.sensor}'`);
|
|
104812
|
+
if (course.launchUrl) {
|
|
104813
|
+
result.launchUrl = course.launchUrl;
|
|
104744
104814
|
}
|
|
104745
|
-
|
|
104746
|
-
|
|
104815
|
+
const ids = formatCourseIds(course.ids);
|
|
104816
|
+
if (ids) {
|
|
104817
|
+
result.ids = ids;
|
|
104747
104818
|
}
|
|
104748
|
-
const
|
|
104749
|
-
if (
|
|
104750
|
-
|
|
104819
|
+
const metadata = formatMetadata(course.metadata);
|
|
104820
|
+
if (metadata) {
|
|
104821
|
+
result.metadata = metadata;
|
|
104751
104822
|
}
|
|
104752
|
-
const
|
|
104753
|
-
if (
|
|
104754
|
-
|
|
104823
|
+
const overrides = formatOverrides(course.overrides);
|
|
104824
|
+
if (overrides) {
|
|
104825
|
+
result.overrides = overrides;
|
|
104755
104826
|
}
|
|
104756
|
-
return
|
|
104757
|
-
${parts.join(`,
|
|
104758
|
-
`)},
|
|
104759
|
-
}`;
|
|
104827
|
+
return orderKeys(result, COURSE_KEY_ORDER);
|
|
104760
104828
|
}
|
|
104761
104829
|
function generateConfigContent(config7) {
|
|
104762
|
-
const
|
|
104763
|
-
|
|
104764
|
-
|
|
104765
|
-
|
|
104830
|
+
const output2 = {
|
|
104831
|
+
$schema: SCHEMA_URL,
|
|
104832
|
+
name: config7.name
|
|
104833
|
+
};
|
|
104766
104834
|
if (config7.launchUrl) {
|
|
104767
|
-
|
|
104835
|
+
output2.launchUrl = config7.launchUrl;
|
|
104768
104836
|
}
|
|
104769
104837
|
if (config7.sensor) {
|
|
104770
|
-
|
|
104838
|
+
output2.sensor = config7.sensor;
|
|
104771
104839
|
}
|
|
104772
|
-
|
|
104773
|
-
|
|
104840
|
+
const defaults = formatDefaults(config7.defaults);
|
|
104841
|
+
if (defaults) {
|
|
104842
|
+
output2.defaults = defaults;
|
|
104774
104843
|
}
|
|
104775
|
-
|
|
104776
|
-
|
|
104777
|
-
|
|
104778
|
-
return `import type { TimebackConfig } from '@timeback/sdk/config'
|
|
104779
|
-
|
|
104780
|
-
export default {
|
|
104781
|
-
${parts.join(`,
|
|
104782
|
-
`)},
|
|
104783
|
-
} satisfies TimebackConfig
|
|
104844
|
+
output2.courses = config7.courses.map(formatCourse);
|
|
104845
|
+
const ordered = orderKeys(output2, TOP_LEVEL_KEY_ORDER);
|
|
104846
|
+
return JSON.stringify(ordered, null, 2) + `
|
|
104784
104847
|
`;
|
|
104785
104848
|
}
|
|
104786
104849
|
// src/lib/config/loader.ts
|
|
104787
|
-
import { writeFile as
|
|
104850
|
+
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
104788
104851
|
async function saveConfig(configPath, config7) {
|
|
104789
104852
|
const content = generateConfigContent(config7);
|
|
104790
|
-
await
|
|
104853
|
+
await writeFile2(configPath, content, "utf-8");
|
|
104791
104854
|
}
|
|
104792
104855
|
// src/lib/compare.ts
|
|
104793
104856
|
function compareValues(local, remote, path, changes, options = {}) {
|
|
@@ -105234,9 +105297,9 @@ async function searchAndSelectCourses2(options) {
|
|
|
105234
105297
|
}
|
|
105235
105298
|
}
|
|
105236
105299
|
// src/lib/setup/setup.ts
|
|
105237
|
-
import { writeFile as
|
|
105238
|
-
import { resolve as
|
|
105239
|
-
var
|
|
105300
|
+
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
105301
|
+
import { resolve as resolve4 } from "node:path";
|
|
105302
|
+
var CONFIG_FILENAME2 = "timeback.config.json";
|
|
105240
105303
|
async function promptEnvironmentToSetup() {
|
|
105241
105304
|
const env2 = await ve({
|
|
105242
105305
|
message: "Which environment would you like to configure?",
|
|
@@ -105265,22 +105328,22 @@ You need to configure your Timeback API credentials first.`, "Credentials Setup"
|
|
|
105265
105328
|
return true;
|
|
105266
105329
|
}
|
|
105267
105330
|
async function ensureConfig(opts = {}) {
|
|
105268
|
-
const { configPath: customPath, skipIntro = false,
|
|
105331
|
+
const { configPath: customPath, skipIntro = false, format = true } = opts;
|
|
105269
105332
|
if (!skipIntro) {
|
|
105270
105333
|
intro("Timeback");
|
|
105271
105334
|
}
|
|
105272
105335
|
const cwd = process.cwd();
|
|
105273
|
-
const configPath = customPath ?
|
|
105336
|
+
const configPath = customPath ? resolve4(cwd, customPath) : resolve4(cwd, CONFIG_FILENAME2);
|
|
105274
105337
|
const configResult = await loadConfig({ configPath: customPath });
|
|
105275
105338
|
if (configResult.success) {
|
|
105276
|
-
M2.info(`Found ${dim(
|
|
105339
|
+
M2.info(`Found ${dim(CONFIG_FILENAME2)}`);
|
|
105277
105340
|
return {
|
|
105278
105341
|
success: true,
|
|
105279
105342
|
config: configResult.config,
|
|
105280
105343
|
configPath: configResult.configPath
|
|
105281
105344
|
};
|
|
105282
105345
|
}
|
|
105283
|
-
Me(`No ${greenBright(
|
|
105346
|
+
Me(`No ${greenBright(CONFIG_FILENAME2)} found in this directory.
|
|
105284
105347
|
Let's set up your Timeback project.`, "First-time setup");
|
|
105285
105348
|
let configuredEnvs = await getConfiguredEnvironments();
|
|
105286
105349
|
if (configuredEnvs.length === 0) {
|
|
@@ -105311,12 +105374,8 @@ Let's set up your Timeback project.`, "First-time setup");
|
|
|
105311
105374
|
courses: searchResult.courses
|
|
105312
105375
|
};
|
|
105313
105376
|
const content = generateConfigContent(config7);
|
|
105314
|
-
await
|
|
105315
|
-
M2.success(`Created ${dim(
|
|
105316
|
-
if (install) {
|
|
105317
|
-
await ensureSdkDependency({ cwd, logger: M2 });
|
|
105318
|
-
await runInstall({ cwd, logger: M2 });
|
|
105319
|
-
}
|
|
105377
|
+
await writeFile3(configPath, content, "utf-8");
|
|
105378
|
+
M2.success(`Created ${dim(CONFIG_FILENAME2)}`);
|
|
105320
105379
|
if (format) {
|
|
105321
105380
|
await formatWithPrettier({ cwd, filePath: configPath, logger: M2 });
|
|
105322
105381
|
}
|
|
@@ -105376,10 +105435,8 @@ async function runImportFlow(opts = {}) {
|
|
|
105376
105435
|
}
|
|
105377
105436
|
}
|
|
105378
105437
|
const content = generateConfigContent(config7);
|
|
105379
|
-
await
|
|
105380
|
-
M2.success(`Updated ${dim(
|
|
105381
|
-
await ensureSdkDependency({ cwd: process.cwd(), logger: M2 });
|
|
105382
|
-
await runInstall({ cwd: process.cwd(), logger: M2 });
|
|
105438
|
+
await writeFile3(configPath, content, "utf-8");
|
|
105439
|
+
M2.success(`Updated ${dim(CONFIG_FILENAME2)}`);
|
|
105383
105440
|
if (format) {
|
|
105384
105441
|
await formatWithPrettier({ cwd: process.cwd(), filePath: configPath, logger: M2 });
|
|
105385
105442
|
}
|
|
@@ -109643,7 +109700,6 @@ async function importInteractive(options) {
|
|
|
109643
109700
|
const createResult = await ensureConfig({
|
|
109644
109701
|
configPath,
|
|
109645
109702
|
skipIntro: true,
|
|
109646
|
-
install: true,
|
|
109647
109703
|
format
|
|
109648
109704
|
});
|
|
109649
109705
|
if (!createResult.success) {
|
|
@@ -109728,9 +109784,9 @@ function registerImportCommand(program2) {
|
|
|
109728
109784
|
}
|
|
109729
109785
|
|
|
109730
109786
|
// src/commands/init/create.ts
|
|
109731
|
-
import { existsSync as
|
|
109732
|
-
import { writeFile as
|
|
109733
|
-
import { basename as basename2, resolve as
|
|
109787
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
109788
|
+
import { writeFile as writeFile4 } from "node:fs/promises";
|
|
109789
|
+
import { basename as basename2, resolve as resolve5 } from "node:path";
|
|
109734
109790
|
|
|
109735
109791
|
// src/commands/sync/lib/compare.ts
|
|
109736
109792
|
function compareWithTitle(localTitle, remoteTitle, localConfig, remoteData) {
|
|
@@ -110016,7 +110072,7 @@ async function syncCommand(options) {
|
|
|
110016
110072
|
}
|
|
110017
110073
|
|
|
110018
110074
|
// src/commands/init/constants.ts
|
|
110019
|
-
var DEFAULT_CONFIG_FILENAME = "timeback.config.
|
|
110075
|
+
var DEFAULT_CONFIG_FILENAME = "timeback.config.json";
|
|
110020
110076
|
|
|
110021
110077
|
// src/commands/init/lib/credentials.ts
|
|
110022
110078
|
async function promptEnvironmentToSetup2() {
|
|
@@ -110323,17 +110379,16 @@ async function createConfig(options = {}) {
|
|
|
110323
110379
|
const {
|
|
110324
110380
|
configPath: customPath,
|
|
110325
110381
|
exitOnComplete = true,
|
|
110326
|
-
install = true,
|
|
110327
110382
|
format = true,
|
|
110328
110383
|
env: env2,
|
|
110329
110384
|
yes = false,
|
|
110330
110385
|
noSync = false
|
|
110331
110386
|
} = options;
|
|
110332
110387
|
const cwd = process.cwd();
|
|
110333
|
-
const configPath = customPath ?
|
|
110388
|
+
const configPath = customPath ? resolve5(cwd, customPath) : resolve5(cwd, DEFAULT_CONFIG_FILENAME);
|
|
110334
110389
|
const configFilename = basename2(configPath);
|
|
110335
110390
|
intro("Timeback");
|
|
110336
|
-
if (
|
|
110391
|
+
if (existsSync4(configPath)) {
|
|
110337
110392
|
M2.warn(`${blueBright(configFilename)} already exists`);
|
|
110338
110393
|
const overwrite = yes ? true : await ye({
|
|
110339
110394
|
message: "Overwrite existing config?",
|
|
@@ -110368,20 +110423,11 @@ async function createConfig(options = {}) {
|
|
|
110368
110423
|
const s = Y2();
|
|
110369
110424
|
s.start(`Creating ${configFilename}...`);
|
|
110370
110425
|
const content = generateConfigContent(config7);
|
|
110371
|
-
await
|
|
110426
|
+
await writeFile4(configPath, content, "utf-8");
|
|
110372
110427
|
if (format) {
|
|
110373
110428
|
await formatWithPrettier({ cwd, filePath: configPath, logger: M2, silent: true });
|
|
110374
110429
|
}
|
|
110375
110430
|
s.stop(`Created ${dim(configFilename)}`);
|
|
110376
|
-
const sdkDepResult = await ensureSdkDependency({ cwd, logger: M2 });
|
|
110377
|
-
const sdkIsInstalled = isPackageInstalled({ cwd, packageName: "@timeback/sdk" });
|
|
110378
|
-
const canInstall = install && sdkDepResult.reason !== "no_package_json";
|
|
110379
|
-
const sdkWasAddedToPackageJson = sdkDepResult.updated;
|
|
110380
|
-
const sdkMissingFromNodeModules = !sdkIsInstalled;
|
|
110381
|
-
const installWouldHelp = sdkWasAddedToPackageJson || sdkMissingFromNodeModules;
|
|
110382
|
-
if (canInstall && installWouldHelp) {
|
|
110383
|
-
await runInstall({ cwd, logger: M2 });
|
|
110384
|
-
}
|
|
110385
110431
|
if (mode === "import") {
|
|
110386
110432
|
outro.success();
|
|
110387
110433
|
if (exitOnComplete)
|
|
@@ -110441,11 +110487,10 @@ async function createConfig(options = {}) {
|
|
|
110441
110487
|
|
|
110442
110488
|
// src/commands/init/index.ts
|
|
110443
110489
|
function registerInitCommand(program2) {
|
|
110444
|
-
program2.command("init").description("Create a new timeback.config.
|
|
110490
|
+
program2.command("init").description("Create a new timeback.config.json file").option("-c, --config <path>", "Path to the config file (default: timeback.config.json)").option("--env <environment>", "Target environment (staging, production)").option("-y, --yes", "Skip confirmations and use defaults where possible").option("--no-format", "Do not run prettier on the generated config file").option("--no-sync", "Skip syncing with Timeback after init").action((opts) => createConfig({
|
|
110445
110491
|
configPath: opts.config,
|
|
110446
110492
|
env: opts.env,
|
|
110447
110493
|
yes: opts.yes,
|
|
110448
|
-
install: opts.install,
|
|
110449
110494
|
format: opts.format,
|
|
110450
110495
|
noSync: opts.sync === false
|
|
110451
110496
|
}));
|
|
@@ -110858,13 +110903,12 @@ import O2 from "node:readline";
|
|
|
110858
110903
|
import { Writable as X2 } from "node:stream";
|
|
110859
110904
|
import y22 from "node:process";
|
|
110860
110905
|
import * as tty2 from "tty";
|
|
110861
|
-
import { mkdir as mkdir2, readFile as
|
|
110906
|
+
import { mkdir as mkdir2, readFile as readFile3, stat as stat2, writeFile as writeFile5 } from "node:fs/promises";
|
|
110862
110907
|
import { homedir as homedir2, platform as platform22 } from "node:os";
|
|
110863
110908
|
import { join as join2 } from "node:path";
|
|
110864
|
-
import { existsSync as existsSync6 } from "node:fs";
|
|
110865
110909
|
import { readFile as readFile22 } from "node:fs/promises";
|
|
110866
|
-
import { basename as basename3, relative as relative2, resolve as
|
|
110867
|
-
import {
|
|
110910
|
+
import { basename as basename3, extname as extname2, relative as relative2, resolve as resolve6 } from "node:path";
|
|
110911
|
+
import { loadConfig as c12LoadConfig2 } from "c12";
|
|
110868
110912
|
import { basename as basename22 } from "node:path";
|
|
110869
110913
|
import { createServer as createServerHTTP } from "http";
|
|
110870
110914
|
import { Http2ServerRequest as Http2ServerRequest2 } from "http2";
|
|
@@ -125444,7 +125488,7 @@ async function ensureCredentialsDir2() {
|
|
|
125444
125488
|
}
|
|
125445
125489
|
async function readCredentialsStore2() {
|
|
125446
125490
|
try {
|
|
125447
|
-
const content = await
|
|
125491
|
+
const content = await readFile3(CREDENTIALS_FILE2, "utf-8");
|
|
125448
125492
|
return JSON.parse(content);
|
|
125449
125493
|
} catch {
|
|
125450
125494
|
return {};
|
|
@@ -125453,7 +125497,7 @@ async function readCredentialsStore2() {
|
|
|
125453
125497
|
async function writeCredentialsStore2(store) {
|
|
125454
125498
|
if (!await ensureCredentialsDir2())
|
|
125455
125499
|
return false;
|
|
125456
|
-
await
|
|
125500
|
+
await writeFile5(CREDENTIALS_FILE2, JSON.stringify(store, null, 2), { mode: 384 });
|
|
125457
125501
|
return true;
|
|
125458
125502
|
}
|
|
125459
125503
|
async function getSavedCredentials2(environment) {
|
|
@@ -125536,7 +125580,7 @@ var outro2 = {
|
|
|
125536
125580
|
warn: (message) => Se2(yellow2(message)),
|
|
125537
125581
|
info: (message) => Se2(dim2(message))
|
|
125538
125582
|
};
|
|
125539
|
-
var
|
|
125583
|
+
var FILE_PATTERNS = ["playcademy.config.ts", "playcademy.config.js", "playcademy.config.json"];
|
|
125540
125584
|
function parse52() {
|
|
125541
125585
|
return Promise.resolve({
|
|
125542
125586
|
success: false,
|
|
@@ -125559,7 +125603,7 @@ function printError(error483) {
|
|
|
125559
125603
|
}
|
|
125560
125604
|
var playcademyParser2 = {
|
|
125561
125605
|
name: "playcademy",
|
|
125562
|
-
filePatterns:
|
|
125606
|
+
filePatterns: FILE_PATTERNS,
|
|
125563
125607
|
parse: parse52,
|
|
125564
125608
|
printError
|
|
125565
125609
|
};
|
|
@@ -125577,7 +125621,7 @@ var TimebackSubject8 = exports_external6.enum([
|
|
|
125577
125621
|
"Math",
|
|
125578
125622
|
"None",
|
|
125579
125623
|
"Other"
|
|
125580
|
-
]);
|
|
125624
|
+
]).meta({ id: "TimebackSubject", description: "Subject area" });
|
|
125581
125625
|
var TimebackGrade8 = exports_external6.union([
|
|
125582
125626
|
exports_external6.literal(-1),
|
|
125583
125627
|
exports_external6.literal(0),
|
|
@@ -125594,7 +125638,10 @@ var TimebackGrade8 = exports_external6.union([
|
|
|
125594
125638
|
exports_external6.literal(11),
|
|
125595
125639
|
exports_external6.literal(12),
|
|
125596
125640
|
exports_external6.literal(13)
|
|
125597
|
-
])
|
|
125641
|
+
]).meta({
|
|
125642
|
+
id: "TimebackGrade",
|
|
125643
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
125644
|
+
});
|
|
125598
125645
|
var ScoreStatus8 = exports_external6.enum([
|
|
125599
125646
|
"exempt",
|
|
125600
125647
|
"fully graded",
|
|
@@ -125824,62 +125871,84 @@ var CaliperListEventsParams8 = exports_external6.object({
|
|
|
125824
125871
|
actorEmail: exports_external6.email().optional()
|
|
125825
125872
|
}).strict();
|
|
125826
125873
|
var CourseIds8 = exports_external6.object({
|
|
125827
|
-
staging: exports_external6.string().optional(),
|
|
125828
|
-
production: exports_external6.string().optional()
|
|
125829
|
-
});
|
|
125830
|
-
var CourseType8 = exports_external6.enum(["base", "hole-filling", "optional"]);
|
|
125831
|
-
var PublishStatus8 = exports_external6.enum(["draft", "testing", "published", "deactivated"]);
|
|
125874
|
+
staging: exports_external6.string().meta({ description: "Course ID in staging environment" }).optional(),
|
|
125875
|
+
production: exports_external6.string().meta({ description: "Course ID in production environment" }).optional()
|
|
125876
|
+
}).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
|
|
125877
|
+
var CourseType8 = exports_external6.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
|
|
125878
|
+
var PublishStatus8 = exports_external6.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
|
|
125832
125879
|
var CourseGoals8 = exports_external6.object({
|
|
125833
|
-
dailyXp: exports_external6.number().int().positive().optional(),
|
|
125834
|
-
dailyLessons: exports_external6.number().int().positive().optional(),
|
|
125835
|
-
dailyActiveMinutes: exports_external6.number().int().positive().optional(),
|
|
125836
|
-
dailyAccuracy: exports_external6.number().int().min(0).max(100).optional(),
|
|
125837
|
-
dailyMasteredUnits: exports_external6.number().int().positive().optional()
|
|
125838
|
-
});
|
|
125880
|
+
dailyXp: exports_external6.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
|
|
125881
|
+
dailyLessons: exports_external6.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
|
|
125882
|
+
dailyActiveMinutes: exports_external6.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
|
|
125883
|
+
dailyAccuracy: exports_external6.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
|
|
125884
|
+
dailyMasteredUnits: exports_external6.number().int().positive().meta({ description: "Target units to master per day" }).optional()
|
|
125885
|
+
}).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
|
|
125839
125886
|
var CourseMetrics8 = exports_external6.object({
|
|
125840
|
-
totalXp: exports_external6.number().int().positive().optional(),
|
|
125841
|
-
totalLessons: exports_external6.number().int().positive().optional(),
|
|
125842
|
-
totalGrades: exports_external6.number().int().positive().optional()
|
|
125843
|
-
});
|
|
125887
|
+
totalXp: exports_external6.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
|
|
125888
|
+
totalLessons: exports_external6.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
|
|
125889
|
+
totalGrades: exports_external6.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
|
|
125890
|
+
}).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
|
|
125844
125891
|
var CourseMetadata8 = exports_external6.object({
|
|
125845
125892
|
courseType: CourseType8.optional(),
|
|
125846
|
-
isSupplemental: exports_external6.boolean().optional(),
|
|
125847
|
-
isCustom: exports_external6.boolean().optional(),
|
|
125893
|
+
isSupplemental: exports_external6.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
|
|
125894
|
+
isCustom: exports_external6.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
|
|
125848
125895
|
publishStatus: PublishStatus8.optional(),
|
|
125849
|
-
contactEmail: exports_external6.email().optional(),
|
|
125850
|
-
primaryApp: exports_external6.string().optional(),
|
|
125896
|
+
contactEmail: exports_external6.email().meta({ description: "Contact email for course issues" }).optional(),
|
|
125897
|
+
primaryApp: exports_external6.string().meta({ description: "Primary application identifier" }).optional(),
|
|
125851
125898
|
goals: CourseGoals8.optional(),
|
|
125852
125899
|
metrics: CourseMetrics8.optional()
|
|
125853
|
-
});
|
|
125900
|
+
}).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
|
|
125854
125901
|
var CourseDefaults8 = exports_external6.object({
|
|
125855
|
-
courseCode: exports_external6.string().optional(),
|
|
125856
|
-
level: exports_external6.string().optional(),
|
|
125902
|
+
courseCode: exports_external6.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
|
|
125903
|
+
level: exports_external6.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
|
|
125857
125904
|
metadata: CourseMetadata8.optional()
|
|
125905
|
+
}).meta({
|
|
125906
|
+
id: "CourseDefaults",
|
|
125907
|
+
description: "Default properties that apply to all courses unless overridden"
|
|
125858
125908
|
});
|
|
125859
125909
|
var CourseEnvOverrides8 = exports_external6.object({
|
|
125860
|
-
level: exports_external6.string().optional(),
|
|
125861
|
-
sensor: exports_external6.
|
|
125862
|
-
launchUrl: exports_external6.
|
|
125910
|
+
level: exports_external6.string().meta({ description: "Course level for this environment" }).optional(),
|
|
125911
|
+
sensor: exports_external6.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
|
|
125912
|
+
launchUrl: exports_external6.url().meta({ description: "LTI launch URL for this environment" }).optional(),
|
|
125863
125913
|
metadata: CourseMetadata8.optional()
|
|
125914
|
+
}).meta({
|
|
125915
|
+
id: "CourseEnvOverrides",
|
|
125916
|
+
description: "Environment-specific course overrides (non-identity fields)"
|
|
125864
125917
|
});
|
|
125865
125918
|
var CourseOverrides8 = exports_external6.object({
|
|
125866
|
-
staging: CourseEnvOverrides8.
|
|
125867
|
-
|
|
125868
|
-
})
|
|
125919
|
+
staging: CourseEnvOverrides8.meta({
|
|
125920
|
+
description: "Overrides for staging environment"
|
|
125921
|
+
}).optional(),
|
|
125922
|
+
production: CourseEnvOverrides8.meta({
|
|
125923
|
+
description: "Overrides for production environment"
|
|
125924
|
+
}).optional()
|
|
125925
|
+
}).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
|
|
125869
125926
|
var CourseConfig8 = CourseDefaults8.extend({
|
|
125870
|
-
subject: TimebackSubject8,
|
|
125871
|
-
grade: TimebackGrade8.
|
|
125927
|
+
subject: TimebackSubject8.meta({ description: "Subject area for this course" }),
|
|
125928
|
+
grade: TimebackGrade8.meta({
|
|
125929
|
+
description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
|
|
125930
|
+
}).optional(),
|
|
125872
125931
|
ids: CourseIds8.nullable().optional(),
|
|
125873
|
-
sensor: exports_external6.
|
|
125874
|
-
launchUrl: exports_external6.
|
|
125932
|
+
sensor: exports_external6.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
|
|
125933
|
+
launchUrl: exports_external6.url().meta({ description: "LTI launch URL for this course" }).optional(),
|
|
125875
125934
|
overrides: CourseOverrides8.optional()
|
|
125935
|
+
}).meta({
|
|
125936
|
+
id: "CourseConfig",
|
|
125937
|
+
description: "Configuration for a single course. Must have either grade or courseCode (or both)."
|
|
125876
125938
|
});
|
|
125877
125939
|
var TimebackConfig8 = exports_external6.object({
|
|
125878
|
-
|
|
125879
|
-
|
|
125880
|
-
|
|
125881
|
-
|
|
125882
|
-
|
|
125940
|
+
$schema: exports_external6.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
|
|
125941
|
+
name: exports_external6.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
|
|
125942
|
+
defaults: CourseDefaults8.meta({
|
|
125943
|
+
description: "Default properties applied to all courses"
|
|
125944
|
+
}).optional(),
|
|
125945
|
+
courses: exports_external6.array(CourseConfig8).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
|
|
125946
|
+
sensor: exports_external6.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
|
|
125947
|
+
launchUrl: exports_external6.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
|
|
125948
|
+
}).meta({
|
|
125949
|
+
id: "TimebackConfig",
|
|
125950
|
+
title: "Timeback Config",
|
|
125951
|
+
description: "Configuration schema for timeback.config.json files"
|
|
125883
125952
|
}).refine((config23) => {
|
|
125884
125953
|
return config23.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
|
|
125885
125954
|
}, {
|
|
@@ -126889,26 +126958,10 @@ var QtiLessonFeedbackInput8 = exports_external6.object({
|
|
|
126889
126958
|
lessonId: exports_external6.string().min(1),
|
|
126890
126959
|
humanApproved: exports_external6.boolean().optional()
|
|
126891
126960
|
}).strict();
|
|
126892
|
-
var
|
|
126893
|
-
var
|
|
126894
|
-
|
|
126895
|
-
|
|
126896
|
-
if (jitiInstance2)
|
|
126897
|
-
return jitiInstance2;
|
|
126898
|
-
const { createJiti } = await import("jiti");
|
|
126899
|
-
jitiInstance2 = createJiti(import.meta.url, { fsCache: false });
|
|
126900
|
-
return jitiInstance2;
|
|
126901
|
-
}
|
|
126902
|
-
async function importModule2(fullPath) {
|
|
126903
|
-
let module;
|
|
126904
|
-
if (isBun2) {
|
|
126905
|
-
const fileUrl = pathToFileURL2(fullPath).href;
|
|
126906
|
-
module = await import(fileUrl);
|
|
126907
|
-
} else {
|
|
126908
|
-
const jiti = await getJiti2();
|
|
126909
|
-
module = await jiti.import(fullPath);
|
|
126910
|
-
}
|
|
126911
|
-
return module.default ?? module;
|
|
126961
|
+
var CONFIG_FILENAME3 = "timeback.config.json";
|
|
126962
|
+
var FILE_PATTERNS2 = [CONFIG_FILENAME3];
|
|
126963
|
+
function isJsonConfigPath2(configPath) {
|
|
126964
|
+
return extname2(configPath).toLowerCase() === ".json";
|
|
126912
126965
|
}
|
|
126913
126966
|
function deriveCourseIds(config32) {
|
|
126914
126967
|
const result = { staging: [], production: [] };
|
|
@@ -126919,65 +126972,80 @@ function deriveCourseIds(config32) {
|
|
|
126919
126972
|
}
|
|
126920
126973
|
async function readPackageVersion(cwd) {
|
|
126921
126974
|
try {
|
|
126922
|
-
const pkgPath =
|
|
126975
|
+
const pkgPath = resolve6(cwd, "package.json");
|
|
126923
126976
|
const pkg = JSON.parse(await readFile22(pkgPath, "utf-8"));
|
|
126924
126977
|
return pkg.version ?? "0.0.0";
|
|
126925
126978
|
} catch {
|
|
126926
126979
|
return "0.0.0";
|
|
126927
126980
|
}
|
|
126928
126981
|
}
|
|
126982
|
+
async function loadWithC122(cwd, configPath) {
|
|
126983
|
+
if (configPath && !isJsonConfigPath2(configPath)) {
|
|
126984
|
+
throw new Error(`Config file must be JSON (.json): ${configPath}`);
|
|
126985
|
+
}
|
|
126986
|
+
const result = await c12LoadConfig2({
|
|
126987
|
+
cwd,
|
|
126988
|
+
name: "timeback",
|
|
126989
|
+
configFile: configPath ?? CONFIG_FILENAME3,
|
|
126990
|
+
rcFile: false,
|
|
126991
|
+
packageJson: false,
|
|
126992
|
+
dotenv: false,
|
|
126993
|
+
envName: false,
|
|
126994
|
+
extend: false,
|
|
126995
|
+
omit$Keys: true,
|
|
126996
|
+
defaults: {},
|
|
126997
|
+
overrides: {}
|
|
126998
|
+
});
|
|
126999
|
+
if (!result.config || Object.keys(result.config).length === 0) {
|
|
127000
|
+
return null;
|
|
127001
|
+
}
|
|
127002
|
+
const rawConfig = result.config;
|
|
127003
|
+
if ("extends" in rawConfig) {
|
|
127004
|
+
throw new Error("The 'extends' feature is not supported in timeback.config.json. " + "Please inline all configuration.");
|
|
127005
|
+
}
|
|
127006
|
+
const { $schema: _schema, ...configWithoutSchema } = rawConfig;
|
|
127007
|
+
return {
|
|
127008
|
+
config: configWithoutSchema,
|
|
127009
|
+
configFile: result.configFile ?? resolve6(cwd, configPath ?? CONFIG_FILENAME3)
|
|
127010
|
+
};
|
|
127011
|
+
}
|
|
126929
127012
|
async function parse62() {
|
|
126930
127013
|
const cwd = process.cwd();
|
|
126931
|
-
|
|
126932
|
-
|
|
126933
|
-
|
|
126934
|
-
|
|
126935
|
-
|
|
126936
|
-
|
|
126937
|
-
|
|
126938
|
-
try {
|
|
126939
|
-
rawConfig = await importModule2(fullPath);
|
|
126940
|
-
foundPath = configPath;
|
|
126941
|
-
break;
|
|
126942
|
-
} catch (err) {
|
|
126943
|
-
loadError = err instanceof Error ? err : new Error(String(err));
|
|
126944
|
-
foundPath = configPath;
|
|
126945
|
-
break;
|
|
127014
|
+
try {
|
|
127015
|
+
const loaded = await loadWithC122(cwd);
|
|
127016
|
+
if (!loaded) {
|
|
127017
|
+
return {
|
|
127018
|
+
success: false,
|
|
127019
|
+
error: `No timeback config found. Create ${CONFIG_FILENAME3}`
|
|
127020
|
+
};
|
|
126946
127021
|
}
|
|
126947
|
-
|
|
126948
|
-
|
|
126949
|
-
|
|
126950
|
-
|
|
126951
|
-
|
|
126952
|
-
|
|
126953
|
-
|
|
126954
|
-
|
|
126955
|
-
|
|
127022
|
+
const result = TimebackConfig8.safeParse(loaded.config);
|
|
127023
|
+
if (!result.success) {
|
|
127024
|
+
const issues = result.error.issues.map((issue26) => ` - ${issue26.path.join(".")}: ${issue26.message}`).join(`
|
|
127025
|
+
`);
|
|
127026
|
+
return {
|
|
127027
|
+
success: false,
|
|
127028
|
+
error: `Invalid config in ${CONFIG_FILENAME3}:
|
|
127029
|
+
${issues}`
|
|
127030
|
+
};
|
|
127031
|
+
}
|
|
127032
|
+
const version23 = await readPackageVersion(cwd);
|
|
127033
|
+
const baseConfig = { ...result.data, version: version23 };
|
|
126956
127034
|
return {
|
|
126957
|
-
success:
|
|
126958
|
-
|
|
127035
|
+
success: true,
|
|
127036
|
+
config: {
|
|
127037
|
+
...baseConfig,
|
|
127038
|
+
path: loaded.configFile,
|
|
127039
|
+
courseIds: deriveCourseIds(baseConfig)
|
|
127040
|
+
}
|
|
126959
127041
|
};
|
|
126960
|
-
}
|
|
126961
|
-
const result = TimebackConfig8.safeParse(rawConfig);
|
|
126962
|
-
if (!result.success) {
|
|
126963
|
-
const issues = result.error.issues.map((issue26) => ` - ${issue26.path.join(".")}: ${issue26.message}`).join(`
|
|
126964
|
-
`);
|
|
127042
|
+
} catch (err) {
|
|
126965
127043
|
return {
|
|
126966
127044
|
success: false,
|
|
126967
|
-
error: `
|
|
126968
|
-
${
|
|
127045
|
+
error: `Failed to load ${CONFIG_FILENAME3}:
|
|
127046
|
+
${err instanceof Error ? err.message : String(err)}`
|
|
126969
127047
|
};
|
|
126970
127048
|
}
|
|
126971
|
-
const version23 = await readPackageVersion(cwd);
|
|
126972
|
-
const baseConfig = { ...result.data, version: version23 };
|
|
126973
|
-
return {
|
|
126974
|
-
success: true,
|
|
126975
|
-
config: {
|
|
126976
|
-
...baseConfig,
|
|
126977
|
-
path: `${cwd}/${foundPath}`,
|
|
126978
|
-
courseIds: deriveCourseIds(baseConfig)
|
|
126979
|
-
}
|
|
126980
|
-
};
|
|
126981
127049
|
}
|
|
126982
127050
|
function printError2(error483) {
|
|
126983
127051
|
console.log();
|
|
@@ -126985,19 +127053,22 @@ function printError2(error483) {
|
|
|
126985
127053
|
console.log();
|
|
126986
127054
|
console.log(` ${error483}`);
|
|
126987
127055
|
console.log();
|
|
126988
|
-
console.log(` ${dim2("Example timeback.config.
|
|
127056
|
+
console.log(` ${dim2("Example timeback.config.json:")}`);
|
|
126989
127057
|
console.log();
|
|
126990
|
-
console.log(` ${yellow2("
|
|
126991
|
-
console.log(` ${yellow2("
|
|
126992
|
-
console.log(` ${yellow2("
|
|
126993
|
-
console.log(` ${yellow2("
|
|
126994
|
-
console.log(` ${yellow2("
|
|
127058
|
+
console.log(` ${yellow2("{")}`);
|
|
127059
|
+
console.log(` ${yellow2(' "$schema": "https://timeback.dev/schema.json",')}`);
|
|
127060
|
+
console.log(` ${yellow2(' "name": "My Timeback App",')}`);
|
|
127061
|
+
console.log(` ${yellow2(' "launchUrl": "https://example.com/play",')}`);
|
|
127062
|
+
console.log(` ${yellow2(' "sensor": "https://example.com/sensor",')}`);
|
|
127063
|
+
console.log(` ${yellow2(' "courses": [')}`);
|
|
127064
|
+
console.log(` ${yellow2(' { "subject": "Math", "grade": 3 }')}`);
|
|
127065
|
+
console.log(` ${yellow2(" ]")}`);
|
|
126995
127066
|
console.log(` ${yellow2("}")}`);
|
|
126996
127067
|
console.log();
|
|
126997
127068
|
}
|
|
126998
127069
|
var timebackParser2 = {
|
|
126999
127070
|
name: "timeback",
|
|
127000
|
-
filePatterns:
|
|
127071
|
+
filePatterns: FILE_PATTERNS2,
|
|
127001
127072
|
parse: parse62,
|
|
127002
127073
|
printError: printError2
|
|
127003
127074
|
};
|
|
@@ -127571,7 +127642,7 @@ async function listCredentials2(options = {}) {
|
|
|
127571
127642
|
lines.push(`${green2("●")} ${env22}: ${creds.clientId}`);
|
|
127572
127643
|
hasAny = true;
|
|
127573
127644
|
} else {
|
|
127574
|
-
lines.push(`${dim2("○")} ${env22}: not configured`);
|
|
127645
|
+
lines.push(`${dim2("○")} ${env22}: ${"not configured"}`);
|
|
127575
127646
|
}
|
|
127576
127647
|
}
|
|
127577
127648
|
Me2(lines.join(`
|
|
@@ -130191,9 +130262,9 @@ var LEVEL_PREFIX9 = {
|
|
|
130191
130262
|
error: "[ERROR]"
|
|
130192
130263
|
};
|
|
130193
130264
|
function formatContext26(context) {
|
|
130194
|
-
return Object.entries(context).map(([key, value]) => `${key}=${
|
|
130265
|
+
return Object.entries(context).map(([key, value]) => `${key}=${formatValue6(value)}`).join(" ");
|
|
130195
130266
|
}
|
|
130196
|
-
function
|
|
130267
|
+
function formatValue6(value) {
|
|
130197
130268
|
if (typeof value === "string")
|
|
130198
130269
|
return value;
|
|
130199
130270
|
if (typeof value === "number")
|
|
@@ -131539,7 +131610,7 @@ function registerSyncCommand(program2) {
|
|
|
131539
131610
|
}
|
|
131540
131611
|
|
|
131541
131612
|
// src/cli.ts
|
|
131542
|
-
var version8 = "0.1.
|
|
131613
|
+
var version8 = "0.1.6";
|
|
131543
131614
|
program.name("timeback").description("CLI for Timeback tools and integrations").version(version8);
|
|
131544
131615
|
registerApiCommand(program);
|
|
131545
131616
|
registerCredentialsCommand(program);
|