timeback-studio 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -16886,7 +16886,7 @@ async function loadCredentials(environment) {
16886
16886
  }
16887
16887
  // ../internal/cli-infra/src/ui.ts
16888
16888
  function intro(title) {
16889
- console.log();
16889
+ console.log("");
16890
16890
  Ie(bgCyan(black(` ${title} `)));
16891
16891
  }
16892
16892
  var outro = {
@@ -16926,10 +16926,9 @@ var playcademyParser = {
16926
16926
  };
16927
16927
 
16928
16928
  // ../internal/cli-infra/src/config/timeback.ts
16929
- import { existsSync } from "node:fs";
16930
16929
  import { readFile as readFile2 } from "node:fs/promises";
16931
- import { basename, relative, resolve } from "node:path";
16932
- import { createJiti } from "jiti";
16930
+ import { basename, extname, relative, resolve } from "node:path";
16931
+ import { loadConfig as c12LoadConfig } from "c12";
16933
16932
  // ../types/src/zod/primitives.ts
16934
16933
  var IsoDateTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
16935
16934
  var IsoDateTimeString = exports_external.string().min(1).regex(IsoDateTimeRegex, "must be a valid ISO 8601 datetime");
@@ -16945,7 +16944,7 @@ var TimebackSubject = exports_external.enum([
16945
16944
  "Math",
16946
16945
  "None",
16947
16946
  "Other"
16948
- ]);
16947
+ ]).meta({ id: "TimebackSubject", description: "Subject area" });
16949
16948
  var TimebackGrade = exports_external.union([
16950
16949
  exports_external.literal(-1),
16951
16950
  exports_external.literal(0),
@@ -16962,7 +16961,10 @@ var TimebackGrade = exports_external.union([
16962
16961
  exports_external.literal(11),
16963
16962
  exports_external.literal(12),
16964
16963
  exports_external.literal(13)
16965
- ]);
16964
+ ]).meta({
16965
+ id: "TimebackGrade",
16966
+ description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
16967
+ });
16966
16968
  var ScoreStatus = exports_external.enum([
16967
16969
  "exempt",
16968
16970
  "fully graded",
@@ -16989,6 +16991,47 @@ var OneRosterUserRole = exports_external.enum([
16989
16991
  "teacher"
16990
16992
  ]);
16991
16993
  var EnrollmentRole = exports_external.enum(["administrator", "proctor", "student", "teacher"]);
16994
+ var ResourceType = exports_external.enum([
16995
+ "qti",
16996
+ "text",
16997
+ "audio",
16998
+ "video",
16999
+ "interactive",
17000
+ "visual",
17001
+ "course-material",
17002
+ "assessment-bank"
17003
+ ]);
17004
+ var QtiSubType = exports_external.enum(["qti-test", "qti-question", "qti-stimulus", "qti-test-bank"]);
17005
+ var CourseMaterialSubType = exports_external.enum(["unit", "course", "resource-collection"]);
17006
+ var QuestionType = exports_external.enum([
17007
+ "choice",
17008
+ "order",
17009
+ "associate",
17010
+ "match",
17011
+ "hotspot",
17012
+ "hottext",
17013
+ "select-point",
17014
+ "graphic-order",
17015
+ "graphic-associate",
17016
+ "graphic-gap-match",
17017
+ "text-entry",
17018
+ "extended-text",
17019
+ "inline-choice",
17020
+ "upload",
17021
+ "slider",
17022
+ "drawing",
17023
+ "media",
17024
+ "custom"
17025
+ ]);
17026
+ var Difficulty = exports_external.enum(["easy", "medium", "hard"]);
17027
+ var LearningObjectiveSetSchema = exports_external.array(exports_external.object({
17028
+ source: exports_external.string(),
17029
+ learningObjectiveIds: exports_external.array(exports_external.string())
17030
+ }));
17031
+ var FastFailConfigSchema = exports_external.object({
17032
+ consecutive_failures: exports_external.number().int().min(1).optional(),
17033
+ stagnation_limit: exports_external.number().int().min(1).optional()
17034
+ }).optional();
16992
17035
  var LessonType = exports_external.enum(["powerpath-100", "quiz", "test-out", "placement", "unit-test", "alpha-read-article"]).nullable();
16993
17036
  var IMSErrorResponse = exports_external.object({
16994
17037
  imsx_codeMajor: exports_external.enum(["failure", "success"]),
@@ -17065,7 +17108,11 @@ var ActivityCompletedInput = exports_external.object({
17065
17108
  eventTime: IsoDateTimeString.optional(),
17066
17109
  metricsId: exports_external.string().optional(),
17067
17110
  id: exports_external.string().optional(),
17068
- extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
17111
+ extensions: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
17112
+ attempt: exports_external.number().int().min(1).optional(),
17113
+ generatedExtensions: exports_external.object({
17114
+ pctCompleteApp: exports_external.number().optional()
17115
+ }).loose().optional()
17069
17116
  }).strict();
17070
17117
  var TimeSpentInput = exports_external.object({
17071
17118
  actor: TimebackUser,
@@ -17149,48 +17196,113 @@ var CaliperListEventsParams = exports_external.object({
17149
17196
  }).strict();
17150
17197
  // ../types/src/zod/config.ts
17151
17198
  var CourseIds = exports_external.object({
17152
- staging: exports_external.string().optional(),
17153
- production: exports_external.string().optional()
17154
- });
17155
- var CourseType = exports_external.enum(["base", "hole-filling", "optional"]);
17156
- var PublishStatus = exports_external.enum(["draft", "testing", "published", "deactivated"]);
17199
+ staging: exports_external.string().meta({ description: "Course ID in staging environment" }).optional(),
17200
+ production: exports_external.string().meta({ description: "Course ID in production environment" }).optional()
17201
+ }).meta({ id: "CourseIds", description: "Environment-specific course IDs (populated by sync)" });
17202
+ var CourseType = exports_external.enum(["base", "hole-filling", "optional"]).meta({ id: "CourseType", description: "Course classification type" });
17203
+ var PublishStatus = exports_external.enum(["draft", "testing", "published", "deactivated"]).meta({ id: "PublishStatus", description: "Course publication status" });
17157
17204
  var CourseGoals = exports_external.object({
17158
- dailyXp: exports_external.number().int().positive().optional(),
17159
- dailyLessons: exports_external.number().int().positive().optional(),
17160
- dailyActiveMinutes: exports_external.number().int().positive().optional(),
17161
- dailyAccuracy: exports_external.number().int().min(0).max(100).optional(),
17162
- dailyMasteredUnits: exports_external.number().int().positive().optional()
17163
- });
17205
+ dailyXp: exports_external.number().int().positive().meta({ description: "Target XP to earn per day" }).optional(),
17206
+ dailyLessons: exports_external.number().int().positive().meta({ description: "Target lessons to complete per day" }).optional(),
17207
+ dailyActiveMinutes: exports_external.number().int().positive().meta({ description: "Target active learning minutes per day" }).optional(),
17208
+ dailyAccuracy: exports_external.number().int().min(0).max(100).meta({ description: "Target accuracy percentage (0-100)" }).optional(),
17209
+ dailyMasteredUnits: exports_external.number().int().positive().meta({ description: "Target units to master per day" }).optional()
17210
+ }).meta({ id: "CourseGoals", description: "Daily learning goals for a course" });
17164
17211
  var CourseMetrics = exports_external.object({
17165
- totalXp: exports_external.number().int().positive().optional(),
17166
- totalLessons: exports_external.number().int().positive().optional(),
17167
- totalGrades: exports_external.number().int().positive().optional()
17168
- });
17212
+ totalXp: exports_external.number().int().positive().meta({ description: "Total XP available in the course" }).optional(),
17213
+ totalLessons: exports_external.number().int().positive().meta({ description: "Total number of lessons/activities" }).optional(),
17214
+ totalGrades: exports_external.number().int().positive().meta({ description: "Total grade levels covered" }).optional()
17215
+ }).meta({ id: "CourseMetrics", description: "Aggregate metrics for a course" });
17169
17216
  var CourseMetadata = exports_external.object({
17170
17217
  courseType: CourseType.optional(),
17171
- isSupplemental: exports_external.boolean().optional(),
17172
- isCustom: exports_external.boolean().optional(),
17218
+ isSupplemental: exports_external.boolean().meta({ description: "Whether this is supplemental to a base course" }).optional(),
17219
+ isCustom: exports_external.boolean().meta({ description: "Whether this is a custom course for an individual student" }).optional(),
17173
17220
  publishStatus: PublishStatus.optional(),
17174
- contactEmail: exports_external.email().optional(),
17175
- primaryApp: exports_external.string().optional(),
17221
+ contactEmail: exports_external.email().meta({ description: "Contact email for course issues" }).optional(),
17222
+ primaryApp: exports_external.string().meta({ description: "Primary application identifier" }).optional(),
17176
17223
  goals: CourseGoals.optional(),
17177
17224
  metrics: CourseMetrics.optional()
17178
- });
17225
+ }).meta({ id: "CourseMetadata", description: "Course metadata (matches API metadata object)" });
17179
17226
  var CourseDefaults = exports_external.object({
17180
- courseCode: exports_external.string().optional(),
17181
- level: exports_external.string().optional(),
17227
+ courseCode: exports_external.string().meta({ description: "Course code (e.g., 'MATH101')" }).optional(),
17228
+ level: exports_external.string().meta({ description: "Course level (e.g., 'AP', 'Honors')" }).optional(),
17182
17229
  metadata: CourseMetadata.optional()
17230
+ }).meta({
17231
+ id: "CourseDefaults",
17232
+ description: "Default properties that apply to all courses unless overridden"
17183
17233
  });
