@timeback/powerpath 0.2.1 → 0.2.2-beta.20260331190459

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.
@@ -636,11 +636,11 @@ class TimebackProvider {
636
636
  env;
637
637
  auth;
638
638
  timeout;
639
- endpoints;
640
- authUrl;
641
- tokenScope;
642
- pathProfiles;
643
- tokenManagers = new Map;
639
+ _endpoints;
640
+ _authUrl;
641
+ _tokenScope;
642
+ _pathProfiles;
643
+ _tokenManagers = new Map;
644
644
  constructor(config) {
645
645
  this.timeout = config.timeout ?? 30000;
646
646
  if (isEnvConfig(config)) {
@@ -653,89 +653,89 @@ class TimebackProvider {
653
653
  if (!platformEndpoints) {
654
654
  throw new Error(`Unknown platform: ${platform}`);
655
655
  }
656
- this.authUrl = platformEndpoints.token[env];
657
- this.tokenScope = platformEndpoints.tokenScope ?? undefined;
658
- this.pathProfiles = PLATFORM_PATHS[platform] ?? BEYONDAI_PATHS;
659
- this.endpoints = {
656
+ this._authUrl = platformEndpoints.token[env];
657
+ this._tokenScope = platformEndpoints.tokenScope ?? undefined;
658
+ this._pathProfiles = PLATFORM_PATHS[platform] ?? BEYONDAI_PATHS;
659
+ this._endpoints = {
660
660
  oneroster: {
661
661
  baseUrl: platformEndpoints.api[env],
662
- authUrl: this.authUrl
662
+ authUrl: this._authUrl
663
663
  },
664
664
  edubridge: {
665
665
  baseUrl: platformEndpoints.api[env],
666
- authUrl: this.authUrl
666
+ authUrl: this._authUrl
667
667
  },
668
668
  powerpath: {
669
669
  baseUrl: platformEndpoints.api[env],
670
- authUrl: this.authUrl
670
+ authUrl: this._authUrl
671
671
  },
672
672
  clr: {
673
673
  baseUrl: platformEndpoints.api[env],
674
- authUrl: this.authUrl
674
+ authUrl: this._authUrl
675
675
  },
676
676
  case: {
677
677
  baseUrl: platformEndpoints.api[env],
678
- authUrl: this.authUrl
678
+ authUrl: this._authUrl
679
679
  },
680
680
  caliper: {
681
681
  baseUrl: platformEndpoints.caliper[env],
682
- authUrl: this.authUrl
682
+ authUrl: this._authUrl
683
683
  },
684
684
  webhooks: {
685
685
  baseUrl: platformEndpoints.caliper[env],
686
- authUrl: this.authUrl
686
+ authUrl: this._authUrl
687
687
  },
688
688
  reporting: {
689
689
  baseUrl: platformEndpoints.api[env],
690
- authUrl: this.authUrl
690
+ authUrl: this._authUrl
691
691
  },
692
692
  qti: {
693
693
  baseUrl: platformEndpoints.qti[env],
694
- authUrl: this.authUrl
694
+ authUrl: this._authUrl
695
695
  }
696
696
  };
697
697
  } else if (isExplicitConfig(config)) {
698
698
  this.auth = config.auth;
699
- this.authUrl = config.authUrl;
700
- this.pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
701
- this.endpoints = {
702
- oneroster: { baseUrl: config.baseUrl, authUrl: this.authUrl },
703
- edubridge: { baseUrl: config.baseUrl, authUrl: this.authUrl },
704
- powerpath: { baseUrl: config.baseUrl, authUrl: this.authUrl },
705
- clr: { baseUrl: config.baseUrl, authUrl: this.authUrl },
706
- case: { baseUrl: config.baseUrl, authUrl: this.authUrl },
707
- caliper: { baseUrl: config.baseUrl, authUrl: this.authUrl },
708
- webhooks: { baseUrl: config.baseUrl, authUrl: this.authUrl },
709
- reporting: { baseUrl: config.baseUrl, authUrl: this.authUrl },
710
- qti: { baseUrl: config.baseUrl, authUrl: this.authUrl }
699
+ this._authUrl = config.authUrl;
700
+ this._pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
701
+ this._endpoints = {
702
+ oneroster: { baseUrl: config.baseUrl, authUrl: this._authUrl },
703
+ edubridge: { baseUrl: config.baseUrl, authUrl: this._authUrl },
704
+ powerpath: { baseUrl: config.baseUrl, authUrl: this._authUrl },
705
+ clr: { baseUrl: config.baseUrl, authUrl: this._authUrl },
706
+ case: { baseUrl: config.baseUrl, authUrl: this._authUrl },
707
+ caliper: { baseUrl: config.baseUrl, authUrl: this._authUrl },
708
+ webhooks: { baseUrl: config.baseUrl, authUrl: this._authUrl },
709
+ reporting: { baseUrl: config.baseUrl, authUrl: this._authUrl },
710
+ qti: { baseUrl: config.baseUrl, authUrl: this._authUrl }
711
711
  };
712
712
  } else if (isServicesConfig(config)) {
713
713
  this.auth = config.auth;
714
- this.authUrl = config.authUrl;
715
- this.pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
716
- this.endpoints = {};
714
+ this._authUrl = config.authUrl;
715
+ this._pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
716
+ this._endpoints = {};
717
717
  for (const [service, baseUrl] of Object.entries(config.services)) {
718
718
  if (baseUrl) {
719
- this.endpoints[service] = {
719
+ this._endpoints[service] = {
720
720
  baseUrl,
721
- authUrl: this.authUrl
721
+ authUrl: this._authUrl
722
722
  };
723
723
  }
724
724
  }
725
725
  } else {
726
726
  throw new Error("Invalid provider configuration");
727
727
  }
728
- for (const service of Object.keys(this.pathProfiles)) {
729
- if (this.pathProfiles[service] === null) {
730
- delete this.endpoints[service];
728
+ for (const service of Object.keys(this._pathProfiles)) {
729
+ if (this._pathProfiles[service] === null) {
730
+ delete this._endpoints[service];
731
731
  }
732
732
  }
733
733
  }
734
734
  getEndpoint(service) {
735
- const endpoint = this.endpoints[service];
735
+ const endpoint = this._endpoints[service];
736
736
  if (!endpoint) {
737
737
  const pathKey = service;
738
- if (pathKey in this.pathProfiles && this.pathProfiles[pathKey] === null) {
738
+ if (pathKey in this._pathProfiles && this._pathProfiles[pathKey] === null) {
739
739
  throw new Error(`Service "${service}" is not supported on ${this.platform ?? "this"} platform.`);
740
740
  }
741
741
  throw new Error(`Service "${service}" is not configured in this provider`);
@@ -743,13 +743,13 @@ class TimebackProvider {
743
743
  return endpoint;
744
744
  }
745
745
  hasService(service) {
746
- return service in this.endpoints;
746
+ return service in this._endpoints;
747
747
  }
748
748
  getAvailableServices() {
749
- return Object.keys(this.endpoints);
749
+ return Object.keys(this._endpoints);
750
750
  }
751
751
  getTokenUrl() {
752
- return this.authUrl;
752
+ return this._authUrl;
753
753
  }
754
754
  getEndpointWithPaths(service) {
755
755
  const endpoint = this.getEndpoint(service);
@@ -757,17 +757,17 @@ class TimebackProvider {
757
757
  return { ...endpoint, paths };
758
758
  }
759
759
  getPaths() {
760
- return this.pathProfiles;
760
+ return this._pathProfiles;
761
761
  }
762
762
  getServicePaths(service) {
763
- const paths = this.pathProfiles[service];
763
+ const paths = this._pathProfiles[service];
764
764
  if (!paths) {
765
765
  throw new Error(`Service "${service}" is not supported on ${this.platform ?? "this"} platform.`);
766
766
  }
767
767
  return paths;
768
768
  }
769
769
  hasServiceSupport(service) {
770
- return this.pathProfiles[service] !== null;
770
+ return this._pathProfiles[service] !== null;
771
771
  }
772
772
  getTokenProvider(service) {
773
773
  const endpoint = this.getEndpoint(service);
@@ -778,7 +778,7 @@ class TimebackProvider {
778
778
  if (!this.auth) {
779
779
  throw new Error(`Service "${service}" requires authentication but no credentials were provided`);
780
780
  }
781
- let manager = this.tokenManagers.get(authUrl);
781
+ let manager = this._tokenManagers.get(authUrl);
782
782
  if (!manager) {
783
783
  manager = new TokenManager({
784
784
  tokenUrl: authUrl,
@@ -786,28 +786,28 @@ class TimebackProvider {
786
786
  clientId: this.auth.clientId,
787
787
  clientSecret: this.auth.clientSecret
788
788
  },
789
- scope: this.tokenScope
789
+ scope: this._tokenScope
790
790
  });
791
- this.tokenManagers.set(authUrl, manager);
791
+ this._tokenManagers.set(authUrl, manager);
792
792
  }
793
793
  return manager;
794
794
  }
795
795
  async checkAuth() {
796
- if (!this.authUrl || !this.auth) {
796
+ if (!this._authUrl || !this.auth) {
797
797
  throw new Error("No auth configured on this provider");
798
798
  }
799
799
  const startTime = Date.now();
800
- let manager = this.tokenManagers.get(this.authUrl);
800
+ let manager = this._tokenManagers.get(this._authUrl);
801
801
  if (!manager) {
802
802
  manager = new TokenManager({
803
- tokenUrl: this.authUrl,
803
+ tokenUrl: this._authUrl,
804
804
  credentials: {
805
805
  clientId: this.auth.clientId,
806
806
  clientSecret: this.auth.clientSecret
807
807
  },
808
- scope: this.tokenScope
808
+ scope: this._tokenScope
809
809
  });
810
- this.tokenManagers.set(this.authUrl, manager);
810
+ this._tokenManagers.set(this._authUrl, manager);
811
811
  }
812
812
  try {
813
813
  await manager.getToken();
@@ -826,10 +826,10 @@ class TimebackProvider {
826
826
  }
827
827
  }
828
828
  invalidateTokens() {
829
- for (const manager of this.tokenManagers.values()) {
829
+ for (const manager of this._tokenManagers.values()) {
830
830
  manager.invalidate?.();
831
831
  }
832
- this.tokenManagers.clear();
832
+ this._tokenManagers.clear();
833
833
  }
834
834
  }
835
835
  // ../../internal/client-infra/src/utils/utils.ts
package/dist/errors.d.ts CHANGED
@@ -1 +1,144 @@
1
- export { ForbiddenError, InputValidationError, NotFoundError, ApiError as PowerPathError, UnauthorizedError, ValidationError } from '@timeback/internal-client-infra';
1
+ /**
2
+ * Error Types
3
+ *
4
+ * Shared types for error helpers.
5
+ */
6
+ /**
7
+ * Validation issue from client-side input validation.
8
+ */
9
+ interface ValidationIssue {
10
+ /** Field path (e.g. "sourcedId", "metadata.email") */
11
+ path: string;
12
+ /** Human-readable error message */
13
+ message: string;
14
+ }
15
+
16
+ /**
17
+ * API Error Classes
18
+ *
19
+ * Base error classes for HTTP API failures.
20
+ * Includes IMS Global error response parsing (OneRoster, QTI, etc.).
21
+ */
22
+
23
+ /**
24
+ * Base error class for all API errors.
25
+ *
26
+ * Provides access to the HTTP status code and raw response body.
27
+ * Includes IMS Global error parsing (minorCodes, details) for
28
+ * IMS-standard APIs like OneRoster and QTI.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * // Catching and inspecting errors
33
+ * try {
34
+ * await client.users.get('non-existent-id')
35
+ * } catch (error) {
36
+ * if (error instanceof ApiError) {
37
+ * console.log(`Error ${error.statusCode}: ${error.message}`)
38
+ * console.log('Minor codes:', error.minorCodes)
39
+ * console.log('Details:', error.details)
40
+ * }
41
+ * }
42
+ * ```
43
+ */
44
+ declare class ApiError extends Error {
45
+ readonly statusCode?: number | undefined;
46
+ readonly response?: unknown;
47
+ readonly name: string;
48
+ /**
49
+ * Creates a new ApiError.
50
+ *
51
+ * @param message - Human-readable error message
52
+ * @param statusCode - HTTP status code
53
+ * @param response - Raw response body (if available)
54
+ */
55
+ constructor(message: string, statusCode?: number | undefined, response?: unknown);
56
+ /**
57
+ * Minor error codes from IMS Global error response.
58
+ *
59
+ * For IMS-standard APIs (OneRoster, QTI), provides specific error codes
60
+ * like "unknownobject" or "invaliddata".
61
+ *
62
+ * @returns Array of field/value pairs, or empty array if not IMS format
63
+ */
64
+ get minorCodes(): Array<{
65
+ field: string;
66
+ value: string;
67
+ }>;
68
+ /**
69
+ * Additional error details from IMS Global response.
70
+ *
71
+ * May contain field-level validation errors or other structured details.
72
+ *
73
+ * @returns Array of key-value objects, or empty array if not present
74
+ */
75
+ get details(): Array<Record<string, string>>;
76
+ }
77
+ /**
78
+ * Error thrown when authentication fails (HTTP 401).
79
+ *
80
+ * Typically indicates invalid or expired credentials.
81
+ */
82
+ declare class UnauthorizedError extends ApiError {
83
+ readonly name = "UnauthorizedError";
84
+ constructor(message?: string, response?: unknown);
85
+ }
86
+ /**
87
+ * Error thrown when the client lacks permission for the operation (HTTP 403).
88
+ *
89
+ * The credentials are valid, but the client is not authorized for this action.
90
+ */
91
+ declare class ForbiddenError extends ApiError {
92
+ readonly name = "ForbiddenError";
93
+ constructor(message?: string, response?: unknown);
94
+ }
95
+ /**
96
+ * Error thrown when a requested resource is not found (HTTP 404).
97
+ */
98
+ declare class NotFoundError extends ApiError {
99
+ readonly name = "NotFoundError";
100
+ constructor(message?: string, response?: unknown);
101
+ }
102
+ /**
103
+ * Error thrown when request data is invalid (HTTP 422).
104
+ *
105
+ * Check the `details` property for field-level validation errors.
106
+ */
107
+ declare class ValidationError extends ApiError {
108
+ readonly name = "ValidationError";
109
+ constructor(message?: string, response?: unknown);
110
+ }
111
+ /**
112
+ * Validation issue from client-side input validation.
113
+ */
114
+ /**
115
+ * Error thrown when client-side input validation fails.
116
+ *
117
+ * This is thrown **before** making a network request, providing fast feedback
118
+ * with actionable, path-based error messages.
119
+ *
120
+ * Uses statusCode 400 (Bad Request) to distinguish from server-side 422 errors.
121
+ * Formats like IMS errors via `imsx_error_details` so existing error formatters work.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * try {
126
+ * await client.users.create({}) // missing required fields
127
+ * } catch (error) {
128
+ * if (error instanceof InputValidationError) {
129
+ * console.log('Invalid input:', error.issues)
130
+ * // [{ path: 'sourcedId', message: 'Required' }]
131
+ * }
132
+ * }
133
+ * ```
134
+ */
135
+ declare class InputValidationError extends ApiError {
136
+ readonly name = "InputValidationError";
137
+ /**
138
+ * The validation issues that caused this error.
139
+ */
140
+ readonly issues: ValidationIssue[];
141
+ constructor(message: string, issues: ValidationIssue[]);
142
+ }
143
+
144
+ export { ForbiddenError, InputValidationError, NotFoundError, ApiError as PowerPathError, UnauthorizedError, ValidationError };
package/dist/errors.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  NotFoundError,
6
6
  UnauthorizedError,
7
7
  ValidationError
8
- } from "./chunk-5a9p0re1.js";
8
+ } from "./chunk-setst1c6.js";
9
9
  import"./chunk-6jf1natv.js";
10
10
  export {
11
11
  ValidationError,