@civic/auth 0.6.0-beta.3 → 0.6.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/dist/shared/version.d.ts +1 -1
- package/dist/shared/version.d.ts.map +1 -1
- package/dist/shared/version.js +1 -1
- package/dist/shared/version.js.map +1 -1
- package/dist/vanillajs/auth/AuthenticationEvents.d.ts +11 -0
- package/dist/vanillajs/auth/AuthenticationEvents.d.ts.map +1 -0
- package/dist/vanillajs/auth/AuthenticationEvents.js +36 -0
- package/dist/vanillajs/auth/AuthenticationEvents.js.map +1 -0
- package/dist/vanillajs/auth/CivicAuth.d.ts +147 -0
- package/dist/vanillajs/auth/CivicAuth.d.ts.map +1 -0
- package/dist/vanillajs/auth/CivicAuth.js +513 -0
- package/dist/vanillajs/auth/CivicAuth.js.map +1 -0
- package/dist/vanillajs/auth/SessionManager.d.ts +17 -0
- package/dist/vanillajs/auth/SessionManager.d.ts.map +1 -0
- package/dist/vanillajs/auth/SessionManager.js +86 -0
- package/dist/vanillajs/auth/SessionManager.js.map +1 -0
- package/dist/vanillajs/iframe/SignalObserver.d.ts +33 -0
- package/dist/vanillajs/iframe/SignalObserver.d.ts.map +1 -0
- package/dist/vanillajs/iframe/SignalObserver.js +162 -0
- package/dist/vanillajs/iframe/SignalObserver.js.map +1 -0
- package/dist/vanillajs/iframe/domUtils.d.ts +4 -0
- package/dist/vanillajs/iframe/domUtils.d.ts.map +1 -0
- package/dist/vanillajs/iframe/domUtils.js +25 -0
- package/dist/vanillajs/iframe/domUtils.js.map +1 -0
- package/dist/vanillajs/index.d.ts +16 -0
- package/dist/vanillajs/index.d.ts.map +1 -0
- package/dist/vanillajs/index.js +15 -0
- package/dist/vanillajs/index.js.map +1 -0
- package/dist/vanillajs/services/ApiService.d.ts +22 -0
- package/dist/vanillajs/services/ApiService.d.ts.map +1 -0
- package/dist/vanillajs/services/ApiService.js +82 -0
- package/dist/vanillajs/services/ApiService.js.map +1 -0
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts +19 -0
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.d.ts.map +1 -0
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js +101 -0
- package/dist/vanillajs/storage/BrowserCookieStorageAdapter.js.map +1 -0
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts +9 -0
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.d.ts.map +1 -0
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js +36 -0
- package/dist/vanillajs/storage/BrowserLocalStorageAdapter.js.map +1 -0
- package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts +9 -0
- package/dist/vanillajs/storage/InMemoryStorageAdapter.d.ts.map +1 -0
- package/dist/vanillajs/storage/InMemoryStorageAdapter.js +16 -0
- package/dist/vanillajs/storage/InMemoryStorageAdapter.js.map +1 -0
- package/dist/vanillajs/storage/StorageAdapter.d.ts +15 -0
- package/dist/vanillajs/storage/StorageAdapter.d.ts.map +1 -0
- package/dist/vanillajs/storage/StorageAdapter.js +16 -0
- package/dist/vanillajs/storage/StorageAdapter.js.map +1 -0
- package/dist/vanillajs/types/index.d.ts +28 -0
- package/dist/vanillajs/types/index.d.ts.map +1 -0
- package/dist/vanillajs/types/index.js +14 -0
- package/dist/vanillajs/types/index.js.map +1 -0
- package/dist/vanillajs/utils/auth-utils.d.ts +13 -0
- package/dist/vanillajs/utils/auth-utils.d.ts.map +1 -0
- package/dist/vanillajs/utils/auth-utils.js +15 -0
- package/dist/vanillajs/utils/auth-utils.js.map +1 -0
- package/dist/vanillajs/utils/logger.d.ts +29 -0
- package/dist/vanillajs/utils/logger.d.ts.map +1 -0
- package/dist/vanillajs/utils/logger.js +62 -0
- package/dist/vanillajs/utils/logger.js.map +1 -0
- package/dist/vanillajs/utils/page-handlers.d.ts +29 -0
- package/dist/vanillajs/utils/page-handlers.d.ts.map +1 -0
- package/dist/vanillajs/utils/page-handlers.js +165 -0
- package/dist/vanillajs/utils/page-handlers.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { AuthEvent } from "../types/index.js";
|
|
2
|
+
import { loggers } from "../utils/logger.js";
|
|
3
|
+
const SESSION_STORAGE_KEY = "civic_auth_session";
|
|
4
|
+
export class SessionManager {
|
|
5
|
+
storage;
|
|
6
|
+
events;
|
|
7
|
+
currentSession = null;
|
|
8
|
+
constructor(storageAdapter, events) {
|
|
9
|
+
this.storage = storageAdapter;
|
|
10
|
+
this.events = events;
|
|
11
|
+
this.loadSession(); // Initial load
|
|
12
|
+
}
|
|
13
|
+
async loadSession() {
|
|
14
|
+
try {
|
|
15
|
+
const storedSession = await this.storage.getItem(SESSION_STORAGE_KEY);
|
|
16
|
+
if (storedSession) {
|
|
17
|
+
this.currentSession = JSON.parse(storedSession);
|
|
18
|
+
// TODO: Add validation, token expiry checks here
|
|
19
|
+
if (this.currentSession?.user) {
|
|
20
|
+
this.events.emit(AuthEvent.USER_SESSION_CHANGED, this.currentSession.user);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
loggers.session("SessionManager: Error loading session from storage", error);
|
|
26
|
+
this.currentSession = null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async setSession(session) {
|
|
30
|
+
this.currentSession = session;
|
|
31
|
+
await this.storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));
|
|
32
|
+
if (session.user) {
|
|
33
|
+
this.events.emit(AuthEvent.USER_SESSION_CHANGED, session.user);
|
|
34
|
+
}
|
|
35
|
+
// TODO: schedule token refresh if applicable based on session.expiresAt
|
|
36
|
+
}
|
|
37
|
+
async clearSession() {
|
|
38
|
+
this.currentSession = null;
|
|
39
|
+
await this.storage.removeItem(SESSION_STORAGE_KEY);
|
|
40
|
+
this.events.emit(AuthEvent.USER_SESSION_CHANGED, null);
|
|
41
|
+
// TODO: cancel any scheduled token refresh
|
|
42
|
+
loggers.session("SessionManager: Session cleared.");
|
|
43
|
+
}
|
|
44
|
+
async getUser() {
|
|
45
|
+
// Potentially refresh or validate session before returning user
|
|
46
|
+
return this.currentSession?.user || null;
|
|
47
|
+
}
|
|
48
|
+
async getSession() {
|
|
49
|
+
return this.currentSession;
|
|
50
|
+
}
|
|
51
|
+
async isAuthenticated() {
|
|
52
|
+
// Add more sophisticated checks, e.g., token validation, expiry
|
|
53
|
+
// For now, just checks if a user object exists in the session
|
|
54
|
+
if (!this.currentSession || !this.currentSession.idToken) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
// Placeholder: In a real scenario, validate token (e.g. using TokenService)
|
|
58
|
+
// const tokenService = new TokenService(); // Or get as dependency
|
|
59
|
+
// return tokenService.isValid(this.currentSession.accessToken);
|
|
60
|
+
return !!this.currentSession.user;
|
|
61
|
+
}
|
|
62
|
+
// Placeholder for token refresh logic
|
|
63
|
+
async refreshToken() {
|
|
64
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED);
|
|
65
|
+
try {
|
|
66
|
+
// Actual refresh logic would go here (e.g., call an API with refresh token)
|
|
67
|
+
// For now, just a placeholder that does nothing or simulates a failure/success
|
|
68
|
+
loggers.session("SessionManager: refreshToken() not implemented.");
|
|
69
|
+
// const newSession = await ApiService.refreshToken(this.currentSession.refreshToken);
|
|
70
|
+
// if (newSession) {
|
|
71
|
+
// await this.setSession(newSession);
|
|
72
|
+
// this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, newSession.user);
|
|
73
|
+
// return newSession;
|
|
74
|
+
// }
|
|
75
|
+
throw new Error("Refresh token flow not implemented.");
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
loggers.session("SessionManager: Token refresh failed", error);
|
|
79
|
+
this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);
|
|
80
|
+
// Potentially clear session if refresh fails critically
|
|
81
|
+
// await this.clearSession();
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=SessionManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionManager.js","sourceRoot":"","sources":["../../../src/vanillajs/auth/SessionManager.ts"],"names":[],"mappings":"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","sourcesContent":["import type { StorageAdapter } from \"../storage/StorageAdapter.js\";\nimport type { AuthenticationEvents } from \"./AuthenticationEvents.js\";\nimport type { User, Session } from \"../types/index.js\"; // Assuming Session might be used internally\nimport { AuthEvent } from \"../types/index.js\";\nimport { loggers } from \"../utils/logger.js\";\n\nconst SESSION_STORAGE_KEY = \"civic_auth_session\";\n\nexport class SessionManager {\n private storage: StorageAdapter;\n private events: AuthenticationEvents;\n private currentSession: Session | null = null;\n\n constructor(storageAdapter: StorageAdapter, events: AuthenticationEvents) {\n this.storage = storageAdapter;\n this.events = events;\n this.loadSession(); // Initial load\n }\n\n async loadSession(): Promise<void> {\n try {\n const storedSession = await this.storage.getItem(SESSION_STORAGE_KEY);\n if (storedSession) {\n this.currentSession = JSON.parse(storedSession);\n // TODO: Add validation, token expiry checks here\n if (this.currentSession?.user) {\n this.events.emit(\n AuthEvent.USER_SESSION_CHANGED,\n this.currentSession.user,\n );\n }\n }\n } catch (error) {\n loggers.session(\n \"SessionManager: Error loading session from storage\",\n error,\n );\n this.currentSession = null;\n }\n }\n\n async setSession(session: Session): Promise<void> {\n this.currentSession = session;\n await this.storage.setItem(SESSION_STORAGE_KEY, JSON.stringify(session));\n if (session.user) {\n this.events.emit(AuthEvent.USER_SESSION_CHANGED, session.user);\n }\n // TODO: schedule token refresh if applicable based on session.expiresAt\n }\n\n async clearSession(): Promise<void> {\n this.currentSession = null;\n await this.storage.removeItem(SESSION_STORAGE_KEY);\n this.events.emit(AuthEvent.USER_SESSION_CHANGED, null);\n // TODO: cancel any scheduled token refresh\n loggers.session(\"SessionManager: Session cleared.\");\n }\n\n async getUser(): Promise<User | null> {\n // Potentially refresh or validate session before returning user\n return this.currentSession?.user || null;\n }\n\n async getSession(): Promise<Session | null> {\n return this.currentSession;\n }\n\n async isAuthenticated(): Promise<boolean> {\n // Add more sophisticated checks, e.g., token validation, expiry\n // For now, just checks if a user object exists in the session\n if (!this.currentSession || !this.currentSession.idToken) {\n return false;\n }\n // Placeholder: In a real scenario, validate token (e.g. using TokenService)\n // const tokenService = new TokenService(); // Or get as dependency\n // return tokenService.isValid(this.currentSession.accessToken);\n return !!this.currentSession.user;\n }\n\n // Placeholder for token refresh logic\n async refreshToken(): Promise<Session | null> {\n this.events.emit(AuthEvent.TOKEN_REFRESH_STARTED);\n try {\n // Actual refresh logic would go here (e.g., call an API with refresh token)\n // For now, just a placeholder that does nothing or simulates a failure/success\n loggers.session(\"SessionManager: refreshToken() not implemented.\");\n // const newSession = await ApiService.refreshToken(this.currentSession.refreshToken);\n // if (newSession) {\n // await this.setSession(newSession);\n // this.events.emit(AuthEvent.TOKEN_REFRESH_COMPLETE, newSession.user);\n // return newSession;\n // }\n throw new Error(\"Refresh token flow not implemented.\");\n } catch (error) {\n loggers.session(\"SessionManager: Token refresh failed\", error);\n this.events.emit(AuthEvent.TOKEN_REFRESH_ERROR, error);\n // Potentially clear session if refresh fails critically\n // await this.clearSession();\n return null;\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AuthenticationEvents } from "../auth/AuthenticationEvents.js";
|
|
2
|
+
import type { createLogger } from "../utils/logger.js";
|
|
3
|
+
import type { AuthResult } from "../types/index.js";
|
|
4
|
+
interface SignalObserverConfig {
|
|
5
|
+
textSignals: {
|
|
6
|
+
success: string;
|
|
7
|
+
error?: string;
|
|
8
|
+
};
|
|
9
|
+
events?: AuthenticationEvents;
|
|
10
|
+
logger: ReturnType<typeof createLogger>;
|
|
11
|
+
}
|
|
12
|
+
export declare class SignalObserver {
|
|
13
|
+
private config;
|
|
14
|
+
private observer?;
|
|
15
|
+
private authPromiseResolve?;
|
|
16
|
+
private authPromiseReject?;
|
|
17
|
+
private cleanupCallback?;
|
|
18
|
+
constructor(config: SignalObserverConfig, authPromiseResolve?: (value: AuthResult) => void, authPromiseReject?: (reason?: Error) => void, cleanupCallback?: () => void);
|
|
19
|
+
setup(iframeDoc: Document): void;
|
|
20
|
+
disconnect(): void;
|
|
21
|
+
private isRelevantMutation;
|
|
22
|
+
private handleSignalNodes;
|
|
23
|
+
private handleSuccessNode;
|
|
24
|
+
private handleErrorNode;
|
|
25
|
+
private handleBodyTextSignals;
|
|
26
|
+
private handleBodySuccessSignal;
|
|
27
|
+
private handleBodyErrorSignal;
|
|
28
|
+
private parseUserInfo;
|
|
29
|
+
private handleInitialSignals;
|
|
30
|
+
private cleanup;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=SignalObserver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignalObserver.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/iframe/SignalObserver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAQ,MAAM,mBAAmB,CAAC;AAE1D,UAAU,oBAAoB;IAC5B,WAAW,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,MAAM,CAAC,EAAE,oBAAoB,CAAC;IAC9B,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;CACzC;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,CAAmB;IACpC,OAAO,CAAC,kBAAkB,CAAC,CAA8B;IACzD,OAAO,CAAC,iBAAiB,CAAC,CAA2B;IACrD,OAAO,CAAC,eAAe,CAAC,CAAa;gBAGnC,MAAM,EAAE,oBAAoB,EAC5B,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,EAChD,iBAAiB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,KAAK,IAAI,EAC5C,eAAe,CAAC,EAAE,MAAM,IAAI;IAQvB,KAAK,CAAC,SAAS,EAAE,QAAQ,GAAG,IAAI;IA4BhC,UAAU,IAAI,IAAI;IAQzB,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,iBAAiB;IAsBzB,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,uBAAuB;IAoB/B,OAAO,CAAC,qBAAqB;IAoB7B,OAAO,CAAC,aAAa;IAsBrB,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,OAAO;CAIhB"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { AuthEvent } from "../types/index.js";
|
|
2
|
+
export class SignalObserver {
|
|
3
|
+
config;
|
|
4
|
+
observer;
|
|
5
|
+
authPromiseResolve;
|
|
6
|
+
authPromiseReject;
|
|
7
|
+
cleanupCallback;
|
|
8
|
+
constructor(config, authPromiseResolve, authPromiseReject, cleanupCallback) {
|
|
9
|
+
this.config = config;
|
|
10
|
+
this.authPromiseResolve = authPromiseResolve;
|
|
11
|
+
this.authPromiseReject = authPromiseReject;
|
|
12
|
+
this.cleanupCallback = cleanupCallback;
|
|
13
|
+
}
|
|
14
|
+
setup(iframeDoc) {
|
|
15
|
+
this.config.logger.info("Setting up signal observer for iframe document");
|
|
16
|
+
this.observer = new MutationObserver((mutationsList) => {
|
|
17
|
+
for (const mutation of mutationsList) {
|
|
18
|
+
if (!this.isRelevantMutation(mutation)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
if (this.handleSignalNodes(iframeDoc)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this.handleBodyTextSignals(iframeDoc);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
this.config.logger.debug("Starting observation of iframe body");
|
|
28
|
+
this.observer.observe(iframeDoc.body, {
|
|
29
|
+
childList: true,
|
|
30
|
+
subtree: true,
|
|
31
|
+
characterData: true,
|
|
32
|
+
});
|
|
33
|
+
// Check for initial signals
|
|
34
|
+
this.handleInitialSignals(iframeDoc);
|
|
35
|
+
}
|
|
36
|
+
disconnect() {
|
|
37
|
+
if (this.observer) {
|
|
38
|
+
this.config.logger.debug("Disconnecting mutation observer");
|
|
39
|
+
this.observer.disconnect();
|
|
40
|
+
this.observer = undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
isRelevantMutation(mutation) {
|
|
44
|
+
return mutation.type === "childList" || mutation.type === "characterData";
|
|
45
|
+
}
|
|
46
|
+
handleSignalNodes(iframeDoc) {
|
|
47
|
+
const successNode = iframeDoc.getElementById("civic-auth-success-signal");
|
|
48
|
+
const errorNode = iframeDoc.getElementById("civic-auth-error-signal");
|
|
49
|
+
if (this.handleSuccessNode(successNode)) {
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
if (this.handleErrorNode(errorNode)) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
handleSuccessNode(successNode) {
|
|
58
|
+
if (successNode?.textContent !== this.config.textSignals.success) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
this.config.logger.info("Success signal detected in iframe by ID");
|
|
62
|
+
const userInfo = this.parseUserInfo(successNode);
|
|
63
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {
|
|
64
|
+
detail: "Success signal detected in iframe",
|
|
65
|
+
user: userInfo,
|
|
66
|
+
});
|
|
67
|
+
this.authPromiseResolve?.({
|
|
68
|
+
user: userInfo,
|
|
69
|
+
signalText: successNode.textContent,
|
|
70
|
+
});
|
|
71
|
+
this.cleanup();
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
handleErrorNode(errorNode) {
|
|
75
|
+
if (!errorNode) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
this.config.logger.warn("Error signal detected in iframe by ID");
|
|
79
|
+
const errorMessage = errorNode.textContent || "Error signal detected in iframe";
|
|
80
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {
|
|
81
|
+
detail: errorMessage,
|
|
82
|
+
});
|
|
83
|
+
this.authPromiseReject?.(new Error(errorMessage));
|
|
84
|
+
this.cleanup();
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
handleBodyTextSignals(iframeDoc) {
|
|
88
|
+
const bodyText = iframeDoc.body?.textContent || "";
|
|
89
|
+
this.config.logger.debug("Checking iframe body text for signals (fallback)", { bodyText });
|
|
90
|
+
if (this.handleBodySuccessSignal(bodyText)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.handleBodyErrorSignal(bodyText);
|
|
94
|
+
}
|
|
95
|
+
handleBodySuccessSignal(bodyText) {
|
|
96
|
+
if (!bodyText.includes(this.config.textSignals.success)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
this.config.logger.info("Success signal detected in iframe by text content (fallback)");
|
|
100
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {
|
|
101
|
+
detail: "Success signal detected in iframe (text fallback)",
|
|
102
|
+
});
|
|
103
|
+
this.authPromiseResolve?.({
|
|
104
|
+
signalText: this.config.textSignals.success,
|
|
105
|
+
});
|
|
106
|
+
this.cleanup();
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
handleBodyErrorSignal(bodyText) {
|
|
110
|
+
if (!this.config.textSignals.error ||
|
|
111
|
+
!bodyText.includes(this.config.textSignals.error)) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
this.config.logger.warn("Error signal detected in iframe by text content (fallback)");
|
|
115
|
+
this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {
|
|
116
|
+
detail: this.config.textSignals.error,
|
|
117
|
+
});
|
|
118
|
+
this.authPromiseReject?.(new Error(this.config.textSignals.error));
|
|
119
|
+
this.cleanup();
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
parseUserInfo(node) {
|
|
123
|
+
const userInfoAttr = node.getAttribute("data-user-info");
|
|
124
|
+
if (!userInfoAttr) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
try {
|
|
128
|
+
const parsed = JSON.parse(userInfoAttr);
|
|
129
|
+
// Ensure we have at least an id field
|
|
130
|
+
if (!parsed.id || typeof parsed.id !== "string") {
|
|
131
|
+
this.config.logger.error("User info missing required 'id' field");
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
134
|
+
return parsed;
|
|
135
|
+
}
|
|
136
|
+
catch (parseError) {
|
|
137
|
+
this.config.logger.error("Failed to parse user info:", {
|
|
138
|
+
error: parseError,
|
|
139
|
+
});
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
handleInitialSignals(iframeDoc) {
|
|
144
|
+
const successNode = iframeDoc.getElementById("civic-auth-success-signal");
|
|
145
|
+
const errorNode = iframeDoc.getElementById("civic-auth-error-signal");
|
|
146
|
+
if (this.handleSuccessNode(successNode) ||
|
|
147
|
+
this.handleErrorNode(errorNode)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const initialBodyText = iframeDoc.body?.textContent || "";
|
|
151
|
+
this.config.logger.debug("Performing initial signal check by text (fallback)", { initialBodyText });
|
|
152
|
+
if (this.handleBodySuccessSignal(initialBodyText) ||
|
|
153
|
+
this.handleBodyErrorSignal(initialBodyText)) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
cleanup() {
|
|
158
|
+
this.disconnect();
|
|
159
|
+
this.cleanupCallback?.();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=SignalObserver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SignalObserver.js","sourceRoot":"","sources":["../../../src/vanillajs/iframe/SignalObserver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAc9C,MAAM,OAAO,cAAc;IACjB,MAAM,CAAuB;IAC7B,QAAQ,CAAoB;IAC5B,kBAAkB,CAA+B;IACjD,iBAAiB,CAA4B;IAC7C,eAAe,CAAc;IAErC,YACE,MAA4B,EAC5B,kBAAgD,EAChD,iBAA4C,EAC5C,eAA4B;QAE5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;QAC7C,IAAI,CAAC,iBAAiB,GAAG,iBAAiB,CAAC;QAC3C,IAAI,CAAC,eAAe,GAAG,eAAe,CAAC;IACzC,CAAC;IAEM,KAAK,CAAC,SAAmB;QAC9B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;QAE1E,IAAI,CAAC,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,aAAa,EAAE,EAAE;YACrD,KAAK,MAAM,QAAQ,IAAI,aAAa,EAAE,CAAC;gBACrC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;oBACvC,SAAS;gBACX,CAAC;gBAED,IAAI,IAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;oBACtC,OAAO;gBACT,CAAC;gBAED,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;YACxC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAChE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE;YACpC,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,IAAI;YACb,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,4BAA4B;QAC5B,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAEM,UAAU;QACf,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;IACH,CAAC;IAEO,kBAAkB,CAAC,QAAwB;QACjD,OAAO,QAAQ,CAAC,IAAI,KAAK,WAAW,IAAI,QAAQ,CAAC,IAAI,KAAK,eAAe,CAAC;IAC5E,CAAC;IAEO,iBAAiB,CAAC,SAAmB;QAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,SAAS,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAEtE,IAAI,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,EAAE,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,iBAAiB,CAAC,WAA+B;QACvD,IAAI,WAAW,EAAE,WAAW,KAAK,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACjE,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QACnE,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;QAEjD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE;YACnD,MAAM,EAAE,mCAAmC;YAC3C,IAAI,EAAE,QAAQ;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,WAAW,CAAC,WAAW;SACpC,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,eAAe,CAAC,SAA6B;QACnD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;QACjE,MAAM,YAAY,GAChB,SAAS,CAAC,WAAW,IAAI,iCAAiC,CAAC;QAE7D,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE;YAChD,MAAM,EAAE,YAAY;SACrB,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,EAAE,CAAC,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,qBAAqB,CAAC,SAAmB;QAC/C,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CACtB,kDAAkD,EAClD,EAAE,QAAQ,EAAE,CACb,CAAC;QAEF,IAAI,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3C,OAAO;QACT,CAAC;QAED,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC;IACvC,CAAC;IAEO,uBAAuB,CAAC,QAAgB;QAC9C,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YACxD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CACrB,8DAA8D,CAC/D,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE;YACnD,MAAM,EAAE,mDAAmD;SAC5D,CAAC,CAAC;QAEH,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO;SAC5C,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,qBAAqB,CAAC,QAAgB;QAC5C,IACE,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK;YAC9B,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,EACjD,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CACrB,4DAA4D,CAC7D,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE;YAChD,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK;SACtC,CAAC,CAAC;QAEH,IAAI,CAAC,iBAAiB,EAAE,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAEO,aAAa,CAAC,IAAiB;QACrC,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACzD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAA+B,CAAC;YACtE,sCAAsC;YACtC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;gBAChD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;gBAClE,OAAO,SAAS,CAAC;YACnB,CAAC;YACD,OAAO,MAAc,CAAC;QACxB,CAAC;QAAC,OAAO,UAAU,EAAE,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE;gBACrD,KAAK,EAAE,UAAU;aAClB,CAAC,CAAC;YACH,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IAEO,oBAAoB,CAAC,SAAmB;QAC9C,MAAM,WAAW,GAAG,SAAS,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,SAAS,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;QAEtE,IACE,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC;YACnC,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAC/B,CAAC;YACD,OAAO;QACT,CAAC;QAED,MAAM,eAAe,GAAG,SAAS,CAAC,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CACtB,oDAAoD,EACpD,EAAE,eAAe,EAAE,CACpB,CAAC;QAEF,IACE,IAAI,CAAC,uBAAuB,CAAC,eAAe,CAAC;YAC7C,IAAI,CAAC,qBAAqB,CAAC,eAAe,CAAC,EAC3C,CAAC;YACD,OAAO;QACT,CAAC;IACH,CAAC;IAEO,OAAO;QACb,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;IAC3B,CAAC;CACF","sourcesContent":["import { AuthEvent } from \"../types/index.js\";\nimport type { AuthenticationEvents } from \"../auth/AuthenticationEvents.js\";\nimport type { createLogger } from \"../utils/logger.js\";\nimport type { AuthResult, User } from \"../types/index.js\";\n\ninterface SignalObserverConfig {\n textSignals: {\n success: string;\n error?: string;\n };\n events?: AuthenticationEvents;\n logger: ReturnType<typeof createLogger>;\n}\n\nexport class SignalObserver {\n private config: SignalObserverConfig;\n private observer?: MutationObserver;\n private authPromiseResolve?: (value: AuthResult) => void;\n private authPromiseReject?: (reason?: Error) => void;\n private cleanupCallback?: () => void;\n\n constructor(\n config: SignalObserverConfig,\n authPromiseResolve?: (value: AuthResult) => void,\n authPromiseReject?: (reason?: Error) => void,\n cleanupCallback?: () => void,\n ) {\n this.config = config;\n this.authPromiseResolve = authPromiseResolve;\n this.authPromiseReject = authPromiseReject;\n this.cleanupCallback = cleanupCallback;\n }\n\n public setup(iframeDoc: Document): void {\n this.config.logger.info(\"Setting up signal observer for iframe document\");\n\n this.observer = new MutationObserver((mutationsList) => {\n for (const mutation of mutationsList) {\n if (!this.isRelevantMutation(mutation)) {\n continue;\n }\n\n if (this.handleSignalNodes(iframeDoc)) {\n return;\n }\n\n this.handleBodyTextSignals(iframeDoc);\n }\n });\n\n this.config.logger.debug(\"Starting observation of iframe body\");\n this.observer.observe(iframeDoc.body, {\n childList: true,\n subtree: true,\n characterData: true,\n });\n\n // Check for initial signals\n this.handleInitialSignals(iframeDoc);\n }\n\n public disconnect(): void {\n if (this.observer) {\n this.config.logger.debug(\"Disconnecting mutation observer\");\n this.observer.disconnect();\n this.observer = undefined;\n }\n }\n\n private isRelevantMutation(mutation: MutationRecord): boolean {\n return mutation.type === \"childList\" || mutation.type === \"characterData\";\n }\n\n private handleSignalNodes(iframeDoc: Document): boolean {\n const successNode = iframeDoc.getElementById(\"civic-auth-success-signal\");\n const errorNode = iframeDoc.getElementById(\"civic-auth-error-signal\");\n\n if (this.handleSuccessNode(successNode)) {\n return true;\n }\n\n if (this.handleErrorNode(errorNode)) {\n return true;\n }\n\n return false;\n }\n\n private handleSuccessNode(successNode: HTMLElement | null): boolean {\n if (successNode?.textContent !== this.config.textSignals.success) {\n return false;\n }\n\n this.config.logger.info(\"Success signal detected in iframe by ID\");\n const userInfo = this.parseUserInfo(successNode);\n\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Success signal detected in iframe\",\n user: userInfo,\n });\n\n this.authPromiseResolve?.({\n user: userInfo,\n signalText: successNode.textContent,\n });\n\n this.cleanup();\n return true;\n }\n\n private handleErrorNode(errorNode: HTMLElement | null): boolean {\n if (!errorNode) {\n return false;\n }\n\n this.config.logger.warn(\"Error signal detected in iframe by ID\");\n const errorMessage =\n errorNode.textContent || \"Error signal detected in iframe\";\n\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: errorMessage,\n });\n\n this.authPromiseReject?.(new Error(errorMessage));\n this.cleanup();\n return true;\n }\n\n private handleBodyTextSignals(iframeDoc: Document): void {\n const bodyText = iframeDoc.body?.textContent || \"\";\n this.config.logger.debug(\n \"Checking iframe body text for signals (fallback)\",\n { bodyText },\n );\n\n if (this.handleBodySuccessSignal(bodyText)) {\n return;\n }\n\n this.handleBodyErrorSignal(bodyText);\n }\n\n private handleBodySuccessSignal(bodyText: string): boolean {\n if (!bodyText.includes(this.config.textSignals.success)) {\n return false;\n }\n\n this.config.logger.info(\n \"Success signal detected in iframe by text content (fallback)\",\n );\n this.config.events?.emit(AuthEvent.SIGN_IN_COMPLETE, {\n detail: \"Success signal detected in iframe (text fallback)\",\n });\n\n this.authPromiseResolve?.({\n signalText: this.config.textSignals.success,\n });\n\n this.cleanup();\n return true;\n }\n\n private handleBodyErrorSignal(bodyText: string): boolean {\n if (\n !this.config.textSignals.error ||\n !bodyText.includes(this.config.textSignals.error)\n ) {\n return false;\n }\n\n this.config.logger.warn(\n \"Error signal detected in iframe by text content (fallback)\",\n );\n this.config.events?.emit(AuthEvent.SIGN_IN_ERROR, {\n detail: this.config.textSignals.error,\n });\n\n this.authPromiseReject?.(new Error(this.config.textSignals.error));\n this.cleanup();\n return true;\n }\n\n private parseUserInfo(node: HTMLElement): User | undefined {\n const userInfoAttr = node.getAttribute(\"data-user-info\");\n if (!userInfoAttr) {\n return undefined;\n }\n\n try {\n const parsed = JSON.parse(userInfoAttr) as { [key: string]: unknown };\n // Ensure we have at least an id field\n if (!parsed.id || typeof parsed.id !== \"string\") {\n this.config.logger.error(\"User info missing required 'id' field\");\n return undefined;\n }\n return parsed as User;\n } catch (parseError) {\n this.config.logger.error(\"Failed to parse user info:\", {\n error: parseError,\n });\n return undefined;\n }\n }\n\n private handleInitialSignals(iframeDoc: Document): void {\n const successNode = iframeDoc.getElementById(\"civic-auth-success-signal\");\n const errorNode = iframeDoc.getElementById(\"civic-auth-error-signal\");\n\n if (\n this.handleSuccessNode(successNode) ||\n this.handleErrorNode(errorNode)\n ) {\n return;\n }\n\n const initialBodyText = iframeDoc.body?.textContent || \"\";\n this.config.logger.debug(\n \"Performing initial signal check by text (fallback)\",\n { initialBodyText },\n );\n\n if (\n this.handleBodySuccessSignal(initialBodyText) ||\n this.handleBodyErrorSignal(initialBodyText)\n ) {\n return;\n }\n }\n\n private cleanup(): void {\n this.disconnect();\n this.cleanupCallback?.();\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domUtils.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/iframe/domUtils.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,WAAW,EACtB,EAAE,CAAC,EAAE,MAAM,GACV,iBAAiB,CAWnB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAQrE;AAKD,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Placeholder for DOM Utilities (Task C)
|
|
2
|
+
// This file will contain helper functions for DOM manipulation related to the iframe.
|
|
3
|
+
export function createIframe(url, container, id) {
|
|
4
|
+
const iframe = document.createElement("iframe");
|
|
5
|
+
iframe.id = id || "civic-auth-iframe";
|
|
6
|
+
iframe.src = url;
|
|
7
|
+
// Basic styling, can be expanded
|
|
8
|
+
iframe.style.border = "none";
|
|
9
|
+
iframe.style.width = "100%";
|
|
10
|
+
iframe.style.height = "100%";
|
|
11
|
+
container.appendChild(iframe);
|
|
12
|
+
return iframe;
|
|
13
|
+
}
|
|
14
|
+
export function removeIframe(iframe) {
|
|
15
|
+
const element = typeof iframe === "string"
|
|
16
|
+
? document.getElementById(iframe)
|
|
17
|
+
: iframe;
|
|
18
|
+
if (element && element.parentNode) {
|
|
19
|
+
element.parentNode.removeChild(element);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// ... other DOM utility functions ...
|
|
23
|
+
// Placeholder for domUtils.ts
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=domUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domUtils.js","sourceRoot":"","sources":["../../../src/vanillajs/iframe/domUtils.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,sFAAsF;AAEtF,MAAM,UAAU,YAAY,CAC1B,GAAW,EACX,SAAsB,EACtB,EAAW;IAEX,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IAChD,MAAM,CAAC,EAAE,GAAG,EAAE,IAAI,mBAAmB,CAAC;IACtC,MAAM,CAAC,GAAG,GAAG,GAAG,CAAC;IACjB,iCAAiC;IACjC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC;IAC5B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IAE7B,SAAS,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC9B,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAkC;IAC7D,MAAM,OAAO,GACX,OAAO,MAAM,KAAK,QAAQ;QACxB,CAAC,CAAE,QAAQ,CAAC,cAAc,CAAC,MAAM,CAAuB;QACxD,CAAC,CAAC,MAAM,CAAC;IACb,IAAI,OAAO,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAC1C,CAAC;AACH,CAAC;AAED,sCAAsC;AAEtC,8BAA8B;AAC9B,OAAO,EAAE,CAAC","sourcesContent":["// Placeholder for DOM Utilities (Task C)\n// This file will contain helper functions for DOM manipulation related to the iframe.\n\nexport function createIframe(\n url: string,\n container: HTMLElement,\n id?: string,\n): HTMLIFrameElement {\n const iframe = document.createElement(\"iframe\");\n iframe.id = id || \"civic-auth-iframe\";\n iframe.src = url;\n // Basic styling, can be expanded\n iframe.style.border = \"none\";\n iframe.style.width = \"100%\";\n iframe.style.height = \"100%\";\n\n container.appendChild(iframe);\n return iframe;\n}\n\nexport function removeIframe(iframe: HTMLIFrameElement | string): void {\n const element =\n typeof iframe === \"string\"\n ? (document.getElementById(iframe) as HTMLIFrameElement)\n : iframe;\n if (element && element.parentNode) {\n element.parentNode.removeChild(element);\n }\n}\n\n// ... other DOM utility functions ...\n\n// Placeholder for domUtils.ts\nexport {};\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from "./auth/AuthenticationEvents.js";
|
|
2
|
+
export * from "./auth/SessionManager.js";
|
|
3
|
+
export * from "./types/index.js";
|
|
4
|
+
export * from "./storage/StorageAdapter.js";
|
|
5
|
+
export * from "./storage/InMemoryStorageAdapter.js";
|
|
6
|
+
export * from "./storage/BrowserLocalStorageAdapter.js";
|
|
7
|
+
export * from "./storage/BrowserCookieStorageAdapter.js";
|
|
8
|
+
export * from "./services/ApiService.js";
|
|
9
|
+
export * from "./auth/CivicAuth.js";
|
|
10
|
+
export { AuthenticationEvents } from "./auth/AuthenticationEvents.js";
|
|
11
|
+
export { AuthEvent } from "./types/index.js";
|
|
12
|
+
export { BrowserCookieStorageAdapter } from "./storage/BrowserCookieStorageAdapter.js";
|
|
13
|
+
export { type StorageAdapter } from "./storage/StorageAdapter.js";
|
|
14
|
+
export { handleOAuthRedirectPage, type HandleOAuthRedirectConfig, } from "./utils/page-handlers.js";
|
|
15
|
+
export type { User, Session } from "./types/index.js";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vanillajs/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AACzD,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,uBAAuB,EACvB,KAAK,yBAAyB,GAC/B,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export * from "./auth/AuthenticationEvents.js";
|
|
2
|
+
export * from "./auth/SessionManager.js";
|
|
3
|
+
export * from "./types/index.js";
|
|
4
|
+
export * from "./storage/StorageAdapter.js";
|
|
5
|
+
export * from "./storage/InMemoryStorageAdapter.js";
|
|
6
|
+
export * from "./storage/BrowserLocalStorageAdapter.js";
|
|
7
|
+
export * from "./storage/BrowserCookieStorageAdapter.js";
|
|
8
|
+
export * from "./services/ApiService.js";
|
|
9
|
+
export * from "./auth/CivicAuth.js";
|
|
10
|
+
export { AuthenticationEvents } from "./auth/AuthenticationEvents.js";
|
|
11
|
+
export { AuthEvent } from "./types/index.js";
|
|
12
|
+
export { BrowserCookieStorageAdapter } from "./storage/BrowserCookieStorageAdapter.js";
|
|
13
|
+
export {} from "./storage/StorageAdapter.js";
|
|
14
|
+
export { handleOAuthRedirectPage, } from "./utils/page-handlers.js";
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vanillajs/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAC;AAC/C,cAAc,0BAA0B,CAAC;AACzC,cAAc,kBAAkB,CAAC;AACjC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,qCAAqC,CAAC;AACpD,cAAc,yCAAyC,CAAC;AACxD,cAAc,0CAA0C,CAAC;AACzD,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACtE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,2BAA2B,EAAE,MAAM,0CAA0C,CAAC;AACvF,OAAO,EAAuB,MAAM,6BAA6B,CAAC;AAClE,OAAO,EACL,uBAAuB,GAExB,MAAM,0BAA0B,CAAC","sourcesContent":["export * from \"./auth/AuthenticationEvents.js\";\nexport * from \"./auth/SessionManager.js\";\nexport * from \"./types/index.js\";\nexport * from \"./storage/StorageAdapter.js\";\nexport * from \"./storage/InMemoryStorageAdapter.js\";\nexport * from \"./storage/BrowserLocalStorageAdapter.js\";\nexport * from \"./storage/BrowserCookieStorageAdapter.js\";\nexport * from \"./services/ApiService.js\";\nexport * from \"./auth/CivicAuth.js\";\n\nexport { AuthenticationEvents } from \"./auth/AuthenticationEvents.js\";\nexport { AuthEvent } from \"./types/index.js\";\nexport { BrowserCookieStorageAdapter } from \"./storage/BrowserCookieStorageAdapter.js\";\nexport { type StorageAdapter } from \"./storage/StorageAdapter.js\";\nexport {\n handleOAuthRedirectPage,\n type HandleOAuthRedirectConfig,\n} from \"./utils/page-handlers.js\";\n\nexport type { User, Session } from \"./types/index.js\";\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface RequestOptions<TBody extends BodyInit | null = BodyInit | null> extends Omit<RequestInit, "body"> {
|
|
2
|
+
baseUrl?: string;
|
|
3
|
+
params?: Record<string, string>;
|
|
4
|
+
body?: TBody;
|
|
5
|
+
token?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* ApiService is a wrapper around the fetch API for making HTTP requests.
|
|
9
|
+
* It can be configured with a base URL and default headers.
|
|
10
|
+
*/
|
|
11
|
+
export declare class ApiService {
|
|
12
|
+
private logger;
|
|
13
|
+
private defaultConfig;
|
|
14
|
+
constructor(defaultConfig?: Omit<RequestOptions, "body" | "params">);
|
|
15
|
+
request<TResponse, TBody extends BodyInit | null = BodyInit | null>(url: string, options?: RequestOptions<TBody>): Promise<TResponse>;
|
|
16
|
+
get<TResponse>(url: string, options?: Omit<RequestOptions<never>, "method" | "body">): Promise<TResponse>;
|
|
17
|
+
post<TResponse, TBody extends BodyInit | null = BodyInit | null>(url: string, options?: Omit<RequestOptions<TBody>, "method">): Promise<TResponse>;
|
|
18
|
+
put<TResponse, TBody extends BodyInit | null = BodyInit | null>(url: string, options?: Omit<RequestOptions<TBody>, "method">): Promise<TResponse>;
|
|
19
|
+
delete<TResponse>(url: string, options?: Omit<RequestOptions<never>, "method" | "body">): Promise<TResponse>;
|
|
20
|
+
patch<TResponse, TBody extends BodyInit | null = BodyInit | null>(url: string, options?: Omit<RequestOptions<TBody>, "method">): Promise<TResponse>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=ApiService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiService.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/services/ApiService.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc,CAAC,KAAK,SAAS,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,CAC7E,SAAQ,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,aAAa,CAA0C;gBAEnD,aAAa,GAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,QAAQ,CAAM;IAUjE,OAAO,CAAC,SAAS,EAAE,KAAK,SAAS,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,EACtE,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,cAAc,CAAC,KAAK,CAAM,GAClC,OAAO,CAAC,SAAS,CAAC;IAwDrB,GAAG,CAAC,SAAS,EACX,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAM,GAC3D,OAAO,CAAC,SAAS,CAAC;IAIrB,IAAI,CAAC,SAAS,EAAE,KAAK,SAAS,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,EAC7D,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAM,GAClD,OAAO,CAAC,SAAS,CAAC;IAIrB,GAAG,CAAC,SAAS,EAAE,KAAK,SAAS,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,EAC5D,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAM,GAClD,OAAO,CAAC,SAAS,CAAC;IAIrB,MAAM,CAAC,SAAS,EACd,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAM,GAC3D,OAAO,CAAC,SAAS,CAAC;IAIrB,KAAK,CAAC,SAAS,EAAE,KAAK,SAAS,QAAQ,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,EAC9D,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAM,GAClD,OAAO,CAAC,SAAS,CAAC;CAGtB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { getCurrentLogger } from "../utils/logger.js";
|
|
2
|
+
/**
|
|
3
|
+
* ApiService is a wrapper around the fetch API for making HTTP requests.
|
|
4
|
+
* It can be configured with a base URL and default headers.
|
|
5
|
+
*/
|
|
6
|
+
export class ApiService {
|
|
7
|
+
logger = getCurrentLogger();
|
|
8
|
+
defaultConfig;
|
|
9
|
+
constructor(defaultConfig = {}) {
|
|
10
|
+
this.defaultConfig = {
|
|
11
|
+
headers: {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
...defaultConfig.headers,
|
|
14
|
+
},
|
|
15
|
+
...defaultConfig,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
async request(url, options = {}) {
|
|
19
|
+
const { baseUrl, params, token, ...fetchOptions } = options;
|
|
20
|
+
// Construct full URL
|
|
21
|
+
let fullUrl = baseUrl ? `${baseUrl}${url}` : url;
|
|
22
|
+
if (params) {
|
|
23
|
+
const searchParams = new URLSearchParams();
|
|
24
|
+
Object.entries(params).forEach(([key, value]) => {
|
|
25
|
+
searchParams.append(key, value);
|
|
26
|
+
});
|
|
27
|
+
fullUrl += `?${searchParams.toString()}`;
|
|
28
|
+
}
|
|
29
|
+
// Add authorization header if token is provided
|
|
30
|
+
if (token) {
|
|
31
|
+
fetchOptions.headers = {
|
|
32
|
+
...fetchOptions.headers,
|
|
33
|
+
Authorization: `Bearer ${token}`,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Stringify body if it's an object
|
|
37
|
+
if (fetchOptions.body &&
|
|
38
|
+
typeof fetchOptions.body === "object" &&
|
|
39
|
+
!(fetchOptions.body instanceof FormData)) {
|
|
40
|
+
fetchOptions.body = JSON.stringify(fetchOptions.body);
|
|
41
|
+
fetchOptions.headers = {
|
|
42
|
+
...fetchOptions.headers,
|
|
43
|
+
"Content-Type": "application/json",
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
this.logger.debug("Making API request", {
|
|
48
|
+
url: fullUrl,
|
|
49
|
+
options: fetchOptions,
|
|
50
|
+
});
|
|
51
|
+
const response = await fetch(fullUrl, fetchOptions);
|
|
52
|
+
if (!response.ok) {
|
|
53
|
+
const error = new Error(`HTTP error! status: ${response.status}`);
|
|
54
|
+
this.logger.error("API request failed", { error, response });
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
const data = await response.json();
|
|
58
|
+
this.logger.debug("API request successful", { data });
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
this.logger.error("API request failed", { error, url: fullUrl });
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
get(url, options = {}) {
|
|
67
|
+
return this.request(url, { ...options, method: "GET" });
|
|
68
|
+
}
|
|
69
|
+
post(url, options = {}) {
|
|
70
|
+
return this.request(url, { ...options, method: "POST" });
|
|
71
|
+
}
|
|
72
|
+
put(url, options = {}) {
|
|
73
|
+
return this.request(url, { ...options, method: "PUT" });
|
|
74
|
+
}
|
|
75
|
+
delete(url, options = {}) {
|
|
76
|
+
return this.request(url, { ...options, method: "DELETE" });
|
|
77
|
+
}
|
|
78
|
+
patch(url, options = {}) {
|
|
79
|
+
return this.request(url, { ...options, method: "PATCH" });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=ApiService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApiService.js","sourceRoot":"","sources":["../../../src/vanillajs/services/ApiService.ts"],"names":[],"mappings":"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","sourcesContent":["import { getCurrentLogger } from \"../utils/logger.js\";\n\nexport interface RequestOptions<TBody extends BodyInit | null = BodyInit | null>\n extends Omit<RequestInit, \"body\"> {\n baseUrl?: string;\n params?: Record<string, string>;\n body?: TBody; // Generic type for request body\n token?: string; // Optional bearer token\n}\n\n/**\n * ApiService is a wrapper around the fetch API for making HTTP requests.\n * It can be configured with a base URL and default headers.\n */\nexport class ApiService {\n private logger = getCurrentLogger();\n private defaultConfig: Omit<RequestOptions, \"body\" | \"params\">;\n\n constructor(defaultConfig: Omit<RequestOptions, \"body\" | \"params\"> = {}) {\n this.defaultConfig = {\n headers: {\n \"Content-Type\": \"application/json\",\n ...defaultConfig.headers,\n },\n ...defaultConfig,\n };\n }\n\n async request<TResponse, TBody extends BodyInit | null = BodyInit | null>(\n url: string,\n options: RequestOptions<TBody> = {},\n ): Promise<TResponse> {\n const { baseUrl, params, token, ...fetchOptions } = options;\n\n // Construct full URL\n let fullUrl = baseUrl ? `${baseUrl}${url}` : url;\n if (params) {\n const searchParams = new URLSearchParams();\n Object.entries(params).forEach(([key, value]) => {\n searchParams.append(key, value);\n });\n fullUrl += `?${searchParams.toString()}`;\n }\n\n // Add authorization header if token is provided\n if (token) {\n fetchOptions.headers = {\n ...fetchOptions.headers,\n Authorization: `Bearer ${token}`,\n };\n }\n\n // Stringify body if it's an object\n if (\n fetchOptions.body &&\n typeof fetchOptions.body === \"object\" &&\n !(fetchOptions.body instanceof FormData)\n ) {\n fetchOptions.body = JSON.stringify(fetchOptions.body) as TBody;\n fetchOptions.headers = {\n ...fetchOptions.headers,\n \"Content-Type\": \"application/json\",\n };\n }\n\n try {\n this.logger.debug(\"Making API request\", {\n url: fullUrl,\n options: fetchOptions,\n });\n const response = await fetch(fullUrl, fetchOptions as RequestInit);\n\n if (!response.ok) {\n const error = new Error(`HTTP error! status: ${response.status}`);\n this.logger.error(\"API request failed\", { error, response });\n throw error;\n }\n\n const data = await response.json();\n this.logger.debug(\"API request successful\", { data });\n return data as TResponse;\n } catch (error) {\n this.logger.error(\"API request failed\", { error, url: fullUrl });\n throw error;\n }\n }\n\n get<TResponse>(\n url: string,\n options: Omit<RequestOptions<never>, \"method\" | \"body\"> = {},\n ): Promise<TResponse> {\n return this.request<TResponse>(url, { ...options, method: \"GET\" });\n }\n\n post<TResponse, TBody extends BodyInit | null = BodyInit | null>(\n url: string,\n options: Omit<RequestOptions<TBody>, \"method\"> = {},\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>(url, { ...options, method: \"POST\" });\n }\n\n put<TResponse, TBody extends BodyInit | null = BodyInit | null>(\n url: string,\n options: Omit<RequestOptions<TBody>, \"method\"> = {},\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>(url, { ...options, method: \"PUT\" });\n }\n\n delete<TResponse>(\n url: string,\n options: Omit<RequestOptions<never>, \"method\" | \"body\"> = {},\n ): Promise<TResponse> {\n return this.request<TResponse>(url, { ...options, method: \"DELETE\" });\n }\n\n patch<TResponse, TBody extends BodyInit | null = BodyInit | null>(\n url: string,\n options: Omit<RequestOptions<TBody>, \"method\"> = {},\n ): Promise<TResponse> {\n return this.request<TResponse, TBody>(url, { ...options, method: \"PATCH\" });\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StorageAdapter } from "./StorageAdapter.js";
|
|
2
|
+
interface CookieOptions {
|
|
3
|
+
days?: number;
|
|
4
|
+
maxAge?: number;
|
|
5
|
+
path?: string;
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
httpOnly?: boolean;
|
|
8
|
+
sameSite?: "Lax" | "Strict" | "None";
|
|
9
|
+
}
|
|
10
|
+
export declare class BrowserCookieStorageAdapter implements StorageAdapter {
|
|
11
|
+
private defaultCookieOptions;
|
|
12
|
+
private logger;
|
|
13
|
+
constructor(defaultOptions?: CookieOptions);
|
|
14
|
+
getItem(key: string): Promise<string | null>;
|
|
15
|
+
setItem(key: string, value: string, itemOptions?: CookieOptions): Promise<void>;
|
|
16
|
+
removeItem(key: string, itemOptions?: Pick<CookieOptions, "path">): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=BrowserCookieStorageAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrowserCookieStorageAdapter.d.ts","sourceRoot":"","sources":["../../../src/vanillajs/storage/BrowserCookieStorageAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,UAAU,aAAa;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;CACtC;AA0DD,qBAAa,2BAA4B,YAAW,cAAc;IAChE,OAAO,CAAC,oBAAoB,CAAgB;IAC5C,OAAO,CAAC,MAAM,CAAsB;gBAExB,cAAc,GAAE,aAAkB;IAQxC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAU5C,OAAO,CACX,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,aAAa,GAC1B,OAAO,CAAC,IAAI,CAAC;IAqBV,UAAU,CACd,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC;CAUjB"}
|