17234
+ var CourseEnvOverrides = exports_external.object({
17235
+ level: exports_external.string().meta({ description: "Course level for this environment" }).optional(),
17236
+ sensor: exports_external.url().meta({ description: "Caliper sensor endpoint URL for this environment" }).optional(),
17237
+ launchUrl: exports_external.url().meta({ description: "LTI launch URL for this environment" }).optional(),
17238
+ metadata: CourseMetadata.optional()
17239
+ }).meta({
17240
+ id: "CourseEnvOverrides",
17241
+ description: "Environment-specific course overrides (non-identity fields)"
17242
+ });
17243
+ var CourseOverrides = exports_external.object({
17244
+ staging: CourseEnvOverrides.meta({
17245
+ description: "Overrides for staging environment"
17246
+ }).optional(),
17247
+ production: CourseEnvOverrides.meta({
17248
+ description: "Overrides for production environment"
17249
+ }).optional()
17250
+ }).meta({ id: "CourseOverrides", description: "Per-environment course overrides" });
17184
17251
  var CourseConfig = CourseDefaults.extend({
17185
- subject: TimebackSubject,
17186
- grade: TimebackGrade,
17187
- ids: CourseIds.nullable().optional()
17252
+ subject: TimebackSubject.meta({ description: "Subject area for this course" }),
17253
+ grade: TimebackGrade.meta({
17254
+ description: "Grade level (-1 = Pre-K, 0 = K, 1-12 = grades, 13 = AP)"
17255
+ }).optional(),
17256
+ ids: CourseIds.nullable().optional(),
17257
+ sensor: exports_external.url().meta({ description: "Caliper sensor endpoint URL for this course" }).optional(),
17258
+ launchUrl: exports_external.url().meta({ description: "LTI launch URL for this course" }).optional(),
17259
+ overrides: CourseOverrides.optional()
17260
+ }).meta({
17261
+ id: "CourseConfig",
17262
+ description: "Configuration for a single course. Must have either grade or courseCode (or both)."
17188
17263
  });
