brightspace-mcp-server 1.5.0 → 1.5.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.
- package/README.md +35 -11
- package/build/api/cache.d.ts.map +1 -1
- package/build/api/cache.js +6 -0
- package/build/api/cache.js.map +1 -1
- package/build/api/client.d.ts +5 -0
- package/build/api/client.d.ts.map +1 -1
- package/build/api/client.js +57 -14
- package/build/api/client.js.map +1 -1
- package/build/api/paginate.d.ts +23 -0
- package/build/api/paginate.d.ts.map +1 -0
- package/build/api/paginate.js +89 -0
- package/build/api/paginate.js.map +1 -0
- package/build/api/retry.d.ts +42 -0
- package/build/api/retry.d.ts.map +1 -0
- package/build/api/retry.js +50 -0
- package/build/api/retry.js.map +1 -0
- package/build/api/types.d.ts +3 -0
- package/build/api/types.d.ts.map +1 -1
- package/build/api/types.js.map +1 -1
- package/build/auth/browser-auth.d.ts.map +1 -1
- package/build/auth/browser-auth.js +2 -1
- package/build/auth/browser-auth.js.map +1 -1
- package/build/auth/session-store.d.ts.map +1 -1
- package/build/auth/session-store.js +4 -4
- package/build/auth/session-store.js.map +1 -1
- package/build/setup.js +1 -1
- package/build/setup.js.map +1 -1
- package/build/tools/get-assignments.d.ts.map +1 -1
- package/build/tools/get-assignments.js +58 -27
- package/build/tools/get-assignments.js.map +1 -1
- package/build/tools/get-classlist-emails.d.ts.map +1 -1
- package/build/tools/get-classlist-emails.js +4 -6
- package/build/tools/get-classlist-emails.js.map +1 -1
- package/build/tools/get-course-content.d.ts.map +1 -1
- package/build/tools/get-course-content.js +12 -2
- package/build/tools/get-course-content.js.map +1 -1
- package/build/tools/get-my-courses.d.ts.map +1 -1
- package/build/tools/get-my-courses.js +4 -7
- package/build/tools/get-my-courses.js.map +1 -1
- package/build/tools/get-roster.d.ts.map +1 -1
- package/build/tools/get-roster.js +7 -10
- package/build/tools/get-roster.js.map +1 -1
- package/build/utils/atomic-write.d.ts +18 -0
- package/build/utils/atomic-write.d.ts.map +1 -0
- package/build/utils/atomic-write.js +84 -0
- package/build/utils/atomic-write.js.map +1 -0
- package/build/utils/config-store.d.ts.map +1 -1
- package/build/utils/config-store.js +2 -3
- package/build/utils/config-store.js.map +1 -1
- package/build/utils/logger.d.ts.map +1 -1
- package/build/utils/logger.js +45 -1
- package/build/utils/logger.js.map +1 -1
- package/build/utils/update-checker.d.ts +30 -5
- package/build/utils/update-checker.d.ts.map +1 -1
- package/build/utils/update-checker.js +79 -45
- package/build/utils/update-checker.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **By [Rohan Muppa](https://github.com/rohanmuppa), ECE @ Purdue**
|
|
4
4
|
|
|
5
|
-
Talk to your Brightspace courses with AI. Ask about grades, due dates, announcements, and more. Works with Claude,
|
|
5
|
+
Talk to your Brightspace courses with AI. Ask about grades, due dates, quizzes, announcements, and more. Works with Claude Desktop, Claude Code, Cursor, ChatGPT Desktop, Windsurf, and any MCP client.
|
|
6
6
|
|
|
7
7
|
This is an [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that connects your AI to D2L Brightspace so it can pull your grades, assignments, syllabus, and course content on demand.
|
|
8
8
|
|
|
@@ -19,7 +19,7 @@ Works with any school that uses D2L Brightspace, including Purdue, SUNY, USC, an
|
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
22
|
-
**You need:** [Node.js 18+](https://nodejs.org/) (download the LTS
|
|
22
|
+
**You need:** [Node.js 18+](https://nodejs.org/) (download the current LTS, 20 or newer)
|
|
23
23
|
|
|
24
24
|
**Option 1: Let your AI do it**
|
|
25
25
|
|
|
@@ -50,7 +50,9 @@ you're at and skips SUNY's campus picker when you sign in:
|
|
|
50
50
|
npx brightspace-mcp-server setup --suny
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
The wizard walks you through login
|
|
53
|
+
The wizard walks you through login and MFA, auto configures Claude Desktop and Cursor, and prints the config to paste into ChatGPT Desktop if it is installed. Restart your AI client when it finishes.
|
|
54
|
+
|
|
55
|
+
Any other D2L school: run `setup` without a flag and paste your Brightspace URL (for example `https://yourschool.brightspace.com`).
|
|
54
56
|
|
|
55
57
|
<details>
|
|
56
58
|
<summary>Using a different client? Configure it manually.</summary>
|
|
@@ -69,18 +71,22 @@ You still need to run `npx brightspace-mcp-server setup` first to save your cred
|
|
|
69
71
|
|
|
70
72
|
## Session Expired?
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
You should rarely see this. Access tokens are re-minted from your saved session cookie in the background (no browser, about 200 ms), and a browser only opens when the Brightspace session itself has ended, typically after a day or two. If that automatic re-login fails, run:
|
|
73
75
|
|
|
74
76
|
```bash
|
|
75
77
|
npx brightspace-mcp-server auth
|
|
76
78
|
```
|
|
77
79
|
|
|
80
|
+
**MFA at Purdue** is Microsoft Authenticator number matching: a two digit number appears in the browser and is also printed in the terminal. Enter it on your phone. Other schools may use Duo or their own app.
|
|
81
|
+
|
|
78
82
|
## What You Can Ask About
|
|
79
83
|
|
|
80
84
|
| Topic | Examples |
|
|
81
85
|
|-------|---------|
|
|
82
86
|
| Grades | "Am I passing all my classes?" · "Compare my grades across all courses" |
|
|
83
|
-
| Assignments | "What's due in the next 48 hours?" · "Summarize every assignment I haven't turned in yet" |
|
|
87
|
+
| Assignments | "What's due in the next 48 hours?" · "Summarize every assignment I haven't turned in yet" · "Give me the link to submit HW 4" |
|
|
88
|
+
| Quizzes | "How many attempts do I have left on Quiz 3?" · "Which quizzes close this week?" |
|
|
89
|
+
| Exams | "Is there a midterm in the gradebook that isn't on my assignments list?" |
|
|
84
90
|
| Announcements | "Did any professor post something important today?" · "What did my CS prof announce this week?" |
|
|
85
91
|
| Course content | "Find the midterm review slides" · "Download every PDF from Module 5" |
|
|
86
92
|
| Roster | "Who are the TAs for ECE 264?" · "Get me my instructor's email" |
|
|
@@ -89,10 +95,11 @@ npx brightspace-mcp-server auth
|
|
|
89
95
|
|
|
90
96
|
## Security
|
|
91
97
|
|
|
92
|
-
-
|
|
93
|
-
- Session tokens
|
|
94
|
-
- All traffic to Brightspace is HTTPS
|
|
95
|
-
-
|
|
98
|
+
- Your username and password stay on your machine in `~/.brightspace-mcp/config.json`, readable only by your user (mode 0600). They are typed into your school's real login page and nowhere else.
|
|
99
|
+
- Session tokens and cookies live in `~/.d2l-session/`, encrypted with AES-256-GCM.
|
|
100
|
+
- All traffic to Brightspace is HTTPS.
|
|
101
|
+
- On startup the server asks the npm registry whether a newer version exists. When running through `npx`, it clears this package's own stale npx cache directories so the next start downloads the new version. It never installs anything itself. Set `D2L_NO_UPDATE_CHECK=1` to turn the check off.
|
|
102
|
+
- Read only: this server never submits, posts, or changes anything in Brightspace.
|
|
96
103
|
|
|
97
104
|
## Contributing & Forking
|
|
98
105
|
|
|
@@ -102,7 +109,8 @@ Want to add your school, build a new tool, or fix something? Fork the repo, make
|
|
|
102
109
|
git clone https://github.com/RohanMuppa/brightspace-mcp-server.git
|
|
103
110
|
cd brightspace-mcp-server
|
|
104
111
|
npm install
|
|
105
|
-
npm run dev
|
|
112
|
+
npm run dev # tsc in watch mode
|
|
113
|
+
npm test # vitest, must be green before you open a PR
|
|
106
114
|
```
|
|
107
115
|
|
|
108
116
|
**Add your school:** Add a preset to `SCHOOL_PRESETS` in `src/setup.ts`. If your school's login flow is different, add a handler in `src/auth/`.
|
|
@@ -117,7 +125,23 @@ Licensed under the MIT License.
|
|
|
117
125
|
|
|
118
126
|
Automatic. Every time your AI client starts a session, it runs `npx brightspace-mcp-server@latest` which pulls the newest version from npm. No action needed.
|
|
119
127
|
|
|
120
|
-
If you ever suspect you're on an old version
|
|
128
|
+
If you ever suspect you're on an old version (the auth banner prints the version), clear the npx cache and restart your client:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npx clear-npx-cache
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## What's new in 1.5.0
|
|
135
|
+
|
|
136
|
+
- Token refresh no longer opens a browser: the access token is re-minted from your session cookie in about 200 ms.
|
|
137
|
+
- Silent re-login when your Microsoft session is still alive, and a fast fallback to the credential login when it is not.
|
|
138
|
+
- The Microsoft Authenticator number match is printed in the terminal, so headless logins can be approved.
|
|
139
|
+
- `get_upcoming_due_dates` reads due dates from assignments and quizzes directly. It no longer reports a quiz as due on the day it opens.
|
|
140
|
+
- Every assignment, quiz, and due date carries a `url` that opens the item in Brightspace.
|
|
141
|
+
- Gradebook columns with no matching assignment or quiz (a proctored midterm, for example) are surfaced as `gradeOnly` items.
|
|
142
|
+
- Unpublished announcements are hidden, and announcements sort by the date they were scheduled to post.
|
|
143
|
+
- A dead session is detected even when Brightspace answers with HTTP 200, so re-login triggers instead of a confusing network error.
|
|
144
|
+
- SUNY preset (`--suny`) and a more robust Microsoft Entra login, contributed by the community.
|
|
121
145
|
|
|
122
146
|
---
|
|
123
147
|
|
package/build/api/cache.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/api/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,qBAAa,QAAQ,CAAC,CAAC,GAAG,OAAO;IAC/B,OAAO,CAAC,KAAK,CAAoC;IAEjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/api/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,qBAAa,QAAQ,CAAC,CAAC,GAAG,OAAO;IAC/B,OAAO,CAAC,KAAK,CAAoC;IAEjD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAsB/C,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;IAK/B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIzB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAU5B,KAAK,IAAI,IAAI;IASb,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
package/build/api/cache.js
CHANGED
|
@@ -15,6 +15,12 @@ export class TTLCache {
|
|
|
15
15
|
const timerId = setTimeout(() => {
|
|
16
16
|
this.cache.delete(key);
|
|
17
17
|
}, ttlMs);
|
|
18
|
+
// An idle cache entry must not hold the process open: a one hour
|
|
19
|
+
// enrollments TTL would otherwise keep the event loop alive after the
|
|
20
|
+
// last request has been answered.
|
|
21
|
+
if (typeof timerId.unref === "function") {
|
|
22
|
+
timerId.unref();
|
|
23
|
+
}
|
|
18
24
|
// Store entry
|
|
19
25
|
this.cache.set(key, { data: value, timerId });
|
|
20
26
|
}
|
package/build/api/cache.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/api/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,OAAO,QAAQ;IACX,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEjD,GAAG,CAAC,GAAW,EAAE,KAAQ,EAAE,KAAa;QACtC,qCAAqC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAED,yCAAyC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC,EAAE,KAAK,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/api/cache.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,MAAM,OAAO,QAAQ;IACX,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEjD,GAAG,CAAC,GAAW,EAAE,KAAQ,EAAE,KAAa;QACtC,qCAAqC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,QAAQ,EAAE,CAAC;YACb,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjC,CAAC;QAED,yCAAyC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC,EAAE,KAAK,CAAC,CAAC;QACV,iEAAiE;QACjE,sEAAsE;QACtE,kCAAkC;QAClC,IAAI,OAAQ,OAAkC,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YACnE,OAAiC,CAAC,KAAK,EAAE,CAAC;QAC7C,CAAC;QAED,cAAc;QACd,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,GAAG,CAAC,GAAW;QACb,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,KAAK,EAAE,IAAI,CAAC;IACrB,CAAC;IAED,GAAG,CAAC,GAAW;QACb,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,GAAW;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK,EAAE,CAAC;YACV,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK;QACH,mBAAmB;QACnB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;YACxC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QACD,YAAY;QACZ,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
|
package/build/api/client.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export declare class D2LApiClient {
|
|
|
25
25
|
private readonly cacheTTLs;
|
|
26
26
|
private readonly timeoutMs;
|
|
27
27
|
private readonly onAuthExpired?;
|
|
28
|
+
private readonly retryConfig;
|
|
28
29
|
private versions;
|
|
29
30
|
constructor(options: D2LApiClientOptions);
|
|
30
31
|
/**
|
|
@@ -60,6 +61,10 @@ export declare class D2LApiClient {
|
|
|
60
61
|
* @throws NetworkError on network/fetch failures
|
|
61
62
|
*/
|
|
62
63
|
getRaw(path: string): Promise<Response>;
|
|
64
|
+
/** One rate limiter token per attempt. */
|
|
65
|
+
private throttled;
|
|
66
|
+
/** Retry 429, 5xx, and network failures. A 401 is never retried here. */
|
|
67
|
+
private retrying;
|
|
63
68
|
/**
|
|
64
69
|
* Attempt auto-reauthentication via the onAuthExpired callback.
|
|
65
70
|
* If successful, returns the fresh token. Otherwise throws 401 ApiError.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAwB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAwB,MAAM,YAAY,CAAC;AAezF;;;;;;;;;;;;GAYG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsC;IACnE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;IACjC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAyB;IACxD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAc;IAC1C,OAAO,CAAC,QAAQ,CAA4B;gBAEhC,OAAO,EAAE,mBAAmB;IAuCxC;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQjC;;;OAGG;IACH,IAAI,WAAW,IAAI,WAAW,CAO7B;IAED;;;;;;;;OAQG;IACG,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,CAAC,CAAC;IA8BlE;;;;;;;;;OASG;IACG,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IAsB7C,0CAA0C;YAC5B,SAAS;IAKvB,yEAAyE;IACzE,OAAO,CAAC,QAAQ;IAQhB;;;OAGG;YACW,aAAa;IAgB3B;;OAEG;YACW,WAAW;IAyHzB;;OAEG;YACW,cAAc;IAuH5B;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAoBxB;;;;OAIG;IACH,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKxB;;;;;OAKG;IACH,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IAK3C;;;;OAIG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAK9B;;OAEG;IACH,UAAU,IAAI,IAAI;IAKlB;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,CAEtB;CACF"}
|
package/build/api/client.js
CHANGED
|
@@ -8,6 +8,7 @@ import { TTLCache } from "./cache.js";
|
|
|
8
8
|
import { TokenBucket } from "./rate-limiter.js";
|
|
9
9
|
import { discoverVersions } from "./version-discovery.js";
|
|
10
10
|
import { ApiError, RateLimitError, NetworkError } from "./errors.js";
|
|
11
|
+
import { withRetry, isRetryableFailure, retryAfterMsFrom } from "./retry.js";
|
|
11
12
|
import { log } from "../utils/logger.js";
|
|
12
13
|
/**
|
|
13
14
|
* The marker in the HTML stub a dead session gets instead of a payload. D2L
|
|
@@ -35,10 +36,19 @@ export class D2LApiClient {
|
|
|
35
36
|
cacheTTLs;
|
|
36
37
|
timeoutMs;
|
|
37
38
|
onAuthExpired;
|
|
39
|
+
retryConfig;
|
|
38
40
|
versions = null;
|
|
39
41
|
constructor(options) {
|
|
40
|
-
// HTTPS-only enforcement
|
|
41
|
-
|
|
42
|
+
// HTTPS-only enforcement, on a parsed URL rather than a string prefix so
|
|
43
|
+
// a malformed base cannot slip through as "not http".
|
|
44
|
+
let parsedBase;
|
|
45
|
+
try {
|
|
46
|
+
parsedBase = new URL(options.baseUrl);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
throw new Error(`Invalid D2L base URL: ${options.baseUrl}`);
|
|
50
|
+
}
|
|
51
|
+
if (parsedBase.protocol !== "https:") {
|
|
42
52
|
throw new Error("HTTPS is required for D2L API client. HTTP URLs are not allowed for security reasons.");
|
|
43
53
|
}
|
|
44
54
|
// Strip trailing slash from baseUrl
|
|
@@ -46,6 +56,7 @@ export class D2LApiClient {
|
|
|
46
56
|
this.tokenManager = options.tokenManager;
|
|
47
57
|
this.timeoutMs = options.timeoutMs ?? 30_000;
|
|
48
58
|
this.onAuthExpired = options.onAuthExpired;
|
|
59
|
+
this.retryConfig = options.retry ?? {};
|
|
49
60
|
// Merge user-provided TTLs with defaults
|
|
50
61
|
this.cacheTTLs = { ...DEFAULT_CACHE_TTLS, ...options.cacheTTLs };
|
|
51
62
|
// Initialize cache and rate limiter
|
|
@@ -90,22 +101,22 @@ export class D2LApiClient {
|
|
|
90
101
|
log("DEBUG", `Cache hit: ${path}`);
|
|
91
102
|
return this.cache.get(path);
|
|
92
103
|
}
|
|
93
|
-
//
|
|
94
|
-
await this.rateLimiter.consume();
|
|
95
|
-
// Get authentication token — auto-reauth if expired
|
|
104
|
+
// Get authentication token, auto-reauth if expired
|
|
96
105
|
let token = await this.tokenManager.getToken();
|
|
97
106
|
if (!token) {
|
|
98
107
|
token = await this.tryAutoReauth(path);
|
|
99
108
|
}
|
|
100
|
-
|
|
109
|
+
const authed = token;
|
|
110
|
+
// Transient failures are retried inside the rate limiter, so every
|
|
111
|
+
// attempt pays for a bucket token and a retry storm cannot bypass it.
|
|
101
112
|
try {
|
|
102
|
-
return await this.makeRequest(path,
|
|
113
|
+
return await this.retrying(() => this.throttled(() => this.makeRequest(path, authed, options)));
|
|
103
114
|
}
|
|
104
115
|
catch (error) {
|
|
105
116
|
if (error instanceof ApiError && error.status === 401) {
|
|
106
117
|
// Final attempt: auto-reauth and retry once
|
|
107
118
|
const freshToken = await this.tryAutoReauth(path);
|
|
108
|
-
return await this.makeRequest(path, freshToken, options);
|
|
119
|
+
return await this.throttled(() => this.makeRequest(path, freshToken, options));
|
|
109
120
|
}
|
|
110
121
|
throw error;
|
|
111
122
|
}
|
|
@@ -121,26 +132,37 @@ export class D2LApiClient {
|
|
|
121
132
|
* @throws NetworkError on network/fetch failures
|
|
122
133
|
*/
|
|
123
134
|
async getRaw(path) {
|
|
124
|
-
//
|
|
125
|
-
await this.rateLimiter.consume();
|
|
126
|
-
// Get authentication token — auto-reauth if expired
|
|
135
|
+
// Get authentication token, auto-reauth if expired
|
|
127
136
|
let token = await this.tokenManager.getToken();
|
|
128
137
|
if (!token) {
|
|
129
138
|
token = await this.tryAutoReauth(path);
|
|
130
139
|
}
|
|
131
|
-
|
|
140
|
+
const authed = token;
|
|
132
141
|
try {
|
|
133
|
-
return await this.makeRawRequest(path,
|
|
142
|
+
return await this.retrying(() => this.throttled(() => this.makeRawRequest(path, authed)));
|
|
134
143
|
}
|
|
135
144
|
catch (error) {
|
|
136
145
|
if (error instanceof ApiError && error.status === 401) {
|
|
137
146
|
// Final attempt: auto-reauth and retry once
|
|
138
147
|
const freshToken = await this.tryAutoReauth(path);
|
|
139
|
-
return await this.makeRawRequest(path, freshToken);
|
|
148
|
+
return await this.throttled(() => this.makeRawRequest(path, freshToken));
|
|
140
149
|
}
|
|
141
150
|
throw error;
|
|
142
151
|
}
|
|
143
152
|
}
|
|
153
|
+
/** One rate limiter token per attempt. */
|
|
154
|
+
async throttled(fn) {
|
|
155
|
+
await this.rateLimiter.consume();
|
|
156
|
+
return fn();
|
|
157
|
+
}
|
|
158
|
+
/** Retry 429, 5xx, and network failures. A 401 is never retried here. */
|
|
159
|
+
retrying(fn) {
|
|
160
|
+
return withRetry(fn, {
|
|
161
|
+
...this.retryConfig,
|
|
162
|
+
shouldRetry: isRetryableFailure,
|
|
163
|
+
retryAfterMs: retryAfterMsFrom,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
144
166
|
/**
|
|
145
167
|
* Attempt auto-reauthentication via the onAuthExpired callback.
|
|
146
168
|
* If successful, returns the fresh token. Otherwise throws 401 ApiError.
|
|
@@ -297,6 +319,27 @@ export class D2LApiClient {
|
|
|
297
319
|
const responseText = await response.text();
|
|
298
320
|
throw new ApiError(response.status, path, responseText);
|
|
299
321
|
}
|
|
322
|
+
// A dead session answers a file request the same way it answers a
|
|
323
|
+
// JSON one: HTTP 200 carrying an HTML stub that redirects to the
|
|
324
|
+
// login page. Left alone, that stub would be saved to disk under the
|
|
325
|
+
// file's own name. Only HTML is inspected, so real downloads are
|
|
326
|
+
// never buffered here.
|
|
327
|
+
const contentType = (response.headers.get("content-type") ?? "").toLowerCase();
|
|
328
|
+
if (contentType.startsWith("text/html")) {
|
|
329
|
+
const body = await response.text();
|
|
330
|
+
if (body.includes(EXPIRED_SESSION_MARKER)) {
|
|
331
|
+
log("DEBUG", "File download answered with the session-expired stub, treating it as a 401");
|
|
332
|
+
await this.tokenManager.clearToken();
|
|
333
|
+
throw new ApiError(401, path, "Session expired. Please re-authenticate via brightspace-auth.");
|
|
334
|
+
}
|
|
335
|
+
// A legitimate HTML page: hand back an equivalent response with the
|
|
336
|
+
// body we already consumed.
|
|
337
|
+
return new Response(body, {
|
|
338
|
+
status: response.status,
|
|
339
|
+
statusText: response.statusText,
|
|
340
|
+
headers: response.headers,
|
|
341
|
+
});
|
|
342
|
+
}
|
|
300
343
|
// Return raw response for caller to process
|
|
301
344
|
return response;
|
|
302
345
|
}
|
package/build/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC;;;GAGG;AACH,MAAM,sBAAsB,GAAG,kBAAkB,CAAC;AAElD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,YAAY;IACN,OAAO,CAAS;IAChB,YAAY,CAAsC;IAClD,KAAK,CAAW;IAChB,WAAW,CAAc;IACzB,SAAS,CAAY;IACrB,SAAS,CAAS;IAClB,aAAa,CAA0B;IAChD,QAAQ,GAAuB,IAAI,CAAC;IAE5C,YAAY,OAA4B;QACtC,yBAAyB;QACzB,IAAI,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,uFAAuF,CACxF,CAAC;QACJ,CAAC;QAED,oCAAoC;QACpC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC;QAC7C,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAE3C,yCAAyC;QACzC,IAAI,CAAC,SAAS,GAAG,EAAE,GAAG,kBAAkB,EAAE,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QAEjE,oCAAoC;QACpC,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI;YACjD,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,CAAC;SACd,CAAC;QACF,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAChC,eAAe,CAAC,QAAQ,EACxB,eAAe,CAAC,UAAU,CAC3B,CAAC;QAEF,GAAG,CAAC,OAAO,EAAE,gCAAgC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,CAAC,QAAQ,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACrE,GAAG,CACD,MAAM,EACN,mCAAmC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAC9E,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,IAAI,WAAW;QACb,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,GAAG,CAAI,IAAY,EAAE,OAA0B;QACnD,oBAAoB;QACpB,IAAI,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACzC,GAAG,CAAC,OAAO,EAAE,cAAc,IAAI,EAAE,CAAC,CAAC;YACnC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAM,CAAC;QACnC,CAAC;QAED,qBAAqB;QACrB,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAEjC,oDAAoD;QACpD,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAED,gCAAgC;QAChC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,WAAW,CAAI,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QACzD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACtD,4CAA4C;gBAC5C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAClD,OAAO,MAAM,IAAI,CAAC,WAAW,CAAI,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;YAC9D,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,MAAM,CAAC,IAAY;QACvB,qBAAqB;QACrB,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAEjC,oDAAoD;QACpD,IAAI,KAAK,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAED,gCAAgC;QAChC,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAChD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,QAAQ,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACtD,4CAA4C;gBAC5C,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAClD,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YACrD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,aAAa,CAAC,IAAY;QACtC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,GAAG,CAAC,MAAM,EAAE,qCAAqC,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAC3C,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;gBACtD,IAAI,UAAU,EAAE,CAAC;oBACf,GAAG,CAAC,MAAM,EAAE,mDAAmD,CAAC,CAAC;oBACjE,OAAO,UAAU,CAAC;gBACpB,CAAC;YACH,CAAC;YACD,GAAG,CAAC,MAAM,EAAE,qDAAqD,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,+DAA+D,CAAC,CAAC;IACjG,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW,CACvB,IAAY,EACZ,KAAgB,EAChB,OAA0B,EAC1B,UAAmB,KAAK;QAExB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,QAAQ,IAAI,EAAE,CAAC,CAAC;YAEnE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO;gBACP,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;aAC5C,CAAC,CAAC;YAEH,8BAA8B;YAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,IAAI,OAAO,EAAE,CAAC;oBACZ,qCAAqC;oBACrC,GAAG,CAAC,OAAO,EAAE,qCAAqC,CAAC,CAAC;oBACpD,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,QAAQ,CAChB,GAAG,EACH,IAAI,EACJ,+DAA+D,CAChE,CAAC;gBACJ,CAAC;gBAED,uCAAuC;gBACvC,GAAG,CAAC,OAAO,EAAE,uDAAuD,CAAC,CAAC;gBACtE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAEtD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;oBAChE,6BAA6B;oBAC7B,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,QAAQ,CAChB,GAAG,EACH,IAAI,EACJ,+DAA+D,CAChE,CAAC;gBACJ,CAAC;gBAED,yBAAyB;gBACzB,OAAO,MAAM,IAAI,CAAC,WAAW,CAAI,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;YACpE,CAAC;YAED,2BAA2B;YAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBACvD,MAAM,iBAAiB,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC5E,MAAM,IAAI,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YACpD,CAAC;YAED,gDAAgD;YAChD,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;YAC9C,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;YAC1D,CAAC;YAED,qEAAqE;YACrE,yEAAyE;YACzE,2EAA2E;YAC3E,yEAAyE;YACzE,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAE3C,IAAI,IAAO,CAAC;YACZ,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAM,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,sEAAsE;gBACtE,qEAAqE;gBACrE,IAAI,YAAY,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,CAAC;oBAClD,GAAG,CAAC,OAAO,EAAE,iEAAiE,CAAC,CAAC;oBAChF,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,QAAQ,CAChB,GAAG,EACH,IAAI,EACJ,+DAA+D,CAChE,CAAC;gBACJ,CAAC;gBACD,MAAM,IAAI,QAAQ,CAChB,QAAQ,CAAC,MAAM,EACf,IAAI,EACJ,sBAAsB,IAAI,6BAA6B,CACxD,CAAC;YACJ,CAAC;YAED,IAAI,OAAO,EAAE,GAAG,EAAE,CAAC;gBACjB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;gBACxC,GAAG,CAAC,OAAO,EAAE,uBAAuB,IAAI,UAAU,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC;YACtE,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0BAA0B;YAC1B,IACE,KAAK,YAAY,QAAQ;gBACzB,KAAK,YAAY,cAAc;gBAC/B,KAAK,YAAY,YAAY,EAC7B,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YAED,4BAA4B;YAC5B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,YAAY,CACpB,cAAc,IAAI,YAAY,OAAO,EAAE,EACvC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAC1B,IAAY,EACZ,KAAgB,EAChB,UAAmB,KAAK;QAExB,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,IAAI,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,GAAG,CAAC,OAAO,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,QAAQ,IAAI,QAAQ,CAAC,CAAC;YAEzE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,KAAK;gBACb,OAAO;gBACP,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;aAC5C,CAAC,CAAC;YAEH,8BAA8B;YAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,IAAI,OAAO,EAAE,CAAC;oBACZ,qCAAqC;oBACrC,GAAG,CAAC,OAAO,EAAE,qCAAqC,CAAC,CAAC;oBACpD,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,QAAQ,CAChB,GAAG,EACH,IAAI,EACJ,+DAA+D,CAChE,CAAC;gBACJ,CAAC;gBAED,uCAAuC;gBACvC,GAAG,CAAC,OAAO,EAAE,uDAAuD,CAAC,CAAC;gBACtE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAEtD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;oBAChE,6BAA6B;oBAC7B,MAAM,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;oBACrC,MAAM,IAAI,QAAQ,CAChB,GAAG,EACH,IAAI,EACJ,+DAA+D,CAChE,CAAC;gBACJ,CAAC;gBAED,yBAAyB;gBACzB,OAAO,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;YAC3D,CAAC;YAED,2BAA2B;YAC3B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBACvD,MAAM,iBAAiB,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC5E,MAAM,IAAI,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YACpD,CAAC;YAED,6DAA6D;YAC7D,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;YAC9C,CAAC;YAED,8BAA8B;YAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,QAAQ,CAAC,GAAG,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAC;YAClD,CAAC;YAED,gCAAgC;YAChC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC3C,MAAM,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;YAC1D,CAAC;YAED,4CAA4C;YAC5C,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0BAA0B;YAC1B,IACE,KAAK,YAAY,QAAQ;gBACzB,KAAK,YAAY,cAAc;gBAC/B,KAAK,YAAY,YAAY,EAC7B,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;YAED,4BAA4B;YAC5B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,IAAI,YAAY,CACpB,cAAc,IAAI,YAAY,OAAO,EAAE,EACvC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC3C,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,gBAAgB,CAAC,KAAgB;QACvC,MAAM,OAAO,GAA2B;YACtC,YAAY,EACV,gFAAgF;SACnF,CAAC;QAEF,8DAA8D;QAC9D,IAAI,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5C,wDAAwD;YACxD,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACnD,GAAG,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,oBAAoB;YACpB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,CAAC,WAAW,EAAE,CAAC;YACzD,GAAG,CAAC,OAAO,EAAE,mCAAmC,CAAC,CAAC;QACpD,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;OAIG;IACH,EAAE,CAAC,IAAY;QACb,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;QAChC,OAAO,eAAe,EAAE,GAAG,IAAI,EAAE,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACH,EAAE,CAAC,SAAiB,EAAE,IAAY;QAChC,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;QAChC,OAAO,eAAe,EAAE,IAAI,SAAS,GAAG,IAAI,EAAE,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,IAAY;QACnB,MAAM,EAAE,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;QAChC,OAAO,eAAe,EAAE,GAAG,IAAI,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACH,UAAU;QACR,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACnB,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;IACzB,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purdue Brightspace MCP Server
|
|
3
|
+
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
+
* Licensed under MIT - see LICENSE file for details.
|
|
5
|
+
*/
|
|
6
|
+
import type { D2LApiClient } from "./client.js";
|
|
7
|
+
export interface PaginateOptions {
|
|
8
|
+
/** Cache TTL, passed through to the client on every page. */
|
|
9
|
+
ttl?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Every item across every page of a { Items, PagingInfo } endpoint, in order.
|
|
13
|
+
*/
|
|
14
|
+
export declare function fetchAllItems<T>(apiClient: D2LApiClient, firstPath: string, options?: PaginateOptions): Promise<T[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Every object across every page of a { Objects, Next } endpoint, in order.
|
|
17
|
+
*
|
|
18
|
+
* Next arrives either as a full next-page URL or as a bare bookmark, so the
|
|
19
|
+
* absolute form is reduced to its path and query and anything else is treated
|
|
20
|
+
* as a bookmark against the first path.
|
|
21
|
+
*/
|
|
22
|
+
export declare function fetchAllObjects<T>(apiClient: D2LApiClient, firstPath: string, options?: PaginateOptions): Promise<T[]>;
|
|
23
|
+
//# sourceMappingURL=paginate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.d.ts","sourceRoot":"","sources":["../../src/api/paginate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAyBhD,MAAM,WAAW,eAAe;IAC9B,6DAA6D;IAC7D,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAQD;;GAEG;AACH,wBAAsB,aAAa,CAAC,CAAC,EACnC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,CAAC,EAAE,CAAC,CA6Bd;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,CAAC,EACrC,SAAS,EAAE,YAAY,EACvB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE,eAAe,GACxB,OAAO,CAAC,CAAC,EAAE,CAAC,CA4Bd"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purdue Brightspace MCP Server
|
|
3
|
+
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
+
* Licensed under MIT - see LICENSE file for details.
|
|
5
|
+
*/
|
|
6
|
+
import { log } from "../utils/logger.js";
|
|
7
|
+
/**
|
|
8
|
+
* Bookmark pagination for the two envelopes D2L answers with.
|
|
9
|
+
*
|
|
10
|
+
* Both loops are bounded twice over: a page ceiling, and a set of the
|
|
11
|
+
* bookmarks already followed. A server that keeps saying "there is more" and
|
|
12
|
+
* hands back the same bookmark would otherwise hang the tool forever.
|
|
13
|
+
*/
|
|
14
|
+
const MAX_PAGES = 200;
|
|
15
|
+
/** The first path with a bookmark appended, opening the query string if needed. */
|
|
16
|
+
function withBookmark(firstPath, bookmark) {
|
|
17
|
+
const separator = firstPath.includes("?") ? "&" : "?";
|
|
18
|
+
return `${firstPath}${separator}bookmark=${encodeURIComponent(bookmark)}`;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Every item across every page of a { Items, PagingInfo } endpoint, in order.
|
|
22
|
+
*/
|
|
23
|
+
export async function fetchAllItems(apiClient, firstPath, options) {
|
|
24
|
+
const items = [];
|
|
25
|
+
const seen = new Set();
|
|
26
|
+
let path = firstPath;
|
|
27
|
+
let pages = 0;
|
|
28
|
+
while (path !== null) {
|
|
29
|
+
if (pages >= MAX_PAGES) {
|
|
30
|
+
log("WARN", `Pagination stopped at the ${MAX_PAGES} page ceiling`, { firstPath });
|
|
31
|
+
break;
|
|
32
|
+
}
|
|
33
|
+
const response = await apiClient.get(path, options);
|
|
34
|
+
pages += 1;
|
|
35
|
+
items.push(...(response?.Items ?? []));
|
|
36
|
+
const paging = response?.PagingInfo;
|
|
37
|
+
const bookmark = paging?.Bookmark;
|
|
38
|
+
if (!paging?.HasMoreItems || !bookmark)
|
|
39
|
+
break;
|
|
40
|
+
if (seen.has(bookmark)) {
|
|
41
|
+
log("WARN", "Pagination stopped: the server repeated a bookmark", { firstPath });
|
|
42
|
+
break;
|
|
43
|
+
}
|
|
44
|
+
seen.add(bookmark);
|
|
45
|
+
path = withBookmark(firstPath, bookmark);
|
|
46
|
+
}
|
|
47
|
+
return items;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Every object across every page of a { Objects, Next } endpoint, in order.
|
|
51
|
+
*
|
|
52
|
+
* Next arrives either as a full next-page URL or as a bare bookmark, so the
|
|
53
|
+
* absolute form is reduced to its path and query and anything else is treated
|
|
54
|
+
* as a bookmark against the first path.
|
|
55
|
+
*/
|
|
56
|
+
export async function fetchAllObjects(apiClient, firstPath, options) {
|
|
57
|
+
const objects = [];
|
|
58
|
+
const seen = new Set();
|
|
59
|
+
let path = firstPath;
|
|
60
|
+
let pages = 0;
|
|
61
|
+
while (path !== null) {
|
|
62
|
+
if (pages >= MAX_PAGES) {
|
|
63
|
+
log("WARN", `Pagination stopped at the ${MAX_PAGES} page ceiling`, { firstPath });
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
const response = await apiClient.get(path, options);
|
|
67
|
+
pages += 1;
|
|
68
|
+
objects.push(...(response?.Objects ?? []));
|
|
69
|
+
const next = response?.Next;
|
|
70
|
+
if (!next)
|
|
71
|
+
break;
|
|
72
|
+
if (seen.has(next)) {
|
|
73
|
+
log("WARN", "Pagination stopped: the server repeated a next page", { firstPath });
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
seen.add(next);
|
|
77
|
+
path = nextPath(firstPath, next);
|
|
78
|
+
}
|
|
79
|
+
return objects;
|
|
80
|
+
}
|
|
81
|
+
/** A Next value resolved to a request path. */
|
|
82
|
+
function nextPath(firstPath, next) {
|
|
83
|
+
if (/^https?:\/\//i.test(next)) {
|
|
84
|
+
const url = new URL(next);
|
|
85
|
+
return `${url.pathname}${url.search}`;
|
|
86
|
+
}
|
|
87
|
+
return withBookmark(firstPath, next);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=paginate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paginate.js","sourceRoot":"","sources":["../../src/api/paginate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purdue Brightspace MCP Server
|
|
3
|
+
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
+
* Licensed under MIT. See LICENSE file for details.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Retry transient failures with exponential backoff and jitter.
|
|
8
|
+
*
|
|
9
|
+
* What counts as transient is decided by the caller through `shouldRetry`,
|
|
10
|
+
* so this module knows nothing about HTTP. A 429 that names a Retry-After is
|
|
11
|
+
* honored verbatim, even past `maxMs`, because the server has told us
|
|
12
|
+
* exactly when to come back and guessing sooner only earns another 429.
|
|
13
|
+
*
|
|
14
|
+
* `sleep` and `jitter` are injectable so the backoff sequence is testable
|
|
15
|
+
* without fake timers.
|
|
16
|
+
*/
|
|
17
|
+
export interface RetryConfig {
|
|
18
|
+
/** Total attempts including the first. Default 3. */
|
|
19
|
+
maxAttempts?: number;
|
|
20
|
+
/** Backoff before the second attempt, doubled thereafter. Default 250. */
|
|
21
|
+
initialMs?: number;
|
|
22
|
+
/** Ceiling on the computed backoff. Default 5000. Retry-After ignores it. */
|
|
23
|
+
maxMs?: number;
|
|
24
|
+
sleep?: (ms: number) => Promise<void>;
|
|
25
|
+
/** Returns a number in [0, 1). Default Math.random. */
|
|
26
|
+
jitter?: () => number;
|
|
27
|
+
}
|
|
28
|
+
export interface RetryOptions extends RetryConfig {
|
|
29
|
+
shouldRetry: (error: unknown) => boolean;
|
|
30
|
+
/** Milliseconds the failure itself asked us to wait, if it did. */
|
|
31
|
+
retryAfterMs?: (error: unknown) => number | undefined;
|
|
32
|
+
}
|
|
33
|
+
export declare function withRetry<T>(fn: () => Promise<T>, options: RetryOptions): Promise<T>;
|
|
34
|
+
/**
|
|
35
|
+
* Exactly three things get better by waiting: a rate limit, a server-side
|
|
36
|
+
* failure, and a dropped connection. A 401 needs a new token, a 403 needs
|
|
37
|
+
* permission, a 404 needs a different path. None of those are retried.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isRetryableFailure(error: unknown): boolean;
|
|
40
|
+
/** The Retry-After a 429 carried, in milliseconds, or undefined. */
|
|
41
|
+
export declare function retryAfterMsFrom(error: unknown): number | undefined;
|
|
42
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/api/retry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;;;;;;;;GAUG;AAEH,MAAM,WAAW,WAAW;IAC1B,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAa,SAAQ,WAAW;IAC/C,WAAW,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;IACzC,mEAAmE;IACnE,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;CACvD;AAOD,wBAAsB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CA4B1F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAI1D;AAED,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAKnE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purdue Brightspace MCP Server
|
|
3
|
+
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
+
* Licensed under MIT. See LICENSE file for details.
|
|
5
|
+
*/
|
|
6
|
+
import { ApiError, NetworkError, RateLimitError } from "./errors.js";
|
|
7
|
+
const JITTER_FRACTION = 0.3;
|
|
8
|
+
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
9
|
+
export async function withRetry(fn, options) {
|
|
10
|
+
const { maxAttempts = 3, initialMs = 250, maxMs = 5000, sleep = defaultSleep, jitter = Math.random, shouldRetry, retryAfterMs, } = options;
|
|
11
|
+
for (let attempt = 1;; attempt++) {
|
|
12
|
+
try {
|
|
13
|
+
return await fn();
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (attempt >= maxAttempts || !shouldRetry(error))
|
|
17
|
+
throw error;
|
|
18
|
+
const requested = retryAfterMs?.(error);
|
|
19
|
+
let delay;
|
|
20
|
+
if (requested !== undefined) {
|
|
21
|
+
delay = requested;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
const base = Math.min(initialMs * 2 ** (attempt - 1), maxMs);
|
|
25
|
+
delay = Math.round(base + base * JITTER_FRACTION * jitter());
|
|
26
|
+
}
|
|
27
|
+
await sleep(delay);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Exactly three things get better by waiting: a rate limit, a server-side
|
|
33
|
+
* failure, and a dropped connection. A 401 needs a new token, a 403 needs
|
|
34
|
+
* permission, a 404 needs a different path. None of those are retried.
|
|
35
|
+
*/
|
|
36
|
+
export function isRetryableFailure(error) {
|
|
37
|
+
if (error instanceof RateLimitError)
|
|
38
|
+
return true;
|
|
39
|
+
if (error instanceof ApiError)
|
|
40
|
+
return error.status >= 500 && error.status <= 599;
|
|
41
|
+
return error instanceof NetworkError;
|
|
42
|
+
}
|
|
43
|
+
/** The Retry-After a 429 carried, in milliseconds, or undefined. */
|
|
44
|
+
export function retryAfterMsFrom(error) {
|
|
45
|
+
if (error instanceof RateLimitError && typeof error.retryAfter === "number" && error.retryAfter > 0) {
|
|
46
|
+
return error.retryAfter * 1000;
|
|
47
|
+
}
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/api/retry.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgCrE,MAAM,eAAe,GAAG,GAAG,CAAC;AAE5B,MAAM,YAAY,GAAG,CAAC,EAAU,EAAiB,EAAE,CACjD,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpD,MAAM,CAAC,KAAK,UAAU,SAAS,CAAI,EAAoB,EAAE,OAAqB;IAC5E,MAAM,EACJ,WAAW,GAAG,CAAC,EACf,SAAS,GAAG,GAAG,EACf,KAAK,GAAG,IAAI,EACZ,KAAK,GAAG,YAAY,EACpB,MAAM,GAAG,IAAI,CAAC,MAAM,EACpB,WAAW,EACX,YAAY,GACb,GAAG,OAAO,CAAC;IAEZ,KAAK,IAAI,OAAO,GAAG,CAAC,GAAI,OAAO,EAAE,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,OAAO,IAAI,WAAW,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;gBAAE,MAAM,KAAK,CAAC;YAE/D,MAAM,SAAS,GAAG,YAAY,EAAE,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,KAAa,CAAC;YAClB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,KAAK,GAAG,SAAS,CAAC;YACpB,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC7D,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,GAAG,eAAe,GAAG,MAAM,EAAE,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAC/C,IAAI,KAAK,YAAY,cAAc;QAAE,OAAO,IAAI,CAAC;IACjD,IAAI,KAAK,YAAY,QAAQ;QAAE,OAAO,KAAK,CAAC,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC;IACjF,OAAO,KAAK,YAAY,YAAY,CAAC;AACvC,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,KAAK,YAAY,cAAc,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,GAAG,CAAC,EAAE,CAAC;QACpG,OAAO,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IACjC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/build/api/types.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { TokenData } from "../types/index.js";
|
|
7
7
|
import type { TokenManager } from "../auth/token-manager.js";
|
|
8
|
+
import type { RetryConfig } from "./retry.js";
|
|
8
9
|
export interface ApiVersions {
|
|
9
10
|
lp: string;
|
|
10
11
|
le: string;
|
|
@@ -31,6 +32,8 @@ export interface D2LApiClientOptions {
|
|
|
31
32
|
timeoutMs?: number;
|
|
32
33
|
/** Called when auth is expired and retries are exhausted. Return true if re-auth succeeded. */
|
|
33
34
|
onAuthExpired?: () => Promise<boolean>;
|
|
35
|
+
/** Backoff for 429, 5xx, and network failures. See retry.ts for defaults. */
|
|
36
|
+
retry?: RetryConfig;
|
|
34
37
|
}
|
|
35
38
|
export type { TokenData };
|
|
36
39
|
//# sourceMappingURL=types.d.ts.map
|
package/build/api/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAG9C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAGD,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,eAAO,MAAM,kBAAkB,EAAE,SAQhC,CAAC;AAGF,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;IAC/B,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,6EAA6E;IAC7E,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB;AAGD,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
package/build/api/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAuBH,uCAAuC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAc;IAC3C,WAAW,EAAE,SAAS,EAAE,SAAS;IACjC,aAAa,EAAE,SAAS,EAAE,SAAS;IACnC,aAAa,EAAE,OAAO,EAAE,QAAQ;IAChC,MAAM,EAAE,OAAO,EAAE,QAAQ;IACzB,WAAW,EAAE,OAAO,EAAE,SAAS;IAC/B,MAAM,EAAE,SAAS,EAAE,SAAS;IAC5B,OAAO,EAAE,SAAS,EAAE,SAAS;CAC9B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-auth.d.ts","sourceRoot":"","sources":["../../src/auth/browser-auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"browser-auth.d.ts","sourceRoot":"","sources":["../../src/auth/browser-auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AASH,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AA2B9D,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,OAAO,CAAU;gBAEb,MAAM,EAAE,SAAS;IAK7B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,aAAa;IAwB5B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,iBAAiB;IAoBhC;;;;;;;;;;;;;OAaG;mBACkB,oBAAoB;IA8CzC;;;;OAIG;YACW,wBAAwB;IAoBhC,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IA6KxC;;;;OAIG;YACW,eAAe;IAyD7B;;;OAGG;YACW,aAAa;IAmC3B;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IA+B9B;;;OAGG;YACW,gBAAgB;IA8C9B,4EAA4E;YAC9D,MAAM;IAQpB;;;OAGG;YACW,cAAc;IAoB5B;;;;;OAKG;YACW,cAAc;IAiB5B;;;OAGG;YACW,mBAAmB;IAsCjC,6EAA6E;YAC/D,UAAU;IAIxB;;;OAGG;YACW,wBAAwB;IAyCtC;;;;;OAKG;YACW,sBAAsB;IAoCpC;;;;OAIG;YACW,eAAe;IAyC7B;;;OAGG;YACW,gBAAgB;IAgE9B;;;OAGG;YACW,kBAAkB;IAiChC;;;OAGG;YACW,gBAAgB;YA8FhB,gBAAgB;IAc9B;;;;;OAKG;YACW,sBAAsB;IA+DpC;;;;;;;;;OASG;YACW,yBAAyB;CAiExC"}
|