@timeback/sdk 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/adapters/react/hooks/types.d.ts +15 -0
- package/dist/client/adapters/react/hooks/types.d.ts.map +1 -0
- package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts +18 -0
- package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts.map +1 -0
- package/dist/client/adapters/react/index.d.ts +2 -0
- package/dist/client/adapters/react/index.d.ts.map +1 -1
- package/dist/client/adapters/react/index.js +139 -9
- package/dist/client/auth/bearer.d.ts +17 -0
- package/dist/client/auth/bearer.d.ts.map +1 -0
- package/dist/client/auth/index.d.ts +3 -0
- package/dist/client/auth/index.d.ts.map +1 -0
- package/dist/client/auth/types.d.ts +39 -0
- package/dist/client/auth/types.d.ts.map +1 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/lib/fetch.d.ts +19 -0
- package/dist/client/lib/fetch.d.ts.map +1 -0
- package/dist/client/namespaces/user.d.ts +25 -2
- package/dist/client/namespaces/user.d.ts.map +1 -1
- package/dist/client/timeback-client.class.d.ts +15 -0
- package/dist/client/timeback-client.class.d.ts.map +1 -1
- package/dist/client/timeback-client.d.ts +3 -0
- package/dist/client/timeback-client.d.ts.map +1 -1
- package/dist/client.d.ts +2 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +69 -6
- package/dist/edge.js +85291 -169
- package/dist/identity.js +85186 -74
- package/dist/index.js +773 -493
- package/dist/server/adapters/express.d.ts.map +1 -1
- package/dist/server/adapters/express.js +169 -193
- package/dist/server/adapters/native.d.ts.map +1 -1
- package/dist/server/adapters/native.js +32 -1
- package/dist/server/adapters/nextjs.js +32 -1
- package/dist/server/adapters/nuxt.d.ts.map +1 -1
- package/dist/server/adapters/nuxt.js +173 -193
- package/dist/server/adapters/solid-start.d.ts.map +1 -1
- package/dist/server/adapters/solid-start.js +173 -193
- package/dist/server/adapters/svelte-kit.d.ts.map +1 -1
- package/dist/server/adapters/svelte-kit.js +37 -1
- package/dist/server/adapters/tanstack-start.d.ts.map +1 -1
- package/dist/server/adapters/tanstack-start.js +168 -193
- package/dist/server/adapters/utils.d.ts +1 -1
- package/dist/server/adapters/utils.d.ts.map +1 -1
- package/dist/server/{lib/build-activity-events.d.ts → handlers/activity/caliper.d.ts} +29 -4
- package/dist/server/handlers/activity/caliper.d.ts.map +1 -0
- package/dist/server/handlers/activity/gradebook.d.ts +56 -0
- package/dist/server/handlers/activity/gradebook.d.ts.map +1 -0
- package/dist/server/handlers/activity/handler.d.ts +15 -0
- package/dist/server/handlers/activity/handler.d.ts.map +1 -0
- package/dist/server/handlers/activity/index.d.ts +9 -0
- package/dist/server/handlers/activity/index.d.ts.map +1 -0
- package/dist/server/handlers/activity/resolve.d.ts +39 -0
- package/dist/server/handlers/activity/resolve.d.ts.map +1 -0
- package/dist/server/handlers/activity/schema.d.ts +52 -0
- package/dist/server/handlers/activity/schema.d.ts.map +1 -0
- package/dist/server/handlers/activity/types.d.ts +52 -0
- package/dist/server/handlers/activity/types.d.ts.map +1 -0
- package/dist/server/handlers/identity/handler.d.ts +14 -0
- package/dist/server/handlers/identity/handler.d.ts.map +1 -0
- package/dist/server/handlers/identity/index.d.ts +8 -0
- package/dist/server/handlers/identity/index.d.ts.map +1 -0
- package/dist/server/handlers/identity/oidc.d.ts +43 -0
- package/dist/server/handlers/identity/oidc.d.ts.map +1 -0
- package/dist/server/handlers/identity/types.d.ts +24 -0
- package/dist/server/handlers/identity/types.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/handler.d.ts +15 -0
- package/dist/server/handlers/identity-only/handler.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/index.d.ts +8 -0
- package/dist/server/handlers/identity-only/index.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/oidc.d.ts +26 -0
- package/dist/server/handlers/identity-only/oidc.d.ts.map +1 -0
- package/dist/server/handlers/identity-only/types.d.ts +19 -0
- package/dist/server/handlers/identity-only/types.d.ts.map +1 -0
- package/dist/server/handlers/index.d.ts +5 -2
- package/dist/server/handlers/index.d.ts.map +1 -1
- package/dist/server/{lib/build-user-profile.d.ts → handlers/user/enrollments.d.ts} +7 -2
- package/dist/server/handlers/user/enrollments.d.ts.map +1 -0
- package/dist/server/handlers/user/handler.d.ts +17 -0
- package/dist/server/handlers/user/handler.d.ts.map +1 -0
- package/dist/server/handlers/user/index.d.ts +10 -0
- package/dist/server/handlers/user/index.d.ts.map +1 -0
- package/dist/server/handlers/user/profile.d.ts +22 -0
- package/dist/server/handlers/user/profile.d.ts.map +1 -0
- package/dist/server/handlers/user/types.d.ts +35 -0
- package/dist/server/handlers/user/types.d.ts.map +1 -0
- package/dist/server/handlers/user/verify.d.ts +25 -0
- package/dist/server/handlers/user/verify.d.ts.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/lib/index.d.ts +4 -5
- package/dist/server/lib/index.d.ts.map +1 -1
- package/dist/server/lib/resolve.d.ts +4 -42
- package/dist/server/lib/resolve.d.ts.map +1 -1
- package/dist/server/lib/sso.d.ts +86 -0
- package/dist/server/lib/sso.d.ts.map +1 -0
- package/dist/server/lib/utils.d.ts +32 -1
- package/dist/server/lib/utils.d.ts.map +1 -1
- package/dist/server/timeback-identity.d.ts.map +1 -1
- package/dist/server/timeback.d.ts.map +1 -1
- package/dist/server/types.d.ts +16 -9
- package/dist/server/types.d.ts.map +1 -1
- package/dist/shared/constants.d.ts +1 -0
- package/dist/shared/constants.d.ts.map +1 -1
- package/dist/shared/types.d.ts +15 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/package.json +6 -2
- package/dist/server/handlers/activity.d.ts +0 -25
- package/dist/server/handlers/activity.d.ts.map +0 -1
- package/dist/server/handlers/identity-full.d.ts +0 -28
- package/dist/server/handlers/identity-full.d.ts.map +0 -1
- package/dist/server/handlers/identity-only.d.ts +0 -22
- package/dist/server/handlers/identity-only.d.ts.map +0 -1
- package/dist/server/handlers/user.d.ts +0 -31
- package/dist/server/handlers/user.d.ts.map +0 -1
- package/dist/server/lib/build-activity-events.d.ts.map +0 -1
- package/dist/server/lib/build-user-profile.d.ts.map +0 -1
|
@@ -434,12 +434,32 @@ async function getUserInfo(params) {
|
|
|
434
434
|
return response.json();
|
|
435
435
|
}
|
|
436
436
|
// src/server/lib/utils.ts
|
|
437
|
+
function safeIdSegment(value) {
|
|
438
|
+
return encodeURIComponent(value).replace(/%/g, "_");
|
|
439
|
+
}
|
|
440
|
+
function hashSuffix64Base36(value) {
|
|
441
|
+
let hash = 0xcbf29ce484222325n;
|
|
442
|
+
const prime = 0x100000001b3n;
|
|
443
|
+
const mod64 = 0xffffffffffffffffn;
|
|
444
|
+
for (let i = 0;i < value.length; i++) {
|
|
445
|
+
hash ^= BigInt(value.charCodeAt(i));
|
|
446
|
+
hash = hash * prime & mod64;
|
|
447
|
+
}
|
|
448
|
+
const base36 = hash.toString(36);
|
|
449
|
+
return base36.length > 12 ? base36.slice(-12) : base36;
|
|
450
|
+
}
|
|
437
451
|
function mapEnvForApi(env) {
|
|
438
452
|
if (env === "local" || env === "staging") {
|
|
439
453
|
return "staging";
|
|
440
454
|
}
|
|
441
455
|
return "production";
|
|
442
456
|
}
|
|
457
|
+
function normalizeEnv(env) {
|
|
458
|
+
if (env === "production" || env === "local" || env === "staging") {
|
|
459
|
+
return env;
|
|
460
|
+
}
|
|
461
|
+
return "staging";
|
|
462
|
+
}
|
|
443
463
|
function jsonResponse(data, status = 200, headers) {
|
|
444
464
|
const responseHeaders = new Headers(headers);
|
|
445
465
|
responseHeaders.set("Content-Type", "application/json");
|
|
@@ -15739,14 +15759,20 @@ var TimebackConfig = exports_external.object({
|
|
|
15739
15759
|
message: "Duplicate courseCode found; each must be unique",
|
|
15740
15760
|
path: ["courses"]
|
|
15741
15761
|
}).refine((config2) => {
|
|
15742
|
-
return config2.courses.every((c) =>
|
|
15743
|
-
|
|
15744
|
-
|
|
15745
|
-
|
|
15746
|
-
|
|
15747
|
-
|
|
15762
|
+
return config2.courses.every((c) => {
|
|
15763
|
+
if (c.sensor !== undefined || config2.sensor !== undefined) {
|
|
15764
|
+
return true;
|
|
15765
|
+
}
|
|
15766
|
+
const launchUrls = [
|
|
15767
|
+
c.launchUrl,
|
|
15768
|
+
config2.launchUrl,
|
|
15769
|
+
c.overrides?.staging?.launchUrl,
|
|
15770
|
+
c.overrides?.production?.launchUrl
|
|
15771
|
+
].filter(Boolean);
|
|
15772
|
+
return launchUrls.length > 0;
|
|
15773
|
+
});
|
|
15748
15774
|
}, {
|
|
15749
|
-
message: "Each course must have an effective
|
|
15775
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
15750
15776
|
path: ["courses"]
|
|
15751
15777
|
});
|
|
15752
15778
|
var EdubridgeDateString = exports_external.union([IsoDateString, IsoDateTimeString]);
|
|
@@ -32142,14 +32168,20 @@ var TimebackConfig2 = exports_external2.object({
|
|
|
32142
32168
|
message: "Duplicate courseCode found; each must be unique",
|
|
32143
32169
|
path: ["courses"]
|
|
32144
32170
|
}).refine((config22) => {
|
|
32145
|
-
return config22.courses.every((c) =>
|
|
32146
|
-
|
|
32147
|
-
|
|
32148
|
-
|
|
32149
|
-
|
|
32150
|
-
|
|
32171
|
+
return config22.courses.every((c) => {
|
|
32172
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
32173
|
+
return true;
|
|
32174
|
+
}
|
|
32175
|
+
const launchUrls = [
|
|
32176
|
+
c.launchUrl,
|
|
32177
|
+
config22.launchUrl,
|
|
32178
|
+
c.overrides?.staging?.launchUrl,
|
|
32179
|
+
c.overrides?.production?.launchUrl
|
|
32180
|
+
].filter(Boolean);
|
|
32181
|
+
return launchUrls.length > 0;
|
|
32182
|
+
});
|
|
32151
32183
|
}, {
|
|
32152
|
-
message: "Each course must have an effective
|
|
32184
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
32153
32185
|
path: ["courses"]
|
|
32154
32186
|
});
|
|
32155
32187
|
var EdubridgeDateString2 = exports_external2.union([IsoDateString2, IsoDateTimeString2]);
|
|
@@ -49575,14 +49607,20 @@ var TimebackConfig3 = exports_external3.object({
|
|
|
49575
49607
|
message: "Duplicate courseCode found; each must be unique",
|
|
49576
49608
|
path: ["courses"]
|
|
49577
49609
|
}).refine((config22) => {
|
|
49578
|
-
return config22.courses.every((c) =>
|
|
49579
|
-
|
|
49580
|
-
|
|
49581
|
-
|
|
49582
|
-
|
|
49583
|
-
|
|
49610
|
+
return config22.courses.every((c) => {
|
|
49611
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
49612
|
+
return true;
|
|
49613
|
+
}
|
|
49614
|
+
const launchUrls = [
|
|
49615
|
+
c.launchUrl,
|
|
49616
|
+
config22.launchUrl,
|
|
49617
|
+
c.overrides?.staging?.launchUrl,
|
|
49618
|
+
c.overrides?.production?.launchUrl
|
|
49619
|
+
].filter(Boolean);
|
|
49620
|
+
return launchUrls.length > 0;
|
|
49621
|
+
});
|
|
49584
49622
|
}, {
|
|
49585
|
-
message: "Each course must have an effective
|
|
49623
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
49586
49624
|
path: ["courses"]
|
|
49587
49625
|
});
|
|
49588
49626
|
var EdubridgeDateString3 = exports_external3.union([IsoDateString3, IsoDateTimeString3]);
|
|
@@ -67207,14 +67245,20 @@ var TimebackConfig4 = exports_external4.object({
|
|
|
67207
67245
|
message: "Duplicate courseCode found; each must be unique",
|
|
67208
67246
|
path: ["courses"]
|
|
67209
67247
|
}).refine((config22) => {
|
|
67210
|
-
return config22.courses.every((c) =>
|
|
67211
|
-
|
|
67212
|
-
|
|
67213
|
-
|
|
67214
|
-
|
|
67215
|
-
|
|
67248
|
+
return config22.courses.every((c) => {
|
|
67249
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
67250
|
+
return true;
|
|
67251
|
+
}
|
|
67252
|
+
const launchUrls = [
|
|
67253
|
+
c.launchUrl,
|
|
67254
|
+
config22.launchUrl,
|
|
67255
|
+
c.overrides?.staging?.launchUrl,
|
|
67256
|
+
c.overrides?.production?.launchUrl
|
|
67257
|
+
].filter(Boolean);
|
|
67258
|
+
return launchUrls.length > 0;
|
|
67259
|
+
});
|
|
67216
67260
|
}, {
|
|
67217
|
-
message: "Each course must have an effective
|
|
67261
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
67218
67262
|
path: ["courses"]
|
|
67219
67263
|
});
|
|
67220
67264
|
var EdubridgeDateString4 = exports_external4.union([IsoDateString4, IsoDateTimeString4]);
|
|
@@ -83869,14 +83913,20 @@ var TimebackConfig5 = exports_external5.object({
|
|
|
83869
83913
|
message: "Duplicate courseCode found; each must be unique",
|
|
83870
83914
|
path: ["courses"]
|
|
83871
83915
|
}).refine((config22) => {
|
|
83872
|
-
return config22.courses.every((c) =>
|
|
83873
|
-
|
|
83874
|
-
|
|
83875
|
-
|
|
83876
|
-
|
|
83877
|
-
|
|
83916
|
+
return config22.courses.every((c) => {
|
|
83917
|
+
if (c.sensor !== undefined || config22.sensor !== undefined) {
|
|
83918
|
+
return true;
|
|
83919
|
+
}
|
|
83920
|
+
const launchUrls = [
|
|
83921
|
+
c.launchUrl,
|
|
83922
|
+
config22.launchUrl,
|
|
83923
|
+
c.overrides?.staging?.launchUrl,
|
|
83924
|
+
c.overrides?.production?.launchUrl
|
|
83925
|
+
].filter(Boolean);
|
|
83926
|
+
return launchUrls.length > 0;
|
|
83927
|
+
});
|
|
83878
83928
|
}, {
|
|
83879
|
-
message: "Each course must have an effective
|
|
83929
|
+
message: "Each course must have an effective sensor. Either set `sensor` explicitly (top-level or per-course), or provide a `launchUrl` so sensor can be derived from its origin.",
|
|
83880
83930
|
path: ["courses"]
|
|
83881
83931
|
});
|
|
83882
83932
|
var EdubridgeDateString5 = exports_external5.union([IsoDateString5, IsoDateTimeString5]);
|
|
@@ -85634,163 +85684,6 @@ async function lookupTimebackIdByEmail(params) {
|
|
|
85634
85684
|
throw new TimebackUserResolutionError(`Failed to lookup Timeback user: ${message}`, "timeback_user_lookup_failed");
|
|
85635
85685
|
}
|
|
85636
85686
|
}
|
|
85637
|
-
|
|
85638
|
-
class ActivityCourseResolutionError extends Error {
|
|
85639
|
-
code;
|
|
85640
|
-
selector;
|
|
85641
|
-
count;
|
|
85642
|
-
constructor(code, selector, count) {
|
|
85643
|
-
super(code);
|
|
85644
|
-
this.code = code;
|
|
85645
|
-
this.selector = selector;
|
|
85646
|
-
this.count = count;
|
|
85647
|
-
}
|
|
85648
|
-
get selectorDescription() {
|
|
85649
|
-
if ("grade" in this.selector) {
|
|
85650
|
-
return `${this.selector.subject} grade ${this.selector.grade}`;
|
|
85651
|
-
}
|
|
85652
|
-
return `code "${this.selector.code}"`;
|
|
85653
|
-
}
|
|
85654
|
-
}
|
|
85655
|
-
function resolveActivityCourse(courses, courseRef) {
|
|
85656
|
-
let matches;
|
|
85657
|
-
if ("grade" in courseRef) {
|
|
85658
|
-
matches = courses.filter((c) => c.subject === courseRef.subject && c.grade === courseRef.grade);
|
|
85659
|
-
} else {
|
|
85660
|
-
matches = courses.filter((c) => c.courseCode === courseRef.code);
|
|
85661
|
-
}
|
|
85662
|
-
if (matches.length === 0) {
|
|
85663
|
-
throw new ActivityCourseResolutionError("unknown_course", courseRef);
|
|
85664
|
-
}
|
|
85665
|
-
if (matches.length > 1) {
|
|
85666
|
-
throw new ActivityCourseResolutionError("ambiguous_course", courseRef, matches.length);
|
|
85667
|
-
}
|
|
85668
|
-
return matches[0];
|
|
85669
|
-
}
|
|
85670
|
-
// src/server/lib/build-activity-events.ts
|
|
85671
|
-
class MissingSyncedCourseIdError extends Error {
|
|
85672
|
-
course;
|
|
85673
|
-
env;
|
|
85674
|
-
constructor(course, env) {
|
|
85675
|
-
const identifier = course.grade === undefined ? course.courseCode ?? course.subject : `${course.subject} grade ${course.grade}`;
|
|
85676
|
-
super(`Course "${identifier}" is missing a synced ID for ${env}. Run \`timeback sync\` first.`);
|
|
85677
|
-
this.name = "MissingSyncedCourseIdError";
|
|
85678
|
-
this.course = course;
|
|
85679
|
-
this.env = env;
|
|
85680
|
-
}
|
|
85681
|
-
}
|
|
85682
|
-
function buildCourseId(course, apiEnv) {
|
|
85683
|
-
const courseId = course.ids?.[apiEnv];
|
|
85684
|
-
if (!courseId) {
|
|
85685
|
-
throw new MissingSyncedCourseIdError(course, apiEnv);
|
|
85686
|
-
}
|
|
85687
|
-
return courseId;
|
|
85688
|
-
}
|
|
85689
|
-
function buildCourseName(course) {
|
|
85690
|
-
if (course.courseCode) {
|
|
85691
|
-
return course.courseCode;
|
|
85692
|
-
}
|
|
85693
|
-
if (course.grade !== undefined) {
|
|
85694
|
-
return `${course.subject} G${String(course.grade)}`;
|
|
85695
|
-
}
|
|
85696
|
-
return course.subject;
|
|
85697
|
-
}
|
|
85698
|
-
|
|
85699
|
-
class InvalidSensorUrlError extends Error {
|
|
85700
|
-
sensor;
|
|
85701
|
-
constructor(sensor) {
|
|
85702
|
-
super(`Invalid sensor URL "${sensor}". Sensor must be a valid absolute URL (e.g., "https://sensor.example.com") to support slug-based activity IDs.`);
|
|
85703
|
-
this.name = "InvalidSensorUrlError";
|
|
85704
|
-
this.sensor = sensor;
|
|
85705
|
-
}
|
|
85706
|
-
}
|
|
85707
|
-
function buildCanonicalActivityUrl(sensor, selector, slug) {
|
|
85708
|
-
let base;
|
|
85709
|
-
try {
|
|
85710
|
-
base = new URL(sensor);
|
|
85711
|
-
} catch {
|
|
85712
|
-
throw new InvalidSensorUrlError(sensor);
|
|
85713
|
-
}
|
|
85714
|
-
const pathSegment = "grade" in selector ? `${selector.subject}/g${String(selector.grade)}` : selector.code;
|
|
85715
|
-
const basePath = base.pathname.replace(/\/+$/, "");
|
|
85716
|
-
base.pathname = `${basePath}/activities/${pathSegment}/${encodeURIComponent(slug)}`;
|
|
85717
|
-
return base.toString();
|
|
85718
|
-
}
|
|
85719
|
-
function buildActivityContext(payload, course, appName, apiEnv, sensor) {
|
|
85720
|
-
return {
|
|
85721
|
-
id: buildCanonicalActivityUrl(sensor, payload.course, payload.id),
|
|
85722
|
-
type: "TimebackActivityContext",
|
|
85723
|
-
subject: course.subject,
|
|
85724
|
-
app: { name: appName },
|
|
85725
|
-
activity: { name: payload.name },
|
|
85726
|
-
course: {
|
|
85727
|
-
id: buildCourseId(course, apiEnv),
|
|
85728
|
-
name: buildCourseName(course)
|
|
85729
|
-
}
|
|
85730
|
-
};
|
|
85731
|
-
}
|
|
85732
|
-
function buildActivityMetrics(metrics) {
|
|
85733
|
-
const result = [];
|
|
85734
|
-
if (metrics.totalQuestions !== undefined) {
|
|
85735
|
-
result.push({ type: "totalQuestions", value: metrics.totalQuestions });
|
|
85736
|
-
}
|
|
85737
|
-
if (metrics.correctQuestions !== undefined) {
|
|
85738
|
-
result.push({ type: "correctQuestions", value: metrics.correctQuestions });
|
|
85739
|
-
}
|
|
85740
|
-
if (metrics.xpEarned !== undefined) {
|
|
85741
|
-
result.push({ type: "xpEarned", value: metrics.xpEarned });
|
|
85742
|
-
}
|
|
85743
|
-
if (metrics.masteredUnits !== undefined) {
|
|
85744
|
-
result.push({ type: "masteredUnits", value: metrics.masteredUnits });
|
|
85745
|
-
}
|
|
85746
|
-
return result;
|
|
85747
|
-
}
|
|
85748
|
-
function buildTimeSpentMetrics(elapsedMs, pausedMs) {
|
|
85749
|
-
const result = [{ type: "active", value: Math.max(0, elapsedMs) / 1000 }];
|
|
85750
|
-
if (pausedMs > 0) {
|
|
85751
|
-
result.push({ type: "inactive", value: Math.max(0, pausedMs) / 1000 });
|
|
85752
|
-
}
|
|
85753
|
-
return result;
|
|
85754
|
-
}
|
|
85755
|
-
async function sendCaliperEnvelope(client, sensor, activityEvent, timeSpentEvent) {
|
|
85756
|
-
await client.caliper.events.send(sensor, [activityEvent, timeSpentEvent]);
|
|
85757
|
-
}
|
|
85758
|
-
// src/server/lib/build-user-profile.ts
|
|
85759
|
-
function buildCourseLookup(courses, apiEnv) {
|
|
85760
|
-
const courseById = new Map;
|
|
85761
|
-
for (const course of courses) {
|
|
85762
|
-
const courseId = course.ids?.[apiEnv];
|
|
85763
|
-
if (courseId) {
|
|
85764
|
-
courseById.set(courseId, course);
|
|
85765
|
-
}
|
|
85766
|
-
}
|
|
85767
|
-
return courseById;
|
|
85768
|
-
}
|
|
85769
|
-
function mapEnrollmentsToCourses(enrollments, courseById) {
|
|
85770
|
-
return enrollments.map((enrollment) => {
|
|
85771
|
-
const configuredCourse = courseById.get(enrollment.course.id);
|
|
85772
|
-
return {
|
|
85773
|
-
id: enrollment.course.id,
|
|
85774
|
-
code: configuredCourse?.courseCode ?? enrollment.course.id,
|
|
85775
|
-
name: enrollment.course.title
|
|
85776
|
-
};
|
|
85777
|
-
});
|
|
85778
|
-
}
|
|
85779
|
-
function pickGoalsFromEnrollments(enrollments) {
|
|
85780
|
-
return enrollments.map((enrollment) => enrollment.metadata?.goals).find(Boolean);
|
|
85781
|
-
}
|
|
85782
|
-
function getUtcDayRange(date6) {
|
|
85783
|
-
const start = new Date(Date.UTC(date6.getUTCFullYear(), date6.getUTCMonth(), date6.getUTCDate()));
|
|
85784
|
-
const end = new Date(Date.UTC(date6.getUTCFullYear(), date6.getUTCMonth(), date6.getUTCDate(), 23, 59, 59, 999));
|
|
85785
|
-
return { start, end };
|
|
85786
|
-
}
|
|
85787
|
-
function sumXp(facts) {
|
|
85788
|
-
return Object.values(facts).reduce((dateTotal, subjects) => {
|
|
85789
|
-
return dateTotal + Object.values(subjects).reduce((subjectTotal, metrics) => {
|
|
85790
|
-
return subjectTotal + (metrics.activityMetrics?.xpEarned ?? 0);
|
|
85791
|
-
}, 0);
|
|
85792
|
-
}, 0);
|
|
85793
|
-
}
|
|
85794
85687
|
// src/shared/constants.ts
|
|
85795
85688
|
var ROUTES = {
|
|
85796
85689
|
ACTIVITY: "/activity",
|
|
@@ -85800,10 +85693,83 @@ var ROUTES = {
|
|
|
85800
85693
|
CALLBACK: "/identity/callback"
|
|
85801
85694
|
},
|
|
85802
85695
|
USER: {
|
|
85803
|
-
ME: "/user/me"
|
|
85696
|
+
ME: "/user/me",
|
|
85697
|
+
VERIFY: "/user/verify"
|
|
85804
85698
|
}
|
|
85805
85699
|
};
|
|
85806
85700
|
|
|
85701
|
+
// src/server/lib/sso.ts
|
|
85702
|
+
function buildErrorContext(error57, errorCode, state, req) {
|
|
85703
|
+
return {
|
|
85704
|
+
error: error57,
|
|
85705
|
+
errorCode,
|
|
85706
|
+
state,
|
|
85707
|
+
req,
|
|
85708
|
+
redirect: redirectResponse,
|
|
85709
|
+
json: jsonResponse
|
|
85710
|
+
};
|
|
85711
|
+
}
|
|
85712
|
+
function tryDecodeState(stateParam) {
|
|
85713
|
+
try {
|
|
85714
|
+
return decodeBase64Url(stateParam);
|
|
85715
|
+
} catch {
|
|
85716
|
+
ssoLog.warn("Failed to decode state");
|
|
85717
|
+
return;
|
|
85718
|
+
}
|
|
85719
|
+
}
|
|
85720
|
+
function handleIdpError(errorParam, url6, state, req, onCallbackError) {
|
|
85721
|
+
const errorDesc = url6.searchParams.get("error_description");
|
|
85722
|
+
ssoLog.error("IdP returned error", { error: errorParam, description: errorDesc });
|
|
85723
|
+
const error57 = new Error(errorDesc ?? errorParam);
|
|
85724
|
+
if (onCallbackError) {
|
|
85725
|
+
return onCallbackError(buildErrorContext(error57, errorParam, state, req));
|
|
85726
|
+
}
|
|
85727
|
+
return jsonResponse({ error: errorParam }, 400);
|
|
85728
|
+
}
|
|
85729
|
+
function handleMissingCode(state, req, onCallbackError) {
|
|
85730
|
+
ssoLog.error("Missing authorization code in callback");
|
|
85731
|
+
const error57 = new Error("Missing authorization code");
|
|
85732
|
+
if (onCallbackError) {
|
|
85733
|
+
return onCallbackError(buildErrorContext(error57, "missing_code", state, req));
|
|
85734
|
+
}
|
|
85735
|
+
return jsonResponse({ error: "Missing authorization code" }, 400);
|
|
85736
|
+
}
|
|
85737
|
+
async function initiateSignIn(params) {
|
|
85738
|
+
const { req, env, clientId, buildState } = params;
|
|
85739
|
+
const issuer = params.issuer ?? getIssuer(env);
|
|
85740
|
+
const url6 = new URL(req.url);
|
|
85741
|
+
let redirectUri = params.redirectUri;
|
|
85742
|
+
if (!redirectUri) {
|
|
85743
|
+
const basePath = url6.pathname.replace(ROUTES.IDENTITY.SIGNIN, "");
|
|
85744
|
+
redirectUri = `${url6.origin}${basePath}${ROUTES.IDENTITY.CALLBACK}`;
|
|
85745
|
+
}
|
|
85746
|
+
ssoLog.debug("SSO sign-in initiated", { env, issuer, clientId, redirectUri });
|
|
85747
|
+
const stateData = buildState ? buildState({ req, url: url6 }) : {};
|
|
85748
|
+
const state = encodeBase64Url(stateData);
|
|
85749
|
+
const authUrl = await buildAuthorizationUrl({
|
|
85750
|
+
issuer,
|
|
85751
|
+
clientId,
|
|
85752
|
+
redirectUri,
|
|
85753
|
+
state
|
|
85754
|
+
});
|
|
85755
|
+
return redirectResponse(authUrl);
|
|
85756
|
+
}
|
|
85757
|
+
function parseCallback(req) {
|
|
85758
|
+
const url6 = new URL(req.url);
|
|
85759
|
+
const code = url6.searchParams.get("code");
|
|
85760
|
+
const errorParam = url6.searchParams.get("error");
|
|
85761
|
+
const stateParam = url6.searchParams.get("state");
|
|
85762
|
+
ssoLog.debug("Received callback from IdP", { hasCode: !!code, error: errorParam });
|
|
85763
|
+
const state = stateParam ? tryDecodeState(stateParam) : undefined;
|
|
85764
|
+
return { url: url6, code, errorParam, state };
|
|
85765
|
+
}
|
|
85766
|
+
function computeRedirectUri(url6, configuredRedirectUri) {
|
|
85767
|
+
if (configuredRedirectUri) {
|
|
85768
|
+
return configuredRedirectUri;
|
|
85769
|
+
}
|
|
85770
|
+
const basePath = url6.pathname.replace(ROUTES.IDENTITY.CALLBACK, "");
|
|
85771
|
+
return `${url6.origin}${basePath}${ROUTES.IDENTITY.CALLBACK}`;
|
|
85772
|
+
}
|
|
85807
85773
|
// src/server/adapters/utils.ts
|
|
85808
85774
|
function normalizePathname(path) {
|
|
85809
85775
|
const raw = path.trim();
|
|
@@ -85853,6 +85819,8 @@ function matchTimebackRoute(params) {
|
|
|
85853
85819
|
return "identity.signOut";
|
|
85854
85820
|
if (relative === ROUTES.USER.ME)
|
|
85855
85821
|
return "user.me";
|
|
85822
|
+
if (relative === ROUTES.USER.VERIFY)
|
|
85823
|
+
return "user.verify";
|
|
85856
85824
|
}
|
|
85857
85825
|
if (method === "POST") {
|
|
85858
85826
|
if (relative === ROUTES.ACTIVITY)
|
|
@@ -85878,6 +85846,8 @@ function matchTimebackRoute(params) {
|
|
|
85878
85846
|
return "identity.signOut";
|
|
85879
85847
|
if (pathname.endsWith(ROUTES.USER.ME))
|
|
85880
85848
|
return "user.me";
|
|
85849
|
+
if (pathname.endsWith(ROUTES.USER.VERIFY))
|
|
85850
|
+
return "user.verify";
|
|
85881
85851
|
}
|
|
85882
85852
|
if (method === "POST") {
|
|
85883
85853
|
if (pathname.endsWith(ROUTES.ACTIVITY))
|
|
@@ -86013,6 +85983,11 @@ async function nuxtHandler(options) {
|
|
|
86013
85983
|
return;
|
|
86014
85984
|
return handle.user.me(request);
|
|
86015
85985
|
}
|
|
85986
|
+
if (route === "user.verify") {
|
|
85987
|
+
if (!hasUserHandler(handle))
|
|
85988
|
+
return;
|
|
85989
|
+
return handle.user.verify(request);
|
|
85990
|
+
}
|
|
86016
85991
|
if (route === "activity") {
|
|
86017
85992
|
if (!hasActivityHandler(handle))
|
|
86018
85993
|
return;
|
|
@@ -86042,6 +86017,11 @@ function toNuxtHandler(input) {
|
|
|
86042
86017
|
return jsonResponse({ error: "Not found" }, 404);
|
|
86043
86018
|
return handle.user.me(request);
|
|
86044
86019
|
}
|
|
86020
|
+
if (route === "user.verify") {
|
|
86021
|
+
if (!hasUserHandler(handle))
|
|
86022
|
+
return jsonResponse({ error: "Not found" }, 404);
|
|
86023
|
+
return handle.user.verify(request);
|
|
86024
|
+
}
|
|
86045
86025
|
if (route === "activity") {
|
|
86046
86026
|
if (!hasActivityHandler(handle))
|
|
86047
86027
|
return jsonResponse({ error: "Not found" }, 404);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"solid-start.d.ts","sourceRoot":"","sources":["../../../src/server/adapters/solid-start.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAM7F;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,kBAAkB,
|
|
1
|
+
{"version":3,"file":"solid-start.d.ts","sourceRoot":"","sources":["../../../src/server/adapters/solid-start.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAM7F;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,kBAAkB,CAuC/E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,wBAAwB,GAC/B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,CA8B1C"}
|