@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.
Files changed (117) hide show
  1. package/dist/client/adapters/react/hooks/types.d.ts +15 -0
  2. package/dist/client/adapters/react/hooks/types.d.ts.map +1 -0
  3. package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts +18 -0
  4. package/dist/client/adapters/react/hooks/useTimebackVerification.d.ts.map +1 -0
  5. package/dist/client/adapters/react/index.d.ts +2 -0
  6. package/dist/client/adapters/react/index.d.ts.map +1 -1
  7. package/dist/client/adapters/react/index.js +139 -9
  8. package/dist/client/auth/bearer.d.ts +17 -0
  9. package/dist/client/auth/bearer.d.ts.map +1 -0
  10. package/dist/client/auth/index.d.ts +3 -0
  11. package/dist/client/auth/index.d.ts.map +1 -0
  12. package/dist/client/auth/types.d.ts +39 -0
  13. package/dist/client/auth/types.d.ts.map +1 -0
  14. package/dist/client/index.d.ts +2 -0
  15. package/dist/client/index.d.ts.map +1 -1
  16. package/dist/client/lib/fetch.d.ts +19 -0
  17. package/dist/client/lib/fetch.d.ts.map +1 -0
  18. package/dist/client/namespaces/user.d.ts +25 -2
  19. package/dist/client/namespaces/user.d.ts.map +1 -1
  20. package/dist/client/timeback-client.class.d.ts +15 -0
  21. package/dist/client/timeback-client.class.d.ts.map +1 -1
  22. package/dist/client/timeback-client.d.ts +3 -0
  23. package/dist/client/timeback-client.d.ts.map +1 -1
  24. package/dist/client.d.ts +2 -1
  25. package/dist/client.d.ts.map +1 -1
  26. package/dist/client.js +69 -6
  27. package/dist/edge.js +85291 -169
  28. package/dist/identity.js +85186 -74
  29. package/dist/index.js +773 -493
  30. package/dist/server/adapters/express.d.ts.map +1 -1
  31. package/dist/server/adapters/express.js +169 -193
  32. package/dist/server/adapters/native.d.ts.map +1 -1
  33. package/dist/server/adapters/native.js +32 -1
  34. package/dist/server/adapters/nextjs.js +32 -1
  35. package/dist/server/adapters/nuxt.d.ts.map +1 -1
  36. package/dist/server/adapters/nuxt.js +173 -193
  37. package/dist/server/adapters/solid-start.d.ts.map +1 -1
  38. package/dist/server/adapters/solid-start.js +173 -193
  39. package/dist/server/adapters/svelte-kit.d.ts.map +1 -1
  40. package/dist/server/adapters/svelte-kit.js +37 -1
  41. package/dist/server/adapters/tanstack-start.d.ts.map +1 -1
  42. package/dist/server/adapters/tanstack-start.js +168 -193
  43. package/dist/server/adapters/utils.d.ts +1 -1
  44. package/dist/server/adapters/utils.d.ts.map +1 -1
  45. package/dist/server/{lib/build-activity-events.d.ts → handlers/activity/caliper.d.ts} +29 -4
  46. package/dist/server/handlers/activity/caliper.d.ts.map +1 -0
  47. package/dist/server/handlers/activity/gradebook.d.ts +56 -0
  48. package/dist/server/handlers/activity/gradebook.d.ts.map +1 -0
  49. package/dist/server/handlers/activity/handler.d.ts +15 -0
  50. package/dist/server/handlers/activity/handler.d.ts.map +1 -0
  51. package/dist/server/handlers/activity/index.d.ts +9 -0
  52. package/dist/server/handlers/activity/index.d.ts.map +1 -0
  53. package/dist/server/handlers/activity/resolve.d.ts +39 -0
  54. package/dist/server/handlers/activity/resolve.d.ts.map +1 -0
  55. package/dist/server/handlers/activity/schema.d.ts +52 -0
  56. package/dist/server/handlers/activity/schema.d.ts.map +1 -0
  57. package/dist/server/handlers/activity/types.d.ts +52 -0
  58. package/dist/server/handlers/activity/types.d.ts.map +1 -0
  59. package/dist/server/handlers/identity/handler.d.ts +14 -0
  60. package/dist/server/handlers/identity/handler.d.ts.map +1 -0
  61. package/dist/server/handlers/identity/index.d.ts +8 -0
  62. package/dist/server/handlers/identity/index.d.ts.map +1 -0
  63. package/dist/server/handlers/identity/oidc.d.ts +43 -0
  64. package/dist/server/handlers/identity/oidc.d.ts.map +1 -0
  65. package/dist/server/handlers/identity/types.d.ts +24 -0
  66. package/dist/server/handlers/identity/types.d.ts.map +1 -0
  67. package/dist/server/handlers/identity-only/handler.d.ts +15 -0
  68. package/dist/server/handlers/identity-only/handler.d.ts.map +1 -0
  69. package/dist/server/handlers/identity-only/index.d.ts +8 -0
  70. package/dist/server/handlers/identity-only/index.d.ts.map +1 -0
  71. package/dist/server/handlers/identity-only/oidc.d.ts +26 -0
  72. package/dist/server/handlers/identity-only/oidc.d.ts.map +1 -0
  73. package/dist/server/handlers/identity-only/types.d.ts +19 -0
  74. package/dist/server/handlers/identity-only/types.d.ts.map +1 -0
  75. package/dist/server/handlers/index.d.ts +5 -2
  76. package/dist/server/handlers/index.d.ts.map +1 -1
  77. package/dist/server/{lib/build-user-profile.d.ts → handlers/user/enrollments.d.ts} +7 -2
  78. package/dist/server/handlers/user/enrollments.d.ts.map +1 -0
  79. package/dist/server/handlers/user/handler.d.ts +17 -0
  80. package/dist/server/handlers/user/handler.d.ts.map +1 -0
  81. package/dist/server/handlers/user/index.d.ts +10 -0
  82. package/dist/server/handlers/user/index.d.ts.map +1 -0
  83. package/dist/server/handlers/user/profile.d.ts +22 -0
  84. package/dist/server/handlers/user/profile.d.ts.map +1 -0
  85. package/dist/server/handlers/user/types.d.ts +35 -0
  86. package/dist/server/handlers/user/types.d.ts.map +1 -0
  87. package/dist/server/handlers/user/verify.d.ts +25 -0
  88. package/dist/server/handlers/user/verify.d.ts.map +1 -0
  89. package/dist/server/index.d.ts +1 -1
  90. package/dist/server/index.d.ts.map +1 -1
  91. package/dist/server/lib/index.d.ts +4 -5
  92. package/dist/server/lib/index.d.ts.map +1 -1
  93. package/dist/server/lib/resolve.d.ts +4 -42
  94. package/dist/server/lib/resolve.d.ts.map +1 -1
  95. package/dist/server/lib/sso.d.ts +86 -0
  96. package/dist/server/lib/sso.d.ts.map +1 -0
  97. package/dist/server/lib/utils.d.ts +32 -1
  98. package/dist/server/lib/utils.d.ts.map +1 -1
  99. package/dist/server/timeback-identity.d.ts.map +1 -1
  100. package/dist/server/timeback.d.ts.map +1 -1
  101. package/dist/server/types.d.ts +16 -9
  102. package/dist/server/types.d.ts.map +1 -1
  103. package/dist/shared/constants.d.ts +1 -0
  104. package/dist/shared/constants.d.ts.map +1 -1
  105. package/dist/shared/types.d.ts +15 -0
  106. package/dist/shared/types.d.ts.map +1 -1
  107. package/package.json +6 -2
  108. package/dist/server/handlers/activity.d.ts +0 -25
  109. package/dist/server/handlers/activity.d.ts.map +0 -1
  110. package/dist/server/handlers/identity-full.d.ts +0 -28
  111. package/dist/server/handlers/identity-full.d.ts.map +0 -1
  112. package/dist/server/handlers/identity-only.d.ts +0 -22
  113. package/dist/server/handlers/identity-only.d.ts.map +0 -1
  114. package/dist/server/handlers/user.d.ts +0 -31
  115. package/dist/server/handlers/user.d.ts.map +0 -1
  116. package/dist/server/lib/build-activity-events.d.ts.map +0 -1
  117. 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) => c.sensor !== undefined || config2.sensor !== undefined);