17189
17264
  var TimebackConfig = exports_external.object({
17190
- name: exports_external.string().min(1, "App name is required"),
17191
- defaults: CourseDefaults.optional(),
17192
- courses: exports_external.array(CourseConfig).min(1, "At least one course is required"),
17193
- sensors: exports_external.array(exports_external.string().url()).optional()
17265
+ $schema: exports_external.string().meta({ description: "JSON Schema reference for editor support" }).optional(),
17266
+ name: exports_external.string().min(1, "App name is required").meta({ description: "Display name for your app" }),
17267
+ defaults: CourseDefaults.meta({
17268
+ description: "Default properties applied to all courses"
17269
+ }).optional(),
17270
+ courses: exports_external.array(CourseConfig).min(1, "At least one course is required").meta({ description: "Courses available in this app" }),
17271
+ sensor: exports_external.url().meta({ description: "Default Caliper sensor endpoint URL for all courses" }).optional(),
17272
+ launchUrl: exports_external.url().meta({ description: "Default LTI launch URL for all courses" }).optional()
17273
+ }).meta({
17274
+ id: "TimebackConfig",
17275
+ title: "Timeback Config",
17276
+ description: "Configuration schema for timeback.config.json files"
17277
+ }).refine((config2) => {
17278
+ return config2.courses.every((c) => c.grade !== undefined || c.courseCode !== undefined);
17279
+ }, {
17280
+ message: "Each course must have either a grade or a courseCode",
17281
+ path: ["courses"]
17282
+ }).refine((config2) => {
17283
+ const withGrade = config2.courses.filter((c) => c.grade !== undefined);
17284
+ const keys = withGrade.map((c) => `${c.subject}:${c.grade}`);
17285
+ return new Set(keys).size === keys.length;
17286
+ }, {
17287
+ message: "Duplicate (subject, grade) pair found; each must be unique",
17288
+ path: ["courses"]
17289
+ }).refine((config2) => {
17290
+ const withCode = config2.courses.filter((c) => c.courseCode !== undefined);
17291
+ const codes = withCode.map((c) => c.courseCode);
17292
+ return new Set(codes).size === codes.length;
17293
+ }, {
17294
+ message: "Duplicate courseCode found; each must be unique",
17295
+ path: ["courses"]
17296
+ }).refine((config2) => {
17297
+ return config2.courses.every((c) => c.sensor !== undefined || config2.sensor !== undefined);
17298
+ }, {
17299
+ message: "Each course must have an effective sensor; set a top-level `sensor` or per-course `sensor`",
17300
+ path: ["courses"]
17301
+ }).refine((config2) => {
17302
+ return config2.courses.every((c) => c.launchUrl !== undefined || config2.launchUrl !== undefined);
17303
+ }, {
17304
+ message: "Each course must have an effective launchUrl; set a top-level `launchUrl` or per-course `launchUrl`",
17305
+ path: ["courses"]
17194
17306
  });
17195
17307
  // ../types/src/zod/edubridge.ts
17196
17308
  var EdubridgeDateString = exports_external.union([IsoDateString, IsoDateTimeString]);
@@ -17441,20 +17553,45 @@ var OneRosterScoreScaleCreateInput = exports_external.object({
17441
17553
  }).strict();
17442
17554
  var OneRosterAssessmentLineItemCreateInput = exports_external.object({
17443
17555
  sourcedId: NonEmptyString2.optional(),
17556
+ status: Status.optional(),
17557
+ dateLastModified: IsoDateTimeString.optional(),
17444
17558
  title: NonEmptyString2.describe("title must be a non-empty string"),
17445
- class: Ref,
17446
- school: Ref,
17447
- category: Ref,
17448
- assignDate: OneRosterDateString,
17449
- dueDate: OneRosterDateString,
17450
- status: Status,
17559
+ description: exports_external.string().nullable().optional(),
17560
+ class: Ref.nullable().optional(),
17561
+ parentAssessmentLineItem: Ref.nullable().optional(),
17562
+ scoreScale: Ref.nullable().optional(),
17563
+ resultValueMin: exports_external.number().nullable().optional(),
17564
+ resultValueMax: exports_external.number().nullable().optional(),
17565
+ component: Ref.nullable().optional(),
17566
+ componentResource: Ref.nullable().optional(),
17567
+ learningObjectiveSet: exports_external.array(exports_external.object({
17568
+ source: exports_external.string(),
17569
+ learningObjectiveIds: exports_external.array(exports_external.string())
17570
+ })).optional().nullable(),
17571
+ course: Ref.nullable().optional(),
17451
17572
  metadata: Metadata
17452
17573
  }).strict();
