@playcademy/sandbox 0.5.2-beta.2 → 0.5.2-beta.3

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.
Files changed (3) hide show
  1. package/dist/cli.js +1700 -1120
  2. package/dist/server.js +1700 -1120
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1078,7 +1078,7 @@ var package_default;
1078
1078
  var init_package = __esm(() => {
1079
1079
  package_default = {
1080
1080
  name: "@playcademy/sandbox",
1081
- version: "0.5.2-beta.2",
1081
+ version: "0.5.2-beta.3",
1082
1082
  description: "Local development server for Playcademy game development",
1083
1083
  type: "module",
1084
1084
  exports: {
@@ -11323,23 +11323,31 @@ var init_table6 = __esm(() => {
11323
11323
  });
11324
11324
 
11325
11325
  // ../data/src/domains/timeback/table.ts
11326
- var gameTimebackIntegrations, gameTimebackAssessmentTests, gameTimebackMetricDiscrepancyVerifications;
11326
+ var gameTimebackIntegrationStatusEnum, gameTimebackIntegrations, gameTimebackAssessmentTests, gameTimebackMetricDiscrepancyVerifications;
11327
11327
  var init_table7 = __esm(() => {
11328
+ init_drizzle_orm();
11328
11329
  init_pg_core();
11329
11330
  init_table5();
11330
11331
  init_table3();
11332
+ gameTimebackIntegrationStatusEnum = pgEnum("game_timeback_integration_status", [
11333
+ "active",
11334
+ "deactivated"
11335
+ ]);
11331
11336
  gameTimebackIntegrations = pgTable("game_timeback_integrations", {
11332
11337
  id: uuid("id").primaryKey().defaultRandom(),
11333
11338
  gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
11334
11339
  courseId: text("course_id").notNull(),
11335
11340
  grade: integer("grade").notNull(),
11336
11341
  subject: text("subject").notNull(),
11342
+ status: gameTimebackIntegrationStatusEnum("status"),
11337
11343
  totalXp: integer("total_xp"),
11338
11344
  lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true }),
11345
+ deactivatedAt: timestamp("deactivated_at", { withTimezone: true }),
11346
+ reactivatedAt: timestamp("reactivated_at", { withTimezone: true }),
11339
11347
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
11340
11348
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
11341
11349
  }, (table3) => [
11342
- uniqueIndex("game_timeback_integrations_game_grade_subject_idx").on(table3.gameId, table3.grade, table3.subject)
11350
+ uniqueIndex("game_timeback_integrations_game_grade_subject_idx").on(table3.gameId, table3.grade, table3.subject).where(sql`${table3.status} IS DISTINCT FROM 'deactivated'`)
11343
11351
  ]);
11344
11352
  gameTimebackAssessmentTests = pgTable("game_timeback_assessment_tests", {
11345
11353
  id: uuid("id").primaryKey().defaultRandom(),
@@ -11382,6 +11390,7 @@ __export(exports_tables_index, {
11382
11390
  gameTypeEnum: () => gameTypeEnum,
11383
11391
  gameTimebackMetricDiscrepancyVerifications: () => gameTimebackMetricDiscrepancyVerifications,
11384
11392
  gameTimebackIntegrations: () => gameTimebackIntegrations,
11393
+ gameTimebackIntegrationStatusEnum: () => gameTimebackIntegrationStatusEnum,
11385
11394
  gameTimebackAssessmentTests: () => gameTimebackAssessmentTests,
11386
11395
  gameScoresRelations: () => gameScoresRelations,
11387
11396
  gameScores: () => gameScores,
@@ -24673,6 +24682,7 @@ var init_helpers = __esm(() => {
24673
24682
 
24674
24683
  // ../cloudflare/src/playcademy/provider/provider.ts
24675
24684
  var init_provider = __esm(() => {
24685
+ init_src();
24676
24686
  init_src();
24677
24687
  init_core();
24678
24688
  init_constants2();
@@ -27768,6 +27778,20 @@ var init_game_member_service = __esm(() => {
27768
27778
  init_spans();
27769
27779
  init_errors();
27770
27780
  });
27781
+ // ../data/src/domains/timeback/helpers.ts
27782
+ function isActiveGameTimebackIntegrationStatus(statusColumn = gameTimebackIntegrations.status) {
27783
+ return sql`${statusColumn} IS DISTINCT FROM ${DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS}`;
27784
+ }
27785
+ var ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS = "active", DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS = "deactivated";
27786
+ var init_helpers2 = __esm(() => {
27787
+ init_drizzle_orm();
27788
+ init_table7();
27789
+ });
27790
+
27791
+ // ../data/src/helpers.index.ts
27792
+ var init_helpers_index = __esm(() => {
27793
+ init_helpers2();
27794
+ });
27771
27795
 
27772
27796
  // ../utils/src/fns.ts
27773
27797
  function sleep(ms) {
@@ -27777,15 +27801,584 @@ function sleep(ms) {
27777
27801
  return new Promise((resolve) => setTimeout(resolve, ms));
27778
27802
  }
27779
27803
 
27804
+ // ../timeback/dist/types.js
27805
+ function isObject(value) {
27806
+ return typeof value === "object" && value !== null;
27807
+ }
27808
+ function isCourseMetadata(value) {
27809
+ return isObject(value);
27810
+ }
27811
+ function isResourceMetadata(value) {
27812
+ return isObject(value);
27813
+ }
27814
+ function isPlaycademyResourceMetadata(value) {
27815
+ if (!isObject(value)) {
27816
+ return false;
27817
+ }
27818
+ if (!("mastery" in value) || value.mastery === undefined) {
27819
+ return true;
27820
+ }
27821
+ return isObject(value.mastery);
27822
+ }
27823
+ function isTimebackSubject(value) {
27824
+ return typeof value === "string" && SUBJECT_VALUES.includes(value);
27825
+ }
27826
+ function isTimebackGrade(value) {
27827
+ return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
27828
+ }
27829
+ var __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS, TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, QTI_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants3, SUBJECT_VALUES, GRADE_VALUES;
27830
+ var init_types2 = __esm(() => {
27831
+ init_src();
27832
+ init_constants3 = __esm2(() => {
27833
+ TIMEBACK_API_URLS = {
27834
+ production: "https://api.alpha-1edtech.ai",
27835
+ staging: "https://api.staging.alpha-1edtech.com"
27836
+ };
27837
+ TIMEBACK_AUTH_URLS = {
27838
+ production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
27839
+ staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
27840
+ };
27841
+ CALIPER_API_URLS = {
27842
+ production: "https://caliper.alpha-1edtech.ai",
27843
+ staging: "https://caliper-staging.alpha-1edtech.com"
27844
+ };
27845
+ ONEROSTER_ENDPOINTS = {
27846
+ organizations: "/ims/oneroster/rostering/v1p2/orgs",
27847
+ courses: "/ims/oneroster/rostering/v1p2/courses",
27848
+ courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
27849
+ resources: "/ims/oneroster/resources/v1p2/resources",
27850
+ componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
27851
+ classes: "/ims/oneroster/rostering/v1p2/classes",
27852
+ enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
27853
+ assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
27854
+ assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
27855
+ users: "/ims/oneroster/rostering/v1p2/users"
27856
+ };
27857
+ QTI_ENDPOINTS = {
27858
+ assessmentTests: "/assessment-tests",
27859
+ assessmentItems: "/assessment-items"
27860
+ };
27861
+ CALIPER_ENDPOINTS = {
27862
+ event: "/caliper/event",
27863
+ events: "/caliper/events",
27864
+ validate: "/caliper/event/validate"
27865
+ };
27866
+ CALIPER_CONSTANTS = {
27867
+ context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
27868
+ profile: "TimebackProfile",
27869
+ dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
27870
+ };
27871
+ TIMEBACK_EVENT_TYPES = {
27872
+ activityEvent: "ActivityEvent",
27873
+ timeSpentEvent: "TimeSpentEvent"
27874
+ };
27875
+ TIMEBACK_ACTIONS = {
27876
+ completed: "Completed",
27877
+ spentTime: "SpentTime"
27878
+ };
27879
+ TIMEBACK_TYPES = {
27880
+ user: "TimebackUser",
27881
+ activityContext: "TimebackActivityContext",
27882
+ activityMetricsCollection: "TimebackActivityMetricsCollection",
27883
+ timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
27884
+ };
27885
+ ACTIVITY_METRIC_TYPES = {
27886
+ totalQuestions: "totalQuestions",
27887
+ correctQuestions: "correctQuestions",
27888
+ xpEarned: "xpEarned",
27889
+ masteredUnits: "masteredUnits"
27890
+ };
27891
+ TIME_METRIC_TYPES = {
27892
+ active: "active",
27893
+ inactive: "inactive",
27894
+ waste: "waste",
27895
+ unknown: "unknown",
27896
+ antiPattern: "anti-pattern"
27897
+ };
27898
+ TIMEBACK_SUBJECTS = [
27899
+ "Math",
27900
+ "FastMath",
27901
+ "Science",
27902
+ "Social Studies",
27903
+ "Language",
27904
+ "Reading",
27905
+ "Vocabulary",
27906
+ "Writing"
27907
+ ];
27908
+ TIMEBACK_GRADE_LEVELS = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
27909
+ TIMEBACK_GRADE_LEVEL_LABELS = {
27910
+ "-1": "pre-k",
27911
+ "0": "kindergarten",
27912
+ "1": "1st grade",
27913
+ "2": "2nd grade",
27914
+ "3": "3rd grade",
27915
+ "4": "4th grade",
27916
+ "5": "5th grade",
27917
+ "6": "6th grade",
27918
+ "7": "7th grade",
27919
+ "8": "8th grade",
27920
+ "9": "9th grade",
27921
+ "10": "10th grade",
27922
+ "11": "11th grade",
27923
+ "12": "12th grade",
27924
+ "13": "AP"
27925
+ };
27926
+ CALIPER_SUBJECTS = {
27927
+ Reading: "Reading",
27928
+ Language: "Language",
27929
+ Vocabulary: "Vocabulary",
27930
+ SocialStudies: "Social Studies",
27931
+ Writing: "Writing",
27932
+ Science: "Science",
27933
+ FastMath: "FastMath",
27934
+ Math: "Math",
27935
+ None: "None"
27936
+ };
27937
+ ONEROSTER_STATUS = {
27938
+ active: "active",
27939
+ toBeDeleted: "tobedeleted"
27940
+ };
27941
+ SCORE_STATUS = {
27942
+ exempt: "exempt",
27943
+ fullyGraded: "fully graded",
27944
+ notSubmitted: "not submitted",
27945
+ partiallyGraded: "partially graded",
27946
+ submitted: "submitted"
27947
+ };
27948
+ ENV_VARS = {
27949
+ clientId: "TIMEBACK_CLIENT_ID",
27950
+ clientSecret: "TIMEBACK_CLIENT_SECRET",
27951
+ baseUrl: "TIMEBACK_BASE_URL",
27952
+ environment: "TIMEBACK_ENVIRONMENT",
27953
+ vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
27954
+ launchBaseUrl: "GAME_URL",
27955
+ qtiClientId: "QTI_CLIENT_ID",
27956
+ qtiClientSecret: "QTI_CLIENT_SECRET",
27957
+ qtiAuthUrl: "QTI_AUTH_URL"
27958
+ };
27959
+ HTTP_DEFAULTS = {
27960
+ timeout: 30000,
27961
+ retries: 3,
27962
+ retryBackoffBase: 2
27963
+ };
27964
+ AUTH_DEFAULTS = {
27965
+ tokenCacheDuration: 50000
27966
+ };
27967
+ CACHE_DEFAULTS = {
27968
+ defaultTTL: 10 * 60 * 1000,
27969
+ defaultMaxSize: 500,
27970
+ defaultName: "TimebackCache",
27971
+ studentTTL: 10 * 60 * 1000,
27972
+ studentMaxSize: 500,
27973
+ assessmentTTL: 30 * 60 * 1000,
27974
+ assessmentMaxSize: 200,
27975
+ enrollmentTTL: 5 * 1000,
27976
+ enrollmentMaxSize: 100
27977
+ };
27978
+ CONFIG_DEFAULTS = {
27979
+ fileNames: ["timeback.config.js", "timeback.config.json"]
27980
+ };
27981
+ PLAYCADEMY_DEFAULTS = {
27982
+ organization: TIMEBACK_ORG_SOURCED_ID,
27983
+ launchBaseUrls: PLAYCADEMY_BASE_URLS
27984
+ };
27985
+ RESOURCE_DEFAULTS = {
27986
+ organization: {
27987
+ name: TIMEBACK_ORG_NAME,
27988
+ type: TIMEBACK_ORG_TYPE
27989
+ },
27990
+ course: {
27991
+ gradingScheme: TIMEBACK_COURSE_DEFAULTS.gradingScheme,
27992
+ level: TIMEBACK_COURSE_DEFAULTS.level,
27993
+ metadata: {
27994
+ goals: TIMEBACK_COURSE_DEFAULTS.goals,
27995
+ metrics: TIMEBACK_COURSE_DEFAULTS.metrics
27996
+ }
27997
+ },
27998
+ component: TIMEBACK_COMPONENT_DEFAULTS,
27999
+ resource: TIMEBACK_RESOURCE_DEFAULTS,
28000
+ componentResource: TIMEBACK_COMPONENT_RESOURCE_DEFAULTS
28001
+ };
28002
+ HTTP_STATUS = {
28003
+ CLIENT_ERROR_MIN: 400,
28004
+ CLIENT_ERROR_MAX: 500,
28005
+ SERVER_ERROR_MIN: 500
28006
+ };
28007
+ ERROR_NAMES = {
28008
+ timebackAuth: "TimebackAuthError",
28009
+ timebackApi: "TimebackApiError",
28010
+ timebackConfig: "TimebackConfigError",
28011
+ timebackSdk: "TimebackSDKError"
28012
+ };
28013
+ });
28014
+ init_constants3();
28015
+ SUBJECT_VALUES = TIMEBACK_SUBJECTS;
28016
+ GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
28017
+ });
28018
+
28019
+ // ../utils/src/string.ts
28020
+ function kebabToTitleCase(kebabStr) {
28021
+ return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
28022
+ }
28023
+
28024
+ // ../api-core/src/utils/timeback.util.ts
28025
+ function isRecord2(value) {
28026
+ return typeof value === "object" && value !== null;
28027
+ }
28028
+ function filterEnrollmentsByGame(enrollments, gameId) {
28029
+ return enrollments.filter((enrollment) => enrollment.gameId === gameId).map(({ gameId: _, ...enrollment }) => enrollment);
28030
+ }
28031
+ function mapEnrollmentsToUserEnrollments(enrollments, integrations) {
28032
+ const enrollmentByCourse = new Map(enrollments.map((enrollment) => [enrollment.courseId, enrollment]));
28033
+ const courseToSchool = new Map(enrollments.filter((enrollment) => enrollment.school?.id).map((enrollment) => [enrollment.courseId, enrollment.school.id]));
28034
+ return integrations.map((integration) => {
28035
+ const enrollment = enrollmentByCourse.get(integration.courseId);
28036
+ return {
28037
+ gameId: integration.gameId,
28038
+ grade: integration.grade,
28039
+ subject: integration.subject,
28040
+ courseId: integration.courseId,
28041
+ orgId: courseToSchool.get(integration.courseId),
28042
+ ...enrollment ? { id: enrollment.sourcedId } : {}
28043
+ };
28044
+ });
28045
+ }
28046
+ function buildGameTimebackSummaries(integrations) {
28047
+ const summaries = {};
28048
+ for (const integration of integrations) {
28049
+ const summary = summaries[integration.gameId] ?? {
28050
+ subject: null,
28051
+ hasActiveIntegration: false,
28052
+ hasRemovedIntegration: false
28053
+ };
28054
+ const isRemoved = integration.status === DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS;
28055
+ if (isRemoved) {
28056
+ summary.hasRemovedIntegration = true;
28057
+ } else {
28058
+ summary.hasActiveIntegration = true;
28059
+ summary.subject ??= integration.subject;
28060
+ }
28061
+ summaries[integration.gameId] = summary;
28062
+ }
28063
+ return summaries;
28064
+ }
28065
+ function getStringValue(value) {
28066
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
28067
+ }
28068
+ function parseSourcedIdFromUrl(url) {
28069
+ if (!url) {
28070
+ return;
28071
+ }
28072
+ const trimmed = url.trim().replace(/\/$/, "");
28073
+ if (!trimmed) {
28074
+ return;
28075
+ }
28076
+ const segments = trimmed.split("/");
28077
+ const lastSegment = segments.at(-1);
28078
+ return lastSegment ? decodeURIComponent(lastSegment) : undefined;
28079
+ }
28080
+ function getGeneratedMetricValue(event, type) {
28081
+ const items = event.generated?.items;
28082
+ if (!Array.isArray(items)) {
28083
+ return;
28084
+ }
28085
+ const metric = items.find((item) => item?.type === type);
28086
+ if (!metric) {
28087
+ return;
28088
+ }
28089
+ const value = typeof metric.value === "number" ? metric.value : Number(metric.value);
28090
+ return Number.isFinite(value) ? value : undefined;
28091
+ }
28092
+ function getMergedCaliperExtensions(event) {
28093
+ const objectActivityExtensions = isRecord2(event.object.activity?.extensions) ? event.object.activity.extensions : undefined;
28094
+ const generatedExtensions = isRecord2(event.generated?.extensions) ? event.generated.extensions : undefined;
28095
+ const eventExtensions = isRecord2(event.extensions) ? event.extensions : undefined;
28096
+ return {
28097
+ ...objectActivityExtensions,
28098
+ ...generatedExtensions,
28099
+ ...eventExtensions
28100
+ };
28101
+ }
28102
+ function getPlaycademyMetadata(event) {
28103
+ const extensions = getMergedCaliperExtensions(event);
28104
+ return isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
28105
+ }
28106
+ function getActivityId(event, playcademy) {
28107
+ const metadataActivityId = getStringValue(playcademy?.activityId);
28108
+ if (metadataActivityId) {
28109
+ return metadataActivityId;
28110
+ }
28111
+ const activityId = getStringValue(event.object.activity?.id);
28112
+ if (activityId) {
28113
+ return activityId;
28114
+ }
28115
+ const objectId = getStringValue(event.object.id);
28116
+ if (!objectId) {
28117
+ return;
28118
+ }
28119
+ const trimmed = objectId.replace(/\/$/, "");
28120
+ const segments = trimmed.split("/");
28121
+ const activityIndex = segments.lastIndexOf("activities");
28122
+ if (activityIndex !== -1 && segments.length >= activityIndex + 3) {
28123
+ const candidate = segments[activityIndex + 2];
28124
+ return candidate ? decodeURIComponent(candidate) : undefined;
28125
+ }
28126
+ return;
28127
+ }
28128
+ function buildResourceMetadata({
28129
+ baseMetadata,
28130
+ subject,
28131
+ grade,
28132
+ totalXp,
28133
+ masterableUnits
28134
+ }) {
28135
+ const normalizedBaseMetadata = isResourceMetadata(baseMetadata) ? baseMetadata : undefined;
28136
+ const metadata2 = {
28137
+ ...normalizedBaseMetadata
28138
+ };
28139
+ metadata2.subject = subject;
28140
+ metadata2.grades = [grade];
28141
+ metadata2.xp = totalXp;
28142
+ if (masterableUnits !== undefined && masterableUnits !== null) {
28143
+ const existingPlaycademy = isPlaycademyResourceMetadata(metadata2.playcademy) ? metadata2.playcademy : undefined;
28144
+ metadata2.playcademy = {
28145
+ ...existingPlaycademy,
28146
+ mastery: {
28147
+ ...existingPlaycademy?.mastery,
28148
+ masterableUnits
28149
+ }
28150
+ };
28151
+ }
28152
+ return metadata2;
28153
+ }
28154
+ function getDurationSecondsFromExtensions(event) {
28155
+ const extensions = getMergedCaliperExtensions(event);
28156
+ const playcademy = isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
28157
+ const rawValue = extensions.durationSeconds ?? playcademy?.durationSeconds;
28158
+ const value = typeof rawValue === "number" ? rawValue : Number(rawValue);
28159
+ return Number.isFinite(value) ? value : undefined;
28160
+ }
28161
+ function getCanonicalRunId(session2) {
28162
+ const sessionId = getStringValue(session2?.id);
28163
+ if (!sessionId) {
28164
+ return;
28165
+ }
28166
+ return sessionId.replace(/^urn:uuid:/, "");
28167
+ }
28168
+ function getResumeId(event) {
28169
+ const playcademy = getPlaycademyMetadata(event);
28170
+ return getStringValue(playcademy?.resumeId);
28171
+ }
28172
+ function isCaliperRemediationOrCompletionEvent(event) {
28173
+ const playcademy = getPlaycademyMetadata(event);
28174
+ return REMEDIATION_OR_COMPLETION_EVENT_KINDS.has(getStringValue(playcademy?.eventKind) || "");
28175
+ }
28176
+ function groupCaliperEventsByRun(events) {
28177
+ const groups = new Map;
28178
+ for (const event of events) {
28179
+ const objectId = getStringValue(event.object.id) || "unknown-activity";
28180
+ const groupKey = `${objectId}::${getStringValue(event.session?.id) || event.externalId}`;
28181
+ const existing = groups.get(groupKey);
28182
+ if (existing) {
28183
+ existing.push(event);
28184
+ } else {
28185
+ groups.set(groupKey, [event]);
28186
+ }
28187
+ }
28188
+ return groups;
28189
+ }
28190
+ function findCaliperEventGroupContainingExternalId(events, externalId) {
28191
+ const targetExternalId = externalId.trim();
28192
+ if (!targetExternalId) {
28193
+ return;
28194
+ }
28195
+ return [...groupCaliperEventsByRun(events).values()].find((group) => group.some((event) => event.externalId === targetExternalId));
28196
+ }
28197
+ function mapCaliperEventGroupToActivity(events, relevantCourseIds) {
28198
+ if (events.length === 0) {
28199
+ return null;
28200
+ }
28201
+ const sortedEvents = events.toSorted((a, b) => a.eventTime.localeCompare(b.eventTime));
28202
+ const activityEvent = [...sortedEvents].toReversed().find((event) => event.type === "ActivityEvent");
28203
+ const contextSource = activityEvent || sortedEvents.at(-1);
28204
+ if (!contextSource) {
28205
+ return null;
28206
+ }
28207
+ const ctx = parseCaliperEventContext(contextSource, relevantCourseIds);
28208
+ if (!ctx) {
28209
+ return null;
28210
+ }
28211
+ const score = activityEvent !== undefined ? (() => {
28212
+ const totalQuestions = getGeneratedMetricValue(activityEvent, "totalQuestions");
28213
+ const correctQuestions = getGeneratedMetricValue(activityEvent, "correctQuestions");
28214
+ if (totalQuestions === undefined || correctQuestions === undefined || totalQuestions <= 0) {
28215
+ return;
28216
+ }
28217
+ return correctQuestions / totalQuestions * 100;
28218
+ })() : undefined;
28219
+ const xpEarned = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "xpEarned") : undefined;
28220
+ const masteredUnits = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "masteredUnits") : undefined;
28221
+ const timeSpentEvents = sortedEvents.filter((event) => event.type === "TimeSpentEvent");
28222
+ let totalActiveTimeSeconds;
28223
+ if (timeSpentEvents.length > 0) {
28224
+ totalActiveTimeSeconds = timeSpentEvents.reduce((sum, event) => sum + (getGeneratedMetricValue(event, "active") ?? 0), 0);
28225
+ } else if (activityEvent !== undefined) {
28226
+ totalActiveTimeSeconds = getDurationSecondsFromExtensions(activityEvent);
28227
+ }
28228
+ const fallbackActivityId = getActivityId(contextSource, getPlaycademyMetadata(contextSource));
28229
+ const occurredAt = getStringValue(activityEvent?.eventTime) || getStringValue(sortedEvents.at(-1)?.eventTime);
28230
+ const runId = getCanonicalRunId(contextSource.session);
28231
+ const resumeIds = new Set(sortedEvents.map((event) => getResumeId(event)).filter((resumeId) => resumeId !== undefined));
28232
+ const sessionCount = resumeIds.size > 0 ? resumeIds.size : 1;
28233
+ const kind = activityEvent !== undefined ? "activity" : "activity-in-progress";
28234
+ if (!occurredAt) {
28235
+ return null;
28236
+ }
28237
+ return {
28238
+ id: activityEvent?.externalId || sortedEvents.at(-1)?.externalId || events[0].externalId,
28239
+ kind,
28240
+ occurredAt,
28241
+ courseId: ctx.courseId,
28242
+ title: getStringValue(activityEvent?.object.activity?.name) || ctx.titleFromEvent || (fallbackActivityId ? kebabToTitleCase(fallbackActivityId) : "Activity completed"),
28243
+ ...ctx.activityId ? { activityId: ctx.activityId } : {},
28244
+ ...ctx.appName ? { appName: ctx.appName } : {},
28245
+ ...score !== undefined ? { score } : {},
28246
+ ...xpEarned !== undefined ? { xpDelta: xpEarned } : {},
28247
+ ...masteredUnits !== undefined ? { masteredUnitsDelta: masteredUnits } : {},
28248
+ ...totalActiveTimeSeconds !== undefined ? { timeDeltaSeconds: totalActiveTimeSeconds } : {},
28249
+ ...runId ? { runId } : {},
28250
+ ...sessionCount > 0 ? { sessionCount } : {}
28251
+ };
28252
+ }
28253
+ function parseCaliperEventContext(event, relevantCourseIds) {
28254
+ const playcademy = getPlaycademyMetadata(event);
28255
+ const courseId = getStringValue(playcademy?.courseId) || parseSourcedIdFromUrl(event.object.course?.id);
28256
+ if (!courseId || !relevantCourseIds.has(courseId)) {
28257
+ return null;
28258
+ }
28259
+ const occurredAt = getStringValue(event.eventTime);
28260
+ if (!occurredAt) {
28261
+ return null;
28262
+ }
28263
+ return {
28264
+ courseId,
28265
+ occurredAt,
28266
+ eventKind: getStringValue(playcademy?.eventKind),
28267
+ source: getStringValue(playcademy?.source),
28268
+ reason: getStringValue(playcademy?.reason),
28269
+ titleFromEvent: getStringValue(event.object.activity?.name),
28270
+ appName: getStringValue(event.object.app?.name),
28271
+ activityId: getActivityId(event, playcademy)
28272
+ };
28273
+ }
28274
+ function mapTimeSpentRemediation(event, ctx) {
28275
+ if (ctx.eventKind !== "remediation-time") {
28276
+ return null;
28277
+ }
28278
+ return {
28279
+ id: event.externalId,
28280
+ kind: "remediation-time",
28281
+ occurredAt: ctx.occurredAt,
28282
+ courseId: ctx.courseId,
28283
+ title: "Time Adjustment",
28284
+ activityId: ctx.activityId,
28285
+ appName: ctx.appName,
28286
+ reason: ctx.reason,
28287
+ timeDeltaSeconds: getGeneratedMetricValue(event, "active")
28288
+ };
28289
+ }
28290
+ function mapActivityRemediation(event, ctx) {
28291
+ if (ctx.eventKind === "remediation-xp") {
28292
+ return {
28293
+ id: event.externalId,
28294
+ kind: "remediation-xp",
28295
+ occurredAt: ctx.occurredAt,
28296
+ courseId: ctx.courseId,
28297
+ title: "XP Adjustment",
28298
+ activityId: ctx.activityId,
28299
+ appName: ctx.appName,
28300
+ reason: ctx.reason,
28301
+ xpDelta: getGeneratedMetricValue(event, "xpEarned"),
28302
+ masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
28303
+ };
28304
+ }
28305
+ if (ctx.eventKind === "remediation-mastery") {
28306
+ return {
28307
+ id: event.externalId,
28308
+ kind: "remediation-mastery",
28309
+ occurredAt: ctx.occurredAt,
28310
+ courseId: ctx.courseId,
28311
+ title: "Mastery Adjustment",
28312
+ activityId: ctx.activityId,
28313
+ appName: ctx.appName,
28314
+ reason: ctx.reason,
28315
+ xpDelta: getGeneratedMetricValue(event, "xpEarned"),
28316
+ masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
28317
+ };
28318
+ }
28319
+ if (ctx.eventKind === "course-completed") {
28320
+ return {
28321
+ id: event.externalId,
28322
+ kind: "course-completed",
28323
+ occurredAt: ctx.occurredAt,
28324
+ courseId: ctx.courseId,
28325
+ title: ctx.source === "admin" ? "Course marked complete" : "Course completed",
28326
+ activityId: ctx.activityId,
28327
+ appName: ctx.appName,
28328
+ reason: ctx.reason
28329
+ };
28330
+ }
28331
+ if (ctx.eventKind === "course-resumed") {
28332
+ return {
28333
+ id: event.externalId,
28334
+ kind: "course-resumed",
28335
+ occurredAt: ctx.occurredAt,
28336
+ courseId: ctx.courseId,
28337
+ title: "Course resumed",
28338
+ activityId: ctx.activityId,
28339
+ appName: ctx.appName,
28340
+ reason: ctx.reason
28341
+ };
28342
+ }
28343
+ return null;
28344
+ }
28345
+ function mapCaliperEventToRemediationActivity(event, relevantCourseIds) {
28346
+ const ctx = parseCaliperEventContext(event, relevantCourseIds);
28347
+ if (!ctx) {
28348
+ return null;
28349
+ }
28350
+ if (event.type === "TimeSpentEvent") {
28351
+ return mapTimeSpentRemediation(event, ctx);
28352
+ }
28353
+ if (event.type === "ActivityEvent") {
28354
+ return mapActivityRemediation(event, ctx);
28355
+ }
28356
+ return null;
28357
+ }
28358
+ var REMEDIATION_OR_COMPLETION_EVENT_KINDS;
28359
+ var init_timeback_util = __esm(() => {
28360
+ init_helpers_index();
28361
+ init_types2();
28362
+ REMEDIATION_OR_COMPLETION_EVENT_KINDS = new Set([
28363
+ "remediation-xp",
28364
+ "remediation-time",
28365
+ "remediation-mastery",
28366
+ "course-completed",
28367
+ "course-resumed"
28368
+ ]);
28369
+ });
28370
+
27780
28371
  // ../api-core/src/services/game.service.ts
27781
28372
  var inFlightManifestFetches, GameService;
27782
28373
  var init_game_service = __esm(() => {
27783
28374
  init_drizzle_orm();
27784
28375
  init_src();
28376
+ init_helpers_index();
27785
28377
  init_tables_index();
27786
28378
  init_spans();
27787
28379
  init_errors();
27788
28380
  init_deployment_util();
28381
+ init_timeback_util();
27789
28382
  inFlightManifestFetches = new Map;
27790
28383
  GameService = class GameService {
27791
28384
  deps;
@@ -27929,6 +28522,7 @@ var init_game_service = __esm(() => {
27929
28522
  const db2 = this.deps.db;
27930
28523
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
27931
28524
  columns: { gameId: true, subject: true },
28525
+ where: isActiveGameTimebackIntegrationStatus(),
27932
28526
  orderBy: [asc(gameTimebackIntegrations.createdAt)]
27933
28527
  });
27934
28528
  const subjectMap = {};
@@ -27939,6 +28533,26 @@ var init_game_service = __esm(() => {
27939
28533
  }
27940
28534
  return subjectMap;
27941
28535
  }
28536
+ async getTimebackSummaries(user) {
28537
+ const db2 = this.deps.db;
28538
+ const canSeeAllGames = user.role === "admin" || user.role === "teacher";
28539
+ let accessibleGameIds = null;
28540
+ if (!canSeeAllGames) {
28541
+ const accessibleGames = await this.listAccessible(user);
28542
+ accessibleGameIds = new Set(accessibleGames.map((game2) => game2.id));
28543
+ }
28544
+ if (accessibleGameIds?.size === 0) {
28545
+ return {};
28546
+ }
28547
+ const integrations = await db2.query.gameTimebackIntegrations.findMany({
28548
+ columns: { gameId: true, subject: true, status: true },
28549
+ ...accessibleGameIds && {
28550
+ where: inArray(gameTimebackIntegrations.gameId, [...accessibleGameIds])
28551
+ },
28552
+ orderBy: [asc(gameTimebackIntegrations.createdAt)]
28553
+ });
28554
+ return buildGameTimebackSummaries(integrations);
28555
+ }
27942
28556
  async getById(gameId, caller) {
27943
28557
  const db2 = this.deps.db;
27944
28558
  const game2 = await db2.query.games.findFirst({
@@ -28576,7 +29190,7 @@ var init_client2 = () => {};
28576
29190
 
28577
29191
  // ../alerts/src/discord/types.ts
28578
29192
  var DiscordColors;
28579
- var init_types2 = __esm(() => {
29193
+ var init_types3 = __esm(() => {
28580
29194
  DiscordColors = {
28581
29195
  DEFAULT: 0,
28582
29196
  WHITE: 16777215,
@@ -28614,7 +29228,7 @@ var init_types2 = __esm(() => {
28614
29228
  // ../alerts/src/discord/index.ts
28615
29229
  var init_discord = __esm(() => {
28616
29230
  init_client2();
28617
- init_types2();
29231
+ init_types3();
28618
29232
  });
28619
29233
 
28620
29234
  // ../api-core/src/services/alerts.service.ts
@@ -29745,7 +30359,7 @@ var init_secrets_service = __esm(() => {
29745
30359
 
29746
30360
  // ../edge-play/src/constants.ts
29747
30361
  var ASSET_ROUTE_PREFIX = "/api/assets/", ROUTES;
29748
- var init_constants3 = __esm(() => {
30362
+ var init_constants4 = __esm(() => {
29749
30363
  init_src();
29750
30364
  ROUTES = {
29751
30365
  INDEX: "/api",
@@ -29772,7 +30386,7 @@ function prefixSecrets(secrets) {
29772
30386
  }
29773
30387
  var init_setup2 = __esm(() => {
29774
30388
  init_src();
29775
- init_constants3();
30389
+ init_constants4();
29776
30390
  });
29777
30391
 
29778
30392
  // ../api-core/src/services/seed.service.ts
@@ -30497,11 +31111,11 @@ var init_schemas3 = __esm(() => {
30497
31111
  });
30498
31112
 
30499
31113
  // ../data/src/domains/timeback/schemas.ts
30500
- function isTimebackGrade(value) {
31114
+ function isTimebackGrade2(value) {
30501
31115
  return Number.isInteger(value) && TIMEBACK_GRADES.includes(value);
30502
31116
  }
30503
- function isTimebackSubject(value) {
30504
- return TIMEBACK_SUBJECTS.includes(value);
31117
+ function isTimebackSubject2(value) {
31118
+ return TIMEBACK_SUBJECTS2.includes(value);
30505
31119
  }
30506
31120
  function isValidAdminAttributionDate(value) {
30507
31121
  const match = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
@@ -30515,13 +31129,13 @@ function isValidAdminAttributionDate(value) {
30515
31129
  const date3 = new Date(Date.UTC(year, month - 1, day, 12, 0, 0));
30516
31130
  return date3.getUTCFullYear() === year && date3.getUTCMonth() + 1 === month && date3.getUTCDate() === day;
30517
31131
  }
30518
- var TIMEBACK_GRADES, TIMEBACK_SUBJECTS, TimebackGradeSchema, TimebackSubjectSchema, CourseGoalsSchema, UpdateGameTimebackIntegrationRequestSchema, TimebackActivityDataSchema, EndActivityRequestSchema, GameRunMetricsSchema, GameCourseMetricsSchema, GameMetricsResponseSchema, AdvanceCourseRequestSchema, UnenrollCourseRequestSchema, HeartbeatRequestSchema, PopulateStudentRequestSchema, DerivedPlatformCourseConfigSchema, TimebackBaseConfigSchema, PlatformTimebackSetupRequestSchema, AdminTimebackMutationBaseSchema, AdminAttributionDateSchema, ADMIN_GRANT_XP_MIN = -1e5, ADMIN_GRANT_XP_MAX = 1e5, ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE, GrantTimebackXpRequestSchema, AdjustTimebackTimeRequestSchema, AdjustTimebackMasteryRequestSchema, ReconcileMasteryForConfigChangeSchema, EnrollStudentRequestSchema, UnenrollStudentRequestSchema, ReactivateEnrollmentRequestSchema, VerifyTimebackMetricDiscrepancyRequestSchema, InsertAssessmentTestSchema, CreateAssessmentRequestSchema, ReorderAssessmentsRequestSchema, ReorderQuestionsRequestSchema;
31132
+ var TIMEBACK_GRADES, TIMEBACK_SUBJECTS2, TimebackGradeSchema, TimebackSubjectSchema, CourseGoalsSchema, UpdateGameTimebackIntegrationRequestSchema, CreateGameTimebackIntegrationRequestSchema, TimebackActivityDataSchema, EndActivityRequestSchema, GameRunMetricsSchema, GameCourseMetricsSchema, GameMetricsResponseSchema, AdvanceCourseRequestSchema, UnenrollCourseRequestSchema, HeartbeatRequestSchema, PopulateStudentRequestSchema, DerivedPlatformCourseConfigSchema, TimebackBaseConfigSchema, PlatformTimebackSetupRequestSchema, AdminTimebackMutationBaseSchema, AdminAttributionDateSchema, ADMIN_GRANT_XP_MIN = -1e5, ADMIN_GRANT_XP_MAX = 1e5, ADMIN_GRANT_XP_AMOUNT_RANGE_MESSAGE, GrantTimebackXpRequestSchema, AdjustTimebackTimeRequestSchema, AdjustTimebackMasteryRequestSchema, ReconcileMasteryForConfigChangeSchema, EnrollStudentRequestSchema, UnenrollStudentRequestSchema, ReactivateEnrollmentRequestSchema, VerifyTimebackMetricDiscrepancyRequestSchema, InsertAssessmentTestSchema, CreateAssessmentRequestSchema, ReorderAssessmentsRequestSchema, ReorderQuestionsRequestSchema;
30519
31133
  var init_schemas4 = __esm(() => {
30520
31134
  init_drizzle_zod();
30521
31135
  init_esm();
30522
31136
  init_table7();
30523
31137
  TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
30524
- TIMEBACK_SUBJECTS = [
31138
+ TIMEBACK_SUBJECTS2 = [
30525
31139
  "Reading",
30526
31140
  "Language",
30527
31141
  "Vocabulary",
@@ -30535,7 +31149,7 @@ var init_schemas4 = __esm(() => {
30535
31149
  TimebackGradeSchema = exports_external.number().int().refine((val) => TIMEBACK_GRADES.includes(val), {
30536
31150
  message: `Grade must be one of: ${TIMEBACK_GRADES.join(", ")}`
30537
31151
  });
30538
- TimebackSubjectSchema = exports_external.enum(TIMEBACK_SUBJECTS);
31152
+ TimebackSubjectSchema = exports_external.enum(TIMEBACK_SUBJECTS2);
30539
31153
  CourseGoalsSchema = exports_external.object({
30540
31154
  dailyXp: exports_external.number().int().nonnegative().nullable().optional(),
30541
31155
  dailyLessons: exports_external.number().int().nonnegative().nullable().optional(),
@@ -30554,6 +31168,15 @@ var init_schemas4 = __esm(() => {
30554
31168
  isSupplemental: exports_external.boolean().optional(),
30555
31169
  timebackVisible: exports_external.boolean().nullable().optional()
30556
31170
  });
31171
+ CreateGameTimebackIntegrationRequestSchema = exports_external.object({
31172
+ title: exports_external.string().trim().min(1),
31173
+ courseCode: exports_external.string().trim().min(1),
31174
+ subject: TimebackSubjectSchema,
31175
+ grade: TimebackGradeSchema,
31176
+ totalXp: exports_external.number().int().positive(),
31177
+ masterableUnits: exports_external.number().int().nonnegative(),
31178
+ level: exports_external.string().trim().min(1).optional()
31179
+ });
30557
31180
  TimebackActivityDataSchema = exports_external.object({
30558
31181
  activityId: exports_external.string().min(1),
30559
31182
  activityName: exports_external.string().optional(),
@@ -30999,10 +31622,6 @@ var init_log = __esm(() => {
30999
31622
  init_ansi();
31000
31623
  init_spinner();
31001
31624
  });
31002
- // ../utils/src/string.ts
31003
- function kebabToTitleCase(kebabStr) {
31004
- return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
31005
- }
31006
31625
  // ../utils/src/timezone.ts
31007
31626
  function formatDateYMDInTimezone(timeZone, date3 = new Date) {
31008
31627
  const parts2 = new Intl.DateTimeFormat("en-US", {
@@ -31112,16 +31731,45 @@ var init_src4 = __esm(() => {
31112
31731
  });
31113
31732
 
31114
31733
  // ../timeback/dist/index.js
31734
+ import { createHash } from "node:crypto";
31115
31735
  import { AsyncLocalStorage } from "node:async_hooks";
31116
31736
  function createOneRosterUrls(baseUrl) {
31117
- const effective = baseUrl || TIMEBACK_API_URLS.production;
31737
+ const effective = baseUrl || TIMEBACK_API_URLS2.production;
31118
31738
  const base = effective.replace(/\/$/, "");
31119
31739
  return {
31120
- user: (userId) => `${base}${ONEROSTER_ENDPOINTS.users}/${userId}`,
31121
- course: (courseId) => `${base}${ONEROSTER_ENDPOINTS.courses}/${courseId}`,
31122
- componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS.componentResources}/${resourceId}`
31740
+ user: (userId) => `${base}${ONEROSTER_ENDPOINTS2.users}/${userId}`,
31741
+ course: (courseId) => `${base}${ONEROSTER_ENDPOINTS2.courses}/${courseId}`,
31742
+ componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS2.componentResources}/${resourceId}`
31123
31743
  };
31124
31744
  }
31745
+ function resolveCourseIdFromCourseUrl(url2) {
31746
+ try {
31747
+ const parts2 = new URL(url2).pathname.split("/").filter(Boolean);
31748
+ const maybeCourses = parts2.at(-2);
31749
+ const maybeId = parts2.at(-1);
31750
+ if (maybeCourses !== "courses" || !maybeId) {
31751
+ return null;
31752
+ }
31753
+ if (UUID_REGEX2.test(maybeId)) {
31754
+ return maybeId;
31755
+ }
31756
+ if (maybeId.length > 2 && !maybeId.includes("/")) {
31757
+ return maybeId;
31758
+ }
31759
+ return null;
31760
+ } catch {
31761
+ return null;
31762
+ }
31763
+ }
31764
+ function computeCaliperLineItemId(objectId, courseSourcedId, courseUrl) {
31765
+ const recovered = resolveCourseIdFromCourseUrl(courseUrl);
31766
+ if (recovered !== courseSourcedId) {
31767
+ throw new ConfigurationError("courseId", `Course id "${courseSourcedId}" is not URL-safe: Timeback Platform would parse it back as ${recovered === null ? "null" : `"${recovered}"`} from the Caliper event, producing a different gradebook line item. Use a UUID or an id with no spaces, slashes, or non-ASCII characters.`);
31768
+ }
31769
+ const idParts = [objectId, courseSourcedId].join("_");
31770
+ const hashedId = createHash("sha256").update(idParts).digest("hex");
31771
+ return `caliper_${hashedId}`;
31772
+ }
31125
31773
  function deriveSourcedIds(courseId) {
31126
31774
  return {
31127
31775
  course: courseId,
@@ -31133,7 +31781,7 @@ function deriveSourcedIds(courseId) {
31133
31781
  async function fetchTimebackConfig(client, courseId) {
31134
31782
  const sourcedIds = deriveSourcedIds(courseId);
31135
31783
  const [org, course, component, resource, componentResource] = await Promise.all([
31136
- client.oneroster.organizations.get(PLAYCADEMY_DEFAULTS.organization),
31784
+ client.oneroster.organizations.get(PLAYCADEMY_DEFAULTS2.organization),
31137
31785
  client.oneroster.courses.get(sourcedIds.course),
31138
31786
  client.oneroster.courseComponents.get(sourcedIds.component),
31139
31787
  client.oneroster.resources.get(sourcedIds.resource),
@@ -31143,7 +31791,7 @@ async function fetchTimebackConfig(client, courseId) {
31143
31791
  organization: {
31144
31792
  name: org.name,
31145
31793
  type: org.type,
31146
- identifier: org.identifier || PLAYCADEMY_DEFAULTS.organization
31794
+ identifier: org.identifier || PLAYCADEMY_DEFAULTS2.organization
31147
31795
  },
31148
31796
  course: {
31149
31797
  title: course.title || "",
@@ -31203,23 +31851,23 @@ async function verifyTimebackResources(client, courseId) {
31203
31851
  }
31204
31852
  };
31205
31853
  }
31206
- function isObject(value) {
31854
+ function isObject2(value) {
31207
31855
  return typeof value === "object" && value !== null;
31208
31856
  }
31209
- function isPlaycademyResourceMetadata(value) {
31210
- if (!isObject(value)) {
31857
+ function isPlaycademyResourceMetadata2(value) {
31858
+ if (!isObject2(value)) {
31211
31859
  return false;
31212
31860
  }
31213
31861
  if (!("mastery" in value) || value.mastery === undefined) {
31214
31862
  return true;
31215
31863
  }
31216
- return isObject(value.mastery);
31864
+ return isObject2(value.mastery);
31217
31865
  }
31218
- function isTimebackSubject2(value) {
31219
- return typeof value === "string" && SUBJECT_VALUES.includes(value);
31866
+ function isTimebackSubject3(value) {
31867
+ return typeof value === "string" && SUBJECT_VALUES2.includes(value);
31220
31868
  }
31221
- function isTimebackGrade2(value) {
31222
- return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
31869
+ function isTimebackGrade3(value) {
31870
+ return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES2.includes(value);
31223
31871
  }
31224
31872
  async function deleteTimebackResources(client, courseId) {
31225
31873
  const sourcedIds = deriveSourcedIds(courseId);
@@ -31270,6 +31918,15 @@ async function deleteTimebackResources(client, courseId) {
31270
31918
  ]);
31271
31919
  setAttribute("app.timeback.resources_deleted", true);
31272
31920
  }
31921
+ async function updateTimebackCourseStatus(client, courseId, status) {
31922
+ const course = await client.oneroster.courses.get(courseId);
31923
+ await client.oneroster.courses.update(courseId, {
31924
+ ...course,
31925
+ sourcedId: courseId,
31926
+ status
31927
+ });
31928
+ setAttribute("app.timeback.course_status", status);
31929
+ }
31273
31930
  async function createCourse(client, config2) {
31274
31931
  const courseData = {
31275
31932
  status: "active",
@@ -31518,14 +32175,14 @@ async function getTimebackTokenResponse(config2) {
31518
32175
  }
31519
32176
  }
31520
32177
  function getAuthUrl(environment = "production") {
31521
- return TIMEBACK_AUTH_URLS[environment];
32178
+ return TIMEBACK_AUTH_URLS2[environment];
31522
32179
  }
31523
32180
  function parseEduBridgeGrade(value) {
31524
32181
  if (value === null || value === undefined || value.trim() === "") {
31525
32182
  return null;
31526
32183
  }
31527
32184
  const parsed = Number(value);
31528
- return isTimebackGrade2(parsed) ? parsed : null;
32185
+ return isTimebackGrade3(parsed) ? parsed : null;
31529
32186
  }
31530
32187
  function normalizeHighestGradeMastered(response, subject) {
31531
32188
  const grades = {
@@ -31602,12 +32259,12 @@ async function withTimebackClientTelemetry(fn) {
31602
32259
  }
31603
32260
  function handleHttpError(res, errorBody, attempt, retries, context2) {
31604
32261
  const error = new TimebackApiError(res.status, res.statusText, errorBody);
31605
- if (res.status >= HTTP_STATUS.CLIENT_ERROR_MIN && res.status < HTTP_STATUS.CLIENT_ERROR_MAX) {
32262
+ if (res.status >= HTTP_STATUS2.CLIENT_ERROR_MIN && res.status < HTTP_STATUS2.CLIENT_ERROR_MAX) {
31606
32263
  recordTimebackHttpFailure();
31607
32264
  throw error;
31608
32265
  }
31609
32266
  if (attempt < retries) {
31610
- const delay = HTTP_DEFAULTS.retryBackoffBase ** attempt * 1000;
32267
+ const delay = HTTP_DEFAULTS2.retryBackoffBase ** attempt * 1000;
31611
32268
  recordTimebackRetry();
31612
32269
  addEvent("timeback.request_retry", {
31613
32270
  "app.timeback.attempt": attempt + 1,
@@ -31684,7 +32341,7 @@ async function request({
31684
32341
  const result = handleHttpError(res, errorBody, attempt, retries, { method, path });
31685
32342
  lastError = result.error;
31686
32343
  if (result.retry) {
31687
- const delay = HTTP_DEFAULTS.retryBackoffBase ** attempt * 1000;
32344
+ const delay = HTTP_DEFAULTS2.retryBackoffBase ** attempt * 1000;
31688
32345
  await new Promise((resolve) => setTimeout(resolve, delay));
31689
32346
  }
31690
32347
  } else {
@@ -31696,7 +32353,7 @@ async function request({
31696
32353
  }
31697
32354
  lastError = error instanceof Error ? error : new Error(String(error));
31698
32355
  if (attempt < retries) {
31699
- const delay = HTTP_DEFAULTS.retryBackoffBase ** attempt * 1000;
32356
+ const delay = HTTP_DEFAULTS2.retryBackoffBase ** attempt * 1000;
31700
32357
  recordTimebackRetry();
31701
32358
  addEvent("timeback.network_retry", {
31702
32359
  "app.timeback.attempt": attempt + 1,
@@ -31745,10 +32402,10 @@ function createCaliperNamespace(client) {
31745
32402
  const envelope = {
31746
32403
  sensor: sensorUrl,
31747
32404
  sendTime: new Date().toISOString(),
31748
- dataVersion: CALIPER_CONSTANTS.dataVersion,
32405
+ dataVersion: CALIPER_CONSTANTS2.dataVersion,
31749
32406
  data: [event]
31750
32407
  };
31751
- return client["requestCaliper"](CALIPER_ENDPOINTS.event, "POST", envelope);
32408
+ return client["requestCaliper"](CALIPER_ENDPOINTS2.event, "POST", envelope);
31752
32409
  },
31753
32410
  emitBatch: async (events, sensorUrl) => {
31754
32411
  if (events.length === 0) {
@@ -31757,10 +32414,10 @@ function createCaliperNamespace(client) {
31757
32414
  const envelope = {
31758
32415
  sensor: sensorUrl,
31759
32416
  sendTime: new Date().toISOString(),
31760
- dataVersion: CALIPER_CONSTANTS.dataVersion,
32417
+ dataVersion: CALIPER_CONSTANTS2.dataVersion,
31761
32418
  data: events
31762
32419
  };
31763
- return client["requestCaliper"](CALIPER_ENDPOINTS.event, "POST", envelope);
32420
+ return client["requestCaliper"](CALIPER_ENDPOINTS2.event, "POST", envelope);
31764
32421
  },
31765
32422
  events: {
31766
32423
  list: async (params = {}) => {
@@ -31790,7 +32447,7 @@ function createCaliperNamespace(client) {
31790
32447
  query.set(`extensions.${key}`, value);
31791
32448
  }
31792
32449
  }
31793
- const requestPath = `${CALIPER_ENDPOINTS.events}?${query.toString()}`;
32450
+ const requestPath = `${CALIPER_ENDPOINTS2.events}?${query.toString()}`;
31794
32451
  return client["requestCaliper"](requestPath, "GET");
31795
32452
  }
31796
32453
  },
@@ -31800,21 +32457,21 @@ function createCaliperNamespace(client) {
31800
32457
  gameId: data.gameId
31801
32458
  });
31802
32459
  const event = {
31803
- "@context": CALIPER_CONSTANTS.context,
32460
+ "@context": CALIPER_CONSTANTS2.context,
31804
32461
  id: `urn:uuid:${crypto.randomUUID()}`,
31805
- type: TIMEBACK_EVENT_TYPES.activityEvent,
32462
+ type: TIMEBACK_EVENT_TYPES2.activityEvent,
31806
32463
  eventTime: data.eventTime || new Date().toISOString(),
31807
- profile: CALIPER_CONSTANTS.profile,
32464
+ profile: CALIPER_CONSTANTS2.profile,
31808
32465
  actor: {
31809
32466
  id: urls.user(data.studentId),
31810
- type: TIMEBACK_TYPES.user,
32467
+ type: TIMEBACK_TYPES2.user,
31811
32468
  email: data.studentEmail
31812
32469
  },
31813
- action: TIMEBACK_ACTIONS.completed,
32470
+ action: TIMEBACK_ACTIONS2.completed,
31814
32471
  ...data.runId ? { session: `urn:uuid:${data.runId}` } : {},
31815
32472
  object: {
31816
32473
  id: data.objectId || caliper.buildActivityUrl(data),
31817
- type: TIMEBACK_TYPES.activityContext,
32474
+ type: TIMEBACK_TYPES2.activityContext,
31818
32475
  subject: data.subject,
31819
32476
  app: {
31820
32477
  name: data.appName
@@ -31828,25 +32485,25 @@ function createCaliperNamespace(client) {
31828
32485
  },
31829
32486
  generated: {
31830
32487
  id: data.generatedId || `urn:timeback:metrics:activity-completion-${crypto.randomUUID()}`,
31831
- type: TIMEBACK_TYPES.activityMetricsCollection,
32488
+ type: TIMEBACK_TYPES2.activityMetricsCollection,
31832
32489
  ...data.includeAttempt === false ? {} : { attempt: data.attemptNumber || 1 },
31833
32490
  items: [
31834
32491
  ...data.totalQuestions !== undefined ? [
31835
32492
  {
31836
- type: ACTIVITY_METRIC_TYPES.totalQuestions,
32493
+ type: ACTIVITY_METRIC_TYPES2.totalQuestions,
31837
32494
  value: data.totalQuestions
31838
32495
  }
31839
32496
  ] : [],
31840
32497
  ...data.correctQuestions !== undefined ? [
31841
32498
  {
31842
- type: ACTIVITY_METRIC_TYPES.correctQuestions,
32499
+ type: ACTIVITY_METRIC_TYPES2.correctQuestions,
31843
32500
  value: data.correctQuestions
31844
32501
  }
31845
32502
  ] : [],
31846
- ...data.xpEarned !== undefined ? [{ type: ACTIVITY_METRIC_TYPES.xpEarned, value: data.xpEarned }] : [],
32503
+ ...data.xpEarned !== undefined ? [{ type: ACTIVITY_METRIC_TYPES2.xpEarned, value: data.xpEarned }] : [],
31847
32504
  ...data.masteredUnits !== undefined ? [
31848
32505
  {
31849
- type: ACTIVITY_METRIC_TYPES.masteredUnits,
32506
+ type: ACTIVITY_METRIC_TYPES2.masteredUnits,
31850
32507
  value: data.masteredUnits
31851
32508
  }
31852
32509
  ] : []
@@ -31868,21 +32525,21 @@ function createCaliperNamespace(client) {
31868
32525
  gameId: data.gameId
31869
32526
  });
31870
32527
  const event = {
31871
- "@context": CALIPER_CONSTANTS.context,
32528
+ "@context": CALIPER_CONSTANTS2.context,
31872
32529
  id: `urn:uuid:${crypto.randomUUID()}`,
31873
- type: TIMEBACK_EVENT_TYPES.timeSpentEvent,
32530
+ type: TIMEBACK_EVENT_TYPES2.timeSpentEvent,
31874
32531
  eventTime: data.eventTime || new Date().toISOString(),
31875
- profile: CALIPER_CONSTANTS.profile,
32532
+ profile: CALIPER_CONSTANTS2.profile,
31876
32533
  actor: {
31877
32534
  id: urls.user(data.studentId),
31878
- type: TIMEBACK_TYPES.user,
32535
+ type: TIMEBACK_TYPES2.user,
31879
32536
  email: data.studentEmail
31880
32537
  },
31881
- action: TIMEBACK_ACTIONS.spentTime,
32538
+ action: TIMEBACK_ACTIONS2.spentTime,
31882
32539
  ...data.runId ? { session: `urn:uuid:${data.runId}` } : {},
31883
32540
  object: {
31884
32541
  id: caliper.buildActivityUrl(data),
31885
- type: TIMEBACK_TYPES.activityContext,
32542
+ type: TIMEBACK_TYPES2.activityContext,
31886
32543
  subject: data.subject,
31887
32544
  app: {
31888
32545
  name: data.appName
@@ -31895,16 +32552,16 @@ function createCaliperNamespace(client) {
31895
32552
  },
31896
32553
  generated: {
31897
32554
  id: `urn:timeback:metrics:time-spent-${crypto.randomUUID()}`,
31898
- type: TIMEBACK_TYPES.timeSpentMetricsCollection,
32555
+ type: TIMEBACK_TYPES2.timeSpentMetricsCollection,
31899
32556
  items: [
31900
- { type: TIME_METRIC_TYPES.active, value: data.activeTimeSeconds },
32557
+ { type: TIME_METRIC_TYPES2.active, value: data.activeTimeSeconds },
31901
32558
  ...data.inactiveTimeSeconds !== undefined ? [
31902
32559
  {
31903
- type: TIME_METRIC_TYPES.inactive,
32560
+ type: TIME_METRIC_TYPES2.inactive,
31904
32561
  value: data.inactiveTimeSeconds
31905
32562
  }
31906
32563
  ] : [],
31907
- ...data.wasteTimeSeconds !== undefined ? [{ type: TIME_METRIC_TYPES.waste, value: data.wasteTimeSeconds }] : []
32564
+ ...data.wasteTimeSeconds !== undefined ? [{ type: TIME_METRIC_TYPES2.waste, value: data.wasteTimeSeconds }] : []
31908
32565
  ],
31909
32566
  ...data.extensions ? { extensions: data.extensions } : {}
31910
32567
  },
@@ -31915,7 +32572,8 @@ function createCaliperNamespace(client) {
31915
32572
  buildActivityUrl: (data) => {
31916
32573
  const base = data.sensorUrl.replace(/\/$/, "");
31917
32574
  return `${base}/activities/${encodeURIComponent(data.courseId)}/${encodeURIComponent(data.activityId)}`;
31918
- }
32575
+ },
32576
+ buildCourseUrl: (courseId) => urls.course(courseId)
31919
32577
  };
31920
32578
  return caliper;
31921
32579
  }
@@ -32038,17 +32696,17 @@ async function listOneRosterCollection(client, endpoint, collectionKey, options)
32038
32696
  function createOneRosterNamespace(client) {
32039
32697
  return {
32040
32698
  classes: {
32041
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.classes, "POST", { class: data }),
32699
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.classes, "POST", { class: data }),
32042
32700
  get: async (sourcedId) => {
32043
- const res = await client["request"](`${ONEROSTER_ENDPOINTS.classes}/${sourcedId}`, "GET");
32701
+ const res = await client["request"](`${ONEROSTER_ENDPOINTS2.classes}/${sourcedId}`, "GET");
32044
32702
  return res.class;
32045
32703
  },
32046
32704
  update: async (sourcedId, data) => {
32047
- const res = await client["request"](`${ONEROSTER_ENDPOINTS.classes}/${sourcedId}`, "PUT", { class: data });
32705
+ const res = await client["request"](`${ONEROSTER_ENDPOINTS2.classes}/${sourcedId}`, "PUT", { class: data });
32048
32706
  return res.class;
32049
32707
  },
32050
32708
  listByCourse: async (courseSourcedId) => {
32051
- const res = await client["request"](`${ONEROSTER_ENDPOINTS.courses}/${courseSourcedId}/classes`, "GET");
32709
+ const res = await client["request"](`${ONEROSTER_ENDPOINTS2.courses}/${courseSourcedId}/classes`, "GET");
32052
32710
  return res.classes;
32053
32711
  },
32054
32712
  listByStudent: async (userSourcedId, options) => {
@@ -32059,7 +32717,7 @@ function createOneRosterNamespace(client) {
32059
32717
  if (options?.offset) {
32060
32718
  queryParams.set("offset", String(options.offset));
32061
32719
  }
32062
- const endpoint = `${ONEROSTER_ENDPOINTS.users}/${userSourcedId}/classes`;
32720
+ const endpoint = `${ONEROSTER_ENDPOINTS2.users}/${userSourcedId}/classes`;
32063
32721
  const url2 = queryParams.toString() ? `${endpoint}?${queryParams}` : endpoint;
32064
32722
  const res = await client["request"](url2, "GET");
32065
32723
  return res.classes || [];
@@ -32067,7 +32725,7 @@ function createOneRosterNamespace(client) {
32067
32725
  },
32068
32726
  enrollments: {
32069
32727
  get: async (sourcedId) => {
32070
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.enrollments}/${sourcedId}`, "GET");
32728
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.enrollments}/${sourcedId}`, "GET");
32071
32729
  return response.enrollment;
32072
32730
  },
32073
32731
  listByClass: async (classSourcedId, options) => {
@@ -32083,7 +32741,7 @@ function createOneRosterNamespace(client) {
32083
32741
  if (options?.offset) {
32084
32742
  queryParams.set("offset", String(options.offset));
32085
32743
  }
32086
- const url2 = `${ONEROSTER_ENDPOINTS.enrollments}?${queryParams}`;
32744
+ const url2 = `${ONEROSTER_ENDPOINTS2.enrollments}?${queryParams}`;
32087
32745
  try {
32088
32746
  const response = await client["request"](url2, "GET");
32089
32747
  return response.enrollments || [];
@@ -32116,7 +32774,7 @@ function createOneRosterNamespace(client) {
32116
32774
  }
32117
32775
  queryParams.set("filter", filters.join(" AND "));
32118
32776
  queryParams.set("limit", "3000");
32119
- const url2 = `${ONEROSTER_ENDPOINTS.enrollments}?${queryParams}`;
32777
+ const url2 = `${ONEROSTER_ENDPOINTS2.enrollments}?${queryParams}`;
32120
32778
  const response = await client["request"](url2, "GET");
32121
32779
  return response.enrollments || [];
32122
32780
  }));
@@ -32146,72 +32804,72 @@ function createOneRosterNamespace(client) {
32146
32804
  throw error;
32147
32805
  }
32148
32806
  },
32149
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.enrollments, "POST", { enrollment: data }),
32807
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.enrollments, "POST", { enrollment: data }),
32150
32808
  update: async (sourcedId, data) => {
32151
- await client["request"](`${ONEROSTER_ENDPOINTS.enrollments}/${sourcedId}`, "PUT", {
32809
+ await client["request"](`${ONEROSTER_ENDPOINTS2.enrollments}/${sourcedId}`, "PUT", {
32152
32810
  enrollment: data
32153
32811
  });
32154
32812
  },
32155
32813
  delete: async (sourcedId) => {
32156
- await client["request"](`${ONEROSTER_ENDPOINTS.enrollments}/${sourcedId}`, "DELETE");
32814
+ await client["request"](`${ONEROSTER_ENDPOINTS2.enrollments}/${sourcedId}`, "DELETE");
32157
32815
  }
32158
32816
  },
32159
32817
  organizations: {
32160
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.organizations, "POST", data),
32161
- get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "GET").then((res) => res.org),
32162
- update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "PUT", data)
32818
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.organizations, "POST", data),
32819
+ get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS2.organizations}/${sourcedId}`, "GET").then((res) => res.org),
32820
+ update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS2.organizations}/${sourcedId}`, "PUT", data)
32163
32821
  },
32164
32822
  courses: {
32165
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.courses, "POST", data),
32823
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.courses, "POST", data),
32166
32824
  get: async (sourcedId) => {
32167
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.courses}/${sourcedId}`, "GET");
32825
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.courses}/${sourcedId}`, "GET");
32168
32826
  return response.course;
32169
32827
  },
32170
32828
  update: async (sourcedId, data) => {
32171
- await client["request"](`${ONEROSTER_ENDPOINTS.courses}/${sourcedId}`, "PUT", {
32829
+ await client["request"](`${ONEROSTER_ENDPOINTS2.courses}/${sourcedId}`, "PUT", {
32172
32830
  course: data
32173
32831
  });
32174
32832
  }
32175
32833
  },
32176
32834
  courseComponents: {
32177
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.courseComponents, "POST", data),
32835
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.courseComponents, "POST", data),
32178
32836
  get: async (sourcedId) => {
32179
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.courseComponents}/${sourcedId}`, "GET");
32837
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.courseComponents}/${sourcedId}`, "GET");
32180
32838
  return response.courseComponent;
32181
32839
  },
32182
32840
  update: async (sourcedId, data) => {
32183
- await client["request"](`${ONEROSTER_ENDPOINTS.courseComponents}/${sourcedId}`, "PUT", { courseComponent: data });
32841
+ await client["request"](`${ONEROSTER_ENDPOINTS2.courseComponents}/${sourcedId}`, "PUT", { courseComponent: data });
32184
32842
  }
32185
32843
  },
32186
32844
  resources: {
32187
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.resources, "POST", data),
32845
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.resources, "POST", data),
32188
32846
  get: async (sourcedId) => {
32189
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.resources}/${sourcedId}`, "GET");
32847
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.resources}/${sourcedId}`, "GET");
32190
32848
  return response.resource;
32191
32849
  },
32192
32850
  update: async (sourcedId, data) => {
32193
- await client["request"](`${ONEROSTER_ENDPOINTS.resources}/${sourcedId}`, "PUT", {
32851
+ await client["request"](`${ONEROSTER_ENDPOINTS2.resources}/${sourcedId}`, "PUT", {
32194
32852
  resource: data
32195
32853
  });
32196
32854
  },
32197
32855
  delete: async (sourcedId) => {
32198
- await client["request"](`${ONEROSTER_ENDPOINTS.resources}/${sourcedId}`, "DELETE");
32856
+ await client["request"](`${ONEROSTER_ENDPOINTS2.resources}/${sourcedId}`, "DELETE");
32199
32857
  }
32200
32858
  },
32201
32859
  componentResources: {
32202
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.componentResources, "POST", data),
32860
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.componentResources, "POST", data),
32203
32861
  get: async (sourcedId) => {
32204
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.componentResources}/${sourcedId}`, "GET");
32862
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.componentResources}/${sourcedId}`, "GET");
32205
32863
  return response.componentResource;
32206
32864
  },
32207
32865
  update: async (sourcedId, data) => {
32208
- await client["request"](`${ONEROSTER_ENDPOINTS.componentResources}/${sourcedId}`, "PUT", { componentResource: data });
32866
+ await client["request"](`${ONEROSTER_ENDPOINTS2.componentResources}/${sourcedId}`, "PUT", { componentResource: data });
32209
32867
  }
32210
32868
  },
32211
32869
  assessmentLineItems: {
32212
32870
  list: async (options) => {
32213
32871
  try {
32214
- return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS.assessmentLineItems, "assessmentLineItems", options);
32872
+ return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentLineItems, "assessmentLineItems", options);
32215
32873
  } catch (error) {
32216
32874
  logTimebackError("list assessment line items", error, {
32217
32875
  filter: options?.filter
@@ -32219,14 +32877,14 @@ function createOneRosterNamespace(client) {
32219
32877
  return [];
32220
32878
  }
32221
32879
  },
32222
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.assessmentLineItems, "POST", { assessmentLineItem: data }),
32880
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.assessmentLineItems, "POST", { assessmentLineItem: data }),
32223
32881
  get: async (sourcedId) => {
32224
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.assessmentLineItems}/${sourcedId}`, "GET");
32882
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.assessmentLineItems}/${sourcedId}`, "GET");
32225
32883
  return response.assessmentLineItem;
32226
32884
  },
32227
32885
  findOrCreate: async (sourcedId, data) => {
32228
32886
  try {
32229
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.assessmentLineItems}/${sourcedId}`, "GET");
32887
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.assessmentLineItems}/${sourcedId}`, "GET");
32230
32888
  return response.assessmentLineItem;
32231
32889
  } catch {
32232
32890
  const createData = {
@@ -32235,7 +32893,7 @@ function createOneRosterNamespace(client) {
32235
32893
  dateLastModified: new Date().toISOString()
32236
32894
  };
32237
32895
  try {
32238
- const response = await client["request"](ONEROSTER_ENDPOINTS.assessmentLineItems, "POST", { assessmentLineItem: createData });
32896
+ const response = await client["request"](ONEROSTER_ENDPOINTS2.assessmentLineItems, "POST", { assessmentLineItem: createData });
32239
32897
  if (!response.sourcedIdPairs?.allocatedSourcedId) {
32240
32898
  throw new Error("Invalid response from OneRoster API - missing allocatedSourcedId");
32241
32899
  }
@@ -32250,7 +32908,7 @@ function createOneRosterNamespace(client) {
32250
32908
  assessmentResults: {
32251
32909
  list: async (options) => {
32252
32910
  try {
32253
- return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS.assessmentResults, "assessmentResults", options);
32911
+ return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentResults, "assessmentResults", options);
32254
32912
  } catch (error) {
32255
32913
  logTimebackError("list assessment results", error, {
32256
32914
  filter: options?.filter
@@ -32258,10 +32916,11 @@ function createOneRosterNamespace(client) {
32258
32916
  return [];
32259
32917
  }
32260
32918
  },
32261
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.assessmentResults, "POST", { assessmentResult: data }),
32919
+ listOrThrow: async (options) => await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentResults, "assessmentResults", options),
32920
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.assessmentResults, "POST", { assessmentResult: data }),
32262
32921
  listByStudent: async (studentSourcedId, options) => {
32263
32922
  try {
32264
- return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS.assessmentResults, "assessmentResults", {
32923
+ return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentResults, "assessmentResults", {
32265
32924
  limit: options?.limit,
32266
32925
  offset: options?.offset,
32267
32926
  fields: options?.fields,
@@ -32280,54 +32939,22 @@ function createOneRosterNamespace(client) {
32280
32939
  sourcedId,
32281
32940
  dateLastModified: new Date().toISOString()
32282
32941
  };
32283
- return client["request"](`${ONEROSTER_ENDPOINTS.assessmentResults}/${sourcedId}`, "PUT", { assessmentResult });
32942
+ return client["request"](`${ONEROSTER_ENDPOINTS2.assessmentResults}/${sourcedId}`, "PUT", { assessmentResult });
32284
32943
  },
32285
32944
  get: async (sourcedId) => {
32286
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.assessmentResults}/${sourcedId}`, "GET");
32945
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.assessmentResults}/${sourcedId}`, "GET");
32287
32946
  return response.assessmentResult;
32288
32947
  },
32289
- update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS.assessmentResults}/${sourcedId}`, "PUT", data),
32290
- getAttemptStats: async (studentId, lineItemId) => {
32291
- try {
32292
- const filter = `student.sourcedId='${studentId}' AND assessmentLineItem.sourcedId='${lineItemId}'`;
32293
- const url2 = `${ONEROSTER_ENDPOINTS.assessmentResults}?filter=${encodeURIComponent(filter)}`;
32294
- const response = await client["request"](url2, "GET");
32295
- const results = response.assessmentResults || [];
32296
- const firstResult = results[0];
32297
- if (!firstResult) {
32298
- return null;
32299
- }
32300
- let maxAttemptResult = firstResult;
32301
- let maxAttemptNumber = maxAttemptResult.metadata?.attemptNumber || 0;
32302
- let activeAttemptCount = 0;
32303
- for (const result of results) {
32304
- const attemptNumber = result.metadata?.attemptNumber || 0;
32305
- if (attemptNumber > maxAttemptNumber) {
32306
- maxAttemptNumber = attemptNumber;
32307
- maxAttemptResult = result;
32308
- }
32309
- if (result.status === "active") {
32310
- activeAttemptCount++;
32311
- }
32312
- }
32313
- return { maxAttemptNumber, activeAttemptCount, maxAttemptResult };
32314
- } catch (error) {
32315
- logTimebackError("query attempt stats", error, {
32316
- studentId,
32317
- lineItemId
32318
- });
32319
- return null;
32320
- }
32321
- }
32948
+ update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS2.assessmentResults}/${sourcedId}`, "PUT", data)
32322
32949
  },
32323
32950
  users: {
32324
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.users, "POST", {
32951
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.users, "POST", {
32325
32952
  user: data
32326
32953
  }),
32327
- get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS.users}/${sourcedId}`, "GET").then((res) => res.user),
32954
+ get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS2.users}/${sourcedId}`, "GET").then((res) => res.user),
32328
32955
  findByEmail: async (email) => {
32329
32956
  const params = new URLSearchParams({ filter: `email='${email}'` });
32330
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.users}?${params}`, "GET");
32957
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.users}?${params}`, "GET");
32331
32958
  if (!response || !response.users || !Array.isArray(response.users)) {
32332
32959
  throw new Error(`Invalid response format from OneRoster API when searching for user with email: ${email}. ` + `Expected { users: [...] } but received: ${JSON.stringify(response)}`);
32333
32960
  }
@@ -32346,7 +32973,7 @@ function createOneRosterNamespace(client) {
32346
32973
  const results = await Promise.all(batches.map(async (batch) => {
32347
32974
  const filter = batch.map((id) => `sourcedId='${escapeFilterValue(id)}'`).join(" OR ");
32348
32975
  const params = new URLSearchParams({ filter });
32349
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.users}?${params}`, "GET");
32976
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.users}?${params}`, "GET");
32350
32977
  return response.users || [];
32351
32978
  }));
32352
32979
  return results.flat();
@@ -32363,11 +32990,11 @@ function createOneRosterNamespace(client) {
32363
32990
  function createQtiNamespace(client) {
32364
32991
  return {
32365
32992
  items: {
32366
- create: async (data) => client["requestQti"](QTI_ENDPOINTS.assessmentItems, "POST", data),
32367
- get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentItems}/${identifier}`, "GET"),
32368
- update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS.assessmentItems}/${identifier}`, "PUT", data),
32993
+ create: async (data) => client["requestQti"](QTI_ENDPOINTS2.assessmentItems, "POST", data),
32994
+ get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentItems}/${identifier}`, "GET"),
32995
+ update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentItems}/${identifier}`, "PUT", data),
32369
32996
  delete: async (identifier) => {
32370
- await client["requestQti"](`${QTI_ENDPOINTS.assessmentItems}/${identifier}`, "DELETE");
32997
+ await client["requestQti"](`${QTI_ENDPOINTS2.assessmentItems}/${identifier}`, "DELETE");
32371
32998
  }
32372
32999
  },
32373
33000
  tests: {
@@ -32389,25 +33016,25 @@ function createQtiNamespace(client) {
32389
33016
  params.set("order", options.order);
32390
33017
  }
32391
33018
  const query = params.toString();
32392
- return client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}${query ? `?${query}` : ""}`, "GET");
33019
+ return client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}${query ? `?${query}` : ""}`, "GET");
32393
33020
  },
32394
- create: async (data) => client["requestQti"](QTI_ENDPOINTS.assessmentTests, "POST", data),
32395
- get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}`, "GET"),
32396
- getQuestions: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}/questions`, "GET"),
32397
- update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}`, "PUT", data),
33021
+ create: async (data) => client["requestQti"](QTI_ENDPOINTS2.assessmentTests, "POST", data),
33022
+ get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}`, "GET"),
33023
+ getQuestions: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}/questions`, "GET"),
33024
+ update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}`, "PUT", data),
32398
33025
  delete: async (identifier) => {
32399
- await client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}`, "DELETE");
33026
+ await client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}`, "DELETE");
32400
33027
  },
32401
- addItem: async (testId, partId, sectionId, itemIdentifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items`, "POST", { identifier: itemIdentifier }),
33028
+ addItem: async (testId, partId, sectionId, itemIdentifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items`, "POST", { identifier: itemIdentifier }),
32402
33029
  removeItem: async (testId, partId, sectionId, itemIdentifier) => {
32403
- await client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/${itemIdentifier}`, "DELETE");
33030
+ await client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/${itemIdentifier}`, "DELETE");
32404
33031
  },
32405
- reorderItems: async (testId, partId, sectionId, items) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/order`, "PUT", { items })
33032
+ reorderItems: async (testId, partId, sectionId, items) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/order`, "PUT", { items })
32406
33033
  }
32407
33034
  };
32408
33035
  }
32409
33036
  function toCaliperSubject(subject) {
32410
- return isTimebackSubject2(subject) ? subject : "None";
33037
+ return isTimebackSubject3(subject) ? subject : "None";
32411
33038
  }
32412
33039
  function buildAdminEventMetadata({
32413
33040
  reason,
@@ -32471,7 +33098,7 @@ class AdminEventRecorder {
32471
33098
  defaultActivityId: "playcademy-admin-manual-xp",
32472
33099
  eventKind: "remediation-xp"
32473
33100
  });
32474
- const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS[this.environment]).course(data.courseId);
33101
+ const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS2[this.environment]).course(data.courseId);
32475
33102
  await this.caliper.emitActivityEvent({
32476
33103
  studentId: ctx.student.id,
32477
33104
  studentEmail: ctx.student.email,
@@ -32521,7 +33148,7 @@ class AdminEventRecorder {
32521
33148
  defaultActivityId: "playcademy-admin-mastery-adjustment",
32522
33149
  eventKind: "remediation-mastery"
32523
33150
  });
32524
- const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS[this.environment]).course(data.courseId);
33151
+ const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS2[this.environment]).course(data.courseId);
32525
33152
  await this.caliper.emitActivityEvent({
32526
33153
  studentId: ctx.student.id,
32527
33154
  studentEmail: ctx.student.email,
@@ -32555,9 +33182,9 @@ class TimebackCache {
32555
33182
  maxSize;
32556
33183
  name;
32557
33184
  constructor(options = {}) {
32558
- this.defaultTTL = options.defaultTTL || CACHE_DEFAULTS.defaultTTL;
32559
- this.maxSize = options.maxSize || CACHE_DEFAULTS.defaultMaxSize;
32560
- this.name = options.name || CACHE_DEFAULTS.defaultName;
33185
+ this.defaultTTL = options.defaultTTL || CACHE_DEFAULTS2.defaultTTL;
33186
+ this.maxSize = options.maxSize || CACHE_DEFAULTS2.defaultMaxSize;
33187
+ this.name = options.name || CACHE_DEFAULTS2.defaultName;
32561
33188
  }
32562
33189
  get(key) {
32563
33190
  const entry = this.cache.get(key);
@@ -32648,23 +33275,23 @@ class TimebackCacheManager {
32648
33275
  enrollmentCache;
32649
33276
  constructor() {
32650
33277
  this.studentCache = new TimebackCache({
32651
- defaultTTL: CACHE_DEFAULTS.studentTTL,
32652
- maxSize: CACHE_DEFAULTS.studentMaxSize,
33278
+ defaultTTL: CACHE_DEFAULTS2.studentTTL,
33279
+ maxSize: CACHE_DEFAULTS2.studentMaxSize,
32653
33280
  name: "StudentCache"
32654
33281
  });
32655
33282
  this.assessmentLineItemCache = new TimebackCache({
32656
- defaultTTL: CACHE_DEFAULTS.assessmentTTL,
32657
- maxSize: CACHE_DEFAULTS.assessmentMaxSize,
33283
+ defaultTTL: CACHE_DEFAULTS2.assessmentTTL,
33284
+ maxSize: CACHE_DEFAULTS2.assessmentMaxSize,
32658
33285
  name: "AssessmentLineItemCache"
32659
33286
  });
32660
33287
  this.resourceMasteryCache = new TimebackCache({
32661
- defaultTTL: CACHE_DEFAULTS.assessmentTTL,
32662
- maxSize: CACHE_DEFAULTS.assessmentMaxSize,
33288
+ defaultTTL: CACHE_DEFAULTS2.assessmentTTL,
33289
+ maxSize: CACHE_DEFAULTS2.assessmentMaxSize,
32663
33290
  name: "ResourceMasteryCache"
32664
33291
  });
32665
33292
  this.enrollmentCache = new TimebackCache({
32666
- defaultTTL: CACHE_DEFAULTS.enrollmentTTL,
32667
- maxSize: CACHE_DEFAULTS.enrollmentMaxSize,
33293
+ defaultTTL: CACHE_DEFAULTS2.enrollmentTTL,
33294
+ maxSize: CACHE_DEFAULTS2.enrollmentMaxSize,
32668
33295
  name: "EnrollmentCache"
32669
33296
  });
32670
33297
  }
@@ -32920,18 +33547,18 @@ class MasteryTracker {
32920
33547
  await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
32921
33548
  sourcedId: lineItemId,
32922
33549
  title: "Mastery Completion",
32923
- status: ONEROSTER_STATUS.active,
33550
+ status: ONEROSTER_STATUS2.active,
32924
33551
  ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } },
32925
33552
  ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
32926
33553
  });
32927
33554
  await this.onerosterNamespace.assessmentResults.upsert(resultId, {
32928
33555
  sourcedId: resultId,
32929
- status: ONEROSTER_STATUS.active,
33556
+ status: ONEROSTER_STATUS2.active,
32930
33557
  assessmentLineItem: { sourcedId: lineItemId },
32931
33558
  student: { sourcedId: studentId },
32932
33559
  score: 100,
32933
33560
  scoreDate: new Date().toISOString(),
32934
- scoreStatus: SCORE_STATUS.fullyGraded,
33561
+ scoreStatus: SCORE_STATUS2.fullyGraded,
32935
33562
  inProgress: "false",
32936
33563
  metadata: {
32937
33564
  isMasteryCompletion: true,
@@ -32943,6 +33570,7 @@ class MasteryTracker {
32943
33570
  "app.timeback.line_item_id": lineItemId,
32944
33571
  "app.timeback.result_id": resultId
32945
33572
  });
33573
+ return true;
32946
33574
  } catch (error) {
32947
33575
  addEvent("timeback.mastery_completion_failed", {
32948
33576
  "app.timeback.student_id": studentId,
@@ -32950,6 +33578,7 @@ class MasteryTracker {
32950
33578
  "exception.type": errorType(error),
32951
33579
  "app.error.message": errorMessage(error)
32952
33580
  });
33581
+ return false;
32953
33582
  }
32954
33583
  }
32955
33584
  async revokeCompletionEntry(studentId, courseId, classId, appName) {
@@ -32960,18 +33589,18 @@ class MasteryTracker {
32960
33589
  await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
32961
33590
  sourcedId: lineItemId,
32962
33591
  title: "Mastery Completion",
32963
- status: ONEROSTER_STATUS.active,
33592
+ status: ONEROSTER_STATUS2.active,
32964
33593
  ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } },
32965
33594
  ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
32966
33595
  });
32967
33596
  await this.onerosterNamespace.assessmentResults.upsert(resultId, {
32968
33597
  sourcedId: resultId,
32969
- status: ONEROSTER_STATUS.active,
33598
+ status: ONEROSTER_STATUS2.active,
32970
33599
  assessmentLineItem: { sourcedId: lineItemId },
32971
33600
  student: { sourcedId: studentId },
32972
33601
  score: 0,
32973
33602
  scoreDate: new Date().toISOString(),
32974
- scoreStatus: SCORE_STATUS.notSubmitted,
33603
+ scoreStatus: SCORE_STATUS2.notSubmitted,
32975
33604
  inProgress: "true",
32976
33605
  metadata: {
32977
33606
  isMasteryCompletion: true,
@@ -33006,7 +33635,7 @@ class MasteryTracker {
33006
33635
  if (!playcademyMetadata) {
33007
33636
  return;
33008
33637
  }
33009
- const masterableUnits = isPlaycademyResourceMetadata(playcademyMetadata) ? playcademyMetadata.mastery?.masterableUnits : undefined;
33638
+ const masterableUnits = isPlaycademyResourceMetadata2(playcademyMetadata) ? playcademyMetadata.mastery?.masterableUnits : undefined;
33010
33639
  this.cacheManager.setResourceMasterableUnits(resourceId, masterableUnits ?? null);
33011
33640
  return masterableUnits;
33012
33641
  } catch (error) {
@@ -33086,13 +33715,11 @@ function validateSessionData(sessionData) {
33086
33715
 
33087
33716
  class ProgressRecorder {
33088
33717
  studentResolver;
33089
- cacheManager;
33090
33718
  onerosterNamespace;
33091
33719
  caliperNamespace;
33092
33720
  masteryTracker;
33093
- constructor(studentResolver, cacheManager, onerosterNamespace, caliperNamespace, masteryTracker) {
33721
+ constructor(studentResolver, onerosterNamespace, caliperNamespace, masteryTracker) {
33094
33722
  this.studentResolver = studentResolver;
33095
- this.cacheManager = cacheManager;
33096
33723
  this.onerosterNamespace = onerosterNamespace;
33097
33724
  this.caliperNamespace = caliperNamespace;
33098
33725
  this.masteryTracker = masteryTracker;
@@ -33101,26 +33728,37 @@ class ProgressRecorder {
33101
33728
  validateProgressData(progressData);
33102
33729
  const { ids, activityId, activityName, courseName, student } = await this.resolveContext(courseId, studentIdentifier, progressData);
33103
33730
  const { id: studentId, email: studentEmail } = student;
33104
- const {
33105
- score,
33106
- totalQuestions,
33107
- correctQuestions,
33108
- xpEarned = 0,
33109
- attemptNumber
33110
- } = progressData;
33111
- let extensions = progressData.extensions;
33112
- const masteryProgress = await this.masteryTracker.checkProgress({
33113
- studentId,
33114
- courseId,
33115
- resourceId: ids.resource,
33116
- masteredUnits: progressData.masteredUnits ?? 0,
33117
- masteredUnitsAbsolute: progressData.masteredUnitsAbsolute
33731
+ const { totalQuestions, correctQuestions, xpEarned = 0, attemptNumber } = progressData;
33732
+ const activityUrl = this.caliperNamespace.buildActivityUrl({
33733
+ courseId: ids.course,
33734
+ activityId,
33735
+ sensorUrl: progressData.sensorUrl
33118
33736
  });
33737
+ const courseUrl = this.caliperNamespace.buildCourseUrl(ids.course);
33738
+ let caliperLineItemId;
33739
+ try {
33740
+ caliperLineItemId = computeCaliperLineItemId(activityUrl, ids.course, courseUrl);
33741
+ } catch (error) {
33742
+ setAttributes({ "app.timeback.course_id_not_url_safe": true });
33743
+ throw error;
33744
+ }
33745
+ const legacyLineItemId = `${ids.course}-${activityId}-assessment`;
33746
+ const [currentAttemptNumber, masteryProgress] = await Promise.all([
33747
+ this.resolveAttemptNumber(attemptNumber, studentId, caliperLineItemId, legacyLineItemId),
33748
+ this.masteryTracker.checkProgress({
33749
+ studentId,
33750
+ courseId,
33751
+ resourceId: ids.resource,
33752
+ masteredUnits: progressData.masteredUnits ?? 0,
33753
+ masteredUnitsAbsolute: progressData.masteredUnitsAbsolute
33754
+ })
33755
+ ]);
33756
+ setAttributes({ "app.timeback.attempt_number": currentAttemptNumber });
33757
+ let extensions = progressData.extensions;
33119
33758
  const effectiveMasteredUnits = masteryProgress ? masteryProgress.effectiveDelta : progressData.masteredUnits ?? 0;
33120
33759
  let pctCompleteApp;
33121
33760
  let masteryAchieved = false;
33122
- let scoreStatus = SCORE_STATUS.fullyGraded;
33123
- const inProgress = "false";
33761
+ let completionEntryWritten = false;
33124
33762
  const warnings = masteryProgress?.writeWarning ? [masteryProgress.writeWarning] : undefined;
33125
33763
  if (masteryProgress) {
33126
33764
  masteryAchieved = masteryProgress.masteryAchieved;
@@ -33129,32 +33767,12 @@ class ProgressRecorder {
33129
33767
  ...extensions,
33130
33768
  ...pctCompleteApp !== undefined ? { pctCompleteApp } : {}
33131
33769
  };
33132
- if (masteryAchieved) {
33133
- scoreStatus = SCORE_STATUS.fullyGraded;
33134
- }
33135
33770
  }
33136
- const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
33137
- const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
33138
- if (score !== undefined) {
33139
- await this.createGradebookEntry({
33140
- lineItemId: actualLineItemId,
33141
- studentId,
33142
- attemptNumber: currentAttemptNumber,
33143
- score,
33144
- xp: xpEarned,
33145
- scoreStatus,
33146
- inProgress,
33147
- appName: progressData.appName,
33148
- totalQuestions,
33149
- correctQuestions,
33150
- masteredUnits: effectiveMasteredUnits || undefined,
33151
- pctCompleteApp
33152
- });
33153
- } else {
33154
- setAttribute("app.timeback.score_provided", false);
33771
+ if (masteryAchieved) {
33772
+ setAttributes({ "app.timeback.mastery_achieved": true });
33155
33773
  }
33156
33774
  if (masteryAchieved) {
33157
- await this.masteryTracker.createCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
33775
+ completionEntryWritten = await this.masteryTracker.createCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
33158
33776
  await this.emitCourseCompletionHistoryEvent({
33159
33777
  studentId,
33160
33778
  studentEmail,
@@ -33170,30 +33788,36 @@ class ProgressRecorder {
33170
33788
  if (masteryProgress?.masteryRevoked) {
33171
33789
  await this.masteryTracker.revokeCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
33172
33790
  }
33173
- await this.emitCaliperEvent({
33174
- studentId,
33175
- studentEmail,
33176
- gameId: progressData.gameId,
33177
- activityId,
33178
- activityName,
33179
- courseId: ids.course,
33180
- courseName,
33181
- totalQuestions,
33182
- correctQuestions,
33183
- xpEarned,
33184
- masteredUnits: effectiveMasteredUnits || undefined,
33185
- attemptNumber: currentAttemptNumber,
33186
- progressData,
33187
- extensions,
33188
- runId: progressData.runId
33189
- });
33791
+ try {
33792
+ await this.emitCaliperEvent({
33793
+ studentId,
33794
+ studentEmail,
33795
+ gameId: progressData.gameId,
33796
+ activityId,
33797
+ activityName,
33798
+ courseId: ids.course,
33799
+ courseName,
33800
+ totalQuestions,
33801
+ correctQuestions,
33802
+ xpEarned,
33803
+ masteredUnits: effectiveMasteredUnits || undefined,
33804
+ attemptNumber: currentAttemptNumber,
33805
+ objectId: activityUrl,
33806
+ progressData,
33807
+ extensions,
33808
+ runId: progressData.runId
33809
+ });
33810
+ } catch (error) {
33811
+ if (completionEntryWritten) {
33812
+ setAttributes({ "app.timeback.completion_orphaned": true });
33813
+ }
33814
+ throw error;
33815
+ }
33190
33816
  return {
33191
33817
  xpAwarded: xpEarned,
33192
33818
  attemptNumber: currentAttemptNumber,
33193
33819
  masteredUnitsApplied: effectiveMasteredUnits,
33194
33820
  pctCompleteApp,
33195
- scoreStatus,
33196
- inProgress,
33197
33821
  ...warnings ? { warnings } : {}
33198
33822
  };
33199
33823
  }
@@ -33205,89 +33829,48 @@ class ProgressRecorder {
33205
33829
  const student = await this.studentResolver.resolve(studentIdentifier, progressData.studentEmail);
33206
33830
  return { ids, activityId, activityName, courseName, student };
33207
33831
  }
33208
- async resolveAssessmentLineItem(activityId, activityName, classId, ids) {
33209
- const lineItemId = `${ids.course}-${activityId}-assessment`;
33210
- let actualLineItemId = this.cacheManager.getAssessmentLineItem(lineItemId);
33211
- if (!actualLineItemId) {
33212
- actualLineItemId = await this.getOrCreateLineItem(lineItemId, activityName, classId, ids);
33213
- this.cacheManager.setAssessmentLineItem(lineItemId, actualLineItemId);
33214
- }
33215
- return actualLineItemId;
33216
- }
33217
- async resolveAttemptNumber(providedAttemptNumber, score, studentId, lineItemId) {
33832
+ async resolveAttemptNumber(providedAttemptNumber, studentId, caliperLineItemId, legacyLineItemId) {
33218
33833
  if (providedAttemptNumber) {
33834
+ setAttributes({ "app.timeback.attempt_source": "provided" });
33219
33835
  return providedAttemptNumber;
33220
33836
  }
33221
- if (score !== undefined) {
33222
- return this.determineAttemptNumber(studentId, lineItemId);
33223
- }
33224
- return 1;
33225
- }
33226
- async getOrCreateLineItem(lineItemId, activityName, classId, ids) {
33227
- try {
33228
- const lineItem = await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
33229
- sourcedId: lineItemId,
33230
- title: activityName,
33231
- status: ONEROSTER_STATUS.active,
33232
- ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } }
33837
+ const caliperAttempt = await this.getLatestActivityAttempt(studentId, caliperLineItemId, "attempt");
33838
+ if (caliperAttempt !== null) {
33839
+ const next = caliperAttempt + 1;
33840
+ setAttributes({
33841
+ "app.timeback.attempt_source": caliperAttempt > 0 ? "caliper" : "caliper_unreadable"
33233
33842
  });
33234
- if (!lineItem.sourcedId) {
33235
- throw new TimebackError(`Assessment line item created but has no sourcedId. ` + `This should not happen and indicates an upstream API issue.`);
33236
- }
33237
- return lineItem.sourcedId;
33238
- } catch (error) {
33239
- if (error instanceof TimebackApiError && error.status === 404) {
33240
- const errorDetails = error.details;
33241
- const description = errorDetails?.imsx_description || error.message;
33242
- if (description.includes("course") && description.includes("not found") || description.includes("component") && description.includes("not found") || description.includes("resource") && description.includes("not found") || description.includes("componentResource") && description.includes("not found")) {
33243
- throw new ResourceNotFoundError("TimeBack resources", "setup-not-run");
33244
- }
33843
+ if (caliperAttempt === 0) {
33844
+ setAttributes({
33845
+ "app.timeback.attempt_regressed": true,
33846
+ "app.timeback.attempt_emitted": next
33847
+ });
33245
33848
  }
33246
- throw error;
33849
+ return next;
33247
33850
  }
33248
- }
33249
- async determineAttemptNumber(studentId, lineItemId) {
33250
- const stats = await this.onerosterNamespace.assessmentResults.getAttemptStats(studentId, lineItemId);
33251
- if (stats) {
33252
- return stats.activeAttemptCount + 1;
33851
+ const legacyAttempt = await this.getLatestActivityAttempt(studentId, legacyLineItemId, "attemptNumber");
33852
+ if (legacyAttempt !== null) {
33853
+ setAttributes({
33854
+ "app.timeback.attempt_source": "legacy_seed",
33855
+ "app.timeback.legacy_seed_attempt": legacyAttempt
33856
+ });
33857
+ return legacyAttempt + 1;
33253
33858
  }
33859
+ setAttributes({ "app.timeback.attempt_source": "first" });
33254
33860
  return 1;
33255
33861
  }
33256
- async createGradebookEntry({
33257
- lineItemId,
33258
- studentId,
33259
- attemptNumber,
33260
- score,
33261
- xp,
33262
- scoreStatus,
33263
- inProgress,
33264
- appName,
33265
- totalQuestions,
33266
- correctQuestions,
33267
- masteredUnits,
33268
- pctCompleteApp
33269
- }) {
33270
- const timestamp3 = Date.now().toString(36);
33271
- const resultId = `${lineItemId}:${studentId}:${timestamp3}`;
33272
- await this.onerosterNamespace.assessmentResults.upsert(resultId, {
33273
- sourcedId: resultId,
33274
- status: ONEROSTER_STATUS.active,
33275
- assessmentLineItem: { sourcedId: lineItemId },
33276
- student: { sourcedId: studentId },
33277
- score,
33278
- scoreDate: new Date().toISOString(),
33279
- scoreStatus,
33280
- inProgress,
33281
- metadata: {
33282
- xp,
33283
- attemptNumber,
33284
- appName,
33285
- ...totalQuestions !== undefined ? { totalQuestions } : {},
33286
- ...correctQuestions !== undefined ? { correctQuestions } : {},
33287
- ...masteredUnits !== undefined ? { masteredUnits } : {},
33288
- ...pctCompleteApp !== undefined ? { pctCompleteApp } : {}
33289
- }
33862
+ async getLatestActivityAttempt(studentId, lineItemId, metadataField) {
33863
+ const results = await this.onerosterNamespace.assessmentResults.listOrThrow({
33864
+ filter: `student.sourcedId='${escapeFilterValue(studentId)}' AND assessmentLineItem.sourcedId='${escapeFilterValue(lineItemId)}' AND status='active'`,
33865
+ sort: "dateLastModified",
33866
+ orderBy: "desc",
33867
+ limit: 1
33290
33868
  });
33869
+ const latest = results[0];
33870
+ if (!latest) {
33871
+ return null;
33872
+ }
33873
+ return latest.metadata?.[metadataField] || 0;
33291
33874
  }
33292
33875
  async emitCaliperEvent({
33293
33876
  studentId,
@@ -33302,6 +33885,7 @@ class ProgressRecorder {
33302
33885
  xpEarned,
33303
33886
  masteredUnits,
33304
33887
  attemptNumber,
33888
+ objectId,
33305
33889
  progressData,
33306
33890
  extensions,
33307
33891
  runId
@@ -33319,12 +33903,18 @@ class ProgressRecorder {
33319
33903
  xpEarned,
33320
33904
  masteredUnits,
33321
33905
  attemptNumber,
33906
+ objectId,
33907
+ process: true,
33322
33908
  subject: progressData.subject,
33323
33909
  appName: progressData.appName,
33324
33910
  sensorUrl: progressData.sensorUrl,
33325
33911
  extensions: extensions || progressData.extensions,
33326
33912
  ...runId ? { runId } : {}
33327
- }).catch(catchEvent("timeback.caliper_event_failed"));
33913
+ }).catch((error) => {
33914
+ setAttributes({ "app.timeback.caliper_emit_failed": true });
33915
+ catchEvent("timeback.caliper_event_failed")(error);
33916
+ throw error;
33917
+ });
33328
33918
  }
33329
33919
  async emitCourseCompletionHistoryEvent(data) {
33330
33920
  await this.caliperNamespace.emitActivityEvent({
@@ -33502,15 +34092,15 @@ class TimebackClient {
33502
34092
  masteryTracker;
33503
34093
  constructor(config2) {
33504
34094
  this.baseUrl = TimebackClient.resolveBaseUrl(config2?.baseUrl);
33505
- this.environment = process.env[ENV_VARS.environment] === "staging" ? "staging" : "production";
34095
+ this.environment = process.env[ENV_VARS2.environment] === "staging" ? "staging" : "production";
33506
34096
  this.caliperUrl = TimebackClient.resolveCaliperUrl(config2?.caliperUrl, this.environment);
33507
34097
  this.authUrl = config2?.credentials?.authUrl;
33508
34098
  this.credentials = config2?.credentials;
33509
34099
  this.qtiCredentials = config2?.qtiCredentials;
33510
34100
  this.options = {
33511
- retries: config2?.options?.retries ?? HTTP_DEFAULTS.retries,
33512
- cacheDuration: config2?.options?.cacheDuration ?? AUTH_DEFAULTS.tokenCacheDuration,
33513
- timeout: config2?.options?.timeout ?? HTTP_DEFAULTS.timeout,
34101
+ retries: config2?.options?.retries ?? HTTP_DEFAULTS2.retries,
34102
+ cacheDuration: config2?.options?.cacheDuration ?? AUTH_DEFAULTS2.tokenCacheDuration,
34103
+ timeout: config2?.options?.timeout ?? HTTP_DEFAULTS2.timeout,
33514
34104
  sensorUrl: config2?.options?.sensorUrl
33515
34105
  };
33516
34106
  this.oneroster = createOneRosterNamespace(this);
@@ -33520,7 +34110,7 @@ class TimebackClient {
33520
34110
  this.cacheManager = new TimebackCacheManager;
33521
34111
  this.studentResolver = new StudentResolver(this.cacheManager, this.oneroster);
33522
34112
  this.masteryTracker = new MasteryTracker(this.cacheManager, this.oneroster, this.edubridge);
33523
- this.progressRecorder = new ProgressRecorder(this.studentResolver, this.cacheManager, this.oneroster, this.caliper, this.masteryTracker);
34113
+ this.progressRecorder = new ProgressRecorder(this.studentResolver, this.oneroster, this.caliper, this.masteryTracker);
33524
34114
  this.sessionRecorder = new SessionRecorder(this.studentResolver, this.caliper);
33525
34115
  this.adminEventRecorder = new AdminEventRecorder(this.studentResolver, this.oneroster, this.caliper, this.environment);
33526
34116
  if (this.credentials) {
@@ -33529,16 +34119,16 @@ class TimebackClient {
33529
34119
  }
33530
34120
  static async init(config2) {
33531
34121
  let credentials = config2?.credentials;
33532
- if (!credentials && process.env[ENV_VARS.clientId] && process.env[ENV_VARS.clientSecret]) {
34122
+ if (!credentials && process.env[ENV_VARS2.clientId] && process.env[ENV_VARS2.clientSecret]) {
33533
34123
  credentials = {
33534
- clientId: process.env[ENV_VARS.clientId],
33535
- clientSecret: process.env[ENV_VARS.clientSecret]
34124
+ clientId: process.env[ENV_VARS2.clientId],
34125
+ clientSecret: process.env[ENV_VARS2.clientSecret]
33536
34126
  };
33537
34127
  }
33538
- const qtiCredentials = config2?.qtiCredentials ?? (process.env[ENV_VARS.qtiClientId] && process.env[ENV_VARS.qtiClientSecret] && process.env[ENV_VARS.qtiAuthUrl] ? {
33539
- clientId: process.env[ENV_VARS.qtiClientId],
33540
- clientSecret: process.env[ENV_VARS.qtiClientSecret],
33541
- authUrl: process.env[ENV_VARS.qtiAuthUrl]
34128
+ const qtiCredentials = config2?.qtiCredentials ?? (process.env[ENV_VARS2.qtiClientId] && process.env[ENV_VARS2.qtiClientSecret] && process.env[ENV_VARS2.qtiAuthUrl] ? {
34129
+ clientId: process.env[ENV_VARS2.qtiClientId],
34130
+ clientSecret: process.env[ENV_VARS2.qtiClientSecret],
34131
+ authUrl: process.env[ENV_VARS2.qtiAuthUrl]
33542
34132
  } : undefined);
33543
34133
  return new TimebackClient({
33544
34134
  ...config2,
@@ -33551,15 +34141,15 @@ class TimebackClient {
33551
34141
  if (explicit) {
33552
34142
  return explicit;
33553
34143
  }
33554
- const envName = process.env[ENV_VARS.environment] === "staging" ? "staging" : "production";
33555
- return TIMEBACK_API_URLS[envName];
34144
+ const envName = process.env[ENV_VARS2.environment] === "staging" ? "staging" : "production";
34145
+ return TIMEBACK_API_URLS2[envName];
33556
34146
  }
33557
34147
  static resolveCaliperUrl(input, environment = "production") {
33558
34148
  const explicit = (input || "").trim();
33559
34149
  if (explicit) {
33560
34150
  return explicit;
33561
34151
  }
33562
- return CALIPER_API_URLS[environment];
34152
+ return CALIPER_API_URLS2[environment];
33563
34153
  }
33564
34154
  getBaseUrl() {
33565
34155
  return this.baseUrl;
@@ -33680,14 +34270,14 @@ class TimebackClient {
33680
34270
  await this._ensureAuthenticated();
33681
34271
  return this.token;
33682
34272
  }
33683
- throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS.qtiClientId}, ${ENV_VARS.qtiClientSecret}, and ${ENV_VARS.qtiAuthUrl}.`);
34273
+ throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS2.qtiClientId}, ${ENV_VARS2.qtiClientSecret}, and ${ENV_VARS2.qtiAuthUrl}.`);
33684
34274
  }
33685
34275
  async ensureQtiAuthenticated() {
33686
34276
  if (this.isQtiAuthenticated()) {
33687
34277
  return;
33688
34278
  }
33689
34279
  if (!this.qtiCredentials) {
33690
- throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS.qtiClientId}, ${ENV_VARS.qtiClientSecret}, and ${ENV_VARS.qtiAuthUrl}.`);
34280
+ throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS2.qtiClientId}, ${ENV_VARS2.qtiClientSecret}, and ${ENV_VARS2.qtiAuthUrl}.`);
33691
34281
  }
33692
34282
  try {
33693
34283
  const tokenData = await getTimebackTokenResponse({
@@ -33699,11 +34289,11 @@ class TimebackClient {
33699
34289
  this.setQtiToken(tokenData.access_token, tokenData.expires_in);
33700
34290
  } catch (error) {
33701
34291
  const errMsg = errorMessage(error);
33702
- throw new TimebackAuthenticationError(`QTI authentication failed: ${errMsg}. ` + `Verify that ${ENV_VARS.qtiClientId}, ${ENV_VARS.qtiClientSecret}, and ${ENV_VARS.qtiAuthUrl} are correct.`);
34292
+ throw new TimebackAuthenticationError(`QTI authentication failed: ${errMsg}. ` + `Verify that ${ENV_VARS2.qtiClientId}, ${ENV_VARS2.qtiClientSecret}, and ${ENV_VARS2.qtiAuthUrl} are correct.`);
33703
34293
  }
33704
34294
  }
33705
34295
  canUseCoreCredentialsForQti() {
33706
- return this.baseUrl.replace(/\/$/, "") === TIMEBACK_API_URLS.production;
34296
+ return this.baseUrl.replace(/\/$/, "") === TIMEBACK_API_URLS2.production;
33707
34297
  }
33708
34298
  async resolveStudent(studentIdentifier, providedEmail) {
33709
34299
  return this.studentResolver.resolve(studentIdentifier, providedEmail);
@@ -33724,8 +34314,8 @@ class TimebackClient {
33724
34314
  await this._ensureAuthenticated();
33725
34315
  const edubridgeEnrollments = await this.edubridge.enrollments.listByUser(studentId);
33726
34316
  const enrollments = edubridgeEnrollments.map((enrollment) => {
33727
- const grades = enrollment.course.grades ? enrollment.course.grades.map((g) => parseInt(g, 10)).filter(isTimebackGrade2) : null;
33728
- const subjects = enrollment.course.subjects ? enrollment.course.subjects.filter(isTimebackSubject2) : null;
34317
+ const grades = enrollment.course.grades ? enrollment.course.grades.map((g) => parseInt(g, 10)).filter(isTimebackGrade3) : null;
34318
+ const subjects = enrollment.course.subjects ? enrollment.course.subjects.filter(isTimebackSubject3) : null;
33729
34319
  return {
33730
34320
  sourcedId: enrollment.id,
33731
34321
  title: enrollment.course.title,
@@ -33791,9 +34381,9 @@ class TimebackClient {
33791
34381
  if (options?.include?.perCourse) {
33792
34382
  const gradeStr = enrollment.course.grades?.[0];
33793
34383
  const parsedGrade = gradeStr ? parseInt(gradeStr, 10) : 0;
33794
- const grade = isTimebackGrade2(parsedGrade) ? parsedGrade : 0;
34384
+ const grade = isTimebackGrade3(parsedGrade) ? parsedGrade : 0;
33795
34385
  const subjectStr = enrollment.course.subjects?.[0];
33796
- const subject = subjectStr && isTimebackSubject2(subjectStr) ? subjectStr : "None";
34386
+ const subject = subjectStr && isTimebackSubject3(subjectStr) ? subjectStr : "None";
33797
34387
  courses.push({
33798
34388
  grade,
33799
34389
  subject,
@@ -33867,9 +34457,9 @@ class TimebackClient {
33867
34457
  if (options?.include?.perCourse) {
33868
34458
  const gradeStr = enrollment.course.grades?.[0];
33869
34459
  const parsedGrade = gradeStr ? parseInt(gradeStr, 10) : 0;
33870
- const grade = isTimebackGrade2(parsedGrade) ? parsedGrade : 0;
34460
+ const grade = isTimebackGrade3(parsedGrade) ? parsedGrade : 0;
33871
34461
  const subjectStr = enrollment.course.subjects?.[0];
33872
- const subject = subjectStr && isTimebackSubject2(subjectStr) ? subjectStr : "None";
34462
+ const subject = subjectStr && isTimebackSubject3(subjectStr) ? subjectStr : "None";
33873
34463
  courses.push({
33874
34464
  grade,
33875
34465
  subject,
@@ -33925,6 +34515,12 @@ class TimebackClient {
33925
34515
  async cleanup(courseId) {
33926
34516
  return deleteTimebackResources(this, courseId);
33927
34517
  }
34518
+ async deactivateCourse(courseId) {
34519
+ return updateTimebackCourseStatus(this, courseId, "tobedeleted");
34520
+ }
34521
+ async reactivateCourse(courseId) {
34522
+ return updateTimebackCourseStatus(this, courseId, "active");
34523
+ }
33928
34524
  }
33929
34525
  var __defProp2, __export2 = (target, all) => {
33930
34526
  for (var name3 in all)
@@ -33934,7 +34530,7 @@ var __defProp2, __export2 = (target, all) => {
33934
34530
  configurable: true,
33935
34531
  set: (newValue) => all[name3] = () => newValue
33936
34532
  });
33937
- }, __esm2 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS, QTI_API_URL = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS, CALIPER_API_URLS, ONEROSTER_ENDPOINTS, QTI_ENDPOINTS, CALIPER_ENDPOINTS, CALIPER_CONSTANTS, TIMEBACK_EVENT_TYPES, TIMEBACK_ACTIONS, TIMEBACK_TYPES, ACTIVITY_METRIC_TYPES, TIME_METRIC_TYPES, TIMEBACK_SUBJECTS2, TIMEBACK_GRADE_LEVELS, TIMEBACK_GRADE_LEVEL_LABELS, CALIPER_SUBJECTS, ONEROSTER_STATUS, SCORE_STATUS, ENV_VARS, HTTP_DEFAULTS, AUTH_DEFAULTS, CACHE_DEFAULTS, CONFIG_DEFAULTS, PLAYCADEMY_DEFAULTS, RESOURCE_DEFAULTS, HTTP_STATUS, ERROR_NAMES, init_constants4, exports_verify, init_verify, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceNotFoundError, SUBJECT_VALUES, GRADE_VALUES, TimebackAuthError, UUID_PATTERN, storage, MASTERY_WRITE_CAPPED_WARNING_CODE = "MASTERY_WRITE_CAPPED", EmailSchema, StudentSourcedIdSchema, StudentIdentifierSchema;
34533
+ }, __esm3 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS2, QTI_API_URL = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS2, CALIPER_API_URLS2, ONEROSTER_ENDPOINTS2, QTI_ENDPOINTS2, CALIPER_ENDPOINTS2, CALIPER_CONSTANTS2, TIMEBACK_EVENT_TYPES2, TIMEBACK_ACTIONS2, TIMEBACK_TYPES2, ACTIVITY_METRIC_TYPES2, TIME_METRIC_TYPES2, TIMEBACK_SUBJECTS3, TIMEBACK_GRADE_LEVELS2, TIMEBACK_GRADE_LEVEL_LABELS2, CALIPER_SUBJECTS2, ONEROSTER_STATUS2, SCORE_STATUS2, ENV_VARS2, HTTP_DEFAULTS2, AUTH_DEFAULTS2, CACHE_DEFAULTS2, CONFIG_DEFAULTS2, PLAYCADEMY_DEFAULTS2, RESOURCE_DEFAULTS2, HTTP_STATUS2, ERROR_NAMES2, init_constants5, TimebackError, TimebackApiError, TimebackAuthenticationError, StudentNotFoundError, ConfigurationError, ResourceAlreadyExistsError, ResourceNotFoundError, init_errors4, UUID_REGEX2, init_ids, exports_verify, init_verify, SUBJECT_VALUES2, GRADE_VALUES2, TimebackAuthError, UUID_PATTERN, storage, MASTERY_WRITE_CAPPED_WARNING_CODE = "MASTERY_WRITE_CAPPED", EmailSchema, StudentSourcedIdSchema, StudentIdentifierSchema;
33938
34534
  var init_dist2 = __esm(() => {
33939
34535
  init_src();
33940
34536
  init_src();
@@ -33960,293 +34556,7 @@ var init_dist2 = __esm(() => {
33960
34556
  init_spans();
33961
34557
  init_esm();
33962
34558
  __defProp2 = Object.defineProperty;
33963
- init_constants4 = __esm2(() => {
33964
- TIMEBACK_API_URLS = {
33965
- production: "https://api.alpha-1edtech.ai",
33966
- staging: "https://api.staging.alpha-1edtech.com"
33967
- };
33968
- TIMEBACK_AUTH_URLS = {
33969
- production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
33970
- staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
33971
- };
33972
- CALIPER_API_URLS = {
33973
- production: "https://caliper.alpha-1edtech.ai",
33974
- staging: "https://caliper-staging.alpha-1edtech.com"
33975
- };
33976
- ONEROSTER_ENDPOINTS = {
33977
- organizations: "/ims/oneroster/rostering/v1p2/orgs",
33978
- courses: "/ims/oneroster/rostering/v1p2/courses",
33979
- courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
33980
- resources: "/ims/oneroster/resources/v1p2/resources",
33981
- componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
33982
- classes: "/ims/oneroster/rostering/v1p2/classes",
33983
- enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
33984
- assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
33985
- assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
33986
- users: "/ims/oneroster/rostering/v1p2/users"
33987
- };
33988
- QTI_ENDPOINTS = {
33989
- assessmentTests: "/assessment-tests",
33990
- assessmentItems: "/assessment-items"
33991
- };
33992
- CALIPER_ENDPOINTS = {
33993
- event: "/caliper/event",
33994
- events: "/caliper/events",
33995
- validate: "/caliper/event/validate"
33996
- };
33997
- CALIPER_CONSTANTS = {
33998
- context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
33999
- profile: "TimebackProfile",
34000
- dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
34001
- };
34002
- TIMEBACK_EVENT_TYPES = {
34003
- activityEvent: "ActivityEvent",
34004
- timeSpentEvent: "TimeSpentEvent"
34005
- };
34006
- TIMEBACK_ACTIONS = {
34007
- completed: "Completed",
34008
- spentTime: "SpentTime"
34009
- };
34010
- TIMEBACK_TYPES = {
34011
- user: "TimebackUser",
34012
- activityContext: "TimebackActivityContext",
34013
- activityMetricsCollection: "TimebackActivityMetricsCollection",
34014
- timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
34015
- };
34016
- ACTIVITY_METRIC_TYPES = {
34017
- totalQuestions: "totalQuestions",
34018
- correctQuestions: "correctQuestions",
34019
- xpEarned: "xpEarned",
34020
- masteredUnits: "masteredUnits"
34021
- };
34022
- TIME_METRIC_TYPES = {
34023
- active: "active",
34024
- inactive: "inactive",
34025
- waste: "waste",
34026
- unknown: "unknown",
34027
- antiPattern: "anti-pattern"
34028
- };
34029
- TIMEBACK_SUBJECTS2 = [
34030
- "Math",
34031
- "FastMath",
34032
- "Science",
34033
- "Social Studies",
34034
- "Language",
34035
- "Reading",
34036
- "Vocabulary",
34037
- "Writing"
34038
- ];
34039
- TIMEBACK_GRADE_LEVELS = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
34040
- TIMEBACK_GRADE_LEVEL_LABELS = {
34041
- "-1": "pre-k",
34042
- "0": "kindergarten",
34043
- "1": "1st grade",
34044
- "2": "2nd grade",
34045
- "3": "3rd grade",
34046
- "4": "4th grade",
34047
- "5": "5th grade",
34048
- "6": "6th grade",
34049
- "7": "7th grade",
34050
- "8": "8th grade",
34051
- "9": "9th grade",
34052
- "10": "10th grade",
34053
- "11": "11th grade",
34054
- "12": "12th grade",
34055
- "13": "AP"
34056
- };
34057
- CALIPER_SUBJECTS = {
34058
- Reading: "Reading",
34059
- Language: "Language",
34060
- Vocabulary: "Vocabulary",
34061
- SocialStudies: "Social Studies",
34062
- Writing: "Writing",
34063
- Science: "Science",
34064
- FastMath: "FastMath",
34065
- Math: "Math",
34066
- None: "None"
34067
- };
34068
- ONEROSTER_STATUS = {
34069
- active: "active",
34070
- toBeDeleted: "tobedeleted"
34071
- };
34072
- SCORE_STATUS = {
34073
- exempt: "exempt",
34074
- fullyGraded: "fully graded",
34075
- notSubmitted: "not submitted",
34076
- partiallyGraded: "partially graded",
34077
- submitted: "submitted"
34078
- };
34079
- ENV_VARS = {
34080
- clientId: "TIMEBACK_CLIENT_ID",
34081
- clientSecret: "TIMEBACK_CLIENT_SECRET",
34082
- baseUrl: "TIMEBACK_BASE_URL",
34083
- environment: "TIMEBACK_ENVIRONMENT",
34084
- vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
34085
- launchBaseUrl: "GAME_URL",
34086
- qtiClientId: "QTI_CLIENT_ID",
34087
- qtiClientSecret: "QTI_CLIENT_SECRET",
34088
- qtiAuthUrl: "QTI_AUTH_URL"
34089
- };
34090
- HTTP_DEFAULTS = {
34091
- timeout: 30000,
34092
- retries: 3,
34093
- retryBackoffBase: 2
34094
- };
34095
- AUTH_DEFAULTS = {
34096
- tokenCacheDuration: 50000
34097
- };
34098
- CACHE_DEFAULTS = {
34099
- defaultTTL: 10 * 60 * 1000,
34100
- defaultMaxSize: 500,
34101
- defaultName: "TimebackCache",
34102
- studentTTL: 10 * 60 * 1000,
34103
- studentMaxSize: 500,
34104
- assessmentTTL: 30 * 60 * 1000,
34105
- assessmentMaxSize: 200,
34106
- enrollmentTTL: 5 * 1000,
34107
- enrollmentMaxSize: 100
34108
- };
34109
- CONFIG_DEFAULTS = {
34110
- fileNames: ["timeback.config.js", "timeback.config.json"]
34111
- };
34112
- PLAYCADEMY_DEFAULTS = {
34113
- organization: TIMEBACK_ORG_SOURCED_ID,
34114
- launchBaseUrls: PLAYCADEMY_BASE_URLS
34115
- };
34116
- RESOURCE_DEFAULTS = {
34117
- organization: {
34118
- name: TIMEBACK_ORG_NAME,
34119
- type: TIMEBACK_ORG_TYPE
34120
- },
34121
- course: {
34122
- gradingScheme: TIMEBACK_COURSE_DEFAULTS.gradingScheme,
34123
- level: TIMEBACK_COURSE_DEFAULTS.level,
34124
- metadata: {
34125
- goals: TIMEBACK_COURSE_DEFAULTS.goals,
34126
- metrics: TIMEBACK_COURSE_DEFAULTS.metrics
34127
- }
34128
- },
34129
- component: TIMEBACK_COMPONENT_DEFAULTS,
34130
- resource: TIMEBACK_RESOURCE_DEFAULTS,
34131
- componentResource: TIMEBACK_COMPONENT_RESOURCE_DEFAULTS
34132
- };
34133
- HTTP_STATUS = {
34134
- CLIENT_ERROR_MIN: 400,
34135
- CLIENT_ERROR_MAX: 500,
34136
- SERVER_ERROR_MIN: 500
34137
- };
34138
- ERROR_NAMES = {
34139
- timebackAuth: "TimebackAuthError",
34140
- timebackApi: "TimebackApiError",
34141
- timebackConfig: "TimebackConfigError",
34142
- timebackSdk: "TimebackSDKError"
34143
- };
34144
- });
34145
- exports_verify = {};
34146
- __export2(exports_verify, {
34147
- verifyTimebackResources: () => verifyTimebackResources,
34148
- fetchTimebackConfig: () => fetchTimebackConfig
34149
- });
34150
- init_verify = __esm2(() => {
34151
- init_constants4();
34152
- });
34153
- init_constants4();
34154
- TimebackError = class TimebackError extends Error {
34155
- constructor(message) {
34156
- super(message);
34157
- this.name = ERROR_NAMES.timebackSdk;
34158
- }
34159
- };
34160
- TimebackApiError = class TimebackApiError extends Error {
34161
- status;
34162
- details;
34163
- constructor(status, message, details) {
34164
- super(`${status} ${message}`);
34165
- this.name = ERROR_NAMES.timebackApi;
34166
- this.status = status;
34167
- this.details = details;
34168
- Object.setPrototypeOf(this, TimebackApiError.prototype);
34169
- }
34170
- };
34171
- TimebackAuthenticationError = class TimebackAuthenticationError extends TimebackError {
34172
- constructor(message) {
34173
- super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
34174
- this.name = "TimebackAuthenticationError";
34175
- Object.setPrototypeOf(this, TimebackAuthenticationError.prototype);
34176
- }
34177
- };
34178
- StudentNotFoundError = class StudentNotFoundError extends TimebackError {
34179
- identifier;
34180
- identifierType;
34181
- constructor(identifier, identifierType = "email") {
34182
- super(`Student not found with ${identifierType}: ${identifier}. ` + `Ensure the student exists in OneRoster. ` + `If this is a new student, they must be created in OneRoster first.`);
34183
- this.name = "StudentNotFoundError";
34184
- this.identifier = identifier;
34185
- this.identifierType = identifierType;
34186
- Object.setPrototypeOf(this, StudentNotFoundError.prototype);
34187
- }
34188
- };
34189
- ConfigurationError = class ConfigurationError extends TimebackError {
34190
- field;
34191
- constructor(field, message) {
34192
- super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
34193
- this.name = "ConfigurationError";
34194
- this.field = field;
34195
- Object.setPrototypeOf(this, ConfigurationError.prototype);
34196
- }
34197
- };
34198
- ResourceNotFoundError = class ResourceNotFoundError extends TimebackError {
34199
- resourceType;
34200
- sourcedId;
34201
- constructor(resourceType, sourcedId) {
34202
- const message = sourcedId === "setup-not-run" ? `TimeBack resources have not been created yet. ` + `Please run 'bunx @playcademy/timeback setup' to create the required resources ` + `(organization, course, components, etc.) before recording progress.` : `${resourceType} with ID '${sourcedId}' not found`;
34203
- super(message);
34204
- this.name = "ResourceNotFoundError";
34205
- this.resourceType = resourceType;
34206
- this.sourcedId = sourcedId;
34207
- Object.setPrototypeOf(this, ResourceNotFoundError.prototype);
34208
- }
34209
- };
34210
- init_constants4();
34211
- SUBJECT_VALUES = TIMEBACK_SUBJECTS2;
34212
- GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
34213
- init_verify();
34214
- init_constants4();
34215
- init_constants4();
34216
- if (process.env.DEBUG === "true") {
34217
- process.env.TERM = "dumb";
34218
- }
34219
- TimebackAuthError = class TimebackAuthError extends Error {
34220
- statusCode;
34221
- constructor(message, statusCode) {
34222
- super(message);
34223
- this.name = ERROR_NAMES.timebackAuth;
34224
- this.statusCode = statusCode;
34225
- }
34226
- };
34227
- init_constants4();
34228
- UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
34229
- storage = new AsyncLocalStorage;
34230
- init_constants4();
34231
- init_constants4();
34232
- init_constants4();
34233
- init_constants4();
34234
- init_constants4();
34235
- init_constants4();
34236
- init_constants4();
34237
- init_constants4();
34238
- EmailSchema = exports_external.string().email();
34239
- StudentSourcedIdSchema = exports_external.string().min(1, {
34240
- message: "Student sourcedId must be a non-empty string"
34241
- });
34242
- StudentIdentifierSchema = exports_external.union([EmailSchema, StudentSourcedIdSchema]);
34243
- });
34244
-
34245
- // ../timeback/dist/constants.js
34246
- var __esm3 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS2, QTI_API_URL2 = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS2, CALIPER_API_URLS2, ONEROSTER_ENDPOINTS2, QTI_ENDPOINTS2, CALIPER_ENDPOINTS2, CALIPER_CONSTANTS2, TIMEBACK_EVENT_TYPES2, TIMEBACK_ACTIONS2, TIMEBACK_TYPES2, ACTIVITY_METRIC_TYPES2, TIME_METRIC_TYPES2, TIMEBACK_SUBJECTS3, TIMEBACK_GRADE_LEVELS2, TIMEBACK_GRADE_LEVEL_LABELS2, CALIPER_SUBJECTS2, ONEROSTER_STATUS2, SCORE_STATUS2, ENV_VARS2, HTTP_DEFAULTS2, AUTH_DEFAULTS2, CACHE_DEFAULTS2, CONFIG_DEFAULTS2, PLAYCADEMY_DEFAULTS2, RESOURCE_DEFAULTS2, HTTP_STATUS2, ERROR_NAMES2, init_constants6;
34247
- var init_constants5 = __esm(() => {
34248
- init_src();
34249
- init_constants6 = __esm3(() => {
34559
+ init_constants5 = __esm3(() => {
34250
34560
  TIMEBACK_API_URLS2 = {
34251
34561
  production: "https://api.alpha-1edtech.ai",
34252
34562
  staging: "https://api.staging.alpha-1edtech.com"
@@ -34428,36 +34738,153 @@ var init_constants5 = __esm(() => {
34428
34738
  timebackSdk: "TimebackSDKError"
34429
34739
  };
34430
34740
  });
34431
- init_constants6();
34741
+ init_errors4 = __esm3(() => {
34742
+ init_constants5();
34743
+ TimebackError = class TimebackError2 extends Error {
34744
+ constructor(message) {
34745
+ super(message);
34746
+ this.name = ERROR_NAMES2.timebackSdk;
34747
+ }
34748
+ };
34749
+ TimebackApiError = class TimebackApiError2 extends Error {
34750
+ status;
34751
+ details;
34752
+ constructor(status, message, details) {
34753
+ super(`${status} ${message}`);
34754
+ this.name = ERROR_NAMES2.timebackApi;
34755
+ this.status = status;
34756
+ this.details = details;
34757
+ Object.setPrototypeOf(this, TimebackApiError2.prototype);
34758
+ }
34759
+ };
34760
+ TimebackAuthenticationError = class TimebackAuthenticationError2 extends TimebackError {
34761
+ constructor(message) {
34762
+ super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
34763
+ this.name = "TimebackAuthenticationError";
34764
+ Object.setPrototypeOf(this, TimebackAuthenticationError2.prototype);
34765
+ }
34766
+ };
34767
+ StudentNotFoundError = class StudentNotFoundError2 extends TimebackError {
34768
+ identifier;
34769
+ identifierType;
34770
+ constructor(identifier, identifierType = "email") {
34771
+ super(`Student not found with ${identifierType}: ${identifier}. ` + `Ensure the student exists in OneRoster. ` + `If this is a new student, they must be created in OneRoster first.`);
34772
+ this.name = "StudentNotFoundError";
34773
+ this.identifier = identifier;
34774
+ this.identifierType = identifierType;
34775
+ Object.setPrototypeOf(this, StudentNotFoundError2.prototype);
34776
+ }
34777
+ };
34778
+ ConfigurationError = class ConfigurationError2 extends TimebackError {
34779
+ field;
34780
+ constructor(field, message) {
34781
+ super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
34782
+ this.name = "ConfigurationError";
34783
+ this.field = field;
34784
+ Object.setPrototypeOf(this, ConfigurationError2.prototype);
34785
+ }
34786
+ };
34787
+ ResourceAlreadyExistsError = class ResourceAlreadyExistsError2 extends TimebackError {
34788
+ resourceType;
34789
+ sourcedId;
34790
+ originalError;
34791
+ constructor(resourceType, sourcedId, originalError) {
34792
+ super(`${resourceType} with ID '${sourcedId}' already exists`);
34793
+ this.name = "ResourceAlreadyExistsError";
34794
+ this.resourceType = resourceType;
34795
+ this.sourcedId = sourcedId;
34796
+ this.originalError = originalError;
34797
+ Object.setPrototypeOf(this, ResourceAlreadyExistsError2.prototype);
34798
+ }
34799
+ };
34800
+ ResourceNotFoundError = class ResourceNotFoundError2 extends TimebackError {
34801
+ resourceType;
34802
+ sourcedId;
34803
+ constructor(resourceType, sourcedId) {
34804
+ const message = sourcedId === "setup-not-run" ? `TimeBack resources have not been created yet. ` + `Please run 'bunx @playcademy/timeback setup' to create the required resources ` + `(organization, course, components, etc.) before recording progress.` : `${resourceType} with ID '${sourcedId}' not found`;
34805
+ super(message);
34806
+ this.name = "ResourceNotFoundError";
34807
+ this.resourceType = resourceType;
34808
+ this.sourcedId = sourcedId;
34809
+ Object.setPrototypeOf(this, ResourceNotFoundError2.prototype);
34810
+ }
34811
+ };
34812
+ });
34813
+ init_ids = __esm3(() => {
34814
+ init_errors4();
34815
+ UUID_REGEX2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
34816
+ });
34817
+ exports_verify = {};
34818
+ __export2(exports_verify, {
34819
+ verifyTimebackResources: () => verifyTimebackResources,
34820
+ fetchTimebackConfig: () => fetchTimebackConfig
34821
+ });
34822
+ init_verify = __esm3(() => {
34823
+ init_constants5();
34824
+ init_ids();
34825
+ });
34826
+ init_constants5();
34827
+ SUBJECT_VALUES2 = TIMEBACK_SUBJECTS3;
34828
+ GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS2;
34829
+ init_ids();
34830
+ init_ids();
34831
+ init_verify();
34832
+ init_ids();
34833
+ init_constants5();
34834
+ init_errors4();
34835
+ init_constants5();
34836
+ if (process.env.DEBUG === "true") {
34837
+ process.env.TERM = "dumb";
34838
+ }
34839
+ TimebackAuthError = class TimebackAuthError extends Error {
34840
+ statusCode;
34841
+ constructor(message, statusCode) {
34842
+ super(message);
34843
+ this.name = ERROR_NAMES2.timebackAuth;
34844
+ this.statusCode = statusCode;
34845
+ }
34846
+ };
34847
+ init_ids();
34848
+ init_constants5();
34849
+ init_errors4();
34850
+ UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
34851
+ storage = new AsyncLocalStorage;
34852
+ init_constants5();
34853
+ init_constants5();
34854
+ init_errors4();
34855
+ init_constants5();
34856
+ init_constants5();
34857
+ init_constants5();
34858
+ init_constants5();
34859
+ init_constants5();
34860
+ init_ids();
34861
+ init_ids();
34862
+ init_errors4();
34863
+ init_ids();
34864
+ init_errors4();
34865
+ EmailSchema = exports_external.string().email();
34866
+ StudentSourcedIdSchema = exports_external.string().min(1, {
34867
+ message: "Student sourcedId must be a non-empty string"
34868
+ });
34869
+ StudentIdentifierSchema = exports_external.union([EmailSchema, StudentSourcedIdSchema]);
34870
+ init_ids();
34432
34871
  });
34433
34872
 
34434
- // ../timeback/dist/types.js
34435
- function isObject2(value) {
34436
- return typeof value === "object" && value !== null;
34437
- }
34438
- function isCourseMetadata(value) {
34439
- return isObject2(value);
34440
- }
34441
- function isResourceMetadata(value) {
34442
- return isObject2(value);
34443
- }
34444
- function isPlaycademyResourceMetadata2(value) {
34445
- if (!isObject2(value)) {
34446
- return false;
34873
+ // ../timeback/dist/constants.js
34874
+ function deriveTimebackCourseLevelFromGrade(grade) {
34875
+ if (grade === 13) {
34876
+ return TIMEBACK_COURSE_DEFAULTS.level.ap;
34447
34877
  }
34448
- if (!("mastery" in value) || value.mastery === undefined) {
34449
- return true;
34878
+ if (grade <= 5) {
34879
+ return TIMEBACK_COURSE_DEFAULTS.level.elementary;
34450
34880
  }
34451
- return isObject2(value.mastery);
34452
- }
34453
- function isTimebackSubject3(value) {
34454
- return typeof value === "string" && SUBJECT_VALUES2.includes(value);
34455
- }
34456
- function isTimebackGrade3(value) {
34457
- return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES2.includes(value);
34881
+ if (grade <= 8) {
34882
+ return TIMEBACK_COURSE_DEFAULTS.level.middle;
34883
+ }
34884
+ return TIMEBACK_COURSE_DEFAULTS.level.high;
34458
34885
  }
34459
- var __esm4 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS3, TIMEBACK_AUTH_URLS3, CALIPER_API_URLS3, ONEROSTER_ENDPOINTS3, QTI_ENDPOINTS3, CALIPER_ENDPOINTS3, CALIPER_CONSTANTS3, TIMEBACK_EVENT_TYPES3, TIMEBACK_ACTIONS3, TIMEBACK_TYPES3, ACTIVITY_METRIC_TYPES3, TIME_METRIC_TYPES3, TIMEBACK_SUBJECTS4, TIMEBACK_GRADE_LEVELS3, TIMEBACK_GRADE_LEVEL_LABELS3, CALIPER_SUBJECTS3, ONEROSTER_STATUS3, SCORE_STATUS3, ENV_VARS3, HTTP_DEFAULTS3, AUTH_DEFAULTS3, CACHE_DEFAULTS3, CONFIG_DEFAULTS3, PLAYCADEMY_DEFAULTS3, RESOURCE_DEFAULTS3, HTTP_STATUS3, ERROR_NAMES3, init_constants7, SUBJECT_VALUES2, GRADE_VALUES2;
34460
- var init_types3 = __esm(() => {
34886
+ var __esm4 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS3, QTI_API_URL2 = "https://qti.alpha-1edtech.ai/api", TIMEBACK_AUTH_URLS3, CALIPER_API_URLS3, ONEROSTER_ENDPOINTS3, QTI_ENDPOINTS3, CALIPER_ENDPOINTS3, CALIPER_CONSTANTS3, TIMEBACK_EVENT_TYPES3, TIMEBACK_ACTIONS3, TIMEBACK_TYPES3, ACTIVITY_METRIC_TYPES3, TIME_METRIC_TYPES3, TIMEBACK_SUBJECTS4, TIMEBACK_GRADE_LEVELS3, TIMEBACK_GRADE_LEVEL_LABELS3, CALIPER_SUBJECTS3, ONEROSTER_STATUS3, SCORE_STATUS3, ENV_VARS3, HTTP_DEFAULTS3, AUTH_DEFAULTS3, CACHE_DEFAULTS3, CONFIG_DEFAULTS3, PLAYCADEMY_DEFAULTS3, RESOURCE_DEFAULTS3, HTTP_STATUS3, ERROR_NAMES3, init_constants7;
34887
+ var init_constants6 = __esm(() => {
34461
34888
  init_src();
34462
34889
  init_constants7 = __esm4(() => {
34463
34890
  TIMEBACK_API_URLS3 = {
@@ -34642,8 +35069,6 @@ var init_types3 = __esm(() => {
34642
35069
  };
34643
35070
  });
34644
35071
  init_constants7();
34645
- SUBJECT_VALUES2 = TIMEBACK_SUBJECTS4;
34646
- GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS3;
34647
35072
  });
34648
35073
 
34649
35074
  // ../timeback/dist/utils.js
@@ -34665,7 +35090,7 @@ function deriveAssessmentBankIds(courseId) {
34665
35090
  function escapeFilterValue2(value) {
34666
35091
  return value.replaceAll("'", String.raw`\'`);
34667
35092
  }
34668
- var __esm5 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS4, TIMEBACK_AUTH_URLS4, CALIPER_API_URLS4, ONEROSTER_ENDPOINTS4, QTI_ENDPOINTS4, CALIPER_ENDPOINTS4, CALIPER_CONSTANTS4, TIMEBACK_EVENT_TYPES4, TIMEBACK_ACTIONS4, TIMEBACK_TYPES4, ACTIVITY_METRIC_TYPES4, TIME_METRIC_TYPES4, TIMEBACK_SUBJECTS5, TIMEBACK_GRADE_LEVELS4, TIMEBACK_GRADE_LEVEL_LABELS4, CALIPER_SUBJECTS4, ONEROSTER_STATUS4, SCORE_STATUS4, ENV_VARS4, HTTP_DEFAULTS4, AUTH_DEFAULTS4, CACHE_DEFAULTS4, CONFIG_DEFAULTS4, PLAYCADEMY_DEFAULTS4, RESOURCE_DEFAULTS4, HTTP_STATUS4, ERROR_NAMES4, init_constants8;
35093
+ var __esm5 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS4, TIMEBACK_AUTH_URLS4, CALIPER_API_URLS4, ONEROSTER_ENDPOINTS4, QTI_ENDPOINTS4, CALIPER_ENDPOINTS4, CALIPER_CONSTANTS4, TIMEBACK_EVENT_TYPES4, TIMEBACK_ACTIONS4, TIMEBACK_TYPES4, ACTIVITY_METRIC_TYPES4, TIME_METRIC_TYPES4, TIMEBACK_SUBJECTS5, TIMEBACK_GRADE_LEVELS4, TIMEBACK_GRADE_LEVEL_LABELS4, CALIPER_SUBJECTS4, ONEROSTER_STATUS4, SCORE_STATUS4, ENV_VARS4, HTTP_DEFAULTS4, AUTH_DEFAULTS4, CACHE_DEFAULTS4, CONFIG_DEFAULTS4, PLAYCADEMY_DEFAULTS4, RESOURCE_DEFAULTS4, HTTP_STATUS4, ERROR_NAMES4, init_constants8, TimebackError2, TimebackApiError2, TimebackAuthenticationError2, StudentNotFoundError2, ConfigurationError2, ResourceAlreadyExistsError2, ResourceNotFoundError2, init_errors5, UUID_REGEX3, init_ids2;
34669
35094
  var init_utils6 = __esm(() => {
34670
35095
  init_src();
34671
35096
  init_constants8 = __esm5(() => {
@@ -34850,6 +35275,82 @@ var init_utils6 = __esm(() => {
34850
35275
  timebackSdk: "TimebackSDKError"
34851
35276
  };
34852
35277
  });
35278
+ init_errors5 = __esm5(() => {
35279
+ init_constants8();
35280
+ TimebackError2 = class TimebackError3 extends Error {
35281
+ constructor(message) {
35282
+ super(message);
35283
+ this.name = ERROR_NAMES4.timebackSdk;
35284
+ }
35285
+ };
35286
+ TimebackApiError2 = class TimebackApiError3 extends Error {
35287
+ status;
35288
+ details;
35289
+ constructor(status, message, details) {
35290
+ super(`${status} ${message}`);
35291
+ this.name = ERROR_NAMES4.timebackApi;
35292
+ this.status = status;
35293
+ this.details = details;
35294
+ Object.setPrototypeOf(this, TimebackApiError3.prototype);
35295
+ }
35296
+ };
35297
+ TimebackAuthenticationError2 = class TimebackAuthenticationError3 extends TimebackError2 {
35298
+ constructor(message) {
35299
+ super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
35300
+ this.name = "TimebackAuthenticationError";
35301
+ Object.setPrototypeOf(this, TimebackAuthenticationError3.prototype);
35302
+ }
35303
+ };
35304
+ StudentNotFoundError2 = class StudentNotFoundError3 extends TimebackError2 {
35305
+ identifier;
35306
+ identifierType;
35307
+ constructor(identifier, identifierType = "email") {
35308
+ super(`Student not found with ${identifierType}: ${identifier}. ` + `Ensure the student exists in OneRoster. ` + `If this is a new student, they must be created in OneRoster first.`);
35309
+ this.name = "StudentNotFoundError";
35310
+ this.identifier = identifier;
35311
+ this.identifierType = identifierType;
35312
+ Object.setPrototypeOf(this, StudentNotFoundError3.prototype);
35313
+ }
35314
+ };
35315
+ ConfigurationError2 = class ConfigurationError3 extends TimebackError2 {
35316
+ field;
35317
+ constructor(field, message) {
35318
+ super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
35319
+ this.name = "ConfigurationError";
35320
+ this.field = field;
35321
+ Object.setPrototypeOf(this, ConfigurationError3.prototype);
35322
+ }
35323
+ };
35324
+ ResourceAlreadyExistsError2 = class ResourceAlreadyExistsError3 extends TimebackError2 {
35325
+ resourceType;
35326
+ sourcedId;
35327
+ originalError;
35328
+ constructor(resourceType, sourcedId, originalError) {
35329
+ super(`${resourceType} with ID '${sourcedId}' already exists`);
35330
+ this.name = "ResourceAlreadyExistsError";
35331
+ this.resourceType = resourceType;
35332
+ this.sourcedId = sourcedId;
35333
+ this.originalError = originalError;
35334
+ Object.setPrototypeOf(this, ResourceAlreadyExistsError3.prototype);
35335
+ }
35336
+ };
35337
+ ResourceNotFoundError2 = class ResourceNotFoundError3 extends TimebackError2 {
35338
+ resourceType;
35339
+ sourcedId;
35340
+ constructor(resourceType, sourcedId) {
35341
+ const message = sourcedId === "setup-not-run" ? `TimeBack resources have not been created yet. ` + `Please run 'bunx @playcademy/timeback setup' to create the required resources ` + `(organization, course, components, etc.) before recording progress.` : `${resourceType} with ID '${sourcedId}' not found`;
35342
+ super(message);
35343
+ this.name = "ResourceNotFoundError";
35344
+ this.resourceType = resourceType;
35345
+ this.sourcedId = sourcedId;
35346
+ Object.setPrototypeOf(this, ResourceNotFoundError3.prototype);
35347
+ }
35348
+ };
35349
+ });
35350
+ init_ids2 = __esm5(() => {
35351
+ init_errors5();
35352
+ UUID_REGEX3 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
35353
+ });
34853
35354
  init_constants8();
34854
35355
  init_constants8();
34855
35356
  if (process.env.DEBUG === "true") {
@@ -35012,333 +35513,6 @@ var init_timeback_admin_util = __esm(() => {
35012
35513
  init_errors();
35013
35514
  });
35014
35515
 
35015
- // ../api-core/src/utils/timeback.util.ts
35016
- function isRecord2(value) {
35017
- return typeof value === "object" && value !== null;
35018
- }
35019
- function filterEnrollmentsByGame(enrollments, gameId) {
35020
- return enrollments.filter((enrollment) => enrollment.gameId === gameId).map(({ gameId: _, ...enrollment }) => enrollment);
35021
- }
35022
- function mapEnrollmentsToUserEnrollments(enrollments, integrations) {
35023
- const enrollmentByCourse = new Map(enrollments.map((enrollment) => [enrollment.courseId, enrollment]));
35024
- const courseToSchool = new Map(enrollments.filter((enrollment) => enrollment.school?.id).map((enrollment) => [enrollment.courseId, enrollment.school.id]));
35025
- return integrations.map((integration) => {
35026
- const enrollment = enrollmentByCourse.get(integration.courseId);
35027
- return {
35028
- gameId: integration.gameId,
35029
- grade: integration.grade,
35030
- subject: integration.subject,
35031
- courseId: integration.courseId,
35032
- orgId: courseToSchool.get(integration.courseId),
35033
- ...enrollment ? { id: enrollment.sourcedId } : {}
35034
- };
35035
- });
35036
- }
35037
- function getStringValue(value) {
35038
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
35039
- }
35040
- function parseSourcedIdFromUrl(url2) {
35041
- if (!url2) {
35042
- return;
35043
- }
35044
- const trimmed = url2.trim().replace(/\/$/, "");
35045
- if (!trimmed) {
35046
- return;
35047
- }
35048
- const segments = trimmed.split("/");
35049
- const lastSegment = segments.at(-1);
35050
- return lastSegment ? decodeURIComponent(lastSegment) : undefined;
35051
- }
35052
- function getGeneratedMetricValue(event, type) {
35053
- const items = event.generated?.items;
35054
- if (!Array.isArray(items)) {
35055
- return;
35056
- }
35057
- const metric = items.find((item) => item?.type === type);
35058
- if (!metric) {
35059
- return;
35060
- }
35061
- const value = typeof metric.value === "number" ? metric.value : Number(metric.value);
35062
- return Number.isFinite(value) ? value : undefined;
35063
- }
35064
- function getMergedCaliperExtensions(event) {
35065
- const objectActivityExtensions = isRecord2(event.object.activity?.extensions) ? event.object.activity.extensions : undefined;
35066
- const generatedExtensions = isRecord2(event.generated?.extensions) ? event.generated.extensions : undefined;
35067
- const eventExtensions = isRecord2(event.extensions) ? event.extensions : undefined;
35068
- return {
35069
- ...objectActivityExtensions,
35070
- ...generatedExtensions,
35071
- ...eventExtensions
35072
- };
35073
- }
35074
- function getPlaycademyMetadata(event) {
35075
- const extensions = getMergedCaliperExtensions(event);
35076
- return isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
35077
- }
35078
- function getActivityId(event, playcademy) {
35079
- const metadataActivityId = getStringValue(playcademy?.activityId);
35080
- if (metadataActivityId) {
35081
- return metadataActivityId;
35082
- }
35083
- const activityId = getStringValue(event.object.activity?.id);
35084
- if (activityId) {
35085
- return activityId;
35086
- }
35087
- const objectId = getStringValue(event.object.id);
35088
- if (!objectId) {
35089
- return;
35090
- }
35091
- const trimmed = objectId.replace(/\/$/, "");
35092
- const segments = trimmed.split("/");
35093
- const activityIndex = segments.lastIndexOf("activities");
35094
- if (activityIndex !== -1 && segments.length >= activityIndex + 3) {
35095
- const candidate = segments[activityIndex + 2];
35096
- return candidate ? decodeURIComponent(candidate) : undefined;
35097
- }
35098
- return;
35099
- }
35100
- function buildResourceMetadata({
35101
- baseMetadata,
35102
- subject,
35103
- grade,
35104
- totalXp,
35105
- masterableUnits
35106
- }) {
35107
- const normalizedBaseMetadata = isResourceMetadata(baseMetadata) ? baseMetadata : undefined;
35108
- const metadata2 = {
35109
- ...normalizedBaseMetadata
35110
- };
35111
- metadata2.subject = subject;
35112
- metadata2.grades = [grade];
35113
- metadata2.xp = totalXp;
35114
- if (masterableUnits !== undefined && masterableUnits !== null) {
35115
- const existingPlaycademy = isPlaycademyResourceMetadata2(metadata2.playcademy) ? metadata2.playcademy : undefined;
35116
- metadata2.playcademy = {
35117
- ...existingPlaycademy,
35118
- mastery: {
35119
- ...existingPlaycademy?.mastery,
35120
- masterableUnits
35121
- }
35122
- };
35123
- }
35124
- return metadata2;
35125
- }
35126
- function getDurationSecondsFromExtensions(event) {
35127
- const extensions = getMergedCaliperExtensions(event);
35128
- const playcademy = isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
35129
- const rawValue = extensions.durationSeconds ?? playcademy?.durationSeconds;
35130
- const value = typeof rawValue === "number" ? rawValue : Number(rawValue);
35131
- return Number.isFinite(value) ? value : undefined;
35132
- }
35133
- function getCanonicalRunId(session2) {
35134
- const sessionId = getStringValue(session2?.id);
35135
- if (!sessionId) {
35136
- return;
35137
- }
35138
- return sessionId.replace(/^urn:uuid:/, "");
35139
- }
35140
- function getResumeId(event) {
35141
- const playcademy = getPlaycademyMetadata(event);
35142
- return getStringValue(playcademy?.resumeId);
35143
- }
35144
- function isCaliperRemediationOrCompletionEvent(event) {
35145
- const playcademy = getPlaycademyMetadata(event);
35146
- return REMEDIATION_OR_COMPLETION_EVENT_KINDS.has(getStringValue(playcademy?.eventKind) || "");
35147
- }
35148
- function groupCaliperEventsByRun(events) {
35149
- const groups = new Map;
35150
- for (const event of events) {
35151
- const objectId = getStringValue(event.object.id) || "unknown-activity";
35152
- const groupKey = `${objectId}::${getStringValue(event.session?.id) || event.externalId}`;
35153
- const existing = groups.get(groupKey);
35154
- if (existing) {
35155
- existing.push(event);
35156
- } else {
35157
- groups.set(groupKey, [event]);
35158
- }
35159
- }
35160
- return groups;
35161
- }
35162
- function findCaliperEventGroupContainingExternalId(events, externalId) {
35163
- const targetExternalId = externalId.trim();
35164
- if (!targetExternalId) {
35165
- return;
35166
- }
35167
- return [...groupCaliperEventsByRun(events).values()].find((group) => group.some((event) => event.externalId === targetExternalId));
35168
- }
35169
- function mapCaliperEventGroupToActivity(events, relevantCourseIds) {
35170
- if (events.length === 0) {
35171
- return null;
35172
- }
35173
- const sortedEvents = events.toSorted((a, b) => a.eventTime.localeCompare(b.eventTime));
35174
- const activityEvent = [...sortedEvents].toReversed().find((event) => event.type === "ActivityEvent");
35175
- const contextSource = activityEvent || sortedEvents.at(-1);
35176
- if (!contextSource) {
35177
- return null;
35178
- }
35179
- const ctx = parseCaliperEventContext(contextSource, relevantCourseIds);
35180
- if (!ctx) {
35181
- return null;
35182
- }
35183
- const score = activityEvent !== undefined ? (() => {
35184
- const totalQuestions = getGeneratedMetricValue(activityEvent, "totalQuestions");
35185
- const correctQuestions = getGeneratedMetricValue(activityEvent, "correctQuestions");
35186
- if (totalQuestions === undefined || correctQuestions === undefined || totalQuestions <= 0) {
35187
- return;
35188
- }
35189
- return correctQuestions / totalQuestions * 100;
35190
- })() : undefined;
35191
- const xpEarned = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "xpEarned") : undefined;
35192
- const masteredUnits = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "masteredUnits") : undefined;
35193
- const timeSpentEvents = sortedEvents.filter((event) => event.type === "TimeSpentEvent");
35194
- let totalActiveTimeSeconds;
35195
- if (timeSpentEvents.length > 0) {
35196
- totalActiveTimeSeconds = timeSpentEvents.reduce((sum, event) => sum + (getGeneratedMetricValue(event, "active") ?? 0), 0);
35197
- } else if (activityEvent !== undefined) {
35198
- totalActiveTimeSeconds = getDurationSecondsFromExtensions(activityEvent);
35199
- }
35200
- const fallbackActivityId = getActivityId(contextSource, getPlaycademyMetadata(contextSource));
35201
- const occurredAt = getStringValue(activityEvent?.eventTime) || getStringValue(sortedEvents.at(-1)?.eventTime);
35202
- const runId = getCanonicalRunId(contextSource.session);
35203
- const resumeIds = new Set(sortedEvents.map((event) => getResumeId(event)).filter((resumeId) => resumeId !== undefined));
35204
- const sessionCount = resumeIds.size > 0 ? resumeIds.size : 1;
35205
- const kind = activityEvent !== undefined ? "activity" : "activity-in-progress";
35206
- if (!occurredAt) {
35207
- return null;
35208
- }
35209
- return {
35210
- id: activityEvent?.externalId || sortedEvents.at(-1)?.externalId || events[0].externalId,
35211
- kind,
35212
- occurredAt,
35213
- courseId: ctx.courseId,
35214
- title: getStringValue(activityEvent?.object.activity?.name) || ctx.titleFromEvent || (fallbackActivityId ? kebabToTitleCase(fallbackActivityId) : "Activity completed"),
35215
- ...ctx.activityId ? { activityId: ctx.activityId } : {},
35216
- ...ctx.appName ? { appName: ctx.appName } : {},
35217
- ...score !== undefined ? { score } : {},
35218
- ...xpEarned !== undefined ? { xpDelta: xpEarned } : {},
35219
- ...masteredUnits !== undefined ? { masteredUnitsDelta: masteredUnits } : {},
35220
- ...totalActiveTimeSeconds !== undefined ? { timeDeltaSeconds: totalActiveTimeSeconds } : {},
35221
- ...runId ? { runId } : {},
35222
- ...sessionCount > 0 ? { sessionCount } : {}
35223
- };
35224
- }
35225
- function parseCaliperEventContext(event, relevantCourseIds) {
35226
- const playcademy = getPlaycademyMetadata(event);
35227
- const courseId = getStringValue(playcademy?.courseId) || parseSourcedIdFromUrl(event.object.course?.id);
35228
- if (!courseId || !relevantCourseIds.has(courseId)) {
35229
- return null;
35230
- }
35231
- const occurredAt = getStringValue(event.eventTime);
35232
- if (!occurredAt) {
35233
- return null;
35234
- }
35235
- return {
35236
- courseId,
35237
- occurredAt,
35238
- eventKind: getStringValue(playcademy?.eventKind),
35239
- source: getStringValue(playcademy?.source),
35240
- reason: getStringValue(playcademy?.reason),
35241
- titleFromEvent: getStringValue(event.object.activity?.name),
35242
- appName: getStringValue(event.object.app?.name),
35243
- activityId: getActivityId(event, playcademy)
35244
- };
35245
- }
35246
- function mapTimeSpentRemediation(event, ctx) {
35247
- if (ctx.eventKind !== "remediation-time") {
35248
- return null;
35249
- }
35250
- return {
35251
- id: event.externalId,
35252
- kind: "remediation-time",
35253
- occurredAt: ctx.occurredAt,
35254
- courseId: ctx.courseId,
35255
- title: "Time Adjustment",
35256
- activityId: ctx.activityId,
35257
- appName: ctx.appName,
35258
- reason: ctx.reason,
35259
- timeDeltaSeconds: getGeneratedMetricValue(event, "active")
35260
- };
35261
- }
35262
- function mapActivityRemediation(event, ctx) {
35263
- if (ctx.eventKind === "remediation-xp") {
35264
- return {
35265
- id: event.externalId,
35266
- kind: "remediation-xp",
35267
- occurredAt: ctx.occurredAt,
35268
- courseId: ctx.courseId,
35269
- title: "XP Adjustment",
35270
- activityId: ctx.activityId,
35271
- appName: ctx.appName,
35272
- reason: ctx.reason,
35273
- xpDelta: getGeneratedMetricValue(event, "xpEarned"),
35274
- masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
35275
- };
35276
- }
35277
- if (ctx.eventKind === "remediation-mastery") {
35278
- return {
35279
- id: event.externalId,
35280
- kind: "remediation-mastery",
35281
- occurredAt: ctx.occurredAt,
35282
- courseId: ctx.courseId,
35283
- title: "Mastery Adjustment",
35284
- activityId: ctx.activityId,
35285
- appName: ctx.appName,
35286
- reason: ctx.reason,
35287
- xpDelta: getGeneratedMetricValue(event, "xpEarned"),
35288
- masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
35289
- };
35290
- }
35291
- if (ctx.eventKind === "course-completed") {
35292
- return {
35293
- id: event.externalId,
35294
- kind: "course-completed",
35295
- occurredAt: ctx.occurredAt,
35296
- courseId: ctx.courseId,
35297
- title: ctx.source === "admin" ? "Course marked complete" : "Course completed",
35298
- activityId: ctx.activityId,
35299
- appName: ctx.appName,
35300
- reason: ctx.reason
35301
- };
35302
- }
35303
- if (ctx.eventKind === "course-resumed") {
35304
- return {
35305
- id: event.externalId,
35306
- kind: "course-resumed",
35307
- occurredAt: ctx.occurredAt,
35308
- courseId: ctx.courseId,
35309
- title: "Course resumed",
35310
- activityId: ctx.activityId,
35311
- appName: ctx.appName,
35312
- reason: ctx.reason
35313
- };
35314
- }
35315
- return null;
35316
- }
35317
- function mapCaliperEventToRemediationActivity(event, relevantCourseIds) {
35318
- const ctx = parseCaliperEventContext(event, relevantCourseIds);
35319
- if (!ctx) {
35320
- return null;
35321
- }
35322
- if (event.type === "TimeSpentEvent") {
35323
- return mapTimeSpentRemediation(event, ctx);
35324
- }
35325
- if (event.type === "ActivityEvent") {
35326
- return mapActivityRemediation(event, ctx);
35327
- }
35328
- return null;
35329
- }
35330
- var REMEDIATION_OR_COMPLETION_EVENT_KINDS;
35331
- var init_timeback_util = __esm(() => {
35332
- init_types3();
35333
- REMEDIATION_OR_COMPLETION_EVENT_KINDS = new Set([
35334
- "remediation-xp",
35335
- "remediation-time",
35336
- "remediation-mastery",
35337
- "course-completed",
35338
- "course-resumed"
35339
- ]);
35340
- });
35341
-
35342
35516
  // ../api-core/src/utils/timeback-discrepancy-queue.util.ts
35343
35517
  function parseDateInputParts(value) {
35344
35518
  const parts2 = value.split("-");
@@ -35712,7 +35886,7 @@ function isAllowedGradeLevelTestType(value) {
35712
35886
  }
35713
35887
  function isQualifyingGradeLevelTestResult(result, options) {
35714
35888
  const metadata2 = metadataOf(result);
35715
- return sourceIdFromRef(result.student) === options.studentId && normalizeText(result.status) === "active" && result.scoreStatus === SCORE_STATUS2.fullyGraded && normalizeText(metadata2.resultType) === "assessment" && stringField(metadata2.subject).trim() === options.subject && isAllowedGradeLevelTestType(metadata2.testType);
35889
+ return sourceIdFromRef(result.student) === options.studentId && normalizeText(result.status) === "active" && result.scoreStatus === SCORE_STATUS3.fullyGraded && normalizeText(metadata2.resultType) === "assessment" && stringField(metadata2.subject).trim() === options.subject && isAllowedGradeLevelTestType(metadata2.testType);
35716
35890
  }
35717
35891
  function mapGradeLevelTestSummary(result, options) {
35718
35892
  if (!isQualifyingGradeLevelTestResult(result, options)) {
@@ -35972,7 +36146,7 @@ function latestAssessmentResultsByLineItem(results) {
35972
36146
  const latestResultsByLineItem = new Map;
35973
36147
  for (const result of results) {
35974
36148
  const lineItemId = sourceIdFromRef(result.assessmentLineItem);
35975
- if (lineItemId && !latestResultsByLineItem.has(lineItemId) && result.scoreStatus === SCORE_STATUS2.fullyGraded) {
36149
+ if (lineItemId && !latestResultsByLineItem.has(lineItemId) && result.scoreStatus === SCORE_STATUS3.fullyGraded) {
35976
36150
  latestResultsByLineItem.set(lineItemId, result);
35977
36151
  }
35978
36152
  }
@@ -36072,7 +36246,7 @@ function qtiIdCandidates(parentLineItem, resource) {
36072
36246
  }
36073
36247
  var GRADE_LEVEL_TEST_TYPES, naturalTitleSort;
36074
36248
  var init_timeback_grade_level_results_util = __esm(() => {
36075
- init_constants5();
36249
+ init_constants6();
36076
36250
  init_utils6();
36077
36251
  GRADE_LEVEL_TEST_TYPES = [
36078
36252
  "placement",
@@ -36097,18 +36271,18 @@ async function upsertMasteryCompletionEntry(params) {
36097
36271
  await client.oneroster.assessmentLineItems.findOrCreate(lineItemId, {
36098
36272
  sourcedId: lineItemId,
36099
36273
  title: "Mastery Completion",
36100
- status: ONEROSTER_STATUS2.active,
36274
+ status: ONEROSTER_STATUS3.active,
36101
36275
  course: { sourcedId: ids.course },
36102
36276
  ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
36103
36277
  });
36104
36278
  await client.oneroster.assessmentResults.upsert(resultId, {
36105
36279
  sourcedId: resultId,
36106
- status: ONEROSTER_STATUS2.active,
36280
+ status: ONEROSTER_STATUS3.active,
36107
36281
  assessmentLineItem: { sourcedId: lineItemId },
36108
36282
  student: { sourcedId: studentId },
36109
36283
  score: 100,
36110
36284
  scoreDate: new Date().toISOString(),
36111
- scoreStatus: SCORE_STATUS2.fullyGraded,
36285
+ scoreStatus: SCORE_STATUS3.fullyGraded,
36112
36286
  inProgress: "false",
36113
36287
  metadata: {
36114
36288
  isMasteryCompletion: true,
@@ -36120,12 +36294,12 @@ async function upsertMasteryCompletionEntry(params) {
36120
36294
  try {
36121
36295
  await client.oneroster.assessmentResults.upsert(resultId, {
36122
36296
  sourcedId: resultId,
36123
- status: ONEROSTER_STATUS2.active,
36297
+ status: ONEROSTER_STATUS3.active,
36124
36298
  assessmentLineItem: { sourcedId: lineItemId },
36125
36299
  student: { sourcedId: studentId },
36126
36300
  score: 0,
36127
36301
  scoreDate: new Date().toISOString(),
36128
- scoreStatus: SCORE_STATUS2.notSubmitted,
36302
+ scoreStatus: SCORE_STATUS3.notSubmitted,
36129
36303
  inProgress: "true",
36130
36304
  metadata: {
36131
36305
  isMasteryCompletion: true,
@@ -36137,7 +36311,7 @@ async function upsertMasteryCompletionEntry(params) {
36137
36311
  }
36138
36312
  }
36139
36313
  var init_timeback_mastery_completion_util = __esm(() => {
36140
- init_constants5();
36314
+ init_constants6();
36141
36315
  init_utils6();
36142
36316
  });
36143
36317
 
@@ -36166,7 +36340,7 @@ class TimebackAdminService {
36166
36340
  this.deps = deps;
36167
36341
  }
36168
36342
  getGradeLevelTestCourseScope(integration) {
36169
- if (!isTimebackSubject(integration.subject) || !isTimebackGrade(integration.grade)) {
36343
+ if (!isTimebackSubject2(integration.subject) || !isTimebackGrade2(integration.grade)) {
36170
36344
  throw new ValidationError("Timeback integration has invalid grade or subject");
36171
36345
  }
36172
36346
  return {
@@ -36245,7 +36419,7 @@ class TimebackAdminService {
36245
36419
  await this.deps.validateDeveloperAccess(user, gameId);
36246
36420
  }
36247
36421
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
36248
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
36422
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
36249
36423
  });
36250
36424
  if (!integration) {
36251
36425
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -36343,7 +36517,7 @@ class TimebackAdminService {
36343
36517
  const ids = deriveSourcedIds2(courseId);
36344
36518
  const resource = await client.oneroster.resources.get(ids.resource);
36345
36519
  const playcademyMetadata = resource.metadata?.playcademy;
36346
- if (!isPlaycademyResourceMetadata2(playcademyMetadata)) {
36520
+ if (!isPlaycademyResourceMetadata(playcademyMetadata)) {
36347
36521
  return;
36348
36522
  }
36349
36523
  return playcademyMetadata?.mastery?.masterableUnits;
@@ -36747,7 +36921,7 @@ class TimebackAdminService {
36747
36921
  "app.timeback.include_inactive": options?.includeInactive ?? false
36748
36922
  });
36749
36923
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
36750
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
36924
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
36751
36925
  });
36752
36926
  if (!integration) {
36753
36927
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -36825,7 +36999,7 @@ class TimebackAdminService {
36825
36999
  columns: { id: true }
36826
37000
  }),
36827
37001
  this.deps.db.query.gameTimebackIntegrations.findMany({
36828
- where: eq(gameTimebackIntegrations.gameId, gameId)
37002
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
36829
37003
  }),
36830
37004
  this.deps.db.query.games.findFirst({
36831
37005
  where: eq(games.id, gameId),
@@ -36928,7 +37102,7 @@ class TimebackAdminService {
36928
37102
  "app.timeback.course_id": courseId
36929
37103
  });
36930
37104
  const integrations = await this.deps.db.query.gameTimebackIntegrations.findMany({
36931
- where: courseId ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId)) : eq(gameTimebackIntegrations.gameId, gameId)
37105
+ where: courseId ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus()) : and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
36932
37106
  });
36933
37107
  if (integrations.length === 0) {
36934
37108
  throw new NotFoundError("Timeback integration", gameId);
@@ -37018,7 +37192,7 @@ class TimebackAdminService {
37018
37192
  });
37019
37193
  const [integration, gameSource] = await Promise.all([
37020
37194
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37021
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37195
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37022
37196
  }),
37023
37197
  this.getGameActivitySource(gameId)
37024
37198
  ]);
@@ -37122,7 +37296,7 @@ class TimebackAdminService {
37122
37296
  "app.timeback.course_id": courseId
37123
37297
  });
37124
37298
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37125
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37299
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37126
37300
  });
37127
37301
  if (!integration) {
37128
37302
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -37177,7 +37351,7 @@ class TimebackAdminService {
37177
37351
  "app.timeback.assessment_result_id": resultId
37178
37352
  });
37179
37353
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37180
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37354
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37181
37355
  });
37182
37356
  if (!integration) {
37183
37357
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -37255,7 +37429,7 @@ class TimebackAdminService {
37255
37429
  });
37256
37430
  const [integration, gameSource, roster] = await Promise.all([
37257
37431
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37258
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37432
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37259
37433
  }),
37260
37434
  this.getGameActivitySource(gameId),
37261
37435
  client.oneroster.enrollments.listByCourse(courseId, {
@@ -37376,7 +37550,7 @@ class TimebackAdminService {
37376
37550
  });
37377
37551
  const [integration, gameSource] = await Promise.all([
37378
37552
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37379
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37553
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37380
37554
  }),
37381
37555
  this.getGameActivitySource(gameId)
37382
37556
  ]);
@@ -37460,7 +37634,7 @@ class TimebackAdminService {
37460
37634
  });
37461
37635
  const [integration, gameSource] = await Promise.all([
37462
37636
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37463
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37637
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37464
37638
  }),
37465
37639
  this.getGameActivitySource(gameId)
37466
37640
  ]);
@@ -37689,7 +37863,7 @@ class TimebackAdminService {
37689
37863
  "app.timeback.course_id": courseId
37690
37864
  });
37691
37865
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37692
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37866
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37693
37867
  });
37694
37868
  if (!integration) {
37695
37869
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -37760,7 +37934,7 @@ class TimebackAdminService {
37760
37934
  "app.timeback.enrollment.operation": "enroll"
37761
37935
  });
37762
37936
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37763
- where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId))
37937
+ where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId), isActiveGameTimebackIntegrationStatus())
37764
37938
  });
37765
37939
  if (!integration) {
37766
37940
  throw new NotFoundError("Timeback integration", `${data.gameId}:${data.courseId}`);
@@ -37800,7 +37974,7 @@ class TimebackAdminService {
37800
37974
  "app.timeback.enrollment.operation": "unenroll"
37801
37975
  });
37802
37976
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37803
- where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId))
37977
+ where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId), isActiveGameTimebackIntegrationStatus())
37804
37978
  });
37805
37979
  if (!integration) {
37806
37980
  throw new NotFoundError("Timeback integration", `${data.gameId}:${data.courseId}`);
@@ -37821,7 +37995,7 @@ class TimebackAdminService {
37821
37995
  "app.timeback.enrollment.operation": "reactivate"
37822
37996
  });
37823
37997
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37824
- where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId))
37998
+ where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId), isActiveGameTimebackIntegrationStatus())
37825
37999
  });
37826
38000
  if (!integration) {
37827
38001
  throw new NotFoundError("Timeback integration", `${data.gameId}:${data.courseId}`);
@@ -37867,7 +38041,7 @@ class TimebackAdminService {
37867
38041
  const resultId = `${lineItemId}:${studentId}:completion`;
37868
38042
  try {
37869
38043
  const result = await client.oneroster.assessmentResults.get(resultId);
37870
- if (result.scoreStatus === SCORE_STATUS2.fullyGraded) {
38044
+ if (result.scoreStatus === SCORE_STATUS3.fullyGraded) {
37871
38045
  return "complete";
37872
38046
  }
37873
38047
  return "incomplete";
@@ -37903,12 +38077,13 @@ class TimebackAdminService {
37903
38077
  var init_timeback_admin_service = __esm(() => {
37904
38078
  init_drizzle_orm();
37905
38079
  init_src();
38080
+ init_helpers_index();
37906
38081
  init_schemas_index();
37907
38082
  init_tables_index();
37908
38083
  init_spans();
37909
38084
  init_dist2();
37910
- init_constants5();
37911
- init_types3();
38085
+ init_constants6();
38086
+ init_types2();
37912
38087
  init_utils6();
37913
38088
  init_src4();
37914
38089
  init_timeback3();
@@ -37923,8 +38098,8 @@ var init_timeback_admin_service = __esm(() => {
37923
38098
  });
37924
38099
 
37925
38100
  // ../timeback/dist/errors.js
37926
- var __esm6 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS5, TIMEBACK_AUTH_URLS5, CALIPER_API_URLS5, ONEROSTER_ENDPOINTS5, QTI_ENDPOINTS5, CALIPER_ENDPOINTS5, CALIPER_CONSTANTS5, TIMEBACK_EVENT_TYPES5, TIMEBACK_ACTIONS5, TIMEBACK_TYPES5, ACTIVITY_METRIC_TYPES5, TIME_METRIC_TYPES5, TIMEBACK_SUBJECTS6, TIMEBACK_GRADE_LEVELS5, TIMEBACK_GRADE_LEVEL_LABELS5, CALIPER_SUBJECTS5, ONEROSTER_STATUS5, SCORE_STATUS5, ENV_VARS5, HTTP_DEFAULTS5, AUTH_DEFAULTS5, CACHE_DEFAULTS5, CONFIG_DEFAULTS5, PLAYCADEMY_DEFAULTS5, RESOURCE_DEFAULTS5, HTTP_STATUS5, ERROR_NAMES5, init_constants9, TimebackApiError2;
37927
- var init_errors4 = __esm(() => {
38101
+ var __esm6 = (fn, res) => () => (fn && (res = fn(fn = 0)), res), TIMEBACK_API_URLS5, TIMEBACK_AUTH_URLS5, CALIPER_API_URLS5, ONEROSTER_ENDPOINTS5, QTI_ENDPOINTS5, CALIPER_ENDPOINTS5, CALIPER_CONSTANTS5, TIMEBACK_EVENT_TYPES5, TIMEBACK_ACTIONS5, TIMEBACK_TYPES5, ACTIVITY_METRIC_TYPES5, TIME_METRIC_TYPES5, TIMEBACK_SUBJECTS6, TIMEBACK_GRADE_LEVELS5, TIMEBACK_GRADE_LEVEL_LABELS5, CALIPER_SUBJECTS5, ONEROSTER_STATUS5, SCORE_STATUS5, ENV_VARS5, HTTP_DEFAULTS5, AUTH_DEFAULTS5, CACHE_DEFAULTS5, CONFIG_DEFAULTS5, PLAYCADEMY_DEFAULTS5, RESOURCE_DEFAULTS5, HTTP_STATUS5, ERROR_NAMES5, init_constants9, TimebackError3, TimebackApiError3, TimebackAuthenticationError3, StudentNotFoundError3, ConfigurationError3, ResourceAlreadyExistsError3, ResourceNotFoundError3, init_errors7;
38102
+ var init_errors6 = __esm(() => {
37928
38103
  init_src();
37929
38104
  init_constants9 = __esm6(() => {
37930
38105
  TIMEBACK_API_URLS5 = {
@@ -38108,18 +38283,79 @@ var init_errors4 = __esm(() => {
38108
38283
  timebackSdk: "TimebackSDKError"
38109
38284
  };
38110
38285
  });
38111
- init_constants9();
38112
- TimebackApiError2 = class TimebackApiError2 extends Error {
38113
- status;
38114
- details;
38115
- constructor(status, message, details) {
38116
- super(`${status} ${message}`);
38117
- this.name = ERROR_NAMES5.timebackApi;
38118
- this.status = status;
38119
- this.details = details;
38120
- Object.setPrototypeOf(this, TimebackApiError2.prototype);
38121
- }
38122
- };
38286
+ init_errors7 = __esm6(() => {
38287
+ init_constants9();
38288
+ TimebackError3 = class TimebackError4 extends Error {
38289
+ constructor(message) {
38290
+ super(message);
38291
+ this.name = ERROR_NAMES5.timebackSdk;
38292
+ }
38293
+ };
38294
+ TimebackApiError3 = class TimebackApiError4 extends Error {
38295
+ status;
38296
+ details;
38297
+ constructor(status, message, details) {
38298
+ super(`${status} ${message}`);
38299
+ this.name = ERROR_NAMES5.timebackApi;
38300
+ this.status = status;
38301
+ this.details = details;
38302
+ Object.setPrototypeOf(this, TimebackApiError4.prototype);
38303
+ }
38304
+ };
38305
+ TimebackAuthenticationError3 = class TimebackAuthenticationError4 extends TimebackError3 {
38306
+ constructor(message) {
38307
+ super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
38308
+ this.name = "TimebackAuthenticationError";
38309
+ Object.setPrototypeOf(this, TimebackAuthenticationError4.prototype);
38310
+ }
38311
+ };
38312
+ StudentNotFoundError3 = class StudentNotFoundError4 extends TimebackError3 {
38313
+ identifier;
38314
+ identifierType;
38315
+ constructor(identifier, identifierType = "email") {
38316
+ super(`Student not found with ${identifierType}: ${identifier}. ` + `Ensure the student exists in OneRoster. ` + `If this is a new student, they must be created in OneRoster first.`);
38317
+ this.name = "StudentNotFoundError";
38318
+ this.identifier = identifier;
38319
+ this.identifierType = identifierType;
38320
+ Object.setPrototypeOf(this, StudentNotFoundError4.prototype);
38321
+ }
38322
+ };
38323
+ ConfigurationError3 = class ConfigurationError4 extends TimebackError3 {
38324
+ field;
38325
+ constructor(field, message) {
38326
+ super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
38327
+ this.name = "ConfigurationError";
38328
+ this.field = field;
38329
+ Object.setPrototypeOf(this, ConfigurationError4.prototype);
38330
+ }
38331
+ };
38332
+ ResourceAlreadyExistsError3 = class ResourceAlreadyExistsError4 extends TimebackError3 {
38333
+ resourceType;
38334
+ sourcedId;
38335
+ originalError;
38336
+ constructor(resourceType, sourcedId, originalError) {
38337
+ super(`${resourceType} with ID '${sourcedId}' already exists`);
38338
+ this.name = "ResourceAlreadyExistsError";
38339
+ this.resourceType = resourceType;
38340
+ this.sourcedId = sourcedId;
38341
+ this.originalError = originalError;
38342
+ Object.setPrototypeOf(this, ResourceAlreadyExistsError4.prototype);
38343
+ }
38344
+ };
38345
+ ResourceNotFoundError3 = class ResourceNotFoundError4 extends TimebackError3 {
38346
+ resourceType;
38347
+ sourcedId;
38348
+ constructor(resourceType, sourcedId) {
38349
+ const message = sourcedId === "setup-not-run" ? `TimeBack resources have not been created yet. ` + `Please run 'bunx @playcademy/timeback setup' to create the required resources ` + `(organization, course, components, etc.) before recording progress.` : `${resourceType} with ID '${sourcedId}' not found`;
38350
+ super(message);
38351
+ this.name = "ResourceNotFoundError";
38352
+ this.resourceType = resourceType;
38353
+ this.sourcedId = sourcedId;
38354
+ Object.setPrototypeOf(this, ResourceNotFoundError4.prototype);
38355
+ }
38356
+ };
38357
+ });
38358
+ init_errors7();
38123
38359
  });
38124
38360
 
38125
38361
  // ../api-core/src/services/timeback-assessments.service.ts
@@ -38131,7 +38367,7 @@ class TimebackAssessmentsService {
38131
38367
  async resolveIntegrationId(gameId, courseId, user) {
38132
38368
  await this.deps.validateGameManagementAccess(user, gameId);
38133
38369
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
38134
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
38370
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
38135
38371
  });
38136
38372
  if (!integration) {
38137
38373
  throw new NotFoundError(`No Timeback integration found for game ${gameId} course ${courseId}`);
@@ -38224,7 +38460,7 @@ class TimebackAssessmentsService {
38224
38460
  ]
38225
38461
  });
38226
38462
  } catch (error) {
38227
- if (error instanceof TimebackApiError2 && error.status === 409) {} else {
38463
+ if (error instanceof TimebackApiError3 && error.status === 409) {} else {
38228
38464
  throw error;
38229
38465
  }
38230
38466
  }
@@ -38524,7 +38760,7 @@ class TimebackAssessmentsService {
38524
38760
  }
38525
38761
  async requireIntegration(integrationId) {
38526
38762
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
38527
- where: eq(gameTimebackIntegrations.id, integrationId)
38763
+ where: and(eq(gameTimebackIntegrations.id, integrationId), isActiveGameTimebackIntegrationStatus())
38528
38764
  });
38529
38765
  if (!integration) {
38530
38766
  throw new NotFoundError(`Integration not found: ${integrationId}`);
@@ -38555,7 +38791,7 @@ class TimebackAssessmentsService {
38555
38791
  }
38556
38792
  });
38557
38793
  } catch (error) {
38558
- if (!(error instanceof TimebackApiError2 && error.status === 409)) {
38794
+ if (!(error instanceof TimebackApiError3 && error.status === 409)) {
38559
38795
  throw error;
38560
38796
  }
38561
38797
  }
@@ -38577,7 +38813,7 @@ class TimebackAssessmentsService {
38577
38813
  }
38578
38814
  });
38579
38815
  } catch (error) {
38580
- if (!(error instanceof TimebackApiError2 && error.status === 409)) {
38816
+ if (!(error instanceof TimebackApiError3 && error.status === 409)) {
38581
38817
  throw error;
38582
38818
  }
38583
38819
  }
@@ -38595,7 +38831,7 @@ class TimebackAssessmentsService {
38595
38831
  }
38596
38832
  });
38597
38833
  } catch (error) {
38598
- if (!(error instanceof TimebackApiError2 && error.status === 409)) {
38834
+ if (!(error instanceof TimebackApiError3 && error.status === 409)) {
38599
38835
  throw error;
38600
38836
  }
38601
38837
  }
@@ -38613,14 +38849,63 @@ class TimebackAssessmentsService {
38613
38849
  }
38614
38850
  var init_timeback_assessments_service = __esm(() => {
38615
38851
  init_drizzle_orm();
38852
+ init_helpers_index();
38616
38853
  init_tables_index();
38617
38854
  init_spans();
38618
- init_constants5();
38619
- init_errors4();
38855
+ init_constants6();
38856
+ init_errors6();
38620
38857
  init_utils6();
38621
38858
  init_errors();
38622
38859
  });
38623
38860
 
38861
+ // ../api-core/src/utils/timeback-create-integration.util.ts
38862
+ function buildTimebackBaseConfigFromExistingConfig(config2) {
38863
+ return {
38864
+ organization: config2.organization,
38865
+ component: {
38866
+ ...config2.component,
38867
+ title: ""
38868
+ },
38869
+ resource: {
38870
+ ...config2.resource,
38871
+ title: ""
38872
+ },
38873
+ componentResource: {
38874
+ ...config2.componentResource,
38875
+ title: ""
38876
+ }
38877
+ };
38878
+ }
38879
+ function getMasterableUnitsFromTimebackConfig(config2) {
38880
+ const playcademyMetadata = config2.resource.metadata?.playcademy;
38881
+ if (!isPlaycademyResourceMetadata(playcademyMetadata)) {
38882
+ return null;
38883
+ }
38884
+ return playcademyMetadata?.mastery?.masterableUnits ?? null;
38885
+ }
38886
+ function getTotalXpFromTimebackConfig(config2) {
38887
+ const courseMetadata = isCourseMetadata(config2.course.metadata) ? config2.course.metadata : undefined;
38888
+ if (typeof courseMetadata?.metrics?.totalXp === "number") {
38889
+ return courseMetadata.metrics.totalXp;
38890
+ }
38891
+ const resourceMetadata = config2.resource.metadata;
38892
+ if (isRecord2(resourceMetadata) && typeof resourceMetadata.xp === "number") {
38893
+ return resourceMetadata.xp;
38894
+ }
38895
+ return null;
38896
+ }
38897
+ function timebackConfigMatchesCreateIntegrationRequest(config2, request2) {
38898
+ const subject = config2.course.subjects[0];
38899
+ const grade = config2.course.grades[0];
38900
+ const requestedLevel = request2.level ?? deriveTimebackCourseLevelFromGrade(request2.grade);
38901
+ return subject === request2.subject && grade === request2.grade && config2.course.title === request2.title && config2.course.courseCode === request2.courseCode && config2.course.level === requestedLevel && (getTotalXpFromTimebackConfig(config2) ?? null) === request2.totalXp && (getMasterableUnitsFromTimebackConfig(config2) ?? null) === request2.masterableUnits;
38902
+ }
38903
+ var init_timeback_create_integration_util = __esm(() => {
38904
+ init_constants6();
38905
+ init_types2();
38906
+ init_timeback_util();
38907
+ });
38908
+
38624
38909
  // ../api-core/src/utils/timeback-promotion.util.ts
38625
38910
  async function promoteCompletedCourse({
38626
38911
  db: db2,
@@ -38630,7 +38915,7 @@ async function promoteCompletedCourse({
38630
38915
  enrollments: prefetchedEnrollments
38631
38916
  }) {
38632
38917
  const subjectIntegrations = await db2.query.gameTimebackIntegrations.findMany({
38633
- where: and(eq(gameTimebackIntegrations.gameId, currentIntegration.gameId), eq(gameTimebackIntegrations.subject, currentIntegration.subject))
38918
+ where: and(eq(gameTimebackIntegrations.gameId, currentIntegration.gameId), eq(gameTimebackIntegrations.subject, currentIntegration.subject), isActiveGameTimebackIntegrationStatus())
38634
38919
  });
38635
38920
  const nextIntegration = subjectIntegrations.filter((integration) => integration.grade > currentIntegration.grade).toSorted((left, right) => left.grade - right.grade)[0];
38636
38921
  if (!nextIntegration) {
@@ -38685,21 +38970,72 @@ async function promoteCompletedCourse({
38685
38970
  }
38686
38971
  var init_timeback_promotion_util = __esm(() => {
38687
38972
  init_drizzle_orm();
38973
+ init_helpers_index();
38688
38974
  init_tables_index();
38689
38975
  init_spans();
38690
38976
  });
38691
38977
 
38978
+ // ../api-core/src/utils/timeback-removed-integration.util.ts
38979
+ function toGameTimebackIntegration(integration) {
38980
+ return {
38981
+ id: integration.id,
38982
+ gameId: integration.gameId,
38983
+ courseId: integration.courseId,
38984
+ grade: integration.grade,
38985
+ subject: integration.subject,
38986
+ totalXp: integration.totalXp ?? null,
38987
+ status: integration.status ?? ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
38988
+ deactivatedAt: integration.deactivatedAt ?? null,
38989
+ reactivatedAt: integration.reactivatedAt ?? null,
38990
+ createdAt: integration.createdAt,
38991
+ updatedAt: integration.updatedAt,
38992
+ lastVerifiedAt: integration.lastVerifiedAt ?? null
38993
+ };
38994
+ }
38995
+ function buildFallbackRemovedGameTimebackIntegration(integration) {
38996
+ if (!isTimebackSubject(integration.subject)) {
38997
+ throw new ValidationError(`Invalid subject "${integration.subject}"`);
38998
+ }
38999
+ if (!isTimebackGrade(integration.grade)) {
39000
+ throw new ValidationError(`Invalid grade "${integration.grade}"`);
39001
+ }
39002
+ return {
39003
+ integration: toGameTimebackIntegration(integration),
39004
+ title: `${integration.subject} ${formatGradeLabel(integration.grade)}`,
39005
+ courseCode: integration.courseId,
39006
+ subject: integration.subject,
39007
+ grade: integration.grade,
39008
+ totalXp: integration.totalXp ?? null,
39009
+ masterableUnits: null,
39010
+ removedAt: integration.deactivatedAt ?? null,
39011
+ metadata: null
39012
+ };
39013
+ }
39014
+ var init_timeback_removed_integration_util = __esm(() => {
39015
+ init_helpers_index();
39016
+ init_types2();
39017
+ init_timeback3();
39018
+ init_errors();
39019
+ });
39020
+
38692
39021
  // ../api-core/src/services/timeback.service.ts
39022
+ async function findGameTimebackIntegrationForUpdate(db2, condition) {
39023
+ const [integration] = await db2.select().from(gameTimebackIntegrations).where(condition).limit(1).for("update");
39024
+ return integration;
39025
+ }
38693
39026
  var TimebackService;
38694
39027
  var init_timeback_service = __esm(() => {
38695
39028
  init_drizzle_orm();
38696
39029
  init_src();
39030
+ init_helpers_index();
38697
39031
  init_tables_index();
38698
39032
  init_spans();
38699
39033
  init_dist2();
38700
- init_types3();
39034
+ init_types2();
38701
39035
  init_errors();
39036
+ init_timeback_create_integration_util();
38702
39037
  init_timeback_promotion_util();
39038
+ init_timeback_removed_integration_util();
38703
39039
  init_timeback_util();
38704
39040
  TimebackService = class TimebackService {
38705
39041
  static HEARTBEAT_DEDUPE_TTL_MS = 5 * 60 * 1000;
@@ -38929,7 +39265,7 @@ var init_timeback_service = __esm(() => {
38929
39265
  return [];
38930
39266
  }
38931
39267
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
38932
- where: inArray(gameTimebackIntegrations.courseId, courseIds)
39268
+ where: and(inArray(gameTimebackIntegrations.courseId, courseIds), isActiveGameTimebackIntegrationStatus())
38933
39269
  });
38934
39270
  return mapEnrollmentsToUserEnrollments(enrollments, integrations);
38935
39271
  } catch (error) {
@@ -38954,6 +39290,7 @@ var init_timeback_service = __esm(() => {
38954
39290
  const verboseData = [];
38955
39291
  let integrationCreatedCount = 0;
38956
39292
  let integrationUpdatedCount = 0;
39293
+ let integrationReactivatedCount = 0;
38957
39294
  for (const courseConfig of courses) {
38958
39295
  let applySuffix = function(text3) {
38959
39296
  return suffix ? `${text3} ${suffix}` : text3;
@@ -38968,16 +39305,16 @@ var init_timeback_service = __esm(() => {
38968
39305
  totalXp: derivedTotalXp,
38969
39306
  masterableUnits: derivedMasterableUnits
38970
39307
  } = courseConfig;
38971
- if (!isTimebackSubject3(subjectInput)) {
39308
+ if (!isTimebackSubject(subjectInput)) {
38972
39309
  throw new ValidationError(`Invalid subject "${subjectInput}"`);
38973
39310
  }
38974
- if (!isTimebackGrade3(grade)) {
39311
+ if (!isTimebackGrade(grade)) {
38975
39312
  throw new ValidationError(`Invalid grade "${grade}"`);
38976
39313
  }
38977
39314
  const subject = subjectInput;
38978
39315
  const courseMetadata = isCourseMetadata(metadata2) ? metadata2 : undefined;
38979
39316
  const totalXp = derivedTotalXp ?? courseMetadata?.metrics?.totalXp;
38980
- const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata2(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
39317
+ const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
38981
39318
  if (typeof totalXp !== "number") {
38982
39319
  throw new ValidationError(`Course "${title}" is missing totalXp`);
38983
39320
  }
@@ -39023,19 +39360,28 @@ var init_timeback_service = __esm(() => {
39023
39360
  title: applySuffix(baseConfig.componentResource.title || "")
39024
39361
  }
39025
39362
  };
39026
- const existingIntegration = existing.find((i2) => i2.grade === grade && i2.subject === subject);
39363
+ const matches = existing.filter((i2) => i2.grade === grade && i2.subject === subject);
39364
+ const existingIntegration = matches.find((i2) => i2.status !== DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS) ?? matches.toSorted((a, b) => (b.deactivatedAt?.getTime() ?? 0) - (a.deactivatedAt?.getTime() ?? 0))[0];
39027
39365
  if (existingIntegration) {
39028
- await client.update(existingIntegration.courseId, fullConfig);
39029
- const [updated] = await db2.update(gameTimebackIntegrations).set({ subject, totalXp, updatedAt: new Date }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
39366
+ const { updated, revived } = await this.updateSetupIntegration({
39367
+ client,
39368
+ existingIntegration,
39369
+ fullConfig,
39370
+ subject,
39371
+ totalXp
39372
+ });
39030
39373
  if (updated) {
39031
- integrations.push(this.toGameTimebackIntegration(updated));
39374
+ integrations.push(toGameTimebackIntegration(updated));
39032
39375
  integrationUpdatedCount++;
39376
+ if (revived) {
39377
+ integrationReactivatedCount++;
39378
+ }
39033
39379
  }
39034
39380
  } else {
39035
39381
  const result = await client.setup(fullConfig, { verbose });
39036
39382
  const [integration] = await db2.insert(gameTimebackIntegrations).values({ gameId, courseId: result.courseId, grade, subject, totalXp }).returning();
39037
39383
  if (integration) {
39038
- const dto = this.toGameTimebackIntegration(integration);
39384
+ const dto = toGameTimebackIntegration(integration);
39039
39385
  integrations.push(dto);
39040
39386
  integrationCreatedCount++;
39041
39387
  if (verbose && result.verboseData) {
@@ -39047,7 +39393,8 @@ var init_timeback_service = __esm(() => {
39047
39393
  setAttributes({
39048
39394
  "app.timeback.integration_count": integrations.length,
39049
39395
  "app.timeback.integration_created_count": integrationCreatedCount,
39050
- "app.timeback.integration_updated_count": integrationUpdatedCount
39396
+ "app.timeback.integration_updated_count": integrationUpdatedCount,
39397
+ "app.timeback.integration_reactivated_count": integrationReactivatedCount
39051
39398
  });
39052
39399
  return {
39053
39400
  integrations,
@@ -39055,19 +39402,221 @@ var init_timeback_service = __esm(() => {
39055
39402
  };
39056
39403
  });
39057
39404
  }
39405
+ async updateSetupIntegration(args2) {
39406
+ const { client, existingIntegration, fullConfig, subject, totalXp } = args2;
39407
+ const revived = existingIntegration.status === DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS;
39408
+ await client.update(existingIntegration.courseId, fullConfig);
39409
+ if (revived) {
39410
+ await client.reactivateCourse(existingIntegration.courseId);
39411
+ }
39412
+ const now2 = new Date;
39413
+ const [updated] = await this.deps.db.update(gameTimebackIntegrations).set({
39414
+ subject,
39415
+ totalXp,
39416
+ updatedAt: now2,
39417
+ ...revived && {
39418
+ status: ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
39419
+ deactivatedAt: null,
39420
+ reactivatedAt: now2
39421
+ }
39422
+ }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
39423
+ return { updated, revived };
39424
+ }
39425
+ async createIntegration(gameId, user, request2) {
39426
+ return this.withClientTelemetry(async () => {
39427
+ const client = this.requireClient();
39428
+ const db2 = this.deps.db;
39429
+ await this.deps.validateDeveloperAccess(user, gameId);
39430
+ setAttributes({
39431
+ "app.timeback.grade": request2.grade,
39432
+ "app.timeback.subject": request2.subject
39433
+ });
39434
+ const activeConflict = await db2.query.gameTimebackIntegrations.findFirst({
39435
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, request2.grade), eq(gameTimebackIntegrations.subject, request2.subject), isActiveGameTimebackIntegrationStatus())
39436
+ });
39437
+ if (activeConflict) {
39438
+ throw new ConflictError(`A TimeBack integration already exists for ${request2.subject} Grade ${request2.grade}`);
39439
+ }
39440
+ const removedCandidates = await db2.query.gameTimebackIntegrations.findMany({
39441
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, request2.grade), eq(gameTimebackIntegrations.subject, request2.subject), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS))
39442
+ });
39443
+ for (const candidate of removedCandidates) {
39444
+ const config2 = await client.getConfig(candidate.courseId).catch((error) => {
39445
+ addEvent("timeback.removed_integration_config_fetch_failed", {
39446
+ "app.game.id": gameId,
39447
+ "app.timeback.course_id": candidate.courseId,
39448
+ "exception.type": errorType(error),
39449
+ "app.error.message": errorMessage(error)
39450
+ });
39451
+ return null;
39452
+ });
39453
+ if (config2 && timebackConfigMatchesCreateIntegrationRequest(config2, request2)) {
39454
+ const updated = await db2.transaction(async (tx) => {
39455
+ const database = tx;
39456
+ const lockedCandidate = await findGameTimebackIntegrationForUpdate(database, eq(gameTimebackIntegrations.id, candidate.id));
39457
+ if (lockedCandidate?.status !== DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS) {
39458
+ throw new ConflictError(`A TimeBack integration already exists for ${request2.subject} Grade ${request2.grade}`);
39459
+ }
39460
+ const now2 = new Date;
39461
+ const [integration2] = await database.update(gameTimebackIntegrations).set({
39462
+ status: ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
39463
+ totalXp: request2.totalXp,
39464
+ deactivatedAt: null,
39465
+ reactivatedAt: now2,
39466
+ updatedAt: now2
39467
+ }).where(and(eq(gameTimebackIntegrations.id, candidate.id), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS))).returning();
39468
+ if (!integration2) {
39469
+ throw new NotFoundError("Timeback integration", candidate.id);
39470
+ }
39471
+ await client.reactivateCourse(candidate.courseId);
39472
+ return integration2;
39473
+ });
39474
+ setAttribute("app.timeback.course_create_mode", "reactivated-removed");
39475
+ return toGameTimebackIntegration(updated);
39476
+ }
39477
+ }
39478
+ const reference = await db2.query.gameTimebackIntegrations.findFirst({
39479
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus()),
39480
+ orderBy: (table8, { asc: asc2 }) => [asc2(table8.createdAt)]
39481
+ }) ?? await db2.query.gameTimebackIntegrations.findFirst({
39482
+ where: eq(gameTimebackIntegrations.gameId, gameId),
39483
+ orderBy: (table8, { asc: asc2 }) => [asc2(table8.createdAt)]
39484
+ });
39485
+ if (!reference) {
39486
+ throw new ValidationError("Run `playcademy timeback setup` before adding courses from the dashboard.");
39487
+ }
39488
+ const referenceConfig = await client.getConfig(reference.courseId);
39489
+ const result = await this.setupIntegration(gameId, {
39490
+ gameId,
39491
+ courses: [
39492
+ {
39493
+ title: request2.title,
39494
+ courseCode: request2.courseCode,
39495
+ subject: request2.subject,
39496
+ grade: request2.grade,
39497
+ level: request2.level ?? deriveTimebackCourseLevelFromGrade(request2.grade),
39498
+ totalXp: request2.totalXp,
39499
+ masterableUnits: request2.masterableUnits
39500
+ }
39501
+ ],
39502
+ baseConfig: buildTimebackBaseConfigFromExistingConfig(referenceConfig)
39503
+ }, user);
39504
+ const integration = result.integrations[0];
39505
+ if (!integration) {
39506
+ throw new InternalError("TimeBack course creation did not return an integration");
39507
+ }
39508
+ setAttribute("app.timeback.course_create_mode", "created-new");
39509
+ return integration;
39510
+ });
39511
+ }
39058
39512
  async getIntegrations(gameId, user) {
39059
39513
  await this.deps.validateGameManagementAccess(user, gameId);
39060
39514
  const rows = await this.deps.db.query.gameTimebackIntegrations.findMany({
39061
- where: eq(gameTimebackIntegrations.gameId, gameId)
39515
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39516
+ });
39517
+ return rows.map((row) => toGameTimebackIntegration(row));
39518
+ }
39519
+ async getRemovedIntegrations(gameId, user) {
39520
+ return this.withClientTelemetry(async () => {
39521
+ const client = this.requireClient();
39522
+ await this.deps.validateGameManagementAccess(user, gameId);
39523
+ const rows = await this.deps.db.query.gameTimebackIntegrations.findMany({
39524
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS)),
39525
+ orderBy: (table8, { asc: asc2 }) => [asc2(table8.subject), asc2(table8.grade)]
39526
+ });
39527
+ setAttribute("app.timeback.removed_integration_count", rows.length);
39528
+ return Promise.all(rows.map(async (row) => {
39529
+ try {
39530
+ const config2 = await client.getConfig(row.courseId);
39531
+ return this.toRemovedGameTimebackIntegration(row, config2);
39532
+ } catch (error) {
39533
+ addEvent("timeback.removed_integration_config_fetch_failed", {
39534
+ "app.game.id": gameId,
39535
+ "app.timeback.course_id": row.courseId,
39536
+ "exception.type": errorType(error),
39537
+ "app.error.message": errorMessage(error)
39538
+ });
39539
+ return buildFallbackRemovedGameTimebackIntegration(row);
39540
+ }
39541
+ }));
39542
+ });
39543
+ }
39544
+ async deactivateCourse(gameId, courseId, user) {
39545
+ return this.withClientTelemetry(async () => {
39546
+ const client = this.requireClient();
39547
+ const db2 = this.deps.db;
39548
+ await this.deps.validateDeveloperAccess(user, gameId);
39549
+ const updated = await db2.transaction(async (tx) => {
39550
+ const database = tx;
39551
+ const integration = await findGameTimebackIntegrationForUpdate(database, and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus()));
39552
+ if (!integration) {
39553
+ throw new NotFoundError("Timeback course", `${gameId}:${courseId}`);
39554
+ }
39555
+ const activeEnrollments = await client.oneroster.enrollments.listByCourse(courseId, {
39556
+ role: "student",
39557
+ includeUsers: false
39558
+ });
39559
+ setAttribute("app.timeback.active_enrollment_count", activeEnrollments.length);
39560
+ if (activeEnrollments.length > 0) {
39561
+ throw new ConflictError("Cannot remove course with active enrollments", {
39562
+ courseId,
39563
+ activeEnrollmentCount: activeEnrollments.length
39564
+ });
39565
+ }
39566
+ const now2 = new Date;
39567
+ const [updatedIntegration] = await database.update(gameTimebackIntegrations).set({
39568
+ status: DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS,
39569
+ deactivatedAt: now2,
39570
+ updatedAt: now2
39571
+ }).where(and(eq(gameTimebackIntegrations.id, integration.id), isActiveGameTimebackIntegrationStatus())).returning();
39572
+ if (!updatedIntegration) {
39573
+ throw new NotFoundError("Timeback course", `${gameId}:${courseId}`);
39574
+ }
39575
+ await client.deactivateCourse(courseId);
39576
+ return updatedIntegration;
39577
+ });
39578
+ return toGameTimebackIntegration(updated);
39579
+ });
39580
+ }
39581
+ async reactivateCourse(gameId, courseId, user) {
39582
+ return this.withClientTelemetry(async () => {
39583
+ const client = this.requireClient();
39584
+ const db2 = this.deps.db;
39585
+ await this.deps.validateDeveloperAccess(user, gameId);
39586
+ const updated = await db2.transaction(async (tx) => {
39587
+ const database = tx;
39588
+ const integration = await findGameTimebackIntegrationForUpdate(database, and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS)));
39589
+ if (!integration) {
39590
+ throw new NotFoundError("Removed Timeback course", `${gameId}:${courseId}`);
39591
+ }
39592
+ const activeConflict = await database.query.gameTimebackIntegrations.findFirst({
39593
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, integration.subject), isActiveGameTimebackIntegrationStatus())
39594
+ });
39595
+ if (activeConflict) {
39596
+ throw new ConflictError(`An active TimeBack course already exists for ${integration.subject} Grade ${integration.grade}`);
39597
+ }
39598
+ const now2 = new Date;
39599
+ const [updatedIntegration] = await database.update(gameTimebackIntegrations).set({
39600
+ status: ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
39601
+ deactivatedAt: null,
39602
+ reactivatedAt: now2,
39603
+ updatedAt: now2
39604
+ }).where(and(eq(gameTimebackIntegrations.id, integration.id), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS))).returning();
39605
+ if (!updatedIntegration) {
39606
+ throw new NotFoundError("Timeback course", `${gameId}:${courseId}`);
39607
+ }
39608
+ await client.reactivateCourse(courseId);
39609
+ return updatedIntegration;
39610
+ });
39611
+ return toGameTimebackIntegration(updated);
39062
39612
  });
39063
- return rows.map((row) => this.toGameTimebackIntegration(row));
39064
39613
  }
39065
39614
  async getIntegrationConfig(gameId, courseId, user) {
39066
39615
  return this.withClientTelemetry(async () => {
39067
39616
  const client = this.requireClient();
39068
39617
  await this.deps.validateGameManagementAccess(user, gameId);
39069
39618
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39070
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
39619
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
39071
39620
  });
39072
39621
  if (!integration) {
39073
39622
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -39084,15 +39633,15 @@ var init_timeback_service = __esm(() => {
39084
39633
  "app.timeback.course_id": courseId
39085
39634
  });
39086
39635
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39087
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
39636
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
39088
39637
  });
39089
39638
  if (!integration) {
39090
39639
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
39091
39640
  }
39092
39641
  const timebackConfig = await client.getConfig(courseId);
39093
39642
  const liveSubject = timebackConfig.course.subjects[0];
39094
- const subject = patch.subject ?? (isTimebackSubject3(liveSubject) ? liveSubject : integration.subject);
39095
- if (!isTimebackSubject3(subject)) {
39643
+ const subject = patch.subject ?? (isTimebackSubject(liveSubject) ? liveSubject : integration.subject);
39644
+ if (!isTimebackSubject(subject)) {
39096
39645
  throw new ValidationError(`Invalid subject "${subject}"`);
39097
39646
  }
39098
39647
  setAttributes({
@@ -39102,14 +39651,14 @@ var init_timeback_service = __esm(() => {
39102
39651
  });
39103
39652
  if (subject !== integration.subject) {
39104
39653
  const subjectConflict = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39105
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, subject))
39654
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, subject), isActiveGameTimebackIntegrationStatus())
39106
39655
  });
39107
39656
  if (subjectConflict && subjectConflict.id !== integration.id) {
39108
39657
  throw new ValidationError(`A TimeBack integration already exists for ${subject} Grade ${integration.grade}`);
39109
39658
  }
39110
39659
  }
39111
- const totalXp = "totalXp" in patch ? patch.totalXp ?? null : TimebackService.getTotalXpFromConfig(timebackConfig) ?? integration.totalXp ?? null;
39112
- const masterableUnits = "masterableUnits" in patch ? patch.masterableUnits ?? null : TimebackService.getMasterableUnitsFromConfig(timebackConfig);
39660
+ const totalXp = "totalXp" in patch ? patch.totalXp ?? null : getTotalXpFromTimebackConfig(timebackConfig) ?? integration.totalXp ?? null;
39661
+ const masterableUnits = "masterableUnits" in patch ? patch.masterableUnits ?? null : getMasterableUnitsFromTimebackConfig(timebackConfig);
39113
39662
  setAttributes({
39114
39663
  "app.timeback.total_xp": totalXp,
39115
39664
  "app.timeback.masterable_units": masterableUnits
@@ -39129,7 +39678,7 @@ var init_timeback_service = __esm(() => {
39129
39678
  if (!updated) {
39130
39679
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
39131
39680
  }
39132
- return this.toGameTimebackIntegration(updated);
39681
+ return toGameTimebackIntegration(updated);
39133
39682
  });
39134
39683
  }
39135
39684
  async verifyIntegration(gameId, user) {
@@ -39139,7 +39688,7 @@ var init_timeback_service = __esm(() => {
39139
39688
  await this.deps.validateDeveloperAccess(user, gameId);
39140
39689
  TimebackService.recordIntegrationOperation("verify_integration");
39141
39690
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
39142
- where: eq(gameTimebackIntegrations.gameId, gameId)
39691
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39143
39692
  });
39144
39693
  if (integrations.length === 0) {
39145
39694
  throw new NotFoundError("Timeback integration", gameId);
@@ -39152,7 +39701,7 @@ var init_timeback_service = __esm(() => {
39152
39701
  const errors3 = Object.entries(resources).filter(([_, r]) => !r.found).map(([name3]) => `${name3} not found`);
39153
39702
  const status = allFound ? "success" : "error";
39154
39703
  return {
39155
- integration: this.toGameTimebackIntegration({
39704
+ integration: toGameTimebackIntegration({
39156
39705
  ...integration,
39157
39706
  lastVerifiedAt: now2
39158
39707
  }),
@@ -39161,7 +39710,7 @@ var init_timeback_service = __esm(() => {
39161
39710
  ...errors3.length > 0 && { errors: errors3 }
39162
39711
  };
39163
39712
  }));
39164
- await db2.update(gameTimebackIntegrations).set({ lastVerifiedAt: now2 }).where(eq(gameTimebackIntegrations.gameId, gameId));
39713
+ await db2.update(gameTimebackIntegrations).set({ lastVerifiedAt: now2 }).where(inArray(gameTimebackIntegrations.id, integrations.map((integration) => integration.id)));
39165
39714
  const overallStatus = results.every((r) => r.status === "success") ? "success" : "error";
39166
39715
  const missingResourceCount = results.reduce((count, result) => count + (result.errors?.length ?? 0), 0);
39167
39716
  setAttributes({
@@ -39177,7 +39726,7 @@ var init_timeback_service = __esm(() => {
39177
39726
  const client = this.requireClient();
39178
39727
  await this.deps.validateDeveloperAccess(user, gameId);
39179
39728
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39180
- where: eq(gameTimebackIntegrations.gameId, gameId)
39729
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39181
39730
  });
39182
39731
  if (!integration) {
39183
39732
  throw new NotFoundError("Timeback integration", gameId);
@@ -39204,24 +39753,6 @@ var init_timeback_service = __esm(() => {
39204
39753
  await db2.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.gameId, gameId));
39205
39754
  });
39206
39755
  }
39207
- static getMasterableUnitsFromConfig(config2) {
39208
- const playcademyMetadata = config2.resource.metadata?.playcademy;
39209
- if (!isPlaycademyResourceMetadata2(playcademyMetadata)) {
39210
- return null;
39211
- }
39212
- return playcademyMetadata?.mastery?.masterableUnits ?? null;
39213
- }
39214
- static getTotalXpFromConfig(config2) {
39215
- const courseMetadata = isCourseMetadata(config2.course.metadata) ? config2.course.metadata : undefined;
39216
- if (typeof courseMetadata?.metrics?.totalXp === "number") {
39217
- return courseMetadata.metrics.totalXp;
39218
- }
39219
- const resourceMetadata = config2.resource.metadata;
39220
- if (isRecord2(resourceMetadata) && typeof resourceMetadata.xp === "number") {
39221
- return resourceMetadata.xp;
39222
- }
39223
- return null;
39224
- }
39225
39756
  static patchCourseMetadata(metadata2, totalXp, options) {
39226
39757
  const nextMetadata = isRecord2(metadata2) ? { ...metadata2 } : {};
39227
39758
  const currentMetrics = isRecord2(nextMetadata.metrics) ? nextMetadata.metrics : {};
@@ -39344,31 +39875,29 @@ var init_timeback_service = __esm(() => {
39344
39875
  }
39345
39876
  };
39346
39877
  }
39347
- toGameTimebackIntegration(integration) {
39878
+ toRemovedGameTimebackIntegration(integration, config2) {
39879
+ const grade = config2.course.grades[0] ?? integration.grade;
39880
+ if (!isTimebackGrade(grade)) {
39881
+ throw new ValidationError(`Invalid grade "${grade}"`);
39882
+ }
39348
39883
  return {
39349
- id: integration.id,
39350
- gameId: integration.gameId,
39351
- courseId: integration.courseId,
39352
- grade: integration.grade,
39353
- subject: integration.subject,
39354
- totalXp: integration.totalXp ?? null,
39355
- createdAt: integration.createdAt,
39356
- updatedAt: integration.updatedAt,
39357
- lastVerifiedAt: integration.lastVerifiedAt ?? null
39884
+ ...this.toGameTimebackIntegrationConfig(integration, config2),
39885
+ grade,
39886
+ removedAt: integration.deactivatedAt ?? null
39358
39887
  };
39359
39888
  }
39360
39889
  toGameTimebackIntegrationConfig(integration, config2) {
39361
39890
  const subject = config2.course.subjects[0] ?? integration.subject;
39362
- if (!isTimebackSubject3(subject)) {
39891
+ if (!isTimebackSubject(subject)) {
39363
39892
  throw new ValidationError(`Invalid subject "${subject}"`);
39364
39893
  }
39365
39894
  return {
39366
- integration: this.toGameTimebackIntegration(integration),
39895
+ integration: toGameTimebackIntegration(integration),
39367
39896
  title: config2.course.title,
39368
39897
  courseCode: config2.course.courseCode,
39369
39898
  subject,
39370
- totalXp: TimebackService.getTotalXpFromConfig(config2) ?? integration.totalXp ?? null,
39371
- masterableUnits: TimebackService.getMasterableUnitsFromConfig(config2),
39899
+ totalXp: getTotalXpFromTimebackConfig(config2) ?? integration.totalXp ?? null,
39900
+ masterableUnits: getMasterableUnitsFromTimebackConfig(config2),
39372
39901
  metadata: isCourseMetadata(config2.course.metadata) ? config2.course.metadata : null
39373
39902
  };
39374
39903
  }
@@ -39400,7 +39929,7 @@ var init_timeback_service = __esm(() => {
39400
39929
  });
39401
39930
  await this.deps.validateDeveloperAccess(user, gameId);
39402
39931
  const integration = await db2.query.gameTimebackIntegrations.findFirst({
39403
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject))
39932
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject), isActiveGameTimebackIntegrationStatus())
39404
39933
  });
39405
39934
  if (!integration) {
39406
39935
  throw new NotFoundError(`Timeback integration for game (grade ${activityData.grade}, subject ${activityData.subject})`);
@@ -39461,9 +39990,7 @@ var init_timeback_service = __esm(() => {
39461
39990
  "app.timeback.xp_awarded": result.xpAwarded,
39462
39991
  "app.timeback.mastered_units_requested": masteredUnits,
39463
39992
  "app.timeback.mastered_units_absolute_requested": masteredUnitsAbsolute,
39464
- "app.timeback.mastered_units_applied": result.masteredUnitsApplied,
39465
- "app.timeback.score_status": result.scoreStatus,
39466
- "app.timeback.in_progress": result.inProgress
39993
+ "app.timeback.mastered_units_applied": result.masteredUnitsApplied
39467
39994
  });
39468
39995
  return {
39469
39996
  status: "ok",
@@ -39471,8 +39998,6 @@ var init_timeback_service = __esm(() => {
39471
39998
  xpAwarded: result.xpAwarded,
39472
39999
  masteredUnits: result.masteredUnitsApplied,
39473
40000
  pctCompleteApp: result.pctCompleteApp,
39474
- scoreStatus: result.scoreStatus,
39475
- inProgress: result.inProgress,
39476
40001
  ...result.warnings ? { warnings: result.warnings } : {}
39477
40002
  };
39478
40003
  }
@@ -39485,7 +40010,7 @@ var init_timeback_service = __esm(() => {
39485
40010
  const client = this.requireClient();
39486
40011
  const db2 = this.deps.db;
39487
40012
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
39488
- where: subject ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.subject, subject)) : eq(gameTimebackIntegrations.gameId, gameId)
40013
+ where: subject ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.subject, subject), isActiveGameTimebackIntegrationStatus()) : and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39489
40014
  });
39490
40015
  if (integrations.length === 0) {
39491
40016
  throw new NotFoundError(subject ? `Timeback integrations for game (subject ${subject})` : "Timeback integrations for game");
@@ -39667,7 +40192,7 @@ var init_timeback_service = __esm(() => {
39667
40192
  }
39668
40193
  const pendingHeartbeat = (async () => {
39669
40194
  const integration = await db2.query.gameTimebackIntegrations.findFirst({
39670
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject))
40195
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject), isActiveGameTimebackIntegrationStatus())
39671
40196
  });
39672
40197
  if (!integration) {
39673
40198
  throw new NotFoundError(`Timeback integration for game (grade ${activityData.grade}, subject ${activityData.subject})`);
@@ -39715,7 +40240,10 @@ var init_timeback_service = __esm(() => {
39715
40240
  let courseIds = [];
39716
40241
  if (options?.gameId) {
39717
40242
  await this.deps.validateDeveloperAccess(user, options.gameId);
39718
- const conditions2 = [eq(gameTimebackIntegrations.gameId, options.gameId)];
40243
+ const conditions2 = [
40244
+ eq(gameTimebackIntegrations.gameId, options.gameId),
40245
+ isActiveGameTimebackIntegrationStatus()
40246
+ ];
39719
40247
  if (options.grade !== undefined && options.subject) {
39720
40248
  conditions2.push(eq(gameTimebackIntegrations.grade, options.grade));
39721
40249
  conditions2.push(eq(gameTimebackIntegrations.subject, options.subject));
@@ -39742,7 +40270,10 @@ var init_timeback_service = __esm(() => {
39742
40270
  const client = this.requireClient();
39743
40271
  const db2 = this.deps.db;
39744
40272
  await this.deps.validateDeveloperAccess(user, options.gameId);
39745
- const conditions2 = [eq(gameTimebackIntegrations.gameId, options.gameId)];
40273
+ const conditions2 = [
40274
+ eq(gameTimebackIntegrations.gameId, options.gameId),
40275
+ isActiveGameTimebackIntegrationStatus()
40276
+ ];
39746
40277
  if (options.grade !== undefined && options.subject) {
39747
40278
  conditions2.push(eq(gameTimebackIntegrations.grade, options.grade));
39748
40279
  conditions2.push(eq(gameTimebackIntegrations.subject, options.subject));
@@ -39769,7 +40300,7 @@ var init_timeback_service = __esm(() => {
39769
40300
  const db2 = this.deps.db;
39770
40301
  await this.deps.validateDeveloperAccess(user, options.gameId);
39771
40302
  const integration = await db2.query.gameTimebackIntegrations.findFirst({
39772
- where: and(eq(gameTimebackIntegrations.gameId, options.gameId), eq(gameTimebackIntegrations.subject, options.subject))
40303
+ where: and(eq(gameTimebackIntegrations.gameId, options.gameId), eq(gameTimebackIntegrations.subject, options.subject), isActiveGameTimebackIntegrationStatus())
39773
40304
  });
39774
40305
  if (!integration) {
39775
40306
  throw new ValidationError(`Subject "${options.subject}" is not configured for game ${options.gameId}`);
@@ -40656,7 +41187,7 @@ class UserService {
40656
41187
  return [];
40657
41188
  }
40658
41189
  const integrations = await this.deps.db.query.gameTimebackIntegrations.findMany({
40659
- where: inArray(gameTimebackIntegrations.courseId, courseIds)
41190
+ where: and(inArray(gameTimebackIntegrations.courseId, courseIds), isActiveGameTimebackIntegrationStatus())
40660
41191
  });
40661
41192
  return mapEnrollmentsToUserEnrollments(enrollments, integrations);
40662
41193
  } catch (error) {
@@ -40678,6 +41209,7 @@ class UserService {
40678
41209
  var init_user_service = __esm(() => {
40679
41210
  init_drizzle_orm();
40680
41211
  init_src();
41212
+ init_helpers_index();
40681
41213
  init_tables_index();
40682
41214
  init_spans();
40683
41215
  init_errors();
@@ -56875,7 +57407,7 @@ function extractTablesRelationalConfig2(schema5, configHelpers) {
56875
57407
  return { tables: tablesConfig, tableNamesMap };
56876
57408
  }
56877
57409
  function relations3(table62, relations22) {
56878
- return new Relations2(table62, (helpers) => Object.fromEntries(Object.entries(relations22(helpers)).map(([key, value]) => [
57410
+ return new Relations2(table62, (helpers3) => Object.fromEntries(Object.entries(relations22(helpers3)).map(([key, value]) => [
56879
57411
  key,
56880
57412
  value.withFieldName(key)
56881
57413
  ])));
@@ -58049,7 +58581,7 @@ var __create2, __defProp3, __getOwnPropDesc, __getOwnPropNames2, __getProtoOf2,
58049
58581
  __defProp3(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
58050
58582
  }
58051
58583
  return to;
58052
- }, __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp3(target, "default", { value: mod, enumerable: true }) : target, mod)), __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value), ANSI_BACKGROUND_OFFSET, wrapAnsi16, wrapAnsi256, wrapAnsi16m, styles2, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default, init_ansi_styles, env, flagForceColor, supportsColor, supports_color_default, init_supports_color, init_utilities, stdoutColor, stderrColor, GENERATOR, STYLER, IS_EMPTY, levelMapping, styles22, applyOptions, chalkFactory, getModelAnsi, usedModels, proto, createStyler, createBuilder, applyStyle, chalk, chalkStderr, source_default, init_source, require_old, require_fs, require_path, require_balanced_match, require_brace_expansion, require_minimatch, require_inherits_browser2, require_inherits2, require_common3, require_sync, require_wrappy, require_once, require_inflight, require_glob, require_readline, require_src3, require_utils4, require_lodash, require_hanji, originUUID, snapshotVersion, mapValues, mapKeys, mapEntries, customMapEntries, init_global2, util3, objectUtil2, ZodParsedType2, getParsedType2, init_util2, ZodIssueCode2, ZodError3, init_ZodError2, errorMap2, en_default2, init_en2, overrideErrorMap2, init_errors5, makeIssue2, ParseStatus2, INVALID2, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, init_parseUtil2, init_typeAliases2, errorUtil2, init_errorUtil2, ParseInputLazyPath2, handleResult2, ZodType2, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString2, ZodNumber2, ZodBigInt2, ZodBoolean2, ZodDate2, ZodSymbol2, ZodUndefined2, ZodNull2, ZodAny2, ZodUnknown2, ZodNever2, ZodVoid2, ZodArray2, ZodObject2, ZodUnion2, getDiscriminator2, ZodDiscriminatedUnion2, ZodIntersection2, ZodTuple2, ZodRecord2, ZodMap2, ZodSet2, ZodFunction2, ZodLazy2, ZodLiteral2, ZodEnum2, ZodNativeEnum2, ZodPromise2, ZodEffects2, ZodOptional2, ZodNullable2, ZodDefault2, ZodCatch2, ZodNaN2, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly2, late2, ZodFirstPartyTypeKind2, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, coerce2, init_types5, init_external2, init_v32, init_esm2, enumSchema, enumSchemaV1, indexColumn, index2, fk, sequenceSchema, roleSchema, sequenceSquashed, column2, checkConstraint, columnSquashed, compositePK, uniqueConstraint, policy, policySquashed, viewWithOption, matViewWithOption, mergedViewWithOption, view2, table8, schemaHash, kitInternals, gelSchemaExternal, gelSchemaInternal, tableSquashed, gelSchemaSquashed, gelSchema, dryGel, init_gelSchema, index22, fk2, column22, tableV3, compositePK2, uniqueConstraint2, checkConstraint2, tableV4, table22, viewMeta, view22, kitInternals2, dialect2, schemaHash2, schemaInternalV3, schemaInternalV4, schemaInternalV5, schemaInternal, schemaV3, schemaV4, schemaV5, schema2, tableSquashedV4, tableSquashed2, viewSquashed, schemaSquashed, schemaSquashedV4, MySqlSquasher, squashMysqlScheme, mysqlSchema, mysqlSchemaV5, mysqlSchemaSquashed, backwardCompatibleMysqlSchema, dryMySql, init_mysqlSchema, indexV2, columnV2, tableV2, enumSchemaV12, enumSchema2, pgSchemaV2, references, columnV1, tableV1, pgSchemaV1, indexColumn2, index3, indexV4, indexV5, indexV6, fk3, sequenceSchema2, roleSchema2, sequenceSquashed2, columnV7, column3, checkConstraint3, columnSquashed2, tableV32, compositePK3, uniqueConstraint3, policy2, policySquashed2, viewWithOption2, matViewWithOption2, mergedViewWithOption2, view3, tableV42, tableV5, tableV6, tableV7, table32, schemaHash3, kitInternals3, pgSchemaInternalV3, pgSchemaInternalV4, pgSchemaInternalV5, pgSchemaInternalV6, pgSchemaExternal, pgSchemaInternalV7, pgSchemaInternal, tableSquashed3, tableSquashedV42, pgSchemaSquashedV4, pgSchemaSquashedV6, pgSchemaSquashed, pgSchemaV3, pgSchemaV4, pgSchemaV5, pgSchemaV6, pgSchemaV7, pgSchema, backwardCompatiblePgSchema, PgSquasher, squashPgScheme, dryPg, init_pgSchema, index4, column4, compositePK4, uniqueConstraint4, table42, viewMeta2, kitInternals4, dialect22, schemaHash4, schemaInternal2, schema22, tableSquashed4, schemaSquashed2, SingleStoreSquasher, squashSingleStoreScheme, singlestoreSchema, singlestoreSchemaSquashed, backwardCompatibleSingleStoreSchema, drySingleStore, init_singlestoreSchema, index5, fk4, compositePK5, column5, tableV33, uniqueConstraint5, checkConstraint4, table52, view4, dialect3, schemaHash5, schemaInternalV32, schemaInternalV42, schemaInternalV52, kitInternals5, latestVersion, schemaInternal3, schemaV32, schemaV42, schemaV52, schema3, tableSquashed5, schemaSquashed3, SQLiteSquasher, squashSqliteScheme, drySQLite, sqliteSchemaV5, sqliteSchema, SQLiteSchemaSquashed, backwardCompatibleSqliteSchema, init_sqliteSchema, copy, prepareMigrationMeta, schemaRenameKey, tableRenameKey, columnRenameKey, init_utils7, import_hanji, warning, error, isRenamePromptItem, ResolveColumnSelect, tableKey, ResolveSelectNamed, ResolveSelect, ResolveSchemasSelect, Spinner2, ProgressView, init_views, glob, init_serializer, fillPgSnapshot, init_migrationPreparator, require_heap, require_heap2, require_difflib, require_difflib2, require_util2, require_styles, require_has_flag2, require_supports_colors, require_trap, require_zalgo, require_america, require_zebra, require_rainbow, require_random, require_colors, require_safe, require_colorize, require_lib4, import_json_diff, mapArraysDiff, findAlternationsInTable, alternationsInColumn, init_jsonDiffer, parseType, Convertor, PgCreateRoleConvertor, PgDropRoleConvertor, PgRenameRoleConvertor, PgAlterRoleConvertor, PgCreatePolicyConvertor, PgDropPolicyConvertor, PgRenamePolicyConvertor, PgAlterPolicyConvertor, PgCreateIndPolicyConvertor, PgDropIndPolicyConvertor, PgRenameIndPolicyConvertor, PgAlterIndPolicyConvertor, PgEnableRlsConvertor, PgDisableRlsConvertor, PgCreateTableConvertor, MySqlCreateTableConvertor, SingleStoreCreateTableConvertor, SQLiteCreateTableConvertor, PgCreateViewConvertor, MySqlCreateViewConvertor, SqliteCreateViewConvertor, PgDropViewConvertor, MySqlDropViewConvertor, SqliteDropViewConvertor, MySqlAlterViewConvertor, PgRenameViewConvertor, MySqlRenameViewConvertor, PgAlterViewSchemaConvertor, PgAlterViewAddWithOptionConvertor, PgAlterViewDropWithOptionConvertor, PgAlterViewAlterTablespaceConvertor, PgAlterViewAlterUsingConvertor, PgAlterTableAlterColumnSetGenerated, PgAlterTableAlterColumnDropGenerated, PgAlterTableAlterColumnAlterGenerated, PgAlterTableAddUniqueConstraintConvertor, PgAlterTableDropUniqueConstraintConvertor, PgAlterTableAddCheckConstraintConvertor, PgAlterTableDeleteCheckConstraintConvertor, MySQLAlterTableAddUniqueConstraintConvertor, MySQLAlterTableDropUniqueConstraintConvertor, MySqlAlterTableAddCheckConstraintConvertor, SingleStoreAlterTableAddUniqueConstraintConvertor, SingleStoreAlterTableDropUniqueConstraintConvertor, MySqlAlterTableDeleteCheckConstraintConvertor, CreatePgSequenceConvertor, DropPgSequenceConvertor, RenamePgSequenceConvertor, MovePgSequenceConvertor, AlterPgSequenceConvertor, CreateTypeEnumConvertor, DropTypeEnumConvertor, AlterTypeAddValueConvertor, AlterTypeSetSchemaConvertor, AlterRenameTypeConvertor, AlterTypeDropValueConvertor, PgDropTableConvertor, MySQLDropTableConvertor, SingleStoreDropTableConvertor, SQLiteDropTableConvertor, PgRenameTableConvertor, SqliteRenameTableConvertor, MySqlRenameTableConvertor, SingleStoreRenameTableConvertor, PgAlterTableRenameColumnConvertor, MySqlAlterTableRenameColumnConvertor, SingleStoreAlterTableRenameColumnConvertor, SQLiteAlterTableRenameColumnConvertor, PgAlterTableDropColumnConvertor, MySqlAlterTableDropColumnConvertor, SingleStoreAlterTableDropColumnConvertor, SQLiteAlterTableDropColumnConvertor, PgAlterTableAddColumnConvertor, MySqlAlterTableAddColumnConvertor, SingleStoreAlterTableAddColumnConvertor, SQLiteAlterTableAddColumnConvertor, PgAlterTableAlterColumnSetTypeConvertor, PgAlterTableAlterColumnSetDefaultConvertor, PgAlterTableAlterColumnDropDefaultConvertor, PgAlterTableAlterColumnDropGeneratedConvertor, PgAlterTableAlterColumnSetExpressionConvertor, PgAlterTableAlterColumnAlterrGeneratedConvertor, SqliteAlterTableAlterColumnDropGeneratedConvertor, SqliteAlterTableAlterColumnSetExpressionConvertor, SqliteAlterTableAlterColumnAlterGeneratedConvertor, MySqlAlterTableAlterColumnAlterrGeneratedConvertor, MySqlAlterTableAddPk, MySqlAlterTableDropPk, LibSQLModifyColumn, MySqlModifyColumn, SingleStoreAlterTableAlterColumnAlterrGeneratedConvertor, SingleStoreAlterTableAddPk, SingleStoreAlterTableDropPk, SingleStoreModifyColumn, PgAlterTableCreateCompositePrimaryKeyConvertor, PgAlterTableDeleteCompositePrimaryKeyConvertor, PgAlterTableAlterCompositePrimaryKeyConvertor, MySqlAlterTableCreateCompositePrimaryKeyConvertor, MySqlAlterTableDeleteCompositePrimaryKeyConvertor, MySqlAlterTableAlterCompositePrimaryKeyConvertor, PgAlterTableAlterColumnSetPrimaryKeyConvertor, PgAlterTableAlterColumnDropPrimaryKeyConvertor, PgAlterTableAlterColumnSetNotNullConvertor, PgAlterTableAlterColumnDropNotNullConvertor, PgCreateForeignKeyConvertor, LibSQLCreateForeignKeyConvertor, MySqlCreateForeignKeyConvertor, PgAlterForeignKeyConvertor, PgDeleteForeignKeyConvertor, MySqlDeleteForeignKeyConvertor, CreatePgIndexConvertor, CreateMySqlIndexConvertor, CreateSingleStoreIndexConvertor, CreateSqliteIndexConvertor, PgDropIndexConvertor, PgCreateSchemaConvertor, PgRenameSchemaConvertor, PgDropSchemaConvertor, PgAlterTableSetSchemaConvertor, PgAlterTableSetNewSchemaConvertor, PgAlterTableRemoveFromSchemaConvertor, SqliteDropIndexConvertor, MySqlDropIndexConvertor, SingleStoreDropIndexConvertor, SQLiteRecreateTableConvertor, LibSQLRecreateTableConvertor, SingleStoreRecreateTableConvertor, convertors, init_sqlgenerator, _moveDataStatements, getOldTableName, getNewTableName, logSuggestionsAndReturn, init_sqlitePushUtils, preparePgCreateTableJson, prepareMySqlCreateTableJson, prepareSingleStoreCreateTableJson, prepareSQLiteCreateTable, prepareDropTableJson, prepareRenameTableJson, prepareCreateEnumJson, prepareAddValuesToEnumJson, prepareDropEnumValues, prepareDropEnumJson, prepareMoveEnumJson, prepareRenameEnumJson, prepareCreateSequenceJson, prepareAlterSequenceJson, prepareDropSequenceJson, prepareMoveSequenceJson, prepareRenameSequenceJson, prepareCreateRoleJson, prepareAlterRoleJson, prepareDropRoleJson, prepareRenameRoleJson, prepareCreateSchemasJson, prepareRenameSchemasJson, prepareDeleteSchemasJson, prepareRenameColumns, _prepareDropColumns, _prepareAddColumns, _prepareSqliteAddColumns, prepareAlterColumnsMysql, preparePgAlterColumns, prepareSqliteAlterColumns, prepareRenamePolicyJsons, prepareRenameIndPolicyJsons, prepareCreatePolicyJsons, prepareCreateIndPolicyJsons, prepareDropPolicyJsons, prepareDropIndPolicyJsons, prepareAlterPolicyJson, prepareAlterIndPolicyJson, preparePgCreateIndexesJson, prepareCreateIndexesJson, prepareCreateReferencesJson, prepareLibSQLCreateReferencesJson, prepareDropReferencesJson, prepareLibSQLDropReferencesJson, prepareAlterReferencesJson, prepareDropIndexesJson, prepareAddCompositePrimaryKeySqlite, prepareDeleteCompositePrimaryKeySqlite, prepareAlterCompositePrimaryKeySqlite, prepareAddCompositePrimaryKeyPg, prepareDeleteCompositePrimaryKeyPg, prepareAlterCompositePrimaryKeyPg, prepareAddUniqueConstraintPg, prepareDeleteUniqueConstraintPg, prepareAddCheckConstraint, prepareDeleteCheckConstraint, prepareAddCompositePrimaryKeyMySql, prepareDeleteCompositePrimaryKeyMySql, prepareAlterCompositePrimaryKeyMySql, preparePgCreateViewJson, prepareMySqlCreateViewJson, prepareSqliteCreateViewJson, prepareDropViewJson, prepareRenameViewJson, preparePgAlterViewAlterSchemaJson, preparePgAlterViewAddWithOptionJson, preparePgAlterViewDropWithOptionJson, preparePgAlterViewAlterTablespaceJson, preparePgAlterViewAlterUsingJson, prepareMySqlAlterView, init_jsonStatements, prepareLibSQLRecreateTable, prepareSQLiteRecreateTable, libSQLCombineStatements, sqliteCombineStatements, prepareSingleStoreRecreateTable, singleStoreCombineStatements, init_statementCombiner, snapshotsDiffer_exports, makeChanged, makeSelfOrChanged, makePatched, makeSelfOrPatched, columnSchema, alteredColumnSchema, enumSchema3, changedEnumSchema, tableScheme, alteredTableScheme, alteredViewCommon, alteredPgViewSchema, alteredMySqlViewSchema, diffResultScheme, diffResultSchemeMysql, diffResultSchemeSingleStore, diffResultSchemeSQLite, schemaChangeFor, nameChangeFor, nameSchemaChangeFor, columnChangeFor, applyPgSnapshotsDiff, applyMysqlSnapshotsDiff, applySingleStoreSnapshotsDiff, applySqliteSnapshotsDiff, applyLibSQLSnapshotsDiff, init_snapshotsDiffer, init_words, dialects, dialect4, commonSquashedSchema, commonSchema, init_schemaValidator, sqliteDriversLiterals, postgresqlDriversLiterals, prefixes, prefix, casingTypes, casingType, sqliteDriver, postgresDriver, driver2, configMigrations, configCommonSchema, casing, introspectParams, configIntrospectCliSchema, configGenerateSchema, configPushSchema, init_common2, withStyle, init_outputs, import_hanji2, schemasResolver, tablesResolver, viewsResolver, mySqlViewsResolver, sqliteViewsResolver, sequencesResolver, roleResolver, policyResolver, indPolicyResolver, enumsResolver, columnsResolver, promptColumnsConflicts, promptNamedConflict, promptNamedWithSchemasConflict, promptSchemasConflict, BREAKPOINT, init_migrate, posixClasses, braceEscape, regexpEscape, rangesToString, parseClass, init_brace_expressions, escape, init_escape, unescape, init_unescape, import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path, sep, GLOBSTAR, plTypes, qmark, star, twoStarDot, twoStarNoDot, charSet, reSpecials, addPatternStartSet, filter, ext, defaults, braceExpand, MAX_PATTERN_LENGTH, assertValidPattern, makeRe, match2, globUnescape, globMagic, regExpEscape, Minimatch, init_mjs, entityKind2, hasOwnEntityKind2, init_entity2, _a, Column2, init_column2, _a2, ColumnBuilder2, init_column_builder2, TableName2, init_table_utils2, _a3, ForeignKeyBuilder2, _a4, ForeignKey2, init_foreign_keys2, init_tracing_utils2, _a5, UniqueConstraintBuilder, _a6, UniqueOnConstraintBuilder, _a7, UniqueConstraint, init_unique_constraint2, init_array2, _a8, _b, PgColumnBuilder2, _a9, _b2, PgColumn2, _a10, _b3, ExtraConfigColumn2, _a11, IndexedColumn2, _a12, _b4, PgArrayBuilder2, _a13, _b5, _PgArray, PgArray2, init_common22, _a14, _b6, PgEnumObjectColumnBuilder2, _a15, _b7, PgEnumObjectColumn2, isPgEnumSym2, _a16, _b8, PgEnumColumnBuilder2, _a17, _b9, PgEnumColumn2, init_enum2, _a18, Subquery2, _a19, _b10, WithSubquery2, init_subquery2, version2, init_version2, otel2, rawTracer2, tracer2, init_tracing2, ViewBaseConfig2, init_view_common3, Schema2, Columns2, ExtraConfigColumns2, OriginalName2, BaseName2, IsAlias2, ExtraConfigBuilder2, IsDrizzleTable2, _a20, _b11, _c, _d, _e3, _f, _g, _h, _i, _j, Table2, init_table8, _a21, FakePrimitiveParam, _a22, StringChunk2, _a23, _SQL, SQL2, _a24, Name2, noopDecoder2, noopEncoder2, noopMapper2, _a25, Param2, _a26, Placeholder2, IsDrizzleView2, _a27, _b12, _c2, View3, init_sql3, _a28, ColumnAliasProxyHandler2, _a29, TableAliasProxyHandler2, _a30, RelationTableAliasProxyHandler, init_alias3, _a31, _b13, DrizzleError2, DrizzleQueryError, _a32, _b14, TransactionRollbackError2, init_errors22, _a33, ConsoleLogWriter2, _a34, DefaultLogger2, _a35, NoopLogger2, init_logger3, init_operations, _a36, _b15, QueryPromise2, init_query_promise2, textDecoder, init_utils22, _a37, _b16, PgIntColumnBaseBuilder2, init_int_common2, _a38, _b17, PgBigInt53Builder2, _a39, _b18, PgBigInt532, _a40, _b19, PgBigInt64Builder2, _a41, _b20, PgBigInt642, init_bigint2, _a42, _b21, PgBigSerial53Builder2, _a43, _b22, PgBigSerial532, _a44, _b23, PgBigSerial64Builder2, _a45, _b24, PgBigSerial642, init_bigserial2, _a46, _b25, PgBooleanBuilder2, _a47, _b26, PgBoolean2, init_boolean2, _a48, _b27, PgCharBuilder2, _a49, _b28, PgChar2, init_char2, _a50, _b29, PgCidrBuilder2, _a51, _b30, PgCidr2, init_cidr2, _a52, _b31, PgCustomColumnBuilder2, _a53, _b32, PgCustomColumn2, init_custom2, _a54, _b33, PgDateColumnBaseBuilder2, init_date_common2, _a55, _b34, PgDateBuilder2, _a56, _b35, PgDate2, _a57, _b36, PgDateStringBuilder2, _a58, _b37, PgDateString2, init_date2, _a59, _b38, PgDoublePrecisionBuilder2, _a60, _b39, PgDoublePrecision2, init_double_precision2, _a61, _b40, PgInetBuilder2, _a62, _b41, PgInet2, init_inet2, _a63, _b42, PgIntegerBuilder2, _a64, _b43, PgInteger2, init_integer2, _a65, _b44, PgIntervalBuilder2, _a66, _b45, PgInterval2, init_interval2, _a67, _b46, PgJsonBuilder2, _a68, _b47, PgJson2, init_json2, _a69, _b48, PgJsonbBuilder2, _a70, _b49, PgJsonb2, init_jsonb2, _a71, _b50, PgLineBuilder2, _a72, _b51, PgLineTuple2, _a73, _b52, PgLineABCBuilder2, _a74, _b53, PgLineABC2, init_line2, _a75, _b54, PgMacaddrBuilder2, _a76, _b55, PgMacaddr2, init_macaddr2, _a77, _b56, PgMacaddr8Builder2, _a78, _b57, PgMacaddr82, init_macaddr82, _a79, _b58, PgNumericBuilder2, _a80, _b59, PgNumeric2, _a81, _b60, PgNumericNumberBuilder2, _a82, _b61, PgNumericNumber2, _a83, _b62, PgNumericBigIntBuilder2, _a84, _b63, PgNumericBigInt2, init_numeric2, _a85, _b64, PgPointTupleBuilder2, _a86, _b65, PgPointTuple2, _a87, _b66, PgPointObjectBuilder2, _a88, _b67, PgPointObject2, init_point2, init_utils32, _a89, _b68, PgGeometryBuilder2, _a90, _b69, PgGeometry2, _a91, _b70, PgGeometryObjectBuilder2, _a92, _b71, PgGeometryObject2, init_geometry2, _a93, _b72, PgRealBuilder2, _a94, _b73, PgReal2, init_real2, _a95, _b74, PgSerialBuilder2, _a96, _b75, PgSerial2, init_serial2, _a97, _b76, PgSmallIntBuilder2, _a98, _b77, PgSmallInt2, init_smallint2, _a99, _b78, PgSmallSerialBuilder2, _a100, _b79, PgSmallSerial2, init_smallserial2, _a101, _b80, PgTextBuilder2, _a102, _b81, PgText2, init_text2, _a103, _b82, PgTimeBuilder2, _a104, _b83, PgTime2, init_time2, _a105, _b84, PgTimestampBuilder2, _a106, _b85, PgTimestamp2, _a107, _b86, PgTimestampStringBuilder2, _a108, _b87, PgTimestampString2, init_timestamp2, _a109, _b88, PgUUIDBuilder2, _a110, _b89, PgUUID2, init_uuid3, _a111, _b90, PgVarcharBuilder2, _a112, _b91, PgVarchar2, init_varchar2, _a113, _b92, PgBinaryVectorBuilder2, _a114, _b93, PgBinaryVector2, init_bit2, _a115, _b94, PgHalfVectorBuilder2, _a116, _b95, PgHalfVector2, init_halfvec2, _a117, _b96, PgSparseVectorBuilder2, _a118, _b97, PgSparseVector2, init_sparsevec2, _a119, _b98, PgVectorBuilder2, _a120, _b99, PgVector2, init_vector3, init_all2, InlineForeignKeys2, EnableRLS2, _a121, _b100, _c3, _d2, _e22, _f2, PgTable2, pgTable2, init_table22, _a122, PrimaryKeyBuilder2, _a123, PrimaryKey2, init_primary_keys2, eq2, ne4, gt3, gte2, lt4, lte2, init_conditions2, init_select3, init_expressions2, _a124, Relation2, _a125, Relations2, _a126, _b101, _One, One2, _a127, _b102, _Many, Many2, init_relations2, init_aggregate2, init_vector22, init_functions2, init_sql22, dist_exports, init_dist6, init_alias22, _a128, CheckBuilder, _a129, Check, init_checks2, init_columns2, _a130, _SelectionProxyHandler, SelectionProxyHandler2, init_selection_proxy2, _a131, IndexBuilderOn2, _a132, IndexBuilder2, _a133, Index2, init_indexes2, _a134, PgPolicy, init_policies2, PgViewConfig2, init_view_common22, _a135, CasingCache2, init_casing2, _a136, _b103, PgViewBase2, init_view_base2, _a137, PgDialect2, init_dialect2, _a138, TypedQueryBuilder2, init_query_builder3, _a139, PgSelectBuilder2, _a140, _b104, PgSelectQueryBuilderBase2, _a141, _b105, PgSelectBase2, getPgSetOperators2, union2, unionAll2, intersect2, intersectAll2, except2, exceptAll2, init_select22, _a142, QueryBuilder2, init_query_builder22, _a143, DefaultViewBuilderCore, _a144, _b106, ViewBuilder, _a145, _b107, ManualViewBuilder, _a146, MaterializedViewBuilderCore, _a147, _b108, MaterializedViewBuilder, _a148, _b109, ManualMaterializedViewBuilder, _a149, _b110, _c4, PgView2, PgMaterializedViewConfig2, _a150, _b111, _c5, PgMaterializedView, init_view2, init_utils42, _a151, _b112, PgDeleteBase2, init_delete2, _a152, PgInsertBuilder2, _a153, _b113, PgInsertBase2, init_insert2, _a154, _b114, PgRefreshMaterializedView2, init_refresh_materialized_view2, init_select_types, _a155, PgUpdateBuilder2, _a156, _b115, PgUpdateBase2, init_update2, init_query_builders2, _a157, _b116, _c6, _PgCountBuilder, PgCountBuilder2, init_count2, _a158, RelationalQueryBuilder2, _a159, _b117, PgRelationalQuery2, init_query2, _a160, _b118, PgRaw2, init_raw2, _a161, PgDatabase2, init_db2, _a162, PgRole, init_roles2, _a163, PgSequence, init_sequence2, _a164, PgSchema5, init_schema3, _a165, Cache, _a166, _b119, NoopCache, init_cache, _a167, PgPreparedQuery2, _a168, PgSession2, _a169, _b120, PgTransaction2, init_session3, init_subquery22, init_utils52, init_pg_core2, vectorOps, init_vector32, sqlToStr, init_utils62, indexName, generatePgSnapshot, trimChar, fromDatabase, defaultForColumn, getColumnsInfoQuery, init_pgSerializer, import_hanji4, Select, init_selector_ui, init_alias32, _a170, CheckBuilder2, _a171, Check2, init_checks22, _a172, ForeignKeyBuilder22, _a173, ForeignKey22, init_foreign_keys22, _a174, UniqueConstraintBuilder2, _a175, UniqueOnConstraintBuilder2, _a176, UniqueConstraint2, init_unique_constraint22, _a177, _b121, SQLiteColumnBuilder, _a178, _b122, SQLiteColumn, init_common3, _a179, _b123, SQLiteBigIntBuilder, _a180, _b124, SQLiteBigInt, _a181, _b125, SQLiteBlobJsonBuilder, _a182, _b126, SQLiteBlobJson, _a183, _b127, SQLiteBlobBufferBuilder, _a184, _b128, SQLiteBlobBuffer, init_blob, _a185, _b129, SQLiteCustomColumnBuilder, _a186, _b130, SQLiteCustomColumn, init_custom22, _a187, _b131, SQLiteBaseIntegerBuilder, _a188, _b132, SQLiteBaseInteger, _a189, _b133, SQLiteIntegerBuilder, _a190, _b134, SQLiteInteger, _a191, _b135, SQLiteTimestampBuilder, _a192, _b136, SQLiteTimestamp, _a193, _b137, SQLiteBooleanBuilder, _a194, _b138, SQLiteBoolean, init_integer22, _a195, _b139, SQLiteNumericBuilder, _a196, _b140, SQLiteNumeric, _a197, _b141, SQLiteNumericNumberBuilder, _a198, _b142, SQLiteNumericNumber, _a199, _b143, SQLiteNumericBigIntBuilder, _a200, _b144, SQLiteNumericBigInt, init_numeric22, _a201, _b145, SQLiteRealBuilder, _a202, _b146, SQLiteReal, init_real22, _a203, _b147, SQLiteTextBuilder, _a204, _b148, SQLiteText, _a205, _b149, SQLiteTextJsonBuilder, _a206, _b150, SQLiteTextJson, init_text22, init_columns22, init_all22, InlineForeignKeys22, _a207, _b151, _c7, _d3, _e32, SQLiteTable, sqliteTable, init_table32, _a208, IndexBuilderOn22, _a209, IndexBuilder22, _a210, Index4, init_indexes22, _a211, PrimaryKeyBuilder22, _a212, PrimaryKey22, init_primary_keys22, init_utils72, _a213, _b152, SQLiteDeleteBase, init_delete22, _a214, _b153, SQLiteViewBase, init_view_base22, _a215, SQLiteDialect, _a216, _b154, SQLiteSyncDialect, _a217, _b155, SQLiteAsyncDialect, init_dialect22, _a218, SQLiteSelectBuilder, _a219, _b156, SQLiteSelectQueryBuilderBase, _a220, _b157, SQLiteSelectBase, getSQLiteSetOperators, union3, unionAll22, intersect22, except22, init_select32, _a221, QueryBuilder22, init_query_builder32, _a222, SQLiteInsertBuilder, _a223, _b158, SQLiteInsertBase, init_insert22, init_select_types2, _a224, SQLiteUpdateBuilder, _a225, _b159, SQLiteUpdateBase, init_update22, init_query_builders22, _a226, _b160, _c8, _SQLiteCountBuilder, SQLiteCountBuilder, init_count22, _a227, RelationalQueryBuilder22, _a228, _b161, SQLiteRelationalQuery, _a229, _b162, SQLiteSyncRelationalQuery, init_query22, _a230, _b163, SQLiteRaw, init_raw22, _a231, BaseSQLiteDatabase, init_db22, _a232, _b164, ExecuteResultSync, _a233, SQLitePreparedQuery, _a234, SQLiteSession, _a235, _b165, SQLiteTransaction, init_session22, init_subquery3, _a236, ViewBuilderCore, _a237, _b166, ViewBuilder2, _a238, _b167, ManualViewBuilder2, _a239, _b168, SQLiteView2, init_view22, init_sqlite_core, generateSqliteSnapshot, fromDatabase2, init_sqliteSerializer, getTablesFilterByExtensions, init_getTablesFilterByExtensions, init_alias4, _a240, CheckBuilder3, _a241, Check3, init_checks3, _a242, ForeignKeyBuilder3, _a243, ForeignKey3, init_foreign_keys3, _a244, UniqueConstraintBuilder3, _a245, UniqueOnConstraintBuilder3, _a246, UniqueConstraint3, init_unique_constraint3, _a247, _b169, MySqlColumnBuilder, _a248, _b170, MySqlColumn, _a249, _b171, MySqlColumnBuilderWithAutoIncrement, _a250, _b172, MySqlColumnWithAutoIncrement, init_common4, _a251, _b173, MySqlBigInt53Builder, _a252, _b174, MySqlBigInt53, _a253, _b175, MySqlBigInt64Builder, _a254, _b176, MySqlBigInt64, init_bigint22, _a255, _b177, MySqlBinaryBuilder, _a256, _b178, MySqlBinary, init_binary, _a257, _b179, MySqlBooleanBuilder, _a258, _b180, MySqlBoolean, init_boolean22, _a259, _b181, MySqlCharBuilder, _a260, _b182, MySqlChar, init_char22, _a261, _b183, MySqlCustomColumnBuilder, _a262, _b184, MySqlCustomColumn, init_custom3, _a263, _b185, MySqlDateBuilder, _a264, _b186, MySqlDate, _a265, _b187, MySqlDateStringBuilder, _a266, _b188, MySqlDateString, init_date22, _a267, _b189, MySqlDateTimeBuilder, _a268, _b190, MySqlDateTime, _a269, _b191, MySqlDateTimeStringBuilder, _a270, _b192, MySqlDateTimeString, init_datetime, _a271, _b193, MySqlDecimalBuilder, _a272, _b194, MySqlDecimal, _a273, _b195, MySqlDecimalNumberBuilder, _a274, _b196, MySqlDecimalNumber, _a275, _b197, MySqlDecimalBigIntBuilder, _a276, _b198, MySqlDecimalBigInt, init_decimal, _a277, _b199, MySqlDoubleBuilder, _a278, _b200, MySqlDouble, init_double, _a279, _b201, MySqlEnumColumnBuilder, _a280, _b202, MySqlEnumColumn, _a281, _b203, MySqlEnumObjectColumnBuilder, _a282, _b204, MySqlEnumObjectColumn, init_enum22, _a283, _b205, MySqlFloatBuilder, _a284, _b206, MySqlFloat, init_float, _a285, _b207, MySqlIntBuilder, _a286, _b208, MySqlInt, init_int, _a287, _b209, MySqlJsonBuilder, _a288, _b210, MySqlJson, init_json22, _a289, _b211, MySqlMediumIntBuilder, _a290, _b212, MySqlMediumInt, init_mediumint, _a291, _b213, MySqlRealBuilder, _a292, _b214, MySqlReal, init_real3, _a293, _b215, MySqlSerialBuilder, _a294, _b216, MySqlSerial, init_serial22, _a295, _b217, MySqlSmallIntBuilder, _a296, _b218, MySqlSmallInt, init_smallint22, _a297, _b219, MySqlTextBuilder, _a298, _b220, MySqlText, init_text3, _a299, _b221, MySqlTimeBuilder, _a300, _b222, MySqlTime, init_time22, _a301, _b223, MySqlDateColumnBaseBuilder, _a302, _b224, MySqlDateBaseColumn, init_date_common22, _a303, _b225, MySqlTimestampBuilder, _a304, _b226, MySqlTimestamp, _a305, _b227, MySqlTimestampStringBuilder, _a306, _b228, MySqlTimestampString, init_timestamp22, _a307, _b229, MySqlTinyIntBuilder, _a308, _b230, MySqlTinyInt, init_tinyint, _a309, _b231, MySqlVarBinaryBuilder, _a310, _b232, MySqlVarBinary, init_varbinary, _a311, _b233, MySqlVarCharBuilder, _a312, _b234, MySqlVarChar, init_varchar22, _a313, _b235, MySqlYearBuilder, _a314, _b236, MySqlYear, init_year, init_columns3, _a315, _b237, _c9, _MySqlCountBuilder, MySqlCountBuilder, init_count3, _a316, IndexBuilderOn3, _a317, IndexBuilder3, _a318, Index5, init_indexes3, init_all3, InlineForeignKeys3, _a319, _b238, _c10, _d4, _e4, MySqlTable, mysqlTable, init_table42, _a320, PrimaryKeyBuilder3, _a321, PrimaryKey3, init_primary_keys3, MySqlViewConfig, init_view_common32, init_utils8, _a322, _b239, MySqlDeleteBase, init_delete3, _a323, _b240, MySqlViewBase, init_view_base3, _a324, MySqlDialect, init_dialect3, _a325, MySqlSelectBuilder, _a326, _b241, MySqlSelectQueryBuilderBase, _a327, _b242, MySqlSelectBase, getMySqlSetOperators, union4, unionAll3, intersect3, intersectAll22, except3, exceptAll22, init_select4, _a328, QueryBuilder3, init_query_builder4, _a329, MySqlInsertBuilder, _a330, _b243, MySqlInsertBase, init_insert3, init_select_types3, _a331, MySqlUpdateBuilder, _a332, _b244, MySqlUpdateBase, init_update3, init_query_builders3, _a333, RelationalQueryBuilder3, _a334, _b245, MySqlRelationalQuery, init_query3, _a335, MySqlDatabase, init_db3, _a336, ViewBuilderCore2, _a337, _b246, ViewBuilder3, _a338, _b247, ManualViewBuilder3, _a339, _b248, _c11, MySqlView2, init_view3, _a340, MySqlSchema5, init_schema22, _a341, MySqlPreparedQuery, _a342, MySqlSession, _a343, _b249, MySqlTransaction, init_session32, init_subquery4, init_mysql_core, handleEnumType, generateMySqlSnapshot, fromDatabase3, init_mysqlSerializer, cliConfigGenerate, pushParams, pullParams, configCheck, cliConfigCheck, init_cli, gelCredentials, init_gel, libSQLCredentials, init_libsql, mysqlCredentials, init_mysql, postgresCredentials, init_postgres, singlestoreCredentials, init_singlestore, sqliteCredentials, init_sqlite, credentials, studioCliParams, studioConfig, init_studio, es5_exports, _3, es5_default, init_es5, import_hanji7, assertES5, safeRegister, migrateConfig, init_utils9, prepareFromExports, init_pgImports, init_alias5, _a344, UniqueConstraintBuilder4, _a345, UniqueOnConstraintBuilder4, _a346, UniqueConstraint4, init_unique_constraint4, _a347, _b250, SingleStoreColumnBuilder, _a348, _b251, SingleStoreColumn, _a349, _b252, SingleStoreColumnBuilderWithAutoIncrement, _a350, _b253, SingleStoreColumnWithAutoIncrement, init_common5, _a351, _b254, SingleStoreBigInt53Builder, _a352, _b255, SingleStoreBigInt53, _a353, _b256, SingleStoreBigInt64Builder, _a354, _b257, SingleStoreBigInt64, init_bigint3, _a355, _b258, SingleStoreBinaryBuilder, _a356, _b259, SingleStoreBinary, init_binary2, _a357, _b260, SingleStoreBooleanBuilder, _a358, _b261, SingleStoreBoolean, init_boolean3, _a359, _b262, SingleStoreCharBuilder, _a360, _b263, SingleStoreChar, init_char3, _a361, _b264, SingleStoreCustomColumnBuilder, _a362, _b265, SingleStoreCustomColumn, init_custom4, _a363, _b266, SingleStoreDateBuilder, _a364, _b267, SingleStoreDate, _a365, _b268, SingleStoreDateStringBuilder, _a366, _b269, SingleStoreDateString, init_date3, _a367, _b270, SingleStoreDateTimeBuilder, _a368, _b271, SingleStoreDateTime, _a369, _b272, SingleStoreDateTimeStringBuilder, _a370, _b273, SingleStoreDateTimeString, init_datetime2, _a371, _b274, SingleStoreDecimalBuilder, _a372, _b275, SingleStoreDecimal, _a373, _b276, SingleStoreDecimalNumberBuilder, _a374, _b277, SingleStoreDecimalNumber, _a375, _b278, SingleStoreDecimalBigIntBuilder, _a376, _b279, SingleStoreDecimalBigInt, init_decimal2, _a377, _b280, SingleStoreDoubleBuilder, _a378, _b281, SingleStoreDouble, init_double2, _a379, _b282, SingleStoreEnumColumnBuilder, _a380, _b283, SingleStoreEnumColumn, init_enum3, _a381, _b284, SingleStoreFloatBuilder, _a382, _b285, SingleStoreFloat, init_float2, _a383, _b286, SingleStoreIntBuilder, _a384, _b287, SingleStoreInt, init_int2, _a385, _b288, SingleStoreJsonBuilder, _a386, _b289, SingleStoreJson, init_json3, _a387, _b290, SingleStoreMediumIntBuilder, _a388, _b291, SingleStoreMediumInt, init_mediumint2, _a389, _b292, SingleStoreRealBuilder, _a390, _b293, SingleStoreReal, init_real4, _a391, _b294, SingleStoreSerialBuilder, _a392, _b295, SingleStoreSerial, init_serial3, _a393, _b296, SingleStoreSmallIntBuilder, _a394, _b297, SingleStoreSmallInt, init_smallint3, _a395, _b298, SingleStoreTextBuilder, _a396, _b299, SingleStoreText, init_text4, _a397, _b300, SingleStoreTimeBuilder, _a398, _b301, SingleStoreTime, init_time3, _a399, _b302, SingleStoreDateColumnBaseBuilder, _a400, _b303, SingleStoreDateBaseColumn, init_date_common3, _a401, _b304, SingleStoreTimestampBuilder, _a402, _b305, SingleStoreTimestamp, _a403, _b306, SingleStoreTimestampStringBuilder, _a404, _b307, SingleStoreTimestampString, init_timestamp3, _a405, _b308, SingleStoreTinyIntBuilder, _a406, _b309, SingleStoreTinyInt, init_tinyint2, _a407, _b310, SingleStoreVarBinaryBuilder, _a408, _b311, SingleStoreVarBinary, init_varbinary2, _a409, _b312, SingleStoreVarCharBuilder, _a410, _b313, SingleStoreVarChar, init_varchar3, _a411, _b314, SingleStoreVectorBuilder, _a412, _b315, SingleStoreVector, init_vector4, _a413, _b316, SingleStoreYearBuilder, _a414, _b317, SingleStoreYear, init_year2, init_columns4, _a415, _b318, _c12, _SingleStoreCountBuilder, SingleStoreCountBuilder, init_count4, _a416, IndexBuilderOn4, _a417, IndexBuilder4, _a418, Index6, init_indexes4, init_all4, _a419, _b319, _c13, _d5, SingleStoreTable, init_table52, _a420, PrimaryKeyBuilder4, _a421, PrimaryKey4, init_primary_keys4, init_utils10, _a422, _b320, SingleStoreDeleteBase, init_delete4, _a423, SingleStoreInsertBuilder, _a424, _b321, SingleStoreInsertBase, init_insert4, _a425, SingleStoreDialect, init_dialect4, _a426, SingleStoreSelectBuilder, _a427, _b322, SingleStoreSelectQueryBuilderBase, _a428, _b323, SingleStoreSelectBase, getSingleStoreSetOperators, union5, unionAll4, intersect4, except4, minus, init_select5, _a429, QueryBuilder4, init_query_builder5, init_select_types4, _a430, SingleStoreUpdateBuilder, _a431, _b324, SingleStoreUpdateBase, init_update4, init_query_builders4, _a432, SingleStoreDatabase, init_db4, _a433, SingleStoreSchema5, init_schema32, _a434, SingleStorePreparedQuery, _a435, SingleStoreSession, _a436, _b325, SingleStoreTransaction, init_session4, init_subquery5, init_singlestore_core, dialect5, generateSingleStoreSnapshot, fromDatabase4, init_singlestoreSerializer, sqliteImports_exports, prepareFromExports2, prepareFromSqliteImports, init_sqliteImports, mysqlImports_exports, prepareFromExports3, prepareFromMySqlImports, init_mysqlImports, mysqlPushUtils_exports, import_hanji8, filterStatements, logSuggestionsAndReturn2, init_mysqlPushUtils, mysqlIntrospect_exports, import_hanji9, mysqlPushIntrospect, init_mysqlIntrospect, singlestoreImports_exports, prepareFromExports4, prepareFromSingleStoreImports, init_singlestoreImports, singlestorePushUtils_exports, import_hanji10, filterStatements2, logSuggestionsAndReturn3, init_singlestorePushUtils, singlestoreIntrospect_exports, import_hanji11, singlestorePushIntrospect, init_singlestoreIntrospect, import_hanji3, pgPushIntrospect = async (db2, filters, schemaFilters, entities, tsSchema) => {
58584
+ }, __toESM2 = (mod, isNodeMode, target) => (target = mod != null ? __create2(__getProtoOf2(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp3(target, "default", { value: mod, enumerable: true }) : target, mod)), __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value), ANSI_BACKGROUND_OFFSET, wrapAnsi16, wrapAnsi256, wrapAnsi16m, styles2, modifierNames, foregroundColorNames, backgroundColorNames, colorNames, ansiStyles, ansi_styles_default, init_ansi_styles, env, flagForceColor, supportsColor, supports_color_default, init_supports_color, init_utilities, stdoutColor, stderrColor, GENERATOR, STYLER, IS_EMPTY, levelMapping, styles22, applyOptions, chalkFactory, getModelAnsi, usedModels, proto, createStyler, createBuilder, applyStyle, chalk, chalkStderr, source_default, init_source, require_old, require_fs, require_path, require_balanced_match, require_brace_expansion, require_minimatch, require_inherits_browser2, require_inherits2, require_common3, require_sync, require_wrappy, require_once, require_inflight, require_glob, require_readline, require_src3, require_utils4, require_lodash, require_hanji, originUUID, snapshotVersion, mapValues, mapKeys, mapEntries, customMapEntries, init_global2, util3, objectUtil2, ZodParsedType2, getParsedType2, init_util2, ZodIssueCode2, ZodError3, init_ZodError2, errorMap2, en_default2, init_en2, overrideErrorMap2, init_errors8, makeIssue2, ParseStatus2, INVALID2, DIRTY2, OK2, isAborted2, isDirty2, isValid2, isAsync2, init_parseUtil2, init_typeAliases2, errorUtil2, init_errorUtil2, ParseInputLazyPath2, handleResult2, ZodType2, cuidRegex2, cuid2Regex2, ulidRegex2, uuidRegex2, nanoidRegex2, jwtRegex2, durationRegex2, emailRegex2, _emojiRegex2, emojiRegex2, ipv4Regex2, ipv4CidrRegex2, ipv6Regex2, ipv6CidrRegex2, base64Regex2, base64urlRegex2, dateRegexSource2, dateRegex2, ZodString2, ZodNumber2, ZodBigInt2, ZodBoolean2, ZodDate2, ZodSymbol2, ZodUndefined2, ZodNull2, ZodAny2, ZodUnknown2, ZodNever2, ZodVoid2, ZodArray2, ZodObject2, ZodUnion2, getDiscriminator2, ZodDiscriminatedUnion2, ZodIntersection2, ZodTuple2, ZodRecord2, ZodMap2, ZodSet2, ZodFunction2, ZodLazy2, ZodLiteral2, ZodEnum2, ZodNativeEnum2, ZodPromise2, ZodEffects2, ZodOptional2, ZodNullable2, ZodDefault2, ZodCatch2, ZodNaN2, BRAND2, ZodBranded2, ZodPipeline2, ZodReadonly2, late2, ZodFirstPartyTypeKind2, stringType2, numberType2, nanType2, bigIntType2, booleanType2, dateType2, symbolType2, undefinedType2, nullType2, anyType2, unknownType2, neverType2, voidType2, arrayType2, objectType2, strictObjectType2, unionType2, discriminatedUnionType2, intersectionType2, tupleType2, recordType2, mapType2, setType2, functionType2, lazyType2, literalType2, enumType2, nativeEnumType2, promiseType2, effectsType2, optionalType2, nullableType2, preprocessType2, pipelineType2, coerce2, init_types5, init_external2, init_v32, init_esm2, enumSchema, enumSchemaV1, indexColumn, index2, fk, sequenceSchema, roleSchema, sequenceSquashed, column2, checkConstraint, columnSquashed, compositePK, uniqueConstraint, policy, policySquashed, viewWithOption, matViewWithOption, mergedViewWithOption, view2, table8, schemaHash, kitInternals, gelSchemaExternal, gelSchemaInternal, tableSquashed, gelSchemaSquashed, gelSchema, dryGel, init_gelSchema, index22, fk2, column22, tableV3, compositePK2, uniqueConstraint2, checkConstraint2, tableV4, table22, viewMeta, view22, kitInternals2, dialect2, schemaHash2, schemaInternalV3, schemaInternalV4, schemaInternalV5, schemaInternal, schemaV3, schemaV4, schemaV5, schema2, tableSquashedV4, tableSquashed2, viewSquashed, schemaSquashed, schemaSquashedV4, MySqlSquasher, squashMysqlScheme, mysqlSchema, mysqlSchemaV5, mysqlSchemaSquashed, backwardCompatibleMysqlSchema, dryMySql, init_mysqlSchema, indexV2, columnV2, tableV2, enumSchemaV12, enumSchema2, pgSchemaV2, references, columnV1, tableV1, pgSchemaV1, indexColumn2, index3, indexV4, indexV5, indexV6, fk3, sequenceSchema2, roleSchema2, sequenceSquashed2, columnV7, column3, checkConstraint3, columnSquashed2, tableV32, compositePK3, uniqueConstraint3, policy2, policySquashed2, viewWithOption2, matViewWithOption2, mergedViewWithOption2, view3, tableV42, tableV5, tableV6, tableV7, table32, schemaHash3, kitInternals3, pgSchemaInternalV3, pgSchemaInternalV4, pgSchemaInternalV5, pgSchemaInternalV6, pgSchemaExternal, pgSchemaInternalV7, pgSchemaInternal, tableSquashed3, tableSquashedV42, pgSchemaSquashedV4, pgSchemaSquashedV6, pgSchemaSquashed, pgSchemaV3, pgSchemaV4, pgSchemaV5, pgSchemaV6, pgSchemaV7, pgSchema, backwardCompatiblePgSchema, PgSquasher, squashPgScheme, dryPg, init_pgSchema, index4, column4, compositePK4, uniqueConstraint4, table42, viewMeta2, kitInternals4, dialect22, schemaHash4, schemaInternal2, schema22, tableSquashed4, schemaSquashed2, SingleStoreSquasher, squashSingleStoreScheme, singlestoreSchema, singlestoreSchemaSquashed, backwardCompatibleSingleStoreSchema, drySingleStore, init_singlestoreSchema, index5, fk4, compositePK5, column5, tableV33, uniqueConstraint5, checkConstraint4, table52, view4, dialect3, schemaHash5, schemaInternalV32, schemaInternalV42, schemaInternalV52, kitInternals5, latestVersion, schemaInternal3, schemaV32, schemaV42, schemaV52, schema3, tableSquashed5, schemaSquashed3, SQLiteSquasher, squashSqliteScheme, drySQLite, sqliteSchemaV5, sqliteSchema, SQLiteSchemaSquashed, backwardCompatibleSqliteSchema, init_sqliteSchema, copy, prepareMigrationMeta, schemaRenameKey, tableRenameKey, columnRenameKey, init_utils7, import_hanji, warning, error, isRenamePromptItem, ResolveColumnSelect, tableKey, ResolveSelectNamed, ResolveSelect, ResolveSchemasSelect, Spinner2, ProgressView, init_views, glob, init_serializer, fillPgSnapshot, init_migrationPreparator, require_heap, require_heap2, require_difflib, require_difflib2, require_util2, require_styles, require_has_flag2, require_supports_colors, require_trap, require_zalgo, require_america, require_zebra, require_rainbow, require_random, require_colors, require_safe, require_colorize, require_lib4, import_json_diff, mapArraysDiff, findAlternationsInTable, alternationsInColumn, init_jsonDiffer, parseType, Convertor, PgCreateRoleConvertor, PgDropRoleConvertor, PgRenameRoleConvertor, PgAlterRoleConvertor, PgCreatePolicyConvertor, PgDropPolicyConvertor, PgRenamePolicyConvertor, PgAlterPolicyConvertor, PgCreateIndPolicyConvertor, PgDropIndPolicyConvertor, PgRenameIndPolicyConvertor, PgAlterIndPolicyConvertor, PgEnableRlsConvertor, PgDisableRlsConvertor, PgCreateTableConvertor, MySqlCreateTableConvertor, SingleStoreCreateTableConvertor, SQLiteCreateTableConvertor, PgCreateViewConvertor, MySqlCreateViewConvertor, SqliteCreateViewConvertor, PgDropViewConvertor, MySqlDropViewConvertor, SqliteDropViewConvertor, MySqlAlterViewConvertor, PgRenameViewConvertor, MySqlRenameViewConvertor, PgAlterViewSchemaConvertor, PgAlterViewAddWithOptionConvertor, PgAlterViewDropWithOptionConvertor, PgAlterViewAlterTablespaceConvertor, PgAlterViewAlterUsingConvertor, PgAlterTableAlterColumnSetGenerated, PgAlterTableAlterColumnDropGenerated, PgAlterTableAlterColumnAlterGenerated, PgAlterTableAddUniqueConstraintConvertor, PgAlterTableDropUniqueConstraintConvertor, PgAlterTableAddCheckConstraintConvertor, PgAlterTableDeleteCheckConstraintConvertor, MySQLAlterTableAddUniqueConstraintConvertor, MySQLAlterTableDropUniqueConstraintConvertor, MySqlAlterTableAddCheckConstraintConvertor, SingleStoreAlterTableAddUniqueConstraintConvertor, SingleStoreAlterTableDropUniqueConstraintConvertor, MySqlAlterTableDeleteCheckConstraintConvertor, CreatePgSequenceConvertor, DropPgSequenceConvertor, RenamePgSequenceConvertor, MovePgSequenceConvertor, AlterPgSequenceConvertor, CreateTypeEnumConvertor, DropTypeEnumConvertor, AlterTypeAddValueConvertor, AlterTypeSetSchemaConvertor, AlterRenameTypeConvertor, AlterTypeDropValueConvertor, PgDropTableConvertor, MySQLDropTableConvertor, SingleStoreDropTableConvertor, SQLiteDropTableConvertor, PgRenameTableConvertor, SqliteRenameTableConvertor, MySqlRenameTableConvertor, SingleStoreRenameTableConvertor, PgAlterTableRenameColumnConvertor, MySqlAlterTableRenameColumnConvertor, SingleStoreAlterTableRenameColumnConvertor, SQLiteAlterTableRenameColumnConvertor, PgAlterTableDropColumnConvertor, MySqlAlterTableDropColumnConvertor, SingleStoreAlterTableDropColumnConvertor, SQLiteAlterTableDropColumnConvertor, PgAlterTableAddColumnConvertor, MySqlAlterTableAddColumnConvertor, SingleStoreAlterTableAddColumnConvertor, SQLiteAlterTableAddColumnConvertor, PgAlterTableAlterColumnSetTypeConvertor, PgAlterTableAlterColumnSetDefaultConvertor, PgAlterTableAlterColumnDropDefaultConvertor, PgAlterTableAlterColumnDropGeneratedConvertor, PgAlterTableAlterColumnSetExpressionConvertor, PgAlterTableAlterColumnAlterrGeneratedConvertor, SqliteAlterTableAlterColumnDropGeneratedConvertor, SqliteAlterTableAlterColumnSetExpressionConvertor, SqliteAlterTableAlterColumnAlterGeneratedConvertor, MySqlAlterTableAlterColumnAlterrGeneratedConvertor, MySqlAlterTableAddPk, MySqlAlterTableDropPk, LibSQLModifyColumn, MySqlModifyColumn, SingleStoreAlterTableAlterColumnAlterrGeneratedConvertor, SingleStoreAlterTableAddPk, SingleStoreAlterTableDropPk, SingleStoreModifyColumn, PgAlterTableCreateCompositePrimaryKeyConvertor, PgAlterTableDeleteCompositePrimaryKeyConvertor, PgAlterTableAlterCompositePrimaryKeyConvertor, MySqlAlterTableCreateCompositePrimaryKeyConvertor, MySqlAlterTableDeleteCompositePrimaryKeyConvertor, MySqlAlterTableAlterCompositePrimaryKeyConvertor, PgAlterTableAlterColumnSetPrimaryKeyConvertor, PgAlterTableAlterColumnDropPrimaryKeyConvertor, PgAlterTableAlterColumnSetNotNullConvertor, PgAlterTableAlterColumnDropNotNullConvertor, PgCreateForeignKeyConvertor, LibSQLCreateForeignKeyConvertor, MySqlCreateForeignKeyConvertor, PgAlterForeignKeyConvertor, PgDeleteForeignKeyConvertor, MySqlDeleteForeignKeyConvertor, CreatePgIndexConvertor, CreateMySqlIndexConvertor, CreateSingleStoreIndexConvertor, CreateSqliteIndexConvertor, PgDropIndexConvertor, PgCreateSchemaConvertor, PgRenameSchemaConvertor, PgDropSchemaConvertor, PgAlterTableSetSchemaConvertor, PgAlterTableSetNewSchemaConvertor, PgAlterTableRemoveFromSchemaConvertor, SqliteDropIndexConvertor, MySqlDropIndexConvertor, SingleStoreDropIndexConvertor, SQLiteRecreateTableConvertor, LibSQLRecreateTableConvertor, SingleStoreRecreateTableConvertor, convertors, init_sqlgenerator, _moveDataStatements, getOldTableName, getNewTableName, logSuggestionsAndReturn, init_sqlitePushUtils, preparePgCreateTableJson, prepareMySqlCreateTableJson, prepareSingleStoreCreateTableJson, prepareSQLiteCreateTable, prepareDropTableJson, prepareRenameTableJson, prepareCreateEnumJson, prepareAddValuesToEnumJson, prepareDropEnumValues, prepareDropEnumJson, prepareMoveEnumJson, prepareRenameEnumJson, prepareCreateSequenceJson, prepareAlterSequenceJson, prepareDropSequenceJson, prepareMoveSequenceJson, prepareRenameSequenceJson, prepareCreateRoleJson, prepareAlterRoleJson, prepareDropRoleJson, prepareRenameRoleJson, prepareCreateSchemasJson, prepareRenameSchemasJson, prepareDeleteSchemasJson, prepareRenameColumns, _prepareDropColumns, _prepareAddColumns, _prepareSqliteAddColumns, prepareAlterColumnsMysql, preparePgAlterColumns, prepareSqliteAlterColumns, prepareRenamePolicyJsons, prepareRenameIndPolicyJsons, prepareCreatePolicyJsons, prepareCreateIndPolicyJsons, prepareDropPolicyJsons, prepareDropIndPolicyJsons, prepareAlterPolicyJson, prepareAlterIndPolicyJson, preparePgCreateIndexesJson, prepareCreateIndexesJson, prepareCreateReferencesJson, prepareLibSQLCreateReferencesJson, prepareDropReferencesJson, prepareLibSQLDropReferencesJson, prepareAlterReferencesJson, prepareDropIndexesJson, prepareAddCompositePrimaryKeySqlite, prepareDeleteCompositePrimaryKeySqlite, prepareAlterCompositePrimaryKeySqlite, prepareAddCompositePrimaryKeyPg, prepareDeleteCompositePrimaryKeyPg, prepareAlterCompositePrimaryKeyPg, prepareAddUniqueConstraintPg, prepareDeleteUniqueConstraintPg, prepareAddCheckConstraint, prepareDeleteCheckConstraint, prepareAddCompositePrimaryKeyMySql, prepareDeleteCompositePrimaryKeyMySql, prepareAlterCompositePrimaryKeyMySql, preparePgCreateViewJson, prepareMySqlCreateViewJson, prepareSqliteCreateViewJson, prepareDropViewJson, prepareRenameViewJson, preparePgAlterViewAlterSchemaJson, preparePgAlterViewAddWithOptionJson, preparePgAlterViewDropWithOptionJson, preparePgAlterViewAlterTablespaceJson, preparePgAlterViewAlterUsingJson, prepareMySqlAlterView, init_jsonStatements, prepareLibSQLRecreateTable, prepareSQLiteRecreateTable, libSQLCombineStatements, sqliteCombineStatements, prepareSingleStoreRecreateTable, singleStoreCombineStatements, init_statementCombiner, snapshotsDiffer_exports, makeChanged, makeSelfOrChanged, makePatched, makeSelfOrPatched, columnSchema, alteredColumnSchema, enumSchema3, changedEnumSchema, tableScheme, alteredTableScheme, alteredViewCommon, alteredPgViewSchema, alteredMySqlViewSchema, diffResultScheme, diffResultSchemeMysql, diffResultSchemeSingleStore, diffResultSchemeSQLite, schemaChangeFor, nameChangeFor, nameSchemaChangeFor, columnChangeFor, applyPgSnapshotsDiff, applyMysqlSnapshotsDiff, applySingleStoreSnapshotsDiff, applySqliteSnapshotsDiff, applyLibSQLSnapshotsDiff, init_snapshotsDiffer, init_words, dialects, dialect4, commonSquashedSchema, commonSchema, init_schemaValidator, sqliteDriversLiterals, postgresqlDriversLiterals, prefixes, prefix, casingTypes, casingType, sqliteDriver, postgresDriver, driver2, configMigrations, configCommonSchema, casing, introspectParams, configIntrospectCliSchema, configGenerateSchema, configPushSchema, init_common2, withStyle, init_outputs, import_hanji2, schemasResolver, tablesResolver, viewsResolver, mySqlViewsResolver, sqliteViewsResolver, sequencesResolver, roleResolver, policyResolver, indPolicyResolver, enumsResolver, columnsResolver, promptColumnsConflicts, promptNamedConflict, promptNamedWithSchemasConflict, promptSchemasConflict, BREAKPOINT, init_migrate, posixClasses, braceEscape, regexpEscape, rangesToString, parseClass, init_brace_expressions, escape, init_escape, unescape, init_unescape, import_brace_expansion, minimatch, starDotExtRE, starDotExtTest, starDotExtTestDot, starDotExtTestNocase, starDotExtTestNocaseDot, starDotStarRE, starDotStarTest, starDotStarTestDot, dotStarRE, dotStarTest, starRE, starTest, starTestDot, qmarksRE, qmarksTestNocase, qmarksTestNocaseDot, qmarksTestDot, qmarksTest, qmarksTestNoExt, qmarksTestNoExtDot, defaultPlatform, path, sep, GLOBSTAR, plTypes, qmark, star, twoStarDot, twoStarNoDot, charSet, reSpecials, addPatternStartSet, filter, ext, defaults, braceExpand, MAX_PATTERN_LENGTH, assertValidPattern, makeRe, match2, globUnescape, globMagic, regExpEscape, Minimatch, init_mjs, entityKind2, hasOwnEntityKind2, init_entity2, _a, Column2, init_column2, _a2, ColumnBuilder2, init_column_builder2, TableName2, init_table_utils2, _a3, ForeignKeyBuilder2, _a4, ForeignKey2, init_foreign_keys2, init_tracing_utils2, _a5, UniqueConstraintBuilder, _a6, UniqueOnConstraintBuilder, _a7, UniqueConstraint, init_unique_constraint2, init_array2, _a8, _b, PgColumnBuilder2, _a9, _b2, PgColumn2, _a10, _b3, ExtraConfigColumn2, _a11, IndexedColumn2, _a12, _b4, PgArrayBuilder2, _a13, _b5, _PgArray, PgArray2, init_common22, _a14, _b6, PgEnumObjectColumnBuilder2, _a15, _b7, PgEnumObjectColumn2, isPgEnumSym2, _a16, _b8, PgEnumColumnBuilder2, _a17, _b9, PgEnumColumn2, init_enum2, _a18, Subquery2, _a19, _b10, WithSubquery2, init_subquery2, version2, init_version2, otel2, rawTracer2, tracer2, init_tracing2, ViewBaseConfig2, init_view_common3, Schema2, Columns2, ExtraConfigColumns2, OriginalName2, BaseName2, IsAlias2, ExtraConfigBuilder2, IsDrizzleTable2, _a20, _b11, _c, _d, _e3, _f, _g, _h, _i, _j, Table2, init_table8, _a21, FakePrimitiveParam, _a22, StringChunk2, _a23, _SQL, SQL2, _a24, Name2, noopDecoder2, noopEncoder2, noopMapper2, _a25, Param2, _a26, Placeholder2, IsDrizzleView2, _a27, _b12, _c2, View3, init_sql3, _a28, ColumnAliasProxyHandler2, _a29, TableAliasProxyHandler2, _a30, RelationTableAliasProxyHandler, init_alias3, _a31, _b13, DrizzleError2, DrizzleQueryError, _a32, _b14, TransactionRollbackError2, init_errors22, _a33, ConsoleLogWriter2, _a34, DefaultLogger2, _a35, NoopLogger2, init_logger3, init_operations, _a36, _b15, QueryPromise2, init_query_promise2, textDecoder, init_utils22, _a37, _b16, PgIntColumnBaseBuilder2, init_int_common2, _a38, _b17, PgBigInt53Builder2, _a39, _b18, PgBigInt532, _a40, _b19, PgBigInt64Builder2, _a41, _b20, PgBigInt642, init_bigint2, _a42, _b21, PgBigSerial53Builder2, _a43, _b22, PgBigSerial532, _a44, _b23, PgBigSerial64Builder2, _a45, _b24, PgBigSerial642, init_bigserial2, _a46, _b25, PgBooleanBuilder2, _a47, _b26, PgBoolean2, init_boolean2, _a48, _b27, PgCharBuilder2, _a49, _b28, PgChar2, init_char2, _a50, _b29, PgCidrBuilder2, _a51, _b30, PgCidr2, init_cidr2, _a52, _b31, PgCustomColumnBuilder2, _a53, _b32, PgCustomColumn2, init_custom2, _a54, _b33, PgDateColumnBaseBuilder2, init_date_common2, _a55, _b34, PgDateBuilder2, _a56, _b35, PgDate2, _a57, _b36, PgDateStringBuilder2, _a58, _b37, PgDateString2, init_date2, _a59, _b38, PgDoublePrecisionBuilder2, _a60, _b39, PgDoublePrecision2, init_double_precision2, _a61, _b40, PgInetBuilder2, _a62, _b41, PgInet2, init_inet2, _a63, _b42, PgIntegerBuilder2, _a64, _b43, PgInteger2, init_integer2, _a65, _b44, PgIntervalBuilder2, _a66, _b45, PgInterval2, init_interval2, _a67, _b46, PgJsonBuilder2, _a68, _b47, PgJson2, init_json2, _a69, _b48, PgJsonbBuilder2, _a70, _b49, PgJsonb2, init_jsonb2, _a71, _b50, PgLineBuilder2, _a72, _b51, PgLineTuple2, _a73, _b52, PgLineABCBuilder2, _a74, _b53, PgLineABC2, init_line2, _a75, _b54, PgMacaddrBuilder2, _a76, _b55, PgMacaddr2, init_macaddr2, _a77, _b56, PgMacaddr8Builder2, _a78, _b57, PgMacaddr82, init_macaddr82, _a79, _b58, PgNumericBuilder2, _a80, _b59, PgNumeric2, _a81, _b60, PgNumericNumberBuilder2, _a82, _b61, PgNumericNumber2, _a83, _b62, PgNumericBigIntBuilder2, _a84, _b63, PgNumericBigInt2, init_numeric2, _a85, _b64, PgPointTupleBuilder2, _a86, _b65, PgPointTuple2, _a87, _b66, PgPointObjectBuilder2, _a88, _b67, PgPointObject2, init_point2, init_utils32, _a89, _b68, PgGeometryBuilder2, _a90, _b69, PgGeometry2, _a91, _b70, PgGeometryObjectBuilder2, _a92, _b71, PgGeometryObject2, init_geometry2, _a93, _b72, PgRealBuilder2, _a94, _b73, PgReal2, init_real2, _a95, _b74, PgSerialBuilder2, _a96, _b75, PgSerial2, init_serial2, _a97, _b76, PgSmallIntBuilder2, _a98, _b77, PgSmallInt2, init_smallint2, _a99, _b78, PgSmallSerialBuilder2, _a100, _b79, PgSmallSerial2, init_smallserial2, _a101, _b80, PgTextBuilder2, _a102, _b81, PgText2, init_text2, _a103, _b82, PgTimeBuilder2, _a104, _b83, PgTime2, init_time2, _a105, _b84, PgTimestampBuilder2, _a106, _b85, PgTimestamp2, _a107, _b86, PgTimestampStringBuilder2, _a108, _b87, PgTimestampString2, init_timestamp2, _a109, _b88, PgUUIDBuilder2, _a110, _b89, PgUUID2, init_uuid3, _a111, _b90, PgVarcharBuilder2, _a112, _b91, PgVarchar2, init_varchar2, _a113, _b92, PgBinaryVectorBuilder2, _a114, _b93, PgBinaryVector2, init_bit2, _a115, _b94, PgHalfVectorBuilder2, _a116, _b95, PgHalfVector2, init_halfvec2, _a117, _b96, PgSparseVectorBuilder2, _a118, _b97, PgSparseVector2, init_sparsevec2, _a119, _b98, PgVectorBuilder2, _a120, _b99, PgVector2, init_vector3, init_all2, InlineForeignKeys2, EnableRLS2, _a121, _b100, _c3, _d2, _e22, _f2, PgTable2, pgTable2, init_table22, _a122, PrimaryKeyBuilder2, _a123, PrimaryKey2, init_primary_keys2, eq2, ne4, gt3, gte2, lt4, lte2, init_conditions2, init_select3, init_expressions2, _a124, Relation2, _a125, Relations2, _a126, _b101, _One, One2, _a127, _b102, _Many, Many2, init_relations2, init_aggregate2, init_vector22, init_functions2, init_sql22, dist_exports, init_dist6, init_alias22, _a128, CheckBuilder, _a129, Check, init_checks2, init_columns2, _a130, _SelectionProxyHandler, SelectionProxyHandler2, init_selection_proxy2, _a131, IndexBuilderOn2, _a132, IndexBuilder2, _a133, Index2, init_indexes2, _a134, PgPolicy, init_policies2, PgViewConfig2, init_view_common22, _a135, CasingCache2, init_casing2, _a136, _b103, PgViewBase2, init_view_base2, _a137, PgDialect2, init_dialect2, _a138, TypedQueryBuilder2, init_query_builder3, _a139, PgSelectBuilder2, _a140, _b104, PgSelectQueryBuilderBase2, _a141, _b105, PgSelectBase2, getPgSetOperators2, union2, unionAll2, intersect2, intersectAll2, except2, exceptAll2, init_select22, _a142, QueryBuilder2, init_query_builder22, _a143, DefaultViewBuilderCore, _a144, _b106, ViewBuilder, _a145, _b107, ManualViewBuilder, _a146, MaterializedViewBuilderCore, _a147, _b108, MaterializedViewBuilder, _a148, _b109, ManualMaterializedViewBuilder, _a149, _b110, _c4, PgView2, PgMaterializedViewConfig2, _a150, _b111, _c5, PgMaterializedView, init_view2, init_utils42, _a151, _b112, PgDeleteBase2, init_delete2, _a152, PgInsertBuilder2, _a153, _b113, PgInsertBase2, init_insert2, _a154, _b114, PgRefreshMaterializedView2, init_refresh_materialized_view2, init_select_types, _a155, PgUpdateBuilder2, _a156, _b115, PgUpdateBase2, init_update2, init_query_builders2, _a157, _b116, _c6, _PgCountBuilder, PgCountBuilder2, init_count2, _a158, RelationalQueryBuilder2, _a159, _b117, PgRelationalQuery2, init_query2, _a160, _b118, PgRaw2, init_raw2, _a161, PgDatabase2, init_db2, _a162, PgRole, init_roles2, _a163, PgSequence, init_sequence2, _a164, PgSchema5, init_schema3, _a165, Cache, _a166, _b119, NoopCache, init_cache, _a167, PgPreparedQuery2, _a168, PgSession2, _a169, _b120, PgTransaction2, init_session3, init_subquery22, init_utils52, init_pg_core2, vectorOps, init_vector32, sqlToStr, init_utils62, indexName, generatePgSnapshot, trimChar, fromDatabase, defaultForColumn, getColumnsInfoQuery, init_pgSerializer, import_hanji4, Select, init_selector_ui, init_alias32, _a170, CheckBuilder2, _a171, Check2, init_checks22, _a172, ForeignKeyBuilder22, _a173, ForeignKey22, init_foreign_keys22, _a174, UniqueConstraintBuilder2, _a175, UniqueOnConstraintBuilder2, _a176, UniqueConstraint2, init_unique_constraint22, _a177, _b121, SQLiteColumnBuilder, _a178, _b122, SQLiteColumn, init_common3, _a179, _b123, SQLiteBigIntBuilder, _a180, _b124, SQLiteBigInt, _a181, _b125, SQLiteBlobJsonBuilder, _a182, _b126, SQLiteBlobJson, _a183, _b127, SQLiteBlobBufferBuilder, _a184, _b128, SQLiteBlobBuffer, init_blob, _a185, _b129, SQLiteCustomColumnBuilder, _a186, _b130, SQLiteCustomColumn, init_custom22, _a187, _b131, SQLiteBaseIntegerBuilder, _a188, _b132, SQLiteBaseInteger, _a189, _b133, SQLiteIntegerBuilder, _a190, _b134, SQLiteInteger, _a191, _b135, SQLiteTimestampBuilder, _a192, _b136, SQLiteTimestamp, _a193, _b137, SQLiteBooleanBuilder, _a194, _b138, SQLiteBoolean, init_integer22, _a195, _b139, SQLiteNumericBuilder, _a196, _b140, SQLiteNumeric, _a197, _b141, SQLiteNumericNumberBuilder, _a198, _b142, SQLiteNumericNumber, _a199, _b143, SQLiteNumericBigIntBuilder, _a200, _b144, SQLiteNumericBigInt, init_numeric22, _a201, _b145, SQLiteRealBuilder, _a202, _b146, SQLiteReal, init_real22, _a203, _b147, SQLiteTextBuilder, _a204, _b148, SQLiteText, _a205, _b149, SQLiteTextJsonBuilder, _a206, _b150, SQLiteTextJson, init_text22, init_columns22, init_all22, InlineForeignKeys22, _a207, _b151, _c7, _d3, _e32, SQLiteTable, sqliteTable, init_table32, _a208, IndexBuilderOn22, _a209, IndexBuilder22, _a210, Index4, init_indexes22, _a211, PrimaryKeyBuilder22, _a212, PrimaryKey22, init_primary_keys22, init_utils72, _a213, _b152, SQLiteDeleteBase, init_delete22, _a214, _b153, SQLiteViewBase, init_view_base22, _a215, SQLiteDialect, _a216, _b154, SQLiteSyncDialect, _a217, _b155, SQLiteAsyncDialect, init_dialect22, _a218, SQLiteSelectBuilder, _a219, _b156, SQLiteSelectQueryBuilderBase, _a220, _b157, SQLiteSelectBase, getSQLiteSetOperators, union3, unionAll22, intersect22, except22, init_select32, _a221, QueryBuilder22, init_query_builder32, _a222, SQLiteInsertBuilder, _a223, _b158, SQLiteInsertBase, init_insert22, init_select_types2, _a224, SQLiteUpdateBuilder, _a225, _b159, SQLiteUpdateBase, init_update22, init_query_builders22, _a226, _b160, _c8, _SQLiteCountBuilder, SQLiteCountBuilder, init_count22, _a227, RelationalQueryBuilder22, _a228, _b161, SQLiteRelationalQuery, _a229, _b162, SQLiteSyncRelationalQuery, init_query22, _a230, _b163, SQLiteRaw, init_raw22, _a231, BaseSQLiteDatabase, init_db22, _a232, _b164, ExecuteResultSync, _a233, SQLitePreparedQuery, _a234, SQLiteSession, _a235, _b165, SQLiteTransaction, init_session22, init_subquery3, _a236, ViewBuilderCore, _a237, _b166, ViewBuilder2, _a238, _b167, ManualViewBuilder2, _a239, _b168, SQLiteView2, init_view22, init_sqlite_core, generateSqliteSnapshot, fromDatabase2, init_sqliteSerializer, getTablesFilterByExtensions, init_getTablesFilterByExtensions, init_alias4, _a240, CheckBuilder3, _a241, Check3, init_checks3, _a242, ForeignKeyBuilder3, _a243, ForeignKey3, init_foreign_keys3, _a244, UniqueConstraintBuilder3, _a245, UniqueOnConstraintBuilder3, _a246, UniqueConstraint3, init_unique_constraint3, _a247, _b169, MySqlColumnBuilder, _a248, _b170, MySqlColumn, _a249, _b171, MySqlColumnBuilderWithAutoIncrement, _a250, _b172, MySqlColumnWithAutoIncrement, init_common4, _a251, _b173, MySqlBigInt53Builder, _a252, _b174, MySqlBigInt53, _a253, _b175, MySqlBigInt64Builder, _a254, _b176, MySqlBigInt64, init_bigint22, _a255, _b177, MySqlBinaryBuilder, _a256, _b178, MySqlBinary, init_binary, _a257, _b179, MySqlBooleanBuilder, _a258, _b180, MySqlBoolean, init_boolean22, _a259, _b181, MySqlCharBuilder, _a260, _b182, MySqlChar, init_char22, _a261, _b183, MySqlCustomColumnBuilder, _a262, _b184, MySqlCustomColumn, init_custom3, _a263, _b185, MySqlDateBuilder, _a264, _b186, MySqlDate, _a265, _b187, MySqlDateStringBuilder, _a266, _b188, MySqlDateString, init_date22, _a267, _b189, MySqlDateTimeBuilder, _a268, _b190, MySqlDateTime, _a269, _b191, MySqlDateTimeStringBuilder, _a270, _b192, MySqlDateTimeString, init_datetime, _a271, _b193, MySqlDecimalBuilder, _a272, _b194, MySqlDecimal, _a273, _b195, MySqlDecimalNumberBuilder, _a274, _b196, MySqlDecimalNumber, _a275, _b197, MySqlDecimalBigIntBuilder, _a276, _b198, MySqlDecimalBigInt, init_decimal, _a277, _b199, MySqlDoubleBuilder, _a278, _b200, MySqlDouble, init_double, _a279, _b201, MySqlEnumColumnBuilder, _a280, _b202, MySqlEnumColumn, _a281, _b203, MySqlEnumObjectColumnBuilder, _a282, _b204, MySqlEnumObjectColumn, init_enum22, _a283, _b205, MySqlFloatBuilder, _a284, _b206, MySqlFloat, init_float, _a285, _b207, MySqlIntBuilder, _a286, _b208, MySqlInt, init_int, _a287, _b209, MySqlJsonBuilder, _a288, _b210, MySqlJson, init_json22, _a289, _b211, MySqlMediumIntBuilder, _a290, _b212, MySqlMediumInt, init_mediumint, _a291, _b213, MySqlRealBuilder, _a292, _b214, MySqlReal, init_real3, _a293, _b215, MySqlSerialBuilder, _a294, _b216, MySqlSerial, init_serial22, _a295, _b217, MySqlSmallIntBuilder, _a296, _b218, MySqlSmallInt, init_smallint22, _a297, _b219, MySqlTextBuilder, _a298, _b220, MySqlText, init_text3, _a299, _b221, MySqlTimeBuilder, _a300, _b222, MySqlTime, init_time22, _a301, _b223, MySqlDateColumnBaseBuilder, _a302, _b224, MySqlDateBaseColumn, init_date_common22, _a303, _b225, MySqlTimestampBuilder, _a304, _b226, MySqlTimestamp, _a305, _b227, MySqlTimestampStringBuilder, _a306, _b228, MySqlTimestampString, init_timestamp22, _a307, _b229, MySqlTinyIntBuilder, _a308, _b230, MySqlTinyInt, init_tinyint, _a309, _b231, MySqlVarBinaryBuilder, _a310, _b232, MySqlVarBinary, init_varbinary, _a311, _b233, MySqlVarCharBuilder, _a312, _b234, MySqlVarChar, init_varchar22, _a313, _b235, MySqlYearBuilder, _a314, _b236, MySqlYear, init_year, init_columns3, _a315, _b237, _c9, _MySqlCountBuilder, MySqlCountBuilder, init_count3, _a316, IndexBuilderOn3, _a317, IndexBuilder3, _a318, Index5, init_indexes3, init_all3, InlineForeignKeys3, _a319, _b238, _c10, _d4, _e4, MySqlTable, mysqlTable, init_table42, _a320, PrimaryKeyBuilder3, _a321, PrimaryKey3, init_primary_keys3, MySqlViewConfig, init_view_common32, init_utils8, _a322, _b239, MySqlDeleteBase, init_delete3, _a323, _b240, MySqlViewBase, init_view_base3, _a324, MySqlDialect, init_dialect3, _a325, MySqlSelectBuilder, _a326, _b241, MySqlSelectQueryBuilderBase, _a327, _b242, MySqlSelectBase, getMySqlSetOperators, union4, unionAll3, intersect3, intersectAll22, except3, exceptAll22, init_select4, _a328, QueryBuilder3, init_query_builder4, _a329, MySqlInsertBuilder, _a330, _b243, MySqlInsertBase, init_insert3, init_select_types3, _a331, MySqlUpdateBuilder, _a332, _b244, MySqlUpdateBase, init_update3, init_query_builders3, _a333, RelationalQueryBuilder3, _a334, _b245, MySqlRelationalQuery, init_query3, _a335, MySqlDatabase, init_db3, _a336, ViewBuilderCore2, _a337, _b246, ViewBuilder3, _a338, _b247, ManualViewBuilder3, _a339, _b248, _c11, MySqlView2, init_view3, _a340, MySqlSchema5, init_schema22, _a341, MySqlPreparedQuery, _a342, MySqlSession, _a343, _b249, MySqlTransaction, init_session32, init_subquery4, init_mysql_core, handleEnumType, generateMySqlSnapshot, fromDatabase3, init_mysqlSerializer, cliConfigGenerate, pushParams, pullParams, configCheck, cliConfigCheck, init_cli, gelCredentials, init_gel, libSQLCredentials, init_libsql, mysqlCredentials, init_mysql, postgresCredentials, init_postgres, singlestoreCredentials, init_singlestore, sqliteCredentials, init_sqlite, credentials, studioCliParams, studioConfig, init_studio, es5_exports, _3, es5_default, init_es5, import_hanji7, assertES5, safeRegister, migrateConfig, init_utils9, prepareFromExports, init_pgImports, init_alias5, _a344, UniqueConstraintBuilder4, _a345, UniqueOnConstraintBuilder4, _a346, UniqueConstraint4, init_unique_constraint4, _a347, _b250, SingleStoreColumnBuilder, _a348, _b251, SingleStoreColumn, _a349, _b252, SingleStoreColumnBuilderWithAutoIncrement, _a350, _b253, SingleStoreColumnWithAutoIncrement, init_common5, _a351, _b254, SingleStoreBigInt53Builder, _a352, _b255, SingleStoreBigInt53, _a353, _b256, SingleStoreBigInt64Builder, _a354, _b257, SingleStoreBigInt64, init_bigint3, _a355, _b258, SingleStoreBinaryBuilder, _a356, _b259, SingleStoreBinary, init_binary2, _a357, _b260, SingleStoreBooleanBuilder, _a358, _b261, SingleStoreBoolean, init_boolean3, _a359, _b262, SingleStoreCharBuilder, _a360, _b263, SingleStoreChar, init_char3, _a361, _b264, SingleStoreCustomColumnBuilder, _a362, _b265, SingleStoreCustomColumn, init_custom4, _a363, _b266, SingleStoreDateBuilder, _a364, _b267, SingleStoreDate, _a365, _b268, SingleStoreDateStringBuilder, _a366, _b269, SingleStoreDateString, init_date3, _a367, _b270, SingleStoreDateTimeBuilder, _a368, _b271, SingleStoreDateTime, _a369, _b272, SingleStoreDateTimeStringBuilder, _a370, _b273, SingleStoreDateTimeString, init_datetime2, _a371, _b274, SingleStoreDecimalBuilder, _a372, _b275, SingleStoreDecimal, _a373, _b276, SingleStoreDecimalNumberBuilder, _a374, _b277, SingleStoreDecimalNumber, _a375, _b278, SingleStoreDecimalBigIntBuilder, _a376, _b279, SingleStoreDecimalBigInt, init_decimal2, _a377, _b280, SingleStoreDoubleBuilder, _a378, _b281, SingleStoreDouble, init_double2, _a379, _b282, SingleStoreEnumColumnBuilder, _a380, _b283, SingleStoreEnumColumn, init_enum3, _a381, _b284, SingleStoreFloatBuilder, _a382, _b285, SingleStoreFloat, init_float2, _a383, _b286, SingleStoreIntBuilder, _a384, _b287, SingleStoreInt, init_int2, _a385, _b288, SingleStoreJsonBuilder, _a386, _b289, SingleStoreJson, init_json3, _a387, _b290, SingleStoreMediumIntBuilder, _a388, _b291, SingleStoreMediumInt, init_mediumint2, _a389, _b292, SingleStoreRealBuilder, _a390, _b293, SingleStoreReal, init_real4, _a391, _b294, SingleStoreSerialBuilder, _a392, _b295, SingleStoreSerial, init_serial3, _a393, _b296, SingleStoreSmallIntBuilder, _a394, _b297, SingleStoreSmallInt, init_smallint3, _a395, _b298, SingleStoreTextBuilder, _a396, _b299, SingleStoreText, init_text4, _a397, _b300, SingleStoreTimeBuilder, _a398, _b301, SingleStoreTime, init_time3, _a399, _b302, SingleStoreDateColumnBaseBuilder, _a400, _b303, SingleStoreDateBaseColumn, init_date_common3, _a401, _b304, SingleStoreTimestampBuilder, _a402, _b305, SingleStoreTimestamp, _a403, _b306, SingleStoreTimestampStringBuilder, _a404, _b307, SingleStoreTimestampString, init_timestamp3, _a405, _b308, SingleStoreTinyIntBuilder, _a406, _b309, SingleStoreTinyInt, init_tinyint2, _a407, _b310, SingleStoreVarBinaryBuilder, _a408, _b311, SingleStoreVarBinary, init_varbinary2, _a409, _b312, SingleStoreVarCharBuilder, _a410, _b313, SingleStoreVarChar, init_varchar3, _a411, _b314, SingleStoreVectorBuilder, _a412, _b315, SingleStoreVector, init_vector4, _a413, _b316, SingleStoreYearBuilder, _a414, _b317, SingleStoreYear, init_year2, init_columns4, _a415, _b318, _c12, _SingleStoreCountBuilder, SingleStoreCountBuilder, init_count4, _a416, IndexBuilderOn4, _a417, IndexBuilder4, _a418, Index6, init_indexes4, init_all4, _a419, _b319, _c13, _d5, SingleStoreTable, init_table52, _a420, PrimaryKeyBuilder4, _a421, PrimaryKey4, init_primary_keys4, init_utils10, _a422, _b320, SingleStoreDeleteBase, init_delete4, _a423, SingleStoreInsertBuilder, _a424, _b321, SingleStoreInsertBase, init_insert4, _a425, SingleStoreDialect, init_dialect4, _a426, SingleStoreSelectBuilder, _a427, _b322, SingleStoreSelectQueryBuilderBase, _a428, _b323, SingleStoreSelectBase, getSingleStoreSetOperators, union5, unionAll4, intersect4, except4, minus, init_select5, _a429, QueryBuilder4, init_query_builder5, init_select_types4, _a430, SingleStoreUpdateBuilder, _a431, _b324, SingleStoreUpdateBase, init_update4, init_query_builders4, _a432, SingleStoreDatabase, init_db4, _a433, SingleStoreSchema5, init_schema32, _a434, SingleStorePreparedQuery, _a435, SingleStoreSession, _a436, _b325, SingleStoreTransaction, init_session4, init_subquery5, init_singlestore_core, dialect5, generateSingleStoreSnapshot, fromDatabase4, init_singlestoreSerializer, sqliteImports_exports, prepareFromExports2, prepareFromSqliteImports, init_sqliteImports, mysqlImports_exports, prepareFromExports3, prepareFromMySqlImports, init_mysqlImports, mysqlPushUtils_exports, import_hanji8, filterStatements, logSuggestionsAndReturn2, init_mysqlPushUtils, mysqlIntrospect_exports, import_hanji9, mysqlPushIntrospect, init_mysqlIntrospect, singlestoreImports_exports, prepareFromExports4, prepareFromSingleStoreImports, init_singlestoreImports, singlestorePushUtils_exports, import_hanji10, filterStatements2, logSuggestionsAndReturn3, init_singlestorePushUtils, singlestoreIntrospect_exports, import_hanji11, singlestorePushIntrospect, init_singlestoreIntrospect, import_hanji3, pgPushIntrospect = async (db2, filters, schemaFilters, entities, tsSchema) => {
58053
58585
  const matchers = filters.map((it3) => {
58054
58586
  return new Minimatch(it3);
58055
58587
  });
@@ -61948,7 +62480,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
61948
62480
  en_default2 = errorMap2;
61949
62481
  }
61950
62482
  });
61951
- init_errors5 = __esm7({
62483
+ init_errors8 = __esm7({
61952
62484
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/errors.js"() {
61953
62485
  init_en2();
61954
62486
  overrideErrorMap2 = en_default2;
@@ -61956,7 +62488,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
61956
62488
  });
61957
62489
  init_parseUtil2 = __esm7({
61958
62490
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/helpers/parseUtil.js"() {
61959
- init_errors5();
62491
+ init_errors8();
61960
62492
  init_en2();
61961
62493
  makeIssue2 = (params) => {
61962
62494
  const { data, path: path2, errorMaps, issueData } = params;
@@ -62062,7 +62594,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
62062
62594
  init_types5 = __esm7({
62063
62595
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/types.js"() {
62064
62596
  init_ZodError2();
62065
- init_errors5();
62597
+ init_errors8();
62066
62598
  init_errorUtil2();
62067
62599
  init_parseUtil2();
62068
62600
  init_util2();
@@ -65220,7 +65752,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
65220
65752
  });
65221
65753
  init_external2 = __esm7({
65222
65754
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/external.js"() {
65223
- init_errors5();
65755
+ init_errors8();
65224
65756
  init_parseUtil2();
65225
65757
  init_typeAliases2();
65226
65758
  init_util2();
@@ -95882,7 +96414,7 @@ async function seedTimebackIntegrations(db2, gameId, courses) {
95882
96414
  const courseId = course.courseId || `mock-${course.subject.toLowerCase()}-g${course.grade}`;
95883
96415
  try {
95884
96416
  const existing = await db2.query.gameTimebackIntegrations.findFirst({
95885
- where: (table9, { and: and3, eq: eq3 }) => and3(eq3(table9.gameId, gameId), eq3(table9.grade, course.grade), eq3(table9.subject, course.subject))
96417
+ where: (table9, { and: and3, eq: eq3 }) => and3(eq3(table9.gameId, gameId), eq3(table9.grade, course.grade), eq3(table9.subject, course.subject), isActiveGameTimebackIntegrationStatus(table9.status))
95886
96418
  });
95887
96419
  if (!existing) {
95888
96420
  await db2.insert(gameTimebackIntegrations).values({
@@ -95902,6 +96434,7 @@ async function seedTimebackIntegrations(db2, gameId, courses) {
95902
96434
  return seededCount;
95903
96435
  }
95904
96436
  var init_timeback5 = __esm(() => {
96437
+ init_helpers_index();
95905
96438
  init_tables_index();
95906
96439
  init_config();
95907
96440
  });
@@ -97136,7 +97669,7 @@ var init_game_member_controller = __esm(() => {
97136
97669
  });
97137
97670
 
97138
97671
  // ../api-core/src/controllers/game.controller.ts
97139
- var list2, listAccessible, getSubjects, getById, getBySlug, getManifest, upsertBySlug, patchGameMetadata, remove2, games2;
97672
+ var list2, listAccessible, getSubjects, getTimebackSummaries, getById, getBySlug, getManifest, upsertBySlug, patchGameMetadata, remove2, games2;
97140
97673
  var init_game_controller = __esm(() => {
97141
97674
  init_esm();
97142
97675
  init_schemas_index();
@@ -97145,6 +97678,7 @@ var init_game_controller = __esm(() => {
97145
97678
  list2 = requireNonAnonymous(async (ctx) => ctx.services.game.list(ctx.user));
97146
97679
  listAccessible = requireNonAnonymous(async (ctx) => ctx.services.game.listAccessible(ctx.user));
97147
97680
  getSubjects = requireNonAnonymous(async (ctx) => ctx.services.game.getSubjects());
97681
+ getTimebackSummaries = requireGameManagementAccess(async (ctx) => ctx.services.game.getTimebackSummaries(ctx.user));
97148
97682
  getById = requireNonAnonymous(async (ctx) => {
97149
97683
  const gameId = requireGameId(ctx.params.gameId);
97150
97684
  return ctx.services.game.getById(gameId, ctx.user);
@@ -97192,6 +97726,7 @@ var init_game_controller = __esm(() => {
97192
97726
  list: list2,
97193
97727
  listAccessible,
97194
97728
  getSubjects,
97729
+ getTimebackSummaries,
97195
97730
  getById,
97196
97731
  getManifest,
97197
97732
  getBySlug,
@@ -97583,7 +98118,7 @@ var init_session_controller = __esm(() => {
97583
98118
  });
97584
98119
 
97585
98120
  // ../api-core/src/controllers/timeback.controller.ts
97586
- var populateStudent, getUser, getUserEnrollments, getUserById, setupIntegration, getIntegrations, updateIntegration, getIntegrationConfig, verifyIntegration, getConfig, deleteIntegrations, endActivity, heartbeat, advanceCourse, unenrollCourse, getStudentXp, getStudentMastery, getStudentHighestGradeMastered, getRoster, getStudentOverview, getGameMetrics, getStudentActivity, getGradeLevelTestResults, getGradeLevelTestReview, getActivityDetail, listMetricDiscrepancies, verifyMetricDiscrepancy, grantXp, adjustTime, adjustMastery, reconcileMasteryForConfigChange, searchStudents, enrollStudent, unenrollStudent, reactivateEnrollment, listAssessments, createAssessment, deleteAssessment, reorderAssessments, reorderQuestions, activateAssessment, deactivateAssessment, listQuestions, createQuestion, updateQuestion, deleteQuestion, getAssessmentBankStatus, destroyAssessmentBank, timeback2;
98121
+ var populateStudent, getUser, getUserEnrollments, getUserById, setupIntegration, getIntegrations, getRemovedIntegrations, createIntegration, updateIntegration, deactivateCourse, reactivateCourse, getIntegrationConfig, verifyIntegration, getConfig, deleteIntegrations, endActivity, heartbeat, advanceCourse, unenrollCourse, getStudentXp, getStudentMastery, getStudentHighestGradeMastered, getRoster, getStudentOverview, getGameMetrics, getStudentActivity, getGradeLevelTestResults, getGradeLevelTestReview, getActivityDetail, listMetricDiscrepancies, verifyMetricDiscrepancy, grantXp, adjustTime, adjustMastery, reconcileMasteryForConfigChange, searchStudents, enrollStudent, unenrollStudent, reactivateEnrollment, listAssessments, createAssessment, deleteAssessment, reorderAssessments, reorderQuestions, activateAssessment, deactivateAssessment, listQuestions, createQuestion, updateQuestion, deleteQuestion, getAssessmentBankStatus, destroyAssessmentBank, timeback2;
97587
98122
  var init_timeback_controller = __esm(() => {
97588
98123
  init_esm();
97589
98124
  init_schemas_index();
@@ -97639,6 +98174,27 @@ var init_timeback_controller = __esm(() => {
97639
98174
  }
97640
98175
  return ctx.services.timeback.getIntegrations(gameId, ctx.user);
97641
98176
  });
98177
+ getRemovedIntegrations = requireGameManagementAccess(async (ctx) => {
98178
+ const gameId = ctx.params.gameId;
98179
+ if (!gameId) {
98180
+ throw ApiError.badRequest("Missing gameId");
98181
+ }
98182
+ if (!isValidUUID(gameId)) {
98183
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98184
+ }
98185
+ return ctx.services.timeback.getRemovedIntegrations(gameId, ctx.user);
98186
+ });
98187
+ createIntegration = requireDeveloper(async (ctx) => {
98188
+ const gameId = ctx.params.gameId;
98189
+ if (!gameId) {
98190
+ throw ApiError.badRequest("Missing gameId");
98191
+ }
98192
+ if (!isValidUUID(gameId)) {
98193
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98194
+ }
98195
+ const body2 = await parseRequestBody(ctx.request, CreateGameTimebackIntegrationRequestSchema);
98196
+ return ctx.services.timeback.createIntegration(gameId, ctx.user, body2);
98197
+ });
97642
98198
  updateIntegration = requireDeveloper(async (ctx) => {
97643
98199
  const { gameId, courseId } = ctx.params;
97644
98200
  if (!gameId || !courseId) {
@@ -97650,6 +98206,26 @@ var init_timeback_controller = __esm(() => {
97650
98206
  const body2 = await parseRequestBody(ctx.request, UpdateGameTimebackIntegrationRequestSchema);
97651
98207
  return ctx.services.timeback.updateIntegration(gameId, courseId, ctx.user, body2);
97652
98208
  });
98209
+ deactivateCourse = requireDeveloper(async (ctx) => {
98210
+ const { gameId, courseId } = ctx.params;
98211
+ if (!gameId || !courseId) {
98212
+ throw ApiError.badRequest("Missing gameId or courseId parameter");
98213
+ }
98214
+ if (!isValidUUID(gameId)) {
98215
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98216
+ }
98217
+ return ctx.services.timeback.deactivateCourse(gameId, courseId, ctx.user);
98218
+ });
98219
+ reactivateCourse = requireDeveloper(async (ctx) => {
98220
+ const { gameId, courseId } = ctx.params;
98221
+ if (!gameId || !courseId) {
98222
+ throw ApiError.badRequest("Missing gameId or courseId parameter");
98223
+ }
98224
+ if (!isValidUUID(gameId)) {
98225
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98226
+ }
98227
+ return ctx.services.timeback.reactivateCourse(gameId, courseId, ctx.user);
98228
+ });
97653
98229
  getIntegrationConfig = requireGameManagementAccess(async (ctx) => {
97654
98230
  const { gameId, courseId } = ctx.params;
97655
98231
  if (!gameId || !courseId) {
@@ -97799,11 +98375,11 @@ var init_timeback_controller = __esm(() => {
97799
98375
  let subject;
97800
98376
  if (gradeParam !== null && subjectParam !== null) {
97801
98377
  const parsedGrade = parseInt(gradeParam, 10);
97802
- if (!isTimebackGrade(parsedGrade)) {
98378
+ if (!isTimebackGrade2(parsedGrade)) {
97803
98379
  throw ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
97804
98380
  }
97805
- if (!isTimebackSubject(subjectParam)) {
97806
- throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
98381
+ if (!isTimebackSubject2(subjectParam)) {
98382
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
97807
98383
  }
97808
98384
  grade = parsedGrade;
97809
98385
  subject = subjectParam;
@@ -97839,11 +98415,11 @@ var init_timeback_controller = __esm(() => {
97839
98415
  let subject;
97840
98416
  if (gradeParam !== null && subjectParam !== null) {
97841
98417
  const parsedGrade = parseInt(gradeParam, 10);
97842
- if (!isTimebackGrade(parsedGrade)) {
98418
+ if (!isTimebackGrade2(parsedGrade)) {
97843
98419
  throw ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
97844
98420
  }
97845
- if (!isTimebackSubject(subjectParam)) {
97846
- throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
98421
+ if (!isTimebackSubject2(subjectParam)) {
98422
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
97847
98423
  }
97848
98424
  grade = parsedGrade;
97849
98425
  subject = subjectParam;
@@ -97873,8 +98449,8 @@ var init_timeback_controller = __esm(() => {
97873
98449
  if (!subjectParam) {
97874
98450
  throw ApiError.badRequest("Missing required subject query parameter");
97875
98451
  }
97876
- if (!isTimebackSubject(subjectParam)) {
97877
- throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
98452
+ if (!isTimebackSubject2(subjectParam)) {
98453
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
97878
98454
  }
97879
98455
  return ctx.services.timeback.getStudentHighestGradeMastered(timebackId, ctx.user, {
97880
98456
  gameId,
@@ -98185,7 +98761,11 @@ var init_timeback_controller = __esm(() => {
98185
98761
  getUserById,
98186
98762
  setupIntegration,
98187
98763
  getIntegrations,
98764
+ getRemovedIntegrations,
98765
+ createIntegration,
98188
98766
  updateIntegration,
98767
+ deactivateCourse,
98768
+ reactivateCourse,
98189
98769
  getIntegrationConfig,
98190
98770
  verifyIntegration,
98191
98771
  getConfig,
@@ -99182,12 +99762,12 @@ var init_timeback7 = __esm(() => {
99182
99762
  }
99183
99763
  if (gradeParam !== null && subjectParam !== null) {
99184
99764
  const grade = parseInt(gradeParam, 10);
99185
- if (!Number.isFinite(grade) || !isTimebackGrade(grade)) {
99765
+ if (!Number.isFinite(grade) || !isTimebackGrade2(grade)) {
99186
99766
  const error2 = ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
99187
99767
  return c2.json(createErrorResponse(error2), error2.status);
99188
99768
  }
99189
- if (!isTimebackSubject(subjectParam)) {
99190
- const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
99769
+ if (!isTimebackSubject2(subjectParam)) {
99770
+ const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
99191
99771
  return c2.json(createErrorResponse(error2), error2.status);
99192
99772
  }
99193
99773
  enrollments = enrollments.filter((e) => e.grade === grade && e.subject === subjectParam);
@@ -99240,12 +99820,12 @@ var init_timeback7 = __esm(() => {
99240
99820
  }
99241
99821
  if (gradeParam !== null && subjectParam !== null) {
99242
99822
  const grade = parseInt(gradeParam, 10);
99243
- if (!Number.isFinite(grade) || !isTimebackGrade(grade)) {
99823
+ if (!Number.isFinite(grade) || !isTimebackGrade2(grade)) {
99244
99824
  const error2 = ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
99245
99825
  return c2.json(createErrorResponse(error2), error2.status);
99246
99826
  }
99247
- if (!isTimebackSubject(subjectParam)) {
99248
- const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
99827
+ if (!isTimebackSubject2(subjectParam)) {
99828
+ const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
99249
99829
  return c2.json(createErrorResponse(error2), error2.status);
99250
99830
  }
99251
99831
  enrollments = enrollments.filter((e) => e.grade === grade && e.subject === subjectParam);
@@ -99294,8 +99874,8 @@ var init_timeback7 = __esm(() => {
99294
99874
  const error2 = ApiError.badRequest("Missing required gameId query parameter");
99295
99875
  return c2.json(createErrorResponse(error2), error2.status);
99296
99876
  }
99297
- if (!isTimebackSubject(subject)) {
99298
- const error2 = ApiError.badRequest(`Invalid subject: ${subject}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
99877
+ if (!isTimebackSubject2(subject)) {
99878
+ const error2 = ApiError.badRequest(`Invalid subject: ${subject}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
99299
99879
  return c2.json(createErrorResponse(error2), error2.status);
99300
99880
  }
99301
99881
  const db2 = c2.get("db");