15743
- }, {
15744
- message: "Each course must have an effective sensor; set a top-level `sensor` or per-course `sensor`",
15745
- path: ["courses"]
15746
- }).refine((config2) => {
15747
- return config2.courses.every((c) => c.launchUrl !== undefined || config2.launchUrl !== undefined);
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 launchUrl; set a top-level `launchUrl` or per-course `launchUrl`",
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) => c.sensor !== undefined || config22.sensor !== undefined);
32146
- }, {
32147
- message: "Each course must have an effective sensor; set a top-level `sensor` or per-course `sensor`",
32148
- path: ["courses"]
32149
- }).refine((config22) => {
32150
- return config22.courses.every((c) => c.launchUrl !== undefined || config22.launchUrl !== undefined);
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 launchUrl; set a top-level `launchUrl` or per-course `launchUrl`",
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) => c.sensor !== undefined || config22.sensor !== undefined);
49579
- }, {
49580
- message: "Each course must have an effective sensor; set a top-level `sensor` or per-course `sensor`",
49581
- path: ["courses"]
49582
- }).refine((config22) => {
49583
- return config22.courses.every((c) => c.launchUrl !== undefined || config22.launchUrl !== undefined);
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 launchUrl; set a top-level `launchUrl` or per-course `launchUrl`",
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) => c.sensor !== undefined || config22.sensor !== undefined);
67211
- }, {
67212
- message: "Each course must have an effective sensor; set a top-level `sensor` or per-course `sensor`",
67213
- path: ["courses"]
67214
- }).refine((config22) => {
67215
- return config22.courses.every((c) => c.launchUrl !== undefined || config22.launchUrl !== undefined);
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 launchUrl; set a top-level `launchUrl` or per-course `launchUrl`",
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) => c.sensor !== undefined || config22.sensor !== undefined);
83873
- }, {
83874
- message: "Each course must have an effective sensor; set a top-level `sensor` or per-course `sensor`",
83875
- path: ["courses"]
83876
- }).refine((config22) => {
83877
- return config22.courses.every((c) => c.launchUrl !== undefined || config22.launchUrl !== undefined);
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 launchUrl; set a top-level `launchUrl` or per-course `launchUrl`",
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,CAmC/E;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,iBAAiB,CAChC,OAAO,EAAE,wBAAwB,GAC/B,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,SAAS,CA0B1C"}
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"}