@timeback/qti 0.1.0 → 0.1.2

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.
@@ -6,12 +6,17 @@
6
6
  import type { ClientUrlMaps, Platform } from '@timeback/internal-client-infra';
7
7
  /**
8
8
  * Environment variable names for fallback config.
9
+ *
10
+ * Supports fallback chains - tries each env var in order until one is defined:
11
+ * - `TIMEBACK_API_*` (canonical/preferred)
12
+ * - `TIMEBACK_*` (unified Timeback shorthand)
13
+ * - `QTI_*` (service-specific legacy)
9
14
  */
10
15
  export declare const QTI_ENV_VARS: {
11
- readonly baseUrl: "QTI_BASE_URL";
12
- readonly clientId: "QTI_CLIENT_ID";
13
- readonly clientSecret: "QTI_CLIENT_SECRET";
14
- readonly authUrl: "QTI_TOKEN_URL";
16
+ readonly baseUrl: readonly ["TIMEBACK_API_BASE_URL", "TIMEBACK_BASE_URL", "QTI_BASE_URL"];
17
+ readonly clientId: readonly ["TIMEBACK_API_CLIENT_ID", "TIMEBACK_CLIENT_ID", "QTI_CLIENT_ID"];
18
+ readonly clientSecret: readonly ["TIMEBACK_API_CLIENT_SECRET", "TIMEBACK_CLIENT_SECRET", "QTI_CLIENT_SECRET"];
19
+ readonly authUrl: readonly ["TIMEBACK_API_AUTH_URL", "TIMEBACK_AUTH_URL", "QTI_TOKEN_URL"];
15
20
  };
