@timeback/core 0.1.0
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/README.md +216 -0
- package/dist/client.d.ts +147 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/constants.d.ts +20 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +1053 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6932 -0
- package/dist/lib/broadcast-results.d.ts +20 -0
- package/dist/lib/broadcast-results.d.ts.map +1 -0
- package/dist/manager.d.ts +129 -0
- package/dist/manager.d.ts.map +1 -0
- package/dist/types/index.d.ts +233 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +56 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +1541 -0
- package/package.json +44 -0
package/README.md
ADDED
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# @timeback/core
|
|
2
|
+
|
|
3
|
+
Unified client for Timeback education APIs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @timeback/core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { TimebackClient } from '@timeback/core'
|
|
15
|
+
|
|
16
|
+
const timeback = new TimebackClient({
|
|
17
|
+
env: 'staging', // or 'production'
|
|
18
|
+
auth: {
|
|
19
|
+
clientId: process.env.CLIENT_ID,
|
|
20
|
+
clientSecret: process.env.CLIENT_SECRET,
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// OneRoster - rostering and gradebook
|
|
25
|
+
for await (const school of timeback.oneroster.schools.list()) {
|
|
26
|
+
console.log(school.name)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Edubridge - simplified enrollments and analytics
|
|
30
|
+
const analytics = await timeback.edubridge.analytics.summary()
|
|
31
|
+
|
|
32
|
+
// Caliper - learning analytics events
|
|
33
|
+
await timeback.caliper.events.send(event)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Managing Multiple Clients
|
|
37
|
+
|
|
38
|
+
For applications that need to manage multiple `TimebackClient` instances, use `TimebackManager`:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { TimebackManager } from '@timeback/core'
|
|
42
|
+
|
|
43
|
+
const manager = new TimebackManager()
|
|
44
|
+
.register('alpha', {
|
|
45
|
+
env: 'production',
|
|
46
|
+
auth: { clientId: '...', clientSecret: '...' },
|
|
47
|
+
})
|
|
48
|
+
.register('beta', {
|
|
49
|
+
env: 'production',
|
|
50
|
+
auth: { clientId: '...', clientSecret: '...' },
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
// Target a specific platform
|
|
54
|
+
const users = await manager.get('alpha').oneroster.users.list()
|
|
55
|
+
|
|
56
|
+
// Sync a user across all platforms (uses Promise.allSettled — never throws)
|
|
57
|
+
const results = await manager.broadcast(client => client.oneroster.users.create(user))
|
|
58
|
+
|
|
59
|
+
// Direct property access (like a plain object)
|
|
60
|
+
if (results.alpha.ok) {
|
|
61
|
+
console.log('Created on alpha:', results.alpha.value.id)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Convenience methods for filtering
|
|
65
|
+
if (results.allSucceeded) {
|
|
66
|
+
console.log('Synced to all platforms!')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
results.succeeded.forEach(([name, user]) => {
|
|
70
|
+
console.log(`Created on ${name}:`, user.id)
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
results.failed.forEach(([name, error]) => {
|
|
74
|
+
console.error(`Failed on ${name}:`, error.message)
|
|
75
|
+
})
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Manager API
|
|
79
|
+
|
|
80
|
+
| Method | Description |
|
|
81
|
+
| ------------------------ | -------------------------------------------------------------------- |
|
|
82
|
+
| `register(name, config)` | Add a named client |
|
|
83
|
+
| `get(name)` | Retrieve a client by name |
|
|
84
|
+
| `has(name)` | Check if a client is registered |
|
|
85
|
+
| `names` | Get all registered client names |
|
|
86
|
+
| `size` | Get number of registered clients |
|
|
87
|
+
| `broadcast(fn)` | Execute on all clients (never throws), returns `BroadcastResults<T>` |
|
|
88
|
+
| `unregister(name)` | Remove and close a client |
|
|
89
|
+
| `close()` | Close all clients |
|
|
90
|
+
|
|
91
|
+
### BroadcastResults API
|
|
92
|
+
|
|
93
|
+
The `broadcast()` method returns a hybrid object — use it like a plain `Record<string, BroadcastResult<T>>` with added convenience methods:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// Direct property access
|
|
97
|
+
results.alpha.ok // true or false
|
|
98
|
+
results['beta'].value // the value if ok
|
|
99
|
+
results.gamma.error // the error if not ok
|
|
100
|
+
|
|
101
|
+
// Standard object methods work
|
|
102
|
+
Object.keys(results) // ['alpha', 'beta', 'gamma']
|
|
103
|
+
Object.entries(results) // [[name, result], ...]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Property/Method | Description |
|
|
107
|
+
| --------------- | ------------------------------------------- |
|
|
108
|
+
| `succeeded` | Get successful results as `[name, value][]` |
|
|
109
|
+
| `failed` | Get failed results as `[name, error][]` |
|
|
110
|
+
| `allSucceeded` | `true` if all operations succeeded |
|
|
111
|
+
| `anyFailed` | `true` if any operation failed |
|
|
112
|
+
| `values()` | Get all values (throws if any failed) |
|
|
113
|
+
|
|
114
|
+
## Configuration
|
|
115
|
+
|
|
116
|
+
The client supports three configuration modes:
|
|
117
|
+
|
|
118
|
+
### Environment Mode (Recommended)
|
|
119
|
+
|
|
120
|
+
Derive all URLs from `staging` or `production`:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
const client = new TimebackClient({
|
|
124
|
+
env: 'staging', // or 'production'
|
|
125
|
+
auth: { clientId: '...', clientSecret: '...' },
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
| Environment | API Base URL |
|
|
130
|
+
| ------------ | ------------------------------ |
|
|
131
|
+
| `staging` | `api.staging.alpha-1edtech.ai` |
|
|
132
|
+
| `production` | `api.alpha-1edtech.ai` |
|
|
133
|
+
|
|
134
|
+
### Base URL Mode
|
|
135
|
+
|
|
136
|
+
For self-hosted or custom deployments with a single base URL:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
const client = new TimebackClient({
|
|
140
|
+
baseUrl: 'https://timeback.myschool.edu',
|
|
141
|
+
auth: {
|
|
142
|
+
clientId: '...',
|
|
143
|
+
clientSecret: '...',
|
|
144
|
+
authUrl: 'https://timeback.myschool.edu/oauth/token',
|
|
145
|
+
},
|
|
146
|
+
})
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Explicit Services Mode
|
|
150
|
+
|
|
151
|
+
Full control over each service URL. Only configure the services you need:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
const client = new TimebackClient({
|
|
155
|
+
services: {
|
|
156
|
+
oneroster: 'https://roster.example.com',
|
|
157
|
+
caliper: 'https://analytics.example.com',
|
|
158
|
+
// edubridge not configured — accessing it will throw
|
|
159
|
+
},
|
|
160
|
+
auth: {
|
|
161
|
+
clientId: '...',
|
|
162
|
+
clientSecret: '...',
|
|
163
|
+
authUrl: 'https://auth.example.com/oauth/token',
|
|
164
|
+
},
|
|
165
|
+
})
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Each service can optionally override the default token URL:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const client = new TimebackClient({
|
|
172
|
+
services: {
|
|
173
|
+
oneroster: 'https://roster.example.com',
|
|
174
|
+
caliper: {
|
|
175
|
+
baseUrl: 'https://analytics.example.com',
|
|
176
|
+
authUrl: 'https://analytics-auth.example.com/token', // different auth provider
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
auth: {
|
|
180
|
+
clientId: '...',
|
|
181
|
+
clientSecret: '...',
|
|
182
|
+
authUrl: 'https://auth.example.com/oauth/token', // default for services without override
|
|
183
|
+
},
|
|
184
|
+
})
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
OAuth tokens are shared across sub-clients that use the same token URL.
|
|
188
|
+
|
|
189
|
+
## Individual Clients
|
|
190
|
+
|
|
191
|
+
For standalone usage, install individual packages:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
bun add @timeback/oneroster
|
|
195
|
+
bun add @timeback/edubridge
|
|
196
|
+
bun add @timeback/caliper
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
```typescript
|
|
200
|
+
import { OneRosterClient } from '@timeback/oneroster'
|
|
201
|
+
|
|
202
|
+
const client = new OneRosterClient({
|
|
203
|
+
env: 'staging',
|
|
204
|
+
auth: { clientId: '...', clientSecret: '...' },
|
|
205
|
+
})
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
## Debug Mode
|
|
209
|
+
|
|
210
|
+
Enable debug logging with `DEBUG=1`:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
DEBUG=1 bun run my-script.ts
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
This outputs detailed logs for HTTP requests and authentication:
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { CaliperClientInstance } from '@timeback/caliper';
|
|
2
|
+
import type { AuthCheckResult, TimebackProvider } from '@timeback/internal-client-infra';
|
|
3
|
+
import type { EdubridgeClientInstance } from '@timeback/edubridge';
|
|
4
|
+
import type { OneRosterClientInstance } from '@timeback/oneroster';
|
|
5
|
+
import type { TimebackClientConfig } from './types/index';
|
|
6
|
+
/**
|
|
7
|
+
* Timeback Client
|
|
8
|
+
*
|
|
9
|
+
* Unified client for all Timeback education APIs.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Unified client for Timeback education APIs.
|
|
13
|
+
*
|
|
14
|
+
* Provides access to all Timeback APIs with shared authentication:
|
|
15
|
+
* - **OneRoster**: Rostering and gradebook data
|
|
16
|
+
* - **Edubridge**: Simplified enrollments and analytics
|
|
17
|
+
* - **Caliper**: Learning analytics events
|
|
18
|
+
*
|
|
19
|
+
* All sub-clients share a single OAuth token, reducing auth requests.
|
|
20
|
+
*
|
|
21
|
+
* @example Environment mode
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const timeback = new TimebackClient({
|
|
24
|
+
* env: 'staging',
|
|
25
|
+
* auth: { clientId: '...', clientSecret: '...' },
|
|
26
|
+
* })
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* @example Platform selection
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const timeback = new TimebackClient({
|
|
32
|
+
* platform: 'LEARNWITH_AI',
|
|
33
|
+
* env: 'production',
|
|
34
|
+
* auth: { clientId: '...', clientSecret: '...' },
|
|
35
|
+
* })
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @example Provider mode (pre-built provider)
|
|
39
|
+
* ```typescript
|
|
40
|
+
* import { TimebackProvider } from '@timeback/internal-client-infra'
|
|
41
|
+
*
|
|
42
|
+
* const provider = new TimebackProvider({
|
|
43
|
+
* platform: 'BEYOND_AI',
|
|
44
|
+
* env: 'staging',
|
|
45
|
+
* auth: { clientId: '...', clientSecret: '...' },
|
|
46
|
+
* })
|
|
47
|
+
*
|
|
48
|
+
* const timeback = new TimebackClient({ provider })
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @example Base URL mode (self-hosted)
|
|
52
|
+
* ```typescript
|
|
53
|
+
* const timeback = new TimebackClient({
|
|
54
|
+
* baseUrl: 'https://timeback.myschool.edu',
|
|
55
|
+
* auth: {
|
|
56
|
+
* clientId: '...',
|
|
57
|
+
* clientSecret: '...',
|
|
58
|
+
* authUrl: 'https://timeback.myschool.edu/oauth/token',
|
|
59
|
+
* },
|
|
60
|
+
* })
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare class TimebackClient {
|
|
64
|
+
private readonly provider;
|
|
65
|
+
private _closed;
|
|
66
|
+
private _oneroster?;
|
|
67
|
+
private _edubridge?;
|
|
68
|
+
private _caliper?;
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new Timeback client.
|
|
71
|
+
*
|
|
72
|
+
* @param config - Client configuration (env, baseUrl, provider, or services mode).
|
|
73
|
+
* If omitted, reads from TIMEBACK_ENV, TIMEBACK_CLIENT_ID,
|
|
74
|
+
* and TIMEBACK_CLIENT_SECRET environment variables.
|
|
75
|
+
*/
|
|
76
|
+
constructor(config?: TimebackClientConfig);
|
|
77
|
+
/**
|
|
78
|
+
* OneRoster API client for rostering and gradebook operations.
|
|
79
|
+
*
|
|
80
|
+
* Lazily initialized on first access. Shares OAuth tokens with other
|
|
81
|
+
* sub-clients through the provider.
|
|
82
|
+
*
|
|
83
|
+
* @returns The OneRoster client instance
|
|
84
|
+
* @throws {Error} If client has been closed or service not configured
|
|
85
|
+
*/
|
|
86
|
+
get oneroster(): OneRosterClientInstance;
|
|
87
|
+
/**
|
|
88
|
+
* Edubridge API client for simplified enrollments and analytics.
|
|
89
|
+
*
|
|
90
|
+
* Lazily initialized on first access. Shares OAuth tokens with other
|
|
91
|
+
* sub-clients through the provider.
|
|
92
|
+
*
|
|
93
|
+
* @returns The Edubridge client instance
|
|
94
|
+
* @throws {Error} If client has been closed or service not configured
|
|
95
|
+
*/
|
|
96
|
+
get edubridge(): EdubridgeClientInstance;
|
|
97
|
+
/**
|
|
98
|
+
* Caliper API client for learning analytics events.
|
|
99
|
+
*
|
|
100
|
+
* Lazily initialized on first access. Shares OAuth tokens with other
|
|
101
|
+
* sub-clients through the provider.
|
|
102
|
+
*
|
|
103
|
+
* @returns The Caliper client instance
|
|
104
|
+
* @throws {Error} If client has been closed or service not configured
|
|
105
|
+
*/
|
|
106
|
+
get caliper(): CaliperClientInstance;
|
|
107
|
+
/**
|
|
108
|
+
* Verify that OAuth authentication is working.
|
|
109
|
+
*
|
|
110
|
+
* Attempts to acquire a token using the provider's credentials.
|
|
111
|
+
* Returns a health check result with success/failure and latency info.
|
|
112
|
+
*
|
|
113
|
+
* @returns Auth check result
|
|
114
|
+
* @throws {Error} If client has been closed
|
|
115
|
+
*/
|
|
116
|
+
checkAuth(): Promise<AuthCheckResult>;
|
|
117
|
+
/**
|
|
118
|
+
* Close the client and release resources.
|
|
119
|
+
*
|
|
120
|
+
* After calling close():
|
|
121
|
+
* - Cached OAuth tokens are invalidated
|
|
122
|
+
* - Sub-client references are cleared
|
|
123
|
+
* - Further API calls will throw an error
|
|
124
|
+
*/
|
|
125
|
+
close(): void;
|
|
126
|
+
/**
|
|
127
|
+
* Check if the client has been closed.
|
|
128
|
+
* @returns True if closed
|
|
129
|
+
*/
|
|
130
|
+
get closed(): boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Get the underlying provider for advanced use cases.
|
|
133
|
+
*
|
|
134
|
+
* @returns The TimebackProvider instance used by this client
|
|
135
|
+
*/
|
|
136
|
+
getProvider(): TimebackProvider;
|
|
137
|
+
/**
|
|
138
|
+
* Throw if the client has been closed.
|
|
139
|
+
*/
|
|
140
|
+
private assertOpen;
|
|
141
|
+
/**
|
|
142
|
+
* Throw if a service is not configured.
|
|
143
|
+
* @param service - Service name to check
|
|
144
|
+
*/
|
|
145
|
+
private assertService;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AACxF,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAEzD;;;;GAIG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,qBAAa,cAAc;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,OAAO,CAAQ;IAEvB,OAAO,CAAC,UAAU,CAAC,CAAyB;IAC5C,OAAO,CAAC,UAAU,CAAC,CAAyB;IAC5C,OAAO,CAAC,QAAQ,CAAC,CAAuB;IAExC;;;;;;OAMG;IACH,YAAY,MAAM,CAAC,EAAE,oBAAoB,EAUxC;IAED;;;;;;;;OAQG;IACH,IAAI,SAAS,IAAI,uBAAuB,CASvC;IAED;;;;;;;;OAQG;IACH,IAAI,SAAS,IAAI,uBAAuB,CASvC;IAED;;;;;;;;OAQG;IACH,IAAI,OAAO,IAAI,qBAAqB,CASnC;IAMD;;;;;;;;OAQG;IACH,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC,CAGpC;IAED;;;;;;;OAOG;IACH,KAAK,IAAI,IAAI,CAUZ;IAED;;;OAGG;IACH,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED;;;;OAIG;IACH,WAAW,IAAI,gBAAgB,CAE9B;IAED;;OAEG;IACH,OAAO,CAAC,UAAU;IAMlB;;;OAGG;IACH,OAAO,CAAC,aAAa;CAKrB"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timeback API Endpoints
|
|
3
|
+
*
|
|
4
|
+
* Re-exports URL constants from `@timeback/internal-constants`.
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolveEnvVars } from '@timeback/internal-client-infra';
|
|
7
|
+
import type { Environment, EnvServiceUrls, Platform } from './types';
|
|
8
|
+
/**
|
|
9
|
+
* Environment variable names for Timeback client configuration.
|
|
10
|
+
*/
|
|
11
|
+
export declare const TIMEBACK_ENV_VARS: ResolveEnvVars;
|
|
12
|
+
/**
|
|
13
|
+
* Get all service URLs for a given platform and environment.
|
|
14
|
+
*
|
|
15
|
+
* @param env - Target environment (staging or production)
|
|
16
|
+
* @param platform - Target platform (defaults to 'BEYOND_AI')
|
|
17
|
+
* @returns Service URLs for the environment
|
|
18
|
+
*/
|
|
19
|
+
export declare function getServiceUrlsForEnv(env: Environment, platform?: Platform): EnvServiceUrls;
|
|
20
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAA;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAMpE;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAM/B,CAAA;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,WAAW,EAChB,QAAQ,GAAE,QAA2B,GACnC,cAAc,CAQhB"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACN,QAAQ,EACR,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,GACf,MAAM,iCAAiC,CAAA"}
|