@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/server.js CHANGED
@@ -1077,7 +1077,7 @@ var package_default;
1077
1077
  var init_package = __esm(() => {
1078
1078
  package_default = {
1079
1079
  name: "@playcademy/sandbox",
1080
- version: "0.5.2-beta.2",
1080
+ version: "0.5.2-beta.3",
1081
1081
  description: "Local development server for Playcademy game development",
1082
1082
  type: "module",
1083
1083
  exports: {
@@ -11322,23 +11322,31 @@ var init_table6 = __esm(() => {
11322
11322
  });
11323
11323
 
11324
11324
  // ../data/src/domains/timeback/table.ts
11325
- var gameTimebackIntegrations, gameTimebackAssessmentTests, gameTimebackMetricDiscrepancyVerifications;
11325
+ var gameTimebackIntegrationStatusEnum, gameTimebackIntegrations, gameTimebackAssessmentTests, gameTimebackMetricDiscrepancyVerifications;
11326
11326
  var init_table7 = __esm(() => {
11327
+ init_drizzle_orm();
11327
11328
  init_pg_core();
11328
11329
  init_table5();
11329
11330
  init_table3();
11331
+ gameTimebackIntegrationStatusEnum = pgEnum("game_timeback_integration_status", [
11332
+ "active",
11333
+ "deactivated"
11334
+ ]);
11330
11335
  gameTimebackIntegrations = pgTable("game_timeback_integrations", {
11331
11336
  id: uuid("id").primaryKey().defaultRandom(),
11332
11337
  gameId: uuid("game_id").notNull().references(() => games.id, { onDelete: "cascade" }),
11333
11338
  courseId: text("course_id").notNull(),
11334
11339
  grade: integer("grade").notNull(),
11335
11340
  subject: text("subject").notNull(),
11341
+ status: gameTimebackIntegrationStatusEnum("status"),
11336
11342
  totalXp: integer("total_xp"),
11337
11343
  lastVerifiedAt: timestamp("last_verified_at", { withTimezone: true }),
11344
+ deactivatedAt: timestamp("deactivated_at", { withTimezone: true }),
11345
+ reactivatedAt: timestamp("reactivated_at", { withTimezone: true }),
11338
11346
  createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
11339
11347
  updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
11340
11348
  }, (table3) => [
11341
- uniqueIndex("game_timeback_integrations_game_grade_subject_idx").on(table3.gameId, table3.grade, table3.subject)
11349
+ uniqueIndex("game_timeback_integrations_game_grade_subject_idx").on(table3.gameId, table3.grade, table3.subject).where(sql`${table3.status} IS DISTINCT FROM 'deactivated'`)
11342
11350
  ]);
11343
11351
  gameTimebackAssessmentTests = pgTable("game_timeback_assessment_tests", {
11344
11352
  id: uuid("id").primaryKey().defaultRandom(),
@@ -11381,6 +11389,7 @@ __export(exports_tables_index, {
11381
11389
  gameTypeEnum: () => gameTypeEnum,
11382
11390
  gameTimebackMetricDiscrepancyVerifications: () => gameTimebackMetricDiscrepancyVerifications,
11383
11391
  gameTimebackIntegrations: () => gameTimebackIntegrations,
11392
+ gameTimebackIntegrationStatusEnum: () => gameTimebackIntegrationStatusEnum,
11384
11393
  gameTimebackAssessmentTests: () => gameTimebackAssessmentTests,
11385
11394
  gameScoresRelations: () => gameScoresRelations,
11386
11395
  gameScores: () => gameScores,
@@ -24672,6 +24681,7 @@ var init_helpers = __esm(() => {
24672
24681
 
24673
24682
  // ../cloudflare/src/playcademy/provider/provider.ts
24674
24683
  var init_provider = __esm(() => {
24684
+ init_src();
24675
24685
  init_src();
24676
24686
  init_core();
24677
24687
  init_constants2();
@@ -27767,6 +27777,20 @@ var init_game_member_service = __esm(() => {
27767
27777
  init_spans();
27768
27778
  init_errors();
27769
27779
  });
27780
+ // ../data/src/domains/timeback/helpers.ts
27781
+ function isActiveGameTimebackIntegrationStatus(statusColumn = gameTimebackIntegrations.status) {
27782
+ return sql`${statusColumn} IS DISTINCT FROM ${DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS}`;
27783
+ }
27784
+ var ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS = "active", DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS = "deactivated";
27785
+ var init_helpers2 = __esm(() => {
27786
+ init_drizzle_orm();
27787
+ init_table7();
27788
+ });
27789
+
27790
+ // ../data/src/helpers.index.ts
27791
+ var init_helpers_index = __esm(() => {
27792
+ init_helpers2();
27793
+ });
27770
27794
 
27771
27795
  // ../utils/src/fns.ts
27772
27796
  function sleep(ms) {
@@ -27776,15 +27800,584 @@ function sleep(ms) {
27776
27800
  return new Promise((resolve) => setTimeout(resolve, ms));
27777
27801
  }
27778
27802
 
27803
+ // ../timeback/dist/types.js
27804
+ function isObject(value) {
27805
+ return typeof value === "object" && value !== null;
27806
+ }
27807
+ function isCourseMetadata(value) {
27808
+ return isObject(value);
27809
+ }
27810
+ function isResourceMetadata(value) {
27811
+ return isObject(value);
27812
+ }
27813
+ function isPlaycademyResourceMetadata(value) {
27814
+ if (!isObject(value)) {
27815
+ return false;
27816
+ }
27817
+ if (!("mastery" in value) || value.mastery === undefined) {
27818
+ return true;
27819
+ }
27820
+ return isObject(value.mastery);
27821
+ }
27822
+ function isTimebackSubject(value) {
27823
+ return typeof value === "string" && SUBJECT_VALUES.includes(value);
27824
+ }
27825
+ function isTimebackGrade(value) {
27826
+ return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
27827
+ }
27828
+ 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;
27829
+ var init_types2 = __esm(() => {
27830
+ init_src();
27831
+ init_constants3 = __esm2(() => {
27832
+ TIMEBACK_API_URLS = {
27833
+ production: "https://api.alpha-1edtech.ai",
27834
+ staging: "https://api.staging.alpha-1edtech.com"
27835
+ };
27836
+ TIMEBACK_AUTH_URLS = {
27837
+ production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
27838
+ staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
27839
+ };
27840
+ CALIPER_API_URLS = {
27841
+ production: "https://caliper.alpha-1edtech.ai",
27842
+ staging: "https://caliper-staging.alpha-1edtech.com"
27843
+ };
27844
+ ONEROSTER_ENDPOINTS = {
27845
+ organizations: "/ims/oneroster/rostering/v1p2/orgs",
27846
+ courses: "/ims/oneroster/rostering/v1p2/courses",
27847
+ courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
27848
+ resources: "/ims/oneroster/resources/v1p2/resources",
27849
+ componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
27850
+ classes: "/ims/oneroster/rostering/v1p2/classes",
27851
+ enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
27852
+ assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
27853
+ assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
27854
+ users: "/ims/oneroster/rostering/v1p2/users"
27855
+ };
27856
+ QTI_ENDPOINTS = {
27857
+ assessmentTests: "/assessment-tests",
27858
+ assessmentItems: "/assessment-items"
27859
+ };
27860
+ CALIPER_ENDPOINTS = {
27861
+ event: "/caliper/event",
27862
+ events: "/caliper/events",
27863
+ validate: "/caliper/event/validate"
27864
+ };
27865
+ CALIPER_CONSTANTS = {
27866
+ context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
27867
+ profile: "TimebackProfile",
27868
+ dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
27869
+ };
27870
+ TIMEBACK_EVENT_TYPES = {
27871
+ activityEvent: "ActivityEvent",
27872
+ timeSpentEvent: "TimeSpentEvent"
27873
+ };
27874
+ TIMEBACK_ACTIONS = {
27875
+ completed: "Completed",
27876
+ spentTime: "SpentTime"
27877
+ };
27878
+ TIMEBACK_TYPES = {
27879
+ user: "TimebackUser",
27880
+ activityContext: "TimebackActivityContext",
27881
+ activityMetricsCollection: "TimebackActivityMetricsCollection",
27882
+ timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
27883
+ };
27884
+ ACTIVITY_METRIC_TYPES = {
27885
+ totalQuestions: "totalQuestions",
27886
+ correctQuestions: "correctQuestions",
27887
+ xpEarned: "xpEarned",
27888
+ masteredUnits: "masteredUnits"
27889
+ };
27890
+ TIME_METRIC_TYPES = {
27891
+ active: "active",
27892
+ inactive: "inactive",
27893
+ waste: "waste",
27894
+ unknown: "unknown",
27895
+ antiPattern: "anti-pattern"
27896
+ };
27897
+ TIMEBACK_SUBJECTS = [
27898
+ "Math",
27899
+ "FastMath",
27900
+ "Science",
27901
+ "Social Studies",
27902
+ "Language",
27903
+ "Reading",
27904
+ "Vocabulary",
27905
+ "Writing"
27906
+ ];
27907
+ TIMEBACK_GRADE_LEVELS = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
27908
+ TIMEBACK_GRADE_LEVEL_LABELS = {
27909
+ "-1": "pre-k",
27910
+ "0": "kindergarten",
27911
+ "1": "1st grade",
27912
+ "2": "2nd grade",
27913
+ "3": "3rd grade",
27914
+ "4": "4th grade",
27915
+ "5": "5th grade",
27916
+ "6": "6th grade",
27917
+ "7": "7th grade",
27918
+ "8": "8th grade",
27919
+ "9": "9th grade",
27920
+ "10": "10th grade",
27921
+ "11": "11th grade",
27922
+ "12": "12th grade",
27923
+ "13": "AP"
27924
+ };
27925
+ CALIPER_SUBJECTS = {
27926
+ Reading: "Reading",
27927
+ Language: "Language",
27928
+ Vocabulary: "Vocabulary",
27929
+ SocialStudies: "Social Studies",
27930
+ Writing: "Writing",
27931
+ Science: "Science",
27932
+ FastMath: "FastMath",
27933
+ Math: "Math",
27934
+ None: "None"
27935
+ };
27936
+ ONEROSTER_STATUS = {
27937
+ active: "active",
27938
+ toBeDeleted: "tobedeleted"
27939
+ };
27940
+ SCORE_STATUS = {
27941
+ exempt: "exempt",
27942
+ fullyGraded: "fully graded",
27943
+ notSubmitted: "not submitted",
27944
+ partiallyGraded: "partially graded",
27945
+ submitted: "submitted"
27946
+ };
27947
+ ENV_VARS = {
27948
+ clientId: "TIMEBACK_CLIENT_ID",
27949
+ clientSecret: "TIMEBACK_CLIENT_SECRET",
27950
+ baseUrl: "TIMEBACK_BASE_URL",
27951
+ environment: "TIMEBACK_ENVIRONMENT",
27952
+ vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
27953
+ launchBaseUrl: "GAME_URL",
27954
+ qtiClientId: "QTI_CLIENT_ID",
27955
+ qtiClientSecret: "QTI_CLIENT_SECRET",
27956
+ qtiAuthUrl: "QTI_AUTH_URL"
27957
+ };
27958
+ HTTP_DEFAULTS = {
27959
+ timeout: 30000,
27960
+ retries: 3,
27961
+ retryBackoffBase: 2
27962
+ };
27963
+ AUTH_DEFAULTS = {
27964
+ tokenCacheDuration: 50000
27965
+ };
27966
+ CACHE_DEFAULTS = {
27967
+ defaultTTL: 10 * 60 * 1000,
27968
+ defaultMaxSize: 500,
27969
+ defaultName: "TimebackCache",
27970
+ studentTTL: 10 * 60 * 1000,
27971
+ studentMaxSize: 500,
27972
+ assessmentTTL: 30 * 60 * 1000,
27973
+ assessmentMaxSize: 200,
27974
+ enrollmentTTL: 5 * 1000,
27975
+ enrollmentMaxSize: 100
27976
+ };
27977
+ CONFIG_DEFAULTS = {
27978
+ fileNames: ["timeback.config.js", "timeback.config.json"]
27979
+ };
27980
+ PLAYCADEMY_DEFAULTS = {
27981
+ organization: TIMEBACK_ORG_SOURCED_ID,
27982
+ launchBaseUrls: PLAYCADEMY_BASE_URLS
27983
+ };
27984
+ RESOURCE_DEFAULTS = {
27985
+ organization: {
27986
+ name: TIMEBACK_ORG_NAME,
27987
+ type: TIMEBACK_ORG_TYPE
27988
+ },
27989
+ course: {
27990
+ gradingScheme: TIMEBACK_COURSE_DEFAULTS.gradingScheme,
27991
+ level: TIMEBACK_COURSE_DEFAULTS.level,
27992
+ metadata: {
27993
+ goals: TIMEBACK_COURSE_DEFAULTS.goals,
27994
+ metrics: TIMEBACK_COURSE_DEFAULTS.metrics
27995
+ }
27996
+ },
27997
+ component: TIMEBACK_COMPONENT_DEFAULTS,
27998
+ resource: TIMEBACK_RESOURCE_DEFAULTS,
27999
+ componentResource: TIMEBACK_COMPONENT_RESOURCE_DEFAULTS
28000
+ };
28001
+ HTTP_STATUS = {
28002
+ CLIENT_ERROR_MIN: 400,
28003
+ CLIENT_ERROR_MAX: 500,
28004
+ SERVER_ERROR_MIN: 500
28005
+ };
28006
+ ERROR_NAMES = {
28007
+ timebackAuth: "TimebackAuthError",
28008
+ timebackApi: "TimebackApiError",
28009
+ timebackConfig: "TimebackConfigError",
28010
+ timebackSdk: "TimebackSDKError"
28011
+ };
28012
+ });
28013
+ init_constants3();
28014
+ SUBJECT_VALUES = TIMEBACK_SUBJECTS;
28015
+ GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
28016
+ });
28017
+
28018
+ // ../utils/src/string.ts
28019
+ function kebabToTitleCase(kebabStr) {
28020
+ return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
28021
+ }
28022
+
28023
+ // ../api-core/src/utils/timeback.util.ts
28024
+ function isRecord2(value) {
28025
+ return typeof value === "object" && value !== null;
28026
+ }
28027
+ function filterEnrollmentsByGame(enrollments, gameId) {
28028
+ return enrollments.filter((enrollment) => enrollment.gameId === gameId).map(({ gameId: _, ...enrollment }) => enrollment);
28029
+ }
28030
+ function mapEnrollmentsToUserEnrollments(enrollments, integrations) {
28031
+ const enrollmentByCourse = new Map(enrollments.map((enrollment) => [enrollment.courseId, enrollment]));
28032
+ const courseToSchool = new Map(enrollments.filter((enrollment) => enrollment.school?.id).map((enrollment) => [enrollment.courseId, enrollment.school.id]));
28033
+ return integrations.map((integration) => {
28034
+ const enrollment = enrollmentByCourse.get(integration.courseId);
28035
+ return {
28036
+ gameId: integration.gameId,
28037
+ grade: integration.grade,
28038
+ subject: integration.subject,
28039
+ courseId: integration.courseId,
28040
+ orgId: courseToSchool.get(integration.courseId),
28041
+ ...enrollment ? { id: enrollment.sourcedId } : {}
28042
+ };
28043
+ });
28044
+ }
28045
+ function buildGameTimebackSummaries(integrations) {
28046
+ const summaries = {};
28047
+ for (const integration of integrations) {
28048
+ const summary = summaries[integration.gameId] ?? {
28049
+ subject: null,
28050
+ hasActiveIntegration: false,
28051
+ hasRemovedIntegration: false
28052
+ };
28053
+ const isRemoved = integration.status === DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS;
28054
+ if (isRemoved) {
28055
+ summary.hasRemovedIntegration = true;
28056
+ } else {
28057
+ summary.hasActiveIntegration = true;
28058
+ summary.subject ??= integration.subject;
28059
+ }
28060
+ summaries[integration.gameId] = summary;
28061
+ }
28062
+ return summaries;
28063
+ }
28064
+ function getStringValue(value) {
28065
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
28066
+ }
28067
+ function parseSourcedIdFromUrl(url) {
28068
+ if (!url) {
28069
+ return;
28070
+ }
28071
+ const trimmed = url.trim().replace(/\/$/, "");
28072
+ if (!trimmed) {
28073
+ return;
28074
+ }
28075
+ const segments = trimmed.split("/");
28076
+ const lastSegment = segments.at(-1);
28077
+ return lastSegment ? decodeURIComponent(lastSegment) : undefined;
28078
+ }
28079
+ function getGeneratedMetricValue(event, type) {
28080
+ const items = event.generated?.items;
28081
+ if (!Array.isArray(items)) {
28082
+ return;
28083
+ }
28084
+ const metric = items.find((item) => item?.type === type);
28085
+ if (!metric) {
28086
+ return;
28087
+ }
28088
+ const value = typeof metric.value === "number" ? metric.value : Number(metric.value);
28089
+ return Number.isFinite(value) ? value : undefined;
28090
+ }
28091
+ function getMergedCaliperExtensions(event) {
28092
+ const objectActivityExtensions = isRecord2(event.object.activity?.extensions) ? event.object.activity.extensions : undefined;
28093
+ const generatedExtensions = isRecord2(event.generated?.extensions) ? event.generated.extensions : undefined;
28094
+ const eventExtensions = isRecord2(event.extensions) ? event.extensions : undefined;
28095
+ return {
28096
+ ...objectActivityExtensions,
28097
+ ...generatedExtensions,
28098
+ ...eventExtensions
28099
+ };
28100
+ }
28101
+ function getPlaycademyMetadata(event) {
28102
+ const extensions = getMergedCaliperExtensions(event);
28103
+ return isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
28104
+ }
28105
+ function getActivityId(event, playcademy) {
28106
+ const metadataActivityId = getStringValue(playcademy?.activityId);
28107
+ if (metadataActivityId) {
28108
+ return metadataActivityId;
28109
+ }
28110
+ const activityId = getStringValue(event.object.activity?.id);
28111
+ if (activityId) {
28112
+ return activityId;
28113
+ }
28114
+ const objectId = getStringValue(event.object.id);
28115
+ if (!objectId) {
28116
+ return;
28117
+ }
28118
+ const trimmed = objectId.replace(/\/$/, "");
28119
+ const segments = trimmed.split("/");
28120
+ const activityIndex = segments.lastIndexOf("activities");
28121
+ if (activityIndex !== -1 && segments.length >= activityIndex + 3) {
28122
+ const candidate = segments[activityIndex + 2];
28123
+ return candidate ? decodeURIComponent(candidate) : undefined;
28124
+ }
28125
+ return;
28126
+ }
28127
+ function buildResourceMetadata({
28128
+ baseMetadata,
28129
+ subject,
28130
+ grade,
28131
+ totalXp,
28132
+ masterableUnits
28133
+ }) {
28134
+ const normalizedBaseMetadata = isResourceMetadata(baseMetadata) ? baseMetadata : undefined;
28135
+ const metadata2 = {
28136
+ ...normalizedBaseMetadata
28137
+ };
28138
+ metadata2.subject = subject;
28139
+ metadata2.grades = [grade];
28140
+ metadata2.xp = totalXp;
28141
+ if (masterableUnits !== undefined && masterableUnits !== null) {
28142
+ const existingPlaycademy = isPlaycademyResourceMetadata(metadata2.playcademy) ? metadata2.playcademy : undefined;
28143
+ metadata2.playcademy = {
28144
+ ...existingPlaycademy,
28145
+ mastery: {
28146
+ ...existingPlaycademy?.mastery,
28147
+ masterableUnits
28148
+ }
28149
+ };
28150
+ }
28151
+ return metadata2;
28152
+ }
28153
+ function getDurationSecondsFromExtensions(event) {
28154
+ const extensions = getMergedCaliperExtensions(event);
28155
+ const playcademy = isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
28156
+ const rawValue = extensions.durationSeconds ?? playcademy?.durationSeconds;
28157
+ const value = typeof rawValue === "number" ? rawValue : Number(rawValue);
28158
+ return Number.isFinite(value) ? value : undefined;
28159
+ }
28160
+ function getCanonicalRunId(session2) {
28161
+ const sessionId = getStringValue(session2?.id);
28162
+ if (!sessionId) {
28163
+ return;
28164
+ }
28165
+ return sessionId.replace(/^urn:uuid:/, "");
28166
+ }
28167
+ function getResumeId(event) {
28168
+ const playcademy = getPlaycademyMetadata(event);
28169
+ return getStringValue(playcademy?.resumeId);
28170
+ }
28171
+ function isCaliperRemediationOrCompletionEvent(event) {
28172
+ const playcademy = getPlaycademyMetadata(event);
28173
+ return REMEDIATION_OR_COMPLETION_EVENT_KINDS.has(getStringValue(playcademy?.eventKind) || "");
28174
+ }
28175
+ function groupCaliperEventsByRun(events) {
28176
+ const groups = new Map;
28177
+ for (const event of events) {
28178
+ const objectId = getStringValue(event.object.id) || "unknown-activity";
28179
+ const groupKey = `${objectId}::${getStringValue(event.session?.id) || event.externalId}`;
28180
+ const existing = groups.get(groupKey);
28181
+ if (existing) {
28182
+ existing.push(event);
28183
+ } else {
28184
+ groups.set(groupKey, [event]);
28185
+ }
28186
+ }
28187
+ return groups;
28188
+ }
28189
+ function findCaliperEventGroupContainingExternalId(events, externalId) {
28190
+ const targetExternalId = externalId.trim();
28191
+ if (!targetExternalId) {
28192
+ return;
28193
+ }
28194
+ return [...groupCaliperEventsByRun(events).values()].find((group) => group.some((event) => event.externalId === targetExternalId));
28195
+ }
28196
+ function mapCaliperEventGroupToActivity(events, relevantCourseIds) {
28197
+ if (events.length === 0) {
28198
+ return null;
28199
+ }
28200
+ const sortedEvents = events.toSorted((a, b) => a.eventTime.localeCompare(b.eventTime));
28201
+ const activityEvent = [...sortedEvents].toReversed().find((event) => event.type === "ActivityEvent");
28202
+ const contextSource = activityEvent || sortedEvents.at(-1);
28203
+ if (!contextSource) {
28204
+ return null;
28205
+ }
28206
+ const ctx = parseCaliperEventContext(contextSource, relevantCourseIds);
28207
+ if (!ctx) {
28208
+ return null;
28209
+ }
28210
+ const score = activityEvent !== undefined ? (() => {
28211
+ const totalQuestions = getGeneratedMetricValue(activityEvent, "totalQuestions");
28212
+ const correctQuestions = getGeneratedMetricValue(activityEvent, "correctQuestions");
28213
+ if (totalQuestions === undefined || correctQuestions === undefined || totalQuestions <= 0) {
28214
+ return;
28215
+ }
28216
+ return correctQuestions / totalQuestions * 100;
28217
+ })() : undefined;
28218
+ const xpEarned = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "xpEarned") : undefined;
28219
+ const masteredUnits = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "masteredUnits") : undefined;
28220
+ const timeSpentEvents = sortedEvents.filter((event) => event.type === "TimeSpentEvent");
28221
+ let totalActiveTimeSeconds;
28222
+ if (timeSpentEvents.length > 0) {
28223
+ totalActiveTimeSeconds = timeSpentEvents.reduce((sum, event) => sum + (getGeneratedMetricValue(event, "active") ?? 0), 0);
28224
+ } else if (activityEvent !== undefined) {
28225
+ totalActiveTimeSeconds = getDurationSecondsFromExtensions(activityEvent);
28226
+ }
28227
+ const fallbackActivityId = getActivityId(contextSource, getPlaycademyMetadata(contextSource));
28228
+ const occurredAt = getStringValue(activityEvent?.eventTime) || getStringValue(sortedEvents.at(-1)?.eventTime);
28229
+ const runId = getCanonicalRunId(contextSource.session);
28230
+ const resumeIds = new Set(sortedEvents.map((event) => getResumeId(event)).filter((resumeId) => resumeId !== undefined));
28231
+ const sessionCount = resumeIds.size > 0 ? resumeIds.size : 1;
28232
+ const kind = activityEvent !== undefined ? "activity" : "activity-in-progress";
28233
+ if (!occurredAt) {
28234
+ return null;
28235
+ }
28236
+ return {
28237
+ id: activityEvent?.externalId || sortedEvents.at(-1)?.externalId || events[0].externalId,
28238
+ kind,
28239
+ occurredAt,
28240
+ courseId: ctx.courseId,
28241
+ title: getStringValue(activityEvent?.object.activity?.name) || ctx.titleFromEvent || (fallbackActivityId ? kebabToTitleCase(fallbackActivityId) : "Activity completed"),
28242
+ ...ctx.activityId ? { activityId: ctx.activityId } : {},
28243
+ ...ctx.appName ? { appName: ctx.appName } : {},
28244
+ ...score !== undefined ? { score } : {},
28245
+ ...xpEarned !== undefined ? { xpDelta: xpEarned } : {},
28246
+ ...masteredUnits !== undefined ? { masteredUnitsDelta: masteredUnits } : {},
28247
+ ...totalActiveTimeSeconds !== undefined ? { timeDeltaSeconds: totalActiveTimeSeconds } : {},
28248
+ ...runId ? { runId } : {},
28249
+ ...sessionCount > 0 ? { sessionCount } : {}
28250
+ };
28251
+ }
28252
+ function parseCaliperEventContext(event, relevantCourseIds) {
28253
+ const playcademy = getPlaycademyMetadata(event);
28254
+ const courseId = getStringValue(playcademy?.courseId) || parseSourcedIdFromUrl(event.object.course?.id);
28255
+ if (!courseId || !relevantCourseIds.has(courseId)) {
28256
+ return null;
28257
+ }
28258
+ const occurredAt = getStringValue(event.eventTime);
28259
+ if (!occurredAt) {
28260
+ return null;
28261
+ }
28262
+ return {
28263
+ courseId,
28264
+ occurredAt,
28265
+ eventKind: getStringValue(playcademy?.eventKind),
28266
+ source: getStringValue(playcademy?.source),
28267
+ reason: getStringValue(playcademy?.reason),
28268
+ titleFromEvent: getStringValue(event.object.activity?.name),
28269
+ appName: getStringValue(event.object.app?.name),
28270
+ activityId: getActivityId(event, playcademy)
28271
+ };
28272
+ }
28273
+ function mapTimeSpentRemediation(event, ctx) {
28274
+ if (ctx.eventKind !== "remediation-time") {
28275
+ return null;
28276
+ }
28277
+ return {
28278
+ id: event.externalId,
28279
+ kind: "remediation-time",
28280
+ occurredAt: ctx.occurredAt,
28281
+ courseId: ctx.courseId,
28282
+ title: "Time Adjustment",
28283
+ activityId: ctx.activityId,
28284
+ appName: ctx.appName,
28285
+ reason: ctx.reason,
28286
+ timeDeltaSeconds: getGeneratedMetricValue(event, "active")
28287
+ };
28288
+ }
28289
+ function mapActivityRemediation(event, ctx) {
28290
+ if (ctx.eventKind === "remediation-xp") {
28291
+ return {
28292
+ id: event.externalId,
28293
+ kind: "remediation-xp",
28294
+ occurredAt: ctx.occurredAt,
28295
+ courseId: ctx.courseId,
28296
+ title: "XP Adjustment",
28297
+ activityId: ctx.activityId,
28298
+ appName: ctx.appName,
28299
+ reason: ctx.reason,
28300
+ xpDelta: getGeneratedMetricValue(event, "xpEarned"),
28301
+ masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
28302
+ };
28303
+ }
28304
+ if (ctx.eventKind === "remediation-mastery") {
28305
+ return {
28306
+ id: event.externalId,
28307
+ kind: "remediation-mastery",
28308
+ occurredAt: ctx.occurredAt,
28309
+ courseId: ctx.courseId,
28310
+ title: "Mastery Adjustment",
28311
+ activityId: ctx.activityId,
28312
+ appName: ctx.appName,
28313
+ reason: ctx.reason,
28314
+ xpDelta: getGeneratedMetricValue(event, "xpEarned"),
28315
+ masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
28316
+ };
28317
+ }
28318
+ if (ctx.eventKind === "course-completed") {
28319
+ return {
28320
+ id: event.externalId,
28321
+ kind: "course-completed",
28322
+ occurredAt: ctx.occurredAt,
28323
+ courseId: ctx.courseId,
28324
+ title: ctx.source === "admin" ? "Course marked complete" : "Course completed",
28325
+ activityId: ctx.activityId,
28326
+ appName: ctx.appName,
28327
+ reason: ctx.reason
28328
+ };
28329
+ }
28330
+ if (ctx.eventKind === "course-resumed") {
28331
+ return {
28332
+ id: event.externalId,
28333
+ kind: "course-resumed",
28334
+ occurredAt: ctx.occurredAt,
28335
+ courseId: ctx.courseId,
28336
+ title: "Course resumed",
28337
+ activityId: ctx.activityId,
28338
+ appName: ctx.appName,
28339
+ reason: ctx.reason
28340
+ };
28341
+ }
28342
+ return null;
28343
+ }
28344
+ function mapCaliperEventToRemediationActivity(event, relevantCourseIds) {
28345
+ const ctx = parseCaliperEventContext(event, relevantCourseIds);
28346
+ if (!ctx) {
28347
+ return null;
28348
+ }
28349
+ if (event.type === "TimeSpentEvent") {
28350
+ return mapTimeSpentRemediation(event, ctx);
28351
+ }
28352
+ if (event.type === "ActivityEvent") {
28353
+ return mapActivityRemediation(event, ctx);
28354
+ }
28355
+ return null;
28356
+ }
28357
+ var REMEDIATION_OR_COMPLETION_EVENT_KINDS;
28358
+ var init_timeback_util = __esm(() => {
28359
+ init_helpers_index();
28360
+ init_types2();
28361
+ REMEDIATION_OR_COMPLETION_EVENT_KINDS = new Set([
28362
+ "remediation-xp",
28363
+ "remediation-time",
28364
+ "remediation-mastery",
28365
+ "course-completed",
28366
+ "course-resumed"
28367
+ ]);
28368
+ });
28369
+
27779
28370
  // ../api-core/src/services/game.service.ts
27780
28371
  var inFlightManifestFetches, GameService;
27781
28372
  var init_game_service = __esm(() => {
27782
28373
  init_drizzle_orm();
27783
28374
  init_src();
28375
+ init_helpers_index();
27784
28376
  init_tables_index();
27785
28377
  init_spans();
27786
28378
  init_errors();
27787
28379
  init_deployment_util();
28380
+ init_timeback_util();
27788
28381
  inFlightManifestFetches = new Map;
27789
28382
  GameService = class GameService {
27790
28383
  deps;
@@ -27928,6 +28521,7 @@ var init_game_service = __esm(() => {
27928
28521
  const db2 = this.deps.db;
27929
28522
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
27930
28523
  columns: { gameId: true, subject: true },
28524
+ where: isActiveGameTimebackIntegrationStatus(),
27931
28525
  orderBy: [asc(gameTimebackIntegrations.createdAt)]
27932
28526
  });
27933
28527
  const subjectMap = {};
@@ -27938,6 +28532,26 @@ var init_game_service = __esm(() => {
27938
28532
  }
27939
28533
  return subjectMap;
27940
28534
  }
28535
+ async getTimebackSummaries(user) {
28536
+ const db2 = this.deps.db;
28537
+ const canSeeAllGames = user.role === "admin" || user.role === "teacher";
28538
+ let accessibleGameIds = null;
28539
+ if (!canSeeAllGames) {
28540
+ const accessibleGames = await this.listAccessible(user);
28541
+ accessibleGameIds = new Set(accessibleGames.map((game2) => game2.id));
28542
+ }
28543
+ if (accessibleGameIds?.size === 0) {
28544
+ return {};
28545
+ }
28546
+ const integrations = await db2.query.gameTimebackIntegrations.findMany({
28547
+ columns: { gameId: true, subject: true, status: true },
28548
+ ...accessibleGameIds && {
28549
+ where: inArray(gameTimebackIntegrations.gameId, [...accessibleGameIds])
28550
+ },
28551
+ orderBy: [asc(gameTimebackIntegrations.createdAt)]
28552
+ });
28553
+ return buildGameTimebackSummaries(integrations);
28554
+ }
27941
28555
  async getById(gameId, caller) {
27942
28556
  const db2 = this.deps.db;
27943
28557
  const game2 = await db2.query.games.findFirst({
@@ -28575,7 +29189,7 @@ var init_client2 = () => {};
28575
29189
 
28576
29190
  // ../alerts/src/discord/types.ts
28577
29191
  var DiscordColors;
28578
- var init_types2 = __esm(() => {
29192
+ var init_types3 = __esm(() => {
28579
29193
  DiscordColors = {
28580
29194
  DEFAULT: 0,
28581
29195
  WHITE: 16777215,
@@ -28613,7 +29227,7 @@ var init_types2 = __esm(() => {
28613
29227
  // ../alerts/src/discord/index.ts
28614
29228
  var init_discord = __esm(() => {
28615
29229
  init_client2();
28616
- init_types2();
29230
+ init_types3();
28617
29231
  });
28618
29232
 
28619
29233
  // ../api-core/src/services/alerts.service.ts
@@ -29744,7 +30358,7 @@ var init_secrets_service = __esm(() => {
29744
30358
 
29745
30359
  // ../edge-play/src/constants.ts
29746
30360
  var ASSET_ROUTE_PREFIX = "/api/assets/", ROUTES;
29747
- var init_constants3 = __esm(() => {
30361
+ var init_constants4 = __esm(() => {
29748
30362
  init_src();
29749
30363
  ROUTES = {
29750
30364
  INDEX: "/api",
@@ -29771,7 +30385,7 @@ function prefixSecrets(secrets) {
29771
30385
  }
29772
30386
  var init_setup2 = __esm(() => {
29773
30387
  init_src();
29774
- init_constants3();
30388
+ init_constants4();
29775
30389
  });
29776
30390
 
29777
30391
  // ../api-core/src/services/seed.service.ts
@@ -30496,11 +31110,11 @@ var init_schemas3 = __esm(() => {
30496
31110
  });
30497
31111
 
30498
31112
  // ../data/src/domains/timeback/schemas.ts
30499
- function isTimebackGrade(value) {
31113
+ function isTimebackGrade2(value) {
30500
31114
  return Number.isInteger(value) && TIMEBACK_GRADES.includes(value);
30501
31115
  }
30502
- function isTimebackSubject(value) {
30503
- return TIMEBACK_SUBJECTS.includes(value);
31116
+ function isTimebackSubject2(value) {
31117
+ return TIMEBACK_SUBJECTS2.includes(value);
30504
31118
  }
30505
31119
  function isValidAdminAttributionDate(value) {
30506
31120
  const match = value.match(/^(\d{4})-(\d{2})-(\d{2})$/);
@@ -30514,13 +31128,13 @@ function isValidAdminAttributionDate(value) {
30514
31128
  const date3 = new Date(Date.UTC(year, month - 1, day, 12, 0, 0));
30515
31129
  return date3.getUTCFullYear() === year && date3.getUTCMonth() + 1 === month && date3.getUTCDate() === day;
30516
31130
  }
30517
- 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;
31131
+ 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;
30518
31132
  var init_schemas4 = __esm(() => {
30519
31133
  init_drizzle_zod();
30520
31134
  init_esm();
30521
31135
  init_table7();
30522
31136
  TIMEBACK_GRADES = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
30523
- TIMEBACK_SUBJECTS = [
31137
+ TIMEBACK_SUBJECTS2 = [
30524
31138
  "Reading",
30525
31139
  "Language",
30526
31140
  "Vocabulary",
@@ -30534,7 +31148,7 @@ var init_schemas4 = __esm(() => {
30534
31148
  TimebackGradeSchema = exports_external.number().int().refine((val) => TIMEBACK_GRADES.includes(val), {
30535
31149
  message: `Grade must be one of: ${TIMEBACK_GRADES.join(", ")}`
30536
31150
  });
30537
- TimebackSubjectSchema = exports_external.enum(TIMEBACK_SUBJECTS);
31151
+ TimebackSubjectSchema = exports_external.enum(TIMEBACK_SUBJECTS2);
30538
31152
  CourseGoalsSchema = exports_external.object({
30539
31153
  dailyXp: exports_external.number().int().nonnegative().nullable().optional(),
30540
31154
  dailyLessons: exports_external.number().int().nonnegative().nullable().optional(),
@@ -30553,6 +31167,15 @@ var init_schemas4 = __esm(() => {
30553
31167
  isSupplemental: exports_external.boolean().optional(),
30554
31168
  timebackVisible: exports_external.boolean().nullable().optional()
30555
31169
  });
31170
+ CreateGameTimebackIntegrationRequestSchema = exports_external.object({
31171
+ title: exports_external.string().trim().min(1),
31172
+ courseCode: exports_external.string().trim().min(1),
31173
+ subject: TimebackSubjectSchema,
31174
+ grade: TimebackGradeSchema,
31175
+ totalXp: exports_external.number().int().positive(),
31176
+ masterableUnits: exports_external.number().int().nonnegative(),
31177
+ level: exports_external.string().trim().min(1).optional()
31178
+ });
30556
31179
  TimebackActivityDataSchema = exports_external.object({
30557
31180
  activityId: exports_external.string().min(1),
30558
31181
  activityName: exports_external.string().optional(),
@@ -30998,10 +31621,6 @@ var init_log = __esm(() => {
30998
31621
  init_ansi();
30999
31622
  init_spinner();
31000
31623
  });
31001
- // ../utils/src/string.ts
31002
- function kebabToTitleCase(kebabStr) {
31003
- return kebabStr.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
31004
- }
31005
31624
  // ../utils/src/timezone.ts
31006
31625
  function formatDateYMDInTimezone(timeZone, date3 = new Date) {
31007
31626
  const parts2 = new Intl.DateTimeFormat("en-US", {
@@ -31111,16 +31730,45 @@ var init_src4 = __esm(() => {
31111
31730
  });
31112
31731
 
31113
31732
  // ../timeback/dist/index.js
31733
+ import { createHash } from "node:crypto";
31114
31734
  import { AsyncLocalStorage } from "node:async_hooks";
31115
31735
  function createOneRosterUrls(baseUrl) {
31116
- const effective = baseUrl || TIMEBACK_API_URLS.production;
31736
+ const effective = baseUrl || TIMEBACK_API_URLS2.production;
31117
31737
  const base = effective.replace(/\/$/, "");
31118
31738
  return {
31119
- user: (userId) => `${base}${ONEROSTER_ENDPOINTS.users}/${userId}`,
31120
- course: (courseId) => `${base}${ONEROSTER_ENDPOINTS.courses}/${courseId}`,
31121
- componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS.componentResources}/${resourceId}`
31739
+ user: (userId) => `${base}${ONEROSTER_ENDPOINTS2.users}/${userId}`,
31740
+ course: (courseId) => `${base}${ONEROSTER_ENDPOINTS2.courses}/${courseId}`,
31741
+ componentResource: (resourceId) => `${base}${ONEROSTER_ENDPOINTS2.componentResources}/${resourceId}`
31122
31742
  };
31123
31743
  }
31744
+ function resolveCourseIdFromCourseUrl(url2) {
31745
+ try {
31746
+ const parts2 = new URL(url2).pathname.split("/").filter(Boolean);
31747
+ const maybeCourses = parts2.at(-2);
31748
+ const maybeId = parts2.at(-1);
31749
+ if (maybeCourses !== "courses" || !maybeId) {
31750
+ return null;
31751
+ }
31752
+ if (UUID_REGEX2.test(maybeId)) {
31753
+ return maybeId;
31754
+ }
31755
+ if (maybeId.length > 2 && !maybeId.includes("/")) {
31756
+ return maybeId;
31757
+ }
31758
+ return null;
31759
+ } catch {
31760
+ return null;
31761
+ }
31762
+ }
31763
+ function computeCaliperLineItemId(objectId, courseSourcedId, courseUrl) {
31764
+ const recovered = resolveCourseIdFromCourseUrl(courseUrl);
31765
+ if (recovered !== courseSourcedId) {
31766
+ 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.`);
31767
+ }
31768
+ const idParts = [objectId, courseSourcedId].join("_");
31769
+ const hashedId = createHash("sha256").update(idParts).digest("hex");
31770
+ return `caliper_${hashedId}`;
31771
+ }
31124
31772
  function deriveSourcedIds(courseId) {
31125
31773
  return {
31126
31774
  course: courseId,
@@ -31132,7 +31780,7 @@ function deriveSourcedIds(courseId) {
31132
31780
  async function fetchTimebackConfig(client, courseId) {
31133
31781
  const sourcedIds = deriveSourcedIds(courseId);
31134
31782
  const [org, course, component, resource, componentResource] = await Promise.all([
31135
- client.oneroster.organizations.get(PLAYCADEMY_DEFAULTS.organization),
31783
+ client.oneroster.organizations.get(PLAYCADEMY_DEFAULTS2.organization),
31136
31784
  client.oneroster.courses.get(sourcedIds.course),
31137
31785
  client.oneroster.courseComponents.get(sourcedIds.component),
31138
31786
  client.oneroster.resources.get(sourcedIds.resource),
@@ -31142,7 +31790,7 @@ async function fetchTimebackConfig(client, courseId) {
31142
31790
  organization: {
31143
31791
  name: org.name,
31144
31792
  type: org.type,
31145
- identifier: org.identifier || PLAYCADEMY_DEFAULTS.organization
31793
+ identifier: org.identifier || PLAYCADEMY_DEFAULTS2.organization
31146
31794
  },
31147
31795
  course: {
31148
31796
  title: course.title || "",
@@ -31202,23 +31850,23 @@ async function verifyTimebackResources(client, courseId) {
31202
31850
  }
31203
31851
  };
31204
31852
  }
31205
- function isObject(value) {
31853
+ function isObject2(value) {
31206
31854
  return typeof value === "object" && value !== null;
31207
31855
  }
31208
- function isPlaycademyResourceMetadata(value) {
31209
- if (!isObject(value)) {
31856
+ function isPlaycademyResourceMetadata2(value) {
31857
+ if (!isObject2(value)) {
31210
31858
  return false;
31211
31859
  }
31212
31860
  if (!("mastery" in value) || value.mastery === undefined) {
31213
31861
  return true;
31214
31862
  }
31215
- return isObject(value.mastery);
31863
+ return isObject2(value.mastery);
31216
31864
  }
31217
- function isTimebackSubject2(value) {
31218
- return typeof value === "string" && SUBJECT_VALUES.includes(value);
31865
+ function isTimebackSubject3(value) {
31866
+ return typeof value === "string" && SUBJECT_VALUES2.includes(value);
31219
31867
  }
31220
- function isTimebackGrade2(value) {
31221
- return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES.includes(value);
31868
+ function isTimebackGrade3(value) {
31869
+ return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES2.includes(value);
31222
31870
  }
31223
31871
  async function deleteTimebackResources(client, courseId) {
31224
31872
  const sourcedIds = deriveSourcedIds(courseId);
@@ -31269,6 +31917,15 @@ async function deleteTimebackResources(client, courseId) {
31269
31917
  ]);
31270
31918
  setAttribute("app.timeback.resources_deleted", true);
31271
31919
  }
31920
+ async function updateTimebackCourseStatus(client, courseId, status) {
31921
+ const course = await client.oneroster.courses.get(courseId);
31922
+ await client.oneroster.courses.update(courseId, {
31923
+ ...course,
31924
+ sourcedId: courseId,
31925
+ status
31926
+ });
31927
+ setAttribute("app.timeback.course_status", status);
31928
+ }
31272
31929
  async function createCourse(client, config2) {
31273
31930
  const courseData = {
31274
31931
  status: "active",
@@ -31517,14 +32174,14 @@ async function getTimebackTokenResponse(config2) {
31517
32174
  }
31518
32175
  }
31519
32176
  function getAuthUrl(environment = "production") {
31520
- return TIMEBACK_AUTH_URLS[environment];
32177
+ return TIMEBACK_AUTH_URLS2[environment];
31521
32178
  }
31522
32179
  function parseEduBridgeGrade(value) {
31523
32180
  if (value === null || value === undefined || value.trim() === "") {
31524
32181
  return null;
31525
32182
  }
31526
32183
  const parsed = Number(value);
31527
- return isTimebackGrade2(parsed) ? parsed : null;
32184
+ return isTimebackGrade3(parsed) ? parsed : null;
31528
32185
  }
31529
32186
  function normalizeHighestGradeMastered(response, subject) {
31530
32187
  const grades = {
@@ -31601,12 +32258,12 @@ async function withTimebackClientTelemetry(fn) {
31601
32258
  }
31602
32259
  function handleHttpError(res, errorBody, attempt, retries, context2) {
31603
32260
  const error = new TimebackApiError(res.status, res.statusText, errorBody);
31604
- if (res.status >= HTTP_STATUS.CLIENT_ERROR_MIN && res.status < HTTP_STATUS.CLIENT_ERROR_MAX) {
32261
+ if (res.status >= HTTP_STATUS2.CLIENT_ERROR_MIN && res.status < HTTP_STATUS2.CLIENT_ERROR_MAX) {
31605
32262
  recordTimebackHttpFailure();
31606
32263
  throw error;
31607
32264
  }
31608
32265
  if (attempt < retries) {
31609
- const delay = HTTP_DEFAULTS.retryBackoffBase ** attempt * 1000;
32266
+ const delay = HTTP_DEFAULTS2.retryBackoffBase ** attempt * 1000;
31610
32267
  recordTimebackRetry();
31611
32268
  addEvent("timeback.request_retry", {
31612
32269
  "app.timeback.attempt": attempt + 1,
@@ -31683,7 +32340,7 @@ async function request({
31683
32340
  const result = handleHttpError(res, errorBody, attempt, retries, { method, path });
31684
32341
  lastError = result.error;
31685
32342
  if (result.retry) {
31686
- const delay = HTTP_DEFAULTS.retryBackoffBase ** attempt * 1000;
32343
+ const delay = HTTP_DEFAULTS2.retryBackoffBase ** attempt * 1000;
31687
32344
  await new Promise((resolve) => setTimeout(resolve, delay));
31688
32345
  }
31689
32346
  } else {
@@ -31695,7 +32352,7 @@ async function request({
31695
32352
  }
31696
32353
  lastError = error instanceof Error ? error : new Error(String(error));
31697
32354
  if (attempt < retries) {
31698
- const delay = HTTP_DEFAULTS.retryBackoffBase ** attempt * 1000;
32355
+ const delay = HTTP_DEFAULTS2.retryBackoffBase ** attempt * 1000;
31699
32356
  recordTimebackRetry();
31700
32357
  addEvent("timeback.network_retry", {
31701
32358
  "app.timeback.attempt": attempt + 1,
@@ -31744,10 +32401,10 @@ function createCaliperNamespace(client) {
31744
32401
  const envelope = {
31745
32402
  sensor: sensorUrl,
31746
32403
  sendTime: new Date().toISOString(),
31747
- dataVersion: CALIPER_CONSTANTS.dataVersion,
32404
+ dataVersion: CALIPER_CONSTANTS2.dataVersion,
31748
32405
  data: [event]
31749
32406
  };
31750
- return client["requestCaliper"](CALIPER_ENDPOINTS.event, "POST", envelope);
32407
+ return client["requestCaliper"](CALIPER_ENDPOINTS2.event, "POST", envelope);
31751
32408
  },
31752
32409
  emitBatch: async (events, sensorUrl) => {
31753
32410
  if (events.length === 0) {
@@ -31756,10 +32413,10 @@ function createCaliperNamespace(client) {
31756
32413
  const envelope = {
31757
32414
  sensor: sensorUrl,
31758
32415
  sendTime: new Date().toISOString(),
31759
- dataVersion: CALIPER_CONSTANTS.dataVersion,
32416
+ dataVersion: CALIPER_CONSTANTS2.dataVersion,
31760
32417
  data: events
31761
32418
  };
31762
- return client["requestCaliper"](CALIPER_ENDPOINTS.event, "POST", envelope);
32419
+ return client["requestCaliper"](CALIPER_ENDPOINTS2.event, "POST", envelope);
31763
32420
  },
31764
32421
  events: {
31765
32422
  list: async (params = {}) => {
@@ -31789,7 +32446,7 @@ function createCaliperNamespace(client) {
31789
32446
  query.set(`extensions.${key}`, value);
31790
32447
  }
31791
32448
  }
31792
- const requestPath = `${CALIPER_ENDPOINTS.events}?${query.toString()}`;
32449
+ const requestPath = `${CALIPER_ENDPOINTS2.events}?${query.toString()}`;
31793
32450
  return client["requestCaliper"](requestPath, "GET");
31794
32451
  }
31795
32452
  },
@@ -31799,21 +32456,21 @@ function createCaliperNamespace(client) {
31799
32456
  gameId: data.gameId
31800
32457
  });
31801
32458
  const event = {
31802
- "@context": CALIPER_CONSTANTS.context,
32459
+ "@context": CALIPER_CONSTANTS2.context,
31803
32460
  id: `urn:uuid:${crypto.randomUUID()}`,
31804
- type: TIMEBACK_EVENT_TYPES.activityEvent,
32461
+ type: TIMEBACK_EVENT_TYPES2.activityEvent,
31805
32462
  eventTime: data.eventTime || new Date().toISOString(),
31806
- profile: CALIPER_CONSTANTS.profile,
32463
+ profile: CALIPER_CONSTANTS2.profile,
31807
32464
  actor: {
31808
32465
  id: urls.user(data.studentId),
31809
- type: TIMEBACK_TYPES.user,
32466
+ type: TIMEBACK_TYPES2.user,
31810
32467
  email: data.studentEmail
31811
32468
  },
31812
- action: TIMEBACK_ACTIONS.completed,
32469
+ action: TIMEBACK_ACTIONS2.completed,
31813
32470
  ...data.runId ? { session: `urn:uuid:${data.runId}` } : {},
31814
32471
  object: {
31815
32472
  id: data.objectId || caliper.buildActivityUrl(data),
31816
- type: TIMEBACK_TYPES.activityContext,
32473
+ type: TIMEBACK_TYPES2.activityContext,
31817
32474
  subject: data.subject,
31818
32475
  app: {
31819
32476
  name: data.appName
@@ -31827,25 +32484,25 @@ function createCaliperNamespace(client) {
31827
32484
  },
31828
32485
  generated: {
31829
32486
  id: data.generatedId || `urn:timeback:metrics:activity-completion-${crypto.randomUUID()}`,
31830
- type: TIMEBACK_TYPES.activityMetricsCollection,
32487
+ type: TIMEBACK_TYPES2.activityMetricsCollection,
31831
32488
  ...data.includeAttempt === false ? {} : { attempt: data.attemptNumber || 1 },
31832
32489
  items: [
31833
32490
  ...data.totalQuestions !== undefined ? [
31834
32491
  {
31835
- type: ACTIVITY_METRIC_TYPES.totalQuestions,
32492
+ type: ACTIVITY_METRIC_TYPES2.totalQuestions,
31836
32493
  value: data.totalQuestions
31837
32494
  }
31838
32495
  ] : [],
31839
32496
  ...data.correctQuestions !== undefined ? [
31840
32497
  {
31841
- type: ACTIVITY_METRIC_TYPES.correctQuestions,
32498
+ type: ACTIVITY_METRIC_TYPES2.correctQuestions,
31842
32499
  value: data.correctQuestions
31843
32500
  }
31844
32501
  ] : [],
31845
- ...data.xpEarned !== undefined ? [{ type: ACTIVITY_METRIC_TYPES.xpEarned, value: data.xpEarned }] : [],
32502
+ ...data.xpEarned !== undefined ? [{ type: ACTIVITY_METRIC_TYPES2.xpEarned, value: data.xpEarned }] : [],
31846
32503
  ...data.masteredUnits !== undefined ? [
31847
32504
  {
31848
- type: ACTIVITY_METRIC_TYPES.masteredUnits,
32505
+ type: ACTIVITY_METRIC_TYPES2.masteredUnits,
31849
32506
  value: data.masteredUnits
31850
32507
  }
31851
32508
  ] : []
@@ -31867,21 +32524,21 @@ function createCaliperNamespace(client) {
31867
32524
  gameId: data.gameId
31868
32525
  });
31869
32526
  const event = {
31870
- "@context": CALIPER_CONSTANTS.context,
32527
+ "@context": CALIPER_CONSTANTS2.context,
31871
32528
  id: `urn:uuid:${crypto.randomUUID()}`,
31872
- type: TIMEBACK_EVENT_TYPES.timeSpentEvent,
32529
+ type: TIMEBACK_EVENT_TYPES2.timeSpentEvent,
31873
32530
  eventTime: data.eventTime || new Date().toISOString(),
31874
- profile: CALIPER_CONSTANTS.profile,
32531
+ profile: CALIPER_CONSTANTS2.profile,
31875
32532
  actor: {
31876
32533
  id: urls.user(data.studentId),
31877
- type: TIMEBACK_TYPES.user,
32534
+ type: TIMEBACK_TYPES2.user,
31878
32535
  email: data.studentEmail
31879
32536
  },
31880
- action: TIMEBACK_ACTIONS.spentTime,
32537
+ action: TIMEBACK_ACTIONS2.spentTime,
31881
32538
  ...data.runId ? { session: `urn:uuid:${data.runId}` } : {},
31882
32539
  object: {
31883
32540
  id: caliper.buildActivityUrl(data),
31884
- type: TIMEBACK_TYPES.activityContext,
32541
+ type: TIMEBACK_TYPES2.activityContext,
31885
32542
  subject: data.subject,
31886
32543
  app: {
31887
32544
  name: data.appName
@@ -31894,16 +32551,16 @@ function createCaliperNamespace(client) {
31894
32551
  },
31895
32552
  generated: {
31896
32553
  id: `urn:timeback:metrics:time-spent-${crypto.randomUUID()}`,
31897
- type: TIMEBACK_TYPES.timeSpentMetricsCollection,
32554
+ type: TIMEBACK_TYPES2.timeSpentMetricsCollection,
31898
32555
  items: [
31899
- { type: TIME_METRIC_TYPES.active, value: data.activeTimeSeconds },
32556
+ { type: TIME_METRIC_TYPES2.active, value: data.activeTimeSeconds },
31900
32557
  ...data.inactiveTimeSeconds !== undefined ? [
31901
32558
  {
31902
- type: TIME_METRIC_TYPES.inactive,
32559
+ type: TIME_METRIC_TYPES2.inactive,
31903
32560
  value: data.inactiveTimeSeconds
31904
32561
  }
31905
32562
  ] : [],
31906
- ...data.wasteTimeSeconds !== undefined ? [{ type: TIME_METRIC_TYPES.waste, value: data.wasteTimeSeconds }] : []
32563
+ ...data.wasteTimeSeconds !== undefined ? [{ type: TIME_METRIC_TYPES2.waste, value: data.wasteTimeSeconds }] : []
31907
32564
  ],
31908
32565
  ...data.extensions ? { extensions: data.extensions } : {}
31909
32566
  },
@@ -31914,7 +32571,8 @@ function createCaliperNamespace(client) {
31914
32571
  buildActivityUrl: (data) => {
31915
32572
  const base = data.sensorUrl.replace(/\/$/, "");
31916
32573
  return `${base}/activities/${encodeURIComponent(data.courseId)}/${encodeURIComponent(data.activityId)}`;
31917
- }
32574
+ },
32575
+ buildCourseUrl: (courseId) => urls.course(courseId)
31918
32576
  };
31919
32577
  return caliper;
31920
32578
  }
@@ -32037,17 +32695,17 @@ async function listOneRosterCollection(client, endpoint, collectionKey, options)
32037
32695
  function createOneRosterNamespace(client) {
32038
32696
  return {
32039
32697
  classes: {
32040
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.classes, "POST", { class: data }),
32698
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.classes, "POST", { class: data }),
32041
32699
  get: async (sourcedId) => {
32042
- const res = await client["request"](`${ONEROSTER_ENDPOINTS.classes}/${sourcedId}`, "GET");
32700
+ const res = await client["request"](`${ONEROSTER_ENDPOINTS2.classes}/${sourcedId}`, "GET");
32043
32701
  return res.class;
32044
32702
  },
32045
32703
  update: async (sourcedId, data) => {
32046
- const res = await client["request"](`${ONEROSTER_ENDPOINTS.classes}/${sourcedId}`, "PUT", { class: data });
32704
+ const res = await client["request"](`${ONEROSTER_ENDPOINTS2.classes}/${sourcedId}`, "PUT", { class: data });
32047
32705
  return res.class;
32048
32706
  },
32049
32707
  listByCourse: async (courseSourcedId) => {
32050
- const res = await client["request"](`${ONEROSTER_ENDPOINTS.courses}/${courseSourcedId}/classes`, "GET");
32708
+ const res = await client["request"](`${ONEROSTER_ENDPOINTS2.courses}/${courseSourcedId}/classes`, "GET");
32051
32709
  return res.classes;
32052
32710
  },
32053
32711
  listByStudent: async (userSourcedId, options) => {
@@ -32058,7 +32716,7 @@ function createOneRosterNamespace(client) {
32058
32716
  if (options?.offset) {
32059
32717
  queryParams.set("offset", String(options.offset));
32060
32718
  }
32061
- const endpoint = `${ONEROSTER_ENDPOINTS.users}/${userSourcedId}/classes`;
32719
+ const endpoint = `${ONEROSTER_ENDPOINTS2.users}/${userSourcedId}/classes`;
32062
32720
  const url2 = queryParams.toString() ? `${endpoint}?${queryParams}` : endpoint;
32063
32721
  const res = await client["request"](url2, "GET");
32064
32722
  return res.classes || [];
@@ -32066,7 +32724,7 @@ function createOneRosterNamespace(client) {
32066
32724
  },
32067
32725
  enrollments: {
32068
32726
  get: async (sourcedId) => {
32069
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.enrollments}/${sourcedId}`, "GET");
32727
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.enrollments}/${sourcedId}`, "GET");
32070
32728
  return response.enrollment;
32071
32729
  },
32072
32730
  listByClass: async (classSourcedId, options) => {
@@ -32082,7 +32740,7 @@ function createOneRosterNamespace(client) {
32082
32740
  if (options?.offset) {
32083
32741
  queryParams.set("offset", String(options.offset));
32084
32742
  }
32085
- const url2 = `${ONEROSTER_ENDPOINTS.enrollments}?${queryParams}`;
32743
+ const url2 = `${ONEROSTER_ENDPOINTS2.enrollments}?${queryParams}`;
32086
32744
  try {
32087
32745
  const response = await client["request"](url2, "GET");
32088
32746
  return response.enrollments || [];
@@ -32115,7 +32773,7 @@ function createOneRosterNamespace(client) {
32115
32773
  }
32116
32774
  queryParams.set("filter", filters.join(" AND "));
32117
32775
  queryParams.set("limit", "3000");
32118
- const url2 = `${ONEROSTER_ENDPOINTS.enrollments}?${queryParams}`;
32776
+ const url2 = `${ONEROSTER_ENDPOINTS2.enrollments}?${queryParams}`;
32119
32777
  const response = await client["request"](url2, "GET");
32120
32778
  return response.enrollments || [];
32121
32779
  }));
@@ -32145,72 +32803,72 @@ function createOneRosterNamespace(client) {
32145
32803
  throw error;
32146
32804
  }
32147
32805
  },
32148
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.enrollments, "POST", { enrollment: data }),
32806
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.enrollments, "POST", { enrollment: data }),
32149
32807
  update: async (sourcedId, data) => {
32150
- await client["request"](`${ONEROSTER_ENDPOINTS.enrollments}/${sourcedId}`, "PUT", {
32808
+ await client["request"](`${ONEROSTER_ENDPOINTS2.enrollments}/${sourcedId}`, "PUT", {
32151
32809
  enrollment: data
32152
32810
  });
32153
32811
  },
32154
32812
  delete: async (sourcedId) => {
32155
- await client["request"](`${ONEROSTER_ENDPOINTS.enrollments}/${sourcedId}`, "DELETE");
32813
+ await client["request"](`${ONEROSTER_ENDPOINTS2.enrollments}/${sourcedId}`, "DELETE");
32156
32814
  }
32157
32815
  },
32158
32816
  organizations: {
32159
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.organizations, "POST", data),
32160
- get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "GET").then((res) => res.org),
32161
- update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS.organizations}/${sourcedId}`, "PUT", data)
32817
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.organizations, "POST", data),
32818
+ get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS2.organizations}/${sourcedId}`, "GET").then((res) => res.org),
32819
+ update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS2.organizations}/${sourcedId}`, "PUT", data)
32162
32820
  },
32163
32821
  courses: {
32164
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.courses, "POST", data),
32822
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.courses, "POST", data),
32165
32823
  get: async (sourcedId) => {
32166
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.courses}/${sourcedId}`, "GET");
32824
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.courses}/${sourcedId}`, "GET");
32167
32825
  return response.course;
32168
32826
  },
32169
32827
  update: async (sourcedId, data) => {
32170
- await client["request"](`${ONEROSTER_ENDPOINTS.courses}/${sourcedId}`, "PUT", {
32828
+ await client["request"](`${ONEROSTER_ENDPOINTS2.courses}/${sourcedId}`, "PUT", {
32171
32829
  course: data
32172
32830
  });
32173
32831
  }
32174
32832
  },
32175
32833
  courseComponents: {
32176
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.courseComponents, "POST", data),
32834
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.courseComponents, "POST", data),
32177
32835
  get: async (sourcedId) => {
32178
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.courseComponents}/${sourcedId}`, "GET");
32836
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.courseComponents}/${sourcedId}`, "GET");
32179
32837
  return response.courseComponent;
32180
32838
  },
32181
32839
  update: async (sourcedId, data) => {
32182
- await client["request"](`${ONEROSTER_ENDPOINTS.courseComponents}/${sourcedId}`, "PUT", { courseComponent: data });
32840
+ await client["request"](`${ONEROSTER_ENDPOINTS2.courseComponents}/${sourcedId}`, "PUT", { courseComponent: data });
32183
32841
  }
32184
32842
  },
32185
32843
  resources: {
32186
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.resources, "POST", data),
32844
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.resources, "POST", data),
32187
32845
  get: async (sourcedId) => {
32188
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.resources}/${sourcedId}`, "GET");
32846
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.resources}/${sourcedId}`, "GET");
32189
32847
  return response.resource;
32190
32848
  },
32191
32849
  update: async (sourcedId, data) => {
32192
- await client["request"](`${ONEROSTER_ENDPOINTS.resources}/${sourcedId}`, "PUT", {
32850
+ await client["request"](`${ONEROSTER_ENDPOINTS2.resources}/${sourcedId}`, "PUT", {
32193
32851
  resource: data
32194
32852
  });
32195
32853
  },
32196
32854
  delete: async (sourcedId) => {
32197
- await client["request"](`${ONEROSTER_ENDPOINTS.resources}/${sourcedId}`, "DELETE");
32855
+ await client["request"](`${ONEROSTER_ENDPOINTS2.resources}/${sourcedId}`, "DELETE");
32198
32856
  }
32199
32857
  },
32200
32858
  componentResources: {
32201
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.componentResources, "POST", data),
32859
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.componentResources, "POST", data),
32202
32860
  get: async (sourcedId) => {
32203
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.componentResources}/${sourcedId}`, "GET");
32861
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.componentResources}/${sourcedId}`, "GET");
32204
32862
  return response.componentResource;
32205
32863
  },
32206
32864
  update: async (sourcedId, data) => {
32207
- await client["request"](`${ONEROSTER_ENDPOINTS.componentResources}/${sourcedId}`, "PUT", { componentResource: data });
32865
+ await client["request"](`${ONEROSTER_ENDPOINTS2.componentResources}/${sourcedId}`, "PUT", { componentResource: data });
32208
32866
  }
32209
32867
  },
32210
32868
  assessmentLineItems: {
32211
32869
  list: async (options) => {
32212
32870
  try {
32213
- return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS.assessmentLineItems, "assessmentLineItems", options);
32871
+ return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentLineItems, "assessmentLineItems", options);
32214
32872
  } catch (error) {
32215
32873
  logTimebackError("list assessment line items", error, {
32216
32874
  filter: options?.filter
@@ -32218,14 +32876,14 @@ function createOneRosterNamespace(client) {
32218
32876
  return [];
32219
32877
  }
32220
32878
  },
32221
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.assessmentLineItems, "POST", { assessmentLineItem: data }),
32879
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.assessmentLineItems, "POST", { assessmentLineItem: data }),
32222
32880
  get: async (sourcedId) => {
32223
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.assessmentLineItems}/${sourcedId}`, "GET");
32881
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.assessmentLineItems}/${sourcedId}`, "GET");
32224
32882
  return response.assessmentLineItem;
32225
32883
  },
32226
32884
  findOrCreate: async (sourcedId, data) => {
32227
32885
  try {
32228
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.assessmentLineItems}/${sourcedId}`, "GET");
32886
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.assessmentLineItems}/${sourcedId}`, "GET");
32229
32887
  return response.assessmentLineItem;
32230
32888
  } catch {
32231
32889
  const createData = {
@@ -32234,7 +32892,7 @@ function createOneRosterNamespace(client) {
32234
32892
  dateLastModified: new Date().toISOString()
32235
32893
  };
32236
32894
  try {
32237
- const response = await client["request"](ONEROSTER_ENDPOINTS.assessmentLineItems, "POST", { assessmentLineItem: createData });
32895
+ const response = await client["request"](ONEROSTER_ENDPOINTS2.assessmentLineItems, "POST", { assessmentLineItem: createData });
32238
32896
  if (!response.sourcedIdPairs?.allocatedSourcedId) {
32239
32897
  throw new Error("Invalid response from OneRoster API - missing allocatedSourcedId");
32240
32898
  }
@@ -32249,7 +32907,7 @@ function createOneRosterNamespace(client) {
32249
32907
  assessmentResults: {
32250
32908
  list: async (options) => {
32251
32909
  try {
32252
- return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS.assessmentResults, "assessmentResults", options);
32910
+ return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentResults, "assessmentResults", options);
32253
32911
  } catch (error) {
32254
32912
  logTimebackError("list assessment results", error, {
32255
32913
  filter: options?.filter
@@ -32257,10 +32915,11 @@ function createOneRosterNamespace(client) {
32257
32915
  return [];
32258
32916
  }
32259
32917
  },
32260
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.assessmentResults, "POST", { assessmentResult: data }),
32918
+ listOrThrow: async (options) => await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentResults, "assessmentResults", options),
32919
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.assessmentResults, "POST", { assessmentResult: data }),
32261
32920
  listByStudent: async (studentSourcedId, options) => {
32262
32921
  try {
32263
- return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS.assessmentResults, "assessmentResults", {
32922
+ return await listOneRosterCollection(client, ONEROSTER_ENDPOINTS2.assessmentResults, "assessmentResults", {
32264
32923
  limit: options?.limit,
32265
32924
  offset: options?.offset,
32266
32925
  fields: options?.fields,
@@ -32279,54 +32938,22 @@ function createOneRosterNamespace(client) {
32279
32938
  sourcedId,
32280
32939
  dateLastModified: new Date().toISOString()
32281
32940
  };
32282
- return client["request"](`${ONEROSTER_ENDPOINTS.assessmentResults}/${sourcedId}`, "PUT", { assessmentResult });
32941
+ return client["request"](`${ONEROSTER_ENDPOINTS2.assessmentResults}/${sourcedId}`, "PUT", { assessmentResult });
32283
32942
  },
32284
32943
  get: async (sourcedId) => {
32285
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.assessmentResults}/${sourcedId}`, "GET");
32944
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.assessmentResults}/${sourcedId}`, "GET");
32286
32945
  return response.assessmentResult;
32287
32946
  },
32288
- update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS.assessmentResults}/${sourcedId}`, "PUT", data),
32289
- getAttemptStats: async (studentId, lineItemId) => {
32290
- try {
32291
- const filter = `student.sourcedId='${studentId}' AND assessmentLineItem.sourcedId='${lineItemId}'`;
32292
- const url2 = `${ONEROSTER_ENDPOINTS.assessmentResults}?filter=${encodeURIComponent(filter)}`;
32293
- const response = await client["request"](url2, "GET");
32294
- const results = response.assessmentResults || [];
32295
- const firstResult = results[0];
32296
- if (!firstResult) {
32297
- return null;
32298
- }
32299
- let maxAttemptResult = firstResult;
32300
- let maxAttemptNumber = maxAttemptResult.metadata?.attemptNumber || 0;
32301
- let activeAttemptCount = 0;
32302
- for (const result of results) {
32303
- const attemptNumber = result.metadata?.attemptNumber || 0;
32304
- if (attemptNumber > maxAttemptNumber) {
32305
- maxAttemptNumber = attemptNumber;
32306
- maxAttemptResult = result;
32307
- }
32308
- if (result.status === "active") {
32309
- activeAttemptCount++;
32310
- }
32311
- }
32312
- return { maxAttemptNumber, activeAttemptCount, maxAttemptResult };
32313
- } catch (error) {
32314
- logTimebackError("query attempt stats", error, {
32315
- studentId,
32316
- lineItemId
32317
- });
32318
- return null;
32319
- }
32320
- }
32947
+ update: async (sourcedId, data) => client["request"](`${ONEROSTER_ENDPOINTS2.assessmentResults}/${sourcedId}`, "PUT", data)
32321
32948
  },
32322
32949
  users: {
32323
- create: async (data) => client["request"](ONEROSTER_ENDPOINTS.users, "POST", {
32950
+ create: async (data) => client["request"](ONEROSTER_ENDPOINTS2.users, "POST", {
32324
32951
  user: data
32325
32952
  }),
32326
- get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS.users}/${sourcedId}`, "GET").then((res) => res.user),
32953
+ get: async (sourcedId) => client["request"](`${ONEROSTER_ENDPOINTS2.users}/${sourcedId}`, "GET").then((res) => res.user),
32327
32954
  findByEmail: async (email) => {
32328
32955
  const params = new URLSearchParams({ filter: `email='${email}'` });
32329
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.users}?${params}`, "GET");
32956
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.users}?${params}`, "GET");
32330
32957
  if (!response || !response.users || !Array.isArray(response.users)) {
32331
32958
  throw new Error(`Invalid response format from OneRoster API when searching for user with email: ${email}. ` + `Expected { users: [...] } but received: ${JSON.stringify(response)}`);
32332
32959
  }
@@ -32345,7 +32972,7 @@ function createOneRosterNamespace(client) {
32345
32972
  const results = await Promise.all(batches.map(async (batch) => {
32346
32973
  const filter = batch.map((id) => `sourcedId='${escapeFilterValue(id)}'`).join(" OR ");
32347
32974
  const params = new URLSearchParams({ filter });
32348
- const response = await client["request"](`${ONEROSTER_ENDPOINTS.users}?${params}`, "GET");
32975
+ const response = await client["request"](`${ONEROSTER_ENDPOINTS2.users}?${params}`, "GET");
32349
32976
  return response.users || [];
32350
32977
  }));
32351
32978
  return results.flat();
@@ -32362,11 +32989,11 @@ function createOneRosterNamespace(client) {
32362
32989
  function createQtiNamespace(client) {
32363
32990
  return {
32364
32991
  items: {
32365
- create: async (data) => client["requestQti"](QTI_ENDPOINTS.assessmentItems, "POST", data),
32366
- get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentItems}/${identifier}`, "GET"),
32367
- update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS.assessmentItems}/${identifier}`, "PUT", data),
32992
+ create: async (data) => client["requestQti"](QTI_ENDPOINTS2.assessmentItems, "POST", data),
32993
+ get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentItems}/${identifier}`, "GET"),
32994
+ update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentItems}/${identifier}`, "PUT", data),
32368
32995
  delete: async (identifier) => {
32369
- await client["requestQti"](`${QTI_ENDPOINTS.assessmentItems}/${identifier}`, "DELETE");
32996
+ await client["requestQti"](`${QTI_ENDPOINTS2.assessmentItems}/${identifier}`, "DELETE");
32370
32997
  }
32371
32998
  },
32372
32999
  tests: {
@@ -32388,25 +33015,25 @@ function createQtiNamespace(client) {
32388
33015
  params.set("order", options.order);
32389
33016
  }
32390
33017
  const query = params.toString();
32391
- return client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}${query ? `?${query}` : ""}`, "GET");
33018
+ return client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}${query ? `?${query}` : ""}`, "GET");
32392
33019
  },
32393
- create: async (data) => client["requestQti"](QTI_ENDPOINTS.assessmentTests, "POST", data),
32394
- get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}`, "GET"),
32395
- getQuestions: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}/questions`, "GET"),
32396
- update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}`, "PUT", data),
33020
+ create: async (data) => client["requestQti"](QTI_ENDPOINTS2.assessmentTests, "POST", data),
33021
+ get: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}`, "GET"),
33022
+ getQuestions: async (identifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}/questions`, "GET"),
33023
+ update: async (identifier, data) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}`, "PUT", data),
32397
33024
  delete: async (identifier) => {
32398
- await client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${identifier}`, "DELETE");
33025
+ await client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${identifier}`, "DELETE");
32399
33026
  },
32400
- addItem: async (testId, partId, sectionId, itemIdentifier) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items`, "POST", { identifier: itemIdentifier }),
33027
+ addItem: async (testId, partId, sectionId, itemIdentifier) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items`, "POST", { identifier: itemIdentifier }),
32401
33028
  removeItem: async (testId, partId, sectionId, itemIdentifier) => {
32402
- await client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/${itemIdentifier}`, "DELETE");
33029
+ await client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/${itemIdentifier}`, "DELETE");
32403
33030
  },
32404
- reorderItems: async (testId, partId, sectionId, items) => client["requestQti"](`${QTI_ENDPOINTS.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/order`, "PUT", { items })
33031
+ reorderItems: async (testId, partId, sectionId, items) => client["requestQti"](`${QTI_ENDPOINTS2.assessmentTests}/${testId}/test-parts/${partId}/sections/${sectionId}/items/order`, "PUT", { items })
32405
33032
  }
32406
33033
  };
32407
33034
  }
32408
33035
  function toCaliperSubject(subject) {
32409
- return isTimebackSubject2(subject) ? subject : "None";
33036
+ return isTimebackSubject3(subject) ? subject : "None";
32410
33037
  }
32411
33038
  function buildAdminEventMetadata({
32412
33039
  reason,
@@ -32470,7 +33097,7 @@ class AdminEventRecorder {
32470
33097
  defaultActivityId: "playcademy-admin-manual-xp",
32471
33098
  eventKind: "remediation-xp"
32472
33099
  });
32473
- const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS[this.environment]).course(data.courseId);
33100
+ const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS2[this.environment]).course(data.courseId);
32474
33101
  await this.caliper.emitActivityEvent({
32475
33102
  studentId: ctx.student.id,
32476
33103
  studentEmail: ctx.student.email,
@@ -32520,7 +33147,7 @@ class AdminEventRecorder {
32520
33147
  defaultActivityId: "playcademy-admin-mastery-adjustment",
32521
33148
  eventKind: "remediation-mastery"
32522
33149
  });
32523
- const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS[this.environment]).course(data.courseId);
33150
+ const courseUrl = createOneRosterUrls(TIMEBACK_API_URLS2[this.environment]).course(data.courseId);
32524
33151
  await this.caliper.emitActivityEvent({
32525
33152
  studentId: ctx.student.id,
32526
33153
  studentEmail: ctx.student.email,
@@ -32554,9 +33181,9 @@ class TimebackCache {
32554
33181
  maxSize;
32555
33182
  name;
32556
33183
  constructor(options = {}) {
32557
- this.defaultTTL = options.defaultTTL || CACHE_DEFAULTS.defaultTTL;
32558
- this.maxSize = options.maxSize || CACHE_DEFAULTS.defaultMaxSize;
32559
- this.name = options.name || CACHE_DEFAULTS.defaultName;
33184
+ this.defaultTTL = options.defaultTTL || CACHE_DEFAULTS2.defaultTTL;
33185
+ this.maxSize = options.maxSize || CACHE_DEFAULTS2.defaultMaxSize;
33186
+ this.name = options.name || CACHE_DEFAULTS2.defaultName;
32560
33187
  }
32561
33188
  get(key) {
32562
33189
  const entry = this.cache.get(key);
@@ -32647,23 +33274,23 @@ class TimebackCacheManager {
32647
33274
  enrollmentCache;
32648
33275
  constructor() {
32649
33276
  this.studentCache = new TimebackCache({
32650
- defaultTTL: CACHE_DEFAULTS.studentTTL,
32651
- maxSize: CACHE_DEFAULTS.studentMaxSize,
33277
+ defaultTTL: CACHE_DEFAULTS2.studentTTL,
33278
+ maxSize: CACHE_DEFAULTS2.studentMaxSize,
32652
33279
  name: "StudentCache"
32653
33280
  });
32654
33281
  this.assessmentLineItemCache = new TimebackCache({
32655
- defaultTTL: CACHE_DEFAULTS.assessmentTTL,
32656
- maxSize: CACHE_DEFAULTS.assessmentMaxSize,
33282
+ defaultTTL: CACHE_DEFAULTS2.assessmentTTL,
33283
+ maxSize: CACHE_DEFAULTS2.assessmentMaxSize,
32657
33284
  name: "AssessmentLineItemCache"
32658
33285
  });
32659
33286
  this.resourceMasteryCache = new TimebackCache({
32660
- defaultTTL: CACHE_DEFAULTS.assessmentTTL,
32661
- maxSize: CACHE_DEFAULTS.assessmentMaxSize,
33287
+ defaultTTL: CACHE_DEFAULTS2.assessmentTTL,
33288
+ maxSize: CACHE_DEFAULTS2.assessmentMaxSize,
32662
33289
  name: "ResourceMasteryCache"
32663
33290
  });
32664
33291
  this.enrollmentCache = new TimebackCache({
32665
- defaultTTL: CACHE_DEFAULTS.enrollmentTTL,
32666
- maxSize: CACHE_DEFAULTS.enrollmentMaxSize,
33292
+ defaultTTL: CACHE_DEFAULTS2.enrollmentTTL,
33293
+ maxSize: CACHE_DEFAULTS2.enrollmentMaxSize,
32667
33294
  name: "EnrollmentCache"
32668
33295
  });
32669
33296
  }
@@ -32919,18 +33546,18 @@ class MasteryTracker {
32919
33546
  await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
32920
33547
  sourcedId: lineItemId,
32921
33548
  title: "Mastery Completion",
32922
- status: ONEROSTER_STATUS.active,
33549
+ status: ONEROSTER_STATUS2.active,
32923
33550
  ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } },
32924
33551
  ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
32925
33552
  });
32926
33553
  await this.onerosterNamespace.assessmentResults.upsert(resultId, {
32927
33554
  sourcedId: resultId,
32928
- status: ONEROSTER_STATUS.active,
33555
+ status: ONEROSTER_STATUS2.active,
32929
33556
  assessmentLineItem: { sourcedId: lineItemId },
32930
33557
  student: { sourcedId: studentId },
32931
33558
  score: 100,
32932
33559
  scoreDate: new Date().toISOString(),
32933
- scoreStatus: SCORE_STATUS.fullyGraded,
33560
+ scoreStatus: SCORE_STATUS2.fullyGraded,
32934
33561
  inProgress: "false",
32935
33562
  metadata: {
32936
33563
  isMasteryCompletion: true,
@@ -32942,6 +33569,7 @@ class MasteryTracker {
32942
33569
  "app.timeback.line_item_id": lineItemId,
32943
33570
  "app.timeback.result_id": resultId
32944
33571
  });
33572
+ return true;
32945
33573
  } catch (error) {
32946
33574
  addEvent("timeback.mastery_completion_failed", {
32947
33575
  "app.timeback.student_id": studentId,
@@ -32949,6 +33577,7 @@ class MasteryTracker {
32949
33577
  "exception.type": errorType(error),
32950
33578
  "app.error.message": errorMessage(error)
32951
33579
  });
33580
+ return false;
32952
33581
  }
32953
33582
  }
32954
33583
  async revokeCompletionEntry(studentId, courseId, classId, appName) {
@@ -32959,18 +33588,18 @@ class MasteryTracker {
32959
33588
  await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
32960
33589
  sourcedId: lineItemId,
32961
33590
  title: "Mastery Completion",
32962
- status: ONEROSTER_STATUS.active,
33591
+ status: ONEROSTER_STATUS2.active,
32963
33592
  ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } },
32964
33593
  ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
32965
33594
  });
32966
33595
  await this.onerosterNamespace.assessmentResults.upsert(resultId, {
32967
33596
  sourcedId: resultId,
32968
- status: ONEROSTER_STATUS.active,
33597
+ status: ONEROSTER_STATUS2.active,
32969
33598
  assessmentLineItem: { sourcedId: lineItemId },
32970
33599
  student: { sourcedId: studentId },
32971
33600
  score: 0,
32972
33601
  scoreDate: new Date().toISOString(),
32973
- scoreStatus: SCORE_STATUS.notSubmitted,
33602
+ scoreStatus: SCORE_STATUS2.notSubmitted,
32974
33603
  inProgress: "true",
32975
33604
  metadata: {
32976
33605
  isMasteryCompletion: true,
@@ -33005,7 +33634,7 @@ class MasteryTracker {
33005
33634
  if (!playcademyMetadata) {
33006
33635
  return;
33007
33636
  }
33008
- const masterableUnits = isPlaycademyResourceMetadata(playcademyMetadata) ? playcademyMetadata.mastery?.masterableUnits : undefined;
33637
+ const masterableUnits = isPlaycademyResourceMetadata2(playcademyMetadata) ? playcademyMetadata.mastery?.masterableUnits : undefined;
33009
33638
  this.cacheManager.setResourceMasterableUnits(resourceId, masterableUnits ?? null);
33010
33639
  return masterableUnits;
33011
33640
  } catch (error) {
@@ -33085,13 +33714,11 @@ function validateSessionData(sessionData) {
33085
33714
 
33086
33715
  class ProgressRecorder {
33087
33716
  studentResolver;
33088
- cacheManager;
33089
33717
  onerosterNamespace;
33090
33718
  caliperNamespace;
33091
33719
  masteryTracker;
33092
- constructor(studentResolver, cacheManager, onerosterNamespace, caliperNamespace, masteryTracker) {
33720
+ constructor(studentResolver, onerosterNamespace, caliperNamespace, masteryTracker) {
33093
33721
  this.studentResolver = studentResolver;
33094
- this.cacheManager = cacheManager;
33095
33722
  this.onerosterNamespace = onerosterNamespace;
33096
33723
  this.caliperNamespace = caliperNamespace;
33097
33724
  this.masteryTracker = masteryTracker;
@@ -33100,26 +33727,37 @@ class ProgressRecorder {
33100
33727
  validateProgressData(progressData);
33101
33728
  const { ids, activityId, activityName, courseName, student } = await this.resolveContext(courseId, studentIdentifier, progressData);
33102
33729
  const { id: studentId, email: studentEmail } = student;
33103
- const {
33104
- score,
33105
- totalQuestions,
33106
- correctQuestions,
33107
- xpEarned = 0,
33108
- attemptNumber
33109
- } = progressData;
33110
- let extensions = progressData.extensions;
33111
- const masteryProgress = await this.masteryTracker.checkProgress({
33112
- studentId,
33113
- courseId,
33114
- resourceId: ids.resource,
33115
- masteredUnits: progressData.masteredUnits ?? 0,
33116
- masteredUnitsAbsolute: progressData.masteredUnitsAbsolute
33730
+ const { totalQuestions, correctQuestions, xpEarned = 0, attemptNumber } = progressData;
33731
+ const activityUrl = this.caliperNamespace.buildActivityUrl({
33732
+ courseId: ids.course,
33733
+ activityId,
33734
+ sensorUrl: progressData.sensorUrl
33117
33735
  });
33736
+ const courseUrl = this.caliperNamespace.buildCourseUrl(ids.course);
33737
+ let caliperLineItemId;
33738
+ try {
33739
+ caliperLineItemId = computeCaliperLineItemId(activityUrl, ids.course, courseUrl);
33740
+ } catch (error) {
33741
+ setAttributes({ "app.timeback.course_id_not_url_safe": true });
33742
+ throw error;
33743
+ }
33744
+ const legacyLineItemId = `${ids.course}-${activityId}-assessment`;
33745
+ const [currentAttemptNumber, masteryProgress] = await Promise.all([
33746
+ this.resolveAttemptNumber(attemptNumber, studentId, caliperLineItemId, legacyLineItemId),
33747
+ this.masteryTracker.checkProgress({
33748
+ studentId,
33749
+ courseId,
33750
+ resourceId: ids.resource,
33751
+ masteredUnits: progressData.masteredUnits ?? 0,
33752
+ masteredUnitsAbsolute: progressData.masteredUnitsAbsolute
33753
+ })
33754
+ ]);
33755
+ setAttributes({ "app.timeback.attempt_number": currentAttemptNumber });
33756
+ let extensions = progressData.extensions;
33118
33757
  const effectiveMasteredUnits = masteryProgress ? masteryProgress.effectiveDelta : progressData.masteredUnits ?? 0;
33119
33758
  let pctCompleteApp;
33120
33759
  let masteryAchieved = false;
33121
- let scoreStatus = SCORE_STATUS.fullyGraded;
33122
- const inProgress = "false";
33760
+ let completionEntryWritten = false;
33123
33761
  const warnings = masteryProgress?.writeWarning ? [masteryProgress.writeWarning] : undefined;
33124
33762
  if (masteryProgress) {
33125
33763
  masteryAchieved = masteryProgress.masteryAchieved;
@@ -33128,32 +33766,12 @@ class ProgressRecorder {
33128
33766
  ...extensions,
33129
33767
  ...pctCompleteApp !== undefined ? { pctCompleteApp } : {}
33130
33768
  };
33131
- if (masteryAchieved) {
33132
- scoreStatus = SCORE_STATUS.fullyGraded;
33133
- }
33134
33769
  }
33135
- const actualLineItemId = await this.resolveAssessmentLineItem(activityId, activityName, progressData.classId, ids);
33136
- const currentAttemptNumber = await this.resolveAttemptNumber(attemptNumber, score, studentId, actualLineItemId);
33137
- if (score !== undefined) {
33138
- await this.createGradebookEntry({
33139
- lineItemId: actualLineItemId,
33140
- studentId,
33141
- attemptNumber: currentAttemptNumber,
33142
- score,
33143
- xp: xpEarned,
33144
- scoreStatus,
33145
- inProgress,
33146
- appName: progressData.appName,
33147
- totalQuestions,
33148
- correctQuestions,
33149
- masteredUnits: effectiveMasteredUnits || undefined,
33150
- pctCompleteApp
33151
- });
33152
- } else {
33153
- setAttribute("app.timeback.score_provided", false);
33770
+ if (masteryAchieved) {
33771
+ setAttributes({ "app.timeback.mastery_achieved": true });
33154
33772
  }
33155
33773
  if (masteryAchieved) {
33156
- await this.masteryTracker.createCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
33774
+ completionEntryWritten = await this.masteryTracker.createCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
33157
33775
  await this.emitCourseCompletionHistoryEvent({
33158
33776
  studentId,
33159
33777
  studentEmail,
@@ -33169,30 +33787,36 @@ class ProgressRecorder {
33169
33787
  if (masteryProgress?.masteryRevoked) {
33170
33788
  await this.masteryTracker.revokeCompletionEntry(studentId, courseId, progressData.classId, progressData.appName);
33171
33789
  }
33172
- await this.emitCaliperEvent({
33173
- studentId,
33174
- studentEmail,
33175
- gameId: progressData.gameId,
33176
- activityId,
33177
- activityName,
33178
- courseId: ids.course,
33179
- courseName,
33180
- totalQuestions,
33181
- correctQuestions,
33182
- xpEarned,
33183
- masteredUnits: effectiveMasteredUnits || undefined,
33184
- attemptNumber: currentAttemptNumber,
33185
- progressData,
33186
- extensions,
33187
- runId: progressData.runId
33188
- });
33790
+ try {
33791
+ await this.emitCaliperEvent({
33792
+ studentId,
33793
+ studentEmail,
33794
+ gameId: progressData.gameId,
33795
+ activityId,
33796
+ activityName,
33797
+ courseId: ids.course,
33798
+ courseName,
33799
+ totalQuestions,
33800
+ correctQuestions,
33801
+ xpEarned,
33802
+ masteredUnits: effectiveMasteredUnits || undefined,
33803
+ attemptNumber: currentAttemptNumber,
33804
+ objectId: activityUrl,
33805
+ progressData,
33806
+ extensions,
33807
+ runId: progressData.runId
33808
+ });
33809
+ } catch (error) {
33810
+ if (completionEntryWritten) {
33811
+ setAttributes({ "app.timeback.completion_orphaned": true });
33812
+ }
33813
+ throw error;
33814
+ }
33189
33815
  return {
33190
33816
  xpAwarded: xpEarned,
33191
33817
  attemptNumber: currentAttemptNumber,
33192
33818
  masteredUnitsApplied: effectiveMasteredUnits,
33193
33819
  pctCompleteApp,
33194
- scoreStatus,
33195
- inProgress,
33196
33820
  ...warnings ? { warnings } : {}
33197
33821
  };
33198
33822
  }
@@ -33204,89 +33828,48 @@ class ProgressRecorder {
33204
33828
  const student = await this.studentResolver.resolve(studentIdentifier, progressData.studentEmail);
33205
33829
  return { ids, activityId, activityName, courseName, student };
33206
33830
  }
33207
- async resolveAssessmentLineItem(activityId, activityName, classId, ids) {
33208
- const lineItemId = `${ids.course}-${activityId}-assessment`;
33209
- let actualLineItemId = this.cacheManager.getAssessmentLineItem(lineItemId);
33210
- if (!actualLineItemId) {
33211
- actualLineItemId = await this.getOrCreateLineItem(lineItemId, activityName, classId, ids);
33212
- this.cacheManager.setAssessmentLineItem(lineItemId, actualLineItemId);
33213
- }
33214
- return actualLineItemId;
33215
- }
33216
- async resolveAttemptNumber(providedAttemptNumber, score, studentId, lineItemId) {
33831
+ async resolveAttemptNumber(providedAttemptNumber, studentId, caliperLineItemId, legacyLineItemId) {
33217
33832
  if (providedAttemptNumber) {
33833
+ setAttributes({ "app.timeback.attempt_source": "provided" });
33218
33834
  return providedAttemptNumber;
33219
33835
  }
33220
- if (score !== undefined) {
33221
- return this.determineAttemptNumber(studentId, lineItemId);
33222
- }
33223
- return 1;
33224
- }
33225
- async getOrCreateLineItem(lineItemId, activityName, classId, ids) {
33226
- try {
33227
- const lineItem = await this.onerosterNamespace.assessmentLineItems.findOrCreate(lineItemId, {
33228
- sourcedId: lineItemId,
33229
- title: activityName,
33230
- status: ONEROSTER_STATUS.active,
33231
- ...classId ? { class: { sourcedId: classId } } : { course: { sourcedId: ids.course } }
33836
+ const caliperAttempt = await this.getLatestActivityAttempt(studentId, caliperLineItemId, "attempt");
33837
+ if (caliperAttempt !== null) {
33838
+ const next = caliperAttempt + 1;
33839
+ setAttributes({
33840
+ "app.timeback.attempt_source": caliperAttempt > 0 ? "caliper" : "caliper_unreadable"
33232
33841
  });
33233
- if (!lineItem.sourcedId) {
33234
- throw new TimebackError(`Assessment line item created but has no sourcedId. ` + `This should not happen and indicates an upstream API issue.`);
33235
- }
33236
- return lineItem.sourcedId;
33237
- } catch (error) {
33238
- if (error instanceof TimebackApiError && error.status === 404) {
33239
- const errorDetails = error.details;
33240
- const description = errorDetails?.imsx_description || error.message;
33241
- 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")) {
33242
- throw new ResourceNotFoundError("TimeBack resources", "setup-not-run");
33243
- }
33842
+ if (caliperAttempt === 0) {
33843
+ setAttributes({
33844
+ "app.timeback.attempt_regressed": true,
33845
+ "app.timeback.attempt_emitted": next
33846
+ });
33244
33847
  }
33245
- throw error;
33848
+ return next;
33246
33849
  }
33247
- }
33248
- async determineAttemptNumber(studentId, lineItemId) {
33249
- const stats = await this.onerosterNamespace.assessmentResults.getAttemptStats(studentId, lineItemId);
33250
- if (stats) {
33251
- return stats.activeAttemptCount + 1;
33850
+ const legacyAttempt = await this.getLatestActivityAttempt(studentId, legacyLineItemId, "attemptNumber");
33851
+ if (legacyAttempt !== null) {
33852
+ setAttributes({
33853
+ "app.timeback.attempt_source": "legacy_seed",
33854
+ "app.timeback.legacy_seed_attempt": legacyAttempt
33855
+ });
33856
+ return legacyAttempt + 1;
33252
33857
  }
33858
+ setAttributes({ "app.timeback.attempt_source": "first" });
33253
33859
  return 1;
33254
33860
  }
33255
- async createGradebookEntry({
33256
- lineItemId,
33257
- studentId,
33258
- attemptNumber,
33259
- score,
33260
- xp,
33261
- scoreStatus,
33262
- inProgress,
33263
- appName,
33264
- totalQuestions,
33265
- correctQuestions,
33266
- masteredUnits,
33267
- pctCompleteApp
33268
- }) {
33269
- const timestamp3 = Date.now().toString(36);
33270
- const resultId = `${lineItemId}:${studentId}:${timestamp3}`;
33271
- await this.onerosterNamespace.assessmentResults.upsert(resultId, {
33272
- sourcedId: resultId,
33273
- status: ONEROSTER_STATUS.active,
33274
- assessmentLineItem: { sourcedId: lineItemId },
33275
- student: { sourcedId: studentId },
33276
- score,
33277
- scoreDate: new Date().toISOString(),
33278
- scoreStatus,
33279
- inProgress,
33280
- metadata: {
33281
- xp,
33282
- attemptNumber,
33283
- appName,
33284
- ...totalQuestions !== undefined ? { totalQuestions } : {},
33285
- ...correctQuestions !== undefined ? { correctQuestions } : {},
33286
- ...masteredUnits !== undefined ? { masteredUnits } : {},
33287
- ...pctCompleteApp !== undefined ? { pctCompleteApp } : {}
33288
- }
33861
+ async getLatestActivityAttempt(studentId, lineItemId, metadataField) {
33862
+ const results = await this.onerosterNamespace.assessmentResults.listOrThrow({
33863
+ filter: `student.sourcedId='${escapeFilterValue(studentId)}' AND assessmentLineItem.sourcedId='${escapeFilterValue(lineItemId)}' AND status='active'`,
33864
+ sort: "dateLastModified",
33865
+ orderBy: "desc",
33866
+ limit: 1
33289
33867
  });
33868
+ const latest = results[0];
33869
+ if (!latest) {
33870
+ return null;
33871
+ }
33872
+ return latest.metadata?.[metadataField] || 0;
33290
33873
  }
33291
33874
  async emitCaliperEvent({
33292
33875
  studentId,
@@ -33301,6 +33884,7 @@ class ProgressRecorder {
33301
33884
  xpEarned,
33302
33885
  masteredUnits,
33303
33886
  attemptNumber,
33887
+ objectId,
33304
33888
  progressData,
33305
33889
  extensions,
33306
33890
  runId
@@ -33318,12 +33902,18 @@ class ProgressRecorder {
33318
33902
  xpEarned,
33319
33903
  masteredUnits,
33320
33904
  attemptNumber,
33905
+ objectId,
33906
+ process: true,
33321
33907
  subject: progressData.subject,
33322
33908
  appName: progressData.appName,
33323
33909
  sensorUrl: progressData.sensorUrl,
33324
33910
  extensions: extensions || progressData.extensions,
33325
33911
  ...runId ? { runId } : {}
33326
- }).catch(catchEvent("timeback.caliper_event_failed"));
33912
+ }).catch((error) => {
33913
+ setAttributes({ "app.timeback.caliper_emit_failed": true });
33914
+ catchEvent("timeback.caliper_event_failed")(error);
33915
+ throw error;
33916
+ });
33327
33917
  }
33328
33918
  async emitCourseCompletionHistoryEvent(data) {
33329
33919
  await this.caliperNamespace.emitActivityEvent({
@@ -33501,15 +34091,15 @@ class TimebackClient {
33501
34091
  masteryTracker;
33502
34092
  constructor(config2) {
33503
34093
  this.baseUrl = TimebackClient.resolveBaseUrl(config2?.baseUrl);
33504
- this.environment = process.env[ENV_VARS.environment] === "staging" ? "staging" : "production";
34094
+ this.environment = process.env[ENV_VARS2.environment] === "staging" ? "staging" : "production";
33505
34095
  this.caliperUrl = TimebackClient.resolveCaliperUrl(config2?.caliperUrl, this.environment);
33506
34096
  this.authUrl = config2?.credentials?.authUrl;
33507
34097
  this.credentials = config2?.credentials;
33508
34098
  this.qtiCredentials = config2?.qtiCredentials;
33509
34099
  this.options = {
33510
- retries: config2?.options?.retries ?? HTTP_DEFAULTS.retries,
33511
- cacheDuration: config2?.options?.cacheDuration ?? AUTH_DEFAULTS.tokenCacheDuration,
33512
- timeout: config2?.options?.timeout ?? HTTP_DEFAULTS.timeout,
34100
+ retries: config2?.options?.retries ?? HTTP_DEFAULTS2.retries,
34101
+ cacheDuration: config2?.options?.cacheDuration ?? AUTH_DEFAULTS2.tokenCacheDuration,
34102
+ timeout: config2?.options?.timeout ?? HTTP_DEFAULTS2.timeout,
33513
34103
  sensorUrl: config2?.options?.sensorUrl
33514
34104
  };
33515
34105
  this.oneroster = createOneRosterNamespace(this);
@@ -33519,7 +34109,7 @@ class TimebackClient {
33519
34109
  this.cacheManager = new TimebackCacheManager;
33520
34110
  this.studentResolver = new StudentResolver(this.cacheManager, this.oneroster);
33521
34111
  this.masteryTracker = new MasteryTracker(this.cacheManager, this.oneroster, this.edubridge);
33522
- this.progressRecorder = new ProgressRecorder(this.studentResolver, this.cacheManager, this.oneroster, this.caliper, this.masteryTracker);
34112
+ this.progressRecorder = new ProgressRecorder(this.studentResolver, this.oneroster, this.caliper, this.masteryTracker);
33523
34113
  this.sessionRecorder = new SessionRecorder(this.studentResolver, this.caliper);
33524
34114
  this.adminEventRecorder = new AdminEventRecorder(this.studentResolver, this.oneroster, this.caliper, this.environment);
33525
34115
  if (this.credentials) {
@@ -33528,16 +34118,16 @@ class TimebackClient {
33528
34118
  }
33529
34119
  static async init(config2) {
33530
34120
  let credentials = config2?.credentials;
33531
- if (!credentials && process.env[ENV_VARS.clientId] && process.env[ENV_VARS.clientSecret]) {
34121
+ if (!credentials && process.env[ENV_VARS2.clientId] && process.env[ENV_VARS2.clientSecret]) {
33532
34122
  credentials = {
33533
- clientId: process.env[ENV_VARS.clientId],
33534
- clientSecret: process.env[ENV_VARS.clientSecret]
34123
+ clientId: process.env[ENV_VARS2.clientId],
34124
+ clientSecret: process.env[ENV_VARS2.clientSecret]
33535
34125
  };
33536
34126
  }
33537
- const qtiCredentials = config2?.qtiCredentials ?? (process.env[ENV_VARS.qtiClientId] && process.env[ENV_VARS.qtiClientSecret] && process.env[ENV_VARS.qtiAuthUrl] ? {
33538
- clientId: process.env[ENV_VARS.qtiClientId],
33539
- clientSecret: process.env[ENV_VARS.qtiClientSecret],
33540
- authUrl: process.env[ENV_VARS.qtiAuthUrl]
34127
+ const qtiCredentials = config2?.qtiCredentials ?? (process.env[ENV_VARS2.qtiClientId] && process.env[ENV_VARS2.qtiClientSecret] && process.env[ENV_VARS2.qtiAuthUrl] ? {
34128
+ clientId: process.env[ENV_VARS2.qtiClientId],
34129
+ clientSecret: process.env[ENV_VARS2.qtiClientSecret],
34130
+ authUrl: process.env[ENV_VARS2.qtiAuthUrl]
33541
34131
  } : undefined);
33542
34132
  return new TimebackClient({
33543
34133
  ...config2,
@@ -33550,15 +34140,15 @@ class TimebackClient {
33550
34140
  if (explicit) {
33551
34141
  return explicit;
33552
34142
  }
33553
- const envName = process.env[ENV_VARS.environment] === "staging" ? "staging" : "production";
33554
- return TIMEBACK_API_URLS[envName];
34143
+ const envName = process.env[ENV_VARS2.environment] === "staging" ? "staging" : "production";
34144
+ return TIMEBACK_API_URLS2[envName];
33555
34145
  }
33556
34146
  static resolveCaliperUrl(input, environment = "production") {
33557
34147
  const explicit = (input || "").trim();
33558
34148
  if (explicit) {
33559
34149
  return explicit;
33560
34150
  }
33561
- return CALIPER_API_URLS[environment];
34151
+ return CALIPER_API_URLS2[environment];
33562
34152
  }
33563
34153
  getBaseUrl() {
33564
34154
  return this.baseUrl;
@@ -33679,14 +34269,14 @@ class TimebackClient {
33679
34269
  await this._ensureAuthenticated();
33680
34270
  return this.token;
33681
34271
  }
33682
- throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS.qtiClientId}, ${ENV_VARS.qtiClientSecret}, and ${ENV_VARS.qtiAuthUrl}.`);
34272
+ throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS2.qtiClientId}, ${ENV_VARS2.qtiClientSecret}, and ${ENV_VARS2.qtiAuthUrl}.`);
33683
34273
  }
33684
34274
  async ensureQtiAuthenticated() {
33685
34275
  if (this.isQtiAuthenticated()) {
33686
34276
  return;
33687
34277
  }
33688
34278
  if (!this.qtiCredentials) {
33689
- throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS.qtiClientId}, ${ENV_VARS.qtiClientSecret}, and ${ENV_VARS.qtiAuthUrl}.`);
34279
+ throw new TimebackAuthenticationError(`QTI credentials are required. Set ${ENV_VARS2.qtiClientId}, ${ENV_VARS2.qtiClientSecret}, and ${ENV_VARS2.qtiAuthUrl}.`);
33690
34280
  }
33691
34281
  try {
33692
34282
  const tokenData = await getTimebackTokenResponse({
@@ -33698,11 +34288,11 @@ class TimebackClient {
33698
34288
  this.setQtiToken(tokenData.access_token, tokenData.expires_in);
33699
34289
  } catch (error) {
33700
34290
  const errMsg = errorMessage(error);
33701
- throw new TimebackAuthenticationError(`QTI authentication failed: ${errMsg}. ` + `Verify that ${ENV_VARS.qtiClientId}, ${ENV_VARS.qtiClientSecret}, and ${ENV_VARS.qtiAuthUrl} are correct.`);
34291
+ throw new TimebackAuthenticationError(`QTI authentication failed: ${errMsg}. ` + `Verify that ${ENV_VARS2.qtiClientId}, ${ENV_VARS2.qtiClientSecret}, and ${ENV_VARS2.qtiAuthUrl} are correct.`);
33702
34292
  }
33703
34293
  }
33704
34294
  canUseCoreCredentialsForQti() {
33705
- return this.baseUrl.replace(/\/$/, "") === TIMEBACK_API_URLS.production;
34295
+ return this.baseUrl.replace(/\/$/, "") === TIMEBACK_API_URLS2.production;
33706
34296
  }
33707
34297
  async resolveStudent(studentIdentifier, providedEmail) {
33708
34298
  return this.studentResolver.resolve(studentIdentifier, providedEmail);
@@ -33723,8 +34313,8 @@ class TimebackClient {
33723
34313
  await this._ensureAuthenticated();
33724
34314
  const edubridgeEnrollments = await this.edubridge.enrollments.listByUser(studentId);
33725
34315
  const enrollments = edubridgeEnrollments.map((enrollment) => {
33726
- const grades = enrollment.course.grades ? enrollment.course.grades.map((g) => parseInt(g, 10)).filter(isTimebackGrade2) : null;
33727
- const subjects = enrollment.course.subjects ? enrollment.course.subjects.filter(isTimebackSubject2) : null;
34316
+ const grades = enrollment.course.grades ? enrollment.course.grades.map((g) => parseInt(g, 10)).filter(isTimebackGrade3) : null;
34317
+ const subjects = enrollment.course.subjects ? enrollment.course.subjects.filter(isTimebackSubject3) : null;
33728
34318
  return {
33729
34319
  sourcedId: enrollment.id,
33730
34320
  title: enrollment.course.title,
@@ -33790,9 +34380,9 @@ class TimebackClient {
33790
34380
  if (options?.include?.perCourse) {
33791
34381
  const gradeStr = enrollment.course.grades?.[0];
33792
34382
  const parsedGrade = gradeStr ? parseInt(gradeStr, 10) : 0;
33793
- const grade = isTimebackGrade2(parsedGrade) ? parsedGrade : 0;
34383
+ const grade = isTimebackGrade3(parsedGrade) ? parsedGrade : 0;
33794
34384
  const subjectStr = enrollment.course.subjects?.[0];
33795
- const subject = subjectStr && isTimebackSubject2(subjectStr) ? subjectStr : "None";
34385
+ const subject = subjectStr && isTimebackSubject3(subjectStr) ? subjectStr : "None";
33796
34386
  courses.push({
33797
34387
  grade,
33798
34388
  subject,
@@ -33866,9 +34456,9 @@ class TimebackClient {
33866
34456
  if (options?.include?.perCourse) {
33867
34457
  const gradeStr = enrollment.course.grades?.[0];
33868
34458
  const parsedGrade = gradeStr ? parseInt(gradeStr, 10) : 0;
33869
- const grade = isTimebackGrade2(parsedGrade) ? parsedGrade : 0;
34459
+ const grade = isTimebackGrade3(parsedGrade) ? parsedGrade : 0;
33870
34460
  const subjectStr = enrollment.course.subjects?.[0];
33871
- const subject = subjectStr && isTimebackSubject2(subjectStr) ? subjectStr : "None";
34461
+ const subject = subjectStr && isTimebackSubject3(subjectStr) ? subjectStr : "None";
33872
34462
  courses.push({
33873
34463
  grade,
33874
34464
  subject,
@@ -33924,6 +34514,12 @@ class TimebackClient {
33924
34514
  async cleanup(courseId) {
33925
34515
  return deleteTimebackResources(this, courseId);
33926
34516
  }
34517
+ async deactivateCourse(courseId) {
34518
+ return updateTimebackCourseStatus(this, courseId, "tobedeleted");
34519
+ }
34520
+ async reactivateCourse(courseId) {
34521
+ return updateTimebackCourseStatus(this, courseId, "active");
34522
+ }
33927
34523
  }
33928
34524
  var __defProp2, __export2 = (target, all) => {
33929
34525
  for (var name3 in all)
@@ -33933,7 +34529,7 @@ var __defProp2, __export2 = (target, all) => {
33933
34529
  configurable: true,
33934
34530
  set: (newValue) => all[name3] = () => newValue
33935
34531
  });
33936
- }, __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;
34532
+ }, __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;
33937
34533
  var init_dist2 = __esm(() => {
33938
34534
  init_src();
33939
34535
  init_src();
@@ -33959,293 +34555,7 @@ var init_dist2 = __esm(() => {
33959
34555
  init_spans();
33960
34556
  init_esm();
33961
34557
  __defProp2 = Object.defineProperty;
33962
- init_constants4 = __esm2(() => {
33963
- TIMEBACK_API_URLS = {
33964
- production: "https://api.alpha-1edtech.ai",
33965
- staging: "https://api.staging.alpha-1edtech.com"
33966
- };
33967
- TIMEBACK_AUTH_URLS = {
33968
- production: "https://prod-beyond-timeback-api-2-idp.auth.us-east-1.amazoncognito.com",
33969
- staging: "https://alpha-auth-development-idp.auth.us-west-2.amazoncognito.com"
33970
- };
33971
- CALIPER_API_URLS = {
33972
- production: "https://caliper.alpha-1edtech.ai",
33973
- staging: "https://caliper-staging.alpha-1edtech.com"
33974
- };
33975
- ONEROSTER_ENDPOINTS = {
33976
- organizations: "/ims/oneroster/rostering/v1p2/orgs",
33977
- courses: "/ims/oneroster/rostering/v1p2/courses",
33978
- courseComponents: "/ims/oneroster/rostering/v1p2/courses/components",
33979
- resources: "/ims/oneroster/resources/v1p2/resources",
33980
- componentResources: "/ims/oneroster/rostering/v1p2/courses/component-resources",
33981
- classes: "/ims/oneroster/rostering/v1p2/classes",
33982
- enrollments: "/ims/oneroster/rostering/v1p2/enrollments",
33983
- assessmentLineItems: "/ims/oneroster/gradebook/v1p2/assessmentLineItems",
33984
- assessmentResults: "/ims/oneroster/gradebook/v1p2/assessmentResults",
33985
- users: "/ims/oneroster/rostering/v1p2/users"
33986
- };
33987
- QTI_ENDPOINTS = {
33988
- assessmentTests: "/assessment-tests",
33989
- assessmentItems: "/assessment-items"
33990
- };
33991
- CALIPER_ENDPOINTS = {
33992
- event: "/caliper/event",
33993
- events: "/caliper/events",
33994
- validate: "/caliper/event/validate"
33995
- };
33996
- CALIPER_CONSTANTS = {
33997
- context: "http://purl.imsglobal.org/ctx/caliper/v1p2",
33998
- profile: "TimebackProfile",
33999
- dataVersion: "http://purl.imsglobal.org/ctx/caliper/v1p2"
34000
- };
34001
- TIMEBACK_EVENT_TYPES = {
34002
- activityEvent: "ActivityEvent",
34003
- timeSpentEvent: "TimeSpentEvent"
34004
- };
34005
- TIMEBACK_ACTIONS = {
34006
- completed: "Completed",
34007
- spentTime: "SpentTime"
34008
- };
34009
- TIMEBACK_TYPES = {
34010
- user: "TimebackUser",
34011
- activityContext: "TimebackActivityContext",
34012
- activityMetricsCollection: "TimebackActivityMetricsCollection",
34013
- timeSpentMetricsCollection: "TimebackTimeSpentMetricsCollection"
34014
- };
34015
- ACTIVITY_METRIC_TYPES = {
34016
- totalQuestions: "totalQuestions",
34017
- correctQuestions: "correctQuestions",
34018
- xpEarned: "xpEarned",
34019
- masteredUnits: "masteredUnits"
34020
- };
34021
- TIME_METRIC_TYPES = {
34022
- active: "active",
34023
- inactive: "inactive",
34024
- waste: "waste",
34025
- unknown: "unknown",
34026
- antiPattern: "anti-pattern"
34027
- };
34028
- TIMEBACK_SUBJECTS2 = [
34029
- "Math",
34030
- "FastMath",
34031
- "Science",
34032
- "Social Studies",
34033
- "Language",
34034
- "Reading",
34035
- "Vocabulary",
34036
- "Writing"
34037
- ];
34038
- TIMEBACK_GRADE_LEVELS = [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13];
34039
- TIMEBACK_GRADE_LEVEL_LABELS = {
34040
- "-1": "pre-k",
34041
- "0": "kindergarten",
34042
- "1": "1st grade",
34043
- "2": "2nd grade",
34044
- "3": "3rd grade",
34045
- "4": "4th grade",
34046
- "5": "5th grade",
34047
- "6": "6th grade",
34048
- "7": "7th grade",
34049
- "8": "8th grade",
34050
- "9": "9th grade",
34051
- "10": "10th grade",
34052
- "11": "11th grade",
34053
- "12": "12th grade",
34054
- "13": "AP"
34055
- };
34056
- CALIPER_SUBJECTS = {
34057
- Reading: "Reading",
34058
- Language: "Language",
34059
- Vocabulary: "Vocabulary",
34060
- SocialStudies: "Social Studies",
34061
- Writing: "Writing",
34062
- Science: "Science",
34063
- FastMath: "FastMath",
34064
- Math: "Math",
34065
- None: "None"
34066
- };
34067
- ONEROSTER_STATUS = {
34068
- active: "active",
34069
- toBeDeleted: "tobedeleted"
34070
- };
34071
- SCORE_STATUS = {
34072
- exempt: "exempt",
34073
- fullyGraded: "fully graded",
34074
- notSubmitted: "not submitted",
34075
- partiallyGraded: "partially graded",
34076
- submitted: "submitted"
34077
- };
34078
- ENV_VARS = {
34079
- clientId: "TIMEBACK_CLIENT_ID",
34080
- clientSecret: "TIMEBACK_CLIENT_SECRET",
34081
- baseUrl: "TIMEBACK_BASE_URL",
34082
- environment: "TIMEBACK_ENVIRONMENT",
34083
- vendorResourceId: "TIMEBACK_VENDOR_RESOURCE_ID",
34084
- launchBaseUrl: "GAME_URL",
34085
- qtiClientId: "QTI_CLIENT_ID",
34086
- qtiClientSecret: "QTI_CLIENT_SECRET",
34087
- qtiAuthUrl: "QTI_AUTH_URL"
34088
- };
34089
- HTTP_DEFAULTS = {
34090
- timeout: 30000,
34091
- retries: 3,
34092
- retryBackoffBase: 2
34093
- };
34094
- AUTH_DEFAULTS = {
34095
- tokenCacheDuration: 50000
34096
- };
34097
- CACHE_DEFAULTS = {
34098
- defaultTTL: 10 * 60 * 1000,
34099
- defaultMaxSize: 500,
34100
- defaultName: "TimebackCache",
34101
- studentTTL: 10 * 60 * 1000,
34102
- studentMaxSize: 500,
34103
- assessmentTTL: 30 * 60 * 1000,
34104
- assessmentMaxSize: 200,
34105
- enrollmentTTL: 5 * 1000,
34106
- enrollmentMaxSize: 100
34107
- };
34108
- CONFIG_DEFAULTS = {
34109
- fileNames: ["timeback.config.js", "timeback.config.json"]
34110
- };
34111
- PLAYCADEMY_DEFAULTS = {
34112
- organization: TIMEBACK_ORG_SOURCED_ID,
34113
- launchBaseUrls: PLAYCADEMY_BASE_URLS
34114
- };
34115
- RESOURCE_DEFAULTS = {
34116
- organization: {
34117
- name: TIMEBACK_ORG_NAME,
34118
- type: TIMEBACK_ORG_TYPE
34119
- },
34120
- course: {
34121
- gradingScheme: TIMEBACK_COURSE_DEFAULTS.gradingScheme,
34122
- level: TIMEBACK_COURSE_DEFAULTS.level,
34123
- metadata: {
34124
- goals: TIMEBACK_COURSE_DEFAULTS.goals,
34125
- metrics: TIMEBACK_COURSE_DEFAULTS.metrics
34126
- }
34127
- },
34128
- component: TIMEBACK_COMPONENT_DEFAULTS,
34129
- resource: TIMEBACK_RESOURCE_DEFAULTS,
34130
- componentResource: TIMEBACK_COMPONENT_RESOURCE_DEFAULTS
34131
- };
34132
- HTTP_STATUS = {
34133
- CLIENT_ERROR_MIN: 400,
34134
- CLIENT_ERROR_MAX: 500,
34135
- SERVER_ERROR_MIN: 500
34136
- };
34137
- ERROR_NAMES = {
34138
- timebackAuth: "TimebackAuthError",
34139
- timebackApi: "TimebackApiError",
34140
- timebackConfig: "TimebackConfigError",
34141
- timebackSdk: "TimebackSDKError"
34142
- };
34143
- });
34144
- exports_verify = {};
34145
- __export2(exports_verify, {
34146
- verifyTimebackResources: () => verifyTimebackResources,
34147
- fetchTimebackConfig: () => fetchTimebackConfig
34148
- });
34149
- init_verify = __esm2(() => {
34150
- init_constants4();
34151
- });
34152
- init_constants4();
34153
- TimebackError = class TimebackError extends Error {
34154
- constructor(message) {
34155
- super(message);
34156
- this.name = ERROR_NAMES.timebackSdk;
34157
- }
34158
- };
34159
- TimebackApiError = class TimebackApiError extends Error {
34160
- status;
34161
- details;
34162
- constructor(status, message, details) {
34163
- super(`${status} ${message}`);
34164
- this.name = ERROR_NAMES.timebackApi;
34165
- this.status = status;
34166
- this.details = details;
34167
- Object.setPrototypeOf(this, TimebackApiError.prototype);
34168
- }
34169
- };
34170
- TimebackAuthenticationError = class TimebackAuthenticationError extends TimebackError {
34171
- constructor(message) {
34172
- super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
34173
- this.name = "TimebackAuthenticationError";
34174
- Object.setPrototypeOf(this, TimebackAuthenticationError.prototype);
34175
- }
34176
- };
34177
- StudentNotFoundError = class StudentNotFoundError extends TimebackError {
34178
- identifier;
34179
- identifierType;
34180
- constructor(identifier, identifierType = "email") {
34181
- 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.`);
34182
- this.name = "StudentNotFoundError";
34183
- this.identifier = identifier;
34184
- this.identifierType = identifierType;
34185
- Object.setPrototypeOf(this, StudentNotFoundError.prototype);
34186
- }
34187
- };
34188
- ConfigurationError = class ConfigurationError extends TimebackError {
34189
- field;
34190
- constructor(field, message) {
34191
- super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
34192
- this.name = "ConfigurationError";
34193
- this.field = field;
34194
- Object.setPrototypeOf(this, ConfigurationError.prototype);
34195
- }
34196
- };
34197
- ResourceNotFoundError = class ResourceNotFoundError extends TimebackError {
34198
- resourceType;
34199
- sourcedId;
34200
- constructor(resourceType, sourcedId) {
34201
- 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`;
34202
- super(message);
34203
- this.name = "ResourceNotFoundError";
34204
- this.resourceType = resourceType;
34205
- this.sourcedId = sourcedId;
34206
- Object.setPrototypeOf(this, ResourceNotFoundError.prototype);
34207
- }
34208
- };
34209
- init_constants4();
34210
- SUBJECT_VALUES = TIMEBACK_SUBJECTS2;
34211
- GRADE_VALUES = TIMEBACK_GRADE_LEVELS;
34212
- init_verify();
34213
- init_constants4();
34214
- init_constants4();
34215
- if (process.env.DEBUG === "true") {
34216
- process.env.TERM = "dumb";
34217
- }
34218
- TimebackAuthError = class TimebackAuthError extends Error {
34219
- statusCode;
34220
- constructor(message, statusCode) {
34221
- super(message);
34222
- this.name = ERROR_NAMES.timebackAuth;
34223
- this.statusCode = statusCode;
34224
- }
34225
- };
34226
- init_constants4();
34227
- UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
34228
- storage = new AsyncLocalStorage;
34229
- init_constants4();
34230
- init_constants4();
34231
- init_constants4();
34232
- init_constants4();
34233
- init_constants4();
34234
- init_constants4();
34235
- init_constants4();
34236
- init_constants4();
34237
- EmailSchema = exports_external.string().email();
34238
- StudentSourcedIdSchema = exports_external.string().min(1, {
34239
- message: "Student sourcedId must be a non-empty string"
34240
- });
34241
- StudentIdentifierSchema = exports_external.union([EmailSchema, StudentSourcedIdSchema]);
34242
- });
34243
-
34244
- // ../timeback/dist/constants.js
34245
- 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;
34246
- var init_constants5 = __esm(() => {
34247
- init_src();
34248
- init_constants6 = __esm3(() => {
34558
+ init_constants5 = __esm3(() => {
34249
34559
  TIMEBACK_API_URLS2 = {
34250
34560
  production: "https://api.alpha-1edtech.ai",
34251
34561
  staging: "https://api.staging.alpha-1edtech.com"
@@ -34427,36 +34737,153 @@ var init_constants5 = __esm(() => {
34427
34737
  timebackSdk: "TimebackSDKError"
34428
34738
  };
34429
34739
  });
34430
- init_constants6();
34740
+ init_errors4 = __esm3(() => {
34741
+ init_constants5();
34742
+ TimebackError = class TimebackError2 extends Error {
34743
+ constructor(message) {
34744
+ super(message);
34745
+ this.name = ERROR_NAMES2.timebackSdk;
34746
+ }
34747
+ };
34748
+ TimebackApiError = class TimebackApiError2 extends Error {
34749
+ status;
34750
+ details;
34751
+ constructor(status, message, details) {
34752
+ super(`${status} ${message}`);
34753
+ this.name = ERROR_NAMES2.timebackApi;
34754
+ this.status = status;
34755
+ this.details = details;
34756
+ Object.setPrototypeOf(this, TimebackApiError2.prototype);
34757
+ }
34758
+ };
34759
+ TimebackAuthenticationError = class TimebackAuthenticationError2 extends TimebackError {
34760
+ constructor(message) {
34761
+ super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
34762
+ this.name = "TimebackAuthenticationError";
34763
+ Object.setPrototypeOf(this, TimebackAuthenticationError2.prototype);
34764
+ }
34765
+ };
34766
+ StudentNotFoundError = class StudentNotFoundError2 extends TimebackError {
34767
+ identifier;
34768
+ identifierType;
34769
+ constructor(identifier, identifierType = "email") {
34770
+ 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.`);
34771
+ this.name = "StudentNotFoundError";
34772
+ this.identifier = identifier;
34773
+ this.identifierType = identifierType;
34774
+ Object.setPrototypeOf(this, StudentNotFoundError2.prototype);
34775
+ }
34776
+ };
34777
+ ConfigurationError = class ConfigurationError2 extends TimebackError {
34778
+ field;
34779
+ constructor(field, message) {
34780
+ super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
34781
+ this.name = "ConfigurationError";
34782
+ this.field = field;
34783
+ Object.setPrototypeOf(this, ConfigurationError2.prototype);
34784
+ }
34785
+ };
34786
+ ResourceAlreadyExistsError = class ResourceAlreadyExistsError2 extends TimebackError {
34787
+ resourceType;
34788
+ sourcedId;
34789
+ originalError;
34790
+ constructor(resourceType, sourcedId, originalError) {
34791
+ super(`${resourceType} with ID '${sourcedId}' already exists`);
34792
+ this.name = "ResourceAlreadyExistsError";
34793
+ this.resourceType = resourceType;
34794
+ this.sourcedId = sourcedId;
34795
+ this.originalError = originalError;
34796
+ Object.setPrototypeOf(this, ResourceAlreadyExistsError2.prototype);
34797
+ }
34798
+ };
34799
+ ResourceNotFoundError = class ResourceNotFoundError2 extends TimebackError {
34800
+ resourceType;
34801
+ sourcedId;
34802
+ constructor(resourceType, sourcedId) {
34803
+ 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`;
34804
+ super(message);
34805
+ this.name = "ResourceNotFoundError";
34806
+ this.resourceType = resourceType;
34807
+ this.sourcedId = sourcedId;
34808
+ Object.setPrototypeOf(this, ResourceNotFoundError2.prototype);
34809
+ }
34810
+ };
34811
+ });
34812
+ init_ids = __esm3(() => {
34813
+ init_errors4();
34814
+ 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;
34815
+ });
34816
+ exports_verify = {};
34817
+ __export2(exports_verify, {
34818
+ verifyTimebackResources: () => verifyTimebackResources,
34819
+ fetchTimebackConfig: () => fetchTimebackConfig
34820
+ });
34821
+ init_verify = __esm3(() => {
34822
+ init_constants5();
34823
+ init_ids();
34824
+ });
34825
+ init_constants5();
34826
+ SUBJECT_VALUES2 = TIMEBACK_SUBJECTS3;
34827
+ GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS2;
34828
+ init_ids();
34829
+ init_ids();
34830
+ init_verify();
34831
+ init_ids();
34832
+ init_constants5();
34833
+ init_errors4();
34834
+ init_constants5();
34835
+ if (process.env.DEBUG === "true") {
34836
+ process.env.TERM = "dumb";
34837
+ }
34838
+ TimebackAuthError = class TimebackAuthError extends Error {
34839
+ statusCode;
34840
+ constructor(message, statusCode) {
34841
+ super(message);
34842
+ this.name = ERROR_NAMES2.timebackAuth;
34843
+ this.statusCode = statusCode;
34844
+ }
34845
+ };
34846
+ init_ids();
34847
+ init_constants5();
34848
+ init_errors4();
34849
+ UUID_PATTERN = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi;
34850
+ storage = new AsyncLocalStorage;
34851
+ init_constants5();
34852
+ init_constants5();
34853
+ init_errors4();
34854
+ init_constants5();
34855
+ init_constants5();
34856
+ init_constants5();
34857
+ init_constants5();
34858
+ init_constants5();
34859
+ init_ids();
34860
+ init_ids();
34861
+ init_errors4();
34862
+ init_ids();
34863
+ init_errors4();
34864
+ EmailSchema = exports_external.string().email();
34865
+ StudentSourcedIdSchema = exports_external.string().min(1, {
34866
+ message: "Student sourcedId must be a non-empty string"
34867
+ });
34868
+ StudentIdentifierSchema = exports_external.union([EmailSchema, StudentSourcedIdSchema]);
34869
+ init_ids();
34431
34870
  });
34432
34871
 
34433
- // ../timeback/dist/types.js
34434
- function isObject2(value) {
34435
- return typeof value === "object" && value !== null;
34436
- }
34437
- function isCourseMetadata(value) {
34438
- return isObject2(value);
34439
- }
34440
- function isResourceMetadata(value) {
34441
- return isObject2(value);
34442
- }
34443
- function isPlaycademyResourceMetadata2(value) {
34444
- if (!isObject2(value)) {
34445
- return false;
34872
+ // ../timeback/dist/constants.js
34873
+ function deriveTimebackCourseLevelFromGrade(grade) {
34874
+ if (grade === 13) {
34875
+ return TIMEBACK_COURSE_DEFAULTS.level.ap;
34446
34876
  }
34447
- if (!("mastery" in value) || value.mastery === undefined) {
34448
- return true;
34877
+ if (grade <= 5) {
34878
+ return TIMEBACK_COURSE_DEFAULTS.level.elementary;
34449
34879
  }
34450
- return isObject2(value.mastery);
34451
- }
34452
- function isTimebackSubject3(value) {
34453
- return typeof value === "string" && SUBJECT_VALUES2.includes(value);
34454
- }
34455
- function isTimebackGrade3(value) {
34456
- return typeof value === "number" && Number.isInteger(value) && GRADE_VALUES2.includes(value);
34880
+ if (grade <= 8) {
34881
+ return TIMEBACK_COURSE_DEFAULTS.level.middle;
34882
+ }
34883
+ return TIMEBACK_COURSE_DEFAULTS.level.high;
34457
34884
  }
34458
- 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;
34459
- var init_types3 = __esm(() => {
34885
+ 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;
34886
+ var init_constants6 = __esm(() => {
34460
34887
  init_src();
34461
34888
  init_constants7 = __esm4(() => {
34462
34889
  TIMEBACK_API_URLS3 = {
@@ -34641,8 +35068,6 @@ var init_types3 = __esm(() => {
34641
35068
  };
34642
35069
  });
34643
35070
  init_constants7();
34644
- SUBJECT_VALUES2 = TIMEBACK_SUBJECTS4;
34645
- GRADE_VALUES2 = TIMEBACK_GRADE_LEVELS3;
34646
35071
  });
34647
35072
 
34648
35073
  // ../timeback/dist/utils.js
@@ -34664,7 +35089,7 @@ function deriveAssessmentBankIds(courseId) {
34664
35089
  function escapeFilterValue2(value) {
34665
35090
  return value.replaceAll("'", String.raw`\'`);
34666
35091
  }
34667
- 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;
35092
+ 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;
34668
35093
  var init_utils6 = __esm(() => {
34669
35094
  init_src();
34670
35095
  init_constants8 = __esm5(() => {
@@ -34849,6 +35274,82 @@ var init_utils6 = __esm(() => {
34849
35274
  timebackSdk: "TimebackSDKError"
34850
35275
  };
34851
35276
  });
35277
+ init_errors5 = __esm5(() => {
35278
+ init_constants8();
35279
+ TimebackError2 = class TimebackError3 extends Error {
35280
+ constructor(message) {
35281
+ super(message);
35282
+ this.name = ERROR_NAMES4.timebackSdk;
35283
+ }
35284
+ };
35285
+ TimebackApiError2 = class TimebackApiError3 extends Error {
35286
+ status;
35287
+ details;
35288
+ constructor(status, message, details) {
35289
+ super(`${status} ${message}`);
35290
+ this.name = ERROR_NAMES4.timebackApi;
35291
+ this.status = status;
35292
+ this.details = details;
35293
+ Object.setPrototypeOf(this, TimebackApiError3.prototype);
35294
+ }
35295
+ };
35296
+ TimebackAuthenticationError2 = class TimebackAuthenticationError3 extends TimebackError2 {
35297
+ constructor(message) {
35298
+ super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
35299
+ this.name = "TimebackAuthenticationError";
35300
+ Object.setPrototypeOf(this, TimebackAuthenticationError3.prototype);
35301
+ }
35302
+ };
35303
+ StudentNotFoundError2 = class StudentNotFoundError3 extends TimebackError2 {
35304
+ identifier;
35305
+ identifierType;
35306
+ constructor(identifier, identifierType = "email") {
35307
+ 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.`);
35308
+ this.name = "StudentNotFoundError";
35309
+ this.identifier = identifier;
35310
+ this.identifierType = identifierType;
35311
+ Object.setPrototypeOf(this, StudentNotFoundError3.prototype);
35312
+ }
35313
+ };
35314
+ ConfigurationError2 = class ConfigurationError3 extends TimebackError2 {
35315
+ field;
35316
+ constructor(field, message) {
35317
+ super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
35318
+ this.name = "ConfigurationError";
35319
+ this.field = field;
35320
+ Object.setPrototypeOf(this, ConfigurationError3.prototype);
35321
+ }
35322
+ };
35323
+ ResourceAlreadyExistsError2 = class ResourceAlreadyExistsError3 extends TimebackError2 {
35324
+ resourceType;
35325
+ sourcedId;
35326
+ originalError;
35327
+ constructor(resourceType, sourcedId, originalError) {
35328
+ super(`${resourceType} with ID '${sourcedId}' already exists`);
35329
+ this.name = "ResourceAlreadyExistsError";
35330
+ this.resourceType = resourceType;
35331
+ this.sourcedId = sourcedId;
35332
+ this.originalError = originalError;
35333
+ Object.setPrototypeOf(this, ResourceAlreadyExistsError3.prototype);
35334
+ }
35335
+ };
35336
+ ResourceNotFoundError2 = class ResourceNotFoundError3 extends TimebackError2 {
35337
+ resourceType;
35338
+ sourcedId;
35339
+ constructor(resourceType, sourcedId) {
35340
+ 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`;
35341
+ super(message);
35342
+ this.name = "ResourceNotFoundError";
35343
+ this.resourceType = resourceType;
35344
+ this.sourcedId = sourcedId;
35345
+ Object.setPrototypeOf(this, ResourceNotFoundError3.prototype);
35346
+ }
35347
+ };
35348
+ });
35349
+ init_ids2 = __esm5(() => {
35350
+ init_errors5();
35351
+ 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;
35352
+ });
34852
35353
  init_constants8();
34853
35354
  init_constants8();
34854
35355
  if (process.env.DEBUG === "true") {
@@ -35011,333 +35512,6 @@ var init_timeback_admin_util = __esm(() => {
35011
35512
  init_errors();
35012
35513
  });
35013
35514
 
35014
- // ../api-core/src/utils/timeback.util.ts
35015
- function isRecord2(value) {
35016
- return typeof value === "object" && value !== null;
35017
- }
35018
- function filterEnrollmentsByGame(enrollments, gameId) {
35019
- return enrollments.filter((enrollment) => enrollment.gameId === gameId).map(({ gameId: _, ...enrollment }) => enrollment);
35020
- }
35021
- function mapEnrollmentsToUserEnrollments(enrollments, integrations) {
35022
- const enrollmentByCourse = new Map(enrollments.map((enrollment) => [enrollment.courseId, enrollment]));
35023
- const courseToSchool = new Map(enrollments.filter((enrollment) => enrollment.school?.id).map((enrollment) => [enrollment.courseId, enrollment.school.id]));
35024
- return integrations.map((integration) => {
35025
- const enrollment = enrollmentByCourse.get(integration.courseId);
35026
- return {
35027
- gameId: integration.gameId,
35028
- grade: integration.grade,
35029
- subject: integration.subject,
35030
- courseId: integration.courseId,
35031
- orgId: courseToSchool.get(integration.courseId),
35032
- ...enrollment ? { id: enrollment.sourcedId } : {}
35033
- };
35034
- });
35035
- }
35036
- function getStringValue(value) {
35037
- return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
35038
- }
35039
- function parseSourcedIdFromUrl(url2) {
35040
- if (!url2) {
35041
- return;
35042
- }
35043
- const trimmed = url2.trim().replace(/\/$/, "");
35044
- if (!trimmed) {
35045
- return;
35046
- }
35047
- const segments = trimmed.split("/");
35048
- const lastSegment = segments.at(-1);
35049
- return lastSegment ? decodeURIComponent(lastSegment) : undefined;
35050
- }
35051
- function getGeneratedMetricValue(event, type) {
35052
- const items = event.generated?.items;
35053
- if (!Array.isArray(items)) {
35054
- return;
35055
- }
35056
- const metric = items.find((item) => item?.type === type);
35057
- if (!metric) {
35058
- return;
35059
- }
35060
- const value = typeof metric.value === "number" ? metric.value : Number(metric.value);
35061
- return Number.isFinite(value) ? value : undefined;
35062
- }
35063
- function getMergedCaliperExtensions(event) {
35064
- const objectActivityExtensions = isRecord2(event.object.activity?.extensions) ? event.object.activity.extensions : undefined;
35065
- const generatedExtensions = isRecord2(event.generated?.extensions) ? event.generated.extensions : undefined;
35066
- const eventExtensions = isRecord2(event.extensions) ? event.extensions : undefined;
35067
- return {
35068
- ...objectActivityExtensions,
35069
- ...generatedExtensions,
35070
- ...eventExtensions
35071
- };
35072
- }
35073
- function getPlaycademyMetadata(event) {
35074
- const extensions = getMergedCaliperExtensions(event);
35075
- return isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
35076
- }
35077
- function getActivityId(event, playcademy) {
35078
- const metadataActivityId = getStringValue(playcademy?.activityId);
35079
- if (metadataActivityId) {
35080
- return metadataActivityId;
35081
- }
35082
- const activityId = getStringValue(event.object.activity?.id);
35083
- if (activityId) {
35084
- return activityId;
35085
- }
35086
- const objectId = getStringValue(event.object.id);
35087
- if (!objectId) {
35088
- return;
35089
- }
35090
- const trimmed = objectId.replace(/\/$/, "");
35091
- const segments = trimmed.split("/");
35092
- const activityIndex = segments.lastIndexOf("activities");
35093
- if (activityIndex !== -1 && segments.length >= activityIndex + 3) {
35094
- const candidate = segments[activityIndex + 2];
35095
- return candidate ? decodeURIComponent(candidate) : undefined;
35096
- }
35097
- return;
35098
- }
35099
- function buildResourceMetadata({
35100
- baseMetadata,
35101
- subject,
35102
- grade,
35103
- totalXp,
35104
- masterableUnits
35105
- }) {
35106
- const normalizedBaseMetadata = isResourceMetadata(baseMetadata) ? baseMetadata : undefined;
35107
- const metadata2 = {
35108
- ...normalizedBaseMetadata
35109
- };
35110
- metadata2.subject = subject;
35111
- metadata2.grades = [grade];
35112
- metadata2.xp = totalXp;
35113
- if (masterableUnits !== undefined && masterableUnits !== null) {
35114
- const existingPlaycademy = isPlaycademyResourceMetadata2(metadata2.playcademy) ? metadata2.playcademy : undefined;
35115
- metadata2.playcademy = {
35116
- ...existingPlaycademy,
35117
- mastery: {
35118
- ...existingPlaycademy?.mastery,
35119
- masterableUnits
35120
- }
35121
- };
35122
- }
35123
- return metadata2;
35124
- }
35125
- function getDurationSecondsFromExtensions(event) {
35126
- const extensions = getMergedCaliperExtensions(event);
35127
- const playcademy = isRecord2(extensions.playcademy) ? extensions.playcademy : undefined;
35128
- const rawValue = extensions.durationSeconds ?? playcademy?.durationSeconds;
35129
- const value = typeof rawValue === "number" ? rawValue : Number(rawValue);
35130
- return Number.isFinite(value) ? value : undefined;
35131
- }
35132
- function getCanonicalRunId(session2) {
35133
- const sessionId = getStringValue(session2?.id);
35134
- if (!sessionId) {
35135
- return;
35136
- }
35137
- return sessionId.replace(/^urn:uuid:/, "");
35138
- }
35139
- function getResumeId(event) {
35140
- const playcademy = getPlaycademyMetadata(event);
35141
- return getStringValue(playcademy?.resumeId);
35142
- }
35143
- function isCaliperRemediationOrCompletionEvent(event) {
35144
- const playcademy = getPlaycademyMetadata(event);
35145
- return REMEDIATION_OR_COMPLETION_EVENT_KINDS.has(getStringValue(playcademy?.eventKind) || "");
35146
- }
35147
- function groupCaliperEventsByRun(events) {
35148
- const groups = new Map;
35149
- for (const event of events) {
35150
- const objectId = getStringValue(event.object.id) || "unknown-activity";
35151
- const groupKey = `${objectId}::${getStringValue(event.session?.id) || event.externalId}`;
35152
- const existing = groups.get(groupKey);
35153
- if (existing) {
35154
- existing.push(event);
35155
- } else {
35156
- groups.set(groupKey, [event]);
35157
- }
35158
- }
35159
- return groups;
35160
- }
35161
- function findCaliperEventGroupContainingExternalId(events, externalId) {
35162
- const targetExternalId = externalId.trim();
35163
- if (!targetExternalId) {
35164
- return;
35165
- }
35166
- return [...groupCaliperEventsByRun(events).values()].find((group) => group.some((event) => event.externalId === targetExternalId));
35167
- }
35168
- function mapCaliperEventGroupToActivity(events, relevantCourseIds) {
35169
- if (events.length === 0) {
35170
- return null;
35171
- }
35172
- const sortedEvents = events.toSorted((a, b) => a.eventTime.localeCompare(b.eventTime));
35173
- const activityEvent = [...sortedEvents].toReversed().find((event) => event.type === "ActivityEvent");
35174
- const contextSource = activityEvent || sortedEvents.at(-1);
35175
- if (!contextSource) {
35176
- return null;
35177
- }
35178
- const ctx = parseCaliperEventContext(contextSource, relevantCourseIds);
35179
- if (!ctx) {
35180
- return null;
35181
- }
35182
- const score = activityEvent !== undefined ? (() => {
35183
- const totalQuestions = getGeneratedMetricValue(activityEvent, "totalQuestions");
35184
- const correctQuestions = getGeneratedMetricValue(activityEvent, "correctQuestions");
35185
- if (totalQuestions === undefined || correctQuestions === undefined || totalQuestions <= 0) {
35186
- return;
35187
- }
35188
- return correctQuestions / totalQuestions * 100;
35189
- })() : undefined;
35190
- const xpEarned = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "xpEarned") : undefined;
35191
- const masteredUnits = activityEvent !== undefined ? getGeneratedMetricValue(activityEvent, "masteredUnits") : undefined;
35192
- const timeSpentEvents = sortedEvents.filter((event) => event.type === "TimeSpentEvent");
35193
- let totalActiveTimeSeconds;
35194
- if (timeSpentEvents.length > 0) {
35195
- totalActiveTimeSeconds = timeSpentEvents.reduce((sum, event) => sum + (getGeneratedMetricValue(event, "active") ?? 0), 0);
35196
- } else if (activityEvent !== undefined) {
35197
- totalActiveTimeSeconds = getDurationSecondsFromExtensions(activityEvent);
35198
- }
35199
- const fallbackActivityId = getActivityId(contextSource, getPlaycademyMetadata(contextSource));
35200
- const occurredAt = getStringValue(activityEvent?.eventTime) || getStringValue(sortedEvents.at(-1)?.eventTime);
35201
- const runId = getCanonicalRunId(contextSource.session);
35202
- const resumeIds = new Set(sortedEvents.map((event) => getResumeId(event)).filter((resumeId) => resumeId !== undefined));
35203
- const sessionCount = resumeIds.size > 0 ? resumeIds.size : 1;
35204
- const kind = activityEvent !== undefined ? "activity" : "activity-in-progress";
35205
- if (!occurredAt) {
35206
- return null;
35207
- }
35208
- return {
35209
- id: activityEvent?.externalId || sortedEvents.at(-1)?.externalId || events[0].externalId,
35210
- kind,
35211
- occurredAt,
35212
- courseId: ctx.courseId,
35213
- title: getStringValue(activityEvent?.object.activity?.name) || ctx.titleFromEvent || (fallbackActivityId ? kebabToTitleCase(fallbackActivityId) : "Activity completed"),
35214
- ...ctx.activityId ? { activityId: ctx.activityId } : {},
35215
- ...ctx.appName ? { appName: ctx.appName } : {},
35216
- ...score !== undefined ? { score } : {},
35217
- ...xpEarned !== undefined ? { xpDelta: xpEarned } : {},
35218
- ...masteredUnits !== undefined ? { masteredUnitsDelta: masteredUnits } : {},
35219
- ...totalActiveTimeSeconds !== undefined ? { timeDeltaSeconds: totalActiveTimeSeconds } : {},
35220
- ...runId ? { runId } : {},
35221
- ...sessionCount > 0 ? { sessionCount } : {}
35222
- };
35223
- }
35224
- function parseCaliperEventContext(event, relevantCourseIds) {
35225
- const playcademy = getPlaycademyMetadata(event);
35226
- const courseId = getStringValue(playcademy?.courseId) || parseSourcedIdFromUrl(event.object.course?.id);
35227
- if (!courseId || !relevantCourseIds.has(courseId)) {
35228
- return null;
35229
- }
35230
- const occurredAt = getStringValue(event.eventTime);
35231
- if (!occurredAt) {
35232
- return null;
35233
- }
35234
- return {
35235
- courseId,
35236
- occurredAt,
35237
- eventKind: getStringValue(playcademy?.eventKind),
35238
- source: getStringValue(playcademy?.source),
35239
- reason: getStringValue(playcademy?.reason),
35240
- titleFromEvent: getStringValue(event.object.activity?.name),
35241
- appName: getStringValue(event.object.app?.name),
35242
- activityId: getActivityId(event, playcademy)
35243
- };
35244
- }
35245
- function mapTimeSpentRemediation(event, ctx) {
35246
- if (ctx.eventKind !== "remediation-time") {
35247
- return null;
35248
- }
35249
- return {
35250
- id: event.externalId,
35251
- kind: "remediation-time",
35252
- occurredAt: ctx.occurredAt,
35253
- courseId: ctx.courseId,
35254
- title: "Time Adjustment",
35255
- activityId: ctx.activityId,
35256
- appName: ctx.appName,
35257
- reason: ctx.reason,
35258
- timeDeltaSeconds: getGeneratedMetricValue(event, "active")
35259
- };
35260
- }
35261
- function mapActivityRemediation(event, ctx) {
35262
- if (ctx.eventKind === "remediation-xp") {
35263
- return {
35264
- id: event.externalId,
35265
- kind: "remediation-xp",
35266
- occurredAt: ctx.occurredAt,
35267
- courseId: ctx.courseId,
35268
- title: "XP Adjustment",
35269
- activityId: ctx.activityId,
35270
- appName: ctx.appName,
35271
- reason: ctx.reason,
35272
- xpDelta: getGeneratedMetricValue(event, "xpEarned"),
35273
- masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
35274
- };
35275
- }
35276
- if (ctx.eventKind === "remediation-mastery") {
35277
- return {
35278
- id: event.externalId,
35279
- kind: "remediation-mastery",
35280
- occurredAt: ctx.occurredAt,
35281
- courseId: ctx.courseId,
35282
- title: "Mastery Adjustment",
35283
- activityId: ctx.activityId,
35284
- appName: ctx.appName,
35285
- reason: ctx.reason,
35286
- xpDelta: getGeneratedMetricValue(event, "xpEarned"),
35287
- masteredUnitsDelta: getGeneratedMetricValue(event, "masteredUnits")
35288
- };
35289
- }
35290
- if (ctx.eventKind === "course-completed") {
35291
- return {
35292
- id: event.externalId,
35293
- kind: "course-completed",
35294
- occurredAt: ctx.occurredAt,
35295
- courseId: ctx.courseId,
35296
- title: ctx.source === "admin" ? "Course marked complete" : "Course completed",
35297
- activityId: ctx.activityId,
35298
- appName: ctx.appName,
35299
- reason: ctx.reason
35300
- };
35301
- }
35302
- if (ctx.eventKind === "course-resumed") {
35303
- return {
35304
- id: event.externalId,
35305
- kind: "course-resumed",
35306
- occurredAt: ctx.occurredAt,
35307
- courseId: ctx.courseId,
35308
- title: "Course resumed",
35309
- activityId: ctx.activityId,
35310
- appName: ctx.appName,
35311
- reason: ctx.reason
35312
- };
35313
- }
35314
- return null;
35315
- }
35316
- function mapCaliperEventToRemediationActivity(event, relevantCourseIds) {
35317
- const ctx = parseCaliperEventContext(event, relevantCourseIds);
35318
- if (!ctx) {
35319
- return null;
35320
- }
35321
- if (event.type === "TimeSpentEvent") {
35322
- return mapTimeSpentRemediation(event, ctx);
35323
- }
35324
- if (event.type === "ActivityEvent") {
35325
- return mapActivityRemediation(event, ctx);
35326
- }
35327
- return null;
35328
- }
35329
- var REMEDIATION_OR_COMPLETION_EVENT_KINDS;
35330
- var init_timeback_util = __esm(() => {
35331
- init_types3();
35332
- REMEDIATION_OR_COMPLETION_EVENT_KINDS = new Set([
35333
- "remediation-xp",
35334
- "remediation-time",
35335
- "remediation-mastery",
35336
- "course-completed",
35337
- "course-resumed"
35338
- ]);
35339
- });
35340
-
35341
35515
  // ../api-core/src/utils/timeback-discrepancy-queue.util.ts
35342
35516
  function parseDateInputParts(value) {
35343
35517
  const parts2 = value.split("-");
@@ -35711,7 +35885,7 @@ function isAllowedGradeLevelTestType(value) {
35711
35885
  }
35712
35886
  function isQualifyingGradeLevelTestResult(result, options) {
35713
35887
  const metadata2 = metadataOf(result);
35714
- 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);
35888
+ 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);
35715
35889
  }
35716
35890
  function mapGradeLevelTestSummary(result, options) {
35717
35891
  if (!isQualifyingGradeLevelTestResult(result, options)) {
@@ -35971,7 +36145,7 @@ function latestAssessmentResultsByLineItem(results) {
35971
36145
  const latestResultsByLineItem = new Map;
35972
36146
  for (const result of results) {
35973
36147
  const lineItemId = sourceIdFromRef(result.assessmentLineItem);
35974
- if (lineItemId && !latestResultsByLineItem.has(lineItemId) && result.scoreStatus === SCORE_STATUS2.fullyGraded) {
36148
+ if (lineItemId && !latestResultsByLineItem.has(lineItemId) && result.scoreStatus === SCORE_STATUS3.fullyGraded) {
35975
36149
  latestResultsByLineItem.set(lineItemId, result);
35976
36150
  }
35977
36151
  }
@@ -36071,7 +36245,7 @@ function qtiIdCandidates(parentLineItem, resource) {
36071
36245
  }
36072
36246
  var GRADE_LEVEL_TEST_TYPES, naturalTitleSort;
36073
36247
  var init_timeback_grade_level_results_util = __esm(() => {
36074
- init_constants5();
36248
+ init_constants6();
36075
36249
  init_utils6();
36076
36250
  GRADE_LEVEL_TEST_TYPES = [
36077
36251
  "placement",
@@ -36096,18 +36270,18 @@ async function upsertMasteryCompletionEntry(params) {
36096
36270
  await client.oneroster.assessmentLineItems.findOrCreate(lineItemId, {
36097
36271
  sourcedId: lineItemId,
36098
36272
  title: "Mastery Completion",
36099
- status: ONEROSTER_STATUS2.active,
36273
+ status: ONEROSTER_STATUS3.active,
36100
36274
  course: { sourcedId: ids.course },
36101
36275
  ...ids.componentResource ? { componentResource: { sourcedId: ids.componentResource } } : {}
36102
36276
  });
36103
36277
  await client.oneroster.assessmentResults.upsert(resultId, {
36104
36278
  sourcedId: resultId,
36105
- status: ONEROSTER_STATUS2.active,
36279
+ status: ONEROSTER_STATUS3.active,
36106
36280
  assessmentLineItem: { sourcedId: lineItemId },
36107
36281
  student: { sourcedId: studentId },
36108
36282
  score: 100,
36109
36283
  scoreDate: new Date().toISOString(),
36110
- scoreStatus: SCORE_STATUS2.fullyGraded,
36284
+ scoreStatus: SCORE_STATUS3.fullyGraded,
36111
36285
  inProgress: "false",
36112
36286
  metadata: {
36113
36287
  isMasteryCompletion: true,
@@ -36119,12 +36293,12 @@ async function upsertMasteryCompletionEntry(params) {
36119
36293
  try {
36120
36294
  await client.oneroster.assessmentResults.upsert(resultId, {
36121
36295
  sourcedId: resultId,
36122
- status: ONEROSTER_STATUS2.active,
36296
+ status: ONEROSTER_STATUS3.active,
36123
36297
  assessmentLineItem: { sourcedId: lineItemId },
36124
36298
  student: { sourcedId: studentId },
36125
36299
  score: 0,
36126
36300
  scoreDate: new Date().toISOString(),
36127
- scoreStatus: SCORE_STATUS2.notSubmitted,
36301
+ scoreStatus: SCORE_STATUS3.notSubmitted,
36128
36302
  inProgress: "true",
36129
36303
  metadata: {
36130
36304
  isMasteryCompletion: true,
@@ -36136,7 +36310,7 @@ async function upsertMasteryCompletionEntry(params) {
36136
36310
  }
36137
36311
  }
36138
36312
  var init_timeback_mastery_completion_util = __esm(() => {
36139
- init_constants5();
36313
+ init_constants6();
36140
36314
  init_utils6();
36141
36315
  });
36142
36316
 
@@ -36165,7 +36339,7 @@ class TimebackAdminService {
36165
36339
  this.deps = deps;
36166
36340
  }
36167
36341
  getGradeLevelTestCourseScope(integration) {
36168
- if (!isTimebackSubject(integration.subject) || !isTimebackGrade(integration.grade)) {
36342
+ if (!isTimebackSubject2(integration.subject) || !isTimebackGrade2(integration.grade)) {
36169
36343
  throw new ValidationError("Timeback integration has invalid grade or subject");
36170
36344
  }
36171
36345
  return {
@@ -36244,7 +36418,7 @@ class TimebackAdminService {
36244
36418
  await this.deps.validateDeveloperAccess(user, gameId);
36245
36419
  }
36246
36420
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
36247
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
36421
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
36248
36422
  });
36249
36423
  if (!integration) {
36250
36424
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -36342,7 +36516,7 @@ class TimebackAdminService {
36342
36516
  const ids = deriveSourcedIds2(courseId);
36343
36517
  const resource = await client.oneroster.resources.get(ids.resource);
36344
36518
  const playcademyMetadata = resource.metadata?.playcademy;
36345
- if (!isPlaycademyResourceMetadata2(playcademyMetadata)) {
36519
+ if (!isPlaycademyResourceMetadata(playcademyMetadata)) {
36346
36520
  return;
36347
36521
  }
36348
36522
  return playcademyMetadata?.mastery?.masterableUnits;
@@ -36746,7 +36920,7 @@ class TimebackAdminService {
36746
36920
  "app.timeback.include_inactive": options?.includeInactive ?? false
36747
36921
  });
36748
36922
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
36749
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
36923
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
36750
36924
  });
36751
36925
  if (!integration) {
36752
36926
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -36824,7 +36998,7 @@ class TimebackAdminService {
36824
36998
  columns: { id: true }
36825
36999
  }),
36826
37000
  this.deps.db.query.gameTimebackIntegrations.findMany({
36827
- where: eq(gameTimebackIntegrations.gameId, gameId)
37001
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
36828
37002
  }),
36829
37003
  this.deps.db.query.games.findFirst({
36830
37004
  where: eq(games.id, gameId),
@@ -36927,7 +37101,7 @@ class TimebackAdminService {
36927
37101
  "app.timeback.course_id": courseId
36928
37102
  });
36929
37103
  const integrations = await this.deps.db.query.gameTimebackIntegrations.findMany({
36930
- where: courseId ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId)) : eq(gameTimebackIntegrations.gameId, gameId)
37104
+ where: courseId ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus()) : and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
36931
37105
  });
36932
37106
  if (integrations.length === 0) {
36933
37107
  throw new NotFoundError("Timeback integration", gameId);
@@ -37017,7 +37191,7 @@ class TimebackAdminService {
37017
37191
  });
37018
37192
  const [integration, gameSource] = await Promise.all([
37019
37193
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37020
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37194
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37021
37195
  }),
37022
37196
  this.getGameActivitySource(gameId)
37023
37197
  ]);
@@ -37121,7 +37295,7 @@ class TimebackAdminService {
37121
37295
  "app.timeback.course_id": courseId
37122
37296
  });
37123
37297
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37124
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37298
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37125
37299
  });
37126
37300
  if (!integration) {
37127
37301
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -37176,7 +37350,7 @@ class TimebackAdminService {
37176
37350
  "app.timeback.assessment_result_id": resultId
37177
37351
  });
37178
37352
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37179
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37353
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37180
37354
  });
37181
37355
  if (!integration) {
37182
37356
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -37254,7 +37428,7 @@ class TimebackAdminService {
37254
37428
  });
37255
37429
  const [integration, gameSource, roster] = await Promise.all([
37256
37430
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37257
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37431
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37258
37432
  }),
37259
37433
  this.getGameActivitySource(gameId),
37260
37434
  client.oneroster.enrollments.listByCourse(courseId, {
@@ -37375,7 +37549,7 @@ class TimebackAdminService {
37375
37549
  });
37376
37550
  const [integration, gameSource] = await Promise.all([
37377
37551
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37378
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37552
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37379
37553
  }),
37380
37554
  this.getGameActivitySource(gameId)
37381
37555
  ]);
@@ -37459,7 +37633,7 @@ class TimebackAdminService {
37459
37633
  });
37460
37634
  const [integration, gameSource] = await Promise.all([
37461
37635
  this.deps.db.query.gameTimebackIntegrations.findFirst({
37462
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37636
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37463
37637
  }),
37464
37638
  this.getGameActivitySource(gameId)
37465
37639
  ]);
@@ -37688,7 +37862,7 @@ class TimebackAdminService {
37688
37862
  "app.timeback.course_id": courseId
37689
37863
  });
37690
37864
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37691
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
37865
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
37692
37866
  });
37693
37867
  if (!integration) {
37694
37868
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -37759,7 +37933,7 @@ class TimebackAdminService {
37759
37933
  "app.timeback.enrollment.operation": "enroll"
37760
37934
  });
37761
37935
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37762
- where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId))
37936
+ where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId), isActiveGameTimebackIntegrationStatus())
37763
37937
  });
37764
37938
  if (!integration) {
37765
37939
  throw new NotFoundError("Timeback integration", `${data.gameId}:${data.courseId}`);
@@ -37799,7 +37973,7 @@ class TimebackAdminService {
37799
37973
  "app.timeback.enrollment.operation": "unenroll"
37800
37974
  });
37801
37975
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37802
- where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId))
37976
+ where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId), isActiveGameTimebackIntegrationStatus())
37803
37977
  });
37804
37978
  if (!integration) {
37805
37979
  throw new NotFoundError("Timeback integration", `${data.gameId}:${data.courseId}`);
@@ -37820,7 +37994,7 @@ class TimebackAdminService {
37820
37994
  "app.timeback.enrollment.operation": "reactivate"
37821
37995
  });
37822
37996
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
37823
- where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId))
37997
+ where: and(eq(gameTimebackIntegrations.gameId, data.gameId), eq(gameTimebackIntegrations.courseId, data.courseId), isActiveGameTimebackIntegrationStatus())
37824
37998
  });
37825
37999
  if (!integration) {
37826
38000
  throw new NotFoundError("Timeback integration", `${data.gameId}:${data.courseId}`);
@@ -37866,7 +38040,7 @@ class TimebackAdminService {
37866
38040
  const resultId = `${lineItemId}:${studentId}:completion`;
37867
38041
  try {
37868
38042
  const result = await client.oneroster.assessmentResults.get(resultId);
37869
- if (result.scoreStatus === SCORE_STATUS2.fullyGraded) {
38043
+ if (result.scoreStatus === SCORE_STATUS3.fullyGraded) {
37870
38044
  return "complete";
37871
38045
  }
37872
38046
  return "incomplete";
@@ -37902,12 +38076,13 @@ class TimebackAdminService {
37902
38076
  var init_timeback_admin_service = __esm(() => {
37903
38077
  init_drizzle_orm();
37904
38078
  init_src();
38079
+ init_helpers_index();
37905
38080
  init_schemas_index();
37906
38081
  init_tables_index();
37907
38082
  init_spans();
37908
38083
  init_dist2();
37909
- init_constants5();
37910
- init_types3();
38084
+ init_constants6();
38085
+ init_types2();
37911
38086
  init_utils6();
37912
38087
  init_src4();
37913
38088
  init_timeback3();
@@ -37922,8 +38097,8 @@ var init_timeback_admin_service = __esm(() => {
37922
38097
  });
37923
38098
 
37924
38099
  // ../timeback/dist/errors.js
37925
- 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;
37926
- var init_errors4 = __esm(() => {
38100
+ 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;
38101
+ var init_errors6 = __esm(() => {
37927
38102
  init_src();
37928
38103
  init_constants9 = __esm6(() => {
37929
38104
  TIMEBACK_API_URLS5 = {
@@ -38107,18 +38282,79 @@ var init_errors4 = __esm(() => {
38107
38282
  timebackSdk: "TimebackSDKError"
38108
38283
  };
38109
38284
  });
38110
- init_constants9();
38111
- TimebackApiError2 = class TimebackApiError2 extends Error {
38112
- status;
38113
- details;
38114
- constructor(status, message, details) {
38115
- super(`${status} ${message}`);
38116
- this.name = ERROR_NAMES5.timebackApi;
38117
- this.status = status;
38118
- this.details = details;
38119
- Object.setPrototypeOf(this, TimebackApiError2.prototype);
38120
- }
38121
- };
38285
+ init_errors7 = __esm6(() => {
38286
+ init_constants9();
38287
+ TimebackError3 = class TimebackError4 extends Error {
38288
+ constructor(message) {
38289
+ super(message);
38290
+ this.name = ERROR_NAMES5.timebackSdk;
38291
+ }
38292
+ };
38293
+ TimebackApiError3 = class TimebackApiError4 extends Error {
38294
+ status;
38295
+ details;
38296
+ constructor(status, message, details) {
38297
+ super(`${status} ${message}`);
38298
+ this.name = ERROR_NAMES5.timebackApi;
38299
+ this.status = status;
38300
+ this.details = details;
38301
+ Object.setPrototypeOf(this, TimebackApiError4.prototype);
38302
+ }
38303
+ };
38304
+ TimebackAuthenticationError3 = class TimebackAuthenticationError4 extends TimebackError3 {
38305
+ constructor(message) {
38306
+ super(message || "Authentication failed. Please verify TIMEBACK_CLIENT_ID and TIMEBACK_CLIENT_SECRET are set correctly.");
38307
+ this.name = "TimebackAuthenticationError";
38308
+ Object.setPrototypeOf(this, TimebackAuthenticationError4.prototype);
38309
+ }
38310
+ };
38311
+ StudentNotFoundError3 = class StudentNotFoundError4 extends TimebackError3 {
38312
+ identifier;
38313
+ identifierType;
38314
+ constructor(identifier, identifierType = "email") {
38315
+ 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.`);
38316
+ this.name = "StudentNotFoundError";
38317
+ this.identifier = identifier;
38318
+ this.identifierType = identifierType;
38319
+ Object.setPrototypeOf(this, StudentNotFoundError4.prototype);
38320
+ }
38321
+ };
38322
+ ConfigurationError3 = class ConfigurationError4 extends TimebackError3 {
38323
+ field;
38324
+ constructor(field, message) {
38325
+ super(message || `Missing required configuration: ${field}. Please check your timeback.config.js file.`);
38326
+ this.name = "ConfigurationError";
38327
+ this.field = field;
38328
+ Object.setPrototypeOf(this, ConfigurationError4.prototype);
38329
+ }
38330
+ };
38331
+ ResourceAlreadyExistsError3 = class ResourceAlreadyExistsError4 extends TimebackError3 {
38332
+ resourceType;
38333
+ sourcedId;
38334
+ originalError;
38335
+ constructor(resourceType, sourcedId, originalError) {
38336
+ super(`${resourceType} with ID '${sourcedId}' already exists`);
38337
+ this.name = "ResourceAlreadyExistsError";
38338
+ this.resourceType = resourceType;
38339
+ this.sourcedId = sourcedId;
38340
+ this.originalError = originalError;
38341
+ Object.setPrototypeOf(this, ResourceAlreadyExistsError4.prototype);
38342
+ }
38343
+ };
38344
+ ResourceNotFoundError3 = class ResourceNotFoundError4 extends TimebackError3 {
38345
+ resourceType;
38346
+ sourcedId;
38347
+ constructor(resourceType, sourcedId) {
38348
+ 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`;
38349
+ super(message);
38350
+ this.name = "ResourceNotFoundError";
38351
+ this.resourceType = resourceType;
38352
+ this.sourcedId = sourcedId;
38353
+ Object.setPrototypeOf(this, ResourceNotFoundError4.prototype);
38354
+ }
38355
+ };
38356
+ });
38357
+ init_errors7();
38122
38358
  });
38123
38359
 
38124
38360
  // ../api-core/src/services/timeback-assessments.service.ts
@@ -38130,7 +38366,7 @@ class TimebackAssessmentsService {
38130
38366
  async resolveIntegrationId(gameId, courseId, user) {
38131
38367
  await this.deps.validateGameManagementAccess(user, gameId);
38132
38368
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
38133
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
38369
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
38134
38370
  });
38135
38371
  if (!integration) {
38136
38372
  throw new NotFoundError(`No Timeback integration found for game ${gameId} course ${courseId}`);
@@ -38223,7 +38459,7 @@ class TimebackAssessmentsService {
38223
38459
  ]
38224
38460
  });
38225
38461
  } catch (error) {
38226
- if (error instanceof TimebackApiError2 && error.status === 409) {} else {
38462
+ if (error instanceof TimebackApiError3 && error.status === 409) {} else {
38227
38463
  throw error;
38228
38464
  }
38229
38465
  }
@@ -38523,7 +38759,7 @@ class TimebackAssessmentsService {
38523
38759
  }
38524
38760
  async requireIntegration(integrationId) {
38525
38761
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
38526
- where: eq(gameTimebackIntegrations.id, integrationId)
38762
+ where: and(eq(gameTimebackIntegrations.id, integrationId), isActiveGameTimebackIntegrationStatus())
38527
38763
  });
38528
38764
  if (!integration) {
38529
38765
  throw new NotFoundError(`Integration not found: ${integrationId}`);
@@ -38554,7 +38790,7 @@ class TimebackAssessmentsService {
38554
38790
  }
38555
38791
  });
38556
38792
  } catch (error) {
38557
- if (!(error instanceof TimebackApiError2 && error.status === 409)) {
38793
+ if (!(error instanceof TimebackApiError3 && error.status === 409)) {
38558
38794
  throw error;
38559
38795
  }
38560
38796
  }
@@ -38576,7 +38812,7 @@ class TimebackAssessmentsService {
38576
38812
  }
38577
38813
  });
38578
38814
  } catch (error) {
38579
- if (!(error instanceof TimebackApiError2 && error.status === 409)) {
38815
+ if (!(error instanceof TimebackApiError3 && error.status === 409)) {
38580
38816
  throw error;
38581
38817
  }
38582
38818
  }
@@ -38594,7 +38830,7 @@ class TimebackAssessmentsService {
38594
38830
  }
38595
38831
  });
38596
38832
  } catch (error) {
38597
- if (!(error instanceof TimebackApiError2 && error.status === 409)) {
38833
+ if (!(error instanceof TimebackApiError3 && error.status === 409)) {
38598
38834
  throw error;
38599
38835
  }
38600
38836
  }
@@ -38612,14 +38848,63 @@ class TimebackAssessmentsService {
38612
38848
  }
38613
38849
  var init_timeback_assessments_service = __esm(() => {
38614
38850
  init_drizzle_orm();
38851
+ init_helpers_index();
38615
38852
  init_tables_index();
38616
38853
  init_spans();
38617
- init_constants5();
38618
- init_errors4();
38854
+ init_constants6();
38855
+ init_errors6();
38619
38856
  init_utils6();
38620
38857
  init_errors();
38621
38858
  });
38622
38859
 
38860
+ // ../api-core/src/utils/timeback-create-integration.util.ts
38861
+ function buildTimebackBaseConfigFromExistingConfig(config2) {
38862
+ return {
38863
+ organization: config2.organization,
38864
+ component: {
38865
+ ...config2.component,
38866
+ title: ""
38867
+ },
38868
+ resource: {
38869
+ ...config2.resource,
38870
+ title: ""
38871
+ },
38872
+ componentResource: {
38873
+ ...config2.componentResource,
38874
+ title: ""
38875
+ }
38876
+ };
38877
+ }
38878
+ function getMasterableUnitsFromTimebackConfig(config2) {
38879
+ const playcademyMetadata = config2.resource.metadata?.playcademy;
38880
+ if (!isPlaycademyResourceMetadata(playcademyMetadata)) {
38881
+ return null;
38882
+ }
38883
+ return playcademyMetadata?.mastery?.masterableUnits ?? null;
38884
+ }
38885
+ function getTotalXpFromTimebackConfig(config2) {
38886
+ const courseMetadata = isCourseMetadata(config2.course.metadata) ? config2.course.metadata : undefined;
38887
+ if (typeof courseMetadata?.metrics?.totalXp === "number") {
38888
+ return courseMetadata.metrics.totalXp;
38889
+ }
38890
+ const resourceMetadata = config2.resource.metadata;
38891
+ if (isRecord2(resourceMetadata) && typeof resourceMetadata.xp === "number") {
38892
+ return resourceMetadata.xp;
38893
+ }
38894
+ return null;
38895
+ }
38896
+ function timebackConfigMatchesCreateIntegrationRequest(config2, request2) {
38897
+ const subject = config2.course.subjects[0];
38898
+ const grade = config2.course.grades[0];
38899
+ const requestedLevel = request2.level ?? deriveTimebackCourseLevelFromGrade(request2.grade);
38900
+ 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;
38901
+ }
38902
+ var init_timeback_create_integration_util = __esm(() => {
38903
+ init_constants6();
38904
+ init_types2();
38905
+ init_timeback_util();
38906
+ });
38907
+
38623
38908
  // ../api-core/src/utils/timeback-promotion.util.ts
38624
38909
  async function promoteCompletedCourse({
38625
38910
  db: db2,
@@ -38629,7 +38914,7 @@ async function promoteCompletedCourse({
38629
38914
  enrollments: prefetchedEnrollments
38630
38915
  }) {
38631
38916
  const subjectIntegrations = await db2.query.gameTimebackIntegrations.findMany({
38632
- where: and(eq(gameTimebackIntegrations.gameId, currentIntegration.gameId), eq(gameTimebackIntegrations.subject, currentIntegration.subject))
38917
+ where: and(eq(gameTimebackIntegrations.gameId, currentIntegration.gameId), eq(gameTimebackIntegrations.subject, currentIntegration.subject), isActiveGameTimebackIntegrationStatus())
38633
38918
  });
38634
38919
  const nextIntegration = subjectIntegrations.filter((integration) => integration.grade > currentIntegration.grade).toSorted((left, right) => left.grade - right.grade)[0];
38635
38920
  if (!nextIntegration) {
@@ -38684,21 +38969,72 @@ async function promoteCompletedCourse({
38684
38969
  }
38685
38970
  var init_timeback_promotion_util = __esm(() => {
38686
38971
  init_drizzle_orm();
38972
+ init_helpers_index();
38687
38973
  init_tables_index();
38688
38974
  init_spans();
38689
38975
  });
38690
38976
 
38977
+ // ../api-core/src/utils/timeback-removed-integration.util.ts
38978
+ function toGameTimebackIntegration(integration) {
38979
+ return {
38980
+ id: integration.id,
38981
+ gameId: integration.gameId,
38982
+ courseId: integration.courseId,
38983
+ grade: integration.grade,
38984
+ subject: integration.subject,
38985
+ totalXp: integration.totalXp ?? null,
38986
+ status: integration.status ?? ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
38987
+ deactivatedAt: integration.deactivatedAt ?? null,
38988
+ reactivatedAt: integration.reactivatedAt ?? null,
38989
+ createdAt: integration.createdAt,
38990
+ updatedAt: integration.updatedAt,
38991
+ lastVerifiedAt: integration.lastVerifiedAt ?? null
38992
+ };
38993
+ }
38994
+ function buildFallbackRemovedGameTimebackIntegration(integration) {
38995
+ if (!isTimebackSubject(integration.subject)) {
38996
+ throw new ValidationError(`Invalid subject "${integration.subject}"`);
38997
+ }
38998
+ if (!isTimebackGrade(integration.grade)) {
38999
+ throw new ValidationError(`Invalid grade "${integration.grade}"`);
39000
+ }
39001
+ return {
39002
+ integration: toGameTimebackIntegration(integration),
39003
+ title: `${integration.subject} ${formatGradeLabel(integration.grade)}`,
39004
+ courseCode: integration.courseId,
39005
+ subject: integration.subject,
39006
+ grade: integration.grade,
39007
+ totalXp: integration.totalXp ?? null,
39008
+ masterableUnits: null,
39009
+ removedAt: integration.deactivatedAt ?? null,
39010
+ metadata: null
39011
+ };
39012
+ }
39013
+ var init_timeback_removed_integration_util = __esm(() => {
39014
+ init_helpers_index();
39015
+ init_types2();
39016
+ init_timeback3();
39017
+ init_errors();
39018
+ });
39019
+
38691
39020
  // ../api-core/src/services/timeback.service.ts
39021
+ async function findGameTimebackIntegrationForUpdate(db2, condition) {
39022
+ const [integration] = await db2.select().from(gameTimebackIntegrations).where(condition).limit(1).for("update");
39023
+ return integration;
39024
+ }
38692
39025
  var TimebackService;
38693
39026
  var init_timeback_service = __esm(() => {
38694
39027
  init_drizzle_orm();
38695
39028
  init_src();
39029
+ init_helpers_index();
38696
39030
  init_tables_index();
38697
39031
  init_spans();
38698
39032
  init_dist2();
38699
- init_types3();
39033
+ init_types2();
38700
39034
  init_errors();
39035
+ init_timeback_create_integration_util();
38701
39036
  init_timeback_promotion_util();
39037
+ init_timeback_removed_integration_util();
38702
39038
  init_timeback_util();
38703
39039
  TimebackService = class TimebackService {
38704
39040
  static HEARTBEAT_DEDUPE_TTL_MS = 5 * 60 * 1000;
@@ -38928,7 +39264,7 @@ var init_timeback_service = __esm(() => {
38928
39264
  return [];
38929
39265
  }
38930
39266
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
38931
- where: inArray(gameTimebackIntegrations.courseId, courseIds)
39267
+ where: and(inArray(gameTimebackIntegrations.courseId, courseIds), isActiveGameTimebackIntegrationStatus())
38932
39268
  });
38933
39269
  return mapEnrollmentsToUserEnrollments(enrollments, integrations);
38934
39270
  } catch (error) {
@@ -38953,6 +39289,7 @@ var init_timeback_service = __esm(() => {
38953
39289
  const verboseData = [];
38954
39290
  let integrationCreatedCount = 0;
38955
39291
  let integrationUpdatedCount = 0;
39292
+ let integrationReactivatedCount = 0;
38956
39293
  for (const courseConfig of courses) {
38957
39294
  let applySuffix = function(text3) {
38958
39295
  return suffix ? `${text3} ${suffix}` : text3;
@@ -38967,16 +39304,16 @@ var init_timeback_service = __esm(() => {
38967
39304
  totalXp: derivedTotalXp,
38968
39305
  masterableUnits: derivedMasterableUnits
38969
39306
  } = courseConfig;
38970
- if (!isTimebackSubject3(subjectInput)) {
39307
+ if (!isTimebackSubject(subjectInput)) {
38971
39308
  throw new ValidationError(`Invalid subject "${subjectInput}"`);
38972
39309
  }
38973
- if (!isTimebackGrade3(grade)) {
39310
+ if (!isTimebackGrade(grade)) {
38974
39311
  throw new ValidationError(`Invalid grade "${grade}"`);
38975
39312
  }
38976
39313
  const subject = subjectInput;
38977
39314
  const courseMetadata = isCourseMetadata(metadata2) ? metadata2 : undefined;
38978
39315
  const totalXp = derivedTotalXp ?? courseMetadata?.metrics?.totalXp;
38979
- const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata2(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
39316
+ const masterableUnits = derivedMasterableUnits ?? (isPlaycademyResourceMetadata(courseMetadata?.playcademy) ? courseMetadata?.playcademy?.mastery?.masterableUnits : undefined);
38980
39317
  if (typeof totalXp !== "number") {
38981
39318
  throw new ValidationError(`Course "${title}" is missing totalXp`);
38982
39319
  }
@@ -39022,19 +39359,28 @@ var init_timeback_service = __esm(() => {
39022
39359
  title: applySuffix(baseConfig.componentResource.title || "")
39023
39360
  }
39024
39361
  };
39025
- const existingIntegration = existing.find((i2) => i2.grade === grade && i2.subject === subject);
39362
+ const matches = existing.filter((i2) => i2.grade === grade && i2.subject === subject);
39363
+ 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];
39026
39364
  if (existingIntegration) {
39027
- await client.update(existingIntegration.courseId, fullConfig);
39028
- const [updated] = await db2.update(gameTimebackIntegrations).set({ subject, totalXp, updatedAt: new Date }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
39365
+ const { updated, revived } = await this.updateSetupIntegration({
39366
+ client,
39367
+ existingIntegration,
39368
+ fullConfig,
39369
+ subject,
39370
+ totalXp
39371
+ });
39029
39372
  if (updated) {
39030
- integrations.push(this.toGameTimebackIntegration(updated));
39373
+ integrations.push(toGameTimebackIntegration(updated));
39031
39374
  integrationUpdatedCount++;
39375
+ if (revived) {
39376
+ integrationReactivatedCount++;
39377
+ }
39032
39378
  }
39033
39379
  } else {
39034
39380
  const result = await client.setup(fullConfig, { verbose });
39035
39381
  const [integration] = await db2.insert(gameTimebackIntegrations).values({ gameId, courseId: result.courseId, grade, subject, totalXp }).returning();
39036
39382
  if (integration) {
39037
- const dto = this.toGameTimebackIntegration(integration);
39383
+ const dto = toGameTimebackIntegration(integration);
39038
39384
  integrations.push(dto);
39039
39385
  integrationCreatedCount++;
39040
39386
  if (verbose && result.verboseData) {
@@ -39046,7 +39392,8 @@ var init_timeback_service = __esm(() => {
39046
39392
  setAttributes({
39047
39393
  "app.timeback.integration_count": integrations.length,
39048
39394
  "app.timeback.integration_created_count": integrationCreatedCount,
39049
- "app.timeback.integration_updated_count": integrationUpdatedCount
39395
+ "app.timeback.integration_updated_count": integrationUpdatedCount,
39396
+ "app.timeback.integration_reactivated_count": integrationReactivatedCount
39050
39397
  });
39051
39398
  return {
39052
39399
  integrations,
@@ -39054,19 +39401,221 @@ var init_timeback_service = __esm(() => {
39054
39401
  };
39055
39402
  });
39056
39403
  }
39404
+ async updateSetupIntegration(args2) {
39405
+ const { client, existingIntegration, fullConfig, subject, totalXp } = args2;
39406
+ const revived = existingIntegration.status === DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS;
39407
+ await client.update(existingIntegration.courseId, fullConfig);
39408
+ if (revived) {
39409
+ await client.reactivateCourse(existingIntegration.courseId);
39410
+ }
39411
+ const now2 = new Date;
39412
+ const [updated] = await this.deps.db.update(gameTimebackIntegrations).set({
39413
+ subject,
39414
+ totalXp,
39415
+ updatedAt: now2,
39416
+ ...revived && {
39417
+ status: ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
39418
+ deactivatedAt: null,
39419
+ reactivatedAt: now2
39420
+ }
39421
+ }).where(eq(gameTimebackIntegrations.id, existingIntegration.id)).returning();
39422
+ return { updated, revived };
39423
+ }
39424
+ async createIntegration(gameId, user, request2) {
39425
+ return this.withClientTelemetry(async () => {
39426
+ const client = this.requireClient();
39427
+ const db2 = this.deps.db;
39428
+ await this.deps.validateDeveloperAccess(user, gameId);
39429
+ setAttributes({
39430
+ "app.timeback.grade": request2.grade,
39431
+ "app.timeback.subject": request2.subject
39432
+ });
39433
+ const activeConflict = await db2.query.gameTimebackIntegrations.findFirst({
39434
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, request2.grade), eq(gameTimebackIntegrations.subject, request2.subject), isActiveGameTimebackIntegrationStatus())
39435
+ });
39436
+ if (activeConflict) {
39437
+ throw new ConflictError(`A TimeBack integration already exists for ${request2.subject} Grade ${request2.grade}`);
39438
+ }
39439
+ const removedCandidates = await db2.query.gameTimebackIntegrations.findMany({
39440
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, request2.grade), eq(gameTimebackIntegrations.subject, request2.subject), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS))
39441
+ });
39442
+ for (const candidate of removedCandidates) {
39443
+ const config2 = await client.getConfig(candidate.courseId).catch((error) => {
39444
+ addEvent("timeback.removed_integration_config_fetch_failed", {
39445
+ "app.game.id": gameId,
39446
+ "app.timeback.course_id": candidate.courseId,
39447
+ "exception.type": errorType(error),
39448
+ "app.error.message": errorMessage(error)
39449
+ });
39450
+ return null;
39451
+ });
39452
+ if (config2 && timebackConfigMatchesCreateIntegrationRequest(config2, request2)) {
39453
+ const updated = await db2.transaction(async (tx) => {
39454
+ const database = tx;
39455
+ const lockedCandidate = await findGameTimebackIntegrationForUpdate(database, eq(gameTimebackIntegrations.id, candidate.id));
39456
+ if (lockedCandidate?.status !== DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS) {
39457
+ throw new ConflictError(`A TimeBack integration already exists for ${request2.subject} Grade ${request2.grade}`);
39458
+ }
39459
+ const now2 = new Date;
39460
+ const [integration2] = await database.update(gameTimebackIntegrations).set({
39461
+ status: ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
39462
+ totalXp: request2.totalXp,
39463
+ deactivatedAt: null,
39464
+ reactivatedAt: now2,
39465
+ updatedAt: now2
39466
+ }).where(and(eq(gameTimebackIntegrations.id, candidate.id), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS))).returning();
39467
+ if (!integration2) {
39468
+ throw new NotFoundError("Timeback integration", candidate.id);
39469
+ }
39470
+ await client.reactivateCourse(candidate.courseId);
39471
+ return integration2;
39472
+ });
39473
+ setAttribute("app.timeback.course_create_mode", "reactivated-removed");
39474
+ return toGameTimebackIntegration(updated);
39475
+ }
39476
+ }
39477
+ const reference = await db2.query.gameTimebackIntegrations.findFirst({
39478
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus()),
39479
+ orderBy: (table8, { asc: asc2 }) => [asc2(table8.createdAt)]
39480
+ }) ?? await db2.query.gameTimebackIntegrations.findFirst({
39481
+ where: eq(gameTimebackIntegrations.gameId, gameId),
39482
+ orderBy: (table8, { asc: asc2 }) => [asc2(table8.createdAt)]
39483
+ });
39484
+ if (!reference) {
39485
+ throw new ValidationError("Run `playcademy timeback setup` before adding courses from the dashboard.");
39486
+ }
39487
+ const referenceConfig = await client.getConfig(reference.courseId);
39488
+ const result = await this.setupIntegration(gameId, {
39489
+ gameId,
39490
+ courses: [
39491
+ {
39492
+ title: request2.title,
39493
+ courseCode: request2.courseCode,
39494
+ subject: request2.subject,
39495
+ grade: request2.grade,
39496
+ level: request2.level ?? deriveTimebackCourseLevelFromGrade(request2.grade),
39497
+ totalXp: request2.totalXp,
39498
+ masterableUnits: request2.masterableUnits
39499
+ }
39500
+ ],
39501
+ baseConfig: buildTimebackBaseConfigFromExistingConfig(referenceConfig)
39502
+ }, user);
39503
+ const integration = result.integrations[0];
39504
+ if (!integration) {
39505
+ throw new InternalError("TimeBack course creation did not return an integration");
39506
+ }
39507
+ setAttribute("app.timeback.course_create_mode", "created-new");
39508
+ return integration;
39509
+ });
39510
+ }
39057
39511
  async getIntegrations(gameId, user) {
39058
39512
  await this.deps.validateGameManagementAccess(user, gameId);
39059
39513
  const rows = await this.deps.db.query.gameTimebackIntegrations.findMany({
39060
- where: eq(gameTimebackIntegrations.gameId, gameId)
39514
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39515
+ });
39516
+ return rows.map((row) => toGameTimebackIntegration(row));
39517
+ }
39518
+ async getRemovedIntegrations(gameId, user) {
39519
+ return this.withClientTelemetry(async () => {
39520
+ const client = this.requireClient();
39521
+ await this.deps.validateGameManagementAccess(user, gameId);
39522
+ const rows = await this.deps.db.query.gameTimebackIntegrations.findMany({
39523
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS)),
39524
+ orderBy: (table8, { asc: asc2 }) => [asc2(table8.subject), asc2(table8.grade)]
39525
+ });
39526
+ setAttribute("app.timeback.removed_integration_count", rows.length);
39527
+ return Promise.all(rows.map(async (row) => {
39528
+ try {
39529
+ const config2 = await client.getConfig(row.courseId);
39530
+ return this.toRemovedGameTimebackIntegration(row, config2);
39531
+ } catch (error) {
39532
+ addEvent("timeback.removed_integration_config_fetch_failed", {
39533
+ "app.game.id": gameId,
39534
+ "app.timeback.course_id": row.courseId,
39535
+ "exception.type": errorType(error),
39536
+ "app.error.message": errorMessage(error)
39537
+ });
39538
+ return buildFallbackRemovedGameTimebackIntegration(row);
39539
+ }
39540
+ }));
39541
+ });
39542
+ }
39543
+ async deactivateCourse(gameId, courseId, user) {
39544
+ return this.withClientTelemetry(async () => {
39545
+ const client = this.requireClient();
39546
+ const db2 = this.deps.db;
39547
+ await this.deps.validateDeveloperAccess(user, gameId);
39548
+ const updated = await db2.transaction(async (tx) => {
39549
+ const database = tx;
39550
+ const integration = await findGameTimebackIntegrationForUpdate(database, and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus()));
39551
+ if (!integration) {
39552
+ throw new NotFoundError("Timeback course", `${gameId}:${courseId}`);
39553
+ }
39554
+ const activeEnrollments = await client.oneroster.enrollments.listByCourse(courseId, {
39555
+ role: "student",
39556
+ includeUsers: false
39557
+ });
39558
+ setAttribute("app.timeback.active_enrollment_count", activeEnrollments.length);
39559
+ if (activeEnrollments.length > 0) {
39560
+ throw new ConflictError("Cannot remove course with active enrollments", {
39561
+ courseId,
39562
+ activeEnrollmentCount: activeEnrollments.length
39563
+ });
39564
+ }
39565
+ const now2 = new Date;
39566
+ const [updatedIntegration] = await database.update(gameTimebackIntegrations).set({
39567
+ status: DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS,
39568
+ deactivatedAt: now2,
39569
+ updatedAt: now2
39570
+ }).where(and(eq(gameTimebackIntegrations.id, integration.id), isActiveGameTimebackIntegrationStatus())).returning();
39571
+ if (!updatedIntegration) {
39572
+ throw new NotFoundError("Timeback course", `${gameId}:${courseId}`);
39573
+ }
39574
+ await client.deactivateCourse(courseId);
39575
+ return updatedIntegration;
39576
+ });
39577
+ return toGameTimebackIntegration(updated);
39578
+ });
39579
+ }
39580
+ async reactivateCourse(gameId, courseId, user) {
39581
+ return this.withClientTelemetry(async () => {
39582
+ const client = this.requireClient();
39583
+ const db2 = this.deps.db;
39584
+ await this.deps.validateDeveloperAccess(user, gameId);
39585
+ const updated = await db2.transaction(async (tx) => {
39586
+ const database = tx;
39587
+ const integration = await findGameTimebackIntegrationForUpdate(database, and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS)));
39588
+ if (!integration) {
39589
+ throw new NotFoundError("Removed Timeback course", `${gameId}:${courseId}`);
39590
+ }
39591
+ const activeConflict = await database.query.gameTimebackIntegrations.findFirst({
39592
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, integration.subject), isActiveGameTimebackIntegrationStatus())
39593
+ });
39594
+ if (activeConflict) {
39595
+ throw new ConflictError(`An active TimeBack course already exists for ${integration.subject} Grade ${integration.grade}`);
39596
+ }
39597
+ const now2 = new Date;
39598
+ const [updatedIntegration] = await database.update(gameTimebackIntegrations).set({
39599
+ status: ACTIVE_GAME_TIMEBACK_INTEGRATION_STATUS,
39600
+ deactivatedAt: null,
39601
+ reactivatedAt: now2,
39602
+ updatedAt: now2
39603
+ }).where(and(eq(gameTimebackIntegrations.id, integration.id), eq(gameTimebackIntegrations.status, DEACTIVATED_GAME_TIMEBACK_INTEGRATION_STATUS))).returning();
39604
+ if (!updatedIntegration) {
39605
+ throw new NotFoundError("Timeback course", `${gameId}:${courseId}`);
39606
+ }
39607
+ await client.reactivateCourse(courseId);
39608
+ return updatedIntegration;
39609
+ });
39610
+ return toGameTimebackIntegration(updated);
39061
39611
  });
39062
- return rows.map((row) => this.toGameTimebackIntegration(row));
39063
39612
  }
39064
39613
  async getIntegrationConfig(gameId, courseId, user) {
39065
39614
  return this.withClientTelemetry(async () => {
39066
39615
  const client = this.requireClient();
39067
39616
  await this.deps.validateGameManagementAccess(user, gameId);
39068
39617
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39069
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
39618
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
39070
39619
  });
39071
39620
  if (!integration) {
39072
39621
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
@@ -39083,15 +39632,15 @@ var init_timeback_service = __esm(() => {
39083
39632
  "app.timeback.course_id": courseId
39084
39633
  });
39085
39634
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39086
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId))
39635
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.courseId, courseId), isActiveGameTimebackIntegrationStatus())
39087
39636
  });
39088
39637
  if (!integration) {
39089
39638
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
39090
39639
  }
39091
39640
  const timebackConfig = await client.getConfig(courseId);
39092
39641
  const liveSubject = timebackConfig.course.subjects[0];
39093
- const subject = patch.subject ?? (isTimebackSubject3(liveSubject) ? liveSubject : integration.subject);
39094
- if (!isTimebackSubject3(subject)) {
39642
+ const subject = patch.subject ?? (isTimebackSubject(liveSubject) ? liveSubject : integration.subject);
39643
+ if (!isTimebackSubject(subject)) {
39095
39644
  throw new ValidationError(`Invalid subject "${subject}"`);
39096
39645
  }
39097
39646
  setAttributes({
@@ -39101,14 +39650,14 @@ var init_timeback_service = __esm(() => {
39101
39650
  });
39102
39651
  if (subject !== integration.subject) {
39103
39652
  const subjectConflict = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39104
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, subject))
39653
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, integration.grade), eq(gameTimebackIntegrations.subject, subject), isActiveGameTimebackIntegrationStatus())
39105
39654
  });
39106
39655
  if (subjectConflict && subjectConflict.id !== integration.id) {
39107
39656
  throw new ValidationError(`A TimeBack integration already exists for ${subject} Grade ${integration.grade}`);
39108
39657
  }
39109
39658
  }
39110
- const totalXp = "totalXp" in patch ? patch.totalXp ?? null : TimebackService.getTotalXpFromConfig(timebackConfig) ?? integration.totalXp ?? null;
39111
- const masterableUnits = "masterableUnits" in patch ? patch.masterableUnits ?? null : TimebackService.getMasterableUnitsFromConfig(timebackConfig);
39659
+ const totalXp = "totalXp" in patch ? patch.totalXp ?? null : getTotalXpFromTimebackConfig(timebackConfig) ?? integration.totalXp ?? null;
39660
+ const masterableUnits = "masterableUnits" in patch ? patch.masterableUnits ?? null : getMasterableUnitsFromTimebackConfig(timebackConfig);
39112
39661
  setAttributes({
39113
39662
  "app.timeback.total_xp": totalXp,
39114
39663
  "app.timeback.masterable_units": masterableUnits
@@ -39128,7 +39677,7 @@ var init_timeback_service = __esm(() => {
39128
39677
  if (!updated) {
39129
39678
  throw new NotFoundError("Timeback integration", `${gameId}:${courseId}`);
39130
39679
  }
39131
- return this.toGameTimebackIntegration(updated);
39680
+ return toGameTimebackIntegration(updated);
39132
39681
  });
39133
39682
  }
39134
39683
  async verifyIntegration(gameId, user) {
@@ -39138,7 +39687,7 @@ var init_timeback_service = __esm(() => {
39138
39687
  await this.deps.validateDeveloperAccess(user, gameId);
39139
39688
  TimebackService.recordIntegrationOperation("verify_integration");
39140
39689
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
39141
- where: eq(gameTimebackIntegrations.gameId, gameId)
39690
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39142
39691
  });
39143
39692
  if (integrations.length === 0) {
39144
39693
  throw new NotFoundError("Timeback integration", gameId);
@@ -39151,7 +39700,7 @@ var init_timeback_service = __esm(() => {
39151
39700
  const errors3 = Object.entries(resources).filter(([_, r]) => !r.found).map(([name3]) => `${name3} not found`);
39152
39701
  const status = allFound ? "success" : "error";
39153
39702
  return {
39154
- integration: this.toGameTimebackIntegration({
39703
+ integration: toGameTimebackIntegration({
39155
39704
  ...integration,
39156
39705
  lastVerifiedAt: now2
39157
39706
  }),
@@ -39160,7 +39709,7 @@ var init_timeback_service = __esm(() => {
39160
39709
  ...errors3.length > 0 && { errors: errors3 }
39161
39710
  };
39162
39711
  }));
39163
- await db2.update(gameTimebackIntegrations).set({ lastVerifiedAt: now2 }).where(eq(gameTimebackIntegrations.gameId, gameId));
39712
+ await db2.update(gameTimebackIntegrations).set({ lastVerifiedAt: now2 }).where(inArray(gameTimebackIntegrations.id, integrations.map((integration) => integration.id)));
39164
39713
  const overallStatus = results.every((r) => r.status === "success") ? "success" : "error";
39165
39714
  const missingResourceCount = results.reduce((count, result) => count + (result.errors?.length ?? 0), 0);
39166
39715
  setAttributes({
@@ -39176,7 +39725,7 @@ var init_timeback_service = __esm(() => {
39176
39725
  const client = this.requireClient();
39177
39726
  await this.deps.validateDeveloperAccess(user, gameId);
39178
39727
  const integration = await this.deps.db.query.gameTimebackIntegrations.findFirst({
39179
- where: eq(gameTimebackIntegrations.gameId, gameId)
39728
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39180
39729
  });
39181
39730
  if (!integration) {
39182
39731
  throw new NotFoundError("Timeback integration", gameId);
@@ -39203,24 +39752,6 @@ var init_timeback_service = __esm(() => {
39203
39752
  await db2.delete(gameTimebackIntegrations).where(eq(gameTimebackIntegrations.gameId, gameId));
39204
39753
  });
39205
39754
  }
39206
- static getMasterableUnitsFromConfig(config2) {
39207
- const playcademyMetadata = config2.resource.metadata?.playcademy;
39208
- if (!isPlaycademyResourceMetadata2(playcademyMetadata)) {
39209
- return null;
39210
- }
39211
- return playcademyMetadata?.mastery?.masterableUnits ?? null;
39212
- }
39213
- static getTotalXpFromConfig(config2) {
39214
- const courseMetadata = isCourseMetadata(config2.course.metadata) ? config2.course.metadata : undefined;
39215
- if (typeof courseMetadata?.metrics?.totalXp === "number") {
39216
- return courseMetadata.metrics.totalXp;
39217
- }
39218
- const resourceMetadata = config2.resource.metadata;
39219
- if (isRecord2(resourceMetadata) && typeof resourceMetadata.xp === "number") {
39220
- return resourceMetadata.xp;
39221
- }
39222
- return null;
39223
- }
39224
39755
  static patchCourseMetadata(metadata2, totalXp, options) {
39225
39756
  const nextMetadata = isRecord2(metadata2) ? { ...metadata2 } : {};
39226
39757
  const currentMetrics = isRecord2(nextMetadata.metrics) ? nextMetadata.metrics : {};
@@ -39343,31 +39874,29 @@ var init_timeback_service = __esm(() => {
39343
39874
  }
39344
39875
  };
39345
39876
  }
39346
- toGameTimebackIntegration(integration) {
39877
+ toRemovedGameTimebackIntegration(integration, config2) {
39878
+ const grade = config2.course.grades[0] ?? integration.grade;
39879
+ if (!isTimebackGrade(grade)) {
39880
+ throw new ValidationError(`Invalid grade "${grade}"`);
39881
+ }
39347
39882
  return {
39348
- id: integration.id,
39349
- gameId: integration.gameId,
39350
- courseId: integration.courseId,
39351
- grade: integration.grade,
39352
- subject: integration.subject,
39353
- totalXp: integration.totalXp ?? null,
39354
- createdAt: integration.createdAt,
39355
- updatedAt: integration.updatedAt,
39356
- lastVerifiedAt: integration.lastVerifiedAt ?? null
39883
+ ...this.toGameTimebackIntegrationConfig(integration, config2),
39884
+ grade,
39885
+ removedAt: integration.deactivatedAt ?? null
39357
39886
  };
39358
39887
  }
39359
39888
  toGameTimebackIntegrationConfig(integration, config2) {
39360
39889
  const subject = config2.course.subjects[0] ?? integration.subject;
39361
- if (!isTimebackSubject3(subject)) {
39890
+ if (!isTimebackSubject(subject)) {
39362
39891
  throw new ValidationError(`Invalid subject "${subject}"`);
39363
39892
  }
39364
39893
  return {
39365
- integration: this.toGameTimebackIntegration(integration),
39894
+ integration: toGameTimebackIntegration(integration),
39366
39895
  title: config2.course.title,
39367
39896
  courseCode: config2.course.courseCode,
39368
39897
  subject,
39369
- totalXp: TimebackService.getTotalXpFromConfig(config2) ?? integration.totalXp ?? null,
39370
- masterableUnits: TimebackService.getMasterableUnitsFromConfig(config2),
39898
+ totalXp: getTotalXpFromTimebackConfig(config2) ?? integration.totalXp ?? null,
39899
+ masterableUnits: getMasterableUnitsFromTimebackConfig(config2),
39371
39900
  metadata: isCourseMetadata(config2.course.metadata) ? config2.course.metadata : null
39372
39901
  };
39373
39902
  }
@@ -39399,7 +39928,7 @@ var init_timeback_service = __esm(() => {
39399
39928
  });
39400
39929
  await this.deps.validateDeveloperAccess(user, gameId);
39401
39930
  const integration = await db2.query.gameTimebackIntegrations.findFirst({
39402
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject))
39931
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject), isActiveGameTimebackIntegrationStatus())
39403
39932
  });
39404
39933
  if (!integration) {
39405
39934
  throw new NotFoundError(`Timeback integration for game (grade ${activityData.grade}, subject ${activityData.subject})`);
@@ -39460,9 +39989,7 @@ var init_timeback_service = __esm(() => {
39460
39989
  "app.timeback.xp_awarded": result.xpAwarded,
39461
39990
  "app.timeback.mastered_units_requested": masteredUnits,
39462
39991
  "app.timeback.mastered_units_absolute_requested": masteredUnitsAbsolute,
39463
- "app.timeback.mastered_units_applied": result.masteredUnitsApplied,
39464
- "app.timeback.score_status": result.scoreStatus,
39465
- "app.timeback.in_progress": result.inProgress
39992
+ "app.timeback.mastered_units_applied": result.masteredUnitsApplied
39466
39993
  });
39467
39994
  return {
39468
39995
  status: "ok",
@@ -39470,8 +39997,6 @@ var init_timeback_service = __esm(() => {
39470
39997
  xpAwarded: result.xpAwarded,
39471
39998
  masteredUnits: result.masteredUnitsApplied,
39472
39999
  pctCompleteApp: result.pctCompleteApp,
39473
- scoreStatus: result.scoreStatus,
39474
- inProgress: result.inProgress,
39475
40000
  ...result.warnings ? { warnings: result.warnings } : {}
39476
40001
  };
39477
40002
  }
@@ -39484,7 +40009,7 @@ var init_timeback_service = __esm(() => {
39484
40009
  const client = this.requireClient();
39485
40010
  const db2 = this.deps.db;
39486
40011
  const integrations = await db2.query.gameTimebackIntegrations.findMany({
39487
- where: subject ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.subject, subject)) : eq(gameTimebackIntegrations.gameId, gameId)
40012
+ where: subject ? and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.subject, subject), isActiveGameTimebackIntegrationStatus()) : and(eq(gameTimebackIntegrations.gameId, gameId), isActiveGameTimebackIntegrationStatus())
39488
40013
  });
39489
40014
  if (integrations.length === 0) {
39490
40015
  throw new NotFoundError(subject ? `Timeback integrations for game (subject ${subject})` : "Timeback integrations for game");
@@ -39666,7 +40191,7 @@ var init_timeback_service = __esm(() => {
39666
40191
  }
39667
40192
  const pendingHeartbeat = (async () => {
39668
40193
  const integration = await db2.query.gameTimebackIntegrations.findFirst({
39669
- where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject))
40194
+ where: and(eq(gameTimebackIntegrations.gameId, gameId), eq(gameTimebackIntegrations.grade, activityData.grade), eq(gameTimebackIntegrations.subject, activityData.subject), isActiveGameTimebackIntegrationStatus())
39670
40195
  });
39671
40196
  if (!integration) {
39672
40197
  throw new NotFoundError(`Timeback integration for game (grade ${activityData.grade}, subject ${activityData.subject})`);
@@ -39714,7 +40239,10 @@ var init_timeback_service = __esm(() => {
39714
40239
  let courseIds = [];
39715
40240
  if (options?.gameId) {
39716
40241
  await this.deps.validateDeveloperAccess(user, options.gameId);
39717
- const conditions2 = [eq(gameTimebackIntegrations.gameId, options.gameId)];
40242
+ const conditions2 = [
40243
+ eq(gameTimebackIntegrations.gameId, options.gameId),
40244
+ isActiveGameTimebackIntegrationStatus()
40245
+ ];
39718
40246
  if (options.grade !== undefined && options.subject) {
39719
40247
  conditions2.push(eq(gameTimebackIntegrations.grade, options.grade));
39720
40248
  conditions2.push(eq(gameTimebackIntegrations.subject, options.subject));
@@ -39741,7 +40269,10 @@ var init_timeback_service = __esm(() => {
39741
40269
  const client = this.requireClient();
39742
40270
  const db2 = this.deps.db;
39743
40271
  await this.deps.validateDeveloperAccess(user, options.gameId);
39744
- const conditions2 = [eq(gameTimebackIntegrations.gameId, options.gameId)];
40272
+ const conditions2 = [
40273
+ eq(gameTimebackIntegrations.gameId, options.gameId),
40274
+ isActiveGameTimebackIntegrationStatus()
40275
+ ];
39745
40276
  if (options.grade !== undefined && options.subject) {
39746
40277
  conditions2.push(eq(gameTimebackIntegrations.grade, options.grade));
39747
40278
  conditions2.push(eq(gameTimebackIntegrations.subject, options.subject));
@@ -39768,7 +40299,7 @@ var init_timeback_service = __esm(() => {
39768
40299
  const db2 = this.deps.db;
39769
40300
  await this.deps.validateDeveloperAccess(user, options.gameId);
39770
40301
  const integration = await db2.query.gameTimebackIntegrations.findFirst({
39771
- where: and(eq(gameTimebackIntegrations.gameId, options.gameId), eq(gameTimebackIntegrations.subject, options.subject))
40302
+ where: and(eq(gameTimebackIntegrations.gameId, options.gameId), eq(gameTimebackIntegrations.subject, options.subject), isActiveGameTimebackIntegrationStatus())
39772
40303
  });
39773
40304
  if (!integration) {
39774
40305
  throw new ValidationError(`Subject "${options.subject}" is not configured for game ${options.gameId}`);
@@ -40655,7 +41186,7 @@ class UserService {
40655
41186
  return [];
40656
41187
  }
40657
41188
  const integrations = await this.deps.db.query.gameTimebackIntegrations.findMany({
40658
- where: inArray(gameTimebackIntegrations.courseId, courseIds)
41189
+ where: and(inArray(gameTimebackIntegrations.courseId, courseIds), isActiveGameTimebackIntegrationStatus())
40659
41190
  });
40660
41191
  return mapEnrollmentsToUserEnrollments(enrollments, integrations);
40661
41192
  } catch (error) {
@@ -40677,6 +41208,7 @@ class UserService {
40677
41208
  var init_user_service = __esm(() => {
40678
41209
  init_drizzle_orm();
40679
41210
  init_src();
41211
+ init_helpers_index();
40680
41212
  init_tables_index();
40681
41213
  init_spans();
40682
41214
  init_errors();
@@ -56874,7 +57406,7 @@ function extractTablesRelationalConfig2(schema5, configHelpers) {
56874
57406
  return { tables: tablesConfig, tableNamesMap };
56875
57407
  }
56876
57408
  function relations3(table62, relations22) {
56877
- return new Relations2(table62, (helpers) => Object.fromEntries(Object.entries(relations22(helpers)).map(([key, value]) => [
57409
+ return new Relations2(table62, (helpers3) => Object.fromEntries(Object.entries(relations22(helpers3)).map(([key, value]) => [
56878
57410
  key,
56879
57411
  value.withFieldName(key)
56880
57412
  ])));
@@ -58048,7 +58580,7 @@ var __create2, __defProp3, __getOwnPropDesc, __getOwnPropNames2, __getProtoOf2,
58048
58580
  __defProp3(to, key, { get: () => from[key], enumerable: !(desc2 = __getOwnPropDesc(from, key)) || desc2.enumerable });
58049
58581
  }
58050
58582
  return to;
58051
- }, __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) => {
58583
+ }, __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) => {
58052
58584
  const matchers = filters.map((it3) => {
58053
58585
  return new Minimatch(it3);
58054
58586
  });
@@ -61947,7 +62479,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
61947
62479
  en_default2 = errorMap2;
61948
62480
  }
61949
62481
  });
61950
- init_errors5 = __esm7({
62482
+ init_errors8 = __esm7({
61951
62483
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/errors.js"() {
61952
62484
  init_en2();
61953
62485
  overrideErrorMap2 = en_default2;
@@ -61955,7 +62487,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
61955
62487
  });
61956
62488
  init_parseUtil2 = __esm7({
61957
62489
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/helpers/parseUtil.js"() {
61958
- init_errors5();
62490
+ init_errors8();
61959
62491
  init_en2();
61960
62492
  makeIssue2 = (params) => {
61961
62493
  const { data, path: path2, errorMaps, issueData } = params;
@@ -62061,7 +62593,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
62061
62593
  init_types5 = __esm7({
62062
62594
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/types.js"() {
62063
62595
  init_ZodError2();
62064
- init_errors5();
62596
+ init_errors8();
62065
62597
  init_errorUtil2();
62066
62598
  init_parseUtil2();
62067
62599
  init_util2();
@@ -65219,7 +65751,7 @@ See: https://github.com/isaacs/node-glob/issues/167`);
65219
65751
  });
65220
65752
  init_external2 = __esm7({
65221
65753
  "../node_modules/.pnpm/zod@3.25.42/node_modules/zod/dist/esm/v3/external.js"() {
65222
- init_errors5();
65754
+ init_errors8();
65223
65755
  init_parseUtil2();
65224
65756
  init_typeAliases2();
65225
65757
  init_util2();
@@ -95881,7 +96413,7 @@ async function seedTimebackIntegrations(db2, gameId, courses) {
95881
96413
  const courseId = course.courseId || `mock-${course.subject.toLowerCase()}-g${course.grade}`;
95882
96414
  try {
95883
96415
  const existing = await db2.query.gameTimebackIntegrations.findFirst({
95884
- where: (table9, { and: and3, eq: eq3 }) => and3(eq3(table9.gameId, gameId), eq3(table9.grade, course.grade), eq3(table9.subject, course.subject))
96416
+ where: (table9, { and: and3, eq: eq3 }) => and3(eq3(table9.gameId, gameId), eq3(table9.grade, course.grade), eq3(table9.subject, course.subject), isActiveGameTimebackIntegrationStatus(table9.status))
95885
96417
  });
95886
96418
  if (!existing) {
95887
96419
  await db2.insert(gameTimebackIntegrations).values({
@@ -95901,6 +96433,7 @@ async function seedTimebackIntegrations(db2, gameId, courses) {
95901
96433
  return seededCount;
95902
96434
  }
95903
96435
  var init_timeback5 = __esm(() => {
96436
+ init_helpers_index();
95904
96437
  init_tables_index();
95905
96438
  init_config();
95906
96439
  });
@@ -97135,7 +97668,7 @@ var init_game_member_controller = __esm(() => {
97135
97668
  });
97136
97669
 
97137
97670
  // ../api-core/src/controllers/game.controller.ts
97138
- var list2, listAccessible, getSubjects, getById, getBySlug, getManifest, upsertBySlug, patchGameMetadata, remove2, games2;
97671
+ var list2, listAccessible, getSubjects, getTimebackSummaries, getById, getBySlug, getManifest, upsertBySlug, patchGameMetadata, remove2, games2;
97139
97672
  var init_game_controller = __esm(() => {
97140
97673
  init_esm();
97141
97674
  init_schemas_index();
@@ -97144,6 +97677,7 @@ var init_game_controller = __esm(() => {
97144
97677
  list2 = requireNonAnonymous(async (ctx) => ctx.services.game.list(ctx.user));
97145
97678
  listAccessible = requireNonAnonymous(async (ctx) => ctx.services.game.listAccessible(ctx.user));
97146
97679
  getSubjects = requireNonAnonymous(async (ctx) => ctx.services.game.getSubjects());
97680
+ getTimebackSummaries = requireGameManagementAccess(async (ctx) => ctx.services.game.getTimebackSummaries(ctx.user));
97147
97681
  getById = requireNonAnonymous(async (ctx) => {
97148
97682
  const gameId = requireGameId(ctx.params.gameId);
97149
97683
  return ctx.services.game.getById(gameId, ctx.user);
@@ -97191,6 +97725,7 @@ var init_game_controller = __esm(() => {
97191
97725
  list: list2,
97192
97726
  listAccessible,
97193
97727
  getSubjects,
97728
+ getTimebackSummaries,
97194
97729
  getById,
97195
97730
  getManifest,
97196
97731
  getBySlug,
@@ -97582,7 +98117,7 @@ var init_session_controller = __esm(() => {
97582
98117
  });
97583
98118
 
97584
98119
  // ../api-core/src/controllers/timeback.controller.ts
97585
- 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;
98120
+ 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;
97586
98121
  var init_timeback_controller = __esm(() => {
97587
98122
  init_esm();
97588
98123
  init_schemas_index();
@@ -97638,6 +98173,27 @@ var init_timeback_controller = __esm(() => {
97638
98173
  }
97639
98174
  return ctx.services.timeback.getIntegrations(gameId, ctx.user);
97640
98175
  });
98176
+ getRemovedIntegrations = requireGameManagementAccess(async (ctx) => {
98177
+ const gameId = ctx.params.gameId;
98178
+ if (!gameId) {
98179
+ throw ApiError.badRequest("Missing gameId");
98180
+ }
98181
+ if (!isValidUUID(gameId)) {
98182
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98183
+ }
98184
+ return ctx.services.timeback.getRemovedIntegrations(gameId, ctx.user);
98185
+ });
98186
+ createIntegration = requireDeveloper(async (ctx) => {
98187
+ const gameId = ctx.params.gameId;
98188
+ if (!gameId) {
98189
+ throw ApiError.badRequest("Missing gameId");
98190
+ }
98191
+ if (!isValidUUID(gameId)) {
98192
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98193
+ }
98194
+ const body2 = await parseRequestBody(ctx.request, CreateGameTimebackIntegrationRequestSchema);
98195
+ return ctx.services.timeback.createIntegration(gameId, ctx.user, body2);
98196
+ });
97641
98197
  updateIntegration = requireDeveloper(async (ctx) => {
97642
98198
  const { gameId, courseId } = ctx.params;
97643
98199
  if (!gameId || !courseId) {
@@ -97649,6 +98205,26 @@ var init_timeback_controller = __esm(() => {
97649
98205
  const body2 = await parseRequestBody(ctx.request, UpdateGameTimebackIntegrationRequestSchema);
97650
98206
  return ctx.services.timeback.updateIntegration(gameId, courseId, ctx.user, body2);
97651
98207
  });
98208
+ deactivateCourse = requireDeveloper(async (ctx) => {
98209
+ const { gameId, courseId } = ctx.params;
98210
+ if (!gameId || !courseId) {
98211
+ throw ApiError.badRequest("Missing gameId or courseId parameter");
98212
+ }
98213
+ if (!isValidUUID(gameId)) {
98214
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98215
+ }
98216
+ return ctx.services.timeback.deactivateCourse(gameId, courseId, ctx.user);
98217
+ });
98218
+ reactivateCourse = requireDeveloper(async (ctx) => {
98219
+ const { gameId, courseId } = ctx.params;
98220
+ if (!gameId || !courseId) {
98221
+ throw ApiError.badRequest("Missing gameId or courseId parameter");
98222
+ }
98223
+ if (!isValidUUID(gameId)) {
98224
+ throw ApiError.unprocessableEntity("Invalid gameId format");
98225
+ }
98226
+ return ctx.services.timeback.reactivateCourse(gameId, courseId, ctx.user);
98227
+ });
97652
98228
  getIntegrationConfig = requireGameManagementAccess(async (ctx) => {
97653
98229
  const { gameId, courseId } = ctx.params;
97654
98230
  if (!gameId || !courseId) {
@@ -97798,11 +98374,11 @@ var init_timeback_controller = __esm(() => {
97798
98374
  let subject;
97799
98375
  if (gradeParam !== null && subjectParam !== null) {
97800
98376
  const parsedGrade = parseInt(gradeParam, 10);
97801
- if (!isTimebackGrade(parsedGrade)) {
98377
+ if (!isTimebackGrade2(parsedGrade)) {
97802
98378
  throw ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
97803
98379
  }
97804
- if (!isTimebackSubject(subjectParam)) {
97805
- throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
98380
+ if (!isTimebackSubject2(subjectParam)) {
98381
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
97806
98382
  }
97807
98383
  grade = parsedGrade;
97808
98384
  subject = subjectParam;
@@ -97838,11 +98414,11 @@ var init_timeback_controller = __esm(() => {
97838
98414
  let subject;
97839
98415
  if (gradeParam !== null && subjectParam !== null) {
97840
98416
  const parsedGrade = parseInt(gradeParam, 10);
97841
- if (!isTimebackGrade(parsedGrade)) {
98417
+ if (!isTimebackGrade2(parsedGrade)) {
97842
98418
  throw ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
97843
98419
  }
97844
- if (!isTimebackSubject(subjectParam)) {
97845
- throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
98420
+ if (!isTimebackSubject2(subjectParam)) {
98421
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
97846
98422
  }
97847
98423
  grade = parsedGrade;
97848
98424
  subject = subjectParam;
@@ -97872,8 +98448,8 @@ var init_timeback_controller = __esm(() => {
97872
98448
  if (!subjectParam) {
97873
98449
  throw ApiError.badRequest("Missing required subject query parameter");
97874
98450
  }
97875
- if (!isTimebackSubject(subjectParam)) {
97876
- throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
98451
+ if (!isTimebackSubject2(subjectParam)) {
98452
+ throw ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
97877
98453
  }
97878
98454
  return ctx.services.timeback.getStudentHighestGradeMastered(timebackId, ctx.user, {
97879
98455
  gameId,
@@ -98184,7 +98760,11 @@ var init_timeback_controller = __esm(() => {
98184
98760
  getUserById,
98185
98761
  setupIntegration,
98186
98762
  getIntegrations,
98763
+ getRemovedIntegrations,
98764
+ createIntegration,
98187
98765
  updateIntegration,
98766
+ deactivateCourse,
98767
+ reactivateCourse,
98188
98768
  getIntegrationConfig,
98189
98769
  verifyIntegration,
98190
98770
  getConfig,
@@ -99181,12 +99761,12 @@ var init_timeback7 = __esm(() => {
99181
99761
  }
99182
99762
  if (gradeParam !== null && subjectParam !== null) {
99183
99763
  const grade = parseInt(gradeParam, 10);
99184
- if (!Number.isFinite(grade) || !isTimebackGrade(grade)) {
99764
+ if (!Number.isFinite(grade) || !isTimebackGrade2(grade)) {
99185
99765
  const error2 = ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
99186
99766
  return c2.json(createErrorResponse(error2), error2.status);
99187
99767
  }
99188
- if (!isTimebackSubject(subjectParam)) {
99189
- const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
99768
+ if (!isTimebackSubject2(subjectParam)) {
99769
+ const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
99190
99770
  return c2.json(createErrorResponse(error2), error2.status);
99191
99771
  }
99192
99772
  enrollments = enrollments.filter((e) => e.grade === grade && e.subject === subjectParam);
@@ -99239,12 +99819,12 @@ var init_timeback7 = __esm(() => {
99239
99819
  }
99240
99820
  if (gradeParam !== null && subjectParam !== null) {
99241
99821
  const grade = parseInt(gradeParam, 10);
99242
- if (!Number.isFinite(grade) || !isTimebackGrade(grade)) {
99822
+ if (!Number.isFinite(grade) || !isTimebackGrade2(grade)) {
99243
99823
  const error2 = ApiError.badRequest(`Invalid grade: ${gradeParam}. Valid grades: ${TIMEBACK_GRADES.join(", ")}`);
99244
99824
  return c2.json(createErrorResponse(error2), error2.status);
99245
99825
  }
99246
- if (!isTimebackSubject(subjectParam)) {
99247
- const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
99826
+ if (!isTimebackSubject2(subjectParam)) {
99827
+ const error2 = ApiError.badRequest(`Invalid subject: ${subjectParam}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
99248
99828
  return c2.json(createErrorResponse(error2), error2.status);
99249
99829
  }
99250
99830
  enrollments = enrollments.filter((e) => e.grade === grade && e.subject === subjectParam);
@@ -99293,8 +99873,8 @@ var init_timeback7 = __esm(() => {
99293
99873
  const error2 = ApiError.badRequest("Missing required gameId query parameter");
99294
99874
  return c2.json(createErrorResponse(error2), error2.status);
99295
99875
  }
99296
- if (!isTimebackSubject(subject)) {
99297
- const error2 = ApiError.badRequest(`Invalid subject: ${subject}. Valid subjects: ${TIMEBACK_SUBJECTS.join(", ")}`);
99876
+ if (!isTimebackSubject2(subject)) {
99877
+ const error2 = ApiError.badRequest(`Invalid subject: ${subject}. Valid subjects: ${TIMEBACK_SUBJECTS2.join(", ")}`);
99298
99878
  return c2.json(createErrorResponse(error2), error2.status);
99299
99879
  }
99300
99880
  const db2 = c2.get("db");