16
21
  /**
17
22
  * Get URL maps for a specific platform.
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAM9E;;GAEG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAA;AAMV;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,QAA2B,GAAG,aAAa,CAM1F"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,iCAAiC,CAAA;AAM9E;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY;;;;;CAKf,CAAA;AAMV;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,GAAE,QAA2B,GAAG,aAAa,CAM1F"}
package/dist/errors.js CHANGED
@@ -15,6 +15,15 @@ var __toESM = (mod, isNodeMode, target) => {
15
15
  });
16
16
  return to;
17
17
  };
18
+ var __export = (target, all) => {
19
+ for (var name in all)
20
+ __defProp(target, name, {
21
+ get: all[name],
22
+ enumerable: true,
23
+ configurable: true,
24
+ set: (newValue) => all[name] = () => newValue
25
+ });
26
+ };
18
27
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
19
28
 
20
29
  // ../../internal/constants/src/endpoints.ts
@@ -68,9 +77,12 @@ var PLATFORM_ENDPOINTS = {
68
77
  // ../../internal/constants/src/typescript.ts
69
78
  var TypeScriptPackages = {
70
79
  tsc: "tsc",
71
- nativePreview: "@typescript/native-preview@7.0.0-dev.20251217.1"
80
+ nativePreview: "@typescript/native-preview"
81
+ };
82
+ var TYPESCRIPT_RUNNER = {
83
+ package: TypeScriptPackages.nativePreview,
84
+ bin: "tsgo"
72
85
  };
73
- var TYPESCRIPT_PACKAGE = TypeScriptPackages.nativePreview;
74
86
  // ../../internal/logger/src/debug.ts
75
87
  var patterns = null;
76
88
  var debugAll = false;
@@ -475,6 +487,9 @@ var BEYONDAI_PATHS = {
475
487
  },
476
488
  edubridge: {
477
489
  base: "/edubridge"
490
+ },
491
+ powerpath: {
492
+ base: "/powerpath"
478
493
  }
479
494
  };
480
495
  var LEARNWITHAI_PATHS = {
@@ -490,7 +505,8 @@ var LEARNWITHAI_PATHS = {
490
505
  gradebook: "/gradebook/1.0",
491
506
  resources: "/resources/1.0"
492
507
  },
493
- edubridge: null
508
+ edubridge: null,
509
+ powerpath: null
494
510
  };
495
511
  var PLATFORM_PATHS = {
496
512
  BEYOND_AI: BEYONDAI_PATHS,
@@ -512,7 +528,8 @@ function resolvePathProfiles(pathProfile, customPaths) {
512
528
  return {
513
529
  caliper: customPaths?.caliper ?? basePaths.caliper,
514
530
  oneroster: customPaths?.oneroster ?? basePaths.oneroster,
515
- edubridge: customPaths?.edubridge ?? basePaths.edubridge
531
+ edubridge: customPaths?.edubridge ?? basePaths.edubridge,
532
+ powerpath: customPaths?.powerpath ?? basePaths.powerpath
516
533
  };
517
534
  }
518
535
 
@@ -548,6 +565,10 @@ class TimebackProvider {
548
565
  baseUrl: platformEndpoints.api[env],
549
566
  authUrl: this.authUrl
550
567
  },
568
+ powerpath: {
569
+ baseUrl: platformEndpoints.api[env],
570
+ authUrl: this.authUrl
571
+ },
551
572
  caliper: {
552
573
  baseUrl: platformEndpoints.caliper[env],
553
574
  authUrl: this.authUrl
@@ -564,6 +585,7 @@ class TimebackProvider {
564
585
  this.endpoints = {
565
586
  oneroster: { baseUrl: config.baseUrl, authUrl: this.authUrl },
566
587
  edubridge: { baseUrl: config.baseUrl, authUrl: this.authUrl },
588
+ powerpath: { baseUrl: config.baseUrl, authUrl: this.authUrl },
567
589
  caliper: { baseUrl: config.baseUrl, authUrl: this.authUrl },
568
590
  qti: { baseUrl: config.baseUrl, authUrl: this.authUrl }
569
591
  };
@@ -682,7 +704,17 @@ class TimebackProvider {
682
704
  // ../../internal/client-infra/src/utils/utils.ts
683
705
  function getEnv(key) {
684
706
  try {
685
- return typeof process === "undefined" ? undefined : process.env[key];
707
+ if (typeof process === "undefined")
708
+ return;
709
+ if (typeof key === "string") {
710
+ return process.env[key];
711
+ }
712
+ for (const k of key) {
713
+ const value = process.env[k];
714
+ if (value !== undefined)
715
+ return value;
716
+ }
717
+ return;
686
718
  } catch {
687
719
  return;
688
720
  }
@@ -716,6 +748,18 @@ var DEFAULT_PROVIDER_REGISTRY = {
716
748
  };
717
749
 
718
750
  // ../../internal/client-infra/src/config/resolve.ts
751
+ function primaryEnvVar(key) {
752
+ if (typeof key === "string") {
753
+ return key;
754
+ }
755
+ if (key.length === 0) {
756
+ throw new Error(`Missing env var key: ${key}`);
757
+ }
758
+ return key[0];
759
+ }
760
+ function formatEnvVarKey(key) {
761
+ return primaryEnvVar(key);
762
+ }
719
763
  function validateEnv(env) {
720
764
  if (env !== "staging" && env !== "production") {
721
765
  throw new Error(`Invalid env "${env}": must be "staging" or "production"`);
@@ -726,10 +770,10 @@ function validateAuth(auth, envVars) {
726
770
  const clientId = auth?.clientId ?? getEnv(envVars.clientId);
727
771
  const clientSecret = auth?.clientSecret ?? getEnv(envVars.clientSecret);
728
772
  if (!clientId) {
729
- throw new Error(`Missing clientId: provide in config or set ${envVars.clientId}`);
773
+ throw new Error(`Missing clientId: provide in config or set ${formatEnvVarKey(envVars.clientId)}`);
730
774
  }
731
775
  if (!clientSecret) {
732
- throw new Error(`Missing clientSecret: provide in config or set ${envVars.clientSecret}`);
776
+ throw new Error(`Missing clientSecret: provide in config or set ${formatEnvVarKey(envVars.clientSecret)}`);
733
777
  }
734
778
  return { clientId, clientSecret };
735
779
  }
@@ -745,21 +789,21 @@ function buildMissingEnvError(envVars) {
745
789
  const clientId = getEnv(envVars.clientId);
746
790
  const clientSecret = getEnv(envVars.clientSecret);
747
791
  if (baseUrl === undefined && clientId === undefined) {
748
- const hint = envVars.env ?? envVars.baseUrl;
792
+ const hint = formatEnvVarKey(envVars.env ?? envVars.baseUrl);
749
793
  return `Missing env: provide in config or set ${hint}`;
750
794
  }
751
795
  const missing = [];
752
796
  if (baseUrl === undefined) {
753
- missing.push(envVars.env ?? envVars.baseUrl);
797
+ missing.push(formatEnvVarKey(envVars.env ?? envVars.baseUrl));
754
798
  }
755
799
  if (baseUrl !== undefined && authUrl === undefined) {
756
- missing.push(envVars.authUrl);
800
+ missing.push(formatEnvVarKey(envVars.authUrl));
757
801
  }
758
802
  if (clientId === undefined) {
759
- missing.push(envVars.clientId);
803
+ missing.push(formatEnvVarKey(envVars.clientId));
760
804
  }
761
805
  if (clientSecret === undefined) {
762
- missing.push(envVars.clientSecret);
806
+ missing.push(formatEnvVarKey(envVars.clientSecret));
763
807
  }
764
808
  return `Missing environment variables: ${missing.join(", ")}`;
765
809
  }
@@ -971,6 +1015,27 @@ class ValidationError extends ApiError {
971
1015
  super(message, 422, response);
972
1016
  }
973
1017
  }
1018
+
1019
+ class InputValidationError extends ApiError {
1020
+ name = "InputValidationError";
1021
+ issues;
1022
+ constructor(message, issues) {
1023
+ const response = {
1024
+ imsx_codeMajor: "failure",
1025
+ imsx_severity: "error",
1026
+ imsx_description: message,
1027
+ imsx_error_details: issues.map((issue) => ({
1028
+ path: issue.path,
1029
+ message: issue.message
1030
+ }))
1031
+ };
1032
+ super(message, 400, response);
1033
+ this.issues = issues;
1034
+ }
1035
+ }
1036
+ function createInputValidationError(message, issues) {
1037
+ return new InputValidationError(message, issues);
1038
+ }
974
1039
  // ../../internal/client-infra/src/transport/constants.ts
975
1040
  var MAX_RETRIES = 3;
976
1041
  var RETRY_STATUS_CODES = [429, 503];
@@ -1396,10 +1461,57 @@ class Paginator {
1396
1461
  };
1397
1462
  }
1398
1463
  }
1464
+ // ../../internal/client-infra/src/validation/index.ts
1465
+ function issue(path, message) {
1466
+ return { path, message };
1467
+ }
1468
+ function validateWithSchema(schema, data, context) {
1469
+ const result = schema.safeParse(data);
1470
+ if (result.success) {
1471
+ return;
1472
+ }
1473
+ const issues = result.error.issues.map((errorIssue) => ({
1474
+ path: errorIssue.path.join(".") || "(root)",
1475
+ message: errorIssue.message
1476
+ }));
1477
+ throw createInputValidationError(`Invalid ${context} data`, issues);
1478
+ }
1479
+ function validateNonEmptyString(value, name) {
1480
+ if (typeof value !== "string" || value.trim() === "") {
1481
+ throw createInputValidationError(`Invalid ${name}`, [
1482
+ issue(name, "Must be a non-empty string")
1483
+ ]);
1484
+ }
1485
+ }
1486
+ function validatePageListParams(params) {
1487
+ if (!params) {
1488
+ return;
1489
+ }
1490
+ const issues = [];
1491
+ if (params.page !== undefined) {
1492
+ if (!Number.isInteger(params.page) || params.page <= 0) {
1493
+ issues.push(issue("page", "Must be a positive integer"));
1494
+ }
1495
+ }
1496
+ if (params.limit !== undefined) {
1497
+ if (!Number.isInteger(params.limit) || params.limit <= 0) {
1498
+ issues.push(issue("limit", "Must be a positive integer"));
1499
+ }
1500
+ }
1501
+ if (params.max !== undefined) {
1502
+ if (!Number.isInteger(params.max) || params.max <= 0) {
1503
+ issues.push(issue("max", "Must be a positive integer"));
1504
+ }
1505
+ }
1506
+ if (issues.length > 0) {
1507
+ throw createInputValidationError("Invalid list parameters", issues);
1508
+ }
1509
+ }
1399
1510
  export {
1400
1511
  ValidationError,
1401
1512
  UnauthorizedError,
1402
1513
  ApiError as QtiError,
1403
1514
  NotFoundError,
1515
+ InputValidationError,
1404
1516
  ForbiddenError
1405
1517
  };