@timeback/webhooks 0.2.1-beta.20260313023436 → 0.2.1-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.
@@ -571,6 +571,13 @@ var BEYONDAI_PATHS = {
571
571
  webhookFilterUpdate: "/webhook-filters/{id}",
572
572
  webhookFilterDelete: "/webhook-filters/{id}",
573
573
  webhookFiltersByWebhook: "/webhook-filters/webhook/{webhookId}"
574
+ },
575
+ reporting: {
576
+ mcp: "/mcp/reporting",
577
+ savedQueryExecute: "/reporting/saved-queries/{id}",
578
+ adminGroupCheck: "/mcp/admin/users/{email}/group",
579
+ adminGroupAdd: "/mcp/admin/users/{email}/group",
580
+ adminGroupRemove: "/mcp/admin/users/{email}/group"
574
581
  }
575
582
  };
576
583
  var LEARNWITHAI_PATHS = {
@@ -587,6 +594,7 @@ var LEARNWITHAI_PATHS = {
587
594
  resources: "/resources/1.0"
588
595
  },
589
596
  webhooks: null,
597
+ reporting: null,
590
598
  edubridge: null,
591
599
  powerpath: null,
592
600
  clr: null,
@@ -615,6 +623,7 @@ function resolvePathProfiles(pathProfile, customPaths) {
615
623
  caliper: customPaths?.caliper ?? basePaths.caliper,
616
624
  oneroster: customPaths?.oneroster ?? basePaths.oneroster,
617
625
  webhooks: customPaths?.webhooks ?? basePaths.webhooks,
626
+ reporting: customPaths?.reporting ?? basePaths.reporting,
618
627
  edubridge: customPaths?.edubridge ?? basePaths.edubridge,
619
628
  powerpath: customPaths?.powerpath ?? basePaths.powerpath,
620
629
  clr: customPaths?.clr ?? basePaths.clr,
@@ -627,11 +636,11 @@ class TimebackProvider {
627
636
  env;
628
637
  auth;
629
638
  timeout;
630
- endpoints;
631
- authUrl;
632
- tokenScope;
633
- pathProfiles;
634
- tokenManagers = new Map;
639
+ _endpoints;
640
+ _authUrl;
641
+ _tokenScope;
642
+ _pathProfiles;
643
+ _tokenManagers = new Map;
635
644
  constructor(config) {
636
645
  this.timeout = config.timeout ?? 30000;
637
646
  if (isEnvConfig(config)) {
@@ -644,84 +653,89 @@ class TimebackProvider {
644
653
  if (!platformEndpoints) {
645
654
  throw new Error(`Unknown platform: ${platform}`);
646
655
  }
647
- this.authUrl = platformEndpoints.token[env];
648
- this.tokenScope = platformEndpoints.tokenScope ?? undefined;
649
- this.pathProfiles = PLATFORM_PATHS[platform] ?? BEYONDAI_PATHS;
650
- 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 = {
651
660
  oneroster: {
652
661
  baseUrl: platformEndpoints.api[env],
653
- authUrl: this.authUrl
662
+ authUrl: this._authUrl
654
663
  },
655
664
  edubridge: {
656
665
  baseUrl: platformEndpoints.api[env],
657
- authUrl: this.authUrl
666
+ authUrl: this._authUrl
658
667
  },
659
668
  powerpath: {
660
669
  baseUrl: platformEndpoints.api[env],
661
- authUrl: this.authUrl
670
+ authUrl: this._authUrl
662
671
  },
663
672
  clr: {
664
673
  baseUrl: platformEndpoints.api[env],
665
- authUrl: this.authUrl
674
+ authUrl: this._authUrl
666
675
  },
667
676
  case: {
668
677
  baseUrl: platformEndpoints.api[env],
669
- authUrl: this.authUrl
678
+ authUrl: this._authUrl
670
679
  },
671
680
  caliper: {
672
681
  baseUrl: platformEndpoints.caliper[env],
673
- authUrl: this.authUrl
682
+ authUrl: this._authUrl
674
683
  },
675
684
  webhooks: {
676
685
  baseUrl: platformEndpoints.caliper[env],
677
- authUrl: this.authUrl
686
+ authUrl: this._authUrl
687
+ },
688
+ reporting: {
689
+ baseUrl: platformEndpoints.api[env],
690
+ authUrl: this._authUrl
678
691
  },
679
692
  qti: {
680
693
  baseUrl: platformEndpoints.qti[env],
681
- authUrl: this.authUrl
694
+ authUrl: this._authUrl
682
695
  }
683
696
  };
684
697
  } else if (isExplicitConfig(config)) {
685
698
  this.auth = config.auth;
686
- this.authUrl = config.authUrl;
687
- this.pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
688
- this.endpoints = {
689
- oneroster: { baseUrl: config.baseUrl, authUrl: this.authUrl },
690
- edubridge: { baseUrl: config.baseUrl, authUrl: this.authUrl },
691
- powerpath: { baseUrl: config.baseUrl, authUrl: this.authUrl },
692
- clr: { baseUrl: config.baseUrl, authUrl: this.authUrl },
693
- case: { baseUrl: config.baseUrl, authUrl: this.authUrl },
694
- caliper: { baseUrl: config.baseUrl, authUrl: this.authUrl },
695
- webhooks: { baseUrl: config.baseUrl, authUrl: this.authUrl },
696
- 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 }
697
711
  };
698
712
  } else if (isServicesConfig(config)) {
699
713
  this.auth = config.auth;
700
- this.authUrl = config.authUrl;
701
- this.pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
702
- this.endpoints = {};
714
+ this._authUrl = config.authUrl;
715
+ this._pathProfiles = resolvePathProfiles(config.pathProfile, config.paths);
716
+ this._endpoints = {};
703
717
  for (const [service, baseUrl] of Object.entries(config.services)) {
704
718
  if (baseUrl) {
705
- this.endpoints[service] = {
719
+ this._endpoints[service] = {
706
720
  baseUrl,
707
- authUrl: this.authUrl
721
+ authUrl: this._authUrl
708
722
  };
709
723
  }
710
724
  }
711
725
  } else {
712
726
  throw new Error("Invalid provider configuration");
713
727
  }
714
- for (const service of Object.keys(this.pathProfiles)) {
715
- if (this.pathProfiles[service] === null) {
716
- delete this.endpoints[service];
728
+ for (const service of Object.keys(this._pathProfiles)) {
729
+ if (this._pathProfiles[service] === null) {
730
+ delete this._endpoints[service];
717
731
  }
718
732
  }
719
733
  }
720
734
  getEndpoint(service) {
721
- const endpoint = this.endpoints[service];
735
+ const endpoint = this._endpoints[service];
722
736
  if (!endpoint) {
723
737
  const pathKey = service;
724
- if (pathKey in this.pathProfiles && this.pathProfiles[pathKey] === null) {
738
+ if (pathKey in this._pathProfiles && this._pathProfiles[pathKey] === null) {
725
739
  throw new Error(`Service "${service}" is not supported on ${this.platform ?? "this"} platform.`);
726
740
  }
727
741
  throw new Error(`Service "${service}" is not configured in this provider`);
@@ -729,13 +743,13 @@ class TimebackProvider {
729
743
  return endpoint;
730
744
  }
731
745
  hasService(service) {
732
- return service in this.endpoints;
746
+ return service in this._endpoints;
733
747
  }
734
748
  getAvailableServices() {
735
- return Object.keys(this.endpoints);
749
+ return Object.keys(this._endpoints);
736
750
  }
737
751
  getTokenUrl() {
738
- return this.authUrl;
752
+ return this._authUrl;
739
753
  }
740
754
  getEndpointWithPaths(service) {
741
755
  const endpoint = this.getEndpoint(service);
@@ -743,17 +757,17 @@ class TimebackProvider {
743
757
  return { ...endpoint, paths };
744
758
  }
745
759
  getPaths() {
746
- return this.pathProfiles;
760
+ return this._pathProfiles;
747
761
  }
748
762
  getServicePaths(service) {
749
- const paths = this.pathProfiles[service];
763
+ const paths = this._pathProfiles[service];
750
764
  if (!paths) {
751
765
  throw new Error(`Service "${service}" is not supported on ${this.platform ?? "this"} platform.`);
752
766
  }
753
767
  return paths;
754
768
  }
755
769
  hasServiceSupport(service) {
756
- return this.pathProfiles[service] !== null;
770
+ return this._pathProfiles[service] !== null;
757
771
  }
758
772
  getTokenProvider(service) {
759
773
  const endpoint = this.getEndpoint(service);
@@ -764,7 +778,7 @@ class TimebackProvider {
764
778
  if (!this.auth) {
765
779
  throw new Error(`Service "${service}" requires authentication but no credentials were provided`);
766
780
  }
767
- let manager = this.tokenManagers.get(authUrl);
781
+ let manager = this._tokenManagers.get(authUrl);
768
782
  if (!manager) {
769
783
  manager = new TokenManager({
770
784
  tokenUrl: authUrl,
@@ -772,28 +786,28 @@ class TimebackProvider {
772
786
  clientId: this.auth.clientId,
773
787
  clientSecret: this.auth.clientSecret
774
788
  },
775
- scope: this.tokenScope
789
+ scope: this._tokenScope
776
790
  });
777
- this.tokenManagers.set(authUrl, manager);
791
+ this._tokenManagers.set(authUrl, manager);
778
792
  }
779
793
  return manager;
780
794
  }
781
795
  async checkAuth() {
782
- if (!this.authUrl || !this.auth) {
796
+ if (!this._authUrl || !this.auth) {
783
797
  throw new Error("No auth configured on this provider");
784
798
  }
785
799
  const startTime = Date.now();
786
- let manager = this.tokenManagers.get(this.authUrl);
800
+ let manager = this._tokenManagers.get(this._authUrl);
787
801
  if (!manager) {
788
802
  manager = new TokenManager({
789
- tokenUrl: this.authUrl,
803
+ tokenUrl: this._authUrl,
790
804
  credentials: {
791
805
  clientId: this.auth.clientId,
792
806
  clientSecret: this.auth.clientSecret
793
807
  },
794
- scope: this.tokenScope
808
+ scope: this._tokenScope
795
809
  });
796
- this.tokenManagers.set(this.authUrl, manager);
810
+ this._tokenManagers.set(this._authUrl, manager);
797
811
  }
798
812
  try {
799
813
  await manager.getToken();
@@ -812,10 +826,10 @@ class TimebackProvider {
812
826
  }
813
827
  }
814
828
  invalidateTokens() {
815
- for (const manager of this.tokenManagers.values()) {
829
+ for (const manager of this._tokenManagers.values()) {
816
830
  manager.invalidate?.();
817
831
  }
818
- this.tokenManagers.clear();
832
+ this._tokenManagers.clear();
819
833
  }
820
834
  }
821
835
  // ../../internal/client-infra/src/utils/utils.ts
package/dist/errors.d.ts CHANGED
@@ -1 +1,144 @@
1
- export { ForbiddenError, InputValidationError, NotFoundError, UnauthorizedError, ValidationError, ApiError as WebhooksError } 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, UnauthorizedError, ValidationError, ApiError as WebhooksError };
package/dist/errors.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  NotFoundError,
6
6
  UnauthorizedError,
7
7
  ValidationError
8
- } from "./chunk-1dmdawx1.js";
8
+ } from "./chunk-9a1sbh56.js";
9
9
  import"./chunk-6jf1natv.js";
10
10
  export {
11
11
  ApiError as WebhooksError,