brightspace-mcp-server 1.6.3 → 2.0.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 +34 -7
- package/build/api/client.d.ts +5 -3
- package/build/api/client.d.ts.map +1 -1
- package/build/api/client.js +71 -79
- package/build/api/client.js.map +1 -1
- package/build/api/errors.d.ts +4 -0
- package/build/api/errors.d.ts.map +1 -1
- package/build/api/errors.js +7 -0
- package/build/api/errors.js.map +1 -1
- package/build/auth/auth-cooldown.d.ts +16 -0
- package/build/auth/auth-cooldown.d.ts.map +1 -0
- package/build/auth/auth-cooldown.js +47 -0
- package/build/auth/auth-cooldown.js.map +1 -0
- package/build/auth/auth-lock.d.ts +7 -0
- package/build/auth/auth-lock.d.ts.map +1 -0
- package/build/auth/auth-lock.js +114 -0
- package/build/auth/auth-lock.js.map +1 -0
- package/build/auth/auth-runner.d.ts +17 -7
- package/build/auth/auth-runner.d.ts.map +1 -1
- package/build/auth/auth-runner.js +122 -26
- package/build/auth/auth-runner.js.map +1 -1
- package/build/auth/browser-auth.d.ts +17 -86
- package/build/auth/browser-auth.d.ts.map +1 -1
- package/build/auth/browser-auth.js +256 -615
- package/build/auth/browser-auth.js.map +1 -1
- package/build/auth/browser-state-store.d.ts +19 -0
- package/build/auth/browser-state-store.d.ts.map +1 -0
- package/build/auth/browser-state-store.js +101 -0
- package/build/auth/browser-state-store.js.map +1 -0
- package/build/auth/credential-store.d.ts +29 -0
- package/build/auth/credential-store.d.ts.map +1 -0
- package/build/auth/credential-store.js +233 -0
- package/build/auth/credential-store.js.map +1 -0
- package/build/auth/encrypted-store.d.ts +25 -0
- package/build/auth/encrypted-store.d.ts.map +1 -0
- package/build/auth/encrypted-store.js +61 -0
- package/build/auth/encrypted-store.js.map +1 -0
- package/build/auth/legacy-profile.d.ts +3 -0
- package/build/auth/legacy-profile.d.ts.map +1 -0
- package/build/auth/legacy-profile.js +41 -0
- package/build/auth/legacy-profile.js.map +1 -0
- package/build/auth/legacy-state.d.ts +14 -0
- package/build/auth/legacy-state.d.ts.map +1 -0
- package/build/auth/legacy-state.js +107 -0
- package/build/auth/legacy-state.js.map +1 -0
- package/build/auth/purdue-sso.d.ts +18 -36
- package/build/auth/purdue-sso.d.ts.map +1 -1
- package/build/auth/purdue-sso.js +165 -192
- package/build/auth/purdue-sso.js.map +1 -1
- package/build/auth/session-store.d.ts +16 -38
- package/build/auth/session-store.d.ts.map +1 -1
- package/build/auth/session-store.js +157 -152
- package/build/auth/session-store.js.map +1 -1
- package/build/auth/sso-flow.d.ts +14 -3
- package/build/auth/sso-flow.d.ts.map +1 -1
- package/build/auth/sso-flow.js +16 -1
- package/build/auth/sso-flow.js.map +1 -1
- package/build/auth/suny-sso.d.ts +3 -2
- package/build/auth/suny-sso.d.ts.map +1 -1
- package/build/auth/suny-sso.js +15 -24
- package/build/auth/suny-sso.js.map +1 -1
- package/build/auth/token-manager.d.ts +10 -3
- package/build/auth/token-manager.d.ts.map +1 -1
- package/build/auth/token-manager.js +62 -26
- package/build/auth/token-manager.js.map +1 -1
- package/build/auth/token-mint.d.ts +2 -2
- package/build/auth/token-mint.d.ts.map +1 -1
- package/build/auth/token-mint.js +31 -9
- package/build/auth/token-mint.js.map +1 -1
- package/build/auth-cli.d.ts +1 -7
- package/build/auth-cli.d.ts.map +1 -1
- package/build/auth-cli.js +29 -73
- package/build/auth-cli.js.map +1 -1
- package/build/index.js +8 -4
- package/build/index.js.map +1 -1
- package/build/setup.js +14 -8
- package/build/setup.js.map +1 -1
- package/build/types/index.d.ts +6 -0
- package/build/types/index.d.ts.map +1 -1
- package/build/utils/config-store.d.ts +1 -0
- package/build/utils/config-store.d.ts.map +1 -1
- package/build/utils/config-store.js +3 -0
- package/build/utils/config-store.js.map +1 -1
- package/build/utils/config.d.ts +2 -1
- package/build/utils/config.d.ts.map +1 -1
- package/build/utils/config.js +30 -10
- package/build/utils/config.js.map +1 -1
- package/build/utils/secure-config.d.ts +6 -0
- package/build/utils/secure-config.d.ts.map +1 -0
- package/build/utils/secure-config.js +57 -0
- package/build/utils/secure-config.js.map +1 -0
- package/package.json +4 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encrypted-store.js","sourceRoot":"","sources":["../../src/auth/encrypted-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-profile.d.ts","sourceRoot":"","sources":["../../src/auth/legacy-profile.ts"],"names":[],"mappings":"AAMA,iGAAiG;AACjG,wBAAsB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B3E"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as os from "node:os";
|
|
4
|
+
import trash from "trash";
|
|
5
|
+
import { log } from "../utils/logger.js";
|
|
6
|
+
/** Retire only the known v1 profile after both encrypted state and token persistence succeed. */
|
|
7
|
+
export async function retireLegacyProfile(sessionDir) {
|
|
8
|
+
const profile = path.join(sessionDir, "browser-data");
|
|
9
|
+
try {
|
|
10
|
+
const stat = await fs.lstat(profile);
|
|
11
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
12
|
+
return;
|
|
13
|
+
await fs.access(path.join(sessionDir, "storage-state.encrypted.json"));
|
|
14
|
+
try {
|
|
15
|
+
const owner = await fs.readlink(path.join(profile, "SingletonLock"));
|
|
16
|
+
const match = /^(.*)-(\d+)$/.exec(owner);
|
|
17
|
+
if (!match || match[1] !== os.hostname())
|
|
18
|
+
return;
|
|
19
|
+
try {
|
|
20
|
+
process.kill(Number(match[2]), 0);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (error.code !== "ESRCH")
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (error.code !== "ENOENT")
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
await trash([profile]);
|
|
33
|
+
log("INFO", "Moved the retired v1 browser-data profile to Trash. It can be restored there.");
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
if (error.code !== "ENOENT") {
|
|
37
|
+
log("WARN", "Could not retire the inactive v1 browser profile. It was preserved.");
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=legacy-profile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-profile.js","sourceRoot":"","sources":["../../src/auth/legacy-profile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAEzC,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,UAAkB;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,cAAc,EAAE;YAAE,OAAO;QACzD,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,8BAA8B,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACzC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;gBAAE,OAAO;YACjD,IAAI,CAAC;gBACH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;gBAClC,OAAO;YACT,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAK,KAA+B,CAAC,IAAI,KAAK,OAAO;oBAAE,OAAO;YAChE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO;QACjE,CAAC;QACD,MAAM,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QACvB,GAAG,CAAC,MAAM,EAAE,+EAA+E,CAAC,CAAC;IAC/F,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,GAAG,CAAC,MAAM,EAAE,qEAAqE,CAAC,CAAC;QACrF,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brightspace MCP Server
|
|
3
|
+
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
+
* Licensed under MIT. See LICENSE file for details.
|
|
5
|
+
*/
|
|
6
|
+
type StateDisposition = "absent" | "encrypted" | "preserved";
|
|
7
|
+
export interface LegacyMigrationResult {
|
|
8
|
+
tokenState: StateDisposition;
|
|
9
|
+
browserState: StateDisposition;
|
|
10
|
+
}
|
|
11
|
+
/** Secure v1 state in its original directory without assigning it to a new identity. */
|
|
12
|
+
export declare function migrateLegacyState(sessionRoot: string): Promise<LegacyMigrationResult>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=legacy-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-state.d.ts","sourceRoot":"","sources":["../../src/auth/legacy-state.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,KAAK,gBAAgB,GAAG,QAAQ,GAAG,WAAW,GAAG,WAAW,CAAC;AAC7D,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,gBAAgB,CAAC;IAC7B,YAAY,EAAE,gBAAgB,CAAC;CAChC;AAmCD,wFAAwF;AACxF,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwD5F"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Brightspace MCP Server
|
|
3
|
+
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
+
* Licensed under MIT. See LICENSE file for details.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from "node:fs/promises";
|
|
7
|
+
import * as path from "node:path";
|
|
8
|
+
import { acquireProcessLock, AuthenticationInProgressError } from "./auth-lock.js";
|
|
9
|
+
import { BrowserStateStore } from "./browser-state-store.js";
|
|
10
|
+
import { NativeCredentialStoreError } from "./credential-store.js";
|
|
11
|
+
import { SessionStore } from "./session-store.js";
|
|
12
|
+
import { log } from "../utils/logger.js";
|
|
13
|
+
async function fileKind(root, name) {
|
|
14
|
+
try {
|
|
15
|
+
const stat = await fs.lstat(path.join(root, name));
|
|
16
|
+
return stat.isFile() && !stat.isSymbolicLink() ? "regular" : "unsafe";
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (error.code === "ENOENT")
|
|
20
|
+
return "absent";
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function reportPreserved(label) {
|
|
25
|
+
log("WARN", `Legacy ${label} could not be migrated safely and was preserved in the original session directory. The new account will use a separate session.`);
|
|
26
|
+
}
|
|
27
|
+
async function migrate(label, operation) {
|
|
28
|
+
try {
|
|
29
|
+
await operation();
|
|
30
|
+
return "encrypted";
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (error instanceof NativeCredentialStoreError || error instanceof AuthenticationInProgressError)
|
|
34
|
+
throw error;
|
|
35
|
+
reportPreserved(label);
|
|
36
|
+
return "preserved";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function isV2Session(root) {
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse(await fs.readFile(path.join(root, "session.json"), "utf8")).version === 2;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/** Secure v1 state in its original directory without assigning it to a new identity. */
|
|
48
|
+
export async function migrateLegacyState(sessionRoot) {
|
|
49
|
+
const names = ["session.json", "storage-state.json", "storage-state.encrypted.json"];
|
|
50
|
+
const kinds = await Promise.all(names.map((name) => fileKind(sessionRoot, name)));
|
|
51
|
+
if (kinds.every((kind) => kind === "absent"))
|
|
52
|
+
return { tokenState: "absent", browserState: "absent" };
|
|
53
|
+
const [token, plainBrowser, encryptedBrowser] = kinds;
|
|
54
|
+
const tokenAlreadyV2 = token === "regular" && await isV2Session(sessionRoot);
|
|
55
|
+
// Once migration is complete, validation is read-only and must not make
|
|
56
|
+
// concurrent MCP startups contend on the authentication lock.
|
|
57
|
+
if ((token === "absent" || token === "unsafe" || tokenAlreadyV2) && plainBrowser === "absent") {
|
|
58
|
+
let tokenState = "absent";
|
|
59
|
+
if (token === "unsafe") {
|
|
60
|
+
reportPreserved("token state");
|
|
61
|
+
tokenState = "preserved";
|
|
62
|
+
}
|
|
63
|
+
else if (tokenAlreadyV2) {
|
|
64
|
+
tokenState = await migrate("token state", () => new SessionStore(sessionRoot).load());
|
|
65
|
+
}
|
|
66
|
+
let browserState = "absent";
|
|
67
|
+
if (encryptedBrowser === "unsafe") {
|
|
68
|
+
reportPreserved("browser state");
|
|
69
|
+
browserState = "preserved";
|
|
70
|
+
}
|
|
71
|
+
else if (encryptedBrowser === "regular") {
|
|
72
|
+
browserState = await migrate("browser state", () => new BrowserStateStore(sessionRoot).load());
|
|
73
|
+
}
|
|
74
|
+
return { tokenState, browserState };
|
|
75
|
+
}
|
|
76
|
+
const release = await acquireProcessLock(path.join(sessionRoot, ".auth.lock"));
|
|
77
|
+
try {
|
|
78
|
+
const result = { tokenState: "absent", browserState: "absent" };
|
|
79
|
+
// Recheck under the process lock; never follow links into another directory.
|
|
80
|
+
const token = await fileKind(sessionRoot, "session.json");
|
|
81
|
+
if (token !== "absent") {
|
|
82
|
+
const salt = await fileKind(sessionRoot, "salt");
|
|
83
|
+
if (token === "unsafe" || salt === "unsafe") {
|
|
84
|
+
reportPreserved("token state");
|
|
85
|
+
result.tokenState = "preserved";
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
result.tokenState = await migrate("token state", () => new SessionStore(sessionRoot).load());
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const [plain, encrypted] = await Promise.all([
|
|
92
|
+
fileKind(sessionRoot, "storage-state.json"), fileKind(sessionRoot, "storage-state.encrypted.json"),
|
|
93
|
+
]);
|
|
94
|
+
if (plain === "unsafe" || encrypted === "unsafe") {
|
|
95
|
+
reportPreserved("browser state");
|
|
96
|
+
result.browserState = "preserved";
|
|
97
|
+
}
|
|
98
|
+
else if (plain !== "absent" || encrypted !== "absent") {
|
|
99
|
+
result.browserState = await migrate("browser state", () => new BrowserStateStore(sessionRoot).load());
|
|
100
|
+
}
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
finally {
|
|
104
|
+
await release();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=legacy-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legacy-state.js","sourceRoot":"","sources":["../../src/auth/legacy-state.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,66 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Purdue Brightspace MCP Server
|
|
3
3
|
* Copyright (c) 2026 Rohan Muppa. All rights reserved.
|
|
4
|
-
* Licensed under MIT
|
|
4
|
+
* Licensed under MIT : see LICENSE file for details.
|
|
5
5
|
*/
|
|
6
6
|
import type { Page } from "playwright";
|
|
7
7
|
interface PurdueSSOConfig {
|
|
8
8
|
username?: string;
|
|
9
9
|
password?: string;
|
|
10
|
+
baseUrl?: string;
|
|
10
11
|
}
|
|
11
12
|
export declare class PurdueSSOFlow {
|
|
12
13
|
private config;
|
|
14
|
+
private accountHintSubmitted;
|
|
13
15
|
constructor(config: PurdueSSOConfig);
|
|
14
16
|
/**
|
|
15
17
|
* Returns true if credentials are available for automated SSO login.
|
|
16
18
|
*/
|
|
17
19
|
hasCredentials(): boolean;
|
|
20
|
+
prepareLogin(page: Page): Promise<void>;
|
|
21
|
+
/** First half of Brightspace Bar's choreography, with no password access. */
|
|
22
|
+
identifyAccount(page: Page): Promise<boolean>;
|
|
18
23
|
/**
|
|
19
24
|
* Execute the complete Microsoft Entra ID SSO login flow for Purdue.
|
|
20
|
-
* Handles
|
|
25
|
+
* Handles the school selector, saved credentials, device MFA approval, and stay-signed-in.
|
|
21
26
|
*
|
|
22
27
|
* @param page - Playwright page instance (already navigated to Brightspace or redirected to login)
|
|
23
|
-
* @returns true
|
|
28
|
+
* @returns true after reaching Brightspace home; failures are typed errors
|
|
24
29
|
*/
|
|
25
30
|
login(page: Page): Promise<boolean>;
|
|
26
|
-
/**
|
|
27
|
-
* Manual login fallback: let the user type credentials and complete MFA themselves.
|
|
28
|
-
* The browser stays open in headed mode while we wait for /d2l/home.
|
|
29
|
-
*/
|
|
30
|
-
manualLogin(page: Page): Promise<boolean>;
|
|
31
31
|
private handleCampusSelector;
|
|
32
32
|
private enterCredentials;
|
|
33
|
-
/**
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*/
|
|
41
|
-
private findVisible;
|
|
42
|
-
/**
|
|
43
|
-
* Advance Microsoft Entra's account-name page.
|
|
44
|
-
*
|
|
45
|
-
* That page carries a password box of its own, and Playwright reports it as
|
|
46
|
-
* visible, so presence cannot tell it apart from a single-page form. The
|
|
47
|
-
* button label can: it reads "Next" there and "Sign in" on the view that
|
|
48
|
-
* follows. Filling the password against the account-name page leaves the
|
|
49
|
-
* browser parked with both fields populated and nothing submitted.
|
|
50
|
-
*/
|
|
51
|
-
private submitAccountName;
|
|
33
|
+
/** Ported from Brightspace Bar's proven four-step Entra choreography. */
|
|
34
|
+
private actWhenReady;
|
|
35
|
+
private fillWhenReady;
|
|
36
|
+
private clickWhenReady;
|
|
37
|
+
/** Match Brightspace Bar's selector loop instead of trusting the first DOM match. */
|
|
38
|
+
private anyVisible;
|
|
39
|
+
/** Brightspace Bar's bounded number/auth/KMSI polling loop. */
|
|
52
40
|
private handleMFA;
|
|
53
|
-
/**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
* Only a CHANGED value is logged: Entra re-mints the number whenever the
|
|
57
|
-
* user asks for a new request, and repeating the same digits every two
|
|
58
|
-
* seconds would bury everything else in the log.
|
|
59
|
-
*/
|
|
60
|
-
private watchNumberMatch;
|
|
41
|
+
/** The login shell also exposes D2L.LP, so verify origin and home as well. */
|
|
42
|
+
private isAuthenticated;
|
|
43
|
+
private clickProvenKmsi;
|
|
61
44
|
/** The digits on screen, or null when Entra is not showing any. */
|
|
62
45
|
private readNumberMatch;
|
|
63
|
-
private handleStaySignedIn;
|
|
64
46
|
}
|
|
65
47
|
export {};
|
|
66
48
|
//# sourceMappingURL=purdue-sso.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"purdue-sso.d.ts","sourceRoot":"","sources":["../../src/auth/purdue-sso.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"purdue-sso.d.ts","sourceRoot":"","sources":["../../src/auth/purdue-sso.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAW,IAAI,EAAE,MAAM,YAAY,CAAC;AAyBhD,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAQD,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,oBAAoB,CAAS;gBAEzB,MAAM,EAAE,eAAe;IAInC;;OAEG;IACH,cAAc,IAAI,OAAO;IAInB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7C,6EAA6E;IACvE,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;IASnD;;;;;;OAMG;IACG,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC;YA2B3B,oBAAoB;YAuBpB,gBAAgB;IAuB9B,yEAAyE;YAC3D,YAAY;YAeZ,aAAa;YAIb,cAAc;IAK5B,qFAAqF;YACvE,UAAU;IAOxB,+DAA+D;YACjD,SAAS;IAoCvB,8EAA8E;YAChE,eAAe;YAkBf,eAAe;IAa7B,mEAAmE;YACrD,eAAe;CAU9B"}
|