17574
+ var LearningObjectiveResult = exports_external.object({
17575
+ learningObjectiveId: exports_external.string(),
17576
+ score: exports_external.number().optional(),
17577
+ textScore: exports_external.string().optional()
17578
+ });
17579
+ var LearningObjectiveScoreSetSchema = exports_external.array(exports_external.object({
17580
+ source: exports_external.string(),
17581
+ learningObjectiveResults: exports_external.array(LearningObjectiveResult)
17582
+ }));
17453
17583
  var OneRosterAssessmentResultCreateInput = exports_external.object({
17454
17584
  sourcedId: NonEmptyString2.optional(),
17455
- lineItem: Ref,
17585
+ status: Status.optional(),
17586
+ dateLastModified: IsoDateTimeString.optional(),
17587
+ metadata: Metadata,
17588
+ assessmentLineItem: Ref,
17456
17589
  student: Ref,
17457
- scoreDate: OneRosterDateString,
17590
+ score: exports_external.number().nullable().optional(),
17591
+ textScore: exports_external.string().nullable().optional(),
17592
+ scoreDate: exports_external.string().datetime(),
17593
+ scoreScale: Ref.nullable().optional(),
17594
+ scorePercentile: exports_external.number().nullable().optional(),
17458
17595
  scoreStatus: exports_external.enum([
17459
17596
  "exempt",
17460
17597
  "fully graded",
@@ -17462,9 +17599,12 @@ var OneRosterAssessmentResultCreateInput = exports_external.object({
17462
17599
  "partially graded",
17463
17600
  "submitted"
17464
17601
  ]),
17465
- score: exports_external.string().optional(),
17466
- status: Status,
17467
- metadata: Metadata
17602
+ comment: exports_external.string().nullable().optional(),
17603
+ learningObjectiveSet: LearningObjectiveScoreSetSchema.nullable().optional(),
17604
+ inProgress: exports_external.string().nullable().optional(),
17605
+ incomplete: exports_external.string().nullable().optional(),
17606
+ late: exports_external.string().nullable().optional(),
17607
+ missing: exports_external.string().nullable().optional()
17468
17608
  }).strict();
17469
17609
  var OneRosterOrgCreateInput = exports_external.object({
17470
17610
  sourcedId: NonEmptyString2.optional(),
@@ -17532,6 +17672,75 @@ var OneRosterCredentialInput = exports_external.object({
17532
17672
  var OneRosterDemographicsCreateInput = exports_external.object({
17533
17673
  sourcedId: NonEmptyString2.describe("sourcedId must be a non-empty string")
17534
17674
  }).loose();
17675
+ var CommonResourceMetadataSchema = exports_external.object({
17676
+ type: ResourceType,
17677
+ subject: TimebackSubject.nullish(),
17678
+ grades: exports_external.array(TimebackGrade).nullish(),
17679
+ language: exports_external.string().nullish(),
17680
+ xp: exports_external.number().nullish(),
17681
+ url: exports_external.url().nullish(),
17682
+ keywords: exports_external.array(exports_external.string()).nullish(),
17683
+ learningObjectiveSet: LearningObjectiveSetSchema.nullish(),
17684
+ lessonType: exports_external.string().nullish()
17685
+ }).passthrough();
17686
+ var QtiMetadataSchema = CommonResourceMetadataSchema.extend({
17687
+ type: exports_external.literal("qti"),
17688
+ subType: QtiSubType,
17689
+ questionType: QuestionType.optional(),
17690
+ difficulty: Difficulty.optional()
17691
+ });
17692
+ var TextMetadataSchema = CommonResourceMetadataSchema.extend({
17693
+ type: exports_external.literal("text"),
17694
+ format: exports_external.string(),
17695
+ author: exports_external.string().optional(),
17696
+ pageCount: exports_external.number().optional()
17697
+ });
17698
+ var AudioMetadataSchema = CommonResourceMetadataSchema.extend({
17699
+ type: exports_external.literal("audio"),
17700
+ duration: exports_external.string().regex(/^\d{2}:\d{2}:\d{2}(\.\d{2})?$/).optional(),
17701
+ format: exports_external.string(),
17702
+ speaker: exports_external.string().optional()
17703
+ });
17704
+ var VideoMetadataSchema = CommonResourceMetadataSchema.extend({
17705
+ type: exports_external.literal("video"),
17706
+ duration: exports_external.string().regex(/^\d{2}:\d{2}:\d{2}(\.\d{2})?$/).optional(),
17707
+ captionsAvailable: exports_external.boolean().optional(),
17708
+ format: exports_external.string()
17709
+ });
17710
+ var InteractiveMetadataSchema = CommonResourceMetadataSchema.extend({
17711
+ type: exports_external.literal("interactive"),
17712
+ launchUrl: exports_external.url().optional(),
17713
+ toolProvider: exports_external.string().optional(),
17714
+ instructionalMethod: exports_external.string().optional(),
17715
+ courseIdOnFail: exports_external.string().nullable().optional(),
17716
+ fail_fast: FastFailConfigSchema
17717
+ });
17718
+ var VisualMetadataSchema = CommonResourceMetadataSchema.extend({
17719
+ type: exports_external.literal("visual"),
17720
+ format: exports_external.string(),
17721
+ resolution: exports_external.string().optional()
17722
+ });
17723
+ var CourseMaterialMetadataSchema = CommonResourceMetadataSchema.extend({
17724
+ type: exports_external.literal("course-material"),
17725
+ subType: CourseMaterialSubType,
17726
+ author: exports_external.string().optional(),
17727
+ format: exports_external.string(),
17728
+ instructionalMethod: exports_external.string().optional()
17729
+ });
17730
+ var AssessmentBankMetadataSchema = CommonResourceMetadataSchema.extend({
17731
+ type: exports_external.literal("assessment-bank"),
17732
+ resources: exports_external.array(exports_external.string())
17733
+ });
17734
+ var ResourceMetadataSchema = exports_external.discriminatedUnion("type", [
17735
+ QtiMetadataSchema,
17736
+ TextMetadataSchema,
17737
+ AudioMetadataSchema,
17738
+ VideoMetadataSchema,
17739
+ InteractiveMetadataSchema,
17740
+ VisualMetadataSchema,
17741
+ CourseMaterialMetadataSchema,
17742
+ AssessmentBankMetadataSchema
17743
+ ]);
17535
17744
  var OneRosterResourceCreateInput = exports_external.object({
17536
17745
  sourcedId: NonEmptyString2.optional(),
17537
17746
  title: NonEmptyString2.describe("title must be a non-empty string"),
@@ -17541,7 +17750,7 @@ var OneRosterResourceCreateInput = exports_external.object({
17541
17750
  vendorId: exports_external.string().optional(),
17542
17751
  applicationId: exports_external.string().optional(),
17543
17752
  status: Status.optional(),
17544
- metadata: Metadata
17753
+ metadata: ResourceMetadataSchema.nullable().optional()
17545
17754
  }).strict();
17546
17755
  var CourseStructureItem = exports_external.object({
17547
17756
  url: NonEmptyString2.describe("courseStructure.url must be a non-empty string"),
@@ -17566,6 +17775,268 @@ var OneRosterBulkResultItem = exports_external.object({
17566
17775
  student: Ref
17567
17776
  }).loose();
17568
17777
  var OneRosterBulkResultsInput = exports_external.array(OneRosterBulkResultItem).min(1, "results must have at least one item");
17778
+ // ../types/src/zod/powerpath.ts
17779
+ var NonEmptyString3 = exports_external.string().trim().min(1);
17780
+ var ToolProvider = exports_external.enum(["edulastic", "mastery-track"]);
17781
+ var LessonTypeRequired = exports_external.enum([
17782
+ "powerpath-100",
17783
+ "quiz",
17784
+ "test-out",
17785
+ "placement",
17786
+ "unit-test",
17787
+ "alpha-read-article"
17788
+ ]);
17789
+ var GradeArray = exports_external.array(TimebackGrade);
17790
+ var ResourceMetadata = exports_external.record(exports_external.string(), exports_external.unknown()).optional();
17791
+ var ExternalTestBase = exports_external.object({
17792
+ courseId: NonEmptyString3,
17793
+ lessonTitle: NonEmptyString3.optional(),
17794
+ launchUrl: exports_external.url().optional(),
17795
+ toolProvider: ToolProvider,
17796
+ unitTitle: NonEmptyString3.optional(),
17797
+ courseComponentSourcedId: NonEmptyString3.optional(),
17798
+ vendorId: NonEmptyString3.optional(),
17799
+ description: NonEmptyString3.optional(),
17800
+ resourceMetadata: ResourceMetadata.nullable().optional(),
17801
+ grades: GradeArray
17802
+ });
17803
+ var ExternalTestOut = ExternalTestBase.extend({
17804
+ lessonType: exports_external.literal("test-out"),
17805
+ xp: exports_external.number()
17806
+ });
17807
+ var ExternalPlacement = ExternalTestBase.extend({
17808
+ lessonType: exports_external.literal("placement"),
17809
+ courseIdOnFail: NonEmptyString3.optional(),
17810
+ xp: exports_external.number().optional()
17811
+ });
17812
+ var InternalTestBase = exports_external.object({
17813
+ courseId: NonEmptyString3,
17814
+ lessonType: LessonTypeRequired,
17815
+ lessonTitle: NonEmptyString3.optional(),
17816
+ unitTitle: NonEmptyString3.optional(),
17817
+ courseComponentSourcedId: NonEmptyString3.optional(),
17818
+ resourceMetadata: ResourceMetadata.nullable().optional(),
17819
+ xp: exports_external.number().optional(),
17820
+ grades: GradeArray.optional(),
17821
+ courseIdOnFail: NonEmptyString3.optional()
17822
+ });
17823
+ var PowerPathCreateInternalTestInput = exports_external.union([
17824
+ InternalTestBase.extend({
17825
+ testType: exports_external.literal("qti"),
17826
+ qti: exports_external.object({
17827
+ url: exports_external.url(),
17828
+ title: NonEmptyString3.optional(),
17829
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
17830
+ })
17831
+ }),
17832
+ InternalTestBase.extend({
17833
+ testType: exports_external.literal("assessment-bank"),
17834
+ assessmentBank: exports_external.object({
17835
+ resources: exports_external.array(exports_external.object({
17836
+ url: exports_external.url(),
17837
+ title: NonEmptyString3.optional(),
17838
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional()
17839
+ }))
17840
+ })
17841
+ })
17842
+ ]);
17843
+ var PowerPathCreateNewAttemptInput = exports_external.object({
17844
+ student: NonEmptyString3,
17845
+ lesson: NonEmptyString3
17846
+ });
17847
+ var PowerPathFinalStudentAssessmentResponseInput = exports_external.object({
17848
+ student: NonEmptyString3,
17849
+ lesson: NonEmptyString3
17850
+ });
17851
+ var PowerPathLessonPlansCreateInput = exports_external.object({
17852
+ courseId: NonEmptyString3,
17853
+ userId: NonEmptyString3,
17854
+ classId: NonEmptyString3.optional()
17855
+ });
17856
+ var LessonPlanTarget = exports_external.object({
17857
+ type: exports_external.enum(["component", "resource"]),
17858
+ id: NonEmptyString3
17859
+ });
17860
+ var PowerPathLessonPlanOperationInput = exports_external.union([
17861
+ exports_external.object({
17862
+ type: exports_external.literal("set-skipped"),
17863
+ payload: exports_external.object({
17864
+ target: LessonPlanTarget,
17865
+ value: exports_external.boolean()
17866
+ })
17867
+ }),
17868
+ exports_external.object({
17869
+ type: exports_external.literal("add-custom-resource"),
17870
+ payload: exports_external.object({
17871
+ resource_id: NonEmptyString3,
17872
+ parent_component_id: NonEmptyString3,
17873
+ skipped: exports_external.boolean().optional()
17874
+ })
17875
+ }),
17876
+ exports_external.object({
17877
+ type: exports_external.literal("move-item-before"),
17878
+ payload: exports_external.object({
17879
+ target: LessonPlanTarget,
17880
+ reference_id: NonEmptyString3
17881
+ })
17882
+ }),
17883
+ exports_external.object({
17884
+ type: exports_external.literal("move-item-after"),
17885
+ payload: exports_external.object({
17886
+ target: LessonPlanTarget,
17887
+ reference_id: NonEmptyString3
17888
+ })
17889
+ }),
17890
+ exports_external.object({
17891
+ type: exports_external.literal("move-item-to-start"),
17892
+ payload: exports_external.object({
17893
+ target: LessonPlanTarget
17894
+ })
17895
+ }),
17896
+ exports_external.object({
17897
+ type: exports_external.literal("move-item-to-end"),
17898
+ payload: exports_external.object({
17899
+ target: LessonPlanTarget
17900
+ })
17901
+ }),
17902
+ exports_external.object({
17903
+ type: exports_external.literal("change-item-parent"),
17904
+ payload: exports_external.object({
17905
+ target: LessonPlanTarget,
17906
+ new_parent_id: NonEmptyString3,
17907
+ position: exports_external.enum(["start", "end"]).optional()
17908
+ })
17909
+ })
17910
+ ]);
17911
+ var PowerPathLessonPlanOperationsInput = exports_external.object({
17912
+ operation: exports_external.array(PowerPathLessonPlanOperationInput),
17913
+ reason: NonEmptyString3.optional()
17914
+ });
17915
+ var PowerPathLessonPlanUpdateStudentItemResponseInput = exports_external.object({
17916
+ studentId: NonEmptyString3,
17917
+ componentResourceId: NonEmptyString3,
17918
+ result: exports_external.object({
17919
+ status: exports_external.enum(["active", "tobedeleted"]),
17920
+ metadata: exports_external.record(exports_external.string(), exports_external.unknown()).optional(),
17921
+ score: exports_external.number().optional(),
17922
+ textScore: NonEmptyString3.optional(),
17923
+ scoreDate: NonEmptyString3,
17924
+ scorePercentile: exports_external.number().optional(),
17925
+ scoreStatus: ScoreStatus,
17926
+ comment: NonEmptyString3.optional(),
17927
+ learningObjectiveSet: exports_external.array(exports_external.object({
17928
+ source: NonEmptyString3,
17929
+ learningObjectiveResults: exports_external.array(exports_external.object({
17930
+ learningObjectiveId: NonEmptyString3,
17931
+ score: exports_external.number().optional(),
17932
+ textScore: NonEmptyString3.optional()
17933
+ }))
17934
+ })).optional(),
17935
+ inProgress: NonEmptyString3.optional(),
17936
+ incomplete: NonEmptyString3.optional(),
17937
+ late: NonEmptyString3.optional(),
17938
+ missing: NonEmptyString3.optional()
17939
+ })
17940
+ });
17941
+ var PowerPathMakeExternalTestAssignmentInput = exports_external.object({
17942
+ student: NonEmptyString3,
17943
+ lesson: NonEmptyString3,
17944
+ applicationName: NonEmptyString3.optional(),
17945
+ testId: NonEmptyString3.optional(),
17946
+ skipCourseEnrollment: exports_external.boolean().optional()
17947
+ });
17948
+ var PowerPathPlacementResetUserPlacementInput = exports_external.object({
17949
+ student: NonEmptyString3,
17950
+ subject: TimebackSubject
17951
+ });
17952
+ var PowerPathResetAttemptInput = exports_external.object({
17953
+ student: NonEmptyString3,
17954
+ lesson: NonEmptyString3
17955
+ });
17956
+ var PowerPathScreeningResetSessionInput = exports_external.object({
17957
+ userId: NonEmptyString3
17958
+ });
17959
+ var PowerPathScreeningAssignTestInput = exports_external.object({
17960
+ userId: NonEmptyString3,
17961
+ subject: exports_external.enum(["Math", "Reading", "Language", "Science"])
17962
+ });
17963
+ var PowerPathTestAssignmentsCreateInput = exports_external.object({
17964
+ student: NonEmptyString3,
17965
+ subject: TimebackSubject,
17966
+ grade: TimebackGrade,
17967
+ testName: NonEmptyString3.optional()
17968
+ });
17969
+ var PowerPathTestAssignmentsUpdateInput = exports_external.object({
17970
+ testName: NonEmptyString3
17971
+ });
17972
+ var PowerPathTestAssignmentItemInput = exports_external.object({
17973
+ student: NonEmptyString3,
17974
+ subject: TimebackSubject,
17975
+ grade: TimebackGrade,
17976
+ testName: NonEmptyString3.optional()
17977
+ });
17978
+ var PowerPathTestAssignmentsBulkInput = exports_external.object({
17979
+ items: exports_external.array(PowerPathTestAssignmentItemInput)
17980
+ });
17981
+ var PowerPathTestAssignmentsImportInput = exports_external.object({
17982
+ spreadsheetUrl: exports_external.url(),
17983
+ sheet: NonEmptyString3
17984
+ });
17985
+ var PowerPathTestAssignmentsListParams = exports_external.object({
17986
+ student: NonEmptyString3,
17987
+ status: exports_external.enum(["assigned", "in_progress", "completed", "failed", "expired", "cancelled"]).optional(),
17988
+ subject: NonEmptyString3.optional(),
17989
+ grade: TimebackGrade.optional(),
17990
+ limit: exports_external.number().int().positive().max(3000).optional(),
17991
+ offset: exports_external.number().int().nonnegative().optional()
17992
+ });
17993
+ var PowerPathTestAssignmentsAdminParams = exports_external.object({
17994
+ student: NonEmptyString3.optional(),
17995
+ status: exports_external.enum(["assigned", "in_progress", "completed", "failed", "expired", "cancelled"]).optional(),
17996
+ subject: NonEmptyString3.optional(),
17997
+ grade: TimebackGrade.optional(),
17998
+ limit: exports_external.number().int().positive().max(3000).optional(),
17999
+ offset: exports_external.number().int().nonnegative().optional()
18000
+ });
18001
+ var PowerPathUpdateStudentQuestionResponseInput = exports_external.object({
18002
+ student: NonEmptyString3,
18003
+ question: NonEmptyString3,
18004
+ response: exports_external.union([NonEmptyString3, exports_external.array(NonEmptyString3)]).optional(),
18005
+ responses: exports_external.record(exports_external.string(), exports_external.union([NonEmptyString3, exports_external.array(NonEmptyString3)])).optional(),
18006
+ lesson: NonEmptyString3
18007
+ });
18008
+ var PowerPathGetAssessmentProgressParams = exports_external.object({
18009
+ student: NonEmptyString3,
18010
+ lesson: NonEmptyString3,
18011
+ attempt: exports_external.number().int().positive().optional()
18012
+ });
18013
+ var PowerPathGetNextQuestionParams = exports_external.object({
18014
+ student: NonEmptyString3,
18015
+ lesson: NonEmptyString3
18016
+ });
18017
+ var PowerPathGetAttemptsParams = exports_external.object({
18018
+ student: NonEmptyString3,
18019
+ lesson: NonEmptyString3
18020
+ });
18021
+ var PowerPathTestOutParams = exports_external.object({
18022
+ student: NonEmptyString3,
18023
+ lesson: NonEmptyString3.optional(),
18024
+ finalized: exports_external.boolean().optional(),
18025
+ toolProvider: NonEmptyString3.optional(),
18026
+ attempt: exports_external.number().int().positive().optional()
18027
+ });
18028
+ var PowerPathImportExternalTestAssignmentResultsParams = exports_external.object({
18029
+ student: NonEmptyString3,
18030
+ lesson: NonEmptyString3,
18031
+ applicationName: NonEmptyString3.optional()
18032
+ });
18033
+ var PowerPathPlacementQueryParams = exports_external.object({
18034
+ student: NonEmptyString3,
18035
+ subject: TimebackSubject
18036
+ });
18037
+ var PowerPathSyllabusQueryParams = exports_external.object({
18038
+ status: exports_external.enum(["active", "tobedeleted"]).optional()
18039
+ });
17569
18040
  // ../types/src/zod/qti.ts
17570
18041
  var QtiAssessmentItemType = exports_external.enum([
17571
18042
  "choice",
@@ -17817,11 +18288,10 @@ var QtiLessonFeedbackInput = exports_external.object({
17817
18288
  humanApproved: exports_external.boolean().optional()
17818
18289
  }).strict();
17819
18290
  // ../internal/cli-infra/src/config/timeback.ts
17820
- var FILE_PATTERNS2 = ["timeback.config.ts", "timeback.config.js", "timeback.config.mjs"];
17821
- var jiti = createJiti(import.meta.url, { fsCache: false });
17822
- async function importModule(fullPath) {
17823
- const module = await jiti.import(fullPath);
17824
- return module.default ?? module;
18291
+ var CONFIG_FILENAME = "timeback.config.json";
18292
+ var FILE_PATTERNS2 = [CONFIG_FILENAME];
18293
+ function isJsonConfigPath(configPath) {
18294
+ return extname(configPath).toLowerCase() === ".json";
17825
18295
  }
17826
18296
  function deriveCourseIds(config3) {
17827
18297
  const result = { staging: [], production: [] };
@@ -17839,58 +18309,73 @@ async function readPackageVersion(cwd) {
17839
18309
  return "0.0.0";
17840
18310
  }
17841
18311
  }
18312
+ async function loadWithC12(cwd, configPath) {
18313
+ if (configPath && !isJsonConfigPath(configPath)) {
18314
+ throw new Error(`Config file must be JSON (.json): ${configPath}`);
18315
+ }
18316
+ const result = await c12LoadConfig({
18317
+ cwd,
18318
+ name: "timeback",
18319
+ configFile: configPath ?? CONFIG_FILENAME,
18320
+ rcFile: false,
18321
+ packageJson: false,
18322
+ dotenv: false,
18323
+ envName: false,
18324
+ extend: false,
18325
+ omit$Keys: true,
18326
+ defaults: {},
18327
+ overrides: {}
18328
+ });
18329
+ if (!result.config || Object.keys(result.config).length === 0) {
18330
+ return null;
18331
+ }
18332
+ const rawConfig = result.config;
18333
+ if ("extends" in rawConfig) {
18334
+ throw new Error("The 'extends' feature is not supported in timeback.config.json. " + "Please inline all configuration.");
18335
+ }
18336
+ const { $schema: _schema, ...configWithoutSchema } = rawConfig;
18337
+ return {
18338
+ config: configWithoutSchema,
18339
+ configFile: result.configFile ?? resolve(cwd, configPath ?? CONFIG_FILENAME)
18340
+ };
18341
+ }
17842
18342
  async function parse6() {
17843
18343
  const cwd = process.cwd();
17844
- let rawConfig = null;
17845
- let foundPath = null;
17846
- let loadError = null;
17847
- for (const configPath of FILE_PATTERNS2) {
17848
- const fullPath = resolve(cwd, configPath);
17849
- if (!existsSync(fullPath))
17850
- continue;
17851
- try {
17852
- rawConfig = await importModule(fullPath);
17853
- foundPath = configPath;
17854
- break;
17855
- } catch (err) {
17856
- loadError = err instanceof Error ? err : new Error(String(err));
17857
- foundPath = configPath;
17858
- break;
18344
+ try {
18345
+ const loaded = await loadWithC12(cwd);
18346
+ if (!loaded) {
18347
+ return {
18348
+ success: false,
18349
+ error: `No timeback config found. Create ${CONFIG_FILENAME}`
18350
+ };
17859
18351
  }
17860
- }
17861
- if (loadError && foundPath) {
17862
- return {
17863
- success: false,
17864
- error: `Failed to load ${foundPath}:
17865
- ${loadError.message}`
17866
- };
17867
- }
17868
- if (!rawConfig || !foundPath) {
18352
+ const result = TimebackConfig.safeParse(loaded.config);
18353
+ if (!result.success) {
18354
+ const issues = result.error.issues.map((issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`).join(`
18355
+ `);
18356
+ return {
18357
+ success: false,
18358
+ error: `Invalid config in ${CONFIG_FILENAME}:
18359
+ ${issues}`
18360
+ };
18361
+ }
18362
+ const version2 = await readPackageVersion(cwd);
18363
+ const baseConfig = { ...result.data, version: version2 };
17869
18364
  return {
17870
- success: false,
17871
- error: `No timeback config found. Create one of: ${FILE_PATTERNS2.join(", ")}`
18365
+ success: true,
18366
+ config: {
18367
+ ...baseConfig,
18368
+ path: loaded.configFile,
18369
+ courseIds: deriveCourseIds(baseConfig)
18370
+ }
17872
18371
  };
17873
- }
17874
- const result = TimebackConfig.safeParse(rawConfig);
17875
- if (!result.success) {
17876
- const issues = result.error.issues.map((issue2) => ` - ${issue2.path.join(".")}: ${issue2.message}`).join(`
17877
- `);
18372
+ } catch (err) {
17878
18373
  return {
17879
18374
  success: false,
17880
- error: `Invalid config in ${foundPath}:
17881
- ${issues}`
18375
+ error: `Failed to load ${CONFIG_FILENAME}:
18376
+ ${err instanceof Error ? err.message : String(err)}`
17882
18377
  };
17883
18378
  }
17884
- const version2 = await readPackageVersion(cwd);
17885
- const baseConfig = { ...result.data, version: version2 };
17886
- return {
17887
- success: true,
17888
- config: {
17889
- ...baseConfig,
17890
- path: `${cwd}/${foundPath}`,
17891
- courseIds: deriveCourseIds(baseConfig)
17892
- }
17893
- };
17894
18379
  }
17895
18380
  function printError2(error48) {
17896
18381
  console.log();
@@ -17898,13 +18383,16 @@ function printError2(error48) {
17898
18383
  console.log();
17899
18384
  console.log(` ${error48}`);
17900
18385
  console.log();
17901
- console.log(` ${dim("Example timeback.config.ts:")}`);
18386
+ console.log(` ${dim("Example timeback.config.json:")}`);
17902
18387
  console.log();
17903
- console.log(` ${yellow("export default {")}`);
17904
- console.log(` ${yellow(" name: 'My Timeback App',")}`);
17905
- console.log(` ${yellow(" courses: [")}`);
17906
- console.log(` ${yellow(" { subject: 'Math', grade: 3 },")}`);
17907
- console.log(` ${yellow(" ],")}`);
18388
+ console.log(` ${yellow("{")}`);
18389
+ console.log(` ${yellow(' "$schema": "https://timeback.dev/schema.json",')}`);
18390
+ console.log(` ${yellow(' "name": "My Timeback App",')}`);
18391
+ console.log(` ${yellow(' "launchUrl": "https://example.com/play",')}`);
18392
+ console.log(` ${yellow(' "sensor": "https://example.com/sensor",')}`);
18393
+ console.log(` ${yellow(' "courses": [')}`);
18394
+ console.log(` ${yellow(' { "subject": "Math", "grade": 3 }')}`);
18395
+ console.log(` ${yellow(" ]")}`);
17908
18396
  console.log(` ${yellow("}")}`);
17909
18397
  console.log();
17910
18398
  }
@@ -18132,29 +18620,18 @@ function isValidUrl(url2) {
18132
18620
  return false;
18133
18621
  }
18134
18622
  }
18135
- async function promptSensors() {
18136
- const wantSensors = await ye({
18137
- message: "Add Caliper sensor URLs for event filtering?",
18138
- initialValue: false
18139
- });
18140
- if (isCancelled(wantSensors)) {
18141
- return;
18142
- }
18143
- if (!wantSensors) {
18144
- return [];
18145
- }
18623
+ async function promptSensor(options) {
18624
+ const { defaultValue } = options ?? {};
18146
18625
  const input = await he({
18147
- message: "Sensor URLs (comma-separated)",
18148
- placeholder: "https://myapp.example.com/caliper/sensors/activity",
18626
+ message: "Sensor URL (your app origin, used for activity tracking)",
18627
+ placeholder: "https://myapp.example.com",
18628
+ defaultValue,
18149
18629
  validate: (value) => {
18150
18630
  if (!value.trim()) {
18151
- return "Enter at least one sensor URL";
18631
+ return "Sensor URL is required for activity tracking";
18152
18632
  }
18153
- const urls = value.split(",").map((s) => s.trim());
18154
- for (const url2 of urls) {
18155
- if (!isValidUrl(url2)) {
18156
- return `Invalid URL: ${url2}`;
18157
- }
18633
+ if (!isValidUrl(value.trim())) {
18634
+ return "Invalid URL format";
18158
18635
  }
18159
18636
  return;
18160
18637
  }
@@ -18162,7 +18639,26 @@ async function promptSensors() {
18162
18639
  if (isCancelled(input)) {
18163
18640
  return;
18164
18641
  }
18165
- return input.split(",").map((s) => s.trim()).filter(Boolean);
18642
+ return input.trim();
18643
+ }
18644
+ // ../internal/cli-infra/src/sensors/utils.ts
18645
+ function deriveSensorsFromConfig(config3) {
18646
+ const sensors = new Set;
18647
+ if (config3.sensor) {
18648
+ sensors.add(config3.sensor);
18649
+ }
18650
+ for (const course of config3.courses) {
18651
+ if (course.sensor) {
18652
+ sensors.add(course.sensor);
18653
+ }
18654
+ if (course.overrides?.staging?.sensor) {
18655
+ sensors.add(course.overrides.staging.sensor);
18656
+ }
18657
+ if (course.overrides?.production?.sensor) {
18658
+ sensors.add(course.overrides.production.sensor);
18659
+ }
18660
+ }
18661
+ return Array.from(sensors);
18166
18662
  }
18167
18663
  // src/cli/commands/credentials/add.ts
18168
18664
  async function addCredentials(options = {}) {
@@ -18726,8 +19222,8 @@ async function promptImportApp(credentials, configuredEnvs) {
18726
19222
  if (!result.success) {
18727
19223
  return result;
18728
19224
  }
18729
- const sensors = await promptSensors();
18730
- if (sensors === undefined) {
19225
+ const sensor = await promptSensor();
19226
+ if (sensor === undefined) {
18731
19227
  return { success: false, cancelled: true };
18732
19228
  }
18733
19229
  return {
@@ -18735,7 +19231,7 @@ async function promptImportApp(credentials, configuredEnvs) {
18735
19231
  name: result.appName,
18736
19232
  courses: result.courses,
18737
19233
  environment: result.environment,
18738
- sensors: sensors.length > 0 ? sensors : undefined
19234
+ sensor
18739
19235
  };
18740
19236
  } catch (error48) {
18741
19237
  const message = error48 instanceof Error ? error48.message : "Unknown error";
@@ -18765,7 +19261,7 @@ async function promptNoConfig(credentials, configuredEnvs, opts = {}) {
18765
19261
  // src/cli/commands/serve/config.ts
18766
19262
  import { basename as basename2 } from "node:path";
18767
19263
  function buildUserConfigFromImport(result) {
18768
- const { name, courses, sensors } = result;
19264
+ const { name, courses, sensor } = result;
18769
19265
  const courseIds = {
18770
19266
  staging: [],
18771
19267
  production: []
@@ -18778,8 +19274,8 @@ function buildUserConfigFromImport(result) {
18778
19274
  }
18779
19275
  return {
18780
19276
  name,
19277
+ sensor,
18781
19278
  courses,
18782
- sensors,
18783
19279
  version: "0.0.0",
18784
19280
  path: "",
18785
19281
  courseIds
@@ -18853,17 +19349,16 @@ async function resolveFromConfigOrImport(credentials, configuredEnvs, defaultEnv
18853
19349
  function parseSensors(sensors) {
18854
19350
  return sensors.split(",").map((s) => s.trim()).filter(Boolean);
18855
19351
  }
18856
- function applyCliOverrides(config3, opts) {
19352
+ function getEffectiveSensors(config3, opts) {
18857
19353
  if (opts.sensors) {
18858
- config3.sensors = parseSensors(opts.sensors);
19354
+ return parseSensors(opts.sensors);
18859
19355
  }
19356
+ const derived = deriveSensorsFromConfig(config3);
19357
+ return derived.length > 0 ? derived : undefined;
18860
19358
  }
18861
19359
  async function resolveConfig(courseIds, opts, credentials, configuredEnvs, defaultEnv) {
18862
19360
  const parserOpts = { playcademy: opts.playcademy };
18863
19361
  const resolved = courseIds.length > 0 ? await resolveFromCourseIds(courseIds, defaultEnv, credentials, configuredEnvs) : await resolveFromConfigOrImport(credentials, configuredEnvs, defaultEnv, parserOpts);
18864
- if (!resolved)
18865
- return null;
18866
- applyCliOverrides(resolved.userConfig, opts);
18867
19362
  return resolved;
18868
19363
  }
18869
19364
 
@@ -22001,7 +22496,7 @@ function createEnvMiddleware(ctx, manager) {
22001
22496
  }, 400);
22002
22497
  }
22003
22498
  const client = manager.get(env2);
22004
- const sensors = ctx.userConfig.sensors;
22499
+ const sensors = ctx.derivedSensors;
22005
22500
  c.set("env", env2);
22006
22501
  c.set("client", client);
22007
22502
  c.set("sensors", sensors);
@@ -22540,7 +23035,8 @@ async function serveCommand(courseIds, opts) {
22540
23035
  serverConfig,
22541
23036
  userConfig: resolved.userConfig,
22542
23037
  credentials,
22543
- defaultEnvironment: resolved.environment
23038
+ defaultEnvironment: resolved.environment,
23039
+ derivedSensors: getEffectiveSensors(resolved.userConfig, opts)
22544
23040
  };
22545
23041
  startServer(ctx, serverConfig, resolved.configFile);
22546
23042
  }